[
  {
    "path": ".codedocs",
    "content": "# CodeDocs.xyz Configuration File\n#\n# Rename this example to '.codedocs' and put it in the root directory of your\n# repository. This file is optional, documentation will still be generated\n# without it using sensible defaults.\n\n#---------------------------------------------------------------------------\n# CodeDocs Configuration\n#---------------------------------------------------------------------------\n\n# Include the Doxygen configuration from another file.\n# The file must be a relative path with respect to the root of the repository.\n# If any of the options in this doxyfile include a path (ie, INPUT), these\n# paths will be considered relative to the root of the repository, not the\n# location of the DOXYFILE.\n\nDOXYFILE = Doxyfile\n\n# Specify external repository to link documentation with.\n# This is similar to Doxygen's TAGFILES option, but will automatically link to\n# tags of other repositories already using CodeDocs. List each repository to\n# link with by giving its location in the form of owner/repository.\n# For example:\n#   TAGLINKS = doxygen/doxygen CodeDocs/osg\n# Note: these repositories must already be built on CodeDocs.\n\nTAGLINKS =\n"
  },
  {
    "path": ".gitattributes",
    "content": "# Explicit list for language for file extension\n*.h linguist-language=C\n*.c linguist-language=C"
  },
  {
    "path": ".github/PULL_REQUEST_TEMPLATE/minor.md",
    "content": "<!--- Use this only if you've made non-breaking improvements or bugfixes -->\n\n## Description\n<!--- Describe your changes in few words/sentences. If your pull request is related to an issue, please put `Closes #issueNumber` or `Related to #issueNumber` sentence here. -->\n\n## Checklist\n<!--- Go over all the following points, and put an `x` in all the boxes that apply. -->\n<!--- If you're unsure about any of these, don't hesitate to ask. We're here to help! -->\n- [ ] My code follows the code style of this project.\n- [ ] My change requires a change to the documentation.\n- [ ] I have updated the documentation accordingly.\n"
  },
  {
    "path": ".github/PULL_REQUEST_TEMPLATE/new_component.md",
    "content": "<!--- Use this only if you've created new ACE component (manager, util, etc.). Please provide a name of your newly created ACE component in title of pull request. -->\n\n## Description\n<!--- Describe your changes in few sentences. If your pull request is related to an issue, please put `Closes #issueNumber` or `Related to #issueNumber` sentence here. -->\n\n## Motivation and Context\n<!--- Why is this change required? What problem does it solve? -->\n\n## ACE inclusion self-assessment\n<!--- It's most likely that we'll include your code in ACE's codebase anyway, however please take a few minutes to answer following questions, which will allow making more conscious decision. -->\n\n**Are there significantly different solutions to same problem? If so, is it the most common/generic one?**\n\n<!--- Please answer here -->\n\n**Are other solutions better and should ACE incorporate it instead of this change in the long run?**\n\n<!--- Please answer here -->\n\n**Is given functionality needed or nice to have for most of games? Is it used often in tandem with ACE?**\n\n<!--- Please answer here -->\n\n**Is it small/simple enough to not require much maintenance?**\n\n<!--- Please answer here -->\n\n**Is the functionality related to a core Amiga concept?**\n\n<!--- Please answer here -->\n\n**Is it entirely, or its ACE interface, written by core ACE team or frequent contributors?**\n\n<!--- Please answer here -->\n\n**Is it a building block or dependency for other parts of code? How much coupling there is between this part and rest of ACE code?**\n\n<!--- Please answer here -->\n\n**Does it allow making significantly better games at reasonable performance cost?**\n\n<!--- Please answer here -->\n\n**Is most of the code first-party?**\n\n<!--- Please answer here -->\n\n**Does it require additions/changes/removal of some other parts of ACE functionality/tooling for its use?**\n\n<!--- Please answer here -->\n\n## How Has This Been Tested?\n<!--- Please describe in detail how you tested your changes. -->\n<!--- Especially point out in which productions it was used so far -->\n\n## Types of changes\n<!--- What types of changes does your code introduce? Put an `x` in all the boxes that apply: -->\n- [ ] Bug fix (non-breaking change which fixes an issue)\n- [ ] New feature (non-breaking change which adds functionality)\n- [ ] Breaking change (fix or feature that would cause existing functionality to change)\n\n## Checklist\n<!--- Go over all the following points, and put an `x` in all the boxes that apply. -->\n<!--- If you're unsure about any of these, don't hesitate to ask. We're here to help! -->\n- [ ] My code follows the code style of this project.\n- [ ] My change requires a change to existing documentation.\n- [ ] My change requires a new chapter in documentation's tutorial.\n- [ ] I have updated the documentation accordingly.\n"
  },
  {
    "path": ".github/PULL_REQUEST_TEMPLATE/significant_changes.md",
    "content": "<!--- Use this only if you've made significant changes to ACE's inner workings. -->\n\n## Description\n<!--- Describe your changes in few sentences. If your pull request is related to an issue, please put `Closes #issueNumber` or `Related to #issueNumber` sentence here. -->\n\n## Motivation and Context\n<!--- Why is this change required? What problem does it solve? -->\n\n## How Has This Been Tested?\n<!--- Please describe in detail how you tested your changes. -->\n<!--- Especially point out in which productions it was used so far -->\n\n## Types of changes\n<!--- What types of changes does your code introduce? Put an `x` in all the boxes that apply: -->\n- [ ] Bug fix (non-breaking change which fixes an issue)\n- [ ] New feature (non-breaking change which adds functionality)\n- [ ] Breaking change (fix or feature that would cause existing functionality to change)\n\n## Checklist\n<!--- Go over all the following points, and put an `x` in all the boxes that apply. -->\n<!--- If you're unsure about any of these, don't hesitate to ask. We're here to help! -->\n- [ ] My code follows the code style of this project.\n- [ ] My change requires a change to the documentation.\n- [ ] I have updated the documentation accordingly.\n"
  },
  {
    "path": ".github/pull_request_template.md",
    "content": "Please go the the `Preview` tab and select the appropriate sub-template:\n\n* [New component](?expand=1&template=new_component.md)\n* [Significant changes](?expand=1&template=significant_changes.md)\n* [Small and non-breaking improvements or bugfixes](?expand=1&template=minor.md)\n"
  },
  {
    "path": ".gitignore",
    "content": ".idea/\r\n**/.vscode/*\r\nace\\.code-workspace\r\n\r\nbuild/\r\nlib/\r\nbin/\r\n\r\n# Showcase\r\nshowcase/showcase\r\nshowcase/*.bmp\r\nshowcase/memory\\.log\r\nshowcase/game\\.log\r\n\r\n# Tools — ignore built tool binaries and generated/test artifacts dropped next to sources\r\ntools/*/*.exe\r\n*.dasm\r\n\r\nshowcase/NUL\r\n"
  },
  {
    "path": "CMakeLists.txt",
    "content": "cmake_minimum_required(VERSION 3.14.0)\nproject(ACE\n\tLANGUAGES C\n\tDESCRIPTION \"Amiga C Engine\"\n\tHOMEPAGE_URL \"https://github.com/AmigaPorts/ACE\"\n)\n\n# TODO: replace with PROJECT_IS_TOP_LEVEL with cmake 3.21+\nget_directory_property(hasParent PARENT_DIRECTORY)\nif(hasParent)\n\t# needed for helper fns\n\tset(ACE_DIR ${CMAKE_CURRENT_LIST_DIR} PARENT_SCOPE)\nelse()\n\tset(ACE_DIR ${CMAKE_CURRENT_LIST_DIR})\nendif()\n\n# Adhere to GNU filesystem layout conventions\ninclude(GNUInstallDirs)\n\n# Lowercase project name for binaries and packaging\nstring(TOLOWER ${PROJECT_NAME} PROJECT_NAME_LOWER)\n\n# Version number in format X.Y.Z\nset(VER_X 0)\nset(VER_Y 0)\nset(VER_Z 1)\nset(VER_FULL \"${VER_X}.${VER_Y}.${VER_Z}\")\n\nif(NOT AMIGA)\n\tmessage(SEND_ERROR \"[ACE] This project only compiles for Amiga\")\nendif()\n\nfile(GLOB_RECURSE SOURCES src/ace/*.c src/fixmath/*.c)\nfile(GLOB HEADERS_ACE include/ace/*.h)\nfile(GLOB HEADERS_ACE_GENERIC include/ace/generic/*.h)\nfile(GLOB HEADERS_ACE_UTILS include/ace/utils/*.h)\nfile(GLOB HEADERS_ACE_MANAGERS include/ace/managers/*.h)\nfile(GLOB HEADERS_ACE_MANAGERS_VP include/ace/managers/viewport/*.h)\nfile(GLOB HEADERS_FIXMATH include/fixmath/*.h)\nset(\n\tHEADERS\n\t${HEADERS_ACE} ${HEADERS_ACE_GENERIC} ${HEADERS_ACE_UTILS}\n\t${HEADERS_ACE_MANAGERS} ${HEADERS_ACE_MANAGERS_VP} ${HEADERS_FIXMATH}\n)\n\ninclude(cmake/ace_config.cmake)\n\n# Linux/other UNIX get a lower-case binary name\nset(TARGET_NAME ${PROJECT_NAME_LOWER})\n\nadd_library(${TARGET_NAME} ${ACE_LIBRARY_KIND} ${SOURCES} ${HEADERS})\n\nset(CMAKE_C_STANDARD 11)\ntarget_compile_definitions(${TARGET_NAME} PUBLIC AMIGA)\ntarget_compile_options(${TARGET_NAME} PRIVATE $<$<OR:$<COMPILE_LANGUAGE:CXX>,$<COMPILE_LANGUAGE:C>>:-Wall -Wextra>)\ntarget_compile_options(${TARGET_NAME} PUBLIC $<$<OR:$<COMPILE_LANGUAGE:CXX>,$<COMPILE_LANGUAGE:C>>:-fomit-frame-pointer>)\n\nif(ACE_DEBUG)\n\ttarget_compile_definitions(${TARGET_NAME} PUBLIC ACE_DEBUG)\nendif()\n\nif(ACE_DEBUG_UAE)\n\ttarget_compile_definitions(${TARGET_NAME} PUBLIC ACE_DEBUG_UAE)\nendif()\n\nif(NOT ACE_BOB_WRAP_Y)\n\ttarget_compile_definitions(${TARGET_NAME} PUBLIC ACE_NO_BOB_WRAP_Y)\nendif()\nif(ACE_BOB_PRISTINE_BUFFER)\n\ttarget_compile_definitions(${TARGET_NAME} PUBLIC ACE_BOB_PRISTINE_BUFFER)\nendif()\nif(ACE_USE_ECS_FEATURES)\n\ttarget_compile_definitions(${TARGET_NAME} PUBLIC ACE_USE_ECS_FEATURES)\nendif()\ntarget_compile_definitions(${TARGET_NAME} PUBLIC ACE_TILEBUFFER_TILE_TYPE=${ACE_TILEBUFFER_TILE_TYPE})\nif(ACE_SCROLLBUFFER_POT_BITMAP_HEIGHT)\n\ttarget_compile_definitions(${TARGET_NAME} PUBLIC ACE_SCROLLBUFFER_POT_BITMAP_HEIGHT)\nendif()\nif(ACE_SCROLLBUFFER_ENABLE_SCROLL_X)\n\ttarget_compile_definitions(${TARGET_NAME} PUBLIC ACE_SCROLLBUFFER_ENABLE_SCROLL_X)\nendif()\nif(ACE_SCROLLBUFFER_ENABLE_SCROLL_Y)\n\ttarget_compile_definitions(${TARGET_NAME} PUBLIC ACE_SCROLLBUFFER_ENABLE_SCROLL_Y)\nendif()\ntarget_compile_definitions(${TARGET_NAME} PUBLIC ACE_SCROLLBUFFER_X_MARGIN_SIZE=${ACE_SCROLLBUFFER_X_MARGIN_SIZE})\ntarget_compile_definitions(${TARGET_NAME} PUBLIC ACE_SCROLLBUFFER_Y_MARGIN_SIZE=${ACE_SCROLLBUFFER_Y_MARGIN_SIZE})\n\nif(ACE_USE_AGA_FEATURES)\n\ttarget_compile_definitions(${TARGET_NAME} PUBLIC ACE_USE_ECS_FEATURES ACE_USE_AGA_FEATURES)\nendif()\n\nif(M68K_COMPILER MATCHES \"Bartman\")\n\tinclude(cmake/CPM.cmake)\n\tCPMAddPackage(\n\t\tNAME bartman_gcc_support\n\t\tGITHUB_REPOSITORY AmigaPorts/bartman_gcc_support\n\t\tGIT_TAG latest\n\t)\n\t# Workaround for nested OBJECT library\n\t# https://stackoverflow.com/questions/71040175\n\ttarget_link_libraries(${TARGET_NAME} PUBLIC bartman_gcc_support \"$<TARGET_OBJECTS:bartman_gcc_support>\")\nendif()\nif(M68K_COMPILER MATCHES \"Bartman\" OR USE_MINI_STD)\n\ttarget_include_directories(${TARGET_NAME} PUBLIC ${PROJECT_SOURCE_DIR}/include/mini_std)\n\tfile(GLOB SOURCES_MINI_STD src/mini_std/*.c)\n\tfile(GLOB HEADERS_MINI_STD include/mini_std/*.h)\n\ttarget_compile_definitions(${TARGET_NAME} PRIVATE PRINTF_DISABLE_SUPPORT_FLOAT PRINTF_DISABLE_SUPPORT_LONG_LONG)\n\ttarget_sources(${TARGET_NAME} PRIVATE ${SOURCES_MINI_STD} ${HEADERS_MINI_STD})\n\tmessage(STATUS \"[ACE] Using mini std\")\nendif()\n\ntarget_include_directories(${TARGET_NAME} PUBLIC ${PROJECT_SOURCE_DIR}/include)\n\ninclude(cmake/ace_install.cmake)\ninclude(cmake/ace_functions.cmake)\n\n"
  },
  {
    "path": "Doxyfile",
    "content": "# Doxyfile 1.8.11\n\n# This file describes the settings to be used by the documentation system\n# doxygen (www.doxygen.org) for a project.\n#\n# All text after a double hash (##) is considered a comment and is placed in\n# front of the TAG it is preceding.\n#\n# All text after a single hash (#) is considered a comment and will be ignored.\n# The format is:\n# TAG = value [value, ...]\n# For lists, items can also be appended using:\n# TAG += value [value, ...]\n# Values that contain spaces should be placed between quotes (\\\" \\\").\n\n#---------------------------------------------------------------------------\n# Project related configuration options\n#---------------------------------------------------------------------------\n\n# This tag specifies the encoding used for all characters in the config file\n# that follow. The default is UTF-8 which is also the encoding used for all text\n# before the first occurrence of this tag. Doxygen uses libiconv (or the iconv\n# built into libc) for the transcoding. See http://www.gnu.org/software/libiconv\n# for the list of possible encodings.\n# The default value is: UTF-8.\n\nDOXYFILE_ENCODING      = UTF-8\n\n# The PROJECT_NAME tag is a single word (or a sequence of words surrounded by\n# double-quotes, unless you are using Doxywizard) that should identify the\n# project for which the documentation is generated. This name is used in the\n# title of most generated pages and in a few other places.\n# The default value is: My Project.\n\nPROJECT_NAME           = \"ACE\"\n\n# The PROJECT_NUMBER tag can be used to enter a project or revision number. This\n# could be handy for archiving the generated documentation or if some version\n# control system is used.\n\nPROJECT_NUMBER         =\n\n# Using the PROJECT_BRIEF tag one can provide an optional one line description\n# for a project that appears at the top of each page and should give viewer a\n# quick idea about the purpose of the project. Keep the description short.\n\nPROJECT_BRIEF          = \"Amiga C Engine\"\n\n# With the PROJECT_LOGO tag one can specify a logo or an icon that is included\n# in the documentation. The maximum height of the logo should not exceed 55\n# pixels and the maximum width should not exceed 200 pixels. Doxygen will copy\n# the logo to the output directory.\n\nPROJECT_LOGO           =\n\n# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path\n# into which the generated documentation will be written. If a relative path is\n# entered, it will be relative to the location where doxygen was started. If\n# left blank the current directory will be used.\n\nOUTPUT_DIRECTORY       = doxygen_docs\n\n# If the CREATE_SUBDIRS tag is set to YES then doxygen will create 4096 sub-\n# directories (in 2 levels) under the output directory of each output format and\n# will distribute the generated files over these directories. Enabling this\n# option can be useful when feeding doxygen a huge amount of source files, where\n# putting all generated files in the same directory would otherwise causes\n# performance problems for the file system.\n# The default value is: NO.\n\nCREATE_SUBDIRS         = NO\n\n# If the ALLOW_UNICODE_NAMES tag is set to YES, doxygen will allow non-ASCII\n# characters to appear in the names of generated files. If set to NO, non-ASCII\n# characters will be escaped, for example _xE3_x81_x84 will be used for Unicode\n# U+3044.\n# The default value is: NO.\n\nALLOW_UNICODE_NAMES    = YES\n\n# The OUTPUT_LANGUAGE tag is used to specify the language in which all\n# documentation generated by doxygen is written. Doxygen will use this\n# information to generate all constant output in the proper language.\n# Possible values are: Afrikaans, Arabic, Armenian, Brazilian, Catalan, Chinese,\n# Chinese-Traditional, Croatian, Czech, Danish, Dutch, English (United States),\n# Esperanto, Farsi (Persian), Finnish, French, German, Greek, Hungarian,\n# Indonesian, Italian, Japanese, Japanese-en (Japanese with English messages),\n# Korean, Korean-en (Korean with English messages), Latvian, Lithuanian,\n# Macedonian, Norwegian, Persian (Farsi), Polish, Portuguese, Romanian, Russian,\n# Serbian, Serbian-Cyrillic, Slovak, Slovene, Spanish, Swedish, Turkish,\n# Ukrainian and Vietnamese.\n# The default value is: English.\n\nOUTPUT_LANGUAGE        = English\n\n# If the BRIEF_MEMBER_DESC tag is set to YES, doxygen will include brief member\n# descriptions after the members that are listed in the file and class\n# documentation (similar to Javadoc). Set to NO to disable this.\n# The default value is: YES.\n\nBRIEF_MEMBER_DESC      = YES\n\n# If the REPEAT_BRIEF tag is set to YES, doxygen will prepend the brief\n# description of a member or function before the detailed description\n#\n# Note: If both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the\n# brief descriptions will be completely suppressed.\n# The default value is: YES.\n\nREPEAT_BRIEF           = YES\n\n# This tag implements a quasi-intelligent brief description abbreviator that is\n# used to form the text in various listings. Each string in this list, if found\n# as the leading text of the brief description, will be stripped from the text\n# and the result, after processing the whole list, is used as the annotated\n# text. Otherwise, the brief description is used as-is. If left blank, the\n# following values are used ($name is automatically replaced with the name of\n# the entity):The $name class, The $name widget, The $name file, is, provides,\n# specifies, contains, represents, a, an and the.\n\nABBREVIATE_BRIEF       =\n\n# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then\n# doxygen will generate a detailed section even if there is only a brief\n# description.\n# The default value is: NO.\n\nALWAYS_DETAILED_SEC    = NO\n\n# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all\n# inherited members of a class in the documentation of that class as if those\n# members were ordinary class members. Constructors, destructors and assignment\n# operators of the base classes will not be shown.\n# The default value is: NO.\n\nINLINE_INHERITED_MEMB  = NO\n\n# If the FULL_PATH_NAMES tag is set to YES, doxygen will prepend the full path\n# before files name in the file list and in the header files. If set to NO the\n# shortest path that makes the file name unique will be used\n# The default value is: YES.\n\nFULL_PATH_NAMES        = YES\n\n# The STRIP_FROM_PATH tag can be used to strip a user-defined part of the path.\n# Stripping is only done if one of the specified strings matches the left-hand\n# part of the path. The tag can be used to show relative paths in the file list.\n# If left blank the directory from which doxygen is run is used as the path to\n# strip.\n#\n# Note that you can specify absolute paths here, but also relative paths, which\n# will be relative from the directory where doxygen is started.\n# This tag requires that the tag FULL_PATH_NAMES is set to YES.\n\nSTRIP_FROM_PATH        =\n\n# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the\n# path mentioned in the documentation of a class, which tells the reader which\n# header file to include in order to use a class. If left blank only the name of\n# the header file containing the class definition is used. Otherwise one should\n# specify the list of include paths that are normally passed to the compiler\n# using the -I flag.\n\nSTRIP_FROM_INC_PATH    =\n\n# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter (but\n# less readable) file names. This can be useful is your file systems doesn't\n# support long names like on DOS, Mac, or CD-ROM.\n# The default value is: NO.\n\nSHORT_NAMES            = NO\n\n# If the JAVADOC_AUTOBRIEF tag is set to YES then doxygen will interpret the\n# first line (until the first dot) of a Javadoc-style comment as the brief\n# description. If set to NO, the Javadoc-style will behave just like regular Qt-\n# style comments (thus requiring an explicit @brief command for a brief\n# description.)\n# The default value is: NO.\n\nJAVADOC_AUTOBRIEF      = NO\n\n# If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first\n# line (until the first dot) of a Qt-style comment as the brief description. If\n# set to NO, the Qt-style will behave just like regular Qt-style comments (thus\n# requiring an explicit \\brief command for a brief description.)\n# The default value is: NO.\n\nQT_AUTOBRIEF           = NO\n\n# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make doxygen treat a\n# multi-line C++ special comment block (i.e. a block of //! or /// comments) as\n# a brief description. This used to be the default behavior. The new default is\n# to treat a multi-line C++ comment block as a detailed description. Set this\n# tag to YES if you prefer the old behavior instead.\n#\n# Note that setting this tag to YES also means that rational rose comments are\n# not recognized any more.\n# The default value is: NO.\n\nMULTILINE_CPP_IS_BRIEF = NO\n\n# If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the\n# documentation from any documented member that it re-implements.\n# The default value is: YES.\n\nINHERIT_DOCS           = YES\n\n# If the SEPARATE_MEMBER_PAGES tag is set to YES then doxygen will produce a new\n# page for each member. If set to NO, the documentation of a member will be part\n# of the file/class/namespace that contains it.\n# The default value is: NO.\n\nSEPARATE_MEMBER_PAGES  = NO\n\n# The TAB_SIZE tag can be used to set the number of spaces in a tab. Doxygen\n# uses this value to replace tabs by spaces in code fragments.\n# Minimum value: 1, maximum value: 16, default value: 4.\n\nTAB_SIZE               = 2\n\n# This tag can be used to specify a number of aliases that act as commands in\n# the documentation. An alias has the form:\n# name=value\n# For example adding\n# \"sideeffect=@par Side Effects:\\n\"\n# will allow you to put the command \\sideeffect (or @sideeffect) in the\n# documentation, which will result in a user-defined paragraph with heading\n# \"Side Effects:\". You can put \\n's in the value part of an alias to insert\n# newlines.\n\nALIASES                =\n\n# This tag can be used to specify a number of word-keyword mappings (TCL only).\n# A mapping has the form \"name=value\". For example adding \"class=itcl::class\"\n# will allow you to use the command class in the itcl::class meaning.\n\nTCL_SUBST              =\n\n# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources\n# only. Doxygen will then generate output that is more tailored for C. For\n# instance, some of the names that are used will be different. The list of all\n# members will be omitted, etc.\n# The default value is: NO.\n\nOPTIMIZE_OUTPUT_FOR_C  = NO\n\n# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java or\n# Python sources only. Doxygen will then generate output that is more tailored\n# for that language. For instance, namespaces will be presented as packages,\n# qualified scopes will look different, etc.\n# The default value is: NO.\n\nOPTIMIZE_OUTPUT_JAVA   = NO\n\n# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran\n# sources. Doxygen will then generate output that is tailored for Fortran.\n# The default value is: NO.\n\nOPTIMIZE_FOR_FORTRAN   = NO\n\n# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL\n# sources. Doxygen will then generate output that is tailored for VHDL.\n# The default value is: NO.\n\nOPTIMIZE_OUTPUT_VHDL   = NO\n\n# Doxygen selects the parser to use depending on the extension of the files it\n# parses. With this tag you can assign which parser to use for a given\n# extension. Doxygen has a built-in mapping, but you can override or extend it\n# using this tag. The format is ext=language, where ext is a file extension, and\n# language is one of the parsers supported by doxygen: IDL, Java, Javascript,\n# C#, C, C++, D, PHP, Objective-C, Python, Fortran (fixed format Fortran:\n# FortranFixed, free formatted Fortran: FortranFree, unknown formatted Fortran:\n# Fortran. In the later case the parser tries to guess whether the code is fixed\n# or free formatted code, this is the default for Fortran type files), VHDL. For\n# instance to make doxygen treat .inc files as Fortran files (default is PHP),\n# and .f files as C (default is Fortran), use: inc=Fortran f=C.\n#\n# Note: For files without extension you can use no_extension as a placeholder.\n#\n# Note that for custom extensions you also need to set FILE_PATTERNS otherwise\n# the files are not read by doxygen.\n\nEXTENSION_MAPPING      =\n\n# If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments\n# according to the Markdown format, which allows for more readable\n# documentation. See http://daringfireball.net/projects/markdown/ for details.\n# The output of markdown processing is further processed by doxygen, so you can\n# mix doxygen, HTML, and XML commands with Markdown formatting. Disable only in\n# case of backward compatibilities issues.\n# The default value is: YES.\n\nMARKDOWN_SUPPORT       = YES\n\n# When enabled doxygen tries to link words that correspond to documented\n# classes, or namespaces to their corresponding documentation. Such a link can\n# be prevented in individual cases by putting a % sign in front of the word or\n# globally by setting AUTOLINK_SUPPORT to NO.\n# The default value is: YES.\n\nAUTOLINK_SUPPORT       = YES\n\n# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want\n# to include (a tag file for) the STL sources as input, then you should set this\n# tag to YES in order to let doxygen match functions declarations and\n# definitions whose arguments contain STL classes (e.g. func(std::string);\n# versus func(std::string) {}). This also make the inheritance and collaboration\n# diagrams that involve STL classes more complete and accurate.\n# The default value is: NO.\n\nBUILTIN_STL_SUPPORT    = NO\n\n# If you use Microsoft's C++/CLI language, you should set this option to YES to\n# enable parsing support.\n# The default value is: NO.\n\nCPP_CLI_SUPPORT        = NO\n\n# Set the SIP_SUPPORT tag to YES if your project consists of sip (see:\n# http://www.riverbankcomputing.co.uk/software/sip/intro) sources only. Doxygen\n# will parse them like normal C++ but will assume all classes use public instead\n# of private inheritance when no explicit protection keyword is present.\n# The default value is: NO.\n\nSIP_SUPPORT            = NO\n\n# For Microsoft's IDL there are propget and propput attributes to indicate\n# getter and setter methods for a property. Setting this option to YES will make\n# doxygen to replace the get and set methods by a property in the documentation.\n# This will only work if the methods are indeed getting or setting a simple\n# type. If this is not the case, or you want to show the methods anyway, you\n# should set this option to NO.\n# The default value is: YES.\n\nIDL_PROPERTY_SUPPORT   = YES\n\n# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC\n# tag is set to YES then doxygen will reuse the documentation of the first\n# member in the group (if any) for the other members of the group. By default\n# all members of a group must be documented explicitly.\n# The default value is: NO.\n\nDISTRIBUTE_GROUP_DOC   = NO\n\n# If one adds a struct or class to a group and this option is enabled, then also\n# any nested class or struct is added to the same group. By default this option\n# is disabled and one has to add nested compounds explicitly via \\ingroup.\n# The default value is: NO.\n\nGROUP_NESTED_COMPOUNDS = NO\n\n# Set the SUBGROUPING tag to YES to allow class member groups of the same type\n# (for instance a group of public functions) to be put as a subgroup of that\n# type (e.g. under the Public Functions section). Set it to NO to prevent\n# subgrouping. Alternatively, this can be done per class using the\n# \\nosubgrouping command.\n# The default value is: YES.\n\nSUBGROUPING            = YES\n\n# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and unions\n# are shown inside the group in which they are included (e.g. using \\ingroup)\n# instead of on a separate page (for HTML and Man pages) or section (for LaTeX\n# and RTF).\n#\n# Note that this feature does not work in combination with\n# SEPARATE_MEMBER_PAGES.\n# The default value is: NO.\n\nINLINE_GROUPED_CLASSES = NO\n\n# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and unions\n# with only public data fields or simple typedef fields will be shown inline in\n# the documentation of the scope in which they are defined (i.e. file,\n# namespace, or group documentation), provided this scope is documented. If set\n# to NO, structs, classes, and unions are shown on a separate page (for HTML and\n# Man pages) or section (for LaTeX and RTF).\n# The default value is: NO.\n\nINLINE_SIMPLE_STRUCTS  = NO\n\n# When TYPEDEF_HIDES_STRUCT tag is enabled, a typedef of a struct, union, or\n# enum is documented as struct, union, or enum with the name of the typedef. So\n# typedef struct TypeS {} TypeT, will appear in the documentation as a struct\n# with name TypeT. When disabled the typedef will appear as a member of a file,\n# namespace, or class. And the struct will be named TypeS. This can typically be\n# useful for C code in case the coding convention dictates that all compound\n# types are typedef'ed and only the typedef is referenced, never the tag name.\n# The default value is: NO.\n\nTYPEDEF_HIDES_STRUCT   = NO\n\n# The size of the symbol lookup cache can be set using LOOKUP_CACHE_SIZE. This\n# cache is used to resolve symbols given their name and scope. Since this can be\n# an expensive process and often the same symbol appears multiple times in the\n# code, doxygen keeps a cache of pre-resolved symbols. If the cache is too small\n# doxygen will become slower. If the cache is too large, memory is wasted. The\n# cache size is given by this formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range\n# is 0..9, the default is 0, corresponding to a cache size of 2^16=65536\n# symbols. At the end of a run doxygen will report the cache usage and suggest\n# the optimal cache size from a speed point of view.\n# Minimum value: 0, maximum value: 9, default value: 0.\n\nLOOKUP_CACHE_SIZE      = 0\n\n#---------------------------------------------------------------------------\n# Build related configuration options\n#---------------------------------------------------------------------------\n\n# If the EXTRACT_ALL tag is set to YES, doxygen will assume all entities in\n# documentation are documented, even if no documentation was available. Private\n# class members and static file members will be hidden unless the\n# EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES.\n# Note: This will also disable the warnings about undocumented members that are\n# normally produced when WARNINGS is set to YES.\n# The default value is: NO.\n\nEXTRACT_ALL            = NO\n\n# If the EXTRACT_PRIVATE tag is set to YES, all private members of a class will\n# be included in the documentation.\n# The default value is: NO.\n\nEXTRACT_PRIVATE        = NO\n\n# If the EXTRACT_PACKAGE tag is set to YES, all members with package or internal\n# scope will be included in the documentation.\n# The default value is: NO.\n\nEXTRACT_PACKAGE        = NO\n\n# If the EXTRACT_STATIC tag is set to YES, all static members of a file will be\n# included in the documentation.\n# The default value is: NO.\n\nEXTRACT_STATIC         = YES\n\n# If the EXTRACT_LOCAL_CLASSES tag is set to YES, classes (and structs) defined\n# locally in source files will be included in the documentation. If set to NO,\n# only classes defined in header files are included. Does not have any effect\n# for Java sources.\n# The default value is: YES.\n\nEXTRACT_LOCAL_CLASSES  = YES\n\n# This flag is only useful for Objective-C code. If set to YES, local methods,\n# which are defined in the implementation section but not in the interface are\n# included in the documentation. If set to NO, only methods in the interface are\n# included.\n# The default value is: NO.\n\nEXTRACT_LOCAL_METHODS  = NO\n\n# If this flag is set to YES, the members of anonymous namespaces will be\n# extracted and appear in the documentation as a namespace called\n# 'anonymous_namespace{file}', where file will be replaced with the base name of\n# the file that contains the anonymous namespace. By default anonymous namespace\n# are hidden.\n# The default value is: NO.\n\nEXTRACT_ANON_NSPACES   = NO\n\n# If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all\n# undocumented members inside documented classes or files. If set to NO these\n# members will be included in the various overviews, but no documentation\n# section is generated. This option has no effect if EXTRACT_ALL is enabled.\n# The default value is: NO.\n\nHIDE_UNDOC_MEMBERS     = NO\n\n# If the HIDE_UNDOC_CLASSES tag is set to YES, doxygen will hide all\n# undocumented classes that are normally visible in the class hierarchy. If set\n# to NO, these classes will be included in the various overviews. This option\n# has no effect if EXTRACT_ALL is enabled.\n# The default value is: NO.\n\nHIDE_UNDOC_CLASSES     = NO\n\n# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend\n# (class|struct|union) declarations. If set to NO, these declarations will be\n# included in the documentation.\n# The default value is: NO.\n\nHIDE_FRIEND_COMPOUNDS  = NO\n\n# If the HIDE_IN_BODY_DOCS tag is set to YES, doxygen will hide any\n# documentation blocks found inside the body of a function. If set to NO, these\n# blocks will be appended to the function's detailed documentation block.\n# The default value is: NO.\n\nHIDE_IN_BODY_DOCS      = NO\n\n# The INTERNAL_DOCS tag determines if documentation that is typed after a\n# \\internal command is included. If the tag is set to NO then the documentation\n# will be excluded. Set it to YES to include the internal documentation.\n# The default value is: NO.\n\nINTERNAL_DOCS          = NO\n\n# If the CASE_SENSE_NAMES tag is set to NO then doxygen will only generate file\n# names in lower-case letters. If set to YES, upper-case letters are also\n# allowed. This is useful if you have classes or files whose names only differ\n# in case and if your file system supports case sensitive file names. Windows\n# and Mac users are advised to set this option to NO.\n# The default value is: system dependent.\n\nCASE_SENSE_NAMES       = YES\n\n# If the HIDE_SCOPE_NAMES tag is set to NO then doxygen will show members with\n# their full class and namespace scopes in the documentation. If set to YES, the\n# scope will be hidden.\n# The default value is: NO.\n\nHIDE_SCOPE_NAMES       = NO\n\n# If the HIDE_COMPOUND_REFERENCE tag is set to NO (default) then doxygen will\n# append additional text to a page's title, such as Class Reference. If set to\n# YES the compound reference will be hidden.\n# The default value is: NO.\n\nHIDE_COMPOUND_REFERENCE= NO\n\n# If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of\n# the files that are included by a file in the documentation of that file.\n# The default value is: YES.\n\nSHOW_INCLUDE_FILES     = YES\n\n# If the SHOW_GROUPED_MEMB_INC tag is set to YES then Doxygen will add for each\n# grouped member an include statement to the documentation, telling the reader\n# which file to include in order to use the member.\n# The default value is: NO.\n\nSHOW_GROUPED_MEMB_INC  = NO\n\n# If the FORCE_LOCAL_INCLUDES tag is set to YES then doxygen will list include\n# files with double quotes in the documentation rather than with sharp brackets.\n# The default value is: NO.\n\nFORCE_LOCAL_INCLUDES   = NO\n\n# If the INLINE_INFO tag is set to YES then a tag [inline] is inserted in the\n# documentation for inline members.\n# The default value is: YES.\n\nINLINE_INFO            = YES\n\n# If the SORT_MEMBER_DOCS tag is set to YES then doxygen will sort the\n# (detailed) documentation of file and class members alphabetically by member\n# name. If set to NO, the members will appear in declaration order.\n# The default value is: YES.\n\nSORT_MEMBER_DOCS       = YES\n\n# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the brief\n# descriptions of file, namespace and class members alphabetically by member\n# name. If set to NO, the members will appear in declaration order. Note that\n# this will also influence the order of the classes in the class list.\n# The default value is: NO.\n\nSORT_BRIEF_DOCS        = NO\n\n# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the\n# (brief and detailed) documentation of class members so that constructors and\n# destructors are listed first. If set to NO the constructors will appear in the\n# respective orders defined by SORT_BRIEF_DOCS and SORT_MEMBER_DOCS.\n# Note: If SORT_BRIEF_DOCS is set to NO this option is ignored for sorting brief\n# member documentation.\n# Note: If SORT_MEMBER_DOCS is set to NO this option is ignored for sorting\n# detailed member documentation.\n# The default value is: NO.\n\nSORT_MEMBERS_CTORS_1ST = YES\n\n# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the hierarchy\n# of group names into alphabetical order. If set to NO the group names will\n# appear in their defined order.\n# The default value is: NO.\n\nSORT_GROUP_NAMES       = NO\n\n# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be sorted by\n# fully-qualified names, including namespaces. If set to NO, the class list will\n# be sorted only by class name, not including the namespace part.\n# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES.\n# Note: This option applies only to the class list, not to the alphabetical\n# list.\n# The default value is: NO.\n\nSORT_BY_SCOPE_NAME     = NO\n\n# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to do proper\n# type resolution of all parameters of a function it will reject a match between\n# the prototype and the implementation of a member function even if there is\n# only one candidate or it is obvious which candidate to choose by doing a\n# simple string match. By disabling STRICT_PROTO_MATCHING doxygen will still\n# accept a match between prototype and implementation in such cases.\n# The default value is: NO.\n\nSTRICT_PROTO_MATCHING  = NO\n\n# The GENERATE_TODOLIST tag can be used to enable (YES) or disable (NO) the todo\n# list. This list is created by putting \\todo commands in the documentation.\n# The default value is: YES.\n\nGENERATE_TODOLIST      = YES\n\n# The GENERATE_TESTLIST tag can be used to enable (YES) or disable (NO) the test\n# list. This list is created by putting \\test commands in the documentation.\n# The default value is: YES.\n\nGENERATE_TESTLIST      = YES\n\n# The GENERATE_BUGLIST tag can be used to enable (YES) or disable (NO) the bug\n# list. This list is created by putting \\bug commands in the documentation.\n# The default value is: YES.\n\nGENERATE_BUGLIST       = YES\n\n# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or disable (NO)\n# the deprecated list. This list is created by putting \\deprecated commands in\n# the documentation.\n# The default value is: YES.\n\nGENERATE_DEPRECATEDLIST= YES\n\n# The ENABLED_SECTIONS tag can be used to enable conditional documentation\n# sections, marked by \\if <section_label> ... \\endif and \\cond <section_label>\n# ... \\endcond blocks.\n\nENABLED_SECTIONS       =\n\n# The MAX_INITIALIZER_LINES tag determines the maximum number of lines that the\n# initial value of a variable or macro / define can have for it to appear in the\n# documentation. If the initializer consists of more lines than specified here\n# it will be hidden. Use a value of 0 to hide initializers completely. The\n# appearance of the value of individual variables and macros / defines can be\n# controlled using \\showinitializer or \\hideinitializer command in the\n# documentation regardless of this setting.\n# Minimum value: 0, maximum value: 10000, default value: 30.\n\nMAX_INITIALIZER_LINES  = 30\n\n# Set the SHOW_USED_FILES tag to NO to disable the list of files generated at\n# the bottom of the documentation of classes and structs. If set to YES, the\n# list will mention the files that were used to generate the documentation.\n# The default value is: YES.\n\nSHOW_USED_FILES        = YES\n\n# Set the SHOW_FILES tag to NO to disable the generation of the Files page. This\n# will remove the Files entry from the Quick Index and from the Folder Tree View\n# (if specified).\n# The default value is: YES.\n\nSHOW_FILES             = YES\n\n# Set the SHOW_NAMESPACES tag to NO to disable the generation of the Namespaces\n# page. This will remove the Namespaces entry from the Quick Index and from the\n# Folder Tree View (if specified).\n# The default value is: YES.\n\nSHOW_NAMESPACES        = YES\n\n# The FILE_VERSION_FILTER tag can be used to specify a program or script that\n# doxygen should invoke to get the current version for each file (typically from\n# the version control system). Doxygen will invoke the program by executing (via\n# popen()) the command command input-file, where command is the value of the\n# FILE_VERSION_FILTER tag, and input-file is the name of an input file provided\n# by doxygen. Whatever the program writes to standard output is used as the file\n# version. For an example see the documentation.\n\nFILE_VERSION_FILTER    =\n\n# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed\n# by doxygen. The layout file controls the global structure of the generated\n# output files in an output format independent way. To create the layout file\n# that represents doxygen's defaults, run doxygen with the -l option. You can\n# optionally specify a file name after the option, if omitted DoxygenLayout.xml\n# will be used as the name of the layout file.\n#\n# Note that if you run doxygen from a directory containing a file called\n# DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE\n# tag is left empty.\n\nLAYOUT_FILE            =\n\n# The CITE_BIB_FILES tag can be used to specify one or more bib files containing\n# the reference definitions. This must be a list of .bib files. The .bib\n# extension is automatically appended if omitted. This requires the bibtex tool\n# to be installed. See also http://en.wikipedia.org/wiki/BibTeX for more info.\n# For LaTeX the style of the bibliography can be controlled using\n# LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the\n# search path. See also \\cite for info how to create references.\n\nCITE_BIB_FILES         =\n\n#---------------------------------------------------------------------------\n# Configuration options related to warning and progress messages\n#---------------------------------------------------------------------------\n\n# The QUIET tag can be used to turn on/off the messages that are generated to\n# standard output by doxygen. If QUIET is set to YES this implies that the\n# messages are off.\n# The default value is: NO.\n\nQUIET                  = NO\n\n# The WARNINGS tag can be used to turn on/off the warning messages that are\n# generated to standard error (stderr) by doxygen. If WARNINGS is set to YES\n# this implies that the warnings are on.\n#\n# Tip: Turn warnings on while writing the documentation.\n# The default value is: YES.\n\nWARNINGS               = YES\n\n# If the WARN_IF_UNDOCUMENTED tag is set to YES then doxygen will generate\n# warnings for undocumented members. If EXTRACT_ALL is set to YES then this flag\n# will automatically be disabled.\n# The default value is: YES.\n\nWARN_IF_UNDOCUMENTED   = YES\n\n# If the WARN_IF_DOC_ERROR tag is set to YES, doxygen will generate warnings for\n# potential errors in the documentation, such as not documenting some parameters\n# in a documented function, or documenting parameters that don't exist or using\n# markup commands wrongly.\n# The default value is: YES.\n\nWARN_IF_DOC_ERROR      = YES\n\n# This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that\n# are documented, but have no documentation for their parameters or return\n# value. If set to NO, doxygen will only warn about wrong or incomplete\n# parameter documentation, but not about the absence of documentation.\n# The default value is: NO.\n\nWARN_NO_PARAMDOC       = NO\n\n# If the WARN_AS_ERROR tag is set to YES then doxygen will immediately stop when\n# a warning is encountered.\n# The default value is: NO.\n\nWARN_AS_ERROR          = NO\n\n# The WARN_FORMAT tag determines the format of the warning messages that doxygen\n# can produce. The string should contain the $file, $line, and $text tags, which\n# will be replaced by the file and line number from which the warning originated\n# and the warning text. Optionally the format may contain $version, which will\n# be replaced by the version of the file (if it could be obtained via\n# FILE_VERSION_FILTER)\n# The default value is: $file:$line: $text.\n\nWARN_FORMAT            = \"$file:$line: $text\"\n\n# The WARN_LOGFILE tag can be used to specify a file to which warning and error\n# messages should be written. If left blank the output is written to standard\n# error (stderr).\n\nWARN_LOGFILE           =\n\n#---------------------------------------------------------------------------\n# Configuration options related to the input files\n#---------------------------------------------------------------------------\n\n# The INPUT tag is used to specify the files and/or directories that contain\n# documented source files. You may enter file names like myfile.cpp or\n# directories like /usr/src/myproject. Separate the files or directories with\n# spaces. See also FILE_PATTERNS and EXTENSION_MAPPING\n# Note: If this tag is empty the current directory is searched.\n\nINPUT                  = ./src ./include\n\n# This tag can be used to specify the character encoding of the source files\n# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses\n# libiconv (or the iconv built into libc) for the transcoding. See the libiconv\n# documentation (see: http://www.gnu.org/software/libiconv) for the list of\n# possible encodings.\n# The default value is: UTF-8.\n\nINPUT_ENCODING         = UTF-8\n\n# If the value of the INPUT tag contains directories, you can use the\n# FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and\n# *.h) to filter out the source-files in the directories.\n#\n# Note that for custom extensions or not directly supported extensions you also\n# need to set EXTENSION_MAPPING for the extension otherwise the files are not\n# read by doxygen.\n#\n# If left blank the following patterns are tested:*.c, *.cc, *.cxx, *.cpp,\n# *.c++, *.java, *.ii, *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h,\n# *.hh, *.hxx, *.hpp, *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc,\n# *.m, *.markdown, *.md, *.mm, *.dox, *.py, *.pyw, *.f90, *.f, *.for, *.tcl,\n# *.vhd, *.vhdl, *.ucf, *.qsf, *.as and *.js.\n\nFILE_PATTERNS          =\n\n# The RECURSIVE tag can be used to specify whether or not subdirectories should\n# be searched for input files as well.\n# The default value is: NO.\n\nRECURSIVE              = YES\n\n# The EXCLUDE tag can be used to specify files and/or directories that should be\n# excluded from the INPUT source files. This way you can easily exclude a\n# subdirectory from a directory tree whose root is specified with the INPUT tag.\n#\n# Note that relative paths are relative to the directory from which doxygen is\n# run.\n\nEXCLUDE                = ./tools ./showcase\n\n# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or\n# directories that are symbolic links (a Unix file system feature) are excluded\n# from the input.\n# The default value is: NO.\n\nEXCLUDE_SYMLINKS       = NO\n\n# If the value of the INPUT tag contains directories, you can use the\n# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude\n# certain files from those directories.\n#\n# Note that the wildcards are matched against the file with absolute path, so to\n# exclude all test directories for example use the pattern */test/*\n\nEXCLUDE_PATTERNS       =\n\n# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names\n# (namespaces, classes, functions, etc.) that should be excluded from the\n# output. The symbol name can be a fully qualified name, a word, or if the\n# wildcard * is used, a substring. Examples: ANamespace, AClass,\n# AClass::ANamespace, ANamespace::*Test\n#\n# Note that the wildcards are matched against the file with absolute path, so to\n# exclude all test directories use the pattern */test/*\n\nEXCLUDE_SYMBOLS        =\n\n# The EXAMPLE_PATH tag can be used to specify one or more files or directories\n# that contain example code fragments that are included (see the \\include\n# command).\n\nEXAMPLE_PATH           =\n\n# If the value of the EXAMPLE_PATH tag contains directories, you can use the\n# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and\n# *.h) to filter out the source-files in the directories. If left blank all\n# files are included.\n\nEXAMPLE_PATTERNS       =\n\n# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be\n# searched for input files to be used with the \\include or \\dontinclude commands\n# irrespective of the value of the RECURSIVE tag.\n# The default value is: NO.\n\nEXAMPLE_RECURSIVE      = NO\n\n# The IMAGE_PATH tag can be used to specify one or more files or directories\n# that contain images that are to be included in the documentation (see the\n# \\image command).\n\nIMAGE_PATH             =\n\n# The INPUT_FILTER tag can be used to specify a program that doxygen should\n# invoke to filter for each input file. Doxygen will invoke the filter program\n# by executing (via popen()) the command:\n#\n# <filter> <input-file>\n#\n# where <filter> is the value of the INPUT_FILTER tag, and <input-file> is the\n# name of an input file. Doxygen will then use the output that the filter\n# program writes to standard output. If FILTER_PATTERNS is specified, this tag\n# will be ignored.\n#\n# Note that the filter must not add or remove lines; it is applied before the\n# code is scanned, but not when the output code is generated. If lines are added\n# or removed, the anchors will not be placed correctly.\n#\n# Note that for custom extensions or not directly supported extensions you also\n# need to set EXTENSION_MAPPING for the extension otherwise the files are not\n# properly processed by doxygen.\n\nINPUT_FILTER           =\n\n# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern\n# basis. Doxygen will compare the file name with each pattern and apply the\n# filter if there is a match. The filters are a list of the form: pattern=filter\n# (like *.cpp=my_cpp_filter). See INPUT_FILTER for further information on how\n# filters are used. If the FILTER_PATTERNS tag is empty or if none of the\n# patterns match the file name, INPUT_FILTER is applied.\n#\n# Note that for custom extensions or not directly supported extensions you also\n# need to set EXTENSION_MAPPING for the extension otherwise the files are not\n# properly processed by doxygen.\n\nFILTER_PATTERNS        =\n\n# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using\n# INPUT_FILTER) will also be used to filter the input files that are used for\n# producing the source files to browse (i.e. when SOURCE_BROWSER is set to YES).\n# The default value is: NO.\n\nFILTER_SOURCE_FILES    = NO\n\n# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file\n# pattern. A pattern will override the setting for FILTER_PATTERN (if any) and\n# it is also possible to disable source filtering for a specific pattern using\n# *.ext= (so without naming a filter).\n# This tag requires that the tag FILTER_SOURCE_FILES is set to YES.\n\nFILTER_SOURCE_PATTERNS =\n\n# If the USE_MDFILE_AS_MAINPAGE tag refers to the name of a markdown file that\n# is part of the input, its contents will be placed on the main page\n# (index.html). This can be useful if you have a project on for instance GitHub\n# and want to reuse the introduction page also for the doxygen output.\n\nUSE_MDFILE_AS_MAINPAGE =\n\n#---------------------------------------------------------------------------\n# Configuration options related to source browsing\n#---------------------------------------------------------------------------\n\n# If the SOURCE_BROWSER tag is set to YES then a list of source files will be\n# generated. Documented entities will be cross-referenced with these sources.\n#\n# Note: To get rid of all source code in the generated output, make sure that\n# also VERBATIM_HEADERS is set to NO.\n# The default value is: NO.\n\nSOURCE_BROWSER         = NO\n\n# Setting the INLINE_SOURCES tag to YES will include the body of functions,\n# classes and enums directly into the documentation.\n# The default value is: NO.\n\nINLINE_SOURCES         = NO\n\n# Setting the STRIP_CODE_COMMENTS tag to YES will instruct doxygen to hide any\n# special comment blocks from generated source code fragments. Normal C, C++ and\n# Fortran comments will always remain visible.\n# The default value is: YES.\n\nSTRIP_CODE_COMMENTS    = YES\n\n# If the REFERENCED_BY_RELATION tag is set to YES then for each documented\n# function all documented functions referencing it will be listed.\n# The default value is: NO.\n\nREFERENCED_BY_RELATION = NO\n\n# If the REFERENCES_RELATION tag is set to YES then for each documented function\n# all documented entities called/used by that function will be listed.\n# The default value is: NO.\n\nREFERENCES_RELATION    = NO\n\n# If the REFERENCES_LINK_SOURCE tag is set to YES and SOURCE_BROWSER tag is set\n# to YES then the hyperlinks from functions in REFERENCES_RELATION and\n# REFERENCED_BY_RELATION lists will link to the source code. Otherwise they will\n# link to the documentation.\n# The default value is: YES.\n\nREFERENCES_LINK_SOURCE = YES\n\n# If SOURCE_TOOLTIPS is enabled (the default) then hovering a hyperlink in the\n# source code will show a tooltip with additional information such as prototype,\n# brief description and links to the definition and documentation. Since this\n# will make the HTML file larger and loading of large files a bit slower, you\n# can opt to disable this feature.\n# The default value is: YES.\n# This tag requires that the tag SOURCE_BROWSER is set to YES.\n\nSOURCE_TOOLTIPS        = YES\n\n# If the USE_HTAGS tag is set to YES then the references to source code will\n# point to the HTML generated by the htags(1) tool instead of doxygen built-in\n# source browser. The htags tool is part of GNU's global source tagging system\n# (see http://www.gnu.org/software/global/global.html). You will need version\n# 4.8.6 or higher.\n#\n# To use it do the following:\n# - Install the latest version of global\n# - Enable SOURCE_BROWSER and USE_HTAGS in the config file\n# - Make sure the INPUT points to the root of the source tree\n# - Run doxygen as normal\n#\n# Doxygen will invoke htags (and that will in turn invoke gtags), so these\n# tools must be available from the command line (i.e. in the search path).\n#\n# The result: instead of the source browser generated by doxygen, the links to\n# source code will now point to the output of htags.\n# The default value is: NO.\n# This tag requires that the tag SOURCE_BROWSER is set to YES.\n\nUSE_HTAGS              = NO\n\n# If the VERBATIM_HEADERS tag is set the YES then doxygen will generate a\n# verbatim copy of the header file for each class for which an include is\n# specified. Set to NO to disable this.\n# See also: Section \\class.\n# The default value is: YES.\n\nVERBATIM_HEADERS       = YES\n\n# If the CLANG_ASSISTED_PARSING tag is set to YES then doxygen will use the\n# clang parser (see: http://clang.llvm.org/) for more accurate parsing at the\n# cost of reduced performance. This can be particularly helpful with template\n# rich C++ code for which doxygen's built-in parser lacks the necessary type\n# information.\n# Note: The availability of this option depends on whether or not doxygen was\n# generated with the -Duse-libclang=ON option for CMake.\n# The default value is: NO.\n\nCLANG_ASSISTED_PARSING = NO\n\n# If clang assisted parsing is enabled you can provide the compiler with command\n# line options that you would normally use when invoking the compiler. Note that\n# the include paths will already be set by doxygen for the files and directories\n# specified with INPUT and INCLUDE_PATH.\n# This tag requires that the tag CLANG_ASSISTED_PARSING is set to YES.\n\nCLANG_OPTIONS          =\n\n#---------------------------------------------------------------------------\n# Configuration options related to the alphabetical class index\n#---------------------------------------------------------------------------\n\n# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index of all\n# compounds will be generated. Enable this if the project contains a lot of\n# classes, structs, unions or interfaces.\n# The default value is: YES.\n\nALPHABETICAL_INDEX     = YES\n\n# The COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns in\n# which the alphabetical index list will be split.\n# Minimum value: 1, maximum value: 20, default value: 5.\n# This tag requires that the tag ALPHABETICAL_INDEX is set to YES.\n\nCOLS_IN_ALPHA_INDEX    = 5\n\n# In case all classes in a project start with a common prefix, all classes will\n# be put under the same header in the alphabetical index. The IGNORE_PREFIX tag\n# can be used to specify a prefix (or a list of prefixes) that should be ignored\n# while generating the index headers.\n# This tag requires that the tag ALPHABETICAL_INDEX is set to YES.\n\nIGNORE_PREFIX          =\n\n#---------------------------------------------------------------------------\n# Configuration options related to the HTML output\n#---------------------------------------------------------------------------\n\n# If the GENERATE_HTML tag is set to YES, doxygen will generate HTML output\n# The default value is: YES.\n\nGENERATE_HTML          = YES\n\n# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. If a\n# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of\n# it.\n# The default directory is: html.\n# This tag requires that the tag GENERATE_HTML is set to YES.\n\nHTML_OUTPUT            = html\n\n# The HTML_FILE_EXTENSION tag can be used to specify the file extension for each\n# generated HTML page (for example: .htm, .php, .asp).\n# The default value is: .html.\n# This tag requires that the tag GENERATE_HTML is set to YES.\n\nHTML_FILE_EXTENSION    = .html\n\n# The HTML_HEADER tag can be used to specify a user-defined HTML header file for\n# each generated HTML page. If the tag is left blank doxygen will generate a\n# standard header.\n#\n# To get valid HTML the header file that includes any scripts and style sheets\n# that doxygen needs, which is dependent on the configuration options used (e.g.\n# the setting GENERATE_TREEVIEW). It is highly recommended to start with a\n# default header using\n# doxygen -w html new_header.html new_footer.html new_stylesheet.css\n# YourConfigFile\n# and then modify the file new_header.html. See also section \"Doxygen usage\"\n# for information on how to generate the default header that doxygen normally\n# uses.\n# Note: The header is subject to change so you typically have to regenerate the\n# default header when upgrading to a newer version of doxygen. For a description\n# of the possible markers and block names see the documentation.\n# This tag requires that the tag GENERATE_HTML is set to YES.\n\nHTML_HEADER            =\n\n# The HTML_FOOTER tag can be used to specify a user-defined HTML footer for each\n# generated HTML page. If the tag is left blank doxygen will generate a standard\n# footer. See HTML_HEADER for more information on how to generate a default\n# footer and what special commands can be used inside the footer. See also\n# section \"Doxygen usage\" for information on how to generate the default footer\n# that doxygen normally uses.\n# This tag requires that the tag GENERATE_HTML is set to YES.\n\nHTML_FOOTER            =\n\n# The HTML_STYLESHEET tag can be used to specify a user-defined cascading style\n# sheet that is used by each HTML page. It can be used to fine-tune the look of\n# the HTML output. If left blank doxygen will generate a default style sheet.\n# See also section \"Doxygen usage\" for information on how to generate the style\n# sheet that doxygen normally uses.\n# Note: It is recommended to use HTML_EXTRA_STYLESHEET instead of this tag, as\n# it is more robust and this tag (HTML_STYLESHEET) will in the future become\n# obsolete.\n# This tag requires that the tag GENERATE_HTML is set to YES.\n\nHTML_STYLESHEET        =\n\n# The HTML_EXTRA_STYLESHEET tag can be used to specify additional user-defined\n# cascading style sheets that are included after the standard style sheets\n# created by doxygen. Using this option one can overrule certain style aspects.\n# This is preferred over using HTML_STYLESHEET since it does not replace the\n# standard style sheet and is therefore more robust against future updates.\n# Doxygen will copy the style sheet files to the output directory.\n# Note: The order of the extra style sheet files is of importance (e.g. the last\n# style sheet in the list overrules the setting of the previous ones in the\n# list). For an example see the documentation.\n# This tag requires that the tag GENERATE_HTML is set to YES.\n\nHTML_EXTRA_STYLESHEET  =\n\n# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or\n# other source files which should be copied to the HTML output directory. Note\n# that these files will be copied to the base HTML output directory. Use the\n# $relpath^ marker in the HTML_HEADER and/or HTML_FOOTER files to load these\n# files. In the HTML_STYLESHEET file, use the file name only. Also note that the\n# files will be copied as-is; there are no commands or markers available.\n# This tag requires that the tag GENERATE_HTML is set to YES.\n\nHTML_EXTRA_FILES       =\n\n# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen\n# will adjust the colors in the style sheet and background images according to\n# this color. Hue is specified as an angle on a colorwheel, see\n# http://en.wikipedia.org/wiki/Hue for more information. For instance the value\n# 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300\n# purple, and 360 is red again.\n# Minimum value: 0, maximum value: 359, default value: 220.\n# This tag requires that the tag GENERATE_HTML is set to YES.\n\nHTML_COLORSTYLE_HUE    = 220\n\n# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors\n# in the HTML output. For a value of 0 the output will use grayscales only. A\n# value of 255 will produce the most vivid colors.\n# Minimum value: 0, maximum value: 255, default value: 100.\n# This tag requires that the tag GENERATE_HTML is set to YES.\n\nHTML_COLORSTYLE_SAT    = 100\n\n# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to the\n# luminance component of the colors in the HTML output. Values below 100\n# gradually make the output lighter, whereas values above 100 make the output\n# darker. The value divided by 100 is the actual gamma applied, so 80 represents\n# a gamma of 0.8, The value 220 represents a gamma of 2.2, and 100 does not\n# change the gamma.\n# Minimum value: 40, maximum value: 240, default value: 80.\n# This tag requires that the tag GENERATE_HTML is set to YES.\n\nHTML_COLORSTYLE_GAMMA  = 80\n\n# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML\n# page will contain the date and time when the page was generated. Setting this\n# to YES can help to show when doxygen was last run and thus if the\n# documentation is up to date.\n# The default value is: NO.\n# This tag requires that the tag GENERATE_HTML is set to YES.\n\nHTML_TIMESTAMP         = NO\n\n# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML\n# documentation will contain sections that can be hidden and shown after the\n# page has loaded.\n# The default value is: NO.\n# This tag requires that the tag GENERATE_HTML is set to YES.\n\nHTML_DYNAMIC_SECTIONS  = NO\n\n# With HTML_INDEX_NUM_ENTRIES one can control the preferred number of entries\n# shown in the various tree structured indices initially; the user can expand\n# and collapse entries dynamically later on. Doxygen will expand the tree to\n# such a level that at most the specified number of entries are visible (unless\n# a fully collapsed tree already exceeds this amount). So setting the number of\n# entries 1 will produce a full collapsed tree by default. 0 is a special value\n# representing an infinite number of entries and will result in a full expanded\n# tree by default.\n# Minimum value: 0, maximum value: 9999, default value: 100.\n# This tag requires that the tag GENERATE_HTML is set to YES.\n\nHTML_INDEX_NUM_ENTRIES = 100\n\n# If the GENERATE_DOCSET tag is set to YES, additional index files will be\n# generated that can be used as input for Apple's Xcode 3 integrated development\n# environment (see: http://developer.apple.com/tools/xcode/), introduced with\n# OSX 10.5 (Leopard). To create a documentation set, doxygen will generate a\n# Makefile in the HTML output directory. Running make will produce the docset in\n# that directory and running make install will install the docset in\n# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at\n# startup. See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html\n# for more information.\n# The default value is: NO.\n# This tag requires that the tag GENERATE_HTML is set to YES.\n\nGENERATE_DOCSET        = NO\n\n# This tag determines the name of the docset feed. A documentation feed provides\n# an umbrella under which multiple documentation sets from a single provider\n# (such as a company or product suite) can be grouped.\n# The default value is: Doxygen generated docs.\n# This tag requires that the tag GENERATE_DOCSET is set to YES.\n\nDOCSET_FEEDNAME        = \"Doxygen generated docs\"\n\n# This tag specifies a string that should uniquely identify the documentation\n# set bundle. This should be a reverse domain-name style string, e.g.\n# com.mycompany.MyDocSet. Doxygen will append .docset to the name.\n# The default value is: org.doxygen.Project.\n# This tag requires that the tag GENERATE_DOCSET is set to YES.\n\nDOCSET_BUNDLE_ID       = org.doxygen.Project\n\n# The DOCSET_PUBLISHER_ID tag specifies a string that should uniquely identify\n# the documentation publisher. This should be a reverse domain-name style\n# string, e.g. com.mycompany.MyDocSet.documentation.\n# The default value is: org.doxygen.Publisher.\n# This tag requires that the tag GENERATE_DOCSET is set to YES.\n\nDOCSET_PUBLISHER_ID    = org.doxygen.Publisher\n\n# The DOCSET_PUBLISHER_NAME tag identifies the documentation publisher.\n# The default value is: Publisher.\n# This tag requires that the tag GENERATE_DOCSET is set to YES.\n\nDOCSET_PUBLISHER_NAME  = Publisher\n\n# If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three\n# additional HTML index files: index.hhp, index.hhc, and index.hhk. The\n# index.hhp is a project file that can be read by Microsoft's HTML Help Workshop\n# (see: http://www.microsoft.com/en-us/download/details.aspx?id=21138) on\n# Windows.\n#\n# The HTML Help Workshop contains a compiler that can convert all HTML output\n# generated by doxygen into a single compiled HTML file (.chm). Compiled HTML\n# files are now used as the Windows 98 help format, and will replace the old\n# Windows help format (.hlp) on all Windows platforms in the future. Compressed\n# HTML files also contain an index, a table of contents, and you can search for\n# words in the documentation. The HTML workshop also contains a viewer for\n# compressed HTML files.\n# The default value is: NO.\n# This tag requires that the tag GENERATE_HTML is set to YES.\n\nGENERATE_HTMLHELP      = NO\n\n# The CHM_FILE tag can be used to specify the file name of the resulting .chm\n# file. You can add a path in front of the file if the result should not be\n# written to the html output directory.\n# This tag requires that the tag GENERATE_HTMLHELP is set to YES.\n\nCHM_FILE               =\n\n# The HHC_LOCATION tag can be used to specify the location (absolute path\n# including file name) of the HTML help compiler (hhc.exe). If non-empty,\n# doxygen will try to run the HTML help compiler on the generated index.hhp.\n# The file has to be specified with full path.\n# This tag requires that the tag GENERATE_HTMLHELP is set to YES.\n\nHHC_LOCATION           =\n\n# The GENERATE_CHI flag controls if a separate .chi index file is generated\n# (YES) or that it should be included in the master .chm file (NO).\n# The default value is: NO.\n# This tag requires that the tag GENERATE_HTMLHELP is set to YES.\n\nGENERATE_CHI           = NO\n\n# The CHM_INDEX_ENCODING is used to encode HtmlHelp index (hhk), content (hhc)\n# and project file content.\n# This tag requires that the tag GENERATE_HTMLHELP is set to YES.\n\nCHM_INDEX_ENCODING     =\n\n# The BINARY_TOC flag controls whether a binary table of contents is generated\n# (YES) or a normal table of contents (NO) in the .chm file. Furthermore it\n# enables the Previous and Next buttons.\n# The default value is: NO.\n# This tag requires that the tag GENERATE_HTMLHELP is set to YES.\n\nBINARY_TOC             = NO\n\n# The TOC_EXPAND flag can be set to YES to add extra items for group members to\n# the table of contents of the HTML help documentation and to the tree view.\n# The default value is: NO.\n# This tag requires that the tag GENERATE_HTMLHELP is set to YES.\n\nTOC_EXPAND             = NO\n\n# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and\n# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated that\n# can be used as input for Qt's qhelpgenerator to generate a Qt Compressed Help\n# (.qch) of the generated HTML documentation.\n# The default value is: NO.\n# This tag requires that the tag GENERATE_HTML is set to YES.\n\nGENERATE_QHP           = NO\n\n# If the QHG_LOCATION tag is specified, the QCH_FILE tag can be used to specify\n# the file name of the resulting .qch file. The path specified is relative to\n# the HTML output folder.\n# This tag requires that the tag GENERATE_QHP is set to YES.\n\nQCH_FILE               =\n\n# The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help\n# Project output. For more information please see Qt Help Project / Namespace\n# (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#namespace).\n# The default value is: org.doxygen.Project.\n# This tag requires that the tag GENERATE_QHP is set to YES.\n\nQHP_NAMESPACE          = org.doxygen.Project\n\n# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt\n# Help Project output. For more information please see Qt Help Project / Virtual\n# Folders (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#virtual-\n# folders).\n# The default value is: doc.\n# This tag requires that the tag GENERATE_QHP is set to YES.\n\nQHP_VIRTUAL_FOLDER     = doc\n\n# If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom\n# filter to add. For more information please see Qt Help Project / Custom\n# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom-\n# filters).\n# This tag requires that the tag GENERATE_QHP is set to YES.\n\nQHP_CUST_FILTER_NAME   =\n\n# The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the\n# custom filter to add. For more information please see Qt Help Project / Custom\n# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom-\n# filters).\n# This tag requires that the tag GENERATE_QHP is set to YES.\n\nQHP_CUST_FILTER_ATTRS  =\n\n# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this\n# project's filter section matches. Qt Help Project / Filter Attributes (see:\n# http://qt-project.org/doc/qt-4.8/qthelpproject.html#filter-attributes).\n# This tag requires that the tag GENERATE_QHP is set to YES.\n\nQHP_SECT_FILTER_ATTRS  =\n\n# The QHG_LOCATION tag can be used to specify the location of Qt's\n# qhelpgenerator. If non-empty doxygen will try to run qhelpgenerator on the\n# generated .qhp file.\n# This tag requires that the tag GENERATE_QHP is set to YES.\n\nQHG_LOCATION           =\n\n# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files will be\n# generated, together with the HTML files, they form an Eclipse help plugin. To\n# install this plugin and make it available under the help contents menu in\n# Eclipse, the contents of the directory containing the HTML and XML files needs\n# to be copied into the plugins directory of eclipse. The name of the directory\n# within the plugins directory should be the same as the ECLIPSE_DOC_ID value.\n# After copying Eclipse needs to be restarted before the help appears.\n# The default value is: NO.\n# This tag requires that the tag GENERATE_HTML is set to YES.\n\nGENERATE_ECLIPSEHELP   = NO\n\n# A unique identifier for the Eclipse help plugin. When installing the plugin\n# the directory name containing the HTML and XML files should also have this\n# name. Each documentation set should have its own identifier.\n# The default value is: org.doxygen.Project.\n# This tag requires that the tag GENERATE_ECLIPSEHELP is set to YES.\n\nECLIPSE_DOC_ID         = org.doxygen.Project\n\n# If you want full control over the layout of the generated HTML pages it might\n# be necessary to disable the index and replace it with your own. The\n# DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) at top\n# of each HTML page. A value of NO enables the index and the value YES disables\n# it. Since the tabs in the index contain the same information as the navigation\n# tree, you can set this option to YES if you also set GENERATE_TREEVIEW to YES.\n# The default value is: NO.\n# This tag requires that the tag GENERATE_HTML is set to YES.\n\nDISABLE_INDEX          = NO\n\n# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index\n# structure should be generated to display hierarchical information. If the tag\n# value is set to YES, a side panel will be generated containing a tree-like\n# index structure (just like the one that is generated for HTML Help). For this\n# to work a browser that supports JavaScript, DHTML, CSS and frames is required\n# (i.e. any modern browser). Windows users are probably better off using the\n# HTML help feature. Via custom style sheets (see HTML_EXTRA_STYLESHEET) one can\n# further fine-tune the look of the index. As an example, the default style\n# sheet generated by doxygen has an example that shows how to put an image at\n# the root of the tree instead of the PROJECT_NAME. Since the tree basically has\n# the same information as the tab index, you could consider setting\n# DISABLE_INDEX to YES when enabling this option.\n# The default value is: NO.\n# This tag requires that the tag GENERATE_HTML is set to YES.\n\nGENERATE_TREEVIEW      = NO\n\n# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that\n# doxygen will group on one line in the generated HTML documentation.\n#\n# Note that a value of 0 will completely suppress the enum values from appearing\n# in the overview section.\n# Minimum value: 0, maximum value: 20, default value: 4.\n# This tag requires that the tag GENERATE_HTML is set to YES.\n\nENUM_VALUES_PER_LINE   = 4\n\n# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be used\n# to set the initial width (in pixels) of the frame in which the tree is shown.\n# Minimum value: 0, maximum value: 1500, default value: 250.\n# This tag requires that the tag GENERATE_HTML is set to YES.\n\nTREEVIEW_WIDTH         = 250\n\n# If the EXT_LINKS_IN_WINDOW option is set to YES, doxygen will open links to\n# external symbols imported via tag files in a separate window.\n# The default value is: NO.\n# This tag requires that the tag GENERATE_HTML is set to YES.\n\nEXT_LINKS_IN_WINDOW    = NO\n\n# Use this tag to change the font size of LaTeX formulas included as images in\n# the HTML documentation. When you change the font size after a successful\n# doxygen run you need to manually remove any form_*.png images from the HTML\n# output directory to force them to be regenerated.\n# Minimum value: 8, maximum value: 50, default value: 10.\n# This tag requires that the tag GENERATE_HTML is set to YES.\n\nFORMULA_FONTSIZE       = 10\n\n# Use the FORMULA_TRANPARENT tag to determine whether or not the images\n# generated for formulas are transparent PNGs. Transparent PNGs are not\n# supported properly for IE 6.0, but are supported on all modern browsers.\n#\n# Note that when changing this option you need to delete any form_*.png files in\n# the HTML output directory before the changes have effect.\n# The default value is: YES.\n# This tag requires that the tag GENERATE_HTML is set to YES.\n\nFORMULA_TRANSPARENT    = YES\n\n# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see\n# http://www.mathjax.org) which uses client side Javascript for the rendering\n# instead of using pre-rendered bitmaps. Use this if you do not have LaTeX\n# installed or if you want to formulas look prettier in the HTML output. When\n# enabled you may also need to install MathJax separately and configure the path\n# to it using the MATHJAX_RELPATH option.\n# The default value is: NO.\n# This tag requires that the tag GENERATE_HTML is set to YES.\n\nUSE_MATHJAX            = NO\n\n# When MathJax is enabled you can set the default output format to be used for\n# the MathJax output. See the MathJax site (see:\n# http://docs.mathjax.org/en/latest/output.html) for more details.\n# Possible values are: HTML-CSS (which is slower, but has the best\n# compatibility), NativeMML (i.e. MathML) and SVG.\n# The default value is: HTML-CSS.\n# This tag requires that the tag USE_MATHJAX is set to YES.\n\nMATHJAX_FORMAT         = HTML-CSS\n\n# When MathJax is enabled you need to specify the location relative to the HTML\n# output directory using the MATHJAX_RELPATH option. The destination directory\n# should contain the MathJax.js script. For instance, if the mathjax directory\n# is located at the same level as the HTML output directory, then\n# MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax\n# Content Delivery Network so you can quickly see the result without installing\n# MathJax. However, it is strongly recommended to install a local copy of\n# MathJax from http://www.mathjax.org before deployment.\n# The default value is: http://cdn.mathjax.org/mathjax/latest.\n# This tag requires that the tag USE_MATHJAX is set to YES.\n\nMATHJAX_RELPATH        = http://cdn.mathjax.org/mathjax/latest\n\n# The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax\n# extension names that should be enabled during MathJax rendering. For example\n# MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols\n# This tag requires that the tag USE_MATHJAX is set to YES.\n\nMATHJAX_EXTENSIONS     =\n\n# The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces\n# of code that will be used on startup of the MathJax code. See the MathJax site\n# (see: http://docs.mathjax.org/en/latest/output.html) for more details. For an\n# example see the documentation.\n# This tag requires that the tag USE_MATHJAX is set to YES.\n\nMATHJAX_CODEFILE       =\n\n# When the SEARCHENGINE tag is enabled doxygen will generate a search box for\n# the HTML output. The underlying search engine uses javascript and DHTML and\n# should work on any modern browser. Note that when using HTML help\n# (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets (GENERATE_DOCSET)\n# there is already a search function so this one should typically be disabled.\n# For large projects the javascript based search engine can be slow, then\n# enabling SERVER_BASED_SEARCH may provide a better solution. It is possible to\n# search using the keyboard; to jump to the search box use <access key> + S\n# (what the <access key> is depends on the OS and browser, but it is typically\n# <CTRL>, <ALT>/<option>, or both). Inside the search box use the <cursor down\n# key> to jump into the search results window, the results can be navigated\n# using the <cursor keys>. Press <Enter> to select an item or <escape> to cancel\n# the search. The filter options can be selected when the cursor is inside the\n# search box by pressing <Shift>+<cursor down>. Also here use the <cursor keys>\n# to select a filter and <Enter> or <escape> to activate or cancel the filter\n# option.\n# The default value is: YES.\n# This tag requires that the tag GENERATE_HTML is set to YES.\n\nSEARCHENGINE           = YES\n\n# When the SERVER_BASED_SEARCH tag is enabled the search engine will be\n# implemented using a web server instead of a web client using Javascript. There\n# are two flavors of web server based searching depending on the EXTERNAL_SEARCH\n# setting. When disabled, doxygen will generate a PHP script for searching and\n# an index file used by the script. When EXTERNAL_SEARCH is enabled the indexing\n# and searching needs to be provided by external tools. See the section\n# \"External Indexing and Searching\" for details.\n# The default value is: NO.\n# This tag requires that the tag SEARCHENGINE is set to YES.\n\nSERVER_BASED_SEARCH    = NO\n\n# When EXTERNAL_SEARCH tag is enabled doxygen will no longer generate the PHP\n# script for searching. Instead the search results are written to an XML file\n# which needs to be processed by an external indexer. Doxygen will invoke an\n# external search engine pointed to by the SEARCHENGINE_URL option to obtain the\n# search results.\n#\n# Doxygen ships with an example indexer (doxyindexer) and search engine\n# (doxysearch.cgi) which are based on the open source search engine library\n# Xapian (see: http://xapian.org/).\n#\n# See the section \"External Indexing and Searching\" for details.\n# The default value is: NO.\n# This tag requires that the tag SEARCHENGINE is set to YES.\n\nEXTERNAL_SEARCH        = NO\n\n# The SEARCHENGINE_URL should point to a search engine hosted by a web server\n# which will return the search results when EXTERNAL_SEARCH is enabled.\n#\n# Doxygen ships with an example indexer (doxyindexer) and search engine\n# (doxysearch.cgi) which are based on the open source search engine library\n# Xapian (see: http://xapian.org/). See the section \"External Indexing and\n# Searching\" for details.\n# This tag requires that the tag SEARCHENGINE is set to YES.\n\nSEARCHENGINE_URL       =\n\n# When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the unindexed\n# search data is written to a file for indexing by an external tool. With the\n# SEARCHDATA_FILE tag the name of this file can be specified.\n# The default file is: searchdata.xml.\n# This tag requires that the tag SEARCHENGINE is set to YES.\n\nSEARCHDATA_FILE        = searchdata.xml\n\n# When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the\n# EXTERNAL_SEARCH_ID tag can be used as an identifier for the project. This is\n# useful in combination with EXTRA_SEARCH_MAPPINGS to search through multiple\n# projects and redirect the results back to the right project.\n# This tag requires that the tag SEARCHENGINE is set to YES.\n\nEXTERNAL_SEARCH_ID     =\n\n# The EXTRA_SEARCH_MAPPINGS tag can be used to enable searching through doxygen\n# projects other than the one defined by this configuration file, but that are\n# all added to the same external search index. Each project needs to have a\n# unique id set via EXTERNAL_SEARCH_ID. The search mapping then maps the id of\n# to a relative location where the documentation can be found. The format is:\n# EXTRA_SEARCH_MAPPINGS = tagname1=loc1 tagname2=loc2 ...\n# This tag requires that the tag SEARCHENGINE is set to YES.\n\nEXTRA_SEARCH_MAPPINGS  =\n\n#---------------------------------------------------------------------------\n# Configuration options related to the LaTeX output\n#---------------------------------------------------------------------------\n\n# If the GENERATE_LATEX tag is set to YES, doxygen will generate LaTeX output.\n# The default value is: YES.\n\nGENERATE_LATEX         = YES\n\n# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. If a\n# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of\n# it.\n# The default directory is: latex.\n# This tag requires that the tag GENERATE_LATEX is set to YES.\n\nLATEX_OUTPUT           = latex\n\n# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be\n# invoked.\n#\n# Note that when enabling USE_PDFLATEX this option is only used for generating\n# bitmaps for formulas in the HTML output, but not in the Makefile that is\n# written to the output directory.\n# The default file is: latex.\n# This tag requires that the tag GENERATE_LATEX is set to YES.\n\nLATEX_CMD_NAME         = latex\n\n# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to generate\n# index for LaTeX.\n# The default file is: makeindex.\n# This tag requires that the tag GENERATE_LATEX is set to YES.\n\nMAKEINDEX_CMD_NAME     = makeindex\n\n# If the COMPACT_LATEX tag is set to YES, doxygen generates more compact LaTeX\n# documents. This may be useful for small projects and may help to save some\n# trees in general.\n# The default value is: NO.\n# This tag requires that the tag GENERATE_LATEX is set to YES.\n\nCOMPACT_LATEX          = NO\n\n# The PAPER_TYPE tag can be used to set the paper type that is used by the\n# printer.\n# Possible values are: a4 (210 x 297 mm), letter (8.5 x 11 inches), legal (8.5 x\n# 14 inches) and executive (7.25 x 10.5 inches).\n# The default value is: a4.\n# This tag requires that the tag GENERATE_LATEX is set to YES.\n\nPAPER_TYPE             = a4\n\n# The EXTRA_PACKAGES tag can be used to specify one or more LaTeX package names\n# that should be included in the LaTeX output. The package can be specified just\n# by its name or with the correct syntax as to be used with the LaTeX\n# \\usepackage command. To get the times font for instance you can specify :\n# EXTRA_PACKAGES=times or EXTRA_PACKAGES={times}\n# To use the option intlimits with the amsmath package you can specify:\n# EXTRA_PACKAGES=[intlimits]{amsmath}\n# If left blank no extra packages will be included.\n# This tag requires that the tag GENERATE_LATEX is set to YES.\n\nEXTRA_PACKAGES         =\n\n# The LATEX_HEADER tag can be used to specify a personal LaTeX header for the\n# generated LaTeX document. The header should contain everything until the first\n# chapter. If it is left blank doxygen will generate a standard header. See\n# section \"Doxygen usage\" for information on how to let doxygen write the\n# default header to a separate file.\n#\n# Note: Only use a user-defined header if you know what you are doing! The\n# following commands have a special meaning inside the header: $title,\n# $datetime, $date, $doxygenversion, $projectname, $projectnumber,\n# $projectbrief, $projectlogo. Doxygen will replace $title with the empty\n# string, for the replacement values of the other commands the user is referred\n# to HTML_HEADER.\n# This tag requires that the tag GENERATE_LATEX is set to YES.\n\nLATEX_HEADER           =\n\n# The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for the\n# generated LaTeX document. The footer should contain everything after the last\n# chapter. If it is left blank doxygen will generate a standard footer. See\n# LATEX_HEADER for more information on how to generate a default footer and what\n# special commands can be used inside the footer.\n#\n# Note: Only use a user-defined footer if you know what you are doing!\n# This tag requires that the tag GENERATE_LATEX is set to YES.\n\nLATEX_FOOTER           =\n\n# The LATEX_EXTRA_STYLESHEET tag can be used to specify additional user-defined\n# LaTeX style sheets that are included after the standard style sheets created\n# by doxygen. Using this option one can overrule certain style aspects. Doxygen\n# will copy the style sheet files to the output directory.\n# Note: The order of the extra style sheet files is of importance (e.g. the last\n# style sheet in the list overrules the setting of the previous ones in the\n# list).\n# This tag requires that the tag GENERATE_LATEX is set to YES.\n\nLATEX_EXTRA_STYLESHEET =\n\n# The LATEX_EXTRA_FILES tag can be used to specify one or more extra images or\n# other source files which should be copied to the LATEX_OUTPUT output\n# directory. Note that the files will be copied as-is; there are no commands or\n# markers available.\n# This tag requires that the tag GENERATE_LATEX is set to YES.\n\nLATEX_EXTRA_FILES      =\n\n# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated is\n# prepared for conversion to PDF (using ps2pdf or pdflatex). The PDF file will\n# contain links (just like the HTML output) instead of page references. This\n# makes the output suitable for online browsing using a PDF viewer.\n# The default value is: YES.\n# This tag requires that the tag GENERATE_LATEX is set to YES.\n\nPDF_HYPERLINKS         = YES\n\n# If the USE_PDFLATEX tag is set to YES, doxygen will use pdflatex to generate\n# the PDF file directly from the LaTeX files. Set this option to YES, to get a\n# higher quality PDF documentation.\n# The default value is: YES.\n# This tag requires that the tag GENERATE_LATEX is set to YES.\n\nUSE_PDFLATEX           = YES\n\n# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode\n# command to the generated LaTeX files. This will instruct LaTeX to keep running\n# if errors occur, instead of asking the user for help. This option is also used\n# when generating formulas in HTML.\n# The default value is: NO.\n# This tag requires that the tag GENERATE_LATEX is set to YES.\n\nLATEX_BATCHMODE        = NO\n\n# If the LATEX_HIDE_INDICES tag is set to YES then doxygen will not include the\n# index chapters (such as File Index, Compound Index, etc.) in the output.\n# The default value is: NO.\n# This tag requires that the tag GENERATE_LATEX is set to YES.\n\nLATEX_HIDE_INDICES     = NO\n\n# If the LATEX_SOURCE_CODE tag is set to YES then doxygen will include source\n# code with syntax highlighting in the LaTeX output.\n#\n# Note that which sources are shown also depends on other settings such as\n# SOURCE_BROWSER.\n# The default value is: NO.\n# This tag requires that the tag GENERATE_LATEX is set to YES.\n\nLATEX_SOURCE_CODE      = NO\n\n# The LATEX_BIB_STYLE tag can be used to specify the style to use for the\n# bibliography, e.g. plainnat, or ieeetr. See\n# http://en.wikipedia.org/wiki/BibTeX and \\cite for more info.\n# The default value is: plain.\n# This tag requires that the tag GENERATE_LATEX is set to YES.\n\nLATEX_BIB_STYLE        = plain\n\n# If the LATEX_TIMESTAMP tag is set to YES then the footer of each generated\n# page will contain the date and time when the page was generated. Setting this\n# to NO can help when comparing the output of multiple runs.\n# The default value is: NO.\n# This tag requires that the tag GENERATE_LATEX is set to YES.\n\nLATEX_TIMESTAMP        = NO\n\n#---------------------------------------------------------------------------\n# Configuration options related to the RTF output\n#---------------------------------------------------------------------------\n\n# If the GENERATE_RTF tag is set to YES, doxygen will generate RTF output. The\n# RTF output is optimized for Word 97 and may not look too pretty with other RTF\n# readers/editors.\n# The default value is: NO.\n\nGENERATE_RTF           = NO\n\n# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. If a\n# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of\n# it.\n# The default directory is: rtf.\n# This tag requires that the tag GENERATE_RTF is set to YES.\n\nRTF_OUTPUT             = rtf\n\n# If the COMPACT_RTF tag is set to YES, doxygen generates more compact RTF\n# documents. This may be useful for small projects and may help to save some\n# trees in general.\n# The default value is: NO.\n# This tag requires that the tag GENERATE_RTF is set to YES.\n\nCOMPACT_RTF            = NO\n\n# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated will\n# contain hyperlink fields. The RTF file will contain links (just like the HTML\n# output) instead of page references. This makes the output suitable for online\n# browsing using Word or some other Word compatible readers that support those\n# fields.\n#\n# Note: WordPad (write) and others do not support links.\n# The default value is: NO.\n# This tag requires that the tag GENERATE_RTF is set to YES.\n\nRTF_HYPERLINKS         = NO\n\n# Load stylesheet definitions from file. Syntax is similar to doxygen's config\n# file, i.e. a series of assignments. You only have to provide replacements,\n# missing definitions are set to their default value.\n#\n# See also section \"Doxygen usage\" for information on how to generate the\n# default style sheet that doxygen normally uses.\n# This tag requires that the tag GENERATE_RTF is set to YES.\n\nRTF_STYLESHEET_FILE    =\n\n# Set optional variables used in the generation of an RTF document. Syntax is\n# similar to doxygen's config file. A template extensions file can be generated\n# using doxygen -e rtf extensionFile.\n# This tag requires that the tag GENERATE_RTF is set to YES.\n\nRTF_EXTENSIONS_FILE    =\n\n# If the RTF_SOURCE_CODE tag is set to YES then doxygen will include source code\n# with syntax highlighting in the RTF output.\n#\n# Note that which sources are shown also depends on other settings such as\n# SOURCE_BROWSER.\n# The default value is: NO.\n# This tag requires that the tag GENERATE_RTF is set to YES.\n\nRTF_SOURCE_CODE        = NO\n\n#---------------------------------------------------------------------------\n# Configuration options related to the man page output\n#---------------------------------------------------------------------------\n\n# If the GENERATE_MAN tag is set to YES, doxygen will generate man pages for\n# classes and files.\n# The default value is: NO.\n\nGENERATE_MAN           = NO\n\n# The MAN_OUTPUT tag is used to specify where the man pages will be put. If a\n# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of\n# it. A directory man3 will be created inside the directory specified by\n# MAN_OUTPUT.\n# The default directory is: man.\n# This tag requires that the tag GENERATE_MAN is set to YES.\n\nMAN_OUTPUT             = man\n\n# The MAN_EXTENSION tag determines the extension that is added to the generated\n# man pages. In case the manual section does not start with a number, the number\n# 3 is prepended. The dot (.) at the beginning of the MAN_EXTENSION tag is\n# optional.\n# The default value is: .3.\n# This tag requires that the tag GENERATE_MAN is set to YES.\n\nMAN_EXTENSION          = .3\n\n# The MAN_SUBDIR tag determines the name of the directory created within\n# MAN_OUTPUT in which the man pages are placed. If defaults to man followed by\n# MAN_EXTENSION with the initial . removed.\n# This tag requires that the tag GENERATE_MAN is set to YES.\n\nMAN_SUBDIR             =\n\n# If the MAN_LINKS tag is set to YES and doxygen generates man output, then it\n# will generate one additional man file for each entity documented in the real\n# man page(s). These additional files only source the real man page, but without\n# them the man command would be unable to find the correct page.\n# The default value is: NO.\n# This tag requires that the tag GENERATE_MAN is set to YES.\n\nMAN_LINKS              = NO\n\n#---------------------------------------------------------------------------\n# Configuration options related to the XML output\n#---------------------------------------------------------------------------\n\n# If the GENERATE_XML tag is set to YES, doxygen will generate an XML file that\n# captures the structure of the code including all documentation.\n# The default value is: NO.\n\nGENERATE_XML           = NO\n\n# The XML_OUTPUT tag is used to specify where the XML pages will be put. If a\n# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of\n# it.\n# The default directory is: xml.\n# This tag requires that the tag GENERATE_XML is set to YES.\n\nXML_OUTPUT             = xml\n\n# If the XML_PROGRAMLISTING tag is set to YES, doxygen will dump the program\n# listings (including syntax highlighting and cross-referencing information) to\n# the XML output. Note that enabling this will significantly increase the size\n# of the XML output.\n# The default value is: YES.\n# This tag requires that the tag GENERATE_XML is set to YES.\n\nXML_PROGRAMLISTING     = YES\n\n#---------------------------------------------------------------------------\n# Configuration options related to the DOCBOOK output\n#---------------------------------------------------------------------------\n\n# If the GENERATE_DOCBOOK tag is set to YES, doxygen will generate Docbook files\n# that can be used to generate PDF.\n# The default value is: NO.\n\nGENERATE_DOCBOOK       = NO\n\n# The DOCBOOK_OUTPUT tag is used to specify where the Docbook pages will be put.\n# If a relative path is entered the value of OUTPUT_DIRECTORY will be put in\n# front of it.\n# The default directory is: docbook.\n# This tag requires that the tag GENERATE_DOCBOOK is set to YES.\n\nDOCBOOK_OUTPUT         = docbook\n\n# If the DOCBOOK_PROGRAMLISTING tag is set to YES, doxygen will include the\n# program listings (including syntax highlighting and cross-referencing\n# information) to the DOCBOOK output. Note that enabling this will significantly\n# increase the size of the DOCBOOK output.\n# The default value is: NO.\n# This tag requires that the tag GENERATE_DOCBOOK is set to YES.\n\nDOCBOOK_PROGRAMLISTING = NO\n\n#---------------------------------------------------------------------------\n# Configuration options for the AutoGen Definitions output\n#---------------------------------------------------------------------------\n\n# If the GENERATE_AUTOGEN_DEF tag is set to YES, doxygen will generate an\n# AutoGen Definitions (see http://autogen.sf.net) file that captures the\n# structure of the code including all documentation. Note that this feature is\n# still experimental and incomplete at the moment.\n# The default value is: NO.\n\nGENERATE_AUTOGEN_DEF   = NO\n\n#---------------------------------------------------------------------------\n# Configuration options related to the Perl module output\n#---------------------------------------------------------------------------\n\n# If the GENERATE_PERLMOD tag is set to YES, doxygen will generate a Perl module\n# file that captures the structure of the code including all documentation.\n#\n# Note that this feature is still experimental and incomplete at the moment.\n# The default value is: NO.\n\nGENERATE_PERLMOD       = NO\n\n# If the PERLMOD_LATEX tag is set to YES, doxygen will generate the necessary\n# Makefile rules, Perl scripts and LaTeX code to be able to generate PDF and DVI\n# output from the Perl module output.\n# The default value is: NO.\n# This tag requires that the tag GENERATE_PERLMOD is set to YES.\n\nPERLMOD_LATEX          = NO\n\n# If the PERLMOD_PRETTY tag is set to YES, the Perl module output will be nicely\n# formatted so it can be parsed by a human reader. This is useful if you want to\n# understand what is going on. On the other hand, if this tag is set to NO, the\n# size of the Perl module output will be much smaller and Perl will parse it\n# just the same.\n# The default value is: YES.\n# This tag requires that the tag GENERATE_PERLMOD is set to YES.\n\nPERLMOD_PRETTY         = YES\n\n# The names of the make variables in the generated doxyrules.make file are\n# prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. This is useful\n# so different doxyrules.make files included by the same Makefile don't\n# overwrite each other's variables.\n# This tag requires that the tag GENERATE_PERLMOD is set to YES.\n\nPERLMOD_MAKEVAR_PREFIX =\n\n#---------------------------------------------------------------------------\n# Configuration options related to the preprocessor\n#---------------------------------------------------------------------------\n\n# If the ENABLE_PREPROCESSING tag is set to YES, doxygen will evaluate all\n# C-preprocessor directives found in the sources and include files.\n# The default value is: YES.\n\nENABLE_PREPROCESSING   = YES\n\n# If the MACRO_EXPANSION tag is set to YES, doxygen will expand all macro names\n# in the source code. If set to NO, only conditional compilation will be\n# performed. Macro expansion can be done in a controlled way by setting\n# EXPAND_ONLY_PREDEF to YES.\n# The default value is: NO.\n# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.\n\nMACRO_EXPANSION        = NO\n\n# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES then\n# the macro expansion is limited to the macros specified with the PREDEFINED and\n# EXPAND_AS_DEFINED tags.\n# The default value is: NO.\n# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.\n\nEXPAND_ONLY_PREDEF     = NO\n\n# If the SEARCH_INCLUDES tag is set to YES, the include files in the\n# INCLUDE_PATH will be searched if a #include is found.\n# The default value is: YES.\n# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.\n\nSEARCH_INCLUDES        = YES\n\n# The INCLUDE_PATH tag can be used to specify one or more directories that\n# contain include files that are not input files but should be processed by the\n# preprocessor.\n# This tag requires that the tag SEARCH_INCLUDES is set to YES.\n\nINCLUDE_PATH           =\n\n# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard\n# patterns (like *.h and *.hpp) to filter out the header-files in the\n# directories. If left blank, the patterns specified with FILE_PATTERNS will be\n# used.\n# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.\n\nINCLUDE_FILE_PATTERNS  =\n\n# The PREDEFINED tag can be used to specify one or more macro names that are\n# defined before the preprocessor is started (similar to the -D option of e.g.\n# gcc). The argument of the tag is a list of macros of the form: name or\n# name=definition (no spaces). If the definition and the \"=\" are omitted, \"=1\"\n# is assumed. To prevent a macro definition from being undefined via #undef or\n# recursively expanded use the := operator instead of the = operator.\n# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.\n\nPREDEFINED             =\n\n# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then this\n# tag can be used to specify a list of macro names that should be expanded. The\n# macro definition that is found in the sources will be used. Use the PREDEFINED\n# tag if you want to use a different macro definition that overrules the\n# definition found in the source code.\n# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.\n\nEXPAND_AS_DEFINED      =\n\n# If the SKIP_FUNCTION_MACROS tag is set to YES then doxygen's preprocessor will\n# remove all references to function-like macros that are alone on a line, have\n# an all uppercase name, and do not end with a semicolon. Such function macros\n# are typically used for boiler-plate code, and will confuse the parser if not\n# removed.\n# The default value is: YES.\n# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.\n\nSKIP_FUNCTION_MACROS   = YES\n\n#---------------------------------------------------------------------------\n# Configuration options related to external references\n#---------------------------------------------------------------------------\n\n# The TAGFILES tag can be used to specify one or more tag files. For each tag\n# file the location of the external documentation should be added. The format of\n# a tag file without this location is as follows:\n# TAGFILES = file1 file2 ...\n# Adding location for the tag files is done as follows:\n# TAGFILES = file1=loc1 \"file2 = loc2\" ...\n# where loc1 and loc2 can be relative or absolute paths or URLs. See the\n# section \"Linking to external documentation\" for more information about the use\n# of tag files.\n# Note: Each tag file must have a unique name (where the name does NOT include\n# the path). If a tag file is not located in the directory in which doxygen is\n# run, you must also specify the path to the tagfile here.\n\nTAGFILES               =\n\n# When a file name is specified after GENERATE_TAGFILE, doxygen will create a\n# tag file that is based on the input files it reads. See section \"Linking to\n# external documentation\" for more information about the usage of tag files.\n\nGENERATE_TAGFILE       =\n\n# If the ALLEXTERNALS tag is set to YES, all external class will be listed in\n# the class index. If set to NO, only the inherited external classes will be\n# listed.\n# The default value is: NO.\n\nALLEXTERNALS           = NO\n\n# If the EXTERNAL_GROUPS tag is set to YES, all external groups will be listed\n# in the modules index. If set to NO, only the current project's groups will be\n# listed.\n# The default value is: YES.\n\nEXTERNAL_GROUPS        = YES\n\n# If the EXTERNAL_PAGES tag is set to YES, all external pages will be listed in\n# the related pages index. If set to NO, only the current project's pages will\n# be listed.\n# The default value is: YES.\n\nEXTERNAL_PAGES         = YES\n\n# The PERL_PATH should be the absolute path and name of the perl script\n# interpreter (i.e. the result of 'which perl').\n# The default file (with absolute path) is: /usr/bin/perl.\n\nPERL_PATH              = /usr/bin/perl\n\n#---------------------------------------------------------------------------\n# Configuration options related to the dot tool\n#---------------------------------------------------------------------------\n\n# If the CLASS_DIAGRAMS tag is set to YES, doxygen will generate a class diagram\n# (in HTML and LaTeX) for classes with base or super classes. Setting the tag to\n# NO turns the diagrams off. Note that this option also works with HAVE_DOT\n# disabled, but it is recommended to install and use dot, since it yields more\n# powerful graphs.\n# The default value is: YES.\n\nCLASS_DIAGRAMS         = YES\n\n# You can define message sequence charts within doxygen comments using the \\msc\n# command. Doxygen will then run the mscgen tool (see:\n# http://www.mcternan.me.uk/mscgen/)) to produce the chart and insert it in the\n# documentation. The MSCGEN_PATH tag allows you to specify the directory where\n# the mscgen tool resides. If left empty the tool is assumed to be found in the\n# default search path.\n\nMSCGEN_PATH            =\n\n# You can include diagrams made with dia in doxygen documentation. Doxygen will\n# then run dia to produce the diagram and insert it in the documentation. The\n# DIA_PATH tag allows you to specify the directory where the dia binary resides.\n# If left empty dia is assumed to be found in the default search path.\n\nDIA_PATH               =\n\n# If set to YES the inheritance and collaboration graphs will hide inheritance\n# and usage relations if the target is undocumented or is not a class.\n# The default value is: YES.\n\nHIDE_UNDOC_RELATIONS   = YES\n\n# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is\n# available from the path. This tool is part of Graphviz (see:\n# http://www.graphviz.org/), a graph visualization toolkit from AT&T and Lucent\n# Bell Labs. The other options in this section have no effect if this option is\n# set to NO\n# The default value is: YES.\n\nHAVE_DOT               = YES\n\n# The DOT_NUM_THREADS specifies the number of dot invocations doxygen is allowed\n# to run in parallel. When set to 0 doxygen will base this on the number of\n# processors available in the system. You can set it explicitly to a value\n# larger than 0 to get control over the balance between CPU load and processing\n# speed.\n# Minimum value: 0, maximum value: 32, default value: 0.\n# This tag requires that the tag HAVE_DOT is set to YES.\n\nDOT_NUM_THREADS        = 0\n\n# When you want a differently looking font in the dot files that doxygen\n# generates you can specify the font name using DOT_FONTNAME. You need to make\n# sure dot is able to find the font, which can be done by putting it in a\n# standard location or by setting the DOTFONTPATH environment variable or by\n# setting DOT_FONTPATH to the directory containing the font.\n# The default value is: Helvetica.\n# This tag requires that the tag HAVE_DOT is set to YES.\n\nDOT_FONTNAME           = Helvetica\n\n# The DOT_FONTSIZE tag can be used to set the size (in points) of the font of\n# dot graphs.\n# Minimum value: 4, maximum value: 24, default value: 10.\n# This tag requires that the tag HAVE_DOT is set to YES.\n\nDOT_FONTSIZE           = 10\n\n# By default doxygen will tell dot to use the default font as specified with\n# DOT_FONTNAME. If you specify a different font using DOT_FONTNAME you can set\n# the path where dot can find it using this tag.\n# This tag requires that the tag HAVE_DOT is set to YES.\n\nDOT_FONTPATH           =\n\n# If the CLASS_GRAPH tag is set to YES then doxygen will generate a graph for\n# each documented class showing the direct and indirect inheritance relations.\n# Setting this tag to YES will force the CLASS_DIAGRAMS tag to NO.\n# The default value is: YES.\n# This tag requires that the tag HAVE_DOT is set to YES.\n\nCLASS_GRAPH            = YES\n\n# If the COLLABORATION_GRAPH tag is set to YES then doxygen will generate a\n# graph for each documented class showing the direct and indirect implementation\n# dependencies (inheritance, containment, and class references variables) of the\n# class with other documented classes.\n# The default value is: YES.\n# This tag requires that the tag HAVE_DOT is set to YES.\n\nCOLLABORATION_GRAPH    = YES\n\n# If the GROUP_GRAPHS tag is set to YES then doxygen will generate a graph for\n# groups, showing the direct groups dependencies.\n# The default value is: YES.\n# This tag requires that the tag HAVE_DOT is set to YES.\n\nGROUP_GRAPHS           = YES\n\n# If the UML_LOOK tag is set to YES, doxygen will generate inheritance and\n# collaboration diagrams in a style similar to the OMG's Unified Modeling\n# Language.\n# The default value is: NO.\n# This tag requires that the tag HAVE_DOT is set to YES.\n\nUML_LOOK               = NO\n\n# If the UML_LOOK tag is enabled, the fields and methods are shown inside the\n# class node. If there are many fields or methods and many nodes the graph may\n# become too big to be useful. The UML_LIMIT_NUM_FIELDS threshold limits the\n# number of items for each type to make the size more manageable. Set this to 0\n# for no limit. Note that the threshold may be exceeded by 50% before the limit\n# is enforced. So when you set the threshold to 10, up to 15 fields may appear,\n# but if the number exceeds 15, the total amount of fields shown is limited to\n# 10.\n# Minimum value: 0, maximum value: 100, default value: 10.\n# This tag requires that the tag HAVE_DOT is set to YES.\n\nUML_LIMIT_NUM_FIELDS   = 10\n\n# If the TEMPLATE_RELATIONS tag is set to YES then the inheritance and\n# collaboration graphs will show the relations between templates and their\n# instances.\n# The default value is: NO.\n# This tag requires that the tag HAVE_DOT is set to YES.\n\nTEMPLATE_RELATIONS     = NO\n\n# If the INCLUDE_GRAPH, ENABLE_PREPROCESSING and SEARCH_INCLUDES tags are set to\n# YES then doxygen will generate a graph for each documented file showing the\n# direct and indirect include dependencies of the file with other documented\n# files.\n# The default value is: YES.\n# This tag requires that the tag HAVE_DOT is set to YES.\n\nINCLUDE_GRAPH          = YES\n\n# If the INCLUDED_BY_GRAPH, ENABLE_PREPROCESSING and SEARCH_INCLUDES tags are\n# set to YES then doxygen will generate a graph for each documented file showing\n# the direct and indirect include dependencies of the file with other documented\n# files.\n# The default value is: YES.\n# This tag requires that the tag HAVE_DOT is set to YES.\n\nINCLUDED_BY_GRAPH      = YES\n\n# If the CALL_GRAPH tag is set to YES then doxygen will generate a call\n# dependency graph for every global function or class method.\n#\n# Note that enabling this option will significantly increase the time of a run.\n# So in most cases it will be better to enable call graphs for selected\n# functions only using the \\callgraph command. Disabling a call graph can be\n# accomplished by means of the command \\hidecallgraph.\n# The default value is: NO.\n# This tag requires that the tag HAVE_DOT is set to YES.\n\nCALL_GRAPH             = NO\n\n# If the CALLER_GRAPH tag is set to YES then doxygen will generate a caller\n# dependency graph for every global function or class method.\n#\n# Note that enabling this option will significantly increase the time of a run.\n# So in most cases it will be better to enable caller graphs for selected\n# functions only using the \\callergraph command. Disabling a caller graph can be\n# accomplished by means of the command \\hidecallergraph.\n# The default value is: NO.\n# This tag requires that the tag HAVE_DOT is set to YES.\n\nCALLER_GRAPH           = NO\n\n# If the GRAPHICAL_HIERARCHY tag is set to YES then doxygen will graphical\n# hierarchy of all classes instead of a textual one.\n# The default value is: YES.\n# This tag requires that the tag HAVE_DOT is set to YES.\n\nGRAPHICAL_HIERARCHY    = YES\n\n# If the DIRECTORY_GRAPH tag is set to YES then doxygen will show the\n# dependencies a directory has on other directories in a graphical way. The\n# dependency relations are determined by the #include relations between the\n# files in the directories.\n# The default value is: YES.\n# This tag requires that the tag HAVE_DOT is set to YES.\n\nDIRECTORY_GRAPH        = YES\n\n# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images\n# generated by dot. For an explanation of the image formats see the section\n# output formats in the documentation of the dot tool (Graphviz (see:\n# http://www.graphviz.org/)).\n# Note: If you choose svg you need to set HTML_FILE_EXTENSION to xhtml in order\n# to make the SVG files visible in IE 9+ (other browsers do not have this\n# requirement).\n# Possible values are: png, png:cairo, png:cairo:cairo, png:cairo:gd, png:gd,\n# png:gd:gd, jpg, jpg:cairo, jpg:cairo:gd, jpg:gd, jpg:gd:gd, gif, gif:cairo,\n# gif:cairo:gd, gif:gd, gif:gd:gd, svg, png:gd, png:gd:gd, png:cairo,\n# png:cairo:gd, png:cairo:cairo, png:cairo:gdiplus, png:gdiplus and\n# png:gdiplus:gdiplus.\n# The default value is: png.\n# This tag requires that the tag HAVE_DOT is set to YES.\n\nDOT_IMAGE_FORMAT       = png\n\n# If DOT_IMAGE_FORMAT is set to svg, then this option can be set to YES to\n# enable generation of interactive SVG images that allow zooming and panning.\n#\n# Note that this requires a modern browser other than Internet Explorer. Tested\n# and working are Firefox, Chrome, Safari, and Opera.\n# Note: For IE 9+ you need to set HTML_FILE_EXTENSION to xhtml in order to make\n# the SVG files visible. Older versions of IE do not have SVG support.\n# The default value is: NO.\n# This tag requires that the tag HAVE_DOT is set to YES.\n\nINTERACTIVE_SVG        = NO\n\n# The DOT_PATH tag can be used to specify the path where the dot tool can be\n# found. If left blank, it is assumed the dot tool can be found in the path.\n# This tag requires that the tag HAVE_DOT is set to YES.\n\nDOT_PATH               =\n\n# The DOTFILE_DIRS tag can be used to specify one or more directories that\n# contain dot files that are included in the documentation (see the \\dotfile\n# command).\n# This tag requires that the tag HAVE_DOT is set to YES.\n\nDOTFILE_DIRS           =\n\n# The MSCFILE_DIRS tag can be used to specify one or more directories that\n# contain msc files that are included in the documentation (see the \\mscfile\n# command).\n\nMSCFILE_DIRS           =\n\n# The DIAFILE_DIRS tag can be used to specify one or more directories that\n# contain dia files that are included in the documentation (see the \\diafile\n# command).\n\nDIAFILE_DIRS           =\n\n# When using plantuml, the PLANTUML_JAR_PATH tag should be used to specify the\n# path where java can find the plantuml.jar file. If left blank, it is assumed\n# PlantUML is not used or called during a preprocessing step. Doxygen will\n# generate a warning when it encounters a \\startuml command in this case and\n# will not generate output for the diagram.\n\nPLANTUML_JAR_PATH      =\n\n# When using plantuml, the specified paths are searched for files specified by\n# the !include statement in a plantuml block.\n\nPLANTUML_INCLUDE_PATH  =\n\n# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of nodes\n# that will be shown in the graph. If the number of nodes in a graph becomes\n# larger than this value, doxygen will truncate the graph, which is visualized\n# by representing a node as a red box. Note that doxygen if the number of direct\n# children of the root node in a graph is already larger than\n# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note that\n# the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH.\n# Minimum value: 0, maximum value: 10000, default value: 50.\n# This tag requires that the tag HAVE_DOT is set to YES.\n\nDOT_GRAPH_MAX_NODES    = 50\n\n# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the graphs\n# generated by dot. A depth value of 3 means that only nodes reachable from the\n# root by following a path via at most 3 edges will be shown. Nodes that lay\n# further from the root node will be omitted. Note that setting this option to 1\n# or 2 may greatly reduce the computation time needed for large code bases. Also\n# note that the size of a graph can be further restricted by\n# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction.\n# Minimum value: 0, maximum value: 1000, default value: 0.\n# This tag requires that the tag HAVE_DOT is set to YES.\n\nMAX_DOT_GRAPH_DEPTH    = 0\n\n# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent\n# background. This is disabled by default, because dot on Windows does not seem\n# to support this out of the box.\n#\n# Warning: Depending on the platform used, enabling this option may lead to\n# badly anti-aliased labels on the edges of a graph (i.e. they become hard to\n# read).\n# The default value is: NO.\n# This tag requires that the tag HAVE_DOT is set to YES.\n\nDOT_TRANSPARENT        = NO\n\n# Set the DOT_MULTI_TARGETS tag to YES to allow dot to generate multiple output\n# files in one run (i.e. multiple -o and -T options on the command line). This\n# makes dot run faster, but since only newer versions of dot (>1.8.10) support\n# this, this feature is disabled by default.\n# The default value is: NO.\n# This tag requires that the tag HAVE_DOT is set to YES.\n\nDOT_MULTI_TARGETS      = NO\n\n# If the GENERATE_LEGEND tag is set to YES doxygen will generate a legend page\n# explaining the meaning of the various boxes and arrows in the dot generated\n# graphs.\n# The default value is: YES.\n# This tag requires that the tag HAVE_DOT is set to YES.\n\nGENERATE_LEGEND        = YES\n\n# If the DOT_CLEANUP tag is set to YES, doxygen will remove the intermediate dot\n# files that are used to generate the various graphs.\n# The default value is: YES.\n# This tag requires that the tag HAVE_DOT is set to YES.\n\nDOT_CLEANUP            = YES\n"
  },
  {
    "path": "Jenkinsfile",
    "content": "def notify(status){\n\temailext (\n\t\tbody: '$DEFAULT_CONTENT',\n\t\trecipientProviders: [\n\t\t\t[$class: 'CulpritsRecipientProvider'],\n\t\t\t[$class: 'DevelopersRecipientProvider'],\n\t\t\t[$class: 'RequesterRecipientProvider']\n\t\t],\n\t\treplyTo: '$DEFAULT_REPLYTO',\n\t\tsubject: '$DEFAULT_SUBJECT',\n\t\tto: '$DEFAULT_RECIPIENTS'\n\t)\n}\n\n@NonCPS\ndef killall_jobs() {\n\tdef jobname = env.JOB_NAME\n\tdef buildnum = env.BUILD_NUMBER.toInteger()\n\tdef killnums = \"\"\n\tdef job = Jenkins.instance.getItemByFullName(jobname)\n\tdef fixed_job_name = env.JOB_NAME.replace('%2F','/')\n\n\tfor (build in job.builds) {\n\t\tif (!build.isBuilding()) { continue; }\n\t\tif (buildnum == build.getNumber().toInteger()) { continue; println \"equals\" }\n\t\tif (buildnum < build.getNumber().toInteger()) { continue; println \"newer\" }\n\n\t\techo \"Kill task = ${build}\"\n\n\t\tkillnums += \"#\" + build.getNumber().toInteger() + \", \"\n\n\t\tbuild.doStop();\n\t}\n\n\tif (killnums != \"\") {\n\t\tdiscordSend description: \"in favor of #${buildnum}, ignore following failed builds for ${killnums}\", footer: \"\", link: env.BUILD_URL, result: \"ABORTED\", title: \"[${split_job_name[0]}] Killing task(s) ${fixed_job_name} ${killnums}\", webhookURL: env.AMIGADEV_WEBHOOK\n\t}\n\techo \"Done killing\"\n}\n\ndef buildStep() {\n\tdef split_job_name = env.JOB_NAME.split(/\\/{1}/);\n\tdef fixed_job_name = split_job_name[1].replace('%2F',' ');\n\n\ttry{\n\t\tstage(\"Building on \\\"amigadev/crosstools:m68k-amigaos\\\" for \\\"Amiga Classic\\\"...\") {\n\t\t\tproperties([pipelineTriggers([githubPush()])])\n\t\t\tdef commondir = env.WORKSPACE + '/../' + fixed_job_name + '/'\n\t\t\tdocker.withRegistry(\"https://index.docker.io/v1/\", \"dockerhub\") {\n\t\t\t    def dockerImageRef = docker.image(\"amigadev/crosstools:m68k-amigaos\");\n\t\t\t    dockerImageRef.pull();\n\n\t\t\t    checkout scm;\n\n\t\t\t    dockerImageRef.inside(\"\") {\n\n\t\t\t\t    if (env.CHANGE_ID) {\n\t\t\t\t\t    echo 'Trying to build pull request'\n\t\t\t\t    }\n\n\t\t\t\t    sh \"mkdir -p lib/\"\n\t\t\t\t    sh \"rm -rfv build-68k/*\"\n\n\t\t\t\t    stage(\"Building...\") {\n\t\t\t\t\t    sh \"cmake -S . -B build-68k -DCMAKE_INSTALL_PREFIX=./install -DCMAKE_BUILD_TYPE=Release\"\n\t\t\t\t\t    sh \"cmake --build build-68k --config Release --target install -j 8\"\n\t\t\t\t\t\n\t\t\t\t\t    sh \"cd install && lha -c ../ace.lha ./*\"\n\n\t\t\t\t\t    archiveArtifacts artifacts: '*.zip,*.tar.gz,*.tgz,*.lha'\n\t\t\t\t    }\n\n\n\t\t\t\t    discordSend description: \"Target: Amiga Classic DockerImage: amigadev/crosstools:m68k-amigaos successful!\", footer: \"\", link: env.BUILD_URL, result: currentBuild.currentResult, title: \"[${split_job_name[0]}] Build Successful: ${fixed_job_name} #${env.BUILD_NUMBER}\", webhookURL: env.AMIGADEV_WEBHOOK\n\t\t\t    }\n\t\t    }\n\t    }\n\t} catch(err) {\n\t\tcurrentBuild.result = 'FAILURE'\n\n\t\tdiscordSend description: \"Build Failed: ${fixed_job_name} #${env.BUILD_NUMBER} Target: Amiga Classic DockerImage: amigadev/crosstools:m68k-amigaos (<${env.BUILD_URL}|Open>)\", footer: \"\", link: env.BUILD_URL, result: currentBuild.currentResult, title: \"[${split_job_name[0]}] Build Failed: ${fixed_job_name} #${env.BUILD_NUMBER}\", webhookURL: env.AMIGADEV_WEBHOOK\n\t\tnotify('Build failed')\n\t\tthrow err\n\t}\n}\n\nnode('master') {\n\tkillall_jobs();\n\tdef split_job_name = env.JOB_NAME.split(/\\/{1}/);\n\tdef fixed_job_name = split_job_name[1].replace('%2F',' ');\n\tcheckout(scm);\n\t\n\tenv.COMMIT_MSG = sh (\n\t\tscript: 'git log -1 --pretty=%B ${GIT_COMMIT}',\n\t\treturnStdout: true\n\t).trim();\n\n\tdiscordSend description: \"${env.COMMIT_MSG}\", footer: \"\", link: env.BUILD_URL, result: currentBuild.currentResult, title: \"[${split_job_name[0]}] Build Started: ${fixed_job_name} #${env.BUILD_NUMBER}\", webhookURL: env.AMIGADEV_WEBHOOK\n\n\tdef branches = [:]\n\n\tbranches[\"Build ACE\"] = {\n\t\tnode {\n\t\t\tbuildStep()\n\t\t}\n\t}\n\n\tsh \"rm -rf ./*\"\n\n\tparallel branches;\n}\n"
  },
  {
    "path": "LICENSE",
    "content": "Mozilla Public License Version 2.0\n==================================\n\n1. Definitions\n--------------\n\n1.1. \"Contributor\"\n    means each individual or legal entity that creates, contributes to\n    the creation of, or owns Covered Software.\n\n1.2. \"Contributor Version\"\n    means the combination of the Contributions of others (if any) used\n    by a Contributor and that particular Contributor's Contribution.\n\n1.3. \"Contribution\"\n    means Covered Software of a particular Contributor.\n\n1.4. \"Covered Software\"\n    means Source Code Form to which the initial Contributor has attached\n    the notice in Exhibit A, the Executable Form of such Source Code\n    Form, and Modifications of such Source Code Form, in each case\n    including portions thereof.\n\n1.5. \"Incompatible With Secondary Licenses\"\n    means\n\n    (a) that the initial Contributor has attached the notice described\n        in Exhibit B to the Covered Software; or\n\n    (b) that the Covered Software was made available under the terms of\n        version 1.1 or earlier of the License, but not also under the\n        terms of a Secondary License.\n\n1.6. \"Executable Form\"\n    means any form of the work other than Source Code Form.\n\n1.7. \"Larger Work\"\n    means a work that combines Covered Software with other material, in\n    a separate file or files, that is not Covered Software.\n\n1.8. \"License\"\n    means this document.\n\n1.9. \"Licensable\"\n    means having the right to grant, to the maximum extent possible,\n    whether at the time of the initial grant or subsequently, any and\n    all of the rights conveyed by this License.\n\n1.10. \"Modifications\"\n    means any of the following:\n\n    (a) any file in Source Code Form that results from an addition to,\n        deletion from, or modification of the contents of Covered\n        Software; or\n\n    (b) any new file in Source Code Form that contains any Covered\n        Software.\n\n1.11. \"Patent Claims\" of a Contributor\n    means any patent claim(s), including without limitation, method,\n    process, and apparatus claims, in any patent Licensable by such\n    Contributor that would be infringed, but for the grant of the\n    License, by the making, using, selling, offering for sale, having\n    made, import, or transfer of either its Contributions or its\n    Contributor Version.\n\n1.12. \"Secondary License\"\n    means either the GNU General Public License, Version 2.0, the GNU\n    Lesser General Public License, Version 2.1, the GNU Affero General\n    Public License, Version 3.0, or any later versions of those\n    licenses.\n\n1.13. \"Source Code Form\"\n    means the form of the work preferred for making modifications.\n\n1.14. \"You\" (or \"Your\")\n    means an individual or a legal entity exercising rights under this\n    License. For legal entities, \"You\" includes any entity that\n    controls, is controlled by, or is under common control with You. For\n    purposes of this definition, \"control\" means (a) the power, direct\n    or indirect, to cause the direction or management of such entity,\n    whether by contract or otherwise, or (b) ownership of more than\n    fifty percent (50%) of the outstanding shares or beneficial\n    ownership of such entity.\n\n2. License Grants and Conditions\n--------------------------------\n\n2.1. Grants\n\nEach Contributor hereby grants You a world-wide, royalty-free,\nnon-exclusive license:\n\n(a) under intellectual property rights (other than patent or trademark)\n    Licensable by such Contributor to use, reproduce, make available,\n    modify, display, perform, distribute, and otherwise exploit its\n    Contributions, either on an unmodified basis, with Modifications, or\n    as part of a Larger Work; and\n\n(b) under Patent Claims of such Contributor to make, use, sell, offer\n    for sale, have made, import, and otherwise transfer either its\n    Contributions or its Contributor Version.\n\n2.2. Effective Date\n\nThe licenses granted in Section 2.1 with respect to any Contribution\nbecome effective for each Contribution on the date the Contributor first\ndistributes such Contribution.\n\n2.3. Limitations on Grant Scope\n\nThe licenses granted in this Section 2 are the only rights granted under\nthis License. No additional rights or licenses will be implied from the\ndistribution or licensing of Covered Software under this License.\nNotwithstanding Section 2.1(b) above, no patent license is granted by a\nContributor:\n\n(a) for any code that a Contributor has removed from Covered Software;\n    or\n\n(b) for infringements caused by: (i) Your and any other third party's\n    modifications of Covered Software, or (ii) the combination of its\n    Contributions with other software (except as part of its Contributor\n    Version); or\n\n(c) under Patent Claims infringed by Covered Software in the absence of\n    its Contributions.\n\nThis License does not grant any rights in the trademarks, service marks,\nor logos of any Contributor (except as may be necessary to comply with\nthe notice requirements in Section 3.4).\n\n2.4. Subsequent Licenses\n\nNo Contributor makes additional grants as a result of Your choice to\ndistribute the Covered Software under a subsequent version of this\nLicense (see Section 10.2) or under the terms of a Secondary License (if\npermitted under the terms of Section 3.3).\n\n2.5. Representation\n\nEach Contributor represents that the Contributor believes its\nContributions are its original creation(s) or it has sufficient rights\nto grant the rights to its Contributions conveyed by this License.\n\n2.6. Fair Use\n\nThis License is not intended to limit any rights You have under\napplicable copyright doctrines of fair use, fair dealing, or other\nequivalents.\n\n2.7. Conditions\n\nSections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted\nin Section 2.1.\n\n3. Responsibilities\n-------------------\n\n3.1. Distribution of Source Form\n\nAll distribution of Covered Software in Source Code Form, including any\nModifications that You create or to which You contribute, must be under\nthe terms of this License. You must inform recipients that the Source\nCode Form of the Covered Software is governed by the terms of this\nLicense, and how they can obtain a copy of this License. You may not\nattempt to alter or restrict the recipients' rights in the Source Code\nForm.\n\n3.2. Distribution of Executable Form\n\nIf You distribute Covered Software in Executable Form then:\n\n(a) such Covered Software must also be made available in Source Code\n    Form, as described in Section 3.1, and You must inform recipients of\n    the Executable Form how they can obtain a copy of such Source Code\n    Form by reasonable means in a timely manner, at a charge no more\n    than the cost of distribution to the recipient; and\n\n(b) You may distribute such Executable Form under the terms of this\n    License, or sublicense it under different terms, provided that the\n    license for the Executable Form does not attempt to limit or alter\n    the recipients' rights in the Source Code Form under this License.\n\n3.3. Distribution of a Larger Work\n\nYou may create and distribute a Larger Work under terms of Your choice,\nprovided that You also comply with the requirements of this License for\nthe Covered Software. If the Larger Work is a combination of Covered\nSoftware with a work governed by one or more Secondary Licenses, and the\nCovered Software is not Incompatible With Secondary Licenses, this\nLicense permits You to additionally distribute such Covered Software\nunder the terms of such Secondary License(s), so that the recipient of\nthe Larger Work may, at their option, further distribute the Covered\nSoftware under the terms of either this License or such Secondary\nLicense(s).\n\n3.4. Notices\n\nYou may not remove or alter the substance of any license notices\n(including copyright notices, patent notices, disclaimers of warranty,\nor limitations of liability) contained within the Source Code Form of\nthe Covered Software, except that You may alter any license notices to\nthe extent required to remedy known factual inaccuracies.\n\n3.5. Application of Additional Terms\n\nYou may choose to offer, and to charge a fee for, warranty, support,\nindemnity or liability obligations to one or more recipients of Covered\nSoftware. However, You may do so only on Your own behalf, and not on\nbehalf of any Contributor. You must make it absolutely clear that any\nsuch warranty, support, indemnity, or liability obligation is offered by\nYou alone, and You hereby agree to indemnify every Contributor for any\nliability incurred by such Contributor as a result of warranty, support,\nindemnity or liability terms You offer. You may include additional\ndisclaimers of warranty and limitations of liability specific to any\njurisdiction.\n\n4. Inability to Comply Due to Statute or Regulation\n---------------------------------------------------\n\nIf it is impossible for You to comply with any of the terms of this\nLicense with respect to some or all of the Covered Software due to\nstatute, judicial order, or regulation then You must: (a) comply with\nthe terms of this License to the maximum extent possible; and (b)\ndescribe the limitations and the code they affect. Such description must\nbe placed in a text file included with all distributions of the Covered\nSoftware under this License. Except to the extent prohibited by statute\nor regulation, such description must be sufficiently detailed for a\nrecipient of ordinary skill to be able to understand it.\n\n5. Termination\n--------------\n\n5.1. The rights granted under this License will terminate automatically\nif You fail to comply with any of its terms. However, if You become\ncompliant, then the rights granted under this License from a particular\nContributor are reinstated (a) provisionally, unless and until such\nContributor explicitly and finally terminates Your grants, and (b) on an\nongoing basis, if such Contributor fails to notify You of the\nnon-compliance by some reasonable means prior to 60 days after You have\ncome back into compliance. Moreover, Your grants from a particular\nContributor are reinstated on an ongoing basis if such Contributor\nnotifies You of the non-compliance by some reasonable means, this is the\nfirst time You have received notice of non-compliance with this License\nfrom such Contributor, and You become compliant prior to 30 days after\nYour receipt of the notice.\n\n5.2. If You initiate litigation against any entity by asserting a patent\ninfringement claim (excluding declaratory judgment actions,\ncounter-claims, and cross-claims) alleging that a Contributor Version\ndirectly or indirectly infringes any patent, then the rights granted to\nYou by any and all Contributors for the Covered Software under Section\n2.1 of this License shall terminate.\n\n5.3. In the event of termination under Sections 5.1 or 5.2 above, all\nend user license agreements (excluding distributors and resellers) which\nhave been validly granted by You or Your distributors under this License\nprior to termination shall survive termination.\n\n************************************************************************\n*                                                                      *\n*  6. Disclaimer of Warranty                                           *\n*  -------------------------                                           *\n*                                                                      *\n*  Covered Software is provided under this License on an \"as is\"       *\n*  basis, without warranty of any kind, either expressed, implied, or  *\n*  statutory, including, without limitation, warranties that the       *\n*  Covered Software is free of defects, merchantable, fit for a        *\n*  particular purpose or non-infringing. The entire risk as to the     *\n*  quality and performance of the Covered Software is with You.        *\n*  Should any Covered Software prove defective in any respect, You     *\n*  (not any Contributor) assume the cost of any necessary servicing,   *\n*  repair, or correction. This disclaimer of warranty constitutes an   *\n*  essential part of this License. No use of any Covered Software is   *\n*  authorized under this License except under this disclaimer.         *\n*                                                                      *\n************************************************************************\n\n************************************************************************\n*                                                                      *\n*  7. Limitation of Liability                                          *\n*  --------------------------                                          *\n*                                                                      *\n*  Under no circumstances and under no legal theory, whether tort      *\n*  (including negligence), contract, or otherwise, shall any           *\n*  Contributor, or anyone who distributes Covered Software as          *\n*  permitted above, be liable to You for any direct, indirect,         *\n*  special, incidental, or consequential damages of any character      *\n*  including, without limitation, damages for lost profits, loss of    *\n*  goodwill, work stoppage, computer failure or malfunction, or any    *\n*  and all other commercial damages or losses, even if such party      *\n*  shall have been informed of the possibility of such damages. This   *\n*  limitation of liability shall not apply to liability for death or   *\n*  personal injury resulting from such party's negligence to the       *\n*  extent applicable law prohibits such limitation. Some               *\n*  jurisdictions do not allow the exclusion or limitation of           *\n*  incidental or consequential damages, so this exclusion and          *\n*  limitation may not apply to You.                                    *\n*                                                                      *\n************************************************************************\n\n8. Litigation\n-------------\n\nAny litigation relating to this License may be brought only in the\ncourts of a jurisdiction where the defendant maintains its principal\nplace of business and such litigation shall be governed by laws of that\njurisdiction, without reference to its conflict-of-law provisions.\nNothing in this Section shall prevent a party's ability to bring\ncross-claims or counter-claims.\n\n9. Miscellaneous\n----------------\n\nThis License represents the complete agreement concerning the subject\nmatter hereof. If any provision of this License is held to be\nunenforceable, such provision shall be reformed only to the extent\nnecessary to make it enforceable. Any law or regulation which provides\nthat the language of a contract shall be construed against the drafter\nshall not be used to construe this License against a Contributor.\n\n10. Versions of the License\n---------------------------\n\n10.1. New Versions\n\nMozilla Foundation is the license steward. Except as provided in Section\n10.3, no one other than the license steward has the right to modify or\npublish new versions of this License. Each version will be given a\ndistinguishing version number.\n\n10.2. Effect of New Versions\n\nYou may distribute the Covered Software under the terms of the version\nof the License under which You originally received the Covered Software,\nor under the terms of any subsequent version published by the license\nsteward.\n\n10.3. Modified Versions\n\nIf you create software not governed by this License, and you want to\ncreate a new license for such software, you may create and use a\nmodified version of this License if you rename the license and remove\nany references to the name of the license steward (except to note that\nsuch modified license differs from this License).\n\n10.4. Distributing Source Code Form that is Incompatible With Secondary\nLicenses\n\nIf You choose to distribute Source Code Form that is Incompatible With\nSecondary Licenses under the terms of this version of the License, the\nnotice described in Exhibit B of this License must be attached.\n\nExhibit A - Source Code Form License Notice\n-------------------------------------------\n\n  This Source Code Form is subject to the terms of the Mozilla Public\n  License, v. 2.0. If a copy of the MPL was not distributed with this\n  file, You can obtain one at http://mozilla.org/MPL/2.0/.\n\nIf it is not possible or desirable to put the notice in a particular\nfile, then You may include the notice in a location (such as a LICENSE\nfile in a relevant directory) where a recipient would be likely to look\nfor such a notice.\n\nYou may add additional accurate notices of copyright ownership.\n\nExhibit B - \"Incompatible With Secondary Licenses\" Notice\n---------------------------------------------------------\n\n  This Source Code Form is \"Incompatible With Secondary Licenses\", as\n  defined by the Mozilla Public License, v. 2.0.\n"
  },
  {
    "path": "README.md",
    "content": "# ACE - Amiga C Engine\r\n\r\n[![Documentation](https://codedocs.xyz/AmigaPorts/ACE.svg)](https://codedocs.xyz/AmigaPorts/ACE/)\r\n\r\nGame engine / framework / support library written totally in C for classic Amiga hardware.\r\nLightweight, flexible and hackable.\r\nACE uses Amiga hardware features directly, aiming for as much speed as possible.\r\nThe code is OS-friendly, allowing running from and exiting to Workbench gracefully.\r\n\r\nCurrent feature set is OCS-oriented, although produced code should work on AGA just fine.\r\nAGA features have been added recently and should work but they weren't thoroughly battle-tested.\r\n\r\nFor build instructions basic how to and contributing guidelines, refer to [docs](docs/README.md).\r\n\r\n## Why I should use ACE?\r\n\r\nACE is best if you want to:\r\n\r\n- Learn how to code on Amiga - the only skill you need is familiarity with C language.\r\n  ACE Provides very thin hardware abstraction layer, which aims to be as documented as possible.\r\n  **Lack of documentation is treated as a bug**, so feel free to report it in an issue!\r\n- Code a high performance game/demo but don't want to do it entirely in assembly.\r\n  Use stock ACE functions to make the code work, trim it down for maximum performance.\r\n  Or just write the assembly by hand for parts which really require it.\r\n\r\n## What ACE does\r\n\r\n- Provides slim HAL for audio, blitter, copper, keyboard and mouse.\r\n- Provides view and viewport system which work in similar manner to Amiga OS, but in less bloated way.\r\n- Has lots of runtime error checks when building in debug mode, which are completely gone in release builds.\r\n- Disables OS for maximum performance, but allows re-enabling it when needed - e.g. for file access, memory allocation, etc.\r\n- Provides optional framework which helps in organizing games and reducing boilerplate code.\r\n- Provides code for scrolling large tilemaps in memory-efficient way.\r\n- Requires only kickstart 1.3, but provides OS2.0+ features, like functions using taglists, interleaved bitplane modes, etc.\r\n\r\n## Things you won't find in ACE\r\n\r\n- A Game Maker experience - you need to code game logic and most of the engine yourself.\r\n- Elaborate sprite management.\r\n- Functions for direct data read from floppy sectors.\r\n\r\nMost of those features were deliberately omitted because they can be done in very different ways depending on the game/demo.\r\nStill, the list of open source games is increasing, so you can copy and modify most building blocks from them to suit your needs.\r\n\r\n## Games created using ACE\r\n\r\nIn alphabetical order:\r\n\r\n- [ami-invaders](https://github.com/approxit/amiga-invaders)\r\n- [AMIner](https://github.com/Last-Minute-Creations/AMIner)\r\n- [Atarenium Falcon](https://github.com/Last-Minute-Creations/AtareniumFalcon)\r\n- [Battle Squadron 2](https://github.com/bitwise-brains/AGJ2024_BS2)\r\n- CastleHack\r\n- [Chaos Arena](https://github.com/Last-Minute-Creations/chaosArena)\r\n- [Flappy Ace](https://github.com/NZjeux26/FlappyAceWin)\r\n- [GermZ](https://github.com/Last-Minute-Creations/germz)\r\n- [GermZ Survivor](https://github.com/Last-Minute-Creations/GermzSurvivor)\r\n- [Goblin Villages](https://github.com/Last-Minute-Creations/goblin-villages)\r\n- [Impsbru](https://github.com/approxit/impsbru)\r\n- [OpenFire](https://github.com/Last-Minute-Creations/openFire)\r\n- [Squared](https://github.com/tehKaiN/ld40-squared)\r\n\r\n## Demos created using ACE\r\n\r\nIn alphabetical order:\r\n\r\n- [Casentino Day 2020 invitation](https://github.com/Ozzyboshi/Casentinoday2020AmigaDemo/)\r\n- [Starfield](https://github.com/Ozzyboshi/AmigaStarfield)\r\n\r\n## License, 3rd party code\r\n\r\nUnless otherwise stated, the code is licensed under [Mozilla Public License 2.0](LICENSE). The exceptions are:\r\n\r\n- The ptplayer module is based on [ptplayer](http://aminet.net/package/mus/play/ptplayer.lha) by Frank Wille (Public Domain)\r\n- the mini_std library is based on 3rd party code:\r\n  - [mpaland/printf](https://github.com/mpaland/printf) (MIT)\r\n  - [strtoul](https://github.com/diegocr/libnix/blob/master/stdlib/strtoul.c) from Libnix (Public Domain)\r\n  - [DeidaraC/ctype](https://github.com/DeidaraC/ctype.h/blob/master/ctype.c) (MIT)\r\n  - `qsort()` replacement: [noporpoise/sort_r](https://github.com/noporpoise/sort_r) (Public Domain)\r\n"
  },
  {
    "path": "cmake/CPM.cmake",
    "content": "# CPM.cmake - CMake's missing package manager\n# ===========================================\n# See https://github.com/cpm-cmake/CPM.cmake for usage and update instructions.\n#\n# MIT License\n# -----------\n#[[\n  Copyright (c) 2019-2023 Lars Melchior and contributors\n\n  Permission is hereby granted, free of charge, to any person obtaining a copy\n  of this software and associated documentation files (the \"Software\"), to deal\n  in the Software without restriction, including without limitation the rights\n  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n  copies of the Software, and to permit persons to whom the Software is\n  furnished to do so, subject to the following conditions:\n\n  The above copyright notice and this permission notice shall be included in all\n  copies or substantial portions of the Software.\n\n  THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n  SOFTWARE.\n]]\n\ncmake_minimum_required(VERSION 3.14 FATAL_ERROR)\n\n# Initialize logging prefix\nif(NOT CPM_INDENT)\n  set(CPM_INDENT\n      \"CPM:\"\n      CACHE INTERNAL \"\"\n  )\nendif()\n\nif(NOT COMMAND cpm_message)\n  function(cpm_message)\n    message(${ARGV})\n  endfunction()\nendif()\n\nset(CURRENT_CPM_VERSION 0.40.2)\n\nget_filename_component(CPM_CURRENT_DIRECTORY \"${CMAKE_CURRENT_LIST_DIR}\" REALPATH)\nif(CPM_DIRECTORY)\n  if(NOT CPM_DIRECTORY STREQUAL CPM_CURRENT_DIRECTORY)\n    if(CPM_VERSION VERSION_LESS CURRENT_CPM_VERSION)\n      message(\n        AUTHOR_WARNING\n          \"${CPM_INDENT} \\\nA dependency is using a more recent CPM version (${CURRENT_CPM_VERSION}) than the current project (${CPM_VERSION}). \\\nIt is recommended to upgrade CPM to the most recent version. \\\nSee https://github.com/cpm-cmake/CPM.cmake for more information.\"\n      )\n    endif()\n    if(${CMAKE_VERSION} VERSION_LESS \"3.17.0\")\n      include(FetchContent)\n    endif()\n    return()\n  endif()\n\n  get_property(\n    CPM_INITIALIZED GLOBAL \"\"\n    PROPERTY CPM_INITIALIZED\n    SET\n  )\n  if(CPM_INITIALIZED)\n    return()\n  endif()\nendif()\n\nif(CURRENT_CPM_VERSION MATCHES \"development-version\")\n  message(\n    WARNING \"${CPM_INDENT} Your project is using an unstable development version of CPM.cmake. \\\nPlease update to a recent release if possible. \\\nSee https://github.com/cpm-cmake/CPM.cmake for details.\"\n  )\nendif()\n\nset_property(GLOBAL PROPERTY CPM_INITIALIZED true)\n\nmacro(cpm_set_policies)\n  # the policy allows us to change options without caching\n  cmake_policy(SET CMP0077 NEW)\n  set(CMAKE_POLICY_DEFAULT_CMP0077 NEW)\n\n  # the policy allows us to change set(CACHE) without caching\n  if(POLICY CMP0126)\n    cmake_policy(SET CMP0126 NEW)\n    set(CMAKE_POLICY_DEFAULT_CMP0126 NEW)\n  endif()\n\n  # The policy uses the download time for timestamp, instead of the timestamp in the archive. This\n  # allows for proper rebuilds when a projects url changes\n  if(POLICY CMP0135)\n    cmake_policy(SET CMP0135 NEW)\n    set(CMAKE_POLICY_DEFAULT_CMP0135 NEW)\n  endif()\n\n  # treat relative git repository paths as being relative to the parent project's remote\n  if(POLICY CMP0150)\n    cmake_policy(SET CMP0150 NEW)\n    set(CMAKE_POLICY_DEFAULT_CMP0150 NEW)\n  endif()\nendmacro()\ncpm_set_policies()\n\noption(CPM_USE_LOCAL_PACKAGES \"Always try to use `find_package` to get dependencies\"\n       $ENV{CPM_USE_LOCAL_PACKAGES}\n)\noption(CPM_LOCAL_PACKAGES_ONLY \"Only use `find_package` to get dependencies\"\n       $ENV{CPM_LOCAL_PACKAGES_ONLY}\n)\noption(CPM_DOWNLOAD_ALL \"Always download dependencies from source\" $ENV{CPM_DOWNLOAD_ALL})\noption(CPM_DONT_UPDATE_MODULE_PATH \"Don't update the module path to allow using find_package\"\n       $ENV{CPM_DONT_UPDATE_MODULE_PATH}\n)\noption(CPM_DONT_CREATE_PACKAGE_LOCK \"Don't create a package lock file in the binary path\"\n       $ENV{CPM_DONT_CREATE_PACKAGE_LOCK}\n)\noption(CPM_INCLUDE_ALL_IN_PACKAGE_LOCK\n       \"Add all packages added through CPM.cmake to the package lock\"\n       $ENV{CPM_INCLUDE_ALL_IN_PACKAGE_LOCK}\n)\noption(CPM_USE_NAMED_CACHE_DIRECTORIES\n       \"Use additional directory of package name in cache on the most nested level.\"\n       $ENV{CPM_USE_NAMED_CACHE_DIRECTORIES}\n)\n\nset(CPM_VERSION\n    ${CURRENT_CPM_VERSION}\n    CACHE INTERNAL \"\"\n)\nset(CPM_DIRECTORY\n    ${CPM_CURRENT_DIRECTORY}\n    CACHE INTERNAL \"\"\n)\nset(CPM_FILE\n    ${CMAKE_CURRENT_LIST_FILE}\n    CACHE INTERNAL \"\"\n)\nset(CPM_PACKAGES\n    \"\"\n    CACHE INTERNAL \"\"\n)\nset(CPM_DRY_RUN\n    OFF\n    CACHE INTERNAL \"Don't download or configure dependencies (for testing)\"\n)\n\nif(DEFINED ENV{CPM_SOURCE_CACHE})\n  set(CPM_SOURCE_CACHE_DEFAULT $ENV{CPM_SOURCE_CACHE})\nelse()\n  set(CPM_SOURCE_CACHE_DEFAULT OFF)\nendif()\n\nset(CPM_SOURCE_CACHE\n    ${CPM_SOURCE_CACHE_DEFAULT}\n    CACHE PATH \"Directory to download CPM dependencies\"\n)\n\nif(NOT CPM_DONT_UPDATE_MODULE_PATH)\n  set(CPM_MODULE_PATH\n      \"${CMAKE_BINARY_DIR}/CPM_modules\"\n      CACHE INTERNAL \"\"\n  )\n  # remove old modules\n  file(REMOVE_RECURSE ${CPM_MODULE_PATH})\n  file(MAKE_DIRECTORY ${CPM_MODULE_PATH})\n  # locally added CPM modules should override global packages\n  set(CMAKE_MODULE_PATH \"${CPM_MODULE_PATH};${CMAKE_MODULE_PATH}\")\nendif()\n\nif(NOT CPM_DONT_CREATE_PACKAGE_LOCK)\n  set(CPM_PACKAGE_LOCK_FILE\n      \"${CMAKE_BINARY_DIR}/cpm-package-lock.cmake\"\n      CACHE INTERNAL \"\"\n  )\n  file(WRITE ${CPM_PACKAGE_LOCK_FILE}\n       \"# CPM Package Lock\\n# This file should be committed to version control\\n\\n\"\n  )\nendif()\n\ninclude(FetchContent)\n\n# Try to infer package name from git repository uri (path or url)\nfunction(cpm_package_name_from_git_uri URI RESULT)\n  if(\"${URI}\" MATCHES \"([^/:]+)/?.git/?$\")\n    set(${RESULT}\n        ${CMAKE_MATCH_1}\n        PARENT_SCOPE\n    )\n  else()\n    unset(${RESULT} PARENT_SCOPE)\n  endif()\nendfunction()\n\n# Try to infer package name and version from a url\nfunction(cpm_package_name_and_ver_from_url url outName outVer)\n  if(url MATCHES \"[/\\\\?]([a-zA-Z0-9_\\\\.-]+)\\\\.(tar|tar\\\\.gz|tar\\\\.bz2|zip|ZIP)(\\\\?|/|$)\")\n    # We matched an archive\n    set(filename \"${CMAKE_MATCH_1}\")\n\n    if(filename MATCHES \"([a-zA-Z0-9_\\\\.-]+)[_-]v?(([0-9]+\\\\.)*[0-9]+[a-zA-Z0-9]*)\")\n      # We matched <name>-<version> (ie foo-1.2.3)\n      set(${outName}\n          \"${CMAKE_MATCH_1}\"\n          PARENT_SCOPE\n      )\n      set(${outVer}\n          \"${CMAKE_MATCH_2}\"\n          PARENT_SCOPE\n      )\n    elseif(filename MATCHES \"(([0-9]+\\\\.)+[0-9]+[a-zA-Z0-9]*)\")\n      # We couldn't find a name, but we found a version\n      #\n      # In many cases (which we don't handle here) the url would look something like\n      # `irrelevant/ACTUAL_PACKAGE_NAME/irrelevant/1.2.3.zip`. In such a case we can't possibly\n      # distinguish the package name from the irrelevant bits. Moreover if we try to match the\n      # package name from the filename, we'd get bogus at best.\n      unset(${outName} PARENT_SCOPE)\n      set(${outVer}\n          \"${CMAKE_MATCH_1}\"\n          PARENT_SCOPE\n      )\n    else()\n      # Boldly assume that the file name is the package name.\n      #\n      # Yes, something like `irrelevant/ACTUAL_NAME/irrelevant/download.zip` will ruin our day, but\n      # such cases should be quite rare. No popular service does this... we think.\n      set(${outName}\n          \"${filename}\"\n          PARENT_SCOPE\n      )\n      unset(${outVer} PARENT_SCOPE)\n    endif()\n  else()\n    # No ideas yet what to do with non-archives\n    unset(${outName} PARENT_SCOPE)\n    unset(${outVer} PARENT_SCOPE)\n  endif()\nendfunction()\n\nfunction(cpm_find_package NAME VERSION)\n  string(REPLACE \" \" \";\" EXTRA_ARGS \"${ARGN}\")\n  find_package(${NAME} ${VERSION} ${EXTRA_ARGS} QUIET)\n  if(${CPM_ARGS_NAME}_FOUND)\n    if(DEFINED ${CPM_ARGS_NAME}_VERSION)\n      set(VERSION ${${CPM_ARGS_NAME}_VERSION})\n    endif()\n    cpm_message(STATUS \"${CPM_INDENT} Using local package ${CPM_ARGS_NAME}@${VERSION}\")\n    CPMRegisterPackage(${CPM_ARGS_NAME} \"${VERSION}\")\n    set(CPM_PACKAGE_FOUND\n        YES\n        PARENT_SCOPE\n    )\n  else()\n    set(CPM_PACKAGE_FOUND\n        NO\n        PARENT_SCOPE\n    )\n  endif()\nendfunction()\n\n# Create a custom FindXXX.cmake module for a CPM package This prevents `find_package(NAME)` from\n# finding the system library\nfunction(cpm_create_module_file Name)\n  if(NOT CPM_DONT_UPDATE_MODULE_PATH)\n    # erase any previous modules\n    file(WRITE ${CPM_MODULE_PATH}/Find${Name}.cmake\n         \"include(\\\"${CPM_FILE}\\\")\\n${ARGN}\\nset(${Name}_FOUND TRUE)\"\n    )\n  endif()\nendfunction()\n\n# Find a package locally or fallback to CPMAddPackage\nfunction(CPMFindPackage)\n  set(oneValueArgs NAME VERSION GIT_TAG FIND_PACKAGE_ARGUMENTS)\n\n  cmake_parse_arguments(CPM_ARGS \"\" \"${oneValueArgs}\" \"\" ${ARGN})\n\n  if(NOT DEFINED CPM_ARGS_VERSION)\n    if(DEFINED CPM_ARGS_GIT_TAG)\n      cpm_get_version_from_git_tag(\"${CPM_ARGS_GIT_TAG}\" CPM_ARGS_VERSION)\n    endif()\n  endif()\n\n  set(downloadPackage ${CPM_DOWNLOAD_ALL})\n  if(DEFINED CPM_DOWNLOAD_${CPM_ARGS_NAME})\n    set(downloadPackage ${CPM_DOWNLOAD_${CPM_ARGS_NAME}})\n  elseif(DEFINED ENV{CPM_DOWNLOAD_${CPM_ARGS_NAME}})\n    set(downloadPackage $ENV{CPM_DOWNLOAD_${CPM_ARGS_NAME}})\n  endif()\n  if(downloadPackage)\n    CPMAddPackage(${ARGN})\n    cpm_export_variables(${CPM_ARGS_NAME})\n    return()\n  endif()\n\n  cpm_find_package(${CPM_ARGS_NAME} \"${CPM_ARGS_VERSION}\" ${CPM_ARGS_FIND_PACKAGE_ARGUMENTS})\n\n  if(NOT CPM_PACKAGE_FOUND)\n    CPMAddPackage(${ARGN})\n    cpm_export_variables(${CPM_ARGS_NAME})\n  endif()\n\nendfunction()\n\n# checks if a package has been added before\nfunction(cpm_check_if_package_already_added CPM_ARGS_NAME CPM_ARGS_VERSION)\n  if(\"${CPM_ARGS_NAME}\" IN_LIST CPM_PACKAGES)\n    CPMGetPackageVersion(${CPM_ARGS_NAME} CPM_PACKAGE_VERSION)\n    if(\"${CPM_PACKAGE_VERSION}\" VERSION_LESS \"${CPM_ARGS_VERSION}\")\n      message(\n        WARNING\n          \"${CPM_INDENT} Requires a newer version of ${CPM_ARGS_NAME} (${CPM_ARGS_VERSION}) than currently included (${CPM_PACKAGE_VERSION}).\"\n      )\n    endif()\n    cpm_get_fetch_properties(${CPM_ARGS_NAME})\n    set(${CPM_ARGS_NAME}_ADDED NO)\n    set(CPM_PACKAGE_ALREADY_ADDED\n        YES\n        PARENT_SCOPE\n    )\n    cpm_export_variables(${CPM_ARGS_NAME})\n  else()\n    set(CPM_PACKAGE_ALREADY_ADDED\n        NO\n        PARENT_SCOPE\n    )\n  endif()\nendfunction()\n\n# Parse the argument of CPMAddPackage in case a single one was provided and convert it to a list of\n# arguments which can then be parsed idiomatically. For example gh:foo/bar@1.2.3 will be converted\n# to: GITHUB_REPOSITORY;foo/bar;VERSION;1.2.3\nfunction(cpm_parse_add_package_single_arg arg outArgs)\n  # Look for a scheme\n  if(\"${arg}\" MATCHES \"^([a-zA-Z]+):(.+)$\")\n    string(TOLOWER \"${CMAKE_MATCH_1}\" scheme)\n    set(uri \"${CMAKE_MATCH_2}\")\n\n    # Check for CPM-specific schemes\n    if(scheme STREQUAL \"gh\")\n      set(out \"GITHUB_REPOSITORY;${uri}\")\n      set(packageType \"git\")\n    elseif(scheme STREQUAL \"gl\")\n      set(out \"GITLAB_REPOSITORY;${uri}\")\n      set(packageType \"git\")\n    elseif(scheme STREQUAL \"bb\")\n      set(out \"BITBUCKET_REPOSITORY;${uri}\")\n      set(packageType \"git\")\n      # A CPM-specific scheme was not found. Looks like this is a generic URL so try to determine\n      # type\n    elseif(arg MATCHES \".git/?(@|#|$)\")\n      set(out \"GIT_REPOSITORY;${arg}\")\n      set(packageType \"git\")\n    else()\n      # Fall back to a URL\n      set(out \"URL;${arg}\")\n      set(packageType \"archive\")\n\n      # We could also check for SVN since FetchContent supports it, but SVN is so rare these days.\n      # We just won't bother with the additional complexity it will induce in this function. SVN is\n      # done by multi-arg\n    endif()\n  else()\n    if(arg MATCHES \".git/?(@|#|$)\")\n      set(out \"GIT_REPOSITORY;${arg}\")\n      set(packageType \"git\")\n    else()\n      # Give up\n      message(FATAL_ERROR \"${CPM_INDENT} Can't determine package type of '${arg}'\")\n    endif()\n  endif()\n\n  # For all packages we interpret @... as version. Only replace the last occurrence. Thus URIs\n  # containing '@' can be used\n  string(REGEX REPLACE \"@([^@]+)$\" \";VERSION;\\\\1\" out \"${out}\")\n\n  # Parse the rest according to package type\n  if(packageType STREQUAL \"git\")\n    # For git repos we interpret #... as a tag or branch or commit hash\n    string(REGEX REPLACE \"#([^#]+)$\" \";GIT_TAG;\\\\1\" out \"${out}\")\n  elseif(packageType STREQUAL \"archive\")\n    # For archives we interpret #... as a URL hash.\n    string(REGEX REPLACE \"#([^#]+)$\" \";URL_HASH;\\\\1\" out \"${out}\")\n    # We don't try to parse the version if it's not provided explicitly. cpm_get_version_from_url\n    # should do this at a later point\n  else()\n    # We should never get here. This is an assertion and hitting it means there's a problem with the\n    # code above. A packageType was set, but not handled by this if-else.\n    message(FATAL_ERROR \"${CPM_INDENT} Unsupported package type '${packageType}' of '${arg}'\")\n  endif()\n\n  set(${outArgs}\n      ${out}\n      PARENT_SCOPE\n  )\nendfunction()\n\n# Check that the working directory for a git repo is clean\nfunction(cpm_check_git_working_dir_is_clean repoPath gitTag isClean)\n\n  find_package(Git REQUIRED)\n\n  if(NOT GIT_EXECUTABLE)\n    # No git executable, assume directory is clean\n    set(${isClean}\n        TRUE\n        PARENT_SCOPE\n    )\n    return()\n  endif()\n\n  # check for uncommitted changes\n  execute_process(\n    COMMAND ${GIT_EXECUTABLE} status --porcelain\n    RESULT_VARIABLE resultGitStatus\n    OUTPUT_VARIABLE repoStatus\n    OUTPUT_STRIP_TRAILING_WHITESPACE ERROR_QUIET\n    WORKING_DIRECTORY ${repoPath}\n  )\n  if(resultGitStatus)\n    # not supposed to happen, assume clean anyway\n    message(WARNING \"${CPM_INDENT} Calling git status on folder ${repoPath} failed\")\n    set(${isClean}\n        TRUE\n        PARENT_SCOPE\n    )\n    return()\n  endif()\n\n  if(NOT \"${repoStatus}\" STREQUAL \"\")\n    set(${isClean}\n        FALSE\n        PARENT_SCOPE\n    )\n    return()\n  endif()\n\n  # check for committed changes\n  execute_process(\n    COMMAND ${GIT_EXECUTABLE} diff -s --exit-code ${gitTag}\n    RESULT_VARIABLE resultGitDiff\n    OUTPUT_STRIP_TRAILING_WHITESPACE OUTPUT_QUIET\n    WORKING_DIRECTORY ${repoPath}\n  )\n\n  if(${resultGitDiff} EQUAL 0)\n    set(${isClean}\n        TRUE\n        PARENT_SCOPE\n    )\n  else()\n    set(${isClean}\n        FALSE\n        PARENT_SCOPE\n    )\n  endif()\n\nendfunction()\n\n# Add PATCH_COMMAND to CPM_ARGS_UNPARSED_ARGUMENTS. This method consumes a list of files in ARGN\n# then generates a `PATCH_COMMAND` appropriate for `ExternalProject_Add()`. This command is appended\n# to the parent scope's `CPM_ARGS_UNPARSED_ARGUMENTS`.\nfunction(cpm_add_patches)\n  # Return if no patch files are supplied.\n  if(NOT ARGN)\n    return()\n  endif()\n\n  # Find the patch program.\n  find_program(PATCH_EXECUTABLE patch)\n  if(WIN32 AND NOT PATCH_EXECUTABLE)\n    # The Windows git executable is distributed with patch.exe. Find the path to the executable, if\n    # it exists, then search `../usr/bin` and `../../usr/bin` for patch.exe.\n    find_package(Git QUIET)\n    if(GIT_EXECUTABLE)\n      get_filename_component(extra_search_path ${GIT_EXECUTABLE} DIRECTORY)\n      get_filename_component(extra_search_path_1up ${extra_search_path} DIRECTORY)\n      get_filename_component(extra_search_path_2up ${extra_search_path_1up} DIRECTORY)\n      find_program(\n        PATCH_EXECUTABLE patch HINTS \"${extra_search_path_1up}/usr/bin\"\n                                     \"${extra_search_path_2up}/usr/bin\"\n      )\n    endif()\n  endif()\n  if(NOT PATCH_EXECUTABLE)\n    message(FATAL_ERROR \"Couldn't find `patch` executable to use with PATCHES keyword.\")\n  endif()\n\n  # Create a temporary\n  set(temp_list ${CPM_ARGS_UNPARSED_ARGUMENTS})\n\n  # Ensure each file exists (or error out) and add it to the list.\n  set(first_item True)\n  foreach(PATCH_FILE ${ARGN})\n    # Make sure the patch file exists, if we can't find it, try again in the current directory.\n    if(NOT EXISTS \"${PATCH_FILE}\")\n      if(NOT EXISTS \"${CMAKE_CURRENT_LIST_DIR}/${PATCH_FILE}\")\n        message(FATAL_ERROR \"Couldn't find patch file: '${PATCH_FILE}'\")\n      endif()\n      set(PATCH_FILE \"${CMAKE_CURRENT_LIST_DIR}/${PATCH_FILE}\")\n    endif()\n\n    # Convert to absolute path for use with patch file command.\n    get_filename_component(PATCH_FILE \"${PATCH_FILE}\" ABSOLUTE)\n\n    # The first patch entry must be preceded by \"PATCH_COMMAND\" while the following items are\n    # preceded by \"&&\".\n    if(first_item)\n      set(first_item False)\n      list(APPEND temp_list \"PATCH_COMMAND\")\n    else()\n      list(APPEND temp_list \"&&\")\n    endif()\n    # Add the patch command to the list\n    list(APPEND temp_list \"${PATCH_EXECUTABLE}\" \"-p1\" \"<\" \"${PATCH_FILE}\")\n  endforeach()\n\n  # Move temp out into parent scope.\n  set(CPM_ARGS_UNPARSED_ARGUMENTS\n      ${temp_list}\n      PARENT_SCOPE\n  )\n\nendfunction()\n\n# method to overwrite internal FetchContent properties, to allow using CPM.cmake to overload\n# FetchContent calls. As these are internal cmake properties, this method should be used carefully\n# and may need modification in future CMake versions. Source:\n# https://github.com/Kitware/CMake/blob/dc3d0b5a0a7d26d43d6cfeb511e224533b5d188f/Modules/FetchContent.cmake#L1152\nfunction(cpm_override_fetchcontent contentName)\n  cmake_parse_arguments(PARSE_ARGV 1 arg \"\" \"SOURCE_DIR;BINARY_DIR\" \"\")\n  if(NOT \"${arg_UNPARSED_ARGUMENTS}\" STREQUAL \"\")\n    message(FATAL_ERROR \"${CPM_INDENT} Unsupported arguments: ${arg_UNPARSED_ARGUMENTS}\")\n  endif()\n\n  string(TOLOWER ${contentName} contentNameLower)\n  set(prefix \"_FetchContent_${contentNameLower}\")\n\n  set(propertyName \"${prefix}_sourceDir\")\n  define_property(\n    GLOBAL\n    PROPERTY ${propertyName}\n    BRIEF_DOCS \"Internal implementation detail of FetchContent_Populate()\"\n    FULL_DOCS \"Details used by FetchContent_Populate() for ${contentName}\"\n  )\n  set_property(GLOBAL PROPERTY ${propertyName} \"${arg_SOURCE_DIR}\")\n\n  set(propertyName \"${prefix}_binaryDir\")\n  define_property(\n    GLOBAL\n    PROPERTY ${propertyName}\n    BRIEF_DOCS \"Internal implementation detail of FetchContent_Populate()\"\n    FULL_DOCS \"Details used by FetchContent_Populate() for ${contentName}\"\n  )\n  set_property(GLOBAL PROPERTY ${propertyName} \"${arg_BINARY_DIR}\")\n\n  set(propertyName \"${prefix}_populated\")\n  define_property(\n    GLOBAL\n    PROPERTY ${propertyName}\n    BRIEF_DOCS \"Internal implementation detail of FetchContent_Populate()\"\n    FULL_DOCS \"Details used by FetchContent_Populate() for ${contentName}\"\n  )\n  set_property(GLOBAL PROPERTY ${propertyName} TRUE)\nendfunction()\n\n# Download and add a package from source\nfunction(CPMAddPackage)\n  cpm_set_policies()\n\n  list(LENGTH ARGN argnLength)\n  if(argnLength EQUAL 1)\n    cpm_parse_add_package_single_arg(\"${ARGN}\" ARGN)\n\n    # The shorthand syntax implies EXCLUDE_FROM_ALL and SYSTEM\n    set(ARGN \"${ARGN};EXCLUDE_FROM_ALL;YES;SYSTEM;YES;\")\n  endif()\n\n  set(oneValueArgs\n      NAME\n      FORCE\n      VERSION\n      GIT_TAG\n      DOWNLOAD_ONLY\n      GITHUB_REPOSITORY\n      GITLAB_REPOSITORY\n      BITBUCKET_REPOSITORY\n      GIT_REPOSITORY\n      SOURCE_DIR\n      FIND_PACKAGE_ARGUMENTS\n      NO_CACHE\n      SYSTEM\n      GIT_SHALLOW\n      EXCLUDE_FROM_ALL\n      SOURCE_SUBDIR\n      CUSTOM_CACHE_KEY\n  )\n\n  set(multiValueArgs URL OPTIONS DOWNLOAD_COMMAND PATCHES)\n\n  cmake_parse_arguments(CPM_ARGS \"\" \"${oneValueArgs}\" \"${multiValueArgs}\" \"${ARGN}\")\n\n  # Set default values for arguments\n\n  if(NOT DEFINED CPM_ARGS_VERSION)\n    if(DEFINED CPM_ARGS_GIT_TAG)\n      cpm_get_version_from_git_tag(\"${CPM_ARGS_GIT_TAG}\" CPM_ARGS_VERSION)\n    endif()\n  endif()\n\n  if(CPM_ARGS_DOWNLOAD_ONLY)\n    set(DOWNLOAD_ONLY ${CPM_ARGS_DOWNLOAD_ONLY})\n  else()\n    set(DOWNLOAD_ONLY NO)\n  endif()\n\n  if(DEFINED CPM_ARGS_GITHUB_REPOSITORY)\n    set(CPM_ARGS_GIT_REPOSITORY \"https://github.com/${CPM_ARGS_GITHUB_REPOSITORY}.git\")\n  elseif(DEFINED CPM_ARGS_GITLAB_REPOSITORY)\n    set(CPM_ARGS_GIT_REPOSITORY \"https://gitlab.com/${CPM_ARGS_GITLAB_REPOSITORY}.git\")\n  elseif(DEFINED CPM_ARGS_BITBUCKET_REPOSITORY)\n    set(CPM_ARGS_GIT_REPOSITORY \"https://bitbucket.org/${CPM_ARGS_BITBUCKET_REPOSITORY}.git\")\n  endif()\n\n  if(DEFINED CPM_ARGS_GIT_REPOSITORY)\n    list(APPEND CPM_ARGS_UNPARSED_ARGUMENTS GIT_REPOSITORY ${CPM_ARGS_GIT_REPOSITORY})\n    if(NOT DEFINED CPM_ARGS_GIT_TAG)\n      set(CPM_ARGS_GIT_TAG v${CPM_ARGS_VERSION})\n    endif()\n\n    # If a name wasn't provided, try to infer it from the git repo\n    if(NOT DEFINED CPM_ARGS_NAME)\n      cpm_package_name_from_git_uri(${CPM_ARGS_GIT_REPOSITORY} CPM_ARGS_NAME)\n    endif()\n  endif()\n\n  set(CPM_SKIP_FETCH FALSE)\n\n  if(DEFINED CPM_ARGS_GIT_TAG)\n    list(APPEND CPM_ARGS_UNPARSED_ARGUMENTS GIT_TAG ${CPM_ARGS_GIT_TAG})\n    # If GIT_SHALLOW is explicitly specified, honor the value.\n    if(DEFINED CPM_ARGS_GIT_SHALLOW)\n      list(APPEND CPM_ARGS_UNPARSED_ARGUMENTS GIT_SHALLOW ${CPM_ARGS_GIT_SHALLOW})\n    endif()\n  endif()\n\n  if(DEFINED CPM_ARGS_URL)\n    # If a name or version aren't provided, try to infer them from the URL\n    list(GET CPM_ARGS_URL 0 firstUrl)\n    cpm_package_name_and_ver_from_url(${firstUrl} nameFromUrl verFromUrl)\n    # If we fail to obtain name and version from the first URL, we could try other URLs if any.\n    # However multiple URLs are expected to be quite rare, so for now we won't bother.\n\n    # If the caller provided their own name and version, they trump the inferred ones.\n    if(NOT DEFINED CPM_ARGS_NAME)\n      set(CPM_ARGS_NAME ${nameFromUrl})\n    endif()\n    if(NOT DEFINED CPM_ARGS_VERSION)\n      set(CPM_ARGS_VERSION ${verFromUrl})\n    endif()\n\n    list(APPEND CPM_ARGS_UNPARSED_ARGUMENTS URL \"${CPM_ARGS_URL}\")\n  endif()\n\n  # Check for required arguments\n\n  if(NOT DEFINED CPM_ARGS_NAME)\n    message(\n      FATAL_ERROR\n        \"${CPM_INDENT} 'NAME' was not provided and couldn't be automatically inferred for package added with arguments: '${ARGN}'\"\n    )\n  endif()\n\n  # Check if package has been added before\n  cpm_check_if_package_already_added(${CPM_ARGS_NAME} \"${CPM_ARGS_VERSION}\")\n  if(CPM_PACKAGE_ALREADY_ADDED)\n    cpm_export_variables(${CPM_ARGS_NAME})\n    return()\n  endif()\n\n  # Check for manual overrides\n  if(NOT CPM_ARGS_FORCE AND NOT \"${CPM_${CPM_ARGS_NAME}_SOURCE}\" STREQUAL \"\")\n    set(PACKAGE_SOURCE ${CPM_${CPM_ARGS_NAME}_SOURCE})\n    set(CPM_${CPM_ARGS_NAME}_SOURCE \"\")\n    CPMAddPackage(\n      NAME \"${CPM_ARGS_NAME}\"\n      SOURCE_DIR \"${PACKAGE_SOURCE}\"\n      EXCLUDE_FROM_ALL \"${CPM_ARGS_EXCLUDE_FROM_ALL}\"\n      SYSTEM \"${CPM_ARGS_SYSTEM}\"\n      PATCHES \"${CPM_ARGS_PATCHES}\"\n      OPTIONS \"${CPM_ARGS_OPTIONS}\"\n      SOURCE_SUBDIR \"${CPM_ARGS_SOURCE_SUBDIR}\"\n      DOWNLOAD_ONLY \"${DOWNLOAD_ONLY}\"\n      FORCE True\n    )\n    cpm_export_variables(${CPM_ARGS_NAME})\n    return()\n  endif()\n\n  # Check for available declaration\n  if(NOT CPM_ARGS_FORCE AND NOT \"${CPM_DECLARATION_${CPM_ARGS_NAME}}\" STREQUAL \"\")\n    set(declaration ${CPM_DECLARATION_${CPM_ARGS_NAME}})\n    set(CPM_DECLARATION_${CPM_ARGS_NAME} \"\")\n    CPMAddPackage(${declaration})\n    cpm_export_variables(${CPM_ARGS_NAME})\n    # checking again to ensure version and option compatibility\n    cpm_check_if_package_already_added(${CPM_ARGS_NAME} \"${CPM_ARGS_VERSION}\")\n    return()\n  endif()\n\n  if(NOT CPM_ARGS_FORCE)\n    if(CPM_USE_LOCAL_PACKAGES OR CPM_LOCAL_PACKAGES_ONLY)\n      cpm_find_package(${CPM_ARGS_NAME} \"${CPM_ARGS_VERSION}\" ${CPM_ARGS_FIND_PACKAGE_ARGUMENTS})\n\n      if(CPM_PACKAGE_FOUND)\n        cpm_export_variables(${CPM_ARGS_NAME})\n        return()\n      endif()\n\n      if(CPM_LOCAL_PACKAGES_ONLY)\n        message(\n          SEND_ERROR\n            \"${CPM_INDENT} ${CPM_ARGS_NAME} not found via find_package(${CPM_ARGS_NAME} ${CPM_ARGS_VERSION})\"\n        )\n      endif()\n    endif()\n  endif()\n\n  CPMRegisterPackage(\"${CPM_ARGS_NAME}\" \"${CPM_ARGS_VERSION}\")\n\n  if(DEFINED CPM_ARGS_GIT_TAG)\n    set(PACKAGE_INFO \"${CPM_ARGS_GIT_TAG}\")\n  elseif(DEFINED CPM_ARGS_SOURCE_DIR)\n    set(PACKAGE_INFO \"${CPM_ARGS_SOURCE_DIR}\")\n  else()\n    set(PACKAGE_INFO \"${CPM_ARGS_VERSION}\")\n  endif()\n\n  if(DEFINED FETCHCONTENT_BASE_DIR)\n    # respect user's FETCHCONTENT_BASE_DIR if set\n    set(CPM_FETCHCONTENT_BASE_DIR ${FETCHCONTENT_BASE_DIR})\n  else()\n    set(CPM_FETCHCONTENT_BASE_DIR ${CMAKE_BINARY_DIR}/_deps)\n  endif()\n\n  cpm_add_patches(${CPM_ARGS_PATCHES})\n\n  if(DEFINED CPM_ARGS_DOWNLOAD_COMMAND)\n    list(APPEND CPM_ARGS_UNPARSED_ARGUMENTS DOWNLOAD_COMMAND ${CPM_ARGS_DOWNLOAD_COMMAND})\n  elseif(DEFINED CPM_ARGS_SOURCE_DIR)\n    list(APPEND CPM_ARGS_UNPARSED_ARGUMENTS SOURCE_DIR ${CPM_ARGS_SOURCE_DIR})\n    if(NOT IS_ABSOLUTE ${CPM_ARGS_SOURCE_DIR})\n      # Expand `CPM_ARGS_SOURCE_DIR` relative path. This is important because EXISTS doesn't work\n      # for relative paths.\n      get_filename_component(\n        source_directory ${CPM_ARGS_SOURCE_DIR} REALPATH BASE_DIR ${CMAKE_CURRENT_BINARY_DIR}\n      )\n    else()\n      set(source_directory ${CPM_ARGS_SOURCE_DIR})\n    endif()\n    if(NOT EXISTS ${source_directory})\n      string(TOLOWER ${CPM_ARGS_NAME} lower_case_name)\n      # remove timestamps so CMake will re-download the dependency\n      file(REMOVE_RECURSE \"${CPM_FETCHCONTENT_BASE_DIR}/${lower_case_name}-subbuild\")\n    endif()\n  elseif(CPM_SOURCE_CACHE AND NOT CPM_ARGS_NO_CACHE)\n    string(TOLOWER ${CPM_ARGS_NAME} lower_case_name)\n    set(origin_parameters ${CPM_ARGS_UNPARSED_ARGUMENTS})\n    list(SORT origin_parameters)\n    if(CPM_ARGS_CUSTOM_CACHE_KEY)\n      # Application set a custom unique directory name\n      set(download_directory ${CPM_SOURCE_CACHE}/${lower_case_name}/${CPM_ARGS_CUSTOM_CACHE_KEY})\n    elseif(CPM_USE_NAMED_CACHE_DIRECTORIES)\n      string(SHA1 origin_hash \"${origin_parameters};NEW_CACHE_STRUCTURE_TAG\")\n      set(download_directory ${CPM_SOURCE_CACHE}/${lower_case_name}/${origin_hash}/${CPM_ARGS_NAME})\n    else()\n      string(SHA1 origin_hash \"${origin_parameters}\")\n      set(download_directory ${CPM_SOURCE_CACHE}/${lower_case_name}/${origin_hash})\n    endif()\n    # Expand `download_directory` relative path. This is important because EXISTS doesn't work for\n    # relative paths.\n    get_filename_component(download_directory ${download_directory} ABSOLUTE)\n    list(APPEND CPM_ARGS_UNPARSED_ARGUMENTS SOURCE_DIR ${download_directory})\n\n    if(CPM_SOURCE_CACHE)\n      file(LOCK ${download_directory}/../cmake.lock)\n    endif()\n\n    if(EXISTS ${download_directory})\n      if(CPM_SOURCE_CACHE)\n        file(LOCK ${download_directory}/../cmake.lock RELEASE)\n      endif()\n\n      cpm_store_fetch_properties(\n        ${CPM_ARGS_NAME} \"${download_directory}\"\n        \"${CPM_FETCHCONTENT_BASE_DIR}/${lower_case_name}-build\"\n      )\n      cpm_get_fetch_properties(\"${CPM_ARGS_NAME}\")\n\n      if(DEFINED CPM_ARGS_GIT_TAG AND NOT (PATCH_COMMAND IN_LIST CPM_ARGS_UNPARSED_ARGUMENTS))\n        # warn if cache has been changed since checkout\n        cpm_check_git_working_dir_is_clean(${download_directory} ${CPM_ARGS_GIT_TAG} IS_CLEAN)\n        if(NOT ${IS_CLEAN})\n          message(\n            WARNING \"${CPM_INDENT} Cache for ${CPM_ARGS_NAME} (${download_directory}) is dirty\"\n          )\n        endif()\n      endif()\n\n      cpm_add_subdirectory(\n        \"${CPM_ARGS_NAME}\"\n        \"${DOWNLOAD_ONLY}\"\n        \"${${CPM_ARGS_NAME}_SOURCE_DIR}/${CPM_ARGS_SOURCE_SUBDIR}\"\n        \"${${CPM_ARGS_NAME}_BINARY_DIR}\"\n        \"${CPM_ARGS_EXCLUDE_FROM_ALL}\"\n        \"${CPM_ARGS_SYSTEM}\"\n        \"${CPM_ARGS_OPTIONS}\"\n      )\n      set(PACKAGE_INFO \"${PACKAGE_INFO} at ${download_directory}\")\n\n      # As the source dir is already cached/populated, we override the call to FetchContent.\n      set(CPM_SKIP_FETCH TRUE)\n      cpm_override_fetchcontent(\n        \"${lower_case_name}\" SOURCE_DIR \"${${CPM_ARGS_NAME}_SOURCE_DIR}/${CPM_ARGS_SOURCE_SUBDIR}\"\n        BINARY_DIR \"${${CPM_ARGS_NAME}_BINARY_DIR}\"\n      )\n\n    else()\n      # Enable shallow clone when GIT_TAG is not a commit hash. Our guess may not be accurate, but\n      # it should guarantee no commit hash get mis-detected.\n      if(NOT DEFINED CPM_ARGS_GIT_SHALLOW)\n        cpm_is_git_tag_commit_hash(\"${CPM_ARGS_GIT_TAG}\" IS_HASH)\n        if(NOT ${IS_HASH})\n          list(APPEND CPM_ARGS_UNPARSED_ARGUMENTS GIT_SHALLOW TRUE)\n        endif()\n      endif()\n\n      # remove timestamps so CMake will re-download the dependency\n      file(REMOVE_RECURSE ${CPM_FETCHCONTENT_BASE_DIR}/${lower_case_name}-subbuild)\n      set(PACKAGE_INFO \"${PACKAGE_INFO} to ${download_directory}\")\n    endif()\n  endif()\n\n  cpm_create_module_file(${CPM_ARGS_NAME} \"CPMAddPackage(\\\"${ARGN}\\\")\")\n\n  if(CPM_PACKAGE_LOCK_ENABLED)\n    if((CPM_ARGS_VERSION AND NOT CPM_ARGS_SOURCE_DIR) OR CPM_INCLUDE_ALL_IN_PACKAGE_LOCK)\n      cpm_add_to_package_lock(${CPM_ARGS_NAME} \"${ARGN}\")\n    elseif(CPM_ARGS_SOURCE_DIR)\n      cpm_add_comment_to_package_lock(${CPM_ARGS_NAME} \"local directory\")\n    else()\n      cpm_add_comment_to_package_lock(${CPM_ARGS_NAME} \"${ARGN}\")\n    endif()\n  endif()\n\n  cpm_message(\n    STATUS \"${CPM_INDENT} Adding package ${CPM_ARGS_NAME}@${CPM_ARGS_VERSION} (${PACKAGE_INFO})\"\n  )\n\n  if(NOT CPM_SKIP_FETCH)\n    # CMake 3.28 added EXCLUDE, SYSTEM (3.25), and SOURCE_SUBDIR (3.18) to FetchContent_Declare.\n    # Calling FetchContent_MakeAvailable will then internally forward these options to\n    # add_subdirectory. Up until these changes, we had to call FetchContent_Populate and\n    # add_subdirectory separately, which is no longer necessary and has been deprecated as of 3.30.\n    set(fetchContentDeclareExtraArgs \"\")\n    if(${CMAKE_VERSION} VERSION_GREATER_EQUAL \"3.28.0\")\n      if(${CPM_ARGS_EXCLUDE_FROM_ALL})\n        list(APPEND fetchContentDeclareExtraArgs EXCLUDE_FROM_ALL)\n      endif()\n      if(${CPM_ARGS_SYSTEM})\n        list(APPEND fetchContentDeclareExtraArgs SYSTEM)\n      endif()\n      if(DEFINED CPM_ARGS_SOURCE_SUBDIR)\n        list(APPEND fetchContentDeclareExtraArgs SOURCE_SUBDIR ${CPM_ARGS_SOURCE_SUBDIR})\n      endif()\n      # For CMake version <3.28 OPTIONS are parsed in cpm_add_subdirectory\n      if(CPM_ARGS_OPTIONS AND NOT DOWNLOAD_ONLY)\n        foreach(OPTION ${CPM_ARGS_OPTIONS})\n          cpm_parse_option(\"${OPTION}\")\n          set(${OPTION_KEY} \"${OPTION_VALUE}\")\n        endforeach()\n      endif()\n    endif()\n    cpm_declare_fetch(\n      \"${CPM_ARGS_NAME}\" ${fetchContentDeclareExtraArgs} \"${CPM_ARGS_UNPARSED_ARGUMENTS}\"\n    )\n\n    cpm_fetch_package(\"${CPM_ARGS_NAME}\" ${DOWNLOAD_ONLY} populated ${CPM_ARGS_UNPARSED_ARGUMENTS})\n    if(CPM_SOURCE_CACHE AND download_directory)\n      file(LOCK ${download_directory}/../cmake.lock RELEASE)\n    endif()\n    if(${populated} AND ${CMAKE_VERSION} VERSION_LESS \"3.28.0\")\n      cpm_add_subdirectory(\n        \"${CPM_ARGS_NAME}\"\n        \"${DOWNLOAD_ONLY}\"\n        \"${${CPM_ARGS_NAME}_SOURCE_DIR}/${CPM_ARGS_SOURCE_SUBDIR}\"\n        \"${${CPM_ARGS_NAME}_BINARY_DIR}\"\n        \"${CPM_ARGS_EXCLUDE_FROM_ALL}\"\n        \"${CPM_ARGS_SYSTEM}\"\n        \"${CPM_ARGS_OPTIONS}\"\n      )\n    endif()\n    cpm_get_fetch_properties(\"${CPM_ARGS_NAME}\")\n  endif()\n\n  set(${CPM_ARGS_NAME}_ADDED YES)\n  cpm_export_variables(\"${CPM_ARGS_NAME}\")\nendfunction()\n\n# Fetch a previously declared package\nmacro(CPMGetPackage Name)\n  if(DEFINED \"CPM_DECLARATION_${Name}\")\n    CPMAddPackage(NAME ${Name})\n  else()\n    message(SEND_ERROR \"${CPM_INDENT} Cannot retrieve package ${Name}: no declaration available\")\n  endif()\nendmacro()\n\n# export variables available to the caller to the parent scope expects ${CPM_ARGS_NAME} to be set\nmacro(cpm_export_variables name)\n  set(${name}_SOURCE_DIR\n      \"${${name}_SOURCE_DIR}\"\n      PARENT_SCOPE\n  )\n  set(${name}_BINARY_DIR\n      \"${${name}_BINARY_DIR}\"\n      PARENT_SCOPE\n  )\n  set(${name}_ADDED\n      \"${${name}_ADDED}\"\n      PARENT_SCOPE\n  )\n  set(CPM_LAST_PACKAGE_NAME\n      \"${name}\"\n      PARENT_SCOPE\n  )\nendmacro()\n\n# declares a package, so that any call to CPMAddPackage for the package name will use these\n# arguments instead. Previous declarations will not be overridden.\nmacro(CPMDeclarePackage Name)\n  if(NOT DEFINED \"CPM_DECLARATION_${Name}\")\n    set(\"CPM_DECLARATION_${Name}\" \"${ARGN}\")\n  endif()\nendmacro()\n\nfunction(cpm_add_to_package_lock Name)\n  if(NOT CPM_DONT_CREATE_PACKAGE_LOCK)\n    cpm_prettify_package_arguments(PRETTY_ARGN false ${ARGN})\n    file(APPEND ${CPM_PACKAGE_LOCK_FILE} \"# ${Name}\\nCPMDeclarePackage(${Name}\\n${PRETTY_ARGN})\\n\")\n  endif()\nendfunction()\n\nfunction(cpm_add_comment_to_package_lock Name)\n  if(NOT CPM_DONT_CREATE_PACKAGE_LOCK)\n    cpm_prettify_package_arguments(PRETTY_ARGN true ${ARGN})\n    file(APPEND ${CPM_PACKAGE_LOCK_FILE}\n         \"# ${Name} (unversioned)\\n# CPMDeclarePackage(${Name}\\n${PRETTY_ARGN}#)\\n\"\n    )\n  endif()\nendfunction()\n\n# includes the package lock file if it exists and creates a target `cpm-update-package-lock` to\n# update it\nmacro(CPMUsePackageLock file)\n  if(NOT CPM_DONT_CREATE_PACKAGE_LOCK)\n    get_filename_component(CPM_ABSOLUTE_PACKAGE_LOCK_PATH ${file} ABSOLUTE)\n    if(EXISTS ${CPM_ABSOLUTE_PACKAGE_LOCK_PATH})\n      include(${CPM_ABSOLUTE_PACKAGE_LOCK_PATH})\n    endif()\n    if(NOT TARGET cpm-update-package-lock)\n      add_custom_target(\n        cpm-update-package-lock COMMAND ${CMAKE_COMMAND} -E copy ${CPM_PACKAGE_LOCK_FILE}\n                                        ${CPM_ABSOLUTE_PACKAGE_LOCK_PATH}\n      )\n    endif()\n    set(CPM_PACKAGE_LOCK_ENABLED true)\n  endif()\nendmacro()\n\n# registers a package that has been added to CPM\nfunction(CPMRegisterPackage PACKAGE VERSION)\n  list(APPEND CPM_PACKAGES ${PACKAGE})\n  set(CPM_PACKAGES\n      ${CPM_PACKAGES}\n      CACHE INTERNAL \"\"\n  )\n  set(\"CPM_PACKAGE_${PACKAGE}_VERSION\"\n      ${VERSION}\n      CACHE INTERNAL \"\"\n  )\nendfunction()\n\n# retrieve the current version of the package to ${OUTPUT}\nfunction(CPMGetPackageVersion PACKAGE OUTPUT)\n  set(${OUTPUT}\n      \"${CPM_PACKAGE_${PACKAGE}_VERSION}\"\n      PARENT_SCOPE\n  )\nendfunction()\n\n# declares a package in FetchContent_Declare\nfunction(cpm_declare_fetch PACKAGE)\n  if(${CPM_DRY_RUN})\n    cpm_message(STATUS \"${CPM_INDENT} Package not declared (dry run)\")\n    return()\n  endif()\n\n  FetchContent_Declare(${PACKAGE} ${ARGN})\nendfunction()\n\n# returns properties for a package previously defined by cpm_declare_fetch\nfunction(cpm_get_fetch_properties PACKAGE)\n  if(${CPM_DRY_RUN})\n    return()\n  endif()\n\n  set(${PACKAGE}_SOURCE_DIR\n      \"${CPM_PACKAGE_${PACKAGE}_SOURCE_DIR}\"\n      PARENT_SCOPE\n  )\n  set(${PACKAGE}_BINARY_DIR\n      \"${CPM_PACKAGE_${PACKAGE}_BINARY_DIR}\"\n      PARENT_SCOPE\n  )\nendfunction()\n\nfunction(cpm_store_fetch_properties PACKAGE source_dir binary_dir)\n  if(${CPM_DRY_RUN})\n    return()\n  endif()\n\n  set(CPM_PACKAGE_${PACKAGE}_SOURCE_DIR\n      \"${source_dir}\"\n      CACHE INTERNAL \"\"\n  )\n  set(CPM_PACKAGE_${PACKAGE}_BINARY_DIR\n      \"${binary_dir}\"\n      CACHE INTERNAL \"\"\n  )\nendfunction()\n\n# adds a package as a subdirectory if viable, according to provided options\nfunction(\n  cpm_add_subdirectory\n  PACKAGE\n  DOWNLOAD_ONLY\n  SOURCE_DIR\n  BINARY_DIR\n  EXCLUDE\n  SYSTEM\n  OPTIONS\n)\n\n  if(NOT DOWNLOAD_ONLY AND EXISTS ${SOURCE_DIR}/CMakeLists.txt)\n    set(addSubdirectoryExtraArgs \"\")\n    if(EXCLUDE)\n      list(APPEND addSubdirectoryExtraArgs EXCLUDE_FROM_ALL)\n    endif()\n    if(\"${SYSTEM}\" AND \"${CMAKE_VERSION}\" VERSION_GREATER_EQUAL \"3.25\")\n      # https://cmake.org/cmake/help/latest/prop_dir/SYSTEM.html#prop_dir:SYSTEM\n      list(APPEND addSubdirectoryExtraArgs SYSTEM)\n    endif()\n    if(OPTIONS)\n      foreach(OPTION ${OPTIONS})\n        cpm_parse_option(\"${OPTION}\")\n        set(${OPTION_KEY} \"${OPTION_VALUE}\")\n      endforeach()\n    endif()\n    set(CPM_OLD_INDENT \"${CPM_INDENT}\")\n    set(CPM_INDENT \"${CPM_INDENT} ${PACKAGE}:\")\n    add_subdirectory(${SOURCE_DIR} ${BINARY_DIR} ${addSubdirectoryExtraArgs})\n    set(CPM_INDENT \"${CPM_OLD_INDENT}\")\n  endif()\nendfunction()\n\n# downloads a previously declared package via FetchContent and exports the variables\n# `${PACKAGE}_SOURCE_DIR` and `${PACKAGE}_BINARY_DIR` to the parent scope\nfunction(cpm_fetch_package PACKAGE DOWNLOAD_ONLY populated)\n  set(${populated}\n      FALSE\n      PARENT_SCOPE\n  )\n  if(${CPM_DRY_RUN})\n    cpm_message(STATUS \"${CPM_INDENT} Package ${PACKAGE} not fetched (dry run)\")\n    return()\n  endif()\n\n  FetchContent_GetProperties(${PACKAGE})\n\n  string(TOLOWER \"${PACKAGE}\" lower_case_name)\n\n  if(NOT ${lower_case_name}_POPULATED)\n    if(${CMAKE_VERSION} VERSION_GREATER_EQUAL \"3.28.0\")\n      if(DOWNLOAD_ONLY)\n        # MakeAvailable will call add_subdirectory internally which is not what we want when\n        # DOWNLOAD_ONLY is set. Populate will only download the dependency without adding it to the\n        # build\n        FetchContent_Populate(\n          ${PACKAGE}\n          SOURCE_DIR \"${CPM_FETCHCONTENT_BASE_DIR}/${lower_case_name}-src\"\n          BINARY_DIR \"${CPM_FETCHCONTENT_BASE_DIR}/${lower_case_name}-build\"\n          SUBBUILD_DIR \"${CPM_FETCHCONTENT_BASE_DIR}/${lower_case_name}-subbuild\"\n          ${ARGN}\n        )\n      else()\n        FetchContent_MakeAvailable(${PACKAGE})\n      endif()\n    else()\n      FetchContent_Populate(${PACKAGE})\n    endif()\n    set(${populated}\n        TRUE\n        PARENT_SCOPE\n    )\n  endif()\n\n  cpm_store_fetch_properties(\n    ${CPM_ARGS_NAME} ${${lower_case_name}_SOURCE_DIR} ${${lower_case_name}_BINARY_DIR}\n  )\n\n  set(${PACKAGE}_SOURCE_DIR\n      ${${lower_case_name}_SOURCE_DIR}\n      PARENT_SCOPE\n  )\n  set(${PACKAGE}_BINARY_DIR\n      ${${lower_case_name}_BINARY_DIR}\n      PARENT_SCOPE\n  )\nendfunction()\n\n# splits a package option\nfunction(cpm_parse_option OPTION)\n  string(REGEX MATCH \"^[^ ]+\" OPTION_KEY \"${OPTION}\")\n  string(LENGTH \"${OPTION}\" OPTION_LENGTH)\n  string(LENGTH \"${OPTION_KEY}\" OPTION_KEY_LENGTH)\n  if(OPTION_KEY_LENGTH STREQUAL OPTION_LENGTH)\n    # no value for key provided, assume user wants to set option to \"ON\"\n    set(OPTION_VALUE \"ON\")\n  else()\n    math(EXPR OPTION_KEY_LENGTH \"${OPTION_KEY_LENGTH}+1\")\n    string(SUBSTRING \"${OPTION}\" \"${OPTION_KEY_LENGTH}\" \"-1\" OPTION_VALUE)\n  endif()\n  set(OPTION_KEY\n      \"${OPTION_KEY}\"\n      PARENT_SCOPE\n  )\n  set(OPTION_VALUE\n      \"${OPTION_VALUE}\"\n      PARENT_SCOPE\n  )\nendfunction()\n\n# guesses the package version from a git tag\nfunction(cpm_get_version_from_git_tag GIT_TAG RESULT)\n  string(LENGTH ${GIT_TAG} length)\n  if(length EQUAL 40)\n    # GIT_TAG is probably a git hash\n    set(${RESULT}\n        0\n        PARENT_SCOPE\n    )\n  else()\n    string(REGEX MATCH \"v?([0123456789.]*).*\" _ ${GIT_TAG})\n    set(${RESULT}\n        ${CMAKE_MATCH_1}\n        PARENT_SCOPE\n    )\n  endif()\nendfunction()\n\n# guesses if the git tag is a commit hash or an actual tag or a branch name.\nfunction(cpm_is_git_tag_commit_hash GIT_TAG RESULT)\n  string(LENGTH \"${GIT_TAG}\" length)\n  # full hash has 40 characters, and short hash has at least 7 characters.\n  if(length LESS 7 OR length GREATER 40)\n    set(${RESULT}\n        0\n        PARENT_SCOPE\n    )\n  else()\n    if(${GIT_TAG} MATCHES \"^[a-fA-F0-9]+$\")\n      set(${RESULT}\n          1\n          PARENT_SCOPE\n      )\n    else()\n      set(${RESULT}\n          0\n          PARENT_SCOPE\n      )\n    endif()\n  endif()\nendfunction()\n\nfunction(cpm_prettify_package_arguments OUT_VAR IS_IN_COMMENT)\n  set(oneValueArgs\n      NAME\n      FORCE\n      VERSION\n      GIT_TAG\n      DOWNLOAD_ONLY\n      GITHUB_REPOSITORY\n      GITLAB_REPOSITORY\n      BITBUCKET_REPOSITORY\n      GIT_REPOSITORY\n      SOURCE_DIR\n      FIND_PACKAGE_ARGUMENTS\n      NO_CACHE\n      SYSTEM\n      GIT_SHALLOW\n      EXCLUDE_FROM_ALL\n      SOURCE_SUBDIR\n  )\n  set(multiValueArgs URL OPTIONS DOWNLOAD_COMMAND)\n  cmake_parse_arguments(CPM_ARGS \"\" \"${oneValueArgs}\" \"${multiValueArgs}\" ${ARGN})\n\n  foreach(oneArgName ${oneValueArgs})\n    if(DEFINED CPM_ARGS_${oneArgName})\n      if(${IS_IN_COMMENT})\n        string(APPEND PRETTY_OUT_VAR \"#\")\n      endif()\n      if(${oneArgName} STREQUAL \"SOURCE_DIR\")\n        string(REPLACE ${CMAKE_SOURCE_DIR} \"\\${CMAKE_SOURCE_DIR}\" CPM_ARGS_${oneArgName}\n                       ${CPM_ARGS_${oneArgName}}\n        )\n      endif()\n      string(APPEND PRETTY_OUT_VAR \"  ${oneArgName} ${CPM_ARGS_${oneArgName}}\\n\")\n    endif()\n  endforeach()\n  foreach(multiArgName ${multiValueArgs})\n    if(DEFINED CPM_ARGS_${multiArgName})\n      if(${IS_IN_COMMENT})\n        string(APPEND PRETTY_OUT_VAR \"#\")\n      endif()\n      string(APPEND PRETTY_OUT_VAR \"  ${multiArgName}\\n\")\n      foreach(singleOption ${CPM_ARGS_${multiArgName}})\n        if(${IS_IN_COMMENT})\n          string(APPEND PRETTY_OUT_VAR \"#\")\n        endif()\n        string(APPEND PRETTY_OUT_VAR \"    \\\"${singleOption}\\\"\\n\")\n      endforeach()\n    endif()\n  endforeach()\n\n  if(NOT \"${CPM_ARGS_UNPARSED_ARGUMENTS}\" STREQUAL \"\")\n    if(${IS_IN_COMMENT})\n      string(APPEND PRETTY_OUT_VAR \"#\")\n    endif()\n    string(APPEND PRETTY_OUT_VAR \" \")\n    foreach(CPM_ARGS_UNPARSED_ARGUMENT ${CPM_ARGS_UNPARSED_ARGUMENTS})\n      string(APPEND PRETTY_OUT_VAR \" ${CPM_ARGS_UNPARSED_ARGUMENT}\")\n    endforeach()\n    string(APPEND PRETTY_OUT_VAR \"\\n\")\n  endif()\n\n  set(${OUT_VAR}\n      ${PRETTY_OUT_VAR}\n      PARENT_SCOPE\n  )\n\nendfunction()\n"
  },
  {
    "path": "cmake/ace_config.cmake",
    "content": "set(ACE_LIBRARY_KIND OBJECT CACHE STRING \"Build kind: static library or bunch of .o files. OBJECT allows for more link-time optimizations.\")\nset(ACE_LIBRARY_KINDS \"OBJECT\" \"STATIC\")\nset_property(CACHE ACE_LIBRARY_KIND PROPERTY STRINGS ${ACE_LIBRARY_KINDS})\nset(ACE_DEBUG OFF CACHE BOOL \"Build with ACE-specific debug/safety functionality.\")\nset(ACE_DEBUG_UAE OFF CACHE BOOL \"With ACE_DEBUG enabled, output log to UAE console.\")\nset(ACE_BOB_WRAP_Y ON CACHE BOOL \"Conrols Y-wrapping support in bob manager. Disable for extra performance in simple buffer scenarios.\")\nset(ACE_BOB_PRISTINE_BUFFER OFF CACHE BOOL \"When enabled, uses pristine buffer for bob undraw instead of allocating restore buffers.\")\nset(ACE_USE_ECS_FEATURES OFF CACHE BOOL \"Enable ECS feature sets, makes ACE OCS-incompatible.\")\nset(ACE_USE_AGA_FEATURES OFF CACHE BOOL \"Enable AGA feature sets, makes ACE use AGA Features.\")\nset(ACE_TILEBUFFER_TILE_TYPE UBYTE CACHE STRING \"Tilebuffer: Specify type used for storing tile indices.\")\nset(ACE_SCROLLBUFFER_POT_BITMAP_HEIGHT ON CACHE BOOL \"Scroll/tilebuffer: Round up the frame buffer height to power of two. More memory usage but faster calculations.\")\nset(ACE_SCROLLBUFFER_ENABLE_SCROLL_X ON CACHE BOOL \"Scroll/tilebuffer: Enables scroll in X direction.\")\nset(ACE_SCROLLBUFFER_ENABLE_SCROLL_Y ON CACHE BOOL \"Scroll/tilebuffer: Enables scroll in Y direction.\")\nset(ACE_SCROLLBUFFER_X_MARGIN_SIZE 1 CACHE STRING \"Scroll/tilebuffer: Number of tiles comprising into offscreen margins in X direction. Bigger allows drawing in bigger objects than tile size.\")\nset(ACE_SCROLLBUFFER_Y_MARGIN_SIZE 1 CACHE STRING \"Scroll/tilebuffer: Number of tiles comprising into offscreen margins in X direction. Bigger allows drawing in bigger objects than tile size.\")\nset(ACE_FILE_USE_ONLY_DISK OFF CACHE BOOL \"If enabled, only diskFile functions will be available for file access.\")\n\nmessage(STATUS \"[ACE] ACE_LIBRARY_KIND: '${ACE_LIBRARY_KIND}'\")\nmessage(STATUS \"[ACE] ACE_DEBUG: '${ACE_DEBUG}'\")\nmessage(STATUS \"[ACE] ACE_DEBUG_UAE: '${ACE_DEBUG_UAE}'\")\nmessage(STATUS \"[ACE] ACE_BOB_WRAP_Y: '${ACE_BOB_WRAP_Y}'\")\nmessage(STATUS \"[ACE] ACE_BOB_PRISTINE_BUFFER: '${ACE_BOB_PRISTINE_BUFFER}'\")\nmessage(STATUS \"[ACE] ACE_USE_ECS_FEATURES: '${ACE_USE_ECS_FEATURES}'\")\nmessage(STATUS \"[ACE] ACE_USE_AGA_FEATURES: '${ACE_USE_AGA_FEATURES}'\")\nmessage(STATUS \"[ACE] ACE_TILEBUFFER_TILE_TYPE: '${ACE_TILEBUFFER_TILE_TYPE}'\")\nmessage(STATUS \"[ACE] ACE_SCROLLBUFFER_POT_BITMAP_HEIGHT: '${ACE_SCROLLBUFFER_POT_BITMAP_HEIGHT}'\")\nmessage(STATUS \"[ACE] ACE_SCROLLBUFFER_ENABLE_SCROLL_X: '${ACE_SCROLLBUFFER_ENABLE_SCROLL_X}'\")\nmessage(STATUS \"[ACE] ACE_SCROLLBUFFER_ENABLE_SCROLL_Y: '${ACE_SCROLLBUFFER_ENABLE_SCROLL_Y}'\")\nmessage(STATUS \"[ACE] ACE_SCROLLBUFFER_X_MARGIN_SIZE: '${ACE_SCROLLBUFFER_X_MARGIN_SIZE}'\")\nmessage(STATUS \"[ACE] ACE_SCROLLBUFFER_Y_MARGIN_SIZE: '${ACE_SCROLLBUFFER_Y_MARGIN_SIZE}'\")\nmessage(STATUS \"[ACE] ACE_FILE_USE_ONLY_DISK: '${ACE_FILE_USE_ONLY_DISK}'\")\n"
  },
  {
    "path": "cmake/ace_functions.cmake",
    "content": "function(toAbsolute PATH_IN)\n\tif(NOT IS_ABSOLUTE ${${PATH_IN}})\n\t\tset(${PATH_IN} \"${CMAKE_CURRENT_SOURCE_DIR}/${${PATH_IN}}\" PARENT_SCOPE)\n\tendif()\nendfunction()\n\nfunction(getToolPath TOOL_NAME TOOL_VAR)\n\t# This should be called from other fns - `ACE_DIR` gets usually populated in parent scope\n\tset(TOOLS_BIN ${ACE_DIR}/tools/bin/)\n\n\tif(CMAKE_HOST_WIN32)\n\t\tset(TOOL_PATHS \"${TOOL_NAME}.exe\" \"Debug/${TOOL_NAME}.exe\" \"Release/${TOOL_NAME}.exe\")\n\telse()\n\t\tset(TOOL_PATHS ${TOOL_NAME})\n\tendif()\n\n\tforeach(TOOL_CANDIDATE IN LISTS TOOL_PATHS)\n\t\tset(${TOOL_VAR} ${TOOLS_BIN}${TOOL_CANDIDATE})\n\t\tif(EXISTS \"${${TOOL_VAR}}\")\n\t\t\tbreak()\n\t\tendif()\n\t\tunset(${TOOL_VAR})\n\tendforeach()\n\n\tif(NOT DEFINED ${TOOL_VAR})\n\t\tmessage(FATAL_ERROR \"Couldn't find ${TOOL_NAME} in ${TOOLS_BIN}${TOOL_PATHS} - have you built tools?\")\n\tendif()\n\n\t# Return value\n\tset(${TOOL_VAR} ${${TOOL_VAR}} PARENT_SCOPE)\nendfunction()\n\nfunction(convertPalette TARGET PALETTE_IN PALETTE_OUT)\n\tgetToolPath(palette_conv TOOL_PALETTE_CONV)\n\tset(options CONVERT_COLORS AGA_COLORS)\n\tset(oneValArgs)\n\tset(multiValArgs)\n\tcmake_parse_arguments(\n\t\tconvertPalette \"${options}\" \"${oneValArgs}\" \"${multiValArgs}\" ${ARGN}\n\t)\n\n\tif(${convertPalette_CONVERT_COLORS})\n\t\tlist(APPEND extraFlags \"-cc\")\n\tendif()\n\tif(${convertPalette_AGA_COLORS})\n\t\tlist(APPEND extraFlags \"-aga\")\n\tendif()\n\n\tadd_custom_command(\n\t\tOUTPUT ${PALETTE_OUT}\n\t\tCOMMAND ${TOOL_PALETTE_CONV} ${PALETTE_IN} ${PALETTE_OUT} ${extraFlags}\n\t\tWORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}\n\t\tDEPENDS ${PALETTE_IN}\n\t)\n\ttarget_sources(${TARGET} PUBLIC ${PALETTE_OUT})\nendfunction()\n\nfunction(convertBitmaps)\n\tgetToolPath(bitmap_conv TOOL_BITMAP_CONV)\n\tset(options INTERLEAVED EHB)\n\tset(oneValArgs TARGET PALETTE MASK_COLOR)\n\tset(multiValArgs SOURCES DESTINATIONS MASKS)\n\tcmake_parse_arguments(\n\t\tconvertBitmaps \"${options}\" \"${oneValArgs}\" \"${multiValArgs}\" ${ARGN}\n\t)\n\n\tif(${convertBitmaps_EHB})\n\t\tlist(APPEND extraFlags \"-ehb\")\n\tendif()\n\n\tif(${convertBitmaps_INTERLEAVED})\n\t\tlist(APPEND extraFlags \"-i\")\n\tendif()\n\n\tlist(LENGTH convertBitmaps_SOURCES srcCount)\n\tlist(LENGTH convertBitmaps_DESTINATIONS dstCount)\n\tlist(LENGTH convertBitmaps_MASKS maskCount)\n\tif(NOT ${srcCount} EQUAL ${dstCount})\n\t\tmessage(FATAL_ERROR \"[convertBitmaps] SOURCES count doesn't match DESTINATIONS count\")\n\tendif()\n\tif(${maskCount} AND NOT ${maskCount} EQUAL ${srcCount})\n\t\tmessage(FATAL_ERROR \"[convertBitmaps] MASKS count doesn't match SOURCES count\")\n\tendif()\n\tif(\"${convertBitmaps_MASK_COLOR} \" STREQUAL \" \")\n\t\tif(${maskCount} GREATER 0)\n\t\t\tmessage(FATAL_ERROR \"[convertBitmaps] MASK_COLOR unspecified\")\n\t\tendif()\n\tendif()\n\n\tMATH(EXPR srcCount \"${srcCount}-1\")\n\tforeach(bitmap_idx RANGE ${srcCount}) # /path/file.png\n\t\tlist(GET convertBitmaps_SOURCES ${bitmap_idx} bitmapPath)\n\t\ttoAbsolute(bitmapPath)\n\t\tlist(GET convertBitmaps_DESTINATIONS ${bitmap_idx} outPath)\n\t\tif(\"${outPath}\" STREQUAL \"NONE\")\n\t\t\tset(outPath \"\")\n\t\telse()\n\t\t\ttoAbsolute(outPath)\n\t\tendif()\n\t\tif(${maskCount} GREATER 0)\n\t\t\tlist(GET convertBitmaps_MASKS ${bitmap_idx} maskPath)\n\t\t\tif(\"${maskPath}\" STREQUAL \"NONE\")\n\t\t\t\tset(maskPath \"\")\n\t\t\telse()\n\t\t\t\ttoAbsolute(maskPath)\n\t\t\tendif()\n\t\tendif()\n\n\t\tset(extraFlagsPerFile ${extraFlags})\n\t\tif(\"${outPath} \" STREQUAL \" \")\n\t\t\tlist(APPEND extraFlagsPerFile -no)\n\t\telse()\n\t\t\tlist(APPEND extraFlagsPerFile -o ${outPath})\n\t\tendif()\n\t\tif(NOT \"${convertBitmaps_MASK_COLOR} \" STREQUAL \" \")\n\t\t\tlist(APPEND extraFlagsPerFile -mc \"\\\"${convertBitmaps_MASK_COLOR}\\\"\")\n\t\t\tif(\"${maskPath} \" STREQUAL \" \")\n\t\t\t\tlist(APPEND extraFlagsPerFile -nmo)\n\t\t\telse()\n\t\t\t\tlist(APPEND extraFlagsPerFile -mf ${maskPath})\n\t\t\tendif()\n\t\tendif()\n\n\t\tadd_custom_command(\n\t\t\tOUTPUT ${outPath} ${maskPath}\n\t\t\tCOMMAND ${TOOL_BITMAP_CONV} ${convertBitmaps_PALETTE} ${bitmapPath} ${extraFlagsPerFile}\n\t\t\tWORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}\n\t\t\tDEPENDS ${convertBitmaps_PALETTE} ${bitmapPath}\n\t\t)\n\t\ttarget_sources(${convertBitmaps_TARGET} PUBLIC ${outPath} ${maskPath})\n\tendforeach()\nendfunction()\n\nfunction(convertFont)\n\tgetToolPath(font_conv TOOL_FONT_CONV)\n\tcmake_parse_arguments(args \"\" \"TARGET;SOURCE;DESTINATION;FIRST_CHAR\" \"\" ${ARGN})\n\ttoAbsolute(args_SOURCE)\n\ttoAbsolute(args_DESTINATION)\n\tget_filename_component(ext ${args_DESTINATION} EXT)\n\tif(ext)\n\t\tstring(SUBSTRING ${ext} 1 -1 ext)\n\telse()\n\t\tSET(ext \"dir\")\n\tendif()\n\n\tif(DEFINED args_FIRST_CHAR)\n\t\tSET(argsOptional ${argsOptional} -fc ${args_FIRST_CHAR})\n\tendif()\n\n\tadd_custom_command(\n\t\tOUTPUT ${args_DESTINATION}\n\t\tCOMMAND ${TOOL_FONT_CONV} ${args_SOURCE} ${ext} -out ${args_DESTINATION} ${argsOptional}\n\t\tWORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}\n\t\tDEPENDS ${args_SOURCE}\n\t)\n\ttarget_sources(${args_TARGET} PUBLIC ${args_DESTINATION})\nendfunction()\n\nfunction(transformBitmap)\n\tgetToolPath(bitmap_transform TOOL_BITMAP_TRANSFORM)\n\tcmake_parse_arguments(args \"\" \"TARGET;SOURCE;DESTINATION\" \"TRANSFORM\" ${ARGN})\n\n\t# Make is dumb and randomly has problem with unescaped # or not\n\tset(argsEscaped \"\")\n\tforeach(arg IN LISTS args_TRANSFORM)\n\t\tlist(APPEND argsEscaped \"\\\"${arg}\\\"\")\n\tendforeach()\n\n\tadd_custom_command(\n\t\tOUTPUT ${args_DESTINATION}\n\t\tCOMMAND ${TOOL_BITMAP_TRANSFORM} ${args_SOURCE} ${args_DESTINATION} ${argsEscaped}\n\t\tWORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}\n\t\tDEPENDS ${args_SOURCE}\n\t)\n\ttarget_sources(${args_TARGET} PUBLIC ${args_DESTINATION})\nendfunction()\n\nfunction(extractBitmaps)\n\tcmake_parse_arguments(args \"\" \"TARGET;SOURCE;GENERATED_FILE_LIST\" \"DESTINATIONS\" ${ARGN})\n\tlist(LENGTH args_DESTINATIONS destArgCount)\n\tMATH(EXPR destCount \"${destArgCount} / 5 - 1\")\n\tforeach(destIdx RANGE ${destCount})\n\t\tMATH(EXPR idxOutName \"5 * ${destIdx} + 0\")\n\t\tMATH(EXPR idxX \"5 * ${destIdx} + 1\")\n\t\tMATH(EXPR idxY \"5 * ${destIdx} + 2\")\n\t\tMATH(EXPR idxWidth \"5 * ${destIdx} + 3\")\n\t\tMATH(EXPR idxHeight \"5 * ${destIdx} + 4\")\n\n\t\tlist(GET args_DESTINATIONS ${idxOutName} outName)\n\t\tlist(GET args_DESTINATIONS ${idxX} X)\n\t\tlist(GET args_DESTINATIONS ${idxY} Y)\n\t\tlist(GET args_DESTINATIONS ${idxWidth} width)\n\t\tlist(GET args_DESTINATIONS ${idxHeight} height)\n\t\ttransformBitmap(\n\t\t\tTARGET ${args_TARGET} SOURCE ${args_SOURCE} DESTINATION ${outName}\n\t\t\tTRANSFORM -extract ${X} ${Y} ${width} ${height}\n\t\t)\n\t\tset(generatedFiles \"${generatedFiles};${outName}\")\n\tendforeach()\n\n\tif(DEFINED args_GENERATED_FILE_LIST)\n\t\tSET(${args_GENERATED_FILE_LIST} ${generatedFiles} PARENT_SCOPE)\n\tendif()\nendfunction()\n\nfunction(convertTileset)\n\tgetToolPath(tileset_conv TOOL_TILESET_CONV)\n\tcmake_parse_arguments(\n\t\targs\n\t\t\"INTERLEAVED;VARIABLE_HEIGHT\"\n\t\t\"TARGET;SIZE;SOURCE;DESTINATION;HEIGHT;PALETTE;COLUMN_WIDTH\"\n\t\t\"TILE_PATHS\" ${ARGN}\n\t)\n\n\tif(DEFINED args_TILE_PATHS)\n\t\tforeach(tileNumber ${args_TILE_PATHS})\n\t\t\tset(convDepends \"${convDepends};${tileNumber}\")\n\t\tendforeach()\n\telse()\n\t\tmessage(FATAL_ERROR \"No TILE_PATHS param found\")\n\tendif()\n\n\tif(${args_INTERLEAVED})\n\t\tSET(argsOptional ${argsOptional} -i)\n\tendif()\n\n\tif(${args_VARIABLE_HEIGHT})\n\t\tSET(argsOptional ${argsOptional} -vh)\n\tendif()\n\n\tif(DEFINED args_HEIGHT)\n\t\tSET(argsOptional ${argsOptional} -h ${args_HEIGHT})\n\tendif()\n\n\tif(DEFINED args_PALETTE)\n\t\tSET(argsOptional ${argsOptional} -plt ${args_PALETTE})\n\tendif()\n\n\tif(DEFINED args_COLUMN_WIDTH)\n\t\tSET(argsOptional ${argsOptional} -cw ${args_COLUMN_WIDTH})\n\tendif()\n\n\tadd_custom_command(\n\t\tOUTPUT ${args_DESTINATION}\n\t\tCOMMAND ${TOOL_TILESET_CONV} ${args_SOURCE} ${args_SIZE} ${args_DESTINATION} ${argsOptional}\n\t\tWORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}\n\t\tDEPENDS ${convDepends}\n\t)\n\ttarget_sources(${args_TARGET} PUBLIC ${args_DESTINATION})\nendfunction()\n\nfunction(convertAudio)\n\tgetToolPath(audio_conv TOOL_AUDIO_CONV)\n\tcmake_parse_arguments(\n\t\targs\n\t\t\"STRICT;PTPLAYER;NORMALIZE;COMPRESS;\"\n\t\t\"TARGET;SOURCE;DESTINATION;PAD_BYTES;DIVIDE_AMPLITUDE;CHECK_DIVIDED_AMPLITUDE\"\n\t\t\"\" ${ARGN}\n\t)\n\n\tif(${args_STRICT})\n\t\tset(argsOptional ${argsOptional} -strict)\n\tendif()\n\tif(${args_PTPLAYER})\n\t\tset(argsOptional ${argsOptional} -fpt)\n\tendif()\n\tif(${args_NORMALIZE})\n\t\tset(argsOptional ${argsOptional} -n)\n\tendif()\n\tif(${args_COMPRESS})\n\t\tset(argsOptional ${argsOptional} -c)\n\tendif()\n\tif(${args_PAD_BYTES})\n\t\tset(argsOptional ${argsOptional} -pad ${args_PAD_BYTES})\n\tendif()\n\n\tif(${args_CHECK_DIVIDED_AMPLITUDE})\n\t\tset(argsOptional ${argsOptional} -cd ${args_CHECK_DIVIDED_AMPLITUDE})\n\telseif(${args_DIVIDE_AMPLITUDE})\n\t\tset(argsOptional ${argsOptional} -d ${args_DIVIDE_AMPLITUDE})\n\tendif()\n\n\ttoAbsolute(args_SOURCE)\n\ttoAbsolute(args_DESTINATION)\n\n\tadd_custom_command(\n\t\tOUTPUT ${args_DESTINATION}\n\t\tCOMMAND ${TOOL_AUDIO_CONV} ${args_SOURCE} -o ${args_DESTINATION} ${argsOptional}\n\t\tWORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}\n\t\tDEPENDS ${args_SOURCE}\n\t)\n\ttarget_sources(${args_TARGET} PUBLIC ${args_DESTINATION})\nendfunction()\n\nfunction(mergeMods)\n\tgetToolPath(mod_tool TOOL_MOD_TOOL)\n\tset(cmdParams \"\")\n\tcmake_parse_arguments(\n\t\targs\n\t\t\"COMPRESS\"\n\t\t\"SAMPLE_PACK;TARGET\"\n\t\t\"SOURCES;DESTINATIONS\" ${ARGN}\n\t)\n\n\tif(NOT (\"${args_SAMPLE_PACK} \" STREQUAL \" \"))\n\t\tlist(APPEND cmdParams -sp ${args_SAMPLE_PACK})\n\tendif()\n\n\tif(${args_COMPRESS})\n\t\tlist(APPEND cmdParams -c)\n\tendif()\n\n\tlist(LENGTH args_SOURCES srcCount)\n\tlist(LENGTH args_DESTINATIONS dstCount)\n\tif(NOT ${srcCount} EQUAL ${dstCount})\n\t\tmessage(FATAL_ERROR \"[mergeMods] SOURCES count ${srcCount} doesn't match DESTINATIONS count ${dstCount}\")\n\tendif()\n\n\tMATH(EXPR srcCount \"${srcCount}-1\")\n\tforeach(mod_idx RANGE ${srcCount})\n\t\tlist(GET args_SOURCES ${mod_idx} inPath)\n\t\ttoAbsolute(inPath)\n\t\tlist(APPEND sourcesAbsolute ${inPath})\n\n\t\tlist(GET args_DESTINATIONS ${mod_idx} outPath)\n\t\ttoAbsolute(outPath)\n\t\tlist(APPEND destinationsAbsolute ${outPath})\n\n\t\tlist(APPEND cmdParams -i ${inPath} -o ${outPath})\n\tendforeach()\n\n\tadd_custom_command(\n\t\tOUTPUT ${destinationsAbsolute}\n\t\tCOMMAND ${TOOL_MOD_TOOL} ${cmdParams}\n\t\tWORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}\n\t\tDEPENDS ${sourcesAbsolute}\n\t)\n\ttarget_sources(${args_TARGET} PUBLIC ${destinationsAbsolute})\nendfunction()\n\nfunction(packDirectory)\n\tgetToolPath(pak_tool TOOL_PAK_TOOL)\n\tcmake_parse_arguments(\n\t\targs\n\t\t\"COMPRESS\"\n\t\t\"SOURCE_DIR;DEST_FILE;TARGET;REORDER_FILE\"\n\t\t\"\"\n\t\t${ARGN}\n\t)\n\n\ttoAbsolute(args_SOURCE_DIR)\n\ttoAbsolute(args_DEST_FILE)\n\tFILE(GLOB_RECURSE sourceDirFiles \"${args_SOURCE_DIR}/*\")\n\n\tif(${args_COMPRESS})\n\t\tset(argsOptional ${argsOptional} -c)\n\tendif()\n\tif(NOT \"${args_REORDER_FILE} \" STREQUAL \" \")\n\t\tset(argsOptional ${argsOptional} -r ${args_REORDER_FILE})\n\tendif()\n\n\tadd_custom_command(\n\t\tOUTPUT ${args_DEST_FILE}\n\t\tCOMMAND ${TOOL_PAK_TOOL} ${args_SOURCE_DIR} ${args_DEST_FILE} ${argsOptional}\n\t\tWORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}\n\t\tDEPENDS ${sourceDirFiles}\n\t)\n\ttarget_sources(${args_TARGET} PUBLIC ${args_DEST_FILE})\nendfunction()\n"
  },
  {
    "path": "cmake/ace_install.cmake",
    "content": "install(TARGETS ${TARGET_NAME} DESTINATION ${CMAKE_INSTALL_LIBDIR})\ninstall(FILES ${HEADERS_ACE} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/ace)\ninstall(FILES ${HEADERS_ACE_GENERIC} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/ace/generic)\ninstall(FILES ${HEADERS_ACE_UTILS} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/ace/utils)\ninstall(FILES ${HEADERS_ACE_MANAGERS} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/ace/managers)\ninstall(FILES ${HEADERS_ACE_MANAGERS_VP} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/ace/managers/viewport)\ninstall(FILES ${HEADERS_FIXMATH} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/fixmath)\n"
  },
  {
    "path": "docs/README.md",
    "content": "# Documentation\n\nWelcome to the ACE docs! If you're interested in something and it's not covered\nhere, or you have a hard time understanding something, please submit an issue.\nWe want to keep those docs as elaborate and easy to understand as possible.\n\n## Installing\n\n- [Compiler setup](installing/compiler.md)\n- [Building ACE](installing/ace.md)\n- [Building tools](installing/tools.md)\n\n## Tutorial\n\n1. [ACE in a nutshell](programming/ace_in_a_nutshell.md)\n1. [Hello World example](programming/hello_world.md)\n1. [View & viewports explained](programming/view.md)\n1. [AGA support](programming/aga.md)\n1. [Blitter](programming/blit.md)\n1. [Moving blitted objects](programming/moving_blits.md)\n1. [Loading images and displaying background](programming/loading_images.md)\n1. [Handling blitted object undraw](programming/blit_undraw.md)\n1. [Blitting with masks](programming/blits_with_mask.md)\n1. [Using BOBs (Blitter OBjects)](programming/using_bobs.md)\n1. [Working with Fonts](programming/fonts.md)\n1. [Palettes](programming/palette.md)\n1. [Fixed-point math](programming/fixed_point.md)\n1. Optimizing blits\n1. [Working with Audio](programming/audio.md)\n1. Debugging memory leaks\n1. Organizing your project\n1. Copperlists\n1. Double buffering\n1. [Sprites](programming/sprites.md)\n1. [Working with and without OS](programming/os.md)\n1. DMA usage\n1. [Multi-directional large tilemaps scrolling with TileBuffer](programming/tilebuffer.md)\n1. [Advanced Sprites](programming/advancedsprites.md)\n\n## Reference manual\n\nTBD, will be doxy-generated or done as wiki pages, idk yet.\n\n## Conversion tools\n\n- [.plt v2 / palette changes (overview)](palette-plt-v2-changes.md)\n- [Palettes](tools/palette_conv.md)\n- [Bitmaps](tools/bitmap_conv.md)\n- [Fonts](tools/font_conv.md)\n- [Audio](tools/audio_conv.md)\n\n## Contributing\n\n- [Code style](contributing/codestyle.md)\n"
  },
  {
    "path": "docs/contributing/codestyle.md",
    "content": "# Code style\n\n## Tabs, braces and indents\n\n``` c\nvoid someFn(void) {\n  if(stuff) {\n\n  }\n  else {\n\n  }\n\n  // the only case when control statement body is in same line\n  while(someEvent()) continue;\n\n  do {\n    // stuff\n  } while(condition);\n\n  switch(var) {\n    case\n  }\n}\n```\n\n- We use one true brace, with `else` being in next line.\n\n- Write braces at all times. Although ommiting braces allows writing more compact and cleaner code, there is one major flaw - expanding statement to block after control expression makes line with condition being highlighted in diff, even if condition hasn't changed.\n\n- @approxit likes tab sized to 4 spaces, @tehKaiN likes 2 spaces, so we're having source tab-based and its size set to different size in one's IDE.\n\n## Code folding\n\nCode is horizontally limited to 80 chars, so naturally some code folding must be done.\nFor functions in C files:\n\n``` c\nvoid fnShort(t1 arg1, t2 fnNameAndArgsFitInOneLine);\n\nvoid fnWithManyArgs(\n  t1 arg1, t2 arg2, t3 allArgsFitInOneLineButWithoutFnName\n);\n\nvoid fnWithTooManyArgs(\n  t1 arg1, t2 arg2, t3 thereAreTooManyFnArgsToFitInOneLine,\n  t4 arg4, t5 arg5, t6 soArgListIsBrokenToMultipleLines\n);\n```\n\nOther arg formatting stuff doesn't mix with variable tab size properly. So I guess it must stay this way.\n\n## Naming conventions\n\ncamelCase with prefixes. List of prefixes:\n\n- `ub` - unsigned byte (`UBYTE`, `uint8_t`)\n- `uw` - unsigned word (`UWORD`, `uint16_t`)\n- `ul` - unsigned long (`ULONG`, `uint32_t`)\n- `ull` - unsigned long long (`uint64_t`)\n-`b`, `w`, `l`, `ll` for signed variants\n- `p` - any pointer or array\n- `cb` - any function pointer (callback)\n- `t` - typedef\n- `e` - enum instance\n- `s` - struct instance\n- `u` - union instance\n- `f` - `float` or fixed-point var\n- `d` - double\n\nfor global var scoping additionally:\n\n- `g_` - global visible from other files\n- `s_` - global visible from current file (`static`)\n\n## Misc stuff\n\n- all named structs and unions should be typedefed using following convention:\n\n```c\ntypedef struct _tTypeName {\n\n} tTypeName;\n```\n\n- all fns in header files **must** be documented using DoxyComments. Functions which are not exported in headers _should_ be documented in .c file\n\n- functions should be as short as possible. If needed, split function to multiple ones. There is no hard limit for fn length, but if it doesn't fit entirely on your screen then it's a good sign you're doing something wrong.\n\n## Include guards\n\nConsider following example:\n\n``` c\n#ifndef _ACE_MANAGERS_BLIT_H_\n#define _ACE_MANAGERS_BLIT_H_\n\n// stuff\n\n#endif // _ACE_MANAGERS_BLIT_H_\n```\n\nA guard is preceded by project name (ACE) and following parts strictly reflect filesystem location (inc/**managers/blit.h**).\n\n## Includes\n\n- if you're in .c/.cpp file, the first include is one complementing the source file (e.g. foo.h if you're in foo.c)\n- then goes the standard library,\n- then goes ACE - try to put managers first, then utils;\n- then includes of your project files.\n- No newlines between include directives.\n\nExample for main.c:\n\n```c\n#include \"main.h\"\n#include <stdlib.h>\n#include <ace/managers/memory.h>\n#include <ace/managers/log.h>\n#include <ace/managers/timer.h>\n#include <ace/utils/palette.h>\n#include \"menu/menu.h\"\n#include \"input.h\"\n```\n\n## Doxygen\n\n- Use javadoc (`@section` instead of `\\section`) style.\n- Always put `@file` doxy comment right after include guard.\n- Always document each globally-visible function in .h file.\n- Document `static` functions in .c files.\n"
  },
  {
    "path": "docs/installing/ace.md",
    "content": "# Building ACE\n\nCurrently, only CMake is supported.\n\n## Building using CMake\n\nCurrently, CMake build supports only GCC (be it Bebbo's or Bartman's version).\nYou need to use the appropriate\nCMake Toolchain File.\nStart with cloning the [AmigaCMakeCrossToolchains](https://github.com/AmigaPorts/AmigaCMakeCrossToolchains) repo to anywhere on your computer.\n\n```shell\ngit clone https://github.com/AmigaPorts/AmigaCMakeCrossToolchains\n```\n\nNotably, this toolchain file allows you to set `M68K_CPU` and `M68K_FPU` variables to your liking, allowing you to optimize code for FPU and/or specific CPU version.\nBy default, for most compatibility, 68000 and soft-FPU is used.\n\n### Using ACE as submodule dependency in your project\n\nThis is the recommended way of building ACE.\nSince ACE's development often breaks things, it's best to attach ACE as a submodule in your game's repository.\nThis way, your commit history will store the last-known good ACE commit which worked well with your project.\n\nTo attach ACE repository as a submodule, do the following in your repo's root directory:\n\n```sh\nmkdir deps\ngit submodule add https://github.com/AmigaPorts/ACE deps/ace\n```\n\nAnd, if you already have CMake project set up, link it to your main executable by adding in CMakeLists.txt:\n\n```cmake\nadd_subdirectory(deps/ace)\ntarget_link_libraries(myGame ace)\n```\n\n### Building standalone ACE library\n\n``` sh\nmkdir build && cd build\ncmake .. -DCMAKE_TOOLCHAIN_FILE=/path/to/AmigaCMakeCrossToolchains/m68k.cmake -DM68K_TOOLCHAIN_PATH=/path/to/toolchain -DM68K_CPU=68000 -DM68K_FPU=soft\nmake\n```\n\nSome notes:\n\n- You can pass other `-DM68K_CPU` values. Supported are `68000`, `68010`, `68020`, `68040` and `68060`. See AmigaCMakeCrossToolchains docs or sources for more info.\n- If you're on cygwin, you might need to add `-G \"Unix Makefiles\"`.\n- If you want to enable debug build (e.g. to have logs and better sanity checks), pass `-DCMAKE_BUILD_TYPE=Debug`.\n- To enable AGA-specific ACE features, pass `-DACE_USE_AGA_FEATURES=ON`.\n- If you really want to depend on standalone-built ACE library, be sure to take note of the commit you've built it from.\n  ACE breaks things very often and it's almost certain that after some time you won't be able to build your game with latest ACE version.\n- By default, ACE is built as a bunch of .o files which are then linked to your executable using powers of CMake.\n  This allows for better link-time optimization.\n  If that's not what you need, add `-DACE_BUILD_KIND=STATIC` to produce `libace.a` for classic link scenarios.\n\nAfter building, you should have a bunch of `.o` files or `libace.a` in your build folder.\nBe sure to link it to your game.\n"
  },
  {
    "path": "docs/installing/compiler.md",
    "content": "# Compiler setup\n\nCurrently, only Bartman's and Bebbo's GCC are supported.\n\n## Bartman's toolchain\n\nBartman has created excellent extension for Visual Studio Code, which comes with latest GCC version and integrated debugging and profiling features.\nTo download it, in VSCode go to Extensions page and install `bartmanabyss.amiga-debug` extension.\n\nNote: Bartman's extension contains prebuilt compiler and slightly modified WinUAE, hence it's **Windows-only**.\n\nNote: currently, only the very old version extension is available directly through VSCode Extensions.\nTo obtain the newest package:\n\n- navigate to [GitHub Releases](https://github.com/BartmanAbyss/vscode-amiga-debug/releases) page,\n- download latest .vsix file\n- in VSCode, enter Extensions tab (<kbd>Ctrl</kbd> + <kbd>Shift</kbd> + <kbd>X</kbd>), select \"...\" icon and select \"Install from VSIX...\" option.\n\n### Using Bartman's compiler with CMake\n\nThis is recommended approach by [Last Minute Creations](https://github.com/Last-Minute-Creations) team members.\nThe latest versions of Bartman's plugin support Windows, Linux, and macOS for development.\nThis setup works on each of these platforms.\n\n- On Windows, you need recent version of either the MinGW GCC compiler toolchain (e.g. [winlibs-x86_64-posix-seh-gcc-12.2.0-llvm-15.0.7-mingw-w64ucrt-10.0.0-r4](https://github.com/brechtsanders/winlibs_mingw/releases/download/12.2.0-15.0.7-10.0.0-ucrt-r4/winlibs-x86_64-posix-seh-gcc-12.2.0-llvm-15.0.7-mingw-w64ucrt-10.0.0-r4.7z)) or MSVC.\n- If using MinGW, make sure the directory containing the `mingw32-make` executable is in the system PATH (you can check it using `where mingw32-make` command in terminal window).\n- **IMPORTANT:** When using MinGW, ensure that there are no spaces, pound signs (`#`) and other special characters in your paths\n- Also, download and install [CMake](https://cmake.org) if you don't have it already.\n- Be sure `cmake`'s executable directory is in your PATH or you'll have to configure vscode extension with it manually (again check using terminal command).\n\nOn Linux or macOS, make sure you have CMake and Make installed and on the PATH.\n\nNow for the VSCode setup:\n\n- In VSCode, install the `ms-vscode.cmake-tools`, `ms-vscode.cpptools` and `BartmanAbyss.amiga-debug` extensions.\n- Also in VSCode, open any directory which will contain your project.\n- Clone the [AmigaCMakeCrossToolchains](https://github.com/AmigaPorts/AmigaCMakeCrossToolchains) repo either as a submodule inside of it or anywhere outside project if you plan to use it globally.\n\nYou now need to set up the compiler for VSCode's CMake extension.\nTo do so on a per-project basis:\n\n- Create a folder `.vscode` in your project\n- Create a file `.vscode/cmake-kits.json` with content as follows.\n  - The only reason there are two entries in configuration file is because PATH on Windows needs `;` as separator, and on Unix it's `:`. If you intend to build your project on a single platform, you can skip the unneeded entry.\n  - Adapt the path to `AmigaCMakeCrossToolchains` to match where you cloned that repository.\n  - Note that this configuration assumes that you have MinGW toolchain installed. You may want to replace `preferredGenerator` with `ninja` if you run into problems with it, use non-GCC compiler for native programs or you want faster building times. In this case, download Ninja from [its releases page](https://github.com/ninja-build/ninja/releases), point your system PATH to its directory and restart vscode before proceeding.\n\n  ```json\n  [\n    {\n      \"name\": \"GCC Bartman m68k Win32\",\n      \"toolchainFile\": \"${workspaceFolder}/../AmigaCMakeCrossToolchains/m68k-bartman.cmake\",\n      \"environmentVariables\": {\n        \"PATH\": \"${command:amiga.bin-path}/opt/bin;${command:amiga.bin-path};${command:amiga.bin-path}/opt/m68k-amiga-elf/bin;${env:PATH}\"\n      },\n      \"preferredGenerator\": {\n        \"name\": \"MinGW Makefiles\"\n      },\n      \"cmakeSettings\": {\n        \"M68K_CPU\": \"68000\",\n        \"TOOLCHAIN_PREFIX\": \"m68k-amiga-elf\",\n        \"TOOLCHAIN_PATH\": \"${command:amiga.bin-path}/opt\"\n      },\n      \"keep\": true\n    },\n    {\n      \"name\": \"GCC Bartman m68k Unix\",\n      \"toolchainFile\": \"${workspaceFolder}/deps/AmigaCMakeCrossToolchains/m68k-bartman.cmake\",\n      \"environmentVariables\": {\n        \"PATH\": \"${command:amiga.bin-path}/opt/bin:${command:amiga.bin-path}:${command:amiga.bin-path}/opt/m68k-amiga-elf/bin:${env:PATH}\"\n      },\n      \"preferredGenerator\": {\n        \"name\": \"Unix Makefiles\"\n      },\n      \"cmakeSettings\": {\n        \"M68K_CPU\": \"68000\",\n        \"TOOLCHAIN_PREFIX\": \"m68k-amiga-elf\",\n        \"TOOLCHAIN_PATH\": \"${command:amiga.bin-path}/opt\"\n      },\n      \"keep\": true\n    }\n  ]\n  ```\n\nNext, create empty CMakeLists.txt file in the base directory of your project **and restart the editor** so that it can discover that you're inside CMake-based project.\n(You can do this via command palette (<kbd>Ctrl</kbd> + <kbd>Shift</kbd> + <kbd>P</kbd>) and typing \"Reload Window\".)\n\nAfter this you should be good to go.\nYou can check in the `.vscode/cmake-kits.json` file, as long as you keep `AmigaCMakeCrossToolchains` in the same relative path to the project.\nYou will be able to compile your project on Windows, macOS, and Linux without any further config.\n\n- From the command palette, select \"CMake Configure\" to configure your project.\n- The <kbd>F7</kbd> key builds your project,\n- The <kbd>F5</kbd> key runs currently selected debugging task.\n\nNote: The Bartman's compiler produces ELF executables instead of Hunk file format.\nTo mitigate this, you need to invoke `elf2hunk` bundled with Bartman's toolchain.\nYou may want to look at how its made in CMakeLists of some other projects (e.g. [GermZ](https://github.com/tehKaiN/germz)) to see how ACE is included and the debugger is invoked there.\nAlso, you may want to further investigate `CMakeLists.txt` there and `.vscode/launch.json` to see how debugger is set up, as well as `.vscode/c_cpp_properties.json` to get auto-completion working.\n\nYou may also want to set up the CMake compiler kit once on your local machine instead of per-project basis.\nTo do so, follow the steps below:\n\n- From command palette, launch \"CMake: Scan for Kits\" command to generate the kit configurations for your user.\n- Access your user's CMake kit config by using the \"CMake: Edit User-Local CMake Kits\" command.\n- Insert the toolchain definitions listed above to tweak the json configuration file and make Bartman's toolchain available for all your projects.\n\n### Integrating ACE into Bartman's sample project\n\nTBD\n\nThe Bartman plugin comes with a command to bootstrap the makefile-based sample project.\nA dirty way is to copy src/inc files from ACE to the base project.\n\n### Setting up the debugger\n\n- By default, your project will be built in newly created `build` folder.\n  After first successful build, take note of the executable's name.\n- Inside `.vscode` folder, create `launch.json` file and paste in following contents, replacing following with your information:\n  - `myGame` with your executable name, without the extension\n  - `/path/to/kick13.rom` and `/path/to/kick31.rom` with valid paths to kickstart ROM files.\n\n```json\n{\n  \"version\": \"0.2.0\",\n  \"configurations\": [\n    {\n      \"type\": \"amiga\",\n      \"request\": \"launch\",\n      \"name\": \"Amiga 500\",\n      \"config\": \"A500\",\n      \"program\": \"${workspaceFolder}/build/myGame\",\n      \"kickstart\": \"/path/to/kick13.rom\",\n      \"internalConsoleOptions\": \"openOnSessionStart\"\n    },\n    {\n      \"type\": \"amiga\",\n      \"request\": \"launch\",\n      \"name\": \"Amiga 1200\",\n      \"config\": \"A1200\",\n      \"program\": \"${workspaceFolder}/build/myGame\",\n      \"kickstart\": \"/path/to/kick31.rom\",\n      \"internalConsoleOptions\": \"openOnSessionStart\"\n    }\n  ]\n}\n```\n\nYou can also add `chipmem` and `fastmem` parameters to tweak the emulator's configuration.\n\n## Bebbo's toolchain\n\nYou can get Bebbo's compiler from his [amiga-gcc](https://github.com/bebbo/amiga-gcc) repository.\nYou can download precompiled libraries (May require MSYS2 installed) or build it from source.\nIts build system tends to be occasionally broken, so if you can't build it by following his instructions, don't be shy and drop him an issue. ;)\nAlso, if you're on Windows, you'll need Cygwin, MSYS2 or Windows Subsystem for Linux.\n\n### Building with WSL\n\nThis is currently the preferred way to build, but requires Windows 10.\nAfter installing WSL in your OS and Ubuntu on it, follow instructions from Bebbo's repo.\n\n### Building with Cygwin\n\nYou may want to create a shortcut which launches `cmd` with cygwin & compiler paths in PATH:\n\n```plain\nC:\\WINDOWS\\system32\\cmd.exe /c \"SET PATH=path/to/bebbo/bin;path/to/cygwin/bin;%PATH%&& set PREFIX=/cygdrive/path/to/bebbo&& START cmd.exe\"\n```\n\nWhere `path/to/bebbo` is a path to destination where Bebbo's compiler is installed. On Cygwin, path `X:/dir1/dir2/file` gets changed to `/cygdrive/x/dir1/dir2/file` so be sure to setup `PREFIX` in proper way.\nBefore building ACE or Bebbo's compiler, enter `sh` or `bash` or you will experience strange errors.\n\nBe sure there are no spaces before `&&` or one of `rm -rf` may get an empty arg and destroy your HDD contents. :)\n\n## Prebuilt VBCC for Windows - **no longer supported**\n\n**ACE doesn't work with VBCC Anymore.**\nVBCC doesn't support latest C standards, popular language extensions, and its optimizers produce broken code.\nThis section is only kept for archive reasons, or in case VBCC gets better in the future.\n\nIf you're allergic to building anything and are using Windows, Kusma maintains\nprebuilt VBCC on his [amiga-dev](https://github.com/kusma/amiga-dev) repo.\n\nAs noted there, you'll need to set up system variables:\n\n- `VBCC`: your `vbcc\\targets\\m68k-amigaos` directory,\n- `PATH`: add your `vbcc\\bin` dir.\n\n## Which compiler to choose\n\nBartman's GCC uses newer version (at the time of writing, GCC 10.1 vs GCC 6.5), has the debugger, latest C/C++ standards support, but doesn't have properly implemented standard library.\nTo mitigate this problem, ACE implements its basic parts in mini-std, but it's not and will never be a complete implementation.\nBebbo implements his own optimizers in GCC code which may produce better code than Bartman's suite, but may also break your code until they get properly tested in the field.\nI'm using following ruleset:\n\n- use Bartman's GCC as main compiler for development, or Bebbo's if you need standard library.\n- when doing release builds and your code doesn't require latest compiler features, do a Bebbo build and compare size and performance.\n- if anything breaks mysteriously with Bebbo's compiler, disable optimizations in ACE/game CMakeLists (change `-O3` to `-O0` or build with `-DCMAKE_BUILD_TYPE=Debug`) and try adding `-fbbb=-` in compile options to disable Bebbo's optimizers.\n- if problem still persists, it's probably your bug.\n- if it's not, try to isolate where bug occurs and report it on ACE repo **with code sample**\n\n## Integrating Bebbo's compiler with Visual Studio Code\n\nIf you don't know VSCode, give it a try - You won't go back to any other IDE.\nTo properly set it up for work with ACE, here are some tips on how to set it up in optimal way:\n\n- If you've installed Bebbo compiler via WSL, install `ms-vscode-remote.remote-wsl` extension.\n  It will allow you to open projects from WSL point of view.\n- Install `twxs.cmake` and `ms-vscode.cmake-tools` extensions for CMake support. Note that you may need to reinstall some of the extensions mentioned above when connecting to WSL as they are stored on target system.\n- Clone the [AmigaCMakeCrossToolchains](https://github.com/AmigaPorts/AmigaCMakeCrossToolchains) repo\n- From Command Palette (<kbd>ctrl</kbd>+<kbd>shift</kbd>+<kbd>p</kbd>), select `CMake Edit User-Local CMake Kits`.\n\nThe CMake kit config is as follows:\n\n```json5\n[\n  {\n    \"name\": \"Some other compiler which was automatically detected\",\n    // Some other fields...\n  },\n  {\n    \"name\": \"GCC for m68k-amigaos 6.5.0b\",\n    \"compilers\": {\n      \"C\": \"/opt/amiga/bin/m68k-amigaos-gcc\",\n      \"CXX\": \"/opt/amiga/bin/m68k-amigaos-g++\"\n    },\n    \"toolchainFile\": \"/path/to/AmigaCMakeCrossToolchains/m68k-amigaos.cmake\",\n    \"cmakeSettings\": {\n      \"M68K_CPU\": \"68000\",\n      \"M68K_FPU\": \"soft\",\n      \"M68K_CRT\": \"nix13\",\n      \"TOOLCHAIN_PREFIX\": \"m68k-amigaos\",\n      \"TOOLCHAIN_PATH\": \"/opt/amiga\"\n    }\n  }\n]\n```\n"
  },
  {
    "path": "docs/installing/tools.md",
    "content": "# Building ACE tools\n\nACE comes bundled with its own tools for converting file formats.\nSince those apps run on your development machine and not the Amiga itself, to build them, you'll need a compiler for your operating system.\n\n- On Windows, you need recent version of either the MinGW GCC compiler toolchain (e.g. [winlibs-x86_64-posix-seh-gcc-12.2.0-llvm-15.0.7-mingw-w64ucrt-10.0.0-r4](https://github.com/brechtsanders/winlibs_mingw/releases/download/12.2.0-15.0.7-10.0.0-ucrt-r4/winlibs-x86_64-posix-seh-gcc-12.2.0-llvm-15.0.7-mingw-w64ucrt-10.0.0-r4.7z)) or MSVC.\n- On Linux, using GCC is strongly recommended.\n- Using Clang on any system is not tested.\n\nTo build your tools, open the terminal, navigate to ACE's `tools` directory, and issue following commands:\n\n```shell\nmkdir build && cd build\n\n# When using MacOS (to avoid Clang) - assuming you have: brew install gcc@13\nexport CC=/usr/local/bin/gcc-13\nexport CXX=/usr/local/bin/g++-13\n\n# When using GCC on Linux, MacOS or MSVC on Windows:\ncmake ..\n# When using MinGW GCC on Windows:\ncmake .. -G \"MinGW Makefiles\"\n\ncmake --build .\n```\n\nWhen done successfully, you should now have `tools/bin` directory with ACE tool executables.\nIf you're stuck by issuing wrong commands, navigate out of build folder, delete it and try again.\n"
  },
  {
    "path": "docs/palette-plt-v2-changes.md",
    "content": "# `.plt` v2, AGA alignment, and `palette_conv` defaults\n\nThis document summarises the palette / `.plt` work: what changed, and why.\n\n## Why change the format?\n\n**Legacy `.plt`** used a **single byte** for the color count, then chose **ECS (2 bytes per color)** vs **AGA-style (4 bytes: `0`, R, G, B)** using **`count > 32`**. That breaks a real case: a **32-color AGA** palette is **not** `> 32`, so the loader treated it as **ECS** and read the wrong record size.\n\n**v2** fixes that by **not** inferring encoding from the count:\n\n- First byte: **`0`** = packed 12-bit ECS/OCS entries, or **`1`** = 4-byte AGA entries.\n- Next two bytes: **big-endian `UWORD`** `num_colors`.\n- Then the color payload for that mode.\n\n**Legacy (v1)** files (first byte **≥ 2**) are **not** loaded or written by current ACE or `palette_conv`; reconvert assets to **v2**.\n\n## Why the leading `0` in AGA file entries?\n\nThe 4-byte AGA record is the same as before: **alpha (0) + R, G, B**. It matches **bulk `ULONG` loads** in `paletteLoadFromFd` and the in-memory **AGA viewport** layout. Dropping to 3 bytes on disk would need a new format version and pack/unpack; the small size win is not worth the API churn for typical 2 MiB chip-RAM targets.\n\n## Runtime (Amiga)\n\n- **`paletteLoadFromPath` / `paletteLoadFromFd`**: **v2** only (ECS or AGA sentinel); legacy v1 returns without loading (`ACE_DEBUG` logs an error). AGA v2 loads into a buffer you use as **`ULONG` per entry** for AGA viewports.\n- **`paletteSaveOcs`**: writes **v2 ECS** (`0` + count + `UWORD` colors).\n- **`paletteSaveAGA`**: writes **v2 AGA** (with `ACE_USE_AGA_FEATURES`).\n- **`paletteDimAGA`**: off-by-one in the loop fixed.\n- **`paletteColorMixAGA`**, **`paletteDumpAGA`**: implemented (were only declared before).\n\n## Tools\n\n- **`tPalette::toPlt` / `fromPlt`**: **v2** read/write only.\n- **`palette_conv` default output** (no flags): **v2 ECS/OCS** so it matches the **OCS/ECS-first** use of ACE and validates 12-bit colors. Use **`--aga`** for **v2 AGA** `.plt`.\n\n## Docs\n\n- See [tools/palette_conv.md](tools/palette_conv.md) and [programming/palette.md](programming/palette.md) for end-user details.\n\n## Integration note (CMake / build)\n\n`convertPalette` in `cmake/ace_functions.cmake` runs `palette_conv` with **no extra flags**, so it now produces **v2 ECS** `.plt` by default. For **AGA-only** palettes, invoke `palette_conv` with **`--aga`** (extend your CMake helper if needed).\n"
  },
  {
    "path": "docs/programming/ace_in_a_nutshell.md",
    "content": "# ACE in a nutshell\n\n## Utils and managers\n\nACE is divided into managers and utils.\n\n### Utils\n\nUtils are for working with small and/or multiple resources of same kind\n(bitmaps, files, fonts, viewports). Also, there are utils which simplify doing\nspecific tasks (chunky processing, taglists) or simplify hardware access\n(Amiga chip registers).\n\nWhen you create a resource using a util, you receive a pointer to it\n(e.g. `pBm = bitmapCreate(...)`). After finishing work with it, you are required\nto free it using dedicated function (e.g. `bitmapDestroy(pBm)`). You can use\ndifferent functions from util to work with such resource, always passing that\nresource as a parameter (e.g. `bitmapGetByteWidth(pBm)`).\n\n### Managers\n\nEvery manager is responsible for management of single global resource\n(blitter, audio, etc.). You create one with \"create\" or \"open\" function\n(e.g. `blitManagerCreate()`) and close with a \"destroy\" or \"close\" counterpart\n(`blitManagerDestroy()`). Between those calls you may use any of manager's\nfunctions (e.g. `blitRect()`, `blitCopy()`, `blitLine()`). Those are used\nusually once per program.\n\n### Viewport managers\n\nThose are a special case and addition to manager/util system. After constructing\na viewport, you need a bitmap buffer to display things on it, scroll it\nand manage it in many other ways. Viewport managers are doing just that.\n\n- A camera manager keeps track of currently displayed rectangle of a bigger\n  playfield\n- A buffer manager creates required bitmap for display and uses camera manager\n  to issue required hardware/software operations to display relevant portion.\n\nBuffer managers are not merely allocate bitmap for you - they do all sorts of\nheavy lifting - scroll buffer displays background buffer making it fold\non Y axis, while tile buffer manages drawing of tiles which are about to display\non such buffer.\n\n## States\n\nEvery game can be broken into some kind of states. For example:\n\n- \"menu\" state may be responsible for displaying menu and navigating through it.\n  When player is ready, \"menu\" should launch proper game and clean up so far\n  used resources.\n- \"game\" state should draw game's screen, process player's events, animate\n  objects on screen, etc. After player wins or loses the game, it should free\n  its resources and move state to menu.\n\nThis shows two basic concepts: lifecycle of state and transitions\nbetween them.\n\n### Lifecycle of state\n\nEach state's life could be split into three phases:\n\n- **creation** during which needed bitmaps gets allocated, screen is set up, and\n  all initializations take place, e.g. initial state of players, game AI, etc.\n- **loop** which is responsible for processing player's key presses, moving\n  objects on screen, processing game logic: loss of health, win conditions,\n  physics, etc.\n- **destruction** which cleans up resources after state - in practice it\n  does the exact opposite of state's creation code.\n\nStates are managed with stack, so besides swapping current state with another\nstate, states can be pushed and popped on stack. See \"Pushing and popping\nstates\" chapter for more in-depth overview. For fine tunning push/pop\ntransitions between states, ACE provides two additional phases:\n\n- **suspend** when some child state is about to be pushed\n- **resume** when some child state just popped\n\nBoth are usefull when you need run some smaller tweaks without touching creation\nor destruction of a state.\n\n### Changing states\n\nSuppose you want to implement the logic above. It can be illustrated as below:\n\n```\nOS  --stateChange-->  menu  --stateChange-->  game\n ^                    |  ^                    |\n |----stateChange-----|  |----stateChange-----|\n```\n\nFunction `stateChange` does the following:\n\n- calls current state's destruction function,\n- sets new state as current one,\n- calls new state's create function.\n\nCurrent state's loop code is called every time game reaches `stateProcess`\nfunction.\n\n### Pushing and popping states\n\nWhat if you'd like to implement in-game menu which pauses game? You can use\nstate pushing and popping:\n\n``` plain\nOS  --stateChange-->  menu  --stateChange-->  game  --statePush--> pause\n ^                    |  ^                    |  ^                 |\n |----stateChange-----|  |----stateChange-----|  |----statePop-----|\n```\n\nThis looks similar to changing state, but there's significant difference:\n\n- when you call `statePush`, _game_ state isn't destroyed. Instead, _game_'s\n  suspend function and then _pause_'s create function are called. From now on\n  `stateProcess` will process _pause_'s loop.\n- when you call `statePop`, _pause_'s state is destroyed, and _game_'s resume\n  function is called, making _game_'s loop the current one. After that\n  `stateProcess` will process _game_ loop.\n\n### Complex state example\n\nSuppose your menu state gets bigger and bigger. Suppose you want to allocate\ncommon things for whole menu (font, background, display) and then process each\npart of menu separately. You can implement this as below:\n\n``` plain\n                     |--POP-----------  menuMapSelect\n                     |                     | ^\n                     |               CHANGE| |CHANGE\n                     v                     v |\nOS  --CREATE-->  menuCommon  --PUSH-->  menuMain\n                   | ^                     | ^\n             CHANGE| |CHANGE         CHANGE| |CHANGE\n                   v |                     v |\n                  game                  menuOptions\n```\n\n- _menuCommon_ allocates common parts and at the end of its create function\n  it pushes _menuMain_.\n- In _menuMain_'s create function you draw main menu's background and make\n  its loop function responsible for processing input and navigation\n  to other parts.\n- When user wants to navigate to options, you change state to _menuOptions_,\n  which in its create function draws its background and options list.\n  Loop is reponsible for setting them and navigating back to menuMain.\n- _menuMapSelect_ is implemented in same way as _menuOptions_, with additional\n  ability of popping into menuCommon when map is selected.\n- lastly, _menuCommon_ should in its loop examine why its loop got called and\n  decide what to do next. It can be done by e.g. examining some global variable.\n  If it was because menuMapSelect requested launching game, you change state\n  to _game_, otherwise you call `gameExit` which will effectively close the\n  game.\n\n## Main file\n\nMost of games have same boilerplate which consists of freezing OS, creating\ncopper & blitter manager etc. To make initial setup less rudimentary, @approxit\nhas created [ace/generic/main.h](../../include/ace/generic/main.h) file.\nInstead of writing `main()` function you just `#include` this file and define:\n\n- `genericCreate()` - for creation of additional managers\n- `genericProcess()` - called in a loop until game gets closed\n- `genericDestroy()` - for freeing previously created managers\n\nIf you prefer exiting your game in other ways than by calling `gameExit`, you\ncan tune game main loop condition by defining `GENERIC_MAIN_LOOP_CONDITION`\nbefore `#include`. For example:\n\n``` c\n#define GENERIC_MAIN_LOOP_CONDITION g_pGameStateManager->pCurrent\n#include <ace/generic/main.h>\n```\n\nThis changes generic main loop's behavior to check if there is any state in\nselected state manager. The only caveat is to put these lines of code after\nmanager definition.\n\n## Debug mode\n\nWhen building ACE in debug mode, you're enabling 3 main things:\n\n- General logging (`game.log`)\n- Memory usage logging (`memory.log`)\n- Sanity checks\n\n### General logging\n\nWhen writing apps, it's very convenient to produce logs with debug messages.\nSince Amiga is low-spec machine and writing to disk/floppy is resource-intensive,\ndecision has been made to only enabling debugging in debug mode. To use it\nyou can use `logWrite()` fn, which accepts printf-like arguments.\nNote that it will not append new line character for you, so be sure to add `\\n`\ncode where appropriate. Simple logging is shown below:\n\n``` c\nlogWrite(\"Hello, my favourite number is %d\\n\", 8);\n// outputs in game.log: \"Hello, my favourite number is 8\"\n```\n\nMost of ACE functions are logging their actions, hence such kind of log\ngets quickly large and illegible. To make it more readable, an indent system\nwas added, called log blocks. It consists of `logBlockBegin()` and `logBlockEnd()`\nfunctions. `logBlockBegin()` also accepts printf-like parameters, while\n`logBlockEnd()` accepts single string.\n\n``` c\nvoid baz(UBYTE x) {\n\tlogBlockBegin(\"bar(x: %hhu)\", x);\n\t// Note that there is no logging inside here except block begin/end\n\t// It will fold into one line in log\n\tlogBlockEnd(\"bar()\");\n}\n\nvoid bar(UBYTE x) {\n\tlogBlockBegin(\"bar(x: %hhu)\", x);\n\t// This will be written with indent\n\tlogWrite(\"this is bar\\n\");\n\tlogBlockEnd(\"bar()\");\n}\n\nvoid foo(UBYTE x) {\n\tlogBlockBegin(\"foo(x: %hhu)\", x);\n\t// And this will not be folded since it will contain other blocks\n\tbar(x+1);\n\tbaz(x-1);\n\tlogBlockEnd(\"foo()\");\n}\n\n// somewhere in the code:\nfoo(7);\n```\n\nAbove code will produce following log:\n```\nBlock begin: foo(x: 7)\nThis is foo\n\tBlock begin: bar(x: 8)\n\t\tThis is bar\n\tBlock end: bar(), time:   0.1 us\n\tBlock begin: baz(6)...OK, time:   0.1 us\nBlock end: foo(), time:   0.1 us\n```\n\nAs you can see, this can also measure performance in limited manner.\nBear in mind that execution time will be most valid for deepest\nblocks, since those containing any other ones will have added time\nwhich was spent on writing internal logBlock messages.\n\nTo speed things up, in release builds `logWrite()` and logBlock\ncalls are changed to no-ops.\n\n### Memory usage log\n\nEach memory allocation and release will be logged into `memory.log`\nfile, as seen in example below:\n\n``` plain\nAllocated FAST memory 0@0x2193ec, size 16 (/path/to/game/ACE/src/ace/managers/copper.c:136)\nAllocated CHIP memory 1@0x1c614, size 336 (/path/to/game/ACE/src/ace/utils/bitmap.c:59)\nfreed memory 1@0x1c614, size 336 (/path/to/game/ACE/src/ace/utils/bitmap.c:258)\nfreed memory 0@0x2193ec, size 16 (/path/to/game/ACE/src/ace/managers/copper.c:207)\n```\n\nThose lines are telling you following things:\n\n- is it allocation (CHIP or FAST mem) or release\n- allocation's unique number, address (`idx@addr`) and size in bytes\n- where allocation/release has been made (`file:line`)\n\nAlso, there are some error messages which appear when:\n\n- memory has been freed more than once\n- free fn has been called with different size than alloc\n- memory has been trashed as in writing to the left or right of allocated space\n  (too big array loop?)\n- memory leaks - some allocations has not been freed until the end of program\n- and some more things added during ACE's development\n\nIt is a good practice to look at this log from time to time in search of lines\nstarting with `ERR:`. Also, at the end of the log you will find summary of allocated\nmemory such as following one:\n\n``` plain\n=============== MEMORY MANAGER DESTROY ==============\nIf something is deallocated past here, you're a wuss!\nPeak usage: CHIP: 858404, FAST: 96053\n```\n\nIf you forgot to free some allocations, you will see them listed beneath this summary.\nSince all those errors shouldn't take place in finished code, decision has been made\nto omit all those checks in Release builds. This makes code lighter and\nless cpu and memory hungry.\n\n### Sanity checks\n\nSome operations are very painful to debug, hence there are sanity checks scattered\nhere and there in the code. An example of such check is one done in blit functions:\nthey check whether source and destination coords, as well as blit size are fitting\ninside source and destination bitmaps and even if bitmap pointers are non-null.\n\nSince sanity checks are computational-expensive, decision has been made to make\nthem only appear by default in Debug builds, since most of the time they shouldn't\nbe needed. In debug build `blitCopy()` function calls `blitSafeCopy()` with\nsanity checks, while in Release build it uses `blitUnsafeCopy()` to squeeze\nas much performance as possible. This way, if your code depends on runtime checks,\nyou can use safe variants where appropriate.\n"
  },
  {
    "path": "docs/programming/advancedsprites.md",
    "content": "# Using Advanced Aprites\n\n## About Advanced Sprites\n\nAdvanced Sprites Manager is an overlay to the sprite manager.\n\nIt allows you to directly use:\n\n- simple 4 colors & 16px wide sprites (same as the Sprites Manager).\n- 4 colors & 32px wide sprites.\n- 16 colors & 16px wide sprites.\n- 16 colors & 32px wide sprites.\n\nBe aware that it can take 2 or 4 channels on the 8 available on Amiga :\n\n| Colors | Width | Start Channel | Number of Channels Taken |\n|--------|-------|---------------|--------------------------|\n| 4      | 16px  | Any           | 1                        |\n| 4      | 32px  | Any           | 2                        |\n| 16     | 16px  | Even (0,2,4,6)| 2                        |\n| 16     | 32px  | Even (0,2,4,6)| 4                        |\n\n\n## Main feature\n\n- [X] Frames/animation\n- [X] 32px sprites\n- [X] 16 colors sprites\n- [ ] Multiplexed sprites (not yet available)\n\n## Initializing Advanced Sprites\n\n\nInit your static variables :\n\n```c\nstatic tAdvancedSprite *s_pASprite;\n```\n\nThen init your manager in your *creation* part:\n```c\nspriteManagerCreate(s_pView, 0);\nsystemSetDmaBit(DMAB_SPRITE, 1);\n```\n\n## Adding sprites\n\nStill in your *creation* part, first load/create your sprite stripe. It must be **vertical** stripe. It can be generated easily with tools like *Aseprite*. Not space between sprites, the same sprite height must be respected for the whole stripe.\n\n```c\n// Init your static variables\nstatic tBitMap *s_pStripe32;\n// [..]\n\n// Init your bitmap in the creation part\ns_pStripe32 = bitmapCreate(32, 32*10, 2, BMF_CLEAR|BMF_INTERLEAVED); // 16x32 2BPP\n  for(int i=0; i<10; i++) {\n    char msg[50];\n    sprintf(msg, \"%d\",i);\n\t  fontDrawStr(s_pFont,  s_pStripe32, 0, i*32+0, msg, 1, FONT_LEFT | FONT_TOP | FONT_COOKIE, s_pTextBitMap);\n    for(int j=0; j<4; j++) {\n      blitRect(s_pStripe32,16*(j%2), i*32+8+8*((j-1>0)&1), randUwMinMax(g_sRand,8,16), randUwMinMax(g_sRand,4,8), j);\n    }\n  }\n```\n\nThen you inject your bitmap while creating your advanced sprites :\n\n```c\n// 2 is the channel number, 32 is the height\ns_pASprite = advancedSpriteAdd(2, 32, s_pStripe32, NULL);\n// Set Init position (x,y)\nadvancedSpriteSetPos(s_pASprite,180,100);\n```\n\nPlease note, that you can destroy the stripe bitmap just after you've added the sprite with the bitmap.\n\n```c\nbitmapDestroy(s_pStripe32);\n```\n\nNULL can be replaced by a second stripe (bitmap are limited to 4096 height).\n\n```c\ns_pHeroSprite = advancedSpriteAdd(MAIN_SPRITE_CHANNEL, MAIN_SPRITE_HEIGHT, pLeftSprites, pRightSprites); \nbitmapDestroy(pRightSprites);\nbitmapDestroy(pLeftSprites);\n```\n\n\n***Bonus :*** If your sprite is showing behind the view layer add this line after the `viewLoad` :\n```c\n// Reset blcon2 to put sprite in front of http://amigadev.elowar.com/read/ADCD_2.1/Hardware_Manual_guide/node0159.html\n  g_pCustom->bplcon2=0b00100000;\n```\n\n## Loop Management\n\nAt the end of of your **loop* part should add this 2 lines in order to :\n\n\n```c\n  advancedSpriteProcess(s_pASprite); // set sprites data\n  advancedSpriteProcessChannel(2,s_pASprite);  // apply it memory and copper\n```\n\nBefore that you can change the sprite position :\n\n```c\nadvancedSpriteSetPos(s_pASprite,180,100); // ==> Set position\nadvancedSpriteSetPosX(s_pASprite,s_pASprite->wX-2); // ==> Move x by -2\nadvancedSpriteSetPosY(s_pASprite,s_pASprite->wY+2); // ==>  Move Y by +2\n```\n\nDo not use `s_pASprite->wX = ...` to change the value, use the available function. \n\n\nYou can also change the current frame in order to manage animation or change of states :\n\n```c\n// 5 is the frame number starting at 0\nadvancedSpriteSetFrame(s_pASprite,5);\n```\n\nBy default frame is 0 on `advancedSpriteAdd`. It's the top sprite of your stripe. Second one is 1, third is 2...\nIf you use Aseprite, it's the frame number minus 1 (1 -> 0, 2 --> 1, 3 -> 2, and so on).\n\nLast function available is to enable/disable the sprite :\n\n```c\nadvancedSpriteSetEnabled(s_pASprite,1); // enable\nadvancedSpriteSetEnabled(s_pASprite,0); // disable\n```\n\nBy default it's enabled on `advancedSpriteAdd`. \n\n\n## Destroy Management\n\nDon't forget to :\n\n1 - Destroy advanced sprites\n```c\nadvancedSpriteRemove(s_pASprite);\n```\n\n2 - destroy manager\n```c\nsystemSetDmaBit(DMAB_SPRITE, 0); // Disable sprite DMA\nspriteManagerDestroy();\n```"
  },
  {
    "path": "docs/programming/aga.md",
    "content": "# AGA support\n\nACE is still OCS/ECS-first, but it includes AGA-specific functionality behind a build flag.\n\n## Enable AGA features\n\nBuild with:\n\n```sh\n-DACE_USE_AGA_FEATURES=ON\n```\n\nThis enables `ACE_USE_AGA_FEATURES` in code.\n\n## AGA support status\n\nSupported:\n\n- Creating AGA-enabled views and viewports via tags in `ace/utils/extview.h`\n- AGA viewport fetch mode selection via `TAG_VPORT_FMODE`\n- AGA palette handling in view loading and viewport palette allocation\n- AGA palette utilities (load/save/dim/mix/dump) when built with `ACE_USE_AGA_FEATURES`\n- AGA sprite palette bank control helpers\n\nNot done yet:\n\n- Wide sprites support is still in progress\n- Sub-pixel scrolling support is still in progress\n\nTo follow status and testing progress, see [issue #151](https://github.com/AmigaPorts/ACE/issues/151).\n\n## Creating an AGA screen\n\nUse AGA tags on your view and viewport:\n\n```c\ns_pView = viewCreate(0,\n  TAG_VIEW_USES_AGA, 1,\nTAG_END);\n\ns_pVpMain = vPortCreate(0,\n  TAG_VPORT_VIEW, s_pView,\n  TAG_VPORT_USES_AGA, 1,\n  TAG_VPORT_BPP, 8,\n  TAG_VPORT_FMODE, 0,\nTAG_END);\n```\n\nSome notes:\n\n- `TAG_VPORT_BPP` still controls depth (`8` means 256 colors)\n- For AGA viewports, palette storage is expected in AGA layout (`ULONG` entries)\n- `TAG_VPORT_FMODE` controls fetch mode for the viewport\n\nFor broader view/viewport basics, see [View & viewports explained](view.md).\n"
  },
  {
    "path": "docs/programming/audio.md",
    "content": "# Working with Audio in ACE\n\nACE provides audio capabilities through integrated PTPlayer by Frank Wille rewritten to C for better integration with ACE features.\nThe basic capabilities are:\n\n- MOD music playback (31-sample format)\n- Handling prioritized sound effects playback\n- Offers channel management (reserving channels for music vs. effects)\n- 64-step volume control\n- Custom callback for song end, e.g. for playlists or adaptative music\n\nYou can also combine it with 3rd party audio mixers for squeezing out more out of the audio playback.\n\n> [!NOTE]\n> Using `ptplayerSetChannelsForPlayer()` will limit ptplayer channel management to only few channels, leaving others intact for e.g. audio mixer to use.\n\n## Amiga-Specific Considerations\n\n- PTPlayer must store music samples as well as sound effects in Amiga's CHIP memory.\n- PTPlayer sound effects should have an empty first word to prevent audio glitches after playback - `audio_conv` can ensure that for you\n- Amiga has 8-bit audio channels, totaling to 4 channels, two bound to left channel, two bound to the right one.\n- It's quite common to games to ignore the stereo separation and treat them all as mono, leaving to the user to ensure such playback.\n\n## Initialization and Configuration\n\nIn your main or gamestate create function, do the following:\n\n```c\n// Initialize (1 = PAL mode, 0 = NTSC)\nptplayerCreate(1);\n\n// Optional: Configure which channels are reserved for music\nptplayerSetMusicChannelMask(0b0011);  // Reserves channels 0 and 1 for music\n\n// Optional: Set master volume\nptplayerSetMasterVolume(48);  // Range is 0-64\n\n// Optional: Configure song repeat behavior\nptplayerConfigureSongRepeat(1, onSongEnd);\n```\n\nTo play the music in your game, in your main or gamestate create function:\n\n```c\n// Load a MOD file\ntPtplayerMod *pMod = ptplayerModCreateFromPath(\"music.mod\");\n\n// Start playback (2nd parameter is NULL to use samples from inside the MOD file, set start position to 0)\nptplayerLoadMod(pMod, NULL, 0);\n\n// Enable music playback\nptplayerEnableMusic(1);\n```\n\nWhile in the game loop, you might want to:\n\n- change the music by calling `ptplayerLoadMod()` with different `pMod`,\n- change the volume with `ptplayerSetMasterVolume()`\n- enable/disable music temporarily with `ptplayerEnableMusic()`\n\nAt the end of the gamestage or the game itself, do the following:\n\n```c\nptplayerStop();\nptplayerModDestroy(pMod);\n\n// When done with all audio\nptplayerDestroy();\n```\n\nPlayback performance will vary depending on:\n\n- Number of channels used in the song\n- Amount/kinds of ProTracker commands stored in the song.\n\n## Playing Sound Effects\n\nTo load a sound effect, be sure to have a .sfx file generated by [`audio_conv`](../tools/audio_conv.md) tool.\n\nManage the sound effect by calling:\n\n```c\ntPtplayerSfx *pSfx = ptplayerSfxCreateFromPath(\"explosion.sfx\", 0);\n\n// When done with the sound effect, after your game loop ends:\nptplayerSfxDestroy(pSfx);\n```\n\nTo play the sound effect:\n\n```c\nptplayerSfxPlay(pSfx, PTPLAYER_SFX_CHANNEL_ANY, PTPLAYER_VOLUME_MAX, 10);\n```\n\n> [!NOTE]\n> The SFX volume takes into account the volume set by `ptplayerSetMasterVolume()`.\n> Setting the sfx volume to half of the range (`32`) with master volume set to `48` will scale it accordingly to `24`.\n\nYou can also set the specific channel, as well as set the sound effect priority.\nWhen using `PTPLAYER_SFX_CHANNEL_ANY`, PTPlayer will use any free channel, if possible.\n\nHigher priority sound effects will replace lower priority ones if needed.\n\n> [!NOTE]\n> By default, PTPlayer prioritizes sound effects over music - if you play the sound effect on a channel which is used by the .mod file, some music notes won't play.\n> Because of that, it is strongly recommended to use PTPlayer to only play music on some channels and use a software audio mixer to play back the samples in remaining channel(s)\n\nYou can also stop the sound effects playing on given channel by calling `ptplayerSfxStopOnChannel()`.\n\n## Advanced Features\n\n- PTPlayer supports ProTracker's `E8` command for synchronizing game events with music.\n  Use `ptplayerGetE8()` to retrieve the last E8 value.\n- You can use `mod_tool` to separate MOD files from their sample data using sample packs to save memory when using multiple songs with shared samples.\n  Use `ptplayerSampleDataCreateFromPath()` to load the sample pack and pass it in 2nd parameter of `ptplayerLoadMod()`.\n- You can adjust individual music sample volumes with `ptplayerSetSampleVolume()` even when music is playing.\n"
  },
  {
    "path": "docs/programming/blit.md",
    "content": "# Blitter\n\nWe still don't have anything except black screen - in this step we're going\nto use some colors. This tutorial will at first aim to recreate classic Pong\ngame, so we need to be able to draw some rectangles and lines.\n\nTo use blit functions, you need to include `<ace/managers/blit.h>`.\n\n## Blitting rectangles\n\nFor this task you can use `blitRect()` function, syntax is as follows:\n\n``` c\nUBYTE blitRect(\n  tBitMap *pDst, WORD wDstX, WORD wDstY,\n  WORD wWidth, WORD wHeight, UBYTE ubColor\n);\n```\n\nWhere `wDstX` and `wDstY` are coords on viewport manager's bitmap where\nyou want to start drawing. We'll use it to draw paddles and ball.\n\n## Blitting lines\n\nLine drawing is done by `blitLine()` function, which syntax is as follows:\n\n``` c\nvoid blitLine(\n  tBitMap *pDst, WORD x1, WORD y1, WORD x2, WORD y2,\n  UBYTE ubColor, UWORD uwPattern, UBYTE isOneDot\n);\n```\n\nBear in mind that `blitLine()` uses blitter's line mode, which makes\nline drawing very DMA-consuming, so if you have to draw horizontal / vertical\nlines you can most likely do them faster using `blitRect()` function by\nspecifying width or height equal to one.\n\nApart from slowdown, blitter's line drawing mode allows you to draw them using\nany 16-bit pattern: for each 1 blitter puts a pixel, whereas for each 0 it does\nnothing. Some examples are shown below:\n\n``` plain\nsolid line (0xFFFF):\n1111 1111 1111 1111 1111 1111 1111 1111\n\ndotted line (0xAAAA):\n1010 1010 1010 1010 1010 1010 1010 1010\n\ndashed line (0xE4E4):\n1110 0100 1110 0100\n```\n\nLast parameter is related to blitter fill mode - it expects filled region's\nborders to be only 1px wide. If you set `isOneDot` parameter to 1, blitter will\nensure to plot only one pixel in a row.\n\n### Faster demo-ish line drawing\n\nSome demos speed up line drawing by doing them only on a single bitplane. This\nfunction directly doesn't support it but you can trick it into such usage.\nAll you need to do is to create `tBitMap` struct with same width and height\nas target bitmap, depth set to 1 and first bitplane pointer to the desired\nbitplane. This way you will create two \"entangled\" bitmaps, one of which can be\nused for general operations, second one for line drawing.\n\n## Tutorial code\n\nWe're all set, so let's use those fns to finally draw something on screen.\nBelow you can see added `#include` for blit manager, some defines to make later\nporion of code more readable, and then blits.\n\nIn next page of tutorial we'll add basic game logic, adding animations in the\nprocess.\n\n``` c\n#include \"game.h\"\n#include <ace/managers/key.h>\n#include <ace/managers/game.h>\n#include <ace/managers/system.h>\n#include <ace/managers/viewport/simplebuffer.h>\n//-------------------------------------------------------------- NEW STUFF START\n#include <ace/managers/blit.h> // Blitting fns\n\n// Let's make code more readable by giving names to numbers\n// It is a good practice to name constant stuff using uppercase\n#define BALL_WIDTH 8\n#define BALL_COLOR 1\n#define PADDLE_WIDTH 8\n#define PADDLE_HEIGHT 32\n#define PADDLE_LEFT_COLOR 2\n#define PADDLE_RIGHT_COLOR 3\n#define SCORE_COLOR 1\n#define WALL_HEIGHT 1\n#define WALL_COLOR 1\n//---------------------------------------------------------------- NEW STUFF END\n\nstatic tView *s_pView; // View containing all the viewports\nstatic tVPort *s_pVpScore; // Viewport for score\nstatic tSimpleBufferManager *s_pScoreBuffer;\nstatic tVPort *s_pVpMain; // Viewport for playfield\nstatic tSimpleBufferManager *s_pMainBuffer;\n\nvoid gameGsCreate(void) {\n  s_pView = viewCreate(0, TAG_END);\n\n  // Viewport for score bar - on top of screen\n  s_pVpScore = vPortCreate(0,\n    TAG_VPORT_VIEW, s_pView,\n    TAG_VPORT_BPP, 4,\n    TAG_VPORT_HEIGHT, 32,\n  TAG_END);\n  s_pScoreBuffer = simpleBufferCreate(0,\n    TAG_SIMPLEBUFFER_VPORT, s_pVpScore,\n    TAG_SIMPLEBUFFER_BITMAP_FLAGS, BMF_CLEAR,\n  TAG_END);\n\n  // Now let's do the same for main playfield\n  s_pVpMain = vPortCreate(0,\n    TAG_VPORT_VIEW, s_pView,\n    TAG_VPORT_BPP, 4,\n  TAG_END);\n  s_pMainBuffer = simpleBufferCreate(0,\n    TAG_SIMPLEBUFFER_VPORT, s_pVpMain,\n    TAG_SIMPLEBUFFER_BITMAP_FLAGS, BMF_CLEAR,\n  TAG_END);\n\n  s_pVpScore->pPalette[0] = 0x0000; // First color is also border color\n  s_pVpScore->pPalette[1] = 0x0888; // Gray\n  s_pVpScore->pPalette[2] = 0x0800; // Red - not max, a bit dark\n  s_pVpScore->pPalette[3] = 0x0008; // Blue - same brightness as red\n\n//-------------------------------------------------------------- NEW STUFF START\n  // Draw line separating score VPort and main VPort, leave one line blank after it\n  blitLine(\n    s_pScoreBuffer->pBack,\n    0, s_pVpScore->uwHeight - 2,\n    s_pVpScore->uwWidth - 1, s_pVpScore->uwHeight - 2,\n    SCORE_COLOR, 0xFFFF, 0 // Try patterns 0xAAAA, 0xEEEE, etc.\n  );\n\n  // Draw wall on the bottom of main VPort\n  blitRect(\n    s_pMainBuffer->pBack,\n    0, s_pVpMain->uwHeight - WALL_HEIGHT,\n    s_pVpMain->uwWidth, WALL_HEIGHT, WALL_COLOR\n  );\n//---------------------------------------------------------------- NEW STUFF END\n\n  systemUnuse();\n\n  // Load the view\n  viewLoad(s_pView);\n}\n\nvoid gameGsLoop(void) {\n  // This will loop every frame\n  if(keyCheck(KEY_ESCAPE)) {\n    gameExit();\n  }\n  else {\n//-------------------------------------------------------------- NEW STUFF START\n    // Draw first paddle\n    blitRect(\n      s_pMainBuffer->pBack, 0, 0,\n      PADDLE_WIDTH, PADDLE_HEIGHT, PADDLE_LEFT_COLOR\n    );\n\n    // Draw second paddle\n    blitRect(\n      s_pMainBuffer->pBack, s_pVpMain->uwWidth - PADDLE_WIDTH, 0,\n      PADDLE_WIDTH, PADDLE_HEIGHT, PADDLE_RIGHT_COLOR\n    );\n\n    // Draw ball\n    blitRect(\n      s_pMainBuffer->pBack,\n      // x center: half of screen width minus half of ball\n      (s_pVpMain->uwWidth - BALL_WIDTH) / 2,\n      // y center: half of screen height minus half of ball\n      (s_pVpMain->uwHeight - BALL_WIDTH) / 2,\n      BALL_WIDTH, BALL_WIDTH, BALL_COLOR\n    );\n    vPortWaitForEnd(s_pVpMain); // Wait for end of frame\n//---------------------------------------------------------------- NEW STUFF END\n  }\n}\n\nvoid gameGsDestroy(void) {\n  systemUse();\n\n  // This will also destroy all associated viewports and viewport managers\n  viewDestroy(s_pView);\n}\n```\n"
  },
  {
    "path": "docs/programming/blit_undraw.md",
    "content": "# Handling blitted object undraw\n\nSo far, you've managed to load and display the background, but paddles are trashing it with black color.\nNow it's time to handle proper background restoring.\n\nIn order to fix this, you need to create bitmaps which you'll use as buffers to store background beneath the paddles.\nTo do so, add following code:\n\n```c\n// ...old defines go here...\n//-------------------------------------------------------------- NEW STUFF START\n#define PADDLE_BG_BUFFER_WIDTH CEIL_TO_FACTOR(PADDLE_WIDTH, 16)\n#define BALL_BG_BUFFER_WIDTH CEIL_TO_FACTOR(BALL_WIDTH, 16)\n//---------------------------------------------------------------- NEW STUFF END\n\n// ...old static variables go here...\n//-------------------------------------------------------------- NEW STUFF START\nstatic tBitMap *s_pBmPaddleLeftBg;\nstatic tBitMap *s_pBmPaddleRightBg;\nstatic tBitMap *s_pBmPaddleBallBg;\nstatic UBYTE s_hasBackgroundToRestore;\n//---------------------------------------------------------------- NEW STUFF END\n\nvoid gameGsCreate(void) {\n  //... old code here\n  // Draw line separating score VPort and main VPort, leave one line blank after it\n  blitLine(\n    s_pScoreBuffer->pBack,\n    0, s_pVpScore->uwHeight - 2,\n    s_pVpScore->uwWidth - 1, s_pVpScore->uwHeight - 2,\n    SCORE_COLOR, 0xFFFF, 0 // Try patterns 0xAAAA, 0xEEEE, etc.\n  );\n\n//-------------------------------------------------------------- NEW STUFF START\n  s_pBmPaddleLeftBg = bitmapCreate(PADDLE_BG_BUFFER_WIDTH, PADDLE_HEIGHT, 4, 0);\n  s_pBmPaddleRightBg = bitmapCreate(PADDLE_BG_BUFFER_WIDTH, PADDLE_HEIGHT, 4, 0);\n  s_pBmPaddleBallBg = bitmapCreate(BALL_BG_BUFFER_WIDTH, BALL_WIDTH, 4, 0);\n  s_hasBackgroundToRestore = 0;\n//---------------------------------------------------------------- NEW STUFF END\n\n  systemUnuse();\n\n  // Load the view\n  viewLoad(s_pView);\n}\n\nvoid gameGsDestroy(void) {\n  systemUse();\n\n//-------------------------------------------------------------- NEW STUFF START\n  bitmapDestroy(s_pBmPaddleLeftBg);\n  bitmapDestroy(s_pBmPaddleRightBg);\n  bitmapDestroy(s_pBmPaddleBallBg);\n//---------------------------------------------------------------- NEW STUFF END\n\n  // This will also destroy all associated viewports and viewport managers\n  viewDestroy(s_pView);\n}\n```\n\nThis will create background buffers for both paddles and the ball the moment the game state gets created, and they will be destroyed along with it.\nNote that bitmap widths are dependent on `PADDLE_BG_BUFFER_WIDTH` and its ball equivalent - remember that bitmaps need to have width equal to multiple of 16 - `CEIL_TO_FACTOR()` allows to easily ensure this.\n\nNow it all boils down to saving fragments of display bitmap on paddles' positions before drawing them, and drawing them back on the start of the frame.\nYou need to also do the check, which will be used for the first loop pass, if background was actually saved before restoring it - without it random garbage contents from paddle background buffers would appear.\n\n```c\nvoid gameGsLoop(void) {\n  // This will loop every frame\n  if(keyCheck(KEY_ESCAPE)) {\n    gameExit();\n    return; // early return - don't process anything else, no need for big `else` anymore\n  }\n\n  UWORD uwPaddleRightPosX = s_pVpMain->uwWidth - PADDLE_WIDTH;\n\n  if(s_hasBackgroundToRestore) {\n    // Restore background under left paddle\n    blitCopy(\n      s_pBmPaddleLeftBg, 0, 0,\n      s_pMainBuffer->pBack, 0, uwPaddleLeftPosY,\n      PADDLE_WIDTH, PADDLE_HEIGHT, MINTERM_COOKIE\n    );\n\n    // Restore background under right paddle\n    blitCopy(\n      s_pBmPaddleRightBg, 0, 0,\n      s_pMainBuffer->pBack, uwPaddleRightPosX, uwPaddleRightPosY,\n      PADDLE_WIDTH, PADDLE_HEIGHT, MINTERM_COOKIE\n    );\n  }\n\n  // Update left paddle position\n  if(keyCheck(KEY_S)) {\n    uwPaddleLeftPosY = MIN(uwPaddleLeftPosY + PADDLE_SPEED, PADDLE_MAX_POS_Y);\n  }\n  else if(keyCheck(KEY_W)) {\n    uwPaddleLeftPosY = MAX(uwPaddleLeftPosY - PADDLE_SPEED, 0);\n  }\n\n  // Update right paddle position\n  if(keyCheck(KEY_DOWN)) {\n    uwPaddleRightPosY = MIN(uwPaddleRightPosY + PADDLE_SPEED, PADDLE_MAX_POS_Y);\n  }\n  else if(keyCheck(KEY_UP)) {\n    uwPaddleRightPosY = MAX(uwPaddleRightPosY - PADDLE_SPEED, 0);\n  }\n\n  // Save background under left paddle\n  blitCopy(\n    s_pMainBuffer->pBack, 0, uwPaddleLeftPosY,\n    s_pBmPaddleLeftBg, 0, 0,\n    PADDLE_WIDTH, PADDLE_HEIGHT, MINTERM_COOKIE\n  );\n\n  // Save background under right paddle\n  blitCopy(\n    s_pMainBuffer->pBack, uwPaddleRightPosX, uwPaddleRightPosY,\n    s_pBmPaddleRightBg, 0, 0,\n    PADDLE_WIDTH, PADDLE_HEIGHT, MINTERM_COOKIE\n  );\n  s_hasBackgroundToRestore = 1;\n\n  // Draw left paddle\n  blitRect(\n    s_pMainBuffer->pBack, 0, uwPaddleLeftPosY,\n    PADDLE_WIDTH, PADDLE_HEIGHT, PADDLE_LEFT_COLOR\n  );\n\n  // Draw right paddle\n  blitRect(\n    s_pMainBuffer->pBack, uwPaddleRightPosX, uwPaddleRightPosY,\n    PADDLE_WIDTH, PADDLE_HEIGHT, PADDLE_RIGHT_COLOR\n  );\n\n  // Draw ball\n  blitRect(\n    s_pMainBuffer->pBack,\n    // x center: half of screen width minus half of ball\n    (s_pVpMain->uwWidth - BALL_WIDTH) / 2,\n    // y center: half of screen height minus half of ball\n    (s_pVpMain->uwHeight - BALL_WIDTH) / 2,\n    BALL_WIDTH, BALL_WIDTH, BALL_COLOR\n  );\n  vPortWaitForEnd(s_pVpMain);\n}\n```\n\nAs you can now observe, background is restored correctly.\nThere's a problem however - in debug builds, the right paddle flickers on its topmost position.\nThis is due to using single-buffered mode - the game simply works too slow to draw everything before it gets displayed on-screen.\nSwitching to release builds in your CMake options should help for now, but there are also some optimizations to be done which could help speed up blitter operations.\n\nThe next step is using proper paddle and ball graphics as well as animating the ball itself.\n"
  },
  {
    "path": "docs/programming/blits_with_mask.md",
    "content": "# Blitting with mask\n\nSo far, you've blitted solid rectangles and maskless backgrounds, as well as used maskless blits to copy stuff to background restore buffers.\nNow it's time to do masked blits.\n\n## How masked hardware works\n\nTODO: move this to separate article on how blitter works and elaborate it A LOT.\n\nIn a nutshell, blitter operates by mixing up to three source channels (bitmaps A, B and C) into one output channel (D).\n\n- To copy data with width equal to a multiple of 16, only single input channel is required and blit can be logically described as `D=A`, `D=B` or `D=C`.\n- In order to get rid of some vertical lines from edges of your blit, you need to mask them out - typically channel A acts as mask, and with B being a source bitmap this can be described as `D=A*B`.\n- However, this will make masked-out edges filled with zeros, so to counter it one needs to also feed blitter with background data in channel C, and use cookie-cut operation: `D=A*B + !A*C`.\n\nThe main takeaway is that for masked blits you need to specify three bitmaps for blitter and use all four channels:\n\n- source for blitted object's mask (channel A),\n- source for blitted object (channel B),\n- source and destination for background data (channels C and D).\n\nSince blitter operates on bitplane-by-bitplane manner, you can't just ask it to treat specific color index as mask - it expects you to pass in additional bitplane with mask information.\nThe upside of this is you don't need to reserve one of the colors for alpha channel  since you pass this data separately.\nThe downside is that you need to store mask separately, which results in a bit more data in memory.\n\n## Converting images with mask data for ACE\n\nThe example uses following bitmap for paddles and ball - copy it to your `res` folder.\n\n![Paddles and ball](../../showcase/res/pong_paddles.png)\n\nTo generate ACE's .bm as well as its mask counterpart, add another `convertBitmaps()` call in your `CMakeLists.txt` file.\nNote that `MASK_COLOR` specifies which color should be used as a source for mask data - it can be, and even should be, the color outside of your project's regular palette.\n\n```cmake\nconvertBitmaps(\n  TARGET ${GAME_LINKED} PALETTE ${RES_DIR}/pong.gpl\n  MASK_COLOR \"#FF00FF\"\n  SOURCES\n    ${RES_DIR}/pong_paddles.png\n  DESTINATIONS\n    ${DATA_DIR}/pong_paddles.bm\n  MASKS\n    ${DATA_DIR}/pong_paddles_mask.bm\n)\n```\n\nObserve that after building your game, two files appeared:\n\n- pong_paddles.bm is a 4BPP bitmap with all `MASK_COLOR` pixels converted to color zero,\n- pong_paddles_mask.bm is a 1BPP bitmap with zeros set where `MASK_COLOR` was and with other pixels encoded as ones.\n\n## Using masked images with ACE\n\nWhat you need to do is:\n\n- Load the bitmap from file like any other one.\n- Load the extra mask bitmap - it's good practice to keep its variable name similar to the bitmap which will use the mask.\n- Use `blitCopyMask()` function to draw masked bitmap.\n  - You need to pass the mask as a `UWORD` pointer directly to where the data resides - typically it's start of bitmap's first bitplane (`pBmMask->Planes[0]`).\n  - During blit, the function will auto-use the same X and Y offset for object's source as well as mask bitmaps.\n- Be sure to clean up the bitmaps after they are no longer needed - in this case in `gameGsDestroy()`.\n\nThe example code looks as follows:\n\n```c\n// ...old defines here...\n#define BALL_BG_BUFFER_WIDTH CEIL_TO_FACTOR(BALL_WIDTH, 16)\n//-------------------------------------------------------------- NEW STUFF START\n#define PADDLE_LEFT_BITMAP_OFFSET_Y 0\n#define PADDLE_RIGHT_BITMAP_OFFSET_Y PADDLE_HEIGHT\n#define BALL_BITMAP_OFFSET_Y (PADDLE_RIGHT_BITMAP_OFFSET_Y + PADDLE_HEIGHT)\n//---------------------------------------------------------------- NEW STUFF END\n\n// ...old static vars here...\nstatic UBYTE s_hasBackgroundToRestore = 0;\n//-------------------------------------------------------------- NEW STUFF START\nstatic tBitMap *s_pBmObjects;\nstatic tBitMap *s_pBmObjectsMask;\n//---------------------------------------------------------------- NEW STUFF END\n\nvoid gameGsCreate(void) {\n  // ...old code...\n  s_pBmPaddleLeftBg = bitmapCreate(PADDLE_BG_BUFFER_WIDTH, PADDLE_HEIGHT, 4, 0);\n  s_pBmPaddleRightBg = bitmapCreate(PADDLE_BG_BUFFER_WIDTH, PADDLE_HEIGHT, 4, 0);\n  s_pBmPaddleBallBg = bitmapCreate(BALL_BG_BUFFER_WIDTH, BALL_WIDTH, 4, 0);\n//-------------------------------------------------------------- NEW STUFF START\n  s_pBmObjects = bitmapCreateFromPath(\"data/pong_paddles.bm\", 0);\n  s_pBmObjectsMask = bitmapCreateFromPath(\"data/pong_paddles_mask.bm\", 0);\n//---------------------------------------------------------------- NEW STUFF END\n  // ...old code...\n}\n\nvoid gameGsLoop(void) {\n  // ...old code here...\n//-------------------------------------------------------------- NEW STUFF START\n  // Draw left paddle\n  blitCopyMask(\n    s_pBmObjects, 0, PADDLE_LEFT_BITMAP_OFFSET_Y,\n    s_pMainBuffer->pBack, 0, uwPaddleLeftPosY,\n    PADDLE_WIDTH, PADDLE_HEIGHT, s_pBmObjectsMask->Planes[0]\n  );\n\n  // Draw right paddle\n  blitCopyMask(\n    s_pBmObjects, 0, PADDLE_RIGHT_BITMAP_OFFSET_Y,\n    s_pMainBuffer->pBack, uwPaddleRightPosX, uwPaddleRightPosY,\n    PADDLE_WIDTH, PADDLE_HEIGHT, s_pBmObjectsMask->Planes[0]\n  );\n\n  // Draw ball\n  blitCopyMask(\n    s_pBmObjects, 0, BALL_BITMAP_OFFSET_Y,\n    s_pMainBuffer->pBack,\n    // x center: half of screen width minus half of ball\n    (s_pVpMain->uwWidth - BALL_WIDTH) / 2,\n    // y center: half of screen height minus half of ball\n    (s_pVpMain->uwHeight - BALL_WIDTH) / 2,\n    BALL_WIDTH, BALL_WIDTH, s_pBmObjectsMask->Planes[0]\n  );\n//---------------------------------------------------------------- NEW STUFF END\n  vPortWaitForEnd(s_pVpMain);\n}\n\nvoid gameGsDestroy(void) {\n  // ...old code here...\n  bitmapDestroy(s_pBmPaddleBallBg);\n//-------------------------------------------------------------- NEW STUFF START\n  bitmapDestroy(s_pBmObjects);\n  bitmapDestroy(s_pBmObjectsMask);\n//---------------------------------------------------------------- NEW STUFF END\n\n  // This will also destroy all associated viewports and viewport managers\n  viewDestroy(s_pView);\n}\n```\n\nNow your paddles and ball have dedicated graphics!\nAll that remains to have a working game is to add some motion to the ball and display the score.\n"
  },
  {
    "path": "docs/programming/fixed_point.md",
    "content": "# Fixed-point math\n\nThe stock Amiga 500 doesn't have hardware support for floating-point numbers and it's too slow to reasonably use their software version.\nUsing them starts to be viable with accelerator cards and FPUs, however even on such configurations they aren't the fastest way to deal with fractions.\nThe solution is to use a fixed-point math instead.\n\nACE comes bundled with libfixmath, so usage should be quite straightforward.\nTo use it, you need to include the `<fixmath/fix16.h>` header.\n\n## Limitations of fixed-point math\n\nContrary to regular n-bit integer that stores its value with bits that represent 2^0 up to 2^(n-1), fixed point numbers use negative powers of two (or 1 repeatedly divided by 2) to represent their value. As such, the typical binary integer `1011` is equal in decimal to `1*1 + 2*1 + 4*0 + 8*1 = 11`, whereas in fixed point that uses 2 bits for fractions, it would be `0.25*1 + 0.5*1 + 1*0 + 2*1 = 2.75`. The conversion between fixed point and regular integers is very fast, as it's a matter of shifting it by the number of fraction bits.\n\nThis way of storing numbers has some noticable downsides:\n\n1. In contrast to floating point that adapts its range by changing its precision, the fixed point encoding has constant precision and range.\n2. Some operations, such as repeated multiplications, may very quickly render their results inaccurate.\n\nLibfixmath uses signed 16.16 format on a 32-bit type called `fix16_t` to represent its numbers - that means 1 bit for sign, 15 bits for integral part and 16 bits for fractional part, thus precision is limited to `1/65535` and the number range spans from `-32767` to `32767`.\nSince it's using 32-bit values, those operations are slower than they would be on a 16-bit counterpart, but offer range and precision acceptable for more use cases.\n\n## Using libfixmath's functions\n\nWhen using fixed point functions, stick to following rules:\n\n1. Convert your values between fixed point and ints using `fix16_from_int()` and `fix16_to_int()` functions.\n1. To convert `const` global values to fixed point in compile-time, use `F16()` macro instead.\n1. Adding integers and `fix16_t` variables won't work correctly - be sure to convert either of them to another one's type.\n1. It's safest to use fixmath's functions to do arithmetics - `fix16_add()`, `fix16_sub()`, `fix16_mul()`, `fix16_div()`, etc.\n1. In some rare scenarios, you can skip those functions to make the code a bit more readable, e.g. when multiplying `fix16_t` and an `int`.\n  When in doubt, refer to `fix16_*()` functions sources and see if it makes sense to skip the conversion.\n\n> [!WARNING]\n> You should only use `F16()` macro to convert your numbers only in places where `fix16_from_int()` won't work - using it in other contexts will make code noticably slower!\n\n> [!NOTE]\n> For performance reasons, `fix16_to_int()` doesn't round the numbers and truncates the fractional part instead.\n> If you need rounding, add it on the side of your code, e.g. by doing `fix16_to_int(fValue + fHalf)`.\n\nA sample code that calculates points on a circle is shown below:\n\n```c\n#include <fixmath/fix16.h>\n\n// ...\n\n// Prepare circle vertex positions.\n// For better accuracy, supply your own precalculated points or more accurate sin/cos table\nconst fix16_t fHalf = fix16_one / 2;\nfix16_t fAngle;\nfor(UBYTE ubPosIndex = 0; ubPosIndex < STAR_POSITION_COUNT; ++ubPosIndex) {\n  fAngle = (fix16_pi*ubPosIndex*2) / STAR_POSITION_COUNT;\n  WORD wSin = fix16_to_int(STAR_RADIUS * fix16_sin(fAngle) + fHalf);\n  WORD wCos = fix16_to_int(STAR_RADIUS * fix16_cos(fAngle) + fHalf);\n  s_pPositions[ubPosIndex].wX = wSin;\n  s_pPositions[ubPosIndex].wY = wCos;\n}\n```\n\n## Speeding up angles and sines\n\nThe `fix16_sin()` and other trigonometric functions are accepting their angles in fixed point format, which is a source for some avoidable slowdowns.\nInstead, you might want to use *brads* - radians stored on a byte, where 0 means 0&deg; and 255 means almost 360&deg;.\nThis will limit your angle precision, but will also allow you to cache trigonometric function values in an array.\nYou can also reduce size of those arrays to your liking by limiting precision even further and making the angle range between `0..127`, `0..63` or some other upper limit of your choice - watch out for overflows and underflows, though.\n\n## Using 16-bit base type for fixed points\n\nIf you don't need all the precision and range that `fix16_t` has to offer, you might want to limit it to gain some more speed.\nYou will need to roll your own functions though, or use another library since libfixmath doesn't offer changing its range or amount of bits in any of its parts.\n\nRolling your own functions isn't that hard, especially if you only need limited amount of functions, and can get away with only addition and multiplying by integers:\n\n```c\ntypedef UWORD tFix10p6; // unsigned fixed point integer with 10.6 split\n\nstatic inline tFix10p6 fix10p6Add(tFix10p6 a, tFix10p6 b) {return a + b; }\nstatic inline tFix10p6 fix10p6FromUword(UWORD x) {return x << 6; }\nstatic inline tFix10p6 fix10p6ToUword(UWORD x) {return x >> 6; }\n```\n"
  },
  {
    "path": "docs/programming/fonts.md",
    "content": "# Working with Fonts\n\nACE provides a font system that allows you to display text in your games with various formatting options.\n\nFonts in ACE are stored as 1-bit bitmap data with each glyph placed side by side in a single continuous bitmap.\nThe system supports:\n\n- Variable width characters\n- Text alignment (left, right, center)\n- Text effects (shadows, cookies)\n- Efficient memory usage with pre-rendered text bitmaps\n- **Single-color texts only**\n\n> [!NOTE]\n> For multi-color texts, consider rolling your own font system.\n\n## Using Fonts in Code\n\nFirst, convert the font from the format of your choice using the [font_conv](../tools/font_conv.md).\nThen, Load your font and create the intermediate Text Bitmap for storing texts composed from separate glyphs:\n\n```c\n#include <ace/utils/font.h>\n\nstatic tFont *s_pFont;\nstatic tTextBitMap *s_pTextBitmap;\n\n// In gamestate create:\ns_pFont = fontCreateFromPath(\"data/fonts/your_font.fnt\");\ns_pTextBitmap = fontCreateTextBitMap(96, s_pFont->uwHeight);\n```\n\n> [!CAUTION]\n> Be sure to create the Text Bitmap with size which can fit the longest text possible in your game.\n>\n> Because of how blitter works, increase the X size by 16.\n\n> [!NOTE]\n> To conserve memory, re-use a single Text Bitmap for drawing different texts.\n\nTo draw the text, do as follows:\n\n```c\n// Draw text directly with formatting\nfontDrawStr(\n  s_pFont,                // The font to use\n  s_pSimpleBuffer->pBack, // Destination bitmap\n  uwX, uwY,               // Position coordinates\n  \"Hello, Amiga!\",        // Text to display\n  ubColor,                // Color index to use\n  FONT_CENTER,            // Formatting flags\n  s_pTextBitmap             // Reusable Text Bitmap\n);\n```\n\nYou can combine following flags with `|` to achieve different text formatting:\n\n- Horizontal alignment: `FONT_LEFT`, `FONT_RIGHT`, `FONT_HCENTER`\n- Vertical alignment: `FONT_TOP`, `FONT_BOTTOM`, `FONT_VCENTER`\n- Combined alignment: `FONT_CENTER` (horizontally and vertically centered)\n- Effects: `FONT_SHADOW` (draw with shadow), `FONT_COOKIE` (text with outline)\n- Lazy draw: `FONT_LAZY`\n\nYou might want to measure your text at some occasions, e.g. to allocate Text Bitmap, or to draw the UI closely matching the text.\nUse `fontMeasureText()` for that.\n\n## Cleanup\n\nAlways free resources when they're no longer needed:\n\n```c\n// Destroy text bitmap buffer\nfontDestroyTextBitMap(s_pTextBitmap);\n\n// Destroy font\nfontDestroy(s_pFont);\n```\n\n## Performance Tips\n\n1. Pre-render text that doesn't change frequently in dedicated Text Bitmap:\n\n   ```c\n   // Create a bitmap containing the text\n   tTextBitMap *s_pStaticText = fontCreateTextBitMapFromStr(s_pFont, \"Game Over\");\n   // Or lazily update its contents with fontFillTextBitMap()\n\n   // Later on, draw the pre-rendered text repeatedly\n   fontDrawTextBitMap(pBuffer->pBack, pStaticText, uwX, uwY, ubColor, ubFlags);\n   ```\n\n2. To minimize blitter operations, only redraw text when it changes.\n3. If you're doing the HUD draws, consider splitting the draws of each part to separate frame.\n It will usually be fast enough and the delay will probably be barely noticable by the player.\n"
  },
  {
    "path": "docs/programming/hello_world.md",
    "content": "# \"Hello world\" example\n\nFirst, create folder for your project. Then, create src folder for keeping your\n.c files. Let's start with `src/main.c`:\n\n```c\n// Use this only if you want to enable logging to file instead of UAE console (heavy performance hit, not recommended)\n#define GENERIC_MAIN_LOG_PATH \"game.log\"\n\n#include <ace/generic/main.h>\n\nvoid genericCreate(void) {\n  // Here goes your startup code\n  logWrite(\"Hello, Amiga!\\n\");\n}\n\nvoid genericProcess(void) {\n  // Here goes code done each game frame\n  // Nothing here right now\n  gameExit();\n}\n\nvoid genericDestroy(void) {\n  // Here goes your cleanup code\n  logWrite(\"Goodbye, Amiga!\\n\");\n}\n```\n\nAs you may suspect, this code will print two lines into log file.\nTo build it, create a CMakeLists.txt file in the base directory of your project.\nYou can base it on one found in `showcase` directory or use one added below.\n\n```cmake\ncmake_minimum_required(VERSION 3.14.0)\nproject(hello LANGUAGES C)\n\n# Lowercase project name for binaries and packaging\nstring(TOLOWER ${PROJECT_NAME} PROJECT_NAME_LOWER)\n\nif(NOT AMIGA)\n\tmessage(SEND_ERROR \"This project only compiles for Amiga\")\nendif()\n\nset(CMAKE_C_STANDARD 11)\nset(CMAKE_C_FLAGS \"${CMAKE_C_FLAGS} -DAMIGA -Wall -Wextra -fomit-frame-pointer\")\nfile(GLOB_RECURSE SOURCES src/*.c)\nfile(GLOB_RECURSE HEADERS src/*.h)\n\ninclude_directories(${PROJECT_SOURCE_DIR}/src)\n\n# Debugging flag exposed via CMake specifically for your game code\nif(GAME_DEBUG)\n  set(CMAKE_C_FLAGS \"${CMAKE_C_FLAGS} -DGAME_DEBUG\")\nendif()\n\n# ACE\nadd_subdirectory(deps/ace ace)\ninclude_directories(deps/ace/include)\n# If you built standalone and installed ACE, use following instead:\n# find_package(ace REQUIRED)\n# include_directories(${ace_INCLUDE_DIRS})\n\n# Force lower-case binary name for Linux etc.\nset(TARGET_NAME ${PROJECT_NAME_LOWER})\n\nif(ELF2HUNK)\n  # Add elf2hunk step for Bartman compiler\n  set(GAME_LINKED ${TARGET_NAME}.elf) # Intermediate executable\n  set(GAME_EXE ${TARGET_NAME}.exe) # Use this to launch the game\n  add_executable(${GAME_LINKED} ${SOURCES} ${HEADERS})\n  add_custom_command(\n    TARGET ${GAME_LINKED} POST_BUILD\n    COMMAND ${ELF2HUNK} ${GAME_LINKED} ${GAME_EXE}\n  )\nelse()\n  # Just produce the executable with Bebbo compiler\n  SET(GAME_LINKED ${TARGET_NAME})\n  SET(GAME_EXE ${TARGET_NAME})\n  add_executable(${GAME_LINKED} ${SOURCES} ${HEADERS})\nendif()\n\ntarget_link_libraries(${GAME_LINKED} ace)\n```\n\nOnce you have that done, compile it.\n\nUsing Visual Studio Code:\n\n- Press <kbd>Ctrl</kbd>+<kbd>Shift</kbd>+<kbd>P</kbd> to invoke command palette.\n- Start typing and select the `CMake: Configure` command.\n  This configures the project for subsequent builds.\n- If asked to choose the compiler, select the Bartman/Bebbo Amiga compiler.\n- To turn on ACE's extra debugging features:\n  - Press <kbd>Ctrl</kbd>+<kbd>Shift</kbd>+<kbd>P</kbd>.\n  - Select `CMake: Edit CMake Cache (UI)`.\n  - Select `ACE_DEBUG` and optionally `ACE_DEBUG_UAE` for better debugging under UAE.\n- Press <kbd>F7</kbd> to build your game.\n\nUsing terminal commands:\n\n```sh\nmkdir build && cd build\n# Add optional -DACE_DEBUG_UAE=ON for better debugging experience under emulator\ncmake .. \\\n  -DCMAKE_TOOLCHAIN_FILE=/path/to/AmigaCMakeCrossToolchains/m68k.cmake \\\n  -DM68K_TOOLCHAIN_PATH=/path/to/toolchain \\\n  -DM68K_CPU=68000 -DM68K_FPU=soft -DACE_DEBUG=ON\ncmake --build .\n```\n\nPut your executable in UAE or real hardware and launch it.\nIf you've enabled `GENERIC_MAIN_LOG_PATH`, observe that `game.log` has been created in the same directory as executable - it has lots of lines showing things done by the engine, among them two lines specified by you with `logWrite`.\nAlternatively, logs should appear inside UAE / VSCode debugging console.\n\nIf `game.log` has not been created, you've not enabled ACE debugging: on CMake call, add `-DACE_DEBUG=ON` and optionally `-DACE_DEBUG_UAE=ON`.\nYou may need to remove `CMakeCache.txt` to enforce whole project rebuild.\n\n## First gamestate\n\nNow let's add a blank loop which will wait until you press escape key on your\nkeyboard. Let's add first gamestate in `src/game.c`:\n\n``` c\n#include \"game.h\"\n#include <ace/managers/key.h> // We'll use key* fns here\n#include <ace/managers/game.h> // For using gameExit\n#include <ace/managers/system.h> // For systemUnuse and systemUse\n\n// \"Gamestate\" is a long word, so let's use shortcut \"Gs\" when naming fns\n\nvoid gameGsCreate(void) {\n  // Initializations for this gamestate - load bitmaps, draw background, etc.\n  // We don't need anything here right now except for unusing OS\n  systemUnuse();\n}\n\nvoid gameGsLoop(void) {\n  // This will loop forever until you \"pop\" or change gamestate\n  // or close the game\n  if(keyCheck(KEY_ESCAPE)) {\n    gameExit();\n  }\n  else {\n    // Process loop normally\n    // We'll come back here later\n  }\n}\n\nvoid gameGsDestroy(void) {\n  systemUse();\n  // Cleanup when leaving this gamestate\n  // Empty at the moment except systemUse\n}\n```\n\nTo make those functions visible outside `game.c` we need to create header file -\nfor convenience we'll name it the same way, with different extension -\n`src/game.h`:\n\n``` c\n#ifndef _GAME_H_\n#define _GAME_H_\n\n// Function headers from game.c go here\n// It's best to put here only those functions which are needed in other files.\n\nvoid gameGsCreate(void);\nvoid gameGsLoop(void);\nvoid gameGsDestroy(void);\n\n#endif // _GAME_H_\n```\n\nThose `#ifndef`/`#define`/`#endif` lines are called\n[include guards](https://en.wikipedia.org/wiki/Include_guard) - they speed up\ncompilation and prevent conflicts as they ensure that given file will be parsed\nonly once - regardless of number of inclusions in other files.\n\nNow let's add this gamestate along with updating keyboard state to `main.c`:\n\n``` c\n// Use this only if you want to enable logging to file instead of UAE console (heavy performance hit, not recommended)\n#define GENERIC_MAIN_LOG_PATH \"game.log\"\n\n#include <ace/generic/main.h>\n#include <ace/managers/key.h>\n#include <ace/managers/state.h>\n// Without it compiler will yell about undeclared gameGsCreate etc\n#include \"game.h\"\n\ntStateManager *g_pGameStateManager = 0;\ntState *g_pGameState = 0;\n\nvoid genericCreate(void) {\n  // Here goes your startup code\n  logWrite(\"Hello, Amiga!\\n\");\n  keyCreate(); // We'll use keyboard\n  // Initialize gamestate\n  g_pGameStateManager = stateManagerCreate();\n  g_pGameState = stateCreate(gameGsCreate, gameGsLoop, gameGsDestroy, 0, 0);\n\n  statePush(g_pGameStateManager, g_pGameState);\n}\n\nvoid genericProcess(void) {\n  // Here goes code done each game frame\n  keyProcess();\n  stateProcess(g_pGameStateManager); // Process current gamestate's loop\n}\n\nvoid genericDestroy(void) {\n  // Here goes your cleanup code\n  stateManagerDestroy(g_pGameStateManager);\n  stateDestroy(g_pGameState);\n  keyDestroy(); // We don't need it anymore\n  logWrite(\"Goodbye, Amiga!\\n\");\n}\n```\n\nAfter launching your executable, you should see a blank screen until you press\nescape. If everything works properly, let's move on and try to put something on\nthe screen.\n"
  },
  {
    "path": "docs/programming/loading_images.md",
    "content": "# Loading images and displaying background\n\nSo far, only solid rectangles were used for graphics.\nIt's time to use images.\nThis step uses graphics based on [MegaCrash's Breakout Assets](https://megacrash.itch.io/breakout-assets).\n\n## Preparing images and palette\n\nWhen preparing graphics for your game, ensure that all of them which are to be displayed on same screen, use the same color palette. Some technical points to consider:\n\n- OCS/ECS Amiga's display modes can handle up to 32-color palettes (5 bits per pixel), with EHB and HAM modes being an exception which need some more work.\n- The bigger the pixel color depth, the slower the system will work - this is due to Denise chip eating memory access cycles, which could otherwise be used by Copper, Blitter or CPU.\n  Consider limiting palette to as little as you can to maintain best performance.\n- Amiga blitter as well as display hardware handles graphics in batches of 16 horizontal pixels - ACE itself doesn't work around it, so be sure that all your bitmaps are saved with width equal to multiple of 16.\n- At the time of writing, ACE's palette converter can handle following palette formats:\n  - GIMP palette file (`.gpl`)\n  - Adobe Color Table file (`.act`)\n  - ProMotion NG palette file (`.pal`)\n- Currently, ACE only supports converting bitmaps from `.png` files.\n\nDownload following assets: [Pong background](../../showcase/res/pong_bg.png) and [Pong palette](../../showcase/res/pong.gpl) and put them in folder of your choice - it is a good practice to put resources for conversion in separate folder from source code, e.g. `res` subdirectory.\n\n## Converting images for ACE's use\n\nACE uses custom file formats: palettes are stored in `.plt` files, whereas for bitmaps `.bm` files are used.\nYou need to convert your files into those formats and the best way to do this is to add some code to CMake so that they're automatically converted for you, including when they've changed their contents.\nTo do so, assuming you've [built the conversion tools](../installing/tools.md), add following lines to your CMakeLists.txt file, somewhere after the `add_executable()` line, e.g. at the end of the file:\n\n```cmake\n# Convenience variables for source/destination paths\nset(RES_DIR ${CMAKE_CURRENT_LIST_DIR}/res)\nset(DATA_DIR ${CMAKE_CURRENT_BINARY_DIR}/data)\n\n# Create directory for converted files next to built executable\nfile(MAKE_DIRECTORY ${DATA_DIR})\n\n# Convert palette and background image\nconvertPalette(${GAME_LINKED} ${RES_DIR}/pong.gpl ${DATA_DIR}/pong.plt)\nconvertBitmaps(\n  TARGET ${GAME_LINKED} PALETTE ${RES_DIR}/pong.gpl\n  SOURCES ${RES_DIR}/pong_bg.png\n  DESTINATIONS ${DATA_DIR}/pong_bg.bm\n)\n```\n\nAfter you've saved and rebuilt your game, you should have `data` folder in your build directory and in it `pong.plt` palette file, as well as `pong_bg.bm` bitmap file for your background.\n\n## Loading palette and images\n\nNow that files are converted, it's time to load them in-game and draw the background.\nReplace the old palette-setting code with new one, as well as add the background from loaded tile.\n\n```c\n// At the top of the file, near other includes\n#include <ace/utils/palette.h>\n\nvoid gameGsCreate(void) {\n  // ...old stuff here...\n\n//-------------------------------------------------------------- NEW STUFF START\n  // Load palette from file to first viewport - second one will use the same\n  // due to TAG_VIEW_GLOBAL_PALETTE being by default set to 1. We're using\n  // 4BPP display, which means max 16 colors.\n  paletteLoadFromPath(\"data/pong.plt\", s_pVpScore->pPalette, 16);\n\n  // Load background graphics and draw them immediately\n  tBitMap *pBmBackground = bitmapCreateFromPath(\"data/pong_bg.bm\", 0);\n  for(UWORD uwX = 0; uwX < s_pMainBuffer->uBfrBounds.uwX; uwX += 16) {\n    for(UWORD uwY = 0; uwY < s_pMainBuffer->uBfrBounds.uwY; uwY += 16) {\n      blitCopyAligned(pBmBackground, 0, 0, s_pMainBuffer->pBack, uwX, uwY, 16, 16);\n    }\n  }\n  bitmapDestroy(pBmBackground);\n//---------------------------------------------------------------- NEW STUFF END\n\n  // Draw line separating score VPort and main VPort, leave one line blank after it\n  blitLine(\n    s_pScoreBuffer->pBack,\n    0, s_pVpScore->uwHeight - 2,\n    s_pVpScore->uwWidth - 1, s_pVpScore->uwHeight - 2,\n    SCORE_COLOR, 0xFFFF, 0 // Try patterns 0xAAAA, 0xEEEE, etc.\n  );\n\n  // NEW: Don't need the line for bottom wall anymore\n\n  systemUnuse();\n\n  // Load the view\n  viewLoad(s_pView);\n}\n```\n\nFunctions which operate on files and that are named `somethingLoad()` usually load file contents into already existing places - in this case you're loading colors from palette file directly into palette.\nOther files are named `somethingCreate()` and those reserve new memory and load file contents into it for you.\nNote that bitmaps and other assets loaded this way must be manually destroyed after they're no longer needed by using `somethingDestroy()` function to free the memory - not doing so will result in memory leak.\n\nWith this code, you should now have fine and dandy background for your pong game.\nThere are some issues, however: the paddles have wrong colors, as well as they erase the background when they move.\nWe'll fix those issues shortly.\n"
  },
  {
    "path": "docs/programming/moving_blits.md",
    "content": "# Moving blitted objects\n\nLast time, we've added static paddles and ball for pong-like game.\nNow it's time to make things move.\n\nThe important thing to understand is that blitter draws objects directly on the bitmap which we'll then display.\nThe problem is, if you draw the paddle in new position, it will still be visible in old one.\nTo visualize this problem, slightly modify your game.c code and add ability to move the right paddle up and down with keyboard's arrow keys:\n\n```c\n// ... rest is without changes\n#define WALL_HEIGHT 1\n#define WALL_COLOR 1\n//-------------------------------------------------------------- NEW STUFF START\n#define PLAYFIELD_HEIGHT (256-32)\n#define PADDLE_MAX_POS_Y (PLAYFIELD_HEIGHT - PADDLE_HEIGHT - 1)\n#define PADDLE_SPEED 4\n//---------------------------------------------------------------- NEW STUFF END\n\nstatic tView *s_pView; // View containing all the viewports\nstatic tVPort *s_pVpScore; // Viewport for score\nstatic tSimpleBufferManager *s_pScoreBuffer;\nstatic tVPort *s_pVpMain; // Viewport for playfield\nstatic tSimpleBufferManager *s_pMainBuffer;\n\n//-------------------------------------------------------------- NEW STUFF START\nstatic UWORD uwPaddleLeftPosY = 0;\nstatic UWORD uwPaddleRightPosY = 0;\n//---------------------------------------------------------------- NEW STUFF END\n\n// ... rest is without changes\n\nvoid gameGsLoop(void) {\n  // This will loop every frame\n  if(keyCheck(KEY_ESCAPE)) {\n    gameExit();\n  }\n  else {\n//-------------------------------------------------------------- NEW STUFF START\n  if(keyCheck(KEY_DOWN)) {\n    uwPaddleRightPosY = MIN(uwPaddleRightPosY + PADDLE_SPEED, PADDLE_MAX_POS_Y);\n  }\n  else if(keyCheck(KEY_UP)) {\n    uwPaddleRightPosY = MAX(uwPaddleRightPosY - PADDLE_SPEED, 0);\n  }\n//---------------------------------------------------------------- NEW STUFF END\n\n    // Draw first paddle\n    // NEW: uwPaddleLeftPosY\n    blitRect(\n      s_pMainBuffer->pBack, 0, uwPaddleLeftPosY,\n      PADDLE_WIDTH, PADDLE_HEIGHT, PADDLE_LEFT_COLOR\n    );\n\n    // Draw second paddle\n    // NEW: uwPaddleRightPosY\n    blitRect(\n      s_pMainBuffer->pBack, s_pVpMain->uwWidth - PADDLE_WIDTH, uwPaddleRightPosY,\n      PADDLE_WIDTH, PADDLE_HEIGHT, PADDLE_RIGHT_COLOR\n    );\n\n    // Draw ball\n    blitRect(\n      s_pMainBuffer->pBack,\n      // x center: half of screen width minus half of ball\n      (s_pVpMain->uwWidth - BALL_WIDTH) / 2,\n      // y center: half of screen height minus half of ball\n      (s_pVpMain->uwHeight - BALL_WIDTH) / 2,\n      BALL_WIDTH, BALL_WIDTH, BALL_COLOR\n    );\n    vPortWaitForEnd(s_pVpMain); // Wait for end of frame\n  }\n}\n```\n\nAfter running the code, you'll see that moving the paddle down makes it draw the blue vertical bar.\nWe'll fix that shortly, but first a bit more of computer graphics theory.\n\n## Immediate and retained draw modes\n\nModern computers are quick enough to draw the whole frame from scratch.\nThis makes generating graphics quite simple and consists of following steps:\n\n- clear the display bitmap\n- draw the background across the whole bitmap\n- draw all the foreground objects\n- display the bitmap\n\nThis however comes with big performance cost and isn't possible to do on stock Amiga hardware while keeping decent frame rate and color count.\nEven clearing the whole display bitmap would eat around half of your frame time budget!\n\nThe other way to do things is to use retained mode - redraw only things that are moving and keeping remaining things intact.\nAssuming there is some kind of background, and we have some foreground objects, all we need to do is:\n\n- \"undraw\" the moving object with background, which we've stored prior to drawing it, by drawing the background on old position of the object,\n- store the background under new position, which will be used for next undraw,\n- draw the object on new position\n\nSince the pong game uses solid background, you don't need to store it - you just have to draw solid black color on old position to undraw the paddle, and then draw it in the new one.\n\n## Tutorial code\n\nThe following code correctly moves paddles up and down without any kind of trails:\n\n```c\n#include \"game.h\"\n#include <ace/managers/key.h>\n#include <ace/managers/game.h>\n#include <ace/managers/system.h>\n#include <ace/managers/viewport/simplebuffer.h>\n#include <ace/managers/blit.h> // Blitting fns\n\n// Let's make code more readable by giving names to numbers\n// It is a good practice to name constant stuff using uppercase\n#define BALL_WIDTH 8\n#define BALL_COLOR 1\n#define PADDLE_WIDTH 8\n#define PADDLE_HEIGHT 32\n#define PADDLE_LEFT_COLOR 2\n#define PADDLE_RIGHT_COLOR 3\n#define SCORE_COLOR 1\n#define WALL_HEIGHT 1\n#define WALL_COLOR 1\n//-------------------------------------------------------------- NEW STUFF START\n#define PLAYFIELD_HEIGHT (256-32)\n#define PADDLE_MAX_POS_Y (PLAYFIELD_HEIGHT - PADDLE_HEIGHT - 1)\n#define PADDLE_SPEED 4\n//---------------------------------------------------------------- NEW STUFF END\n\nstatic tView *s_pView; // View containing all the viewports\nstatic tVPort *s_pVpScore; // Viewport for score\nstatic tSimpleBufferManager *s_pScoreBuffer;\nstatic tVPort *s_pVpMain; // Viewport for playfield\nstatic tSimpleBufferManager *s_pMainBuffer;\n\n//-------------------------------------------------------------- NEW STUFF START\nstatic UWORD uwPaddleLeftPosY = 0;\nstatic UWORD uwPaddleRightPosY = 0;\n//---------------------------------------------------------------- NEW STUFF END\n\nvoid gameGsCreate(void) {\n  s_pView = viewCreate(0, TAG_END);\n\n  // Viewport for score bar - on top of screen\n  s_pVpScore = vPortCreate(0,\n    TAG_VPORT_VIEW, s_pView,\n    TAG_VPORT_BPP, 4,\n    TAG_VPORT_HEIGHT, 32,\n  TAG_END);\n  s_pScoreBuffer = simpleBufferCreate(0,\n    TAG_SIMPLEBUFFER_VPORT, s_pVpScore,\n    TAG_SIMPLEBUFFER_BITMAP_FLAGS, BMF_CLEAR,\n  TAG_END);\n\n  // Now let's do the same for main playfield\n  s_pVpMain = vPortCreate(0,\n    TAG_VPORT_VIEW, s_pView,\n    TAG_VPORT_BPP, 4,\n  TAG_END);\n  s_pMainBuffer = simpleBufferCreate(0,\n    TAG_SIMPLEBUFFER_VPORT, s_pVpMain,\n    TAG_SIMPLEBUFFER_BITMAP_FLAGS, BMF_CLEAR,\n  TAG_END);\n\n  s_pVpScore->pPalette[0] = 0x0000; // First color is also border color\n  s_pVpScore->pPalette[1] = 0x0888; // Gray\n  s_pVpScore->pPalette[2] = 0x0800; // Red - not max, a bit dark\n  s_pVpScore->pPalette[3] = 0x0008; // Blue - same brightness as red\n\n  // Draw line separating score VPort and main VPort, leave one line blank after it\n  blitLine(\n    s_pScoreBuffer->pBack,\n    0, s_pVpScore->uwHeight - 2,\n    s_pVpScore->uwWidth - 1, s_pVpScore->uwHeight - 2,\n    SCORE_COLOR, 0xFFFF, 0 // Try patterns 0xAAAA, 0xEEEE, etc.\n  );\n\n  // Draw wall on the bottom of main VPort\n  blitRect(\n    s_pMainBuffer->pBack,\n    0, s_pVpMain->uwHeight - WALL_HEIGHT,\n    s_pVpMain->uwWidth, WALL_HEIGHT, WALL_COLOR\n  );\n\n  systemUnuse();\n\n  // Load the view\n  viewLoad(s_pView);\n}\n\nvoid gameGsLoop(void) {\n  // This will loop every frame\n  if(keyCheck(KEY_ESCAPE)) {\n    gameExit();\n  }\n  else {\n//-------------------------------------------------------------- NEW STUFF START\n  // Undraw left paddle\n  blitRect(\n    s_pMainBuffer->pBack, 0, uwPaddleLeftPosY,\n    PADDLE_WIDTH, PADDLE_HEIGHT, 0 // color zero is black\n  );\n\n  // Update left paddle position\n  if(keyCheck(KEY_S)) {\n    uwPaddleLeftPosY = MIN(uwPaddleLeftPosY + PADDLE_SPEED, PADDLE_MAX_POS_Y);\n  }\n  else if(keyCheck(KEY_W)) {\n    uwPaddleLeftPosY = MAX(uwPaddleLeftPosY - PADDLE_SPEED, 0);\n  }\n\n  // Undraw right paddle\n  blitRect(\n    s_pMainBuffer->pBack, s_pVpMain->uwWidth - PADDLE_WIDTH, uwPaddleRightPosY,\n    PADDLE_WIDTH, PADDLE_HEIGHT, 0 // color zero is black\n  );\n\n  // Update right paddle position\n  if(keyCheck(KEY_DOWN)) {\n    uwPaddleRightPosY = MIN(uwPaddleRightPosY + PADDLE_SPEED, PADDLE_MAX_POS_Y);\n  }\n  else if(keyCheck(KEY_UP)) {\n    uwPaddleRightPosY = MAX(uwPaddleRightPosY - PADDLE_SPEED, 0);\n  }\n    // Draw left paddle - NEW: uwPaddleLeftPosY\n    blitRect(\n      s_pMainBuffer->pBack, 0, uwPaddleLeftPosY,\n      PADDLE_WIDTH, PADDLE_HEIGHT, PADDLE_LEFT_COLOR\n    );\n\n    // Draw right paddle - NEW: uwPaddleRightPosY\n    blitRect(\n      s_pMainBuffer->pBack, s_pVpMain->uwWidth - PADDLE_WIDTH, uwPaddleRightPosY,\n      PADDLE_WIDTH, PADDLE_HEIGHT, PADDLE_RIGHT_COLOR\n    );\n//---------------------------------------------------------------- NEW STUFF END\n\n    // Draw ball\n    blitRect(\n      s_pMainBuffer->pBack,\n      // x center: half of screen width minus half of ball\n      (s_pVpMain->uwWidth - BALL_WIDTH) / 2,\n      // y center: half of screen height minus half of ball\n      (s_pVpMain->uwHeight - BALL_WIDTH) / 2,\n      BALL_WIDTH, BALL_WIDTH, BALL_COLOR\n    );\n    vPortWaitForEnd(s_pVpMain);\n  }\n}\n\nvoid gameGsDestroy(void) {\n  systemUse();\n\n  // This will also destroy all associated viewports and viewport managers\n  viewDestroy(s_pView);\n}\n```\n"
  },
  {
    "path": "docs/programming/os.md",
    "content": "# Working with and without OS\n\nTo squeeze as much performance as possible, ACE allows for disabling Amiga OS and re-enabling it when needed.\nTypically, 95% of stuff which game performs doesn't need operating system, so you're safe to have it disabled when your game runs.\nThings that require having OS enabled:\n\n- memory allocation and deallocation - most `ace/managers/memory.h` functions\n- logging to file - all `ace/managers/log.h` functions if log file is created and when in debug mode\n- general file access - all `ace/utils/file.h` and `ace/utils/dir.h` functions\n- system .library and .device usage\n- multithreading, communicating with other apps\n\n## Manually managing OS state\n\n**By default, ACE leaves OS in enabled state.**\nYou should disable it using `systemUnuse()` to reach the maximum performance.\n\nThe functions which require OS will try to re-enable and disable it on the fly.\nAlthough it's safe approach, it is not optimal, since each OS enabling/disabling takes lots of time (about 2-4 frames, or 40-80ms).\nConsider following code:\n\n```c\nsystemUnuse(); // Assume that OS is disabled at this point\n\nlogWrite(\"I'm initializing stuff\\n\");\npaletteLoadFromPath(\"palette.plt\", s_pPalette, 32);\ns_pBm1 = bitmapCreate(320, 256, 5);\ns_pBm2 = fontCreate(\"test.fnt\");\nlogWrite(\"I'm done initializing\\n\");\n```\n\nThis small code wastes about quarter to half a second to do very simple things, because each of this function re-enables OS at start and disables it at its end.\nThis can be easily fixed by adding `systemUse()` and `systemUnuse()` calls:\n\n```c\nsystemUse(); // Re-enable OS once\nlogWrite(\"I'm initializing stuff\\n\");       // Any of these functions\npaletteLoadFromPath(\"palette.plt\", s_pPalette, 32); // Won't re-enable/disable OS\ns_pBm1 = bitmapCreate(320, 256, 5);         // They have systemUse()/systemUnuse calls\ns_pBm2 = fontCreate(\"test.fnt\");            // But they won't do anything since OS\nlogWrite(\"I'm done initializing\\n\");        // Is already enabled\nsystemUnuse(); // Disable OS once when we're done with it\n```\n\n## Best practices\n\nTry to have OS disabled at the end of gamestate creation, and to re-enable it at the beginning of gamestate destruction.\nThis way, the game loop performs with maximum performance, whereas you have OS at your disposal in create/destroy phases.\n\nYou can assume that every `create()` and `destroy()` function use OS.\nThus, try to not use them in game loop.\nInstead, call them close to each other in state's create/destroy phases and put `systemUse()` / `systemUnuse()` calls around them.\n\nBe careful when using state pushing/popping.\nIf pushed state needs OS and previous state disabled OS by that point, be sure to have it re-enabled at the beginning of gamestate create phase and disabled at the end of gamestate destroy phase.\n\n## Things that doesn't work when OS is enabled\n\nIn future, ACE will be fully usable whether OS is enabled or not.\nCurrently, this is not the case. Some things will not work when OS is enabled:\n\n- .mod playback and other audio stuff (requires CIA/audio interrupts)\n- keyboard handling (requires CIA interrupts)\n- any ACE interrupt handlers and features which requires them\n- timers (requires vertical blanking interrupt)\n\n## System usage stacking\n\nHow does the grouping OS enabling work?\n`systemUse()` and `systemUnuse()` use internal OS usage counter: the former increments it, while the latter decreases its value.\nThe only time the OS gets enabled is when the counter gets to 1, and disabled if it gets to 0.\nConsider following code:\n\n```c\n// Os is disabled at this point - counter value is 0\nsystemUse(); // Usage counter gets set to 1 - re-enable OS\n\n// Internal workings of bitmapCreate fn:\nsystemUse(); // Usage counter increased to 2\nlogWrite(...); // systemUse/unuse inside fn: Usage counter gets to 3, then to 2\nmemAllocChip(...); // ditto, os usage 2 -> 3 -> 2\nlogWrite(...);     // ditto, os usage 2 -> 3 -> 2\nsystemUnuse(); // Usage counter decreased to 1\n\nsystemUnuse(); // Usage counter gets set to 0 - disable OS\n```\n"
  },
  {
    "path": "docs/programming/palette.md",
    "content": "# Using Palettes\n\nACE uses its custom `.plt` file format, to which you can convert your palettes from multiple common formats.\nSee [palette_conv](../tools/palette_conv.md) for details.\n\nBy default `palette_conv` writes **v2 ECS/OCS** (first byte `0`): big-endian **UWORD** color count, then packed 12-bit colors. Pass **`--aga`** for **v2 AGA** (first byte `1`, 4 bytes per color). Use **`-cc`** with ECS output to quantize 8-bit RGB to OCS 12-bit instead of erroring (see [palette_conv](../tools/palette_conv.md)).\n\n## Loading palette into your game\n\nTo load your palette in the game, do the following:\n\n```c\n// GAME_BPP is your number of color choice - 4 for 16 colors, 5 for 32 colors\n#define GAME_BPP 5\n\nstatic UWORD s_pPalette[1 << GAME_BPP];\n\nvoid gameGsCreate(void) {\n  // ...\n\n  // Load your palette\n  paletteLoadFromPath(\"data/mypalette.plt\", s_pPalette, 1 << GAME_BPP);\n  // Copy the palette to your viewport.\n  // When using `TAG_VIEW_GLOBAL_PALETTE`, only palette in topmost viewport matters.\n  memcpy(s_pViewPort->pPalette, s_pPalette, sizeof(s_pVpMain->pPalette));\n\n  // ...\n\n  // If using `TAG_VIEW_GLOBAL_PALETTE`, load the changed palette\n  viewUpdateGlobalPalette(s_pView);\n}\n```\n\nFor an **AGA** viewport (`VP_FLAG_AGA`), use a **`ULONG`** palette buffer sized for your bit depth (`1 << bpp`). Pass the same pointer to `paletteLoadFromPath()`; when the file’s first byte is **1** (AGA v2), entries are read as in the viewport.\n\nUse **`paletteSaveOcs()`** for v2 ECS output and **`paletteSaveAga()`** (with `ACE_USE_AGA_FEATURES`) for v2 AGA output.\n\n> [!NOTE]\n> If you don't need any fancy palette effects, you can load your palette to the `s_pVpMain->pPalette` directly.\n\n## Dimming the palette\n\nYou can dim your palette using `paletteDim()` as well as `paletteColorDim()`.\nThe `ubLevel` parameter accepts values between 0 and 15, where 0 results in fully dimmed color and 15 results in unchanged color.\n\n> [!CAUTION]\n> Using previously-dimmed palette/color as a `paletteDim()`/`paletteColorDim()` input will yield degraded color quality.\n> Always use pristine palette as a fade source!\n\n> [!NOTE]\n> When using `TAG_VIEW_GLOBAL_PALETTE`, store the dimmed result in `s_pVpMain->pPalette` and be sure to call `viewUpdateGlobalPalette()` to update your displayed colors afterwards.\n"
  },
  {
    "path": "docs/programming/res/overworld.gpl",
    "content": "GIMP Palette\nName: Palette\nColumns: 4\n# Author: Anonymous\n# URL: https://lospec.com/palette-list\n# Profile: sRGB\n# Colors: 32\n000 000 000 000000\n017 017 017 111111\n034 034 034 222222\n068 068 051 444433\n119 017 017 771111\n153 051 017 993311\n136 085 068 885544\n187 051 034 BB3322\n170 102 068 AA6644\n119 102 085 776655\n051 085 068 335544\n204 102 000 CC6600\n255 136 000 FF8800\n136 136 119 888877\n204 153 085 CC9955\n221 170 119 DDAA77\n204 187 153 CCBB99\n051 102 051 336633\n068 119 102 447766\n153 170 051 99AA33\n119 153 068 779944\n255 187 000 FFBB00\n170 204 051 AACC33\n170 170 153 AAAA99\n221 204 119 DDCC77\n085 136 068 558844\n136 153 136 889988\n017 068 136 114488\n068 119 187 4477BB\n136 034 085 882255\n187 051 085 BB3355\n204 085 136 CC5588"
  },
  {
    "path": "docs/programming/sprites.md",
    "content": "# Using sprites\n\n## Basic description of sprite hardware\n\nThere are eight sprite channels, meaning that Amiga can display data of 8 different sprites on the same line.\nEach channel has its own assigned sprite, specified by filling `sprXpt` custom register with pointer to sprite data, where `X` is the channel number.\n\nThe sprite data consists of:\n\n- the header consisting of 2 16-bit words and indicating the position of the sprite as well as its height,\n- the actual sprite display data,\n- the footer consisting of a single 32-bit pointer to the data of next sprite to be shown after displaying the previous one. Such configuration is often described as *sprite list* or *sprite chain*.\n\nOn Amiga hardware, each sprite is 16 pixels wide, can be of arbitrary height and is always 2BPP.\nWith header and footer in mind, this means that e.g. 16x32 sprite data can be prepared as 16x34 2BPP interleaved bitmap.\n\nIn order to create wider sprites, you need to use multiple 16px-wide sprites and position them next to each other.\nAlthough AGA chipset supports wider sprites, the support for that feature is still unimplemented.\n\nThe final sprite palette is dependent on the channel.\nThe sprite 2BPP colors are translated into colors from upper half of the current display palette, even if lower screen BPP is used:\n\n| Sprite color index | 0 (always transparent) |  1 |  2 |  3 |\n|:------------------:|:----------------------:|:--:|:--:|:--:|\n|  channels 0 and 1  |    16 (none)           | 17 | 18 | 19 |\n|  channels 2 and 3  |    20 (none)           | 21 | 22 | 23 |\n|  channels 4 and 5  |    24 (none)           | 25 | 26 | 27 |\n|  channels 6 and 7  |    28 (none)           | 29 | 30 | 31 |\n\nTo enable loading sprite data, you must enable sprite-related bit on DMACON register.\nThis operation enables all sprite channels at once.\nIn order for Amiga hardware to display meaningful data, you must set up `sprXpt` registers on each VBlank - otherwise the hardware will fetch and display garbage on screen from random location. If you don't intend to use a channel, you must still ensure that its `sprXpt` points to valid data - the best way to not display anything is to point it to an empty two 16-bit words of CHIP memory.\n\nIt is possible to attach pairs of sprite channels together to form 16-color sprites - this way the data fetched by one channel controls the lower 2BPP of 4BPP sprites, whereas the other controls the upper half.\n\nIt is also possible to skip sprite DMA and load sprite's data directly into designated registers using copper, but it's more advanced topic.\nFor more elaborate description on sprite hardware, be sure to read other materials, such as Amiga Hardware Reference Manual.\n\n## Using sprite manager\n\nThe sprite manager is located in [managers/sprite.h](../../include/ace/managers/sprite.h).\nIt's principle of work is based on hardware-based linked list of sprites which are set separately for each channel.\nThe manager works in block, as well as raw copperlist mode.\n\n### Manager setup\n\n```c\n// Somewhere in your gamestate creation:\nvoid myGsCreate(void) {\n  // Some stuff goes here...\n\n  spriteManagerCreate(s_pView, 0, NULL); // For raw copper mode, pass position on\n                                         // copperlist for sprite initialization.\n  systemSetDmaBit(DMAB_SPRITE, 1); // Enable sprite DMA.\n\n  // Stuff continues...\n}\n\n// Somewhere in your gamestate destruction:\nvoid myGsDestroy(void) {\n  // Some stuff goes here...\n\n  systemSetDmaBit(DMAB_SPRITE, 0); // Disable sprite DMA\n  spriteManagerDestroy();\n\n  // Stuff continues...\n}\n\n// Somewhere in gamestate loop\nvoid myGsLoop(void) {\n  // Some stuff goes here...\n\n  // Before you call copProcessBlocks():\n  spriteProcessChannel(0); // Process first sprite channel...\n  spriteProcessChannel(3); // ...and the fourth one.\n\n  // Stuff continues...\n\n  copProcessBlocks(); // Be sure to call it or sprite-related copper commands won't work!\n  vPortWaitForEnd(s_pVp);\n}\n```\n\nNote that each channel's processing must be called separately.\nThis allows for further optimization and doing only what is required at the moment.\nYou can of course call processing of all 8 channels each frame, even if you don't use most of them, but this way you lose a bit of processing time.\n\n### Adding sprites\n\nAmiga sprites use 2BPP interleaved format, so you can load its data using bitmap funcions.\nApart from data, adding sprite requires channel index.\n\n```c\ntSprite *s_pSprite0, *s_pSprite3;\ntBitMap *s_pSprite0Data, *s_pSprite3Data;\n\n// Somewhere in your gamestate creation:\nspriteManagerCreate(...);\n// Remember about limited width to 16px AND extra line for header and footer\ns_pSprite0Data = bitmapCreate(16, 34, 2, BMF_CLEAR | BMF_INTERLEAVED); // 16x32 2BPP\ns_pSprite3Data = bitmapCreate(16, 34, 2, BMF_CLEAR | BMF_INTERLEAVED); // 16x32 2BPP\ns_pSprite0 = spriteAdd(0, s_pSprite0Data); // Add sprite to channel 0\ns_pSprite3 = spriteAdd(3, s_pSprite3Data); // Add second sprite to channel 3\n```\n\n> [!NOTE]\n> You can't share sprite data bitmaps across channels - although the display data is the same, the header and footer metadata will differ.\n\nBe sure to dispose of them afterwards:\n\n```c\n// Somewhere in your gamestate destruction:\nbitmapDestroy(s_pSprite0Data);\nbitmapDestroy(s_pSprite3Data);\nspriteRemove(s_pSprite0);\nspriteRemove(s_pSprite3);\nspriteManagerDestroy();\n```\n\n### Updating sprite\n\nIn order for sprite to successfully update its metadata, you need to call `spriteProcess(tSprite *)`.\nThis function will do almost nothing if no change has been done, so you can call it every frame for each sprite.\nWhen optimizing its calls, you need to call it at least twice (once for each double-buffered copperlist buffer) after significant metadata change has been made, including but not limited to:\n\n- position,\n- height,\n- sprite bitmap,\n- enabling sprite,\n- changes in sprite chaining.\n\n### Chaining sprites in a single channel\n\nThis is currently not supported.\n\n## Managing sprites in a different way\n\nIt is very much possible that you will find ACE's sprite manager's abilities insufficient (e.g. you want to manage your sprite pointers or data using copperlist).\nIn this case, you should make your own sprite manager.\nIn order to do this more easily, you may want to use primitives found in [utils/sprite.h](../../include/ace/utils/sprite.h).\n"
  },
  {
    "path": "docs/programming/tilebuffer.md",
    "content": "# Multi-directional large tilemaps scrolling with TileBuffer\n\n## Basic description\n\nThis tutorial will focus on multi-directional scrolling as used for RPG or games like Alien Breed, Chaos Engine or large platform game like Turrican or Superfrog.\n\nAlthough you could use simpleBuffer for drawing and scrolling large tilemaps, it would eat a lot of RAM. In order to do this efficiently, you need to use the [managers/viewport/tilebuffer.h](../../include/ace/managers/viewport/tilebuffer.h). It's specifically design for drawing tiles and scrolling in any direction.\n\n## Prerequisites\n\nThe tile manager takes 2 pre-requisites :\n\n1. a set of tiles\n2. a map using this tiles.\n\nLast pre-requisites, you need the *palette* linked to your tiles graphic. [See Palette Tutorial](./palette.md)\n\n### Prepare the set of tiles\n\nLet's use this resource from open game art: https://opengameart.org/content/overworld-grass-biome\n\nGet `TilesetGrass/overworld_tileset_grass.png` and convert it in 32 colors (use [grafx2](http://grafx2.chez.com/) for example).\n\nNow Select [Aseprite](https://www.aseprite.org/]).\n\n1. Do `File > Import > Import Sprite Sheet`  Select 16x16 sprites option.\n\n2. On the palette editor, reduce the palette to 32 colors. Remove all useless black square after the 32nd colors.\n\n3. Use plugin [Aseprite Script: Amiga OCS/ECS Color Palette Mixe](https://prismaticrealms.itch.io/aseprite-script-amiga-ocsecs-color-palette-mixer) to align png and palette to amiga capacity/rgb colors.\n\n4. Select `File > Export >  Export Sprite Sheet` and then `File > Saves As` and save as `overworld.png`. You must choose **Vertical Strip** for ACE tileBuffer.\n\nThe file is ready for use here : [overworld.png](./res/overworld.png)\n\nAlso, be sure to [export the palette](./palette.md) as `overworld.gpl`\n\nThe palette file is ready for use here : [overworld.gpl](./res/overworld.gpl)\n\n### Prepare the map\n\nYou need to use [Tiled](https://www.mapeditor.org/)\n\nAnd install this addon : https://github.com/youenchene/tiled-export-to-amiga\n\n1. Go to `Settings`\n2. Then `Plugins`\n3. Click Open after the Directory, and copy inside `gogitum.mjs`  \n\nOn **Tiled** :\n\n1. Create new Project\n2. Click on `New Tileset...`\n3. Load `overworld.png` set it to 16 x 16\n4. Then `New Map...`\n5. Choose `Orthogonal`, `CSV` and `Right Down`, `200` tiles x `100` tiles and `16px` tile size\n6. Draw a map\n7. `File > Export As...`\n8. Choose `GOGITUM Export ACE - pTileData (UBYTE)` format and export as `overworld.dat` in your res `folder`.\n\n\nThe map file is ready for use here : [overworld.dat](./res/overworld.dat)\n\n### Recap\n\nIn your `res` folder you should have :\n\n- `overworld.dat` (map)\n- `overworld.gpl` (palette)\n- `overworld.png` (tiles)\n\n## Let's Code\n\n### Assets Preprocessing\n\nFirst, append your `CMakeLists.txt` file and add at the end. \n\nIt loads and converts the palette and then use it to convert your tiles file. It also loads the map file.\n\n```cmake\n# Convert palette and background image\nconvertPalette(${GAME_LINKED} ${RES_DIR}/overworld.gpl ${DATA_DIR}/overworld.plt)\nconvertBitmaps(\n  TARGET ${GAME_LINKED} PALETTE ${RES_DIR}/overworld.gpl\n  INTERLEAVED SOURCES ${RES_DIR}/overworld.png\n  DESTINATIONS ${DATA_DIR}/overworld.bm\n)\n\nfile(COPY ${RES_DIR}/overworld.dat DESTINATION ${DATA_DIR})\n```\n\n### Update your game.c\n\nThen on on your `game.c` or equivalent.\n\nDeclare constants and main static variables\n\n```c\n#define TILE_MAP_SIZE_X 200\n#define TILE_MAP_SIZE_Y 80\n#define GAME_BPP 5 // 32 colors\n#define SCORE_HEIGHT 16\n\n// View containing all the viewports\nstatic tView *s_pView; \n// For score - won't be used in this tuto\nstatic tVPort *s_pVpScore; // Viewport for score\nstatic tSimpleBufferManager *s_pScoreBuffer;\n// Viewport for playfield\nstatic tVPort *s_pVpMain; \n// Your buffer manager, it will handle your scrolling\nstatic tTileBufferManager *s_pMainBuffer;\n// Tiles\nstatic tBitMap *s_pTiles;\n// Palette\nstatic UWORD s_pPalette[1 << GAME_BPP];\n\nstatic UWORD s_uwMapTileWidth;\nstatic UWORD s_uwMapTileHeight;\n//[...]\n// To controle camera/view on scrolling\nUWORD g_uwCameraX=0;\nUWORD g_uwCameraY=0;\nUWORD g_uwCameraSpeed=2;\n//[...]\n\n```\n\nThen, add a function to load your map. The map is loaded column by column for speed purpose :\n\n```c\nstatic void loadMap(void) {\n    logWrite(\"Map Loading...\\n\");\n    tFile *pFileTilemap = diskFileOpen(\"data/overworld.dat\", \"rb\");\n    fileRead(pFileTilemap, &s_uwMapTileWidth, sizeof(s_uwMapTileWidth));\n    fileRead(pFileTilemap, &s_uwMapTileHeight, sizeof(s_uwMapTileHeight));\n    s_uwMapTileWidth++;\n    s_uwMapTileHeight++;\n    logWrite(\"Map Width %u\",s_uwMapTileWidth);\n    logWrite(\"Map Height %u\",s_uwMapTileHeight);\n    for (int x = 0; x < s_uwMapTileWidth; x++) {\n        fileRead(pFileTilemap, s_pMainBuffer->pTileData[x], s_uwMapTileHeight);\n    }\n    fileClose(pFileTilemap); \n    logWrite(\"Map Loaded!\\n\");\n}\n```\n\nAnd this function (in a next iteration of the tutorial I will be able to explain this one) :\n```c\nstatic void onTileDraw(\n    UWORD uwTileX, UWORD uwTileY,\n    tBitMap *pBitMap, UWORD uwBitMapX, UWORD uwBitMapY\n) {\n}\n```\n\nThen, in your `gameGsCreate` function:\n\n```c\n// To move scrolling\nkeyCreate();\njoyOpen();\n\ns_pView = viewCreate(0, TAG_END);\n\n// Viewport for score bar - on top of screen\ns_pVpScore = vPortCreate(0,\n    TAG_VPORT_VIEW, s_pView,\n    TAG_VPORT_BPP, GAME_BPP,\nvTAG_VPORT_HEIGHT, SCORE_HEIGHT,\nTAG_END);\n\ns_pScoreBuffer = simpleBufferCreate(0,\n    TAG_SIMPLEBUFFER_VPORT, s_pVpScore,\n    TAG_SIMPLEBUFFER_BITMAP_FLAGS, BMF_CLEAR,\n    TAG_SIMPLEBUFFER_BOUND_WIDTH, 320,\n    TAG_SIMPLEBUFFER_BOUND_HEIGHT, SCORE_HEIGHT,\nTAG_END);\n\n// Now let's do the same for main playfield where the scrolling happen\ns_pVpMain = vPortCreate(0,\n    TAG_VPORT_VIEW, s_pView,\n    TAG_VPORT_BPP, GAME_BPP,\nTAG_END);\n\n// Load tiles\ns_pTiles = bitmapCreateFromPath(\"data/overworld.bm\", 0);\n\nlogWrite(\"Tiles Loaded!\\n\");\n\n// Init your scrolling tile buffer \ns_pMainBuffer = tileBufferCreate(0,\n    TAG_TILEBUFFER_VPORT, s_pVpMain,  // Select View Port\n    TAG_TILEBUFFER_BITMAP_FLAGS, BMF_CLEAR | BMF_INTERLEAVED,  // If you put interleaved there, it should be also in your cmakelist part.\n    TAG_TILEBUFFER_BOUND_TILE_X, TILE_MAP_SIZE_X, // Map size in number of tile\n    TAG_TILEBUFFER_BOUND_TILE_Y, TILE_MAP_SIZE_Y, // Map size in number of tile\n    TAG_TILEBUFFER_IS_DBLBUF, 1, // Activatey double buffering\n    TAG_TILEBUFFER_TILE_SHIFT, 4, //Size of tile, given in bitshift. Set to 4 for 16px, 5 for 32px, etc. Mandatory.\n    TAG_TILEBUFFER_REDRAW_QUEUE_LENGTH, 200, // cursor between handling fast scrolling versus your amiga power\n    TAG_TILEBUFFER_CALLBACK_TILE_DRAW, onTileDraw, // To be documented\n    TAG_TILEBUFFER_TILESET, s_pTiles,\nTAG_END);\n\n\n// Load and apply palette\npaletteLoadFromPath(\"data/overworld.plt\", s_pPalette, 1 << GAME_BPP);\nmemcpy(s_pVpScore->pPalette, s_pPalette, sizeof(s_pVpScore->pPalette));\nmemcpy(s_pVpMain->pPalette, s_pPalette, sizeof(s_pVpMain->pPalette));\n\n\nloadMap();\n\n//IO operations end here - let's unload the OS and display some stuff\nsystemUnuse();\n\nlogWrite(\"Camera Reset\\n\");\ncameraReset(s_pMainBuffer->pCamera, 0, 0, s_uwMapTileWidth*16, s_uwMapTileHeight * 16, 1);\n\n// Initial draw\ntileBufferRedrawAll(s_pMainBuffer);\n\n// Set initial camera\ncameraSetCoord(s_pMainBuffer->pCamera, g_uwCameraX, g_uwCameraY);\n\n// Load & Display the view\nviewLoad(s_pView);\n```\n\nAnd in your `gameGsDestroy` method to unload memory :\n\n```c\nvoid gameGsDestroy(void) {\n    systemUse();\n    bitmapDestroy(s_pTiles);\n    viewDestroy(s_pView);\n    keyDestroy();\n    oyClose(); \n}\n```\n\nFinally let's control our scrolling in `gameGsLoop`:\n\n```c\n// Handle keyboard and joystick events\nkeyProcess();\njoyProcess();\n//[...]//\n// Let's control your scrolling\n// Q for speeding up (A in azerty keyboard)\n// W for speeding down (Z in azerty keyboard)\nWORD wDx = 0, wDy = 0;\nif(keyCheck(KEY_Q)) {\n    g_uwCameraSpeed+=1;\n}\nif(keyCheck(KEY_W)) {\n    if(g_uwCameraSpeed>1) {\n        g_uwCameraSpeed-=1;\n    }\n}\n// Joy direction to move\nif(joyCheck(JOY1_UP || keyCheck(KEY_UP))) {\n    wDy=-1*g_uwCameraSpeed;\n}\nif(joyCheck(JOY1_DOWN) || keyCheck(KEY_DOWN)) {\n    wDy=g_uwCameraSpeed;\n}\nif(joyCheck(JOY1_LEFT) || keyCheck(KEY_LEFT)) {\n    wDx=-1*g_uwCameraSpeed;\n}\nif(joyCheck(JOY1_RIGHT)|| keyCheck(KEY_RIGHT)) {\n    wDx=g_uwCameraSpeed;\n}\ncameraMoveBy(s_pMainBuffer->pCamera, wDx, wDy);\n//[...]//\n// Process scrolling Mandatory\nviewProcessManagers(s_pView);\n// Process Copper list - mandatory\ncopProcessBlocks();\n// Wait for end of frame\nvPortWaitForEnd(s_pVpMain); \n```\n\nAt the end you should scroll over the map :\n\n![Screenshot Map](./res/screen-tilebuffer.jpg)\n"
  },
  {
    "path": "docs/programming/using_bobs.md",
    "content": "# Working with BOBs (Blitter OBjects)\n\nACE provides a powerful system for managing and animating 2D sprites using the Amiga's hardware blitter through its BOB (Blitter OBject) system.\n\nBOBs are 2D graphic elements that can be efficiently moved around the screen using the Amiga's hardware blitter.\nThey do some busywork for you:\n\n- Manage background restoring after moving/removing the object,\n- Optimize blitter operations in contrast to more versatile `blitCopy...()` functions\n- Optimize memory usage for either minimal or extensive usage of bobs by using bg restore buffer or pristine buffer\n- Allow an easy switch of displayed frames for each bob\n\nThere are also some caveats:\n\n- Requires interleaved bitmaps for it to work\n- Double-buffering is recommended for any reasonable use\n- Resizing bobs requires some extra attention\n- Adding bob structs must be done outside the game loop, so in dynamic scenarios bob struct pooling might be required\n\n## Pristine Buffer Vs Undraw Buffer\n\nACE BOBs can work in two ways:\n\n- Undraw Buffer creates two bitmaps of size totalling to all of your initialized BOB dimensions - this scenario is most memory-efficient if you have a limited amount of BOBs, or a large main display buffer (e.g. Simple Buffer with large dimensions).\n- Pristine Buffer creates a third buffer for your display buffer, which is used to do the BOB undraw.\n  - This is a faster approach since it skips the background save phase\n  - It might be more memory-wasteful with small amount of BOBs\n  - On the other hand, it might be more efficient for large amount of BOBs.\n  - If you need to update your backgrounds/tiles, you are responsible for keeping the Pristine Buffer up to date.\n\nTo enable Pristine Buffer, be sure to build ACE with `ACE_BOB_PRISTINE_BUFFER` CMake switch enabled.\n\n## Setting Up Your Game for BOBs\n\n> [!NOTE]\n> For non-Tile Buffer games, disable `ACE_BOB_WRAP_Y` CMake switch for better performance.\n\nBefore using BOBs, you need to set up a proper display buffer.\nBOBs work best with interleaved and double-buffered simplebuffers:\n\n```c\n// Create a simple buffer viewport manager with double buffering and interleaved bitmap\ns_pVpManager = simpleBufferCreate(0,\n   TAG_SIMPLEBUFFER_BITMAP_FLAGS, BMF_CLEAR | BMF_INTERLEAVED,\n   TAG_SIMPLEBUFFER_IS_DBLBUF, 1,\n   // Add other tags as needed\nTAG_DONE);\n```\n\n> [!NOTE]\n> Make sure to export your bitmap resources as interleaved format.\n\nAt the end of each frame, you should process viewport managers and wait for vertical blank:\n\n```c\n// End of game loop\nviewProcessManagers(s_pView);\ncopProcessBlocks();\nvPortWaitForEnd(s_pVp);\n```\n\n## Using BOBs\n\nDefine some bob structs for later use.\nYou don't need to use them each frame, so you can define as much as you will need in peak scenarios.\n\n```c\nstatic tBob s_sBobPlayer;\nstatic tBob s_sBobEnemy;\n```\n\nIn gamestate create, initialize the bob structs, then reallocate buffers for them:\n\n```c\n// Create manager with your buffers\nbobManagerCreate(s_pVpManager->pFront, s_pVpManager->pBack, uwAvailHeight);\n\n// Initialize each BOB struct\nbobInit(\n   &s_sBobPlayer, uwWidth, uwHeight, 1,\n   bobCalcFrameAddress(s_pBmPlayerFrames, 0),\n   bobCalcFrameAddress(s_pBmPlayerMasks, 0),\n   uwX, uwY\n);\nbobInit(\n   &s_sBobEnemy, uwWidth, uwHeight, 1,\n   bobCalcFrameAddress(s_pBmEnemyFrames, 0),\n   bobCalcFrameAddress(s_pBmEnemyMasks, 0),\n   uwX, uwY\n);\n// ... initialize more BOBs as needed\n\n// Allocate draw queues and memory for background saving.\n// Must be called after all BOBs are initialized!\nbobReallocateBuffers();\n```\n\n> [!NOTE]\n> If you dare to use single buffering, passing same front/back pointers in `bobManagerCreate()` should work.\n\nIn gamestate loop, you need to:\n\n- trigger the undraw,\n- add bobs to draw queue,\n- ensure that all bobs are drawn\n\n```c\n// Begin the BOB drawing cycle - undraws previous BOBs\nbobBegin();\n\n// At this point, it's the best time to draw non-bob stuff, e.g. update background.\n\n// Update BOB positions.\n// You can safely modify the `sPos` field to update a BOB's position at any time.\n// Other fields, especially with underscore prefix, should only be changed\n// using the provided functions.\ns_sBobPlayer.sPos.uwX = newX;\ns_sBobPlayer.sPos.uwY = newY;\n\n// Add BOBs to drawing queue - this will trigger a blitter operation if blitter is idle\nbobPush(&s_sBobPlayer);\n// ... perform other calculations, e.g. weave-in game logic processing while the blitter is busy\nbobPush(&s_sBobEnemy);\n\n// Signal no more BOBs will be added this frame\nbobPushingDone();\n\n// Process remaining BOBs (draw them on the back buffer)\nbobEnd();\n```\n\n> [!CAUTION]\n> Don't ever do any blitter operations between first `bobPush()` and calling `bobEnd()` - it will destroy the blitter state expected by the bob system!\n\n> [!CAUTION]\n> Drawing anything after `bobEnd()` will likely cause it to be destroyed by the bob undraw.\n> It's best to draw your stuff between `bobBegin()` and first `bobPush()`.\n\n> [!NOTE]\n> If you do some `bobPush()` close to each other, your blits will be enqueued but they won't automatically trigger after the finishing of the previous one.\n> Instead, the next one will try to execute at the end of next `bobPush()` call.\n> To process the queue manually, you can weave in `bobProcessNext()` between your calculations.\n\nTo clean up the bob system, do folliwing in your gamestate destroy:\n\n```c\nbobManagerDestroy();\n```\n\n## Animating your BOBs\n\nBOB system expects bitmaps to use single-column bitmaps with frame animations one beneath the other.\nThe bitmap itself must be of same width as the BOB.\n\nUse `bobSetFrame()` to change the animation frame:\n\n```c\nbobSetFrame(\n   &s_sBobPlayer,\n   bobCalcFrameAddress(s_pBmPlayerFrames, ubFrameIndex * s_sBobPlayer.uwHeight),\n   bobCalcFrameAddress(s_pBmPlayerMasks, ubFrameIndex * s_sBobPlayer.uwHeight),\n);\n```\n\nTo speed things up, you should precalculate results of `bobCalcFrameAddress()` and e.g. store it in array indexed by animation frame index, or something.\n\n> [!NOTE]\n> Since pixel data and mask are stored separately, you can pass the solid color rectangle frame to your bob to make a common hit effect.\n\n## Resizing your BOBs\n\nTo resize the bobs, use `bobSetWidth()` and `bobSetHeight()` functions.\nBe sure to call them after `bobBegin()` in your current frame.\n\n> [!CAUTION]\n> When using Undraw Buffer mode, make sure that the bob wasn't drawn in frame preceding the resize, since it will trash the undraw operation.\n> If you need such feature, please report it in the issue on the ACE repository.\n>\n> This doesn't affect the BOBs with `isUndrawRequired` set to `0`.\n\n> [!CAUTION]\n> When resizing BOBs in Undraw Buffer mode, be sure not to exceed initial bob size used prior to `bobReallocateBuffers()` call.\n> Doing so will make the BOB system exceed the background restore buffers, and thus potentially corrupting your game's memory.\n>\n> This doesn't affect the BOBs with `isUndrawRequired` set to `0`.\n\n## Tile Buffer considerations\n\n- make sure that you're building ACE with `ACE_BOB_WRAP_Y` CMake switch enabled - otherwise, drawing bobs on buffers with large height won't work correctly!\n- If you want to \"teleport\" your camera and/or use `tileBufferRedrawAll()` at any time, you should call `bobDiscardUndraw()` to skip the undraw of your bobs from previous frame.\n- You can easily instruct the Tile Buffer to update the Pristine Buffer for you with a tile callback function:\n\n```c\nstatic void onTileDraw(\n   UNUSED_ARG UWORD uwTileX, UNUSED_ARG UWORD uwTileY,\n   tBitMap *pBitMap, UWORD uwBitMapX, UWORD uwBitMapY\n) {\n   blitCopyAligned(\n      pBitMap, uwBitMapX, uwBitMapY,\n      s_pPristineBuffer, uwBitMapX, uwBitMapY, TILE_SIZE, TILE_SIZE\n   );\n}\n\n// Initialize the Tile Buffer with following:\ng_pMainBuffer = tileBufferCreate(0,\n   TAG_TILEBUFFER_CALLBACK_TILE_DRAW, onTileDraw,\n   // ... other tags here\nTAG_END);\n```\n"
  },
  {
    "path": "docs/programming/view.md",
    "content": "# Views and viewports\n\nIf you did any Amiga development using graphics.library, you'll discover that\nACE builds on same basic concepts but implements it a bit differently.\n\n## Views\n\nEveryting on screen is contained by a single view. You create view using\n`viewCreate` function.\n\nYou can have multiple views, but only one can be displayed at once. To switch\nbetween views, use `viewLoad` function.\n\n## Viewports\n\nEach view consists of at least one viewport. Viewports are scrollable windows\ndisplaying associated bitmaps. Viewports may have different palettes, resolution\netc. For example, they can be used to split view into main game area and\nhorizontal HUD bar at top and/or bottom of screen.\n\nThe only limitation of viewports is that they have to be placed one beneath\nanother - they can't be located side by side or one over another. This is\nbecause of Amiga hardware - as data gets sent to display from left to right,\nfrom top to bottom, viewpors are implemented by changing data source,\nbut it takes so long that it usually needs whole horizontal blanking time\nbetween display lines.\n\n## Viewport managers\n\nA viewport alone doesn't display anything. It needs viewport managers to expand\nits features:\n\n- **Simple buffer manager** allocates display bitmap and allows for its\n  scrolling. Since it's simple, it works on plain bitmap, which results\n  in relatively large memory usage and prevents it from being used in games\n  with large scrollable backgrounds: shmup, beat 'em up, RTS, etc.\n- **Scroll buffer manager** allocates bitmap only a little larger than\n  viewport's dimensions. It wraps bitmap buffer vertically and reserves\n  additional buffer lines to facilitate long, but finite horizontal scrolls\n  efficiently. Since display bitmap is larger than viewport, it allows\n  off-screen drawing just before that portion gets displayed.\n- **Tile buffer manager** is derivative of scroll buffer manager. Apart from\n  facilitating large scrolls it manages drawing background for you using\n  tilemaps. This is what you'll most likely want to use.\n\n## AGA tags\n\nIf ACE is built with `ACE_USE_AGA_FEATURES=ON`, you can enable AGA behavior when creating a view or viewport.\n\n- `TAG_VIEW_USES_AGA, 1` on `viewCreate()`\n- `TAG_VPORT_USES_AGA, 1` on `vPortCreate()`\n- `TAG_VPORT_FMODE, <value>` on `vPortCreate()` if you want to set fetch mode\n\n`TAG_VPORT_BPP` still controls color depth (e.g. 8 means 256 colors).\n\n## Tutorial code\n\nNow let's expand `src/game.c` with basic view & viewport creation. There'll be\ntwo viewports: one for score, second one for proper playfield. We still won't\ndisplay anything on it but we'll get there next time.\n\nView and viewport creation uses tag syntax - it derives from native Amigan style\nof coding. The first arg is zero, then it's option-value pair, and then it ends\nwith `TAG_DONE` or `TAG_END`. You don't need to specify all tags, some are\ncompulsory. If you omit optional tag, it will result with view/viewport's\ndefault behavior. Be sure to check game.log for errors after running game -\nif you omitted something important you'll get an error along with game's crash.\nThe order of passed tags is irrelevant.\n\n``` c\n#include \"game.h\"\n#include <ace/managers/key.h> // Keyboard processing\n#include <ace/managers/game.h> // For using gameExit\n#include <ace/managers/system.h> // For systemUnuse and systemUse\n#include <ace/managers/viewport/simplebuffer.h> // Simple buffer\n\n// All variables outside fns are global - can be accessed in any fn\n// Static means here that given var is only for this file, hence 's_' prefix\n// You can have many variables with same name in different files and they'll be\n// independent as long as they're static\n// * means pointer, hence 'p' prefix\nstatic tView *s_pView; // View containing all the viewports\nstatic tVPort *s_pVpScore; // Viewport for score\nstatic tSimpleBufferManager *s_pScoreBuffer;\nstatic tVPort *s_pVpMain; // Viewport for playfield\nstatic tSimpleBufferManager *s_pMainBuffer;\n\nvoid gameGsCreate(void) {\n  // Create a view - first arg is always zero, then it's option-value\n  s_pView = viewCreate(0,\n    // Same color palette for all viewports, can be skipped as it's set\n    // by default to 1.\n    TAG_VIEW_GLOBAL_PALETTE, 1,\n  TAG_END); // Must always end with TAG_END or synonym: TAG_DONE\n\n  // Viewport for score bar - on top of screen\n  s_pVpScore = vPortCreate(0,\n    TAG_VPORT_VIEW, s_pView, // Required: specify parent view\n    TAG_VPORT_BPP, 4, // Optional: 4 bits per pixel, 16 colors\n    TAG_VPORT_HEIGHT, 32, // Optional: let's make it 32px high\n  TAG_END); // same syntax as view creation\n\n  // Create simple buffer manager with bitmap exactly as large as viewport\n  s_pScoreBuffer = simpleBufferCreate(0,\n    TAG_SIMPLEBUFFER_VPORT, s_pVpScore, // Required: parent viewport\n    // Optional: buffer bitmap creation flags\n    // we'll use them to initially clear the bitmap\n    TAG_SIMPLEBUFFER_BITMAP_FLAGS, BMF_CLEAR,\n  TAG_END);\n\n  // Now let's do the same for main playfield\n  s_pVpMain = vPortCreate(0,\n    TAG_VPORT_VIEW, s_pView,\n    TAG_VPORT_BPP, 4, // 4 bits per pixel, 16 colors\n    // We won't specify height here - viewport will take remaining space.\n  TAG_END);\n  s_pMainBuffer = simpleBufferCreate(0,\n    TAG_SIMPLEBUFFER_VPORT, s_pVpMain, // Required: parent viewport\n    TAG_SIMPLEBUFFER_BITMAP_FLAGS, BMF_CLEAR,\n  TAG_END);\n\n  // Since we've set up global palette, palette will be loaded from first viewport\n  // Colors are 0x0RGB, each channel accepts values from 0 to 15 (0 to F).\n  s_pVpScore->pPalette[0] = 0x0000; // First color is also border color\n  s_pVpScore->pPalette[1] = 0x0888; // Gray\n  s_pVpScore->pPalette[2] = 0x0800; // Red - not max, a bit dark\n  s_pVpScore->pPalette[3] = 0x0008; // Blue - same brightness as red\n\n  // We don't need anything from OS anymore\n  systemUnuse();\n\n  // Load the view\n  viewLoad(s_pView);\n}\n\nvoid gameGsLoop(void) {\n  // This will loop forever until you \"pop\" or change gamestate\n  // or close the game\n  if(keyCheck(KEY_ESCAPE)) {\n    gameExit();\n  }\n  else {\n    // Process loop normally\n    // We'll come back here later\n  }\n}\n\nvoid gameGsDestroy(void) {\n  // Cleanup when leaving this gamestate\n  systemUse();\n\n  // This will also destroy all associated viewports and viewport managers\n  viewDestroy(s_pView);\n}\n```\n"
  },
  {
    "path": "docs/tools/audio_conv.md",
    "content": "# Converting Audio for ACE\n\nBefore using sound effects in your game, you'll need to convert your audio files using the `audio_conv` tool.\nThe simplest usage is:\n\n```shell\naudio_conv explode.wav -o explode.sfx\n```\n\n> [!CAUTION]\n> `audio_conv` you should only use 8-bit signed/unsigned PCM files - although it can resample from 16-bit, it does so very naively and it will yield worse results than resampling indedicated audio software.\n\nAdditional options are as follows:\n\n- `-n` - Normalizes audio amplitude, making sure it uses full value range\n- `-d N` - Divide amplitude by N - useful for audio mixers\n- `-cd N` - Check that amplitude divided by N fits in range - useful for audio mixers\n- `-strict` - Treat warnings as errors (recommended)\n- `-fpt` - Enforce PTPlayer-friendly mode (adds empty first word if missing)\n- `-fpad N` - Force specific byte padding - useful for audio mixers\n\n## CMake Integration\n\nYou can automate audio conversion in your build process:\n\n```cmake\nconvertAudio(\n  TARGET your_target\n  SOURCE path/to/input.wav\n  DESTINATION path/to/output.sfx\n  PTPLAYER  # Enable PTPlayer-friendly mode\n  NORMALIZE # Normalize amplitude\n  STRICT    # Treat warnings as errors\n  PAD 2     # Ensure 16-bit alignment\n  # For audio mixers:\n  DIVIDE_AMPLITUDE 3 # Allows playback of up to 3 samples on same channel without audio glitches\n)\n```\n"
  },
  {
    "path": "docs/tools/bitmap_conv.md",
    "content": "# Bitmap conversion\n\nAfter you've got yourself a palette, you may want to use it to display some images. For this task there's a `bitmap_conv` command line tool. Currently it supports only PNG input files, but other formats will be supported some day.\n\nIf you ever get stuck, just type `bitmap_conv` and it will display detailed info about its switches and params.\n\n## `.bm` file format\n\n`.bm` files are ACE-specific and currently implemented as raw bitplane data preceeded by minimal header. It supports planar and interleaved encoding for loading times optimization, which also currently determines bitmap use mode in game - bitmap functions won't be able to load interleaved bitmap into portion of non-interleaved one, and vice versa.\n\nThe format was born since @tehKaiN was not happy with IFF - it seemed too bloated for him and required additional time to understand all of its features, which are rarily needed. If you need something more fancy than plain bitplane storage, you are strongly encouraged to go with IFF files by using `iffparse.library`.\n\n## How to...\n\nFirst argument is always `.plt` palette, second is source image. Then you can throw some additional switches. Input file doesn't have to be indexed, but needs to have only colors present in palette. Colors will be outputted with same indices as order of appearance in palette.\n\n### Convert plan bitmap\n\n- This will save image in current directory:\n\n  `bitmap_conv path/to/palette.plt path/to/image.png`\n\n- If you want to save image somewhere else, use `-o` (_output_):\n\n  `bitmap_conv path/to/palette.plt path/to/image.png -o path/to/output/file.bm`\n\n- If you want to save in interleaved mode, just throw `-i` (_interleaved_) somewhere:\n\n  `bitmap_conv path/to/palette.plt path/to/image.png -o path/to/output/file.bm -i`\n\n### Convert bitmap with transparency color\n\nTo define transparency mask, use in your image one more color than defined in palette, say `#f0f`. Then, during conversion add `-mc #ff00ff` (_mask color_) switch so that `bitmap_conv` will threat this color as transparency mask. Mask will be outputted to `.msk` file which currently is just raw bitplane with width/height header.\n\n- Simple conversion:\n\n  `bitmap_conv path/to/palette.plt path/to/image.png -o path/to/output/file.bm -mc #ff00ff`\n\n- Save mask somewhere else: `-mo` (_mask output_)\n\n  `bitmap_conv path/to/palette.plt path/to/image.png -o path/to/output/file.bm -mc #ff00ff -mo path/to/mask/file.msk`\n"
  },
  {
    "path": "docs/tools/font_conv.md",
    "content": "# Converting Fonts for ACE\n\nThe `font_conv` tool allows you to convert common font files to ACE's custom `.fnt` file format.\n\nTo convert .ttf file to output.fnt file, with given glyph set, do the following:\n\n```shell\nfont_conv input.ttf fnt -out output.fnt -size 8 -chars \"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz\"\n```\n\nThe second parameter specifies the file format of the output.\nAt the time of writing, the `font_conv` tool supports following formats:\n\n- ttf - TrueType Fonts (.ttf)\n- dir - Directory with separate PNG glyphs\n- png - Single PNG file with whole font\n- fnt - ACE .fnt file\n- pmng - PNG fonts from ProMotion NG\n\nUnless otherwise stated, you are free to convert between any of them.\n\n> [!NOTE]\n> It is not recommended to convert from TTF directly to .fnt as automatic rasterization and determining margins might need some manual cleanup.\n\nExtra options are:\n\n- `-chars` - Specifies characters to include in the font\n- `-charFile` - Use characters from a text file\n- `-size` - Set font size for rasterization (for TTF fonts)\n- `-out` - Specify output path\n- `-fc` - Set first character index (for ProMotion NG fonts)\n\n## CMake Integration\n\nYou can automate font conversion in your build process using the `convertFont` function in your CMakeLists.txt file:\n\n```cmake\nconvertFont(\n  TARGET your_target\n  SOURCE path/to/source_font.ttf\n  DESTINATION path/to/output.fnt\n  FIRST_CHAR 33 # Equivalent to -fc param\n)\n```\n\nThe `convertFont` function will automatically convert the font during the build process and add the resulting file as a dependency to your target.\n"
  },
  {
    "path": "docs/tools/palette_conv.md",
    "content": "# Palette Conversion Tool\n\nThe palette_conv tool allows you to convert between various palette formats for use with the ACE engine.\n\n## Supported Palette Formats\n\nAt the time of writing, The `palette_conv` tool supports following formats:\n\n- `.plt` - ACE's native palette format (binary; **v2** by default — see below)\n- `.gpl` - GIMP Palette format (text) - full spec can be found at https://developer.gimp.org/core/standards/gpl/\n- `.act` - Adobe Color Table format\n- `.pal` - ProMotion NG palette format\n- `.png` - Image preview of the palette - supported only as output format\n\n### `.plt` v2 layout (default when writing `.plt`)\n\nThe first byte selects encoding; the next two bytes are a **big-endian** 16-bit color count; then the color records.\n\n| First byte | Meaning | Record size |\n|------------|---------|-------------|\n| `0` | ECS/OCS packed 12-bit | 2 bytes per color |\n| `1` | AGA (`0`, R, G, B per entry) | 4 bytes per color |\n\nOlder **v1** `.plt` files (first byte **≥ 2**) are not supported; reconvert sources with `palette_conv`.\n\n### Extracting .gpl palette from from Aseprite\n\nYou might have to apply addon [Aseprite Script: Amiga OCS/ECS Color Palette Mixer](https://prismaticrealms.itch.io/aseprite-script-amiga-ocsecs-color-palette-mixer) to align png and palette to amiga capacity/rgb colors.\n\nYou need to add an addon just process to this installation : https://github.com/behreajj/AsepriteAddons/\n\nThen go to `File > Script > dialogs > palette > gplExport` and put your `.tpl` into your `res` folder.\n\nNOTE: in asesprite you can also save directely in `.act` format.\n\n### Extracting .gpl palette from from GIMP\n\n_To be completed_\n\n## Command Line Usage\n\nTo convert palette.gpl to palette.plt, use following command:\n\n```shell\npalette_conv palette.gpl palette.plt\n```\n\nIf no output path is provided, it defaults to converting to `.gpl` format with same file name.\n\nWhen writing `.plt`, optional flags:\n\n| Flag | Effect |\n|------|--------|\n| _(none)_ | **v2 ECS/OCS** — sentinel `0`, big-endian count, packed 12-bit colors (input must be valid OCS 12-bit unless `-cc`) |\n| `--aga` | **v2 AGA** — sentinel `1`, 4 bytes per color (`0`, R, G, B) |\n| `--ocs` | Same as default (explicit ECS/OCS v2) |\n| `-cc` | With ECS/OCS output only: **truncate** 8-bit RGB inputs to 12-bit OCS precision (optional escape hatch; default is strict validation so bad colors surface here, not in `bitmap_conv`) |\n\nExamples:\n\n```shell\npalette_conv palette.gpl palette.plt\npalette_conv palette.gpl palette_aga.plt --aga\npalette_conv palette.gpl palette.plt -cc\n```\n\n> [!NOTE]\n> You can also generate an image with palette preview using `palette_conv palette.gpl preview.png`\n\n## Color Considerations\n\nACE is primarily designed for the Amiga OCS/ECS hardware, which uses 12-bit color (4 bits per RGB channel).\n\nWhen converting to ACE's native `.plt` format by default (**ECS/OCS v2**), the tool validates that colors are compatible with OCS limitations, throwing errors when that's not the case—unless you pass **`-cc`**, which quantizes channels to 12-bit instead.\n\nUse **`--aga`** for **AGA v2** `.plt` (full 8-bit RGB channels per color).\n\nWhen creating artwork for your game, you have to:\n\n- Use colors that work within Amiga's 12-bit color limitations (4 bits per channel), e.g. hex code `#112233` but not `#123456` (when targeting ECS/OCS output)\n- Limit your palette to the number of colors supported by your chosen bit depth\n\n## CMake Integration\n\nYou can automate palette conversion in your build process using the `convertPalette` function in your CMakeLists.txt file:\n\n```cmake\nconvertPalette(\n  ${TARGET_NAME}          # Your target binary\n  ${RES_DIR}/palette.gpl  # Source palette file\n  ${DATA_DIR}/palette.plt # Destination palette file\n)\n```\n\nThis will automatically convert the palette during the build process and add the resulting file as a dependency to your target.\n"
  },
  {
    "path": "include/ace/generic/main.h",
    "content": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at http://mozilla.org/MPL/2.0/. */\n\n#ifndef _ACE_GENERIC_MAIN_H_\n#define _ACE_GENERIC_MAIN_H_\n\n/**\n * @file main.h\n * @brief Implements generic way of starting ACE project, allowing to avoid\n * excess boilerplate.\n *\n * This module is based around Arduino's setup/loop idiom: the idea is to have\n * unified way of setting up stuff that almost every project will use,\n * and moving management of everything else to dedicated callbacks.\n *\n * You can always skip including this file if you prefer to have custom main()\n * and program flow.\n */\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n#include <stdlib.h>\n#include <ace/types.h>\n#include <ace/managers/system.h>\n#include <ace/managers/memory.h>\n#include <ace/managers/log.h>\n#include <ace/managers/timer.h>\n#include <ace/managers/blit.h>\n#include <ace/managers/copper.h>\n#include <ace/managers/game.h>\n\n#ifndef GENERIC_MAIN_LOG_PATH\n#define GENERIC_MAIN_LOG_PATH 0\n#endif\n\n//--------------------------------------------------------- USER FUNCTIONS BEGIN\n// Those functions must be defined by the user in some other file (e.g. main.c)!\n\n/**\n * @brief User initialization code.\n *\n * This is called once ACE is mostly set up, before calling genericProcess.\n * Use it to initialize additional ACE modules or set up your game.\n *\n * @see genericProcess()\n * @see genericDestroy()\n */\nvoid genericCreate(void);\n\n/**\n * @brief Main loop code.\n *\n * This is called while GENERIC_MAIN_LOOP_CONDITION is true.\n * Use it to process things every frame, e.g. current game state,\n * or additional ACE modules.\n *\n * @see genericCreate()\n * @see genericDestroy()\n */\nvoid genericProcess(void);\n\n/**\n * @brief User deinitialization code.\n *\n * This is called once GENERIC_MAIN_LOOP_CONDITION returns false.\n * After executing this function, app will deinitialize and return to OS.\n * Use it to clean up after things you've set up in genericCreate.\n *\n * @see genericCreate()\n * @see genericProcess()\n */\nvoid genericDestroy(void);\n\n//----------------------------------------------------------- USER FUNCTIONS END\n\n// You can define this macro before including this file to change app's\n// loop condition\n#ifndef GENERIC_MAIN_LOOP_CONDITION\n#define GENERIC_MAIN_LOOP_CONDITION gameIsRunning()\n#endif\n\n//-------------------------------------------------------- STACK SMASH DETECTION\n#if defined(__GNUC__)\n#include <stdint.h>\n\n#if UINT32_MAX == UINTPTR_MAX\n#define STACK_CHK_GUARD 0xe2dee396\n#else\n#define STACK_CHK_GUARD 0x595e9fbd94fda766\n#endif\n\nuintptr_t __stack_chk_guard = STACK_CHK_GUARD;\n\n__attribute__((noreturn))\nvoid __stack_chk_fail(void) {\n\tlogWrite(\"ERR: STACK SMASHED\\n\");\n\twhile(1) continue;\n}\n#endif\n\n//-------------------------------------------------------- GENERIC MAIN FUNCTION\n\nint main(void) {\n\tsystemCreate();\n\tlogOpen(GENERIC_MAIN_LOG_PATH);\n\tmemCreate();\n#if !defined(GENERIC_MAIN_NO_TIMER)\n\ttimerCreate();\n#endif\n\n\tblitManagerCreate();\n\tcopCreate();\n\n\t// Call user callbacks:\n\tgenericCreate();\n\twhile (GENERIC_MAIN_LOOP_CONDITION) {\n#if !defined(GENERIC_MAIN_NO_TIMER)\n\t\ttimerProcess();\n#endif\n\t\tgenericProcess();\n\t}\n\tgenericDestroy();\n\n\tcopDestroy();\n\tblitManagerDestroy();\n\n#if !defined(GENERIC_MAIN_NO_TIMER)\n\ttimerDestroy();\n#endif\n\tmemDestroy();\n\tlogClose();\n\tsystemDestroy();\n\n\treturn EXIT_SUCCESS;\n}\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif\n"
  },
  {
    "path": "include/ace/generic/screen.h",
    "content": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at http://mozilla.org/MPL/2.0/. */\n\n#ifndef _ACE_GENERIC_SCREEN_H_\n#define _ACE_GENERIC_SCREEN_H_\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n#include <ace/types.h>\n\n#define SCREEN_XOFFSET 0x81\n\n#define SCREEN_PAL_YOFFSET 0x2C\n#define SCREEN_PAL_WIDTH 320\n#define SCREEN_PAL_HEIGHT 256\n#define SCREEN_PAL_HIRES_WIDTH 640\n#define SCREEN_PAL_LACED_HEIGHT 512\n\n#define SCREEN_NTSC_YOFFSET 0x22\n#define SCREEN_NTSC_WIDTH 320\n#define SCREEN_NTSC_HEIGHT 200\n#define SCREEN_NTSC_HIRES_WIDTH 640\n#define SCREEN_HTSC_LACED_HEIGHT 400\n\n\n// For EHB screens to work properly, Copper has to wait for the line before\n// the actual display starts and change the regs in horizontal blanking.\n// Positions 0xD0, 0xD8, 0xE0 work, but 0xE2 doesn't - use the last valid copper\n// wait pos so that the regs are ready just before the display.\n//\n// User stuff must go prior this wait pos, so it's nice to give explicit wiggle\n// room.\n//\n// What follows is just how we arrived at those values:\n// 0xE0 didn't work for KaiN in simplebuffer - 0xDC up to BPP 5 seems to\n// work fine for everyone so far.\n//\n// For EHB (6 bitplanes) the wait pos is 0xD9, because that was the last that\n// worked in simplebuffer for timfel.\n//\n// Vairn reports that AGA modes need a smaller value than EHB, and that 7bpp\n// should use 0xC6, 8bpp 0xA0.\n//\n// TODO: some ppl might want to have the display set up as soon as possible\n// (probably could be done earlier than 0xD0) and then e.g. start changing\n// palette colors before display + right after bitplanes get displayed.\n// Maybe add the switch for this behavior?\n// TODO: Add a calculation on proper wait pos (less BPP - later).\n// TODO: Test and find the most optional values.\n// TODO: Figure out if this is more related to fetchmodes for AGA.\nstatic const UWORD s_pCopperWaitXByBitplanes[9] = {0x00, 0xDC, 0xDC, 0xDC, 0xDC, 0xDC, 0xD9, 0xC6, 0xA0};\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif // _ACE_GENERIC_SCREEN_H_\n"
  },
  {
    "path": "include/ace/macros.h",
    "content": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at http://mozilla.org/MPL/2.0/. */\n\n#ifndef _ACE_MACROS_H_\n#define _ACE_MACROS_H_\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n#include <ace/types.h>\n\n/**\n * ACE Macros\n * General purpose macros used throughout all code\n * Insert all somewhat universal macros here even if used only by single module\n * so future expansion will keep macro dependencies at bay\n */\n\n/**\n * Block count - determine how many blocks of given size are in given length\n * blockCountFloor - counts only full blocks\n * blockCountCeil - counts also non-filled block\n */\n#define blockCountFloor(length, blockSize) (length/blockSize)\n#define blockCountCeil(length, blockSize) ((length + blockSize-1)/blockSize)\n\n// Rotate fns - should be optimized away by compiler to single instruction\n// Based on https://stackoverflow.com/questions/776508/best-practices-for-circular-shift-rotate-operations-in-c\n\nstatic inline UWORD rol16(UWORD uwIn, UBYTE ubRot) {\n  const UWORD uwMask = ((sizeof(uwIn)<<3) - 1);\n  ubRot &= uwMask;\n  return (uwIn << ubRot) | (uwIn >> ((-ubRot) & uwMask));\n}\n\nstatic inline UWORD ror16(UWORD uwIn, UBYTE ubRot) {\n  const UWORD uwMask = ((sizeof(uwIn)<<3) - 1);\n  ubRot &= uwMask;\n  return (uwIn >> ubRot) | (uwIn << ((-ubRot) & uwMask));\n}\n\nstatic inline ULONG rol32(ULONG ulIn, UBYTE ubRot) {\n  const ULONG ulMask = ((sizeof(ulIn)<<3) - 1);\n  ubRot &= ulMask;\n  return (ulIn << ubRot) | (ulIn >> ((-ubRot) & ulMask));\n}\n\nstatic inline ULONG ror32(ULONG ulIn, UBYTE ubRot) {\n  const ULONG ulMask = ((sizeof(ulIn)<<3) - 1);\n  ubRot &= ulMask;\n  return (ulIn >> ubRot) | (ulIn << ((-ubRot) & ulMask));\n}\n\n/**\n * @brief Swaps contents of two vars.\n */\n#define SWAP(a, b) do {typeof(a) tmp; tmp = a; a = b; b = tmp;} while(0)\n\n// Math\n#define ABS(x) ((x)<0 ? -(x) : (x))\n#define SGN(x) ((x) > 0 ? 1 : ((x) < 0 ? -1 : 0))\n// #define SGN(x) ((x > 0) - (x < 0)) // Branchless, subtracting is slower?\n#define MIN(x,y) ((x)<(y)? (x): (y))\n#define MAX(x,y) ((x)>(y)? (x): (y))\n#define CLAMP(x, min, max) ((x) < (min)? (min) : ((x) > (max) ? (max) : (x)))\n#define CEIL_TO_FACTOR(x, m) ((((x) + (m) - 1) / (m)) * (m))\n#define FLOOR_TO_FACTOR(x, m) (((x) / (m)) * (m))\n#define ROUND_TO_FACTOR(x, m) ((((x) + (x) / 2) / (m)) * (m))\n#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))\n\n/**\n * Bit value macro - useful for setting & testing bits.\n */\n#define BV(x) (1 << (x))\n#define BTST(x, b) (((x) & BV(b)) != 0)\n\n/**\n *  Checks if given x,y is in specified tRect.\n */\n#define inRect(x, y, r) (                     \\\n\t(x) >= r.uwX && (x) <= r.uwX + r.uwWidth && \\\n\t(y) >= r.uwY && (y) <= r.uwY+r.uwHeight     \\\n)\n\n#define inAbsRect(x, y, ar) (          \\\n\t(x) >= ar.uwX1 && (x) <= ar.uwX2  && \\\n\t(y) >= ar.uwY1 && (y) <= ar.uwY2     \\\n)\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif // _ACE_MACROS_H_\n"
  },
  {
    "path": "include/ace/managers/advancedsprite.h",
    "content": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at http://mozilla.org/MPL/2.0/. */\n\n#ifndef _ACE_MANAGERS_ADVANCED_SPRITE_H_\n#define _ACE_MANAGERS_ADVANCED_SPRITE_H_\n\n/**\n * @file sprite.h\n * @brief The advanced sprite manager which rely on the basic sprite manager.\n *\n * @todo Multiplexed sprites\n */\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n#include <ace/utils/bitmap.h>\n#include <ace/utils/extview.h>\n#include <ace/managers/sprite.h>\n\ntypedef struct tAdvancedSprite {\n    tSprite **pSprites;\n    UBYTE ubSpriteCount;\n    WORD wX; ///< X position, measured from the left of the view.\n    WORD wY; ///< Y position, measured from the top of the view.\n    tBitMap **pAnimBitmap;\n    UWORD uwAnimFrame; \n    UWORD uwAnimCount;\n    UWORD uwHeight;\n    UBYTE ubByteWidth;\n    UBYTE uwWidth;\n    UBYTE ubChannelIndex;\n    UBYTE isEnabled;\n    UBYTE isHeaderToBeUpdated;\n    UBYTE is4PP; // 16-color sprites only.\n} tAdvancedSprite;\n\n/**\n * @brief Add sprite on selected hardware channel.\n * Currently, only single sprite per channel is supported.\n *\n * @note This function may temporarily re-enable OS.\n *\n * @param ubChannelIndex Index of the channel. 0 is the first channel.\n * @param pBitmap Bitmap to be used to display sprite. See spriteSetBitMap()'s\n * documentation for relevant constraints.\n * @param pSpriteVerticalStripBitmap Bitmap vertical strip to be used to display sprite and it's animation. Bitmap width is the target sprite width (16px or 32px).\n * @param uwSpriteHeight Height of the sprite.\n * @return Newly created advanced sprite struct on success, 0 on failure.\n *\n * @see advancedSpriteRemove()\n */\ntAdvancedSprite *advancedSpriteAdd(UBYTE ubChannelIndex, UWORD uwSpriteHeight,tBitMap *pSpriteVerticalStripBitmap1, tBitMap *pSpriteVerticalStripBitmap2 );\n\n/**\n * @brief Removes given sprite from the display and destroys its struct.\n *\n * @note This function may temporarily re-enable OS.\n *\n * @param tAdvancedSprite Advanced Sprite to be destroyed.\n * @see advancedSpriteAdd()\n */\nvoid advancedSpriteRemove(tAdvancedSprite *tAdvancedSprite);\n\n/**\n * @brief Set Anim/content of sprite to display.\n *\n * @param pAdvancedSprite Sprite to be enabled.\n * @param animIndex Animation index from the sprite vertical strip bitmap.\n */\nvoid advancedSpriteSetFrame(tAdvancedSprite *pAdvancedSprite, UWORD animFrame);\n\n/**\n * @brief Enables or disables a given sprite.\n *\n * @param pAdvancedSprite Sprite to be enabled.\n * @param isEnabled Set to 1 to enable sprite, otherwise set to 0.\n */\nvoid advancedSpriteSetEnabled(tAdvancedSprite *pAdvancedSprite, UBYTE isEnabled);\n\n/**\n * @brief Set Position of the sprite.\n *\n * @param pAdvancedSprite Sprite to be enabled.\n * @param wX X position, measured from the left of the view.\n * @param wY Y position, measured from the top of the view.\n */\nvoid advancedSpriteSetPos(tAdvancedSprite *pAdvancedSprite,WORD wX, WORD wY);\n\n/**\n * @brief Set Position of the sprite.\n *\n * @param pAdvancedSprite Sprite to be enabled.\n * @param wX X position, measured from the left of the view.\n */\nvoid advancedSpriteSetPosX(tAdvancedSprite *pAdvancedSprite,WORD wX);\n\n/**\n * @brief Set Position of the sprite. \n *\n * @param pAdvancedSprite Sprite to be enabled.\n * @param wY Y position, measured from the top of the view.\n */\nvoid advancedSpriteSetPosY(tAdvancedSprite *pAdvancedSprite, WORD wY);\n\n/**\n * @brief Updates the sprite's metadata if set as requiring update.\n * Be sure to call it at least whenever sprite's metadata needs updating.\n *\n * @param pAdvancedSprite Sprite of which screen position is to be updated.\n *\n * @see advancedSpriteProcessChannel()\n */\nvoid advancedSpriteProcess(tAdvancedSprite *pAdvancedSprite);\n\n/**\n * @brief Updates the given sprite channel.\n * Be sure to call it whenever the first sprite in channel have changed\n * and/or was enabled/disabled.\n *\n * @param ubChannelIndex\n *\n * @see advancedSpriteProcess()\n */\nvoid advancedSpriteProcessChannel(tAdvancedSprite *pAdvancedSprite);\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif // _ACE_MANAGERS_SPRITE_H_\n"
  },
  {
    "path": "include/ace/managers/blit.h",
    "content": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at http://mozilla.org/MPL/2.0/. */\n\n#ifndef _ACE_MANAGERS_BLIT_H_\n#define _ACE_MANAGERS_BLIT_H_\n\n/**\n * @file \"blit.h\"\n * @brief The blitter manager. Provides the basic abstraction layer for common\n * blitter operations.\n *\n * @note Earlier versions of blitter manager implemented blit queues driven\n * by blitter interrupt. However, it yielded worse performance than manual\n * blitting and was removed.\n *\n * @todo Some convenience for async blitting - state machine?\n */\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n#ifdef AMIGA\n#include <exec/interrupts.h>  // struct Interrupt\n#include <hardware/dmabits.h> // DMAF_BLITTER\n#include <hardware/intbits.h> // INTB_BLIT\n#endif // AMIGA\n\n#include <ace/types.h>\n#include <ace/managers/log.h>\n#include <ace/managers/memory.h>\n#include <ace/utils/custom.h>\n#include <ace/utils/bitmap.h>\n\n// BltCon0 channel enable bits\n#define USEA 0x800\n#define USEB 0x400\n#define USEC 0x200\n#define USED 0x100\n\n// Minterm presets - OR unfriendly!\n#define MINTERM_A 0xF0\n#define MINTERM_B 0xCC\n#define MINTERM_C 0xAA\n#define MINTERM_A_OR_C 0xFA\n#define MINTERM_NA_AND_C 0x0A\n#define MINTERM_COOKIE 0xCA\n#define MINTERM_REVERSE_COOKIE 0xAC\n#define MINTERM_COPY 0xC0\n\ntypedef enum tBlitLineMode {\n\tBLIT_LINE_MODE_OR = ((ABC | ABNC | NABC | NANBC) | (SRCA | SRCC | DEST)),\n\tBLIT_LINE_MODE_XOR = ((ABNC | NABC | NANBC) | (SRCA | SRCC | DEST)),\n\tBLIT_LINE_MODE_ERASE = ((NABC | NANBC | ANBC) | (SRCA | SRCC | DEST)),\n} tBlitLineMode;\n\n/**\n * @brief Creates and initializes the blitter manager.\n *\n * Call this function before you use any other blitter-related one.\n */\nvoid blitManagerCreate(void);\n\n/**\n * @brief Cleans up and destroys the blitter manager.\n *\n * Call this function after you have finished using the blitter, e.g. when game\n * closes.\n */\nvoid blitManagerDestroy(void);\n\n/**\n * @brief Checks if blitter is idle.\n *\n * Polls 2 times, taking A1000 Agnus bug workaround into account.\n *\n * @return 1 if blitter is idle, otherwise 0.\n *\n * @see blitWait()\n */\nUBYTE blitIsIdle(void);\n\n/**\n * @brief Waits until blitter finishes its work.\n *\n * Polls at least 2 times, taking A1000 Agnus bug workaround into account.\n *\n * @todo Investigate if autosetting BLITHOG inside it is beneficial.\n *\n * @see blitIsIdle()\n */\nvoid blitWait(void);\n\n/**\n * @brief Performs the rectangular copy between two bitmap regions,\n * without any safety checks.\n *\n * @note The data regions should not overlap.\n *\n * @param pSrc Source bitmap.\n * @param wSrcX Source rectangle top-left position's X-coordinate.\n * @param wSrcY Source rectangle top-left position's Y-coordinate.\n * @param pDst Destination bitmap. Can be same as pSrc.\n * @param wDstX Destination rectangle top-left position's X-coordinate.\n * @param wDstY Destination rectangle top-left position's Y-coordinate.\n * @param wWidth Rectangle width.\n * @param wHeight Rectangle height.\n * @param ubMinterm Minterm to be used for blitter operation, usually MINTERM_COOKIE.\n * @return Always 1.\n *\n * @see blitCopyAligned()\n * @see blitSafeCopy()\n * @see blitCopy()\n */\nUBYTE blitUnsafeCopy(\n\tconst tBitMap *pSrc, WORD wSrcX, WORD wSrcY,\n\ttBitMap *pDst, WORD wDstX, WORD wDstY,\n\tWORD wWidth, WORD wHeight, UBYTE ubMinterm\n);\n\n/**\n * @brief Performs the safe version of the rectangular copy between two bitmap\n * regions.\n *\n * The safety comes from extra blitCheck() call within.\n *\n * @note This function is slower than blitUnsafeCopy() - it is recommended\n * to use blitCopy() for extra checks only when compiling in ACE_DEBUG mode.\n *\n * @param pSrc Source bitmap.\n * @param wSrcX Source rectangle top-left position's X-coordinate.\n * @param wSrcY Source rectangle top-left position's Y-coordinate.\n * @param pDst Destination bitmap. Can be same as pSrc.\n * @param wDstX Destination rectangle top-left position's X-coordinate.\n * @param wDstY Destination rectangle top-left position's Y-coordinate.\n * @param wWidth Rectangle width.\n * @param wHeight Rectangle height.\n * @param ubMinterm Minterm to be used for blitter operation, usually MINTERM_COOKIE.\n * @param uwLine Source code line for error message. Use blitCopy() for auto-fill.\n * @param szFile Source code file for error message. Use blitCopy() for auto-fill.\n * @return 1 if blit was successful, otherwise 0.\n *\n * @see blitCopyAligned()\n * @see blitUnsafeCopy()\n * @see blitCopy()\n * @see blitCheck()\n */\nUBYTE blitSafeCopy(\n\tconst tBitMap *pSrc, WORD wSrcX, WORD wSrcY,\n\ttBitMap *pDst, WORD wDstX, WORD wDstY,\n\tWORD wWidth, WORD wHeight, UBYTE ubMinterm,\n\tUWORD uwLine, const char *szFile\n);\n\n/**\n * @brief Performs the optimized rectangular copy between two bitmap regions,\n * without any safety checks.\n *\n * @note This function requires that X-coordinates of copy regions as well\n * as width are multiples of 16. If you need more generic blit, use blitCopy()\n * instead.\n *\n * @param pSrc Source bitmap.\n * @param wSrcX Source rectangle top-left position's X-coordinate.\n * @param wSrcY Source rectangle top-left position's Y-coordinate.\n * @param pDst Destination bitmap. Can be same as pSrc.\n * @param wDstX Destination rectangle top-left position's X-coordinate.\n * @param wDstY Destination rectangle top-left position's Y-coordinate.\n * @param wWidth Rectangle width.\n * @param wHeight Rectangle height.\n * @return Always 1.\n *\n * @see blitSafeCopyAligned()\n * @see blitCopyAligned()\n * @see blitCopy()\n */\nUBYTE blitUnsafeCopyAligned(\n\tconst tBitMap *pSrc, WORD wSrcX, WORD wSrcY,\n\ttBitMap *pDst, WORD wDstX, WORD wDstY,\n\tWORD wWidth, WORD wHeight\n);\n\n/**\n * @brief Performs the safe version of optimized rectangular copy between\n * two bitmap regions.\n *\n * @note This function requires that X-coordinates of copy regions as well\n * as width are multiples of 16. If you need more generic blit, use blitCopy()\n * instead.\n *\n * The safety comes from extra blitCheck() call within.\n *\n * @note This function is slower than blitUnsafeCopyAligned() - it is recommended\n * to use blitCopyAligned() for extra checks only when compiling in ACE_DEBUG mode.\n *\n * @param pSrc Source bitmap.\n * @param wSrcX Source rectangle top-left position's X-coordinate.\n * @param wSrcY Source rectangle top-left position's Y-coordinate.\n * @param pDst Destination bitmap. Can be same as pSrc.\n * @param wDstX Destination rectangle top-left position's X-coordinate.\n * @param wDstY Destination rectangle top-left position's Y-coordinate.\n * @param wWidth Rectangle width.\n * @param wHeight Rectangle height.\n * @param uwLine Source code line for error message. Use blitCopyAligned() for auto-fill.\n * @param szFile Source code file for error message. Use blitCopyAligned() for auto-fill.\n * @return 1 if blit was successful, otherwise 0.\n *\n * @see blitUnsafeCopyAligned()\n * @see blitCopyAligned()\n * @see blitCopy()\n */\nUBYTE blitSafeCopyAligned(\n\tconst tBitMap *pSrc, WORD wSrcX, WORD wSrcY,\n\ttBitMap *pDst, WORD wDstX, WORD wDstY,\n\tWORD wWidth, WORD wHeight,\n\tUWORD uwLine, const char *szFile\n);\n\n/**\n * @brief Performs the rectangular copy between two bitmap regions using\n * the mask data.\n *\n * @note For regular bitmaps, mask data represents an alpha channel for single\n * bitplane of pSrc.\n * For interleaved blits, the mask must also have the interleaved format,\n * repeating its data for each line of each bitplane.\n *\n * @param pSrc Source bitmap.\n * @param wSrcX Source rectangle top-left position's X-coordinate.\n * @param wSrcY Source rectangle top-left position's Y-coordinate.\n * @param pDst Destination bitmap. Can be same as pSrc.\n * @param wDstX Destination rectangle top-left position's X-coordinate.\n * @param wDstY Destination rectangle top-left position's Y-coordinate.\n * @param wWidth Rectangle width.\n * @param wHeight Rectangle height.\n * @param pMsk Raw mask bitplane data.\n * @return Always 1.\n *\n * @see blitSafeCopyMask()\n * @see blitCopyMask()\n */\nUBYTE blitUnsafeCopyMask(\n\tconst tBitMap *pSrc, WORD wSrcX, WORD wSrcY,\n\ttBitMap *pDst, WORD wDstX, WORD wDstY,\n\tWORD wWidth, WORD wHeight, const UBYTE *pMsk\n);\n\n/**\n * @brief Performs the safe version of rectangular copy between two bitmap\n * regions using the mask data.\n *\n * The safety comes from extra blitCheck() call within.\n *\n * @note This function is slower than blitUnsafeCopyMask() - it is recommended\n * to use blitCopyMask() for extra checks only when compiling in ACE_DEBUG mode.\n *\n * @note For regular bitmaps, mask data represents an alpha channel for single\n * bitplane of pSrc.\n * For interleaved blits, the mask must also have the interleaved format,\n * repeating its data for each line of each bitplane.\n *\n * @param pSrc Source bitmap.\n * @param wSrcX Source rectangle top-left position's X-coordinate.\n * @param wSrcY Source rectangle top-left position's Y-coordinate.\n * @param pDst Destination bitmap. Can be same as pSrc.\n * @param wDstX Destination rectangle top-left position's X-coordinate.\n * @param wDstY Destination rectangle top-left position's Y-coordinate.\n * @param wWidth Rectangle width.\n * @param wHeight Rectangle height.\n * @param pMsk Raw mask bitplane data.\n * @param uwLine Source code line for error message. Use blitCopyMask() for auto-fill.\n * @param szFile Source code file for error message. Use blitCopyMask() for auto-fill.\n * @return 1 if blit was successful, otherwise 0.\n *\n * @see blitUnsafeCopyMask()\n * @see blitCopyMask()\n */\nUBYTE blitSafeCopyMask(\n\tconst tBitMap *pSrc, WORD wSrcX, WORD wSrcY,\n\ttBitMap *pDst, WORD wDstX, WORD wDstY,\n\tWORD wWidth, WORD wHeight, const UBYTE *pMsk,\n\tUWORD uwLine, const char *szFile\n);\n\n/**\n * @brief Performs the rectangular fill with selected color.\n *\n * The blit is configured bitplane-by-bitplane as follows:\n * - A: rectangle mask, memory read disabled\n * - C: destination read\n * - D: destination write\n *\n * @note This can't be used for large blits - OCS blitter limits apply.\n * Maximum blit size is 1024x1024 pixels. For interleaved bitmaps, divide\n * max height by bitmap's depth.\n *\n * @param pDst Destination bitmap.\n * @param wDstX Destination rectangle top-left position's X-coordinate.\n * @param wDstY Destination rectangle top-left position's Y-coordinate.\n * @param wWidth Rectangle width.\n * @param wHeight Rectangle height.\n * @param ubColor Target color index.\n * @return Always 1.\n *\n * @see blitSafeRect()\n * @see blitRect()\n */\nUBYTE blitUnsafeRect(\n\ttBitMap *pDst, WORD wDstX, WORD wDstY, WORD wWidth, WORD wHeight,\n\tUBYTE ubColor\n);\n\n/**\n * @brief Performs the safe version of rectangular fill with selected color.\n *\n * The blit is configured bitplane-by-bitplane as follows:\n * - A: rectangle mask, memory read disabled\n * - C: destination read\n * - D: destination write\n *\n * The safety comes from extra blitCheck() call within.\n *\n * @note This function is slower than blitUnsafeRect() - it is recommended\n * to use blitRect() for extra checks only when compiling in ACE_DEBUG mode.\n *\n * @note This can't be used for large blits - OCS blitter limits apply.\n * Maximum blit size is 1024x1024 pixels. For interleaved bitmaps, divide\n * max height by bitmap's depth.\n *\n * @param pDst Destination bitmap.\n * @param wDstX Destination rectangle top-left position's X-coordinate.\n * @param wDstY Destination rectangle top-left position's Y-coordinate.\n * @param wWidth Rectangle width.\n * @param wHeight Rectangle height.\n * @param ubColor Target color index.\n * @param uwLine Source code line for error message. Use blitRect() for auto-fill.\n * @param szFile Source code file for error message. Use blitRect() for auto-fill.\n * @return 1 if blit was successful, otherwise 0.\n *\n * @see blitUnsafeRect()\n * @see blitRect()\n */\nUBYTE blitSafeRect(\n\ttBitMap *pDst, WORD wDstX, WORD wDstY, WORD wWidth, WORD wHeight,\n\tUBYTE ubColor, UWORD uwLine, const char *szFile\n);\n\n/**\n * @brief Performs the shape fill on a single bitplane inside given rectangle.\n *\n * @note IF ACE is not in ECS mode, OCS blitter limits apply.\n * Maximum blit size is 1024x1024 pixels.\n *\n * @note This function requires that X-coordinate as well as width\n * of the fill region are multiples of 16.\n *\n * @param pDst Destination bitmap.\n * @param wDstX Destination rectangle top-left position's X-coordinate.\n * @param wDstY Destination rectangle top-left position's Y-coordinate.\n * @param wWidth Rectangle width.\n * @param wHeight Rectangle height.\n * @param ubPlane Bitplane to be used.\n * @param ubFillMode A combination of `FILL_OR`, `FILL_XOR` and `FILL_CARRYIN`.\n * @return Always 1.\n *\n * @see blitSafeFillAligned()\n */\nvoid blitUnsafeFillAligned(\n\ttBitMap *pDst, WORD wDstX, WORD wDstY, WORD wWidth, WORD wHeight,\n\tUBYTE ubPlane, UBYTE ubFillMode\n);\n\n/**\n * @brief Performs the safe version of shape fill on a single bitplane inside\n * given rectangle.\n *\n * The safety comes from extra blitCheck() call within.\n *\n * @note IF ACE is not in ECS mode, OCS blitter limits apply.\n * Maximum blit size is 1024x1024 pixels.\n *\n * @note This function requires that X-coordinate as well as width\n * of the fill region are multiples of 16.\n *\n * @param pDst Destination bitmap.\n * @param wDstX Destination rectangle top-left position's X-coordinate.\n * @param wDstY Destination rectangle top-left position's Y-coordinate.\n * @param wWidth Rectangle width.\n * @param wHeight Rectangle height.\n * @param ubPlane Bitplane to be used.\n * @param ubFillMode A combination of `FILL_OR`, `FILL_XOR` and `FILL_CARRYIN`.\n * @param uwLine Source code line for error message. Use blitFillAligned() for auto-fill.\n * @param szFile Source code file for error message. Use blitFillAligned() for auto-fill.\n * @return Always 1.\n *\n * @see blitUnsafeFillAligned()\n */\nUBYTE blitSafeFillAligned(\n\ttBitMap *pDst, WORD wDstX, WORD wDstY, WORD wWidth, WORD wHeight,\n\tUBYTE ubPlane, UBYTE ubFillMode, UWORD uwLine, const char *szFile\n);\n\n/**\n * @brief Draws line of given color between two points.\n *\n * This function writes through all bitmap's bitplanes, so it's quite slow.\n * You can speed up your lines by drawing on only single bitplane - that's what\n * most demos do.\n *\n * @param pDst: Destination bitmap.\n * @param wX1: Line start position's X-coordinate.\n * @param wY1: Line start position's Y-coordinate.\n * @param wX2: Line end position's X-coordinate.\n * @param wY2: Line end position's Y-coordinate.\n * @param ubColor: Line's color index.\n * @param uwPattern: 16-bit pattern to be used. 1: filled pixel, 0: omitted.\n * @param isOneDot: If set to 1, draws fill-friendly lines.\n *\n * @see blitLinePlane()\n */\nvoid blitLine(\n\ttBitMap *pDst, WORD x1, WORD y1, WORD x2, WORD y2,\n\tUBYTE ubColor, UWORD uwPattern, UBYTE isOneDot\n);\n\n/**\n * @brief Draws line between two points on a single bitplane.\n *\n * This is way faster than drawing a line across multiple bitplanes.\n *\n * @param pDst: Destination bitmap.\n * @param wX1: Line start position's X-coordinate.\n * @param wY1: Line start position's Y-coordinate.\n * @param wX2: Line end position's X-coordinate.\n * @param wY2: Line end position's Y-coordinate.\n * @param ubPlane Bitplane index to use.\n * @param uwPattern: 16-bit pattern to be used. 1: filled pixel, 0: omitted.\n * @param eMode Set to one of tBlitLineMode values.\n * @param isOneDot: If set to 1, draws fill-friendly lines.\n *\n * @see blitLine()\n */\nvoid blitLinePlane(\n\ttBitMap *pDst, WORD wX1, WORD wY1, WORD wX2, WORD wY2,\n\tUBYTE ubPlane, UWORD uwPattern, tBlitLineMode eMode, UBYTE isOneDot\n);\n\n#ifdef ACE_DEBUG\n\n/**\n * @brief Checks if blit is legal at coords at given source and destination.\n *\n * @param pSrc Source bitmap.\n * @param wSrcX Source rectangle top-left position's X-coordinate.\n * @param wSrcY Source rectangle top-left position's Y-coordinate.\n * @param pDst Destination bitmap. Can be same as pSrc.\n * @param wDstX Destination rectangle top-left position's X-coordinate.\n * @param wDstY Destination rectangle top-left position's Y-coordinate.\n * @param wWidth Rectangle width.\n * @param wHeight Rectangle height.\n * @param uwLine Source code line for error message. Use blitCheck() for auto-fill.\n * @param szFile Source code file for error message. Use blitCheck() for auto-fill.\n * @return 1 if blit can safely be made, otherwise 0.\n */\nUBYTE _blitCheck(\n\tconst tBitMap *pSrc, WORD wSrcX, WORD wSrcY,\n\tconst tBitMap *pDst, WORD wDstX, WORD wDstY, WORD wWidth, WORD wHeight,\n\tUWORD uwLine, const char *szFile\n);\n\n#define blitCheck(pSrc, wSrcX, wSrcY, pDst, wDstX, wDstY, wWidth, wHeight, uwLine, szFile) \\\n\t_blitCheck(pSrc, wSrcX, wSrcY, pDst, wDstX, wDstY, wWidth, wHeight, uwLine, szFile)\n#define blitCopy(pSrc, wSrcX, wSrcY, pDst, wDstX, wDstY, wWidth, wHeight, ubMinterm) \\\n\tblitSafeCopy(pSrc, wSrcX, wSrcY, pDst, wDstX, wDstY, wWidth, wHeight, ubMinterm, __LINE__, __FILE__)\n#define blitCopyAligned(pSrc, wSrcX, wSrcY, pDst, wDstX, wDstY, wWidth, wHeight) \\\n\tblitSafeCopyAligned(pSrc, wSrcX, wSrcY, pDst, wDstX, wDstY, wWidth, wHeight, __LINE__, __FILE__)\n#define blitCopyMask(pSrc, wSrcX, wSrcY, pDst, wDstX, wDstY, wWidth, wHeight, pMsk) \\\n\tblitSafeCopyMask(pSrc, wSrcX, wSrcY, pDst, wDstX, wDstY, wWidth, wHeight, pMsk, __LINE__, __FILE__)\n#define blitRect(pDst, wDstX, wDstY, wWidth, wHeight, ubColor) \\\n\tblitSafeRect(pDst, wDstX, wDstY, wWidth, wHeight, ubColor, __LINE__, __FILE__)\n#define blitFillAligned(pDst, wDstX, wDstY, wWidth, wHeight, ubPlane, ubFillMode) \\\n\tblitSafeFillAligned(pDst, wDstX, wDstY, wWidth, wHeight, ubPlane, ubFillMode, __LINE__, __FILE__)\n\n#else\n\n#define blitCheck(pSrc, wSrcX, wSrcY, pDst, wDstX, wDstY, wWidth, wHeight, uwLine, szFile) \\\n\t({(void)(uwLine); (void)(szFile); 1;})\n#define blitCopy(pSrc, wSrcX, wSrcY, pDst, wDstX, wDstY, wWidth, wHeight, ubMinterm) \\\n\tblitUnsafeCopy(pSrc, wSrcX, wSrcY, pDst, wDstX, wDstY, wWidth, wHeight, ubMinterm)\n#define blitCopyAligned(pSrc, wSrcX, wSrcY, pDst, wDstX, wDstY, wWidth, wHeight) \\\n\tblitUnsafeCopyAligned(pSrc, wSrcX, wSrcY, pDst, wDstX, wDstY, wWidth, wHeight)\n#define blitCopyMask(pSrc, wSrcX, wSrcY, pDst, wDstX, wDstY, wWidth, wHeight, pMsk) \\\n\tblitUnsafeCopyMask(pSrc, wSrcX, wSrcY, pDst, wDstX, wDstY, wWidth, wHeight, pMsk)\n#define blitRect(pDst, wDstX, wDstY, wWidth, wHeight, ubColor) \\\n\tblitUnsafeRect(pDst, wDstX, wDstY, wWidth, wHeight, ubColor)\n#define blitFillAligned(pDst, wDstX, wDstY, wWidth, wHeight, ubPlane, ubFillMode) \\\n\tblitUnsafeFillAligned(pDst, wDstX, wDstY, wWidth, wHeight, ubPlane, ubFillMode)\n\n#endif // ACE_DEBUG\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif // _ACE_MANAGERS_BLIT_H_\n"
  },
  {
    "path": "include/ace/managers/bob.h",
    "content": "/* This Source Code Form is subject to the terms of the Mozilla Public\r\n * License, v. 2.0. If a copy of the MPL was not distributed with this\r\n * file, You can obtain one at http://mozilla.org/MPL/2.0/. */\r\n\r\n#ifndef _ACE_MANAGERS_BOB_H_\r\n#define _ACE_MANAGERS_BOB_H_\r\n\r\n#ifdef __cplusplus\r\nextern \"C\" {\r\n#endif\r\n\r\n#include <ace/types.h>\r\n#include <ace/managers/blit.h>\r\n\r\n/**\r\n * @file \"bob.h\"\r\n * @brief The mighty bob manager.\r\n * Its workflow is as follows:\r\n *\r\n * in gamestate create:\r\n * bobManagerCreate(...)\r\n * bobInit(&sBob1, ...)\r\n * bobInit(&sBob2, ...)\r\n * bobInit(&sBobN, ...)\r\n * bobReallocateBuffers()\r\n *\r\n * in gamestate loop:\r\n * bobBegin()\r\n * someCalcHereOrOtherBlitterOperationsHere()\r\n * bobPush(&sBobX) <-- no other blitting past this point\r\n * someCalcHere()\r\n * bobPush(&sBobY)\r\n * bobPush(&sBobZ)\r\n * someCalcHere()\r\n * bobProcessNext()\r\n * someCalcHere()\r\n * bobPush(&sBobT)\r\n * someCalcHere()\r\n * bobProcessNext()\r\n * someCalcHere()\r\n * bobPushingDone()\r\n * someCalcHere()\r\n * bobProcessNext()\r\n * someCalcHere()\r\n * bobProcessNext()\r\n * someCalcHere()\r\n * bobEnd()\r\n * someCalcHereOrOtherBlitterOperationsHere()\r\n *\r\n * in gamestate destroy:\r\n * bobManagerDestroy()\r\n */\r\n\r\n/**\r\n * @brief The bob structure.\r\n * You can safely change sPos to set new position. Rest is read-only and should\r\n * only be changed by provided fns.\r\n */\r\ntypedef struct tBob {\r\n\tUBYTE *pFrameData;\r\n\tUBYTE *pMaskData;\r\n\ttUwCoordYX pOldPositions[2];\r\n\ttUwCoordYX sPos;\r\n\tUWORD uwWidth;\r\n\tUWORD uwHeight;\r\n\tUBYTE isUndrawRequired;\r\n\t// Platform-dependent private fields. Don't rely on them externally.\r\n#if defined(ACE_DEBUG)\r\n\tUWORD _uwOriginalWidth;\r\n\tUWORD _uwOriginalHeight;\r\n#endif\r\n\tUWORD _uwBlitSize;\r\n\tWORD _wModuloUndrawSave;\r\n\tUWORD _uwInterleavedHeight;\r\n#if defined(ACE_BOB_PRISTINE_BUFFER)\r\n\tULONG _pSaveOffsets[2];\r\n#else\r\n\tUBYTE *_pBufferDrawPtrs[2];\r\n#endif\r\n} tBob;\r\n\r\n/**\r\n * @brief Creates bob manager with optional double buffering support.\r\n * If you use single buffering, pass same pointer in pFront and pBack.\r\n *\r\n * After calling this fn you should call series of bobInit() followed by\r\n * single bobReallocateBuffers().\r\n *\r\n * @param pFront Double buffering's front buffer bitmap.\r\n * @param pBack Double buffering's back buffer bitmap.\r\n * @param uwAvailHeight True available height for Y-scroll in passed bitmap.\r\n * For tileBuffer you should use `pTileBuffer->pScroll->uwBmAvailHeight`.\r\n * For scrollBuffer you should use `pScrollBuffer->uwBmAvailHeight`.\r\n *\r\n * @see bobInit()\r\n * @see bobReallocateBuffers()\r\n * @see bobManagerDestroy()\r\n */\r\nvoid bobManagerCreate(\r\n\ttBitMap *pFront, tBitMap *pBack,\r\n#if defined(ACE_BOB_PRISTINE_BUFFER)\r\n\ttBitMap *pPristineBuffer,\r\n#endif\r\n\tUWORD uwAvailHeight\r\n);\r\n\r\n/**\r\n * @brief Destroys bob manager, releasing all its resources.\r\n *\r\n * @see bobManagerCreate()\r\n */\r\nvoid bobManagerDestroy(void);\r\n\r\nvoid bobManagerReset(void);\r\n\r\n/**\r\n * @brief Initializes new bob for use with manager.\r\n *\r\n * @param pBob Pointer to bob structure.\r\n * @param uwWidth Bob's width.\r\n * @param uwHeight Bob's height.\r\n * @param isUndrawRequired If set to 1, its background will be undrawn.\r\n * @param pFrameData Pointer to frame to be displayed.\r\n * @param pMaskData Pointer to transparency mask of pFrameData.\r\n * @param uwX Initial X position.\r\n * @param uwY Initial Y position.\r\n */\r\nvoid bobInit(\r\n\ttBob *pBob, UWORD uwWidth, UWORD uwHeight, UBYTE isUndrawRequired,\r\n\tUBYTE *pFrameData, UBYTE *pMaskData, UWORD uwX, UWORD uwY\r\n);\r\n\r\n/**\r\n * @brief Allocates buffers for storing background for later undrawing of bobs.\r\n * Background of all bobs are stored in single buffer. This way there is no need\r\n * to reconfigure blitter's destination register when storing BGs.\r\n *\r\n * After call to this function, you can't call bobInit() anymore!\r\n */\r\nvoid bobReallocateBuffers(void);\r\n\r\n/**\r\n * @brief Changes bob's animation frame.\r\n *\r\n * Storing animation frames one under another implies simplest calculations,\r\n * hence exclusively supported by this manager.\r\n *\r\n * @param pBob Bob which should have its frame changed.\r\n * @param pFrameData Pointer to frame to be displayed.\r\n * @param pMaskData Pointer to transparency mask of pFrameData.\r\n */\r\nvoid bobSetFrame(tBob *pBob, UBYTE *pFrameData, UBYTE *pMaskData);\r\n\r\n/**\r\n * @brief Changes bob's width.\r\n *\r\n * @warning When using BG restore for bob, Watch out for BG buffer size\r\n * calculations - be sure to set initial bob's width to maximum value.\r\n * Otherwise, you're risking memory corruption!\r\n *\r\n * @param pBob Bob which width is to be resized.\r\n * @param uwWidth New width.\r\n */\r\nvoid bobSetWidth(tBob *pBob, UWORD uwWidth);\r\n\r\n/**\r\n * @brief Changes bob's height.\r\n *\r\n * @warning When using BG restore for bob, Watch out for BG buffer size\r\n * calculations - be sure to set initial bob's height to maximum value.\r\n * Otherwise, you're risking memory corruption!\r\n *\r\n * @param pBob Bob which height is to be resized.\r\n * @param uwHeight New height.\r\n */\r\nvoid bobSetHeight(tBob *pBob, UWORD uwHeight);\r\n\r\n/**\r\n * @brief Calculates byte address of a frame located at given Y offset.\r\n *\r\n * This function assumes that bitmap is exactly 1 frame-wide and next frames\r\n * are located one after another.\r\n *\r\n * @param pBitmap Bitmap which stores animation frames/masks.\r\n * @param uwOffsetY Y Offset of frame which address is to be calculated.\r\n * @return Byte address of frame/mask data of given frame.\r\n */\r\nUBYTE *bobCalcFrameAddress(tBitMap *pBitmap, UWORD uwOffsetY);\r\n\r\n/**\r\n * @brief Undraws all bobs, restoring BG to its former state.\r\n * Also bob current drawing queue is reset, making room for pushing new bobs.\r\n * After calling this function, you may push new bobs to screen.\r\n *\r\n * @see bobPush()\r\n */\r\nvoid bobBegin(tBitMap *pBuffer);\r\n\r\n/**\r\n * @brief Adds next bob to draw queue.\r\n * Bobs which were pushed in previous frame but not in current will still be\r\n * undrawn if needed.\r\n * There is no z-order, thus bobs are drawn in order of pushing.\r\n * When this function operates, it calls bobProcessNext().\r\n * Don't modify bob's struct past calling this fn - there is no guarantee when\r\n * bob system will access its data!\r\n *\r\n * @param pBob Pointer to bob to be drawn.\r\n *\r\n * @see bobProcessNext()\r\n * @see bobPushingDone()\r\n */\r\nvoid bobPush(tBob *pBob);\r\n\r\n/**\r\n * @brief Tries to store BG of or draw next bob.\r\n * Call this function periodically to check if blitter is idle and if it is,\r\n * give it more work to do.\r\n * Before calling bobPushingDone() bobs have their BG stored so that BG of\r\n * later pushed bobs won't get corrupted with gfx of earlier processed ones.\r\n *\r\n * Don't use blitter for any other thing until you do bobEnd()! It will\r\n * heavily corrupt memory!\r\n *\r\n * @return 1 if there's still some work to do by the blitter, otherwise 0.\r\n */\r\nUBYTE bobProcessNext(void);\r\n\r\n/**\r\n * @brief Closes drawing queue.\r\n * After calling this function bobs will get actually drawn, instead of just\r\n * storing BGs of bobs pushed to this point.\r\n * It also indicates that there will be no call to bobPush() until next\r\n * bobBegin().\r\n *\r\n * @see bobEnd()\r\n */\r\nvoid bobPushingDone(void);\r\n\r\n/**\r\n * @brief Processes all pending bobs so far.\r\n * This is only for advanced usage while ensuring that the bobs pushed so far\r\n * were already processed, e.g. alter the bitmaps mid-bob (un)draw.\r\n */\r\nvoid bobProcessAll(void);\r\n\r\n/**\r\n * @brief Gets the index of currently processed buffer in double buffering.\r\n * Used only in advanced scenarios to allow external access to bob struct's\r\n * private fields.\r\n * @return Index of the buffer - either 0 or 1.\r\n */\r\nUBYTE bobGetCurrentBufferIndex(void);\r\n\r\n/**\r\n * @brief Ends bob processing, enforcing all remaining bobs to be drawn.\r\n * After making this call all other blitter operations are safe again.\r\n */\r\nvoid bobEnd(void);\r\n\r\nvoid bobDiscardUndraw(void);\r\n\r\n/**\r\n * @brief Sets the current buffer to given bitmap in case it loses sync.\r\n * Usually used in tandem with bobDiscardUndraw() when bob system was disabled\r\n * for some time.\r\n *\r\n * @param pCurrent Current buffer to use. Must be same as one of passed\r\n * in bobManagerCreate().\r\n */\r\nvoid bobSetCurrentBuffer(tBitMap *pCurrent);\r\n\r\n#ifdef __cplusplus\r\n}\r\n#endif\r\n\r\n#endif // _ACE_MANAGERS_BOB_H_\r\n"
  },
  {
    "path": "include/ace/managers/copper.h",
    "content": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at http://mozilla.org/MPL/2.0/. */\n\n#ifndef _ACE_MANAGERS_COPPER_H_\n#define _ACE_MANAGERS_COPPER_H_\n\n/**\n * @file copper.h\n * @brief Double-buffered copper manager - one to rule them all.\n * Implements copperlist buffers and lowlevel-ish copper cmds.\n *\n * For convenience at cost of speed, one may use copper blocks - MOVE cmds\n * grouped together by single WAIT cmd. They are automatically reordered\n * if needed and may be used for small MOVE groups moving across the list.\n * This approach is superior with fast CPU and true FAST ram.\n *\n * If one needs quicker copperlist access on bare machine, one may write\n * directly into buffers inside CHIP ram using lowlevel-ish functions, command\n * bitfield modifications or even blits. Lastly, buffer swap fn must be called.\n *\n * @warning if you plan using raw buffer access, you'll have to better know\n * viewport managers internals to know how they work and to interface with them\n * corretly. Some of them are only made to use copperblocks, so they may be\n * unusable without them. Some things you'll have to implement by yourself.\n * You have been warned.\n */\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n#ifdef AMIGA\n#include <hardware/dmabits.h> // DMAF defines\n\n#include <ace/types.h>\n#include <ace/managers/log.h>\n#include <ace/utils/custom.h>\n#include <ace/utils/tag.h>\n\ntypedef enum tCopListCreateTags {\n\tTAG_COPPER_LIST_MODE = (TAG_USER|1),\n\tTAG_COPPER_RAW_COUNT = (TAG_USER|2),\n} tCopListCreateTags;\n\n// Values for TAG_COPPER_LIST_TYPE\n#define COPPER_MODE_BLOCK 0\n#define COPPER_MODE_RAW   1\n\n// Since copperlist is double buffered, status flags must be propagated for 2 passes\n\n#define STATUS_REALLOC_PREV 1\n#define STATUS_REALLOC_CURR 2\n#define STATUS_REALLOC (1|2)  /// Block added/removed - realloc merged memory\n\n#define STATUS_UPDATE_PREV 4\n#define STATUS_UPDATE_CURR 8\n#define STATUS_UPDATE (4|8)   /// Blocks changed content\n#define STATUS_REORDER 16     /// Blocks changed order\n\n//------------------------------------------------------------------------ TYPES\n\ntypedef struct tCopMoveCmd {\n\t// Higher word\n\tunsigned bfUnused  :7;  /// Always set to 0\n\tunsigned bfDestAddr:9;  /// Register offset from &custom segment\n\t                        /// LSBit must be set to 0 - WAIT check\n\t// Lower word\n\tunsigned bfValue:16;    /// New value\n} tCopMoveCmd;\n\ntypedef struct _tCopWaitCmd {\n\t// Higher word\n\tunsigned bfWaitY        :8; /// Y position\n\tunsigned bfWaitX        :7; /// X position\n\tunsigned bfIsWait       :1; /// Always set to 1\n\t// Lower word\n\tunsigned bfBlitterIgnore:1; /// If set to 0, waits for pos and blit finish\n\tunsigned bfVE           :7; /// Y compare enable bits\n\tunsigned bfHE           :7; /// X compare enable bits\n\tunsigned bfIsSkip       :1; /// Set to 1 for SKIP, 0 for WAIT\n} tCopWaitCmd;\n\ntypedef union _tCopCmd {\n\ttCopMoveCmd sMove;\n\ttCopWaitCmd sWait;\n\tULONG ulCode;\n} tCopCmd;\n\ntypedef struct _tCopBfr {\n\tUWORD uwAllocSize; /// Allocated memory size\n\tUWORD uwCmdCount;  /// Copper command count\n\ttCopCmd *pList;    /// HW Copperlist pointer\n} tCopBfr;\n\ntypedef struct _tCopBlock {\n\tstruct _tCopBlock *pNext;\n\ttUwCoordYX uWaitPos; /// Wait pos YX\n\tUWORD uwMaxCmds;     /// Command limit\n\tUWORD uwCurrCount;   /// Curr instruction count\n\tUBYTE ubDisabled;    /// 1: disabled, 0: enabled\n\tUBYTE ubUpdated;     /// 2: curr update, 1: prev update, 0: no update\n\tUBYTE ubResized;     /// 2: curr size change, 1: prev size change, 0: no change\n\ttCopCmd *pCmds;      /// Command pointer\n} tCopBlock;\n\ntypedef struct _tCopList {\n\tUWORD uwBlockCount;     /// Total number of blocks\n\tUBYTE ubStatus;         /// Status flags for processing\n\tUBYTE ubMode;           /// Sets block/raw mode\n\ttCopBfr *pFrontBfr;     /// Currently displayed copperlist\n\ttCopBfr *pBackBfr;      /// Editable copperlist\n\ttCopBlock *pFirstBlock; /// Block list\n} tCopList;\n\ntypedef struct _tCopManager {\n\ttCopList *pCopList;   /// Currently displayed tCopList\n\ttCopList *pBlankList; /// Empty copperlist - LoadView(0) equivalent\n} tCopManager;\n\n/**\n * @brief Values for composing bit mask of sprites.\n * Note that the first sprite is called \"0\" because this way it is consistent\n * with odd/even sprite naming which is widespread in literature.\n */\ntypedef enum tSpriteMask {\n\tSPRITE_0 = BV(0),\n\tSPRITE_1 = BV(1),\n\tSPRITE_2 = BV(2),\n\tSPRITE_3 = BV(3),\n\tSPRITE_4 = BV(4),\n\tSPRITE_5 = BV(5),\n\tSPRITE_6 = BV(6),\n\tSPRITE_7 = BV(7),\n} tSpriteMask;\n\n//---------------------------------------------------------------------- GLOBALS\n\nextern tCopManager g_sCopManager;\n\n//-------------------------------------------------------------------- FUNCTIONS\n\n/********************* Copper manager functions *******************************/\n\nvoid copCreate(void);\nvoid copDestroy(void);\nvoid copSwapBuffers(void);\nvoid copDumpBlocks(void);\nvoid copDumpBfr(tCopBfr *pBfr);\n\n/********************* Copper list functions **********************************/\n\ntCopList *copListCreate(void *pTagList, ...);\n\n/**\n * @brief Destroys copperlist along with all attached blocks.\n */\nvoid copListDestroy(tCopList *pCopList);\n\n/********************* Copper block functions *********************************/\n\n/**\n * @brief Creates new copperlist instruction block with given command count,\n * automatically WAITing for given x,y.\n *\n * Block creation sets STATUS_REORDER on parent copperlist, so they don't need\n * to be added in order.\n */\ntCopBlock *copBlockCreate(\n\ttCopList *pCopList, UWORD uwMaxCmds, UWORD uwWaitX, UWORD uwWaitY\n);\n\nvoid copBlockDestroy(tCopList *pCopList,tCopBlock *pBlock);\n\n/**\n * @brief Disables instruction block, so it will be omitted during copperlist\n * merge.\n */\nvoid copBlockDisable(tCopList *pCopList,tCopBlock *pBlock);\n\n/**\n * @brief Enables previously disabled instruction block.\n */\nvoid copBlockEnable(tCopList *pCopList,tCopBlock *pBlock);\n\n/**\n * @brief Prcesses current state of copper blocks into unified copperlist buffer.\n *\n * This function takes care of block reordering, buffer reallocating\n * and updating its contents from blocks which were marked as dirty.\n * If you need fine-grained control, you can use separate functions for those steps.\n *\n * Usually, it's best to use this function at the end of your frame loop code.\n *\n * @see copBfrRealloc()\n * @see copUpdateFromBlocks()\n * @see copReorderBlocks()\n */\nvoid copProcessBlocks(void);\n\n/**\n * @brief Reallocs current backBfr so that it will fit all copper blocks\n *\n * @return New status value of copper block.\n */\nUBYTE copBfrRealloc(void);\n\n/**\n * @brief Updates contents of current copperlist backbuffer with contents\n * of copper blocks.\n *\n * @return New status value of copper block.\n */\nUBYTE copUpdateFromBlocks(void);\n\n/**\n * @brief Reorders whole copper block list.\n */\nvoid copReorderBlocks(void);\n\n/********************* Copperblock cmd functions ******************************/\n\n/**\n * @brief Changes WAIT position for given copper block.\n *\n * Wait may result in copper block reorder - setting STATUS_REORDER\n * in copperlist lies on user's hands. This is not done automatically for\n * performance sake.\n *\n * @param pCopList Parent copperlist.\n * @param pBlock CopBlock to be modified.\n * @param uwX WAIT cmd's X position.\n * @param uwY Ditto, Y.\n */\nvoid copBlockWait(tCopList *pCopList, tCopBlock *pBlock, UWORD uwX, UWORD uwY);\n\n/**\n * @brief Appends MOVE command to end of copper block.\n *\n * @param pCopList Parent copperlist\n * @param pBlock CopBlock to be modified\n * @param pReg Custom chip register address to be set\n * @param uwValue New register's value.\n */\nvoid copMove(\n\ttCopList *pCopList, tCopBlock *pBlock, volatile void *pReg, UWORD uwValue\n);\n\n/********************* Lowlevel-ish cmd functions *****************************/\n\n/**\n * @brief Prepares WAIT command on given memory address.\n *\n * @note This fn is relatively slow for editing copperlist, since it builds\n * whole WAIT cmd from scratch.\n * If you exactly know what you're doing, you can just adjust wait pos\n * of already generated WAIT cmd and omit applying same values to rest of fields.\n *\n * @param pWaitCmd Pointer to copper command to be modified.\n * @param ubX WAIT cmd's X position.\n * @param ubY Ditto, Y.\n */\nvoid copSetWait(tCopWaitCmd *pWaitCmd, UBYTE ubX, UBYTE ubY);\n\n/**\n * @brief Prepares MOVE command on given memory address.\n *\n * @note This fn is relatively slow for editing copperlist, since it builds\n * whole WAIT cmd from scratch.\n * If you exactly know what you're doing, you can just adjust wait pos\n * of already generated WAIT cmd and omit applying same values to rest of fields.\n *\n * @param pMoveCmd Pointer to copper command to be modified.\n * @param pReg Custom chip register address to be set\n * @param uwValue New register's value.\n *\n * @see copSetMoveVal()\n */\nvoid copSetMove(tCopMoveCmd *pMoveCmd, volatile void *pReg, UWORD uwValue);\n\n/**\n * @brief Sets the MOVE command target value to a new one.\n * This is way faster than calling copSetMove() repeatedly if you're just\n * changing the value.\n *\n * @param pMoveCmd Pointer to copper command to be modified.\n * @param uwValue  New register's value. The target register doesn't change.\n *\n * @see copSetMoveVal()\n */\nstatic inline void copSetMoveVal(tCopMoveCmd *pMoveCmd, UWORD uwValue) {\n\tpMoveCmd->bfValue = uwValue;\n}\n\n#endif // AMIGA\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif // _ACE_MANAGERS_COPPER_H_\n"
  },
  {
    "path": "include/ace/managers/game.h",
    "content": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at http://mozilla.org/MPL/2.0/. */\n\n#ifndef _ACE_MANAGERS_GAME_H_\n#define _ACE_MANAGERS_GAME_H_\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n#include <ace/types.h> // Amiga typedefs\n\n/* Functions */\n\nvoid gameExit(void);\n\nUBYTE gameIsRunning(void);\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif // _ACE_MANAGERS_GAME_H_\n"
  },
  {
    "path": "include/ace/managers/joy.h",
    "content": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at http://mozilla.org/MPL/2.0/. */\n\n#ifndef _ACE_MANAGERS_JOY_H_\n#define _ACE_MANAGERS_JOY_H_\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n#include <ace/types.h>\n\n/* Types */\n#define JPORT1 1\n#define JPORT2 2\n\n// Combined access: JOYn + JOY_action\n#define JOY_FIRE  0\n#define JOY_UP    1\n#define JOY_DOWN  2\n#define JOY_LEFT  3\n#define JOY_RIGHT 4\n#define JOY_FIRE2 5\n\n#define JOY1 0\n#define JOY2 6\n#define JOY3 12\n#define JOY4 18\n\n#define JOY1_FIRE\t(JOY1 + JOY_FIRE)\n#define JOY1_UP\t\t(JOY1 + JOY_UP)\n#define JOY1_DOWN\t(JOY1 + JOY_DOWN)\n#define JOY1_LEFT\t(JOY1 + JOY_LEFT)\n#define JOY1_RIGHT\t(JOY1 + JOY_RIGHT)\n#define JOY1_FIRE2\t(JOY1 + JOY_FIRE2)\n\n#define JOY2_FIRE\t(JOY2 + JOY_FIRE)\n#define JOY2_UP\t\t(JOY2 + JOY_UP)\n#define JOY2_DOWN\t(JOY2 + JOY_DOWN)\n#define JOY2_LEFT\t(JOY2 + JOY_LEFT)\n#define JOY2_RIGHT\t(JOY2 + JOY_RIGHT)\n#define JOY2_FIRE2\t(JOY2 + JOY_FIRE2)\n\n#define JOY3_FIRE\t(JOY3 + JOY_FIRE)\n#define JOY3_UP\t\t(JOY3 + JOY_UP)\n#define JOY3_DOWN\t(JOY3 + JOY_DOWN)\n#define JOY3_LEFT\t(JOY3 + JOY_LEFT)\n#define JOY3_RIGHT\t(JOY3 + JOY_RIGHT)\n#define JOY3_FIRE2\t(JOY3 + JOY_FIRE2)\n\n#define JOY4_FIRE\t(JOY4 + JOY_FIRE)\n#define JOY4_UP\t\t(JOY4 + JOY_UP)\n#define JOY4_DOWN\t(JOY4 + JOY_DOWN)\n#define JOY4_LEFT\t(JOY4 + JOY_LEFT)\n#define JOY4_RIGHT\t(JOY4 + JOY_RIGHT)\n#define JOY4_FIRE2\t(JOY4 + JOY_FIRE2)\n\n\n#define JOY_NACTIVE 0\n#define JOY_USED 1\n#define JOY_ACTIVE 2\n\ntypedef struct _tJoyManager {\n\tUBYTE pStates[20];\n} tJoyManager;\n\n/* Globals */\nextern tJoyManager g_sJoyManager;\n\n/* Functions */\n\n/**\n * @brief Initializes joy manager.\n */\nvoid joyOpen(void);\n\n/**\n * @brief Enables additional joystricks through parallel adapter.\n *\n * @return 1 on success, otherwise 0.\n */\nUBYTE joyEnableParallel(void);\n\n/**\n * @brief Disables additional joysticks through parallel adapter.\n */\nvoid joyDisableParallel(void);\n\nUBYTE joyIsParallelEnabled(void);\n\nvoid joySetState(UBYTE ubJoyCode, UBYTE ubJoyState);\n\nUBYTE joyCheck(UBYTE ubJoyCode);\n\nUBYTE joyUse(UBYTE ubJoyCode);\n\nvoid joyProcess(void);\n\n/**\n * @brief Finishes work of joy manager.\n * This will also call joyDisableParallel() if needed.\n *\n * @see joyDisableParallel()\n */\nvoid joyClose(void);\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif\n"
  },
  {
    "path": "include/ace/managers/key.h",
    "content": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at http://mozilla.org/MPL/2.0/. */\n\n#ifndef _ACE_MANAGERS_KEY_H_\n#define _ACE_MANAGERS_KEY_H_\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n#include <ace/types.h>\n#ifdef AMIGA\n#include <exec/interrupts.h>  // struct Interrupt\n#endif // AMIGA\n\n//---------------------------------------------------------------------- DEFINES\n\n/**\n * Key codes\n * see http://amigadev.elowar.com/read/ADCD_2.1/Libraries_Manual_guide/node0479.html\n */\n\n// F-keys\n#define KEY_F1 0x50\n#define KEY_F2 0x51\n#define KEY_F3 0x52\n#define KEY_F4 0x53\n#define KEY_F5 0x54\n#define KEY_F6 0x55\n#define KEY_F7 0x56\n#define KEY_F8 0x57\n#define KEY_F9 0x58\n#define KEY_F10 0x59\n\n// Digits\n#define KEY_1 0x01\n#define KEY_2 0x02\n#define KEY_3 0x03\n#define KEY_4 0x04\n#define KEY_5 0x05\n#define KEY_6 0x06\n#define KEY_7 0x07\n#define KEY_8 0x08\n#define KEY_9 0x09\n#define KEY_0 0x0A\n\n// Chars - row 1\n#define KEY_Q 0x10\n#define KEY_W 0x11\n#define KEY_E 0x12\n#define KEY_R 0x13\n#define KEY_T 0x14\n#define KEY_Y 0x15\n#define KEY_U 0x16\n#define KEY_I 0x17\n#define KEY_O 0x18\n#define KEY_P 0x19\n\n// Chars - row 2\n#define KEY_A 0x20\n#define KEY_S 0x21\n#define KEY_D 0x22\n#define KEY_F 0x23\n#define KEY_G 0x24\n#define KEY_H 0x25\n#define KEY_J 0x26\n#define KEY_K 0x27\n#define KEY_L 0x28\n\n// Chars - row 3\n#define KEY_Z 0x31\n#define KEY_X 0x32\n#define KEY_C 0x33\n#define KEY_V 0x34\n#define KEY_B 0x35\n#define KEY_N 0x36\n#define KEY_M 0x37\n\n// Numpad: digits\n#define KEY_NUM0 0x0F\n#define KEY_NUM1 0x1D\n#define KEY_NUM2 0x1E\n#define KEY_NUM3 0x1F\n#define KEY_NUM4 0x2D\n#define KEY_NUM5 0x2E\n#define KEY_NUM6 0x2F\n#define KEY_NUM7 0x3D\n#define KEY_NUM8 0x3E\n#define KEY_NUM9 0x3F\n\n// Arrows\n#define KEY_UP 0x4C\n#define KEY_DOWN 0x4D\n#define KEY_RIGHT 0x4E\n#define KEY_LEFT 0x4F\n\n// Numpad: ()/*+-. and Enter\n#define KEY_NUMLPARENTHESES 0x5A\n#define KEY_NUMRPARENTHESES 0x5B\n#define KEY_NUMSLASH 0x5C\n#define KEY_NUMMULTIPLY 0x5D\n#define KEY_NUMPLUS 0x5E\n#define KEY_NUMMINUS 0x4A\n#define KEY_NUMPERIOD 0x3C\n#define KEY_NUMENTER 0x43\n\n// Misc\n#define KEY_ESCAPE 0x45\n#define KEY_ACCENT 0x00\n#define KEY_MINUS 0x0B\n#define KEY_EQUALS 0x0C\n#define KEY_BACKSLASH 0x0D\n#define KEY_TAB 0x42\n#define KEY_LBRACKET 0x1A\n#define KEY_RBRACKET 0x1B\n#define KEY_RETURN 0x44\n#define KEY_CONTROL 0x63\n#define KEY_CAPSLOCK 0x62\n#define KEY_SEMICOLON 0x29\n#define KEY_APOSTROPHE 0x2A\n#define KEY_REGIONAL1 0x2B\n#define KEY_LSHIFT 0x60\n#define KEY_REGIONAL2 0x30\n#define KEY_COMMA 0x38\n#define KEY_PERIOD 0x39\n#define KEY_BACKSPACE 0x41\n#define KEY_SLASH 0x3A\n#define KEY_RSHIFT 0x61\n#define KEY_LALT 0x64\n#define KEY_LAMIGA 0x66\n#define KEY_SPACE 0x40\n#define KEY_RAMIGA 0x67\n#define KEY_RALT 0x64\n#define KEY_DEL 0x46\n#define KEY_HELP 0x5F\n\n// Key state flags\n#define KEY_NACTIVE 0\n#define KEY_USED 1\n#define KEY_ACTIVE 2\n\n#define KEY_COUNT 104\n\n//------------------------------------------------------------------------ TYPES\n\ntypedef struct _tKeyManager {\n\tvolatile UBYTE pStates[KEY_COUNT];\n\tvolatile UBYTE ubLastKey;\n} tKeyManager;\n\n//---------------------------------------------------------------------- GLOBALS\n\nextern tKeyManager g_sKeyManager;\nextern const UBYTE g_pFromAscii[];\nextern const UBYTE g_pToAscii[];\n\n//-------------------------------------------------------------------- FUNCTIONS\n\n/**\n * Initializes Key manager.\n */\nvoid keyCreate(void);\n\n/**\n * Cleans up after Key manager.\n */\nvoid keyDestroy(void);\n\n/**\n * Processes key manager, updating keys' states.\n * This function should be called once per frame.\n */\nvoid keyProcess(void);\n\n/**\n * Sets state of given key.\n * @param ubKeyCode: Code of key, which state should be changed.\n * @param ubKeyState: Key state (KEY_ACTIVE, KEY_NACTIVE or KEY_USED).\n */\nvoid keySetState(UBYTE ubKeyCode, UBYTE ubKeyState);\n\n/**\n * Polls state of key with given code.\n * @param ubKeyCode: Code of key, which state should be polled.\n * @return 1 if key is pressed, otherwise 0.\n * @see keyUse()\n */\nUBYTE keyCheck(UBYTE ubKeyCode);\n\n/**\n * Checks if given key was recently pressed.\n * If key's code is ACTIVE, fn returns 1 and changes key state to USED.\n * @param ubKeyCode: Code of key, which state should be polled.\n * @return 1 if key was recently pressed, otherwise 0.\n * @see keyCheck()\n */\nstatic inline UBYTE keyUse(UBYTE ubKeyCode) {\n\tif (g_sKeyManager.pStates[ubKeyCode] == KEY_ACTIVE) {\n\t\tg_sKeyManager.pStates[ubKeyCode] = KEY_USED;\n\t\treturn 1;\n\t}\n\treturn 0;\n}\n\nstatic inline void keyReset(void) {\n\tfor(UBYTE i = 0; i < KEY_COUNT; ++i) {\n\t\tg_sKeyManager.pStates[i] = KEY_NACTIVE;\n\t}\n}\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif // _ACE_MANAGERS_KEY_H_\n"
  },
  {
    "path": "include/ace/managers/log.h",
    "content": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at http://mozilla.org/MPL/2.0/. */\n\n#ifndef _ACE_MANAGERS_LOG_H_\n#define _ACE_MANAGERS_LOG_H_\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n#include <string.h> // strlen etc\n#include <stdarg.h> // va_list etc\n#include <ace/types.h>\n#include <ace/managers/timer.h>\n#include <ace/utils/file.h>\n\n// Types\n\ntypedef struct _tAvg {\n\tUWORD uwAllocCount;\n\tUWORD uwUsedCount;\n\tUWORD uwCurrDelta;\n\tULONG ulMin;\n\tULONG ulMax;\n\tULONG ulStartTime;\n\tULONG *pDeltas;\n\tchar *szName;\n} tAvg;\n\n\ntypedef struct _tLogManager {\n\ttFile *pFile;\n\tUBYTE ubIndent;\n\tWORD wInterruptDepth;\n\tUBYTE wasLastInline;\n\tULONG pTimeStack[256];\n\tchar szTimeBfr[255];\n\tUBYTE isBlockEmpty;\n\tUBYTE ubShutUp;\n} tLogManager;\n\n#ifdef ACE_DEBUG\n// Globals\nextern tLogManager g_sLogManager;\n\n// Functions - general\n\nvoid _logOpen(const char *szFilePath);\nvoid _logClose(void);\n\nvoid _logPushIndent(void);\nvoid _logPopIndent(void);\n\nvoid _logPushInt(void);\nvoid _logPopInt(void);\n\nvoid _logWrite(char *szFormat, ...) __attribute__ ((format (printf, 1, 2)));\n\nvoid _logWriteVa(char *szFormat, va_list vaArgs);\n\n// Functions - block logging\n\nvoid _logBlockBegin(char *szBlockName, ...) __attribute__ ((format (printf, 1, 2)));\nvoid _logBlockEnd(char *szBlockName);\n\n// Functions - average block time\n\ntAvg *_logAvgCreate(char *szName, UWORD uwCount);\nvoid _logAvgDestroy(tAvg *pAvg);\nvoid _logAvgBegin(tAvg *pAvg);\nvoid _logAvgEnd(tAvg *pAvg);\nvoid _logAvgWrite(tAvg *pAvg);\n\n// Functions - general logging\n\n#define logOpen(szFilePath) _logOpen(szFilePath)\n#define logClose() _logClose()\n#define logPushIndent() _logPushIndent()\n#define logPopIndent() _logPopIndent()\n#define logPushInt() _logPushInt()\n#define logPopInt() _logPopInt()\n#define logWrite(...) _logWrite(__VA_ARGS__)\n#define logWriteVa(szFormat, vaArgs) _logWriteVa(szFormat, vaArgs)\n\n#define logBlockBegin(...) _logBlockBegin(__VA_ARGS__)\n#define logBlockEnd(szBlockName) _logBlockEnd(szBlockName)\n\n#define logAvgCreate(szName, wCount) _logAvgCreate(szName, wCount)\n#define logAvgDestroy(pAvg) _logAvgDestroy(pAvg)\n#define logAvgBegin(pAvg) _logAvgBegin(pAvg)\n#define logAvgEnd(pAvg) _logAvgEnd(pAvg)\n#define logAvgWrite(pAvg) _logAvgWrite(pAvg)\n\n#else\n#define logOpen(szFilePath)\n#define logClose()\n#define logPushIndent()\n#define logPopIndent()\n#define logPushInt()\n#define logPopInt()\n#define logWrite(...)\n#define logWriteVa(szFormat, vaArgs)\n\n#define logBlockBegin(...)\n#define logBlockEnd(szBlockName)\n\n#define logAvgCreate(szName, wCount) 0\n#define logAvgDestroy(pAvg)\n#define logAvgBegin(pAvg)\n#define logAvgEnd(pAvg)\n#define logAvgWrite(pAvg)\n#endif // ACE_DEBUG\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif // _ACE_MANAGERS_LOG_H_\n"
  },
  {
    "path": "include/ace/managers/memory.h",
    "content": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at http://mozilla.org/MPL/2.0/. */\n\n#ifndef _ACE_MANAGERS_MEMORY_H_\n#define _ACE_MANAGERS_MEMORY_H_\n\n/**\n * Memory manager functions.\n * mainly used for debug, should be replaced by NOP on release builds.\n */\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n#ifdef AMIGA\n#include <exec/memory.h> // MEMF_CLEAR etc\n#else\n#define MEMF_CHIP    0\n#define MEMF_FAST    1\n#define MEMF_CLEAR   2\n#define MEMF_PUBLIC  4\n#define MEMF_LARGEST 8\n#endif // AMIGA\n\n#include <ace/types.h>\n\n/* Types */\n\n/* Globals */\n\n/* Functions */\n\n/**\n * @brief Checks whether memory pointer is in CHIP or FAST mem.\n *\n * @param pMem Pointer to memory to be checked.\n * @return MEMF_CHIP or MEMF_FAST.\n */\nUBYTE memType(const void *pMem);\n\nULONG memGetFreeChipSize(void);\n\nULONG memGetFreeSize(void);\n\nvoid _memCreate(void);\nvoid _memDestroy(void);\n\nvoid *_memAllocDbg(ULONG ulSize, ULONG ulFlags, UWORD uwLine, const char *szFile);\nvoid _memFreeDbg(void *pMem, ULONG ulSize, UWORD uwLine, const char *szFile);\nvoid *_memAllocRls(ULONG ulSize, ULONG ulFlags) __attribute__((malloc));\nvoid _memFreeRls(void *pMem, ULONG ulSize);\n\nvoid _memCheckTrashAtAddr(void *pMem, UWORD uwLine, const char *szFile);\n\nvoid _memCheckIntegrity(UWORD uwLine, const char *szFile);\n\nvoid _memLogPeak(void);\n\n/**\n * Macros for enabling or disabling logging\n */\n\n#ifdef ACE_DEBUG\n# define memAlloc(ulSize, ulFlags) _memAllocDbg(ulSize, ulFlags, __LINE__, __FILE__)\n# define memFree(pMem, ulSize) _memFreeDbg(pMem, ulSize, __LINE__, __FILE__)\n# define memCreate() _memCreate()\n# define memDestroy() _memDestroy()\n# define memCheckTrashAtAddr(pAddr) _memCheckTrashAtAddr(pAddr, __LINE__, __FILE__)\n# define memCheckIntegrity() _memCheckIntegrity(__LINE__, __FILE__)\n# define memLogPeak() _memLogPeak()\n#else\n# define memAlloc(ulSize, ulFlags) _memAllocRls(ulSize, ulFlags)\n# define memFree(pMem, ulSize) _memFreeRls(pMem, ulSize)\n# define memCreate()\n# define memDestroy()\n# define memCheckTrashAtAddr(pAddr, ulSize)\n# define memCheckIntegrity()\n# define memLogPeak()\n#endif // ACE_DEBUG\n\n// Shorthands\n#define memAllocFast(ulSize) memAlloc(ulSize, MEMF_ANY)\n#define memAllocChip(ulSize) memAlloc(ulSize, MEMF_CHIP)\n#define memAllocFastClear(ulSize) memAlloc(ulSize, MEMF_ANY | MEMF_CLEAR)\n#define memAllocChipClear(ulSize) memAlloc(ulSize, MEMF_CHIP | MEMF_CLEAR)\n#define memAllocChipFlags(ulSize, ulFlags) memAlloc(ulSize, MEMF_CHIP | ulFlags)\n#define memAllocFastFlags(ulSize, ulFlags) memAlloc(ulSize, MEMF_ANY |ulFlags)\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif // _ACE_MANAGERS_MEMORY_H_\n"
  },
  {
    "path": "include/ace/managers/mouse.h",
    "content": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at http://mozilla.org/MPL/2.0/. */\n\n#ifndef _ACE_MANAGERS_MOUSE_H_\n#define _ACE_MANAGERS_MOUSE_H_\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n#include <ace/types.h>\n#include <ace/macros.h>\n\n// Mouse button identifiers\n#define MOUSE_LMB 0\n#define MOUSE_RMB 1\n#define MOUSE_MMB 2\n\n// Button state defines\n#define MOUSE_NACTIVE 0\n#define MOUSE_USED 1\n#define MOUSE_ACTIVE 2\n\n// Mouse ports\n// #define MOUSE_PORT_0 0 // Unused mouse port for alignment\n#define MOUSE_PORT_1 1\n#define MOUSE_PORT_2 2\n\n/* Types */\ntypedef struct _tMouse {\n\tUWORD uwX;\n\tUWORD uwY;\n\tUBYTE pButtonStates[3];\n\ttUwAbsRect sBounds; ///< Min/max mouse position.\n#ifdef AMIGA\n\tUBYTE ubPrevHwX;\n\tUBYTE ubPrevHwY;\n#endif\n} tMouse;\n\ntypedef struct _tMouseManager {\n\tUBYTE ubPortFlags;\n\ttMouse pMice[3]; ///< Zero is pad, faster than subtracting from port code.\n#ifdef AMIGA\n\tUWORD uwPrevPotGo; ///< Previous control port config.\n#endif // AMIGA\n} tMouseManager;\n\n/* Globals */\nextern tMouseManager g_sMouseManager;\n\n/* Functions */\n\n/**\n * Initializes mouse management for given ports.\n * @param ubPortFlags: Ports in which mouse should be processed.\n *        OR combination of MOUSE_PORT_* defines.\n * @see mouseDestroy()\n * @see mouseProcess()\n */\nvoid mouseCreate(UBYTE ubPortFlags);\n\n/**\n * Cleans up after mouse maanger.\n * @see mouseCreate()\n */\nvoid mouseDestroy(void);\n\n/**\n * Processes mouse manager, updating mice's position and button states.\n * Should be called once per frame.\n */\nvoid mouseProcess(void);\n\n/**\n * Set on-screen constraints for cursor.\n * @param ubMousePort: Mouse port to be constrained.\n * @param uwLoX: Minimum cursor X position.\n * @param uwLoX: Minimum cursor Y position.\n * @param uwHiY: Maximum cursor X position.\n * @param uwHiY: Maximum cursor Y position.\n */\nstatic inline void mouseSetBounds(\n\tUBYTE ubMousePort, UWORD uwLoX, UWORD uwLoY, UWORD uwHiX, UWORD uwHiY\n) {\n\tg_sMouseManager.pMice[ubMousePort].sBounds.uwX1 = uwLoX;\n\tg_sMouseManager.pMice[ubMousePort].sBounds.uwY1 = uwLoY;\n\tg_sMouseManager.pMice[ubMousePort].sBounds.uwX2 = uwHiX;\n\tg_sMouseManager.pMice[ubMousePort].sBounds.uwY2 = uwHiY;\n}\n\n\n/**\n * Returns given mouse's current X position.\n * @param ubMousePort: Mouse to be polled. Use one of MOUSE_PORT_* values.\n * @return Mouse's current X position relative to top-left screen pos.\n */\nstatic inline UWORD mouseGetX(UBYTE ubMousePort) {\n\treturn g_sMouseManager.pMice[ubMousePort].uwX;\n}\n\n/**\n * Returns given mouse's current Y position.\n * @param ubMousePort: Mouse to be polled. Use one of MOUSE_PORT_* values.\n * @return Mouse's current X position relative to top-left screen pos.\n */\nstatic inline UWORD mouseGetY(UBYTE ubMousePort) {\n\treturn g_sMouseManager.pMice[ubMousePort].uwY;\n}\n\n/**\n * Sets given mouse's button to desired state.\n * @param ubMousePort: Mouse to be set.\n * @param ubMouseCode: Mouse button, which state should be changed\n *        (MOUSE_LMB, MOUSE_RMB or MOUSE_MMB).\n * @param ubMouseState: New button state\n *        (MOUSE_NACTIVE, MOUSE_USED, MOUSE_ACTIVE).\n */\nstatic inline void mouseSetButton(\n\tUBYTE ubMousePort, UBYTE ubMouseCode, UBYTE ubMouseState\n) {\n\tg_sMouseManager.pMice[ubMousePort].pButtonStates[ubMouseCode] = ubMouseState;\n}\n\n/**\n * Returns given mouse's button state.\n * @param ubMousePort: Mouse to be polled.\n * @param ubMouseCode: Button to be polled (MOUSE_LMB, MOUSE_RMB or MOUSE_MMB).\n * @return 1 if button is pressed, otherwise 0.\n */\nstatic inline UBYTE mouseCheck(UBYTE ubMousePort, UBYTE ubMouseCode) {\n\tUBYTE ubBtn = g_sMouseManager.pMice[ubMousePort].pButtonStates[ubMouseCode];\n\treturn ubBtn != MOUSE_NACTIVE;\n}\n\n/**\n * Returns whether given button was recently pressed.\n * If button was polled as ACTIVE, function returns 1 and sets button as USED.\n * @param ubMousePort: Mouse to be polled.\n * @param ubMouseCode: Button to be polled (MOUSE_LMB, MOUSE_RMB or MOUSE_MMB).\n * @return 1 if button was recently pressed, otherwise 0.\n */\nstatic inline UBYTE mouseUse(UBYTE ubMousePort, UBYTE ubMouseCode) {\n\ttMouse *pMouse = &g_sMouseManager.pMice[ubMousePort];\n\tif(pMouse->pButtonStates[ubMouseCode] == MOUSE_ACTIVE) {\n\t\tpMouse->pButtonStates[ubMouseCode] = MOUSE_USED;\n\t\treturn 1;\n\t}\n\treturn 0;\n}\n\n/**\n * Checks if given mouse has position contained within given rectangle.\n * @param ubMousePort: Mouse to be polled.\n * @param sRect: Rectangle to be checked.\n * @return 1 if mouse position is within given rectangle, otherwise 0.\n */\nstatic inline UBYTE mouseInRect(UBYTE ubMousePort, tUwRect sRect) {\n\tUWORD uwMouseX = g_sMouseManager.pMice[ubMousePort].uwX;\n\tUWORD uwMouseY = g_sMouseManager.pMice[ubMousePort].uwY;\n\treturn (\n\t\t(sRect.uwX <= uwMouseX) && (uwMouseX < sRect.uwX + sRect.uwWidth) &&\n\t\t(sRect.uwY <= uwMouseY) && (uwMouseY < sRect.uwY + sRect.uwHeight)\n\t);\n}\n\n/**\n *  Sets mouse position to given absolute position.\n * This function takes into account bounds specified by mouseSetBounds().\n * @param ubMousePort: Mouse of which position should be changed.\n * @param uwNewX: new X position.\n * @param uwNewY: new Y position.\n * @see mouseSetBounds()\n * @see mouseMoveBy()\n */\nstatic inline void mouseSetPosition(\n\tUBYTE ubMousePort, UWORD uwNewX, UWORD uwNewY\n) {\n\ttMouse *pMouse = &g_sMouseManager.pMice[ubMousePort];\n\tpMouse->uwX = CLAMP(uwNewX, pMouse->sBounds.uwX1, pMouse->sBounds.uwX2);\n\tpMouse->uwY = CLAMP(uwNewY, pMouse->sBounds.uwY1, pMouse->sBounds.uwY2);\n}\n\n/**\n * Moves mouse pointer from current position by relative offsets.\n * This function takes into account bounds specified by mouseSetBounds().\n * @param ubMousePort: Mouse of which position should be changed.\n * @param wDx: Positive value moves mouse right, negative moves left.\n * @param wDy: Positive value moves mouse down, negative moves left.\n * @see mouseSetBounds()\n * @see mouseSetPosition()\n */\nstatic inline void mouseMoveBy(UBYTE ubMousePort, WORD wDx, WORD wDy) {\n\ttMouse *pMouse = &g_sMouseManager.pMice[ubMousePort];\n\tpMouse->uwX = CLAMP(\n\t\tpMouse->uwX + wDx, pMouse->sBounds.uwX1, pMouse->sBounds.uwX2\n\t);\n\tpMouse->uwY = CLAMP(\n\t\tpMouse->uwY + wDy, pMouse->sBounds.uwY1, pMouse->sBounds.uwY2\n\t);\n}\n\n/**\n * Resets mouse position to center of legal coordinate range.\n * @param ubMousePort: Mouse of which position should be reset.\n */\nstatic inline void mouseResetPos(UBYTE ubMousePort) {\n\tconst tUwAbsRect *pBounds = &g_sMouseManager.pMice[ubMousePort].sBounds;\n\tg_sMouseManager.pMice[ubMousePort].uwX = (pBounds->uwX2 - pBounds->uwX1) >> 1;\n\tg_sMouseManager.pMice[ubMousePort].uwY = (pBounds->uwY2 - pBounds->uwY1) >> 1;\n}\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif // _ACE_MANAGERS_MOUSE_H_\n"
  },
  {
    "path": "include/ace/managers/ptplayer.h",
    "content": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at http://mozilla.org/MPL/2.0/. */\n\n// Protracker V2.3B Playroutine Version 6.3\n// Original written in assembly by Frank Wille in 2013, 2016-2023.\n// Rewritten for ACE usage to C.\n\n#ifndef _ACE_MANAGERS_PTPLAYER_H_\n#define _ACE_MANAGERS_PTPLAYER_H_\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n#define PTPLAYER_VOLUME_MAX 64\n#define PTPLAYER_SFX_CHANNEL_ANY 0xFF\n#define PTPLAYER_MOD_SAMPLE_COUNT 31\n\n#include <ace/types.h>\n#include <ace/utils/bitmap.h>\n#include <ace/utils/font.h>\n\n#if defined(ACE_DEBUG_ALL) && !defined(ACE_DEBUG_PTPLAYER)\n#define ACE_DEBUG_PTPLAYER\n#endif\n\ntypedef struct _tPtplayerSfx {\n\tUWORD *pData;       ///< Sample start in Chip RAM, even address.\n\tUWORD uwWordLength; ///< Sample length in words.\n\tUWORD uwPeriod;     ///< Hardware replay period for sample.\n} tPtplayerSfx;\n\ntypedef struct _tPtplayerSampleHeader {\n\tchar szName[22];\n\tUWORD uwLength; ///< Sample data length, in words.\n\tUBYTE ubFineTune; ///< Finetune. Only lower nibble is used.\n\t                  ///  Values translate to finetune: {0..7, -8..-1}\n\tUBYTE ubVolume; ///< Sample volume. 0..64\n\tUWORD uwRepeatOffs; ///< In words.\n\tUWORD uwRepeatLength; ///< In words.\n} tPtplayerSampleHeader;\n\ntypedef struct _tPtplayerMod {\n\tchar szSongName[20];\n\ttPtplayerSampleHeader pSampleHeaders[PTPLAYER_MOD_SAMPLE_COUNT];\n\tUBYTE ubArrangementLength; ///< Length of arrangement, not to be confused with\n\t                           /// pattern count in file. Max 128.\n\tUBYTE ubSongEndPos;\n\tUBYTE pArrangement[128]; ///< song arrangmenet list (pattern Table).\n\t                         /// These list up to 128 pattern numbers\n\t                         /// and the order they should be played in.\n\tchar pFileFormatTag[4];  ///< Should be \"M.K.\" for 31-sample format.\n\t// MOD pattern/sample data follows\n\n\tUBYTE *pPatterns;\n\tUWORD *pSampleStarts[PTPLAYER_MOD_SAMPLE_COUNT];\n\tULONG ulPatternsSize;\n\tUBYTE isOwningSamples;\n} tPtplayerMod;\n\ntypedef struct tPtplayerSamplePack {\n\tUBYTE ubSampleCount;\n\ttPtplayerSfx pSamples[PTPLAYER_MOD_SAMPLE_COUNT];\n} tPtplayerSamplePack;\n\ntypedef void (*tPtplayerCbSongEnd)(void);\ntypedef void (*tPtplayerCbE8)(UBYTE ubE8);\n\n/**\n * @brief Install a CIA-B interrupt for calling _mt_music or mt_sfxonly.\n * The music module is replayed via _mt_music when _mt_Enable is non-zero.\n * Otherwise the interrupt handler calls mt_sfxonly to play sound effects only.\n *\n * @param isPal In CIA mode, Set to 1 on PAL configs, zero on NTSC.\n */\nvoid ptplayerCreate(UBYTE isPal);\n\nvoid ptplayerDestroy(void);\n\nvoid ptplayerProcess(void);\n\n/**\n * @brief Sets PAL/NTSC mode. Relevant in CIA-based playback mode.\n *\n * Note that each tSfx stores period calculated for mode which was set during\n * call to ptplayerSfxCreateFromFd(). You may need to correct their values\n * manually.\n *\n * @param isPal In CIA mode, Set to 1 on PAL configs, zero on NTSC.\n */\nvoid ptplayerSetPal(UBYTE isPal);\n\n/**\n * @brief Loads new MOD from file.\n * @note This function may use OS.\n *\n * @param szPath Path to .mod file.\n * @return Pointer to new MOD structure, initialized with file contents.\n */\ntPtplayerMod *ptplayerModCreateFromPath(const char *szPath);\n\n/**\n * @brief Loads new MOD from file.\n * @note This function may use OS.\n *\n * @param pFileMod Handle to the .mod file. Will be closed on function return.\n * @return Pointer to new MOD structure, initialized with file contents.\n */\ntPtplayerMod *ptplayerModCreateFromFd(tFile *pFileMod);\n\n/**\n * @brief Frees given MOD from memory.\n * @note This function may use OS.\n *\n * @param pMod MOD struct to be destroyed.\n */\nvoid ptplayerModDestroy(tPtplayerMod *pMod);\n\n/**\n * @brief Initialize a new module but doesn't automatically play it.\n * You still need to call ptplayerEnableMusic().\n * Reset speed to 6, tempo to 125 and start at the given position.\n * Master volume is at 64 (maximum).\n *\n * @param pMod Pointer to MOD struct.\n * @param pExternalSamples When set to 0, the samples are assumed to be stored inside\n * the MOD, after the patterns. Otherwise, uses samples from given samplepack.\n * @param uwInitialSongPos\n *\n * @see ptplayerEnableMusic()\n * @see ptplayerStop()\n */\nvoid ptplayerLoadMod(\n\ttPtplayerMod *pMod, tPtplayerSamplePack *pExternalSamples,\n\tUWORD uwInitialSongPos\n);\n\n/**\n * @brief Stop playing current module.\n * After calling this function, you need to call ptplayerLoadMod() again.\n *\n * @see ptplayerLoadMod()\n */\nvoid ptplayerStop(void);\n\n/**\n * @brief Set bits in the mask define which specific channels are reserved\n * for music only.\n *\n * When calling ptplayerSfxPlay with automatic channel selection\n * (sfx_cha=-1) then these masked channels will never be picked.\n * The mask defaults to 0.\n *\n * @param ubChannelMask Mask of channels reserved for playing music. Set bit 0\n * for channel 0, bit 1 for channel 1, etc.\n * @see ptplayerSfxPlay()\n */\nvoid ptplayerSetMusicChannelMask(UBYTE ubChannelMask);\n\n/**\n * @brief Set a master volume for all music channels.\n * Note that the master volume does not affect the volume of external\n * sound effects (which is desired).\n *\n * @param ubMasterVolume Value between 0 and 64. Bigger is louder.\n */\nvoid ptplayerSetMasterVolume(UBYTE ubMasterVolume);\n\n/**\n * @brief Define which channels are used for the player. Set bit 0 for channel 0, etc.\n *\n * @param ubChannelMask Bit mask of music channels to be used. Uses bits 0..3.\n */\nvoid ptplayerSetChannelsForPlayer(UBYTE ubChannelMask);\n\n/**\n * @brief Enables or disables music playback.\n * You can still play sound effects, while music is stopped.\n * Music is by default disabled after ptplayerInit().\n *\n * @param isEnabled Set to 1 to enable music playback, zero to disable.\n */\nvoid ptplayerEnableMusic(UBYTE isEnabled);\n\n/**\n * @brief Gets the value of the last E8 command.\n * It is reset to 0 after ptplayerInit().\n *\n * @return Value of last-played E8 command.\n */\nUBYTE ptplayerGetE8(void);\n\n/**\n * @brief Define the number of channels which should be dedicated only for music.\n * If set to zero, sound effects can take over any channel if they have high\n * enough priority. When set to 4, no sound effects are played.\n *\n * At initialization, zero channels are reserved for music.\n *\n * @param ubChannelCount Number of channels to be used only for playing music.\n */\nvoid ptplayerReserveChannelsForMusic(UBYTE ubChannelCount);\n\n/**\n * @brief Redefine a sample's volume on currently played MOD.\n * May also be done while the song is playing. This change is persistent and can\n * only be reverted by setting volume to previous value or reloading the MOD.\n *\n * @param ubSampleIndex Sample number (0-31).\n * @param ubVolume Volume (0-64).\n */\nvoid ptplayerSetSampleVolume(UBYTE ubSampleIndex, UBYTE ubVolume);\n\n//-------------------------------------------------------------------------- SFX\n\n/**\n * @brief Loads SFX from given file.\n * Note that this function sets SFX period based on currently set PAL/NTSC video\n * mode. If you plan to change it after loading SFX, be sure to adjust\n * the period value for new mode.\n * @note This function may use OS.\n *\n * @param szPath Path to .sfx file.\n * @param isFast Set to 1 if you wish to load SFX to FAST memory.\n * Useful for software-based audio-mixing, unusable with ptplayer.\n * @return Newly loaded SFX.\n *\n * @see ptplayerSfxDestroy()\n * @see ptplayerSfxPlay()\n */\ntPtplayerSfx *ptplayerSfxCreateFromPath(const char *szPath, UBYTE isFast);\n\n/**\n * @brief Loads SFX from given file.\n * Note that this function sets SFX period based on currently set PAL/NTSC video\n * mode. If you plan to change it after loading SFX, be sure to adjust\n * the period value for new mode.\n * @note This function may use OS.\n *\n * @param pFileSfx Handle to the .sfx file. Will be closed on function return.\n * @param isFast Set to 1 if you wish to load SFX to FAST memory.\n * Useful for software-based audio-mixing, unusable with ptplayer.\n * @return Newly loaded SFX.\n *\n * @see ptplayerSfxDestroy()\n * @see ptplayerSfxPlay()\n */\ntPtplayerSfx *ptplayerSfxCreateFromFd(tFile *pFileSfx, UBYTE isFast);\n\n/**\n * @brief Destroys given SFX, freeing its resources to OS.\n * @note This function may use OS.\n *\n * @param pSfx SFX to be destroyed.\n *\n * @see ptplayerSfxCreateFromFd()\n */\nvoid ptplayerSfxDestroy(tPtplayerSfx *pSfx);\n\n/**\n * @brief Request playing of a prioritized external sound effect, either on a\n * fixed channel or on the most unused one.\n *\n * When multiple samples are assigned to the same channel the lower priority\n * sample will be replaced. When priorities are the same, then the older sample\n * is replaced.\n * The chosen channel is blocked for music until the effect has completely\n * been replayed.\n *\n * @param pSfx SFX sample to be played. Must be allocated in CHIP memory.\n * @param bChannel Selected replay channel (0..3), PTPLAYER_SFX_CHANNEL_ANY\n * selects best channel.\n * @param ubVolume Playback volume 0..64, unaffected by the song's master volume.\n * @param ubPriority Playback priority. The bigger the value, the higher\n * the priority. Must be non-zero.\n *\n * @see ptplayerSetMusicChannelMask()\n * @see ptplayerSfxPlayLooped()\n */\nvoid ptplayerSfxPlay(\n\tconst tPtplayerSfx *pSfx, UBYTE ubChannel, UBYTE ubVolume, UBYTE ubPriority\n);\n\n/**\n * @brief Request playing of a looped external sound effect, on a fixed channel.\n *\n * @param pSfx Sfx sample to be played. Must be allocated in CHIP memory.\n * @param ubChannel Selected replay channel (0..3).\n * @param ubVolume Playback volume 0..64, unaffected by the song's master volume.\n *\n * @see ptplayerSfxPlay()\n */\nvoid ptplayerSfxPlayLooped(\n\tconst tPtplayerSfx *pSfx, UBYTE ubChannel, UBYTE ubVolume\n);\n\n/**\n * @brief Stops SFX played on given channel.\n *\n * @param ubChannel Selected SFX channel (0..3).\n */\nvoid ptplayerSfxStopOnChannel(UBYTE ubChannel);\n\n/**\n * @brief Configure behavior on song being played to the end.\n * By default the player loops the song indefinitely.\n *\n * If you want to repeat the song given number of times, disable repeats\n * and put additional logic in cbSongEnd.\n *\n * @param isRepeat Set to 1 for endless repeat, 0 makes the song play only once.\n * @param cbSongEnd Pointer to song end callback - set to zero if not needed.\n */\nvoid ptplayerConfigureSongRepeat(UBYTE isRepeat, tPtplayerCbSongEnd cbSongEnd);\n\n/**\n * @brief Waits until all sound effects have been played.\n */\nvoid ptplayerWaitForSfx(void);\n\nUBYTE ptplayerSfxLengthInFrames(const tPtplayerSfx *pSfx);\n\n/**\n * @brief Loads MOD sample pack from file at given path.\n * @note This function may use OS.\n *\n * @param szPath Path to sample pack to be loaded.\n * @return Pointer to newly allocated sample pack, zero on failure.\n */\ntPtplayerSamplePack *ptplayerSampleDataCreateFromPath(const char *szPath);\n\n/**\n * @brief Loads MOD sample pack from file at given path.\n * @note This function may use OS.\n *\n * @param pFileSamples Handle to the sample pack file to be loaded. Will be closed on function return.\n * @return Pointer to newly allocated sample pack, zero on failure.\n */\ntPtplayerSamplePack *ptplayerSampleDataCreateFromFd(tFile *pFileSamples);\n\n/**\n * @brief Destroys given sample pack, freeing its resources to OS.\n * @note This function may use OS.\n *\n * @param pSamplePack Sample pack to be destroyed.\n */\nvoid ptplayerSamplePackDestroy(tPtplayerSamplePack *pSamplePack);\n\n/**\n * @brief Sets the function to call on parsing the E8 command.\n *\n * @param cbOnE8 Function to be called. E8 argument nibble is passed\n * as argument. Set to zero if not needed.\n */\nvoid ptplayerSetE8Callback(tPtplayerCbE8 cbOnE8);\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif // _ACE_MANAGERS_PTPLAYER_H_\n"
  },
  {
    "path": "include/ace/managers/rand.h",
    "content": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at http://mozilla.org/MPL/2.0/. */\n\n#ifndef _ACE_MANAGERS_RAND_H_\n#define _ACE_MANAGERS_RAND_H_\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n#include <ace/types.h>\n\n//---------------------------------------------------------------------- DEFINES\n\n//------------------------------------------------------------------------ TYPES\n\ntypedef struct _tRandManager {\n\tUWORD uwState1;\n\tUWORD uwState2;\n} tRandManager;\n\n//-------------------------------------------------------------------- FUNCTIONS\n\n/**\n * @brief Initializes random number generator with given seed value.\n * You must call it at least once before using other rand fns.\n *\n * Both seed values must be non-zero!\n *\n * @param pRand Instance of RNG to use.\n * @param uwSeed1 First part of seed value for RNG.\n * @param uwSeed2 Second part of seed value for RNG.\n * @see randCreate()\n */\nvoid randInit(tRandManager *pRand, UWORD uwSeed1, UWORD uwSeed2);\n\n/**\n * @brief Allocates and initializes new random number generator.\n *\n * @param uwSeed1 First part of seed value for RNG.\n * @param uwSeed2 Second part of seed value for RNG.\n * @return New instance of random number generator.\n * @see randInit()\n * @see randDestroy()\n */\ntRandManager *randCreate(UWORD uwSeed1, UWORD uwSeed2);\n\n/**\n * @brief Destroys previously allocated instance of random number generator.\n *\n * @param pRand Instance of random number generator to destroy.\n * @see randCreate()\n */\nvoid randDestroy(tRandManager *pRand);\n\n/**\n * @brief Returns the random number value from range of all 16-bit values.\n *\n * @param pRand Instance of RNG to use.\n * @return Next random value.\n */\nUWORD randUw(tRandManager *pRand);\n\n/**\n * @brief Returns the random value from 0 up to uwMax, including uwMax.\n *\n * @param pRand Instance of RNG to use.\n * @param uwMax Upper bound of the random value.\n * @return Next random value constrained in specified boundaries.\n */\nUWORD randUwMax(tRandManager *pRand, UWORD uwMax);\n\n/**\n * @brief Returns the random value between uwMin and uwMax, including uwMin and uwMax.\n *\n * @param pRand Instance of RNG to use.\n * @param uwMin Lower bound of the random value.\n * @param uwMax  Upper bound of the random value.\n * @return Next random value constrained in specified boundaries.\n */\nUWORD randUwMinMax(tRandManager *pRand, UWORD uwMin, UWORD uwMax);\n\n/**\n * @brief Returns the random 32-bit number.\n *\n * Operating on 32-bit values on OCS is considerably slower than 16-bit,\n * so use 16-bit randomness where possible.\n *\n * Internally, this function merges two 16-bit random numbers into a 32-bit one,\n * so quality of this RNG is quite bad.\n *\n * @param pRand Instance of RNG to use.\n * @return Next random 32-bit value.\n * @see randUw()\n */\nULONG randUl(tRandManager *pRand);\n\nULONG randUlMax(tRandManager *pRand, ULONG ulMax);\n\nULONG randUlMinMax(tRandManager *pRand, ULONG ulMin, ULONG ulMax);\n\n//---------------------------------------------------------------------- GLOBALS\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif // _ACE_MANAGERS_RAND_H_\n"
  },
  {
    "path": "include/ace/managers/sprite.h",
    "content": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at http://mozilla.org/MPL/2.0/. */\n\n#ifndef _ACE_MANAGERS_SPRITE_H_\n#define _ACE_MANAGERS_SPRITE_H_\n\n/**\n * @file sprite.h\n * @brief The basic sprite manager. Sets up the chained sprite list for each\n * of hardware sprite channels.\n *\n * @todo Add support for chained sprites - only one per channel atm\n * @todo Add support for attached (16-color) sprites?\n * @todo AGA differences?\n * @todo Separate spriteAdd/spriteRemove from spriteCreate/spriteDestroy\n * @todo Make allocations optional, allow using spriteInit(tSprite *) instead of Create/Destroy\n * @todo Allow using fragments of bitmap (specified Y offset) for sprite tiles support. How to solve metadata writing?\n */\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n#include <ace/utils/bitmap.h>\n#include <ace/utils/extview.h>\n\ntypedef struct tSprite {\n\ttBitMap *pBitmap;\n\tWORD wX; ///< X position, measured from the left of the view.\n\tWORD wY; ///< Y position, measured from the top of the view.\n\tUWORD uwHeight;\n\tUBYTE ubChannelIndex;\n\tUBYTE isEnabled;\n\tUBYTE isHeaderToBeUpdated;\n\tUBYTE isAttached; // Odd Sprites Only.\n} tSprite;\n\n/**\n * @brief Initializes the hardware sprite manager.\n *\n * @note This function may temporarily re-enable OS.\n * @note Be sure to enable sprites by turning on sprite DMA as well as disable\n * unused sprites.\n * @note This function doesn't handle the mouse input etc. automatically,\n * since one may want to control it with joy, keyboard or in other kind of way.\n *\n * @param pView View used for displaying sprites.\n * @param uwRawCopPos In raw mode, specifies an offset on where\n * the sprite commands should reside. Requires space of 16 copper commands.\n * @param pBlankSprite 2 words of CHIP memory (the blank sprite control words).\n * Pass NULL to let the manager deal with the blank sprite memory.\n *\n * @see spriteDisableInCopBlockMode()\n * @see spriteDisableInCopRawMode()\n * @see systemSetDmaBit()\n * @see spriteManagerDestroy()\n */\nvoid spriteManagerCreate(const tView *pView, UWORD uwRawCopPos, ULONG pBlankSprite[1]);\n\n/**\n * @brief Destroys the hardware sprite manager.\n * This also removes all registered sprites in the process.\n *\n * @note This function may temporarily re-enable OS.\n *\n * @see spriteManagerCreate().\n */\nvoid spriteManagerDestroy(void);\n\n/**\n * @brief Add sprite on selected hardware channel.\n * Currently, only single sprite per channel is supported.\n *\n * @note This function may temporarily re-enable OS.\n *\n * @param ubChannelIndex Index of the channel. 0 is the first channel.\n * @param pBitmap Bitmap to be used to display sprite. See spriteSetBitmap()'s\n * documentation for relevant constraints.\n * @return Newly created sprite struct on success, 0 on failure.\n *\n * @see spriteRemove()\n * @see spriteSetBitmap()\n */\ntSprite *spriteAdd(UBYTE ubChannelIndex, tBitMap *pBitmap);\n\n/**\n * @brief Removes given sprite from the display and destroys its struct.\n *\n * @note This function may temporarily re-enable OS.\n *\n * @param pSprite Sprite to be destroyed.\n * @see spriteAdd()\n */\nvoid spriteRemove(tSprite *pSprite);\n\n/**\n * @brief Changes bitmap image used to display the sprite.\n * Also resizes sprite to bitmap height.\n *\n * @note The sprite will write to the bitmap's bitplanes to update its control\n * words. If you need to use same bitmap for different sprites, be sure to have\n * separate copies.\n *\n * @param pSprite Sprite of which bitmap is to be updated.\n * @param pBitmap Bitmap to be used for display/control data. The bitmap must be\n * in 2BPP interleaved format as well as start and end with an empty line,\n * which will not be displayed but used for storing control data.\n */\nvoid spriteSetBitmap(tSprite *pSprite, tBitMap *pBitmap);\n\n/**\n * @brief Overrides sprite height to given value.\n * Also sets metadata update pending flag.\n *\n * @param pSprite Sprite of which height is to be changed.\n * @param uwHeight New sprite height. Maximum is 511.\n */\nvoid spriteSetHeight(tSprite *pSprite, UWORD uwHeight);\n\n/**\n * @brief Enables or disables a given sprite.\n *\n * @param pSprite Sprite to be enabled.\n * @param isEnabled Set to 1 to enable sprite, otherwise set to 0.\n */\nvoid spriteSetEnabled(tSprite *pSprite, UBYTE isEnabled);\n\n/**\n * @brief Sets whether the sprite is an attached sprite.\n * Attached sprites are only available on odd sprite channels.\n *\n * @param isAttached Set to 1 to enable sprite attachment, otherwise set to 0.\n *\n * @see spriteProcess()\n */\nvoid spriteSetAttached(tSprite *pSprite, UBYTE isAttached);\n\n/**\n * @brief Sets metadata update as pending. Be sure to call it after\n * changing sprite's position, sizing or pointer to the next sprite.\n *\n * Multiple operations on sprite may independently require rebuilding\n * its metadata.\n * This function marks it as invalid so that it will be rebuilt only once\n * by spriteProcess() later on.\n *\n * @param pSprite Sprite of which metadata should be set to pending update.\n *\n * @see spriteProcess()\n */\nvoid spriteRequestMetadataUpdate(tSprite *pSprite);\n\n/**\n * @brief Updates the sprite's metadata if set as requiring update.\n * Be sure to call it at least whenever sprite's metadata needs updating.\n *\n * @param pSprite Sprite of which screen position is to be updated.\n *\n * @see spriteRequestMetadataUpdate()\n * @see spriteProcessChannel()\n */\nvoid spriteProcess(tSprite *pSprite);\n\n/**\n * @brief Updates the given sprite channel.\n * Be sure to call it whenever the first sprite in channel have changed\n * and/or was enabled/disabled.\n *\n * @param ubChannelIndex\n *\n * @see spriteProcess()\n */\nvoid spriteProcessChannel(UBYTE ubChannelIndex);\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif // _ACE_MANAGERS_SPRITE_H_\n"
  },
  {
    "path": "include/ace/managers/state.h",
    "content": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at http://mozilla.org/MPL/2.0/. */\n\n#ifndef _ACE_MANAGERS_STATE_H_\n#define _ACE_MANAGERS_STATE_H_\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n#include <ace/types.h> // Amiga typedefs\n\n/* Types */\n\ntypedef void (*tStateCb)(void);\n\n/**\n * State struct.\n */\ntypedef struct _tState {\n\ttStateCb cbCreate;     ///< Optional callback that fires when state manager\n\t                       ///< enters to this state.\n\n\ttStateCb cbLoop;       ///< Optional callback that fires at manager process.\n\n\ttStateCb cbDestroy;    ///< Optional callback that fires when state manager\n\t                       ///< exists from this state.\n\n\ttStateCb cbSuspend;    ///< Optional callback that fires when state manager\n\t                       ///< pushes new state over this state.\n\n\ttStateCb cbResume;     ///< Optional callback that fires when state manager\n\t                       ///< pops old state over this state.\n\n\tstruct _tState *pPrev; ///< Optional pointer to previous state.\n\t                       ///< Zero if there is no previous state. Will be\n\t                       ///< overriden when pushed into state manager.\n} tState;\n\n/**\n * State manager struct.\n */\ntypedef struct _tStateManager {\n\ttState *pCurrent; ///< Pointer to currently handled state.\n} tStateManager;\n\n/* Functions */\n\n/**\n * Initializes state manager.\n * @see stateManagerDestroy()\n */\ntStateManager *stateManagerCreate(void);\n\n/**\n * Cleans up after state manager.\n * @param pStateManager: Pointer to state manager previously created\n *        with stateManagerCreate.\n * @see stateManagerCreate()\n */\nvoid stateManagerDestroy(tStateManager *pStateManager);\n\n/**\n * Initializes state callbacks collection and chaining.\n * @param cbCreate: Callback that fires when state manager enters to this state.\n * @param cbLoop: Callback that fires at manager process.\n * @param cbDestroy: Callback that fires when state manager exists from this state.\n * @param cbSuspend: Callback that fires when state manager pushes new state over this state.\n * @param cbResume: Callback that fires when state manager pops old state over this state.\n * @see stateDestroy()\n */\ntState *stateCreate(\n\ttStateCb cbCreate, tStateCb cbLoop, tStateCb cbDestroy,\n\ttStateCb cbSuspend, tStateCb cbResume\n);\n\n/**\n * Cleans up after state.\n * @param pState: Pointer to state previously created with stateCreate.\n * @see stateCreate()\n */\nvoid stateDestroy(tState *pState);\n\n/**\n * Pushes given state over current state in given state manager. Calls cbSuspend\n * on old state and cbCreate on new state. Will update pPrev in given state to\n * point the old one.\n * @param pStateManager: Pointer to desired state manager where push will happen.\n * @param pState: Pointer to desired state which will be pushed.\n * @see statePop()\n * @see statePopAll()\n * @see stateChange()\n */\nvoid statePush(tStateManager *pStateManager, tState *pState);\n\n/**\n * Pops single state from given state manager. Calls cbDestroy on current state\n * and cbResume on previous state.\n * @param pStateManager: Pointer to desired state manager where pop will happen.\n * @see statePop()\n * @see statePopAll()\n * @see stateChange()\n */\nvoid statePop(tStateManager *pStateManager);\n\n/**\n * Pops all states from given state manager. Calls cbDestroy on all states\n * when sets pCurrent to zero.\n * @param pStateManager: Pointer to desired state manager where pop will happen.\n * @see statePop()\n * @see statePopAll()\n * @see stateChange()\n */\nvoid statePopAll(tStateManager *pStateManager);\n\n/**\n * Swaps state from given state manager with given state. Calls cbDestroy on\n * previous state and cbCreate on new state.\n * @param pStateManager: Pointer to desired state manager where pop will happen.\n * @param pState: Pointer to desired state which will be swapped.\n * @see statePop()\n * @see statePopAll()\n * @see stateChange()\n */\nvoid stateChange(tStateManager *pStateManager, tState *pState);\n\n/**\n * Calls current state's cbLoop on given state manager,\n * @param pStateManager: Pointer to desired state manager too call cbLoop.\n */\nvoid stateProcess(tStateManager *pStateManager);\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif // _ACE_MANAGERS_STATE_H_\n"
  },
  {
    "path": "include/ace/managers/system.h",
    "content": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at http://mozilla.org/MPL/2.0/. */\n\n#ifndef _ACE_MANAGERS_SYSTEM_H_\n#define _ACE_MANAGERS_SYSTEM_H_\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n#include <graphics/gfxbase.h> // Required for GfxBase\n#include <ace/types.h>\n#include <ace/utils/custom.h>\n\n//---------------------------------------------------------------------- DEFINES\n\n//------------------------------------------------------------------------ TYPES\n\ntypedef void (*tAceIntHandler)(\n\tREGARG(volatile tCustom *pCustom, \"a0\"), REGARG(volatile void *pData, \"a1\")\n);\n\ntypedef void (*tKeyInputHandler)(UBYTE ubRawKeyCode);\n\n//-------------------------------------------------------------------- FUNCTIONS\n\n/**\n * @brief The startup code to give ACE somewhat initial state.\n * Prepares OS for enabling / disabling. Disables as much of it as possible,\n * but leaves it in enabled state.\n * This is the first thing you should call in your ACE app.\n */\nvoid systemCreate(void);\n\n/**\n * @brief Cleans up after app, restores anything that systemCreate took over.\n * After running the function, the system to its state before running your app.\n * This is the last thing you should call in your ACE app.\n */\nvoid systemDestroy(void);\n\nvoid systemKill(const char *szMsg);\n\nvoid systemUse(void);\n\nvoid systemUnuse(void);\n\nUBYTE systemIsUsed(void);\n\nvoid systemGetBlitterFromOs(void);\n\nvoid systemReleaseBlitterToOs(void);\n\nUBYTE systemBlitterIsReleasedToOs(void);\n\nvoid systemDump(void);\n\nvoid systemSetKeyInputHandler(tKeyInputHandler cbKeyInputHandler);\n\nvoid systemSetInt(UBYTE ubIntNumber, tAceIntHandler pHandler, void *pIntData);\n\nvoid systemSetCiaInt(\n\tUBYTE ubCia, UBYTE ubIntBit, tAceIntHandler cbHandler, void *pIntData\n);\n\nvoid systemSetCiaCr(UBYTE ubCia, UBYTE isCrB, UBYTE ubCrValue);\n\nvoid systemSetDmaBit(UBYTE ubDmaBit, UBYTE isEnabled);\n\nvoid systemSetDmaMask(UWORD uwDmaMask, UBYTE isEnabled);\n\nvoid systemSetTimer(UBYTE ubCia, UBYTE ubTimer, UWORD uwTicks);\n\nvoid systemIdleBegin(void);\n\nvoid systemIdleEnd(void);\n\nUBYTE systemGetVerticalBlankFrequency(void);\n\nUBYTE systemIsPal(void);\n\nvoid systemCheckStack(void);\n\n/**\n * @brief Returns the major system (exec.library) version from the OS.\n * See https://wiki.amigaos.net/wiki/AmigaOS_Versions to determine to which\n * kickstart corresponds given number.\n *\n * @return Major component of version of running exec.library. Zero if couldn't\n * be read.\n */\nUWORD systemGetVersion(void);\n\nUBYTE systemIsStartVolumeWritable(void);\n\n/**\n * Disable caches on 680x0 CPUs. Previous cache control words\n * are stored so they can later be restored with\n * systemRestoreCpuCaches.\n *\n * @see systemRestoreCpuCaches\n */\nvoid systemDisableCpuCaches();\n\n/**\n * Restore cache control settings after a previous call to\n * systemDisableCpuCaches.\n *\n * @see systemDisableCpuCaches\n */\nvoid systemRestoreCpuCaches();\n\n//---------------------------------------------------------------------- GLOBALS\n\nextern struct GfxBase *GfxBase;\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif // _ACE_MANAGERS_SYSTEM_H_\n"
  },
  {
    "path": "include/ace/managers/timer.h",
    "content": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at http://mozilla.org/MPL/2.0/. */\n\n#ifndef _ACE_MANAGERS_TIMER_H_\n#define _ACE_MANAGERS_TIMER_H_\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n#ifdef AMIGA\n#include <clib/exec_protos.h> // Amiga typedefs\n#include <exec/interrupts.h>  // struct Interrupt\n#include <hardware/intbits.h> // INTB_VERTB\n#endif // AMIGA\n\n#include <ace/types.h>\n#include <ace/managers/memory.h>\n#include <ace/utils/custom.h>\n\n/* Types */\n\n/**\n * Timer manager structure\n * ulGameTicks should be used by all timers, as it won't update during pause\n * Game pause should be implemented as setting ubPause to 1\n * and still calling timerProcess during pause loop\n */\ntypedef struct _tTimerManager {\n\tULONG ulGameTicks;             /// Actual ticks passed in game\n\tULONG ulLastTime;              /// Internal - used to update ulGameTicks\n\tvolatile UWORD uwFrameCounter; /// Incremented by VBlank interrupt\n\tUBYTE ubPaused;                /// 1: pause on\n} tTimerManager;\n\n/* Globals */\nextern tTimerManager g_sTimerManager;\n\n/* Functions */\n\n/**\n * Creates Vertical Blank server for counting frames.\n */\nvoid timerCreate(void);\n\n/**\n * Removes Vertical Blank server.\n */\nvoid timerDestroy(void);\n\n/**\n * Gets current time based on frame number\n * One tick equals: PAL - 20ms, NTSC - 16.67ms\n * Max time capacity: 33 months\n */\nULONG timerGet(void);\n\n/**\n * Gets as precise current time as possible\n * Implementation based on ray position and frame number\n * One tick equals: PAL - 0.40us, NTSC - 0.45us\n * Max time capacity: 1715s (28,5 min)\n */\nULONG timerGetPrec(void);\n\n/**\n * Gets time difference between two times\n * For use on both precise and frame time\n */\nULONG timerGetDelta(ULONG ulStart, ULONG ulStop);\n\n/**\n * Returns if timer has passed without updating its state\n */\nUBYTE timerPeek(ULONG *pTimer, ULONG ulTimerDelay);\n\n/**\n * Returns if timer has passed\n * If passed, its state gets resetted and countdown starts again\n */\nUBYTE timerCheck(ULONG *pTimer,ULONG ulTimerDelay);\n\n/**\n * Updates game ticks if game not paused\n */\nvoid timerProcess(void);\n\n/**\n * Formats precise time to human readable form on supplied buffer\n * Current version works correctly only on ulPrecTime < 0xFFFFFFFF/4 (7 min)\n * and there seems to be no easy fix for this\n */\nvoid timerFormatPrec(char *szBfr, ULONG ulPrecTime);\n\n/**\n *  Min number of us to wait: 5. It is recommended to wait for multiples of 5us.\n */\nvoid timerWaitUs(UWORD uwUsCnt);\n\nvoid timerOnInterrupt(void);\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif // _ACE_MANAGERS_TIMER_H_\n"
  },
  {
    "path": "include/ace/managers/viewport/camera.h",
    "content": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at http://mozilla.org/MPL/2.0/. */\n\n#ifndef _ACE_MANAGERS_VIEWPORT_CAMERA_H_\n#define _ACE_MANAGERS_VIEWPORT_CAMERA_H_\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n/**\n * 2D Camera manager\n * Keeps track of previous and current XY\n * Datasource only - scrolling etc. should be done as separate managers\n * All coords are generally used as top-left position of camera unless specified otherwise\n */\n\n#include <ace/types.h>\n#include <ace/utils/extview.h>\n\ntypedef struct _tCameraManager {\n\ttVpManager sCommon;\n\ttUwCoordYX uPos;        ///< Current camera pos\n\ttUwCoordYX uLastPos[2]; ///< Previous camera pos\n\ttUwCoordYX uMaxPos;     ///< Max camera pos: world W&H - camera W&H\n\tUBYTE ubBfr;            ///< Currently used buffer for double buffering\n\tUBYTE isDblBfr;\n} tCameraManager;\n\ntCameraManager *cameraCreate(\n\ttVPort *pVPort, UWORD uwPosX, UWORD uwPosY, UWORD uwMaxX, UWORD uwMaxY,\n\tUBYTE isDblBfr\n);\n\nvoid cameraDestroy(tCameraManager *pManager);\nvoid cameraProcess(tCameraManager *pManager);\n\nvoid cameraReset(\n\ttCameraManager *pManager,\n\tUWORD uwPosX, UWORD uwPosY, UWORD uwMaxX, UWORD uwMaxY, UBYTE isDblBfr\n);\n\nvoid cameraSetCoord(tCameraManager *pManager, UWORD uwX, UWORD uwY);\n\nvoid cameraMoveBy(tCameraManager *pManager, WORD wDx, WORD wDy);\n\nvoid cameraCenterAt(tCameraManager *pManager, UWORD uwAvgX, UWORD uwAvgY);\n\nUBYTE cameraIsMoved(const tCameraManager *pManager);\n\nUWORD cameraGetXDiff(const tCameraManager *pManager);\n\nUWORD cameraGetYDiff(const tCameraManager *pManager);\n\nWORD cameraGetDeltaX(const tCameraManager *pManager);\n\nWORD cameraGetDeltaY(const tCameraManager *pManager);\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif // _ACE_MANAGERS_VIEWPORT_CAMERA_H_\n"
  },
  {
    "path": "include/ace/managers/viewport/scrollbuffer.h",
    "content": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at http://mozilla.org/MPL/2.0/. */\n\n#ifndef _ACE_MANAGERS_VIEWPORT_SCROLLBUFFER_H_\n#define _ACE_MANAGERS_VIEWPORT_SCROLLBUFFER_H_\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n/**\n * Scrollable buffer manager\n * Uses scrolling-trick from aminet to achieve memory-efficient scroll\n * Must be processed as last, because it calls WaitTOF\n * Requires viewport managers:\n * \t- camera\n * TODO: make it work without tileBuffer manager\n */\n\n#include <ace/types.h>\n#include <ace/macros.h>\n#include <ace/types.h>\n#include <ace/utils/custom.h>\n#include <ace/utils/extview.h>\n#include <ace/utils/bitmap.h>\n\n#include <ace/managers/blit.h>\n#include <ace/managers/copper.h>\n#include <ace/managers/viewport/camera.h>\n\n#if defined(ACE_SCROLLBUFFER_POT_BITMAP_HEIGHT)\n#define SCROLLBUFFER_HEIGHT_MODULO(x, h) ((x) & ((h) - 1))\n#else\n#define SCROLLBUFFER_HEIGHT_MODULO(x, h) ((x) % (h))\n#endif\n\n#if defined(ACE_SCROLLBUFFER_ENABLE_SCROLL_X)\n#define SCROLLBUFFER_X_DRAW_MARGIN_SIZE 1\n#else\n#define SCROLLBUFFER_X_DRAW_MARGIN_SIZE 0\n#endif\n\n#if defined(ACE_SCROLLBUFFER_ENABLE_SCROLL_Y)\n#define SCROLLBUFFER_Y_DRAW_MARGIN_SIZE 1\n#else\n#define SCROLLBUFFER_Y_DRAW_MARGIN_SIZE 0\n#endif\n\n// vPort ptr\ntypedef enum tScrollBufferCreateTags {\n\tTAG_SCROLLBUFFER_VPORT =          (TAG_USER|1),\n\n\t// Scrollable area bounds, in pixels\n\tTAG_SCROLLBUFFER_BOUND_WIDTH =    (TAG_USER|2),\n\tTAG_SCROLLBUFFER_BOUND_HEIGHT =   (TAG_USER|3),\n\n\t// Buffer bitmap creation flags\n\tTAG_SCROLLBUFFER_BITMAP_FLAGS =   (TAG_USER|4),\n\tTAG_SCROLLBUFFER_IS_DBLBUF =      (TAG_USER|5),\n\n\t// If in raw mode, offset on copperlist for placing required copper\n\t// instructions, specified in copper instruction count since beginning.\n\tTAG_SCROLLBUFFER_COPLIST_OFFSET_START = (TAG_USER|6),\n\tTAG_SCROLLBUFFER_COPLIST_OFFSET_BREAK = (TAG_USER|7),\n\n\tTAG_SCROLLBUFFER_MARGIN_WIDTH =   (TAG_USER|8),\n} tScrollBufferCreateTags;\n\n#define SCROLLBUFFER_FLAG_COPLIST_RAW 1\n\n/* Types */\n\ntypedef struct _tScrollBufferManager {\n\ttVpManager sCommon;\n\ttCameraManager *pCamera;       ///< Quick ref to camera\n\n\ttBitMap *pFront;               ///< Front buffer in double buffering\n\ttBitMap *pBack;                ///< Back buffer in double buffering\n\tunion {\n\t\ttCopBlock *pStartBlock;    ///< Initial data fetch\n\t\tUWORD uwCopperOffsetStart; ///< Start offset on copperlist in COP_RAW mode.\n\t};                    ///< Select which field is valid based on SCROLLBUFFER_FLAG_COPLIST_RAW\n\tunion {\n\t\ttCopBlock *pBreakBlock;    ///< Bitplane ptr reset\n\t\tUWORD uwCopperOffsetBreak; ///< Break offset on copperlist in COP_RAW mode.\n\t};                    ///< Select which field is valid based on SCROLLBUFFER_FLAG_COPLIST_RAW\n\ttUwCoordYX uBfrBounds;         ///< Real bounds of buffer (includes height reserved for x-scroll)\n\tUWORD uwBmAvailHeight;         ///< Avail height of buffer to blit (excludes height reserved for x-scroll)\n\tUWORD uwVpHeightPrev;          ///< Prev height of related VPort, used to force refresh on change\n\tUWORD uwModulo;                ///< Bitplane modulo\n\tUWORD uwDDfStrt;                ///< Display datafetch start\n\tUWORD uwDDfStop;                ///< Display datafetch stop\n\tUBYTE ubFlags;                 ///< Read only. See SCROLLBUFFER_FLAG_*.\n} tScrollBufferManager;\n\n/* Globals */\n\n/* Functions */\n\n/**\n * Creates scroll manager\n */\ntScrollBufferManager *scrollBufferCreate(void *pTags, ...);\n\nvoid scrollBufferDestroy(tScrollBufferManager *pManager);\n\n/**\n * Scroll buffer process function\n */\nvoid scrollBufferProcess(tScrollBufferManager *pManager);\n\nvoid scrollBufferReset(\n\ttScrollBufferManager *pManager, UBYTE ubMarginWidth,\n\tUWORD uwBoundWidth, UWORD uwBoundHeight, UBYTE ubBitmapFlags, UBYTE isDblBfr\n);\n\n/**\n * Uses unsafe blit copy for using out-of-bound X ccord\n */\nvoid scrollBufferBlitMask(\n\ttBitMap *pSrc, WORD wSrcX, WORD wSrcY,\n\ttScrollBufferManager *pDstManager,\n\tWORD wDstX, WORD wDstY,\n\tWORD wWidth, WORD wHeight,\n\tUWORD *pMsk\n);\n\nUBYTE scrollBufferGetRawCopperlistInstructionCountStart(UBYTE ubBpp);\n\nUBYTE scrollBufferGetRawCopperlistInstructionCountBreak(UBYTE ubBpp);\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif // _ACE_MANAGERS_VIEWPORT_SCROLLBUFFER_H_\n"
  },
  {
    "path": "include/ace/managers/viewport/simplebuffer.h",
    "content": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at http://mozilla.org/MPL/2.0/. */\n\n#ifndef _ACE_MANAGERS_VIEWPORT_SIMPLEBUFFER_H_\n#define _ACE_MANAGERS_VIEWPORT_SIMPLEBUFFER_H_\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n#ifdef AMIGA\n\n/**\n *  Buffer with naive scrolling techniques. Uses loadsa CHIP RAM but there\n *  should'nt be any quirks while using it.\n */\n\n#include <ace/types.h>\n#include <ace/managers/viewport/camera.h>\n#include <ace/utils/bitmap.h>\n#include <ace/utils/tag.h>\n\ntypedef enum tSimpleBufferCreateTags {\n\t// vPort ptr\n\tTAG_SIMPLEBUFFER_VPORT =          (TAG_USER | 1),\n\n\t// Scrollable area bounds, in pixels\n\tTAG_SIMPLEBUFFER_BOUND_WIDTH =    (TAG_USER | 2),\n\tTAG_SIMPLEBUFFER_BOUND_HEIGHT =   (TAG_USER | 3),\n\n\t// Buffer bitmap creation flags\n\tTAG_SIMPLEBUFFER_BITMAP_FLAGS =   (TAG_USER | 4),\n\tTAG_SIMPLEBUFFER_IS_DBLBUF =      (TAG_USER | 5),\n\n\t// If in raw mode, offset on copperlist for placing required copper\n\t// instructions, specified in copper instruction count since beginning.\n\tTAG_SIMPLEBUFFER_COPLIST_OFFSET = (TAG_USER | 6),\n\tTAG_SIMPLEBUFFER_USE_X_SCROLLING = (TAG_USER | 7),\n} tSimpleBufferCreateTags;\n\ntypedef struct _tSimpleBufferManager {\n\ttVpManager sCommon;\n\ttCameraManager *pCamera;\n\t// scroll-specific fields\n\ttBitMap *pFront;       ///< Currently displayed buffer.\n\ttBitMap *pBack;        ///< Buffer for drawing.\n\ttCopBlock *pCopBlock;  ///< CopBlock containing modulo/shift/bitplane cmds\n\ttUwCoordYX uBfrBounds; ///< Buffer bounds in pixels\n\tUBYTE ubFlags;         ///< Read only. See SIMPLEBUFFER_FLAG_*.\n\tUWORD uwCopperOffset;  ///< Offset on copperlist in COP_RAW mode.\n\tUBYTE ubDirtyCounter;  ///< Number of pending copperlist updates.\n} tSimpleBufferManager;\n\n/**\n *  @brief Creates new simple-scrolled buffer manager along with required buffer\n *  bitmap.\n *  This approach is not suitable for big buffers, because you'll run\n *  out of memory quite easily.\n *\n *  @param pTags Initialization taglist.\n *  @param ...   Taglist passed as va_args.\n *  @return Pointer to newly created buffer manager.\n *\n *  @see simpleBufferDestroy\n *  @see simpleBufferSetBitmap\n */\ntSimpleBufferManager *simpleBufferCreate(void *pTags,\t...);\n\n /**\n *  @brief Sets new bitmap to be displayed by buffer manager.\n *  If there was buffer created by manager, be sure to intercept & free it.\n *  Also, both buffer bitmaps must have same BPP, as difference would require\n *  copBlock realloc, which is not implemented.\n *  @param pManager The buffer manager, which buffer is to be changed.\n *  @param pBitMap  New bitmap to be used by manager.\n *\n *  @todo Realloc copper buffer to reflect BPP change.\n */\nvoid simpleBufferSetBitmap(tSimpleBufferManager *pManager, tBitMap *pBitMap);\n\nvoid simpleBufferDestroy(tSimpleBufferManager *pManager);\n\nvoid simpleBufferProcess(tSimpleBufferManager *pManager);\n\nUBYTE simpleBufferIsRectVisible(\n\ttSimpleBufferManager *pManager,\n\tUWORD uwX, UWORD uwY, UWORD uwWidth, UWORD uwHeight\n);\n\nUBYTE simpleBufferGetRawCopperlistInstructionCount(UBYTE ubBpp);\n\n#endif // AMIGA\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif // _ACE_MANAGERS_VIEWPORT_SIMPLEBUFFER_H_\n"
  },
  {
    "path": "include/ace/managers/viewport/tilebuffer.h",
    "content": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at http://mozilla.org/MPL/2.0/. */\n\n#ifndef _ACE_MANAGERS_VIEWPORT_TILEBUFFER_H_\n#define _ACE_MANAGERS_VIEWPORT_TILEBUFFER_H_\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n/**\n * Tilemap buffer manager\n * Provides speed- and memory-efficient tilemap buffer\n * Redraws only 1-tile margin beyond viewport in all dirs\n * Requires viewport managers:\n * \t- camera\n * \t- scroll\n */\n\n#include <ace/types.h>\n#include <ace/utils/extview.h>\n#include <ace/managers/viewport/camera.h>\n#include <ace/managers/viewport/scrollbuffer.h>\n\ntypedef ACE_TILEBUFFER_TILE_TYPE tTileBufferTileIndex;\n\ntypedef enum tTileBufferCreateTags {\n\t/**\n\t * @brief Pointer to parent vPort. Mandatory.\n\t */\n\tTAG_TILEBUFFER_VPORT = (TAG_USER | 1),\n\n\t/**\n\t * @brief Scrollable area bounds, in tiles. Mandatory.\n\t */\n\tTAG_TILEBUFFER_BOUND_TILE_X = (TAG_USER | 2),\n\tTAG_TILEBUFFER_BOUND_TILE_Y = (TAG_USER | 3),\n\n\t/**\n\t * @brief Size of tile, given in bitshift. Set to 4 for 16px, 5 for 32px, etc. Mandatory.\n\t */\n\tTAG_TILEBUFFER_TILE_SHIFT = (TAG_USER | 4),\n\n\t/**\n\t * @brief Buffer bitmap creation flags. Defaults to BMF_CLEAR.\n\t */\n\tTAG_TILEBUFFER_BITMAP_FLAGS = (TAG_USER | 5),\n\n\t/**\n\t * @brief Set this flag to 1 to enable double buffering. Defaults to 0.\n\t */\n\tTAG_TILEBUFFER_IS_DBLBUF =    (TAG_USER | 6),\n\n\t/**\n\t * @brief If in raw copper mode, offset on copperlist for placing required\n\t * copper instructions, specified in copper instruction count since beginning.\n\t */\n\tTAG_TILEBUFFER_COPLIST_OFFSET_START = (TAG_USER | 7),\n\tTAG_TILEBUFFER_COPLIST_OFFSET_BREAK = (TAG_USER | 8),\n\n\t/**\n\t * @brief Pointer to tileset bitmap. Expects it to have all tiles in single\n\t * column. Mandatory.\n\t */\n\tTAG_TILEBUFFER_TILESET = (TAG_USER | 9),\n\n\t/**\n\t * @brief Pointer to callback which gets called in case any tile gets drawn.\n\t *\n\t * Use this to draw extra stuff on top of your tiles.\n\t *\n\t * @see tTileDrawCallback\n\t */\n\tTAG_TILEBUFFER_CALLBACK_TILE_DRAW = (TAG_USER | 10),\n\n\t/**\n\t * @brief Max length of tile redraw queue. Mandatory, must be non-zero.\n\t *\n\t * @see tileBufferQueueProcess()\n\t */\n\tTAG_TILEBUFFER_REDRAW_QUEUE_LENGTH = (TAG_USER | 11),\n\n\t/**\n\t * @brief Maximum tile index used in the tileset.\n\t * Optional, limits the tile lookup table size.\n\t */\n\tTAG_TILEBUFFER_MAX_TILESET_SIZE = (TAG_USER | 12),\n} tTileBufferCreateTags;\n\n/* types */\n\ntypedef void (*tTileDrawCallback)(\n\tUWORD uwTileX, UWORD uwTileY,\n\ttBitMap *pBitMap, UWORD uwBitMapX, UWORD uwBitMapY\n);\n\ntypedef struct tMarginState {\n\tWORD wTilePos; ///< Index of row/col to update\n\tWORD wTileCurr; ///< Index of current tile to update in row/col\n\tWORD wTileEnd;  ///< Index of last+1  tile to update in row/col\n} tMarginState;\n\ntypedef struct tRedrawState {\n#if defined(ACE_SCROLLBUFFER_ENABLE_SCROLL_X)\n\ttMarginState sMarginL; ///< Data for left margin\n\ttMarginState sMarginR; ///< Ditto, right\n#endif\n#if defined(ACE_SCROLLBUFFER_ENABLE_SCROLL_Y)\n\ttMarginState sMarginU; ///< Ditto, up\n\ttMarginState sMarginD; ///< Ditto, down\n#endif\n\t// Vars needed in Process, reset in Create\n#if defined(ACE_SCROLLBUFFER_ENABLE_SCROLL_X)\n\ttMarginState *pMarginX;         ///< Idx of X margin to be redrawn\n\ttMarginState *pMarginOppositeX; ///< Opposite margin of pMarginX\n#endif\n#if defined(ACE_SCROLLBUFFER_ENABLE_SCROLL_Y)\n\ttMarginState *pMarginY;         ///< Idx of Y margin to be redrawn\n\ttMarginState *pMarginOppositeY; ///< Opposite margin of pMarginY\n#endif\n\t// Tile redraw queue\n\ttUwCoordYX *pPendingQueue;\n\tUBYTE ubPendingCount;\n} tRedrawState;\n\ntypedef struct tTileBufferManager {\n\ttVpManager sCommon;\n\ttCameraManager *pCamera;       ///< Quick ref to Camera\n\ttScrollBufferManager *pScroll; ///< Quick ref to Scroll\n\t// Manager vars\n\ttUwCoordYX uTileBounds;       ///< Tile count in x,y\n\tUBYTE ubTileSize;             ///< Tile size in pixels\n\tUBYTE ubTileShift;            ///< Tile size in shift, e.g. 4 for 16: 1 << 4 == 16\n\tUWORD uwMarginedWidth;        ///< Width of visible area + margins\n\tUWORD uwMarginedHeight;       ///< Height of visible area + margins\n\t                              ///  TODO: refresh when scrollbuffer changes\n\ttTileDrawCallback cbTileDraw; ///< Called when tile is redrawn\n\ttTileBufferTileIndex **pTileData; ///< 2D array of tile indices\n\ttBitMap *pTileSet;            ///< Tileset - one tile beneath another\n\tUBYTE **pTileSetOffsets;      ///< Lookup table for tile offsets in pTileSet\n\t// Margin & queue geometry\n\tUBYTE ubMarginXLength; ///< Tile number in margins: left & right\n\tUBYTE ubMarginYLength; ///< Ditto, up & down\n\tUBYTE ubQueueSize;\n\t// Redraw state and double buffering\n\tUBYTE ubStateIdx;\n\ttRedrawState pRedrawStates[2];\n\tULONG ulMaxTilesetSize;\n} tTileBufferManager;\n\n/* globals */\n\n/* functions */\n\n/**\n * @brief Processes tile queue. Typically should be called once per game loop,\n * but other refreshing strategies can be used for better load balancing.\n *\n * @param pManager The tile manager to be processed.\n * @see tileBufferProcess()\n */\nvoid tileBufferQueueProcess(tTileBufferManager *pManager);\n\n/**\n * Tilemap buffer manager create fn. See TAG_TILEBUFFER_* for available options.\n *\n * After calling this function, be sure to do the following:\n * - set initial pos in camera manager,\n * - fill tilemap on .pTileData with tile indices,\n * - call tileBufferRedrawAll()\n *\n * @see tileBufferRedrawAll()\n * @see tileBufferDestroy()\n */\ntTileBufferManager *tileBufferCreate(void *pTags, ...);\n\nvoid tileBufferDestroy(tTileBufferManager *pManager);\n\n/**\n * @brief Processes given tile buffer manager.\n *\n * Typically, redraws one tile for X and one for Y margins.\n * In case of impending display of a margin, redraws all of its remaining tiles.\n * It doesn't redraw manually invalidated/changed tiles!\n *\n * @see tileBufferQueueProcess()\n */\nvoid tileBufferProcess(tTileBufferManager *pManager);\n\nvoid tileBufferReset(\n\ttTileBufferManager *pManager, UWORD uwTileX, UWORD uwTileY,\n\tUBYTE ubBitmapFlags, UBYTE isDblBuf, UWORD uwCoplistOffStart, UWORD uwCoplistOffBreak\n);\n\n/**\n * Redraws tiles on whole screen.\n * \n * Use for init or something like that, as it's slooooooooow.\n * Be sure to have display turned off or palette dimmed since even on double\n * buffering it will redraw both buffers.\n * \n * If you want to only fully redraw the back buffer, use tileBufferRedrawBack.\n *\n * @see tileBufferRedrawBack\n */\nvoid tileBufferRedrawAll(tTileBufferManager *pManager);\n\n/**\n * Redraws the tiles on the entire backbuffer.\n * \n * This method is slower than redrawing only what's needed, but depending on\n * how many tiles need to be redrawn every frame, it may be competitive.\n * When a lot is going on (many BOBs), the code when used with interleaved\n * tilebuffer and tilemap is pretty optimized, to the point that redraw of half a\n * 4bpp low-res screen of 16x16 tiles is possible on an A500. That saves then having\n * to undraw BOBs, and may thus be better und some circumstances.\n */\nvoid tileBufferRedrawBack(tTileBufferManager *pManager);\n\n/**\n * Redraws selected tile, calls custom redraw callback\n * Calculates destination on buffer\n * Use for single redraws\n */\nvoid tileBufferDrawTile(\n\tconst tTileBufferManager *pManager, UWORD uwTileIdxX, UWORD uwTileIdxY\n);\n\n/**\n * Redraws selected tile, calls custom redraw callback\n * Destination coord on buffer must be calculated externally - avoids recalc\n * Use for batch redraws with smart uwBfrXY update\n */\nvoid tileBufferDrawTileQuick(\n\tconst tTileBufferManager *pManager,\n\tUWORD uwTileIdxX, UWORD uwTileIdxY, UWORD uwBfrX, UWORD uwBfrY\n);\n\n/**\n * Redraws all tiles intersecting with given rectangle\n * Only tiles currently on buffer are redrawn\n */\nvoid tileBufferInvalidateRect(\n\ttTileBufferManager *pManager, UWORD uwX, UWORD uwY,\n\tUWORD uwWidth, UWORD uwHeight\n);\n\nvoid tileBufferInvalidateTile(\n\ttTileBufferManager *pManager, UWORD uwTileX, UWORD uwTileY\n);\n\n/**\n * @brief Checks if given tiles is in on currently valid part of bitmap buffer.\n * This excludes potentially dirty outer redraw margin,\n * but includes the valid single-tile inner margin.\n *\n * @param pManager The tile manager to be used.\n * @param uwTileX The X coordinate of tile, in tile-space.\n * @param uwTileY The Y coordinate of tile, in tile-space.\n * @return 1 if tile is on valid part of bitmap buffer, otherwise zero.\n */\nUBYTE tileBufferIsTileOnBuffer(\n\tconst tTileBufferManager *pManager, UWORD uwTileX, UWORD uwTileY\n);\n\nUBYTE tileBufferIsRectFullyOnBuffer(\n\tconst tTileBufferManager *pManager, UWORD uwX, UWORD uwY, UWORD uwWidth, UWORD uwHeight\n);\n\n/**\n * @brief Changes tile at given position to another tile and schedules its\n * redraw using redraw queue.\n *\n * @param pManager The tile manager to be used.\n * @param uwX The X coordinate of tile, in tile-space.\n * @param uwY The Y coordinate of tile, in tile-space.\n * @param Index Index of tile to be placed on given position.\n */\nvoid tileBufferSetTile(\n\ttTileBufferManager *pManager, UWORD uwX, UWORD uwY, tTileBufferTileIndex Index\n);\n\nstatic inline UBYTE tileBufferGetRawCopperlistInstructionCountStart(UBYTE ubBpp) {\n    return scrollBufferGetRawCopperlistInstructionCountStart(ubBpp);\n}\n\nstatic inline UBYTE tileBufferGetRawCopperlistInstructionCountBreak(UBYTE ubBpp) {\n    return scrollBufferGetRawCopperlistInstructionCountBreak(ubBpp);\n}\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif // _ACE_MANAGERS_VIEWPORT_TILEBUFFER_H_\n"
  },
  {
    "path": "include/ace/types.h",
    "content": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at http://mozilla.org/MPL/2.0/. */\n\n#ifndef _ACE_TYPES_H_\n#define _ACE_TYPES_H_\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n#if defined(ACE_DEBUG_ALL) && !defined(ACE_DEBUG)\n#define ACE_DEBUG\n#endif\n\n// Full OS takeover\n#define CONFIG_SYSTEM_OS_TAKEOVER\n// OS-friendly (old) mode\n// #define CONFIG_SYSTEM_OS_FRIENDLY // TODO: implement\n\n#ifdef AMIGA\n#include <exec/types.h>\n#else\n#include <stdint.h>\n\ntypedef uint8_t  UBYTE;\ntypedef uint16_t UWORD;\ntypedef uint32_t ULONG;\n\ntypedef int8_t  BYTE;\ntypedef int16_t WORD;\ntypedef int32_t LONG;\n#endif // AMIGA\n\n// Potential collision with stdio\n#if !defined(ULONG_MAX)\n#define ULONG_MAX 0xFFFFFFFFu\n#endif\n#define UWORD_MAX 0xFFFFu\n#define UBYTE_MAX 0xFFu\n\n#if defined(__CODE_CHECKER__) || defined(__INTELLISENSE__)\n// My realtime source checker has problems with GCC asm() expanded from REGARG()\n// being in fn arg list, so I just use blank defines for it\n#define INTERRUPT\n#define INTERRUPT_END do {} while(0)\n#define HWINTERRUPT\n#define UNUSED_ARG __attribute__((unused))\n#define REGARG(arg, reg) arg\n#define CHIP\n// Data in chip memory. While on Amiga CHIP mem is all one region, GCC needs to tell apart executable from data, from zero-initialized data\n#define CHIP_DATA\n// Code in chip memory. While on Amiga CHIP mem is all one region, GCC needs to tell apart executable from data, from zero-initialized data\n#define CHIP_CODE\n// Zero-initialized data in chip memory. While on Amiga CHIP mem is all one region, GCC needs to tell apart executable from data, from zero-initialized data\n#define CHIP_BSS\n#define FAR\n#define ALWAYS_INLINE\n#define FN_HOTSPOT\n#define FN_COLDSPOT\n#define LIKELY(x) x\n#define UNLIKELY(x) x\n#define BITFIELD_STRUCT struct __attribute__((packed))\n#elif defined(BARTMAN_GCC)\n#define INTERRUPT\n#define INTERRUPT_END do {} while(0)\n#define HWINTERRUPT __attribute__((interrupt))\n#define UNUSED_ARG __attribute__((unused))\n#define REGARG(arg, reg) arg\n#define CHIP __attribute__((section(\".MEMF_CHIP\")))\n// Data in chip memory. While on Amiga CHIP mem is all one region, GCC needs to tell apart executable from data, from zero-initialized data\n// The naming is like this because \"ld\" absorbs \".data.*\" sections, and elf2hunk looks for sections ending in \".MEMF_CHIP\" to put in chip memory\n#define CHIP_DATA __attribute__((section(\".chipdata.MEMF_CHIP\")))\n// Code in chip memory. While on Amiga CHIP mem is all one region, GCC needs to tell apart executable from data, from zero-initialized data\n// The naming is like this because \"ld\" absorbs \".text.*\" sections, and elf2hunk looks for sections ending in \".MEMF_CHIP\" to put in chip memory\n#define CHIP_CODE __attribute__((section(\".chiptext.MEMF_CHIP\")))\n// Zero-initialized data in chip memory. While on Amiga CHIP mem is all one region, GCC needs to tell apart executable from data, from zero-initialized data\n// The naming is like this because \"ld\" absorbs \".bss.*\" sections, and elf2hunk looks for sections ending in \".MEMF_CHIP\" to put in chip memory\n#define CHIP_BSS __attribute__((section(\".chipbss.MEMF_CHIP\")))\n#define FAR\n#define ALWAYS_INLINE __attribute__((always_inline))\n#define FN_HOTSPOT __attribute__((hot))\n#define FN_COLDSPOT __attribute__((cold))\n#define LIKELY(x) __builtin_expect(!!(x), 1)\n#define UNLIKELY(x) __builtin_expect(!!(x), 0)\n#define BITFIELD_STRUCT struct\n#elif defined(__GNUC__) // Bebbo\n#if defined(CONFIG_SYSTEM_OS_FRIENDLY)\n// Interrupt macros for OS interrupts (handlers)\n#define INTERRUPT\n#define INTERRUPT_END asm(\"cmp d0,d0\")\n#elif defined(CONFIG_SYSTEM_OS_TAKEOVER)\n// Interrupt macros for ACE interrupts\n#define INTERRUPT\n#define INTERRUPT_END do {} while(0)\n#endif\n\n#define HWINTERRUPT __attribute__((interrupt))\n#define UNUSED_ARG __attribute__((unused))\n#define REGARG(arg, reg) arg asm(reg)\n#define CHIP __attribute__((chip))\n#define CHIP_DATA __attribute__((chip))\n#define CHIP_CODE __attribute__((chip))\n#define CHIP_BSS __attribute__((chip))\n#define FAR __far\n#define ALWAYS_INLINE __attribute__((always_inline))\n#define FN_HOTSPOT __attribute__((hot))\n#define FN_COLDSPOT __attribute__((cold))\n#define LIKELY(x) __builtin_expect(!!(x), 1)\n#define UNLIKELY(x) __builtin_expect(!!(x), 0)\n#define BITFIELD_STRUCT struct\n#else\n#error \"Compiler not supported!\"\n#endif\n\n// Fast types\n// TODO: AGA: perhaps 32-bit?\ntypedef UWORD FUBYTE;\ntypedef UWORD FUWORD;\ntypedef ULONG FULONG;\ntypedef WORD FBYTE;\ntypedef WORD FWORD;\ntypedef LONG FLONG;\n\n#define PRI_FUBYTE \"hu\"\n#define PRI_FUWORD \"hu\"\n#define PRI_FULONG \"u\"\n#define PRI_FBYTE  \"hd\"\n#define PRI_FWORD  \"hd\"\n#define PRI_FLONG  \"d\"\n\n/**\n * Coord type with fast sorting option\n */\ntypedef union _tUwCoordYX {\n\tULONG ulYX;\n\tstruct {\n\t\tUWORD uwY;\n\t\tUWORD uwX;\n\t};\n} tUwCoordYX;\n\ntypedef union _tUbCoordYX {\n\tUWORD uwYX;\n\tstruct {\n\t\tUBYTE ubY;\n\t\tUBYTE ubX;\n\t};\n} tUbCoordYX;\n\ntypedef struct _tBCoordYX {\n\tBYTE bY;\n\tBYTE bX;\n} tBCoordYX;\n\ntypedef struct _tWCoordYX {\n\tWORD wY;\n\tWORD wX;\n} tWCoordYX;\n\n/**\n * Rectangle type\n */\ntypedef struct _tUwRect {\n\tUWORD uwY;\n\tUWORD uwX;\n\tUWORD uwWidth;\n\tUWORD uwHeight;\n} tUwRect;\n\ntypedef struct _tUwAbsRect {\n\tUWORD uwY1;\n\tUWORD uwX1;\n\tUWORD uwY2;\n\tUWORD uwX2;\n} tUwAbsRect;\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif // _ACE_TYPES_H_\n"
  },
  {
    "path": "include/ace/utils/bitmap.h",
    "content": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at http://mozilla.org/MPL/2.0/. */\n\n#ifndef _ACE_UTILS_BITMAP_H_\n#define _ACE_UTILS_BITMAP_H_\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n#include <ace/types.h>\n#include <ace/utils/file.h>\n\n// File has its own 'flags' field - could be used in new ACE bitmap struct\n#define BITMAP_INTERLEAVED 1\n// FEATURE PROPOSAL:\n// If set, ubBpp shows how many bitplanes are in bitmap, but after last one\n// there is mask attached. Could be useful with c2p transforms - mask could be\n// rotated with bitmap. Mask would be attached and detached with\n// bitmapAttachMask() and bitmapDetachMask() fns.\n#define BITMAP_MASK_ATTACHED 2\n\n/* Types */\n\n#ifdef AMIGA\n#include <clib/graphics_protos.h> // BitMap etc\ntypedef struct BitMap tBitMap;\n#else\ntypedef struct _tBitMap {\n\tUWORD BytesPerRow;\n\tUWORD Rows;\n\tUBYTE Flags;\n\tUBYTE Depth;\n\tUWORD pad;\n\tUWORD *Planes[8];\n} tBitMap;\n#define BMF_CLEAR       (1 << 0)\n#define BMF_DISPLAYABLE (1 << 1)\n#define BMF_INTERLEAVED (1 << 2)\n#define BMF_STANDARD    (1 << 3)\n#define BMF_MINPLANES   (1 << 4)\n#endif // AMIGA\n\n/**\n * @brief Stores bitplanes in FAST memory. Can be handy to load extra bitmaps\n * to non-CHIP mem and copy in their contents when needed.\n */\n#define BMF_FASTMEM (1 << 5)\n\n/**\n * @brief Stores bitplanes in one contiguous chunk of memory, one after another.\n *  This is needed for some optimized routines, e.g. Kalms C2P. *\n */\n#define BMF_CONTIGUOUS (1 << 6)\n\n/**\n * @brief New bitmap format.\n * Don't use until adopted into entire engine - this struct is more like feature\n * request or memo.\n */\ntypedef struct _tAceBitmap {\n\tUWORD uwWidth; ///< Actual width, in pixels.\n\tUWORD uwHeight;\n\tUWORD uwBytesPerRow; ///< Useful during raw ops, faster than (uwWidth+15)>>3.\n\t                     /// Perhaps uwWordsPerRow would be more useful?\n\tUBYTE ubBpp;\n\tUBYTE ubFlags; ///< Interleaved or not\n\tUWORD *pPlanes[8]; ///< OCS uses up to 6, AGA up to 8\n} tAceBitmap;\n\n/* Globals */\n\n/* Functions */\n\n/**\n *  @brief Allocates bitmap of given dimensions and depth.\n *  OS' AllocBitMap is not present on KS1.3, hence this OS-compatible\n *  implementation.\n *\n *  @param uwWidth  Desired bitmap width, in pixels.\n *  @param uwHeight Desired bitmap height, in pixels.\n *  @param ubDepth  Desired bitmap depth (bits per pixel)\n *  @param ubFlags  Bitmap creation flags, see BMF_* defines\n *  @return Newly created OS-compatible bitmap, 0 on error.\n *\n *  @see bitmapDestroy\n *  @see bitmapCreateFromFd\n *  @see bitmapLoadFromFd\n */\ntBitMap* bitmapCreate(\n\tUWORD uwWidth, UWORD uwHeight, UBYTE ubDepth, UBYTE ubFlags\n);\n\n/**\n *  @brief Loads bitmap data from file to already existing bitmap.\n *  If source is smaller than destination, you can use uwStartX & uwStartY\n *  params to load bitmap on given coords.\n *\n *  @param pBitMap Pointer to destination bitmap\n *  @param szFilePath Source bitmap file path.\n *  @param uwStartX Start X-coordinate on destination bitmap, 8-pixel aligned.\n *  @param uwStartY Start Y-coordinate on destination bitmap\n *\n *  @see bitmapCreate\n *  @see bitmapCreateFromFd\n *  @see bitmapCreateFromPath\n *  @see bitmapLoadFromFd\n */\nvoid bitmapLoadFromPath(\n\ttBitMap *pBitMap, const char *szPath, UWORD uwStartX, UWORD uwStartY\n);\n\n/**\n *  @brief Loads bitmap data from file to already existing bitmap.\n *  If source is smaller than destination, you can use uwStartX & uwStartY\n *  params to load bitmap on given coords.\n *\n *  @param pBitMap Pointer to destination bitmap\n *  @param pFile Handle to the bitmap file. Will be closed on function return.\n *  @param uwStartX Start X-coordinate on destination bitmap, 8-pixel aligned.\n *  @param uwStartY Start Y-coordinate on destination bitmap\n *\n *  @see bitmapCreate\n *  @see bitmapCreateFromFd\n *  @see bitmapCreateFromPath\n *  @see bitmapLoadFromPath\n */\nvoid bitmapLoadFromFd(\n\ttBitMap *pBitMap, tFile *pFile, UWORD uwStartX, UWORD uwStartY\n);\n\n/**\n *  @brief Creates bitmap and loads its data from file.\n *  As opposed to bitmapLoadFromPath, this function creates bitmap based\n *  on dimensions, BPP & flags stored in file.\n *\n *  @param szFilePath Source bitmap file path.\n *  @param isFast True to allocate bitmap in FAST RAM\n *  @return Pointer to newly created bitmap based on file, 0 on error.\n *\n *  @see bitmapCreateFromFd\n *  @see bitmapLoadFromFd\n *  @see bitmapLoadFromPath\n *  @see bitmapCreate\n *  @see bitmapDestroy\n */\ntBitMap* bitmapCreateFromPath(const char *szPath, UBYTE isFast);\n\n/**\n *  @brief Creates bitmap and loads its data from file.\n *  As opposed to bitmapLoadFromFd, this function creates bitmap based\n *  on dimensions, BPP & flags stored in file.\n *\n *  @param pFile Handle to the bitmap file. Will be closed on function return.\n *  @param isFast True to allocate bitmap in FAST RAM\n *  @return Pointer to newly created bitmap based on file, 0 on error.\n *\n *  @see bitmapCreateFromPath\n *  @see bitmapLoadFromFd\n *  @see bitmapLoadFromPath\n *  @see bitmapCreate\n *  @see bitmapDestroy\n */\ntBitMap* bitmapCreateFromFd(tFile *pFile, UBYTE isFast);\n\n/**\n *  @brief Destroys given bitmap, freeing its resources to OS.\n *  Be sure to end all blitter & display operations on this bitmap\n *  prior to calling this function.\n *\n *  @param pBitMap Bitmap to be destroyed.\n *\n *  @see bitmapCreate\n *  @see bitmapCreateFromFd\n */\nvoid bitmapDestroy(tBitMap *pBitMap);\n\n/**\n *  @brief Checks if given bitmap is interleaved.\n *  Detection should work on any OS bitmap.\n *\n *  @param pBitMap Bitmap to be checked.\n *  @return non-zero if bitmap is interleaved, otherwise zero.\n */\nUBYTE bitmapIsInterleaved(const tBitMap *pBitMap);\n\n/**\n * @brief Checks if given bitmap is in CHIP memory.\n *\n * @param pBitMap Bitmap to be checked.\n * @return 1 if bitmap is in CHIP memory, otherwise zero.\n */\nUBYTE bitmapIsChip(const tBitMap *pBitMap);\n\n/**\n *  @brief Saves basic Bitmap information to log file.\n *\n *  @param pBitMap Bitmap to be dumped.\n *\n *  @see bitmapSaveBMP\n */\nvoid bitmapDump(const tBitMap *pBitMap);\n\n/**\n * Saves bitmap in ACE .bm format.\n * @param pBitMap Bitmap to be saved.\n * @param szPath  Path of destination file.\n */\nvoid bitmapSave(const tBitMap *pBitMap, const char *szPath);\n\n/**\n *  @brief Saves given Bitmap as BMP file.\n *  Use only for debug purposes, as conversion is outrageously slow.\n *\n *  @param pBitMap    Bitmap to be dumped.\n *  @param pPalette   Palette to be used during export.\n *  @param szFilePath Destination file path.\n */\nvoid bitmapSaveBmp(\n\tconst tBitMap *pBitMap, const UWORD *pPalette, const char *szFileName\n);\n\n/**\n *  @brief Returns bitmap width in bytes.\n *  Direct check to BytesPerRow may lead to errors as in interleaved mode it\n *  stores value multiplied by bitplane count.\n */\nUWORD bitmapGetByteWidth(const tBitMap *pBitMap);\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif // _ACE_UTILS_BITMAP_H_\n"
  },
  {
    "path": "include/ace/utils/bmframe.h",
    "content": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at http://mozilla.org/MPL/2.0/. */\n\n#ifndef _ACE_UTILS_BMFRAME_H_\n#define _ACE_UTILS_BMFRAME_H_\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n#include <ace/utils/bitmap.h>\n#include <ace/managers/blit.h>\n\n/**\n * @brief Draws the border from passed tileset.\n *\n * @param pFrameSet Tileset. Must consist of 9 tiles: NW, N, NE, W, MID, E, SW, S, SE.\n * @param pDest Destination bitmap.\n * @param uwX\n * @param uwY\n * @param ubCols\n * @param ubRows\n * @param ubTileSize\n */\nvoid bmFrameDraw(\n\tconst tBitMap *pFrameSet, tBitMap *pDest,\n\tUWORD uwX, UWORD uwY, UBYTE ubCols, UBYTE ubRows, UBYTE ubTileSize\n);\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif // _ACE_UTILS_BMFRAME_H_\n"
  },
  {
    "path": "include/ace/utils/chunky.h",
    "content": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at http://mozilla.org/MPL/2.0/. */\n\n#ifndef _ACE_UTILS_CHUNKY_H_\n#define _ACE_UTILS_CHUNKY_H_\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n#include <ace/types.h>\n#include <ace/utils/bitmap.h>\n#include <fixmath/fix16.h>\n\n/**\n * @brief Returns color indices for 16 colors in a row starting from supplied\n *        coords.\n *\n * @param pBitMap Bitmap, from which pixel colors will be read\n * @param uwX     Starting X coord, always word-aligned.\n *                E.g. Read from pixel 18 will start it from x = 16 anyway.\n * @param uwY     Row number, from which pixels will be read.\n * @param pOut    Color index output buffer.\n *\n * @see chunkyFromPlanar()\n */\nvoid chunkyFromPlanar16(\n\tconst tBitMap *pBitMap, UWORD uwX, UWORD uwY, UBYTE *pOut\n);\n\n/**\n * @brief Returns color index of selected pixel.\n * Inefficient as hell - use if really needed or for prototyping convenience!\n *\n * @param pBitMap Bitmap, from which pixel color will be read.\n * @param uwX     Pixel X coord.\n * @param uwY     Pixel Y coord.\n * @return Pixels palette color index.\n *\n * @see chunkyFromPlanar16()\n */\nUBYTE chunkyFromPlanar(const tBitMap *pBitMap, UWORD uwX, UWORD uwY);\n\n/**\n * @brief Rotates chunky pixels by given angle, on spefied background.\n *\n * This function uses fixed point from libfixmath, so its speed should be\n * acceptable for precalcs.\n * Also, dr Dobb's implementation is faster, but yields greater errors:\n * http://www.drdobbs.com/architecture-and-design/fast-bitmap-rotation-and-scaling/184416337\n *\n * @param pSource   Source chunky pixels.\n * @param pDest     Destination chunky pixels.\n * @param fSin      Sine value of rotation angle.\n * @param fCos      Cosine value of rotation angle.\n * @param ubBgColor Background color to use if rotation goes out of source.\n * @param wWidth    Source/destination chunky map width.\n * @param wHeight   Ditto, height.\n */\nvoid chunkyRotate(\n\tconst UBYTE *pSource, UBYTE *pDest,\n\tfix16_t fSin, fix16_t fCos,\n\tUBYTE ubBgColor, WORD wWidth, WORD wHeight\n);\n\n/**\n * @brief Puts 16-pixel chunky row on bitmap at given coordinates.\n *\n * This function assumes that chunky pixels are of same depth as bitmap.\n * Higher chunky bits will thus be ignored.\n *\n * @param pIn  Source chunky pixels.\n * @param uwX  Destination start X coordinate.\n * @param uwY  Destination Y coordinate.\n * @param pOut Destination bitmap.\n *\n * @see chunkyFromPlanar16\n * @see chunkyToPlanar\n */\nvoid chunkyToPlanar16(const UBYTE *pIn, UWORD uwX, UWORD uwY, tBitMap *pOut);\n\n/**\n * Puts single chunky pixel on bitmap at given coordinates.\n *\n * Inefficient as hell - use if really needed or for prototyping convenience!\n *\n * @param ubIn: Chunky pixel value (color index).\n * @param uwX: Pixel's x position on bitmap.\n * @param uwY: Pixel's y position on bitmap.\n * @param pOut: Destination bitmap.\n *\n * @see chunkyToPlanar16\n * @see chunkyFromPlanar16\n * @see chunkyFromPlanar\n */\nvoid chunkyToPlanar(const UBYTE ubIn, UWORD uwX, UWORD uwY, tBitMap *pOut);\n\n/**\n * @brief Reads given portion of bitmap to chunky buffer.\n *\n * @param pBitmap Source bitmap image.\n * @param pChunky Desitination chunky buffer.\n * @param uwSrcOffsX X offset of conversion area, in pixels.\n * @param uwSrcOffsY Y offset of conversion area, in pixels.\n * @param uwWidth Width of conversion area, in pixels.\n * @param uwHeight Height of conversion area, in pixels.\n *\n * @see chunkyToBitmap\n */\nvoid chunkyFromBitmap(\n\tconst tBitMap *pBitmap, UBYTE *pChunky,\n\tUWORD uwSrcOffsX, UWORD uwSrcOffsY, UWORD uwWidth, UWORD uwHeight\n);\n\n/**\n * @brief Writes given chunky buffer into specified portion of bitmap\n *\n * @param pChunky Source chunky data buffer.\n * @param pBitmap Destination bitmap.\n * @param uwDstOffsX X offset of conversion area, in pixels.\n * @param uwDstOffsY Y offset of conversion area, in pixels.\n * @param uwWidth Width of conversion area, in pixels.\n * @param uwHeight Height of conversion area, in pixels.\n */\nvoid chunkyToBitmap(\n\tconst UBYTE *pChunky, tBitMap *pBitmap,\n\tUWORD uwDstOffsX, UWORD uwDstOffsY, UWORD uwWidth, UWORD uwHeight\n);\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif // _ACE_UTILS_CHUNKY_H_\n"
  },
  {
    "path": "include/ace/utils/custom.h",
    "content": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at http://mozilla.org/MPL/2.0/. */\n\n#ifndef _ACE_UTILS_CUSTOM_H_\n#define _ACE_UTILS_CUSTOM_H_\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n#include <ace/macros.h>\n\n#ifdef AMIGA\n\n#include <hardware/custom.h> // Custom chip register addresses\n\n#define REGPTR volatile * const\n#define HARDWARE_SPRITE_CHANNEL_COUNT 8\n\ntypedef struct Custom tCustom;\n\n/**\n * Ray position struct.\n * Merges vposr and vhposr read into one.\n * Setting fields as volatile is mandatory for VBCC 0.9d as setting pointer\n * to volatile struct was insufficient.\n */\ntypedef struct _tRayPos {\n\tunion {\n\t\tstruct {\n\t\t\tvolatile unsigned bfLaced:1;   ///< 1 for interlaced screens\n\t\t\tvolatile unsigned bfUnused:14;\n\t\t\tvolatile unsigned bfPosY:9;    ///< PAL: 0..312, NTSC: 0..?\n\t\t\tvolatile unsigned bfPosX:8;    ///< 0..159?\n\t\t};\n\t\tULONG ulValue;\n\t};\n} tRayPos;\n\ntypedef struct _tCopperUlong {\n\tUWORD uwHi; ///< upper WORD\n\tUWORD uwLo; ///< lower WORD\n} tCopperUlong;\n\n/**\n * CIA registers.\n * Borrowed from https://github.com/keirf/Amiga-Stuff\n */\ntypedef struct _tCia {\n\tvolatile UBYTE pra;\n\tvolatile UBYTE _0[0xff];\n\tvolatile UBYTE prb;\n\tvolatile UBYTE _1[0xff];\n\tvolatile UBYTE ddra;\n\tvolatile UBYTE _2[0xff];\n\tvolatile UBYTE ddrb;\n\tvolatile UBYTE _3[0xff];\n\tvolatile UBYTE talo;\n\tvolatile UBYTE _4[0xff];\n\tvolatile UBYTE tahi;\n\tvolatile UBYTE _5[0xff];\n\tvolatile UBYTE tblo;\n\tvolatile UBYTE _6[0xff];\n\tvolatile UBYTE tbhi;\n\tvolatile UBYTE _7[0xff];\n\tvolatile UBYTE todlow;\n\tvolatile UBYTE _8[0xff];\n\tvolatile UBYTE todmid;\n\tvolatile UBYTE _9[0xff];\n\tvolatile UBYTE todhi;\n\tvolatile UBYTE _a[0xff];\n\tvolatile UBYTE b00;\n\tvolatile UBYTE _b[0xff];\n\tvolatile UBYTE sdr;\n\tvolatile UBYTE _c[0xff];\n\tvolatile UBYTE icr;\n\tvolatile UBYTE _d[0xff];\n\tvolatile UBYTE cra;\n\tvolatile UBYTE _e[0xff];\n\tvolatile UBYTE crb;\n\tvolatile UBYTE _f[0xff];\n} tCia;\n\n/**\n * @brief The hardware sprite header. Used to prepare values for sprxpos/sprxctl\n * registers and sprite list headers.\n */\ntypedef union tHardwareSpriteHeader {\n\tstruct {\n\t\tunion {\n\t\t\tstruct {\n\t\t\t\tUBYTE ubStartYLo; ///< Y start position, bits 7..0.\n\t\t\t\tUBYTE ubStartXHi; ///< Upper bits of X start position, bits 8..1.\n\t\t\t};\n\t\t\tUWORD uwRawPos; ///< Sprite's \"position\" word.\n\t\t};\n\t\tunion {\n\t\t\tBITFIELD_STRUCT {\n\t\t\t\tunsigned bfStopY: 8; ///< Y stop position, bits 7..0.\n\t\t\t\tunsigned bfAttach: 1; ///< Set to 1 for attached sprites. Odd sprites only!\n\t\t\t\tunsigned bfReserved: 4;\n\t\t\t\tunsigned bfStartYHi: 1; ///< Y start position, bit 8.\n\t\t\t\tunsigned bfStopYHi: 1; ///< Y stop position, bit 8.\n\t\t\t\tunsigned bfStartXLo: 1; ///< X start position, bit 0.\n\t\t\t};\n\t\t\tUWORD uwRawCtl; ///< Sprite's \"control\" word.\n\t\t};\n\t};\n\tULONG ulRaw;\n} tHardwareSpriteHeader;\n\n/**\n * CIA defines.\n */\n#define CIA_A 0\n#define CIA_B 1\n#define CIA_COUNT 2\n\n#define CIAAPRA_OVL  BV(0)\n#define CIAAPRA_LED  BV(1)\n#define CIAAPRA_CHNG BV(2)\n#define CIAAPRA_WPRO BV(3)\n#define CIAAPRA_TK0  BV(4)\n#define CIAAPRA_RDY  BV(5)\n#define CIAAPRA_FIR0 BV(6)\n#define CIAAPRA_FIR1 BV(7)\n\n#define CIABPRB_STEP BV(0)\n#define CIABPRB_DIR  BV(1)\n#define CIABPRB_SIDE BV(2)\n#define CIABPRB_SEL0 BV(3)\n#define CIABPRB_SEL1 BV(4)\n#define CIABPRB_SEL2 BV(5)\n#define CIABPRB_SEL3 BV(6)\n#define CIABPRB_MTR  BV(7)\n\n#define CIAICRB_TIMER_A 0\n#define CIAICRB_TIMER_B 1\n#define CIAICRB_TOD     2\n#define CIAICRB_SERIAL  3\n#define CIAICRB_FLAG    4\n#define CIAICRB_SETCLR  7\n\n#define CIAICRF_TIMER_A BV(CIAICRB_TIMER_A)\n#define CIAICRF_TIMER_B BV(CIAICRB_TIMER_B)\n#define CIAICRF_TOD     BV(CIAICRB_TOD)\n#define CIAICRF_SERIAL  BV(CIAICRB_SERIAL)\n#define CIAICRF_FLAG    BV(CIAICRB_FLAG)\n#define CIAICRF_SETCLR  BV(CIAICRB_SETCLR)\n\n#define CIACRA_START   BV(0)\n#define CIACRA_PBON    BV(1)\n#define CIACRA_OUTMODE BV(2)\n#define CIACRA_RUNMODE BV(3)\n#define CIACRA_LOAD    BV(4)\n#define CIACRA_INMODE  BV(5)\n#define CIACRA_SPMODE  BV(6)\n\n#define CIACRB_START   BV(0)\n#define CIACRB_PBON    BV(1)\n#define CIACRB_OUTMODE BV(2)\n#define CIACRB_RUNMODE BV(3)\n#define CIACRB_LOAD    BV(4)\n#define CIACRB_INMODE_0 0\n#define CIACRB_INMODE_1 BV(5)\n#define CIACRB_INMODE_2 BV(6)\n#define CIACRB_INMODE_3 (BV(5) | BV(6))\n#define CIACRB_ALARM   BV(7)\n\n/**\n * @brief Gets consistent Timer A value from given CIA chip.\n * Based on https://github.com/keirf/HxC_FF_File_Selector/blob/master/amiga/amiga.c\n * @param pCia Base CIA chip address.\n */\nUWORD ciaGetTimerA(tCia REGPTR pCia);\n\nvoid ciaSetTimerA(tCia REGPTR pCia, UWORD uwTicks);\n\n/**\n * @brief Gets consistent Timer A value from given CIA chip.\n * Based on https://github.com/keirf/HxC_FF_File_Selector/blob/master/amiga/amiga.c\n * @param pCia Base CIA chip address.\n */\nUWORD ciaGetTimerB(tCia REGPTR pCia);\n\nvoid ciaSetTimerB(tCia REGPTR pCia, UWORD uwTicks);\n\n/**\n * @brief Returns the consistence-checked current position of display ray.\n * This function reads custom.vposr and custom.vhposr registers and combines\n * their values into a convenient struct.\n *\n * @return Current position of display ray.\n */\ntRayPos getRayPos(void);\n\nextern tCustom FAR REGPTR g_pCustom;\n\n/**\n * Bitplane display regs with 16-bit access.\n * For use with Copper. Other stuff should use g_pCustom->bplpt\n */\nextern tCopperUlong FAR REGPTR g_pSprFetch;\nextern tCopperUlong FAR REGPTR g_pBplFetch;\nextern tCopperUlong FAR REGPTR g_pCopLc;\nextern tCopperUlong FAR REGPTR g_pCop2Lc;\n\nextern tCia FAR REGPTR g_pCia[CIA_COUNT];\n\n#endif // AMIGA\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif // _ACE_UTILS_CUSTOM_H_\n"
  },
  {
    "path": "include/ace/utils/dir.h",
    "content": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at http://mozilla.org/MPL/2.0/. */\n\n#ifndef _ACE_UTILS_DIR_H\n#define _ACE_UTILS_DIR_H\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n#include <dos/dos.h>\n#include <clib/dos_protos.h>\n#include <ace/types.h>\n\ntypedef struct _tDir {\n\tBPTR pLock;\n\tstruct FileInfoBlock sFileBlock;\n} tDir;\n\n/**\n * @brief Opens directory handle for reading consecutive directory names.\n * On Amiga, this function may use OS.\n *\n * @param szPath Path to directory to be opened.\n * @return tDir* On success, directory handle, otherwise 0.\n *\n * @see dirClose()\n * @see dirRead()\n */\ntDir *dirOpen(const char *szPath);\n\n/**\n * @brief Reads next file name in given directory to buffer of specified length.\n * After reading file name, directory handle is set to read next file.\n * On Amiga, this function may use OS.\n *\n * @param pDir Directory handle.\n * @param szFileName Destination buffer for null-terminated file name.\n * @param uwFileNameMax Length of szFileName buffer. On Amiga, OS limit for file\n *                      names is 108 chars, including null termination.\n * @return UBYTE 1 on success, otherwise false.\n *\n * @see dirOpen()\n * @see dirClose()\n */\nUBYTE dirRead(tDir *pDir, char *szFileName, UWORD uwFileNameMax);\n\n/**\n * @brief Closes directory handle.\n * On Amiga, this function may use OS.\n *\n * @param pDir Directory handle.\n *\n * @see dirOpen()\n */\nvoid dirClose(tDir *pDir);\n\n\n/**\n * @brief Checks if given directory exists and is a directory.\n *\n * @param szPath Directory to be checked.\n * @return Success: 1, otherwise 0.\n *\n * @see dirCreate()\n * @see dirCreatePath()\n */\nUBYTE dirExists(const char *szPath);\n\n/**\n * @brief Creates given directory.\n * This function accepts paths, but will expect that only last directory\n * needs to be created.\n *\n * @param szName Path to directory to be created.\n * @return Success: 1, otherwise 0.\n *\n * @see dirExists()\n * @see dirCreatePath()\n */\nUBYTE dirCreate(const char *szName);\n\n/**\n * @brief Recursively creates given path.\n * This function will continue its work even if part of directory hierarchy\n * already exists.\n * If whole path already exists, it will still treat it as success.\n *\n * @param szPath Path to be created.\n * @return Success: 1, otherwise 0.\n *\n * @see dirExists()\n * @see dirCreate()\n */\nUBYTE dirCreatePath(const char *szPath);\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif // _ACE_UTILS_DIR_H\n"
  },
  {
    "path": "include/ace/utils/disk_file.h",
    "content": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at http://mozilla.org/MPL/2.0/. */\n\n#ifndef _ACE_UTILS_DISK_FILE_H_\n#define _ACE_UTILS_DISK_FILE_H_\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n#include \"file.h\"\n\ntypedef enum tDiskFileMode {\n\tDISK_FILE_MODE_READ,\n\tDISK_FILE_MODE_WRITE,\n} tDiskFileMode;\n\n/**\n * @brief Opens the filesystem file for read/write.\n *\n * @param szPath Path to file to be opened.\n * @param eMode File open mode - see tDiskFileMode\n * @param isUninterrupted Set to 1 if file won't remain opened while\n * you enable/disable OS or meddle with blitter ownership.\n * Speeds up the read/write operations.\n * @return File handle on success, zero on failure.\n */\ntFile *diskFileOpen(const char *szPath, tDiskFileMode eMode, UBYTE isUninterrupted);\n\n/**\n * @brief Check whether file at given path exists and is not a directory.\n *\n * @param szPath Path to file to be checked.\n * @return Success: 1, otherwise 0.\n *\n * @see dirExists()\n */\nUBYTE diskFileExists(const char *szPath);\n\n/**\n * @brief Deletes the selected file.\n *\n * @param szPath Path to file to be deleted.\n * @return 1 on success, otherwise 0, including if file does not exist.\n */\nUBYTE diskFileDelete(const char *szPath);\n\n/**\n * @brief Moves or renames selected file into another file.\n *\n * @param szSource Path to source file to be moved.\n * @param szDest Path to new file destination.\n * @return 1 on success, otherwise 0, including if source file doesn't exist or destination path is already occupied.\n */\nUBYTE diskFileMove(const char *szSource, const char *szDest);\n\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif // _ACE_UTILS_DISK_FILE_H_\n"
  },
  {
    "path": "include/ace/utils/disk_file_private.h",
    "content": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at http://mozilla.org/MPL/2.0/. */\n\n#ifndef _ACE_UTILS_DISK_FILE_PRIVATE_H_\n#define _ACE_UTILS_DISK_FILE_PRIVATE_H_\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n#include <ace/types.h>\n\n#if defined(ACE_FILE_USE_ONLY_DISK)\n#define DISKFILE_PRIVATE\n#else\n#define DISKFILE_PRIVATE static\n#endif\n\nDISKFILE_PRIVATE void diskFileClose(void *pData);\nDISKFILE_PRIVATE ULONG diskFileRead(void *pData, void *pDest, ULONG ulSize);\nDISKFILE_PRIVATE ULONG diskFileWrite(void *pData, const void *pSrc, ULONG ulSize);\nDISKFILE_PRIVATE ULONG diskFileSeek(void *pData, LONG lPos, WORD wMode);\nDISKFILE_PRIVATE ULONG diskFileGetPos(void *pData);\nDISKFILE_PRIVATE ULONG diskFileGetSize(void *pData);\nDISKFILE_PRIVATE UBYTE diskFileIsEof(void *pData);\nDISKFILE_PRIVATE void diskFileFlush(void *pData);\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif // _ACE_UTILS_DISK_FILE_PRIVATE_H_\n"
  },
  {
    "path": "include/ace/utils/endian.h",
    "content": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at http://mozilla.org/MPL/2.0/. */\n\n#ifndef _ACE_UTILS_ENDIAN_H_\n#define _ACE_UTILS_ENDIAN_H_\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n/**\n *  Endian conversion functions.\n *  Allows convenient converting between Little and Big Endian.\n *  @todo Distinguish platform's endian and avoid conversion if endian\n *        is matching.\n */\n\n#include <ace/types.h>\n\n/**\n *  @brief Converts _native_ 16-bit from/to Little (Intel) Endian.\n *\n *  @param uwIn 16-bit value to be converted\n *  @return Supplied value, byte-swapped if neccessary.\n *\n *  @see endianLittle32()\n */\nstatic inline UWORD endianLittle16(UWORD uwIn) {\n#ifdef AMIGA\n\treturn (uwIn << 8) | (uwIn >> 8);\n#else\n\treturn uwIn;\n#endif // AMIGA\n}\n\n/**\n *  @brief Converts big-endian wire format to/from native 16-bit.\n *\n *  Use after reading a big-endian `UWORD` from a file, or before writing one.\n *  On Amiga (big-endian native) this is a no-op.\n *\n *  @param uwIn 16-bit value in wire (big-endian) layout as stored by `fileRead()`.\n *  @return Value in native endian.\n *\n *  @see endianLittle16()\n */\nstatic inline UWORD endianBig16(UWORD uwIn) {\n#ifdef AMIGA\n\treturn uwIn;\n#else\n\treturn (uwIn << 8) | (uwIn >> 8);\n#endif // AMIGA\n}\n\n/**\n *  @brief Converts _native_ 32-bit from/to Little (Intel) Endian.\n *\n *  @param ulIn 32-bit value to be converted\n *  @return Supplied value, byte-swapped if neccessary.\n *\n *  @see endianLittle16()\n */\nstatic inline ULONG endianLittle32(ULONG ulIn) {\n#ifdef AMIGA\n\treturn (ulIn << 24) | ((ulIn & 0xFF00) << 8) | ((ulIn & 0xFF0000) >> 8) | (ulIn >> 24);\n#else\n\treturn ulIn;\n#endif // AMIGA\n}\n\n/**\n *  @brief Converts big-endian wire format to/from native 32-bit.\n *\n *  Use after reading a big-endian `ULONG` from a file, or before writing one.\n *  On Amiga (big-endian native) this is a no-op.\n *\n *  @param ulIn 32-bit value in wire (big-endian) layout as stored by `fileRead()`.\n *  @return Value in native endian.\n *\n *  @see endianLittle32()\n */\nstatic inline ULONG endianBig32(ULONG ulIn) {\n#ifdef AMIGA\n\treturn ulIn;\n#else\n\treturn (ulIn << 24) | ((ulIn & 0xFF00) << 8) | ((ulIn & 0xFF0000) >> 8) | (ulIn >> 24);\n#endif // AMIGA\n}\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif // _ACE_UTILS_ENDIAN_H_\n"
  },
  {
    "path": "include/ace/utils/extview.h",
    "content": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at http://mozilla.org/MPL/2.0/. */\n\n#ifndef _ACE_UTILS_EXTVIEW_H_\n#define _ACE_UTILS_EXTVIEW_H_\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n/**\n *  View, viewport & viewport manager base functions.\n *  @todo viewport resolution, lace & EHB control. Managers should react accordingly.\n */\n\n#include <ace/types.h>\n#include <ace/utils/tag.h>\n#include <ace/managers/log.h>\n#include <ace/managers/memory.h>\n#include <ace/managers/copper.h>\n\ntypedef enum tTagView {\n\t// Copperlist mode: raw/block\n\tTAG_VIEW_COPLIST_MODE      = TAG_USER | 1,\n\t// If in raw mode, specifies copperlist instruction count.\n\tTAG_VIEW_COPLIST_RAW_COUNT = TAG_USER | 2,\n\t// If set to non-zero, view will use first vport's palette as global & ignore other ones.\n\tTAG_VIEW_GLOBAL_PALETTE    = TAG_USER | 3,\n\t// The X value for display window start.\n\tTAG_VIEW_WINDOW_START_X    = TAG_USER | 4,\n\t// The Y value for display window start.\n\tTAG_VIEW_WINDOW_START_Y    = TAG_USER | 5,\n\t// The width of display window.\n\tTAG_VIEW_WINDOW_WIDTH      = TAG_USER | 6,\n\t// The height of display window. Defaults to (lastPalScanline - TAG_VIEW_WINDOW_START_Y)\n\tTAG_VIEW_WINDOW_HEIGHT     = TAG_USER | 7,\n\t// If set to non-zero, view will use first vport's bpp value for whole screen.\n\tTAG_VIEW_GLOBAL_BPP        = TAG_USER | 8,\n\t// If set to non-zero, view will use first vport's horizontal resolution (hires on/off) setting for whole screen.\n\tTAG_VIEW_GLOBAL_HRES       = TAG_USER | 9,\n#ifdef ACE_USE_AGA_FEATURES\n\tTAG_VIEW_USES_AGA          = TAG_USER | 10,\n#endif\n} tTagView;\n\n// Values for TAG_VIEW_COPLIST_MODE\n#define VIEW_COPLIST_MODE_BLOCK COPPER_MODE_BLOCK\n#define VIEW_COPLIST_MODE_RAW   COPPER_MODE_RAW\n\ntypedef enum tTagVport {\n\t// Ptr to parent view\n\tTAG_VPORT_VIEW         = TAG_USER | 1,\n\t// vPort dimensions, in pixels\n\tTAG_VPORT_WIDTH        = TAG_USER | 2,\n\t// vPort height. Defaults to remaining space in view.\n\tTAG_VPORT_HEIGHT       = TAG_USER | 3,\n\t// vPort depth, best effects on OCS with 4 or less since copper is faster\n\tTAG_VPORT_BPP          = TAG_USER | 4,\n\t// Pointer to palette to initialize vPort with and its size, in color count.\n\tTAG_VPORT_PALETTE_PTR  = TAG_USER | 5,\n\tTAG_VPORT_PALETTE_SIZE = TAG_USER | 6,\n\t// Specify vertical offset from previous VPort\n\t// TODO auto CopBlocks for disabling bitplane DMA\n\t// When in raw mode, you have to disable DMA yourself, 'cuz making it work\n\t// automatically would mean passing additional 2 offsets for WAIT/MOVEs for\n\t// disabling/enabling DMA and then wasting all cycles between it for VPort\n\t// manager stuff without letting you including custom instructions in spare\n\t// time.\n\tTAG_VPORT_OFFSET_TOP   = TAG_USER | 7,\n\t// Set to 1 to enable hires mode, set to zero for lores\n\tTAG_VPORT_HIRES        = TAG_USER | 8,\n#ifdef ACE_USE_AGA_FEATURES\n\tTAG_VPORT_USES_AGA     = TAG_USER | 9,\n\tTAG_VPORT_FMODE        = TAG_USER | 10,\n#endif\n} tTagVport;\n\n\n\n/* Types */\n\n/**\n *  View flags.\n */\ntypedef enum tViewFlags {\n\tVIEW_FLAG_GLOBAL_PALETTE = BV(0),\n\tVIEW_FLAG_COPLIST_RAW    = BV(1),\n\tVIEW_FLAG_GLOBAL_BPP     = BV(2),\n\tVIEW_FLAG_GLOBAL_HRES    = BV(3),\n#ifdef ACE_USE_AGA_FEATURES\n\tVIEW_FLAG_GLOBAL_AGA     = BV(4),\n#endif\n} tViewFlags;\n\n/**\n * Viewport flags.\n */\ntypedef enum tVpFlag {\n\tVP_FLAG_HAS_OWN_PALETTE = BV(0),\n\tVP_FLAG_HIRES           = BV(1),\n#ifdef ACE_USE_AGA_FEATURES\n\tVP_FLAG_AGA            = BV(2),\n#endif\n} tVpFlag;\n\n/**\n *  Viewport manager IDs.\n *  Number determines processing order. Camera is last, so rest may see\n *  a difference between its current and previous position\n */\n#define VPM_SCROLL       0\n#define VPM_TILEBUFFER   1\n#define VPM_DOUBLEBUFFER 2\n#define VPM_CAMERA       128\n\n/**\n *  @brief ViewPort manager structure.\n *  Only process and destroy included, each manager has different init params.\n */\ntypedef struct tVpManager {\n\tstruct tVpManager *pNext;                      ///< Pointer to next manager.\n\tvoid  (*process)(struct tVpManager *pManager); ///< Process fn handle.\n\tvoid  (*destroy)(struct tVpManager *pManager); ///< Destroy fn handle.\n\tstruct _tVPort *pVPort;                         ///< Quick ref to VPort.\n\tUBYTE ubId;                                     ///< Manager ID.\n} tVpManager;\n\ntypedef void (*tVpManagerFn)(tVpManager *pManager);\n\n/**\n *  @brief The view structure.\n *  View describes everything what goes to Amiga screen. Each view\n *  is composed of copperlist and viewports.\n */\ntypedef struct tView {\n\tUBYTE ubVpCount;             ///< Viewport count.\n\tUWORD uwFlags;               ///< Creation flags.\n\tUBYTE ubPosX;                ///< Directly populates the DIWSTRT value.\n\tUBYTE ubPosY;                ///< Directly populates the DIWSTRT value.\n\tUWORD uwWidth;\n\tUWORD uwHeight;\n\tUWORD uwBplCon0;             ///< Initial/global bplcon0 values.\n\tstruct _tCopList *pCopList;  ///< Pointer to copperlist.\n\tstruct _tVPort *pFirstVPort; ///< Pointer to first VPort on list.\n} tView;\n\n/**\n *  @brief The viewport structure.\n *  Each viewport has specified resolution, screen dimensions and its own\n *  manager list.\n */\ntypedef struct _tVPort {\n\t// Main\n\ttView *pView;              ///< Pointer to parent tView.\n\tstruct _tVPort *pNext;     ///< Pointer to next tVPort.\n\ttVpManager *pFirstManager; ///< Pointer to first viewport manager on list.\n\ttVpFlag eFlags;             ///< Creation flags.\n\n\t// VPort dimensions\n\tUWORD uwOffsX;  ///< Viewport's X offset on view.\n\tUWORD uwOffsY;  ///< Viewport's Y offset on view.\n\tUWORD uwWidth;  ///< Viewport's width\n\tUWORD uwHeight; ///< Viewport's height\n\n\t// Color info\n\tUBYTE ubBpp;        ///< Bitplane count\n#ifdef ACE_USE_AGA_FEATURES\n\tUBYTE ubFmode;      ///< FMODE value\n#endif\n\tUWORD *pPalette;\n} tVPort;\n\n/* Globals */\n\n/* Functions */\n\n/*=========================== View functions =================================*/\n\n/**\n *  @brief Creates blank tView.\n *\n *  @param pTags Pointer to tag list.\n *  @param ... Tag list, see TAG_VIEW_* defines.\n *  @return initialized View structure.\n *\n *  @see viewDestroy()\n *  @see vPortCreate()\n */\ntView *viewCreate(void *pTags, ...);\n\n/**\n *  @brief Destroys given tView along with attached viewports.\n *\n *  @param pView View to be destroyed.\n *\n *  @see vCreate()\n *  @see vPortDestroy()\n */\nvoid viewDestroy(tView *pView);\n\n/**\n *  @brief Processes all viewport managers attached to view's viewports.\n *\n *  @param pView View to be processed.\n */\nvoid viewProcessManagers(tView *pView);\n\n/**\n *  Updates palette for view, if in global palette mode.\n *\n *  @param pView View to use the colors from.\n */\nvoid viewUpdateGlobalPalette(const tView *pView);\n\n/**\n *  Sets given view as current and displays it on screen.\n *\n *  @param pView View to be set as current.\n */\nvoid viewLoad(tView *pView);\n\n/*=========================== Viewport functions =============================*/\n\n/**\n *  @brief Creates new tVPort inside given view with supplied dimensions and BPP.\n *  Line-spacing shouldn't be required if VPort has common palette with predecessor.\n *\n *  @param pView    Parent view\n *  @param pTagList Pointer to tag list.\n *  @param ...      Tag list, see TAG_VPORT_* defines\n *  @return initialized VPort structure.\n *\n *  @see vPortDestroy()\n */\n tVPort *vPortCreate(void *pTagList, ...);\n\n/**\n *  @brief Destroys given tVPort along with attached managers.\n *\n *  @param pVPort Viewport to be destroyed.\n *\n *  @see vPortCreate()\n */\nvoid vPortDestroy(tVPort *pVPort);\n\n/**\n * @brief Waits for display beam to pass given Y-position on VPort.\n *\n * @param pVPort VPort which has given Y-position.\n * @param uwPosY Y-position on viewport.\n * @param isExact If set to 1, it will wait for exact position.\n * If set to 0, it will return immediately if current position is greater\n * or equal than end position.\n */\nvoid vPortWaitForPos(const tVPort *pVPort, UWORD uwPosY, UBYTE isExact);\n\n/**\n * @brief Waits for display beam to exactly reach end of given VPort.\n * It can be called multiple times to skip given amount of frames.\n * Even if it's called exactly right at the end pos, it will wait for whole next frame.\n *\n * @param pVPort VPort to be passed.\n *\n * @todo Make view offset dependent on DiWStrt.\n */\nvoid vPortWaitForEnd(const tVPort *pVPort);\n\n/**\n * @brief Waits for display beam to pass end of given VPort.\n * This will NOT work when calling multiple times to skip given amount of frames.\n * If beam position is past given point, it will return immediately.\n *\n * @param pVPort\n */\nvoid vPortWaitUntilEnd(const tVPort *pVPort);\n\n/**\n * @brief Processes all managers of given VPort.\n *\n * @param pVPort VPort of which managers should be processed.\n */\nvoid vPortProcessManagers(tVPort *pVPort);\n\n/*=========================== Viewport manager functions =====================*/\n\n/**\n *  @brief Attaches specified VPort manager to given VPort.\n *\n *  @param pVPort     Parent VPort.\n *  @param pVpManager VPort manager to be attached.\n *\n *  @see vPortRmManager()\n *  @see vPortGetManager()\n */\nvoid vPortAddManager(tVPort *pVPort, tVpManager *pVpManager);\n\n/**\n *  @brief Detaches specified manager from VPort and calls its destroy callback.\n *\n *  @param pVPort     Parent VPort.\n *  @param pVpManager VPort manager to be detached.\n *\n *  @see vPortAddManager()\n */\nvoid vPortRmManager(tVPort *pVPort, tVpManager *pVpManager);\n\n/**\n *  @brief Returns maanger with given ID attached to specified VPort.\n *\n *  @param pVPort Parent VPort.\n *  @param ubId   VPort manager ID to be found.\n *  @return if found, pointer to VPort manager, otherwise zero.\n */\ntVpManager *vPortGetManager(tVPort *pVPort, UBYTE ubId);\n\n/*=========================== Viewport copperblock functions =================*/\n\nstruct UCopList *vPortAddCopperBlock(tVPort *pVPort, UWORD uwLength);\n\nvoid vPortRmCopperBlock(tVPort *pVPort, struct UCopList *pUCopList);\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif // _ACE_UTILS_EXTVIEW_H_\n"
  },
  {
    "path": "include/ace/utils/file.h",
    "content": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at http://mozilla.org/MPL/2.0/. */\n\n#ifndef _ACE_UTILS_FILE_H_\n#define _ACE_UTILS_FILE_H_\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n#include <stdio.h>\n#include <ace/types.h>\n\n#define FILE_SEEK_CURRENT SEEK_CUR\n#define FILE_SEEK_SET SEEK_SET\n#define FILE_SEEK_END SEEK_END\n\n#if defined(ACE_FILE_USE_ONLY_DISK)\ntypedef void *tFile;\n#else\ntypedef void (*tCbFileClose)(void *pData);\ntypedef ULONG (*tCbFileRead)(void *pData, void *pDest, ULONG ulSize);\ntypedef ULONG (*tCbFileWrite)(void *pData, const void *pSrc, ULONG ulSize);\ntypedef ULONG (*tCbFileSeek)(void *pData, LONG lPos, WORD wMode);\ntypedef ULONG (*tCbFileGetPos)(void *pData);\ntypedef ULONG (*tCbFileGetSize)(void *pData);\ntypedef UBYTE (*tCbFileIsEof)(void *pData);\ntypedef void (*tCbFileFlush)(void *pData);\n\ntypedef struct tFileCallbacks {\n\ttCbFileClose cbFileClose;\n\ttCbFileRead cbFileRead;\n\ttCbFileWrite cbFileWrite;\n\ttCbFileSeek cbFileSeek;\n\ttCbFileGetPos cbFileGetPos;\n\ttCbFileGetSize cbFileGetSize;\n\ttCbFileIsEof cbFileIsEof;\n\ttCbFileFlush cbFileFlush;\n} tFileCallbacks;\n\ntypedef struct tFile {\n\tconst tFileCallbacks *pCallbacks;\n\tvoid *pData;\n} tFile;\n#endif\n\nvoid fileClose(tFile *pFile);\n\nULONG fileRead(tFile *pFile, void *pDest, ULONG ulSize);\n\nULONG fileWrite(tFile *pFile, const void *pSrc, ULONG ulSize);\n\nULONG fileSeek(tFile *pFile, LONG lPos, WORD wMode);\n\nULONG fileGetPos(tFile *pFile);\n\nUBYTE fileIsEof(tFile *pFile);\n\nvoid fileFlush(tFile *pFile);\n\n/**\n * @brief Returns file size of file, in bytes.\n *\n * @param pFile File handle.\n * @return On fail -1, otherwise file size in bytes.\n */\nLONG fileGetSize(tFile *pFile);\n\nvoid fileWriteStr(tFile *pFile, const char *szLine);\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif // _ACE_UTILS_FILE_H_\n"
  },
  {
    "path": "include/ace/utils/font.h",
    "content": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at http://mozilla.org/MPL/2.0/. */\n\n#ifndef _ACE_UTILS_FONT_H_\n#define _ACE_UTILS_FONT_H_\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n/**\n *  Font & text drawing utils.\n *  @todo Consider changing prefix to 'txt' or splitting to two modules:\n *        'font' and 'txt'.\n */\n\n#include <ace/types.h>\n#include <ace/managers/blit.h>\n#include <ace/utils/bitmap.h>\n\n/* Types */\n#define FONT_LEFT    0\n#define FONT_RIGHT   1\n#define FONT_HCENTER 2\n#define FONT_TOP     0\n#define FONT_BOTTOM  4\n#define FONT_VCENTER 8\n#define FONT_SHADOW  16\n#define FONT_COOKIE  32\n#define FONT_LAZY    64\n#define FONT_CENTER (FONT_HCENTER|FONT_VCENTER)\n\n/**\n *  @brief The font structure.\n *  All font glyphs are stored in continuous 1bb bitmap. Its width is\n *  determined by glyph count and height by font size.\n *  Not all glyphs in codepage must be included - all missing glyphs share\n *  offset with next implemented glyph.\n */\ntypedef struct _tFont {\n\tUWORD uwWidth;       ///< Packed font bitmap width.\n\tUWORD uwHeight;      ///< Packed font bitmap height.\n\tUBYTE ubChars;       ///< Glyph count in font.\n\tUWORD *pCharOffsets; ///< Glyph offsets in packed bitmap.\n\ttBitMap *pRawData;   ///< Pointer to packed bitmap.\n} tFont;\n\n/**\n * @brief The 1bpp bitmap buffer containing text assembled from glyphs.\n * Since text assembly from chars is time-consuming process, it is usually\n * better to store once assembled text for future redraws.\n * Buffer may be bigger than contained text, hence proper dimensions are stored\n * separately.\n */\ntypedef struct _tTextBitMap {\n\ttBitMap *pBitMap;    ///< Word-aligned bitmap buffer with pre-drawn text.\n\tUWORD uwActualWidth; ///< Actual text width for precise blitting.\n\tUWORD uwActualHeight; ///< Actual text height for precise blitting.\n} tTextBitMap;\n\n/* Globals */\n\n/* Functions */\n\n/**\n * @brief Creates font instance from specified file.\n *\n * @param szPath Path to font file to be loaded.\n * @return pointer to loaded font.\n *\n * @see fontDestroy()\n * @see fontCreateFromFd\n */\ntFont *fontCreateFromPath(const char *szPath);\n\n/**\n *  @brief Creates font instance from specified file.\n *\n *  @param pFontFile Handle to the font file. Will be closed on function return.\n *  @return pointer to loaded font.\n *\n *  @see fontDestroy()\n */\ntFont *fontCreateFromFd(tFile *pFontFile);\n\n/**\n *  @brief Destroys given font instance.\n *\n *  @param pFont Font to be destroyed.\n *\n *  @see fontCreate()\n */\nvoid fontDestroy(tFont *pFont);\n\n/**\n * @brief Draws given string using passed font on specified 1BPP bitmap.\n * This function draws text as fast as possible.\n * Background beneath bitmap is not cleared because you may want to remember\n * length of previous text and erase only relevant portion of bitmap.\n *\n * @param pFont Font to be used.\n * @param pBitMap Destination bitmap.\n * @param uwStartX X position of the text.\n * @param uwStartY Y position of the text.\n * @param szText Text to be written.\n * @return Bitmap coord for bottom-right corner of the text\n *\n * @see fontDrawStr\n */\ntUwCoordYX fontDrawStr1bpp(\n\tconst tFont *pFont, tBitMap *pBitMap, UWORD uwStartX, UWORD uwStartY,\n\tconst char *szText\n);\n\ntTextBitMap *fontCreateTextBitMap(UWORD uwWidth, UWORD uwHeight);\n\n/**\n *  @brief Creates text bitmap with specified font, containing given text.\n *  Treat as cache - allows faster reblit of text without need\n *  of assembling it again.\n *\n *  @param pFont  Font to be used during text assembly.\n *  @param szText String to be printed on bitmap buffer.\n *  @return Newly-created text bitmap pointer.\n *\n *  @see fontCreateTextBitMap()\n *  @see fontDestroyTextBitMap()\n *  @see fontDrawTextBitMap()\n */\ntTextBitMap *fontCreateTextBitMapFromStr(\n\tconst tFont *pFont, const char *szText\n);\n\nvoid fontFillTextBitMap(\n\tconst tFont *pFont, tTextBitMap *pTextBitMap, const char *szText\n);\n\n/**\n *  @brief Destroys specified buffered text bitmap.\n *\n *  @param pTextBitMap Text bitmap to be destroyed.\n *\n *  @see fontCreateTextBitMap()\n */\nvoid fontDestroyTextBitMap(tTextBitMap *pTextBitMap);\n\n/**\n * @brief Gets dimensions occupied by specified text drawn by given font.\n *\n * @param pFont Font to be used for measurement.\n * @param szText Text to be measured.\n * @return tUwCoordYX Coord containing dimensions: x is width, y - height.\n */\ntUwCoordYX fontMeasureText(const tFont *pFont, const char *szText);\n\n/**\n * @brief Gets width of specified glyph on given font.\n *\n * @param pFont Font to be used for measurement.\n * @param c Glyph to be checked\n * @return Width of glyph, in pixels.\n */\nUBYTE fontGlyphWidth(const tFont *pFont, char c);\n\n/**\n * @brief Checks if given text fits inside specified text buffer.\n *\n * @param pFont Font to be used for measurement.\n * @param pTextBitmap Destination text bitmap.\n * @param szText Text to be fitted.\n * @return 1 if text fully fits inside buffer, otherwise 0.\n */\nUBYTE fontTextFitsInTextBitmap(\n\tconst tFont *pFont, const tTextBitMap *pTextBitmap, const char *szText\n);\n\n/**\n *  @brief Draws specified text bitmap at given position, color and flags.\n *\n *  @param pDest       Destination bitmap.\n *  @param pTextbitMap Source text bitmap.\n *  @param uwX         X position on destination bitmap.\n *  @param uwY         Y position on destination bitmap.\n *  @param ubColor     Desired text color.\n *  @param ubFlags     Text draw flags (FONT_*).\n *\n *  @see fontCreateTextBitMap()\n *  @see fontDrawStr()\n */\nvoid fontDrawTextBitMap(\n\ttBitMap *pDest, tTextBitMap *pTextBitMap,\n\tUWORD uwX, UWORD uwY, UBYTE ubColor, UBYTE ubFlags\n);\n\n/**\n *  @brief Writes one-time texts on specified destination bitmap.\n *  This function should be used very carefully, as text assembling is\n *  time-consuming. If same text is going to be redrawn in game loop, its bitmap\n *  buffer should be stored and used for redraw.\n *\n *  @param pFont Font to be used for text assembly.\n *  @param pDest Destination bitmap.\n *  @param uwX X position on destination bitmap.\n *  @param uwY Y position on destination bitmap.\n *  @param szText String to be printed on destination bitmap.\n *  @param ubColor Desired text color.\n *  @param ubFlags Text draw flags (FONT_*).\n *  @param pTextBitMap Bitmap buffer to be used when composing text.\n *\n *  @see fontDrawTextBitMap()\n */\nvoid fontDrawStr(\n\tconst tFont *pFont, tBitMap *pDest, UWORD uwX, UWORD uwY,\n\tconst char *szText, UBYTE ubColor, UBYTE ubFlags, tTextBitMap *pTextBitMap\n);\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif // _ACE_UTILS_FONT_H_\n"
  },
  {
    "path": "include/ace/utils/mini_std.h",
    "content": "#ifndef _ACE_UTILS_MINI_STD_H_\n#define _ACE_UTILS_MINI_STD_H_\n\n// All the missing stuff that ACE needs and which Bartman's GCC doesn't provide.\n\n#include <stddef.h>\n#include <stdarg.h>\n\n#define SEEK_SET 0\n#define SEEK_CUR 1\n#define SEEK_END 2\n\ntypedef int FILE;\n\nsize_t strlen(const char *szStr);\n\nint vsprintf(char *szOut, const char *szFmt, va_list vaArgs);\n\nchar *strcpy(char *szDest, const char *szSrc);\n\nchar *strcat(char *szDest, const char *szSrc);\n\nint fseek(FILE * stream, long int offset, int origin);\n\n#endif // _ACE_UTILS_MINI_STD_H_\n"
  },
  {
    "path": "include/ace/utils/pak_file.h",
    "content": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at http://mozilla.org/MPL/2.0/. */\n\n#ifndef _ACE_UTILS_PAK_FILE_H_\n#define _ACE_UTILS_PAK_FILE_H_\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n\n#include \"file.h\"\n\n#if !defined(ACE_FILE_USE_ONLY_DISK)\n\ntypedef struct tPakFileEntry {\n\tULONG ulOffs;\n\tULONG ulSizeUncompressed;\n\tULONG ulSizeData;\n\tULONG ulPathChecksum; // adler32\n} tPakFileEntry;\n\ntypedef struct tPakFile {\n\ttFile *pFile;\n\tvoid *pPrevReadSubfile;\n\tUWORD uwFileCount;\n\ttPakFileEntry *pEntries;\n} tPakFile;\n\ntPakFile *pakFileOpen(const char *szPath, UBYTE isUninterrupted);\n\nvoid pakFileClose(tPakFile *pPakFile);\n\ntFile *pakFileGetFile(tPakFile *pPakFile, const char *szInternalPath);\n\n#endif\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif // _ACE_UTILS_PAK_FILE_H_\n"
  },
  {
    "path": "include/ace/utils/palette.h",
    "content": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at http://mozilla.org/MPL/2.0/. */\n\n#ifndef _ACE_UTILS_PALETTE_H\n#define _ACE_UTILS_PALETTE_H\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n/**\n * Palette utilities.\n */\n\n#include <ace/types.h>\n#include <ace/utils/extview.h>\n\n/**\n * @brief Loads palette from supplied .plt file to given address.\n *\n * Supports **v2** only: first byte **0** (ECS/OCS packed) or **1** (AGA), then big-endian UWORD count.\n * Legacy **v1** `.plt` (first byte ≥ 2) is rejected (`ACE_DEBUG`: log error; @p pPalette unchanged).\n * For v2 AGA (first byte **1**), @p pPalette must point at storage suitable for ULONG-sized colors\n * (same layout as an AGA viewport palette).\n *\n * @param szPath Palette source path.\n * @param pPalette Palette destination pointer.\n * @param uwMaxLength Maximum number of colors to read.\n *\n * @see paletteLoadFromFd()\n */\nvoid paletteLoadFromPath(const char *szPath, UWORD *pPalette, UWORD uwMaxLength);\n\n/**\n * @brief Saves ECS/OCS palette into .plt v2 file (sentinel 0 + BE count + packed colors).\n */\nvoid paletteSaveOcs(const UWORD *pPalette, UWORD uwColorCnt, char *szPath);\n\n#ifdef ACE_USE_AGA_FEATURES\n/**\n * @brief Saves AGA palette into .plt v2 file (sentinel 1 + BE count + 4 bytes per color).\n */\nvoid paletteSaveAga(const ULONG *pPalette, UWORD uwColorCnt, char *szPath);\n#endif\n\n/**\n * @brief Loads palette from supplied .plt file to given address.\n * @param pFile Handle to the palette file. Will be closed on function return.\n * @param pPalette Palette destination pointer. For v2 AGA files, this must be\n *        storage suitable for `ULONG` per entry (e.g. AGA viewport palette).\n * @param uwMaxLength Maximum number of colors to read.\n *\n * @see paletteLoadFromPath()\n */\nvoid paletteLoadFromFd(tFile *pFile, UWORD *pPalette, UWORD uwMaxLength);\n\n/**\n * @brief Dims palette to given brightness level.\n * @param pSource Pointer to source palette.\n * @param pDest Pointer to destination palette. Can be same as pSource.\n * Can also be pointing directly on chipset palette registers.\n * @param uwColorCount Number of colors in palette.\n * @param ubLevel Brightness level - 15 for no dim, 0 for total blackness.\n *\n * @warning DON'T point pSource to chipset palette registers, they are read-only!\n */\nvoid paletteDimOcs(\n\tUWORD *pSource, volatile UWORD *pDest, UWORD uwColorCount, UBYTE ubLevel\n);\n\n#ifdef ACE_USE_AGA_FEATURES\nvoid paletteDimAga(\n\tULONG *pSource, volatile ULONG *pDest, UWORD uwColorCount, UBYTE ubLevel\n);\n#endif\n\n/**\n * @brief Dims a single input color to given brightness level.\n * @param uwFullColor Full color used as a base to calculate percentage.\n * @param ubLevel Brightness level - 15 for no dim, 0 for total blackness.\n *\n * @see paletteColorMixOcs()\n */\nUWORD paletteColorDimOcs(UWORD uwFullColor, UBYTE ubLevel);\n#ifdef ACE_USE_AGA_FEATURES\nULONG paletteColorDimAga(ULONG ulFullColor, UBYTE ubLevel);\n#endif\n\n/**\n * @brief Interpolates two colors at given level.\n * @param uwColorPrimary Primary color in the mix.\n * @param uwColorSecondary Secondary color in the mix.\n * @param ubLevel Mix ratio - 15 results in primary color, 0 in secondary.\n * @return Mixed color between uwColorPrimary and uwColorSecondary.\n *\n * @note This function is slower than paletteColorDimOcs().\n * @see paletteColorDimOcs()\n */\nUWORD paletteColorMixOcs(UWORD uwColorPrimary, UWORD uwColorSecondary, UBYTE ubLevel);\n\n#ifdef ACE_USE_AGA_FEATURES\n/**\n * @brief Interpolates two AGA colors at given level.\n * @param ulColorPrimary Primary AGA color in the mix.\n * @param ulColorSecondary Secondary AGA color in the mix.\n * @param ubLevel Mix ratio - 255 results in primary color, 0 in secondary.\n * @return Mixed AGA color between ulColorPrimary and ulColorSecondary.\n *\n * @note This function is slower than paletteColorDimAga().\n * @see paletteColorDimAga()\n */\nULONG paletteColorMixAga(ULONG ulColorPrimary, ULONG ulColorSecondary, UBYTE ubLevel);\n#endif\n\n/**\n * @brief Writes given palette to debug .bmp file.\n *\n * This function is horribly slow and should only be used for debug purposes.\n *\n * @param pPalette Palette to be dumped.\n * @param fubColorCnt Number of colors in palette.\n * @param szPath Destination path for .bmp file.\n */\nvoid paletteDumpOcs(UWORD *pPalette, UWORD uwColorCnt, char *szPath);\n\n#ifdef ACE_USE_AGA_FEATURES\n/**\n * @brief Writes given AGA palette to debug .bmp file.\n *\n * This function is horribly slow and should only be used for debug purposes.\n *\n * @param pPalette AGA palette to be dumped.\n * @param uwColorCnt Number of colors in palette.\n * @param szPath Destination path for .bmp file.\n */\nvoid paletteDumpAga(ULONG *pPalette, UWORD uwColorCnt, char *szPath);\n#endif\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif // _ACE_UTILS_PALETTE_H\n"
  },
  {
    "path": "include/ace/utils/sprite.h",
    "content": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at http://mozilla.org/MPL/2.0/. */\n\n#ifndef _ACE_UTILS_SPRITE_H_\n#define _ACE_UTILS_SPRITE_H_\n\n/**\n * @file sprite.h\n * @brief Useful utilities for sprite management if you don't intend to use the\n * ACE's sprite manager.\n */\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n#include <ace/managers/copper.h>\n\n/**\n * @brief Disables given sprites on supplied copperlist at given cmd offset.\n *\n * This function doesn't add any WAIT cmd, be sure to put those cmds in VBlank.\n * Number of MOVE instructions added equals two times number of sprites disabled.\n *\n * @param pList Copperlist to be edited.\n * @param eSpriteMask Determines sprites to be disabled.\n * @param uwCmdOffs Start position on raw copperlist.\n * @param pBlankSprite 2 words of CHIP memory (the blank sprite control words)\n * @return Number of MOVE instructions added.\n */\nUBYTE spriteDisableInCopRawMode(\n\ttCopList *pList, tSpriteMask eSpriteMask, UWORD uwCmdOffs, ULONG pBlankSprite[1]\n);\n\n/**\n * @brief Adds copBlock which disables given sprites.\n * Resulting copBlock is placed at 0,0 so that it will be executed during VBlank.\n *\n * @param pList Copperlist to be edited.\n * @param eSpriteMask Determines sprites to be disabled.\n * @param pBlankSprite 2 words of CHIP memory (the blank sprite control words)\n *\n * @return Pointer to newly created copBlock.\n */\ntCopBlock *spriteDisableInCopBlockMode(tCopList *pList, tSpriteMask eSpriteMask, ULONG pBlankSprite[1]);\n\nvoid spriteInit(void);\n\n#ifdef ACE_USE_AGA_FEATURES\n/**\n * @brief Sets the palette bank for AGA sprites on odd channels.\n * @param ubIndex The palette bank index (0-15)\n * @see spriteSetEvenColorPaletteBank\n */\nvoid spriteSetOddColorPaletteBank(UBYTE ubIndex);\n\n/**\n * @brief Sets the palette bank for AGA sprites on even channels.\n * @param ubIndex The palette bank index (0-15)\n * @see spriteSetOddColorPaletteBank\n */\nvoid spriteSetEvenColorPaletteBank(UBYTE ubIndex);\n#endif\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif // _ACE_UTILS_SPRITE_H_\n"
  },
  {
    "path": "include/ace/utils/string.h",
    "content": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at http://mozilla.org/MPL/2.0/. */\n\n#ifndef _ACE_UTILS_STRING_H_\n#define _ACE_UTILS_STRING_H_\n\n// Contains highly optimized string functions.\n// Those should be preferred over standard library in game loop.\n// The functions returning pointer to null terminator at the end can be easily\n// used in concatenation chains.\n\n#include <ace/types.h>\n\n/**\n * @brief Writes the unsigned value into destination string.\n * Relies on prior verification that buffer != NULL and bufsize != 0\n *\n * @param ulVal Value to be stringified.\n * @param pDst Destination string. Must be non-null and be at least of size\n * fitting the target value and null terminator.\n * @return Pointer to the null-terminator at the end of stringified value.\n */\nchar *stringDecimalFromULong(ULONG ulVal, char *pDst);\n\n/**\n * @brief Copies string to new location, converting it to upper case.\n * The uppercasing works on basic 26-letter ASCII alphabet.\n * This does nothing for non-uppercase chars.\n *\n * @param szSrc Source string.\n * @param szDst Destination string.\n */\nvoid strToUpper(const char *szSrc, char *szDst);\n\n/**\n * @brief Convers single character to uppercase. Works only on basic\n * 26-letter ASCII alphabet.\n * This does nothing for non-uppercase chars.\n *\n * @param c Character to convert to uppercase.\n * @return Character converted to uppercase.\n */\nchar charToUpper(char c);\n\n/**\n * @brief Checks if string is empty.\n * The check stops on first null-terminator.\n *\n * @param szStr String to be checked.\n * @return 1 if string consists only of null-temrinator, otherwise 0.\n */\nUBYTE stringIsEmpty(const char *szStr);\n\n/**\n * @brief Copies string from given source to destination buffer.\n *\n * @param szSrc Source string.\n * @param szDest Buffer for destination string.\n * @return Pointer to null-terminator character at the end of szDest.\n */\nchar *stringCopy(const char *szSrc, char *szDest);\n\n/**\n * @brief Copies string from given source to destination buffer, with specified\n * length limit.\n *\n * The resulting string in destination buffer is null-terminated.\n *\n * @param szSrc Source string.\n * @param szDest Buffer for destination string.\n * @param uwMaxLength Maximum length of string to be written in szDest,\n * including the null terminator. Must be non-zero\n * @return Pointer to null-terminator character at the end of szDest.\n */\nchar *stringCopyLimited(const char *szSrc, char *szDest, UWORD uwMaxLength);\n\n#endif // _ACE_UTILS_STRING_H_\n"
  },
  {
    "path": "include/ace/utils/tag.h",
    "content": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at http://mozilla.org/MPL/2.0/. */\n\n#ifndef _ACE_UTILS_TAG_H_\n#define _ACE_UTILS_TAG_H_\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n/**\n * Util for handling AmigaOS tag list pattern.\n */\n\n#include <stdarg.h>\n#include <ace/types.h>\n\n// This is implemented on AOS 2.0+ (utility/tagitem.h) and I could include it\n// But I can't detect if we're building for 1.3. Even if I could do that\n// I'm overriding type name for ACE convention, so I just define needed stuff.\n// Ifdef is needed because of e.g. utils/bitmap.h includes graphics_protos.h\n// which may (or may not on KS 1.3) in turn include tag defines.\ntypedef ULONG tTag;\n#ifndef TAG_DONE\n#define TAG_DONE   0UL\n#define TAG_END    0UL\n#define TAG_IGNORE 1UL\n#define TAG_MORE   2UL\n#define TAG_SKIP   3UL\n#define TAG_USER   BV(31)\n#endif // TAG_DONE\n\n/**\n *  Finds and returns value of specified tag name from tag list.\n *  Tag list may be supplied as list or va_list.\n *  TODO: 1st arg doesn't work yet\n *  @param pTagListPtr  Pointer to tag list.\n *  @param vaSrcList    va_list containing alternating tags and values.\n *  @param ulTagToFind  Tag name, of which value should be returned.\n *  @param ulOnNotFound Value to be returned if tag was not found on list.\n *  @return ulOnNotFound if tag was not found, otherwise tag value.\n */\nULONG tagGet(\n\tvoid *pTagListPtr, va_list vaSrcList, tTag ulTagToFind, ULONG ulOnNotFound\n);\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif // _ACE_UTILS_TAG_H_\n"
  },
  {
    "path": "include/fixmath/fix16.h",
    "content": "#ifndef __fixmath_fix16_h__\n#define __fixmath_fix16_h__\n\n#define FIXMATH_NO_ROUNDING      // Faster but less accurate\n#define FIXMATH_NO_CACHE         // Don't cache results\n#define FIXMATH_FAST_SIN         // Faster but less accurate\n\n//#define FIXMATH_USE_FLOATS       // Enables floating point fns\n//#define FIXMATH_NO_OVERFLOW    // Faster but risk of garbage\n//#define FIXMATH_OPTIMIZE_8BIT  // Significant only on 8-bit CPUs\n//#define FIXMATH_SIN_LUT        // Uses loadsa RAM\n\n#ifdef __cplusplus\nextern \"C\"\n{\n#endif\n\n/* These options may let the optimizer to remove some calls to the functions.\n * Refer to http://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html\n */\n#ifndef FIXMATH_FUNC_ATTRS\n# ifdef __GNUC__\n#   if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 6)\n#     define FIXMATH_FUNC_ATTRS __attribute__((leaf, nothrow, const))\n#   else\n#     define FIXMATH_FUNC_ATTRS __attribute__((nothrow, const))\n#   endif\n# else\n#   define FIXMATH_FUNC_ATTRS\n# endif\n#endif\n\n#include <stdint.h>\n\ntypedef int32_t fix16_t;\n\nstatic const fix16_t FOUR_DIV_PI  = 0x145F3;            /*!< Fix16 value of 4/PI */\nstatic const fix16_t _FOUR_DIV_PI2 = 0xFFFF9840;        /*!< Fix16 value of -4/PI² */\nstatic const fix16_t X4_CORRECTION_COMPONENT = 0x399A; \t/*!< Fix16 value of 0.225 */\nstatic const fix16_t PI_DIV_4 = 0x0000C90F;             /*!< Fix16 value of PI/4 */\nstatic const fix16_t THREE_PI_DIV_4 = 0x00025B2F;       /*!< Fix16 value of 3PI/4 */\n\nstatic const fix16_t fix16_maximum  = 0x7FFFFFFF; /*!< the maximum value of fix16_t */\nstatic const fix16_t fix16_minimum  = 0x80000000; /*!< the minimum value of fix16_t */\nstatic const fix16_t fix16_overflow = 0x80000000; /*!< the value used to indicate overflows when FIXMATH_NO_OVERFLOW is not specified */\n\nstatic const fix16_t fix16_pi  = 205887;     /*!< fix16_t value of pi */\nstatic const fix16_t fix16_e   = 178145;     /*!< fix16_t value of e */\nstatic const fix16_t fix16_one = 0x00010000; /*!< fix16_t value of 1 */\n\n/* Conversion functions between fix16_t and float/integer.\n * These are inlined to allow compiler to optimize away constant numbers\n */\nstatic inline fix16_t fix16_from_int(int a)     { return a * fix16_one; }\n#ifdef FIXMATH_USE_FLOATS\nstatic inline float   fix16_to_float(fix16_t a) { return (float)a / fix16_one; }\nstatic inline double  fix16_to_dbl(fix16_t a)   { return (double)a / fix16_one; }\n#endif\n\nstatic inline int fix16_to_int(fix16_t a)\n{\n#ifdef FIXMATH_NO_ROUNDING\n    return (a >> 16);\n#else\n\tif (a >= 0)\n\t\treturn (a + (fix16_one >> 1)) / fix16_one;\n\treturn (a - (fix16_one >> 1)) / fix16_one;\n#endif\n}\n\n#ifdef FIXMATH_USE_FLOATS\nstatic inline fix16_t fix16_from_float(float a)\n{\n\tfloat temp = a * fix16_one;\n#ifndef FIXMATH_NO_ROUNDING\n\ttemp += (temp >= 0) ? 0.5f : -0.5f;\n#endif\n\treturn (fix16_t)temp;\n}\n\nstatic inline fix16_t fix16_from_dbl(double a)\n{\n\tdouble temp = a * fix16_one;\n#ifndef FIXMATH_NO_ROUNDING\n\ttemp += (temp >= 0) ? 0.5f : -0.5f;\n#endif\n\treturn (fix16_t)temp;\n}\n#endif\n\n/* Macro for defining fix16_t constant values.\n   The functions above can't be used from e.g. global variable initializers,\n   and their names are quite long also. This macro is useful for constants\n   springled alongside code, e.g. F16(1.234).\n\n   Note that the argument is evaluated multiple times, and also otherwise\n   you should only use this for constant values. For runtime-conversions,\n   use the functions above.\n*/\n#define F16(x) ((fix16_t)(((x) >= 0) ? ((x) * 65536.0 + 0.5) : ((x) * 65536.0 - 0.5)))\n\nstatic inline fix16_t fix16_abs(fix16_t x)\n\t{ return (x < 0 ? -x : x); }\nstatic inline fix16_t fix16_floor(fix16_t x)\n\t{ return (x & 0xFFFF0000UL); }\nstatic inline fix16_t fix16_ceil(fix16_t x)\n\t{ return (x & 0xFFFF0000UL) + (x & 0x0000FFFFUL ? fix16_one : 0); }\nstatic inline fix16_t fix16_min(fix16_t x, fix16_t y)\n\t{ return (x < y ? x : y); }\nstatic inline fix16_t fix16_max(fix16_t x, fix16_t y)\n\t{ return (x > y ? x : y); }\nstatic inline fix16_t fix16_clamp(fix16_t x, fix16_t lo, fix16_t hi)\n\t{ return fix16_min(fix16_max(x, lo), hi); }\n\n/* Subtraction and addition with (optional) overflow detection. */\n#ifdef FIXMATH_NO_OVERFLOW\n\nstatic inline fix16_t fix16_add(fix16_t inArg0, fix16_t inArg1) { return (inArg0 + inArg1); }\nstatic inline fix16_t fix16_sub(fix16_t inArg0, fix16_t inArg1) { return (inArg0 - inArg1); }\n\n#else\n\nextern fix16_t fix16_add(fix16_t a, fix16_t b) FIXMATH_FUNC_ATTRS;\nextern fix16_t fix16_sub(fix16_t a, fix16_t b) FIXMATH_FUNC_ATTRS;\n\n/* Saturating arithmetic */\nextern fix16_t fix16_sadd(fix16_t a, fix16_t b) FIXMATH_FUNC_ATTRS;\nextern fix16_t fix16_ssub(fix16_t a, fix16_t b) FIXMATH_FUNC_ATTRS;\n\n#endif\n\n/*! Multiplies the two given fix16_t's and returns the result.\n*/\nextern fix16_t fix16_mul(fix16_t inArg0, fix16_t inArg1) FIXMATH_FUNC_ATTRS;\n\n/*! Divides the first given fix16_t by the second and returns the result.\n*/\nextern fix16_t fix16_div(fix16_t inArg0, fix16_t inArg1) FIXMATH_FUNC_ATTRS;\n\n#ifndef FIXMATH_NO_OVERFLOW\n/*! Performs a saturated multiplication (overflow-protected) of the two given fix16_t's and returns the result.\n*/\nextern fix16_t fix16_smul(fix16_t inArg0, fix16_t inArg1) FIXMATH_FUNC_ATTRS;\n\n/*! Performs a saturated division (overflow-protected) of the first fix16_t by the second and returns the result.\n*/\nextern fix16_t fix16_sdiv(fix16_t inArg0, fix16_t inArg1) FIXMATH_FUNC_ATTRS;\n#endif\n\n/*! Divides the first given fix16_t by the second and returns the result.\n*/\nextern fix16_t fix16_mod(fix16_t x, fix16_t y) FIXMATH_FUNC_ATTRS;\n\n\n\n/*! Returns the linear interpolation: (inArg0 * (1 - inFract)) + (inArg1 * inFract)\n*/\nextern fix16_t fix16_lerp8(fix16_t inArg0, fix16_t inArg1, uint8_t inFract) FIXMATH_FUNC_ATTRS;\nextern fix16_t fix16_lerp16(fix16_t inArg0, fix16_t inArg1, uint16_t inFract) FIXMATH_FUNC_ATTRS;\n#ifndef FIXMATH_NO_64BIT\nextern fix16_t fix16_lerp32(fix16_t inArg0, fix16_t inArg1, uint32_t inFract) FIXMATH_FUNC_ATTRS;\n#endif\n\n\n\n/*! Returns the sine of the given fix16_t.\n*/\nextern fix16_t fix16_sin_parabola(fix16_t inAngle) FIXMATH_FUNC_ATTRS;\n\n/*! Returns the sine of the given fix16_t.\n*/\nextern fix16_t fix16_sin(fix16_t inAngle) FIXMATH_FUNC_ATTRS;\n\n/*! Returns the cosine of the given fix16_t.\n*/\nextern fix16_t fix16_cos(fix16_t inAngle) FIXMATH_FUNC_ATTRS;\n\n/*! Returns the tangent of the given fix16_t.\n*/\nextern fix16_t fix16_tan(fix16_t inAngle) FIXMATH_FUNC_ATTRS;\n\n/*! Returns the arcsine of the given fix16_t.\n*/\nextern fix16_t fix16_asin(fix16_t inValue) FIXMATH_FUNC_ATTRS;\n\n/*! Returns the arccosine of the given fix16_t.\n*/\nextern fix16_t fix16_acos(fix16_t inValue) FIXMATH_FUNC_ATTRS;\n\n/*! Returns the arctangent of the given fix16_t.\n*/\nextern fix16_t fix16_atan(fix16_t inValue) FIXMATH_FUNC_ATTRS;\n\n/*! Returns the arctangent of inY/inX.\n*/\nextern fix16_t fix16_atan2(fix16_t inY, fix16_t inX) FIXMATH_FUNC_ATTRS;\n\nstatic const fix16_t fix16_rad_to_deg_mult = 3754936;\nstatic inline fix16_t fix16_rad_to_deg(fix16_t radians)\n\t{ return fix16_mul(radians, fix16_rad_to_deg_mult); }\n\nstatic const fix16_t fix16_deg_to_rad_mult = 1144;\nstatic inline fix16_t fix16_deg_to_rad(fix16_t degrees)\n\t{ return fix16_mul(degrees, fix16_deg_to_rad_mult); }\n\n/*! Converts degrees to radians.\n*/\nstatic inline fix16_t fix16_deg2rad(fix16_t fAngleDegrees) {\n  return fix16_div(fix16_mul(fAngleDegrees, fix16_pi),fix16_from_int(180));\n}\n\n/*! Converts radians to degrees.\n*/\nstatic inline fix16_t fix16_rad2deg(fix16_t fAngleRads) {\n  return fix16_div(fix16_mul(fAngleRads, fix16_from_int(180)),fix16_pi);\n}\n\n/*! Returns the square root of the given fix16_t.\n*/\nextern fix16_t fix16_sqrt(fix16_t inValue) FIXMATH_FUNC_ATTRS;\n\n/*! Returns the square of the given fix16_t.\n*/\nstatic inline fix16_t fix16_sq(fix16_t x)\n\t{ return fix16_mul(x, x); }\n\n/*! Returns the exponent (e^) of the given fix16_t.\n*/\nextern fix16_t fix16_exp(fix16_t inValue) FIXMATH_FUNC_ATTRS;\n\n/*! Returns the natural logarithm of the given fix16_t.\n */\nextern fix16_t fix16_log(fix16_t inValue) FIXMATH_FUNC_ATTRS;\n\n/*! Returns the base 2 logarithm of the given fix16_t.\n */\nextern fix16_t fix16_log2(fix16_t x) FIXMATH_FUNC_ATTRS;\n\n/*! Returns the saturated base 2 logarithm of the given fix16_t.\n */\nextern fix16_t fix16_slog2(fix16_t x) FIXMATH_FUNC_ATTRS;\n\n/*! Convert fix16_t value to a string.\n * Required buffer length for largest values is 13 bytes.\n */\nextern void fix16_to_str(fix16_t value, char *buf, int decimals);\n\n/*! Convert string to a fix16_t value\n * Ignores spaces at beginning and end. Returns fix16_overflow if\n * value is too large or there were garbage characters.\n */\nextern fix16_t fix16_from_str(const char *buf);\n\n/** Helper macro for F16C. Replace token with its number of characters/digits. */\n#define FIXMATH_TOKLEN(token) ( sizeof( #token ) - 1 )\n\n/** Helper macro for F16C. Handles pow(10, n) for n from 0 to 8. */\n#define FIXMATH_CONSTANT_POW10(times) ( \\\n  (times == 0) ? 1ULL \\\n        : (times == 1) ? 10ULL \\\n            : (times == 2) ? 100ULL \\\n                : (times == 3) ? 1000ULL \\\n                    : (times == 4) ? 10000ULL \\\n                        : (times == 5) ? 100000ULL \\\n                            : (times == 6) ? 1000000ULL \\\n                                : (times == 7) ? 10000000ULL \\\n                                    : 100000000ULL \\\n)\n\n\n/** Helper macro for F16C, the type uint64_t is only used at compile time and\n *  shouldn't be visible in the generated code.\n *\n * @note We do not use fix16_one instead of 65536ULL, because the\n *       \"use of a const variable in a constant expression is nonstandard in C\".\n */\n#define FIXMATH_CONVERT_MANTISSA(m) \\\n( (unsigned) \\\n    ( \\\n        ( \\\n            ( \\\n                (uint64_t)( ( ( 1 ## m ## ULL ) - FIXMATH_CONSTANT_POW10(FIXMATH_TOKLEN(m)) ) * FIXMATH_CONSTANT_POW10(5 - FIXMATH_TOKLEN(m)) ) \\\n                * 100000ULL * 65536ULL \\\n            ) \\\n            + 5000000000ULL /* rounding: + 0.5 */ \\\n        ) \\\n        / \\\n        10000000000LL \\\n    ) \\\n)\n\n\n#define FIXMATH_COMBINE_I_M(i, m) \\\n( \\\n    ( \\\n        (    i ) \\\n        << 16 \\\n    ) \\\n    | \\\n    ( \\\n        FIXMATH_CONVERT_MANTISSA(m) \\\n        & 0xFFFF \\\n    ) \\\n)\n\n\n/** Create int16_t (Q16.16) constant from separate integer and mantissa part.\n *\n * Only tested on 32-bit ARM Cortex-M0 / x86 Intel.\n *\n * This macro is needed when compiling with options like \"--fpu=none\",\n * which forbid all and every use of float and related types and\n * would thus make it impossible to have fix16_t constants.\n *\n * Just replace uses of F16() with F16C() like this:\n *   F16(123.1234) becomes F16C(123,1234)\n *\n * @warning Specification of any value outside the mentioned intervals\n *          WILL result in undefined behavior!\n *\n * @note Regardless of the specified minimum and maximum values for i and m below,\n *       the total value of the number represented by i and m MUST be in the interval\n *       ]-32768.00000:32767.99999[ else usage with this macro will yield undefined behavior.\n *\n * @param i Signed integer constant with a value in the interval ]-32768:32767[.\n * @param m Positive integer constant in the interval ]0:99999[ (fractional part/mantissa).\n */\n#define F16C(i, m) \\\n( (fix16_t) \\\n    ( \\\n      (( #i[0] ) == '-') \\\n        ? -FIXMATH_COMBINE_I_M((unsigned)( ( (i) * -1) ), m) \\\n        : FIXMATH_COMBINE_I_M(i, m) \\\n    ) \\\n)\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif\n"
  },
  {
    "path": "include/fixmath/fix16_trig_sin_lut.h",
    "content": "#ifndef __fix16_trig_sin_lut_h__\n#define __fix16_trig_sin_lut_h__\n\nstatic const uint32_t _fix16_sin_lut_count = 102688;\nstatic uint16_t _fix16_sin_lut[102688] = {\n\t0, 1, 2, 3, 4, 5, 6, 7, \n\t8, 9, 10, 11, 12, 13, 14, 15, \n\t16, 17, 18, 19, 20, 21, 22, 23, \n\t24, 25, 26, 27, 28, 29, 30, 31, \n\t32, 33, 34, 35, 36, 37, 38, 39, \n\t40, 41, 42, 43, 44, 45, 46, 47, \n\t48, 49, 50, 51, 52, 53, 54, 55, \n\t56, 57, 58, 59, 60, 61, 62, 63, \n\t64, 65, 66, 67, 68, 69, 70, 71, \n\t72, 73, 74, 75, 76, 77, 78, 79, \n\t80, 81, 82, 83, 84, 85, 86, 87, \n\t88, 89, 90, 91, 92, 93, 94, 95, \n\t96, 97, 98, 99, 100, 101, 102, 103, \n\t104, 105, 106, 107, 108, 109, 110, 111, \n\t112, 113, 114, 115, 116, 117, 118, 119, \n\t120, 121, 122, 123, 124, 125, 126, 127, \n\t128, 129, 130, 131, 132, 133, 134, 135, \n\t136, 137, 138, 139, 140, 141, 142, 143, \n\t144, 145, 146, 147, 148, 149, 150, 151, \n\t152, 153, 154, 155, 156, 157, 158, 159, \n\t160, 161, 162, 163, 164, 165, 166, 167, \n\t168, 169, 170, 171, 172, 173, 174, 175, \n\t176, 177, 178, 179, 180, 181, 182, 183, \n\t184, 185, 186, 187, 188, 189, 190, 191, \n\t192, 193, 194, 195, 196, 197, 198, 199, \n\t200, 201, 202, 203, 204, 205, 206, 207, \n\t208, 209, 210, 211, 212, 213, 214, 215, \n\t216, 217, 218, 219, 220, 221, 222, 223, \n\t224, 225, 226, 227, 228, 229, 230, 231, \n\t232, 233, 234, 235, 236, 237, 238, 239, \n\t240, 241, 242, 243, 244, 245, 246, 247, \n\t248, 249, 250, 251, 252, 253, 254, 255, \n\t256, 257, 258, 259, 260, 261, 262, 263, \n\t264, 265, 266, 267, 268, 269, 270, 271, \n\t272, 273, 274, 275, 276, 277, 278, 279, \n\t280, 281, 282, 283, 284, 285, 286, 287, \n\t288, 289, 290, 291, 292, 293, 294, 295, \n\t296, 297, 298, 299, 300, 301, 302, 303, \n\t304, 305, 306, 307, 308, 309, 310, 311, \n\t312, 313, 314, 315, 316, 317, 318, 319, \n\t320, 321, 322, 323, 324, 325, 326, 327, \n\t328, 329, 330, 331, 332, 333, 334, 335, \n\t336, 337, 338, 339, 340, 341, 342, 343, \n\t344, 345, 346, 347, 348, 349, 350, 351, \n\t352, 353, 354, 355, 356, 357, 358, 359, \n\t360, 361, 362, 363, 364, 365, 366, 367, \n\t368, 369, 370, 371, 372, 373, 374, 375, \n\t376, 377, 378, 379, 380, 381, 382, 383, \n\t384, 385, 386, 387, 388, 389, 390, 391, \n\t392, 393, 394, 395, 396, 397, 398, 399, \n\t400, 401, 402, 403, 404, 405, 406, 407, \n\t408, 409, 410, 411, 412, 413, 414, 415, \n\t416, 417, 418, 419, 420, 421, 422, 423, \n\t424, 425, 426, 427, 428, 429, 430, 431, \n\t432, 433, 434, 435, 436, 437, 438, 439, \n\t440, 441, 442, 443, 444, 445, 446, 447, \n\t448, 449, 450, 451, 452, 453, 454, 455, \n\t456, 457, 458, 459, 460, 461, 462, 463, \n\t464, 465, 466, 467, 468, 469, 470, 471, \n\t472, 473, 474, 475, 476, 477, 478, 479, \n\t480, 481, 482, 483, 484, 485, 486, 487, \n\t488, 489, 490, 491, 492, 493, 494, 495, \n\t496, 497, 498, 499, 500, 501, 502, 503, \n\t504, 505, 506, 507, 508, 509, 510, 511, \n\t512, 513, 514, 515, 516, 517, 518, 519, \n\t520, 521, 522, 523, 524, 525, 526, 527, \n\t528, 529, 530, 531, 532, 533, 534, 535, \n\t536, 537, 538, 539, 540, 541, 542, 543, \n\t544, 545, 546, 547, 548, 549, 550, 551, \n\t552, 553, 554, 555, 556, 557, 558, 559, \n\t560, 561, 562, 563, 564, 565, 566, 567, \n\t568, 569, 570, 571, 572, 573, 574, 575, \n\t576, 577, 578, 579, 580, 581, 582, 583, \n\t584, 585, 586, 587, 588, 589, 590, 591, \n\t592, 593, 594, 595, 596, 597, 598, 599, \n\t600, 601, 602, 603, 604, 605, 606, 607, \n\t608, 609, 610, 611, 612, 613, 614, 615, \n\t616, 617, 618, 619, 620, 621, 622, 623, \n\t624, 625, 626, 627, 628, 629, 630, 631, \n\t632, 633, 634, 635, 636, 637, 638, 639, \n\t640, 641, 642, 643, 644, 645, 646, 647, \n\t648, 649, 650, 651, 652, 653, 654, 655, \n\t656, 657, 658, 659, 660, 661, 662, 663, \n\t664, 665, 666, 667, 668, 669, 670, 671, \n\t672, 673, 674, 675, 676, 677, 678, 679, \n\t680, 681, 682, 683, 684, 685, 686, 687, \n\t688, 689, 690, 691, 692, 693, 694, 695, \n\t696, 697, 698, 699, 700, 701, 702, 703, \n\t704, 705, 706, 707, 708, 709, 710, 711, \n\t712, 713, 714, 715, 716, 717, 718, 719, \n\t720, 721, 722, 723, 724, 725, 726, 727, \n\t728, 729, 730, 731, 732, 733, 734, 735, \n\t736, 737, 738, 739, 740, 741, 742, 743, \n\t744, 745, 746, 747, 748, 749, 750, 751, \n\t752, 753, 754, 755, 756, 757, 758, 759, \n\t760, 761, 762, 763, 764, 765, 766, 767, \n\t768, 769, 770, 771, 772, 773, 774, 775, \n\t776, 777, 778, 779, 780, 781, 782, 783, \n\t784, 785, 786, 787, 788, 789, 790, 791, \n\t792, 793, 794, 795, 796, 797, 798, 799, \n\t800, 801, 802, 803, 804, 805, 806, 807, \n\t808, 809, 810, 811, 812, 813, 814, 815, \n\t816, 817, 818, 819, 820, 821, 822, 823, \n\t824, 825, 826, 827, 828, 829, 830, 831, \n\t832, 833, 834, 835, 836, 837, 838, 839, \n\t840, 841, 842, 843, 844, 845, 846, 847, \n\t848, 849, 850, 851, 852, 853, 854, 855, \n\t856, 857, 858, 859, 860, 861, 862, 863, \n\t864, 865, 866, 867, 868, 869, 870, 871, \n\t872, 873, 874, 875, 876, 877, 878, 879, \n\t880, 881, 882, 883, 884, 885, 886, 887, \n\t888, 889, 890, 891, 892, 893, 894, 895, \n\t896, 897, 898, 899, 900, 901, 902, 903, \n\t904, 905, 906, 907, 908, 909, 910, 911, \n\t912, 913, 914, 915, 916, 917, 918, 919, \n\t920, 921, 922, 923, 924, 925, 926, 927, \n\t928, 929, 930, 931, 932, 933, 934, 935, \n\t936, 937, 938, 939, 940, 941, 942, 943, \n\t944, 945, 946, 947, 948, 949, 950, 951, \n\t952, 953, 954, 955, 956, 957, 958, 959, \n\t960, 961, 962, 963, 964, 965, 966, 967, \n\t968, 969, 970, 971, 972, 973, 974, 975, \n\t976, 977, 978, 979, 980, 981, 982, 983, \n\t984, 985, 986, 987, 988, 989, 990, 991, \n\t992, 993, 994, 995, 996, 997, 998, 999, \n\t1000, 1001, 1002, 1003, 1004, 1005, 1006, 1007, \n\t1008, 1009, 1010, 1011, 1012, 1013, 1014, 1015, \n\t1016, 1017, 1018, 1019, 1020, 1021, 1022, 1023, \n\t1024, 1025, 1026, 1027, 1028, 1029, 1030, 1031, \n\t1032, 1033, 1034, 1035, 1036, 1037, 1038, 1039, \n\t1040, 1041, 1042, 1043, 1044, 1045, 1046, 1047, \n\t1048, 1049, 1050, 1051, 1052, 1053, 1054, 1055, \n\t1056, 1057, 1058, 1059, 1060, 1061, 1062, 1063, \n\t1064, 1065, 1066, 1067, 1068, 1069, 1070, 1071, \n\t1072, 1073, 1074, 1075, 1076, 1077, 1078, 1079, \n\t1080, 1081, 1082, 1083, 1084, 1085, 1086, 1087, \n\t1088, 1089, 1090, 1091, 1092, 1093, 1094, 1095, \n\t1096, 1097, 1098, 1099, 1100, 1101, 1102, 1103, \n\t1104, 1105, 1106, 1107, 1108, 1109, 1110, 1111, \n\t1112, 1113, 1114, 1115, 1116, 1117, 1118, 1119, \n\t1120, 1121, 1122, 1123, 1124, 1125, 1126, 1127, \n\t1128, 1129, 1130, 1131, 1132, 1133, 1134, 1135, \n\t1136, 1137, 1138, 1139, 1140, 1141, 1142, 1143, \n\t1144, 1145, 1146, 1147, 1148, 1149, 1150, 1151, \n\t1152, 1153, 1154, 1155, 1156, 1157, 1158, 1159, \n\t1160, 1161, 1162, 1163, 1164, 1165, 1166, 1167, \n\t1168, 1169, 1170, 1171, 1172, 1173, 1174, 1175, \n\t1176, 1177, 1178, 1179, 1180, 1181, 1182, 1183, \n\t1184, 1185, 1186, 1187, 1188, 1189, 1190, 1191, \n\t1192, 1193, 1194, 1195, 1196, 1197, 1198, 1199, \n\t1200, 1201, 1202, 1203, 1204, 1205, 1206, 1207, \n\t1208, 1209, 1210, 1211, 1212, 1213, 1214, 1215, \n\t1216, 1217, 1218, 1219, 1220, 1221, 1222, 1223, \n\t1224, 1225, 1226, 1227, 1228, 1229, 1230, 1231, \n\t1232, 1233, 1234, 1235, 1236, 1237, 1238, 1239, \n\t1240, 1241, 1242, 1243, 1244, 1245, 1246, 1247, \n\t1248, 1249, 1250, 1251, 1252, 1253, 1254, 1255, \n\t1256, 1257, 1258, 1259, 1260, 1261, 1262, 1263, \n\t1264, 1265, 1266, 1267, 1268, 1269, 1270, 1271, \n\t1272, 1273, 1274, 1275, 1276, 1277, 1278, 1279, \n\t1280, 1281, 1282, 1283, 1284, 1285, 1286, 1287, \n\t1288, 1289, 1290, 1291, 1292, 1293, 1294, 1295, \n\t1296, 1297, 1298, 1299, 1300, 1301, 1302, 1303, \n\t1304, 1305, 1306, 1307, 1308, 1309, 1310, 1311, \n\t1312, 1313, 1314, 1315, 1316, 1317, 1318, 1319, \n\t1320, 1321, 1322, 1323, 1324, 1325, 1326, 1327, \n\t1328, 1329, 1330, 1331, 1332, 1333, 1334, 1335, \n\t1336, 1337, 1338, 1339, 1340, 1341, 1342, 1343, \n\t1344, 1345, 1346, 1347, 1348, 1349, 1350, 1351, \n\t1352, 1353, 1354, 1355, 1356, 1357, 1358, 1359, \n\t1360, 1361, 1362, 1363, 1364, 1365, 1366, 1367, \n\t1368, 1369, 1370, 1371, 1372, 1373, 1374, 1375, \n\t1376, 1377, 1378, 1379, 1380, 1381, 1382, 1383, \n\t1384, 1385, 1386, 1387, 1388, 1389, 1390, 1391, \n\t1392, 1393, 1394, 1395, 1396, 1397, 1398, 1399, \n\t1400, 1401, 1402, 1403, 1404, 1405, 1406, 1407, \n\t1408, 1409, 1410, 1411, 1412, 1413, 1414, 1415, \n\t1416, 1417, 1418, 1419, 1420, 1421, 1422, 1423, \n\t1424, 1425, 1426, 1427, 1428, 1429, 1430, 1431, \n\t1432, 1433, 1434, 1435, 1436, 1437, 1438, 1439, \n\t1440, 1441, 1442, 1443, 1444, 1445, 1446, 1447, \n\t1448, 1449, 1450, 1451, 1452, 1453, 1454, 1455, \n\t1456, 1457, 1458, 1459, 1460, 1461, 1462, 1463, \n\t1464, 1465, 1466, 1467, 1468, 1469, 1470, 1471, \n\t1472, 1473, 1474, 1475, 1476, 1477, 1478, 1479, \n\t1480, 1481, 1482, 1483, 1484, 1485, 1486, 1487, \n\t1488, 1489, 1490, 1491, 1492, 1493, 1494, 1495, \n\t1496, 1497, 1498, 1499, 1500, 1501, 1502, 1503, \n\t1504, 1505, 1506, 1507, 1508, 1509, 1510, 1511, \n\t1512, 1513, 1514, 1515, 1516, 1517, 1518, 1519, \n\t1520, 1521, 1522, 1523, 1524, 1525, 1526, 1527, \n\t1528, 1529, 1530, 1531, 1532, 1533, 1534, 1535, \n\t1536, 1537, 1538, 1539, 1540, 1541, 1542, 1543, \n\t1544, 1545, 1546, 1547, 1548, 1549, 1550, 1551, \n\t1552, 1553, 1554, 1555, 1556, 1557, 1558, 1559, \n\t1560, 1561, 1562, 1563, 1564, 1565, 1566, 1567, \n\t1568, 1569, 1570, 1571, 1572, 1573, 1574, 1575, \n\t1576, 1577, 1578, 1579, 1580, 1581, 1582, 1583, \n\t1584, 1585, 1586, 1587, 1588, 1589, 1590, 1591, \n\t1592, 1593, 1594, 1595, 1596, 1597, 1598, 1599, \n\t1600, 1601, 1602, 1603, 1604, 1605, 1606, 1607, \n\t1608, 1609, 1610, 1611, 1612, 1613, 1614, 1615, \n\t1616, 1617, 1618, 1619, 1620, 1621, 1622, 1623, \n\t1624, 1625, 1626, 1627, 1628, 1629, 1630, 1631, \n\t1632, 1633, 1634, 1635, 1636, 1637, 1638, 1639, \n\t1640, 1641, 1642, 1643, 1644, 1645, 1646, 1647, \n\t1648, 1649, 1650, 1651, 1652, 1653, 1654, 1655, \n\t1656, 1657, 1658, 1659, 1660, 1661, 1662, 1663, \n\t1664, 1665, 1666, 1667, 1668, 1669, 1670, 1671, \n\t1672, 1673, 1674, 1675, 1676, 1677, 1678, 1679, \n\t1680, 1681, 1682, 1683, 1684, 1685, 1686, 1687, \n\t1688, 1689, 1690, 1691, 1692, 1693, 1694, 1695, \n\t1696, 1697, 1698, 1699, 1700, 1701, 1702, 1703, \n\t1704, 1705, 1706, 1707, 1708, 1709, 1710, 1711, \n\t1712, 1713, 1714, 1715, 1716, 1717, 1718, 1719, \n\t1720, 1721, 1722, 1723, 1724, 1725, 1726, 1727, \n\t1728, 1729, 1730, 1731, 1732, 1733, 1734, 1735, \n\t1736, 1737, 1738, 1739, 1740, 1741, 1742, 1743, \n\t1744, 1745, 1746, 1747, 1748, 1749, 1750, 1751, \n\t1752, 1753, 1754, 1755, 1756, 1757, 1758, 1759, \n\t1760, 1761, 1762, 1763, 1764, 1765, 1766, 1767, \n\t1768, 1769, 1770, 1771, 1772, 1773, 1774, 1775, \n\t1776, 1777, 1778, 1779, 1780, 1781, 1782, 1783, \n\t1784, 1785, 1786, 1787, 1788, 1789, 1790, 1791, \n\t1792, 1793, 1794, 1795, 1796, 1797, 1798, 1799, \n\t1800, 1801, 1802, 1803, 1804, 1805, 1806, 1807, \n\t1808, 1809, 1810, 1811, 1812, 1813, 1814, 1815, \n\t1816, 1817, 1818, 1819, 1820, 1821, 1822, 1823, \n\t1824, 1825, 1826, 1827, 1828, 1829, 1830, 1831, \n\t1832, 1833, 1834, 1835, 1836, 1837, 1838, 1839, \n\t1840, 1841, 1842, 1843, 1844, 1845, 1846, 1847, \n\t1848, 1849, 1850, 1851, 1852, 1853, 1854, 1855, \n\t1856, 1857, 1858, 1859, 1860, 1861, 1862, 1863, \n\t1864, 1865, 1866, 1867, 1868, 1869, 1870, 1871, \n\t1872, 1873, 1874, 1875, 1876, 1877, 1878, 1879, \n\t1880, 1881, 1882, 1883, 1884, 1885, 1886, 1887, \n\t1888, 1889, 1890, 1891, 1892, 1893, 1894, 1895, \n\t1896, 1897, 1898, 1899, 1900, 1901, 1902, 1903, \n\t1904, 1905, 1906, 1907, 1908, 1909, 1910, 1911, \n\t1912, 1913, 1914, 1915, 1916, 1917, 1918, 1919, \n\t1920, 1921, 1922, 1923, 1924, 1925, 1926, 1927, \n\t1928, 1929, 1930, 1931, 1932, 1933, 1934, 1935, \n\t1936, 1937, 1938, 1939, 1940, 1941, 1942, 1943, \n\t1944, 1945, 1946, 1947, 1948, 1949, 1950, 1951, \n\t1952, 1953, 1954, 1955, 1956, 1957, 1958, 1959, \n\t1960, 1961, 1962, 1963, 1964, 1965, 1966, 1967, \n\t1968, 1969, 1970, 1971, 1972, 1973, 1974, 1975, \n\t1976, 1977, 1978, 1979, 1980, 1981, 1982, 1983, \n\t1984, 1985, 1986, 1987, 1988, 1989, 1990, 1991, \n\t1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, \n\t2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, \n\t2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, \n\t2016, 2017, 2018, 2019, 2020, 2021, 2022, 2023, \n\t2024, 2025, 2026, 2027, 2028, 2029, 2030, 2031, \n\t2032, 2033, 2034, 2035, 2036, 2037, 2038, 2039, \n\t2040, 2041, 2042, 2043, 2044, 2045, 2046, 2047, \n\t2048, 2049, 2050, 2051, 2052, 2053, 2054, 2055, \n\t2056, 2057, 2058, 2059, 2060, 2061, 2062, 2063, \n\t2064, 2065, 2066, 2067, 2068, 2069, 2070, 2071, \n\t2072, 2073, 2074, 2075, 2076, 2077, 2078, 2079, \n\t2080, 2081, 2082, 2083, 2084, 2085, 2086, 2087, \n\t2088, 2089, 2090, 2091, 2092, 2093, 2094, 2095, \n\t2096, 2097, 2098, 2099, 2100, 2101, 2102, 2103, \n\t2104, 2105, 2106, 2107, 2108, 2109, 2110, 2111, \n\t2112, 2113, 2114, 2115, 2116, 2117, 2118, 2119, \n\t2120, 2121, 2122, 2123, 2124, 2125, 2126, 2127, \n\t2128, 2129, 2130, 2131, 2132, 2133, 2134, 2135, \n\t2136, 2137, 2138, 2139, 2140, 2141, 2142, 2143, \n\t2144, 2145, 2146, 2147, 2148, 2149, 2150, 2151, \n\t2152, 2153, 2154, 2155, 2156, 2157, 2158, 2159, \n\t2160, 2161, 2162, 2163, 2164, 2165, 2166, 2167, \n\t2168, 2169, 2170, 2171, 2172, 2173, 2174, 2175, \n\t2176, 2177, 2178, 2179, 2180, 2181, 2182, 2183, \n\t2184, 2185, 2186, 2187, 2188, 2189, 2190, 2191, \n\t2192, 2193, 2194, 2195, 2196, 2197, 2198, 2199, \n\t2200, 2201, 2202, 2203, 2204, 2205, 2206, 2207, \n\t2208, 2209, 2210, 2211, 2212, 2213, 2214, 2215, \n\t2216, 2217, 2218, 2219, 2220, 2221, 2222, 2223, \n\t2224, 2225, 2226, 2227, 2228, 2229, 2230, 2231, \n\t2232, 2233, 2234, 2235, 2236, 2237, 2238, 2239, \n\t2240, 2241, 2242, 2243, 2244, 2245, 2246, 2247, \n\t2248, 2249, 2250, 2251, 2252, 2253, 2254, 2255, \n\t2256, 2257, 2258, 2259, 2260, 2261, 2262, 2263, \n\t2264, 2265, 2266, 2267, 2268, 2269, 2270, 2271, \n\t2272, 2273, 2274, 2275, 2276, 2277, 2278, 2279, \n\t2280, 2281, 2282, 2283, 2284, 2285, 2286, 2287, \n\t2288, 2289, 2290, 2291, 2292, 2293, 2294, 2295, \n\t2296, 2297, 2298, 2299, 2300, 2301, 2302, 2303, \n\t2304, 2305, 2306, 2307, 2308, 2309, 2310, 2311, \n\t2312, 2313, 2314, 2315, 2316, 2317, 2318, 2319, \n\t2320, 2321, 2322, 2323, 2324, 2325, 2326, 2327, \n\t2328, 2329, 2330, 2331, 2332, 2333, 2334, 2335, \n\t2336, 2337, 2338, 2339, 2340, 2341, 2342, 2343, \n\t2344, 2344, 2345, 2346, 2347, 2348, 2349, 2350, \n\t2351, 2352, 2353, 2354, 2355, 2356, 2357, 2358, \n\t2359, 2360, 2361, 2362, 2363, 2364, 2365, 2366, \n\t2367, 2368, 2369, 2370, 2371, 2372, 2373, 2374, \n\t2375, 2376, 2377, 2378, 2379, 2380, 2381, 2382, \n\t2383, 2384, 2385, 2386, 2387, 2388, 2389, 2390, \n\t2391, 2392, 2393, 2394, 2395, 2396, 2397, 2398, \n\t2399, 2400, 2401, 2402, 2403, 2404, 2405, 2406, \n\t2407, 2408, 2409, 2410, 2411, 2412, 2413, 2414, \n\t2415, 2416, 2417, 2418, 2419, 2420, 2421, 2422, \n\t2423, 2424, 2425, 2426, 2427, 2428, 2429, 2430, \n\t2431, 2432, 2433, 2434, 2435, 2436, 2437, 2438, \n\t2439, 2440, 2441, 2442, 2443, 2444, 2445, 2446, \n\t2447, 2448, 2449, 2450, 2451, 2452, 2453, 2454, \n\t2455, 2456, 2457, 2458, 2459, 2460, 2461, 2462, \n\t2463, 2464, 2465, 2466, 2467, 2468, 2469, 2470, \n\t2471, 2472, 2473, 2474, 2475, 2476, 2477, 2478, \n\t2479, 2480, 2481, 2482, 2483, 2484, 2485, 2486, \n\t2487, 2488, 2489, 2490, 2491, 2492, 2493, 2494, \n\t2495, 2496, 2497, 2498, 2499, 2500, 2501, 2502, \n\t2503, 2504, 2505, 2506, 2507, 2508, 2509, 2510, \n\t2511, 2512, 2513, 2514, 2515, 2516, 2517, 2518, \n\t2519, 2520, 2521, 2522, 2523, 2524, 2525, 2526, \n\t2527, 2528, 2529, 2530, 2531, 2532, 2533, 2534, \n\t2535, 2536, 2537, 2538, 2539, 2540, 2541, 2542, \n\t2543, 2544, 2545, 2546, 2547, 2548, 2549, 2550, \n\t2551, 2552, 2553, 2554, 2555, 2556, 2557, 2558, \n\t2559, 2560, 2561, 2562, 2563, 2564, 2565, 2566, \n\t2567, 2568, 2569, 2570, 2571, 2572, 2573, 2574, \n\t2575, 2576, 2577, 2578, 2579, 2580, 2581, 2582, \n\t2583, 2584, 2585, 2586, 2587, 2588, 2589, 2590, \n\t2591, 2592, 2593, 2594, 2595, 2596, 2597, 2598, \n\t2599, 2600, 2601, 2602, 2603, 2604, 2605, 2606, \n\t2607, 2608, 2609, 2610, 2611, 2612, 2613, 2614, \n\t2615, 2616, 2617, 2618, 2619, 2620, 2621, 2622, \n\t2623, 2624, 2625, 2626, 2627, 2628, 2629, 2630, \n\t2631, 2632, 2633, 2634, 2635, 2636, 2637, 2638, \n\t2639, 2640, 2641, 2642, 2643, 2644, 2645, 2646, \n\t2647, 2648, 2649, 2650, 2651, 2652, 2653, 2654, \n\t2655, 2656, 2657, 2658, 2659, 2660, 2661, 2662, \n\t2663, 2664, 2665, 2666, 2667, 2668, 2669, 2670, \n\t2671, 2672, 2673, 2674, 2675, 2676, 2677, 2678, \n\t2679, 2680, 2681, 2682, 2683, 2684, 2685, 2686, \n\t2687, 2688, 2689, 2690, 2691, 2692, 2693, 2694, \n\t2695, 2696, 2697, 2698, 2699, 2700, 2701, 2702, \n\t2703, 2704, 2705, 2706, 2707, 2708, 2709, 2710, \n\t2711, 2712, 2713, 2714, 2715, 2716, 2717, 2718, \n\t2719, 2720, 2721, 2722, 2723, 2724, 2725, 2726, \n\t2727, 2728, 2729, 2730, 2731, 2732, 2733, 2734, \n\t2735, 2736, 2737, 2738, 2739, 2740, 2741, 2742, \n\t2743, 2744, 2745, 2746, 2747, 2748, 2749, 2750, \n\t2751, 2752, 2753, 2754, 2755, 2756, 2757, 2758, \n\t2759, 2760, 2761, 2762, 2763, 2764, 2765, 2766, \n\t2767, 2768, 2769, 2770, 2771, 2772, 2773, 2774, \n\t2775, 2776, 2777, 2778, 2779, 2780, 2781, 2782, \n\t2783, 2784, 2785, 2786, 2787, 2788, 2789, 2790, \n\t2791, 2792, 2793, 2794, 2795, 2796, 2797, 2798, \n\t2799, 2800, 2801, 2802, 2803, 2804, 2805, 2806, \n\t2807, 2808, 2809, 2810, 2811, 2812, 2813, 2814, \n\t2815, 2816, 2817, 2818, 2819, 2820, 2821, 2822, \n\t2823, 2824, 2825, 2826, 2827, 2828, 2829, 2830, \n\t2831, 2832, 2833, 2834, 2835, 2836, 2837, 2838, \n\t2839, 2840, 2841, 2842, 2843, 2844, 2845, 2846, \n\t2847, 2848, 2849, 2850, 2851, 2852, 2853, 2854, \n\t2855, 2856, 2857, 2858, 2859, 2860, 2861, 2862, \n\t2863, 2864, 2865, 2866, 2867, 2868, 2869, 2870, \n\t2871, 2872, 2873, 2874, 2875, 2876, 2877, 2878, \n\t2879, 2880, 2881, 2882, 2883, 2884, 2885, 2886, \n\t2887, 2888, 2889, 2890, 2891, 2892, 2893, 2894, \n\t2895, 2896, 2897, 2898, 2899, 2900, 2901, 2902, \n\t2903, 2904, 2905, 2906, 2907, 2908, 2909, 2910, \n\t2911, 2912, 2913, 2914, 2915, 2916, 2917, 2918, \n\t2919, 2920, 2921, 2922, 2923, 2924, 2925, 2926, \n\t2927, 2928, 2929, 2930, 2931, 2932, 2933, 2934, \n\t2935, 2936, 2937, 2938, 2939, 2940, 2941, 2942, \n\t2943, 2944, 2945, 2946, 2947, 2948, 2949, 2950, \n\t2951, 2952, 2953, 2954, 2955, 2956, 2957, 2958, \n\t2959, 2960, 2961, 2962, 2963, 2964, 2965, 2966, \n\t2967, 2968, 2969, 2970, 2971, 2972, 2973, 2974, \n\t2975, 2976, 2977, 2978, 2979, 2980, 2981, 2982, \n\t2983, 2984, 2985, 2986, 2987, 2988, 2989, 2990, \n\t2991, 2992, 2993, 2994, 2995, 2996, 2997, 2998, \n\t2999, 3000, 3001, 3002, 3003, 3004, 3005, 3006, \n\t3007, 3008, 3009, 3010, 3011, 3012, 3013, 3014, \n\t3015, 3016, 3017, 3018, 3019, 3020, 3021, 3022, \n\t3023, 3024, 3025, 3026, 3027, 3028, 3029, 3030, \n\t3031, 3032, 3033, 3034, 3035, 3036, 3037, 3038, \n\t3039, 3040, 3041, 3042, 3043, 3044, 3045, 3046, \n\t3047, 3048, 3049, 3050, 3051, 3052, 3053, 3054, \n\t3055, 3056, 3057, 3058, 3059, 3060, 3061, 3062, \n\t3063, 3064, 3065, 3066, 3067, 3068, 3069, 3070, \n\t3071, 3072, 3073, 3074, 3075, 3076, 3077, 3078, \n\t3079, 3080, 3081, 3082, 3083, 3084, 3085, 3086, \n\t3087, 3088, 3089, 3090, 3091, 3092, 3093, 3094, \n\t3095, 3096, 3097, 3098, 3099, 3100, 3101, 3102, \n\t3103, 3104, 3105, 3106, 3107, 3108, 3109, 3110, \n\t3111, 3112, 3113, 3114, 3115, 3116, 3117, 3118, \n\t3119, 3120, 3121, 3122, 3123, 3124, 3125, 3126, \n\t3127, 3128, 3129, 3130, 3131, 3132, 3133, 3134, \n\t3135, 3136, 3137, 3138, 3139, 3140, 3141, 3142, \n\t3143, 3144, 3145, 3146, 3147, 3148, 3149, 3150, \n\t3151, 3152, 3153, 3154, 3155, 3156, 3157, 3158, \n\t3159, 3160, 3161, 3162, 3163, 3164, 3165, 3166, \n\t3167, 3168, 3169, 3170, 3171, 3172, 3173, 3174, \n\t3175, 3176, 3177, 3178, 3179, 3180, 3181, 3182, \n\t3183, 3184, 3185, 3186, 3187, 3188, 3189, 3190, \n\t3191, 3192, 3193, 3194, 3195, 3196, 3197, 3198, \n\t3199, 3200, 3201, 3202, 3203, 3204, 3205, 3206, \n\t3207, 3208, 3209, 3210, 3211, 3212, 3213, 3214, \n\t3215, 3216, 3217, 3218, 3219, 3220, 3221, 3222, \n\t3223, 3224, 3225, 3226, 3227, 3228, 3229, 3230, \n\t3231, 3232, 3233, 3234, 3235, 3236, 3237, 3238, \n\t3239, 3240, 3241, 3242, 3243, 3244, 3245, 3246, \n\t3247, 3248, 3249, 3250, 3251, 3252, 3253, 3254, \n\t3255, 3256, 3257, 3258, 3259, 3260, 3261, 3262, \n\t3263, 3264, 3265, 3266, 3267, 3268, 3269, 3270, \n\t3271, 3272, 3273, 3274, 3275, 3276, 3277, 3278, \n\t3279, 3280, 3281, 3282, 3283, 3284, 3285, 3286, \n\t3287, 3288, 3289, 3290, 3291, 3292, 3293, 3294, \n\t3295, 3296, 3297, 3298, 3299, 3300, 3301, 3302, \n\t3303, 3304, 3305, 3306, 3307, 3308, 3309, 3310, \n\t3311, 3312, 3313, 3314, 3315, 3316, 3317, 3318, \n\t3319, 3320, 3321, 3322, 3323, 3324, 3325, 3326, \n\t3327, 3328, 3329, 3330, 3331, 3332, 3333, 3334, \n\t3335, 3336, 3337, 3338, 3339, 3340, 3341, 3342, \n\t3343, 3344, 3345, 3346, 3347, 3348, 3349, 3350, \n\t3351, 3352, 3353, 3354, 3355, 3356, 3357, 3358, \n\t3359, 3360, 3361, 3362, 3363, 3364, 3365, 3366, \n\t3367, 3368, 3369, 3370, 3371, 3372, 3373, 3374, \n\t3375, 3376, 3377, 3378, 3379, 3380, 3380, 3381, \n\t3382, 3383, 3384, 3385, 3386, 3387, 3388, 3389, \n\t3390, 3391, 3392, 3393, 3394, 3395, 3396, 3397, \n\t3398, 3399, 3400, 3401, 3402, 3403, 3404, 3405, \n\t3406, 3407, 3408, 3409, 3410, 3411, 3412, 3413, \n\t3414, 3415, 3416, 3417, 3418, 3419, 3420, 3421, \n\t3422, 3423, 3424, 3425, 3426, 3427, 3428, 3429, \n\t3430, 3431, 3432, 3433, 3434, 3435, 3436, 3437, \n\t3438, 3439, 3440, 3441, 3442, 3443, 3444, 3445, \n\t3446, 3447, 3448, 3449, 3450, 3451, 3452, 3453, \n\t3454, 3455, 3456, 3457, 3458, 3459, 3460, 3461, \n\t3462, 3463, 3464, 3465, 3466, 3467, 3468, 3469, \n\t3470, 3471, 3472, 3473, 3474, 3475, 3476, 3477, \n\t3478, 3479, 3480, 3481, 3482, 3483, 3484, 3485, \n\t3486, 3487, 3488, 3489, 3490, 3491, 3492, 3493, \n\t3494, 3495, 3496, 3497, 3498, 3499, 3500, 3501, \n\t3502, 3503, 3504, 3505, 3506, 3507, 3508, 3509, \n\t3510, 3511, 3512, 3513, 3514, 3515, 3516, 3517, \n\t3518, 3519, 3520, 3521, 3522, 3523, 3524, 3525, \n\t3526, 3527, 3528, 3529, 3530, 3531, 3532, 3533, \n\t3534, 3535, 3536, 3537, 3538, 3539, 3540, 3541, \n\t3542, 3543, 3544, 3545, 3546, 3547, 3548, 3549, \n\t3550, 3551, 3552, 3553, 3554, 3555, 3556, 3557, \n\t3558, 3559, 3560, 3561, 3562, 3563, 3564, 3565, \n\t3566, 3567, 3568, 3569, 3570, 3571, 3572, 3573, \n\t3574, 3575, 3576, 3577, 3578, 3579, 3580, 3581, \n\t3582, 3583, 3584, 3585, 3586, 3587, 3588, 3589, \n\t3590, 3591, 3592, 3593, 3594, 3595, 3596, 3597, \n\t3598, 3599, 3600, 3601, 3602, 3603, 3604, 3605, \n\t3606, 3607, 3608, 3609, 3610, 3611, 3612, 3613, \n\t3614, 3615, 3616, 3617, 3618, 3619, 3620, 3621, \n\t3622, 3623, 3624, 3625, 3626, 3627, 3628, 3629, \n\t3630, 3631, 3632, 3633, 3634, 3635, 3636, 3637, \n\t3638, 3639, 3640, 3641, 3642, 3643, 3644, 3645, \n\t3646, 3647, 3648, 3649, 3650, 3651, 3652, 3653, \n\t3654, 3655, 3656, 3657, 3658, 3659, 3660, 3661, \n\t3662, 3663, 3664, 3665, 3666, 3667, 3668, 3669, \n\t3670, 3671, 3672, 3673, 3674, 3675, 3676, 3677, \n\t3678, 3679, 3680, 3681, 3682, 3683, 3684, 3685, \n\t3686, 3687, 3688, 3689, 3690, 3691, 3692, 3693, \n\t3694, 3695, 3696, 3697, 3698, 3699, 3700, 3701, \n\t3702, 3703, 3704, 3705, 3706, 3707, 3708, 3709, \n\t3710, 3711, 3712, 3713, 3714, 3715, 3716, 3717, \n\t3718, 3719, 3720, 3721, 3722, 3723, 3724, 3725, \n\t3726, 3727, 3728, 3729, 3730, 3731, 3732, 3733, \n\t3734, 3735, 3736, 3737, 3738, 3739, 3740, 3741, \n\t3742, 3743, 3744, 3745, 3746, 3747, 3748, 3749, \n\t3750, 3751, 3752, 3753, 3754, 3755, 3756, 3757, \n\t3758, 3759, 3760, 3761, 3762, 3763, 3764, 3765, \n\t3766, 3767, 3768, 3769, 3770, 3771, 3772, 3773, \n\t3774, 3775, 3776, 3777, 3778, 3779, 3780, 3781, \n\t3782, 3783, 3784, 3785, 3786, 3787, 3788, 3789, \n\t3790, 3791, 3792, 3793, 3794, 3795, 3796, 3797, \n\t3798, 3799, 3800, 3801, 3802, 3803, 3804, 3805, \n\t3806, 3807, 3808, 3809, 3810, 3811, 3812, 3813, \n\t3814, 3815, 3816, 3817, 3818, 3819, 3820, 3821, \n\t3822, 3823, 3824, 3825, 3826, 3827, 3828, 3829, \n\t3830, 3831, 3832, 3833, 3834, 3835, 3836, 3837, \n\t3838, 3839, 3840, 3841, 3842, 3843, 3844, 3845, \n\t3846, 3847, 3848, 3849, 3850, 3851, 3852, 3853, \n\t3854, 3855, 3856, 3857, 3858, 3859, 3860, 3861, \n\t3862, 3863, 3864, 3865, 3866, 3867, 3868, 3869, \n\t3870, 3871, 3872, 3873, 3874, 3875, 3876, 3877, \n\t3878, 3879, 3880, 3881, 3882, 3883, 3884, 3885, \n\t3886, 3887, 3888, 3889, 3890, 3891, 3892, 3893, \n\t3894, 3895, 3896, 3897, 3898, 3899, 3900, 3901, \n\t3902, 3903, 3904, 3905, 3906, 3907, 3908, 3909, \n\t3910, 3911, 3912, 3913, 3914, 3915, 3916, 3917, \n\t3918, 3919, 3920, 3921, 3922, 3923, 3924, 3925, \n\t3926, 3927, 3928, 3929, 3930, 3931, 3932, 3933, \n\t3934, 3935, 3936, 3937, 3938, 3939, 3940, 3941, \n\t3942, 3943, 3944, 3945, 3946, 3947, 3948, 3949, \n\t3950, 3951, 3952, 3953, 3954, 3955, 3956, 3957, \n\t3958, 3959, 3960, 3961, 3962, 3963, 3964, 3965, \n\t3966, 3967, 3968, 3969, 3970, 3971, 3972, 3973, \n\t3974, 3975, 3976, 3977, 3978, 3979, 3980, 3981, \n\t3982, 3983, 3984, 3985, 3986, 3987, 3988, 3989, \n\t3990, 3991, 3992, 3993, 3994, 3995, 3996, 3997, \n\t3998, 3999, 4000, 4001, 4002, 4003, 4004, 4005, \n\t4006, 4007, 4007, 4008, 4009, 4010, 4011, 4012, \n\t4013, 4014, 4015, 4016, 4017, 4018, 4019, 4020, \n\t4021, 4022, 4023, 4024, 4025, 4026, 4027, 4028, \n\t4029, 4030, 4031, 4032, 4033, 4034, 4035, 4036, \n\t4037, 4038, 4039, 4040, 4041, 4042, 4043, 4044, \n\t4045, 4046, 4047, 4048, 4049, 4050, 4051, 4052, \n\t4053, 4054, 4055, 4056, 4057, 4058, 4059, 4060, \n\t4061, 4062, 4063, 4064, 4065, 4066, 4067, 4068, \n\t4069, 4070, 4071, 4072, 4073, 4074, 4075, 4076, \n\t4077, 4078, 4079, 4080, 4081, 4082, 4083, 4084, \n\t4085, 4086, 4087, 4088, 4089, 4090, 4091, 4092, \n\t4093, 4094, 4095, 4096, 4097, 4098, 4099, 4100, \n\t4101, 4102, 4103, 4104, 4105, 4106, 4107, 4108, \n\t4109, 4110, 4111, 4112, 4113, 4114, 4115, 4116, \n\t4117, 4118, 4119, 4120, 4121, 4122, 4123, 4124, \n\t4125, 4126, 4127, 4128, 4129, 4130, 4131, 4132, \n\t4133, 4134, 4135, 4136, 4137, 4138, 4139, 4140, \n\t4141, 4142, 4143, 4144, 4145, 4146, 4147, 4148, \n\t4149, 4150, 4151, 4152, 4153, 4154, 4155, 4156, \n\t4157, 4158, 4159, 4160, 4161, 4162, 4163, 4164, \n\t4165, 4166, 4167, 4168, 4169, 4170, 4171, 4172, \n\t4173, 4174, 4175, 4176, 4177, 4178, 4179, 4180, \n\t4181, 4182, 4183, 4184, 4185, 4186, 4187, 4188, \n\t4189, 4190, 4191, 4192, 4193, 4194, 4195, 4196, \n\t4197, 4198, 4199, 4200, 4201, 4202, 4203, 4204, \n\t4205, 4206, 4207, 4208, 4209, 4210, 4211, 4212, \n\t4213, 4214, 4215, 4216, 4217, 4218, 4219, 4220, \n\t4221, 4222, 4223, 4224, 4225, 4226, 4227, 4228, \n\t4229, 4230, 4231, 4232, 4233, 4234, 4235, 4236, \n\t4237, 4238, 4239, 4240, 4241, 4242, 4243, 4244, \n\t4245, 4246, 4247, 4248, 4249, 4250, 4251, 4252, \n\t4253, 4254, 4255, 4256, 4257, 4258, 4259, 4260, \n\t4261, 4262, 4263, 4264, 4265, 4266, 4267, 4268, \n\t4269, 4270, 4271, 4272, 4273, 4274, 4275, 4276, \n\t4277, 4278, 4279, 4280, 4281, 4282, 4283, 4284, \n\t4285, 4286, 4287, 4288, 4289, 4290, 4291, 4292, \n\t4293, 4294, 4295, 4296, 4297, 4298, 4299, 4300, \n\t4301, 4302, 4303, 4304, 4305, 4306, 4307, 4308, \n\t4309, 4310, 4311, 4312, 4313, 4314, 4315, 4316, \n\t4317, 4318, 4319, 4320, 4321, 4322, 4323, 4324, \n\t4325, 4326, 4327, 4328, 4329, 4330, 4331, 4332, \n\t4333, 4334, 4335, 4336, 4337, 4338, 4339, 4340, \n\t4341, 4342, 4343, 4344, 4345, 4346, 4347, 4348, \n\t4349, 4350, 4351, 4352, 4353, 4354, 4355, 4356, \n\t4357, 4358, 4359, 4360, 4361, 4362, 4363, 4364, \n\t4365, 4366, 4367, 4368, 4369, 4370, 4371, 4372, \n\t4373, 4374, 4375, 4376, 4377, 4378, 4379, 4380, \n\t4381, 4382, 4383, 4384, 4385, 4386, 4387, 4388, \n\t4389, 4390, 4391, 4392, 4393, 4394, 4395, 4396, \n\t4397, 4398, 4399, 4400, 4401, 4402, 4403, 4404, \n\t4405, 4406, 4407, 4408, 4409, 4410, 4411, 4412, \n\t4413, 4414, 4415, 4416, 4417, 4418, 4419, 4420, \n\t4421, 4422, 4423, 4424, 4425, 4426, 4427, 4428, \n\t4429, 4430, 4431, 4432, 4433, 4434, 4435, 4436, \n\t4437, 4438, 4439, 4440, 4441, 4442, 4443, 4444, \n\t4445, 4446, 4447, 4448, 4449, 4450, 4451, 4452, \n\t4453, 4454, 4455, 4456, 4457, 4458, 4459, 4460, \n\t4461, 4462, 4463, 4464, 4465, 4466, 4467, 4468, \n\t4469, 4470, 4471, 4472, 4473, 4474, 4475, 4476, \n\t4477, 4478, 4479, 4480, 4481, 4481, 4482, 4483, \n\t4484, 4485, 4486, 4487, 4488, 4489, 4490, 4491, \n\t4492, 4493, 4494, 4495, 4496, 4497, 4498, 4499, \n\t4500, 4501, 4502, 4503, 4504, 4505, 4506, 4507, \n\t4508, 4509, 4510, 4511, 4512, 4513, 4514, 4515, \n\t4516, 4517, 4518, 4519, 4520, 4521, 4522, 4523, \n\t4524, 4525, 4526, 4527, 4528, 4529, 4530, 4531, \n\t4532, 4533, 4534, 4535, 4536, 4537, 4538, 4539, \n\t4540, 4541, 4542, 4543, 4544, 4545, 4546, 4547, \n\t4548, 4549, 4550, 4551, 4552, 4553, 4554, 4555, \n\t4556, 4557, 4558, 4559, 4560, 4561, 4562, 4563, \n\t4564, 4565, 4566, 4567, 4568, 4569, 4570, 4571, \n\t4572, 4573, 4574, 4575, 4576, 4577, 4578, 4579, \n\t4580, 4581, 4582, 4583, 4584, 4585, 4586, 4587, \n\t4588, 4589, 4590, 4591, 4592, 4593, 4594, 4595, \n\t4596, 4597, 4598, 4599, 4600, 4601, 4602, 4603, \n\t4604, 4605, 4606, 4607, 4608, 4609, 4610, 4611, \n\t4612, 4613, 4614, 4615, 4616, 4617, 4618, 4619, \n\t4620, 4621, 4622, 4623, 4624, 4625, 4626, 4627, \n\t4628, 4629, 4630, 4631, 4632, 4633, 4634, 4635, \n\t4636, 4637, 4638, 4639, 4640, 4641, 4642, 4643, \n\t4644, 4645, 4646, 4647, 4648, 4649, 4650, 4651, \n\t4652, 4653, 4654, 4655, 4656, 4657, 4658, 4659, \n\t4660, 4661, 4662, 4663, 4664, 4665, 4666, 4667, \n\t4668, 4669, 4670, 4671, 4672, 4673, 4674, 4675, \n\t4676, 4677, 4678, 4679, 4680, 4681, 4682, 4683, \n\t4684, 4685, 4686, 4687, 4688, 4689, 4690, 4691, \n\t4692, 4693, 4694, 4695, 4696, 4697, 4698, 4699, \n\t4700, 4701, 4702, 4703, 4704, 4705, 4706, 4707, \n\t4708, 4709, 4710, 4711, 4712, 4713, 4714, 4715, \n\t4716, 4717, 4718, 4719, 4720, 4721, 4722, 4723, \n\t4724, 4725, 4726, 4727, 4728, 4729, 4730, 4731, \n\t4732, 4733, 4734, 4735, 4736, 4737, 4738, 4739, \n\t4740, 4741, 4742, 4743, 4744, 4745, 4746, 4747, \n\t4748, 4749, 4750, 4751, 4752, 4753, 4754, 4755, \n\t4756, 4757, 4758, 4759, 4760, 4761, 4762, 4763, \n\t4764, 4765, 4766, 4767, 4768, 4769, 4770, 4771, \n\t4772, 4773, 4774, 4775, 4776, 4777, 4778, 4779, \n\t4780, 4781, 4782, 4783, 4784, 4785, 4786, 4787, \n\t4788, 4789, 4790, 4791, 4792, 4793, 4794, 4795, \n\t4796, 4797, 4798, 4799, 4800, 4801, 4802, 4803, \n\t4804, 4805, 4806, 4807, 4808, 4809, 4810, 4811, \n\t4812, 4813, 4814, 4815, 4816, 4817, 4818, 4819, \n\t4820, 4821, 4822, 4823, 4824, 4825, 4826, 4827, \n\t4828, 4829, 4830, 4831, 4832, 4833, 4834, 4835, \n\t4836, 4837, 4838, 4839, 4840, 4841, 4842, 4843, \n\t4844, 4845, 4846, 4847, 4848, 4849, 4850, 4851, \n\t4852, 4853, 4854, 4855, 4856, 4857, 4858, 4859, \n\t4860, 4861, 4862, 4863, 4864, 4865, 4866, 4867, \n\t4868, 4869, 4870, 4871, 4872, 4872, 4873, 4874, \n\t4875, 4876, 4877, 4878, 4879, 4880, 4881, 4882, \n\t4883, 4884, 4885, 4886, 4887, 4888, 4889, 4890, \n\t4891, 4892, 4893, 4894, 4895, 4896, 4897, 4898, \n\t4899, 4900, 4901, 4902, 4903, 4904, 4905, 4906, \n\t4907, 4908, 4909, 4910, 4911, 4912, 4913, 4914, \n\t4915, 4916, 4917, 4918, 4919, 4920, 4921, 4922, \n\t4923, 4924, 4925, 4926, 4927, 4928, 4929, 4930, \n\t4931, 4932, 4933, 4934, 4935, 4936, 4937, 4938, \n\t4939, 4940, 4941, 4942, 4943, 4944, 4945, 4946, \n\t4947, 4948, 4949, 4950, 4951, 4952, 4953, 4954, \n\t4955, 4956, 4957, 4958, 4959, 4960, 4961, 4962, \n\t4963, 4964, 4965, 4966, 4967, 4968, 4969, 4970, \n\t4971, 4972, 4973, 4974, 4975, 4976, 4977, 4978, \n\t4979, 4980, 4981, 4982, 4983, 4984, 4985, 4986, \n\t4987, 4988, 4989, 4990, 4991, 4992, 4993, 4994, \n\t4995, 4996, 4997, 4998, 4999, 5000, 5001, 5002, \n\t5003, 5004, 5005, 5006, 5007, 5008, 5009, 5010, \n\t5011, 5012, 5013, 5014, 5015, 5016, 5017, 5018, \n\t5019, 5020, 5021, 5022, 5023, 5024, 5025, 5026, \n\t5027, 5028, 5029, 5030, 5031, 5032, 5033, 5034, \n\t5035, 5036, 5037, 5038, 5039, 5040, 5041, 5042, \n\t5043, 5044, 5045, 5046, 5047, 5048, 5049, 5050, \n\t5051, 5052, 5053, 5054, 5055, 5056, 5057, 5058, \n\t5059, 5060, 5061, 5062, 5063, 5064, 5065, 5066, \n\t5067, 5068, 5069, 5070, 5071, 5072, 5073, 5074, \n\t5075, 5076, 5077, 5078, 5079, 5080, 5081, 5082, \n\t5083, 5084, 5085, 5086, 5087, 5088, 5089, 5090, \n\t5091, 5092, 5093, 5094, 5095, 5096, 5097, 5098, \n\t5099, 5100, 5101, 5102, 5103, 5104, 5105, 5106, \n\t5107, 5108, 5109, 5110, 5111, 5112, 5113, 5114, \n\t5115, 5116, 5117, 5118, 5119, 5120, 5121, 5122, \n\t5123, 5124, 5125, 5126, 5127, 5128, 5129, 5130, \n\t5131, 5132, 5133, 5134, 5135, 5136, 5137, 5138, \n\t5139, 5140, 5141, 5142, 5143, 5144, 5145, 5146, \n\t5147, 5148, 5149, 5150, 5151, 5152, 5153, 5154, \n\t5155, 5156, 5157, 5158, 5159, 5160, 5161, 5162, \n\t5163, 5164, 5165, 5166, 5167, 5168, 5169, 5170, \n\t5171, 5172, 5173, 5174, 5175, 5176, 5177, 5178, \n\t5179, 5180, 5181, 5182, 5183, 5184, 5185, 5186, \n\t5187, 5188, 5189, 5190, 5191, 5192, 5193, 5194, \n\t5195, 5196, 5197, 5198, 5199, 5200, 5201, 5202, \n\t5203, 5204, 5205, 5206, 5207, 5208, 5209, 5209, \n\t5210, 5211, 5212, 5213, 5214, 5215, 5216, 5217, \n\t5218, 5219, 5220, 5221, 5222, 5223, 5224, 5225, \n\t5226, 5227, 5228, 5229, 5230, 5231, 5232, 5233, \n\t5234, 5235, 5236, 5237, 5238, 5239, 5240, 5241, \n\t5242, 5243, 5244, 5245, 5246, 5247, 5248, 5249, \n\t5250, 5251, 5252, 5253, 5254, 5255, 5256, 5257, \n\t5258, 5259, 5260, 5261, 5262, 5263, 5264, 5265, \n\t5266, 5267, 5268, 5269, 5270, 5271, 5272, 5273, \n\t5274, 5275, 5276, 5277, 5278, 5279, 5280, 5281, \n\t5282, 5283, 5284, 5285, 5286, 5287, 5288, 5289, \n\t5290, 5291, 5292, 5293, 5294, 5295, 5296, 5297, \n\t5298, 5299, 5300, 5301, 5302, 5303, 5304, 5305, \n\t5306, 5307, 5308, 5309, 5310, 5311, 5312, 5313, \n\t5314, 5315, 5316, 5317, 5318, 5319, 5320, 5321, \n\t5322, 5323, 5324, 5325, 5326, 5327, 5328, 5329, \n\t5330, 5331, 5332, 5333, 5334, 5335, 5336, 5337, \n\t5338, 5339, 5340, 5341, 5342, 5343, 5344, 5345, \n\t5346, 5347, 5348, 5349, 5350, 5351, 5352, 5353, \n\t5354, 5355, 5356, 5357, 5358, 5359, 5360, 5361, \n\t5362, 5363, 5364, 5365, 5366, 5367, 5368, 5369, \n\t5370, 5371, 5372, 5373, 5374, 5375, 5376, 5377, \n\t5378, 5379, 5380, 5381, 5382, 5383, 5384, 5385, \n\t5386, 5387, 5388, 5389, 5390, 5391, 5392, 5393, \n\t5394, 5395, 5396, 5397, 5398, 5399, 5400, 5401, \n\t5402, 5403, 5404, 5405, 5406, 5407, 5408, 5409, \n\t5410, 5411, 5412, 5413, 5414, 5415, 5416, 5417, \n\t5418, 5419, 5420, 5421, 5422, 5423, 5424, 5425, \n\t5426, 5427, 5428, 5429, 5430, 5431, 5432, 5433, \n\t5434, 5435, 5436, 5437, 5438, 5439, 5440, 5441, \n\t5442, 5443, 5444, 5445, 5446, 5447, 5448, 5449, \n\t5450, 5451, 5452, 5453, 5454, 5455, 5456, 5457, \n\t5458, 5459, 5460, 5461, 5462, 5463, 5464, 5465, \n\t5466, 5467, 5468, 5469, 5470, 5471, 5472, 5473, \n\t5474, 5475, 5476, 5477, 5478, 5479, 5480, 5481, \n\t5482, 5483, 5484, 5485, 5486, 5487, 5488, 5489, \n\t5490, 5491, 5492, 5493, 5494, 5495, 5496, 5497, \n\t5498, 5499, 5500, 5501, 5502, 5503, 5504, 5505, \n\t5506, 5507, 5507, 5508, 5509, 5510, 5511, 5512, \n\t5513, 5514, 5515, 5516, 5517, 5518, 5519, 5520, \n\t5521, 5522, 5523, 5524, 5525, 5526, 5527, 5528, \n\t5529, 5530, 5531, 5532, 5533, 5534, 5535, 5536, \n\t5537, 5538, 5539, 5540, 5541, 5542, 5543, 5544, \n\t5545, 5546, 5547, 5548, 5549, 5550, 5551, 5552, \n\t5553, 5554, 5555, 5556, 5557, 5558, 5559, 5560, \n\t5561, 5562, 5563, 5564, 5565, 5566, 5567, 5568, \n\t5569, 5570, 5571, 5572, 5573, 5574, 5575, 5576, \n\t5577, 5578, 5579, 5580, 5581, 5582, 5583, 5584, \n\t5585, 5586, 5587, 5588, 5589, 5590, 5591, 5592, \n\t5593, 5594, 5595, 5596, 5597, 5598, 5599, 5600, \n\t5601, 5602, 5603, 5604, 5605, 5606, 5607, 5608, \n\t5609, 5610, 5611, 5612, 5613, 5614, 5615, 5616, \n\t5617, 5618, 5619, 5620, 5621, 5622, 5623, 5624, \n\t5625, 5626, 5627, 5628, 5629, 5630, 5631, 5632, \n\t5633, 5634, 5635, 5636, 5637, 5638, 5639, 5640, \n\t5641, 5642, 5643, 5644, 5645, 5646, 5647, 5648, \n\t5649, 5650, 5651, 5652, 5653, 5654, 5655, 5656, \n\t5657, 5658, 5659, 5660, 5661, 5662, 5663, 5664, \n\t5665, 5666, 5667, 5668, 5669, 5670, 5671, 5672, \n\t5673, 5674, 5675, 5676, 5677, 5678, 5679, 5680, \n\t5681, 5682, 5683, 5684, 5685, 5686, 5687, 5688, \n\t5689, 5690, 5691, 5692, 5693, 5694, 5695, 5696, \n\t5697, 5698, 5699, 5700, 5701, 5702, 5703, 5704, \n\t5705, 5706, 5707, 5708, 5709, 5710, 5711, 5712, \n\t5713, 5714, 5715, 5716, 5717, 5718, 5719, 5720, \n\t5721, 5722, 5723, 5724, 5725, 5726, 5727, 5728, \n\t5729, 5730, 5731, 5732, 5733, 5734, 5735, 5736, \n\t5737, 5738, 5739, 5740, 5741, 5742, 5743, 5744, \n\t5745, 5746, 5747, 5748, 5749, 5750, 5751, 5752, \n\t5753, 5754, 5755, 5756, 5757, 5758, 5759, 5760, \n\t5761, 5762, 5763, 5764, 5765, 5766, 5767, 5768, \n\t5769, 5770, 5771, 5772, 5773, 5774, 5775, 5775, \n\t5776, 5777, 5778, 5779, 5780, 5781, 5782, 5783, \n\t5784, 5785, 5786, 5787, 5788, 5789, 5790, 5791, \n\t5792, 5793, 5794, 5795, 5796, 5797, 5798, 5799, \n\t5800, 5801, 5802, 5803, 5804, 5805, 5806, 5807, \n\t5808, 5809, 5810, 5811, 5812, 5813, 5814, 5815, \n\t5816, 5817, 5818, 5819, 5820, 5821, 5822, 5823, \n\t5824, 5825, 5826, 5827, 5828, 5829, 5830, 5831, \n\t5832, 5833, 5834, 5835, 5836, 5837, 5838, 5839, \n\t5840, 5841, 5842, 5843, 5844, 5845, 5846, 5847, \n\t5848, 5849, 5850, 5851, 5852, 5853, 5854, 5855, \n\t5856, 5857, 5858, 5859, 5860, 5861, 5862, 5863, \n\t5864, 5865, 5866, 5867, 5868, 5869, 5870, 5871, \n\t5872, 5873, 5874, 5875, 5876, 5877, 5878, 5879, \n\t5880, 5881, 5882, 5883, 5884, 5885, 5886, 5887, \n\t5888, 5889, 5890, 5891, 5892, 5893, 5894, 5895, \n\t5896, 5897, 5898, 5899, 5900, 5901, 5902, 5903, \n\t5904, 5905, 5906, 5907, 5908, 5909, 5910, 5911, \n\t5912, 5913, 5914, 5915, 5916, 5917, 5918, 5919, \n\t5920, 5921, 5922, 5923, 5924, 5925, 5926, 5927, \n\t5928, 5929, 5930, 5931, 5932, 5933, 5934, 5935, \n\t5936, 5937, 5938, 5939, 5940, 5941, 5942, 5943, \n\t5944, 5945, 5946, 5947, 5948, 5949, 5950, 5951, \n\t5952, 5953, 5954, 5955, 5956, 5957, 5958, 5959, \n\t5960, 5961, 5962, 5963, 5964, 5965, 5966, 5967, \n\t5968, 5969, 5970, 5971, 5972, 5973, 5974, 5975, \n\t5976, 5977, 5978, 5979, 5980, 5981, 5982, 5983, \n\t5984, 5985, 5986, 5987, 5988, 5989, 5990, 5991, \n\t5992, 5993, 5994, 5995, 5996, 5997, 5998, 5999, \n\t6000, 6001, 6002, 6003, 6004, 6005, 6006, 6007, \n\t6008, 6009, 6010, 6011, 6012, 6013, 6014, 6015, \n\t6016, 6017, 6018, 6019, 6020, 6020, 6021, 6022, \n\t6023, 6024, 6025, 6026, 6027, 6028, 6029, 6030, \n\t6031, 6032, 6033, 6034, 6035, 6036, 6037, 6038, \n\t6039, 6040, 6041, 6042, 6043, 6044, 6045, 6046, \n\t6047, 6048, 6049, 6050, 6051, 6052, 6053, 6054, \n\t6055, 6056, 6057, 6058, 6059, 6060, 6061, 6062, \n\t6063, 6064, 6065, 6066, 6067, 6068, 6069, 6070, \n\t6071, 6072, 6073, 6074, 6075, 6076, 6077, 6078, \n\t6079, 6080, 6081, 6082, 6083, 6084, 6085, 6086, \n\t6087, 6088, 6089, 6090, 6091, 6092, 6093, 6094, \n\t6095, 6096, 6097, 6098, 6099, 6100, 6101, 6102, \n\t6103, 6104, 6105, 6106, 6107, 6108, 6109, 6110, \n\t6111, 6112, 6113, 6114, 6115, 6116, 6117, 6118, \n\t6119, 6120, 6121, 6122, 6123, 6124, 6125, 6126, \n\t6127, 6128, 6129, 6130, 6131, 6132, 6133, 6134, \n\t6135, 6136, 6137, 6138, 6139, 6140, 6141, 6142, \n\t6143, 6144, 6145, 6146, 6147, 6148, 6149, 6150, \n\t6151, 6152, 6153, 6154, 6155, 6156, 6157, 6158, \n\t6159, 6160, 6161, 6162, 6163, 6164, 6165, 6166, \n\t6167, 6168, 6169, 6170, 6171, 6172, 6173, 6174, \n\t6175, 6176, 6177, 6178, 6179, 6180, 6181, 6182, \n\t6183, 6184, 6185, 6186, 6187, 6188, 6189, 6190, \n\t6191, 6192, 6193, 6194, 6195, 6196, 6197, 6198, \n\t6199, 6200, 6201, 6202, 6203, 6204, 6205, 6206, \n\t6207, 6208, 6209, 6210, 6211, 6212, 6213, 6214, \n\t6215, 6216, 6217, 6218, 6219, 6220, 6221, 6222, \n\t6223, 6224, 6225, 6226, 6227, 6228, 6229, 6230, \n\t6231, 6232, 6233, 6234, 6235, 6236, 6237, 6238, \n\t6239, 6240, 6241, 6242, 6243, 6244, 6245, 6246, \n\t6247, 6247, 6248, 6249, 6250, 6251, 6252, 6253, \n\t6254, 6255, 6256, 6257, 6258, 6259, 6260, 6261, \n\t6262, 6263, 6264, 6265, 6266, 6267, 6268, 6269, \n\t6270, 6271, 6272, 6273, 6274, 6275, 6276, 6277, \n\t6278, 6279, 6280, 6281, 6282, 6283, 6284, 6285, \n\t6286, 6287, 6288, 6289, 6290, 6291, 6292, 6293, \n\t6294, 6295, 6296, 6297, 6298, 6299, 6300, 6301, \n\t6302, 6303, 6304, 6305, 6306, 6307, 6308, 6309, \n\t6310, 6311, 6312, 6313, 6314, 6315, 6316, 6317, \n\t6318, 6319, 6320, 6321, 6322, 6323, 6324, 6325, \n\t6326, 6327, 6328, 6329, 6330, 6331, 6332, 6333, \n\t6334, 6335, 6336, 6337, 6338, 6339, 6340, 6341, \n\t6342, 6343, 6344, 6345, 6346, 6347, 6348, 6349, \n\t6350, 6351, 6352, 6353, 6354, 6355, 6356, 6357, \n\t6358, 6359, 6360, 6361, 6362, 6363, 6364, 6365, \n\t6366, 6367, 6368, 6369, 6370, 6371, 6372, 6373, \n\t6374, 6375, 6376, 6377, 6378, 6379, 6380, 6381, \n\t6382, 6383, 6384, 6385, 6386, 6387, 6388, 6389, \n\t6390, 6391, 6392, 6393, 6394, 6395, 6396, 6397, \n\t6398, 6399, 6400, 6401, 6402, 6403, 6404, 6405, \n\t6406, 6407, 6408, 6409, 6410, 6411, 6412, 6413, \n\t6414, 6415, 6416, 6417, 6418, 6419, 6420, 6421, \n\t6422, 6423, 6424, 6425, 6426, 6427, 6428, 6429, \n\t6430, 6431, 6432, 6433, 6434, 6435, 6436, 6437, \n\t6438, 6439, 6440, 6441, 6442, 6443, 6444, 6445, \n\t6446, 6447, 6448, 6449, 6450, 6451, 6452, 6453, \n\t6454, 6455, 6456, 6457, 6458, 6459, 6459, 6460, \n\t6461, 6462, 6463, 6464, 6465, 6466, 6467, 6468, \n\t6469, 6470, 6471, 6472, 6473, 6474, 6475, 6476, \n\t6477, 6478, 6479, 6480, 6481, 6482, 6483, 6484, \n\t6485, 6486, 6487, 6488, 6489, 6490, 6491, 6492, \n\t6493, 6494, 6495, 6496, 6497, 6498, 6499, 6500, \n\t6501, 6502, 6503, 6504, 6505, 6506, 6507, 6508, \n\t6509, 6510, 6511, 6512, 6513, 6514, 6515, 6516, \n\t6517, 6518, 6519, 6520, 6521, 6522, 6523, 6524, \n\t6525, 6526, 6527, 6528, 6529, 6530, 6531, 6532, \n\t6533, 6534, 6535, 6536, 6537, 6538, 6539, 6540, \n\t6541, 6542, 6543, 6544, 6545, 6546, 6547, 6548, \n\t6549, 6550, 6551, 6552, 6553, 6554, 6555, 6556, \n\t6557, 6558, 6559, 6560, 6561, 6562, 6563, 6564, \n\t6565, 6566, 6567, 6568, 6569, 6570, 6571, 6572, \n\t6573, 6574, 6575, 6576, 6577, 6578, 6579, 6580, \n\t6581, 6582, 6583, 6584, 6585, 6586, 6587, 6588, \n\t6589, 6590, 6591, 6592, 6593, 6594, 6595, 6596, \n\t6597, 6598, 6599, 6600, 6601, 6602, 6603, 6604, \n\t6605, 6606, 6607, 6608, 6609, 6610, 6611, 6612, \n\t6613, 6614, 6615, 6616, 6617, 6618, 6619, 6620, \n\t6621, 6622, 6623, 6624, 6625, 6626, 6627, 6628, \n\t6629, 6630, 6631, 6632, 6633, 6634, 6635, 6636, \n\t6637, 6638, 6639, 6640, 6641, 6642, 6643, 6644, \n\t6645, 6646, 6647, 6648, 6649, 6650, 6651, 6652, \n\t6653, 6654, 6655, 6656, 6657, 6657, 6658, 6659, \n\t6660, 6661, 6662, 6663, 6664, 6665, 6666, 6667, \n\t6668, 6669, 6670, 6671, 6672, 6673, 6674, 6675, \n\t6676, 6677, 6678, 6679, 6680, 6681, 6682, 6683, \n\t6684, 6685, 6686, 6687, 6688, 6689, 6690, 6691, \n\t6692, 6693, 6694, 6695, 6696, 6697, 6698, 6699, \n\t6700, 6701, 6702, 6703, 6704, 6705, 6706, 6707, \n\t6708, 6709, 6710, 6711, 6712, 6713, 6714, 6715, \n\t6716, 6717, 6718, 6719, 6720, 6721, 6722, 6723, \n\t6724, 6725, 6726, 6727, 6728, 6729, 6730, 6731, \n\t6732, 6733, 6734, 6735, 6736, 6737, 6738, 6739, \n\t6740, 6741, 6742, 6743, 6744, 6745, 6746, 6747, \n\t6748, 6749, 6750, 6751, 6752, 6753, 6754, 6755, \n\t6756, 6757, 6758, 6759, 6760, 6761, 6762, 6763, \n\t6764, 6765, 6766, 6767, 6768, 6769, 6770, 6771, \n\t6772, 6773, 6774, 6775, 6776, 6777, 6778, 6779, \n\t6780, 6781, 6782, 6783, 6784, 6785, 6786, 6787, \n\t6788, 6789, 6790, 6791, 6792, 6793, 6794, 6795, \n\t6796, 6797, 6798, 6799, 6800, 6801, 6802, 6803, \n\t6804, 6805, 6806, 6807, 6808, 6809, 6810, 6811, \n\t6812, 6813, 6814, 6815, 6816, 6817, 6818, 6819, \n\t6820, 6821, 6822, 6823, 6824, 6825, 6826, 6827, \n\t6828, 6829, 6830, 6831, 6832, 6833, 6834, 6835, \n\t6836, 6837, 6838, 6839, 6840, 6841, 6842, 6843, \n\t6844, 6844, 6845, 6846, 6847, 6848, 6849, 6850, \n\t6851, 6852, 6853, 6854, 6855, 6856, 6857, 6858, \n\t6859, 6860, 6861, 6862, 6863, 6864, 6865, 6866, \n\t6867, 6868, 6869, 6870, 6871, 6872, 6873, 6874, \n\t6875, 6876, 6877, 6878, 6879, 6880, 6881, 6882, \n\t6883, 6884, 6885, 6886, 6887, 6888, 6889, 6890, \n\t6891, 6892, 6893, 6894, 6895, 6896, 6897, 6898, \n\t6899, 6900, 6901, 6902, 6903, 6904, 6905, 6906, \n\t6907, 6908, 6909, 6910, 6911, 6912, 6913, 6914, \n\t6915, 6916, 6917, 6918, 6919, 6920, 6921, 6922, \n\t6923, 6924, 6925, 6926, 6927, 6928, 6929, 6930, \n\t6931, 6932, 6933, 6934, 6935, 6936, 6937, 6938, \n\t6939, 6940, 6941, 6942, 6943, 6944, 6945, 6946, \n\t6947, 6948, 6949, 6950, 6951, 6952, 6953, 6954, \n\t6955, 6956, 6957, 6958, 6959, 6960, 6961, 6962, \n\t6963, 6964, 6965, 6966, 6967, 6968, 6969, 6970, \n\t6971, 6972, 6973, 6974, 6975, 6976, 6977, 6978, \n\t6979, 6980, 6981, 6982, 6983, 6984, 6985, 6986, \n\t6987, 6988, 6989, 6990, 6991, 6992, 6993, 6994, \n\t6995, 6996, 6997, 6998, 6999, 7000, 7001, 7002, \n\t7003, 7004, 7005, 7006, 7007, 7008, 7009, 7010, \n\t7011, 7012, 7013, 7014, 7015, 7016, 7017, 7018, \n\t7019, 7020, 7021, 7021, 7022, 7023, 7024, 7025, \n\t7026, 7027, 7028, 7029, 7030, 7031, 7032, 7033, \n\t7034, 7035, 7036, 7037, 7038, 7039, 7040, 7041, \n\t7042, 7043, 7044, 7045, 7046, 7047, 7048, 7049, \n\t7050, 7051, 7052, 7053, 7054, 7055, 7056, 7057, \n\t7058, 7059, 7060, 7061, 7062, 7063, 7064, 7065, \n\t7066, 7067, 7068, 7069, 7070, 7071, 7072, 7073, \n\t7074, 7075, 7076, 7077, 7078, 7079, 7080, 7081, \n\t7082, 7083, 7084, 7085, 7086, 7087, 7088, 7089, \n\t7090, 7091, 7092, 7093, 7094, 7095, 7096, 7097, \n\t7098, 7099, 7100, 7101, 7102, 7103, 7104, 7105, \n\t7106, 7107, 7108, 7109, 7110, 7111, 7112, 7113, \n\t7114, 7115, 7116, 7117, 7118, 7119, 7120, 7121, \n\t7122, 7123, 7124, 7125, 7126, 7127, 7128, 7129, \n\t7130, 7131, 7132, 7133, 7134, 7135, 7136, 7137, \n\t7138, 7139, 7140, 7141, 7142, 7143, 7144, 7145, \n\t7146, 7147, 7148, 7149, 7150, 7151, 7152, 7153, \n\t7154, 7155, 7156, 7157, 7158, 7159, 7160, 7161, \n\t7162, 7163, 7164, 7165, 7166, 7167, 7168, 7169, \n\t7170, 7171, 7172, 7173, 7174, 7175, 7176, 7177, \n\t7178, 7179, 7180, 7181, 7182, 7183, 7184, 7185, \n\t7186, 7187, 7188, 7189, 7190, 7190, 7191, 7192, \n\t7193, 7194, 7195, 7196, 7197, 7198, 7199, 7200, \n\t7201, 7202, 7203, 7204, 7205, 7206, 7207, 7208, \n\t7209, 7210, 7211, 7212, 7213, 7214, 7215, 7216, \n\t7217, 7218, 7219, 7220, 7221, 7222, 7223, 7224, \n\t7225, 7226, 7227, 7228, 7229, 7230, 7231, 7232, \n\t7233, 7234, 7235, 7236, 7237, 7238, 7239, 7240, \n\t7241, 7242, 7243, 7244, 7245, 7246, 7247, 7248, \n\t7249, 7250, 7251, 7252, 7253, 7254, 7255, 7256, \n\t7257, 7258, 7259, 7260, 7261, 7262, 7263, 7264, \n\t7265, 7266, 7267, 7268, 7269, 7270, 7271, 7272, \n\t7273, 7274, 7275, 7276, 7277, 7278, 7279, 7280, \n\t7281, 7282, 7283, 7284, 7285, 7286, 7287, 7288, \n\t7289, 7290, 7291, 7292, 7293, 7294, 7295, 7296, \n\t7297, 7298, 7299, 7300, 7301, 7302, 7303, 7304, \n\t7305, 7306, 7307, 7308, 7309, 7310, 7311, 7312, \n\t7313, 7314, 7315, 7316, 7317, 7318, 7319, 7320, \n\t7321, 7322, 7323, 7324, 7325, 7326, 7327, 7328, \n\t7329, 7330, 7331, 7332, 7333, 7334, 7335, 7336, \n\t7337, 7338, 7339, 7340, 7341, 7342, 7343, 7344, \n\t7345, 7346, 7347, 7348, 7349, 7350, 7351, 7351, \n\t7352, 7353, 7354, 7355, 7356, 7357, 7358, 7359, \n\t7360, 7361, 7362, 7363, 7364, 7365, 7366, 7367, \n\t7368, 7369, 7370, 7371, 7372, 7373, 7374, 7375, \n\t7376, 7377, 7378, 7379, 7380, 7381, 7382, 7383, \n\t7384, 7385, 7386, 7387, 7388, 7389, 7390, 7391, \n\t7392, 7393, 7394, 7395, 7396, 7397, 7398, 7399, \n\t7400, 7401, 7402, 7403, 7404, 7405, 7406, 7407, \n\t7408, 7409, 7410, 7411, 7412, 7413, 7414, 7415, \n\t7416, 7417, 7418, 7419, 7420, 7421, 7422, 7423, \n\t7424, 7425, 7426, 7427, 7428, 7429, 7430, 7431, \n\t7432, 7433, 7434, 7435, 7436, 7437, 7438, 7439, \n\t7440, 7441, 7442, 7443, 7444, 7445, 7446, 7447, \n\t7448, 7449, 7450, 7451, 7452, 7453, 7454, 7455, \n\t7456, 7457, 7458, 7459, 7460, 7461, 7462, 7463, \n\t7464, 7465, 7466, 7467, 7468, 7469, 7470, 7471, \n\t7472, 7473, 7474, 7475, 7476, 7477, 7478, 7479, \n\t7480, 7481, 7482, 7483, 7484, 7485, 7486, 7487, \n\t7488, 7489, 7490, 7491, 7492, 7493, 7494, 7495, \n\t7496, 7497, 7498, 7499, 7500, 7501, 7502, 7503, \n\t7504, 7505, 7505, 7506, 7507, 7508, 7509, 7510, \n\t7511, 7512, 7513, 7514, 7515, 7516, 7517, 7518, \n\t7519, 7520, 7521, 7522, 7523, 7524, 7525, 7526, \n\t7527, 7528, 7529, 7530, 7531, 7532, 7533, 7534, \n\t7535, 7536, 7537, 7538, 7539, 7540, 7541, 7542, \n\t7543, 7544, 7545, 7546, 7547, 7548, 7549, 7550, \n\t7551, 7552, 7553, 7554, 7555, 7556, 7557, 7558, \n\t7559, 7560, 7561, 7562, 7563, 7564, 7565, 7566, \n\t7567, 7568, 7569, 7570, 7571, 7572, 7573, 7574, \n\t7575, 7576, 7577, 7578, 7579, 7580, 7581, 7582, \n\t7583, 7584, 7585, 7586, 7587, 7588, 7589, 7590, \n\t7591, 7592, 7593, 7594, 7595, 7596, 7597, 7598, \n\t7599, 7600, 7601, 7602, 7603, 7604, 7605, 7606, \n\t7607, 7608, 7609, 7610, 7611, 7612, 7613, 7614, \n\t7615, 7616, 7617, 7618, 7619, 7620, 7621, 7622, \n\t7623, 7624, 7625, 7626, 7627, 7628, 7629, 7630, \n\t7631, 7632, 7633, 7634, 7635, 7636, 7637, 7638, \n\t7639, 7640, 7641, 7642, 7643, 7644, 7645, 7646, \n\t7647, 7648, 7649, 7650, 7651, 7652, 7653, 7653, \n\t7654, 7655, 7656, 7657, 7658, 7659, 7660, 7661, \n\t7662, 7663, 7664, 7665, 7666, 7667, 7668, 7669, \n\t7670, 7671, 7672, 7673, 7674, 7675, 7676, 7677, \n\t7678, 7679, 7680, 7681, 7682, 7683, 7684, 7685, \n\t7686, 7687, 7688, 7689, 7690, 7691, 7692, 7693, \n\t7694, 7695, 7696, 7697, 7698, 7699, 7700, 7701, \n\t7702, 7703, 7704, 7705, 7706, 7707, 7708, 7709, \n\t7710, 7711, 7712, 7713, 7714, 7715, 7716, 7717, \n\t7718, 7719, 7720, 7721, 7722, 7723, 7724, 7725, \n\t7726, 7727, 7728, 7729, 7730, 7731, 7732, 7733, \n\t7734, 7735, 7736, 7737, 7738, 7739, 7740, 7741, \n\t7742, 7743, 7744, 7745, 7746, 7747, 7748, 7749, \n\t7750, 7751, 7752, 7753, 7754, 7755, 7756, 7757, \n\t7758, 7759, 7760, 7761, 7762, 7763, 7764, 7765, \n\t7766, 7767, 7768, 7769, 7770, 7771, 7772, 7773, \n\t7774, 7775, 7776, 7777, 7778, 7779, 7780, 7781, \n\t7782, 7783, 7784, 7785, 7786, 7787, 7788, 7789, \n\t7790, 7791, 7792, 7793, 7794, 7795, 7795, 7796, \n\t7797, 7798, 7799, 7800, 7801, 7802, 7803, 7804, \n\t7805, 7806, 7807, 7808, 7809, 7810, 7811, 7812, \n\t7813, 7814, 7815, 7816, 7817, 7818, 7819, 7820, \n\t7821, 7822, 7823, 7824, 7825, 7826, 7827, 7828, \n\t7829, 7830, 7831, 7832, 7833, 7834, 7835, 7836, \n\t7837, 7838, 7839, 7840, 7841, 7842, 7843, 7844, \n\t7845, 7846, 7847, 7848, 7849, 7850, 7851, 7852, \n\t7853, 7854, 7855, 7856, 7857, 7858, 7859, 7860, \n\t7861, 7862, 7863, 7864, 7865, 7866, 7867, 7868, \n\t7869, 7870, 7871, 7872, 7873, 7874, 7875, 7876, \n\t7877, 7878, 7879, 7880, 7881, 7882, 7883, 7884, \n\t7885, 7886, 7887, 7888, 7889, 7890, 7891, 7892, \n\t7893, 7894, 7895, 7896, 7897, 7898, 7899, 7900, \n\t7901, 7902, 7903, 7904, 7905, 7906, 7907, 7908, \n\t7909, 7910, 7911, 7912, 7913, 7914, 7915, 7916, \n\t7917, 7918, 7919, 7920, 7921, 7922, 7923, 7924, \n\t7925, 7926, 7927, 7928, 7929, 7930, 7931, 7932, \n\t7933, 7933, 7934, 7935, 7936, 7937, 7938, 7939, \n\t7940, 7941, 7942, 7943, 7944, 7945, 7946, 7947, \n\t7948, 7949, 7950, 7951, 7952, 7953, 7954, 7955, \n\t7956, 7957, 7958, 7959, 7960, 7961, 7962, 7963, \n\t7964, 7965, 7966, 7967, 7968, 7969, 7970, 7971, \n\t7972, 7973, 7974, 7975, 7976, 7977, 7978, 7979, \n\t7980, 7981, 7982, 7983, 7984, 7985, 7986, 7987, \n\t7988, 7989, 7990, 7991, 7992, 7993, 7994, 7995, \n\t7996, 7997, 7998, 7999, 8000, 8001, 8002, 8003, \n\t8004, 8005, 8006, 8007, 8008, 8009, 8010, 8011, \n\t8012, 8013, 8014, 8015, 8016, 8017, 8018, 8019, \n\t8020, 8021, 8022, 8023, 8024, 8025, 8026, 8027, \n\t8028, 8029, 8030, 8031, 8032, 8033, 8034, 8035, \n\t8036, 8037, 8038, 8039, 8040, 8041, 8042, 8043, \n\t8044, 8045, 8046, 8047, 8048, 8049, 8050, 8051, \n\t8052, 8053, 8054, 8055, 8056, 8057, 8058, 8059, \n\t8060, 8061, 8062, 8063, 8064, 8065, 8065, 8066, \n\t8067, 8068, 8069, 8070, 8071, 8072, 8073, 8074, \n\t8075, 8076, 8077, 8078, 8079, 8080, 8081, 8082, \n\t8083, 8084, 8085, 8086, 8087, 8088, 8089, 8090, \n\t8091, 8092, 8093, 8094, 8095, 8096, 8097, 8098, \n\t8099, 8100, 8101, 8102, 8103, 8104, 8105, 8106, \n\t8107, 8108, 8109, 8110, 8111, 8112, 8113, 8114, \n\t8115, 8116, 8117, 8118, 8119, 8120, 8121, 8122, \n\t8123, 8124, 8125, 8126, 8127, 8128, 8129, 8130, \n\t8131, 8132, 8133, 8134, 8135, 8136, 8137, 8138, \n\t8139, 8140, 8141, 8142, 8143, 8144, 8145, 8146, \n\t8147, 8148, 8149, 8150, 8151, 8152, 8153, 8154, \n\t8155, 8156, 8157, 8158, 8159, 8160, 8161, 8162, \n\t8163, 8164, 8165, 8166, 8167, 8168, 8169, 8170, \n\t8171, 8172, 8173, 8174, 8175, 8176, 8177, 8178, \n\t8179, 8180, 8181, 8182, 8183, 8184, 8185, 8186, \n\t8187, 8188, 8189, 8190, 8191, 8192, 8193, 8194, \n\t8194, 8195, 8196, 8197, 8198, 8199, 8200, 8201, \n\t8202, 8203, 8204, 8205, 8206, 8207, 8208, 8209, \n\t8210, 8211, 8212, 8213, 8214, 8215, 8216, 8217, \n\t8218, 8219, 8220, 8221, 8222, 8223, 8224, 8225, \n\t8226, 8227, 8228, 8229, 8230, 8231, 8232, 8233, \n\t8234, 8235, 8236, 8237, 8238, 8239, 8240, 8241, \n\t8242, 8243, 8244, 8245, 8246, 8247, 8248, 8249, \n\t8250, 8251, 8252, 8253, 8254, 8255, 8256, 8257, \n\t8258, 8259, 8260, 8261, 8262, 8263, 8264, 8265, \n\t8266, 8267, 8268, 8269, 8270, 8271, 8272, 8273, \n\t8274, 8275, 8276, 8277, 8278, 8279, 8280, 8281, \n\t8282, 8283, 8284, 8285, 8286, 8287, 8288, 8289, \n\t8290, 8291, 8292, 8293, 8294, 8295, 8296, 8297, \n\t8298, 8299, 8300, 8301, 8302, 8303, 8304, 8305, \n\t8306, 8307, 8308, 8309, 8310, 8311, 8312, 8313, \n\t8314, 8315, 8316, 8317, 8318, 8318, 8319, 8320, \n\t8321, 8322, 8323, 8324, 8325, 8326, 8327, 8328, \n\t8329, 8330, 8331, 8332, 8333, 8334, 8335, 8336, \n\t8337, 8338, 8339, 8340, 8341, 8342, 8343, 8344, \n\t8345, 8346, 8347, 8348, 8349, 8350, 8351, 8352, \n\t8353, 8354, 8355, 8356, 8357, 8358, 8359, 8360, \n\t8361, 8362, 8363, 8364, 8365, 8366, 8367, 8368, \n\t8369, 8370, 8371, 8372, 8373, 8374, 8375, 8376, \n\t8377, 8378, 8379, 8380, 8381, 8382, 8383, 8384, \n\t8385, 8386, 8387, 8388, 8389, 8390, 8391, 8392, \n\t8393, 8394, 8395, 8396, 8397, 8398, 8399, 8400, \n\t8401, 8402, 8403, 8404, 8405, 8406, 8407, 8408, \n\t8409, 8410, 8411, 8412, 8413, 8414, 8415, 8416, \n\t8417, 8418, 8419, 8420, 8421, 8422, 8423, 8424, \n\t8425, 8426, 8427, 8428, 8429, 8430, 8431, 8432, \n\t8433, 8434, 8435, 8436, 8437, 8438, 8439, 8439, \n\t8440, 8441, 8442, 8443, 8444, 8445, 8446, 8447, \n\t8448, 8449, 8450, 8451, 8452, 8453, 8454, 8455, \n\t8456, 8457, 8458, 8459, 8460, 8461, 8462, 8463, \n\t8464, 8465, 8466, 8467, 8468, 8469, 8470, 8471, \n\t8472, 8473, 8474, 8475, 8476, 8477, 8478, 8479, \n\t8480, 8481, 8482, 8483, 8484, 8485, 8486, 8487, \n\t8488, 8489, 8490, 8491, 8492, 8493, 8494, 8495, \n\t8496, 8497, 8498, 8499, 8500, 8501, 8502, 8503, \n\t8504, 8505, 8506, 8507, 8508, 8509, 8510, 8511, \n\t8512, 8513, 8514, 8515, 8516, 8517, 8518, 8519, \n\t8520, 8521, 8522, 8523, 8524, 8525, 8526, 8527, \n\t8528, 8529, 8530, 8531, 8532, 8533, 8534, 8535, \n\t8536, 8537, 8538, 8539, 8540, 8541, 8542, 8543, \n\t8544, 8545, 8546, 8547, 8548, 8549, 8550, 8551, \n\t8552, 8553, 8554, 8555, 8556, 8557, 8557, 8558, \n\t8559, 8560, 8561, 8562, 8563, 8564, 8565, 8566, \n\t8567, 8568, 8569, 8570, 8571, 8572, 8573, 8574, \n\t8575, 8576, 8577, 8578, 8579, 8580, 8581, 8582, \n\t8583, 8584, 8585, 8586, 8587, 8588, 8589, 8590, \n\t8591, 8592, 8593, 8594, 8595, 8596, 8597, 8598, \n\t8599, 8600, 8601, 8602, 8603, 8604, 8605, 8606, \n\t8607, 8608, 8609, 8610, 8611, 8612, 8613, 8614, \n\t8615, 8616, 8617, 8618, 8619, 8620, 8621, 8622, \n\t8623, 8624, 8625, 8626, 8627, 8628, 8629, 8630, \n\t8631, 8632, 8633, 8634, 8635, 8636, 8637, 8638, \n\t8639, 8640, 8641, 8642, 8643, 8644, 8645, 8646, \n\t8647, 8648, 8649, 8650, 8651, 8652, 8653, 8654, \n\t8655, 8656, 8657, 8658, 8659, 8660, 8661, 8662, \n\t8663, 8664, 8665, 8666, 8667, 8668, 8669, 8670, \n\t8671, 8671, 8672, 8673, 8674, 8675, 8676, 8677, \n\t8678, 8679, 8680, 8681, 8682, 8683, 8684, 8685, \n\t8686, 8687, 8688, 8689, 8690, 8691, 8692, 8693, \n\t8694, 8695, 8696, 8697, 8698, 8699, 8700, 8701, \n\t8702, 8703, 8704, 8705, 8706, 8707, 8708, 8709, \n\t8710, 8711, 8712, 8713, 8714, 8715, 8716, 8717, \n\t8718, 8719, 8720, 8721, 8722, 8723, 8724, 8725, \n\t8726, 8727, 8728, 8729, 8730, 8731, 8732, 8733, \n\t8734, 8735, 8736, 8737, 8738, 8739, 8740, 8741, \n\t8742, 8743, 8744, 8745, 8746, 8747, 8748, 8749, \n\t8750, 8751, 8752, 8753, 8754, 8755, 8756, 8757, \n\t8758, 8759, 8760, 8761, 8762, 8763, 8764, 8765, \n\t8766, 8767, 8768, 8769, 8770, 8771, 8772, 8773, \n\t8774, 8775, 8776, 8777, 8778, 8779, 8780, 8781, \n\t8782, 8782, 8783, 8784, 8785, 8786, 8787, 8788, \n\t8789, 8790, 8791, 8792, 8793, 8794, 8795, 8796, \n\t8797, 8798, 8799, 8800, 8801, 8802, 8803, 8804, \n\t8805, 8806, 8807, 8808, 8809, 8810, 8811, 8812, \n\t8813, 8814, 8815, 8816, 8817, 8818, 8819, 8820, \n\t8821, 8822, 8823, 8824, 8825, 8826, 8827, 8828, \n\t8829, 8830, 8831, 8832, 8833, 8834, 8835, 8836, \n\t8837, 8838, 8839, 8840, 8841, 8842, 8843, 8844, \n\t8845, 8846, 8847, 8848, 8849, 8850, 8851, 8852, \n\t8853, 8854, 8855, 8856, 8857, 8858, 8859, 8860, \n\t8861, 8862, 8863, 8864, 8865, 8866, 8867, 8868, \n\t8869, 8870, 8871, 8872, 8873, 8874, 8875, 8876, \n\t8877, 8878, 8879, 8880, 8881, 8882, 8883, 8884, \n\t8885, 8886, 8887, 8888, 8889, 8890, 8891, 8891, \n\t8892, 8893, 8894, 8895, 8896, 8897, 8898, 8899, \n\t8900, 8901, 8902, 8903, 8904, 8905, 8906, 8907, \n\t8908, 8909, 8910, 8911, 8912, 8913, 8914, 8915, \n\t8916, 8917, 8918, 8919, 8920, 8921, 8922, 8923, \n\t8924, 8925, 8926, 8927, 8928, 8929, 8930, 8931, \n\t8932, 8933, 8934, 8935, 8936, 8937, 8938, 8939, \n\t8940, 8941, 8942, 8943, 8944, 8945, 8946, 8947, \n\t8948, 8949, 8950, 8951, 8952, 8953, 8954, 8955, \n\t8956, 8957, 8958, 8959, 8960, 8961, 8962, 8963, \n\t8964, 8965, 8966, 8967, 8968, 8969, 8970, 8971, \n\t8972, 8973, 8974, 8975, 8976, 8977, 8978, 8979, \n\t8980, 8981, 8982, 8983, 8984, 8985, 8986, 8987, \n\t8988, 8989, 8990, 8991, 8992, 8993, 8994, 8995, \n\t8996, 8997, 8997, 8998, 8999, 9000, 9001, 9002, \n\t9003, 9004, 9005, 9006, 9007, 9008, 9009, 9010, \n\t9011, 9012, 9013, 9014, 9015, 9016, 9017, 9018, \n\t9019, 9020, 9021, 9022, 9023, 9024, 9025, 9026, \n\t9027, 9028, 9029, 9030, 9031, 9032, 9033, 9034, \n\t9035, 9036, 9037, 9038, 9039, 9040, 9041, 9042, \n\t9043, 9044, 9045, 9046, 9047, 9048, 9049, 9050, \n\t9051, 9052, 9053, 9054, 9055, 9056, 9057, 9058, \n\t9059, 9060, 9061, 9062, 9063, 9064, 9065, 9066, \n\t9067, 9068, 9069, 9070, 9071, 9072, 9073, 9074, \n\t9075, 9076, 9077, 9078, 9079, 9080, 9081, 9082, \n\t9083, 9084, 9085, 9086, 9087, 9088, 9089, 9090, \n\t9091, 9092, 9093, 9094, 9095, 9096, 9097, 9098, \n\t9099, 9100, 9100, 9101, 9102, 9103, 9104, 9105, \n\t9106, 9107, 9108, 9109, 9110, 9111, 9112, 9113, \n\t9114, 9115, 9116, 9117, 9118, 9119, 9120, 9121, \n\t9122, 9123, 9124, 9125, 9126, 9127, 9128, 9129, \n\t9130, 9131, 9132, 9133, 9134, 9135, 9136, 9137, \n\t9138, 9139, 9140, 9141, 9142, 9143, 9144, 9145, \n\t9146, 9147, 9148, 9149, 9150, 9151, 9152, 9153, \n\t9154, 9155, 9156, 9157, 9158, 9159, 9160, 9161, \n\t9162, 9163, 9164, 9165, 9166, 9167, 9168, 9169, \n\t9170, 9171, 9172, 9173, 9174, 9175, 9176, 9177, \n\t9178, 9179, 9180, 9181, 9182, 9183, 9184, 9185, \n\t9186, 9187, 9188, 9189, 9190, 9191, 9192, 9193, \n\t9194, 9195, 9196, 9197, 9198, 9199, 9200, 9201, \n\t9201, 9202, 9203, 9204, 9205, 9206, 9207, 9208, \n\t9209, 9210, 9211, 9212, 9213, 9214, 9215, 9216, \n\t9217, 9218, 9219, 9220, 9221, 9222, 9223, 9224, \n\t9225, 9226, 9227, 9228, 9229, 9230, 9231, 9232, \n\t9233, 9234, 9235, 9236, 9237, 9238, 9239, 9240, \n\t9241, 9242, 9243, 9244, 9245, 9246, 9247, 9248, \n\t9249, 9250, 9251, 9252, 9253, 9254, 9255, 9256, \n\t9257, 9258, 9259, 9260, 9261, 9262, 9263, 9264, \n\t9265, 9266, 9267, 9268, 9269, 9270, 9271, 9272, \n\t9273, 9274, 9275, 9276, 9277, 9278, 9279, 9280, \n\t9281, 9282, 9283, 9284, 9285, 9286, 9287, 9288, \n\t9289, 9290, 9291, 9292, 9293, 9294, 9295, 9296, \n\t9297, 9298, 9299, 9300, 9300, 9301, 9302, 9303, \n\t9304, 9305, 9306, 9307, 9308, 9309, 9310, 9311, \n\t9312, 9313, 9314, 9315, 9316, 9317, 9318, 9319, \n\t9320, 9321, 9322, 9323, 9324, 9325, 9326, 9327, \n\t9328, 9329, 9330, 9331, 9332, 9333, 9334, 9335, \n\t9336, 9337, 9338, 9339, 9340, 9341, 9342, 9343, \n\t9344, 9345, 9346, 9347, 9348, 9349, 9350, 9351, \n\t9352, 9353, 9354, 9355, 9356, 9357, 9358, 9359, \n\t9360, 9361, 9362, 9363, 9364, 9365, 9366, 9367, \n\t9368, 9369, 9370, 9371, 9372, 9373, 9374, 9375, \n\t9376, 9377, 9378, 9379, 9380, 9381, 9382, 9383, \n\t9384, 9385, 9386, 9387, 9388, 9389, 9390, 9391, \n\t9392, 9393, 9394, 9395, 9396, 9397, 9397, 9398, \n\t9399, 9400, 9401, 9402, 9403, 9404, 9405, 9406, \n\t9407, 9408, 9409, 9410, 9411, 9412, 9413, 9414, \n\t9415, 9416, 9417, 9418, 9419, 9420, 9421, 9422, \n\t9423, 9424, 9425, 9426, 9427, 9428, 9429, 9430, \n\t9431, 9432, 9433, 9434, 9435, 9436, 9437, 9438, \n\t9439, 9440, 9441, 9442, 9443, 9444, 9445, 9446, \n\t9447, 9448, 9449, 9450, 9451, 9452, 9453, 9454, \n\t9455, 9456, 9457, 9458, 9459, 9460, 9461, 9462, \n\t9463, 9464, 9465, 9466, 9467, 9468, 9469, 9470, \n\t9471, 9472, 9473, 9474, 9475, 9476, 9477, 9478, \n\t9479, 9480, 9481, 9482, 9483, 9484, 9485, 9486, \n\t9487, 9488, 9489, 9490, 9491, 9492, 9492, 9493, \n\t9494, 9495, 9496, 9497, 9498, 9499, 9500, 9501, \n\t9502, 9503, 9504, 9505, 9506, 9507, 9508, 9509, \n\t9510, 9511, 9512, 9513, 9514, 9515, 9516, 9517, \n\t9518, 9519, 9520, 9521, 9522, 9523, 9524, 9525, \n\t9526, 9527, 9528, 9529, 9530, 9531, 9532, 9533, \n\t9534, 9535, 9536, 9537, 9538, 9539, 9540, 9541, \n\t9542, 9543, 9544, 9545, 9546, 9547, 9548, 9549, \n\t9550, 9551, 9552, 9553, 9554, 9555, 9556, 9557, \n\t9558, 9559, 9560, 9561, 9562, 9563, 9564, 9565, \n\t9566, 9567, 9568, 9569, 9570, 9571, 9572, 9573, \n\t9574, 9575, 9576, 9577, 9578, 9579, 9580, 9581, \n\t9582, 9583, 9584, 9585, 9585, 9586, 9587, 9588, \n\t9589, 9590, 9591, 9592, 9593, 9594, 9595, 9596, \n\t9597, 9598, 9599, 9600, 9601, 9602, 9603, 9604, \n\t9605, 9606, 9607, 9608, 9609, 9610, 9611, 9612, \n\t9613, 9614, 9615, 9616, 9617, 9618, 9619, 9620, \n\t9621, 9622, 9623, 9624, 9625, 9626, 9627, 9628, \n\t9629, 9630, 9631, 9632, 9633, 9634, 9635, 9636, \n\t9637, 9638, 9639, 9640, 9641, 9642, 9643, 9644, \n\t9645, 9646, 9647, 9648, 9649, 9650, 9651, 9652, \n\t9653, 9654, 9655, 9656, 9657, 9658, 9659, 9660, \n\t9661, 9662, 9663, 9664, 9665, 9666, 9667, 9668, \n\t9669, 9670, 9671, 9672, 9673, 9674, 9675, 9676, \n\t9676, 9677, 9678, 9679, 9680, 9681, 9682, 9683, \n\t9684, 9685, 9686, 9687, 9688, 9689, 9690, 9691, \n\t9692, 9693, 9694, 9695, 9696, 9697, 9698, 9699, \n\t9700, 9701, 9702, 9703, 9704, 9705, 9706, 9707, \n\t9708, 9709, 9710, 9711, 9712, 9713, 9714, 9715, \n\t9716, 9717, 9718, 9719, 9720, 9721, 9722, 9723, \n\t9724, 9725, 9726, 9727, 9728, 9729, 9730, 9731, \n\t9732, 9733, 9734, 9735, 9736, 9737, 9738, 9739, \n\t9740, 9741, 9742, 9743, 9744, 9745, 9746, 9747, \n\t9748, 9749, 9750, 9751, 9752, 9753, 9754, 9755, \n\t9756, 9757, 9758, 9759, 9760, 9761, 9762, 9763, \n\t9764, 9765, 9765, 9766, 9767, 9768, 9769, 9770, \n\t9771, 9772, 9773, 9774, 9775, 9776, 9777, 9778, \n\t9779, 9780, 9781, 9782, 9783, 9784, 9785, 9786, \n\t9787, 9788, 9789, 9790, 9791, 9792, 9793, 9794, \n\t9795, 9796, 9797, 9798, 9799, 9800, 9801, 9802, \n\t9803, 9804, 9805, 9806, 9807, 9808, 9809, 9810, \n\t9811, 9812, 9813, 9814, 9815, 9816, 9817, 9818, \n\t9819, 9820, 9821, 9822, 9823, 9824, 9825, 9826, \n\t9827, 9828, 9829, 9830, 9831, 9832, 9833, 9834, \n\t9835, 9836, 9837, 9838, 9839, 9840, 9841, 9842, \n\t9843, 9844, 9845, 9846, 9847, 9848, 9849, 9850, \n\t9851, 9852, 9853, 9853, 9854, 9855, 9856, 9857, \n\t9858, 9859, 9860, 9861, 9862, 9863, 9864, 9865, \n\t9866, 9867, 9868, 9869, 9870, 9871, 9872, 9873, \n\t9874, 9875, 9876, 9877, 9878, 9879, 9880, 9881, \n\t9882, 9883, 9884, 9885, 9886, 9887, 9888, 9889, \n\t9890, 9891, 9892, 9893, 9894, 9895, 9896, 9897, \n\t9898, 9899, 9900, 9901, 9902, 9903, 9904, 9905, \n\t9906, 9907, 9908, 9909, 9910, 9911, 9912, 9913, \n\t9914, 9915, 9916, 9917, 9918, 9919, 9920, 9921, \n\t9922, 9923, 9924, 9925, 9926, 9927, 9928, 9929, \n\t9930, 9931, 9932, 9933, 9934, 9935, 9936, 9937, \n\t9938, 9939, 9939, 9940, 9941, 9942, 9943, 9944, \n\t9945, 9946, 9947, 9948, 9949, 9950, 9951, 9952, \n\t9953, 9954, 9955, 9956, 9957, 9958, 9959, 9960, \n\t9961, 9962, 9963, 9964, 9965, 9966, 9967, 9968, \n\t9969, 9970, 9971, 9972, 9973, 9974, 9975, 9976, \n\t9977, 9978, 9979, 9980, 9981, 9982, 9983, 9984, \n\t9985, 9986, 9987, 9988, 9989, 9990, 9991, 9992, \n\t9993, 9994, 9995, 9996, 9997, 9998, 9999, 10000, \n\t10001, 10002, 10003, 10004, 10005, 10006, 10007, 10008, \n\t10009, 10010, 10011, 10012, 10013, 10014, 10015, 10016, \n\t10017, 10018, 10019, 10020, 10021, 10022, 10023, 10024, \n\t10024, 10025, 10026, 10027, 10028, 10029, 10030, 10031, \n\t10032, 10033, 10034, 10035, 10036, 10037, 10038, 10039, \n\t10040, 10041, 10042, 10043, 10044, 10045, 10046, 10047, \n\t10048, 10049, 10050, 10051, 10052, 10053, 10054, 10055, \n\t10056, 10057, 10058, 10059, 10060, 10061, 10062, 10063, \n\t10064, 10065, 10066, 10067, 10068, 10069, 10070, 10071, \n\t10072, 10073, 10074, 10075, 10076, 10077, 10078, 10079, \n\t10080, 10081, 10082, 10083, 10084, 10085, 10086, 10087, \n\t10088, 10089, 10090, 10091, 10092, 10093, 10094, 10095, \n\t10096, 10097, 10098, 10099, 10100, 10101, 10102, 10103, \n\t10104, 10105, 10106, 10107, 10107, 10108, 10109, 10110, \n\t10111, 10112, 10113, 10114, 10115, 10116, 10117, 10118, \n\t10119, 10120, 10121, 10122, 10123, 10124, 10125, 10126, \n\t10127, 10128, 10129, 10130, 10131, 10132, 10133, 10134, \n\t10135, 10136, 10137, 10138, 10139, 10140, 10141, 10142, \n\t10143, 10144, 10145, 10146, 10147, 10148, 10149, 10150, \n\t10151, 10152, 10153, 10154, 10155, 10156, 10157, 10158, \n\t10159, 10160, 10161, 10162, 10163, 10164, 10165, 10166, \n\t10167, 10168, 10169, 10170, 10171, 10172, 10173, 10174, \n\t10175, 10176, 10177, 10178, 10179, 10180, 10181, 10182, \n\t10183, 10184, 10185, 10186, 10187, 10188, 10189, 10189, \n\t10190, 10191, 10192, 10193, 10194, 10195, 10196, 10197, \n\t10198, 10199, 10200, 10201, 10202, 10203, 10204, 10205, \n\t10206, 10207, 10208, 10209, 10210, 10211, 10212, 10213, \n\t10214, 10215, 10216, 10217, 10218, 10219, 10220, 10221, \n\t10222, 10223, 10224, 10225, 10226, 10227, 10228, 10229, \n\t10230, 10231, 10232, 10233, 10234, 10235, 10236, 10237, \n\t10238, 10239, 10240, 10241, 10242, 10243, 10244, 10245, \n\t10246, 10247, 10248, 10249, 10250, 10251, 10252, 10253, \n\t10254, 10255, 10256, 10257, 10258, 10259, 10260, 10261, \n\t10262, 10263, 10264, 10265, 10266, 10267, 10268, 10269, \n\t10270, 10270, 10271, 10272, 10273, 10274, 10275, 10276, \n\t10277, 10278, 10279, 10280, 10281, 10282, 10283, 10284, \n\t10285, 10286, 10287, 10288, 10289, 10290, 10291, 10292, \n\t10293, 10294, 10295, 10296, 10297, 10298, 10299, 10300, \n\t10301, 10302, 10303, 10304, 10305, 10306, 10307, 10308, \n\t10309, 10310, 10311, 10312, 10313, 10314, 10315, 10316, \n\t10317, 10318, 10319, 10320, 10321, 10322, 10323, 10324, \n\t10325, 10326, 10327, 10328, 10329, 10330, 10331, 10332, \n\t10333, 10334, 10335, 10336, 10337, 10338, 10339, 10340, \n\t10341, 10342, 10343, 10344, 10345, 10346, 10347, 10348, \n\t10349, 10349, 10350, 10351, 10352, 10353, 10354, 10355, \n\t10356, 10357, 10358, 10359, 10360, 10361, 10362, 10363, \n\t10364, 10365, 10366, 10367, 10368, 10369, 10370, 10371, \n\t10372, 10373, 10374, 10375, 10376, 10377, 10378, 10379, \n\t10380, 10381, 10382, 10383, 10384, 10385, 10386, 10387, \n\t10388, 10389, 10390, 10391, 10392, 10393, 10394, 10395, \n\t10396, 10397, 10398, 10399, 10400, 10401, 10402, 10403, \n\t10404, 10405, 10406, 10407, 10408, 10409, 10410, 10411, \n\t10412, 10413, 10414, 10415, 10416, 10417, 10418, 10419, \n\t10420, 10421, 10422, 10423, 10424, 10425, 10426, 10427, \n\t10427, 10428, 10429, 10430, 10431, 10432, 10433, 10434, \n\t10435, 10436, 10437, 10438, 10439, 10440, 10441, 10442, \n\t10443, 10444, 10445, 10446, 10447, 10448, 10449, 10450, \n\t10451, 10452, 10453, 10454, 10455, 10456, 10457, 10458, \n\t10459, 10460, 10461, 10462, 10463, 10464, 10465, 10466, \n\t10467, 10468, 10469, 10470, 10471, 10472, 10473, 10474, \n\t10475, 10476, 10477, 10478, 10479, 10480, 10481, 10482, \n\t10483, 10484, 10485, 10486, 10487, 10488, 10489, 10490, \n\t10491, 10492, 10493, 10494, 10495, 10496, 10497, 10498, \n\t10499, 10500, 10501, 10502, 10503, 10504, 10504, 10505, \n\t10506, 10507, 10508, 10509, 10510, 10511, 10512, 10513, \n\t10514, 10515, 10516, 10517, 10518, 10519, 10520, 10521, \n\t10522, 10523, 10524, 10525, 10526, 10527, 10528, 10529, \n\t10530, 10531, 10532, 10533, 10534, 10535, 10536, 10537, \n\t10538, 10539, 10540, 10541, 10542, 10543, 10544, 10545, \n\t10546, 10547, 10548, 10549, 10550, 10551, 10552, 10553, \n\t10554, 10555, 10556, 10557, 10558, 10559, 10560, 10561, \n\t10562, 10563, 10564, 10565, 10566, 10567, 10568, 10569, \n\t10570, 10571, 10572, 10573, 10574, 10575, 10576, 10577, \n\t10578, 10579, 10580, 10580, 10581, 10582, 10583, 10584, \n\t10585, 10586, 10587, 10588, 10589, 10590, 10591, 10592, \n\t10593, 10594, 10595, 10596, 10597, 10598, 10599, 10600, \n\t10601, 10602, 10603, 10604, 10605, 10606, 10607, 10608, \n\t10609, 10610, 10611, 10612, 10613, 10614, 10615, 10616, \n\t10617, 10618, 10619, 10620, 10621, 10622, 10623, 10624, \n\t10625, 10626, 10627, 10628, 10629, 10630, 10631, 10632, \n\t10633, 10634, 10635, 10636, 10637, 10638, 10639, 10640, \n\t10641, 10642, 10643, 10644, 10645, 10646, 10647, 10648, \n\t10649, 10650, 10651, 10652, 10653, 10654, 10654, 10655, \n\t10656, 10657, 10658, 10659, 10660, 10661, 10662, 10663, \n\t10664, 10665, 10666, 10667, 10668, 10669, 10670, 10671, \n\t10672, 10673, 10674, 10675, 10676, 10677, 10678, 10679, \n\t10680, 10681, 10682, 10683, 10684, 10685, 10686, 10687, \n\t10688, 10689, 10690, 10691, 10692, 10693, 10694, 10695, \n\t10696, 10697, 10698, 10699, 10700, 10701, 10702, 10703, \n\t10704, 10705, 10706, 10707, 10708, 10709, 10710, 10711, \n\t10712, 10713, 10714, 10715, 10716, 10717, 10718, 10719, \n\t10720, 10721, 10722, 10723, 10724, 10725, 10726, 10727, \n\t10728, 10728, 10729, 10730, 10731, 10732, 10733, 10734, \n\t10735, 10736, 10737, 10738, 10739, 10740, 10741, 10742, \n\t10743, 10744, 10745, 10746, 10747, 10748, 10749, 10750, \n\t10751, 10752, 10753, 10754, 10755, 10756, 10757, 10758, \n\t10759, 10760, 10761, 10762, 10763, 10764, 10765, 10766, \n\t10767, 10768, 10769, 10770, 10771, 10772, 10773, 10774, \n\t10775, 10776, 10777, 10778, 10779, 10780, 10781, 10782, \n\t10783, 10784, 10785, 10786, 10787, 10788, 10789, 10790, \n\t10791, 10792, 10793, 10794, 10795, 10796, 10797, 10798, \n\t10799, 10800, 10801, 10801, 10802, 10803, 10804, 10805, \n\t10806, 10807, 10808, 10809, 10810, 10811, 10812, 10813, \n\t10814, 10815, 10816, 10817, 10818, 10819, 10820, 10821, \n\t10822, 10823, 10824, 10825, 10826, 10827, 10828, 10829, \n\t10830, 10831, 10832, 10833, 10834, 10835, 10836, 10837, \n\t10838, 10839, 10840, 10841, 10842, 10843, 10844, 10845, \n\t10846, 10847, 10848, 10849, 10850, 10851, 10852, 10853, \n\t10854, 10855, 10856, 10857, 10858, 10859, 10860, 10861, \n\t10862, 10863, 10864, 10865, 10866, 10867, 10868, 10869, \n\t10870, 10871, 10872, 10872, 10873, 10874, 10875, 10876, \n\t10877, 10878, 10879, 10880, 10881, 10882, 10883, 10884, \n\t10885, 10886, 10887, 10888, 10889, 10890, 10891, 10892, \n\t10893, 10894, 10895, 10896, 10897, 10898, 10899, 10900, \n\t10901, 10902, 10903, 10904, 10905, 10906, 10907, 10908, \n\t10909, 10910, 10911, 10912, 10913, 10914, 10915, 10916, \n\t10917, 10918, 10919, 10920, 10921, 10922, 10923, 10924, \n\t10925, 10926, 10927, 10928, 10929, 10930, 10931, 10932, \n\t10933, 10934, 10935, 10936, 10937, 10938, 10939, 10940, \n\t10941, 10942, 10943, 10943, 10944, 10945, 10946, 10947, \n\t10948, 10949, 10950, 10951, 10952, 10953, 10954, 10955, \n\t10956, 10957, 10958, 10959, 10960, 10961, 10962, 10963, \n\t10964, 10965, 10966, 10967, 10968, 10969, 10970, 10971, \n\t10972, 10973, 10974, 10975, 10976, 10977, 10978, 10979, \n\t10980, 10981, 10982, 10983, 10984, 10985, 10986, 10987, \n\t10988, 10989, 10990, 10991, 10992, 10993, 10994, 10995, \n\t10996, 10997, 10998, 10999, 11000, 11001, 11002, 11003, \n\t11004, 11005, 11006, 11007, 11008, 11009, 11010, 11011, \n\t11012, 11013, 11013, 11014, 11015, 11016, 11017, 11018, \n\t11019, 11020, 11021, 11022, 11023, 11024, 11025, 11026, \n\t11027, 11028, 11029, 11030, 11031, 11032, 11033, 11034, \n\t11035, 11036, 11037, 11038, 11039, 11040, 11041, 11042, \n\t11043, 11044, 11045, 11046, 11047, 11048, 11049, 11050, \n\t11051, 11052, 11053, 11054, 11055, 11056, 11057, 11058, \n\t11059, 11060, 11061, 11062, 11063, 11064, 11065, 11066, \n\t11067, 11068, 11069, 11070, 11071, 11072, 11073, 11074, \n\t11075, 11076, 11077, 11078, 11079, 11080, 11081, 11082, \n\t11082, 11083, 11084, 11085, 11086, 11087, 11088, 11089, \n\t11090, 11091, 11092, 11093, 11094, 11095, 11096, 11097, \n\t11098, 11099, 11100, 11101, 11102, 11103, 11104, 11105, \n\t11106, 11107, 11108, 11109, 11110, 11111, 11112, 11113, \n\t11114, 11115, 11116, 11117, 11118, 11119, 11120, 11121, \n\t11122, 11123, 11124, 11125, 11126, 11127, 11128, 11129, \n\t11130, 11131, 11132, 11133, 11134, 11135, 11136, 11137, \n\t11138, 11139, 11140, 11141, 11142, 11143, 11144, 11145, \n\t11146, 11147, 11148, 11149, 11150, 11150, 11151, 11152, \n\t11153, 11154, 11155, 11156, 11157, 11158, 11159, 11160, \n\t11161, 11162, 11163, 11164, 11165, 11166, 11167, 11168, \n\t11169, 11170, 11171, 11172, 11173, 11174, 11175, 11176, \n\t11177, 11178, 11179, 11180, 11181, 11182, 11183, 11184, \n\t11185, 11186, 11187, 11188, 11189, 11190, 11191, 11192, \n\t11193, 11194, 11195, 11196, 11197, 11198, 11199, 11200, \n\t11201, 11202, 11203, 11204, 11205, 11206, 11207, 11208, \n\t11209, 11210, 11211, 11212, 11213, 11214, 11215, 11216, \n\t11217, 11217, 11218, 11219, 11220, 11221, 11222, 11223, \n\t11224, 11225, 11226, 11227, 11228, 11229, 11230, 11231, \n\t11232, 11233, 11234, 11235, 11236, 11237, 11238, 11239, \n\t11240, 11241, 11242, 11243, 11244, 11245, 11246, 11247, \n\t11248, 11249, 11250, 11251, 11252, 11253, 11254, 11255, \n\t11256, 11257, 11258, 11259, 11260, 11261, 11262, 11263, \n\t11264, 11265, 11266, 11267, 11268, 11269, 11270, 11271, \n\t11272, 11273, 11274, 11275, 11276, 11277, 11278, 11279, \n\t11280, 11281, 11282, 11283, 11283, 11284, 11285, 11286, \n\t11287, 11288, 11289, 11290, 11291, 11292, 11293, 11294, \n\t11295, 11296, 11297, 11298, 11299, 11300, 11301, 11302, \n\t11303, 11304, 11305, 11306, 11307, 11308, 11309, 11310, \n\t11311, 11312, 11313, 11314, 11315, 11316, 11317, 11318, \n\t11319, 11320, 11321, 11322, 11323, 11324, 11325, 11326, \n\t11327, 11328, 11329, 11330, 11331, 11332, 11333, 11334, \n\t11335, 11336, 11337, 11338, 11339, 11340, 11341, 11342, \n\t11343, 11344, 11345, 11346, 11347, 11348, 11349, 11349, \n\t11350, 11351, 11352, 11353, 11354, 11355, 11356, 11357, \n\t11358, 11359, 11360, 11361, 11362, 11363, 11364, 11365, \n\t11366, 11367, 11368, 11369, 11370, 11371, 11372, 11373, \n\t11374, 11375, 11376, 11377, 11378, 11379, 11380, 11381, \n\t11382, 11383, 11384, 11385, 11386, 11387, 11388, 11389, \n\t11390, 11391, 11392, 11393, 11394, 11395, 11396, 11397, \n\t11398, 11399, 11400, 11401, 11402, 11403, 11404, 11405, \n\t11406, 11407, 11408, 11409, 11410, 11411, 11412, 11413, \n\t11414, 11414, 11415, 11416, 11417, 11418, 11419, 11420, \n\t11421, 11422, 11423, 11424, 11425, 11426, 11427, 11428, \n\t11429, 11430, 11431, 11432, 11433, 11434, 11435, 11436, \n\t11437, 11438, 11439, 11440, 11441, 11442, 11443, 11444, \n\t11445, 11446, 11447, 11448, 11449, 11450, 11451, 11452, \n\t11453, 11454, 11455, 11456, 11457, 11458, 11459, 11460, \n\t11461, 11462, 11463, 11464, 11465, 11466, 11467, 11468, \n\t11469, 11470, 11471, 11472, 11473, 11474, 11475, 11476, \n\t11477, 11478, 11478, 11479, 11480, 11481, 11482, 11483, \n\t11484, 11485, 11486, 11487, 11488, 11489, 11490, 11491, \n\t11492, 11493, 11494, 11495, 11496, 11497, 11498, 11499, \n\t11500, 11501, 11502, 11503, 11504, 11505, 11506, 11507, \n\t11508, 11509, 11510, 11511, 11512, 11513, 11514, 11515, \n\t11516, 11517, 11518, 11519, 11520, 11521, 11522, 11523, \n\t11524, 11525, 11526, 11527, 11528, 11529, 11530, 11531, \n\t11532, 11533, 11534, 11535, 11536, 11537, 11538, 11539, \n\t11540, 11541, 11541, 11542, 11543, 11544, 11545, 11546, \n\t11547, 11548, 11549, 11550, 11551, 11552, 11553, 11554, \n\t11555, 11556, 11557, 11558, 11559, 11560, 11561, 11562, \n\t11563, 11564, 11565, 11566, 11567, 11568, 11569, 11570, \n\t11571, 11572, 11573, 11574, 11575, 11576, 11577, 11578, \n\t11579, 11580, 11581, 11582, 11583, 11584, 11585, 11586, \n\t11587, 11588, 11589, 11590, 11591, 11592, 11593, 11594, \n\t11595, 11596, 11597, 11598, 11599, 11600, 11601, 11602, \n\t11603, 11604, 11604, 11605, 11606, 11607, 11608, 11609, \n\t11610, 11611, 11612, 11613, 11614, 11615, 11616, 11617, \n\t11618, 11619, 11620, 11621, 11622, 11623, 11624, 11625, \n\t11626, 11627, 11628, 11629, 11630, 11631, 11632, 11633, \n\t11634, 11635, 11636, 11637, 11638, 11639, 11640, 11641, \n\t11642, 11643, 11644, 11645, 11646, 11647, 11648, 11649, \n\t11650, 11651, 11652, 11653, 11654, 11655, 11656, 11657, \n\t11658, 11659, 11660, 11661, 11662, 11663, 11664, 11665, \n\t11666, 11666, 11667, 11668, 11669, 11670, 11671, 11672, \n\t11673, 11674, 11675, 11676, 11677, 11678, 11679, 11680, \n\t11681, 11682, 11683, 11684, 11685, 11686, 11687, 11688, \n\t11689, 11690, 11691, 11692, 11693, 11694, 11695, 11696, \n\t11697, 11698, 11699, 11700, 11701, 11702, 11703, 11704, \n\t11705, 11706, 11707, 11708, 11709, 11710, 11711, 11712, \n\t11713, 11714, 11715, 11716, 11717, 11718, 11719, 11720, \n\t11721, 11722, 11723, 11724, 11725, 11726, 11727, 11727, \n\t11728, 11729, 11730, 11731, 11732, 11733, 11734, 11735, \n\t11736, 11737, 11738, 11739, 11740, 11741, 11742, 11743, \n\t11744, 11745, 11746, 11747, 11748, 11749, 11750, 11751, \n\t11752, 11753, 11754, 11755, 11756, 11757, 11758, 11759, \n\t11760, 11761, 11762, 11763, 11764, 11765, 11766, 11767, \n\t11768, 11769, 11770, 11771, 11772, 11773, 11774, 11775, \n\t11776, 11777, 11778, 11779, 11780, 11781, 11782, 11783, \n\t11784, 11785, 11786, 11787, 11788, 11788, 11789, 11790, \n\t11791, 11792, 11793, 11794, 11795, 11796, 11797, 11798, \n\t11799, 11800, 11801, 11802, 11803, 11804, 11805, 11806, \n\t11807, 11808, 11809, 11810, 11811, 11812, 11813, 11814, \n\t11815, 11816, 11817, 11818, 11819, 11820, 11821, 11822, \n\t11823, 11824, 11825, 11826, 11827, 11828, 11829, 11830, \n\t11831, 11832, 11833, 11834, 11835, 11836, 11837, 11838, \n\t11839, 11840, 11841, 11842, 11843, 11844, 11845, 11846, \n\t11847, 11848, 11848, 11849, 11850, 11851, 11852, 11853, \n\t11854, 11855, 11856, 11857, 11858, 11859, 11860, 11861, \n\t11862, 11863, 11864, 11865, 11866, 11867, 11868, 11869, \n\t11870, 11871, 11872, 11873, 11874, 11875, 11876, 11877, \n\t11878, 11879, 11880, 11881, 11882, 11883, 11884, 11885, \n\t11886, 11887, 11888, 11889, 11890, 11891, 11892, 11893, \n\t11894, 11895, 11896, 11897, 11898, 11899, 11900, 11901, \n\t11902, 11903, 11904, 11905, 11906, 11907, 11907, 11908, \n\t11909, 11910, 11911, 11912, 11913, 11914, 11915, 11916, \n\t11917, 11918, 11919, 11920, 11921, 11922, 11923, 11924, \n\t11925, 11926, 11927, 11928, 11929, 11930, 11931, 11932, \n\t11933, 11934, 11935, 11936, 11937, 11938, 11939, 11940, \n\t11941, 11942, 11943, 11944, 11945, 11946, 11947, 11948, \n\t11949, 11950, 11951, 11952, 11953, 11954, 11955, 11956, \n\t11957, 11958, 11959, 11960, 11961, 11962, 11963, 11964, \n\t11965, 11966, 11966, 11967, 11968, 11969, 11970, 11971, \n\t11972, 11973, 11974, 11975, 11976, 11977, 11978, 11979, \n\t11980, 11981, 11982, 11983, 11984, 11985, 11986, 11987, \n\t11988, 11989, 11990, 11991, 11992, 11993, 11994, 11995, \n\t11996, 11997, 11998, 11999, 12000, 12001, 12002, 12003, \n\t12004, 12005, 12006, 12007, 12008, 12009, 12010, 12011, \n\t12012, 12013, 12014, 12015, 12016, 12017, 12018, 12019, \n\t12020, 12021, 12022, 12023, 12024, 12024, 12025, 12026, \n\t12027, 12028, 12029, 12030, 12031, 12032, 12033, 12034, \n\t12035, 12036, 12037, 12038, 12039, 12040, 12041, 12042, \n\t12043, 12044, 12045, 12046, 12047, 12048, 12049, 12050, \n\t12051, 12052, 12053, 12054, 12055, 12056, 12057, 12058, \n\t12059, 12060, 12061, 12062, 12063, 12064, 12065, 12066, \n\t12067, 12068, 12069, 12070, 12071, 12072, 12073, 12074, \n\t12075, 12076, 12077, 12078, 12079, 12080, 12081, 12082, \n\t12082, 12083, 12084, 12085, 12086, 12087, 12088, 12089, \n\t12090, 12091, 12092, 12093, 12094, 12095, 12096, 12097, \n\t12098, 12099, 12100, 12101, 12102, 12103, 12104, 12105, \n\t12106, 12107, 12108, 12109, 12110, 12111, 12112, 12113, \n\t12114, 12115, 12116, 12117, 12118, 12119, 12120, 12121, \n\t12122, 12123, 12124, 12125, 12126, 12127, 12128, 12129, \n\t12130, 12131, 12132, 12133, 12134, 12135, 12136, 12137, \n\t12138, 12139, 12139, 12140, 12141, 12142, 12143, 12144, \n\t12145, 12146, 12147, 12148, 12149, 12150, 12151, 12152, \n\t12153, 12154, 12155, 12156, 12157, 12158, 12159, 12160, \n\t12161, 12162, 12163, 12164, 12165, 12166, 12167, 12168, \n\t12169, 12170, 12171, 12172, 12173, 12174, 12175, 12176, \n\t12177, 12178, 12179, 12180, 12181, 12182, 12183, 12184, \n\t12185, 12186, 12187, 12188, 12189, 12190, 12191, 12192, \n\t12193, 12194, 12195, 12195, 12196, 12197, 12198, 12199, \n\t12200, 12201, 12202, 12203, 12204, 12205, 12206, 12207, \n\t12208, 12209, 12210, 12211, 12212, 12213, 12214, 12215, \n\t12216, 12217, 12218, 12219, 12220, 12221, 12222, 12223, \n\t12224, 12225, 12226, 12227, 12228, 12229, 12230, 12231, \n\t12232, 12233, 12234, 12235, 12236, 12237, 12238, 12239, \n\t12240, 12241, 12242, 12243, 12244, 12245, 12246, 12247, \n\t12248, 12249, 12250, 12251, 12251, 12252, 12253, 12254, \n\t12255, 12256, 12257, 12258, 12259, 12260, 12261, 12262, \n\t12263, 12264, 12265, 12266, 12267, 12268, 12269, 12270, \n\t12271, 12272, 12273, 12274, 12275, 12276, 12277, 12278, \n\t12279, 12280, 12281, 12282, 12283, 12284, 12285, 12286, \n\t12287, 12288, 12289, 12290, 12291, 12292, 12293, 12294, \n\t12295, 12296, 12297, 12298, 12299, 12300, 12301, 12302, \n\t12303, 12304, 12305, 12306, 12307, 12307, 12308, 12309, \n\t12310, 12311, 12312, 12313, 12314, 12315, 12316, 12317, \n\t12318, 12319, 12320, 12321, 12322, 12323, 12324, 12325, \n\t12326, 12327, 12328, 12329, 12330, 12331, 12332, 12333, \n\t12334, 12335, 12336, 12337, 12338, 12339, 12340, 12341, \n\t12342, 12343, 12344, 12345, 12346, 12347, 12348, 12349, \n\t12350, 12351, 12352, 12353, 12354, 12355, 12356, 12357, \n\t12358, 12359, 12360, 12361, 12362, 12362, 12363, 12364, \n\t12365, 12366, 12367, 12368, 12369, 12370, 12371, 12372, \n\t12373, 12374, 12375, 12376, 12377, 12378, 12379, 12380, \n\t12381, 12382, 12383, 12384, 12385, 12386, 12387, 12388, \n\t12389, 12390, 12391, 12392, 12393, 12394, 12395, 12396, \n\t12397, 12398, 12399, 12400, 12401, 12402, 12403, 12404, \n\t12405, 12406, 12407, 12408, 12409, 12410, 12411, 12412, \n\t12413, 12414, 12415, 12416, 12416, 12417, 12418, 12419, \n\t12420, 12421, 12422, 12423, 12424, 12425, 12426, 12427, \n\t12428, 12429, 12430, 12431, 12432, 12433, 12434, 12435, \n\t12436, 12437, 12438, 12439, 12440, 12441, 12442, 12443, \n\t12444, 12445, 12446, 12447, 12448, 12449, 12450, 12451, \n\t12452, 12453, 12454, 12455, 12456, 12457, 12458, 12459, \n\t12460, 12461, 12462, 12463, 12464, 12465, 12466, 12467, \n\t12468, 12469, 12470, 12470, 12471, 12472, 12473, 12474, \n\t12475, 12476, 12477, 12478, 12479, 12480, 12481, 12482, \n\t12483, 12484, 12485, 12486, 12487, 12488, 12489, 12490, \n\t12491, 12492, 12493, 12494, 12495, 12496, 12497, 12498, \n\t12499, 12500, 12501, 12502, 12503, 12504, 12505, 12506, \n\t12507, 12508, 12509, 12510, 12511, 12512, 12513, 12514, \n\t12515, 12516, 12517, 12518, 12519, 12520, 12521, 12522, \n\t12523, 12524, 12524, 12525, 12526, 12527, 12528, 12529, \n\t12530, 12531, 12532, 12533, 12534, 12535, 12536, 12537, \n\t12538, 12539, 12540, 12541, 12542, 12543, 12544, 12545, \n\t12546, 12547, 12548, 12549, 12550, 12551, 12552, 12553, \n\t12554, 12555, 12556, 12557, 12558, 12559, 12560, 12561, \n\t12562, 12563, 12564, 12565, 12566, 12567, 12568, 12569, \n\t12570, 12571, 12572, 12573, 12574, 12575, 12576, 12577, \n\t12577, 12578, 12579, 12580, 12581, 12582, 12583, 12584, \n\t12585, 12586, 12587, 12588, 12589, 12590, 12591, 12592, \n\t12593, 12594, 12595, 12596, 12597, 12598, 12599, 12600, \n\t12601, 12602, 12603, 12604, 12605, 12606, 12607, 12608, \n\t12609, 12610, 12611, 12612, 12613, 12614, 12615, 12616, \n\t12617, 12618, 12619, 12620, 12621, 12622, 12623, 12624, \n\t12625, 12626, 12627, 12628, 12629, 12629, 12630, 12631, \n\t12632, 12633, 12634, 12635, 12636, 12637, 12638, 12639, \n\t12640, 12641, 12642, 12643, 12644, 12645, 12646, 12647, \n\t12648, 12649, 12650, 12651, 12652, 12653, 12654, 12655, \n\t12656, 12657, 12658, 12659, 12660, 12661, 12662, 12663, \n\t12664, 12665, 12666, 12667, 12668, 12669, 12670, 12671, \n\t12672, 12673, 12674, 12675, 12676, 12677, 12678, 12679, \n\t12680, 12681, 12681, 12682, 12683, 12684, 12685, 12686, \n\t12687, 12688, 12689, 12690, 12691, 12692, 12693, 12694, \n\t12695, 12696, 12697, 12698, 12699, 12700, 12701, 12702, \n\t12703, 12704, 12705, 12706, 12707, 12708, 12709, 12710, \n\t12711, 12712, 12713, 12714, 12715, 12716, 12717, 12718, \n\t12719, 12720, 12721, 12722, 12723, 12724, 12725, 12726, \n\t12727, 12728, 12729, 12730, 12731, 12732, 12733, 12733, \n\t12734, 12735, 12736, 12737, 12738, 12739, 12740, 12741, \n\t12742, 12743, 12744, 12745, 12746, 12747, 12748, 12749, \n\t12750, 12751, 12752, 12753, 12754, 12755, 12756, 12757, \n\t12758, 12759, 12760, 12761, 12762, 12763, 12764, 12765, \n\t12766, 12767, 12768, 12769, 12770, 12771, 12772, 12773, \n\t12774, 12775, 12776, 12777, 12778, 12779, 12780, 12781, \n\t12782, 12783, 12784, 12784, 12785, 12786, 12787, 12788, \n\t12789, 12790, 12791, 12792, 12793, 12794, 12795, 12796, \n\t12797, 12798, 12799, 12800, 12801, 12802, 12803, 12804, \n\t12805, 12806, 12807, 12808, 12809, 12810, 12811, 12812, \n\t12813, 12814, 12815, 12816, 12817, 12818, 12819, 12820, \n\t12821, 12822, 12823, 12824, 12825, 12826, 12827, 12828, \n\t12829, 12830, 12831, 12832, 12833, 12834, 12835, 12835, \n\t12836, 12837, 12838, 12839, 12840, 12841, 12842, 12843, \n\t12844, 12845, 12846, 12847, 12848, 12849, 12850, 12851, \n\t12852, 12853, 12854, 12855, 12856, 12857, 12858, 12859, \n\t12860, 12861, 12862, 12863, 12864, 12865, 12866, 12867, \n\t12868, 12869, 12870, 12871, 12872, 12873, 12874, 12875, \n\t12876, 12877, 12878, 12879, 12880, 12881, 12882, 12883, \n\t12884, 12885, 12885, 12886, 12887, 12888, 12889, 12890, \n\t12891, 12892, 12893, 12894, 12895, 12896, 12897, 12898, \n\t12899, 12900, 12901, 12902, 12903, 12904, 12905, 12906, \n\t12907, 12908, 12909, 12910, 12911, 12912, 12913, 12914, \n\t12915, 12916, 12917, 12918, 12919, 12920, 12921, 12922, \n\t12923, 12924, 12925, 12926, 12927, 12928, 12929, 12930, \n\t12931, 12932, 12933, 12934, 12935, 12936, 12936, 12937, \n\t12938, 12939, 12940, 12941, 12942, 12943, 12944, 12945, \n\t12946, 12947, 12948, 12949, 12950, 12951, 12952, 12953, \n\t12954, 12955, 12956, 12957, 12958, 12959, 12960, 12961, \n\t12962, 12963, 12964, 12965, 12966, 12967, 12968, 12969, \n\t12970, 12971, 12972, 12973, 12974, 12975, 12976, 12977, \n\t12978, 12979, 12980, 12981, 12982, 12983, 12984, 12985, \n\t12985, 12986, 12987, 12988, 12989, 12990, 12991, 12992, \n\t12993, 12994, 12995, 12996, 12997, 12998, 12999, 13000, \n\t13001, 13002, 13003, 13004, 13005, 13006, 13007, 13008, \n\t13009, 13010, 13011, 13012, 13013, 13014, 13015, 13016, \n\t13017, 13018, 13019, 13020, 13021, 13022, 13023, 13024, \n\t13025, 13026, 13027, 13028, 13029, 13030, 13031, 13032, \n\t13033, 13034, 13034, 13035, 13036, 13037, 13038, 13039, \n\t13040, 13041, 13042, 13043, 13044, 13045, 13046, 13047, \n\t13048, 13049, 13050, 13051, 13052, 13053, 13054, 13055, \n\t13056, 13057, 13058, 13059, 13060, 13061, 13062, 13063, \n\t13064, 13065, 13066, 13067, 13068, 13069, 13070, 13071, \n\t13072, 13073, 13074, 13075, 13076, 13077, 13078, 13079, \n\t13080, 13081, 13082, 13083, 13083, 13084, 13085, 13086, \n\t13087, 13088, 13089, 13090, 13091, 13092, 13093, 13094, \n\t13095, 13096, 13097, 13098, 13099, 13100, 13101, 13102, \n\t13103, 13104, 13105, 13106, 13107, 13108, 13109, 13110, \n\t13111, 13112, 13113, 13114, 13115, 13116, 13117, 13118, \n\t13119, 13120, 13121, 13122, 13123, 13124, 13125, 13126, \n\t13127, 13128, 13129, 13130, 13131, 13132, 13132, 13133, \n\t13134, 13135, 13136, 13137, 13138, 13139, 13140, 13141, \n\t13142, 13143, 13144, 13145, 13146, 13147, 13148, 13149, \n\t13150, 13151, 13152, 13153, 13154, 13155, 13156, 13157, \n\t13158, 13159, 13160, 13161, 13162, 13163, 13164, 13165, \n\t13166, 13167, 13168, 13169, 13170, 13171, 13172, 13173, \n\t13174, 13175, 13176, 13177, 13178, 13179, 13180, 13180, \n\t13181, 13182, 13183, 13184, 13185, 13186, 13187, 13188, \n\t13189, 13190, 13191, 13192, 13193, 13194, 13195, 13196, \n\t13197, 13198, 13199, 13200, 13201, 13202, 13203, 13204, \n\t13205, 13206, 13207, 13208, 13209, 13210, 13211, 13212, \n\t13213, 13214, 13215, 13216, 13217, 13218, 13219, 13220, \n\t13221, 13222, 13223, 13224, 13225, 13226, 13227, 13228, \n\t13228, 13229, 13230, 13231, 13232, 13233, 13234, 13235, \n\t13236, 13237, 13238, 13239, 13240, 13241, 13242, 13243, \n\t13244, 13245, 13246, 13247, 13248, 13249, 13250, 13251, \n\t13252, 13253, 13254, 13255, 13256, 13257, 13258, 13259, \n\t13260, 13261, 13262, 13263, 13264, 13265, 13266, 13267, \n\t13268, 13269, 13270, 13271, 13272, 13273, 13274, 13275, \n\t13275, 13276, 13277, 13278, 13279, 13280, 13281, 13282, \n\t13283, 13284, 13285, 13286, 13287, 13288, 13289, 13290, \n\t13291, 13292, 13293, 13294, 13295, 13296, 13297, 13298, \n\t13299, 13300, 13301, 13302, 13303, 13304, 13305, 13306, \n\t13307, 13308, 13309, 13310, 13311, 13312, 13313, 13314, \n\t13315, 13316, 13317, 13318, 13319, 13320, 13321, 13322, \n\t13322, 13323, 13324, 13325, 13326, 13327, 13328, 13329, \n\t13330, 13331, 13332, 13333, 13334, 13335, 13336, 13337, \n\t13338, 13339, 13340, 13341, 13342, 13343, 13344, 13345, \n\t13346, 13347, 13348, 13349, 13350, 13351, 13352, 13353, \n\t13354, 13355, 13356, 13357, 13358, 13359, 13360, 13361, \n\t13362, 13363, 13364, 13365, 13366, 13367, 13368, 13369, \n\t13369, 13370, 13371, 13372, 13373, 13374, 13375, 13376, \n\t13377, 13378, 13379, 13380, 13381, 13382, 13383, 13384, \n\t13385, 13386, 13387, 13388, 13389, 13390, 13391, 13392, \n\t13393, 13394, 13395, 13396, 13397, 13398, 13399, 13400, \n\t13401, 13402, 13403, 13404, 13405, 13406, 13407, 13408, \n\t13409, 13410, 13411, 13412, 13413, 13414, 13415, 13415, \n\t13416, 13417, 13418, 13419, 13420, 13421, 13422, 13423, \n\t13424, 13425, 13426, 13427, 13428, 13429, 13430, 13431, \n\t13432, 13433, 13434, 13435, 13436, 13437, 13438, 13439, \n\t13440, 13441, 13442, 13443, 13444, 13445, 13446, 13447, \n\t13448, 13449, 13450, 13451, 13452, 13453, 13454, 13455, \n\t13456, 13457, 13458, 13459, 13460, 13461, 13461, 13462, \n\t13463, 13464, 13465, 13466, 13467, 13468, 13469, 13470, \n\t13471, 13472, 13473, 13474, 13475, 13476, 13477, 13478, \n\t13479, 13480, 13481, 13482, 13483, 13484, 13485, 13486, \n\t13487, 13488, 13489, 13490, 13491, 13492, 13493, 13494, \n\t13495, 13496, 13497, 13498, 13499, 13500, 13501, 13502, \n\t13503, 13504, 13505, 13506, 13507, 13507, 13508, 13509, \n\t13510, 13511, 13512, 13513, 13514, 13515, 13516, 13517, \n\t13518, 13519, 13520, 13521, 13522, 13523, 13524, 13525, \n\t13526, 13527, 13528, 13529, 13530, 13531, 13532, 13533, \n\t13534, 13535, 13536, 13537, 13538, 13539, 13540, 13541, \n\t13542, 13543, 13544, 13545, 13546, 13547, 13548, 13549, \n\t13550, 13551, 13552, 13552, 13553, 13554, 13555, 13556, \n\t13557, 13558, 13559, 13560, 13561, 13562, 13563, 13564, \n\t13565, 13566, 13567, 13568, 13569, 13570, 13571, 13572, \n\t13573, 13574, 13575, 13576, 13577, 13578, 13579, 13580, \n\t13581, 13582, 13583, 13584, 13585, 13586, 13587, 13588, \n\t13589, 13590, 13591, 13592, 13593, 13594, 13595, 13596, \n\t13597, 13598, 13598, 13599, 13600, 13601, 13602, 13603, \n\t13604, 13605, 13606, 13607, 13608, 13609, 13610, 13611, \n\t13612, 13613, 13614, 13615, 13616, 13617, 13618, 13619, \n\t13620, 13621, 13622, 13623, 13624, 13625, 13626, 13627, \n\t13628, 13629, 13630, 13631, 13632, 13633, 13634, 13635, \n\t13636, 13637, 13638, 13639, 13640, 13641, 13642, 13642, \n\t13643, 13644, 13645, 13646, 13647, 13648, 13649, 13650, \n\t13651, 13652, 13653, 13654, 13655, 13656, 13657, 13658, \n\t13659, 13660, 13661, 13662, 13663, 13664, 13665, 13666, \n\t13667, 13668, 13669, 13670, 13671, 13672, 13673, 13674, \n\t13675, 13676, 13677, 13678, 13679, 13680, 13681, 13682, \n\t13683, 13684, 13685, 13686, 13687, 13687, 13688, 13689, \n\t13690, 13691, 13692, 13693, 13694, 13695, 13696, 13697, \n\t13698, 13699, 13700, 13701, 13702, 13703, 13704, 13705, \n\t13706, 13707, 13708, 13709, 13710, 13711, 13712, 13713, \n\t13714, 13715, 13716, 13717, 13718, 13719, 13720, 13721, \n\t13722, 13723, 13724, 13725, 13726, 13727, 13728, 13729, \n\t13730, 13731, 13731, 13732, 13733, 13734, 13735, 13736, \n\t13737, 13738, 13739, 13740, 13741, 13742, 13743, 13744, \n\t13745, 13746, 13747, 13748, 13749, 13750, 13751, 13752, \n\t13753, 13754, 13755, 13756, 13757, 13758, 13759, 13760, \n\t13761, 13762, 13763, 13764, 13765, 13766, 13767, 13768, \n\t13769, 13770, 13771, 13772, 13773, 13774, 13775, 13775, \n\t13776, 13777, 13778, 13779, 13780, 13781, 13782, 13783, \n\t13784, 13785, 13786, 13787, 13788, 13789, 13790, 13791, \n\t13792, 13793, 13794, 13795, 13796, 13797, 13798, 13799, \n\t13800, 13801, 13802, 13803, 13804, 13805, 13806, 13807, \n\t13808, 13809, 13810, 13811, 13812, 13813, 13814, 13815, \n\t13816, 13817, 13818, 13819, 13819, 13820, 13821, 13822, \n\t13823, 13824, 13825, 13826, 13827, 13828, 13829, 13830, \n\t13831, 13832, 13833, 13834, 13835, 13836, 13837, 13838, \n\t13839, 13840, 13841, 13842, 13843, 13844, 13845, 13846, \n\t13847, 13848, 13849, 13850, 13851, 13852, 13853, 13854, \n\t13855, 13856, 13857, 13858, 13859, 13860, 13861, 13862, \n\t13862, 13863, 13864, 13865, 13866, 13867, 13868, 13869, \n\t13870, 13871, 13872, 13873, 13874, 13875, 13876, 13877, \n\t13878, 13879, 13880, 13881, 13882, 13883, 13884, 13885, \n\t13886, 13887, 13888, 13889, 13890, 13891, 13892, 13893, \n\t13894, 13895, 13896, 13897, 13898, 13899, 13900, 13901, \n\t13902, 13903, 13904, 13905, 13905, 13906, 13907, 13908, \n\t13909, 13910, 13911, 13912, 13913, 13914, 13915, 13916, \n\t13917, 13918, 13919, 13920, 13921, 13922, 13923, 13924, \n\t13925, 13926, 13927, 13928, 13929, 13930, 13931, 13932, \n\t13933, 13934, 13935, 13936, 13937, 13938, 13939, 13940, \n\t13941, 13942, 13943, 13944, 13945, 13946, 13947, 13948, \n\t13948, 13949, 13950, 13951, 13952, 13953, 13954, 13955, \n\t13956, 13957, 13958, 13959, 13960, 13961, 13962, 13963, \n\t13964, 13965, 13966, 13967, 13968, 13969, 13970, 13971, \n\t13972, 13973, 13974, 13975, 13976, 13977, 13978, 13979, \n\t13980, 13981, 13982, 13983, 13984, 13985, 13986, 13987, \n\t13988, 13989, 13990, 13990, 13991, 13992, 13993, 13994, \n\t13995, 13996, 13997, 13998, 13999, 14000, 14001, 14002, \n\t14003, 14004, 14005, 14006, 14007, 14008, 14009, 14010, \n\t14011, 14012, 14013, 14014, 14015, 14016, 14017, 14018, \n\t14019, 14020, 14021, 14022, 14023, 14024, 14025, 14026, \n\t14027, 14028, 14029, 14030, 14031, 14032, 14033, 14033, \n\t14034, 14035, 14036, 14037, 14038, 14039, 14040, 14041, \n\t14042, 14043, 14044, 14045, 14046, 14047, 14048, 14049, \n\t14050, 14051, 14052, 14053, 14054, 14055, 14056, 14057, \n\t14058, 14059, 14060, 14061, 14062, 14063, 14064, 14065, \n\t14066, 14067, 14068, 14069, 14070, 14071, 14072, 14073, \n\t14074, 14075, 14075, 14076, 14077, 14078, 14079, 14080, \n\t14081, 14082, 14083, 14084, 14085, 14086, 14087, 14088, \n\t14089, 14090, 14091, 14092, 14093, 14094, 14095, 14096, \n\t14097, 14098, 14099, 14100, 14101, 14102, 14103, 14104, \n\t14105, 14106, 14107, 14108, 14109, 14110, 14111, 14112, \n\t14113, 14114, 14115, 14116, 14116, 14117, 14118, 14119, \n\t14120, 14121, 14122, 14123, 14124, 14125, 14126, 14127, \n\t14128, 14129, 14130, 14131, 14132, 14133, 14134, 14135, \n\t14136, 14137, 14138, 14139, 14140, 14141, 14142, 14143, \n\t14144, 14145, 14146, 14147, 14148, 14149, 14150, 14151, \n\t14152, 14153, 14154, 14155, 14156, 14157, 14158, 14158, \n\t14159, 14160, 14161, 14162, 14163, 14164, 14165, 14166, \n\t14167, 14168, 14169, 14170, 14171, 14172, 14173, 14174, \n\t14175, 14176, 14177, 14178, 14179, 14180, 14181, 14182, \n\t14183, 14184, 14185, 14186, 14187, 14188, 14189, 14190, \n\t14191, 14192, 14193, 14194, 14195, 14196, 14197, 14198, \n\t14199, 14199, 14200, 14201, 14202, 14203, 14204, 14205, \n\t14206, 14207, 14208, 14209, 14210, 14211, 14212, 14213, \n\t14214, 14215, 14216, 14217, 14218, 14219, 14220, 14221, \n\t14222, 14223, 14224, 14225, 14226, 14227, 14228, 14229, \n\t14230, 14231, 14232, 14233, 14234, 14235, 14236, 14237, \n\t14238, 14239, 14240, 14240, 14241, 14242, 14243, 14244, \n\t14245, 14246, 14247, 14248, 14249, 14250, 14251, 14252, \n\t14253, 14254, 14255, 14256, 14257, 14258, 14259, 14260, \n\t14261, 14262, 14263, 14264, 14265, 14266, 14267, 14268, \n\t14269, 14270, 14271, 14272, 14273, 14274, 14275, 14276, \n\t14277, 14278, 14279, 14280, 14281, 14281, 14282, 14283, \n\t14284, 14285, 14286, 14287, 14288, 14289, 14290, 14291, \n\t14292, 14293, 14294, 14295, 14296, 14297, 14298, 14299, \n\t14300, 14301, 14302, 14303, 14304, 14305, 14306, 14307, \n\t14308, 14309, 14310, 14311, 14312, 14313, 14314, 14315, \n\t14316, 14317, 14318, 14319, 14320, 14321, 14321, 14322, \n\t14323, 14324, 14325, 14326, 14327, 14328, 14329, 14330, \n\t14331, 14332, 14333, 14334, 14335, 14336, 14337, 14338, \n\t14339, 14340, 14341, 14342, 14343, 14344, 14345, 14346, \n\t14347, 14348, 14349, 14350, 14351, 14352, 14353, 14354, \n\t14355, 14356, 14357, 14358, 14359, 14360, 14361, 14361, \n\t14362, 14363, 14364, 14365, 14366, 14367, 14368, 14369, \n\t14370, 14371, 14372, 14373, 14374, 14375, 14376, 14377, \n\t14378, 14379, 14380, 14381, 14382, 14383, 14384, 14385, \n\t14386, 14387, 14388, 14389, 14390, 14391, 14392, 14393, \n\t14394, 14395, 14396, 14397, 14398, 14399, 14400, 14401, \n\t14401, 14402, 14403, 14404, 14405, 14406, 14407, 14408, \n\t14409, 14410, 14411, 14412, 14413, 14414, 14415, 14416, \n\t14417, 14418, 14419, 14420, 14421, 14422, 14423, 14424, \n\t14425, 14426, 14427, 14428, 14429, 14430, 14431, 14432, \n\t14433, 14434, 14435, 14436, 14437, 14438, 14439, 14440, \n\t14441, 14441, 14442, 14443, 14444, 14445, 14446, 14447, \n\t14448, 14449, 14450, 14451, 14452, 14453, 14454, 14455, \n\t14456, 14457, 14458, 14459, 14460, 14461, 14462, 14463, \n\t14464, 14465, 14466, 14467, 14468, 14469, 14470, 14471, \n\t14472, 14473, 14474, 14475, 14476, 14477, 14478, 14479, \n\t14480, 14481, 14481, 14482, 14483, 14484, 14485, 14486, \n\t14487, 14488, 14489, 14490, 14491, 14492, 14493, 14494, \n\t14495, 14496, 14497, 14498, 14499, 14500, 14501, 14502, \n\t14503, 14504, 14505, 14506, 14507, 14508, 14509, 14510, \n\t14511, 14512, 14513, 14514, 14515, 14516, 14517, 14518, \n\t14519, 14520, 14520, 14521, 14522, 14523, 14524, 14525, \n\t14526, 14527, 14528, 14529, 14530, 14531, 14532, 14533, \n\t14534, 14535, 14536, 14537, 14538, 14539, 14540, 14541, \n\t14542, 14543, 14544, 14545, 14546, 14547, 14548, 14549, \n\t14550, 14551, 14552, 14553, 14554, 14555, 14556, 14557, \n\t14558, 14559, 14559, 14560, 14561, 14562, 14563, 14564, \n\t14565, 14566, 14567, 14568, 14569, 14570, 14571, 14572, \n\t14573, 14574, 14575, 14576, 14577, 14578, 14579, 14580, \n\t14581, 14582, 14583, 14584, 14585, 14586, 14587, 14588, \n\t14589, 14590, 14591, 14592, 14593, 14594, 14595, 14596, \n\t14597, 14598, 14598, 14599, 14600, 14601, 14602, 14603, \n\t14604, 14605, 14606, 14607, 14608, 14609, 14610, 14611, \n\t14612, 14613, 14614, 14615, 14616, 14617, 14618, 14619, \n\t14620, 14621, 14622, 14623, 14624, 14625, 14626, 14627, \n\t14628, 14629, 14630, 14631, 14632, 14633, 14634, 14635, \n\t14636, 14637, 14637, 14638, 14639, 14640, 14641, 14642, \n\t14643, 14644, 14645, 14646, 14647, 14648, 14649, 14650, \n\t14651, 14652, 14653, 14654, 14655, 14656, 14657, 14658, \n\t14659, 14660, 14661, 14662, 14663, 14664, 14665, 14666, \n\t14667, 14668, 14669, 14670, 14671, 14672, 14673, 14674, \n\t14675, 14675, 14676, 14677, 14678, 14679, 14680, 14681, \n\t14682, 14683, 14684, 14685, 14686, 14687, 14688, 14689, \n\t14690, 14691, 14692, 14693, 14694, 14695, 14696, 14697, \n\t14698, 14699, 14700, 14701, 14702, 14703, 14704, 14705, \n\t14706, 14707, 14708, 14709, 14710, 14711, 14712, 14713, \n\t14714, 14714, 14715, 14716, 14717, 14718, 14719, 14720, \n\t14721, 14722, 14723, 14724, 14725, 14726, 14727, 14728, \n\t14729, 14730, 14731, 14732, 14733, 14734, 14735, 14736, \n\t14737, 14738, 14739, 14740, 14741, 14742, 14743, 14744, \n\t14745, 14746, 14747, 14748, 14749, 14750, 14751, 14752, \n\t14752, 14753, 14754, 14755, 14756, 14757, 14758, 14759, \n\t14760, 14761, 14762, 14763, 14764, 14765, 14766, 14767, \n\t14768, 14769, 14770, 14771, 14772, 14773, 14774, 14775, \n\t14776, 14777, 14778, 14779, 14780, 14781, 14782, 14783, \n\t14784, 14785, 14786, 14787, 14788, 14789, 14790, 14790, \n\t14791, 14792, 14793, 14794, 14795, 14796, 14797, 14798, \n\t14799, 14800, 14801, 14802, 14803, 14804, 14805, 14806, \n\t14807, 14808, 14809, 14810, 14811, 14812, 14813, 14814, \n\t14815, 14816, 14817, 14818, 14819, 14820, 14821, 14822, \n\t14823, 14824, 14825, 14826, 14827, 14827, 14828, 14829, \n\t14830, 14831, 14832, 14833, 14834, 14835, 14836, 14837, \n\t14838, 14839, 14840, 14841, 14842, 14843, 14844, 14845, \n\t14846, 14847, 14848, 14849, 14850, 14851, 14852, 14853, \n\t14854, 14855, 14856, 14857, 14858, 14859, 14860, 14861, \n\t14862, 14863, 14864, 14865, 14865, 14866, 14867, 14868, \n\t14869, 14870, 14871, 14872, 14873, 14874, 14875, 14876, \n\t14877, 14878, 14879, 14880, 14881, 14882, 14883, 14884, \n\t14885, 14886, 14887, 14888, 14889, 14890, 14891, 14892, \n\t14893, 14894, 14895, 14896, 14897, 14898, 14899, 14900, \n\t14901, 14902, 14902, 14903, 14904, 14905, 14906, 14907, \n\t14908, 14909, 14910, 14911, 14912, 14913, 14914, 14915, \n\t14916, 14917, 14918, 14919, 14920, 14921, 14922, 14923, \n\t14924, 14925, 14926, 14927, 14928, 14929, 14930, 14931, \n\t14932, 14933, 14934, 14935, 14936, 14937, 14938, 14939, \n\t14939, 14940, 14941, 14942, 14943, 14944, 14945, 14946, \n\t14947, 14948, 14949, 14950, 14951, 14952, 14953, 14954, \n\t14955, 14956, 14957, 14958, 14959, 14960, 14961, 14962, \n\t14963, 14964, 14965, 14966, 14967, 14968, 14969, 14970, \n\t14971, 14972, 14973, 14974, 14975, 14976, 14976, 14977, \n\t14978, 14979, 14980, 14981, 14982, 14983, 14984, 14985, \n\t14986, 14987, 14988, 14989, 14990, 14991, 14992, 14993, \n\t14994, 14995, 14996, 14997, 14998, 14999, 15000, 15001, \n\t15002, 15003, 15004, 15005, 15006, 15007, 15008, 15009, \n\t15010, 15011, 15012, 15013, 15013, 15014, 15015, 15016, \n\t15017, 15018, 15019, 15020, 15021, 15022, 15023, 15024, \n\t15025, 15026, 15027, 15028, 15029, 15030, 15031, 15032, \n\t15033, 15034, 15035, 15036, 15037, 15038, 15039, 15040, \n\t15041, 15042, 15043, 15044, 15045, 15046, 15047, 15048, \n\t15049, 15049, 15050, 15051, 15052, 15053, 15054, 15055, \n\t15056, 15057, 15058, 15059, 15060, 15061, 15062, 15063, \n\t15064, 15065, 15066, 15067, 15068, 15069, 15070, 15071, \n\t15072, 15073, 15074, 15075, 15076, 15077, 15078, 15079, \n\t15080, 15081, 15082, 15083, 15084, 15085, 15086, 15086, \n\t15087, 15088, 15089, 15090, 15091, 15092, 15093, 15094, \n\t15095, 15096, 15097, 15098, 15099, 15100, 15101, 15102, \n\t15103, 15104, 15105, 15106, 15107, 15108, 15109, 15110, \n\t15111, 15112, 15113, 15114, 15115, 15116, 15117, 15118, \n\t15119, 15120, 15121, 15122, 15122, 15123, 15124, 15125, \n\t15126, 15127, 15128, 15129, 15130, 15131, 15132, 15133, \n\t15134, 15135, 15136, 15137, 15138, 15139, 15140, 15141, \n\t15142, 15143, 15144, 15145, 15146, 15147, 15148, 15149, \n\t15150, 15151, 15152, 15153, 15154, 15155, 15156, 15157, \n\t15158, 15158, 15159, 15160, 15161, 15162, 15163, 15164, \n\t15165, 15166, 15167, 15168, 15169, 15170, 15171, 15172, \n\t15173, 15174, 15175, 15176, 15177, 15178, 15179, 15180, \n\t15181, 15182, 15183, 15184, 15185, 15186, 15187, 15188, \n\t15189, 15190, 15191, 15192, 15193, 15193, 15194, 15195, \n\t15196, 15197, 15198, 15199, 15200, 15201, 15202, 15203, \n\t15204, 15205, 15206, 15207, 15208, 15209, 15210, 15211, \n\t15212, 15213, 15214, 15215, 15216, 15217, 15218, 15219, \n\t15220, 15221, 15222, 15223, 15224, 15225, 15226, 15227, \n\t15228, 15229, 15229, 15230, 15231, 15232, 15233, 15234, \n\t15235, 15236, 15237, 15238, 15239, 15240, 15241, 15242, \n\t15243, 15244, 15245, 15246, 15247, 15248, 15249, 15250, \n\t15251, 15252, 15253, 15254, 15255, 15256, 15257, 15258, \n\t15259, 15260, 15261, 15262, 15263, 15264, 15264, 15265, \n\t15266, 15267, 15268, 15269, 15270, 15271, 15272, 15273, \n\t15274, 15275, 15276, 15277, 15278, 15279, 15280, 15281, \n\t15282, 15283, 15284, 15285, 15286, 15287, 15288, 15289, \n\t15290, 15291, 15292, 15293, 15294, 15295, 15296, 15297, \n\t15298, 15299, 15300, 15300, 15301, 15302, 15303, 15304, \n\t15305, 15306, 15307, 15308, 15309, 15310, 15311, 15312, \n\t15313, 15314, 15315, 15316, 15317, 15318, 15319, 15320, \n\t15321, 15322, 15323, 15324, 15325, 15326, 15327, 15328, \n\t15329, 15330, 15331, 15332, 15333, 15334, 15335, 15335, \n\t15336, 15337, 15338, 15339, 15340, 15341, 15342, 15343, \n\t15344, 15345, 15346, 15347, 15348, 15349, 15350, 15351, \n\t15352, 15353, 15354, 15355, 15356, 15357, 15358, 15359, \n\t15360, 15361, 15362, 15363, 15364, 15365, 15366, 15367, \n\t15368, 15369, 15370, 15370, 15371, 15372, 15373, 15374, \n\t15375, 15376, 15377, 15378, 15379, 15380, 15381, 15382, \n\t15383, 15384, 15385, 15386, 15387, 15388, 15389, 15390, \n\t15391, 15392, 15393, 15394, 15395, 15396, 15397, 15398, \n\t15399, 15400, 15401, 15402, 15403, 15404, 15405, 15405, \n\t15406, 15407, 15408, 15409, 15410, 15411, 15412, 15413, \n\t15414, 15415, 15416, 15417, 15418, 15419, 15420, 15421, \n\t15422, 15423, 15424, 15425, 15426, 15427, 15428, 15429, \n\t15430, 15431, 15432, 15433, 15434, 15435, 15436, 15437, \n\t15438, 15439, 15439, 15440, 15441, 15442, 15443, 15444, \n\t15445, 15446, 15447, 15448, 15449, 15450, 15451, 15452, \n\t15453, 15454, 15455, 15456, 15457, 15458, 15459, 15460, \n\t15461, 15462, 15463, 15464, 15465, 15466, 15467, 15468, \n\t15469, 15470, 15471, 15472, 15473, 15474, 15474, 15475, \n\t15476, 15477, 15478, 15479, 15480, 15481, 15482, 15483, \n\t15484, 15485, 15486, 15487, 15488, 15489, 15490, 15491, \n\t15492, 15493, 15494, 15495, 15496, 15497, 15498, 15499, \n\t15500, 15501, 15502, 15503, 15504, 15505, 15506, 15507, \n\t15508, 15508, 15509, 15510, 15511, 15512, 15513, 15514, \n\t15515, 15516, 15517, 15518, 15519, 15520, 15521, 15522, \n\t15523, 15524, 15525, 15526, 15527, 15528, 15529, 15530, \n\t15531, 15532, 15533, 15534, 15535, 15536, 15537, 15538, \n\t15539, 15540, 15541, 15542, 15542, 15543, 15544, 15545, \n\t15546, 15547, 15548, 15549, 15550, 15551, 15552, 15553, \n\t15554, 15555, 15556, 15557, 15558, 15559, 15560, 15561, \n\t15562, 15563, 15564, 15565, 15566, 15567, 15568, 15569, \n\t15570, 15571, 15572, 15573, 15574, 15575, 15576, 15576, \n\t15577, 15578, 15579, 15580, 15581, 15582, 15583, 15584, \n\t15585, 15586, 15587, 15588, 15589, 15590, 15591, 15592, \n\t15593, 15594, 15595, 15596, 15597, 15598, 15599, 15600, \n\t15601, 15602, 15603, 15604, 15605, 15606, 15607, 15608, \n\t15609, 15610, 15610, 15611, 15612, 15613, 15614, 15615, \n\t15616, 15617, 15618, 15619, 15620, 15621, 15622, 15623, \n\t15624, 15625, 15626, 15627, 15628, 15629, 15630, 15631, \n\t15632, 15633, 15634, 15635, 15636, 15637, 15638, 15639, \n\t15640, 15641, 15642, 15643, 15644, 15644, 15645, 15646, \n\t15647, 15648, 15649, 15650, 15651, 15652, 15653, 15654, \n\t15655, 15656, 15657, 15658, 15659, 15660, 15661, 15662, \n\t15663, 15664, 15665, 15666, 15667, 15668, 15669, 15670, \n\t15671, 15672, 15673, 15674, 15675, 15676, 15677, 15677, \n\t15678, 15679, 15680, 15681, 15682, 15683, 15684, 15685, \n\t15686, 15687, 15688, 15689, 15690, 15691, 15692, 15693, \n\t15694, 15695, 15696, 15697, 15698, 15699, 15700, 15701, \n\t15702, 15703, 15704, 15705, 15706, 15707, 15708, 15709, \n\t15710, 15710, 15711, 15712, 15713, 15714, 15715, 15716, \n\t15717, 15718, 15719, 15720, 15721, 15722, 15723, 15724, \n\t15725, 15726, 15727, 15728, 15729, 15730, 15731, 15732, \n\t15733, 15734, 15735, 15736, 15737, 15738, 15739, 15740, \n\t15741, 15742, 15743, 15744, 15744, 15745, 15746, 15747, \n\t15748, 15749, 15750, 15751, 15752, 15753, 15754, 15755, \n\t15756, 15757, 15758, 15759, 15760, 15761, 15762, 15763, \n\t15764, 15765, 15766, 15767, 15768, 15769, 15770, 15771, \n\t15772, 15773, 15774, 15775, 15776, 15777, 15777, 15778, \n\t15779, 15780, 15781, 15782, 15783, 15784, 15785, 15786, \n\t15787, 15788, 15789, 15790, 15791, 15792, 15793, 15794, \n\t15795, 15796, 15797, 15798, 15799, 15800, 15801, 15802, \n\t15803, 15804, 15805, 15806, 15807, 15808, 15809, 15810, \n\t15810, 15811, 15812, 15813, 15814, 15815, 15816, 15817, \n\t15818, 15819, 15820, 15821, 15822, 15823, 15824, 15825, \n\t15826, 15827, 15828, 15829, 15830, 15831, 15832, 15833, \n\t15834, 15835, 15836, 15837, 15838, 15839, 15840, 15841, \n\t15842, 15842, 15843, 15844, 15845, 15846, 15847, 15848, \n\t15849, 15850, 15851, 15852, 15853, 15854, 15855, 15856, \n\t15857, 15858, 15859, 15860, 15861, 15862, 15863, 15864, \n\t15865, 15866, 15867, 15868, 15869, 15870, 15871, 15872, \n\t15873, 15874, 15875, 15875, 15876, 15877, 15878, 15879, \n\t15880, 15881, 15882, 15883, 15884, 15885, 15886, 15887, \n\t15888, 15889, 15890, 15891, 15892, 15893, 15894, 15895, \n\t15896, 15897, 15898, 15899, 15900, 15901, 15902, 15903, \n\t15904, 15905, 15906, 15907, 15908, 15908, 15909, 15910, \n\t15911, 15912, 15913, 15914, 15915, 15916, 15917, 15918, \n\t15919, 15920, 15921, 15922, 15923, 15924, 15925, 15926, \n\t15927, 15928, 15929, 15930, 15931, 15932, 15933, 15934, \n\t15935, 15936, 15937, 15938, 15939, 15940, 15940, 15941, \n\t15942, 15943, 15944, 15945, 15946, 15947, 15948, 15949, \n\t15950, 15951, 15952, 15953, 15954, 15955, 15956, 15957, \n\t15958, 15959, 15960, 15961, 15962, 15963, 15964, 15965, \n\t15966, 15967, 15968, 15969, 15970, 15971, 15972, 15972, \n\t15973, 15974, 15975, 15976, 15977, 15978, 15979, 15980, \n\t15981, 15982, 15983, 15984, 15985, 15986, 15987, 15988, \n\t15989, 15990, 15991, 15992, 15993, 15994, 15995, 15996, \n\t15997, 15998, 15999, 16000, 16001, 16002, 16003, 16004, \n\t16004, 16005, 16006, 16007, 16008, 16009, 16010, 16011, \n\t16012, 16013, 16014, 16015, 16016, 16017, 16018, 16019, \n\t16020, 16021, 16022, 16023, 16024, 16025, 16026, 16027, \n\t16028, 16029, 16030, 16031, 16032, 16033, 16034, 16035, \n\t16036, 16036, 16037, 16038, 16039, 16040, 16041, 16042, \n\t16043, 16044, 16045, 16046, 16047, 16048, 16049, 16050, \n\t16051, 16052, 16053, 16054, 16055, 16056, 16057, 16058, \n\t16059, 16060, 16061, 16062, 16063, 16064, 16065, 16066, \n\t16067, 16068, 16068, 16069, 16070, 16071, 16072, 16073, \n\t16074, 16075, 16076, 16077, 16078, 16079, 16080, 16081, \n\t16082, 16083, 16084, 16085, 16086, 16087, 16088, 16089, \n\t16090, 16091, 16092, 16093, 16094, 16095, 16096, 16097, \n\t16098, 16099, 16100, 16100, 16101, 16102, 16103, 16104, \n\t16105, 16106, 16107, 16108, 16109, 16110, 16111, 16112, \n\t16113, 16114, 16115, 16116, 16117, 16118, 16119, 16120, \n\t16121, 16122, 16123, 16124, 16125, 16126, 16127, 16128, \n\t16129, 16130, 16131, 16131, 16132, 16133, 16134, 16135, \n\t16136, 16137, 16138, 16139, 16140, 16141, 16142, 16143, \n\t16144, 16145, 16146, 16147, 16148, 16149, 16150, 16151, \n\t16152, 16153, 16154, 16155, 16156, 16157, 16158, 16159, \n\t16160, 16161, 16162, 16163, 16163, 16164, 16165, 16166, \n\t16167, 16168, 16169, 16170, 16171, 16172, 16173, 16174, \n\t16175, 16176, 16177, 16178, 16179, 16180, 16181, 16182, \n\t16183, 16184, 16185, 16186, 16187, 16188, 16189, 16190, \n\t16191, 16192, 16193, 16194, 16194, 16195, 16196, 16197, \n\t16198, 16199, 16200, 16201, 16202, 16203, 16204, 16205, \n\t16206, 16207, 16208, 16209, 16210, 16211, 16212, 16213, \n\t16214, 16215, 16216, 16217, 16218, 16219, 16220, 16221, \n\t16222, 16223, 16224, 16225, 16225, 16226, 16227, 16228, \n\t16229, 16230, 16231, 16232, 16233, 16234, 16235, 16236, \n\t16237, 16238, 16239, 16240, 16241, 16242, 16243, 16244, \n\t16245, 16246, 16247, 16248, 16249, 16250, 16251, 16252, \n\t16253, 16254, 16255, 16256, 16256, 16257, 16258, 16259, \n\t16260, 16261, 16262, 16263, 16264, 16265, 16266, 16267, \n\t16268, 16269, 16270, 16271, 16272, 16273, 16274, 16275, \n\t16276, 16277, 16278, 16279, 16280, 16281, 16282, 16283, \n\t16284, 16285, 16286, 16287, 16287, 16288, 16289, 16290, \n\t16291, 16292, 16293, 16294, 16295, 16296, 16297, 16298, \n\t16299, 16300, 16301, 16302, 16303, 16304, 16305, 16306, \n\t16307, 16308, 16309, 16310, 16311, 16312, 16313, 16314, \n\t16315, 16316, 16317, 16318, 16318, 16319, 16320, 16321, \n\t16322, 16323, 16324, 16325, 16326, 16327, 16328, 16329, \n\t16330, 16331, 16332, 16333, 16334, 16335, 16336, 16337, \n\t16338, 16339, 16340, 16341, 16342, 16343, 16344, 16345, \n\t16346, 16347, 16348, 16349, 16349, 16350, 16351, 16352, \n\t16353, 16354, 16355, 16356, 16357, 16358, 16359, 16360, \n\t16361, 16362, 16363, 16364, 16365, 16366, 16367, 16368, \n\t16369, 16370, 16371, 16372, 16373, 16374, 16375, 16376, \n\t16377, 16378, 16379, 16379, 16380, 16381, 16382, 16383, \n\t16384, 16385, 16386, 16387, 16388, 16389, 16390, 16391, \n\t16392, 16393, 16394, 16395, 16396, 16397, 16398, 16399, \n\t16400, 16401, 16402, 16403, 16404, 16405, 16406, 16407, \n\t16408, 16409, 16410, 16410, 16411, 16412, 16413, 16414, \n\t16415, 16416, 16417, 16418, 16419, 16420, 16421, 16422, \n\t16423, 16424, 16425, 16426, 16427, 16428, 16429, 16430, \n\t16431, 16432, 16433, 16434, 16435, 16436, 16437, 16438, \n\t16439, 16440, 16440, 16441, 16442, 16443, 16444, 16445, \n\t16446, 16447, 16448, 16449, 16450, 16451, 16452, 16453, \n\t16454, 16455, 16456, 16457, 16458, 16459, 16460, 16461, \n\t16462, 16463, 16464, 16465, 16466, 16467, 16468, 16469, \n\t16470, 16470, 16471, 16472, 16473, 16474, 16475, 16476, \n\t16477, 16478, 16479, 16480, 16481, 16482, 16483, 16484, \n\t16485, 16486, 16487, 16488, 16489, 16490, 16491, 16492, \n\t16493, 16494, 16495, 16496, 16497, 16498, 16499, 16500, \n\t16500, 16501, 16502, 16503, 16504, 16505, 16506, 16507, \n\t16508, 16509, 16510, 16511, 16512, 16513, 16514, 16515, \n\t16516, 16517, 16518, 16519, 16520, 16521, 16522, 16523, \n\t16524, 16525, 16526, 16527, 16528, 16529, 16530, 16530, \n\t16531, 16532, 16533, 16534, 16535, 16536, 16537, 16538, \n\t16539, 16540, 16541, 16542, 16543, 16544, 16545, 16546, \n\t16547, 16548, 16549, 16550, 16551, 16552, 16553, 16554, \n\t16555, 16556, 16557, 16558, 16559, 16560, 16560, 16561, \n\t16562, 16563, 16564, 16565, 16566, 16567, 16568, 16569, \n\t16570, 16571, 16572, 16573, 16574, 16575, 16576, 16577, \n\t16578, 16579, 16580, 16581, 16582, 16583, 16584, 16585, \n\t16586, 16587, 16588, 16589, 16590, 16590, 16591, 16592, \n\t16593, 16594, 16595, 16596, 16597, 16598, 16599, 16600, \n\t16601, 16602, 16603, 16604, 16605, 16606, 16607, 16608, \n\t16609, 16610, 16611, 16612, 16613, 16614, 16615, 16616, \n\t16617, 16618, 16619, 16620, 16620, 16621, 16622, 16623, \n\t16624, 16625, 16626, 16627, 16628, 16629, 16630, 16631, \n\t16632, 16633, 16634, 16635, 16636, 16637, 16638, 16639, \n\t16640, 16641, 16642, 16643, 16644, 16645, 16646, 16647, \n\t16648, 16649, 16649, 16650, 16651, 16652, 16653, 16654, \n\t16655, 16656, 16657, 16658, 16659, 16660, 16661, 16662, \n\t16663, 16664, 16665, 16666, 16667, 16668, 16669, 16670, \n\t16671, 16672, 16673, 16674, 16675, 16676, 16677, 16678, \n\t16679, 16679, 16680, 16681, 16682, 16683, 16684, 16685, \n\t16686, 16687, 16688, 16689, 16690, 16691, 16692, 16693, \n\t16694, 16695, 16696, 16697, 16698, 16699, 16700, 16701, \n\t16702, 16703, 16704, 16705, 16706, 16707, 16708, 16708, \n\t16709, 16710, 16711, 16712, 16713, 16714, 16715, 16716, \n\t16717, 16718, 16719, 16720, 16721, 16722, 16723, 16724, \n\t16725, 16726, 16727, 16728, 16729, 16730, 16731, 16732, \n\t16733, 16734, 16735, 16736, 16737, 16737, 16738, 16739, \n\t16740, 16741, 16742, 16743, 16744, 16745, 16746, 16747, \n\t16748, 16749, 16750, 16751, 16752, 16753, 16754, 16755, \n\t16756, 16757, 16758, 16759, 16760, 16761, 16762, 16763, \n\t16764, 16765, 16766, 16766, 16767, 16768, 16769, 16770, \n\t16771, 16772, 16773, 16774, 16775, 16776, 16777, 16778, \n\t16779, 16780, 16781, 16782, 16783, 16784, 16785, 16786, \n\t16787, 16788, 16789, 16790, 16791, 16792, 16793, 16794, \n\t16795, 16795, 16796, 16797, 16798, 16799, 16800, 16801, \n\t16802, 16803, 16804, 16805, 16806, 16807, 16808, 16809, \n\t16810, 16811, 16812, 16813, 16814, 16815, 16816, 16817, \n\t16818, 16819, 16820, 16821, 16822, 16823, 16824, 16824, \n\t16825, 16826, 16827, 16828, 16829, 16830, 16831, 16832, \n\t16833, 16834, 16835, 16836, 16837, 16838, 16839, 16840, \n\t16841, 16842, 16843, 16844, 16845, 16846, 16847, 16848, \n\t16849, 16850, 16851, 16852, 16853, 16853, 16854, 16855, \n\t16856, 16857, 16858, 16859, 16860, 16861, 16862, 16863, \n\t16864, 16865, 16866, 16867, 16868, 16869, 16870, 16871, \n\t16872, 16873, 16874, 16875, 16876, 16877, 16878, 16879, \n\t16880, 16881, 16882, 16882, 16883, 16884, 16885, 16886, \n\t16887, 16888, 16889, 16890, 16891, 16892, 16893, 16894, \n\t16895, 16896, 16897, 16898, 16899, 16900, 16901, 16902, \n\t16903, 16904, 16905, 16906, 16907, 16908, 16909, 16910, \n\t16910, 16911, 16912, 16913, 16914, 16915, 16916, 16917, \n\t16918, 16919, 16920, 16921, 16922, 16923, 16924, 16925, \n\t16926, 16927, 16928, 16929, 16930, 16931, 16932, 16933, \n\t16934, 16935, 16936, 16937, 16938, 16939, 16939, 16940, \n\t16941, 16942, 16943, 16944, 16945, 16946, 16947, 16948, \n\t16949, 16950, 16951, 16952, 16953, 16954, 16955, 16956, \n\t16957, 16958, 16959, 16960, 16961, 16962, 16963, 16964, \n\t16965, 16966, 16967, 16967, 16968, 16969, 16970, 16971, \n\t16972, 16973, 16974, 16975, 16976, 16977, 16978, 16979, \n\t16980, 16981, 16982, 16983, 16984, 16985, 16986, 16987, \n\t16988, 16989, 16990, 16991, 16992, 16993, 16994, 16995, \n\t16995, 16996, 16997, 16998, 16999, 17000, 17001, 17002, \n\t17003, 17004, 17005, 17006, 17007, 17008, 17009, 17010, \n\t17011, 17012, 17013, 17014, 17015, 17016, 17017, 17018, \n\t17019, 17020, 17021, 17022, 17023, 17024, 17024, 17025, \n\t17026, 17027, 17028, 17029, 17030, 17031, 17032, 17033, \n\t17034, 17035, 17036, 17037, 17038, 17039, 17040, 17041, \n\t17042, 17043, 17044, 17045, 17046, 17047, 17048, 17049, \n\t17050, 17051, 17052, 17052, 17053, 17054, 17055, 17056, \n\t17057, 17058, 17059, 17060, 17061, 17062, 17063, 17064, \n\t17065, 17066, 17067, 17068, 17069, 17070, 17071, 17072, \n\t17073, 17074, 17075, 17076, 17077, 17078, 17079, 17080, \n\t17080, 17081, 17082, 17083, 17084, 17085, 17086, 17087, \n\t17088, 17089, 17090, 17091, 17092, 17093, 17094, 17095, \n\t17096, 17097, 17098, 17099, 17100, 17101, 17102, 17103, \n\t17104, 17105, 17106, 17107, 17107, 17108, 17109, 17110, \n\t17111, 17112, 17113, 17114, 17115, 17116, 17117, 17118, \n\t17119, 17120, 17121, 17122, 17123, 17124, 17125, 17126, \n\t17127, 17128, 17129, 17130, 17131, 17132, 17133, 17134, \n\t17135, 17135, 17136, 17137, 17138, 17139, 17140, 17141, \n\t17142, 17143, 17144, 17145, 17146, 17147, 17148, 17149, \n\t17150, 17151, 17152, 17153, 17154, 17155, 17156, 17157, \n\t17158, 17159, 17160, 17161, 17162, 17163, 17163, 17164, \n\t17165, 17166, 17167, 17168, 17169, 17170, 17171, 17172, \n\t17173, 17174, 17175, 17176, 17177, 17178, 17179, 17180, \n\t17181, 17182, 17183, 17184, 17185, 17186, 17187, 17188, \n\t17189, 17190, 17191, 17191, 17192, 17193, 17194, 17195, \n\t17196, 17197, 17198, 17199, 17200, 17201, 17202, 17203, \n\t17204, 17205, 17206, 17207, 17208, 17209, 17210, 17211, \n\t17212, 17213, 17214, 17215, 17216, 17217, 17218, 17218, \n\t17219, 17220, 17221, 17222, 17223, 17224, 17225, 17226, \n\t17227, 17228, 17229, 17230, 17231, 17232, 17233, 17234, \n\t17235, 17236, 17237, 17238, 17239, 17240, 17241, 17242, \n\t17243, 17244, 17245, 17246, 17246, 17247, 17248, 17249, \n\t17250, 17251, 17252, 17253, 17254, 17255, 17256, 17257, \n\t17258, 17259, 17260, 17261, 17262, 17263, 17264, 17265, \n\t17266, 17267, 17268, 17269, 17270, 17271, 17272, 17273, \n\t17273, 17274, 17275, 17276, 17277, 17278, 17279, 17280, \n\t17281, 17282, 17283, 17284, 17285, 17286, 17287, 17288, \n\t17289, 17290, 17291, 17292, 17293, 17294, 17295, 17296, \n\t17297, 17298, 17299, 17300, 17300, 17301, 17302, 17303, \n\t17304, 17305, 17306, 17307, 17308, 17309, 17310, 17311, \n\t17312, 17313, 17314, 17315, 17316, 17317, 17318, 17319, \n\t17320, 17321, 17322, 17323, 17324, 17325, 17326, 17327, \n\t17327, 17328, 17329, 17330, 17331, 17332, 17333, 17334, \n\t17335, 17336, 17337, 17338, 17339, 17340, 17341, 17342, \n\t17343, 17344, 17345, 17346, 17347, 17348, 17349, 17350, \n\t17351, 17352, 17353, 17354, 17354, 17355, 17356, 17357, \n\t17358, 17359, 17360, 17361, 17362, 17363, 17364, 17365, \n\t17366, 17367, 17368, 17369, 17370, 17371, 17372, 17373, \n\t17374, 17375, 17376, 17377, 17378, 17379, 17380, 17381, \n\t17381, 17382, 17383, 17384, 17385, 17386, 17387, 17388, \n\t17389, 17390, 17391, 17392, 17393, 17394, 17395, 17396, \n\t17397, 17398, 17399, 17400, 17401, 17402, 17403, 17404, \n\t17405, 17406, 17407, 17408, 17408, 17409, 17410, 17411, \n\t17412, 17413, 17414, 17415, 17416, 17417, 17418, 17419, \n\t17420, 17421, 17422, 17423, 17424, 17425, 17426, 17427, \n\t17428, 17429, 17430, 17431, 17432, 17433, 17434, 17435, \n\t17435, 17436, 17437, 17438, 17439, 17440, 17441, 17442, \n\t17443, 17444, 17445, 17446, 17447, 17448, 17449, 17450, \n\t17451, 17452, 17453, 17454, 17455, 17456, 17457, 17458, \n\t17459, 17460, 17461, 17462, 17462, 17463, 17464, 17465, \n\t17466, 17467, 17468, 17469, 17470, 17471, 17472, 17473, \n\t17474, 17475, 17476, 17477, 17478, 17479, 17480, 17481, \n\t17482, 17483, 17484, 17485, 17486, 17487, 17488, 17488, \n\t17489, 17490, 17491, 17492, 17493, 17494, 17495, 17496, \n\t17497, 17498, 17499, 17500, 17501, 17502, 17503, 17504, \n\t17505, 17506, 17507, 17508, 17509, 17510, 17511, 17512, \n\t17513, 17514, 17515, 17515, 17516, 17517, 17518, 17519, \n\t17520, 17521, 17522, 17523, 17524, 17525, 17526, 17527, \n\t17528, 17529, 17530, 17531, 17532, 17533, 17534, 17535, \n\t17536, 17537, 17538, 17539, 17540, 17541, 17541, 17542, \n\t17543, 17544, 17545, 17546, 17547, 17548, 17549, 17550, \n\t17551, 17552, 17553, 17554, 17555, 17556, 17557, 17558, \n\t17559, 17560, 17561, 17562, 17563, 17564, 17565, 17566, \n\t17567, 17568, 17568, 17569, 17570, 17571, 17572, 17573, \n\t17574, 17575, 17576, 17577, 17578, 17579, 17580, 17581, \n\t17582, 17583, 17584, 17585, 17586, 17587, 17588, 17589, \n\t17590, 17591, 17592, 17593, 17594, 17594, 17595, 17596, \n\t17597, 17598, 17599, 17600, 17601, 17602, 17603, 17604, \n\t17605, 17606, 17607, 17608, 17609, 17610, 17611, 17612, \n\t17613, 17614, 17615, 17616, 17617, 17618, 17619, 17620, \n\t17620, 17621, 17622, 17623, 17624, 17625, 17626, 17627, \n\t17628, 17629, 17630, 17631, 17632, 17633, 17634, 17635, \n\t17636, 17637, 17638, 17639, 17640, 17641, 17642, 17643, \n\t17644, 17645, 17646, 17646, 17647, 17648, 17649, 17650, \n\t17651, 17652, 17653, 17654, 17655, 17656, 17657, 17658, \n\t17659, 17660, 17661, 17662, 17663, 17664, 17665, 17666, \n\t17667, 17668, 17669, 17670, 17671, 17672, 17672, 17673, \n\t17674, 17675, 17676, 17677, 17678, 17679, 17680, 17681, \n\t17682, 17683, 17684, 17685, 17686, 17687, 17688, 17689, \n\t17690, 17691, 17692, 17693, 17694, 17695, 17696, 17697, \n\t17698, 17698, 17699, 17700, 17701, 17702, 17703, 17704, \n\t17705, 17706, 17707, 17708, 17709, 17710, 17711, 17712, \n\t17713, 17714, 17715, 17716, 17717, 17718, 17719, 17720, \n\t17721, 17722, 17723, 17724, 17724, 17725, 17726, 17727, \n\t17728, 17729, 17730, 17731, 17732, 17733, 17734, 17735, \n\t17736, 17737, 17738, 17739, 17740, 17741, 17742, 17743, \n\t17744, 17745, 17746, 17747, 17748, 17749, 17750, 17750, \n\t17751, 17752, 17753, 17754, 17755, 17756, 17757, 17758, \n\t17759, 17760, 17761, 17762, 17763, 17764, 17765, 17766, \n\t17767, 17768, 17769, 17770, 17771, 17772, 17773, 17774, \n\t17775, 17776, 17776, 17777, 17778, 17779, 17780, 17781, \n\t17782, 17783, 17784, 17785, 17786, 17787, 17788, 17789, \n\t17790, 17791, 17792, 17793, 17794, 17795, 17796, 17797, \n\t17798, 17799, 17800, 17801, 17801, 17802, 17803, 17804, \n\t17805, 17806, 17807, 17808, 17809, 17810, 17811, 17812, \n\t17813, 17814, 17815, 17816, 17817, 17818, 17819, 17820, \n\t17821, 17822, 17823, 17824, 17825, 17826, 17827, 17827, \n\t17828, 17829, 17830, 17831, 17832, 17833, 17834, 17835, \n\t17836, 17837, 17838, 17839, 17840, 17841, 17842, 17843, \n\t17844, 17845, 17846, 17847, 17848, 17849, 17850, 17851, \n\t17852, 17852, 17853, 17854, 17855, 17856, 17857, 17858, \n\t17859, 17860, 17861, 17862, 17863, 17864, 17865, 17866, \n\t17867, 17868, 17869, 17870, 17871, 17872, 17873, 17874, \n\t17875, 17876, 17877, 17878, 17878, 17879, 17880, 17881, \n\t17882, 17883, 17884, 17885, 17886, 17887, 17888, 17889, \n\t17890, 17891, 17892, 17893, 17894, 17895, 17896, 17897, \n\t17898, 17899, 17900, 17901, 17902, 17903, 17903, 17904, \n\t17905, 17906, 17907, 17908, 17909, 17910, 17911, 17912, \n\t17913, 17914, 17915, 17916, 17917, 17918, 17919, 17920, \n\t17921, 17922, 17923, 17924, 17925, 17926, 17927, 17928, \n\t17928, 17929, 17930, 17931, 17932, 17933, 17934, 17935, \n\t17936, 17937, 17938, 17939, 17940, 17941, 17942, 17943, \n\t17944, 17945, 17946, 17947, 17948, 17949, 17950, 17951, \n\t17952, 17953, 17953, 17954, 17955, 17956, 17957, 17958, \n\t17959, 17960, 17961, 17962, 17963, 17964, 17965, 17966, \n\t17967, 17968, 17969, 17970, 17971, 17972, 17973, 17974, \n\t17975, 17976, 17977, 17978, 17979, 17979, 17980, 17981, \n\t17982, 17983, 17984, 17985, 17986, 17987, 17988, 17989, \n\t17990, 17991, 17992, 17993, 17994, 17995, 17996, 17997, \n\t17998, 17999, 18000, 18001, 18002, 18003, 18004, 18004, \n\t18005, 18006, 18007, 18008, 18009, 18010, 18011, 18012, \n\t18013, 18014, 18015, 18016, 18017, 18018, 18019, 18020, \n\t18021, 18022, 18023, 18024, 18025, 18026, 18027, 18028, \n\t18029, 18029, 18030, 18031, 18032, 18033, 18034, 18035, \n\t18036, 18037, 18038, 18039, 18040, 18041, 18042, 18043, \n\t18044, 18045, 18046, 18047, 18048, 18049, 18050, 18051, \n\t18052, 18053, 18053, 18054, 18055, 18056, 18057, 18058, \n\t18059, 18060, 18061, 18062, 18063, 18064, 18065, 18066, \n\t18067, 18068, 18069, 18070, 18071, 18072, 18073, 18074, \n\t18075, 18076, 18077, 18078, 18078, 18079, 18080, 18081, \n\t18082, 18083, 18084, 18085, 18086, 18087, 18088, 18089, \n\t18090, 18091, 18092, 18093, 18094, 18095, 18096, 18097, \n\t18098, 18099, 18100, 18101, 18102, 18103, 18103, 18104, \n\t18105, 18106, 18107, 18108, 18109, 18110, 18111, 18112, \n\t18113, 18114, 18115, 18116, 18117, 18118, 18119, 18120, \n\t18121, 18122, 18123, 18124, 18125, 18126, 18127, 18128, \n\t18128, 18129, 18130, 18131, 18132, 18133, 18134, 18135, \n\t18136, 18137, 18138, 18139, 18140, 18141, 18142, 18143, \n\t18144, 18145, 18146, 18147, 18148, 18149, 18150, 18151, \n\t18152, 18152, 18153, 18154, 18155, 18156, 18157, 18158, \n\t18159, 18160, 18161, 18162, 18163, 18164, 18165, 18166, \n\t18167, 18168, 18169, 18170, 18171, 18172, 18173, 18174, \n\t18175, 18176, 18177, 18177, 18178, 18179, 18180, 18181, \n\t18182, 18183, 18184, 18185, 18186, 18187, 18188, 18189, \n\t18190, 18191, 18192, 18193, 18194, 18195, 18196, 18197, \n\t18198, 18199, 18200, 18201, 18201, 18202, 18203, 18204, \n\t18205, 18206, 18207, 18208, 18209, 18210, 18211, 18212, \n\t18213, 18214, 18215, 18216, 18217, 18218, 18219, 18220, \n\t18221, 18222, 18223, 18224, 18225, 18226, 18226, 18227, \n\t18228, 18229, 18230, 18231, 18232, 18233, 18234, 18235, \n\t18236, 18237, 18238, 18239, 18240, 18241, 18242, 18243, \n\t18244, 18245, 18246, 18247, 18248, 18249, 18250, 18250, \n\t18251, 18252, 18253, 18254, 18255, 18256, 18257, 18258, \n\t18259, 18260, 18261, 18262, 18263, 18264, 18265, 18266, \n\t18267, 18268, 18269, 18270, 18271, 18272, 18273, 18274, \n\t18274, 18275, 18276, 18277, 18278, 18279, 18280, 18281, \n\t18282, 18283, 18284, 18285, 18286, 18287, 18288, 18289, \n\t18290, 18291, 18292, 18293, 18294, 18295, 18296, 18297, \n\t18298, 18298, 18299, 18300, 18301, 18302, 18303, 18304, \n\t18305, 18306, 18307, 18308, 18309, 18310, 18311, 18312, \n\t18313, 18314, 18315, 18316, 18317, 18318, 18319, 18320, \n\t18321, 18322, 18322, 18323, 18324, 18325, 18326, 18327, \n\t18328, 18329, 18330, 18331, 18332, 18333, 18334, 18335, \n\t18336, 18337, 18338, 18339, 18340, 18341, 18342, 18343, \n\t18344, 18345, 18346, 18346, 18347, 18348, 18349, 18350, \n\t18351, 18352, 18353, 18354, 18355, 18356, 18357, 18358, \n\t18359, 18360, 18361, 18362, 18363, 18364, 18365, 18366, \n\t18367, 18368, 18369, 18370, 18370, 18371, 18372, 18373, \n\t18374, 18375, 18376, 18377, 18378, 18379, 18380, 18381, \n\t18382, 18383, 18384, 18385, 18386, 18387, 18388, 18389, \n\t18390, 18391, 18392, 18393, 18394, 18394, 18395, 18396, \n\t18397, 18398, 18399, 18400, 18401, 18402, 18403, 18404, \n\t18405, 18406, 18407, 18408, 18409, 18410, 18411, 18412, \n\t18413, 18414, 18415, 18416, 18417, 18418, 18418, 18419, \n\t18420, 18421, 18422, 18423, 18424, 18425, 18426, 18427, \n\t18428, 18429, 18430, 18431, 18432, 18433, 18434, 18435, \n\t18436, 18437, 18438, 18439, 18440, 18441, 18442, 18442, \n\t18443, 18444, 18445, 18446, 18447, 18448, 18449, 18450, \n\t18451, 18452, 18453, 18454, 18455, 18456, 18457, 18458, \n\t18459, 18460, 18461, 18462, 18463, 18464, 18465, 18466, \n\t18466, 18467, 18468, 18469, 18470, 18471, 18472, 18473, \n\t18474, 18475, 18476, 18477, 18478, 18479, 18480, 18481, \n\t18482, 18483, 18484, 18485, 18486, 18487, 18488, 18489, \n\t18489, 18490, 18491, 18492, 18493, 18494, 18495, 18496, \n\t18497, 18498, 18499, 18500, 18501, 18502, 18503, 18504, \n\t18505, 18506, 18507, 18508, 18509, 18510, 18511, 18512, \n\t18513, 18513, 18514, 18515, 18516, 18517, 18518, 18519, \n\t18520, 18521, 18522, 18523, 18524, 18525, 18526, 18527, \n\t18528, 18529, 18530, 18531, 18532, 18533, 18534, 18535, \n\t18536, 18536, 18537, 18538, 18539, 18540, 18541, 18542, \n\t18543, 18544, 18545, 18546, 18547, 18548, 18549, 18550, \n\t18551, 18552, 18553, 18554, 18555, 18556, 18557, 18558, \n\t18559, 18560, 18560, 18561, 18562, 18563, 18564, 18565, \n\t18566, 18567, 18568, 18569, 18570, 18571, 18572, 18573, \n\t18574, 18575, 18576, 18577, 18578, 18579, 18580, 18581, \n\t18582, 18583, 18583, 18584, 18585, 18586, 18587, 18588, \n\t18589, 18590, 18591, 18592, 18593, 18594, 18595, 18596, \n\t18597, 18598, 18599, 18600, 18601, 18602, 18603, 18604, \n\t18605, 18606, 18607, 18607, 18608, 18609, 18610, 18611, \n\t18612, 18613, 18614, 18615, 18616, 18617, 18618, 18619, \n\t18620, 18621, 18622, 18623, 18624, 18625, 18626, 18627, \n\t18628, 18629, 18630, 18630, 18631, 18632, 18633, 18634, \n\t18635, 18636, 18637, 18638, 18639, 18640, 18641, 18642, \n\t18643, 18644, 18645, 18646, 18647, 18648, 18649, 18650, \n\t18651, 18652, 18653, 18653, 18654, 18655, 18656, 18657, \n\t18658, 18659, 18660, 18661, 18662, 18663, 18664, 18665, \n\t18666, 18667, 18668, 18669, 18670, 18671, 18672, 18673, \n\t18674, 18675, 18676, 18676, 18677, 18678, 18679, 18680, \n\t18681, 18682, 18683, 18684, 18685, 18686, 18687, 18688, \n\t18689, 18690, 18691, 18692, 18693, 18694, 18695, 18696, \n\t18697, 18698, 18699, 18699, 18700, 18701, 18702, 18703, \n\t18704, 18705, 18706, 18707, 18708, 18709, 18710, 18711, \n\t18712, 18713, 18714, 18715, 18716, 18717, 18718, 18719, \n\t18720, 18721, 18722, 18722, 18723, 18724, 18725, 18726, \n\t18727, 18728, 18729, 18730, 18731, 18732, 18733, 18734, \n\t18735, 18736, 18737, 18738, 18739, 18740, 18741, 18742, \n\t18743, 18744, 18745, 18745, 18746, 18747, 18748, 18749, \n\t18750, 18751, 18752, 18753, 18754, 18755, 18756, 18757, \n\t18758, 18759, 18760, 18761, 18762, 18763, 18764, 18765, \n\t18766, 18767, 18768, 18768, 18769, 18770, 18771, 18772, \n\t18773, 18774, 18775, 18776, 18777, 18778, 18779, 18780, \n\t18781, 18782, 18783, 18784, 18785, 18786, 18787, 18788, \n\t18789, 18790, 18791, 18791, 18792, 18793, 18794, 18795, \n\t18796, 18797, 18798, 18799, 18800, 18801, 18802, 18803, \n\t18804, 18805, 18806, 18807, 18808, 18809, 18810, 18811, \n\t18812, 18813, 18814, 18814, 18815, 18816, 18817, 18818, \n\t18819, 18820, 18821, 18822, 18823, 18824, 18825, 18826, \n\t18827, 18828, 18829, 18830, 18831, 18832, 18833, 18834, \n\t18835, 18836, 18837, 18837, 18838, 18839, 18840, 18841, \n\t18842, 18843, 18844, 18845, 18846, 18847, 18848, 18849, \n\t18850, 18851, 18852, 18853, 18854, 18855, 18856, 18857, \n\t18858, 18859, 18859, 18860, 18861, 18862, 18863, 18864, \n\t18865, 18866, 18867, 18868, 18869, 18870, 18871, 18872, \n\t18873, 18874, 18875, 18876, 18877, 18878, 18879, 18880, \n\t18881, 18882, 18882, 18883, 18884, 18885, 18886, 18887, \n\t18888, 18889, 18890, 18891, 18892, 18893, 18894, 18895, \n\t18896, 18897, 18898, 18899, 18900, 18901, 18902, 18903, \n\t18904, 18904, 18905, 18906, 18907, 18908, 18909, 18910, \n\t18911, 18912, 18913, 18914, 18915, 18916, 18917, 18918, \n\t18919, 18920, 18921, 18922, 18923, 18924, 18925, 18926, \n\t18927, 18927, 18928, 18929, 18930, 18931, 18932, 18933, \n\t18934, 18935, 18936, 18937, 18938, 18939, 18940, 18941, \n\t18942, 18943, 18944, 18945, 18946, 18947, 18948, 18949, \n\t18949, 18950, 18951, 18952, 18953, 18954, 18955, 18956, \n\t18957, 18958, 18959, 18960, 18961, 18962, 18963, 18964, \n\t18965, 18966, 18967, 18968, 18969, 18970, 18971, 18972, \n\t18972, 18973, 18974, 18975, 18976, 18977, 18978, 18979, \n\t18980, 18981, 18982, 18983, 18984, 18985, 18986, 18987, \n\t18988, 18989, 18990, 18991, 18992, 18993, 18994, 18994, \n\t18995, 18996, 18997, 18998, 18999, 19000, 19001, 19002, \n\t19003, 19004, 19005, 19006, 19007, 19008, 19009, 19010, \n\t19011, 19012, 19013, 19014, 19015, 19016, 19016, 19017, \n\t19018, 19019, 19020, 19021, 19022, 19023, 19024, 19025, \n\t19026, 19027, 19028, 19029, 19030, 19031, 19032, 19033, \n\t19034, 19035, 19036, 19037, 19038, 19039, 19039, 19040, \n\t19041, 19042, 19043, 19044, 19045, 19046, 19047, 19048, \n\t19049, 19050, 19051, 19052, 19053, 19054, 19055, 19056, \n\t19057, 19058, 19059, 19060, 19061, 19061, 19062, 19063, \n\t19064, 19065, 19066, 19067, 19068, 19069, 19070, 19071, \n\t19072, 19073, 19074, 19075, 19076, 19077, 19078, 19079, \n\t19080, 19081, 19082, 19083, 19083, 19084, 19085, 19086, \n\t19087, 19088, 19089, 19090, 19091, 19092, 19093, 19094, \n\t19095, 19096, 19097, 19098, 19099, 19100, 19101, 19102, \n\t19103, 19104, 19105, 19105, 19106, 19107, 19108, 19109, \n\t19110, 19111, 19112, 19113, 19114, 19115, 19116, 19117, \n\t19118, 19119, 19120, 19121, 19122, 19123, 19124, 19125, \n\t19126, 19127, 19127, 19128, 19129, 19130, 19131, 19132, \n\t19133, 19134, 19135, 19136, 19137, 19138, 19139, 19140, \n\t19141, 19142, 19143, 19144, 19145, 19146, 19147, 19148, \n\t19149, 19149, 19150, 19151, 19152, 19153, 19154, 19155, \n\t19156, 19157, 19158, 19159, 19160, 19161, 19162, 19163, \n\t19164, 19165, 19166, 19167, 19168, 19169, 19170, 19171, \n\t19171, 19172, 19173, 19174, 19175, 19176, 19177, 19178, \n\t19179, 19180, 19181, 19182, 19183, 19184, 19185, 19186, \n\t19187, 19188, 19189, 19190, 19191, 19192, 19193, 19193, \n\t19194, 19195, 19196, 19197, 19198, 19199, 19200, 19201, \n\t19202, 19203, 19204, 19205, 19206, 19207, 19208, 19209, \n\t19210, 19211, 19212, 19213, 19214, 19214, 19215, 19216, \n\t19217, 19218, 19219, 19220, 19221, 19222, 19223, 19224, \n\t19225, 19226, 19227, 19228, 19229, 19230, 19231, 19232, \n\t19233, 19234, 19235, 19236, 19236, 19237, 19238, 19239, \n\t19240, 19241, 19242, 19243, 19244, 19245, 19246, 19247, \n\t19248, 19249, 19250, 19251, 19252, 19253, 19254, 19255, \n\t19256, 19257, 19258, 19258, 19259, 19260, 19261, 19262, \n\t19263, 19264, 19265, 19266, 19267, 19268, 19269, 19270, \n\t19271, 19272, 19273, 19274, 19275, 19276, 19277, 19278, \n\t19279, 19279, 19280, 19281, 19282, 19283, 19284, 19285, \n\t19286, 19287, 19288, 19289, 19290, 19291, 19292, 19293, \n\t19294, 19295, 19296, 19297, 19298, 19299, 19300, 19301, \n\t19301, 19302, 19303, 19304, 19305, 19306, 19307, 19308, \n\t19309, 19310, 19311, 19312, 19313, 19314, 19315, 19316, \n\t19317, 19318, 19319, 19320, 19321, 19322, 19322, 19323, \n\t19324, 19325, 19326, 19327, 19328, 19329, 19330, 19331, \n\t19332, 19333, 19334, 19335, 19336, 19337, 19338, 19339, \n\t19340, 19341, 19342, 19343, 19344, 19344, 19345, 19346, \n\t19347, 19348, 19349, 19350, 19351, 19352, 19353, 19354, \n\t19355, 19356, 19357, 19358, 19359, 19360, 19361, 19362, \n\t19363, 19364, 19365, 19365, 19366, 19367, 19368, 19369, \n\t19370, 19371, 19372, 19373, 19374, 19375, 19376, 19377, \n\t19378, 19379, 19380, 19381, 19382, 19383, 19384, 19385, \n\t19386, 19387, 19387, 19388, 19389, 19390, 19391, 19392, \n\t19393, 19394, 19395, 19396, 19397, 19398, 19399, 19400, \n\t19401, 19402, 19403, 19404, 19405, 19406, 19407, 19408, \n\t19408, 19409, 19410, 19411, 19412, 19413, 19414, 19415, \n\t19416, 19417, 19418, 19419, 19420, 19421, 19422, 19423, \n\t19424, 19425, 19426, 19427, 19428, 19429, 19429, 19430, \n\t19431, 19432, 19433, 19434, 19435, 19436, 19437, 19438, \n\t19439, 19440, 19441, 19442, 19443, 19444, 19445, 19446, \n\t19447, 19448, 19449, 19450, 19451, 19451, 19452, 19453, \n\t19454, 19455, 19456, 19457, 19458, 19459, 19460, 19461, \n\t19462, 19463, 19464, 19465, 19466, 19467, 19468, 19469, \n\t19470, 19471, 19472, 19472, 19473, 19474, 19475, 19476, \n\t19477, 19478, 19479, 19480, 19481, 19482, 19483, 19484, \n\t19485, 19486, 19487, 19488, 19489, 19490, 19491, 19492, \n\t19493, 19493, 19494, 19495, 19496, 19497, 19498, 19499, \n\t19500, 19501, 19502, 19503, 19504, 19505, 19506, 19507, \n\t19508, 19509, 19510, 19511, 19512, 19513, 19514, 19514, \n\t19515, 19516, 19517, 19518, 19519, 19520, 19521, 19522, \n\t19523, 19524, 19525, 19526, 19527, 19528, 19529, 19530, \n\t19531, 19532, 19533, 19534, 19535, 19535, 19536, 19537, \n\t19538, 19539, 19540, 19541, 19542, 19543, 19544, 19545, \n\t19546, 19547, 19548, 19549, 19550, 19551, 19552, 19553, \n\t19554, 19555, 19556, 19556, 19557, 19558, 19559, 19560, \n\t19561, 19562, 19563, 19564, 19565, 19566, 19567, 19568, \n\t19569, 19570, 19571, 19572, 19573, 19574, 19575, 19576, \n\t19577, 19577, 19578, 19579, 19580, 19581, 19582, 19583, \n\t19584, 19585, 19586, 19587, 19588, 19589, 19590, 19591, \n\t19592, 19593, 19594, 19595, 19596, 19597, 19598, 19598, \n\t19599, 19600, 19601, 19602, 19603, 19604, 19605, 19606, \n\t19607, 19608, 19609, 19610, 19611, 19612, 19613, 19614, \n\t19615, 19616, 19617, 19618, 19618, 19619, 19620, 19621, \n\t19622, 19623, 19624, 19625, 19626, 19627, 19628, 19629, \n\t19630, 19631, 19632, 19633, 19634, 19635, 19636, 19637, \n\t19638, 19639, 19639, 19640, 19641, 19642, 19643, 19644, \n\t19645, 19646, 19647, 19648, 19649, 19650, 19651, 19652, \n\t19653, 19654, 19655, 19656, 19657, 19658, 19659, 19660, \n\t19660, 19661, 19662, 19663, 19664, 19665, 19666, 19667, \n\t19668, 19669, 19670, 19671, 19672, 19673, 19674, 19675, \n\t19676, 19677, 19678, 19679, 19680, 19681, 19681, 19682, \n\t19683, 19684, 19685, 19686, 19687, 19688, 19689, 19690, \n\t19691, 19692, 19693, 19694, 19695, 19696, 19697, 19698, \n\t19699, 19700, 19701, 19701, 19702, 19703, 19704, 19705, \n\t19706, 19707, 19708, 19709, 19710, 19711, 19712, 19713, \n\t19714, 19715, 19716, 19717, 19718, 19719, 19720, 19721, \n\t19722, 19722, 19723, 19724, 19725, 19726, 19727, 19728, \n\t19729, 19730, 19731, 19732, 19733, 19734, 19735, 19736, \n\t19737, 19738, 19739, 19740, 19741, 19742, 19742, 19743, \n\t19744, 19745, 19746, 19747, 19748, 19749, 19750, 19751, \n\t19752, 19753, 19754, 19755, 19756, 19757, 19758, 19759, \n\t19760, 19761, 19762, 19763, 19763, 19764, 19765, 19766, \n\t19767, 19768, 19769, 19770, 19771, 19772, 19773, 19774, \n\t19775, 19776, 19777, 19778, 19779, 19780, 19781, 19782, \n\t19783, 19783, 19784, 19785, 19786, 19787, 19788, 19789, \n\t19790, 19791, 19792, 19793, 19794, 19795, 19796, 19797, \n\t19798, 19799, 19800, 19801, 19802, 19803, 19804, 19804, \n\t19805, 19806, 19807, 19808, 19809, 19810, 19811, 19812, \n\t19813, 19814, 19815, 19816, 19817, 19818, 19819, 19820, \n\t19821, 19822, 19823, 19824, 19824, 19825, 19826, 19827, \n\t19828, 19829, 19830, 19831, 19832, 19833, 19834, 19835, \n\t19836, 19837, 19838, 19839, 19840, 19841, 19842, 19843, \n\t19844, 19845, 19845, 19846, 19847, 19848, 19849, 19850, \n\t19851, 19852, 19853, 19854, 19855, 19856, 19857, 19858, \n\t19859, 19860, 19861, 19862, 19863, 19864, 19865, 19865, \n\t19866, 19867, 19868, 19869, 19870, 19871, 19872, 19873, \n\t19874, 19875, 19876, 19877, 19878, 19879, 19880, 19881, \n\t19882, 19883, 19884, 19885, 19885, 19886, 19887, 19888, \n\t19889, 19890, 19891, 19892, 19893, 19894, 19895, 19896, \n\t19897, 19898, 19899, 19900, 19901, 19902, 19903, 19904, \n\t19905, 19905, 19906, 19907, 19908, 19909, 19910, 19911, \n\t19912, 19913, 19914, 19915, 19916, 19917, 19918, 19919, \n\t19920, 19921, 19922, 19923, 19924, 19925, 19925, 19926, \n\t19927, 19928, 19929, 19930, 19931, 19932, 19933, 19934, \n\t19935, 19936, 19937, 19938, 19939, 19940, 19941, 19942, \n\t19943, 19944, 19945, 19946, 19946, 19947, 19948, 19949, \n\t19950, 19951, 19952, 19953, 19954, 19955, 19956, 19957, \n\t19958, 19959, 19960, 19961, 19962, 19963, 19964, 19965, \n\t19966, 19966, 19967, 19968, 19969, 19970, 19971, 19972, \n\t19973, 19974, 19975, 19976, 19977, 19978, 19979, 19980, \n\t19981, 19982, 19983, 19984, 19985, 19986, 19986, 19987, \n\t19988, 19989, 19990, 19991, 19992, 19993, 19994, 19995, \n\t19996, 19997, 19998, 19999, 20000, 20001, 20002, 20003, \n\t20004, 20005, 20006, 20006, 20007, 20008, 20009, 20010, \n\t20011, 20012, 20013, 20014, 20015, 20016, 20017, 20018, \n\t20019, 20020, 20021, 20022, 20023, 20024, 20025, 20025, \n\t20026, 20027, 20028, 20029, 20030, 20031, 20032, 20033, \n\t20034, 20035, 20036, 20037, 20038, 20039, 20040, 20041, \n\t20042, 20043, 20044, 20045, 20045, 20046, 20047, 20048, \n\t20049, 20050, 20051, 20052, 20053, 20054, 20055, 20056, \n\t20057, 20058, 20059, 20060, 20061, 20062, 20063, 20064, \n\t20065, 20065, 20066, 20067, 20068, 20069, 20070, 20071, \n\t20072, 20073, 20074, 20075, 20076, 20077, 20078, 20079, \n\t20080, 20081, 20082, 20083, 20084, 20085, 20085, 20086, \n\t20087, 20088, 20089, 20090, 20091, 20092, 20093, 20094, \n\t20095, 20096, 20097, 20098, 20099, 20100, 20101, 20102, \n\t20103, 20104, 20105, 20105, 20106, 20107, 20108, 20109, \n\t20110, 20111, 20112, 20113, 20114, 20115, 20116, 20117, \n\t20118, 20119, 20120, 20121, 20122, 20123, 20124, 20124, \n\t20125, 20126, 20127, 20128, 20129, 20130, 20131, 20132, \n\t20133, 20134, 20135, 20136, 20137, 20138, 20139, 20140, \n\t20141, 20142, 20143, 20144, 20144, 20145, 20146, 20147, \n\t20148, 20149, 20150, 20151, 20152, 20153, 20154, 20155, \n\t20156, 20157, 20158, 20159, 20160, 20161, 20162, 20163, \n\t20164, 20164, 20165, 20166, 20167, 20168, 20169, 20170, \n\t20171, 20172, 20173, 20174, 20175, 20176, 20177, 20178, \n\t20179, 20180, 20181, 20182, 20183, 20183, 20184, 20185, \n\t20186, 20187, 20188, 20189, 20190, 20191, 20192, 20193, \n\t20194, 20195, 20196, 20197, 20198, 20199, 20200, 20201, \n\t20202, 20203, 20203, 20204, 20205, 20206, 20207, 20208, \n\t20209, 20210, 20211, 20212, 20213, 20214, 20215, 20216, \n\t20217, 20218, 20219, 20220, 20221, 20222, 20222, 20223, \n\t20224, 20225, 20226, 20227, 20228, 20229, 20230, 20231, \n\t20232, 20233, 20234, 20235, 20236, 20237, 20238, 20239, \n\t20240, 20241, 20242, 20242, 20243, 20244, 20245, 20246, \n\t20247, 20248, 20249, 20250, 20251, 20252, 20253, 20254, \n\t20255, 20256, 20257, 20258, 20259, 20260, 20261, 20261, \n\t20262, 20263, 20264, 20265, 20266, 20267, 20268, 20269, \n\t20270, 20271, 20272, 20273, 20274, 20275, 20276, 20277, \n\t20278, 20279, 20280, 20281, 20281, 20282, 20283, 20284, \n\t20285, 20286, 20287, 20288, 20289, 20290, 20291, 20292, \n\t20293, 20294, 20295, 20296, 20297, 20298, 20299, 20300, \n\t20300, 20301, 20302, 20303, 20304, 20305, 20306, 20307, \n\t20308, 20309, 20310, 20311, 20312, 20313, 20314, 20315, \n\t20316, 20317, 20318, 20319, 20319, 20320, 20321, 20322, \n\t20323, 20324, 20325, 20326, 20327, 20328, 20329, 20330, \n\t20331, 20332, 20333, 20334, 20335, 20336, 20337, 20338, \n\t20339, 20339, 20340, 20341, 20342, 20343, 20344, 20345, \n\t20346, 20347, 20348, 20349, 20350, 20351, 20352, 20353, \n\t20354, 20355, 20356, 20357, 20358, 20358, 20359, 20360, \n\t20361, 20362, 20363, 20364, 20365, 20366, 20367, 20368, \n\t20369, 20370, 20371, 20372, 20373, 20374, 20375, 20376, \n\t20377, 20377, 20378, 20379, 20380, 20381, 20382, 20383, \n\t20384, 20385, 20386, 20387, 20388, 20389, 20390, 20391, \n\t20392, 20393, 20394, 20395, 20396, 20396, 20397, 20398, \n\t20399, 20400, 20401, 20402, 20403, 20404, 20405, 20406, \n\t20407, 20408, 20409, 20410, 20411, 20412, 20413, 20414, \n\t20415, 20415, 20416, 20417, 20418, 20419, 20420, 20421, \n\t20422, 20423, 20424, 20425, 20426, 20427, 20428, 20429, \n\t20430, 20431, 20432, 20433, 20434, 20434, 20435, 20436, \n\t20437, 20438, 20439, 20440, 20441, 20442, 20443, 20444, \n\t20445, 20446, 20447, 20448, 20449, 20450, 20451, 20452, \n\t20453, 20454, 20454, 20455, 20456, 20457, 20458, 20459, \n\t20460, 20461, 20462, 20463, 20464, 20465, 20466, 20467, \n\t20468, 20469, 20470, 20471, 20472, 20473, 20473, 20474, \n\t20475, 20476, 20477, 20478, 20479, 20480, 20481, 20482, \n\t20483, 20484, 20485, 20486, 20487, 20488, 20489, 20490, \n\t20491, 20491, 20492, 20493, 20494, 20495, 20496, 20497, \n\t20498, 20499, 20500, 20501, 20502, 20503, 20504, 20505, \n\t20506, 20507, 20508, 20509, 20510, 20510, 20511, 20512, \n\t20513, 20514, 20515, 20516, 20517, 20518, 20519, 20520, \n\t20521, 20522, 20523, 20524, 20525, 20526, 20527, 20528, \n\t20529, 20529, 20530, 20531, 20532, 20533, 20534, 20535, \n\t20536, 20537, 20538, 20539, 20540, 20541, 20542, 20543, \n\t20544, 20545, 20546, 20547, 20548, 20548, 20549, 20550, \n\t20551, 20552, 20553, 20554, 20555, 20556, 20557, 20558, \n\t20559, 20560, 20561, 20562, 20563, 20564, 20565, 20566, \n\t20567, 20567, 20568, 20569, 20570, 20571, 20572, 20573, \n\t20574, 20575, 20576, 20577, 20578, 20579, 20580, 20581, \n\t20582, 20583, 20584, 20585, 20586, 20586, 20587, 20588, \n\t20589, 20590, 20591, 20592, 20593, 20594, 20595, 20596, \n\t20597, 20598, 20599, 20600, 20601, 20602, 20603, 20604, \n\t20604, 20605, 20606, 20607, 20608, 20609, 20610, 20611, \n\t20612, 20613, 20614, 20615, 20616, 20617, 20618, 20619, \n\t20620, 20621, 20622, 20623, 20623, 20624, 20625, 20626, \n\t20627, 20628, 20629, 20630, 20631, 20632, 20633, 20634, \n\t20635, 20636, 20637, 20638, 20639, 20640, 20641, 20642, \n\t20642, 20643, 20644, 20645, 20646, 20647, 20648, 20649, \n\t20650, 20651, 20652, 20653, 20654, 20655, 20656, 20657, \n\t20658, 20659, 20660, 20660, 20661, 20662, 20663, 20664, \n\t20665, 20666, 20667, 20668, 20669, 20670, 20671, 20672, \n\t20673, 20674, 20675, 20676, 20677, 20678, 20679, 20679, \n\t20680, 20681, 20682, 20683, 20684, 20685, 20686, 20687, \n\t20688, 20689, 20690, 20691, 20692, 20693, 20694, 20695, \n\t20696, 20697, 20698, 20698, 20699, 20700, 20701, 20702, \n\t20703, 20704, 20705, 20706, 20707, 20708, 20709, 20710, \n\t20711, 20712, 20713, 20714, 20715, 20716, 20716, 20717, \n\t20718, 20719, 20720, 20721, 20722, 20723, 20724, 20725, \n\t20726, 20727, 20728, 20729, 20730, 20731, 20732, 20733, \n\t20734, 20735, 20735, 20736, 20737, 20738, 20739, 20740, \n\t20741, 20742, 20743, 20744, 20745, 20746, 20747, 20748, \n\t20749, 20750, 20751, 20752, 20753, 20753, 20754, 20755, \n\t20756, 20757, 20758, 20759, 20760, 20761, 20762, 20763, \n\t20764, 20765, 20766, 20767, 20768, 20769, 20770, 20771, \n\t20771, 20772, 20773, 20774, 20775, 20776, 20777, 20778, \n\t20779, 20780, 20781, 20782, 20783, 20784, 20785, 20786, \n\t20787, 20788, 20789, 20790, 20790, 20791, 20792, 20793, \n\t20794, 20795, 20796, 20797, 20798, 20799, 20800, 20801, \n\t20802, 20803, 20804, 20805, 20806, 20807, 20808, 20808, \n\t20809, 20810, 20811, 20812, 20813, 20814, 20815, 20816, \n\t20817, 20818, 20819, 20820, 20821, 20822, 20823, 20824, \n\t20825, 20826, 20827, 20827, 20828, 20829, 20830, 20831, \n\t20832, 20833, 20834, 20835, 20836, 20837, 20838, 20839, \n\t20840, 20841, 20842, 20843, 20844, 20845, 20845, 20846, \n\t20847, 20848, 20849, 20850, 20851, 20852, 20853, 20854, \n\t20855, 20856, 20857, 20858, 20859, 20860, 20861, 20862, \n\t20863, 20863, 20864, 20865, 20866, 20867, 20868, 20869, \n\t20870, 20871, 20872, 20873, 20874, 20875, 20876, 20877, \n\t20878, 20879, 20880, 20881, 20881, 20882, 20883, 20884, \n\t20885, 20886, 20887, 20888, 20889, 20890, 20891, 20892, \n\t20893, 20894, 20895, 20896, 20897, 20898, 20899, 20899, \n\t20900, 20901, 20902, 20903, 20904, 20905, 20906, 20907, \n\t20908, 20909, 20910, 20911, 20912, 20913, 20914, 20915, \n\t20916, 20917, 20918, 20918, 20919, 20920, 20921, 20922, \n\t20923, 20924, 20925, 20926, 20927, 20928, 20929, 20930, \n\t20931, 20932, 20933, 20934, 20935, 20936, 20936, 20937, \n\t20938, 20939, 20940, 20941, 20942, 20943, 20944, 20945, \n\t20946, 20947, 20948, 20949, 20950, 20951, 20952, 20953, \n\t20954, 20954, 20955, 20956, 20957, 20958, 20959, 20960, \n\t20961, 20962, 20963, 20964, 20965, 20966, 20967, 20968, \n\t20969, 20970, 20971, 20972, 20972, 20973, 20974, 20975, \n\t20976, 20977, 20978, 20979, 20980, 20981, 20982, 20983, \n\t20984, 20985, 20986, 20987, 20988, 20989, 20990, 20990, \n\t20991, 20992, 20993, 20994, 20995, 20996, 20997, 20998, \n\t20999, 21000, 21001, 21002, 21003, 21004, 21005, 21006, \n\t21007, 21008, 21008, 21009, 21010, 21011, 21012, 21013, \n\t21014, 21015, 21016, 21017, 21018, 21019, 21020, 21021, \n\t21022, 21023, 21024, 21025, 21026, 21026, 21027, 21028, \n\t21029, 21030, 21031, 21032, 21033, 21034, 21035, 21036, \n\t21037, 21038, 21039, 21040, 21041, 21042, 21043, 21044, \n\t21044, 21045, 21046, 21047, 21048, 21049, 21050, 21051, \n\t21052, 21053, 21054, 21055, 21056, 21057, 21058, 21059, \n\t21060, 21061, 21061, 21062, 21063, 21064, 21065, 21066, \n\t21067, 21068, 21069, 21070, 21071, 21072, 21073, 21074, \n\t21075, 21076, 21077, 21078, 21079, 21079, 21080, 21081, \n\t21082, 21083, 21084, 21085, 21086, 21087, 21088, 21089, \n\t21090, 21091, 21092, 21093, 21094, 21095, 21096, 21097, \n\t21097, 21098, 21099, 21100, 21101, 21102, 21103, 21104, \n\t21105, 21106, 21107, 21108, 21109, 21110, 21111, 21112, \n\t21113, 21114, 21115, 21115, 21116, 21117, 21118, 21119, \n\t21120, 21121, 21122, 21123, 21124, 21125, 21126, 21127, \n\t21128, 21129, 21130, 21131, 21132, 21133, 21133, 21134, \n\t21135, 21136, 21137, 21138, 21139, 21140, 21141, 21142, \n\t21143, 21144, 21145, 21146, 21147, 21148, 21149, 21150, \n\t21150, 21151, 21152, 21153, 21154, 21155, 21156, 21157, \n\t21158, 21159, 21160, 21161, 21162, 21163, 21164, 21165, \n\t21166, 21167, 21168, 21168, 21169, 21170, 21171, 21172, \n\t21173, 21174, 21175, 21176, 21177, 21178, 21179, 21180, \n\t21181, 21182, 21183, 21184, 21185, 21186, 21186, 21187, \n\t21188, 21189, 21190, 21191, 21192, 21193, 21194, 21195, \n\t21196, 21197, 21198, 21199, 21200, 21201, 21202, 21203, \n\t21203, 21204, 21205, 21206, 21207, 21208, 21209, 21210, \n\t21211, 21212, 21213, 21214, 21215, 21216, 21217, 21218, \n\t21219, 21220, 21221, 21221, 21222, 21223, 21224, 21225, \n\t21226, 21227, 21228, 21229, 21230, 21231, 21232, 21233, \n\t21234, 21235, 21236, 21237, 21238, 21238, 21239, 21240, \n\t21241, 21242, 21243, 21244, 21245, 21246, 21247, 21248, \n\t21249, 21250, 21251, 21252, 21253, 21254, 21255, 21256, \n\t21256, 21257, 21258, 21259, 21260, 21261, 21262, 21263, \n\t21264, 21265, 21266, 21267, 21268, 21269, 21270, 21271, \n\t21272, 21273, 21273, 21274, 21275, 21276, 21277, 21278, \n\t21279, 21280, 21281, 21282, 21283, 21284, 21285, 21286, \n\t21287, 21288, 21289, 21290, 21291, 21291, 21292, 21293, \n\t21294, 21295, 21296, 21297, 21298, 21299, 21300, 21301, \n\t21302, 21303, 21304, 21305, 21306, 21307, 21308, 21308, \n\t21309, 21310, 21311, 21312, 21313, 21314, 21315, 21316, \n\t21317, 21318, 21319, 21320, 21321, 21322, 21323, 21324, \n\t21325, 21326, 21326, 21327, 21328, 21329, 21330, 21331, \n\t21332, 21333, 21334, 21335, 21336, 21337, 21338, 21339, \n\t21340, 21341, 21342, 21343, 21343, 21344, 21345, 21346, \n\t21347, 21348, 21349, 21350, 21351, 21352, 21353, 21354, \n\t21355, 21356, 21357, 21358, 21359, 21360, 21360, 21361, \n\t21362, 21363, 21364, 21365, 21366, 21367, 21368, 21369, \n\t21370, 21371, 21372, 21373, 21374, 21375, 21376, 21377, \n\t21378, 21378, 21379, 21380, 21381, 21382, 21383, 21384, \n\t21385, 21386, 21387, 21388, 21389, 21390, 21391, 21392, \n\t21393, 21394, 21395, 21395, 21396, 21397, 21398, 21399, \n\t21400, 21401, 21402, 21403, 21404, 21405, 21406, 21407, \n\t21408, 21409, 21410, 21411, 21412, 21412, 21413, 21414, \n\t21415, 21416, 21417, 21418, 21419, 21420, 21421, 21422, \n\t21423, 21424, 21425, 21426, 21427, 21428, 21429, 21429, \n\t21430, 21431, 21432, 21433, 21434, 21435, 21436, 21437, \n\t21438, 21439, 21440, 21441, 21442, 21443, 21444, 21445, \n\t21446, 21446, 21447, 21448, 21449, 21450, 21451, 21452, \n\t21453, 21454, 21455, 21456, 21457, 21458, 21459, 21460, \n\t21461, 21462, 21463, 21464, 21464, 21465, 21466, 21467, \n\t21468, 21469, 21470, 21471, 21472, 21473, 21474, 21475, \n\t21476, 21477, 21478, 21479, 21480, 21481, 21481, 21482, \n\t21483, 21484, 21485, 21486, 21487, 21488, 21489, 21490, \n\t21491, 21492, 21493, 21494, 21495, 21496, 21497, 21498, \n\t21498, 21499, 21500, 21501, 21502, 21503, 21504, 21505, \n\t21506, 21507, 21508, 21509, 21510, 21511, 21512, 21513, \n\t21514, 21515, 21515, 21516, 21517, 21518, 21519, 21520, \n\t21521, 21522, 21523, 21524, 21525, 21526, 21527, 21528, \n\t21529, 21530, 21531, 21532, 21532, 21533, 21534, 21535, \n\t21536, 21537, 21538, 21539, 21540, 21541, 21542, 21543, \n\t21544, 21545, 21546, 21547, 21548, 21549, 21549, 21550, \n\t21551, 21552, 21553, 21554, 21555, 21556, 21557, 21558, \n\t21559, 21560, 21561, 21562, 21563, 21564, 21565, 21566, \n\t21566, 21567, 21568, 21569, 21570, 21571, 21572, 21573, \n\t21574, 21575, 21576, 21577, 21578, 21579, 21580, 21581, \n\t21582, 21583, 21583, 21584, 21585, 21586, 21587, 21588, \n\t21589, 21590, 21591, 21592, 21593, 21594, 21595, 21596, \n\t21597, 21598, 21599, 21600, 21600, 21601, 21602, 21603, \n\t21604, 21605, 21606, 21607, 21608, 21609, 21610, 21611, \n\t21612, 21613, 21614, 21615, 21616, 21617, 21617, 21618, \n\t21619, 21620, 21621, 21622, 21623, 21624, 21625, 21626, \n\t21627, 21628, 21629, 21630, 21631, 21632, 21633, 21633, \n\t21634, 21635, 21636, 21637, 21638, 21639, 21640, 21641, \n\t21642, 21643, 21644, 21645, 21646, 21647, 21648, 21649, \n\t21650, 21650, 21651, 21652, 21653, 21654, 21655, 21656, \n\t21657, 21658, 21659, 21660, 21661, 21662, 21663, 21664, \n\t21665, 21666, 21667, 21667, 21668, 21669, 21670, 21671, \n\t21672, 21673, 21674, 21675, 21676, 21677, 21678, 21679, \n\t21680, 21681, 21682, 21683, 21684, 21684, 21685, 21686, \n\t21687, 21688, 21689, 21690, 21691, 21692, 21693, 21694, \n\t21695, 21696, 21697, 21698, 21699, 21700, 21701, 21701, \n\t21702, 21703, 21704, 21705, 21706, 21707, 21708, 21709, \n\t21710, 21711, 21712, 21713, 21714, 21715, 21716, 21717, \n\t21717, 21718, 21719, 21720, 21721, 21722, 21723, 21724, \n\t21725, 21726, 21727, 21728, 21729, 21730, 21731, 21732, \n\t21733, 21734, 21734, 21735, 21736, 21737, 21738, 21739, \n\t21740, 21741, 21742, 21743, 21744, 21745, 21746, 21747, \n\t21748, 21749, 21750, 21751, 21751, 21752, 21753, 21754, \n\t21755, 21756, 21757, 21758, 21759, 21760, 21761, 21762, \n\t21763, 21764, 21765, 21766, 21767, 21767, 21768, 21769, \n\t21770, 21771, 21772, 21773, 21774, 21775, 21776, 21777, \n\t21778, 21779, 21780, 21781, 21782, 21783, 21784, 21784, \n\t21785, 21786, 21787, 21788, 21789, 21790, 21791, 21792, \n\t21793, 21794, 21795, 21796, 21797, 21798, 21799, 21800, \n\t21800, 21801, 21802, 21803, 21804, 21805, 21806, 21807, \n\t21808, 21809, 21810, 21811, 21812, 21813, 21814, 21815, \n\t21816, 21817, 21817, 21818, 21819, 21820, 21821, 21822, \n\t21823, 21824, 21825, 21826, 21827, 21828, 21829, 21830, \n\t21831, 21832, 21833, 21833, 21834, 21835, 21836, 21837, \n\t21838, 21839, 21840, 21841, 21842, 21843, 21844, 21845, \n\t21846, 21847, 21848, 21849, 21850, 21850, 21851, 21852, \n\t21853, 21854, 21855, 21856, 21857, 21858, 21859, 21860, \n\t21861, 21862, 21863, 21864, 21865, 21866, 21866, 21867, \n\t21868, 21869, 21870, 21871, 21872, 21873, 21874, 21875, \n\t21876, 21877, 21878, 21879, 21880, 21881, 21882, 21883, \n\t21883, 21884, 21885, 21886, 21887, 21888, 21889, 21890, \n\t21891, 21892, 21893, 21894, 21895, 21896, 21897, 21898, \n\t21899, 21899, 21900, 21901, 21902, 21903, 21904, 21905, \n\t21906, 21907, 21908, 21909, 21910, 21911, 21912, 21913, \n\t21914, 21915, 21916, 21916, 21917, 21918, 21919, 21920, \n\t21921, 21922, 21923, 21924, 21925, 21926, 21927, 21928, \n\t21929, 21930, 21931, 21932, 21932, 21933, 21934, 21935, \n\t21936, 21937, 21938, 21939, 21940, 21941, 21942, 21943, \n\t21944, 21945, 21946, 21947, 21948, 21948, 21949, 21950, \n\t21951, 21952, 21953, 21954, 21955, 21956, 21957, 21958, \n\t21959, 21960, 21961, 21962, 21963, 21964, 21965, 21965, \n\t21966, 21967, 21968, 21969, 21970, 21971, 21972, 21973, \n\t21974, 21975, 21976, 21977, 21978, 21979, 21980, 21981, \n\t21981, 21982, 21983, 21984, 21985, 21986, 21987, 21988, \n\t21989, 21990, 21991, 21992, 21993, 21994, 21995, 21996, \n\t21997, 21997, 21998, 21999, 22000, 22001, 22002, 22003, \n\t22004, 22005, 22006, 22007, 22008, 22009, 22010, 22011, \n\t22012, 22013, 22013, 22014, 22015, 22016, 22017, 22018, \n\t22019, 22020, 22021, 22022, 22023, 22024, 22025, 22026, \n\t22027, 22028, 22029, 22030, 22030, 22031, 22032, 22033, \n\t22034, 22035, 22036, 22037, 22038, 22039, 22040, 22041, \n\t22042, 22043, 22044, 22045, 22046, 22046, 22047, 22048, \n\t22049, 22050, 22051, 22052, 22053, 22054, 22055, 22056, \n\t22057, 22058, 22059, 22060, 22061, 22062, 22062, 22063, \n\t22064, 22065, 22066, 22067, 22068, 22069, 22070, 22071, \n\t22072, 22073, 22074, 22075, 22076, 22077, 22078, 22078, \n\t22079, 22080, 22081, 22082, 22083, 22084, 22085, 22086, \n\t22087, 22088, 22089, 22090, 22091, 22092, 22093, 22094, \n\t22094, 22095, 22096, 22097, 22098, 22099, 22100, 22101, \n\t22102, 22103, 22104, 22105, 22106, 22107, 22108, 22109, \n\t22110, 22110, 22111, 22112, 22113, 22114, 22115, 22116, \n\t22117, 22118, 22119, 22120, 22121, 22122, 22123, 22124, \n\t22125, 22126, 22126, 22127, 22128, 22129, 22130, 22131, \n\t22132, 22133, 22134, 22135, 22136, 22137, 22138, 22139, \n\t22140, 22141, 22142, 22142, 22143, 22144, 22145, 22146, \n\t22147, 22148, 22149, 22150, 22151, 22152, 22153, 22154, \n\t22155, 22156, 22157, 22158, 22158, 22159, 22160, 22161, \n\t22162, 22163, 22164, 22165, 22166, 22167, 22168, 22169, \n\t22170, 22171, 22172, 22173, 22174, 22174, 22175, 22176, \n\t22177, 22178, 22179, 22180, 22181, 22182, 22183, 22184, \n\t22185, 22186, 22187, 22188, 22189, 22190, 22190, 22191, \n\t22192, 22193, 22194, 22195, 22196, 22197, 22198, 22199, \n\t22200, 22201, 22202, 22203, 22204, 22205, 22206, 22206, \n\t22207, 22208, 22209, 22210, 22211, 22212, 22213, 22214, \n\t22215, 22216, 22217, 22218, 22219, 22220, 22221, 22222, \n\t22222, 22223, 22224, 22225, 22226, 22227, 22228, 22229, \n\t22230, 22231, 22232, 22233, 22234, 22235, 22236, 22237, \n\t22238, 22238, 22239, 22240, 22241, 22242, 22243, 22244, \n\t22245, 22246, 22247, 22248, 22249, 22250, 22251, 22252, \n\t22253, 22254, 22254, 22255, 22256, 22257, 22258, 22259, \n\t22260, 22261, 22262, 22263, 22264, 22265, 22266, 22267, \n\t22268, 22269, 22270, 22270, 22271, 22272, 22273, 22274, \n\t22275, 22276, 22277, 22278, 22279, 22280, 22281, 22282, \n\t22283, 22284, 22285, 22285, 22286, 22287, 22288, 22289, \n\t22290, 22291, 22292, 22293, 22294, 22295, 22296, 22297, \n\t22298, 22299, 22300, 22301, 22301, 22302, 22303, 22304, \n\t22305, 22306, 22307, 22308, 22309, 22310, 22311, 22312, \n\t22313, 22314, 22315, 22316, 22317, 22317, 22318, 22319, \n\t22320, 22321, 22322, 22323, 22324, 22325, 22326, 22327, \n\t22328, 22329, 22330, 22331, 22332, 22333, 22333, 22334, \n\t22335, 22336, 22337, 22338, 22339, 22340, 22341, 22342, \n\t22343, 22344, 22345, 22346, 22347, 22348, 22348, 22349, \n\t22350, 22351, 22352, 22353, 22354, 22355, 22356, 22357, \n\t22358, 22359, 22360, 22361, 22362, 22363, 22364, 22364, \n\t22365, 22366, 22367, 22368, 22369, 22370, 22371, 22372, \n\t22373, 22374, 22375, 22376, 22377, 22378, 22379, 22380, \n\t22380, 22381, 22382, 22383, 22384, 22385, 22386, 22387, \n\t22388, 22389, 22390, 22391, 22392, 22393, 22394, 22395, \n\t22395, 22396, 22397, 22398, 22399, 22400, 22401, 22402, \n\t22403, 22404, 22405, 22406, 22407, 22408, 22409, 22410, \n\t22411, 22411, 22412, 22413, 22414, 22415, 22416, 22417, \n\t22418, 22419, 22420, 22421, 22422, 22423, 22424, 22425, \n\t22426, 22426, 22427, 22428, 22429, 22430, 22431, 22432, \n\t22433, 22434, 22435, 22436, 22437, 22438, 22439, 22440, \n\t22441, 22442, 22442, 22443, 22444, 22445, 22446, 22447, \n\t22448, 22449, 22450, 22451, 22452, 22453, 22454, 22455, \n\t22456, 22457, 22457, 22458, 22459, 22460, 22461, 22462, \n\t22463, 22464, 22465, 22466, 22467, 22468, 22469, 22470, \n\t22471, 22472, 22473, 22473, 22474, 22475, 22476, 22477, \n\t22478, 22479, 22480, 22481, 22482, 22483, 22484, 22485, \n\t22486, 22487, 22488, 22488, 22489, 22490, 22491, 22492, \n\t22493, 22494, 22495, 22496, 22497, 22498, 22499, 22500, \n\t22501, 22502, 22503, 22504, 22504, 22505, 22506, 22507, \n\t22508, 22509, 22510, 22511, 22512, 22513, 22514, 22515, \n\t22516, 22517, 22518, 22519, 22519, 22520, 22521, 22522, \n\t22523, 22524, 22525, 22526, 22527, 22528, 22529, 22530, \n\t22531, 22532, 22533, 22534, 22535, 22535, 22536, 22537, \n\t22538, 22539, 22540, 22541, 22542, 22543, 22544, 22545, \n\t22546, 22547, 22548, 22549, 22550, 22550, 22551, 22552, \n\t22553, 22554, 22555, 22556, 22557, 22558, 22559, 22560, \n\t22561, 22562, 22563, 22564, 22565, 22565, 22566, 22567, \n\t22568, 22569, 22570, 22571, 22572, 22573, 22574, 22575, \n\t22576, 22577, 22578, 22579, 22580, 22581, 22581, 22582, \n\t22583, 22584, 22585, 22586, 22587, 22588, 22589, 22590, \n\t22591, 22592, 22593, 22594, 22595, 22596, 22596, 22597, \n\t22598, 22599, 22600, 22601, 22602, 22603, 22604, 22605, \n\t22606, 22607, 22608, 22609, 22610, 22611, 22611, 22612, \n\t22613, 22614, 22615, 22616, 22617, 22618, 22619, 22620, \n\t22621, 22622, 22623, 22624, 22625, 22626, 22627, 22627, \n\t22628, 22629, 22630, 22631, 22632, 22633, 22634, 22635, \n\t22636, 22637, 22638, 22639, 22640, 22641, 22642, 22642, \n\t22643, 22644, 22645, 22646, 22647, 22648, 22649, 22650, \n\t22651, 22652, 22653, 22654, 22655, 22656, 22657, 22657, \n\t22658, 22659, 22660, 22661, 22662, 22663, 22664, 22665, \n\t22666, 22667, 22668, 22669, 22670, 22671, 22672, 22672, \n\t22673, 22674, 22675, 22676, 22677, 22678, 22679, 22680, \n\t22681, 22682, 22683, 22684, 22685, 22686, 22687, 22688, \n\t22688, 22689, 22690, 22691, 22692, 22693, 22694, 22695, \n\t22696, 22697, 22698, 22699, 22700, 22701, 22702, 22703, \n\t22703, 22704, 22705, 22706, 22707, 22708, 22709, 22710, \n\t22711, 22712, 22713, 22714, 22715, 22716, 22717, 22718, \n\t22718, 22719, 22720, 22721, 22722, 22723, 22724, 22725, \n\t22726, 22727, 22728, 22729, 22730, 22731, 22732, 22733, \n\t22733, 22734, 22735, 22736, 22737, 22738, 22739, 22740, \n\t22741, 22742, 22743, 22744, 22745, 22746, 22747, 22748, \n\t22748, 22749, 22750, 22751, 22752, 22753, 22754, 22755, \n\t22756, 22757, 22758, 22759, 22760, 22761, 22762, 22763, \n\t22763, 22764, 22765, 22766, 22767, 22768, 22769, 22770, \n\t22771, 22772, 22773, 22774, 22775, 22776, 22777, 22778, \n\t22778, 22779, 22780, 22781, 22782, 22783, 22784, 22785, \n\t22786, 22787, 22788, 22789, 22790, 22791, 22792, 22793, \n\t22793, 22794, 22795, 22796, 22797, 22798, 22799, 22800, \n\t22801, 22802, 22803, 22804, 22805, 22806, 22807, 22808, \n\t22808, 22809, 22810, 22811, 22812, 22813, 22814, 22815, \n\t22816, 22817, 22818, 22819, 22820, 22821, 22822, 22823, \n\t22823, 22824, 22825, 22826, 22827, 22828, 22829, 22830, \n\t22831, 22832, 22833, 22834, 22835, 22836, 22837, 22838, \n\t22838, 22839, 22840, 22841, 22842, 22843, 22844, 22845, \n\t22846, 22847, 22848, 22849, 22850, 22851, 22852, 22853, \n\t22853, 22854, 22855, 22856, 22857, 22858, 22859, 22860, \n\t22861, 22862, 22863, 22864, 22865, 22866, 22867, 22868, \n\t22868, 22869, 22870, 22871, 22872, 22873, 22874, 22875, \n\t22876, 22877, 22878, 22879, 22880, 22881, 22882, 22883, \n\t22883, 22884, 22885, 22886, 22887, 22888, 22889, 22890, \n\t22891, 22892, 22893, 22894, 22895, 22896, 22897, 22898, \n\t22898, 22899, 22900, 22901, 22902, 22903, 22904, 22905, \n\t22906, 22907, 22908, 22909, 22910, 22911, 22912, 22913, \n\t22913, 22914, 22915, 22916, 22917, 22918, 22919, 22920, \n\t22921, 22922, 22923, 22924, 22925, 22926, 22927, 22928, \n\t22928, 22929, 22930, 22931, 22932, 22933, 22934, 22935, \n\t22936, 22937, 22938, 22939, 22940, 22941, 22942, 22942, \n\t22943, 22944, 22945, 22946, 22947, 22948, 22949, 22950, \n\t22951, 22952, 22953, 22954, 22955, 22956, 22957, 22957, \n\t22958, 22959, 22960, 22961, 22962, 22963, 22964, 22965, \n\t22966, 22967, 22968, 22969, 22970, 22971, 22972, 22972, \n\t22973, 22974, 22975, 22976, 22977, 22978, 22979, 22980, \n\t22981, 22982, 22983, 22984, 22985, 22986, 22987, 22987, \n\t22988, 22989, 22990, 22991, 22992, 22993, 22994, 22995, \n\t22996, 22997, 22998, 22999, 23000, 23001, 23001, 23002, \n\t23003, 23004, 23005, 23006, 23007, 23008, 23009, 23010, \n\t23011, 23012, 23013, 23014, 23015, 23016, 23016, 23017, \n\t23018, 23019, 23020, 23021, 23022, 23023, 23024, 23025, \n\t23026, 23027, 23028, 23029, 23030, 23031, 23031, 23032, \n\t23033, 23034, 23035, 23036, 23037, 23038, 23039, 23040, \n\t23041, 23042, 23043, 23044, 23045, 23045, 23046, 23047, \n\t23048, 23049, 23050, 23051, 23052, 23053, 23054, 23055, \n\t23056, 23057, 23058, 23059, 23060, 23060, 23061, 23062, \n\t23063, 23064, 23065, 23066, 23067, 23068, 23069, 23070, \n\t23071, 23072, 23073, 23074, 23075, 23075, 23076, 23077, \n\t23078, 23079, 23080, 23081, 23082, 23083, 23084, 23085, \n\t23086, 23087, 23088, 23089, 23089, 23090, 23091, 23092, \n\t23093, 23094, 23095, 23096, 23097, 23098, 23099, 23100, \n\t23101, 23102, 23103, 23104, 23104, 23105, 23106, 23107, \n\t23108, 23109, 23110, 23111, 23112, 23113, 23114, 23115, \n\t23116, 23117, 23118, 23118, 23119, 23120, 23121, 23122, \n\t23123, 23124, 23125, 23126, 23127, 23128, 23129, 23130, \n\t23131, 23132, 23133, 23133, 23134, 23135, 23136, 23137, \n\t23138, 23139, 23140, 23141, 23142, 23143, 23144, 23145, \n\t23146, 23147, 23148, 23148, 23149, 23150, 23151, 23152, \n\t23153, 23154, 23155, 23156, 23157, 23158, 23159, 23160, \n\t23161, 23162, 23162, 23163, 23164, 23165, 23166, 23167, \n\t23168, 23169, 23170, 23171, 23172, 23173, 23174, 23175, \n\t23176, 23177, 23177, 23178, 23179, 23180, 23181, 23182, \n\t23183, 23184, 23185, 23186, 23187, 23188, 23189, 23190, \n\t23191, 23191, 23192, 23193, 23194, 23195, 23196, 23197, \n\t23198, 23199, 23200, 23201, 23202, 23203, 23204, 23205, \n\t23205, 23206, 23207, 23208, 23209, 23210, 23211, 23212, \n\t23213, 23214, 23215, 23216, 23217, 23218, 23219, 23220, \n\t23220, 23221, 23222, 23223, 23224, 23225, 23226, 23227, \n\t23228, 23229, 23230, 23231, 23232, 23233, 23234, 23234, \n\t23235, 23236, 23237, 23238, 23239, 23240, 23241, 23242, \n\t23243, 23244, 23245, 23246, 23247, 23248, 23249, 23249, \n\t23250, 23251, 23252, 23253, 23254, 23255, 23256, 23257, \n\t23258, 23259, 23260, 23261, 23262, 23263, 23263, 23264, \n\t23265, 23266, 23267, 23268, 23269, 23270, 23271, 23272, \n\t23273, 23274, 23275, 23276, 23277, 23277, 23278, 23279, \n\t23280, 23281, 23282, 23283, 23284, 23285, 23286, 23287, \n\t23288, 23289, 23290, 23291, 23292, 23292, 23293, 23294, \n\t23295, 23296, 23297, 23298, 23299, 23300, 23301, 23302, \n\t23303, 23304, 23305, 23306, 23306, 23307, 23308, 23309, \n\t23310, 23311, 23312, 23313, 23314, 23315, 23316, 23317, \n\t23318, 23319, 23320, 23320, 23321, 23322, 23323, 23324, \n\t23325, 23326, 23327, 23328, 23329, 23330, 23331, 23332, \n\t23333, 23334, 23335, 23335, 23336, 23337, 23338, 23339, \n\t23340, 23341, 23342, 23343, 23344, 23345, 23346, 23347, \n\t23348, 23349, 23349, 23350, 23351, 23352, 23353, 23354, \n\t23355, 23356, 23357, 23358, 23359, 23360, 23361, 23362, \n\t23363, 23363, 23364, 23365, 23366, 23367, 23368, 23369, \n\t23370, 23371, 23372, 23373, 23374, 23375, 23376, 23377, \n\t23377, 23378, 23379, 23380, 23381, 23382, 23383, 23384, \n\t23385, 23386, 23387, 23388, 23389, 23390, 23391, 23391, \n\t23392, 23393, 23394, 23395, 23396, 23397, 23398, 23399, \n\t23400, 23401, 23402, 23403, 23404, 23405, 23406, 23406, \n\t23407, 23408, 23409, 23410, 23411, 23412, 23413, 23414, \n\t23415, 23416, 23417, 23418, 23419, 23420, 23420, 23421, \n\t23422, 23423, 23424, 23425, 23426, 23427, 23428, 23429, \n\t23430, 23431, 23432, 23433, 23434, 23434, 23435, 23436, \n\t23437, 23438, 23439, 23440, 23441, 23442, 23443, 23444, \n\t23445, 23446, 23447, 23448, 23448, 23449, 23450, 23451, \n\t23452, 23453, 23454, 23455, 23456, 23457, 23458, 23459, \n\t23460, 23461, 23462, 23462, 23463, 23464, 23465, 23466, \n\t23467, 23468, 23469, 23470, 23471, 23472, 23473, 23474, \n\t23475, 23476, 23476, 23477, 23478, 23479, 23480, 23481, \n\t23482, 23483, 23484, 23485, 23486, 23487, 23488, 23489, \n\t23490, 23490, 23491, 23492, 23493, 23494, 23495, 23496, \n\t23497, 23498, 23499, 23500, 23501, 23502, 23503, 23504, \n\t23504, 23505, 23506, 23507, 23508, 23509, 23510, 23511, \n\t23512, 23513, 23514, 23515, 23516, 23517, 23518, 23518, \n\t23519, 23520, 23521, 23522, 23523, 23524, 23525, 23526, \n\t23527, 23528, 23529, 23530, 23531, 23532, 23532, 23533, \n\t23534, 23535, 23536, 23537, 23538, 23539, 23540, 23541, \n\t23542, 23543, 23544, 23545, 23546, 23546, 23547, 23548, \n\t23549, 23550, 23551, 23552, 23553, 23554, 23555, 23556, \n\t23557, 23558, 23559, 23560, 23560, 23561, 23562, 23563, \n\t23564, 23565, 23566, 23567, 23568, 23569, 23570, 23571, \n\t23572, 23573, 23574, 23574, 23575, 23576, 23577, 23578, \n\t23579, 23580, 23581, 23582, 23583, 23584, 23585, 23586, \n\t23587, 23588, 23588, 23589, 23590, 23591, 23592, 23593, \n\t23594, 23595, 23596, 23597, 23598, 23599, 23600, 23601, \n\t23602, 23602, 23603, 23604, 23605, 23606, 23607, 23608, \n\t23609, 23610, 23611, 23612, 23613, 23614, 23615, 23616, \n\t23616, 23617, 23618, 23619, 23620, 23621, 23622, 23623, \n\t23624, 23625, 23626, 23627, 23628, 23629, 23630, 23630, \n\t23631, 23632, 23633, 23634, 23635, 23636, 23637, 23638, \n\t23639, 23640, 23641, 23642, 23643, 23644, 23644, 23645, \n\t23646, 23647, 23648, 23649, 23650, 23651, 23652, 23653, \n\t23654, 23655, 23656, 23657, 23658, 23658, 23659, 23660, \n\t23661, 23662, 23663, 23664, 23665, 23666, 23667, 23668, \n\t23669, 23670, 23671, 23671, 23672, 23673, 23674, 23675, \n\t23676, 23677, 23678, 23679, 23680, 23681, 23682, 23683, \n\t23684, 23685, 23685, 23686, 23687, 23688, 23689, 23690, \n\t23691, 23692, 23693, 23694, 23695, 23696, 23697, 23698, \n\t23699, 23699, 23700, 23701, 23702, 23703, 23704, 23705, \n\t23706, 23707, 23708, 23709, 23710, 23711, 23712, 23713, \n\t23713, 23714, 23715, 23716, 23717, 23718, 23719, 23720, \n\t23721, 23722, 23723, 23724, 23725, 23726, 23726, 23727, \n\t23728, 23729, 23730, 23731, 23732, 23733, 23734, 23735, \n\t23736, 23737, 23738, 23739, 23740, 23740, 23741, 23742, \n\t23743, 23744, 23745, 23746, 23747, 23748, 23749, 23750, \n\t23751, 23752, 23753, 23754, 23754, 23755, 23756, 23757, \n\t23758, 23759, 23760, 23761, 23762, 23763, 23764, 23765, \n\t23766, 23767, 23768, 23768, 23769, 23770, 23771, 23772, \n\t23773, 23774, 23775, 23776, 23777, 23778, 23779, 23780, \n\t23781, 23781, 23782, 23783, 23784, 23785, 23786, 23787, \n\t23788, 23789, 23790, 23791, 23792, 23793, 23794, 23795, \n\t23795, 23796, 23797, 23798, 23799, 23800, 23801, 23802, \n\t23803, 23804, 23805, 23806, 23807, 23808, 23809, 23809, \n\t23810, 23811, 23812, 23813, 23814, 23815, 23816, 23817, \n\t23818, 23819, 23820, 23821, 23822, 23822, 23823, 23824, \n\t23825, 23826, 23827, 23828, 23829, 23830, 23831, 23832, \n\t23833, 23834, 23835, 23836, 23836, 23837, 23838, 23839, \n\t23840, 23841, 23842, 23843, 23844, 23845, 23846, 23847, \n\t23848, 23849, 23849, 23850, 23851, 23852, 23853, 23854, \n\t23855, 23856, 23857, 23858, 23859, 23860, 23861, 23862, \n\t23863, 23863, 23864, 23865, 23866, 23867, 23868, 23869, \n\t23870, 23871, 23872, 23873, 23874, 23875, 23876, 23877, \n\t23877, 23878, 23879, 23880, 23881, 23882, 23883, 23884, \n\t23885, 23886, 23887, 23888, 23889, 23890, 23890, 23891, \n\t23892, 23893, 23894, 23895, 23896, 23897, 23898, 23899, \n\t23900, 23901, 23902, 23903, 23904, 23904, 23905, 23906, \n\t23907, 23908, 23909, 23910, 23911, 23912, 23913, 23914, \n\t23915, 23916, 23917, 23917, 23918, 23919, 23920, 23921, \n\t23922, 23923, 23924, 23925, 23926, 23927, 23928, 23929, \n\t23930, 23931, 23931, 23932, 23933, 23934, 23935, 23936, \n\t23937, 23938, 23939, 23940, 23941, 23942, 23943, 23944, \n\t23944, 23945, 23946, 23947, 23948, 23949, 23950, 23951, \n\t23952, 23953, 23954, 23955, 23956, 23957, 23958, 23958, \n\t23959, 23960, 23961, 23962, 23963, 23964, 23965, 23966, \n\t23967, 23968, 23969, 23970, 23971, 23971, 23972, 23973, \n\t23974, 23975, 23976, 23977, 23978, 23979, 23980, 23981, \n\t23982, 23983, 23984, 23984, 23985, 23986, 23987, 23988, \n\t23989, 23990, 23991, 23992, 23993, 23994, 23995, 23996, \n\t23997, 23998, 23998, 23999, 24000, 24001, 24002, 24003, \n\t24004, 24005, 24006, 24007, 24008, 24009, 24010, 24011, \n\t24011, 24012, 24013, 24014, 24015, 24016, 24017, 24018, \n\t24019, 24020, 24021, 24022, 24023, 24024, 24025, 24025, \n\t24026, 24027, 24028, 24029, 24030, 24031, 24032, 24033, \n\t24034, 24035, 24036, 24037, 24038, 24038, 24039, 24040, \n\t24041, 24042, 24043, 24044, 24045, 24046, 24047, 24048, \n\t24049, 24050, 24051, 24051, 24052, 24053, 24054, 24055, \n\t24056, 24057, 24058, 24059, 24060, 24061, 24062, 24063, \n\t24064, 24065, 24065, 24066, 24067, 24068, 24069, 24070, \n\t24071, 24072, 24073, 24074, 24075, 24076, 24077, 24078, \n\t24078, 24079, 24080, 24081, 24082, 24083, 24084, 24085, \n\t24086, 24087, 24088, 24089, 24090, 24091, 24091, 24092, \n\t24093, 24094, 24095, 24096, 24097, 24098, 24099, 24100, \n\t24101, 24102, 24103, 24104, 24104, 24105, 24106, 24107, \n\t24108, 24109, 24110, 24111, 24112, 24113, 24114, 24115, \n\t24116, 24117, 24118, 24118, 24119, 24120, 24121, 24122, \n\t24123, 24124, 24125, 24126, 24127, 24128, 24129, 24130, \n\t24131, 24131, 24132, 24133, 24134, 24135, 24136, 24137, \n\t24138, 24139, 24140, 24141, 24142, 24143, 24144, 24144, \n\t24145, 24146, 24147, 24148, 24149, 24150, 24151, 24152, \n\t24153, 24154, 24155, 24156, 24157, 24157, 24158, 24159, \n\t24160, 24161, 24162, 24163, 24164, 24165, 24166, 24167, \n\t24168, 24169, 24170, 24171, 24171, 24172, 24173, 24174, \n\t24175, 24176, 24177, 24178, 24179, 24180, 24181, 24182, \n\t24183, 24184, 24184, 24185, 24186, 24187, 24188, 24189, \n\t24190, 24191, 24192, 24193, 24194, 24195, 24196, 24197, \n\t24197, 24198, 24199, 24200, 24201, 24202, 24203, 24204, \n\t24205, 24206, 24207, 24208, 24209, 24210, 24210, 24211, \n\t24212, 24213, 24214, 24215, 24216, 24217, 24218, 24219, \n\t24220, 24221, 24222, 24223, 24223, 24224, 24225, 24226, \n\t24227, 24228, 24229, 24230, 24231, 24232, 24233, 24234, \n\t24235, 24236, 24236, 24237, 24238, 24239, 24240, 24241, \n\t24242, 24243, 24244, 24245, 24246, 24247, 24248, 24249, \n\t24249, 24250, 24251, 24252, 24253, 24254, 24255, 24256, \n\t24257, 24258, 24259, 24260, 24261, 24262, 24263, 24263, \n\t24264, 24265, 24266, 24267, 24268, 24269, 24270, 24271, \n\t24272, 24273, 24274, 24275, 24276, 24276, 24277, 24278, \n\t24279, 24280, 24281, 24282, 24283, 24284, 24285, 24286, \n\t24287, 24288, 24289, 24289, 24290, 24291, 24292, 24293, \n\t24294, 24295, 24296, 24297, 24298, 24299, 24300, 24301, \n\t24302, 24302, 24303, 24304, 24305, 24306, 24307, 24308, \n\t24309, 24310, 24311, 24312, 24313, 24314, 24315, 24315, \n\t24316, 24317, 24318, 24319, 24320, 24321, 24322, 24323, \n\t24324, 24325, 24326, 24327, 24328, 24328, 24329, 24330, \n\t24331, 24332, 24333, 24334, 24335, 24336, 24337, 24338, \n\t24339, 24340, 24341, 24341, 24342, 24343, 24344, 24345, \n\t24346, 24347, 24348, 24349, 24350, 24351, 24352, 24353, \n\t24354, 24354, 24355, 24356, 24357, 24358, 24359, 24360, \n\t24361, 24362, 24363, 24364, 24365, 24366, 24367, 24367, \n\t24368, 24369, 24370, 24371, 24372, 24373, 24374, 24375, \n\t24376, 24377, 24378, 24379, 24380, 24380, 24381, 24382, \n\t24383, 24384, 24385, 24386, 24387, 24388, 24389, 24390, \n\t24391, 24392, 24392, 24393, 24394, 24395, 24396, 24397, \n\t24398, 24399, 24400, 24401, 24402, 24403, 24404, 24405, \n\t24405, 24406, 24407, 24408, 24409, 24410, 24411, 24412, \n\t24413, 24414, 24415, 24416, 24417, 24418, 24418, 24419, \n\t24420, 24421, 24422, 24423, 24424, 24425, 24426, 24427, \n\t24428, 24429, 24430, 24431, 24431, 24432, 24433, 24434, \n\t24435, 24436, 24437, 24438, 24439, 24440, 24441, 24442, \n\t24443, 24444, 24444, 24445, 24446, 24447, 24448, 24449, \n\t24450, 24451, 24452, 24453, 24454, 24455, 24456, 24457, \n\t24457, 24458, 24459, 24460, 24461, 24462, 24463, 24464, \n\t24465, 24466, 24467, 24468, 24469, 24470, 24470, 24471, \n\t24472, 24473, 24474, 24475, 24476, 24477, 24478, 24479, \n\t24480, 24481, 24482, 24483, 24483, 24484, 24485, 24486, \n\t24487, 24488, 24489, 24490, 24491, 24492, 24493, 24494, \n\t24495, 24495, 24496, 24497, 24498, 24499, 24500, 24501, \n\t24502, 24503, 24504, 24505, 24506, 24507, 24508, 24508, \n\t24509, 24510, 24511, 24512, 24513, 24514, 24515, 24516, \n\t24517, 24518, 24519, 24520, 24521, 24521, 24522, 24523, \n\t24524, 24525, 24526, 24527, 24528, 24529, 24530, 24531, \n\t24532, 24533, 24534, 24534, 24535, 24536, 24537, 24538, \n\t24539, 24540, 24541, 24542, 24543, 24544, 24545, 24546, \n\t24546, 24547, 24548, 24549, 24550, 24551, 24552, 24553, \n\t24554, 24555, 24556, 24557, 24558, 24559, 24559, 24560, \n\t24561, 24562, 24563, 24564, 24565, 24566, 24567, 24568, \n\t24569, 24570, 24571, 24572, 24572, 24573, 24574, 24575, \n\t24576, 24577, 24578, 24579, 24580, 24581, 24582, 24583, \n\t24584, 24585, 24585, 24586, 24587, 24588, 24589, 24590, \n\t24591, 24592, 24593, 24594, 24595, 24596, 24597, 24597, \n\t24598, 24599, 24600, 24601, 24602, 24603, 24604, 24605, \n\t24606, 24607, 24608, 24609, 24610, 24610, 24611, 24612, \n\t24613, 24614, 24615, 24616, 24617, 24618, 24619, 24620, \n\t24621, 24622, 24623, 24623, 24624, 24625, 24626, 24627, \n\t24628, 24629, 24630, 24631, 24632, 24633, 24634, 24635, \n\t24635, 24636, 24637, 24638, 24639, 24640, 24641, 24642, \n\t24643, 24644, 24645, 24646, 24647, 24648, 24648, 24649, \n\t24650, 24651, 24652, 24653, 24654, 24655, 24656, 24657, \n\t24658, 24659, 24660, 24660, 24661, 24662, 24663, 24664, \n\t24665, 24666, 24667, 24668, 24669, 24670, 24671, 24672, \n\t24673, 24673, 24674, 24675, 24676, 24677, 24678, 24679, \n\t24680, 24681, 24682, 24683, 24684, 24685, 24686, 24686, \n\t24687, 24688, 24689, 24690, 24691, 24692, 24693, 24694, \n\t24695, 24696, 24697, 24698, 24698, 24699, 24700, 24701, \n\t24702, 24703, 24704, 24705, 24706, 24707, 24708, 24709, \n\t24710, 24711, 24711, 24712, 24713, 24714, 24715, 24716, \n\t24717, 24718, 24719, 24720, 24721, 24722, 24723, 24723, \n\t24724, 24725, 24726, 24727, 24728, 24729, 24730, 24731, \n\t24732, 24733, 24734, 24735, 24736, 24736, 24737, 24738, \n\t24739, 24740, 24741, 24742, 24743, 24744, 24745, 24746, \n\t24747, 24748, 24748, 24749, 24750, 24751, 24752, 24753, \n\t24754, 24755, 24756, 24757, 24758, 24759, 24760, 24761, \n\t24761, 24762, 24763, 24764, 24765, 24766, 24767, 24768, \n\t24769, 24770, 24771, 24772, 24773, 24773, 24774, 24775, \n\t24776, 24777, 24778, 24779, 24780, 24781, 24782, 24783, \n\t24784, 24785, 24786, 24786, 24787, 24788, 24789, 24790, \n\t24791, 24792, 24793, 24794, 24795, 24796, 24797, 24798, \n\t24798, 24799, 24800, 24801, 24802, 24803, 24804, 24805, \n\t24806, 24807, 24808, 24809, 24810, 24811, 24811, 24812, \n\t24813, 24814, 24815, 24816, 24817, 24818, 24819, 24820, \n\t24821, 24822, 24823, 24823, 24824, 24825, 24826, 24827, \n\t24828, 24829, 24830, 24831, 24832, 24833, 24834, 24835, \n\t24836, 24836, 24837, 24838, 24839, 24840, 24841, 24842, \n\t24843, 24844, 24845, 24846, 24847, 24848, 24848, 24849, \n\t24850, 24851, 24852, 24853, 24854, 24855, 24856, 24857, \n\t24858, 24859, 24860, 24860, 24861, 24862, 24863, 24864, \n\t24865, 24866, 24867, 24868, 24869, 24870, 24871, 24872, \n\t24873, 24873, 24874, 24875, 24876, 24877, 24878, 24879, \n\t24880, 24881, 24882, 24883, 24884, 24885, 24885, 24886, \n\t24887, 24888, 24889, 24890, 24891, 24892, 24893, 24894, \n\t24895, 24896, 24897, 24897, 24898, 24899, 24900, 24901, \n\t24902, 24903, 24904, 24905, 24906, 24907, 24908, 24909, \n\t24910, 24910, 24911, 24912, 24913, 24914, 24915, 24916, \n\t24917, 24918, 24919, 24920, 24921, 24922, 24922, 24923, \n\t24924, 24925, 24926, 24927, 24928, 24929, 24930, 24931, \n\t24932, 24933, 24934, 24934, 24935, 24936, 24937, 24938, \n\t24939, 24940, 24941, 24942, 24943, 24944, 24945, 24946, \n\t24947, 24947, 24948, 24949, 24950, 24951, 24952, 24953, \n\t24954, 24955, 24956, 24957, 24958, 24959, 24959, 24960, \n\t24961, 24962, 24963, 24964, 24965, 24966, 24967, 24968, \n\t24969, 24970, 24971, 24971, 24972, 24973, 24974, 24975, \n\t24976, 24977, 24978, 24979, 24980, 24981, 24982, 24983, \n\t24983, 24984, 24985, 24986, 24987, 24988, 24989, 24990, \n\t24991, 24992, 24993, 24994, 24995, 24996, 24996, 24997, \n\t24998, 24999, 25000, 25001, 25002, 25003, 25004, 25005, \n\t25006, 25007, 25008, 25008, 25009, 25010, 25011, 25012, \n\t25013, 25014, 25015, 25016, 25017, 25018, 25019, 25020, \n\t25020, 25021, 25022, 25023, 25024, 25025, 25026, 25027, \n\t25028, 25029, 25030, 25031, 25032, 25032, 25033, 25034, \n\t25035, 25036, 25037, 25038, 25039, 25040, 25041, 25042, \n\t25043, 25044, 25044, 25045, 25046, 25047, 25048, 25049, \n\t25050, 25051, 25052, 25053, 25054, 25055, 25056, 25057, \n\t25057, 25058, 25059, 25060, 25061, 25062, 25063, 25064, \n\t25065, 25066, 25067, 25068, 25069, 25069, 25070, 25071, \n\t25072, 25073, 25074, 25075, 25076, 25077, 25078, 25079, \n\t25080, 25081, 25081, 25082, 25083, 25084, 25085, 25086, \n\t25087, 25088, 25089, 25090, 25091, 25092, 25093, 25093, \n\t25094, 25095, 25096, 25097, 25098, 25099, 25100, 25101, \n\t25102, 25103, 25104, 25105, 25105, 25106, 25107, 25108, \n\t25109, 25110, 25111, 25112, 25113, 25114, 25115, 25116, \n\t25117, 25117, 25118, 25119, 25120, 25121, 25122, 25123, \n\t25124, 25125, 25126, 25127, 25128, 25129, 25129, 25130, \n\t25131, 25132, 25133, 25134, 25135, 25136, 25137, 25138, \n\t25139, 25140, 25141, 25141, 25142, 25143, 25144, 25145, \n\t25146, 25147, 25148, 25149, 25150, 25151, 25152, 25153, \n\t25154, 25154, 25155, 25156, 25157, 25158, 25159, 25160, \n\t25161, 25162, 25163, 25164, 25165, 25166, 25166, 25167, \n\t25168, 25169, 25170, 25171, 25172, 25173, 25174, 25175, \n\t25176, 25177, 25178, 25178, 25179, 25180, 25181, 25182, \n\t25183, 25184, 25185, 25186, 25187, 25188, 25189, 25190, \n\t25190, 25191, 25192, 25193, 25194, 25195, 25196, 25197, \n\t25198, 25199, 25200, 25201, 25202, 25202, 25203, 25204, \n\t25205, 25206, 25207, 25208, 25209, 25210, 25211, 25212, \n\t25213, 25214, 25214, 25215, 25216, 25217, 25218, 25219, \n\t25220, 25221, 25222, 25223, 25224, 25225, 25226, 25226, \n\t25227, 25228, 25229, 25230, 25231, 25232, 25233, 25234, \n\t25235, 25236, 25237, 25238, 25238, 25239, 25240, 25241, \n\t25242, 25243, 25244, 25245, 25246, 25247, 25248, 25249, \n\t25250, 25250, 25251, 25252, 25253, 25254, 25255, 25256, \n\t25257, 25258, 25259, 25260, 25261, 25261, 25262, 25263, \n\t25264, 25265, 25266, 25267, 25268, 25269, 25270, 25271, \n\t25272, 25273, 25273, 25274, 25275, 25276, 25277, 25278, \n\t25279, 25280, 25281, 25282, 25283, 25284, 25285, 25285, \n\t25286, 25287, 25288, 25289, 25290, 25291, 25292, 25293, \n\t25294, 25295, 25296, 25297, 25297, 25298, 25299, 25300, \n\t25301, 25302, 25303, 25304, 25305, 25306, 25307, 25308, \n\t25309, 25309, 25310, 25311, 25312, 25313, 25314, 25315, \n\t25316, 25317, 25318, 25319, 25320, 25321, 25321, 25322, \n\t25323, 25324, 25325, 25326, 25327, 25328, 25329, 25330, \n\t25331, 25332, 25333, 25333, 25334, 25335, 25336, 25337, \n\t25338, 25339, 25340, 25341, 25342, 25343, 25344, 25345, \n\t25345, 25346, 25347, 25348, 25349, 25350, 25351, 25352, \n\t25353, 25354, 25355, 25356, 25357, 25357, 25358, 25359, \n\t25360, 25361, 25362, 25363, 25364, 25365, 25366, 25367, \n\t25368, 25368, 25369, 25370, 25371, 25372, 25373, 25374, \n\t25375, 25376, 25377, 25378, 25379, 25380, 25380, 25381, \n\t25382, 25383, 25384, 25385, 25386, 25387, 25388, 25389, \n\t25390, 25391, 25392, 25392, 25393, 25394, 25395, 25396, \n\t25397, 25398, 25399, 25400, 25401, 25402, 25403, 25404, \n\t25404, 25405, 25406, 25407, 25408, 25409, 25410, 25411, \n\t25412, 25413, 25414, 25415, 25416, 25416, 25417, 25418, \n\t25419, 25420, 25421, 25422, 25423, 25424, 25425, 25426, \n\t25427, 25427, 25428, 25429, 25430, 25431, 25432, 25433, \n\t25434, 25435, 25436, 25437, 25438, 25439, 25439, 25440, \n\t25441, 25442, 25443, 25444, 25445, 25446, 25447, 25448, \n\t25449, 25450, 25451, 25451, 25452, 25453, 25454, 25455, \n\t25456, 25457, 25458, 25459, 25460, 25461, 25462, 25463, \n\t25463, 25464, 25465, 25466, 25467, 25468, 25469, 25470, \n\t25471, 25472, 25473, 25474, 25474, 25475, 25476, 25477, \n\t25478, 25479, 25480, 25481, 25482, 25483, 25484, 25485, \n\t25486, 25486, 25487, 25488, 25489, 25490, 25491, 25492, \n\t25493, 25494, 25495, 25496, 25497, 25498, 25498, 25499, \n\t25500, 25501, 25502, 25503, 25504, 25505, 25506, 25507, \n\t25508, 25509, 25509, 25510, 25511, 25512, 25513, 25514, \n\t25515, 25516, 25517, 25518, 25519, 25520, 25521, 25521, \n\t25522, 25523, 25524, 25525, 25526, 25527, 25528, 25529, \n\t25530, 25531, 25532, 25533, 25533, 25534, 25535, 25536, \n\t25537, 25538, 25539, 25540, 25541, 25542, 25543, 25544, \n\t25544, 25545, 25546, 25547, 25548, 25549, 25550, 25551, \n\t25552, 25553, 25554, 25555, 25556, 25556, 25557, 25558, \n\t25559, 25560, 25561, 25562, 25563, 25564, 25565, 25566, \n\t25567, 25568, 25568, 25569, 25570, 25571, 25572, 25573, \n\t25574, 25575, 25576, 25577, 25578, 25579, 25579, 25580, \n\t25581, 25582, 25583, 25584, 25585, 25586, 25587, 25588, \n\t25589, 25590, 25591, 25591, 25592, 25593, 25594, 25595, \n\t25596, 25597, 25598, 25599, 25600, 25601, 25602, 25603, \n\t25603, 25604, 25605, 25606, 25607, 25608, 25609, 25610, \n\t25611, 25612, 25613, 25614, 25614, 25615, 25616, 25617, \n\t25618, 25619, 25620, 25621, 25622, 25623, 25624, 25625, \n\t25626, 25626, 25627, 25628, 25629, 25630, 25631, 25632, \n\t25633, 25634, 25635, 25636, 25637, 25637, 25638, 25639, \n\t25640, 25641, 25642, 25643, 25644, 25645, 25646, 25647, \n\t25648, 25649, 25649, 25650, 25651, 25652, 25653, 25654, \n\t25655, 25656, 25657, 25658, 25659, 25660, 25660, 25661, \n\t25662, 25663, 25664, 25665, 25666, 25667, 25668, 25669, \n\t25670, 25671, 25672, 25672, 25673, 25674, 25675, 25676, \n\t25677, 25678, 25679, 25680, 25681, 25682, 25683, 25683, \n\t25684, 25685, 25686, 25687, 25688, 25689, 25690, 25691, \n\t25692, 25693, 25694, 25695, 25695, 25696, 25697, 25698, \n\t25699, 25700, 25701, 25702, 25703, 25704, 25705, 25706, \n\t25706, 25707, 25708, 25709, 25710, 25711, 25712, 25713, \n\t25714, 25715, 25716, 25717, 25718, 25718, 25719, 25720, \n\t25721, 25722, 25723, 25724, 25725, 25726, 25727, 25728, \n\t25729, 25729, 25730, 25731, 25732, 25733, 25734, 25735, \n\t25736, 25737, 25738, 25739, 25740, 25741, 25741, 25742, \n\t25743, 25744, 25745, 25746, 25747, 25748, 25749, 25750, \n\t25751, 25752, 25752, 25753, 25754, 25755, 25756, 25757, \n\t25758, 25759, 25760, 25761, 25762, 25763, 25764, 25764, \n\t25765, 25766, 25767, 25768, 25769, 25770, 25771, 25772, \n\t25773, 25774, 25775, 25775, 25776, 25777, 25778, 25779, \n\t25780, 25781, 25782, 25783, 25784, 25785, 25786, 25786, \n\t25787, 25788, 25789, 25790, 25791, 25792, 25793, 25794, \n\t25795, 25796, 25797, 25798, 25798, 25799, 25800, 25801, \n\t25802, 25803, 25804, 25805, 25806, 25807, 25808, 25809, \n\t25809, 25810, 25811, 25812, 25813, 25814, 25815, 25816, \n\t25817, 25818, 25819, 25820, 25821, 25821, 25822, 25823, \n\t25824, 25825, 25826, 25827, 25828, 25829, 25830, 25831, \n\t25832, 25832, 25833, 25834, 25835, 25836, 25837, 25838, \n\t25839, 25840, 25841, 25842, 25843, 25843, 25844, 25845, \n\t25846, 25847, 25848, 25849, 25850, 25851, 25852, 25853, \n\t25854, 25855, 25855, 25856, 25857, 25858, 25859, 25860, \n\t25861, 25862, 25863, 25864, 25865, 25866, 25866, 25867, \n\t25868, 25869, 25870, 25871, 25872, 25873, 25874, 25875, \n\t25876, 25877, 25877, 25878, 25879, 25880, 25881, 25882, \n\t25883, 25884, 25885, 25886, 25887, 25888, 25888, 25889, \n\t25890, 25891, 25892, 25893, 25894, 25895, 25896, 25897, \n\t25898, 25899, 25900, 25900, 25901, 25902, 25903, 25904, \n\t25905, 25906, 25907, 25908, 25909, 25910, 25911, 25911, \n\t25912, 25913, 25914, 25915, 25916, 25917, 25918, 25919, \n\t25920, 25921, 25922, 25922, 25923, 25924, 25925, 25926, \n\t25927, 25928, 25929, 25930, 25931, 25932, 25933, 25934, \n\t25934, 25935, 25936, 25937, 25938, 25939, 25940, 25941, \n\t25942, 25943, 25944, 25945, 25945, 25946, 25947, 25948, \n\t25949, 25950, 25951, 25952, 25953, 25954, 25955, 25956, \n\t25956, 25957, 25958, 25959, 25960, 25961, 25962, 25963, \n\t25964, 25965, 25966, 25967, 25967, 25968, 25969, 25970, \n\t25971, 25972, 25973, 25974, 25975, 25976, 25977, 25978, \n\t25979, 25979, 25980, 25981, 25982, 25983, 25984, 25985, \n\t25986, 25987, 25988, 25989, 25990, 25990, 25991, 25992, \n\t25993, 25994, 25995, 25996, 25997, 25998, 25999, 26000, \n\t26001, 26001, 26002, 26003, 26004, 26005, 26006, 26007, \n\t26008, 26009, 26010, 26011, 26012, 26012, 26013, 26014, \n\t26015, 26016, 26017, 26018, 26019, 26020, 26021, 26022, \n\t26023, 26023, 26024, 26025, 26026, 26027, 26028, 26029, \n\t26030, 26031, 26032, 26033, 26034, 26034, 26035, 26036, \n\t26037, 26038, 26039, 26040, 26041, 26042, 26043, 26044, \n\t26045, 26046, 26046, 26047, 26048, 26049, 26050, 26051, \n\t26052, 26053, 26054, 26055, 26056, 26057, 26057, 26058, \n\t26059, 26060, 26061, 26062, 26063, 26064, 26065, 26066, \n\t26067, 26068, 26068, 26069, 26070, 26071, 26072, 26073, \n\t26074, 26075, 26076, 26077, 26078, 26079, 26079, 26080, \n\t26081, 26082, 26083, 26084, 26085, 26086, 26087, 26088, \n\t26089, 26090, 26090, 26091, 26092, 26093, 26094, 26095, \n\t26096, 26097, 26098, 26099, 26100, 26101, 26101, 26102, \n\t26103, 26104, 26105, 26106, 26107, 26108, 26109, 26110, \n\t26111, 26112, 26112, 26113, 26114, 26115, 26116, 26117, \n\t26118, 26119, 26120, 26121, 26122, 26123, 26123, 26124, \n\t26125, 26126, 26127, 26128, 26129, 26130, 26131, 26132, \n\t26133, 26134, 26134, 26135, 26136, 26137, 26138, 26139, \n\t26140, 26141, 26142, 26143, 26144, 26145, 26145, 26146, \n\t26147, 26148, 26149, 26150, 26151, 26152, 26153, 26154, \n\t26155, 26156, 26156, 26157, 26158, 26159, 26160, 26161, \n\t26162, 26163, 26164, 26165, 26166, 26167, 26167, 26168, \n\t26169, 26170, 26171, 26172, 26173, 26174, 26175, 26176, \n\t26177, 26178, 26178, 26179, 26180, 26181, 26182, 26183, \n\t26184, 26185, 26186, 26187, 26188, 26189, 26189, 26190, \n\t26191, 26192, 26193, 26194, 26195, 26196, 26197, 26198, \n\t26199, 26200, 26200, 26201, 26202, 26203, 26204, 26205, \n\t26206, 26207, 26208, 26209, 26210, 26211, 26211, 26212, \n\t26213, 26214, 26215, 26216, 26217, 26218, 26219, 26220, \n\t26221, 26222, 26222, 26223, 26224, 26225, 26226, 26227, \n\t26228, 26229, 26230, 26231, 26232, 26233, 26233, 26234, \n\t26235, 26236, 26237, 26238, 26239, 26240, 26241, 26242, \n\t26243, 26244, 26244, 26245, 26246, 26247, 26248, 26249, \n\t26250, 26251, 26252, 26253, 26254, 26255, 26255, 26256, \n\t26257, 26258, 26259, 26260, 26261, 26262, 26263, 26264, \n\t26265, 26266, 26266, 26267, 26268, 26269, 26270, 26271, \n\t26272, 26273, 26274, 26275, 26276, 26277, 26277, 26278, \n\t26279, 26280, 26281, 26282, 26283, 26284, 26285, 26286, \n\t26287, 26288, 26288, 26289, 26290, 26291, 26292, 26293, \n\t26294, 26295, 26296, 26297, 26298, 26299, 26299, 26300, \n\t26301, 26302, 26303, 26304, 26305, 26306, 26307, 26308, \n\t26309, 26310, 26310, 26311, 26312, 26313, 26314, 26315, \n\t26316, 26317, 26318, 26319, 26320, 26321, 26321, 26322, \n\t26323, 26324, 26325, 26326, 26327, 26328, 26329, 26330, \n\t26331, 26332, 26332, 26333, 26334, 26335, 26336, 26337, \n\t26338, 26339, 26340, 26341, 26342, 26342, 26343, 26344, \n\t26345, 26346, 26347, 26348, 26349, 26350, 26351, 26352, \n\t26353, 26353, 26354, 26355, 26356, 26357, 26358, 26359, \n\t26360, 26361, 26362, 26363, 26364, 26364, 26365, 26366, \n\t26367, 26368, 26369, 26370, 26371, 26372, 26373, 26374, \n\t26375, 26375, 26376, 26377, 26378, 26379, 26380, 26381, \n\t26382, 26383, 26384, 26385, 26386, 26386, 26387, 26388, \n\t26389, 26390, 26391, 26392, 26393, 26394, 26395, 26396, \n\t26397, 26397, 26398, 26399, 26400, 26401, 26402, 26403, \n\t26404, 26405, 26406, 26407, 26407, 26408, 26409, 26410, \n\t26411, 26412, 26413, 26414, 26415, 26416, 26417, 26418, \n\t26418, 26419, 26420, 26421, 26422, 26423, 26424, 26425, \n\t26426, 26427, 26428, 26429, 26429, 26430, 26431, 26432, \n\t26433, 26434, 26435, 26436, 26437, 26438, 26439, 26440, \n\t26440, 26441, 26442, 26443, 26444, 26445, 26446, 26447, \n\t26448, 26449, 26450, 26451, 26451, 26452, 26453, 26454, \n\t26455, 26456, 26457, 26458, 26459, 26460, 26461, 26461, \n\t26462, 26463, 26464, 26465, 26466, 26467, 26468, 26469, \n\t26470, 26471, 26472, 26472, 26473, 26474, 26475, 26476, \n\t26477, 26478, 26479, 26480, 26481, 26482, 26483, 26483, \n\t26484, 26485, 26486, 26487, 26488, 26489, 26490, 26491, \n\t26492, 26493, 26493, 26494, 26495, 26496, 26497, 26498, \n\t26499, 26500, 26501, 26502, 26503, 26504, 26504, 26505, \n\t26506, 26507, 26508, 26509, 26510, 26511, 26512, 26513, \n\t26514, 26515, 26515, 26516, 26517, 26518, 26519, 26520, \n\t26521, 26522, 26523, 26524, 26525, 26526, 26526, 26527, \n\t26528, 26529, 26530, 26531, 26532, 26533, 26534, 26535, \n\t26536, 26536, 26537, 26538, 26539, 26540, 26541, 26542, \n\t26543, 26544, 26545, 26546, 26547, 26547, 26548, 26549, \n\t26550, 26551, 26552, 26553, 26554, 26555, 26556, 26557, \n\t26558, 26558, 26559, 26560, 26561, 26562, 26563, 26564, \n\t26565, 26566, 26567, 26568, 26568, 26569, 26570, 26571, \n\t26572, 26573, 26574, 26575, 26576, 26577, 26578, 26579, \n\t26579, 26580, 26581, 26582, 26583, 26584, 26585, 26586, \n\t26587, 26588, 26589, 26590, 26590, 26591, 26592, 26593, \n\t26594, 26595, 26596, 26597, 26598, 26599, 26600, 26600, \n\t26601, 26602, 26603, 26604, 26605, 26606, 26607, 26608, \n\t26609, 26610, 26611, 26611, 26612, 26613, 26614, 26615, \n\t26616, 26617, 26618, 26619, 26620, 26621, 26621, 26622, \n\t26623, 26624, 26625, 26626, 26627, 26628, 26629, 26630, \n\t26631, 26632, 26632, 26633, 26634, 26635, 26636, 26637, \n\t26638, 26639, 26640, 26641, 26642, 26643, 26643, 26644, \n\t26645, 26646, 26647, 26648, 26649, 26650, 26651, 26652, \n\t26653, 26653, 26654, 26655, 26656, 26657, 26658, 26659, \n\t26660, 26661, 26662, 26663, 26664, 26664, 26665, 26666, \n\t26667, 26668, 26669, 26670, 26671, 26672, 26673, 26674, \n\t26674, 26675, 26676, 26677, 26678, 26679, 26680, 26681, \n\t26682, 26683, 26684, 26685, 26685, 26686, 26687, 26688, \n\t26689, 26690, 26691, 26692, 26693, 26694, 26695, 26695, \n\t26696, 26697, 26698, 26699, 26700, 26701, 26702, 26703, \n\t26704, 26705, 26706, 26706, 26707, 26708, 26709, 26710, \n\t26711, 26712, 26713, 26714, 26715, 26716, 26716, 26717, \n\t26718, 26719, 26720, 26721, 26722, 26723, 26724, 26725, \n\t26726, 26727, 26727, 26728, 26729, 26730, 26731, 26732, \n\t26733, 26734, 26735, 26736, 26737, 26737, 26738, 26739, \n\t26740, 26741, 26742, 26743, 26744, 26745, 26746, 26747, \n\t26748, 26748, 26749, 26750, 26751, 26752, 26753, 26754, \n\t26755, 26756, 26757, 26758, 26758, 26759, 26760, 26761, \n\t26762, 26763, 26764, 26765, 26766, 26767, 26768, 26769, \n\t26769, 26770, 26771, 26772, 26773, 26774, 26775, 26776, \n\t26777, 26778, 26779, 26779, 26780, 26781, 26782, 26783, \n\t26784, 26785, 26786, 26787, 26788, 26789, 26790, 26790, \n\t26791, 26792, 26793, 26794, 26795, 26796, 26797, 26798, \n\t26799, 26800, 26800, 26801, 26802, 26803, 26804, 26805, \n\t26806, 26807, 26808, 26809, 26810, 26811, 26811, 26812, \n\t26813, 26814, 26815, 26816, 26817, 26818, 26819, 26820, \n\t26821, 26821, 26822, 26823, 26824, 26825, 26826, 26827, \n\t26828, 26829, 26830, 26831, 26831, 26832, 26833, 26834, \n\t26835, 26836, 26837, 26838, 26839, 26840, 26841, 26842, \n\t26842, 26843, 26844, 26845, 26846, 26847, 26848, 26849, \n\t26850, 26851, 26852, 26852, 26853, 26854, 26855, 26856, \n\t26857, 26858, 26859, 26860, 26861, 26862, 26863, 26863, \n\t26864, 26865, 26866, 26867, 26868, 26869, 26870, 26871, \n\t26872, 26873, 26873, 26874, 26875, 26876, 26877, 26878, \n\t26879, 26880, 26881, 26882, 26883, 26883, 26884, 26885, \n\t26886, 26887, 26888, 26889, 26890, 26891, 26892, 26893, \n\t26894, 26894, 26895, 26896, 26897, 26898, 26899, 26900, \n\t26901, 26902, 26903, 26904, 26904, 26905, 26906, 26907, \n\t26908, 26909, 26910, 26911, 26912, 26913, 26914, 26914, \n\t26915, 26916, 26917, 26918, 26919, 26920, 26921, 26922, \n\t26923, 26924, 26925, 26925, 26926, 26927, 26928, 26929, \n\t26930, 26931, 26932, 26933, 26934, 26935, 26935, 26936, \n\t26937, 26938, 26939, 26940, 26941, 26942, 26943, 26944, \n\t26945, 26945, 26946, 26947, 26948, 26949, 26950, 26951, \n\t26952, 26953, 26954, 26955, 26956, 26956, 26957, 26958, \n\t26959, 26960, 26961, 26962, 26963, 26964, 26965, 26966, \n\t26966, 26967, 26968, 26969, 26970, 26971, 26972, 26973, \n\t26974, 26975, 26976, 26976, 26977, 26978, 26979, 26980, \n\t26981, 26982, 26983, 26984, 26985, 26986, 26987, 26987, \n\t26988, 26989, 26990, 26991, 26992, 26993, 26994, 26995, \n\t26996, 26997, 26997, 26998, 26999, 27000, 27001, 27002, \n\t27003, 27004, 27005, 27006, 27007, 27007, 27008, 27009, \n\t27010, 27011, 27012, 27013, 27014, 27015, 27016, 27017, \n\t27017, 27018, 27019, 27020, 27021, 27022, 27023, 27024, \n\t27025, 27026, 27027, 27028, 27028, 27029, 27030, 27031, \n\t27032, 27033, 27034, 27035, 27036, 27037, 27038, 27038, \n\t27039, 27040, 27041, 27042, 27043, 27044, 27045, 27046, \n\t27047, 27048, 27048, 27049, 27050, 27051, 27052, 27053, \n\t27054, 27055, 27056, 27057, 27058, 27058, 27059, 27060, \n\t27061, 27062, 27063, 27064, 27065, 27066, 27067, 27068, \n\t27068, 27069, 27070, 27071, 27072, 27073, 27074, 27075, \n\t27076, 27077, 27078, 27079, 27079, 27080, 27081, 27082, \n\t27083, 27084, 27085, 27086, 27087, 27088, 27089, 27089, \n\t27090, 27091, 27092, 27093, 27094, 27095, 27096, 27097, \n\t27098, 27099, 27099, 27100, 27101, 27102, 27103, 27104, \n\t27105, 27106, 27107, 27108, 27109, 27109, 27110, 27111, \n\t27112, 27113, 27114, 27115, 27116, 27117, 27118, 27119, \n\t27119, 27120, 27121, 27122, 27123, 27124, 27125, 27126, \n\t27127, 27128, 27129, 27129, 27130, 27131, 27132, 27133, \n\t27134, 27135, 27136, 27137, 27138, 27139, 27140, 27140, \n\t27141, 27142, 27143, 27144, 27145, 27146, 27147, 27148, \n\t27149, 27150, 27150, 27151, 27152, 27153, 27154, 27155, \n\t27156, 27157, 27158, 27159, 27160, 27160, 27161, 27162, \n\t27163, 27164, 27165, 27166, 27167, 27168, 27169, 27170, \n\t27170, 27171, 27172, 27173, 27174, 27175, 27176, 27177, \n\t27178, 27179, 27180, 27180, 27181, 27182, 27183, 27184, \n\t27185, 27186, 27187, 27188, 27189, 27190, 27190, 27191, \n\t27192, 27193, 27194, 27195, 27196, 27197, 27198, 27199, \n\t27200, 27200, 27201, 27202, 27203, 27204, 27205, 27206, \n\t27207, 27208, 27209, 27210, 27210, 27211, 27212, 27213, \n\t27214, 27215, 27216, 27217, 27218, 27219, 27220, 27220, \n\t27221, 27222, 27223, 27224, 27225, 27226, 27227, 27228, \n\t27229, 27230, 27230, 27231, 27232, 27233, 27234, 27235, \n\t27236, 27237, 27238, 27239, 27240, 27241, 27241, 27242, \n\t27243, 27244, 27245, 27246, 27247, 27248, 27249, 27250, \n\t27251, 27251, 27252, 27253, 27254, 27255, 27256, 27257, \n\t27258, 27259, 27260, 27261, 27261, 27262, 27263, 27264, \n\t27265, 27266, 27267, 27268, 27269, 27270, 27271, 27271, \n\t27272, 27273, 27274, 27275, 27276, 27277, 27278, 27279, \n\t27280, 27281, 27281, 27282, 27283, 27284, 27285, 27286, \n\t27287, 27288, 27289, 27290, 27291, 27291, 27292, 27293, \n\t27294, 27295, 27296, 27297, 27298, 27299, 27300, 27301, \n\t27301, 27302, 27303, 27304, 27305, 27306, 27307, 27308, \n\t27309, 27310, 27311, 27311, 27312, 27313, 27314, 27315, \n\t27316, 27317, 27318, 27319, 27320, 27321, 27321, 27322, \n\t27323, 27324, 27325, 27326, 27327, 27328, 27329, 27330, \n\t27331, 27331, 27332, 27333, 27334, 27335, 27336, 27337, \n\t27338, 27339, 27340, 27341, 27341, 27342, 27343, 27344, \n\t27345, 27346, 27347, 27348, 27349, 27350, 27351, 27351, \n\t27352, 27353, 27354, 27355, 27356, 27357, 27358, 27359, \n\t27360, 27361, 27361, 27362, 27363, 27364, 27365, 27366, \n\t27367, 27368, 27369, 27370, 27371, 27371, 27372, 27373, \n\t27374, 27375, 27376, 27377, 27378, 27379, 27380, 27380, \n\t27381, 27382, 27383, 27384, 27385, 27386, 27387, 27388, \n\t27389, 27390, 27390, 27391, 27392, 27393, 27394, 27395, \n\t27396, 27397, 27398, 27399, 27400, 27400, 27401, 27402, \n\t27403, 27404, 27405, 27406, 27407, 27408, 27409, 27410, \n\t27410, 27411, 27412, 27413, 27414, 27415, 27416, 27417, \n\t27418, 27419, 27420, 27420, 27421, 27422, 27423, 27424, \n\t27425, 27426, 27427, 27428, 27429, 27430, 27430, 27431, \n\t27432, 27433, 27434, 27435, 27436, 27437, 27438, 27439, \n\t27440, 27440, 27441, 27442, 27443, 27444, 27445, 27446, \n\t27447, 27448, 27449, 27450, 27450, 27451, 27452, 27453, \n\t27454, 27455, 27456, 27457, 27458, 27459, 27460, 27460, \n\t27461, 27462, 27463, 27464, 27465, 27466, 27467, 27468, \n\t27469, 27470, 27470, 27471, 27472, 27473, 27474, 27475, \n\t27476, 27477, 27478, 27479, 27479, 27480, 27481, 27482, \n\t27483, 27484, 27485, 27486, 27487, 27488, 27489, 27489, \n\t27490, 27491, 27492, 27493, 27494, 27495, 27496, 27497, \n\t27498, 27499, 27499, 27500, 27501, 27502, 27503, 27504, \n\t27505, 27506, 27507, 27508, 27509, 27509, 27510, 27511, \n\t27512, 27513, 27514, 27515, 27516, 27517, 27518, 27519, \n\t27519, 27520, 27521, 27522, 27523, 27524, 27525, 27526, \n\t27527, 27528, 27529, 27529, 27530, 27531, 27532, 27533, \n\t27534, 27535, 27536, 27537, 27538, 27538, 27539, 27540, \n\t27541, 27542, 27543, 27544, 27545, 27546, 27547, 27548, \n\t27548, 27549, 27550, 27551, 27552, 27553, 27554, 27555, \n\t27556, 27557, 27558, 27558, 27559, 27560, 27561, 27562, \n\t27563, 27564, 27565, 27566, 27567, 27568, 27568, 27569, \n\t27570, 27571, 27572, 27573, 27574, 27575, 27576, 27577, \n\t27577, 27578, 27579, 27580, 27581, 27582, 27583, 27584, \n\t27585, 27586, 27587, 27587, 27588, 27589, 27590, 27591, \n\t27592, 27593, 27594, 27595, 27596, 27597, 27597, 27598, \n\t27599, 27600, 27601, 27602, 27603, 27604, 27605, 27606, \n\t27607, 27607, 27608, 27609, 27610, 27611, 27612, 27613, \n\t27614, 27615, 27616, 27617, 27617, 27618, 27619, 27620, \n\t27621, 27622, 27623, 27624, 27625, 27626, 27626, 27627, \n\t27628, 27629, 27630, 27631, 27632, 27633, 27634, 27635, \n\t27636, 27636, 27637, 27638, 27639, 27640, 27641, 27642, \n\t27643, 27644, 27645, 27646, 27646, 27647, 27648, 27649, \n\t27650, 27651, 27652, 27653, 27654, 27655, 27655, 27656, \n\t27657, 27658, 27659, 27660, 27661, 27662, 27663, 27664, \n\t27665, 27665, 27666, 27667, 27668, 27669, 27670, 27671, \n\t27672, 27673, 27674, 27675, 27675, 27676, 27677, 27678, \n\t27679, 27680, 27681, 27682, 27683, 27684, 27684, 27685, \n\t27686, 27687, 27688, 27689, 27690, 27691, 27692, 27693, \n\t27694, 27694, 27695, 27696, 27697, 27698, 27699, 27700, \n\t27701, 27702, 27703, 27704, 27704, 27705, 27706, 27707, \n\t27708, 27709, 27710, 27711, 27712, 27713, 27713, 27714, \n\t27715, 27716, 27717, 27718, 27719, 27720, 27721, 27722, \n\t27723, 27723, 27724, 27725, 27726, 27727, 27728, 27729, \n\t27730, 27731, 27732, 27733, 27733, 27734, 27735, 27736, \n\t27737, 27738, 27739, 27740, 27741, 27742, 27742, 27743, \n\t27744, 27745, 27746, 27747, 27748, 27749, 27750, 27751, \n\t27752, 27752, 27753, 27754, 27755, 27756, 27757, 27758, \n\t27759, 27760, 27761, 27762, 27762, 27763, 27764, 27765, \n\t27766, 27767, 27768, 27769, 27770, 27771, 27771, 27772, \n\t27773, 27774, 27775, 27776, 27777, 27778, 27779, 27780, \n\t27781, 27781, 27782, 27783, 27784, 27785, 27786, 27787, \n\t27788, 27789, 27790, 27791, 27791, 27792, 27793, 27794, \n\t27795, 27796, 27797, 27798, 27799, 27800, 27800, 27801, \n\t27802, 27803, 27804, 27805, 27806, 27807, 27808, 27809, \n\t27810, 27810, 27811, 27812, 27813, 27814, 27815, 27816, \n\t27817, 27818, 27819, 27819, 27820, 27821, 27822, 27823, \n\t27824, 27825, 27826, 27827, 27828, 27829, 27829, 27830, \n\t27831, 27832, 27833, 27834, 27835, 27836, 27837, 27838, \n\t27838, 27839, 27840, 27841, 27842, 27843, 27844, 27845, \n\t27846, 27847, 27848, 27848, 27849, 27850, 27851, 27852, \n\t27853, 27854, 27855, 27856, 27857, 27858, 27858, 27859, \n\t27860, 27861, 27862, 27863, 27864, 27865, 27866, 27867, \n\t27867, 27868, 27869, 27870, 27871, 27872, 27873, 27874, \n\t27875, 27876, 27877, 27877, 27878, 27879, 27880, 27881, \n\t27882, 27883, 27884, 27885, 27886, 27886, 27887, 27888, \n\t27889, 27890, 27891, 27892, 27893, 27894, 27895, 27896, \n\t27896, 27897, 27898, 27899, 27900, 27901, 27902, 27903, \n\t27904, 27905, 27905, 27906, 27907, 27908, 27909, 27910, \n\t27911, 27912, 27913, 27914, 27915, 27915, 27916, 27917, \n\t27918, 27919, 27920, 27921, 27922, 27923, 27924, 27924, \n\t27925, 27926, 27927, 27928, 27929, 27930, 27931, 27932, \n\t27933, 27934, 27934, 27935, 27936, 27937, 27938, 27939, \n\t27940, 27941, 27942, 27943, 27943, 27944, 27945, 27946, \n\t27947, 27948, 27949, 27950, 27951, 27952, 27953, 27953, \n\t27954, 27955, 27956, 27957, 27958, 27959, 27960, 27961, \n\t27962, 27962, 27963, 27964, 27965, 27966, 27967, 27968, \n\t27969, 27970, 27971, 27971, 27972, 27973, 27974, 27975, \n\t27976, 27977, 27978, 27979, 27980, 27981, 27981, 27982, \n\t27983, 27984, 27985, 27986, 27987, 27988, 27989, 27990, \n\t27990, 27991, 27992, 27993, 27994, 27995, 27996, 27997, \n\t27998, 27999, 28000, 28000, 28001, 28002, 28003, 28004, \n\t28005, 28006, 28007, 28008, 28009, 28009, 28010, 28011, \n\t28012, 28013, 28014, 28015, 28016, 28017, 28018, 28019, \n\t28019, 28020, 28021, 28022, 28023, 28024, 28025, 28026, \n\t28027, 28028, 28028, 28029, 28030, 28031, 28032, 28033, \n\t28034, 28035, 28036, 28037, 28037, 28038, 28039, 28040, \n\t28041, 28042, 28043, 28044, 28045, 28046, 28047, 28047, \n\t28048, 28049, 28050, 28051, 28052, 28053, 28054, 28055, \n\t28056, 28056, 28057, 28058, 28059, 28060, 28061, 28062, \n\t28063, 28064, 28065, 28066, 28066, 28067, 28068, 28069, \n\t28070, 28071, 28072, 28073, 28074, 28075, 28075, 28076, \n\t28077, 28078, 28079, 28080, 28081, 28082, 28083, 28084, \n\t28084, 28085, 28086, 28087, 28088, 28089, 28090, 28091, \n\t28092, 28093, 28094, 28094, 28095, 28096, 28097, 28098, \n\t28099, 28100, 28101, 28102, 28103, 28103, 28104, 28105, \n\t28106, 28107, 28108, 28109, 28110, 28111, 28112, 28112, \n\t28113, 28114, 28115, 28116, 28117, 28118, 28119, 28120, \n\t28121, 28122, 28122, 28123, 28124, 28125, 28126, 28127, \n\t28128, 28129, 28130, 28131, 28131, 28132, 28133, 28134, \n\t28135, 28136, 28137, 28138, 28139, 28140, 28140, 28141, \n\t28142, 28143, 28144, 28145, 28146, 28147, 28148, 28149, \n\t28150, 28150, 28151, 28152, 28153, 28154, 28155, 28156, \n\t28157, 28158, 28159, 28159, 28160, 28161, 28162, 28163, \n\t28164, 28165, 28166, 28167, 28168, 28168, 28169, 28170, \n\t28171, 28172, 28173, 28174, 28175, 28176, 28177, 28178, \n\t28178, 28179, 28180, 28181, 28182, 28183, 28184, 28185, \n\t28186, 28187, 28187, 28188, 28189, 28190, 28191, 28192, \n\t28193, 28194, 28195, 28196, 28196, 28197, 28198, 28199, \n\t28200, 28201, 28202, 28203, 28204, 28205, 28206, 28206, \n\t28207, 28208, 28209, 28210, 28211, 28212, 28213, 28214, \n\t28215, 28215, 28216, 28217, 28218, 28219, 28220, 28221, \n\t28222, 28223, 28224, 28224, 28225, 28226, 28227, 28228, \n\t28229, 28230, 28231, 28232, 28233, 28233, 28234, 28235, \n\t28236, 28237, 28238, 28239, 28240, 28241, 28242, 28243, \n\t28243, 28244, 28245, 28246, 28247, 28248, 28249, 28250, \n\t28251, 28252, 28252, 28253, 28254, 28255, 28256, 28257, \n\t28258, 28259, 28260, 28261, 28261, 28262, 28263, 28264, \n\t28265, 28266, 28267, 28268, 28269, 28270, 28270, 28271, \n\t28272, 28273, 28274, 28275, 28276, 28277, 28278, 28279, \n\t28280, 28280, 28281, 28282, 28283, 28284, 28285, 28286, \n\t28287, 28288, 28289, 28289, 28290, 28291, 28292, 28293, \n\t28294, 28295, 28296, 28297, 28298, 28298, 28299, 28300, \n\t28301, 28302, 28303, 28304, 28305, 28306, 28307, 28307, \n\t28308, 28309, 28310, 28311, 28312, 28313, 28314, 28315, \n\t28316, 28316, 28317, 28318, 28319, 28320, 28321, 28322, \n\t28323, 28324, 28325, 28325, 28326, 28327, 28328, 28329, \n\t28330, 28331, 28332, 28333, 28334, 28335, 28335, 28336, \n\t28337, 28338, 28339, 28340, 28341, 28342, 28343, 28344, \n\t28344, 28345, 28346, 28347, 28348, 28349, 28350, 28351, \n\t28352, 28353, 28353, 28354, 28355, 28356, 28357, 28358, \n\t28359, 28360, 28361, 28362, 28362, 28363, 28364, 28365, \n\t28366, 28367, 28368, 28369, 28370, 28371, 28371, 28372, \n\t28373, 28374, 28375, 28376, 28377, 28378, 28379, 28380, \n\t28380, 28381, 28382, 28383, 28384, 28385, 28386, 28387, \n\t28388, 28389, 28390, 28390, 28391, 28392, 28393, 28394, \n\t28395, 28396, 28397, 28398, 28399, 28399, 28400, 28401, \n\t28402, 28403, 28404, 28405, 28406, 28407, 28408, 28408, \n\t28409, 28410, 28411, 28412, 28413, 28414, 28415, 28416, \n\t28417, 28417, 28418, 28419, 28420, 28421, 28422, 28423, \n\t28424, 28425, 28426, 28426, 28427, 28428, 28429, 28430, \n\t28431, 28432, 28433, 28434, 28435, 28435, 28436, 28437, \n\t28438, 28439, 28440, 28441, 28442, 28443, 28444, 28444, \n\t28445, 28446, 28447, 28448, 28449, 28450, 28451, 28452, \n\t28453, 28453, 28454, 28455, 28456, 28457, 28458, 28459, \n\t28460, 28461, 28462, 28462, 28463, 28464, 28465, 28466, \n\t28467, 28468, 28469, 28470, 28471, 28471, 28472, 28473, \n\t28474, 28475, 28476, 28477, 28478, 28479, 28480, 28481, \n\t28481, 28482, 28483, 28484, 28485, 28486, 28487, 28488, \n\t28489, 28490, 28490, 28491, 28492, 28493, 28494, 28495, \n\t28496, 28497, 28498, 28499, 28499, 28500, 28501, 28502, \n\t28503, 28504, 28505, 28506, 28507, 28508, 28508, 28509, \n\t28510, 28511, 28512, 28513, 28514, 28515, 28516, 28517, \n\t28517, 28518, 28519, 28520, 28521, 28522, 28523, 28524, \n\t28525, 28526, 28526, 28527, 28528, 28529, 28530, 28531, \n\t28532, 28533, 28534, 28535, 28535, 28536, 28537, 28538, \n\t28539, 28540, 28541, 28542, 28543, 28544, 28544, 28545, \n\t28546, 28547, 28548, 28549, 28550, 28551, 28552, 28553, \n\t28553, 28554, 28555, 28556, 28557, 28558, 28559, 28560, \n\t28561, 28562, 28562, 28563, 28564, 28565, 28566, 28567, \n\t28568, 28569, 28570, 28571, 28571, 28572, 28573, 28574, \n\t28575, 28576, 28577, 28578, 28579, 28580, 28580, 28581, \n\t28582, 28583, 28584, 28585, 28586, 28587, 28588, 28589, \n\t28589, 28590, 28591, 28592, 28593, 28594, 28595, 28596, \n\t28597, 28598, 28598, 28599, 28600, 28601, 28602, 28603, \n\t28604, 28605, 28606, 28607, 28607, 28608, 28609, 28610, \n\t28611, 28612, 28613, 28614, 28615, 28616, 28616, 28617, \n\t28618, 28619, 28620, 28621, 28622, 28623, 28624, 28625, \n\t28625, 28626, 28627, 28628, 28629, 28630, 28631, 28632, \n\t28633, 28634, 28634, 28635, 28636, 28637, 28638, 28639, \n\t28640, 28641, 28642, 28643, 28643, 28644, 28645, 28646, \n\t28647, 28648, 28649, 28650, 28651, 28652, 28652, 28653, \n\t28654, 28655, 28656, 28657, 28658, 28659, 28660, 28660, \n\t28661, 28662, 28663, 28664, 28665, 28666, 28667, 28668, \n\t28669, 28669, 28670, 28671, 28672, 28673, 28674, 28675, \n\t28676, 28677, 28678, 28678, 28679, 28680, 28681, 28682, \n\t28683, 28684, 28685, 28686, 28687, 28687, 28688, 28689, \n\t28690, 28691, 28692, 28693, 28694, 28695, 28696, 28696, \n\t28697, 28698, 28699, 28700, 28701, 28702, 28703, 28704, \n\t28705, 28705, 28706, 28707, 28708, 28709, 28710, 28711, \n\t28712, 28713, 28714, 28714, 28715, 28716, 28717, 28718, \n\t28719, 28720, 28721, 28722, 28723, 28723, 28724, 28725, \n\t28726, 28727, 28728, 28729, 28730, 28731, 28732, 28732, \n\t28733, 28734, 28735, 28736, 28737, 28738, 28739, 28740, \n\t28741, 28741, 28742, 28743, 28744, 28745, 28746, 28747, \n\t28748, 28749, 28749, 28750, 28751, 28752, 28753, 28754, \n\t28755, 28756, 28757, 28758, 28758, 28759, 28760, 28761, \n\t28762, 28763, 28764, 28765, 28766, 28767, 28767, 28768, \n\t28769, 28770, 28771, 28772, 28773, 28774, 28775, 28776, \n\t28776, 28777, 28778, 28779, 28780, 28781, 28782, 28783, \n\t28784, 28785, 28785, 28786, 28787, 28788, 28789, 28790, \n\t28791, 28792, 28793, 28794, 28794, 28795, 28796, 28797, \n\t28798, 28799, 28800, 28801, 28802, 28803, 28803, 28804, \n\t28805, 28806, 28807, 28808, 28809, 28810, 28811, 28811, \n\t28812, 28813, 28814, 28815, 28816, 28817, 28818, 28819, \n\t28820, 28820, 28821, 28822, 28823, 28824, 28825, 28826, \n\t28827, 28828, 28829, 28829, 28830, 28831, 28832, 28833, \n\t28834, 28835, 28836, 28837, 28838, 28838, 28839, 28840, \n\t28841, 28842, 28843, 28844, 28845, 28846, 28847, 28847, \n\t28848, 28849, 28850, 28851, 28852, 28853, 28854, 28855, \n\t28855, 28856, 28857, 28858, 28859, 28860, 28861, 28862, \n\t28863, 28864, 28864, 28865, 28866, 28867, 28868, 28869, \n\t28870, 28871, 28872, 28873, 28873, 28874, 28875, 28876, \n\t28877, 28878, 28879, 28880, 28881, 28882, 28882, 28883, \n\t28884, 28885, 28886, 28887, 28888, 28889, 28890, 28891, \n\t28891, 28892, 28893, 28894, 28895, 28896, 28897, 28898, \n\t28899, 28899, 28900, 28901, 28902, 28903, 28904, 28905, \n\t28906, 28907, 28908, 28908, 28909, 28910, 28911, 28912, \n\t28913, 28914, 28915, 28916, 28917, 28917, 28918, 28919, \n\t28920, 28921, 28922, 28923, 28924, 28925, 28926, 28926, \n\t28927, 28928, 28929, 28930, 28931, 28932, 28933, 28934, \n\t28934, 28935, 28936, 28937, 28938, 28939, 28940, 28941, \n\t28942, 28943, 28943, 28944, 28945, 28946, 28947, 28948, \n\t28949, 28950, 28951, 28952, 28952, 28953, 28954, 28955, \n\t28956, 28957, 28958, 28959, 28960, 28960, 28961, 28962, \n\t28963, 28964, 28965, 28966, 28967, 28968, 28969, 28969, \n\t28970, 28971, 28972, 28973, 28974, 28975, 28976, 28977, \n\t28978, 28978, 28979, 28980, 28981, 28982, 28983, 28984, \n\t28985, 28986, 28987, 28987, 28988, 28989, 28990, 28991, \n\t28992, 28993, 28994, 28995, 28995, 28996, 28997, 28998, \n\t28999, 29000, 29001, 29002, 29003, 29004, 29004, 29005, \n\t29006, 29007, 29008, 29009, 29010, 29011, 29012, 29013, \n\t29013, 29014, 29015, 29016, 29017, 29018, 29019, 29020, \n\t29021, 29021, 29022, 29023, 29024, 29025, 29026, 29027, \n\t29028, 29029, 29030, 29030, 29031, 29032, 29033, 29034, \n\t29035, 29036, 29037, 29038, 29039, 29039, 29040, 29041, \n\t29042, 29043, 29044, 29045, 29046, 29047, 29047, 29048, \n\t29049, 29050, 29051, 29052, 29053, 29054, 29055, 29056, \n\t29056, 29057, 29058, 29059, 29060, 29061, 29062, 29063, \n\t29064, 29065, 29065, 29066, 29067, 29068, 29069, 29070, \n\t29071, 29072, 29073, 29073, 29074, 29075, 29076, 29077, \n\t29078, 29079, 29080, 29081, 29082, 29082, 29083, 29084, \n\t29085, 29086, 29087, 29088, 29089, 29090, 29090, 29091, \n\t29092, 29093, 29094, 29095, 29096, 29097, 29098, 29099, \n\t29099, 29100, 29101, 29102, 29103, 29104, 29105, 29106, \n\t29107, 29108, 29108, 29109, 29110, 29111, 29112, 29113, \n\t29114, 29115, 29116, 29116, 29117, 29118, 29119, 29120, \n\t29121, 29122, 29123, 29124, 29125, 29125, 29126, 29127, \n\t29128, 29129, 29130, 29131, 29132, 29133, 29134, 29134, \n\t29135, 29136, 29137, 29138, 29139, 29140, 29141, 29142, \n\t29142, 29143, 29144, 29145, 29146, 29147, 29148, 29149, \n\t29150, 29151, 29151, 29152, 29153, 29154, 29155, 29156, \n\t29157, 29158, 29159, 29159, 29160, 29161, 29162, 29163, \n\t29164, 29165, 29166, 29167, 29168, 29168, 29169, 29170, \n\t29171, 29172, 29173, 29174, 29175, 29176, 29176, 29177, \n\t29178, 29179, 29180, 29181, 29182, 29183, 29184, 29185, \n\t29185, 29186, 29187, 29188, 29189, 29190, 29191, 29192, \n\t29193, 29194, 29194, 29195, 29196, 29197, 29198, 29199, \n\t29200, 29201, 29202, 29202, 29203, 29204, 29205, 29206, \n\t29207, 29208, 29209, 29210, 29211, 29211, 29212, 29213, \n\t29214, 29215, 29216, 29217, 29218, 29219, 29219, 29220, \n\t29221, 29222, 29223, 29224, 29225, 29226, 29227, 29228, \n\t29228, 29229, 29230, 29231, 29232, 29233, 29234, 29235, \n\t29236, 29236, 29237, 29238, 29239, 29240, 29241, 29242, \n\t29243, 29244, 29245, 29245, 29246, 29247, 29248, 29249, \n\t29250, 29251, 29252, 29253, 29253, 29254, 29255, 29256, \n\t29257, 29258, 29259, 29260, 29261, 29262, 29262, 29263, \n\t29264, 29265, 29266, 29267, 29268, 29269, 29270, 29270, \n\t29271, 29272, 29273, 29274, 29275, 29276, 29277, 29278, \n\t29279, 29279, 29280, 29281, 29282, 29283, 29284, 29285, \n\t29286, 29287, 29287, 29288, 29289, 29290, 29291, 29292, \n\t29293, 29294, 29295, 29296, 29296, 29297, 29298, 29299, \n\t29300, 29301, 29302, 29303, 29304, 29304, 29305, 29306, \n\t29307, 29308, 29309, 29310, 29311, 29312, 29313, 29313, \n\t29314, 29315, 29316, 29317, 29318, 29319, 29320, 29321, \n\t29321, 29322, 29323, 29324, 29325, 29326, 29327, 29328, \n\t29329, 29330, 29330, 29331, 29332, 29333, 29334, 29335, \n\t29336, 29337, 29338, 29338, 29339, 29340, 29341, 29342, \n\t29343, 29344, 29345, 29346, 29346, 29347, 29348, 29349, \n\t29350, 29351, 29352, 29353, 29354, 29355, 29355, 29356, \n\t29357, 29358, 29359, 29360, 29361, 29362, 29363, 29363, \n\t29364, 29365, 29366, 29367, 29368, 29369, 29370, 29371, \n\t29372, 29372, 29373, 29374, 29375, 29376, 29377, 29378, \n\t29379, 29380, 29380, 29381, 29382, 29383, 29384, 29385, \n\t29386, 29387, 29388, 29389, 29389, 29390, 29391, 29392, \n\t29393, 29394, 29395, 29396, 29397, 29397, 29398, 29399, \n\t29400, 29401, 29402, 29403, 29404, 29405, 29405, 29406, \n\t29407, 29408, 29409, 29410, 29411, 29412, 29413, 29414, \n\t29414, 29415, 29416, 29417, 29418, 29419, 29420, 29421, \n\t29422, 29422, 29423, 29424, 29425, 29426, 29427, 29428, \n\t29429, 29430, 29431, 29431, 29432, 29433, 29434, 29435, \n\t29436, 29437, 29438, 29439, 29439, 29440, 29441, 29442, \n\t29443, 29444, 29445, 29446, 29447, 29447, 29448, 29449, \n\t29450, 29451, 29452, 29453, 29454, 29455, 29456, 29456, \n\t29457, 29458, 29459, 29460, 29461, 29462, 29463, 29464, \n\t29464, 29465, 29466, 29467, 29468, 29469, 29470, 29471, \n\t29472, 29473, 29473, 29474, 29475, 29476, 29477, 29478, \n\t29479, 29480, 29481, 29481, 29482, 29483, 29484, 29485, \n\t29486, 29487, 29488, 29489, 29489, 29490, 29491, 29492, \n\t29493, 29494, 29495, 29496, 29497, 29498, 29498, 29499, \n\t29500, 29501, 29502, 29503, 29504, 29505, 29506, 29506, \n\t29507, 29508, 29509, 29510, 29511, 29512, 29513, 29514, \n\t29514, 29515, 29516, 29517, 29518, 29519, 29520, 29521, \n\t29522, 29523, 29523, 29524, 29525, 29526, 29527, 29528, \n\t29529, 29530, 29531, 29531, 29532, 29533, 29534, 29535, \n\t29536, 29537, 29538, 29539, 29539, 29540, 29541, 29542, \n\t29543, 29544, 29545, 29546, 29547, 29548, 29548, 29549, \n\t29550, 29551, 29552, 29553, 29554, 29555, 29556, 29556, \n\t29557, 29558, 29559, 29560, 29561, 29562, 29563, 29564, \n\t29564, 29565, 29566, 29567, 29568, 29569, 29570, 29571, \n\t29572, 29572, 29573, 29574, 29575, 29576, 29577, 29578, \n\t29579, 29580, 29581, 29581, 29582, 29583, 29584, 29585, \n\t29586, 29587, 29588, 29589, 29589, 29590, 29591, 29592, \n\t29593, 29594, 29595, 29596, 29597, 29597, 29598, 29599, \n\t29600, 29601, 29602, 29603, 29604, 29605, 29606, 29606, \n\t29607, 29608, 29609, 29610, 29611, 29612, 29613, 29614, \n\t29614, 29615, 29616, 29617, 29618, 29619, 29620, 29621, \n\t29622, 29622, 29623, 29624, 29625, 29626, 29627, 29628, \n\t29629, 29630, 29630, 29631, 29632, 29633, 29634, 29635, \n\t29636, 29637, 29638, 29639, 29639, 29640, 29641, 29642, \n\t29643, 29644, 29645, 29646, 29647, 29647, 29648, 29649, \n\t29650, 29651, 29652, 29653, 29654, 29655, 29655, 29656, \n\t29657, 29658, 29659, 29660, 29661, 29662, 29663, 29663, \n\t29664, 29665, 29666, 29667, 29668, 29669, 29670, 29671, \n\t29672, 29672, 29673, 29674, 29675, 29676, 29677, 29678, \n\t29679, 29680, 29680, 29681, 29682, 29683, 29684, 29685, \n\t29686, 29687, 29688, 29688, 29689, 29690, 29691, 29692, \n\t29693, 29694, 29695, 29696, 29696, 29697, 29698, 29699, \n\t29700, 29701, 29702, 29703, 29704, 29704, 29705, 29706, \n\t29707, 29708, 29709, 29710, 29711, 29712, 29713, 29713, \n\t29714, 29715, 29716, 29717, 29718, 29719, 29720, 29721, \n\t29721, 29722, 29723, 29724, 29725, 29726, 29727, 29728, \n\t29729, 29729, 29730, 29731, 29732, 29733, 29734, 29735, \n\t29736, 29737, 29737, 29738, 29739, 29740, 29741, 29742, \n\t29743, 29744, 29745, 29745, 29746, 29747, 29748, 29749, \n\t29750, 29751, 29752, 29753, 29754, 29754, 29755, 29756, \n\t29757, 29758, 29759, 29760, 29761, 29762, 29762, 29763, \n\t29764, 29765, 29766, 29767, 29768, 29769, 29770, 29770, \n\t29771, 29772, 29773, 29774, 29775, 29776, 29777, 29778, \n\t29778, 29779, 29780, 29781, 29782, 29783, 29784, 29785, \n\t29786, 29786, 29787, 29788, 29789, 29790, 29791, 29792, \n\t29793, 29794, 29794, 29795, 29796, 29797, 29798, 29799, \n\t29800, 29801, 29802, 29803, 29803, 29804, 29805, 29806, \n\t29807, 29808, 29809, 29810, 29811, 29811, 29812, 29813, \n\t29814, 29815, 29816, 29817, 29818, 29819, 29819, 29820, \n\t29821, 29822, 29823, 29824, 29825, 29826, 29827, 29827, \n\t29828, 29829, 29830, 29831, 29832, 29833, 29834, 29835, \n\t29835, 29836, 29837, 29838, 29839, 29840, 29841, 29842, \n\t29843, 29843, 29844, 29845, 29846, 29847, 29848, 29849, \n\t29850, 29851, 29851, 29852, 29853, 29854, 29855, 29856, \n\t29857, 29858, 29859, 29859, 29860, 29861, 29862, 29863, \n\t29864, 29865, 29866, 29867, 29868, 29868, 29869, 29870, \n\t29871, 29872, 29873, 29874, 29875, 29876, 29876, 29877, \n\t29878, 29879, 29880, 29881, 29882, 29883, 29884, 29884, \n\t29885, 29886, 29887, 29888, 29889, 29890, 29891, 29892, \n\t29892, 29893, 29894, 29895, 29896, 29897, 29898, 29899, \n\t29900, 29900, 29901, 29902, 29903, 29904, 29905, 29906, \n\t29907, 29908, 29908, 29909, 29910, 29911, 29912, 29913, \n\t29914, 29915, 29916, 29916, 29917, 29918, 29919, 29920, \n\t29921, 29922, 29923, 29924, 29924, 29925, 29926, 29927, \n\t29928, 29929, 29930, 29931, 29932, 29932, 29933, 29934, \n\t29935, 29936, 29937, 29938, 29939, 29940, 29940, 29941, \n\t29942, 29943, 29944, 29945, 29946, 29947, 29948, 29948, \n\t29949, 29950, 29951, 29952, 29953, 29954, 29955, 29956, \n\t29956, 29957, 29958, 29959, 29960, 29961, 29962, 29963, \n\t29964, 29964, 29965, 29966, 29967, 29968, 29969, 29970, \n\t29971, 29972, 29972, 29973, 29974, 29975, 29976, 29977, \n\t29978, 29979, 29980, 29980, 29981, 29982, 29983, 29984, \n\t29985, 29986, 29987, 29988, 29988, 29989, 29990, 29991, \n\t29992, 29993, 29994, 29995, 29996, 29996, 29997, 29998, \n\t29999, 30000, 30001, 30002, 30003, 30004, 30004, 30005, \n\t30006, 30007, 30008, 30009, 30010, 30011, 30012, 30012, \n\t30013, 30014, 30015, 30016, 30017, 30018, 30019, 30020, \n\t30020, 30021, 30022, 30023, 30024, 30025, 30026, 30027, \n\t30028, 30028, 30029, 30030, 30031, 30032, 30033, 30034, \n\t30035, 30036, 30036, 30037, 30038, 30039, 30040, 30041, \n\t30042, 30043, 30044, 30044, 30045, 30046, 30047, 30048, \n\t30049, 30050, 30051, 30052, 30052, 30053, 30054, 30055, \n\t30056, 30057, 30058, 30059, 30060, 30060, 30061, 30062, \n\t30063, 30064, 30065, 30066, 30067, 30068, 30068, 30069, \n\t30070, 30071, 30072, 30073, 30074, 30075, 30076, 30076, \n\t30077, 30078, 30079, 30080, 30081, 30082, 30083, 30084, \n\t30084, 30085, 30086, 30087, 30088, 30089, 30090, 30091, \n\t30092, 30092, 30093, 30094, 30095, 30096, 30097, 30098, \n\t30099, 30100, 30100, 30101, 30102, 30103, 30104, 30105, \n\t30106, 30107, 30108, 30108, 30109, 30110, 30111, 30112, \n\t30113, 30114, 30115, 30116, 30116, 30117, 30118, 30119, \n\t30120, 30121, 30122, 30123, 30124, 30124, 30125, 30126, \n\t30127, 30128, 30129, 30130, 30131, 30132, 30132, 30133, \n\t30134, 30135, 30136, 30137, 30138, 30139, 30140, 30140, \n\t30141, 30142, 30143, 30144, 30145, 30146, 30147, 30148, \n\t30148, 30149, 30150, 30151, 30152, 30153, 30154, 30155, \n\t30156, 30156, 30157, 30158, 30159, 30160, 30161, 30162, \n\t30163, 30164, 30164, 30165, 30166, 30167, 30168, 30169, \n\t30170, 30171, 30172, 30172, 30173, 30174, 30175, 30176, \n\t30177, 30178, 30179, 30180, 30180, 30181, 30182, 30183, \n\t30184, 30185, 30186, 30187, 30187, 30188, 30189, 30190, \n\t30191, 30192, 30193, 30194, 30195, 30195, 30196, 30197, \n\t30198, 30199, 30200, 30201, 30202, 30203, 30203, 30204, \n\t30205, 30206, 30207, 30208, 30209, 30210, 30211, 30211, \n\t30212, 30213, 30214, 30215, 30216, 30217, 30218, 30219, \n\t30219, 30220, 30221, 30222, 30223, 30224, 30225, 30226, \n\t30227, 30227, 30228, 30229, 30230, 30231, 30232, 30233, \n\t30234, 30235, 30235, 30236, 30237, 30238, 30239, 30240, \n\t30241, 30242, 30243, 30243, 30244, 30245, 30246, 30247, \n\t30248, 30249, 30250, 30250, 30251, 30252, 30253, 30254, \n\t30255, 30256, 30257, 30258, 30258, 30259, 30260, 30261, \n\t30262, 30263, 30264, 30265, 30266, 30266, 30267, 30268, \n\t30269, 30270, 30271, 30272, 30273, 30274, 30274, 30275, \n\t30276, 30277, 30278, 30279, 30280, 30281, 30282, 30282, \n\t30283, 30284, 30285, 30286, 30287, 30288, 30289, 30290, \n\t30290, 30291, 30292, 30293, 30294, 30295, 30296, 30297, \n\t30297, 30298, 30299, 30300, 30301, 30302, 30303, 30304, \n\t30305, 30305, 30306, 30307, 30308, 30309, 30310, 30311, \n\t30312, 30313, 30313, 30314, 30315, 30316, 30317, 30318, \n\t30319, 30320, 30321, 30321, 30322, 30323, 30324, 30325, \n\t30326, 30327, 30328, 30329, 30329, 30330, 30331, 30332, \n\t30333, 30334, 30335, 30336, 30337, 30337, 30338, 30339, \n\t30340, 30341, 30342, 30343, 30344, 30344, 30345, 30346, \n\t30347, 30348, 30349, 30350, 30351, 30352, 30352, 30353, \n\t30354, 30355, 30356, 30357, 30358, 30359, 30360, 30360, \n\t30361, 30362, 30363, 30364, 30365, 30366, 30367, 30368, \n\t30368, 30369, 30370, 30371, 30372, 30373, 30374, 30375, \n\t30376, 30376, 30377, 30378, 30379, 30380, 30381, 30382, \n\t30383, 30383, 30384, 30385, 30386, 30387, 30388, 30389, \n\t30390, 30391, 30391, 30392, 30393, 30394, 30395, 30396, \n\t30397, 30398, 30399, 30399, 30400, 30401, 30402, 30403, \n\t30404, 30405, 30406, 30407, 30407, 30408, 30409, 30410, \n\t30411, 30412, 30413, 30414, 30414, 30415, 30416, 30417, \n\t30418, 30419, 30420, 30421, 30422, 30422, 30423, 30424, \n\t30425, 30426, 30427, 30428, 30429, 30430, 30430, 30431, \n\t30432, 30433, 30434, 30435, 30436, 30437, 30438, 30438, \n\t30439, 30440, 30441, 30442, 30443, 30444, 30445, 30445, \n\t30446, 30447, 30448, 30449, 30450, 30451, 30452, 30453, \n\t30453, 30454, 30455, 30456, 30457, 30458, 30459, 30460, \n\t30461, 30461, 30462, 30463, 30464, 30465, 30466, 30467, \n\t30468, 30469, 30469, 30470, 30471, 30472, 30473, 30474, \n\t30475, 30476, 30476, 30477, 30478, 30479, 30480, 30481, \n\t30482, 30483, 30484, 30484, 30485, 30486, 30487, 30488, \n\t30489, 30490, 30491, 30492, 30492, 30493, 30494, 30495, \n\t30496, 30497, 30498, 30499, 30499, 30500, 30501, 30502, \n\t30503, 30504, 30505, 30506, 30507, 30507, 30508, 30509, \n\t30510, 30511, 30512, 30513, 30514, 30515, 30515, 30516, \n\t30517, 30518, 30519, 30520, 30521, 30522, 30522, 30523, \n\t30524, 30525, 30526, 30527, 30528, 30529, 30530, 30530, \n\t30531, 30532, 30533, 30534, 30535, 30536, 30537, 30538, \n\t30538, 30539, 30540, 30541, 30542, 30543, 30544, 30545, \n\t30546, 30546, 30547, 30548, 30549, 30550, 30551, 30552, \n\t30553, 30553, 30554, 30555, 30556, 30557, 30558, 30559, \n\t30560, 30561, 30561, 30562, 30563, 30564, 30565, 30566, \n\t30567, 30568, 30569, 30569, 30570, 30571, 30572, 30573, \n\t30574, 30575, 30576, 30576, 30577, 30578, 30579, 30580, \n\t30581, 30582, 30583, 30584, 30584, 30585, 30586, 30587, \n\t30588, 30589, 30590, 30591, 30592, 30592, 30593, 30594, \n\t30595, 30596, 30597, 30598, 30599, 30599, 30600, 30601, \n\t30602, 30603, 30604, 30605, 30606, 30607, 30607, 30608, \n\t30609, 30610, 30611, 30612, 30613, 30614, 30614, 30615, \n\t30616, 30617, 30618, 30619, 30620, 30621, 30622, 30622, \n\t30623, 30624, 30625, 30626, 30627, 30628, 30629, 30630, \n\t30630, 30631, 30632, 30633, 30634, 30635, 30636, 30637, \n\t30637, 30638, 30639, 30640, 30641, 30642, 30643, 30644, \n\t30645, 30645, 30646, 30647, 30648, 30649, 30650, 30651, \n\t30652, 30653, 30653, 30654, 30655, 30656, 30657, 30658, \n\t30659, 30660, 30660, 30661, 30662, 30663, 30664, 30665, \n\t30666, 30667, 30668, 30668, 30669, 30670, 30671, 30672, \n\t30673, 30674, 30675, 30675, 30676, 30677, 30678, 30679, \n\t30680, 30681, 30682, 30683, 30683, 30684, 30685, 30686, \n\t30687, 30688, 30689, 30690, 30691, 30691, 30692, 30693, \n\t30694, 30695, 30696, 30697, 30698, 30698, 30699, 30700, \n\t30701, 30702, 30703, 30704, 30705, 30706, 30706, 30707, \n\t30708, 30709, 30710, 30711, 30712, 30713, 30713, 30714, \n\t30715, 30716, 30717, 30718, 30719, 30720, 30721, 30721, \n\t30722, 30723, 30724, 30725, 30726, 30727, 30728, 30728, \n\t30729, 30730, 30731, 30732, 30733, 30734, 30735, 30736, \n\t30736, 30737, 30738, 30739, 30740, 30741, 30742, 30743, \n\t30744, 30744, 30745, 30746, 30747, 30748, 30749, 30750, \n\t30751, 30751, 30752, 30753, 30754, 30755, 30756, 30757, \n\t30758, 30759, 30759, 30760, 30761, 30762, 30763, 30764, \n\t30765, 30766, 30766, 30767, 30768, 30769, 30770, 30771, \n\t30772, 30773, 30774, 30774, 30775, 30776, 30777, 30778, \n\t30779, 30780, 30781, 30781, 30782, 30783, 30784, 30785, \n\t30786, 30787, 30788, 30789, 30789, 30790, 30791, 30792, \n\t30793, 30794, 30795, 30796, 30796, 30797, 30798, 30799, \n\t30800, 30801, 30802, 30803, 30804, 30804, 30805, 30806, \n\t30807, 30808, 30809, 30810, 30811, 30811, 30812, 30813, \n\t30814, 30815, 30816, 30817, 30818, 30819, 30819, 30820, \n\t30821, 30822, 30823, 30824, 30825, 30826, 30826, 30827, \n\t30828, 30829, 30830, 30831, 30832, 30833, 30834, 30834, \n\t30835, 30836, 30837, 30838, 30839, 30840, 30841, 30841, \n\t30842, 30843, 30844, 30845, 30846, 30847, 30848, 30849, \n\t30849, 30850, 30851, 30852, 30853, 30854, 30855, 30856, \n\t30856, 30857, 30858, 30859, 30860, 30861, 30862, 30863, \n\t30864, 30864, 30865, 30866, 30867, 30868, 30869, 30870, \n\t30871, 30871, 30872, 30873, 30874, 30875, 30876, 30877, \n\t30878, 30879, 30879, 30880, 30881, 30882, 30883, 30884, \n\t30885, 30886, 30886, 30887, 30888, 30889, 30890, 30891, \n\t30892, 30893, 30894, 30894, 30895, 30896, 30897, 30898, \n\t30899, 30900, 30901, 30901, 30902, 30903, 30904, 30905, \n\t30906, 30907, 30908, 30909, 30909, 30910, 30911, 30912, \n\t30913, 30914, 30915, 30916, 30916, 30917, 30918, 30919, \n\t30920, 30921, 30922, 30923, 30924, 30924, 30925, 30926, \n\t30927, 30928, 30929, 30930, 30931, 30931, 30932, 30933, \n\t30934, 30935, 30936, 30937, 30938, 30939, 30939, 30940, \n\t30941, 30942, 30943, 30944, 30945, 30946, 30946, 30947, \n\t30948, 30949, 30950, 30951, 30952, 30953, 30953, 30954, \n\t30955, 30956, 30957, 30958, 30959, 30960, 30961, 30961, \n\t30962, 30963, 30964, 30965, 30966, 30967, 30968, 30968, \n\t30969, 30970, 30971, 30972, 30973, 30974, 30975, 30976, \n\t30976, 30977, 30978, 30979, 30980, 30981, 30982, 30983, \n\t30983, 30984, 30985, 30986, 30987, 30988, 30989, 30990, \n\t30991, 30991, 30992, 30993, 30994, 30995, 30996, 30997, \n\t30998, 30998, 30999, 31000, 31001, 31002, 31003, 31004, \n\t31005, 31005, 31006, 31007, 31008, 31009, 31010, 31011, \n\t31012, 31013, 31013, 31014, 31015, 31016, 31017, 31018, \n\t31019, 31020, 31020, 31021, 31022, 31023, 31024, 31025, \n\t31026, 31027, 31028, 31028, 31029, 31030, 31031, 31032, \n\t31033, 31034, 31035, 31035, 31036, 31037, 31038, 31039, \n\t31040, 31041, 31042, 31042, 31043, 31044, 31045, 31046, \n\t31047, 31048, 31049, 31050, 31050, 31051, 31052, 31053, \n\t31054, 31055, 31056, 31057, 31057, 31058, 31059, 31060, \n\t31061, 31062, 31063, 31064, 31064, 31065, 31066, 31067, \n\t31068, 31069, 31070, 31071, 31072, 31072, 31073, 31074, \n\t31075, 31076, 31077, 31078, 31079, 31079, 31080, 31081, \n\t31082, 31083, 31084, 31085, 31086, 31087, 31087, 31088, \n\t31089, 31090, 31091, 31092, 31093, 31094, 31094, 31095, \n\t31096, 31097, 31098, 31099, 31100, 31101, 31101, 31102, \n\t31103, 31104, 31105, 31106, 31107, 31108, 31109, 31109, \n\t31110, 31111, 31112, 31113, 31114, 31115, 31116, 31116, \n\t31117, 31118, 31119, 31120, 31121, 31122, 31123, 31123, \n\t31124, 31125, 31126, 31127, 31128, 31129, 31130, 31131, \n\t31131, 31132, 31133, 31134, 31135, 31136, 31137, 31138, \n\t31138, 31139, 31140, 31141, 31142, 31143, 31144, 31145, \n\t31145, 31146, 31147, 31148, 31149, 31150, 31151, 31152, \n\t31153, 31153, 31154, 31155, 31156, 31157, 31158, 31159, \n\t31160, 31160, 31161, 31162, 31163, 31164, 31165, 31166, \n\t31167, 31167, 31168, 31169, 31170, 31171, 31172, 31173, \n\t31174, 31175, 31175, 31176, 31177, 31178, 31179, 31180, \n\t31181, 31182, 31182, 31183, 31184, 31185, 31186, 31187, \n\t31188, 31189, 31189, 31190, 31191, 31192, 31193, 31194, \n\t31195, 31196, 31196, 31197, 31198, 31199, 31200, 31201, \n\t31202, 31203, 31204, 31204, 31205, 31206, 31207, 31208, \n\t31209, 31210, 31211, 31211, 31212, 31213, 31214, 31215, \n\t31216, 31217, 31218, 31218, 31219, 31220, 31221, 31222, \n\t31223, 31224, 31225, 31226, 31226, 31227, 31228, 31229, \n\t31230, 31231, 31232, 31233, 31233, 31234, 31235, 31236, \n\t31237, 31238, 31239, 31240, 31240, 31241, 31242, 31243, \n\t31244, 31245, 31246, 31247, 31247, 31248, 31249, 31250, \n\t31251, 31252, 31253, 31254, 31255, 31255, 31256, 31257, \n\t31258, 31259, 31260, 31261, 31262, 31262, 31263, 31264, \n\t31265, 31266, 31267, 31268, 31269, 31269, 31270, 31271, \n\t31272, 31273, 31274, 31275, 31276, 31276, 31277, 31278, \n\t31279, 31280, 31281, 31282, 31283, 31284, 31284, 31285, \n\t31286, 31287, 31288, 31289, 31290, 31291, 31291, 31292, \n\t31293, 31294, 31295, 31296, 31297, 31298, 31298, 31299, \n\t31300, 31301, 31302, 31303, 31304, 31305, 31305, 31306, \n\t31307, 31308, 31309, 31310, 31311, 31312, 31313, 31313, \n\t31314, 31315, 31316, 31317, 31318, 31319, 31320, 31320, \n\t31321, 31322, 31323, 31324, 31325, 31326, 31327, 31327, \n\t31328, 31329, 31330, 31331, 31332, 31333, 31334, 31334, \n\t31335, 31336, 31337, 31338, 31339, 31340, 31341, 31341, \n\t31342, 31343, 31344, 31345, 31346, 31347, 31348, 31349, \n\t31349, 31350, 31351, 31352, 31353, 31354, 31355, 31356, \n\t31356, 31357, 31358, 31359, 31360, 31361, 31362, 31363, \n\t31363, 31364, 31365, 31366, 31367, 31368, 31369, 31370, \n\t31370, 31371, 31372, 31373, 31374, 31375, 31376, 31377, \n\t31377, 31378, 31379, 31380, 31381, 31382, 31383, 31384, \n\t31385, 31385, 31386, 31387, 31388, 31389, 31390, 31391, \n\t31392, 31392, 31393, 31394, 31395, 31396, 31397, 31398, \n\t31399, 31399, 31400, 31401, 31402, 31403, 31404, 31405, \n\t31406, 31406, 31407, 31408, 31409, 31410, 31411, 31412, \n\t31413, 31413, 31414, 31415, 31416, 31417, 31418, 31419, \n\t31420, 31421, 31421, 31422, 31423, 31424, 31425, 31426, \n\t31427, 31428, 31428, 31429, 31430, 31431, 31432, 31433, \n\t31434, 31435, 31435, 31436, 31437, 31438, 31439, 31440, \n\t31441, 31442, 31442, 31443, 31444, 31445, 31446, 31447, \n\t31448, 31449, 31449, 31450, 31451, 31452, 31453, 31454, \n\t31455, 31456, 31456, 31457, 31458, 31459, 31460, 31461, \n\t31462, 31463, 31464, 31464, 31465, 31466, 31467, 31468, \n\t31469, 31470, 31471, 31471, 31472, 31473, 31474, 31475, \n\t31476, 31477, 31478, 31478, 31479, 31480, 31481, 31482, \n\t31483, 31484, 31485, 31485, 31486, 31487, 31488, 31489, \n\t31490, 31491, 31492, 31492, 31493, 31494, 31495, 31496, \n\t31497, 31498, 31499, 31499, 31500, 31501, 31502, 31503, \n\t31504, 31505, 31506, 31506, 31507, 31508, 31509, 31510, \n\t31511, 31512, 31513, 31513, 31514, 31515, 31516, 31517, \n\t31518, 31519, 31520, 31521, 31521, 31522, 31523, 31524, \n\t31525, 31526, 31527, 31528, 31528, 31529, 31530, 31531, \n\t31532, 31533, 31534, 31535, 31535, 31536, 31537, 31538, \n\t31539, 31540, 31541, 31542, 31542, 31543, 31544, 31545, \n\t31546, 31547, 31548, 31549, 31549, 31550, 31551, 31552, \n\t31553, 31554, 31555, 31556, 31556, 31557, 31558, 31559, \n\t31560, 31561, 31562, 31563, 31563, 31564, 31565, 31566, \n\t31567, 31568, 31569, 31570, 31570, 31571, 31572, 31573, \n\t31574, 31575, 31576, 31577, 31577, 31578, 31579, 31580, \n\t31581, 31582, 31583, 31584, 31584, 31585, 31586, 31587, \n\t31588, 31589, 31590, 31591, 31591, 31592, 31593, 31594, \n\t31595, 31596, 31597, 31598, 31599, 31599, 31600, 31601, \n\t31602, 31603, 31604, 31605, 31606, 31606, 31607, 31608, \n\t31609, 31610, 31611, 31612, 31613, 31613, 31614, 31615, \n\t31616, 31617, 31618, 31619, 31620, 31620, 31621, 31622, \n\t31623, 31624, 31625, 31626, 31627, 31627, 31628, 31629, \n\t31630, 31631, 31632, 31633, 31634, 31634, 31635, 31636, \n\t31637, 31638, 31639, 31640, 31641, 31641, 31642, 31643, \n\t31644, 31645, 31646, 31647, 31648, 31648, 31649, 31650, \n\t31651, 31652, 31653, 31654, 31655, 31655, 31656, 31657, \n\t31658, 31659, 31660, 31661, 31662, 31662, 31663, 31664, \n\t31665, 31666, 31667, 31668, 31669, 31669, 31670, 31671, \n\t31672, 31673, 31674, 31675, 31676, 31676, 31677, 31678, \n\t31679, 31680, 31681, 31682, 31683, 31683, 31684, 31685, \n\t31686, 31687, 31688, 31689, 31690, 31690, 31691, 31692, \n\t31693, 31694, 31695, 31696, 31697, 31697, 31698, 31699, \n\t31700, 31701, 31702, 31703, 31704, 31704, 31705, 31706, \n\t31707, 31708, 31709, 31710, 31711, 31711, 31712, 31713, \n\t31714, 31715, 31716, 31717, 31718, 31718, 31719, 31720, \n\t31721, 31722, 31723, 31724, 31725, 31725, 31726, 31727, \n\t31728, 31729, 31730, 31731, 31732, 31732, 31733, 31734, \n\t31735, 31736, 31737, 31738, 31739, 31739, 31740, 31741, \n\t31742, 31743, 31744, 31745, 31746, 31746, 31747, 31748, \n\t31749, 31750, 31751, 31752, 31753, 31753, 31754, 31755, \n\t31756, 31757, 31758, 31759, 31760, 31760, 31761, 31762, \n\t31763, 31764, 31765, 31766, 31767, 31767, 31768, 31769, \n\t31770, 31771, 31772, 31773, 31774, 31774, 31775, 31776, \n\t31777, 31778, 31779, 31780, 31781, 31781, 31782, 31783, \n\t31784, 31785, 31786, 31787, 31788, 31788, 31789, 31790, \n\t31791, 31792, 31793, 31794, 31795, 31795, 31796, 31797, \n\t31798, 31799, 31800, 31801, 31802, 31802, 31803, 31804, \n\t31805, 31806, 31807, 31808, 31809, 31809, 31810, 31811, \n\t31812, 31813, 31814, 31815, 31816, 31816, 31817, 31818, \n\t31819, 31820, 31821, 31822, 31823, 31823, 31824, 31825, \n\t31826, 31827, 31828, 31829, 31830, 31830, 31831, 31832, \n\t31833, 31834, 31835, 31836, 31837, 31837, 31838, 31839, \n\t31840, 31841, 31842, 31843, 31844, 31844, 31845, 31846, \n\t31847, 31848, 31849, 31850, 31851, 31851, 31852, 31853, \n\t31854, 31855, 31856, 31857, 31858, 31858, 31859, 31860, \n\t31861, 31862, 31863, 31864, 31864, 31865, 31866, 31867, \n\t31868, 31869, 31870, 31871, 31871, 31872, 31873, 31874, \n\t31875, 31876, 31877, 31878, 31878, 31879, 31880, 31881, \n\t31882, 31883, 31884, 31885, 31885, 31886, 31887, 31888, \n\t31889, 31890, 31891, 31892, 31892, 31893, 31894, 31895, \n\t31896, 31897, 31898, 31899, 31899, 31900, 31901, 31902, \n\t31903, 31904, 31905, 31906, 31906, 31907, 31908, 31909, \n\t31910, 31911, 31912, 31913, 31913, 31914, 31915, 31916, \n\t31917, 31918, 31919, 31920, 31920, 31921, 31922, 31923, \n\t31924, 31925, 31926, 31927, 31927, 31928, 31929, 31930, \n\t31931, 31932, 31933, 31934, 31934, 31935, 31936, 31937, \n\t31938, 31939, 31940, 31940, 31941, 31942, 31943, 31944, \n\t31945, 31946, 31947, 31947, 31948, 31949, 31950, 31951, \n\t31952, 31953, 31954, 31954, 31955, 31956, 31957, 31958, \n\t31959, 31960, 31961, 31961, 31962, 31963, 31964, 31965, \n\t31966, 31967, 31968, 31968, 31969, 31970, 31971, 31972, \n\t31973, 31974, 31975, 31975, 31976, 31977, 31978, 31979, \n\t31980, 31981, 31982, 31982, 31983, 31984, 31985, 31986, \n\t31987, 31988, 31989, 31989, 31990, 31991, 31992, 31993, \n\t31994, 31995, 31995, 31996, 31997, 31998, 31999, 32000, \n\t32001, 32002, 32002, 32003, 32004, 32005, 32006, 32007, \n\t32008, 32009, 32009, 32010, 32011, 32012, 32013, 32014, \n\t32015, 32016, 32016, 32017, 32018, 32019, 32020, 32021, \n\t32022, 32023, 32023, 32024, 32025, 32026, 32027, 32028, \n\t32029, 32030, 32030, 32031, 32032, 32033, 32034, 32035, \n\t32036, 32036, 32037, 32038, 32039, 32040, 32041, 32042, \n\t32043, 32043, 32044, 32045, 32046, 32047, 32048, 32049, \n\t32050, 32050, 32051, 32052, 32053, 32054, 32055, 32056, \n\t32057, 32057, 32058, 32059, 32060, 32061, 32062, 32063, \n\t32064, 32064, 32065, 32066, 32067, 32068, 32069, 32070, \n\t32071, 32071, 32072, 32073, 32074, 32075, 32076, 32077, \n\t32077, 32078, 32079, 32080, 32081, 32082, 32083, 32084, \n\t32084, 32085, 32086, 32087, 32088, 32089, 32090, 32091, \n\t32091, 32092, 32093, 32094, 32095, 32096, 32097, 32098, \n\t32098, 32099, 32100, 32101, 32102, 32103, 32104, 32105, \n\t32105, 32106, 32107, 32108, 32109, 32110, 32111, 32111, \n\t32112, 32113, 32114, 32115, 32116, 32117, 32118, 32118, \n\t32119, 32120, 32121, 32122, 32123, 32124, 32125, 32125, \n\t32126, 32127, 32128, 32129, 32130, 32131, 32132, 32132, \n\t32133, 32134, 32135, 32136, 32137, 32138, 32139, 32139, \n\t32140, 32141, 32142, 32143, 32144, 32145, 32145, 32146, \n\t32147, 32148, 32149, 32150, 32151, 32152, 32152, 32153, \n\t32154, 32155, 32156, 32157, 32158, 32159, 32159, 32160, \n\t32161, 32162, 32163, 32164, 32165, 32166, 32166, 32167, \n\t32168, 32169, 32170, 32171, 32172, 32172, 32173, 32174, \n\t32175, 32176, 32177, 32178, 32179, 32179, 32180, 32181, \n\t32182, 32183, 32184, 32185, 32186, 32186, 32187, 32188, \n\t32189, 32190, 32191, 32192, 32193, 32193, 32194, 32195, \n\t32196, 32197, 32198, 32199, 32200, 32200, 32201, 32202, \n\t32203, 32204, 32205, 32206, 32206, 32207, 32208, 32209, \n\t32210, 32211, 32212, 32213, 32213, 32214, 32215, 32216, \n\t32217, 32218, 32219, 32220, 32220, 32221, 32222, 32223, \n\t32224, 32225, 32226, 32226, 32227, 32228, 32229, 32230, \n\t32231, 32232, 32233, 32233, 32234, 32235, 32236, 32237, \n\t32238, 32239, 32240, 32240, 32241, 32242, 32243, 32244, \n\t32245, 32246, 32247, 32247, 32248, 32249, 32250, 32251, \n\t32252, 32253, 32253, 32254, 32255, 32256, 32257, 32258, \n\t32259, 32260, 32260, 32261, 32262, 32263, 32264, 32265, \n\t32266, 32267, 32267, 32268, 32269, 32270, 32271, 32272, \n\t32273, 32274, 32274, 32275, 32276, 32277, 32278, 32279, \n\t32280, 32280, 32281, 32282, 32283, 32284, 32285, 32286, \n\t32287, 32287, 32288, 32289, 32290, 32291, 32292, 32293, \n\t32294, 32294, 32295, 32296, 32297, 32298, 32299, 32300, \n\t32300, 32301, 32302, 32303, 32304, 32305, 32306, 32307, \n\t32307, 32308, 32309, 32310, 32311, 32312, 32313, 32314, \n\t32314, 32315, 32316, 32317, 32318, 32319, 32320, 32320, \n\t32321, 32322, 32323, 32324, 32325, 32326, 32327, 32327, \n\t32328, 32329, 32330, 32331, 32332, 32333, 32334, 32334, \n\t32335, 32336, 32337, 32338, 32339, 32340, 32341, 32341, \n\t32342, 32343, 32344, 32345, 32346, 32347, 32347, 32348, \n\t32349, 32350, 32351, 32352, 32353, 32354, 32354, 32355, \n\t32356, 32357, 32358, 32359, 32360, 32361, 32361, 32362, \n\t32363, 32364, 32365, 32366, 32367, 32367, 32368, 32369, \n\t32370, 32371, 32372, 32373, 32374, 32374, 32375, 32376, \n\t32377, 32378, 32379, 32380, 32381, 32381, 32382, 32383, \n\t32384, 32385, 32386, 32387, 32387, 32388, 32389, 32390, \n\t32391, 32392, 32393, 32394, 32394, 32395, 32396, 32397, \n\t32398, 32399, 32400, 32400, 32401, 32402, 32403, 32404, \n\t32405, 32406, 32407, 32407, 32408, 32409, 32410, 32411, \n\t32412, 32413, 32414, 32414, 32415, 32416, 32417, 32418, \n\t32419, 32420, 32420, 32421, 32422, 32423, 32424, 32425, \n\t32426, 32427, 32427, 32428, 32429, 32430, 32431, 32432, \n\t32433, 32434, 32434, 32435, 32436, 32437, 32438, 32439, \n\t32440, 32440, 32441, 32442, 32443, 32444, 32445, 32446, \n\t32447, 32447, 32448, 32449, 32450, 32451, 32452, 32453, \n\t32454, 32454, 32455, 32456, 32457, 32458, 32459, 32460, \n\t32460, 32461, 32462, 32463, 32464, 32465, 32466, 32467, \n\t32467, 32468, 32469, 32470, 32471, 32472, 32473, 32473, \n\t32474, 32475, 32476, 32477, 32478, 32479, 32480, 32480, \n\t32481, 32482, 32483, 32484, 32485, 32486, 32487, 32487, \n\t32488, 32489, 32490, 32491, 32492, 32493, 32493, 32494, \n\t32495, 32496, 32497, 32498, 32499, 32500, 32500, 32501, \n\t32502, 32503, 32504, 32505, 32506, 32506, 32507, 32508, \n\t32509, 32510, 32511, 32512, 32513, 32513, 32514, 32515, \n\t32516, 32517, 32518, 32519, 32520, 32520, 32521, 32522, \n\t32523, 32524, 32525, 32526, 32526, 32527, 32528, 32529, \n\t32530, 32531, 32532, 32533, 32533, 32534, 32535, 32536, \n\t32537, 32538, 32539, 32539, 32540, 32541, 32542, 32543, \n\t32544, 32545, 32546, 32546, 32547, 32548, 32549, 32550, \n\t32551, 32552, 32552, 32553, 32554, 32555, 32556, 32557, \n\t32558, 32559, 32559, 32560, 32561, 32562, 32563, 32564, \n\t32565, 32566, 32566, 32567, 32568, 32569, 32570, 32571, \n\t32572, 32572, 32573, 32574, 32575, 32576, 32577, 32578, \n\t32579, 32579, 32580, 32581, 32582, 32583, 32584, 32585, \n\t32585, 32586, 32587, 32588, 32589, 32590, 32591, 32592, \n\t32592, 32593, 32594, 32595, 32596, 32597, 32598, 32598, \n\t32599, 32600, 32601, 32602, 32603, 32604, 32605, 32605, \n\t32606, 32607, 32608, 32609, 32610, 32611, 32611, 32612, \n\t32613, 32614, 32615, 32616, 32617, 32618, 32618, 32619, \n\t32620, 32621, 32622, 32623, 32624, 32625, 32625, 32626, \n\t32627, 32628, 32629, 32630, 32631, 32631, 32632, 32633, \n\t32634, 32635, 32636, 32637, 32638, 32638, 32639, 32640, \n\t32641, 32642, 32643, 32644, 32644, 32645, 32646, 32647, \n\t32648, 32649, 32650, 32651, 32651, 32652, 32653, 32654, \n\t32655, 32656, 32657, 32657, 32658, 32659, 32660, 32661, \n\t32662, 32663, 32664, 32664, 32665, 32666, 32667, 32668, \n\t32669, 32670, 32670, 32671, 32672, 32673, 32674, 32675, \n\t32676, 32677, 32677, 32678, 32679, 32680, 32681, 32682, \n\t32683, 32683, 32684, 32685, 32686, 32687, 32688, 32689, \n\t32690, 32690, 32691, 32692, 32693, 32694, 32695, 32696, \n\t32696, 32697, 32698, 32699, 32700, 32701, 32702, 32703, \n\t32703, 32704, 32705, 32706, 32707, 32708, 32709, 32709, \n\t32710, 32711, 32712, 32713, 32714, 32715, 32716, 32716, \n\t32717, 32718, 32719, 32720, 32721, 32722, 32722, 32723, \n\t32724, 32725, 32726, 32727, 32728, 32729, 32729, 32730, \n\t32731, 32732, 32733, 32734, 32735, 32735, 32736, 32737, \n\t32738, 32739, 32740, 32741, 32742, 32742, 32743, 32744, \n\t32745, 32746, 32747, 32748, 32748, 32749, 32750, 32751, \n\t32752, 32753, 32754, 32755, 32755, 32756, 32757, 32758, \n\t32759, 32760, 32761, 32761, 32762, 32763, 32764, 32765, \n\t32766, 32767, 32768, 32768, 32769, 32770, 32771, 32772, \n\t32773, 32774, 32774, 32775, 32776, 32777, 32778, 32779, \n\t32780, 32780, 32781, 32782, 32783, 32784, 32785, 32786, \n\t32787, 32787, 32788, 32789, 32790, 32791, 32792, 32793, \n\t32793, 32794, 32795, 32796, 32797, 32798, 32799, 32800, \n\t32800, 32801, 32802, 32803, 32804, 32805, 32806, 32806, \n\t32807, 32808, 32809, 32810, 32811, 32812, 32813, 32813, \n\t32814, 32815, 32816, 32817, 32818, 32819, 32819, 32820, \n\t32821, 32822, 32823, 32824, 32825, 32826, 32826, 32827, \n\t32828, 32829, 32830, 32831, 32832, 32832, 32833, 32834, \n\t32835, 32836, 32837, 32838, 32838, 32839, 32840, 32841, \n\t32842, 32843, 32844, 32845, 32845, 32846, 32847, 32848, \n\t32849, 32850, 32851, 32851, 32852, 32853, 32854, 32855, \n\t32856, 32857, 32858, 32858, 32859, 32860, 32861, 32862, \n\t32863, 32864, 32864, 32865, 32866, 32867, 32868, 32869, \n\t32870, 32871, 32871, 32872, 32873, 32874, 32875, 32876, \n\t32877, 32877, 32878, 32879, 32880, 32881, 32882, 32883, \n\t32883, 32884, 32885, 32886, 32887, 32888, 32889, 32890, \n\t32890, 32891, 32892, 32893, 32894, 32895, 32896, 32896, \n\t32897, 32898, 32899, 32900, 32901, 32902, 32903, 32903, \n\t32904, 32905, 32906, 32907, 32908, 32909, 32909, 32910, \n\t32911, 32912, 32913, 32914, 32915, 32915, 32916, 32917, \n\t32918, 32919, 32920, 32921, 32922, 32922, 32923, 32924, \n\t32925, 32926, 32927, 32928, 32928, 32929, 32930, 32931, \n\t32932, 32933, 32934, 32935, 32935, 32936, 32937, 32938, \n\t32939, 32940, 32941, 32941, 32942, 32943, 32944, 32945, \n\t32946, 32947, 32947, 32948, 32949, 32950, 32951, 32952, \n\t32953, 32954, 32954, 32955, 32956, 32957, 32958, 32959, \n\t32960, 32960, 32961, 32962, 32963, 32964, 32965, 32966, \n\t32966, 32967, 32968, 32969, 32970, 32971, 32972, 32973, \n\t32973, 32974, 32975, 32976, 32977, 32978, 32979, 32979, \n\t32980, 32981, 32982, 32983, 32984, 32985, 32986, 32986, \n\t32987, 32988, 32989, 32990, 32991, 32992, 32992, 32993, \n\t32994, 32995, 32996, 32997, 32998, 32998, 32999, 33000, \n\t33001, 33002, 33003, 33004, 33005, 33005, 33006, 33007, \n\t33008, 33009, 33010, 33011, 33011, 33012, 33013, 33014, \n\t33015, 33016, 33017, 33017, 33018, 33019, 33020, 33021, \n\t33022, 33023, 33024, 33024, 33025, 33026, 33027, 33028, \n\t33029, 33030, 33030, 33031, 33032, 33033, 33034, 33035, \n\t33036, 33036, 33037, 33038, 33039, 33040, 33041, 33042, \n\t33043, 33043, 33044, 33045, 33046, 33047, 33048, 33049, \n\t33049, 33050, 33051, 33052, 33053, 33054, 33055, 33055, \n\t33056, 33057, 33058, 33059, 33060, 33061, 33062, 33062, \n\t33063, 33064, 33065, 33066, 33067, 33068, 33068, 33069, \n\t33070, 33071, 33072, 33073, 33074, 33074, 33075, 33076, \n\t33077, 33078, 33079, 33080, 33081, 33081, 33082, 33083, \n\t33084, 33085, 33086, 33087, 33087, 33088, 33089, 33090, \n\t33091, 33092, 33093, 33093, 33094, 33095, 33096, 33097, \n\t33098, 33099, 33099, 33100, 33101, 33102, 33103, 33104, \n\t33105, 33106, 33106, 33107, 33108, 33109, 33110, 33111, \n\t33112, 33112, 33113, 33114, 33115, 33116, 33117, 33118, \n\t33118, 33119, 33120, 33121, 33122, 33123, 33124, 33125, \n\t33125, 33126, 33127, 33128, 33129, 33130, 33131, 33131, \n\t33132, 33133, 33134, 33135, 33136, 33137, 33137, 33138, \n\t33139, 33140, 33141, 33142, 33143, 33144, 33144, 33145, \n\t33146, 33147, 33148, 33149, 33150, 33150, 33151, 33152, \n\t33153, 33154, 33155, 33156, 33156, 33157, 33158, 33159, \n\t33160, 33161, 33162, 33162, 33163, 33164, 33165, 33166, \n\t33167, 33168, 33169, 33169, 33170, 33171, 33172, 33173, \n\t33174, 33175, 33175, 33176, 33177, 33178, 33179, 33180, \n\t33181, 33181, 33182, 33183, 33184, 33185, 33186, 33187, \n\t33187, 33188, 33189, 33190, 33191, 33192, 33193, 33194, \n\t33194, 33195, 33196, 33197, 33198, 33199, 33200, 33200, \n\t33201, 33202, 33203, 33204, 33205, 33206, 33206, 33207, \n\t33208, 33209, 33210, 33211, 33212, 33212, 33213, 33214, \n\t33215, 33216, 33217, 33218, 33219, 33219, 33220, 33221, \n\t33222, 33223, 33224, 33225, 33225, 33226, 33227, 33228, \n\t33229, 33230, 33231, 33231, 33232, 33233, 33234, 33235, \n\t33236, 33237, 33237, 33238, 33239, 33240, 33241, 33242, \n\t33243, 33244, 33244, 33245, 33246, 33247, 33248, 33249, \n\t33250, 33250, 33251, 33252, 33253, 33254, 33255, 33256, \n\t33256, 33257, 33258, 33259, 33260, 33261, 33262, 33262, \n\t33263, 33264, 33265, 33266, 33267, 33268, 33269, 33269, \n\t33270, 33271, 33272, 33273, 33274, 33275, 33275, 33276, \n\t33277, 33278, 33279, 33280, 33281, 33281, 33282, 33283, \n\t33284, 33285, 33286, 33287, 33287, 33288, 33289, 33290, \n\t33291, 33292, 33293, 33293, 33294, 33295, 33296, 33297, \n\t33298, 33299, 33300, 33300, 33301, 33302, 33303, 33304, \n\t33305, 33306, 33306, 33307, 33308, 33309, 33310, 33311, \n\t33312, 33312, 33313, 33314, 33315, 33316, 33317, 33318, \n\t33318, 33319, 33320, 33321, 33322, 33323, 33324, 33325, \n\t33325, 33326, 33327, 33328, 33329, 33330, 33331, 33331, \n\t33332, 33333, 33334, 33335, 33336, 33337, 33337, 33338, \n\t33339, 33340, 33341, 33342, 33343, 33343, 33344, 33345, \n\t33346, 33347, 33348, 33349, 33349, 33350, 33351, 33352, \n\t33353, 33354, 33355, 33355, 33356, 33357, 33358, 33359, \n\t33360, 33361, 33362, 33362, 33363, 33364, 33365, 33366, \n\t33367, 33368, 33368, 33369, 33370, 33371, 33372, 33373, \n\t33374, 33374, 33375, 33376, 33377, 33378, 33379, 33380, \n\t33380, 33381, 33382, 33383, 33384, 33385, 33386, 33386, \n\t33387, 33388, 33389, 33390, 33391, 33392, 33393, 33393, \n\t33394, 33395, 33396, 33397, 33398, 33399, 33399, 33400, \n\t33401, 33402, 33403, 33404, 33405, 33405, 33406, 33407, \n\t33408, 33409, 33410, 33411, 33411, 33412, 33413, 33414, \n\t33415, 33416, 33417, 33417, 33418, 33419, 33420, 33421, \n\t33422, 33423, 33423, 33424, 33425, 33426, 33427, 33428, \n\t33429, 33429, 33430, 33431, 33432, 33433, 33434, 33435, \n\t33436, 33436, 33437, 33438, 33439, 33440, 33441, 33442, \n\t33442, 33443, 33444, 33445, 33446, 33447, 33448, 33448, \n\t33449, 33450, 33451, 33452, 33453, 33454, 33454, 33455, \n\t33456, 33457, 33458, 33459, 33460, 33460, 33461, 33462, \n\t33463, 33464, 33465, 33466, 33466, 33467, 33468, 33469, \n\t33470, 33471, 33472, 33472, 33473, 33474, 33475, 33476, \n\t33477, 33478, 33479, 33479, 33480, 33481, 33482, 33483, \n\t33484, 33485, 33485, 33486, 33487, 33488, 33489, 33490, \n\t33491, 33491, 33492, 33493, 33494, 33495, 33496, 33497, \n\t33497, 33498, 33499, 33500, 33501, 33502, 33503, 33503, \n\t33504, 33505, 33506, 33507, 33508, 33509, 33509, 33510, \n\t33511, 33512, 33513, 33514, 33515, 33515, 33516, 33517, \n\t33518, 33519, 33520, 33521, 33521, 33522, 33523, 33524, \n\t33525, 33526, 33527, 33527, 33528, 33529, 33530, 33531, \n\t33532, 33533, 33534, 33534, 33535, 33536, 33537, 33538, \n\t33539, 33540, 33540, 33541, 33542, 33543, 33544, 33545, \n\t33546, 33546, 33547, 33548, 33549, 33550, 33551, 33552, \n\t33552, 33553, 33554, 33555, 33556, 33557, 33558, 33558, \n\t33559, 33560, 33561, 33562, 33563, 33564, 33564, 33565, \n\t33566, 33567, 33568, 33569, 33570, 33570, 33571, 33572, \n\t33573, 33574, 33575, 33576, 33576, 33577, 33578, 33579, \n\t33580, 33581, 33582, 33582, 33583, 33584, 33585, 33586, \n\t33587, 33588, 33588, 33589, 33590, 33591, 33592, 33593, \n\t33594, 33594, 33595, 33596, 33597, 33598, 33599, 33600, \n\t33601, 33601, 33602, 33603, 33604, 33605, 33606, 33607, \n\t33607, 33608, 33609, 33610, 33611, 33612, 33613, 33613, \n\t33614, 33615, 33616, 33617, 33618, 33619, 33619, 33620, \n\t33621, 33622, 33623, 33624, 33625, 33625, 33626, 33627, \n\t33628, 33629, 33630, 33631, 33631, 33632, 33633, 33634, \n\t33635, 33636, 33637, 33637, 33638, 33639, 33640, 33641, \n\t33642, 33643, 33643, 33644, 33645, 33646, 33647, 33648, \n\t33649, 33649, 33650, 33651, 33652, 33653, 33654, 33655, \n\t33655, 33656, 33657, 33658, 33659, 33660, 33661, 33661, \n\t33662, 33663, 33664, 33665, 33666, 33667, 33667, 33668, \n\t33669, 33670, 33671, 33672, 33673, 33673, 33674, 33675, \n\t33676, 33677, 33678, 33679, 33679, 33680, 33681, 33682, \n\t33683, 33684, 33685, 33685, 33686, 33687, 33688, 33689, \n\t33690, 33691, 33691, 33692, 33693, 33694, 33695, 33696, \n\t33697, 33697, 33698, 33699, 33700, 33701, 33702, 33703, \n\t33703, 33704, 33705, 33706, 33707, 33708, 33709, 33709, \n\t33710, 33711, 33712, 33713, 33714, 33715, 33715, 33716, \n\t33717, 33718, 33719, 33720, 33721, 33721, 33722, 33723, \n\t33724, 33725, 33726, 33727, 33727, 33728, 33729, 33730, \n\t33731, 33732, 33733, 33733, 33734, 33735, 33736, 33737, \n\t33738, 33739, 33739, 33740, 33741, 33742, 33743, 33744, \n\t33745, 33745, 33746, 33747, 33748, 33749, 33750, 33751, \n\t33751, 33752, 33753, 33754, 33755, 33756, 33757, 33757, \n\t33758, 33759, 33760, 33761, 33762, 33763, 33763, 33764, \n\t33765, 33766, 33767, 33768, 33769, 33769, 33770, 33771, \n\t33772, 33773, 33774, 33775, 33775, 33776, 33777, 33778, \n\t33779, 33780, 33781, 33781, 33782, 33783, 33784, 33785, \n\t33786, 33787, 33787, 33788, 33789, 33790, 33791, 33792, \n\t33793, 33793, 33794, 33795, 33796, 33797, 33798, 33799, \n\t33799, 33800, 33801, 33802, 33803, 33804, 33805, 33805, \n\t33806, 33807, 33808, 33809, 33810, 33811, 33811, 33812, \n\t33813, 33814, 33815, 33816, 33817, 33817, 33818, 33819, \n\t33820, 33821, 33822, 33823, 33823, 33824, 33825, 33826, \n\t33827, 33828, 33829, 33829, 33830, 33831, 33832, 33833, \n\t33834, 33835, 33835, 33836, 33837, 33838, 33839, 33840, \n\t33841, 33841, 33842, 33843, 33844, 33845, 33846, 33847, \n\t33847, 33848, 33849, 33850, 33851, 33852, 33853, 33853, \n\t33854, 33855, 33856, 33857, 33858, 33859, 33859, 33860, \n\t33861, 33862, 33863, 33864, 33865, 33865, 33866, 33867, \n\t33868, 33869, 33870, 33871, 33871, 33872, 33873, 33874, \n\t33875, 33876, 33877, 33877, 33878, 33879, 33880, 33881, \n\t33882, 33883, 33883, 33884, 33885, 33886, 33887, 33888, \n\t33889, 33889, 33890, 33891, 33892, 33893, 33894, 33895, \n\t33895, 33896, 33897, 33898, 33899, 33900, 33901, 33901, \n\t33902, 33903, 33904, 33905, 33906, 33907, 33907, 33908, \n\t33909, 33910, 33911, 33912, 33912, 33913, 33914, 33915, \n\t33916, 33917, 33918, 33918, 33919, 33920, 33921, 33922, \n\t33923, 33924, 33924, 33925, 33926, 33927, 33928, 33929, \n\t33930, 33930, 33931, 33932, 33933, 33934, 33935, 33936, \n\t33936, 33937, 33938, 33939, 33940, 33941, 33942, 33942, \n\t33943, 33944, 33945, 33946, 33947, 33948, 33948, 33949, \n\t33950, 33951, 33952, 33953, 33954, 33954, 33955, 33956, \n\t33957, 33958, 33959, 33960, 33960, 33961, 33962, 33963, \n\t33964, 33965, 33966, 33966, 33967, 33968, 33969, 33970, \n\t33971, 33972, 33972, 33973, 33974, 33975, 33976, 33977, \n\t33978, 33978, 33979, 33980, 33981, 33982, 33983, 33983, \n\t33984, 33985, 33986, 33987, 33988, 33989, 33989, 33990, \n\t33991, 33992, 33993, 33994, 33995, 33995, 33996, 33997, \n\t33998, 33999, 34000, 34001, 34001, 34002, 34003, 34004, \n\t34005, 34006, 34007, 34007, 34008, 34009, 34010, 34011, \n\t34012, 34013, 34013, 34014, 34015, 34016, 34017, 34018, \n\t34019, 34019, 34020, 34021, 34022, 34023, 34024, 34025, \n\t34025, 34026, 34027, 34028, 34029, 34030, 34031, 34031, \n\t34032, 34033, 34034, 34035, 34036, 34036, 34037, 34038, \n\t34039, 34040, 34041, 34042, 34042, 34043, 34044, 34045, \n\t34046, 34047, 34048, 34048, 34049, 34050, 34051, 34052, \n\t34053, 34054, 34054, 34055, 34056, 34057, 34058, 34059, \n\t34060, 34060, 34061, 34062, 34063, 34064, 34065, 34066, \n\t34066, 34067, 34068, 34069, 34070, 34071, 34072, 34072, \n\t34073, 34074, 34075, 34076, 34077, 34078, 34078, 34079, \n\t34080, 34081, 34082, 34083, 34083, 34084, 34085, 34086, \n\t34087, 34088, 34089, 34089, 34090, 34091, 34092, 34093, \n\t34094, 34095, 34095, 34096, 34097, 34098, 34099, 34100, \n\t34101, 34101, 34102, 34103, 34104, 34105, 34106, 34107, \n\t34107, 34108, 34109, 34110, 34111, 34112, 34113, 34113, \n\t34114, 34115, 34116, 34117, 34118, 34118, 34119, 34120, \n\t34121, 34122, 34123, 34124, 34124, 34125, 34126, 34127, \n\t34128, 34129, 34130, 34130, 34131, 34132, 34133, 34134, \n\t34135, 34136, 34136, 34137, 34138, 34139, 34140, 34141, \n\t34142, 34142, 34143, 34144, 34145, 34146, 34147, 34148, \n\t34148, 34149, 34150, 34151, 34152, 34153, 34153, 34154, \n\t34155, 34156, 34157, 34158, 34159, 34159, 34160, 34161, \n\t34162, 34163, 34164, 34165, 34165, 34166, 34167, 34168, \n\t34169, 34170, 34171, 34171, 34172, 34173, 34174, 34175, \n\t34176, 34177, 34177, 34178, 34179, 34180, 34181, 34182, \n\t34183, 34183, 34184, 34185, 34186, 34187, 34188, 34188, \n\t34189, 34190, 34191, 34192, 34193, 34194, 34194, 34195, \n\t34196, 34197, 34198, 34199, 34200, 34200, 34201, 34202, \n\t34203, 34204, 34205, 34206, 34206, 34207, 34208, 34209, \n\t34210, 34211, 34212, 34212, 34213, 34214, 34215, 34216, \n\t34217, 34217, 34218, 34219, 34220, 34221, 34222, 34223, \n\t34223, 34224, 34225, 34226, 34227, 34228, 34229, 34229, \n\t34230, 34231, 34232, 34233, 34234, 34235, 34235, 34236, \n\t34237, 34238, 34239, 34240, 34241, 34241, 34242, 34243, \n\t34244, 34245, 34246, 34246, 34247, 34248, 34249, 34250, \n\t34251, 34252, 34252, 34253, 34254, 34255, 34256, 34257, \n\t34258, 34258, 34259, 34260, 34261, 34262, 34263, 34264, \n\t34264, 34265, 34266, 34267, 34268, 34269, 34269, 34270, \n\t34271, 34272, 34273, 34274, 34275, 34275, 34276, 34277, \n\t34278, 34279, 34280, 34281, 34281, 34282, 34283, 34284, \n\t34285, 34286, 34287, 34287, 34288, 34289, 34290, 34291, \n\t34292, 34293, 34293, 34294, 34295, 34296, 34297, 34298, \n\t34298, 34299, 34300, 34301, 34302, 34303, 34304, 34304, \n\t34305, 34306, 34307, 34308, 34309, 34310, 34310, 34311, \n\t34312, 34313, 34314, 34315, 34316, 34316, 34317, 34318, \n\t34319, 34320, 34321, 34321, 34322, 34323, 34324, 34325, \n\t34326, 34327, 34327, 34328, 34329, 34330, 34331, 34332, \n\t34333, 34333, 34334, 34335, 34336, 34337, 34338, 34339, \n\t34339, 34340, 34341, 34342, 34343, 34344, 34344, 34345, \n\t34346, 34347, 34348, 34349, 34350, 34350, 34351, 34352, \n\t34353, 34354, 34355, 34356, 34356, 34357, 34358, 34359, \n\t34360, 34361, 34362, 34362, 34363, 34364, 34365, 34366, \n\t34367, 34367, 34368, 34369, 34370, 34371, 34372, 34373, \n\t34373, 34374, 34375, 34376, 34377, 34378, 34379, 34379, \n\t34380, 34381, 34382, 34383, 34384, 34384, 34385, 34386, \n\t34387, 34388, 34389, 34390, 34390, 34391, 34392, 34393, \n\t34394, 34395, 34396, 34396, 34397, 34398, 34399, 34400, \n\t34401, 34402, 34402, 34403, 34404, 34405, 34406, 34407, \n\t34407, 34408, 34409, 34410, 34411, 34412, 34413, 34413, \n\t34414, 34415, 34416, 34417, 34418, 34419, 34419, 34420, \n\t34421, 34422, 34423, 34424, 34424, 34425, 34426, 34427, \n\t34428, 34429, 34430, 34430, 34431, 34432, 34433, 34434, \n\t34435, 34436, 34436, 34437, 34438, 34439, 34440, 34441, \n\t34442, 34442, 34443, 34444, 34445, 34446, 34447, 34447, \n\t34448, 34449, 34450, 34451, 34452, 34453, 34453, 34454, \n\t34455, 34456, 34457, 34458, 34459, 34459, 34460, 34461, \n\t34462, 34463, 34464, 34464, 34465, 34466, 34467, 34468, \n\t34469, 34470, 34470, 34471, 34472, 34473, 34474, 34475, \n\t34476, 34476, 34477, 34478, 34479, 34480, 34481, 34481, \n\t34482, 34483, 34484, 34485, 34486, 34487, 34487, 34488, \n\t34489, 34490, 34491, 34492, 34493, 34493, 34494, 34495, \n\t34496, 34497, 34498, 34498, 34499, 34500, 34501, 34502, \n\t34503, 34504, 34504, 34505, 34506, 34507, 34508, 34509, \n\t34510, 34510, 34511, 34512, 34513, 34514, 34515, 34515, \n\t34516, 34517, 34518, 34519, 34520, 34521, 34521, 34522, \n\t34523, 34524, 34525, 34526, 34527, 34527, 34528, 34529, \n\t34530, 34531, 34532, 34532, 34533, 34534, 34535, 34536, \n\t34537, 34538, 34538, 34539, 34540, 34541, 34542, 34543, \n\t34544, 34544, 34545, 34546, 34547, 34548, 34549, 34549, \n\t34550, 34551, 34552, 34553, 34554, 34555, 34555, 34556, \n\t34557, 34558, 34559, 34560, 34561, 34561, 34562, 34563, \n\t34564, 34565, 34566, 34566, 34567, 34568, 34569, 34570, \n\t34571, 34572, 34572, 34573, 34574, 34575, 34576, 34577, \n\t34578, 34578, 34579, 34580, 34581, 34582, 34583, 34583, \n\t34584, 34585, 34586, 34587, 34588, 34589, 34589, 34590, \n\t34591, 34592, 34593, 34594, 34595, 34595, 34596, 34597, \n\t34598, 34599, 34600, 34600, 34601, 34602, 34603, 34604, \n\t34605, 34606, 34606, 34607, 34608, 34609, 34610, 34611, \n\t34612, 34612, 34613, 34614, 34615, 34616, 34617, 34617, \n\t34618, 34619, 34620, 34621, 34622, 34623, 34623, 34624, \n\t34625, 34626, 34627, 34628, 34628, 34629, 34630, 34631, \n\t34632, 34633, 34634, 34634, 34635, 34636, 34637, 34638, \n\t34639, 34640, 34640, 34641, 34642, 34643, 34644, 34645, \n\t34645, 34646, 34647, 34648, 34649, 34650, 34651, 34651, \n\t34652, 34653, 34654, 34655, 34656, 34656, 34657, 34658, \n\t34659, 34660, 34661, 34662, 34662, 34663, 34664, 34665, \n\t34666, 34667, 34668, 34668, 34669, 34670, 34671, 34672, \n\t34673, 34673, 34674, 34675, 34676, 34677, 34678, 34679, \n\t34679, 34680, 34681, 34682, 34683, 34684, 34685, 34685, \n\t34686, 34687, 34688, 34689, 34690, 34690, 34691, 34692, \n\t34693, 34694, 34695, 34696, 34696, 34697, 34698, 34699, \n\t34700, 34701, 34701, 34702, 34703, 34704, 34705, 34706, \n\t34707, 34707, 34708, 34709, 34710, 34711, 34712, 34712, \n\t34713, 34714, 34715, 34716, 34717, 34718, 34718, 34719, \n\t34720, 34721, 34722, 34723, 34724, 34724, 34725, 34726, \n\t34727, 34728, 34729, 34729, 34730, 34731, 34732, 34733, \n\t34734, 34735, 34735, 34736, 34737, 34738, 34739, 34740, \n\t34740, 34741, 34742, 34743, 34744, 34745, 34746, 34746, \n\t34747, 34748, 34749, 34750, 34751, 34752, 34752, 34753, \n\t34754, 34755, 34756, 34757, 34757, 34758, 34759, 34760, \n\t34761, 34762, 34763, 34763, 34764, 34765, 34766, 34767, \n\t34768, 34768, 34769, 34770, 34771, 34772, 34773, 34774, \n\t34774, 34775, 34776, 34777, 34778, 34779, 34779, 34780, \n\t34781, 34782, 34783, 34784, 34785, 34785, 34786, 34787, \n\t34788, 34789, 34790, 34790, 34791, 34792, 34793, 34794, \n\t34795, 34796, 34796, 34797, 34798, 34799, 34800, 34801, \n\t34802, 34802, 34803, 34804, 34805, 34806, 34807, 34807, \n\t34808, 34809, 34810, 34811, 34812, 34813, 34813, 34814, \n\t34815, 34816, 34817, 34818, 34818, 34819, 34820, 34821, \n\t34822, 34823, 34824, 34824, 34825, 34826, 34827, 34828, \n\t34829, 34829, 34830, 34831, 34832, 34833, 34834, 34835, \n\t34835, 34836, 34837, 34838, 34839, 34840, 34840, 34841, \n\t34842, 34843, 34844, 34845, 34846, 34846, 34847, 34848, \n\t34849, 34850, 34851, 34851, 34852, 34853, 34854, 34855, \n\t34856, 34857, 34857, 34858, 34859, 34860, 34861, 34862, \n\t34863, 34863, 34864, 34865, 34866, 34867, 34868, 34868, \n\t34869, 34870, 34871, 34872, 34873, 34874, 34874, 34875, \n\t34876, 34877, 34878, 34879, 34879, 34880, 34881, 34882, \n\t34883, 34884, 34885, 34885, 34886, 34887, 34888, 34889, \n\t34890, 34890, 34891, 34892, 34893, 34894, 34895, 34896, \n\t34896, 34897, 34898, 34899, 34900, 34901, 34901, 34902, \n\t34903, 34904, 34905, 34906, 34907, 34907, 34908, 34909, \n\t34910, 34911, 34912, 34912, 34913, 34914, 34915, 34916, \n\t34917, 34918, 34918, 34919, 34920, 34921, 34922, 34923, \n\t34923, 34924, 34925, 34926, 34927, 34928, 34929, 34929, \n\t34930, 34931, 34932, 34933, 34934, 34934, 34935, 34936, \n\t34937, 34938, 34939, 34940, 34940, 34941, 34942, 34943, \n\t34944, 34945, 34945, 34946, 34947, 34948, 34949, 34950, \n\t34951, 34951, 34952, 34953, 34954, 34955, 34956, 34956, \n\t34957, 34958, 34959, 34960, 34961, 34962, 34962, 34963, \n\t34964, 34965, 34966, 34967, 34967, 34968, 34969, 34970, \n\t34971, 34972, 34973, 34973, 34974, 34975, 34976, 34977, \n\t34978, 34978, 34979, 34980, 34981, 34982, 34983, 34984, \n\t34984, 34985, 34986, 34987, 34988, 34989, 34989, 34990, \n\t34991, 34992, 34993, 34994, 34995, 34995, 34996, 34997, \n\t34998, 34999, 35000, 35000, 35001, 35002, 35003, 35004, \n\t35005, 35005, 35006, 35007, 35008, 35009, 35010, 35011, \n\t35011, 35012, 35013, 35014, 35015, 35016, 35016, 35017, \n\t35018, 35019, 35020, 35021, 35022, 35022, 35023, 35024, \n\t35025, 35026, 35027, 35027, 35028, 35029, 35030, 35031, \n\t35032, 35033, 35033, 35034, 35035, 35036, 35037, 35038, \n\t35038, 35039, 35040, 35041, 35042, 35043, 35044, 35044, \n\t35045, 35046, 35047, 35048, 35049, 35049, 35050, 35051, \n\t35052, 35053, 35054, 35055, 35055, 35056, 35057, 35058, \n\t35059, 35060, 35060, 35061, 35062, 35063, 35064, 35065, \n\t35065, 35066, 35067, 35068, 35069, 35070, 35071, 35071, \n\t35072, 35073, 35074, 35075, 35076, 35076, 35077, 35078, \n\t35079, 35080, 35081, 35082, 35082, 35083, 35084, 35085, \n\t35086, 35087, 35087, 35088, 35089, 35090, 35091, 35092, \n\t35093, 35093, 35094, 35095, 35096, 35097, 35098, 35098, \n\t35099, 35100, 35101, 35102, 35103, 35104, 35104, 35105, \n\t35106, 35107, 35108, 35109, 35109, 35110, 35111, 35112, \n\t35113, 35114, 35114, 35115, 35116, 35117, 35118, 35119, \n\t35120, 35120, 35121, 35122, 35123, 35124, 35125, 35125, \n\t35126, 35127, 35128, 35129, 35130, 35131, 35131, 35132, \n\t35133, 35134, 35135, 35136, 35136, 35137, 35138, 35139, \n\t35140, 35141, 35141, 35142, 35143, 35144, 35145, 35146, \n\t35147, 35147, 35148, 35149, 35150, 35151, 35152, 35152, \n\t35153, 35154, 35155, 35156, 35157, 35158, 35158, 35159, \n\t35160, 35161, 35162, 35163, 35163, 35164, 35165, 35166, \n\t35167, 35168, 35169, 35169, 35170, 35171, 35172, 35173, \n\t35174, 35174, 35175, 35176, 35177, 35178, 35179, 35179, \n\t35180, 35181, 35182, 35183, 35184, 35185, 35185, 35186, \n\t35187, 35188, 35189, 35190, 35190, 35191, 35192, 35193, \n\t35194, 35195, 35195, 35196, 35197, 35198, 35199, 35200, \n\t35201, 35201, 35202, 35203, 35204, 35205, 35206, 35206, \n\t35207, 35208, 35209, 35210, 35211, 35212, 35212, 35213, \n\t35214, 35215, 35216, 35217, 35217, 35218, 35219, 35220, \n\t35221, 35222, 35222, 35223, 35224, 35225, 35226, 35227, \n\t35228, 35228, 35229, 35230, 35231, 35232, 35233, 35233, \n\t35234, 35235, 35236, 35237, 35238, 35239, 35239, 35240, \n\t35241, 35242, 35243, 35244, 35244, 35245, 35246, 35247, \n\t35248, 35249, 35249, 35250, 35251, 35252, 35253, 35254, \n\t35255, 35255, 35256, 35257, 35258, 35259, 35260, 35260, \n\t35261, 35262, 35263, 35264, 35265, 35265, 35266, 35267, \n\t35268, 35269, 35270, 35271, 35271, 35272, 35273, 35274, \n\t35275, 35276, 35276, 35277, 35278, 35279, 35280, 35281, \n\t35281, 35282, 35283, 35284, 35285, 35286, 35287, 35287, \n\t35288, 35289, 35290, 35291, 35292, 35292, 35293, 35294, \n\t35295, 35296, 35297, 35298, 35298, 35299, 35300, 35301, \n\t35302, 35303, 35303, 35304, 35305, 35306, 35307, 35308, \n\t35308, 35309, 35310, 35311, 35312, 35313, 35314, 35314, \n\t35315, 35316, 35317, 35318, 35319, 35319, 35320, 35321, \n\t35322, 35323, 35324, 35324, 35325, 35326, 35327, 35328, \n\t35329, 35330, 35330, 35331, 35332, 35333, 35334, 35335, \n\t35335, 35336, 35337, 35338, 35339, 35340, 35340, 35341, \n\t35342, 35343, 35344, 35345, 35346, 35346, 35347, 35348, \n\t35349, 35350, 35351, 35351, 35352, 35353, 35354, 35355, \n\t35356, 35356, 35357, 35358, 35359, 35360, 35361, 35362, \n\t35362, 35363, 35364, 35365, 35366, 35367, 35367, 35368, \n\t35369, 35370, 35371, 35372, 35372, 35373, 35374, 35375, \n\t35376, 35377, 35378, 35378, 35379, 35380, 35381, 35382, \n\t35383, 35383, 35384, 35385, 35386, 35387, 35388, 35388, \n\t35389, 35390, 35391, 35392, 35393, 35394, 35394, 35395, \n\t35396, 35397, 35398, 35399, 35399, 35400, 35401, 35402, \n\t35403, 35404, 35404, 35405, 35406, 35407, 35408, 35409, \n\t35409, 35410, 35411, 35412, 35413, 35414, 35415, 35415, \n\t35416, 35417, 35418, 35419, 35420, 35420, 35421, 35422, \n\t35423, 35424, 35425, 35425, 35426, 35427, 35428, 35429, \n\t35430, 35431, 35431, 35432, 35433, 35434, 35435, 35436, \n\t35436, 35437, 35438, 35439, 35440, 35441, 35441, 35442, \n\t35443, 35444, 35445, 35446, 35447, 35447, 35448, 35449, \n\t35450, 35451, 35452, 35452, 35453, 35454, 35455, 35456, \n\t35457, 35457, 35458, 35459, 35460, 35461, 35462, 35462, \n\t35463, 35464, 35465, 35466, 35467, 35468, 35468, 35469, \n\t35470, 35471, 35472, 35473, 35473, 35474, 35475, 35476, \n\t35477, 35478, 35478, 35479, 35480, 35481, 35482, 35483, \n\t35484, 35484, 35485, 35486, 35487, 35488, 35489, 35489, \n\t35490, 35491, 35492, 35493, 35494, 35494, 35495, 35496, \n\t35497, 35498, 35499, 35499, 35500, 35501, 35502, 35503, \n\t35504, 35505, 35505, 35506, 35507, 35508, 35509, 35510, \n\t35510, 35511, 35512, 35513, 35514, 35515, 35515, 35516, \n\t35517, 35518, 35519, 35520, 35520, 35521, 35522, 35523, \n\t35524, 35525, 35526, 35526, 35527, 35528, 35529, 35530, \n\t35531, 35531, 35532, 35533, 35534, 35535, 35536, 35536, \n\t35537, 35538, 35539, 35540, 35541, 35542, 35542, 35543, \n\t35544, 35545, 35546, 35547, 35547, 35548, 35549, 35550, \n\t35551, 35552, 35552, 35553, 35554, 35555, 35556, 35557, \n\t35557, 35558, 35559, 35560, 35561, 35562, 35563, 35563, \n\t35564, 35565, 35566, 35567, 35568, 35568, 35569, 35570, \n\t35571, 35572, 35573, 35573, 35574, 35575, 35576, 35577, \n\t35578, 35578, 35579, 35580, 35581, 35582, 35583, 35584, \n\t35584, 35585, 35586, 35587, 35588, 35589, 35589, 35590, \n\t35591, 35592, 35593, 35594, 35594, 35595, 35596, 35597, \n\t35598, 35599, 35599, 35600, 35601, 35602, 35603, 35604, \n\t35604, 35605, 35606, 35607, 35608, 35609, 35610, 35610, \n\t35611, 35612, 35613, 35614, 35615, 35615, 35616, 35617, \n\t35618, 35619, 35620, 35620, 35621, 35622, 35623, 35624, \n\t35625, 35625, 35626, 35627, 35628, 35629, 35630, 35631, \n\t35631, 35632, 35633, 35634, 35635, 35636, 35636, 35637, \n\t35638, 35639, 35640, 35641, 35641, 35642, 35643, 35644, \n\t35645, 35646, 35646, 35647, 35648, 35649, 35650, 35651, \n\t35651, 35652, 35653, 35654, 35655, 35656, 35657, 35657, \n\t35658, 35659, 35660, 35661, 35662, 35662, 35663, 35664, \n\t35665, 35666, 35667, 35667, 35668, 35669, 35670, 35671, \n\t35672, 35672, 35673, 35674, 35675, 35676, 35677, 35678, \n\t35678, 35679, 35680, 35681, 35682, 35683, 35683, 35684, \n\t35685, 35686, 35687, 35688, 35688, 35689, 35690, 35691, \n\t35692, 35693, 35693, 35694, 35695, 35696, 35697, 35698, \n\t35698, 35699, 35700, 35701, 35702, 35703, 35704, 35704, \n\t35705, 35706, 35707, 35708, 35709, 35709, 35710, 35711, \n\t35712, 35713, 35714, 35714, 35715, 35716, 35717, 35718, \n\t35719, 35719, 35720, 35721, 35722, 35723, 35724, 35724, \n\t35725, 35726, 35727, 35728, 35729, 35729, 35730, 35731, \n\t35732, 35733, 35734, 35735, 35735, 35736, 35737, 35738, \n\t35739, 35740, 35740, 35741, 35742, 35743, 35744, 35745, \n\t35745, 35746, 35747, 35748, 35749, 35750, 35750, 35751, \n\t35752, 35753, 35754, 35755, 35755, 35756, 35757, 35758, \n\t35759, 35760, 35761, 35761, 35762, 35763, 35764, 35765, \n\t35766, 35766, 35767, 35768, 35769, 35770, 35771, 35771, \n\t35772, 35773, 35774, 35775, 35776, 35776, 35777, 35778, \n\t35779, 35780, 35781, 35781, 35782, 35783, 35784, 35785, \n\t35786, 35786, 35787, 35788, 35789, 35790, 35791, 35792, \n\t35792, 35793, 35794, 35795, 35796, 35797, 35797, 35798, \n\t35799, 35800, 35801, 35802, 35802, 35803, 35804, 35805, \n\t35806, 35807, 35807, 35808, 35809, 35810, 35811, 35812, \n\t35812, 35813, 35814, 35815, 35816, 35817, 35817, 35818, \n\t35819, 35820, 35821, 35822, 35822, 35823, 35824, 35825, \n\t35826, 35827, 35828, 35828, 35829, 35830, 35831, 35832, \n\t35833, 35833, 35834, 35835, 35836, 35837, 35838, 35838, \n\t35839, 35840, 35841, 35842, 35843, 35843, 35844, 35845, \n\t35846, 35847, 35848, 35848, 35849, 35850, 35851, 35852, \n\t35853, 35853, 35854, 35855, 35856, 35857, 35858, 35858, \n\t35859, 35860, 35861, 35862, 35863, 35864, 35864, 35865, \n\t35866, 35867, 35868, 35869, 35869, 35870, 35871, 35872, \n\t35873, 35874, 35874, 35875, 35876, 35877, 35878, 35879, \n\t35879, 35880, 35881, 35882, 35883, 35884, 35884, 35885, \n\t35886, 35887, 35888, 35889, 35889, 35890, 35891, 35892, \n\t35893, 35894, 35894, 35895, 35896, 35897, 35898, 35899, \n\t35900, 35900, 35901, 35902, 35903, 35904, 35905, 35905, \n\t35906, 35907, 35908, 35909, 35910, 35910, 35911, 35912, \n\t35913, 35914, 35915, 35915, 35916, 35917, 35918, 35919, \n\t35920, 35920, 35921, 35922, 35923, 35924, 35925, 35925, \n\t35926, 35927, 35928, 35929, 35930, 35930, 35931, 35932, \n\t35933, 35934, 35935, 35935, 35936, 35937, 35938, 35939, \n\t35940, 35940, 35941, 35942, 35943, 35944, 35945, 35946, \n\t35946, 35947, 35948, 35949, 35950, 35951, 35951, 35952, \n\t35953, 35954, 35955, 35956, 35956, 35957, 35958, 35959, \n\t35960, 35961, 35961, 35962, 35963, 35964, 35965, 35966, \n\t35966, 35967, 35968, 35969, 35970, 35971, 35971, 35972, \n\t35973, 35974, 35975, 35976, 35976, 35977, 35978, 35979, \n\t35980, 35981, 35981, 35982, 35983, 35984, 35985, 35986, \n\t35986, 35987, 35988, 35989, 35990, 35991, 35991, 35992, \n\t35993, 35994, 35995, 35996, 35996, 35997, 35998, 35999, \n\t36000, 36001, 36002, 36002, 36003, 36004, 36005, 36006, \n\t36007, 36007, 36008, 36009, 36010, 36011, 36012, 36012, \n\t36013, 36014, 36015, 36016, 36017, 36017, 36018, 36019, \n\t36020, 36021, 36022, 36022, 36023, 36024, 36025, 36026, \n\t36027, 36027, 36028, 36029, 36030, 36031, 36032, 36032, \n\t36033, 36034, 36035, 36036, 36037, 36037, 36038, 36039, \n\t36040, 36041, 36042, 36042, 36043, 36044, 36045, 36046, \n\t36047, 36047, 36048, 36049, 36050, 36051, 36052, 36052, \n\t36053, 36054, 36055, 36056, 36057, 36057, 36058, 36059, \n\t36060, 36061, 36062, 36062, 36063, 36064, 36065, 36066, \n\t36067, 36067, 36068, 36069, 36070, 36071, 36072, 36073, \n\t36073, 36074, 36075, 36076, 36077, 36078, 36078, 36079, \n\t36080, 36081, 36082, 36083, 36083, 36084, 36085, 36086, \n\t36087, 36088, 36088, 36089, 36090, 36091, 36092, 36093, \n\t36093, 36094, 36095, 36096, 36097, 36098, 36098, 36099, \n\t36100, 36101, 36102, 36103, 36103, 36104, 36105, 36106, \n\t36107, 36108, 36108, 36109, 36110, 36111, 36112, 36113, \n\t36113, 36114, 36115, 36116, 36117, 36118, 36118, 36119, \n\t36120, 36121, 36122, 36123, 36123, 36124, 36125, 36126, \n\t36127, 36128, 36128, 36129, 36130, 36131, 36132, 36133, \n\t36133, 36134, 36135, 36136, 36137, 36138, 36138, 36139, \n\t36140, 36141, 36142, 36143, 36143, 36144, 36145, 36146, \n\t36147, 36148, 36148, 36149, 36150, 36151, 36152, 36153, \n\t36153, 36154, 36155, 36156, 36157, 36158, 36158, 36159, \n\t36160, 36161, 36162, 36163, 36163, 36164, 36165, 36166, \n\t36167, 36168, 36168, 36169, 36170, 36171, 36172, 36173, \n\t36173, 36174, 36175, 36176, 36177, 36178, 36178, 36179, \n\t36180, 36181, 36182, 36183, 36183, 36184, 36185, 36186, \n\t36187, 36188, 36188, 36189, 36190, 36191, 36192, 36193, \n\t36193, 36194, 36195, 36196, 36197, 36198, 36198, 36199, \n\t36200, 36201, 36202, 36203, 36203, 36204, 36205, 36206, \n\t36207, 36208, 36208, 36209, 36210, 36211, 36212, 36213, \n\t36213, 36214, 36215, 36216, 36217, 36218, 36218, 36219, \n\t36220, 36221, 36222, 36223, 36223, 36224, 36225, 36226, \n\t36227, 36228, 36228, 36229, 36230, 36231, 36232, 36233, \n\t36233, 36234, 36235, 36236, 36237, 36238, 36238, 36239, \n\t36240, 36241, 36242, 36243, 36243, 36244, 36245, 36246, \n\t36247, 36248, 36248, 36249, 36250, 36251, 36252, 36253, \n\t36253, 36254, 36255, 36256, 36257, 36258, 36258, 36259, \n\t36260, 36261, 36262, 36263, 36263, 36264, 36265, 36266, \n\t36267, 36268, 36268, 36269, 36270, 36271, 36272, 36273, \n\t36273, 36274, 36275, 36276, 36277, 36278, 36278, 36279, \n\t36280, 36281, 36282, 36283, 36283, 36284, 36285, 36286, \n\t36287, 36288, 36288, 36289, 36290, 36291, 36292, 36293, \n\t36293, 36294, 36295, 36296, 36297, 36298, 36298, 36299, \n\t36300, 36301, 36302, 36303, 36303, 36304, 36305, 36306, \n\t36307, 36308, 36308, 36309, 36310, 36311, 36312, 36313, \n\t36313, 36314, 36315, 36316, 36317, 36318, 36318, 36319, \n\t36320, 36321, 36322, 36323, 36323, 36324, 36325, 36326, \n\t36327, 36328, 36328, 36329, 36330, 36331, 36332, 36333, \n\t36333, 36334, 36335, 36336, 36337, 36338, 36338, 36339, \n\t36340, 36341, 36342, 36343, 36343, 36344, 36345, 36346, \n\t36347, 36348, 36348, 36349, 36350, 36351, 36352, 36353, \n\t36353, 36354, 36355, 36356, 36357, 36358, 36358, 36359, \n\t36360, 36361, 36362, 36363, 36363, 36364, 36365, 36366, \n\t36367, 36368, 36368, 36369, 36370, 36371, 36372, 36373, \n\t36373, 36374, 36375, 36376, 36377, 36378, 36378, 36379, \n\t36380, 36381, 36382, 36382, 36383, 36384, 36385, 36386, \n\t36387, 36387, 36388, 36389, 36390, 36391, 36392, 36392, \n\t36393, 36394, 36395, 36396, 36397, 36397, 36398, 36399, \n\t36400, 36401, 36402, 36402, 36403, 36404, 36405, 36406, \n\t36407, 36407, 36408, 36409, 36410, 36411, 36412, 36412, \n\t36413, 36414, 36415, 36416, 36417, 36417, 36418, 36419, \n\t36420, 36421, 36422, 36422, 36423, 36424, 36425, 36426, \n\t36427, 36427, 36428, 36429, 36430, 36431, 36432, 36432, \n\t36433, 36434, 36435, 36436, 36437, 36437, 36438, 36439, \n\t36440, 36441, 36442, 36442, 36443, 36444, 36445, 36446, \n\t36447, 36447, 36448, 36449, 36450, 36451, 36452, 36452, \n\t36453, 36454, 36455, 36456, 36456, 36457, 36458, 36459, \n\t36460, 36461, 36461, 36462, 36463, 36464, 36465, 36466, \n\t36466, 36467, 36468, 36469, 36470, 36471, 36471, 36472, \n\t36473, 36474, 36475, 36476, 36476, 36477, 36478, 36479, \n\t36480, 36481, 36481, 36482, 36483, 36484, 36485, 36486, \n\t36486, 36487, 36488, 36489, 36490, 36491, 36491, 36492, \n\t36493, 36494, 36495, 36496, 36496, 36497, 36498, 36499, \n\t36500, 36501, 36501, 36502, 36503, 36504, 36505, 36506, \n\t36506, 36507, 36508, 36509, 36510, 36510, 36511, 36512, \n\t36513, 36514, 36515, 36515, 36516, 36517, 36518, 36519, \n\t36520, 36520, 36521, 36522, 36523, 36524, 36525, 36525, \n\t36526, 36527, 36528, 36529, 36530, 36530, 36531, 36532, \n\t36533, 36534, 36535, 36535, 36536, 36537, 36538, 36539, \n\t36540, 36540, 36541, 36542, 36543, 36544, 36545, 36545, \n\t36546, 36547, 36548, 36549, 36550, 36550, 36551, 36552, \n\t36553, 36554, 36554, 36555, 36556, 36557, 36558, 36559, \n\t36559, 36560, 36561, 36562, 36563, 36564, 36564, 36565, \n\t36566, 36567, 36568, 36569, 36569, 36570, 36571, 36572, \n\t36573, 36574, 36574, 36575, 36576, 36577, 36578, 36579, \n\t36579, 36580, 36581, 36582, 36583, 36584, 36584, 36585, \n\t36586, 36587, 36588, 36589, 36589, 36590, 36591, 36592, \n\t36593, 36593, 36594, 36595, 36596, 36597, 36598, 36598, \n\t36599, 36600, 36601, 36602, 36603, 36603, 36604, 36605, \n\t36606, 36607, 36608, 36608, 36609, 36610, 36611, 36612, \n\t36613, 36613, 36614, 36615, 36616, 36617, 36618, 36618, \n\t36619, 36620, 36621, 36622, 36623, 36623, 36624, 36625, \n\t36626, 36627, 36627, 36628, 36629, 36630, 36631, 36632, \n\t36632, 36633, 36634, 36635, 36636, 36637, 36637, 36638, \n\t36639, 36640, 36641, 36642, 36642, 36643, 36644, 36645, \n\t36646, 36647, 36647, 36648, 36649, 36650, 36651, 36652, \n\t36652, 36653, 36654, 36655, 36656, 36657, 36657, 36658, \n\t36659, 36660, 36661, 36661, 36662, 36663, 36664, 36665, \n\t36666, 36666, 36667, 36668, 36669, 36670, 36671, 36671, \n\t36672, 36673, 36674, 36675, 36676, 36676, 36677, 36678, \n\t36679, 36680, 36681, 36681, 36682, 36683, 36684, 36685, \n\t36686, 36686, 36687, 36688, 36689, 36690, 36690, 36691, \n\t36692, 36693, 36694, 36695, 36695, 36696, 36697, 36698, \n\t36699, 36700, 36700, 36701, 36702, 36703, 36704, 36705, \n\t36705, 36706, 36707, 36708, 36709, 36710, 36710, 36711, \n\t36712, 36713, 36714, 36715, 36715, 36716, 36717, 36718, \n\t36719, 36719, 36720, 36721, 36722, 36723, 36724, 36724, \n\t36725, 36726, 36727, 36728, 36729, 36729, 36730, 36731, \n\t36732, 36733, 36734, 36734, 36735, 36736, 36737, 36738, \n\t36739, 36739, 36740, 36741, 36742, 36743, 36744, 36744, \n\t36745, 36746, 36747, 36748, 36748, 36749, 36750, 36751, \n\t36752, 36753, 36753, 36754, 36755, 36756, 36757, 36758, \n\t36758, 36759, 36760, 36761, 36762, 36763, 36763, 36764, \n\t36765, 36766, 36767, 36768, 36768, 36769, 36770, 36771, \n\t36772, 36772, 36773, 36774, 36775, 36776, 36777, 36777, \n\t36778, 36779, 36780, 36781, 36782, 36782, 36783, 36784, \n\t36785, 36786, 36787, 36787, 36788, 36789, 36790, 36791, \n\t36792, 36792, 36793, 36794, 36795, 36796, 36796, 36797, \n\t36798, 36799, 36800, 36801, 36801, 36802, 36803, 36804, \n\t36805, 36806, 36806, 36807, 36808, 36809, 36810, 36811, \n\t36811, 36812, 36813, 36814, 36815, 36816, 36816, 36817, \n\t36818, 36819, 36820, 36820, 36821, 36822, 36823, 36824, \n\t36825, 36825, 36826, 36827, 36828, 36829, 36830, 36830, \n\t36831, 36832, 36833, 36834, 36835, 36835, 36836, 36837, \n\t36838, 36839, 36840, 36840, 36841, 36842, 36843, 36844, \n\t36844, 36845, 36846, 36847, 36848, 36849, 36849, 36850, \n\t36851, 36852, 36853, 36854, 36854, 36855, 36856, 36857, \n\t36858, 36859, 36859, 36860, 36861, 36862, 36863, 36863, \n\t36864, 36865, 36866, 36867, 36868, 36868, 36869, 36870, \n\t36871, 36872, 36873, 36873, 36874, 36875, 36876, 36877, \n\t36878, 36878, 36879, 36880, 36881, 36882, 36882, 36883, \n\t36884, 36885, 36886, 36887, 36887, 36888, 36889, 36890, \n\t36891, 36892, 36892, 36893, 36894, 36895, 36896, 36897, \n\t36897, 36898, 36899, 36900, 36901, 36902, 36902, 36903, \n\t36904, 36905, 36906, 36906, 36907, 36908, 36909, 36910, \n\t36911, 36911, 36912, 36913, 36914, 36915, 36916, 36916, \n\t36917, 36918, 36919, 36920, 36921, 36921, 36922, 36923, \n\t36924, 36925, 36925, 36926, 36927, 36928, 36929, 36930, \n\t36930, 36931, 36932, 36933, 36934, 36935, 36935, 36936, \n\t36937, 36938, 36939, 36940, 36940, 36941, 36942, 36943, \n\t36944, 36944, 36945, 36946, 36947, 36948, 36949, 36949, \n\t36950, 36951, 36952, 36953, 36954, 36954, 36955, 36956, \n\t36957, 36958, 36959, 36959, 36960, 36961, 36962, 36963, \n\t36963, 36964, 36965, 36966, 36967, 36968, 36968, 36969, \n\t36970, 36971, 36972, 36973, 36973, 36974, 36975, 36976, \n\t36977, 36977, 36978, 36979, 36980, 36981, 36982, 36982, \n\t36983, 36984, 36985, 36986, 36987, 36987, 36988, 36989, \n\t36990, 36991, 36992, 36992, 36993, 36994, 36995, 36996, \n\t36996, 36997, 36998, 36999, 37000, 37001, 37001, 37002, \n\t37003, 37004, 37005, 37006, 37006, 37007, 37008, 37009, \n\t37010, 37011, 37011, 37012, 37013, 37014, 37015, 37015, \n\t37016, 37017, 37018, 37019, 37020, 37020, 37021, 37022, \n\t37023, 37024, 37025, 37025, 37026, 37027, 37028, 37029, \n\t37029, 37030, 37031, 37032, 37033, 37034, 37034, 37035, \n\t37036, 37037, 37038, 37039, 37039, 37040, 37041, 37042, \n\t37043, 37044, 37044, 37045, 37046, 37047, 37048, 37048, \n\t37049, 37050, 37051, 37052, 37053, 37053, 37054, 37055, \n\t37056, 37057, 37058, 37058, 37059, 37060, 37061, 37062, \n\t37062, 37063, 37064, 37065, 37066, 37067, 37067, 37068, \n\t37069, 37070, 37071, 37072, 37072, 37073, 37074, 37075, \n\t37076, 37077, 37077, 37078, 37079, 37080, 37081, 37081, \n\t37082, 37083, 37084, 37085, 37086, 37086, 37087, 37088, \n\t37089, 37090, 37091, 37091, 37092, 37093, 37094, 37095, \n\t37095, 37096, 37097, 37098, 37099, 37100, 37100, 37101, \n\t37102, 37103, 37104, 37105, 37105, 37106, 37107, 37108, \n\t37109, 37109, 37110, 37111, 37112, 37113, 37114, 37114, \n\t37115, 37116, 37117, 37118, 37119, 37119, 37120, 37121, \n\t37122, 37123, 37123, 37124, 37125, 37126, 37127, 37128, \n\t37128, 37129, 37130, 37131, 37132, 37133, 37133, 37134, \n\t37135, 37136, 37137, 37138, 37138, 37139, 37140, 37141, \n\t37142, 37142, 37143, 37144, 37145, 37146, 37147, 37147, \n\t37148, 37149, 37150, 37151, 37152, 37152, 37153, 37154, \n\t37155, 37156, 37156, 37157, 37158, 37159, 37160, 37161, \n\t37161, 37162, 37163, 37164, 37165, 37166, 37166, 37167, \n\t37168, 37169, 37170, 37170, 37171, 37172, 37173, 37174, \n\t37175, 37175, 37176, 37177, 37178, 37179, 37180, 37180, \n\t37181, 37182, 37183, 37184, 37184, 37185, 37186, 37187, \n\t37188, 37189, 37189, 37190, 37191, 37192, 37193, 37194, \n\t37194, 37195, 37196, 37197, 37198, 37198, 37199, 37200, \n\t37201, 37202, 37203, 37203, 37204, 37205, 37206, 37207, \n\t37208, 37208, 37209, 37210, 37211, 37212, 37212, 37213, \n\t37214, 37215, 37216, 37217, 37217, 37218, 37219, 37220, \n\t37221, 37222, 37222, 37223, 37224, 37225, 37226, 37226, \n\t37227, 37228, 37229, 37230, 37231, 37231, 37232, 37233, \n\t37234, 37235, 37235, 37236, 37237, 37238, 37239, 37240, \n\t37240, 37241, 37242, 37243, 37244, 37245, 37245, 37246, \n\t37247, 37248, 37249, 37249, 37250, 37251, 37252, 37253, \n\t37254, 37254, 37255, 37256, 37257, 37258, 37259, 37259, \n\t37260, 37261, 37262, 37263, 37263, 37264, 37265, 37266, \n\t37267, 37268, 37268, 37269, 37270, 37271, 37272, 37273, \n\t37273, 37274, 37275, 37276, 37277, 37277, 37278, 37279, \n\t37280, 37281, 37282, 37282, 37283, 37284, 37285, 37286, \n\t37286, 37287, 37288, 37289, 37290, 37291, 37291, 37292, \n\t37293, 37294, 37295, 37296, 37296, 37297, 37298, 37299, \n\t37300, 37300, 37301, 37302, 37303, 37304, 37305, 37305, \n\t37306, 37307, 37308, 37309, 37310, 37310, 37311, 37312, \n\t37313, 37314, 37314, 37315, 37316, 37317, 37318, 37319, \n\t37319, 37320, 37321, 37322, 37323, 37323, 37324, 37325, \n\t37326, 37327, 37328, 37328, 37329, 37330, 37331, 37332, \n\t37333, 37333, 37334, 37335, 37336, 37337, 37337, 37338, \n\t37339, 37340, 37341, 37342, 37342, 37343, 37344, 37345, \n\t37346, 37347, 37347, 37348, 37349, 37350, 37351, 37351, \n\t37352, 37353, 37354, 37355, 37356, 37356, 37357, 37358, \n\t37359, 37360, 37360, 37361, 37362, 37363, 37364, 37365, \n\t37365, 37366, 37367, 37368, 37369, 37370, 37370, 37371, \n\t37372, 37373, 37374, 37374, 37375, 37376, 37377, 37378, \n\t37379, 37379, 37380, 37381, 37382, 37383, 37383, 37384, \n\t37385, 37386, 37387, 37388, 37388, 37389, 37390, 37391, \n\t37392, 37393, 37393, 37394, 37395, 37396, 37397, 37397, \n\t37398, 37399, 37400, 37401, 37402, 37402, 37403, 37404, \n\t37405, 37406, 37406, 37407, 37408, 37409, 37410, 37411, \n\t37411, 37412, 37413, 37414, 37415, 37416, 37416, 37417, \n\t37418, 37419, 37420, 37420, 37421, 37422, 37423, 37424, \n\t37425, 37425, 37426, 37427, 37428, 37429, 37429, 37430, \n\t37431, 37432, 37433, 37434, 37434, 37435, 37436, 37437, \n\t37438, 37438, 37439, 37440, 37441, 37442, 37443, 37443, \n\t37444, 37445, 37446, 37447, 37448, 37448, 37449, 37450, \n\t37451, 37452, 37452, 37453, 37454, 37455, 37456, 37457, \n\t37457, 37458, 37459, 37460, 37461, 37461, 37462, 37463, \n\t37464, 37465, 37466, 37466, 37467, 37468, 37469, 37470, \n\t37470, 37471, 37472, 37473, 37474, 37475, 37475, 37476, \n\t37477, 37478, 37479, 37480, 37480, 37481, 37482, 37483, \n\t37484, 37484, 37485, 37486, 37487, 37488, 37489, 37489, \n\t37490, 37491, 37492, 37493, 37493, 37494, 37495, 37496, \n\t37497, 37498, 37498, 37499, 37500, 37501, 37502, 37502, \n\t37503, 37504, 37505, 37506, 37507, 37507, 37508, 37509, \n\t37510, 37511, 37512, 37512, 37513, 37514, 37515, 37516, \n\t37516, 37517, 37518, 37519, 37520, 37521, 37521, 37522, \n\t37523, 37524, 37525, 37525, 37526, 37527, 37528, 37529, \n\t37530, 37530, 37531, 37532, 37533, 37534, 37534, 37535, \n\t37536, 37537, 37538, 37539, 37539, 37540, 37541, 37542, \n\t37543, 37543, 37544, 37545, 37546, 37547, 37548, 37548, \n\t37549, 37550, 37551, 37552, 37552, 37553, 37554, 37555, \n\t37556, 37557, 37557, 37558, 37559, 37560, 37561, 37562, \n\t37562, 37563, 37564, 37565, 37566, 37566, 37567, 37568, \n\t37569, 37570, 37571, 37571, 37572, 37573, 37574, 37575, \n\t37575, 37576, 37577, 37578, 37579, 37580, 37580, 37581, \n\t37582, 37583, 37584, 37584, 37585, 37586, 37587, 37588, \n\t37589, 37589, 37590, 37591, 37592, 37593, 37593, 37594, \n\t37595, 37596, 37597, 37598, 37598, 37599, 37600, 37601, \n\t37602, 37602, 37603, 37604, 37605, 37606, 37607, 37607, \n\t37608, 37609, 37610, 37611, 37611, 37612, 37613, 37614, \n\t37615, 37616, 37616, 37617, 37618, 37619, 37620, 37620, \n\t37621, 37622, 37623, 37624, 37625, 37625, 37626, 37627, \n\t37628, 37629, 37629, 37630, 37631, 37632, 37633, 37634, \n\t37634, 37635, 37636, 37637, 37638, 37638, 37639, 37640, \n\t37641, 37642, 37643, 37643, 37644, 37645, 37646, 37647, \n\t37647, 37648, 37649, 37650, 37651, 37652, 37652, 37653, \n\t37654, 37655, 37656, 37657, 37657, 37658, 37659, 37660, \n\t37661, 37661, 37662, 37663, 37664, 37665, 37666, 37666, \n\t37667, 37668, 37669, 37670, 37670, 37671, 37672, 37673, \n\t37674, 37675, 37675, 37676, 37677, 37678, 37679, 37679, \n\t37680, 37681, 37682, 37683, 37684, 37684, 37685, 37686, \n\t37687, 37688, 37688, 37689, 37690, 37691, 37692, 37693, \n\t37693, 37694, 37695, 37696, 37697, 37697, 37698, 37699, \n\t37700, 37701, 37702, 37702, 37703, 37704, 37705, 37706, \n\t37706, 37707, 37708, 37709, 37710, 37711, 37711, 37712, \n\t37713, 37714, 37715, 37715, 37716, 37717, 37718, 37719, \n\t37719, 37720, 37721, 37722, 37723, 37724, 37724, 37725, \n\t37726, 37727, 37728, 37728, 37729, 37730, 37731, 37732, \n\t37733, 37733, 37734, 37735, 37736, 37737, 37737, 37738, \n\t37739, 37740, 37741, 37742, 37742, 37743, 37744, 37745, \n\t37746, 37746, 37747, 37748, 37749, 37750, 37751, 37751, \n\t37752, 37753, 37754, 37755, 37755, 37756, 37757, 37758, \n\t37759, 37760, 37760, 37761, 37762, 37763, 37764, 37764, \n\t37765, 37766, 37767, 37768, 37769, 37769, 37770, 37771, \n\t37772, 37773, 37773, 37774, 37775, 37776, 37777, 37778, \n\t37778, 37779, 37780, 37781, 37782, 37782, 37783, 37784, \n\t37785, 37786, 37787, 37787, 37788, 37789, 37790, 37791, \n\t37791, 37792, 37793, 37794, 37795, 37796, 37796, 37797, \n\t37798, 37799, 37800, 37800, 37801, 37802, 37803, 37804, \n\t37804, 37805, 37806, 37807, 37808, 37809, 37809, 37810, \n\t37811, 37812, 37813, 37813, 37814, 37815, 37816, 37817, \n\t37818, 37818, 37819, 37820, 37821, 37822, 37822, 37823, \n\t37824, 37825, 37826, 37827, 37827, 37828, 37829, 37830, \n\t37831, 37831, 37832, 37833, 37834, 37835, 37836, 37836, \n\t37837, 37838, 37839, 37840, 37840, 37841, 37842, 37843, \n\t37844, 37845, 37845, 37846, 37847, 37848, 37849, 37849, \n\t37850, 37851, 37852, 37853, 37853, 37854, 37855, 37856, \n\t37857, 37858, 37858, 37859, 37860, 37861, 37862, 37862, \n\t37863, 37864, 37865, 37866, 37867, 37867, 37868, 37869, \n\t37870, 37871, 37871, 37872, 37873, 37874, 37875, 37876, \n\t37876, 37877, 37878, 37879, 37880, 37880, 37881, 37882, \n\t37883, 37884, 37885, 37885, 37886, 37887, 37888, 37889, \n\t37889, 37890, 37891, 37892, 37893, 37893, 37894, 37895, \n\t37896, 37897, 37898, 37898, 37899, 37900, 37901, 37902, \n\t37902, 37903, 37904, 37905, 37906, 37907, 37907, 37908, \n\t37909, 37910, 37911, 37911, 37912, 37913, 37914, 37915, \n\t37916, 37916, 37917, 37918, 37919, 37920, 37920, 37921, \n\t37922, 37923, 37924, 37924, 37925, 37926, 37927, 37928, \n\t37929, 37929, 37930, 37931, 37932, 37933, 37933, 37934, \n\t37935, 37936, 37937, 37938, 37938, 37939, 37940, 37941, \n\t37942, 37942, 37943, 37944, 37945, 37946, 37946, 37947, \n\t37948, 37949, 37950, 37951, 37951, 37952, 37953, 37954, \n\t37955, 37955, 37956, 37957, 37958, 37959, 37960, 37960, \n\t37961, 37962, 37963, 37964, 37964, 37965, 37966, 37967, \n\t37968, 37969, 37969, 37970, 37971, 37972, 37973, 37973, \n\t37974, 37975, 37976, 37977, 37977, 37978, 37979, 37980, \n\t37981, 37982, 37982, 37983, 37984, 37985, 37986, 37986, \n\t37987, 37988, 37989, 37990, 37991, 37991, 37992, 37993, \n\t37994, 37995, 37995, 37996, 37997, 37998, 37999, 37999, \n\t38000, 38001, 38002, 38003, 38004, 38004, 38005, 38006, \n\t38007, 38008, 38008, 38009, 38010, 38011, 38012, 38013, \n\t38013, 38014, 38015, 38016, 38017, 38017, 38018, 38019, \n\t38020, 38021, 38021, 38022, 38023, 38024, 38025, 38026, \n\t38026, 38027, 38028, 38029, 38030, 38030, 38031, 38032, \n\t38033, 38034, 38034, 38035, 38036, 38037, 38038, 38039, \n\t38039, 38040, 38041, 38042, 38043, 38043, 38044, 38045, \n\t38046, 38047, 38048, 38048, 38049, 38050, 38051, 38052, \n\t38052, 38053, 38054, 38055, 38056, 38056, 38057, 38058, \n\t38059, 38060, 38061, 38061, 38062, 38063, 38064, 38065, \n\t38065, 38066, 38067, 38068, 38069, 38070, 38070, 38071, \n\t38072, 38073, 38074, 38074, 38075, 38076, 38077, 38078, \n\t38078, 38079, 38080, 38081, 38082, 38083, 38083, 38084, \n\t38085, 38086, 38087, 38087, 38088, 38089, 38090, 38091, \n\t38091, 38092, 38093, 38094, 38095, 38096, 38096, 38097, \n\t38098, 38099, 38100, 38100, 38101, 38102, 38103, 38104, \n\t38104, 38105, 38106, 38107, 38108, 38109, 38109, 38110, \n\t38111, 38112, 38113, 38113, 38114, 38115, 38116, 38117, \n\t38118, 38118, 38119, 38120, 38121, 38122, 38122, 38123, \n\t38124, 38125, 38126, 38126, 38127, 38128, 38129, 38130, \n\t38131, 38131, 38132, 38133, 38134, 38135, 38135, 38136, \n\t38137, 38138, 38139, 38139, 38140, 38141, 38142, 38143, \n\t38144, 38144, 38145, 38146, 38147, 38148, 38148, 38149, \n\t38150, 38151, 38152, 38152, 38153, 38154, 38155, 38156, \n\t38157, 38157, 38158, 38159, 38160, 38161, 38161, 38162, \n\t38163, 38164, 38165, 38165, 38166, 38167, 38168, 38169, \n\t38170, 38170, 38171, 38172, 38173, 38174, 38174, 38175, \n\t38176, 38177, 38178, 38179, 38179, 38180, 38181, 38182, \n\t38183, 38183, 38184, 38185, 38186, 38187, 38187, 38188, \n\t38189, 38190, 38191, 38192, 38192, 38193, 38194, 38195, \n\t38196, 38196, 38197, 38198, 38199, 38200, 38200, 38201, \n\t38202, 38203, 38204, 38205, 38205, 38206, 38207, 38208, \n\t38209, 38209, 38210, 38211, 38212, 38213, 38213, 38214, \n\t38215, 38216, 38217, 38218, 38218, 38219, 38220, 38221, \n\t38222, 38222, 38223, 38224, 38225, 38226, 38226, 38227, \n\t38228, 38229, 38230, 38231, 38231, 38232, 38233, 38234, \n\t38235, 38235, 38236, 38237, 38238, 38239, 38239, 38240, \n\t38241, 38242, 38243, 38243, 38244, 38245, 38246, 38247, \n\t38248, 38248, 38249, 38250, 38251, 38252, 38252, 38253, \n\t38254, 38255, 38256, 38256, 38257, 38258, 38259, 38260, \n\t38261, 38261, 38262, 38263, 38264, 38265, 38265, 38266, \n\t38267, 38268, 38269, 38269, 38270, 38271, 38272, 38273, \n\t38274, 38274, 38275, 38276, 38277, 38278, 38278, 38279, \n\t38280, 38281, 38282, 38282, 38283, 38284, 38285, 38286, \n\t38287, 38287, 38288, 38289, 38290, 38291, 38291, 38292, \n\t38293, 38294, 38295, 38295, 38296, 38297, 38298, 38299, \n\t38300, 38300, 38301, 38302, 38303, 38304, 38304, 38305, \n\t38306, 38307, 38308, 38308, 38309, 38310, 38311, 38312, \n\t38312, 38313, 38314, 38315, 38316, 38317, 38317, 38318, \n\t38319, 38320, 38321, 38321, 38322, 38323, 38324, 38325, \n\t38325, 38326, 38327, 38328, 38329, 38330, 38330, 38331, \n\t38332, 38333, 38334, 38334, 38335, 38336, 38337, 38338, \n\t38338, 38339, 38340, 38341, 38342, 38343, 38343, 38344, \n\t38345, 38346, 38347, 38347, 38348, 38349, 38350, 38351, \n\t38351, 38352, 38353, 38354, 38355, 38355, 38356, 38357, \n\t38358, 38359, 38360, 38360, 38361, 38362, 38363, 38364, \n\t38364, 38365, 38366, 38367, 38368, 38368, 38369, 38370, \n\t38371, 38372, 38373, 38373, 38374, 38375, 38376, 38377, \n\t38377, 38378, 38379, 38380, 38381, 38381, 38382, 38383, \n\t38384, 38385, 38385, 38386, 38387, 38388, 38389, 38390, \n\t38390, 38391, 38392, 38393, 38394, 38394, 38395, 38396, \n\t38397, 38398, 38398, 38399, 38400, 38401, 38402, 38402, \n\t38403, 38404, 38405, 38406, 38407, 38407, 38408, 38409, \n\t38410, 38411, 38411, 38412, 38413, 38414, 38415, 38415, \n\t38416, 38417, 38418, 38419, 38420, 38420, 38421, 38422, \n\t38423, 38424, 38424, 38425, 38426, 38427, 38428, 38428, \n\t38429, 38430, 38431, 38432, 38432, 38433, 38434, 38435, \n\t38436, 38437, 38437, 38438, 38439, 38440, 38441, 38441, \n\t38442, 38443, 38444, 38445, 38445, 38446, 38447, 38448, \n\t38449, 38449, 38450, 38451, 38452, 38453, 38454, 38454, \n\t38455, 38456, 38457, 38458, 38458, 38459, 38460, 38461, \n\t38462, 38462, 38463, 38464, 38465, 38466, 38466, 38467, \n\t38468, 38469, 38470, 38471, 38471, 38472, 38473, 38474, \n\t38475, 38475, 38476, 38477, 38478, 38479, 38479, 38480, \n\t38481, 38482, 38483, 38483, 38484, 38485, 38486, 38487, \n\t38488, 38488, 38489, 38490, 38491, 38492, 38492, 38493, \n\t38494, 38495, 38496, 38496, 38497, 38498, 38499, 38500, \n\t38500, 38501, 38502, 38503, 38504, 38505, 38505, 38506, \n\t38507, 38508, 38509, 38509, 38510, 38511, 38512, 38513, \n\t38513, 38514, 38515, 38516, 38517, 38517, 38518, 38519, \n\t38520, 38521, 38522, 38522, 38523, 38524, 38525, 38526, \n\t38526, 38527, 38528, 38529, 38530, 38530, 38531, 38532, \n\t38533, 38534, 38534, 38535, 38536, 38537, 38538, 38538, \n\t38539, 38540, 38541, 38542, 38543, 38543, 38544, 38545, \n\t38546, 38547, 38547, 38548, 38549, 38550, 38551, 38551, \n\t38552, 38553, 38554, 38555, 38555, 38556, 38557, 38558, \n\t38559, 38560, 38560, 38561, 38562, 38563, 38564, 38564, \n\t38565, 38566, 38567, 38568, 38568, 38569, 38570, 38571, \n\t38572, 38572, 38573, 38574, 38575, 38576, 38577, 38577, \n\t38578, 38579, 38580, 38581, 38581, 38582, 38583, 38584, \n\t38585, 38585, 38586, 38587, 38588, 38589, 38589, 38590, \n\t38591, 38592, 38593, 38593, 38594, 38595, 38596, 38597, \n\t38598, 38598, 38599, 38600, 38601, 38602, 38602, 38603, \n\t38604, 38605, 38606, 38606, 38607, 38608, 38609, 38610, \n\t38610, 38611, 38612, 38613, 38614, 38614, 38615, 38616, \n\t38617, 38618, 38619, 38619, 38620, 38621, 38622, 38623, \n\t38623, 38624, 38625, 38626, 38627, 38627, 38628, 38629, \n\t38630, 38631, 38631, 38632, 38633, 38634, 38635, 38635, \n\t38636, 38637, 38638, 38639, 38640, 38640, 38641, 38642, \n\t38643, 38644, 38644, 38645, 38646, 38647, 38648, 38648, \n\t38649, 38650, 38651, 38652, 38652, 38653, 38654, 38655, \n\t38656, 38656, 38657, 38658, 38659, 38660, 38661, 38661, \n\t38662, 38663, 38664, 38665, 38665, 38666, 38667, 38668, \n\t38669, 38669, 38670, 38671, 38672, 38673, 38673, 38674, \n\t38675, 38676, 38677, 38677, 38678, 38679, 38680, 38681, \n\t38682, 38682, 38683, 38684, 38685, 38686, 38686, 38687, \n\t38688, 38689, 38690, 38690, 38691, 38692, 38693, 38694, \n\t38694, 38695, 38696, 38697, 38698, 38698, 38699, 38700, \n\t38701, 38702, 38703, 38703, 38704, 38705, 38706, 38707, \n\t38707, 38708, 38709, 38710, 38711, 38711, 38712, 38713, \n\t38714, 38715, 38715, 38716, 38717, 38718, 38719, 38719, \n\t38720, 38721, 38722, 38723, 38723, 38724, 38725, 38726, \n\t38727, 38728, 38728, 38729, 38730, 38731, 38732, 38732, \n\t38733, 38734, 38735, 38736, 38736, 38737, 38738, 38739, \n\t38740, 38740, 38741, 38742, 38743, 38744, 38744, 38745, \n\t38746, 38747, 38748, 38748, 38749, 38750, 38751, 38752, \n\t38753, 38753, 38754, 38755, 38756, 38757, 38757, 38758, \n\t38759, 38760, 38761, 38761, 38762, 38763, 38764, 38765, \n\t38765, 38766, 38767, 38768, 38769, 38769, 38770, 38771, \n\t38772, 38773, 38773, 38774, 38775, 38776, 38777, 38778, \n\t38778, 38779, 38780, 38781, 38782, 38782, 38783, 38784, \n\t38785, 38786, 38786, 38787, 38788, 38789, 38790, 38790, \n\t38791, 38792, 38793, 38794, 38794, 38795, 38796, 38797, \n\t38798, 38798, 38799, 38800, 38801, 38802, 38803, 38803, \n\t38804, 38805, 38806, 38807, 38807, 38808, 38809, 38810, \n\t38811, 38811, 38812, 38813, 38814, 38815, 38815, 38816, \n\t38817, 38818, 38819, 38819, 38820, 38821, 38822, 38823, \n\t38823, 38824, 38825, 38826, 38827, 38827, 38828, 38829, \n\t38830, 38831, 38832, 38832, 38833, 38834, 38835, 38836, \n\t38836, 38837, 38838, 38839, 38840, 38840, 38841, 38842, \n\t38843, 38844, 38844, 38845, 38846, 38847, 38848, 38848, \n\t38849, 38850, 38851, 38852, 38852, 38853, 38854, 38855, \n\t38856, 38856, 38857, 38858, 38859, 38860, 38861, 38861, \n\t38862, 38863, 38864, 38865, 38865, 38866, 38867, 38868, \n\t38869, 38869, 38870, 38871, 38872, 38873, 38873, 38874, \n\t38875, 38876, 38877, 38877, 38878, 38879, 38880, 38881, \n\t38881, 38882, 38883, 38884, 38885, 38885, 38886, 38887, \n\t38888, 38889, 38889, 38890, 38891, 38892, 38893, 38894, \n\t38894, 38895, 38896, 38897, 38898, 38898, 38899, 38900, \n\t38901, 38902, 38902, 38903, 38904, 38905, 38906, 38906, \n\t38907, 38908, 38909, 38910, 38910, 38911, 38912, 38913, \n\t38914, 38914, 38915, 38916, 38917, 38918, 38918, 38919, \n\t38920, 38921, 38922, 38922, 38923, 38924, 38925, 38926, \n\t38927, 38927, 38928, 38929, 38930, 38931, 38931, 38932, \n\t38933, 38934, 38935, 38935, 38936, 38937, 38938, 38939, \n\t38939, 38940, 38941, 38942, 38943, 38943, 38944, 38945, \n\t38946, 38947, 38947, 38948, 38949, 38950, 38951, 38951, \n\t38952, 38953, 38954, 38955, 38955, 38956, 38957, 38958, \n\t38959, 38959, 38960, 38961, 38962, 38963, 38963, 38964, \n\t38965, 38966, 38967, 38968, 38968, 38969, 38970, 38971, \n\t38972, 38972, 38973, 38974, 38975, 38976, 38976, 38977, \n\t38978, 38979, 38980, 38980, 38981, 38982, 38983, 38984, \n\t38984, 38985, 38986, 38987, 38988, 38988, 38989, 38990, \n\t38991, 38992, 38992, 38993, 38994, 38995, 38996, 38996, \n\t38997, 38998, 38999, 39000, 39000, 39001, 39002, 39003, \n\t39004, 39004, 39005, 39006, 39007, 39008, 39009, 39009, \n\t39010, 39011, 39012, 39013, 39013, 39014, 39015, 39016, \n\t39017, 39017, 39018, 39019, 39020, 39021, 39021, 39022, \n\t39023, 39024, 39025, 39025, 39026, 39027, 39028, 39029, \n\t39029, 39030, 39031, 39032, 39033, 39033, 39034, 39035, \n\t39036, 39037, 39037, 39038, 39039, 39040, 39041, 39041, \n\t39042, 39043, 39044, 39045, 39045, 39046, 39047, 39048, \n\t39049, 39049, 39050, 39051, 39052, 39053, 39053, 39054, \n\t39055, 39056, 39057, 39058, 39058, 39059, 39060, 39061, \n\t39062, 39062, 39063, 39064, 39065, 39066, 39066, 39067, \n\t39068, 39069, 39070, 39070, 39071, 39072, 39073, 39074, \n\t39074, 39075, 39076, 39077, 39078, 39078, 39079, 39080, \n\t39081, 39082, 39082, 39083, 39084, 39085, 39086, 39086, \n\t39087, 39088, 39089, 39090, 39090, 39091, 39092, 39093, \n\t39094, 39094, 39095, 39096, 39097, 39098, 39098, 39099, \n\t39100, 39101, 39102, 39102, 39103, 39104, 39105, 39106, \n\t39106, 39107, 39108, 39109, 39110, 39110, 39111, 39112, \n\t39113, 39114, 39115, 39115, 39116, 39117, 39118, 39119, \n\t39119, 39120, 39121, 39122, 39123, 39123, 39124, 39125, \n\t39126, 39127, 39127, 39128, 39129, 39130, 39131, 39131, \n\t39132, 39133, 39134, 39135, 39135, 39136, 39137, 39138, \n\t39139, 39139, 39140, 39141, 39142, 39143, 39143, 39144, \n\t39145, 39146, 39147, 39147, 39148, 39149, 39150, 39151, \n\t39151, 39152, 39153, 39154, 39155, 39155, 39156, 39157, \n\t39158, 39159, 39159, 39160, 39161, 39162, 39163, 39163, \n\t39164, 39165, 39166, 39167, 39167, 39168, 39169, 39170, \n\t39171, 39171, 39172, 39173, 39174, 39175, 39175, 39176, \n\t39177, 39178, 39179, 39179, 39180, 39181, 39182, 39183, \n\t39183, 39184, 39185, 39186, 39187, 39187, 39188, 39189, \n\t39190, 39191, 39191, 39192, 39193, 39194, 39195, 39195, \n\t39196, 39197, 39198, 39199, 39200, 39200, 39201, 39202, \n\t39203, 39204, 39204, 39205, 39206, 39207, 39208, 39208, \n\t39209, 39210, 39211, 39212, 39212, 39213, 39214, 39215, \n\t39216, 39216, 39217, 39218, 39219, 39220, 39220, 39221, \n\t39222, 39223, 39224, 39224, 39225, 39226, 39227, 39228, \n\t39228, 39229, 39230, 39231, 39232, 39232, 39233, 39234, \n\t39235, 39236, 39236, 39237, 39238, 39239, 39240, 39240, \n\t39241, 39242, 39243, 39244, 39244, 39245, 39246, 39247, \n\t39248, 39248, 39249, 39250, 39251, 39252, 39252, 39253, \n\t39254, 39255, 39256, 39256, 39257, 39258, 39259, 39260, \n\t39260, 39261, 39262, 39263, 39264, 39264, 39265, 39266, \n\t39267, 39268, 39268, 39269, 39270, 39271, 39272, 39272, \n\t39273, 39274, 39275, 39276, 39276, 39277, 39278, 39279, \n\t39280, 39280, 39281, 39282, 39283, 39284, 39284, 39285, \n\t39286, 39287, 39288, 39288, 39289, 39290, 39291, 39292, \n\t39292, 39293, 39294, 39295, 39296, 39296, 39297, 39298, \n\t39299, 39300, 39300, 39301, 39302, 39303, 39304, 39304, \n\t39305, 39306, 39307, 39308, 39308, 39309, 39310, 39311, \n\t39312, 39312, 39313, 39314, 39315, 39316, 39316, 39317, \n\t39318, 39319, 39320, 39320, 39321, 39322, 39323, 39324, \n\t39324, 39325, 39326, 39327, 39328, 39328, 39329, 39330, \n\t39331, 39332, 39332, 39333, 39334, 39335, 39336, 39336, \n\t39337, 39338, 39339, 39340, 39340, 39341, 39342, 39343, \n\t39344, 39344, 39345, 39346, 39347, 39348, 39348, 39349, \n\t39350, 39351, 39352, 39352, 39353, 39354, 39355, 39356, \n\t39356, 39357, 39358, 39359, 39360, 39360, 39361, 39362, \n\t39363, 39364, 39364, 39365, 39366, 39367, 39368, 39368, \n\t39369, 39370, 39371, 39372, 39372, 39373, 39374, 39375, \n\t39376, 39376, 39377, 39378, 39379, 39380, 39380, 39381, \n\t39382, 39383, 39384, 39384, 39385, 39386, 39387, 39388, \n\t39388, 39389, 39390, 39391, 39392, 39392, 39393, 39394, \n\t39395, 39396, 39396, 39397, 39398, 39399, 39400, 39400, \n\t39401, 39402, 39403, 39404, 39404, 39405, 39406, 39407, \n\t39408, 39408, 39409, 39410, 39411, 39412, 39412, 39413, \n\t39414, 39415, 39416, 39416, 39417, 39418, 39419, 39420, \n\t39420, 39421, 39422, 39423, 39424, 39424, 39425, 39426, \n\t39427, 39428, 39428, 39429, 39430, 39431, 39432, 39432, \n\t39433, 39434, 39435, 39436, 39436, 39437, 39438, 39439, \n\t39440, 39440, 39441, 39442, 39443, 39444, 39444, 39445, \n\t39446, 39447, 39447, 39448, 39449, 39450, 39451, 39451, \n\t39452, 39453, 39454, 39455, 39455, 39456, 39457, 39458, \n\t39459, 39459, 39460, 39461, 39462, 39463, 39463, 39464, \n\t39465, 39466, 39467, 39467, 39468, 39469, 39470, 39471, \n\t39471, 39472, 39473, 39474, 39475, 39475, 39476, 39477, \n\t39478, 39479, 39479, 39480, 39481, 39482, 39483, 39483, \n\t39484, 39485, 39486, 39487, 39487, 39488, 39489, 39490, \n\t39491, 39491, 39492, 39493, 39494, 39495, 39495, 39496, \n\t39497, 39498, 39499, 39499, 39500, 39501, 39502, 39503, \n\t39503, 39504, 39505, 39506, 39507, 39507, 39508, 39509, \n\t39510, 39511, 39511, 39512, 39513, 39514, 39515, 39515, \n\t39516, 39517, 39518, 39519, 39519, 39520, 39521, 39522, \n\t39523, 39523, 39524, 39525, 39526, 39527, 39527, 39528, \n\t39529, 39530, 39530, 39531, 39532, 39533, 39534, 39534, \n\t39535, 39536, 39537, 39538, 39538, 39539, 39540, 39541, \n\t39542, 39542, 39543, 39544, 39545, 39546, 39546, 39547, \n\t39548, 39549, 39550, 39550, 39551, 39552, 39553, 39554, \n\t39554, 39555, 39556, 39557, 39558, 39558, 39559, 39560, \n\t39561, 39562, 39562, 39563, 39564, 39565, 39566, 39566, \n\t39567, 39568, 39569, 39570, 39570, 39571, 39572, 39573, \n\t39574, 39574, 39575, 39576, 39577, 39578, 39578, 39579, \n\t39580, 39581, 39582, 39582, 39583, 39584, 39585, 39586, \n\t39586, 39587, 39588, 39589, 39589, 39590, 39591, 39592, \n\t39593, 39593, 39594, 39595, 39596, 39597, 39597, 39598, \n\t39599, 39600, 39601, 39601, 39602, 39603, 39604, 39605, \n\t39605, 39606, 39607, 39608, 39609, 39609, 39610, 39611, \n\t39612, 39613, 39613, 39614, 39615, 39616, 39617, 39617, \n\t39618, 39619, 39620, 39621, 39621, 39622, 39623, 39624, \n\t39625, 39625, 39626, 39627, 39628, 39629, 39629, 39630, \n\t39631, 39632, 39633, 39633, 39634, 39635, 39636, 39636, \n\t39637, 39638, 39639, 39640, 39640, 39641, 39642, 39643, \n\t39644, 39644, 39645, 39646, 39647, 39648, 39648, 39649, \n\t39650, 39651, 39652, 39652, 39653, 39654, 39655, 39656, \n\t39656, 39657, 39658, 39659, 39660, 39660, 39661, 39662, \n\t39663, 39664, 39664, 39665, 39666, 39667, 39668, 39668, \n\t39669, 39670, 39671, 39672, 39672, 39673, 39674, 39675, \n\t39676, 39676, 39677, 39678, 39679, 39679, 39680, 39681, \n\t39682, 39683, 39683, 39684, 39685, 39686, 39687, 39687, \n\t39688, 39689, 39690, 39691, 39691, 39692, 39693, 39694, \n\t39695, 39695, 39696, 39697, 39698, 39699, 39699, 39700, \n\t39701, 39702, 39703, 39703, 39704, 39705, 39706, 39707, \n\t39707, 39708, 39709, 39710, 39711, 39711, 39712, 39713, \n\t39714, 39714, 39715, 39716, 39717, 39718, 39718, 39719, \n\t39720, 39721, 39722, 39722, 39723, 39724, 39725, 39726, \n\t39726, 39727, 39728, 39729, 39730, 39730, 39731, 39732, \n\t39733, 39734, 39734, 39735, 39736, 39737, 39738, 39738, \n\t39739, 39740, 39741, 39742, 39742, 39743, 39744, 39745, \n\t39746, 39746, 39747, 39748, 39749, 39749, 39750, 39751, \n\t39752, 39753, 39753, 39754, 39755, 39756, 39757, 39757, \n\t39758, 39759, 39760, 39761, 39761, 39762, 39763, 39764, \n\t39765, 39765, 39766, 39767, 39768, 39769, 39769, 39770, \n\t39771, 39772, 39773, 39773, 39774, 39775, 39776, 39777, \n\t39777, 39778, 39779, 39780, 39780, 39781, 39782, 39783, \n\t39784, 39784, 39785, 39786, 39787, 39788, 39788, 39789, \n\t39790, 39791, 39792, 39792, 39793, 39794, 39795, 39796, \n\t39796, 39797, 39798, 39799, 39800, 39800, 39801, 39802, \n\t39803, 39804, 39804, 39805, 39806, 39807, 39808, 39808, \n\t39809, 39810, 39811, 39811, 39812, 39813, 39814, 39815, \n\t39815, 39816, 39817, 39818, 39819, 39819, 39820, 39821, \n\t39822, 39823, 39823, 39824, 39825, 39826, 39827, 39827, \n\t39828, 39829, 39830, 39831, 39831, 39832, 39833, 39834, \n\t39835, 39835, 39836, 39837, 39838, 39838, 39839, 39840, \n\t39841, 39842, 39842, 39843, 39844, 39845, 39846, 39846, \n\t39847, 39848, 39849, 39850, 39850, 39851, 39852, 39853, \n\t39854, 39854, 39855, 39856, 39857, 39858, 39858, 39859, \n\t39860, 39861, 39861, 39862, 39863, 39864, 39865, 39865, \n\t39866, 39867, 39868, 39869, 39869, 39870, 39871, 39872, \n\t39873, 39873, 39874, 39875, 39876, 39877, 39877, 39878, \n\t39879, 39880, 39881, 39881, 39882, 39883, 39884, 39885, \n\t39885, 39886, 39887, 39888, 39888, 39889, 39890, 39891, \n\t39892, 39892, 39893, 39894, 39895, 39896, 39896, 39897, \n\t39898, 39899, 39900, 39900, 39901, 39902, 39903, 39904, \n\t39904, 39905, 39906, 39907, 39908, 39908, 39909, 39910, \n\t39911, 39911, 39912, 39913, 39914, 39915, 39915, 39916, \n\t39917, 39918, 39919, 39919, 39920, 39921, 39922, 39923, \n\t39923, 39924, 39925, 39926, 39927, 39927, 39928, 39929, \n\t39930, 39931, 39931, 39932, 39933, 39934, 39934, 39935, \n\t39936, 39937, 39938, 39938, 39939, 39940, 39941, 39942, \n\t39942, 39943, 39944, 39945, 39946, 39946, 39947, 39948, \n\t39949, 39950, 39950, 39951, 39952, 39953, 39954, 39954, \n\t39955, 39956, 39957, 39957, 39958, 39959, 39960, 39961, \n\t39961, 39962, 39963, 39964, 39965, 39965, 39966, 39967, \n\t39968, 39969, 39969, 39970, 39971, 39972, 39973, 39973, \n\t39974, 39975, 39976, 39976, 39977, 39978, 39979, 39980, \n\t39980, 39981, 39982, 39983, 39984, 39984, 39985, 39986, \n\t39987, 39988, 39988, 39989, 39990, 39991, 39992, 39992, \n\t39993, 39994, 39995, 39996, 39996, 39997, 39998, 39999, \n\t39999, 40000, 40001, 40002, 40003, 40003, 40004, 40005, \n\t40006, 40007, 40007, 40008, 40009, 40010, 40011, 40011, \n\t40012, 40013, 40014, 40015, 40015, 40016, 40017, 40018, \n\t40018, 40019, 40020, 40021, 40022, 40022, 40023, 40024, \n\t40025, 40026, 40026, 40027, 40028, 40029, 40030, 40030, \n\t40031, 40032, 40033, 40034, 40034, 40035, 40036, 40037, \n\t40037, 40038, 40039, 40040, 40041, 40041, 40042, 40043, \n\t40044, 40045, 40045, 40046, 40047, 40048, 40049, 40049, \n\t40050, 40051, 40052, 40053, 40053, 40054, 40055, 40056, \n\t40056, 40057, 40058, 40059, 40060, 40060, 40061, 40062, \n\t40063, 40064, 40064, 40065, 40066, 40067, 40068, 40068, \n\t40069, 40070, 40071, 40072, 40072, 40073, 40074, 40075, \n\t40075, 40076, 40077, 40078, 40079, 40079, 40080, 40081, \n\t40082, 40083, 40083, 40084, 40085, 40086, 40087, 40087, \n\t40088, 40089, 40090, 40091, 40091, 40092, 40093, 40094, \n\t40094, 40095, 40096, 40097, 40098, 40098, 40099, 40100, \n\t40101, 40102, 40102, 40103, 40104, 40105, 40106, 40106, \n\t40107, 40108, 40109, 40109, 40110, 40111, 40112, 40113, \n\t40113, 40114, 40115, 40116, 40117, 40117, 40118, 40119, \n\t40120, 40121, 40121, 40122, 40123, 40124, 40125, 40125, \n\t40126, 40127, 40128, 40128, 40129, 40130, 40131, 40132, \n\t40132, 40133, 40134, 40135, 40136, 40136, 40137, 40138, \n\t40139, 40140, 40140, 40141, 40142, 40143, 40143, 40144, \n\t40145, 40146, 40147, 40147, 40148, 40149, 40150, 40151, \n\t40151, 40152, 40153, 40154, 40155, 40155, 40156, 40157, \n\t40158, 40159, 40159, 40160, 40161, 40162, 40162, 40163, \n\t40164, 40165, 40166, 40166, 40167, 40168, 40169, 40170, \n\t40170, 40171, 40172, 40173, 40174, 40174, 40175, 40176, \n\t40177, 40177, 40178, 40179, 40180, 40181, 40181, 40182, \n\t40183, 40184, 40185, 40185, 40186, 40187, 40188, 40189, \n\t40189, 40190, 40191, 40192, 40192, 40193, 40194, 40195, \n\t40196, 40196, 40197, 40198, 40199, 40200, 40200, 40201, \n\t40202, 40203, 40204, 40204, 40205, 40206, 40207, 40207, \n\t40208, 40209, 40210, 40211, 40211, 40212, 40213, 40214, \n\t40215, 40215, 40216, 40217, 40218, 40219, 40219, 40220, \n\t40221, 40222, 40222, 40223, 40224, 40225, 40226, 40226, \n\t40227, 40228, 40229, 40230, 40230, 40231, 40232, 40233, \n\t40234, 40234, 40235, 40236, 40237, 40237, 40238, 40239, \n\t40240, 40241, 40241, 40242, 40243, 40244, 40245, 40245, \n\t40246, 40247, 40248, 40249, 40249, 40250, 40251, 40252, \n\t40252, 40253, 40254, 40255, 40256, 40256, 40257, 40258, \n\t40259, 40260, 40260, 40261, 40262, 40263, 40264, 40264, \n\t40265, 40266, 40267, 40267, 40268, 40269, 40270, 40271, \n\t40271, 40272, 40273, 40274, 40275, 40275, 40276, 40277, \n\t40278, 40279, 40279, 40280, 40281, 40282, 40282, 40283, \n\t40284, 40285, 40286, 40286, 40287, 40288, 40289, 40290, \n\t40290, 40291, 40292, 40293, 40293, 40294, 40295, 40296, \n\t40297, 40297, 40298, 40299, 40300, 40301, 40301, 40302, \n\t40303, 40304, 40305, 40305, 40306, 40307, 40308, 40308, \n\t40309, 40310, 40311, 40312, 40312, 40313, 40314, 40315, \n\t40316, 40316, 40317, 40318, 40319, 40320, 40320, 40321, \n\t40322, 40323, 40323, 40324, 40325, 40326, 40327, 40327, \n\t40328, 40329, 40330, 40331, 40331, 40332, 40333, 40334, \n\t40334, 40335, 40336, 40337, 40338, 40338, 40339, 40340, \n\t40341, 40342, 40342, 40343, 40344, 40345, 40346, 40346, \n\t40347, 40348, 40349, 40349, 40350, 40351, 40352, 40353, \n\t40353, 40354, 40355, 40356, 40357, 40357, 40358, 40359, \n\t40360, 40361, 40361, 40362, 40363, 40364, 40364, 40365, \n\t40366, 40367, 40368, 40368, 40369, 40370, 40371, 40372, \n\t40372, 40373, 40374, 40375, 40375, 40376, 40377, 40378, \n\t40379, 40379, 40380, 40381, 40382, 40383, 40383, 40384, \n\t40385, 40386, 40386, 40387, 40388, 40389, 40390, 40390, \n\t40391, 40392, 40393, 40394, 40394, 40395, 40396, 40397, \n\t40398, 40398, 40399, 40400, 40401, 40401, 40402, 40403, \n\t40404, 40405, 40405, 40406, 40407, 40408, 40409, 40409, \n\t40410, 40411, 40412, 40412, 40413, 40414, 40415, 40416, \n\t40416, 40417, 40418, 40419, 40420, 40420, 40421, 40422, \n\t40423, 40424, 40424, 40425, 40426, 40427, 40427, 40428, \n\t40429, 40430, 40431, 40431, 40432, 40433, 40434, 40435, \n\t40435, 40436, 40437, 40438, 40438, 40439, 40440, 40441, \n\t40442, 40442, 40443, 40444, 40445, 40446, 40446, 40447, \n\t40448, 40449, 40449, 40450, 40451, 40452, 40453, 40453, \n\t40454, 40455, 40456, 40457, 40457, 40458, 40459, 40460, \n\t40460, 40461, 40462, 40463, 40464, 40464, 40465, 40466, \n\t40467, 40468, 40468, 40469, 40470, 40471, 40471, 40472, \n\t40473, 40474, 40475, 40475, 40476, 40477, 40478, 40479, \n\t40479, 40480, 40481, 40482, 40483, 40483, 40484, 40485, \n\t40486, 40486, 40487, 40488, 40489, 40490, 40490, 40491, \n\t40492, 40493, 40494, 40494, 40495, 40496, 40497, 40497, \n\t40498, 40499, 40500, 40501, 40501, 40502, 40503, 40504, \n\t40505, 40505, 40506, 40507, 40508, 40508, 40509, 40510, \n\t40511, 40512, 40512, 40513, 40514, 40515, 40516, 40516, \n\t40517, 40518, 40519, 40519, 40520, 40521, 40522, 40523, \n\t40523, 40524, 40525, 40526, 40527, 40527, 40528, 40529, \n\t40530, 40530, 40531, 40532, 40533, 40534, 40534, 40535, \n\t40536, 40537, 40538, 40538, 40539, 40540, 40541, 40541, \n\t40542, 40543, 40544, 40545, 40545, 40546, 40547, 40548, \n\t40549, 40549, 40550, 40551, 40552, 40552, 40553, 40554, \n\t40555, 40556, 40556, 40557, 40558, 40559, 40560, 40560, \n\t40561, 40562, 40563, 40563, 40564, 40565, 40566, 40567, \n\t40567, 40568, 40569, 40570, 40571, 40571, 40572, 40573, \n\t40574, 40574, 40575, 40576, 40577, 40578, 40578, 40579, \n\t40580, 40581, 40582, 40582, 40583, 40584, 40585, 40585, \n\t40586, 40587, 40588, 40589, 40589, 40590, 40591, 40592, \n\t40593, 40593, 40594, 40595, 40596, 40596, 40597, 40598, \n\t40599, 40600, 40600, 40601, 40602, 40603, 40604, 40604, \n\t40605, 40606, 40607, 40607, 40608, 40609, 40610, 40611, \n\t40611, 40612, 40613, 40614, 40614, 40615, 40616, 40617, \n\t40618, 40618, 40619, 40620, 40621, 40622, 40622, 40623, \n\t40624, 40625, 40625, 40626, 40627, 40628, 40629, 40629, \n\t40630, 40631, 40632, 40633, 40633, 40634, 40635, 40636, \n\t40636, 40637, 40638, 40639, 40640, 40640, 40641, 40642, \n\t40643, 40644, 40644, 40645, 40646, 40647, 40647, 40648, \n\t40649, 40650, 40651, 40651, 40652, 40653, 40654, 40655, \n\t40655, 40656, 40657, 40658, 40658, 40659, 40660, 40661, \n\t40662, 40662, 40663, 40664, 40665, 40665, 40666, 40667, \n\t40668, 40669, 40669, 40670, 40671, 40672, 40673, 40673, \n\t40674, 40675, 40676, 40676, 40677, 40678, 40679, 40680, \n\t40680, 40681, 40682, 40683, 40684, 40684, 40685, 40686, \n\t40687, 40687, 40688, 40689, 40690, 40691, 40691, 40692, \n\t40693, 40694, 40694, 40695, 40696, 40697, 40698, 40698, \n\t40699, 40700, 40701, 40702, 40702, 40703, 40704, 40705, \n\t40705, 40706, 40707, 40708, 40709, 40709, 40710, 40711, \n\t40712, 40713, 40713, 40714, 40715, 40716, 40716, 40717, \n\t40718, 40719, 40720, 40720, 40721, 40722, 40723, 40723, \n\t40724, 40725, 40726, 40727, 40727, 40728, 40729, 40730, \n\t40731, 40731, 40732, 40733, 40734, 40734, 40735, 40736, \n\t40737, 40738, 40738, 40739, 40740, 40741, 40742, 40742, \n\t40743, 40744, 40745, 40745, 40746, 40747, 40748, 40749, \n\t40749, 40750, 40751, 40752, 40752, 40753, 40754, 40755, \n\t40756, 40756, 40757, 40758, 40759, 40760, 40760, 40761, \n\t40762, 40763, 40763, 40764, 40765, 40766, 40767, 40767, \n\t40768, 40769, 40770, 40770, 40771, 40772, 40773, 40774, \n\t40774, 40775, 40776, 40777, 40778, 40778, 40779, 40780, \n\t40781, 40781, 40782, 40783, 40784, 40785, 40785, 40786, \n\t40787, 40788, 40788, 40789, 40790, 40791, 40792, 40792, \n\t40793, 40794, 40795, 40796, 40796, 40797, 40798, 40799, \n\t40799, 40800, 40801, 40802, 40803, 40803, 40804, 40805, \n\t40806, 40806, 40807, 40808, 40809, 40810, 40810, 40811, \n\t40812, 40813, 40814, 40814, 40815, 40816, 40817, 40817, \n\t40818, 40819, 40820, 40821, 40821, 40822, 40823, 40824, \n\t40824, 40825, 40826, 40827, 40828, 40828, 40829, 40830, \n\t40831, 40832, 40832, 40833, 40834, 40835, 40835, 40836, \n\t40837, 40838, 40839, 40839, 40840, 40841, 40842, 40842, \n\t40843, 40844, 40845, 40846, 40846, 40847, 40848, 40849, \n\t40850, 40850, 40851, 40852, 40853, 40853, 40854, 40855, \n\t40856, 40857, 40857, 40858, 40859, 40860, 40860, 40861, \n\t40862, 40863, 40864, 40864, 40865, 40866, 40867, 40867, \n\t40868, 40869, 40870, 40871, 40871, 40872, 40873, 40874, \n\t40875, 40875, 40876, 40877, 40878, 40878, 40879, 40880, \n\t40881, 40882, 40882, 40883, 40884, 40885, 40885, 40886, \n\t40887, 40888, 40889, 40889, 40890, 40891, 40892, 40893, \n\t40893, 40894, 40895, 40896, 40896, 40897, 40898, 40899, \n\t40900, 40900, 40901, 40902, 40903, 40903, 40904, 40905, \n\t40906, 40907, 40907, 40908, 40909, 40910, 40910, 40911, \n\t40912, 40913, 40914, 40914, 40915, 40916, 40917, 40918, \n\t40918, 40919, 40920, 40921, 40921, 40922, 40923, 40924, \n\t40925, 40925, 40926, 40927, 40928, 40928, 40929, 40930, \n\t40931, 40932, 40932, 40933, 40934, 40935, 40935, 40936, \n\t40937, 40938, 40939, 40939, 40940, 40941, 40942, 40942, \n\t40943, 40944, 40945, 40946, 40946, 40947, 40948, 40949, \n\t40950, 40950, 40951, 40952, 40953, 40953, 40954, 40955, \n\t40956, 40957, 40957, 40958, 40959, 40960, 40960, 40961, \n\t40962, 40963, 40964, 40964, 40965, 40966, 40967, 40967, \n\t40968, 40969, 40970, 40971, 40971, 40972, 40973, 40974, \n\t40975, 40975, 40976, 40977, 40978, 40978, 40979, 40980, \n\t40981, 40982, 40982, 40983, 40984, 40985, 40985, 40986, \n\t40987, 40988, 40989, 40989, 40990, 40991, 40992, 40992, \n\t40993, 40994, 40995, 40996, 40996, 40997, 40998, 40999, \n\t40999, 41000, 41001, 41002, 41003, 41003, 41004, 41005, \n\t41006, 41006, 41007, 41008, 41009, 41010, 41010, 41011, \n\t41012, 41013, 41014, 41014, 41015, 41016, 41017, 41017, \n\t41018, 41019, 41020, 41021, 41021, 41022, 41023, 41024, \n\t41024, 41025, 41026, 41027, 41028, 41028, 41029, 41030, \n\t41031, 41031, 41032, 41033, 41034, 41035, 41035, 41036, \n\t41037, 41038, 41038, 41039, 41040, 41041, 41042, 41042, \n\t41043, 41044, 41045, 41045, 41046, 41047, 41048, 41049, \n\t41049, 41050, 41051, 41052, 41052, 41053, 41054, 41055, \n\t41056, 41056, 41057, 41058, 41059, 41060, 41060, 41061, \n\t41062, 41063, 41063, 41064, 41065, 41066, 41067, 41067, \n\t41068, 41069, 41070, 41070, 41071, 41072, 41073, 41074, \n\t41074, 41075, 41076, 41077, 41077, 41078, 41079, 41080, \n\t41081, 41081, 41082, 41083, 41084, 41084, 41085, 41086, \n\t41087, 41088, 41088, 41089, 41090, 41091, 41091, 41092, \n\t41093, 41094, 41095, 41095, 41096, 41097, 41098, 41098, \n\t41099, 41100, 41101, 41102, 41102, 41103, 41104, 41105, \n\t41105, 41106, 41107, 41108, 41109, 41109, 41110, 41111, \n\t41112, 41112, 41113, 41114, 41115, 41116, 41116, 41117, \n\t41118, 41119, 41120, 41120, 41121, 41122, 41123, 41123, \n\t41124, 41125, 41126, 41127, 41127, 41128, 41129, 41130, \n\t41130, 41131, 41132, 41133, 41134, 41134, 41135, 41136, \n\t41137, 41137, 41138, 41139, 41140, 41141, 41141, 41142, \n\t41143, 41144, 41144, 41145, 41146, 41147, 41148, 41148, \n\t41149, 41150, 41151, 41151, 41152, 41153, 41154, 41155, \n\t41155, 41156, 41157, 41158, 41158, 41159, 41160, 41161, \n\t41162, 41162, 41163, 41164, 41165, 41165, 41166, 41167, \n\t41168, 41169, 41169, 41170, 41171, 41172, 41172, 41173, \n\t41174, 41175, 41176, 41176, 41177, 41178, 41179, 41179, \n\t41180, 41181, 41182, 41183, 41183, 41184, 41185, 41186, \n\t41186, 41187, 41188, 41189, 41190, 41190, 41191, 41192, \n\t41193, 41193, 41194, 41195, 41196, 41197, 41197, 41198, \n\t41199, 41200, 41200, 41201, 41202, 41203, 41204, 41204, \n\t41205, 41206, 41207, 41207, 41208, 41209, 41210, 41211, \n\t41211, 41212, 41213, 41214, 41214, 41215, 41216, 41217, \n\t41218, 41218, 41219, 41220, 41221, 41221, 41222, 41223, \n\t41224, 41225, 41225, 41226, 41227, 41228, 41228, 41229, \n\t41230, 41231, 41232, 41232, 41233, 41234, 41235, 41235, \n\t41236, 41237, 41238, 41239, 41239, 41240, 41241, 41242, \n\t41242, 41243, 41244, 41245, 41246, 41246, 41247, 41248, \n\t41249, 41249, 41250, 41251, 41252, 41253, 41253, 41254, \n\t41255, 41256, 41256, 41257, 41258, 41259, 41260, 41260, \n\t41261, 41262, 41263, 41263, 41264, 41265, 41266, 41266, \n\t41267, 41268, 41269, 41270, 41270, 41271, 41272, 41273, \n\t41273, 41274, 41275, 41276, 41277, 41277, 41278, 41279, \n\t41280, 41280, 41281, 41282, 41283, 41284, 41284, 41285, \n\t41286, 41287, 41287, 41288, 41289, 41290, 41291, 41291, \n\t41292, 41293, 41294, 41294, 41295, 41296, 41297, 41298, \n\t41298, 41299, 41300, 41301, 41301, 41302, 41303, 41304, \n\t41305, 41305, 41306, 41307, 41308, 41308, 41309, 41310, \n\t41311, 41312, 41312, 41313, 41314, 41315, 41315, 41316, \n\t41317, 41318, 41319, 41319, 41320, 41321, 41322, 41322, \n\t41323, 41324, 41325, 41326, 41326, 41327, 41328, 41329, \n\t41329, 41330, 41331, 41332, 41332, 41333, 41334, 41335, \n\t41336, 41336, 41337, 41338, 41339, 41339, 41340, 41341, \n\t41342, 41343, 41343, 41344, 41345, 41346, 41346, 41347, \n\t41348, 41349, 41350, 41350, 41351, 41352, 41353, 41353, \n\t41354, 41355, 41356, 41357, 41357, 41358, 41359, 41360, \n\t41360, 41361, 41362, 41363, 41364, 41364, 41365, 41366, \n\t41367, 41367, 41368, 41369, 41370, 41371, 41371, 41372, \n\t41373, 41374, 41374, 41375, 41376, 41377, 41377, 41378, \n\t41379, 41380, 41381, 41381, 41382, 41383, 41384, 41384, \n\t41385, 41386, 41387, 41388, 41388, 41389, 41390, 41391, \n\t41391, 41392, 41393, 41394, 41395, 41395, 41396, 41397, \n\t41398, 41398, 41399, 41400, 41401, 41402, 41402, 41403, \n\t41404, 41405, 41405, 41406, 41407, 41408, 41409, 41409, \n\t41410, 41411, 41412, 41412, 41413, 41414, 41415, 41415, \n\t41416, 41417, 41418, 41419, 41419, 41420, 41421, 41422, \n\t41422, 41423, 41424, 41425, 41426, 41426, 41427, 41428, \n\t41429, 41429, 41430, 41431, 41432, 41433, 41433, 41434, \n\t41435, 41436, 41436, 41437, 41438, 41439, 41439, 41440, \n\t41441, 41442, 41443, 41443, 41444, 41445, 41446, 41446, \n\t41447, 41448, 41449, 41450, 41450, 41451, 41452, 41453, \n\t41453, 41454, 41455, 41456, 41457, 41457, 41458, 41459, \n\t41460, 41460, 41461, 41462, 41463, 41464, 41464, 41465, \n\t41466, 41467, 41467, 41468, 41469, 41470, 41470, 41471, \n\t41472, 41473, 41474, 41474, 41475, 41476, 41477, 41477, \n\t41478, 41479, 41480, 41481, 41481, 41482, 41483, 41484, \n\t41484, 41485, 41486, 41487, 41488, 41488, 41489, 41490, \n\t41491, 41491, 41492, 41493, 41494, 41494, 41495, 41496, \n\t41497, 41498, 41498, 41499, 41500, 41501, 41501, 41502, \n\t41503, 41504, 41505, 41505, 41506, 41507, 41508, 41508, \n\t41509, 41510, 41511, 41512, 41512, 41513, 41514, 41515, \n\t41515, 41516, 41517, 41518, 41518, 41519, 41520, 41521, \n\t41522, 41522, 41523, 41524, 41525, 41525, 41526, 41527, \n\t41528, 41529, 41529, 41530, 41531, 41532, 41532, 41533, \n\t41534, 41535, 41535, 41536, 41537, 41538, 41539, 41539, \n\t41540, 41541, 41542, 41542, 41543, 41544, 41545, 41546, \n\t41546, 41547, 41548, 41549, 41549, 41550, 41551, 41552, \n\t41553, 41553, 41554, 41555, 41556, 41556, 41557, 41558, \n\t41559, 41559, 41560, 41561, 41562, 41563, 41563, 41564, \n\t41565, 41566, 41566, 41567, 41568, 41569, 41570, 41570, \n\t41571, 41572, 41573, 41573, 41574, 41575, 41576, 41576, \n\t41577, 41578, 41579, 41580, 41580, 41581, 41582, 41583, \n\t41583, 41584, 41585, 41586, 41587, 41587, 41588, 41589, \n\t41590, 41590, 41591, 41592, 41593, 41593, 41594, 41595, \n\t41596, 41597, 41597, 41598, 41599, 41600, 41600, 41601, \n\t41602, 41603, 41604, 41604, 41605, 41606, 41607, 41607, \n\t41608, 41609, 41610, 41610, 41611, 41612, 41613, 41614, \n\t41614, 41615, 41616, 41617, 41617, 41618, 41619, 41620, \n\t41621, 41621, 41622, 41623, 41624, 41624, 41625, 41626, \n\t41627, 41627, 41628, 41629, 41630, 41631, 41631, 41632, \n\t41633, 41634, 41634, 41635, 41636, 41637, 41638, 41638, \n\t41639, 41640, 41641, 41641, 41642, 41643, 41644, 41644, \n\t41645, 41646, 41647, 41648, 41648, 41649, 41650, 41651, \n\t41651, 41652, 41653, 41654, 41654, 41655, 41656, 41657, \n\t41658, 41658, 41659, 41660, 41661, 41661, 41662, 41663, \n\t41664, 41665, 41665, 41666, 41667, 41668, 41668, 41669, \n\t41670, 41671, 41671, 41672, 41673, 41674, 41675, 41675, \n\t41676, 41677, 41678, 41678, 41679, 41680, 41681, 41682, \n\t41682, 41683, 41684, 41685, 41685, 41686, 41687, 41688, \n\t41688, 41689, 41690, 41691, 41692, 41692, 41693, 41694, \n\t41695, 41695, 41696, 41697, 41698, 41698, 41699, 41700, \n\t41701, 41702, 41702, 41703, 41704, 41705, 41705, 41706, \n\t41707, 41708, 41709, 41709, 41710, 41711, 41712, 41712, \n\t41713, 41714, 41715, 41715, 41716, 41717, 41718, 41719, \n\t41719, 41720, 41721, 41722, 41722, 41723, 41724, 41725, \n\t41725, 41726, 41727, 41728, 41729, 41729, 41730, 41731, \n\t41732, 41732, 41733, 41734, 41735, 41736, 41736, 41737, \n\t41738, 41739, 41739, 41740, 41741, 41742, 41742, 41743, \n\t41744, 41745, 41746, 41746, 41747, 41748, 41749, 41749, \n\t41750, 41751, 41752, 41752, 41753, 41754, 41755, 41756, \n\t41756, 41757, 41758, 41759, 41759, 41760, 41761, 41762, \n\t41762, 41763, 41764, 41765, 41766, 41766, 41767, 41768, \n\t41769, 41769, 41770, 41771, 41772, 41772, 41773, 41774, \n\t41775, 41776, 41776, 41777, 41778, 41779, 41779, 41780, \n\t41781, 41782, 41783, 41783, 41784, 41785, 41786, 41786, \n\t41787, 41788, 41789, 41789, 41790, 41791, 41792, 41793, \n\t41793, 41794, 41795, 41796, 41796, 41797, 41798, 41799, \n\t41799, 41800, 41801, 41802, 41803, 41803, 41804, 41805, \n\t41806, 41806, 41807, 41808, 41809, 41809, 41810, 41811, \n\t41812, 41813, 41813, 41814, 41815, 41816, 41816, 41817, \n\t41818, 41819, 41819, 41820, 41821, 41822, 41823, 41823, \n\t41824, 41825, 41826, 41826, 41827, 41828, 41829, 41829, \n\t41830, 41831, 41832, 41833, 41833, 41834, 41835, 41836, \n\t41836, 41837, 41838, 41839, 41839, 41840, 41841, 41842, \n\t41843, 41843, 41844, 41845, 41846, 41846, 41847, 41848, \n\t41849, 41850, 41850, 41851, 41852, 41853, 41853, 41854, \n\t41855, 41856, 41856, 41857, 41858, 41859, 41860, 41860, \n\t41861, 41862, 41863, 41863, 41864, 41865, 41866, 41866, \n\t41867, 41868, 41869, 41870, 41870, 41871, 41872, 41873, \n\t41873, 41874, 41875, 41876, 41876, 41877, 41878, 41879, \n\t41880, 41880, 41881, 41882, 41883, 41883, 41884, 41885, \n\t41886, 41886, 41887, 41888, 41889, 41890, 41890, 41891, \n\t41892, 41893, 41893, 41894, 41895, 41896, 41896, 41897, \n\t41898, 41899, 41900, 41900, 41901, 41902, 41903, 41903, \n\t41904, 41905, 41906, 41906, 41907, 41908, 41909, 41910, \n\t41910, 41911, 41912, 41913, 41913, 41914, 41915, 41916, \n\t41916, 41917, 41918, 41919, 41919, 41920, 41921, 41922, \n\t41923, 41923, 41924, 41925, 41926, 41926, 41927, 41928, \n\t41929, 41929, 41930, 41931, 41932, 41933, 41933, 41934, \n\t41935, 41936, 41936, 41937, 41938, 41939, 41939, 41940, \n\t41941, 41942, 41943, 41943, 41944, 41945, 41946, 41946, \n\t41947, 41948, 41949, 41949, 41950, 41951, 41952, 41953, \n\t41953, 41954, 41955, 41956, 41956, 41957, 41958, 41959, \n\t41959, 41960, 41961, 41962, 41963, 41963, 41964, 41965, \n\t41966, 41966, 41967, 41968, 41969, 41969, 41970, 41971, \n\t41972, 41973, 41973, 41974, 41975, 41976, 41976, 41977, \n\t41978, 41979, 41979, 41980, 41981, 41982, 41982, 41983, \n\t41984, 41985, 41986, 41986, 41987, 41988, 41989, 41989, \n\t41990, 41991, 41992, 41992, 41993, 41994, 41995, 41996, \n\t41996, 41997, 41998, 41999, 41999, 42000, 42001, 42002, \n\t42002, 42003, 42004, 42005, 42006, 42006, 42007, 42008, \n\t42009, 42009, 42010, 42011, 42012, 42012, 42013, 42014, \n\t42015, 42016, 42016, 42017, 42018, 42019, 42019, 42020, \n\t42021, 42022, 42022, 42023, 42024, 42025, 42025, 42026, \n\t42027, 42028, 42029, 42029, 42030, 42031, 42032, 42032, \n\t42033, 42034, 42035, 42035, 42036, 42037, 42038, 42039, \n\t42039, 42040, 42041, 42042, 42042, 42043, 42044, 42045, \n\t42045, 42046, 42047, 42048, 42048, 42049, 42050, 42051, \n\t42052, 42052, 42053, 42054, 42055, 42055, 42056, 42057, \n\t42058, 42058, 42059, 42060, 42061, 42062, 42062, 42063, \n\t42064, 42065, 42065, 42066, 42067, 42068, 42068, 42069, \n\t42070, 42071, 42071, 42072, 42073, 42074, 42075, 42075, \n\t42076, 42077, 42078, 42078, 42079, 42080, 42081, 42081, \n\t42082, 42083, 42084, 42085, 42085, 42086, 42087, 42088, \n\t42088, 42089, 42090, 42091, 42091, 42092, 42093, 42094, \n\t42094, 42095, 42096, 42097, 42098, 42098, 42099, 42100, \n\t42101, 42101, 42102, 42103, 42104, 42104, 42105, 42106, \n\t42107, 42108, 42108, 42109, 42110, 42111, 42111, 42112, \n\t42113, 42114, 42114, 42115, 42116, 42117, 42117, 42118, \n\t42119, 42120, 42121, 42121, 42122, 42123, 42124, 42124, \n\t42125, 42126, 42127, 42127, 42128, 42129, 42130, 42131, \n\t42131, 42132, 42133, 42134, 42134, 42135, 42136, 42137, \n\t42137, 42138, 42139, 42140, 42140, 42141, 42142, 42143, \n\t42144, 42144, 42145, 42146, 42147, 42147, 42148, 42149, \n\t42150, 42150, 42151, 42152, 42153, 42153, 42154, 42155, \n\t42156, 42157, 42157, 42158, 42159, 42160, 42160, 42161, \n\t42162, 42163, 42163, 42164, 42165, 42166, 42166, 42167, \n\t42168, 42169, 42170, 42170, 42171, 42172, 42173, 42173, \n\t42174, 42175, 42176, 42176, 42177, 42178, 42179, 42180, \n\t42180, 42181, 42182, 42183, 42183, 42184, 42185, 42186, \n\t42186, 42187, 42188, 42189, 42189, 42190, 42191, 42192, \n\t42193, 42193, 42194, 42195, 42196, 42196, 42197, 42198, \n\t42199, 42199, 42200, 42201, 42202, 42202, 42203, 42204, \n\t42205, 42206, 42206, 42207, 42208, 42209, 42209, 42210, \n\t42211, 42212, 42212, 42213, 42214, 42215, 42215, 42216, \n\t42217, 42218, 42219, 42219, 42220, 42221, 42222, 42222, \n\t42223, 42224, 42225, 42225, 42226, 42227, 42228, 42228, \n\t42229, 42230, 42231, 42232, 42232, 42233, 42234, 42235, \n\t42235, 42236, 42237, 42238, 42238, 42239, 42240, 42241, \n\t42241, 42242, 42243, 42244, 42245, 42245, 42246, 42247, \n\t42248, 42248, 42249, 42250, 42251, 42251, 42252, 42253, \n\t42254, 42254, 42255, 42256, 42257, 42258, 42258, 42259, \n\t42260, 42261, 42261, 42262, 42263, 42264, 42264, 42265, \n\t42266, 42267, 42267, 42268, 42269, 42270, 42271, 42271, \n\t42272, 42273, 42274, 42274, 42275, 42276, 42277, 42277, \n\t42278, 42279, 42280, 42280, 42281, 42282, 42283, 42284, \n\t42284, 42285, 42286, 42287, 42287, 42288, 42289, 42290, \n\t42290, 42291, 42292, 42293, 42293, 42294, 42295, 42296, \n\t42296, 42297, 42298, 42299, 42300, 42300, 42301, 42302, \n\t42303, 42303, 42304, 42305, 42306, 42306, 42307, 42308, \n\t42309, 42309, 42310, 42311, 42312, 42313, 42313, 42314, \n\t42315, 42316, 42316, 42317, 42318, 42319, 42319, 42320, \n\t42321, 42322, 42322, 42323, 42324, 42325, 42326, 42326, \n\t42327, 42328, 42329, 42329, 42330, 42331, 42332, 42332, \n\t42333, 42334, 42335, 42335, 42336, 42337, 42338, 42338, \n\t42339, 42340, 42341, 42342, 42342, 42343, 42344, 42345, \n\t42345, 42346, 42347, 42348, 42348, 42349, 42350, 42351, \n\t42351, 42352, 42353, 42354, 42355, 42355, 42356, 42357, \n\t42358, 42358, 42359, 42360, 42361, 42361, 42362, 42363, \n\t42364, 42364, 42365, 42366, 42367, 42367, 42368, 42369, \n\t42370, 42371, 42371, 42372, 42373, 42374, 42374, 42375, \n\t42376, 42377, 42377, 42378, 42379, 42380, 42380, 42381, \n\t42382, 42383, 42384, 42384, 42385, 42386, 42387, 42387, \n\t42388, 42389, 42390, 42390, 42391, 42392, 42393, 42393, \n\t42394, 42395, 42396, 42396, 42397, 42398, 42399, 42400, \n\t42400, 42401, 42402, 42403, 42403, 42404, 42405, 42406, \n\t42406, 42407, 42408, 42409, 42409, 42410, 42411, 42412, \n\t42412, 42413, 42414, 42415, 42416, 42416, 42417, 42418, \n\t42419, 42419, 42420, 42421, 42422, 42422, 42423, 42424, \n\t42425, 42425, 42426, 42427, 42428, 42428, 42429, 42430, \n\t42431, 42432, 42432, 42433, 42434, 42435, 42435, 42436, \n\t42437, 42438, 42438, 42439, 42440, 42441, 42441, 42442, \n\t42443, 42444, 42444, 42445, 42446, 42447, 42448, 42448, \n\t42449, 42450, 42451, 42451, 42452, 42453, 42454, 42454, \n\t42455, 42456, 42457, 42457, 42458, 42459, 42460, 42460, \n\t42461, 42462, 42463, 42464, 42464, 42465, 42466, 42467, \n\t42467, 42468, 42469, 42470, 42470, 42471, 42472, 42473, \n\t42473, 42474, 42475, 42476, 42476, 42477, 42478, 42479, \n\t42480, 42480, 42481, 42482, 42483, 42483, 42484, 42485, \n\t42486, 42486, 42487, 42488, 42489, 42489, 42490, 42491, \n\t42492, 42492, 42493, 42494, 42495, 42496, 42496, 42497, \n\t42498, 42499, 42499, 42500, 42501, 42502, 42502, 42503, \n\t42504, 42505, 42505, 42506, 42507, 42508, 42508, 42509, \n\t42510, 42511, 42512, 42512, 42513, 42514, 42515, 42515, \n\t42516, 42517, 42518, 42518, 42519, 42520, 42521, 42521, \n\t42522, 42523, 42524, 42524, 42525, 42526, 42527, 42527, \n\t42528, 42529, 42530, 42531, 42531, 42532, 42533, 42534, \n\t42534, 42535, 42536, 42537, 42537, 42538, 42539, 42540, \n\t42540, 42541, 42542, 42543, 42543, 42544, 42545, 42546, \n\t42547, 42547, 42548, 42549, 42550, 42550, 42551, 42552, \n\t42553, 42553, 42554, 42555, 42556, 42556, 42557, 42558, \n\t42559, 42559, 42560, 42561, 42562, 42562, 42563, 42564, \n\t42565, 42566, 42566, 42567, 42568, 42569, 42569, 42570, \n\t42571, 42572, 42572, 42573, 42574, 42575, 42575, 42576, \n\t42577, 42578, 42578, 42579, 42580, 42581, 42581, 42582, \n\t42583, 42584, 42585, 42585, 42586, 42587, 42588, 42588, \n\t42589, 42590, 42591, 42591, 42592, 42593, 42594, 42594, \n\t42595, 42596, 42597, 42597, 42598, 42599, 42600, 42600, \n\t42601, 42602, 42603, 42604, 42604, 42605, 42606, 42607, \n\t42607, 42608, 42609, 42610, 42610, 42611, 42612, 42613, \n\t42613, 42614, 42615, 42616, 42616, 42617, 42618, 42619, \n\t42619, 42620, 42621, 42622, 42623, 42623, 42624, 42625, \n\t42626, 42626, 42627, 42628, 42629, 42629, 42630, 42631, \n\t42632, 42632, 42633, 42634, 42635, 42635, 42636, 42637, \n\t42638, 42638, 42639, 42640, 42641, 42642, 42642, 42643, \n\t42644, 42645, 42645, 42646, 42647, 42648, 42648, 42649, \n\t42650, 42651, 42651, 42652, 42653, 42654, 42654, 42655, \n\t42656, 42657, 42657, 42658, 42659, 42660, 42660, 42661, \n\t42662, 42663, 42664, 42664, 42665, 42666, 42667, 42667, \n\t42668, 42669, 42670, 42670, 42671, 42672, 42673, 42673, \n\t42674, 42675, 42676, 42676, 42677, 42678, 42679, 42679, \n\t42680, 42681, 42682, 42682, 42683, 42684, 42685, 42686, \n\t42686, 42687, 42688, 42689, 42689, 42690, 42691, 42692, \n\t42692, 42693, 42694, 42695, 42695, 42696, 42697, 42698, \n\t42698, 42699, 42700, 42701, 42701, 42702, 42703, 42704, \n\t42705, 42705, 42706, 42707, 42708, 42708, 42709, 42710, \n\t42711, 42711, 42712, 42713, 42714, 42714, 42715, 42716, \n\t42717, 42717, 42718, 42719, 42720, 42720, 42721, 42722, \n\t42723, 42723, 42724, 42725, 42726, 42726, 42727, 42728, \n\t42729, 42730, 42730, 42731, 42732, 42733, 42733, 42734, \n\t42735, 42736, 42736, 42737, 42738, 42739, 42739, 42740, \n\t42741, 42742, 42742, 42743, 42744, 42745, 42745, 42746, \n\t42747, 42748, 42748, 42749, 42750, 42751, 42752, 42752, \n\t42753, 42754, 42755, 42755, 42756, 42757, 42758, 42758, \n\t42759, 42760, 42761, 42761, 42762, 42763, 42764, 42764, \n\t42765, 42766, 42767, 42767, 42768, 42769, 42770, 42770, \n\t42771, 42772, 42773, 42773, 42774, 42775, 42776, 42777, \n\t42777, 42778, 42779, 42780, 42780, 42781, 42782, 42783, \n\t42783, 42784, 42785, 42786, 42786, 42787, 42788, 42789, \n\t42789, 42790, 42791, 42792, 42792, 42793, 42794, 42795, \n\t42795, 42796, 42797, 42798, 42798, 42799, 42800, 42801, \n\t42802, 42802, 42803, 42804, 42805, 42805, 42806, 42807, \n\t42808, 42808, 42809, 42810, 42811, 42811, 42812, 42813, \n\t42814, 42814, 42815, 42816, 42817, 42817, 42818, 42819, \n\t42820, 42820, 42821, 42822, 42823, 42823, 42824, 42825, \n\t42826, 42826, 42827, 42828, 42829, 42830, 42830, 42831, \n\t42832, 42833, 42833, 42834, 42835, 42836, 42836, 42837, \n\t42838, 42839, 42839, 42840, 42841, 42842, 42842, 42843, \n\t42844, 42845, 42845, 42846, 42847, 42848, 42848, 42849, \n\t42850, 42851, 42851, 42852, 42853, 42854, 42854, 42855, \n\t42856, 42857, 42858, 42858, 42859, 42860, 42861, 42861, \n\t42862, 42863, 42864, 42864, 42865, 42866, 42867, 42867, \n\t42868, 42869, 42870, 42870, 42871, 42872, 42873, 42873, \n\t42874, 42875, 42876, 42876, 42877, 42878, 42879, 42879, \n\t42880, 42881, 42882, 42882, 42883, 42884, 42885, 42886, \n\t42886, 42887, 42888, 42889, 42889, 42890, 42891, 42892, \n\t42892, 42893, 42894, 42895, 42895, 42896, 42897, 42898, \n\t42898, 42899, 42900, 42901, 42901, 42902, 42903, 42904, \n\t42904, 42905, 42906, 42907, 42907, 42908, 42909, 42910, \n\t42910, 42911, 42912, 42913, 42913, 42914, 42915, 42916, \n\t42917, 42917, 42918, 42919, 42920, 42920, 42921, 42922, \n\t42923, 42923, 42924, 42925, 42926, 42926, 42927, 42928, \n\t42929, 42929, 42930, 42931, 42932, 42932, 42933, 42934, \n\t42935, 42935, 42936, 42937, 42938, 42938, 42939, 42940, \n\t42941, 42941, 42942, 42943, 42944, 42944, 42945, 42946, \n\t42947, 42947, 42948, 42949, 42950, 42951, 42951, 42952, \n\t42953, 42954, 42954, 42955, 42956, 42957, 42957, 42958, \n\t42959, 42960, 42960, 42961, 42962, 42963, 42963, 42964, \n\t42965, 42966, 42966, 42967, 42968, 42969, 42969, 42970, \n\t42971, 42972, 42972, 42973, 42974, 42975, 42975, 42976, \n\t42977, 42978, 42978, 42979, 42980, 42981, 42981, 42982, \n\t42983, 42984, 42984, 42985, 42986, 42987, 42988, 42988, \n\t42989, 42990, 42991, 42991, 42992, 42993, 42994, 42994, \n\t42995, 42996, 42997, 42997, 42998, 42999, 43000, 43000, \n\t43001, 43002, 43003, 43003, 43004, 43005, 43006, 43006, \n\t43007, 43008, 43009, 43009, 43010, 43011, 43012, 43012, \n\t43013, 43014, 43015, 43015, 43016, 43017, 43018, 43018, \n\t43019, 43020, 43021, 43021, 43022, 43023, 43024, 43024, \n\t43025, 43026, 43027, 43027, 43028, 43029, 43030, 43031, \n\t43031, 43032, 43033, 43034, 43034, 43035, 43036, 43037, \n\t43037, 43038, 43039, 43040, 43040, 43041, 43042, 43043, \n\t43043, 43044, 43045, 43046, 43046, 43047, 43048, 43049, \n\t43049, 43050, 43051, 43052, 43052, 43053, 43054, 43055, \n\t43055, 43056, 43057, 43058, 43058, 43059, 43060, 43061, \n\t43061, 43062, 43063, 43064, 43064, 43065, 43066, 43067, \n\t43067, 43068, 43069, 43070, 43070, 43071, 43072, 43073, \n\t43073, 43074, 43075, 43076, 43076, 43077, 43078, 43079, \n\t43080, 43080, 43081, 43082, 43083, 43083, 43084, 43085, \n\t43086, 43086, 43087, 43088, 43089, 43089, 43090, 43091, \n\t43092, 43092, 43093, 43094, 43095, 43095, 43096, 43097, \n\t43098, 43098, 43099, 43100, 43101, 43101, 43102, 43103, \n\t43104, 43104, 43105, 43106, 43107, 43107, 43108, 43109, \n\t43110, 43110, 43111, 43112, 43113, 43113, 43114, 43115, \n\t43116, 43116, 43117, 43118, 43119, 43119, 43120, 43121, \n\t43122, 43122, 43123, 43124, 43125, 43125, 43126, 43127, \n\t43128, 43128, 43129, 43130, 43131, 43131, 43132, 43133, \n\t43134, 43134, 43135, 43136, 43137, 43138, 43138, 43139, \n\t43140, 43141, 43141, 43142, 43143, 43144, 43144, 43145, \n\t43146, 43147, 43147, 43148, 43149, 43150, 43150, 43151, \n\t43152, 43153, 43153, 43154, 43155, 43156, 43156, 43157, \n\t43158, 43159, 43159, 43160, 43161, 43162, 43162, 43163, \n\t43164, 43165, 43165, 43166, 43167, 43168, 43168, 43169, \n\t43170, 43171, 43171, 43172, 43173, 43174, 43174, 43175, \n\t43176, 43177, 43177, 43178, 43179, 43180, 43180, 43181, \n\t43182, 43183, 43183, 43184, 43185, 43186, 43186, 43187, \n\t43188, 43189, 43189, 43190, 43191, 43192, 43192, 43193, \n\t43194, 43195, 43195, 43196, 43197, 43198, 43198, 43199, \n\t43200, 43201, 43201, 43202, 43203, 43204, 43204, 43205, \n\t43206, 43207, 43207, 43208, 43209, 43210, 43210, 43211, \n\t43212, 43213, 43213, 43214, 43215, 43216, 43217, 43217, \n\t43218, 43219, 43220, 43220, 43221, 43222, 43223, 43223, \n\t43224, 43225, 43226, 43226, 43227, 43228, 43229, 43229, \n\t43230, 43231, 43232, 43232, 43233, 43234, 43235, 43235, \n\t43236, 43237, 43238, 43238, 43239, 43240, 43241, 43241, \n\t43242, 43243, 43244, 43244, 43245, 43246, 43247, 43247, \n\t43248, 43249, 43250, 43250, 43251, 43252, 43253, 43253, \n\t43254, 43255, 43256, 43256, 43257, 43258, 43259, 43259, \n\t43260, 43261, 43262, 43262, 43263, 43264, 43265, 43265, \n\t43266, 43267, 43268, 43268, 43269, 43270, 43271, 43271, \n\t43272, 43273, 43274, 43274, 43275, 43276, 43277, 43277, \n\t43278, 43279, 43280, 43280, 43281, 43282, 43283, 43283, \n\t43284, 43285, 43286, 43286, 43287, 43288, 43289, 43289, \n\t43290, 43291, 43292, 43292, 43293, 43294, 43295, 43295, \n\t43296, 43297, 43298, 43298, 43299, 43300, 43301, 43301, \n\t43302, 43303, 43304, 43304, 43305, 43306, 43307, 43307, \n\t43308, 43309, 43310, 43310, 43311, 43312, 43313, 43313, \n\t43314, 43315, 43316, 43316, 43317, 43318, 43319, 43319, \n\t43320, 43321, 43322, 43322, 43323, 43324, 43325, 43325, \n\t43326, 43327, 43328, 43328, 43329, 43330, 43331, 43331, \n\t43332, 43333, 43334, 43334, 43335, 43336, 43337, 43337, \n\t43338, 43339, 43340, 43340, 43341, 43342, 43343, 43343, \n\t43344, 43345, 43346, 43346, 43347, 43348, 43349, 43349, \n\t43350, 43351, 43352, 43352, 43353, 43354, 43355, 43355, \n\t43356, 43357, 43358, 43358, 43359, 43360, 43361, 43361, \n\t43362, 43363, 43364, 43364, 43365, 43366, 43367, 43367, \n\t43368, 43369, 43370, 43370, 43371, 43372, 43373, 43373, \n\t43374, 43375, 43376, 43376, 43377, 43378, 43379, 43379, \n\t43380, 43381, 43382, 43382, 43383, 43384, 43385, 43385, \n\t43386, 43387, 43388, 43388, 43389, 43390, 43391, 43391, \n\t43392, 43393, 43394, 43394, 43395, 43396, 43397, 43397, \n\t43398, 43399, 43400, 43400, 43401, 43402, 43403, 43403, \n\t43404, 43405, 43406, 43406, 43407, 43408, 43409, 43409, \n\t43410, 43411, 43412, 43412, 43413, 43414, 43415, 43415, \n\t43416, 43417, 43418, 43418, 43419, 43420, 43421, 43421, \n\t43422, 43423, 43424, 43424, 43425, 43426, 43427, 43427, \n\t43428, 43429, 43430, 43430, 43431, 43432, 43433, 43433, \n\t43434, 43435, 43436, 43436, 43437, 43438, 43439, 43439, \n\t43440, 43441, 43442, 43442, 43443, 43444, 43445, 43445, \n\t43446, 43447, 43448, 43448, 43449, 43450, 43451, 43451, \n\t43452, 43453, 43454, 43454, 43455, 43456, 43457, 43457, \n\t43458, 43459, 43460, 43460, 43461, 43462, 43463, 43463, \n\t43464, 43465, 43466, 43466, 43467, 43468, 43469, 43469, \n\t43470, 43471, 43472, 43472, 43473, 43474, 43475, 43475, \n\t43476, 43477, 43478, 43478, 43479, 43480, 43480, 43481, \n\t43482, 43483, 43483, 43484, 43485, 43486, 43486, 43487, \n\t43488, 43489, 43489, 43490, 43491, 43492, 43492, 43493, \n\t43494, 43495, 43495, 43496, 43497, 43498, 43498, 43499, \n\t43500, 43501, 43501, 43502, 43503, 43504, 43504, 43505, \n\t43506, 43507, 43507, 43508, 43509, 43510, 43510, 43511, \n\t43512, 43513, 43513, 43514, 43515, 43516, 43516, 43517, \n\t43518, 43519, 43519, 43520, 43521, 43522, 43522, 43523, \n\t43524, 43525, 43525, 43526, 43527, 43528, 43528, 43529, \n\t43530, 43531, 43531, 43532, 43533, 43534, 43534, 43535, \n\t43536, 43537, 43537, 43538, 43539, 43540, 43540, 43541, \n\t43542, 43543, 43543, 43544, 43545, 43546, 43546, 43547, \n\t43548, 43549, 43549, 43550, 43551, 43552, 43552, 43553, \n\t43554, 43555, 43555, 43556, 43557, 43558, 43558, 43559, \n\t43560, 43560, 43561, 43562, 43563, 43563, 43564, 43565, \n\t43566, 43566, 43567, 43568, 43569, 43569, 43570, 43571, \n\t43572, 43572, 43573, 43574, 43575, 43575, 43576, 43577, \n\t43578, 43578, 43579, 43580, 43581, 43581, 43582, 43583, \n\t43584, 43584, 43585, 43586, 43587, 43587, 43588, 43589, \n\t43590, 43590, 43591, 43592, 43593, 43593, 43594, 43595, \n\t43596, 43596, 43597, 43598, 43599, 43599, 43600, 43601, \n\t43602, 43602, 43603, 43604, 43605, 43605, 43606, 43607, \n\t43608, 43608, 43609, 43610, 43611, 43611, 43612, 43613, \n\t43614, 43614, 43615, 43616, 43617, 43617, 43618, 43619, \n\t43619, 43620, 43621, 43622, 43622, 43623, 43624, 43625, \n\t43625, 43626, 43627, 43628, 43628, 43629, 43630, 43631, \n\t43631, 43632, 43633, 43634, 43634, 43635, 43636, 43637, \n\t43637, 43638, 43639, 43640, 43640, 43641, 43642, 43643, \n\t43643, 43644, 43645, 43646, 43646, 43647, 43648, 43649, \n\t43649, 43650, 43651, 43652, 43652, 43653, 43654, 43655, \n\t43655, 43656, 43657, 43658, 43658, 43659, 43660, 43661, \n\t43661, 43662, 43663, 43664, 43664, 43665, 43666, 43666, \n\t43667, 43668, 43669, 43669, 43670, 43671, 43672, 43672, \n\t43673, 43674, 43675, 43675, 43676, 43677, 43678, 43678, \n\t43679, 43680, 43681, 43681, 43682, 43683, 43684, 43684, \n\t43685, 43686, 43687, 43687, 43688, 43689, 43690, 43690, \n\t43691, 43692, 43693, 43693, 43694, 43695, 43696, 43696, \n\t43697, 43698, 43699, 43699, 43700, 43701, 43702, 43702, \n\t43703, 43704, 43705, 43705, 43706, 43707, 43707, 43708, \n\t43709, 43710, 43710, 43711, 43712, 43713, 43713, 43714, \n\t43715, 43716, 43716, 43717, 43718, 43719, 43719, 43720, \n\t43721, 43722, 43722, 43723, 43724, 43725, 43725, 43726, \n\t43727, 43728, 43728, 43729, 43730, 43731, 43731, 43732, \n\t43733, 43734, 43734, 43735, 43736, 43737, 43737, 43738, \n\t43739, 43740, 43740, 43741, 43742, 43742, 43743, 43744, \n\t43745, 43745, 43746, 43747, 43748, 43748, 43749, 43750, \n\t43751, 43751, 43752, 43753, 43754, 43754, 43755, 43756, \n\t43757, 43757, 43758, 43759, 43760, 43760, 43761, 43762, \n\t43763, 43763, 43764, 43765, 43766, 43766, 43767, 43768, \n\t43769, 43769, 43770, 43771, 43772, 43772, 43773, 43774, \n\t43775, 43775, 43776, 43777, 43777, 43778, 43779, 43780, \n\t43780, 43781, 43782, 43783, 43783, 43784, 43785, 43786, \n\t43786, 43787, 43788, 43789, 43789, 43790, 43791, 43792, \n\t43792, 43793, 43794, 43795, 43795, 43796, 43797, 43798, \n\t43798, 43799, 43800, 43801, 43801, 43802, 43803, 43804, \n\t43804, 43805, 43806, 43806, 43807, 43808, 43809, 43809, \n\t43810, 43811, 43812, 43812, 43813, 43814, 43815, 43815, \n\t43816, 43817, 43818, 43818, 43819, 43820, 43821, 43821, \n\t43822, 43823, 43824, 43824, 43825, 43826, 43827, 43827, \n\t43828, 43829, 43830, 43830, 43831, 43832, 43833, 43833, \n\t43834, 43835, 43835, 43836, 43837, 43838, 43838, 43839, \n\t43840, 43841, 43841, 43842, 43843, 43844, 43844, 43845, \n\t43846, 43847, 43847, 43848, 43849, 43850, 43850, 43851, \n\t43852, 43853, 43853, 43854, 43855, 43856, 43856, 43857, \n\t43858, 43859, 43859, 43860, 43861, 43862, 43862, 43863, \n\t43864, 43864, 43865, 43866, 43867, 43867, 43868, 43869, \n\t43870, 43870, 43871, 43872, 43873, 43873, 43874, 43875, \n\t43876, 43876, 43877, 43878, 43879, 43879, 43880, 43881, \n\t43882, 43882, 43883, 43884, 43885, 43885, 43886, 43887, \n\t43888, 43888, 43889, 43890, 43890, 43891, 43892, 43893, \n\t43893, 43894, 43895, 43896, 43896, 43897, 43898, 43899, \n\t43899, 43900, 43901, 43902, 43902, 43903, 43904, 43905, \n\t43905, 43906, 43907, 43908, 43908, 43909, 43910, 43911, \n\t43911, 43912, 43913, 43913, 43914, 43915, 43916, 43916, \n\t43917, 43918, 43919, 43919, 43920, 43921, 43922, 43922, \n\t43923, 43924, 43925, 43925, 43926, 43927, 43928, 43928, \n\t43929, 43930, 43931, 43931, 43932, 43933, 43934, 43934, \n\t43935, 43936, 43937, 43937, 43938, 43939, 43939, 43940, \n\t43941, 43942, 43942, 43943, 43944, 43945, 43945, 43946, \n\t43947, 43948, 43948, 43949, 43950, 43951, 43951, 43952, \n\t43953, 43954, 43954, 43955, 43956, 43957, 43957, 43958, \n\t43959, 43959, 43960, 43961, 43962, 43962, 43963, 43964, \n\t43965, 43965, 43966, 43967, 43968, 43968, 43969, 43970, \n\t43971, 43971, 43972, 43973, 43974, 43974, 43975, 43976, \n\t43977, 43977, 43978, 43979, 43980, 43980, 43981, 43982, \n\t43982, 43983, 43984, 43985, 43985, 43986, 43987, 43988, \n\t43988, 43989, 43990, 43991, 43991, 43992, 43993, 43994, \n\t43994, 43995, 43996, 43997, 43997, 43998, 43999, 44000, \n\t44000, 44001, 44002, 44002, 44003, 44004, 44005, 44005, \n\t44006, 44007, 44008, 44008, 44009, 44010, 44011, 44011, \n\t44012, 44013, 44014, 44014, 44015, 44016, 44017, 44017, \n\t44018, 44019, 44020, 44020, 44021, 44022, 44023, 44023, \n\t44024, 44025, 44025, 44026, 44027, 44028, 44028, 44029, \n\t44030, 44031, 44031, 44032, 44033, 44034, 44034, 44035, \n\t44036, 44037, 44037, 44038, 44039, 44040, 44040, 44041, \n\t44042, 44042, 44043, 44044, 44045, 44045, 44046, 44047, \n\t44048, 44048, 44049, 44050, 44051, 44051, 44052, 44053, \n\t44054, 44054, 44055, 44056, 44057, 44057, 44058, 44059, \n\t44060, 44060, 44061, 44062, 44062, 44063, 44064, 44065, \n\t44065, 44066, 44067, 44068, 44068, 44069, 44070, 44071, \n\t44071, 44072, 44073, 44074, 44074, 44075, 44076, 44077, \n\t44077, 44078, 44079, 44080, 44080, 44081, 44082, 44082, \n\t44083, 44084, 44085, 44085, 44086, 44087, 44088, 44088, \n\t44089, 44090, 44091, 44091, 44092, 44093, 44094, 44094, \n\t44095, 44096, 44097, 44097, 44098, 44099, 44099, 44100, \n\t44101, 44102, 44102, 44103, 44104, 44105, 44105, 44106, \n\t44107, 44108, 44108, 44109, 44110, 44111, 44111, 44112, \n\t44113, 44114, 44114, 44115, 44116, 44117, 44117, 44118, \n\t44119, 44119, 44120, 44121, 44122, 44122, 44123, 44124, \n\t44125, 44125, 44126, 44127, 44128, 44128, 44129, 44130, \n\t44131, 44131, 44132, 44133, 44134, 44134, 44135, 44136, \n\t44136, 44137, 44138, 44139, 44139, 44140, 44141, 44142, \n\t44142, 44143, 44144, 44145, 44145, 44146, 44147, 44148, \n\t44148, 44149, 44150, 44151, 44151, 44152, 44153, 44153, \n\t44154, 44155, 44156, 44156, 44157, 44158, 44159, 44159, \n\t44160, 44161, 44162, 44162, 44163, 44164, 44165, 44165, \n\t44166, 44167, 44168, 44168, 44169, 44170, 44170, 44171, \n\t44172, 44173, 44173, 44174, 44175, 44176, 44176, 44177, \n\t44178, 44179, 44179, 44180, 44181, 44182, 44182, 44183, \n\t44184, 44184, 44185, 44186, 44187, 44187, 44188, 44189, \n\t44190, 44190, 44191, 44192, 44193, 44193, 44194, 44195, \n\t44196, 44196, 44197, 44198, 44199, 44199, 44200, 44201, \n\t44201, 44202, 44203, 44204, 44204, 44205, 44206, 44207, \n\t44207, 44208, 44209, 44210, 44210, 44211, 44212, 44213, \n\t44213, 44214, 44215, 44216, 44216, 44217, 44218, 44218, \n\t44219, 44220, 44221, 44221, 44222, 44223, 44224, 44224, \n\t44225, 44226, 44227, 44227, 44228, 44229, 44230, 44230, \n\t44231, 44232, 44232, 44233, 44234, 44235, 44235, 44236, \n\t44237, 44238, 44238, 44239, 44240, 44241, 44241, 44242, \n\t44243, 44244, 44244, 44245, 44246, 44246, 44247, 44248, \n\t44249, 44249, 44250, 44251, 44252, 44252, 44253, 44254, \n\t44255, 44255, 44256, 44257, 44258, 44258, 44259, 44260, \n\t44261, 44261, 44262, 44263, 44263, 44264, 44265, 44266, \n\t44266, 44267, 44268, 44269, 44269, 44270, 44271, 44272, \n\t44272, 44273, 44274, 44275, 44275, 44276, 44277, 44277, \n\t44278, 44279, 44280, 44280, 44281, 44282, 44283, 44283, \n\t44284, 44285, 44286, 44286, 44287, 44288, 44289, 44289, \n\t44290, 44291, 44291, 44292, 44293, 44294, 44294, 44295, \n\t44296, 44297, 44297, 44298, 44299, 44300, 44300, 44301, \n\t44302, 44303, 44303, 44304, 44305, 44305, 44306, 44307, \n\t44308, 44308, 44309, 44310, 44311, 44311, 44312, 44313, \n\t44314, 44314, 44315, 44316, 44317, 44317, 44318, 44319, \n\t44319, 44320, 44321, 44322, 44322, 44323, 44324, 44325, \n\t44325, 44326, 44327, 44328, 44328, 44329, 44330, 44331, \n\t44331, 44332, 44333, 44333, 44334, 44335, 44336, 44336, \n\t44337, 44338, 44339, 44339, 44340, 44341, 44342, 44342, \n\t44343, 44344, 44345, 44345, 44346, 44347, 44347, 44348, \n\t44349, 44350, 44350, 44351, 44352, 44353, 44353, 44354, \n\t44355, 44356, 44356, 44357, 44358, 44359, 44359, 44360, \n\t44361, 44361, 44362, 44363, 44364, 44364, 44365, 44366, \n\t44367, 44367, 44368, 44369, 44370, 44370, 44371, 44372, \n\t44372, 44373, 44374, 44375, 44375, 44376, 44377, 44378, \n\t44378, 44379, 44380, 44381, 44381, 44382, 44383, 44384, \n\t44384, 44385, 44386, 44386, 44387, 44388, 44389, 44389, \n\t44390, 44391, 44392, 44392, 44393, 44394, 44395, 44395, \n\t44396, 44397, 44398, 44398, 44399, 44400, 44400, 44401, \n\t44402, 44403, 44403, 44404, 44405, 44406, 44406, 44407, \n\t44408, 44409, 44409, 44410, 44411, 44411, 44412, 44413, \n\t44414, 44414, 44415, 44416, 44417, 44417, 44418, 44419, \n\t44420, 44420, 44421, 44422, 44423, 44423, 44424, 44425, \n\t44425, 44426, 44427, 44428, 44428, 44429, 44430, 44431, \n\t44431, 44432, 44433, 44434, 44434, 44435, 44436, 44436, \n\t44437, 44438, 44439, 44439, 44440, 44441, 44442, 44442, \n\t44443, 44444, 44445, 44445, 44446, 44447, 44447, 44448, \n\t44449, 44450, 44450, 44451, 44452, 44453, 44453, 44454, \n\t44455, 44456, 44456, 44457, 44458, 44459, 44459, 44460, \n\t44461, 44461, 44462, 44463, 44464, 44464, 44465, 44466, \n\t44467, 44467, 44468, 44469, 44470, 44470, 44471, 44472, \n\t44472, 44473, 44474, 44475, 44475, 44476, 44477, 44478, \n\t44478, 44479, 44480, 44481, 44481, 44482, 44483, 44483, \n\t44484, 44485, 44486, 44486, 44487, 44488, 44489, 44489, \n\t44490, 44491, 44492, 44492, 44493, 44494, 44495, 44495, \n\t44496, 44497, 44497, 44498, 44499, 44500, 44500, 44501, \n\t44502, 44503, 44503, 44504, 44505, 44506, 44506, 44507, \n\t44508, 44508, 44509, 44510, 44511, 44511, 44512, 44513, \n\t44514, 44514, 44515, 44516, 44517, 44517, 44518, 44519, \n\t44519, 44520, 44521, 44522, 44522, 44523, 44524, 44525, \n\t44525, 44526, 44527, 44528, 44528, 44529, 44530, 44530, \n\t44531, 44532, 44533, 44533, 44534, 44535, 44536, 44536, \n\t44537, 44538, 44539, 44539, 44540, 44541, 44541, 44542, \n\t44543, 44544, 44544, 44545, 44546, 44547, 44547, 44548, \n\t44549, 44550, 44550, 44551, 44552, 44552, 44553, 44554, \n\t44555, 44555, 44556, 44557, 44558, 44558, 44559, 44560, \n\t44561, 44561, 44562, 44563, 44563, 44564, 44565, 44566, \n\t44566, 44567, 44568, 44569, 44569, 44570, 44571, 44572, \n\t44572, 44573, 44574, 44574, 44575, 44576, 44577, 44577, \n\t44578, 44579, 44580, 44580, 44581, 44582, 44583, 44583, \n\t44584, 44585, 44585, 44586, 44587, 44588, 44588, 44589, \n\t44590, 44591, 44591, 44592, 44593, 44594, 44594, 44595, \n\t44596, 44596, 44597, 44598, 44599, 44599, 44600, 44601, \n\t44602, 44602, 44603, 44604, 44605, 44605, 44606, 44607, \n\t44607, 44608, 44609, 44610, 44610, 44611, 44612, 44613, \n\t44613, 44614, 44615, 44616, 44616, 44617, 44618, 44618, \n\t44619, 44620, 44621, 44621, 44622, 44623, 44624, 44624, \n\t44625, 44626, 44626, 44627, 44628, 44629, 44629, 44630, \n\t44631, 44632, 44632, 44633, 44634, 44635, 44635, 44636, \n\t44637, 44637, 44638, 44639, 44640, 44640, 44641, 44642, \n\t44643, 44643, 44644, 44645, 44646, 44646, 44647, 44648, \n\t44648, 44649, 44650, 44651, 44651, 44652, 44653, 44654, \n\t44654, 44655, 44656, 44657, 44657, 44658, 44659, 44659, \n\t44660, 44661, 44662, 44662, 44663, 44664, 44665, 44665, \n\t44666, 44667, 44667, 44668, 44669, 44670, 44670, 44671, \n\t44672, 44673, 44673, 44674, 44675, 44676, 44676, 44677, \n\t44678, 44678, 44679, 44680, 44681, 44681, 44682, 44683, \n\t44684, 44684, 44685, 44686, 44687, 44687, 44688, 44689, \n\t44689, 44690, 44691, 44692, 44692, 44693, 44694, 44695, \n\t44695, 44696, 44697, 44697, 44698, 44699, 44700, 44700, \n\t44701, 44702, 44703, 44703, 44704, 44705, 44706, 44706, \n\t44707, 44708, 44708, 44709, 44710, 44711, 44711, 44712, \n\t44713, 44714, 44714, 44715, 44716, 44716, 44717, 44718, \n\t44719, 44719, 44720, 44721, 44722, 44722, 44723, 44724, \n\t44725, 44725, 44726, 44727, 44727, 44728, 44729, 44730, \n\t44730, 44731, 44732, 44733, 44733, 44734, 44735, 44735, \n\t44736, 44737, 44738, 44738, 44739, 44740, 44741, 44741, \n\t44742, 44743, 44744, 44744, 44745, 44746, 44746, 44747, \n\t44748, 44749, 44749, 44750, 44751, 44752, 44752, 44753, \n\t44754, 44754, 44755, 44756, 44757, 44757, 44758, 44759, \n\t44760, 44760, 44761, 44762, 44763, 44763, 44764, 44765, \n\t44765, 44766, 44767, 44768, 44768, 44769, 44770, 44771, \n\t44771, 44772, 44773, 44773, 44774, 44775, 44776, 44776, \n\t44777, 44778, 44779, 44779, 44780, 44781, 44782, 44782, \n\t44783, 44784, 44784, 44785, 44786, 44787, 44787, 44788, \n\t44789, 44790, 44790, 44791, 44792, 44792, 44793, 44794, \n\t44795, 44795, 44796, 44797, 44798, 44798, 44799, 44800, \n\t44800, 44801, 44802, 44803, 44803, 44804, 44805, 44806, \n\t44806, 44807, 44808, 44809, 44809, 44810, 44811, 44811, \n\t44812, 44813, 44814, 44814, 44815, 44816, 44817, 44817, \n\t44818, 44819, 44819, 44820, 44821, 44822, 44822, 44823, \n\t44824, 44825, 44825, 44826, 44827, 44827, 44828, 44829, \n\t44830, 44830, 44831, 44832, 44833, 44833, 44834, 44835, \n\t44836, 44836, 44837, 44838, 44838, 44839, 44840, 44841, \n\t44841, 44842, 44843, 44844, 44844, 44845, 44846, 44846, \n\t44847, 44848, 44849, 44849, 44850, 44851, 44852, 44852, \n\t44853, 44854, 44854, 44855, 44856, 44857, 44857, 44858, \n\t44859, 44860, 44860, 44861, 44862, 44862, 44863, 44864, \n\t44865, 44865, 44866, 44867, 44868, 44868, 44869, 44870, \n\t44871, 44871, 44872, 44873, 44873, 44874, 44875, 44876, \n\t44876, 44877, 44878, 44879, 44879, 44880, 44881, 44881, \n\t44882, 44883, 44884, 44884, 44885, 44886, 44887, 44887, \n\t44888, 44889, 44889, 44890, 44891, 44892, 44892, 44893, \n\t44894, 44895, 44895, 44896, 44897, 44897, 44898, 44899, \n\t44900, 44900, 44901, 44902, 44903, 44903, 44904, 44905, \n\t44905, 44906, 44907, 44908, 44908, 44909, 44910, 44911, \n\t44911, 44912, 44913, 44913, 44914, 44915, 44916, 44916, \n\t44917, 44918, 44919, 44919, 44920, 44921, 44922, 44922, \n\t44923, 44924, 44924, 44925, 44926, 44927, 44927, 44928, \n\t44929, 44930, 44930, 44931, 44932, 44932, 44933, 44934, \n\t44935, 44935, 44936, 44937, 44938, 44938, 44939, 44940, \n\t44940, 44941, 44942, 44943, 44943, 44944, 44945, 44946, \n\t44946, 44947, 44948, 44948, 44949, 44950, 44951, 44951, \n\t44952, 44953, 44954, 44954, 44955, 44956, 44956, 44957, \n\t44958, 44959, 44959, 44960, 44961, 44962, 44962, 44963, \n\t44964, 44964, 44965, 44966, 44967, 44967, 44968, 44969, \n\t44970, 44970, 44971, 44972, 44972, 44973, 44974, 44975, \n\t44975, 44976, 44977, 44978, 44978, 44979, 44980, 44980, \n\t44981, 44982, 44983, 44983, 44984, 44985, 44986, 44986, \n\t44987, 44988, 44988, 44989, 44990, 44991, 44991, 44992, \n\t44993, 44994, 44994, 44995, 44996, 44996, 44997, 44998, \n\t44999, 44999, 45000, 45001, 45002, 45002, 45003, 45004, \n\t45004, 45005, 45006, 45007, 45007, 45008, 45009, 45010, \n\t45010, 45011, 45012, 45012, 45013, 45014, 45015, 45015, \n\t45016, 45017, 45018, 45018, 45019, 45020, 45020, 45021, \n\t45022, 45023, 45023, 45024, 45025, 45026, 45026, 45027, \n\t45028, 45028, 45029, 45030, 45031, 45031, 45032, 45033, \n\t45034, 45034, 45035, 45036, 45036, 45037, 45038, 45039, \n\t45039, 45040, 45041, 45042, 45042, 45043, 45044, 45044, \n\t45045, 45046, 45047, 45047, 45048, 45049, 45049, 45050, \n\t45051, 45052, 45052, 45053, 45054, 45055, 45055, 45056, \n\t45057, 45057, 45058, 45059, 45060, 45060, 45061, 45062, \n\t45063, 45063, 45064, 45065, 45065, 45066, 45067, 45068, \n\t45068, 45069, 45070, 45071, 45071, 45072, 45073, 45073, \n\t45074, 45075, 45076, 45076, 45077, 45078, 45079, 45079, \n\t45080, 45081, 45081, 45082, 45083, 45084, 45084, 45085, \n\t45086, 45087, 45087, 45088, 45089, 45089, 45090, 45091, \n\t45092, 45092, 45093, 45094, 45095, 45095, 45096, 45097, \n\t45097, 45098, 45099, 45100, 45100, 45101, 45102, 45102, \n\t45103, 45104, 45105, 45105, 45106, 45107, 45108, 45108, \n\t45109, 45110, 45110, 45111, 45112, 45113, 45113, 45114, \n\t45115, 45116, 45116, 45117, 45118, 45118, 45119, 45120, \n\t45121, 45121, 45122, 45123, 45124, 45124, 45125, 45126, \n\t45126, 45127, 45128, 45129, 45129, 45130, 45131, 45131, \n\t45132, 45133, 45134, 45134, 45135, 45136, 45137, 45137, \n\t45138, 45139, 45139, 45140, 45141, 45142, 45142, 45143, \n\t45144, 45145, 45145, 45146, 45147, 45147, 45148, 45149, \n\t45150, 45150, 45151, 45152, 45153, 45153, 45154, 45155, \n\t45155, 45156, 45157, 45158, 45158, 45159, 45160, 45160, \n\t45161, 45162, 45163, 45163, 45164, 45165, 45166, 45166, \n\t45167, 45168, 45168, 45169, 45170, 45171, 45171, 45172, \n\t45173, 45174, 45174, 45175, 45176, 45176, 45177, 45178, \n\t45179, 45179, 45180, 45181, 45182, 45182, 45183, 45184, \n\t45184, 45185, 45186, 45187, 45187, 45188, 45189, 45189, \n\t45190, 45191, 45192, 45192, 45193, 45194, 45195, 45195, \n\t45196, 45197, 45197, 45198, 45199, 45200, 45200, 45201, \n\t45202, 45203, 45203, 45204, 45205, 45205, 45206, 45207, \n\t45208, 45208, 45209, 45210, 45210, 45211, 45212, 45213, \n\t45213, 45214, 45215, 45216, 45216, 45217, 45218, 45218, \n\t45219, 45220, 45221, 45221, 45222, 45223, 45223, 45224, \n\t45225, 45226, 45226, 45227, 45228, 45229, 45229, 45230, \n\t45231, 45231, 45232, 45233, 45234, 45234, 45235, 45236, \n\t45237, 45237, 45238, 45239, 45239, 45240, 45241, 45242, \n\t45242, 45243, 45244, 45244, 45245, 45246, 45247, 45247, \n\t45248, 45249, 45250, 45250, 45251, 45252, 45252, 45253, \n\t45254, 45255, 45255, 45256, 45257, 45258, 45258, 45259, \n\t45260, 45260, 45261, 45262, 45263, 45263, 45264, 45265, \n\t45265, 45266, 45267, 45268, 45268, 45269, 45270, 45271, \n\t45271, 45272, 45273, 45273, 45274, 45275, 45276, 45276, \n\t45277, 45278, 45278, 45279, 45280, 45281, 45281, 45282, \n\t45283, 45284, 45284, 45285, 45286, 45286, 45287, 45288, \n\t45289, 45289, 45290, 45291, 45291, 45292, 45293, 45294, \n\t45294, 45295, 45296, 45297, 45297, 45298, 45299, 45299, \n\t45300, 45301, 45302, 45302, 45303, 45304, 45304, 45305, \n\t45306, 45307, 45307, 45308, 45309, 45310, 45310, 45311, \n\t45312, 45312, 45313, 45314, 45315, 45315, 45316, 45317, \n\t45317, 45318, 45319, 45320, 45320, 45321, 45322, 45323, \n\t45323, 45324, 45325, 45325, 45326, 45327, 45328, 45328, \n\t45329, 45330, 45330, 45331, 45332, 45333, 45333, 45334, \n\t45335, 45336, 45336, 45337, 45338, 45338, 45339, 45340, \n\t45341, 45341, 45342, 45343, 45343, 45344, 45345, 45346, \n\t45346, 45347, 45348, 45349, 45349, 45350, 45351, 45351, \n\t45352, 45353, 45354, 45354, 45355, 45356, 45356, 45357, \n\t45358, 45359, 45359, 45360, 45361, 45362, 45362, 45363, \n\t45364, 45364, 45365, 45366, 45367, 45367, 45368, 45369, \n\t45369, 45370, 45371, 45372, 45372, 45373, 45374, 45375, \n\t45375, 45376, 45377, 45377, 45378, 45379, 45380, 45380, \n\t45381, 45382, 45382, 45383, 45384, 45385, 45385, 45386, \n\t45387, 45388, 45388, 45389, 45390, 45390, 45391, 45392, \n\t45393, 45393, 45394, 45395, 45395, 45396, 45397, 45398, \n\t45398, 45399, 45400, 45401, 45401, 45402, 45403, 45403, \n\t45404, 45405, 45406, 45406, 45407, 45408, 45408, 45409, \n\t45410, 45411, 45411, 45412, 45413, 45413, 45414, 45415, \n\t45416, 45416, 45417, 45418, 45419, 45419, 45420, 45421, \n\t45421, 45422, 45423, 45424, 45424, 45425, 45426, 45426, \n\t45427, 45428, 45429, 45429, 45430, 45431, 45432, 45432, \n\t45433, 45434, 45434, 45435, 45436, 45437, 45437, 45438, \n\t45439, 45439, 45440, 45441, 45442, 45442, 45443, 45444, \n\t45444, 45445, 45446, 45447, 45447, 45448, 45449, 45450, \n\t45450, 45451, 45452, 45452, 45453, 45454, 45455, 45455, \n\t45456, 45457, 45457, 45458, 45459, 45460, 45460, 45461, \n\t45462, 45462, 45463, 45464, 45465, 45465, 45466, 45467, \n\t45468, 45468, 45469, 45470, 45470, 45471, 45472, 45473, \n\t45473, 45474, 45475, 45475, 45476, 45477, 45478, 45478, \n\t45479, 45480, 45480, 45481, 45482, 45483, 45483, 45484, \n\t45485, 45486, 45486, 45487, 45488, 45488, 45489, 45490, \n\t45491, 45491, 45492, 45493, 45493, 45494, 45495, 45496, \n\t45496, 45497, 45498, 45498, 45499, 45500, 45501, 45501, \n\t45502, 45503, 45504, 45504, 45505, 45506, 45506, 45507, \n\t45508, 45509, 45509, 45510, 45511, 45511, 45512, 45513, \n\t45514, 45514, 45515, 45516, 45516, 45517, 45518, 45519, \n\t45519, 45520, 45521, 45522, 45522, 45523, 45524, 45524, \n\t45525, 45526, 45527, 45527, 45528, 45529, 45529, 45530, \n\t45531, 45532, 45532, 45533, 45534, 45534, 45535, 45536, \n\t45537, 45537, 45538, 45539, 45539, 45540, 45541, 45542, \n\t45542, 45543, 45544, 45545, 45545, 45546, 45547, 45547, \n\t45548, 45549, 45550, 45550, 45551, 45552, 45552, 45553, \n\t45554, 45555, 45555, 45556, 45557, 45557, 45558, 45559, \n\t45560, 45560, 45561, 45562, 45562, 45563, 45564, 45565, \n\t45565, 45566, 45567, 45568, 45568, 45569, 45570, 45570, \n\t45571, 45572, 45573, 45573, 45574, 45575, 45575, 45576, \n\t45577, 45578, 45578, 45579, 45580, 45580, 45581, 45582, \n\t45583, 45583, 45584, 45585, 45585, 45586, 45587, 45588, \n\t45588, 45589, 45590, 45591, 45591, 45592, 45593, 45593, \n\t45594, 45595, 45596, 45596, 45597, 45598, 45598, 45599, \n\t45600, 45601, 45601, 45602, 45603, 45603, 45604, 45605, \n\t45606, 45606, 45607, 45608, 45608, 45609, 45610, 45611, \n\t45611, 45612, 45613, 45614, 45614, 45615, 45616, 45616, \n\t45617, 45618, 45619, 45619, 45620, 45621, 45621, 45622, \n\t45623, 45624, 45624, 45625, 45626, 45626, 45627, 45628, \n\t45629, 45629, 45630, 45631, 45631, 45632, 45633, 45634, \n\t45634, 45635, 45636, 45636, 45637, 45638, 45639, 45639, \n\t45640, 45641, 45641, 45642, 45643, 45644, 45644, 45645, \n\t45646, 45647, 45647, 45648, 45649, 45649, 45650, 45651, \n\t45652, 45652, 45653, 45654, 45654, 45655, 45656, 45657, \n\t45657, 45658, 45659, 45659, 45660, 45661, 45662, 45662, \n\t45663, 45664, 45664, 45665, 45666, 45667, 45667, 45668, \n\t45669, 45669, 45670, 45671, 45672, 45672, 45673, 45674, \n\t45674, 45675, 45676, 45677, 45677, 45678, 45679, 45680, \n\t45680, 45681, 45682, 45682, 45683, 45684, 45685, 45685, \n\t45686, 45687, 45687, 45688, 45689, 45690, 45690, 45691, \n\t45692, 45692, 45693, 45694, 45695, 45695, 45696, 45697, \n\t45697, 45698, 45699, 45700, 45700, 45701, 45702, 45702, \n\t45703, 45704, 45705, 45705, 45706, 45707, 45707, 45708, \n\t45709, 45710, 45710, 45711, 45712, 45712, 45713, 45714, \n\t45715, 45715, 45716, 45717, 45718, 45718, 45719, 45720, \n\t45720, 45721, 45722, 45723, 45723, 45724, 45725, 45725, \n\t45726, 45727, 45728, 45728, 45729, 45730, 45730, 45731, \n\t45732, 45733, 45733, 45734, 45735, 45735, 45736, 45737, \n\t45738, 45738, 45739, 45740, 45740, 45741, 45742, 45743, \n\t45743, 45744, 45745, 45745, 45746, 45747, 45748, 45748, \n\t45749, 45750, 45750, 45751, 45752, 45753, 45753, 45754, \n\t45755, 45755, 45756, 45757, 45758, 45758, 45759, 45760, \n\t45760, 45761, 45762, 45763, 45763, 45764, 45765, 45765, \n\t45766, 45767, 45768, 45768, 45769, 45770, 45770, 45771, \n\t45772, 45773, 45773, 45774, 45775, 45776, 45776, 45777, \n\t45778, 45778, 45779, 45780, 45781, 45781, 45782, 45783, \n\t45783, 45784, 45785, 45786, 45786, 45787, 45788, 45788, \n\t45789, 45790, 45791, 45791, 45792, 45793, 45793, 45794, \n\t45795, 45796, 45796, 45797, 45798, 45798, 45799, 45800, \n\t45801, 45801, 45802, 45803, 45803, 45804, 45805, 45806, \n\t45806, 45807, 45808, 45808, 45809, 45810, 45811, 45811, \n\t45812, 45813, 45813, 45814, 45815, 45816, 45816, 45817, \n\t45818, 45818, 45819, 45820, 45821, 45821, 45822, 45823, \n\t45823, 45824, 45825, 45826, 45826, 45827, 45828, 45828, \n\t45829, 45830, 45831, 45831, 45832, 45833, 45833, 45834, \n\t45835, 45836, 45836, 45837, 45838, 45838, 45839, 45840, \n\t45841, 45841, 45842, 45843, 45843, 45844, 45845, 45846, \n\t45846, 45847, 45848, 45848, 45849, 45850, 45851, 45851, \n\t45852, 45853, 45853, 45854, 45855, 45856, 45856, 45857, \n\t45858, 45858, 45859, 45860, 45861, 45861, 45862, 45863, \n\t45863, 45864, 45865, 45866, 45866, 45867, 45868, 45868, \n\t45869, 45870, 45871, 45871, 45872, 45873, 45873, 45874, \n\t45875, 45876, 45876, 45877, 45878, 45878, 45879, 45880, \n\t45881, 45881, 45882, 45883, 45883, 45884, 45885, 45886, \n\t45886, 45887, 45888, 45888, 45889, 45890, 45891, 45891, \n\t45892, 45893, 45893, 45894, 45895, 45896, 45896, 45897, \n\t45898, 45898, 45899, 45900, 45901, 45901, 45902, 45903, \n\t45903, 45904, 45905, 45906, 45906, 45907, 45908, 45908, \n\t45909, 45910, 45911, 45911, 45912, 45913, 45913, 45914, \n\t45915, 45916, 45916, 45917, 45918, 45918, 45919, 45920, \n\t45921, 45921, 45922, 45923, 45923, 45924, 45925, 45926, \n\t45926, 45927, 45928, 45928, 45929, 45930, 45931, 45931, \n\t45932, 45933, 45933, 45934, 45935, 45936, 45936, 45937, \n\t45938, 45938, 45939, 45940, 45941, 45941, 45942, 45943, \n\t45943, 45944, 45945, 45946, 45946, 45947, 45948, 45948, \n\t45949, 45950, 45951, 45951, 45952, 45953, 45953, 45954, \n\t45955, 45956, 45956, 45957, 45958, 45958, 45959, 45960, \n\t45960, 45961, 45962, 45963, 45963, 45964, 45965, 45965, \n\t45966, 45967, 45968, 45968, 45969, 45970, 45970, 45971, \n\t45972, 45973, 45973, 45974, 45975, 45975, 45976, 45977, \n\t45978, 45978, 45979, 45980, 45980, 45981, 45982, 45983, \n\t45983, 45984, 45985, 45985, 45986, 45987, 45988, 45988, \n\t45989, 45990, 45990, 45991, 45992, 45993, 45993, 45994, \n\t45995, 45995, 45996, 45997, 45998, 45998, 45999, 46000, \n\t46000, 46001, 46002, 46003, 46003, 46004, 46005, 46005, \n\t46006, 46007, 46008, 46008, 46009, 46010, 46010, 46011, \n\t46012, 46013, 46013, 46014, 46015, 46015, 46016, 46017, \n\t46017, 46018, 46019, 46020, 46020, 46021, 46022, 46022, \n\t46023, 46024, 46025, 46025, 46026, 46027, 46027, 46028, \n\t46029, 46030, 46030, 46031, 46032, 46032, 46033, 46034, \n\t46035, 46035, 46036, 46037, 46037, 46038, 46039, 46040, \n\t46040, 46041, 46042, 46042, 46043, 46044, 46045, 46045, \n\t46046, 46047, 46047, 46048, 46049, 46050, 46050, 46051, \n\t46052, 46052, 46053, 46054, 46055, 46055, 46056, 46057, \n\t46057, 46058, 46059, 46059, 46060, 46061, 46062, 46062, \n\t46063, 46064, 46064, 46065, 46066, 46067, 46067, 46068, \n\t46069, 46069, 46070, 46071, 46072, 46072, 46073, 46074, \n\t46074, 46075, 46076, 46077, 46077, 46078, 46079, 46079, \n\t46080, 46081, 46082, 46082, 46083, 46084, 46084, 46085, \n\t46086, 46087, 46087, 46088, 46089, 46089, 46090, 46091, \n\t46091, 46092, 46093, 46094, 46094, 46095, 46096, 46096, \n\t46097, 46098, 46099, 46099, 46100, 46101, 46101, 46102, \n\t46103, 46104, 46104, 46105, 46106, 46106, 46107, 46108, \n\t46109, 46109, 46110, 46111, 46111, 46112, 46113, 46114, \n\t46114, 46115, 46116, 46116, 46117, 46118, 46118, 46119, \n\t46120, 46121, 46121, 46122, 46123, 46123, 46124, 46125, \n\t46126, 46126, 46127, 46128, 46128, 46129, 46130, 46131, \n\t46131, 46132, 46133, 46133, 46134, 46135, 46136, 46136, \n\t46137, 46138, 46138, 46139, 46140, 46141, 46141, 46142, \n\t46143, 46143, 46144, 46145, 46145, 46146, 46147, 46148, \n\t46148, 46149, 46150, 46150, 46151, 46152, 46153, 46153, \n\t46154, 46155, 46155, 46156, 46157, 46158, 46158, 46159, \n\t46160, 46160, 46161, 46162, 46163, 46163, 46164, 46165, \n\t46165, 46166, 46167, 46167, 46168, 46169, 46170, 46170, \n\t46171, 46172, 46172, 46173, 46174, 46175, 46175, 46176, \n\t46177, 46177, 46178, 46179, 46180, 46180, 46181, 46182, \n\t46182, 46183, 46184, 46185, 46185, 46186, 46187, 46187, \n\t46188, 46189, 46189, 46190, 46191, 46192, 46192, 46193, \n\t46194, 46194, 46195, 46196, 46197, 46197, 46198, 46199, \n\t46199, 46200, 46201, 46202, 46202, 46203, 46204, 46204, \n\t46205, 46206, 46207, 46207, 46208, 46209, 46209, 46210, \n\t46211, 46211, 46212, 46213, 46214, 46214, 46215, 46216, \n\t46216, 46217, 46218, 46219, 46219, 46220, 46221, 46221, \n\t46222, 46223, 46224, 46224, 46225, 46226, 46226, 46227, \n\t46228, 46228, 46229, 46230, 46231, 46231, 46232, 46233, \n\t46233, 46234, 46235, 46236, 46236, 46237, 46238, 46238, \n\t46239, 46240, 46241, 46241, 46242, 46243, 46243, 46244, \n\t46245, 46245, 46246, 46247, 46248, 46248, 46249, 46250, \n\t46250, 46251, 46252, 46253, 46253, 46254, 46255, 46255, \n\t46256, 46257, 46258, 46258, 46259, 46260, 46260, 46261, \n\t46262, 46262, 46263, 46264, 46265, 46265, 46266, 46267, \n\t46267, 46268, 46269, 46270, 46270, 46271, 46272, 46272, \n\t46273, 46274, 46275, 46275, 46276, 46277, 46277, 46278, \n\t46279, 46279, 46280, 46281, 46282, 46282, 46283, 46284, \n\t46284, 46285, 46286, 46287, 46287, 46288, 46289, 46289, \n\t46290, 46291, 46292, 46292, 46293, 46294, 46294, 46295, \n\t46296, 46296, 46297, 46298, 46299, 46299, 46300, 46301, \n\t46301, 46302, 46303, 46304, 46304, 46305, 46306, 46306, \n\t46307, 46308, 46309, 46309, 46310, 46311, 46311, 46312, \n\t46313, 46313, 46314, 46315, 46316, 46316, 46317, 46318, \n\t46318, 46319, 46320, 46321, 46321, 46322, 46323, 46323, \n\t46324, 46325, 46325, 46326, 46327, 46328, 46328, 46329, \n\t46330, 46330, 46331, 46332, 46333, 46333, 46334, 46335, \n\t46335, 46336, 46337, 46338, 46338, 46339, 46340, 46340, \n\t46341, 46342, 46342, 46343, 46344, 46345, 46345, 46346, \n\t46347, 46347, 46348, 46349, 46350, 46350, 46351, 46352, \n\t46352, 46353, 46354, 46354, 46355, 46356, 46357, 46357, \n\t46358, 46359, 46359, 46360, 46361, 46362, 46362, 46363, \n\t46364, 46364, 46365, 46366, 46367, 46367, 46368, 46369, \n\t46369, 46370, 46371, 46371, 46372, 46373, 46374, 46374, \n\t46375, 46376, 46376, 46377, 46378, 46379, 46379, 46380, \n\t46381, 46381, 46382, 46383, 46383, 46384, 46385, 46386, \n\t46386, 46387, 46388, 46388, 46389, 46390, 46391, 46391, \n\t46392, 46393, 46393, 46394, 46395, 46395, 46396, 46397, \n\t46398, 46398, 46399, 46400, 46400, 46401, 46402, 46403, \n\t46403, 46404, 46405, 46405, 46406, 46407, 46407, 46408, \n\t46409, 46410, 46410, 46411, 46412, 46412, 46413, 46414, \n\t46415, 46415, 46416, 46417, 46417, 46418, 46419, 46419, \n\t46420, 46421, 46422, 46422, 46423, 46424, 46424, 46425, \n\t46426, 46427, 46427, 46428, 46429, 46429, 46430, 46431, \n\t46431, 46432, 46433, 46434, 46434, 46435, 46436, 46436, \n\t46437, 46438, 46439, 46439, 46440, 46441, 46441, 46442, \n\t46443, 46443, 46444, 46445, 46446, 46446, 46447, 46448, \n\t46448, 46449, 46450, 46451, 46451, 46452, 46453, 46453, \n\t46454, 46455, 46455, 46456, 46457, 46458, 46458, 46459, \n\t46460, 46460, 46461, 46462, 46463, 46463, 46464, 46465, \n\t46465, 46466, 46467, 46467, 46468, 46469, 46470, 46470, \n\t46471, 46472, 46472, 46473, 46474, 46475, 46475, 46476, \n\t46477, 46477, 46478, 46479, 46479, 46480, 46481, 46482, \n\t46482, 46483, 46484, 46484, 46485, 46486, 46486, 46487, \n\t46488, 46489, 46489, 46490, 46491, 46491, 46492, 46493, \n\t46494, 46494, 46495, 46496, 46496, 46497, 46498, 46498, \n\t46499, 46500, 46501, 46501, 46502, 46503, 46503, 46504, \n\t46505, 46506, 46506, 46507, 46508, 46508, 46509, 46510, \n\t46510, 46511, 46512, 46513, 46513, 46514, 46515, 46515, \n\t46516, 46517, 46517, 46518, 46519, 46520, 46520, 46521, \n\t46522, 46522, 46523, 46524, 46525, 46525, 46526, 46527, \n\t46527, 46528, 46529, 46529, 46530, 46531, 46532, 46532, \n\t46533, 46534, 46534, 46535, 46536, 46537, 46537, 46538, \n\t46539, 46539, 46540, 46541, 46541, 46542, 46543, 46544, \n\t46544, 46545, 46546, 46546, 46547, 46548, 46548, 46549, \n\t46550, 46551, 46551, 46552, 46553, 46553, 46554, 46555, \n\t46556, 46556, 46557, 46558, 46558, 46559, 46560, 46560, \n\t46561, 46562, 46563, 46563, 46564, 46565, 46565, 46566, \n\t46567, 46567, 46568, 46569, 46570, 46570, 46571, 46572, \n\t46572, 46573, 46574, 46575, 46575, 46576, 46577, 46577, \n\t46578, 46579, 46579, 46580, 46581, 46582, 46582, 46583, \n\t46584, 46584, 46585, 46586, 46586, 46587, 46588, 46589, \n\t46589, 46590, 46591, 46591, 46592, 46593, 46594, 46594, \n\t46595, 46596, 46596, 46597, 46598, 46598, 46599, 46600, \n\t46601, 46601, 46602, 46603, 46603, 46604, 46605, 46605, \n\t46606, 46607, 46608, 46608, 46609, 46610, 46610, 46611, \n\t46612, 46612, 46613, 46614, 46615, 46615, 46616, 46617, \n\t46617, 46618, 46619, 46620, 46620, 46621, 46622, 46622, \n\t46623, 46624, 46624, 46625, 46626, 46627, 46627, 46628, \n\t46629, 46629, 46630, 46631, 46631, 46632, 46633, 46634, \n\t46634, 46635, 46636, 46636, 46637, 46638, 46638, 46639, \n\t46640, 46641, 46641, 46642, 46643, 46643, 46644, 46645, \n\t46646, 46646, 46647, 46648, 46648, 46649, 46650, 46650, \n\t46651, 46652, 46653, 46653, 46654, 46655, 46655, 46656, \n\t46657, 46657, 46658, 46659, 46660, 46660, 46661, 46662, \n\t46662, 46663, 46664, 46664, 46665, 46666, 46667, 46667, \n\t46668, 46669, 46669, 46670, 46671, 46671, 46672, 46673, \n\t46674, 46674, 46675, 46676, 46676, 46677, 46678, 46679, \n\t46679, 46680, 46681, 46681, 46682, 46683, 46683, 46684, \n\t46685, 46686, 46686, 46687, 46688, 46688, 46689, 46690, \n\t46690, 46691, 46692, 46693, 46693, 46694, 46695, 46695, \n\t46696, 46697, 46697, 46698, 46699, 46700, 46700, 46701, \n\t46702, 46702, 46703, 46704, 46704, 46705, 46706, 46707, \n\t46707, 46708, 46709, 46709, 46710, 46711, 46711, 46712, \n\t46713, 46714, 46714, 46715, 46716, 46716, 46717, 46718, \n\t46719, 46719, 46720, 46721, 46721, 46722, 46723, 46723, \n\t46724, 46725, 46726, 46726, 46727, 46728, 46728, 46729, \n\t46730, 46730, 46731, 46732, 46733, 46733, 46734, 46735, \n\t46735, 46736, 46737, 46737, 46738, 46739, 46740, 46740, \n\t46741, 46742, 46742, 46743, 46744, 46744, 46745, 46746, \n\t46747, 46747, 46748, 46749, 46749, 46750, 46751, 46751, \n\t46752, 46753, 46754, 46754, 46755, 46756, 46756, 46757, \n\t46758, 46758, 46759, 46760, 46761, 46761, 46762, 46763, \n\t46763, 46764, 46765, 46765, 46766, 46767, 46768, 46768, \n\t46769, 46770, 46770, 46771, 46772, 46772, 46773, 46774, \n\t46775, 46775, 46776, 46777, 46777, 46778, 46779, 46779, \n\t46780, 46781, 46782, 46782, 46783, 46784, 46784, 46785, \n\t46786, 46786, 46787, 46788, 46789, 46789, 46790, 46791, \n\t46791, 46792, 46793, 46793, 46794, 46795, 46796, 46796, \n\t46797, 46798, 46798, 46799, 46800, 46800, 46801, 46802, \n\t46803, 46803, 46804, 46805, 46805, 46806, 46807, 46807, \n\t46808, 46809, 46810, 46810, 46811, 46812, 46812, 46813, \n\t46814, 46814, 46815, 46816, 46817, 46817, 46818, 46819, \n\t46819, 46820, 46821, 46821, 46822, 46823, 46824, 46824, \n\t46825, 46826, 46826, 46827, 46828, 46828, 46829, 46830, \n\t46831, 46831, 46832, 46833, 46833, 46834, 46835, 46835, \n\t46836, 46837, 46838, 46838, 46839, 46840, 46840, 46841, \n\t46842, 46842, 46843, 46844, 46845, 46845, 46846, 46847, \n\t46847, 46848, 46849, 46849, 46850, 46851, 46852, 46852, \n\t46853, 46854, 46854, 46855, 46856, 46856, 46857, 46858, \n\t46859, 46859, 46860, 46861, 46861, 46862, 46863, 46863, \n\t46864, 46865, 46866, 46866, 46867, 46868, 46868, 46869, \n\t46870, 46870, 46871, 46872, 46873, 46873, 46874, 46875, \n\t46875, 46876, 46877, 46877, 46878, 46879, 46880, 46880, \n\t46881, 46882, 46882, 46883, 46884, 46884, 46885, 46886, \n\t46887, 46887, 46888, 46889, 46889, 46890, 46891, 46891, \n\t46892, 46893, 46893, 46894, 46895, 46896, 46896, 46897, \n\t46898, 46898, 46899, 46900, 46900, 46901, 46902, 46903, \n\t46903, 46904, 46905, 46905, 46906, 46907, 46907, 46908, \n\t46909, 46910, 46910, 46911, 46912, 46912, 46913, 46914, \n\t46914, 46915, 46916, 46917, 46917, 46918, 46919, 46919, \n\t46920, 46921, 46921, 46922, 46923, 46924, 46924, 46925, \n\t46926, 46926, 46927, 46928, 46928, 46929, 46930, 46931, \n\t46931, 46932, 46933, 46933, 46934, 46935, 46935, 46936, \n\t46937, 46937, 46938, 46939, 46940, 46940, 46941, 46942, \n\t46942, 46943, 46944, 46944, 46945, 46946, 46947, 46947, \n\t46948, 46949, 46949, 46950, 46951, 46951, 46952, 46953, \n\t46954, 46954, 46955, 46956, 46956, 46957, 46958, 46958, \n\t46959, 46960, 46961, 46961, 46962, 46963, 46963, 46964, \n\t46965, 46965, 46966, 46967, 46967, 46968, 46969, 46970, \n\t46970, 46971, 46972, 46972, 46973, 46974, 46974, 46975, \n\t46976, 46977, 46977, 46978, 46979, 46979, 46980, 46981, \n\t46981, 46982, 46983, 46984, 46984, 46985, 46986, 46986, \n\t46987, 46988, 46988, 46989, 46990, 46990, 46991, 46992, \n\t46993, 46993, 46994, 46995, 46995, 46996, 46997, 46997, \n\t46998, 46999, 47000, 47000, 47001, 47002, 47002, 47003, \n\t47004, 47004, 47005, 47006, 47007, 47007, 47008, 47009, \n\t47009, 47010, 47011, 47011, 47012, 47013, 47013, 47014, \n\t47015, 47016, 47016, 47017, 47018, 47018, 47019, 47020, \n\t47020, 47021, 47022, 47023, 47023, 47024, 47025, 47025, \n\t47026, 47027, 47027, 47028, 47029, 47030, 47030, 47031, \n\t47032, 47032, 47033, 47034, 47034, 47035, 47036, 47036, \n\t47037, 47038, 47039, 47039, 47040, 47041, 47041, 47042, \n\t47043, 47043, 47044, 47045, 47046, 47046, 47047, 47048, \n\t47048, 47049, 47050, 47050, 47051, 47052, 47052, 47053, \n\t47054, 47055, 47055, 47056, 47057, 47057, 47058, 47059, \n\t47059, 47060, 47061, 47062, 47062, 47063, 47064, 47064, \n\t47065, 47066, 47066, 47067, 47068, 47068, 47069, 47070, \n\t47071, 47071, 47072, 47073, 47073, 47074, 47075, 47075, \n\t47076, 47077, 47078, 47078, 47079, 47080, 47080, 47081, \n\t47082, 47082, 47083, 47084, 47084, 47085, 47086, 47087, \n\t47087, 47088, 47089, 47089, 47090, 47091, 47091, 47092, \n\t47093, 47094, 47094, 47095, 47096, 47096, 47097, 47098, \n\t47098, 47099, 47100, 47100, 47101, 47102, 47103, 47103, \n\t47104, 47105, 47105, 47106, 47107, 47107, 47108, 47109, \n\t47110, 47110, 47111, 47112, 47112, 47113, 47114, 47114, \n\t47115, 47116, 47116, 47117, 47118, 47119, 47119, 47120, \n\t47121, 47121, 47122, 47123, 47123, 47124, 47125, 47126, \n\t47126, 47127, 47128, 47128, 47129, 47130, 47130, 47131, \n\t47132, 47132, 47133, 47134, 47135, 47135, 47136, 47137, \n\t47137, 47138, 47139, 47139, 47140, 47141, 47141, 47142, \n\t47143, 47144, 47144, 47145, 47146, 47146, 47147, 47148, \n\t47148, 47149, 47150, 47151, 47151, 47152, 47153, 47153, \n\t47154, 47155, 47155, 47156, 47157, 47157, 47158, 47159, \n\t47160, 47160, 47161, 47162, 47162, 47163, 47164, 47164, \n\t47165, 47166, 47166, 47167, 47168, 47169, 47169, 47170, \n\t47171, 47171, 47172, 47173, 47173, 47174, 47175, 47176, \n\t47176, 47177, 47178, 47178, 47179, 47180, 47180, 47181, \n\t47182, 47182, 47183, 47184, 47185, 47185, 47186, 47187, \n\t47187, 47188, 47189, 47189, 47190, 47191, 47191, 47192, \n\t47193, 47194, 47194, 47195, 47196, 47196, 47197, 47198, \n\t47198, 47199, 47200, 47200, 47201, 47202, 47203, 47203, \n\t47204, 47205, 47205, 47206, 47207, 47207, 47208, 47209, \n\t47210, 47210, 47211, 47212, 47212, 47213, 47214, 47214, \n\t47215, 47216, 47216, 47217, 47218, 47219, 47219, 47220, \n\t47221, 47221, 47222, 47223, 47223, 47224, 47225, 47225, \n\t47226, 47227, 47228, 47228, 47229, 47230, 47230, 47231, \n\t47232, 47232, 47233, 47234, 47234, 47235, 47236, 47237, \n\t47237, 47238, 47239, 47239, 47240, 47241, 47241, 47242, \n\t47243, 47243, 47244, 47245, 47246, 47246, 47247, 47248, \n\t47248, 47249, 47250, 47250, 47251, 47252, 47252, 47253, \n\t47254, 47255, 47255, 47256, 47257, 47257, 47258, 47259, \n\t47259, 47260, 47261, 47262, 47262, 47263, 47264, 47264, \n\t47265, 47266, 47266, 47267, 47268, 47268, 47269, 47270, \n\t47271, 47271, 47272, 47273, 47273, 47274, 47275, 47275, \n\t47276, 47277, 47277, 47278, 47279, 47280, 47280, 47281, \n\t47282, 47282, 47283, 47284, 47284, 47285, 47286, 47286, \n\t47287, 47288, 47289, 47289, 47290, 47291, 47291, 47292, \n\t47293, 47293, 47294, 47295, 47295, 47296, 47297, 47298, \n\t47298, 47299, 47300, 47300, 47301, 47302, 47302, 47303, \n\t47304, 47304, 47305, 47306, 47307, 47307, 47308, 47309, \n\t47309, 47310, 47311, 47311, 47312, 47313, 47313, 47314, \n\t47315, 47316, 47316, 47317, 47318, 47318, 47319, 47320, \n\t47320, 47321, 47322, 47322, 47323, 47324, 47325, 47325, \n\t47326, 47327, 47327, 47328, 47329, 47329, 47330, 47331, \n\t47331, 47332, 47333, 47333, 47334, 47335, 47336, 47336, \n\t47337, 47338, 47338, 47339, 47340, 47340, 47341, 47342, \n\t47342, 47343, 47344, 47345, 47345, 47346, 47347, 47347, \n\t47348, 47349, 47349, 47350, 47351, 47351, 47352, 47353, \n\t47354, 47354, 47355, 47356, 47356, 47357, 47358, 47358, \n\t47359, 47360, 47360, 47361, 47362, 47363, 47363, 47364, \n\t47365, 47365, 47366, 47367, 47367, 47368, 47369, 47369, \n\t47370, 47371, 47372, 47372, 47373, 47374, 47374, 47375, \n\t47376, 47376, 47377, 47378, 47378, 47379, 47380, 47381, \n\t47381, 47382, 47383, 47383, 47384, 47385, 47385, 47386, \n\t47387, 47387, 47388, 47389, 47389, 47390, 47391, 47392, \n\t47392, 47393, 47394, 47394, 47395, 47396, 47396, 47397, \n\t47398, 47398, 47399, 47400, 47401, 47401, 47402, 47403, \n\t47403, 47404, 47405, 47405, 47406, 47407, 47407, 47408, \n\t47409, 47410, 47410, 47411, 47412, 47412, 47413, 47414, \n\t47414, 47415, 47416, 47416, 47417, 47418, 47418, 47419, \n\t47420, 47421, 47421, 47422, 47423, 47423, 47424, 47425, \n\t47425, 47426, 47427, 47427, 47428, 47429, 47430, 47430, \n\t47431, 47432, 47432, 47433, 47434, 47434, 47435, 47436, \n\t47436, 47437, 47438, 47438, 47439, 47440, 47441, 47441, \n\t47442, 47443, 47443, 47444, 47445, 47445, 47446, 47447, \n\t47447, 47448, 47449, 47450, 47450, 47451, 47452, 47452, \n\t47453, 47454, 47454, 47455, 47456, 47456, 47457, 47458, \n\t47458, 47459, 47460, 47461, 47461, 47462, 47463, 47463, \n\t47464, 47465, 47465, 47466, 47467, 47467, 47468, 47469, \n\t47470, 47470, 47471, 47472, 47472, 47473, 47474, 47474, \n\t47475, 47476, 47476, 47477, 47478, 47478, 47479, 47480, \n\t47481, 47481, 47482, 47483, 47483, 47484, 47485, 47485, \n\t47486, 47487, 47487, 47488, 47489, 47490, 47490, 47491, \n\t47492, 47492, 47493, 47494, 47494, 47495, 47496, 47496, \n\t47497, 47498, 47498, 47499, 47500, 47501, 47501, 47502, \n\t47503, 47503, 47504, 47505, 47505, 47506, 47507, 47507, \n\t47508, 47509, 47510, 47510, 47511, 47512, 47512, 47513, \n\t47514, 47514, 47515, 47516, 47516, 47517, 47518, 47518, \n\t47519, 47520, 47521, 47521, 47522, 47523, 47523, 47524, \n\t47525, 47525, 47526, 47527, 47527, 47528, 47529, 47529, \n\t47530, 47531, 47532, 47532, 47533, 47534, 47534, 47535, \n\t47536, 47536, 47537, 47538, 47538, 47539, 47540, 47540, \n\t47541, 47542, 47543, 47543, 47544, 47545, 47545, 47546, \n\t47547, 47547, 47548, 47549, 47549, 47550, 47551, 47551, \n\t47552, 47553, 47554, 47554, 47555, 47556, 47556, 47557, \n\t47558, 47558, 47559, 47560, 47560, 47561, 47562, 47563, \n\t47563, 47564, 47565, 47565, 47566, 47567, 47567, 47568, \n\t47569, 47569, 47570, 47571, 47571, 47572, 47573, 47574, \n\t47574, 47575, 47576, 47576, 47577, 47578, 47578, 47579, \n\t47580, 47580, 47581, 47582, 47582, 47583, 47584, 47585, \n\t47585, 47586, 47587, 47587, 47588, 47589, 47589, 47590, \n\t47591, 47591, 47592, 47593, 47593, 47594, 47595, 47596, \n\t47596, 47597, 47598, 47598, 47599, 47600, 47600, 47601, \n\t47602, 47602, 47603, 47604, 47604, 47605, 47606, 47607, \n\t47607, 47608, 47609, 47609, 47610, 47611, 47611, 47612, \n\t47613, 47613, 47614, 47615, 47615, 47616, 47617, 47618, \n\t47618, 47619, 47620, 47620, 47621, 47622, 47622, 47623, \n\t47624, 47624, 47625, 47626, 47626, 47627, 47628, 47629, \n\t47629, 47630, 47631, 47631, 47632, 47633, 47633, 47634, \n\t47635, 47635, 47636, 47637, 47637, 47638, 47639, 47639, \n\t47640, 47641, 47642, 47642, 47643, 47644, 47644, 47645, \n\t47646, 47646, 47647, 47648, 47648, 47649, 47650, 47650, \n\t47651, 47652, 47653, 47653, 47654, 47655, 47655, 47656, \n\t47657, 47657, 47658, 47659, 47659, 47660, 47661, 47661, \n\t47662, 47663, 47664, 47664, 47665, 47666, 47666, 47667, \n\t47668, 47668, 47669, 47670, 47670, 47671, 47672, 47672, \n\t47673, 47674, 47674, 47675, 47676, 47677, 47677, 47678, \n\t47679, 47679, 47680, 47681, 47681, 47682, 47683, 47683, \n\t47684, 47685, 47685, 47686, 47687, 47688, 47688, 47689, \n\t47690, 47690, 47691, 47692, 47692, 47693, 47694, 47694, \n\t47695, 47696, 47696, 47697, 47698, 47699, 47699, 47700, \n\t47701, 47701, 47702, 47703, 47703, 47704, 47705, 47705, \n\t47706, 47707, 47707, 47708, 47709, 47709, 47710, 47711, \n\t47712, 47712, 47713, 47714, 47714, 47715, 47716, 47716, \n\t47717, 47718, 47718, 47719, 47720, 47720, 47721, 47722, \n\t47723, 47723, 47724, 47725, 47725, 47726, 47727, 47727, \n\t47728, 47729, 47729, 47730, 47731, 47731, 47732, 47733, \n\t47733, 47734, 47735, 47736, 47736, 47737, 47738, 47738, \n\t47739, 47740, 47740, 47741, 47742, 47742, 47743, 47744, \n\t47744, 47745, 47746, 47746, 47747, 47748, 47749, 47749, \n\t47750, 47751, 47751, 47752, 47753, 47753, 47754, 47755, \n\t47755, 47756, 47757, 47757, 47758, 47759, 47759, 47760, \n\t47761, 47762, 47762, 47763, 47764, 47764, 47765, 47766, \n\t47766, 47767, 47768, 47768, 47769, 47770, 47770, 47771, \n\t47772, 47773, 47773, 47774, 47775, 47775, 47776, 47777, \n\t47777, 47778, 47779, 47779, 47780, 47781, 47781, 47782, \n\t47783, 47783, 47784, 47785, 47786, 47786, 47787, 47788, \n\t47788, 47789, 47790, 47790, 47791, 47792, 47792, 47793, \n\t47794, 47794, 47795, 47796, 47796, 47797, 47798, 47799, \n\t47799, 47800, 47801, 47801, 47802, 47803, 47803, 47804, \n\t47805, 47805, 47806, 47807, 47807, 47808, 47809, 47809, \n\t47810, 47811, 47812, 47812, 47813, 47814, 47814, 47815, \n\t47816, 47816, 47817, 47818, 47818, 47819, 47820, 47820, \n\t47821, 47822, 47822, 47823, 47824, 47824, 47825, 47826, \n\t47827, 47827, 47828, 47829, 47829, 47830, 47831, 47831, \n\t47832, 47833, 47833, 47834, 47835, 47835, 47836, 47837, \n\t47837, 47838, 47839, 47840, 47840, 47841, 47842, 47842, \n\t47843, 47844, 47844, 47845, 47846, 47846, 47847, 47848, \n\t47848, 47849, 47850, 47850, 47851, 47852, 47853, 47853, \n\t47854, 47855, 47855, 47856, 47857, 47857, 47858, 47859, \n\t47859, 47860, 47861, 47861, 47862, 47863, 47863, 47864, \n\t47865, 47866, 47866, 47867, 47868, 47868, 47869, 47870, \n\t47870, 47871, 47872, 47872, 47873, 47874, 47874, 47875, \n\t47876, 47876, 47877, 47878, 47878, 47879, 47880, 47881, \n\t47881, 47882, 47883, 47883, 47884, 47885, 47885, 47886, \n\t47887, 47887, 47888, 47889, 47889, 47890, 47891, 47891, \n\t47892, 47893, 47893, 47894, 47895, 47896, 47896, 47897, \n\t47898, 47898, 47899, 47900, 47900, 47901, 47902, 47902, \n\t47903, 47904, 47904, 47905, 47906, 47906, 47907, 47908, \n\t47909, 47909, 47910, 47911, 47911, 47912, 47913, 47913, \n\t47914, 47915, 47915, 47916, 47917, 47917, 47918, 47919, \n\t47919, 47920, 47921, 47921, 47922, 47923, 47924, 47924, \n\t47925, 47926, 47926, 47927, 47928, 47928, 47929, 47930, \n\t47930, 47931, 47932, 47932, 47933, 47934, 47934, 47935, \n\t47936, 47936, 47937, 47938, 47939, 47939, 47940, 47941, \n\t47941, 47942, 47943, 47943, 47944, 47945, 47945, 47946, \n\t47947, 47947, 47948, 47949, 47949, 47950, 47951, 47951, \n\t47952, 47953, 47954, 47954, 47955, 47956, 47956, 47957, \n\t47958, 47958, 47959, 47960, 47960, 47961, 47962, 47962, \n\t47963, 47964, 47964, 47965, 47966, 47966, 47967, 47968, \n\t47969, 47969, 47970, 47971, 47971, 47972, 47973, 47973, \n\t47974, 47975, 47975, 47976, 47977, 47977, 47978, 47979, \n\t47979, 47980, 47981, 47981, 47982, 47983, 47984, 47984, \n\t47985, 47986, 47986, 47987, 47988, 47988, 47989, 47990, \n\t47990, 47991, 47992, 47992, 47993, 47994, 47994, 47995, \n\t47996, 47996, 47997, 47998, 47998, 47999, 48000, 48001, \n\t48001, 48002, 48003, 48003, 48004, 48005, 48005, 48006, \n\t48007, 48007, 48008, 48009, 48009, 48010, 48011, 48011, \n\t48012, 48013, 48013, 48014, 48015, 48016, 48016, 48017, \n\t48018, 48018, 48019, 48020, 48020, 48021, 48022, 48022, \n\t48023, 48024, 48024, 48025, 48026, 48026, 48027, 48028, \n\t48028, 48029, 48030, 48030, 48031, 48032, 48033, 48033, \n\t48034, 48035, 48035, 48036, 48037, 48037, 48038, 48039, \n\t48039, 48040, 48041, 48041, 48042, 48043, 48043, 48044, \n\t48045, 48045, 48046, 48047, 48047, 48048, 48049, 48050, \n\t48050, 48051, 48052, 48052, 48053, 48054, 48054, 48055, \n\t48056, 48056, 48057, 48058, 48058, 48059, 48060, 48060, \n\t48061, 48062, 48062, 48063, 48064, 48064, 48065, 48066, \n\t48067, 48067, 48068, 48069, 48069, 48070, 48071, 48071, \n\t48072, 48073, 48073, 48074, 48075, 48075, 48076, 48077, \n\t48077, 48078, 48079, 48079, 48080, 48081, 48081, 48082, \n\t48083, 48084, 48084, 48085, 48086, 48086, 48087, 48088, \n\t48088, 48089, 48090, 48090, 48091, 48092, 48092, 48093, \n\t48094, 48094, 48095, 48096, 48096, 48097, 48098, 48098, \n\t48099, 48100, 48100, 48101, 48102, 48103, 48103, 48104, \n\t48105, 48105, 48106, 48107, 48107, 48108, 48109, 48109, \n\t48110, 48111, 48111, 48112, 48113, 48113, 48114, 48115, \n\t48115, 48116, 48117, 48117, 48118, 48119, 48120, 48120, \n\t48121, 48122, 48122, 48123, 48124, 48124, 48125, 48126, \n\t48126, 48127, 48128, 48128, 48129, 48130, 48130, 48131, \n\t48132, 48132, 48133, 48134, 48134, 48135, 48136, 48136, \n\t48137, 48138, 48139, 48139, 48140, 48141, 48141, 48142, \n\t48143, 48143, 48144, 48145, 48145, 48146, 48147, 48147, \n\t48148, 48149, 48149, 48150, 48151, 48151, 48152, 48153, \n\t48153, 48154, 48155, 48155, 48156, 48157, 48158, 48158, \n\t48159, 48160, 48160, 48161, 48162, 48162, 48163, 48164, \n\t48164, 48165, 48166, 48166, 48167, 48168, 48168, 48169, \n\t48170, 48170, 48171, 48172, 48172, 48173, 48174, 48174, \n\t48175, 48176, 48176, 48177, 48178, 48179, 48179, 48180, \n\t48181, 48181, 48182, 48183, 48183, 48184, 48185, 48185, \n\t48186, 48187, 48187, 48188, 48189, 48189, 48190, 48191, \n\t48191, 48192, 48193, 48193, 48194, 48195, 48195, 48196, \n\t48197, 48198, 48198, 48199, 48200, 48200, 48201, 48202, \n\t48202, 48203, 48204, 48204, 48205, 48206, 48206, 48207, \n\t48208, 48208, 48209, 48210, 48210, 48211, 48212, 48212, \n\t48213, 48214, 48214, 48215, 48216, 48216, 48217, 48218, \n\t48219, 48219, 48220, 48221, 48221, 48222, 48223, 48223, \n\t48224, 48225, 48225, 48226, 48227, 48227, 48228, 48229, \n\t48229, 48230, 48231, 48231, 48232, 48233, 48233, 48234, \n\t48235, 48235, 48236, 48237, 48237, 48238, 48239, 48239, \n\t48240, 48241, 48242, 48242, 48243, 48244, 48244, 48245, \n\t48246, 48246, 48247, 48248, 48248, 48249, 48250, 48250, \n\t48251, 48252, 48252, 48253, 48254, 48254, 48255, 48256, \n\t48256, 48257, 48258, 48258, 48259, 48260, 48260, 48261, \n\t48262, 48262, 48263, 48264, 48265, 48265, 48266, 48267, \n\t48267, 48268, 48269, 48269, 48270, 48271, 48271, 48272, \n\t48273, 48273, 48274, 48275, 48275, 48276, 48277, 48277, \n\t48278, 48279, 48279, 48280, 48281, 48281, 48282, 48283, \n\t48283, 48284, 48285, 48285, 48286, 48287, 48288, 48288, \n\t48289, 48290, 48290, 48291, 48292, 48292, 48293, 48294, \n\t48294, 48295, 48296, 48296, 48297, 48298, 48298, 48299, \n\t48300, 48300, 48301, 48302, 48302, 48303, 48304, 48304, \n\t48305, 48306, 48306, 48307, 48308, 48308, 48309, 48310, \n\t48311, 48311, 48312, 48313, 48313, 48314, 48315, 48315, \n\t48316, 48317, 48317, 48318, 48319, 48319, 48320, 48321, \n\t48321, 48322, 48323, 48323, 48324, 48325, 48325, 48326, \n\t48327, 48327, 48328, 48329, 48329, 48330, 48331, 48331, \n\t48332, 48333, 48333, 48334, 48335, 48335, 48336, 48337, \n\t48338, 48338, 48339, 48340, 48340, 48341, 48342, 48342, \n\t48343, 48344, 48344, 48345, 48346, 48346, 48347, 48348, \n\t48348, 48349, 48350, 48350, 48351, 48352, 48352, 48353, \n\t48354, 48354, 48355, 48356, 48356, 48357, 48358, 48358, \n\t48359, 48360, 48360, 48361, 48362, 48363, 48363, 48364, \n\t48365, 48365, 48366, 48367, 48367, 48368, 48369, 48369, \n\t48370, 48371, 48371, 48372, 48373, 48373, 48374, 48375, \n\t48375, 48376, 48377, 48377, 48378, 48379, 48379, 48380, \n\t48381, 48381, 48382, 48383, 48383, 48384, 48385, 48385, \n\t48386, 48387, 48387, 48388, 48389, 48389, 48390, 48391, \n\t48392, 48392, 48393, 48394, 48394, 48395, 48396, 48396, \n\t48397, 48398, 48398, 48399, 48400, 48400, 48401, 48402, \n\t48402, 48403, 48404, 48404, 48405, 48406, 48406, 48407, \n\t48408, 48408, 48409, 48410, 48410, 48411, 48412, 48412, \n\t48413, 48414, 48414, 48415, 48416, 48416, 48417, 48418, \n\t48418, 48419, 48420, 48420, 48421, 48422, 48423, 48423, \n\t48424, 48425, 48425, 48426, 48427, 48427, 48428, 48429, \n\t48429, 48430, 48431, 48431, 48432, 48433, 48433, 48434, \n\t48435, 48435, 48436, 48437, 48437, 48438, 48439, 48439, \n\t48440, 48441, 48441, 48442, 48443, 48443, 48444, 48445, \n\t48445, 48446, 48447, 48447, 48448, 48449, 48449, 48450, \n\t48451, 48451, 48452, 48453, 48454, 48454, 48455, 48456, \n\t48456, 48457, 48458, 48458, 48459, 48460, 48460, 48461, \n\t48462, 48462, 48463, 48464, 48464, 48465, 48466, 48466, \n\t48467, 48468, 48468, 48469, 48470, 48470, 48471, 48472, \n\t48472, 48473, 48474, 48474, 48475, 48476, 48476, 48477, \n\t48478, 48478, 48479, 48480, 48480, 48481, 48482, 48482, \n\t48483, 48484, 48484, 48485, 48486, 48486, 48487, 48488, \n\t48489, 48489, 48490, 48491, 48491, 48492, 48493, 48493, \n\t48494, 48495, 48495, 48496, 48497, 48497, 48498, 48499, \n\t48499, 48500, 48501, 48501, 48502, 48503, 48503, 48504, \n\t48505, 48505, 48506, 48507, 48507, 48508, 48509, 48509, \n\t48510, 48511, 48511, 48512, 48513, 48513, 48514, 48515, \n\t48515, 48516, 48517, 48517, 48518, 48519, 48519, 48520, \n\t48521, 48521, 48522, 48523, 48523, 48524, 48525, 48525, \n\t48526, 48527, 48528, 48528, 48529, 48530, 48530, 48531, \n\t48532, 48532, 48533, 48534, 48534, 48535, 48536, 48536, \n\t48537, 48538, 48538, 48539, 48540, 48540, 48541, 48542, \n\t48542, 48543, 48544, 48544, 48545, 48546, 48546, 48547, \n\t48548, 48548, 48549, 48550, 48550, 48551, 48552, 48552, \n\t48553, 48554, 48554, 48555, 48556, 48556, 48557, 48558, \n\t48558, 48559, 48560, 48560, 48561, 48562, 48562, 48563, \n\t48564, 48564, 48565, 48566, 48566, 48567, 48568, 48568, \n\t48569, 48570, 48570, 48571, 48572, 48573, 48573, 48574, \n\t48575, 48575, 48576, 48577, 48577, 48578, 48579, 48579, \n\t48580, 48581, 48581, 48582, 48583, 48583, 48584, 48585, \n\t48585, 48586, 48587, 48587, 48588, 48589, 48589, 48590, \n\t48591, 48591, 48592, 48593, 48593, 48594, 48595, 48595, \n\t48596, 48597, 48597, 48598, 48599, 48599, 48600, 48601, \n\t48601, 48602, 48603, 48603, 48604, 48605, 48605, 48606, \n\t48607, 48607, 48608, 48609, 48609, 48610, 48611, 48611, \n\t48612, 48613, 48613, 48614, 48615, 48615, 48616, 48617, \n\t48617, 48618, 48619, 48619, 48620, 48621, 48621, 48622, \n\t48623, 48623, 48624, 48625, 48626, 48626, 48627, 48628, \n\t48628, 48629, 48630, 48630, 48631, 48632, 48632, 48633, \n\t48634, 48634, 48635, 48636, 48636, 48637, 48638, 48638, \n\t48639, 48640, 48640, 48641, 48642, 48642, 48643, 48644, \n\t48644, 48645, 48646, 48646, 48647, 48648, 48648, 48649, \n\t48650, 48650, 48651, 48652, 48652, 48653, 48654, 48654, \n\t48655, 48656, 48656, 48657, 48658, 48658, 48659, 48660, \n\t48660, 48661, 48662, 48662, 48663, 48664, 48664, 48665, \n\t48666, 48666, 48667, 48668, 48668, 48669, 48670, 48670, \n\t48671, 48672, 48672, 48673, 48674, 48674, 48675, 48676, \n\t48676, 48677, 48678, 48678, 48679, 48680, 48680, 48681, \n\t48682, 48682, 48683, 48684, 48684, 48685, 48686, 48686, \n\t48687, 48688, 48688, 48689, 48690, 48690, 48691, 48692, \n\t48692, 48693, 48694, 48695, 48695, 48696, 48697, 48697, \n\t48698, 48699, 48699, 48700, 48701, 48701, 48702, 48703, \n\t48703, 48704, 48705, 48705, 48706, 48707, 48707, 48708, \n\t48709, 48709, 48710, 48711, 48711, 48712, 48713, 48713, \n\t48714, 48715, 48715, 48716, 48717, 48717, 48718, 48719, \n\t48719, 48720, 48721, 48721, 48722, 48723, 48723, 48724, \n\t48725, 48725, 48726, 48727, 48727, 48728, 48729, 48729, \n\t48730, 48731, 48731, 48732, 48733, 48733, 48734, 48735, \n\t48735, 48736, 48737, 48737, 48738, 48739, 48739, 48740, \n\t48741, 48741, 48742, 48743, 48743, 48744, 48745, 48745, \n\t48746, 48747, 48747, 48748, 48749, 48749, 48750, 48751, \n\t48751, 48752, 48753, 48753, 48754, 48755, 48755, 48756, \n\t48757, 48757, 48758, 48759, 48759, 48760, 48761, 48761, \n\t48762, 48763, 48763, 48764, 48765, 48765, 48766, 48767, \n\t48767, 48768, 48769, 48769, 48770, 48771, 48771, 48772, \n\t48773, 48773, 48774, 48775, 48775, 48776, 48777, 48777, \n\t48778, 48779, 48779, 48780, 48781, 48781, 48782, 48783, \n\t48783, 48784, 48785, 48785, 48786, 48787, 48787, 48788, \n\t48789, 48789, 48790, 48791, 48791, 48792, 48793, 48793, \n\t48794, 48795, 48795, 48796, 48797, 48797, 48798, 48799, \n\t48799, 48800, 48801, 48801, 48802, 48803, 48803, 48804, \n\t48805, 48805, 48806, 48807, 48807, 48808, 48809, 48809, \n\t48810, 48811, 48811, 48812, 48813, 48813, 48814, 48815, \n\t48815, 48816, 48817, 48817, 48818, 48819, 48819, 48820, \n\t48821, 48821, 48822, 48823, 48823, 48824, 48825, 48825, \n\t48826, 48827, 48827, 48828, 48829, 48829, 48830, 48831, \n\t48831, 48832, 48833, 48833, 48834, 48835, 48835, 48836, \n\t48837, 48837, 48838, 48839, 48839, 48840, 48841, 48841, \n\t48842, 48843, 48843, 48844, 48845, 48845, 48846, 48847, \n\t48847, 48848, 48849, 48849, 48850, 48851, 48851, 48852, \n\t48853, 48853, 48854, 48855, 48855, 48856, 48857, 48857, \n\t48858, 48859, 48859, 48860, 48861, 48861, 48862, 48863, \n\t48863, 48864, 48865, 48865, 48866, 48867, 48867, 48868, \n\t48869, 48869, 48870, 48871, 48871, 48872, 48873, 48873, \n\t48874, 48875, 48875, 48876, 48877, 48877, 48878, 48879, \n\t48879, 48880, 48881, 48881, 48882, 48883, 48883, 48884, \n\t48885, 48885, 48886, 48887, 48887, 48888, 48889, 48889, \n\t48890, 48891, 48891, 48892, 48893, 48893, 48894, 48895, \n\t48895, 48896, 48897, 48897, 48898, 48899, 48899, 48900, \n\t48901, 48901, 48902, 48903, 48903, 48904, 48905, 48905, \n\t48906, 48907, 48907, 48908, 48909, 48909, 48910, 48911, \n\t48911, 48912, 48913, 48913, 48914, 48915, 48915, 48916, \n\t48917, 48917, 48918, 48919, 48919, 48920, 48921, 48921, \n\t48922, 48923, 48923, 48924, 48925, 48925, 48926, 48927, \n\t48927, 48928, 48929, 48929, 48930, 48931, 48931, 48932, \n\t48933, 48933, 48934, 48935, 48935, 48936, 48937, 48937, \n\t48938, 48939, 48939, 48940, 48941, 48941, 48942, 48943, \n\t48943, 48944, 48945, 48945, 48946, 48947, 48947, 48948, \n\t48949, 48949, 48950, 48951, 48951, 48952, 48953, 48953, \n\t48954, 48955, 48955, 48956, 48957, 48957, 48958, 48959, \n\t48959, 48960, 48961, 48961, 48962, 48963, 48963, 48964, \n\t48965, 48965, 48966, 48967, 48967, 48968, 48969, 48969, \n\t48970, 48971, 48971, 48972, 48973, 48973, 48974, 48975, \n\t48975, 48976, 48977, 48977, 48978, 48979, 48979, 48980, \n\t48981, 48981, 48982, 48983, 48983, 48984, 48985, 48985, \n\t48986, 48987, 48987, 48988, 48989, 48989, 48990, 48991, \n\t48991, 48992, 48993, 48993, 48994, 48995, 48995, 48996, \n\t48997, 48997, 48998, 48999, 48999, 49000, 49000, 49001, \n\t49002, 49002, 49003, 49004, 49004, 49005, 49006, 49006, \n\t49007, 49008, 49008, 49009, 49010, 49010, 49011, 49012, \n\t49012, 49013, 49014, 49014, 49015, 49016, 49016, 49017, \n\t49018, 49018, 49019, 49020, 49020, 49021, 49022, 49022, \n\t49023, 49024, 49024, 49025, 49026, 49026, 49027, 49028, \n\t49028, 49029, 49030, 49030, 49031, 49032, 49032, 49033, \n\t49034, 49034, 49035, 49036, 49036, 49037, 49038, 49038, \n\t49039, 49040, 49040, 49041, 49042, 49042, 49043, 49044, \n\t49044, 49045, 49046, 49046, 49047, 49048, 49048, 49049, \n\t49050, 49050, 49051, 49052, 49052, 49053, 49054, 49054, \n\t49055, 49056, 49056, 49057, 49058, 49058, 49059, 49060, \n\t49060, 49061, 49062, 49062, 49063, 49064, 49064, 49065, \n\t49066, 49066, 49067, 49068, 49068, 49069, 49069, 49070, \n\t49071, 49071, 49072, 49073, 49073, 49074, 49075, 49075, \n\t49076, 49077, 49077, 49078, 49079, 49079, 49080, 49081, \n\t49081, 49082, 49083, 49083, 49084, 49085, 49085, 49086, \n\t49087, 49087, 49088, 49089, 49089, 49090, 49091, 49091, \n\t49092, 49093, 49093, 49094, 49095, 49095, 49096, 49097, \n\t49097, 49098, 49099, 49099, 49100, 49101, 49101, 49102, \n\t49103, 49103, 49104, 49105, 49105, 49106, 49107, 49107, \n\t49108, 49109, 49109, 49110, 49111, 49111, 49112, 49113, \n\t49113, 49114, 49115, 49115, 49116, 49117, 49117, 49118, \n\t49119, 49119, 49120, 49121, 49121, 49122, 49122, 49123, \n\t49124, 49124, 49125, 49126, 49126, 49127, 49128, 49128, \n\t49129, 49130, 49130, 49131, 49132, 49132, 49133, 49134, \n\t49134, 49135, 49136, 49136, 49137, 49138, 49138, 49139, \n\t49140, 49140, 49141, 49142, 49142, 49143, 49144, 49144, \n\t49145, 49146, 49146, 49147, 49148, 49148, 49149, 49150, \n\t49150, 49151, 49152, 49152, 49153, 49154, 49154, 49155, \n\t49156, 49156, 49157, 49158, 49158, 49159, 49160, 49160, \n\t49161, 49162, 49162, 49163, 49164, 49164, 49165, 49165, \n\t49166, 49167, 49167, 49168, 49169, 49169, 49170, 49171, \n\t49171, 49172, 49173, 49173, 49174, 49175, 49175, 49176, \n\t49177, 49177, 49178, 49179, 49179, 49180, 49181, 49181, \n\t49182, 49183, 49183, 49184, 49185, 49185, 49186, 49187, \n\t49187, 49188, 49189, 49189, 49190, 49191, 49191, 49192, \n\t49193, 49193, 49194, 49195, 49195, 49196, 49197, 49197, \n\t49198, 49199, 49199, 49200, 49201, 49201, 49202, 49203, \n\t49203, 49204, 49204, 49205, 49206, 49206, 49207, 49208, \n\t49208, 49209, 49210, 49210, 49211, 49212, 49212, 49213, \n\t49214, 49214, 49215, 49216, 49216, 49217, 49218, 49218, \n\t49219, 49220, 49220, 49221, 49222, 49222, 49223, 49224, \n\t49224, 49225, 49226, 49226, 49227, 49228, 49228, 49229, \n\t49230, 49230, 49231, 49232, 49232, 49233, 49234, 49234, \n\t49235, 49236, 49236, 49237, 49237, 49238, 49239, 49239, \n\t49240, 49241, 49241, 49242, 49243, 49243, 49244, 49245, \n\t49245, 49246, 49247, 49247, 49248, 49249, 49249, 49250, \n\t49251, 49251, 49252, 49253, 49253, 49254, 49255, 49255, \n\t49256, 49257, 49257, 49258, 49259, 49259, 49260, 49261, \n\t49261, 49262, 49263, 49263, 49264, 49265, 49265, 49266, \n\t49267, 49267, 49268, 49269, 49269, 49270, 49270, 49271, \n\t49272, 49272, 49273, 49274, 49274, 49275, 49276, 49276, \n\t49277, 49278, 49278, 49279, 49280, 49280, 49281, 49282, \n\t49282, 49283, 49284, 49284, 49285, 49286, 49286, 49287, \n\t49288, 49288, 49289, 49290, 49290, 49291, 49292, 49292, \n\t49293, 49294, 49294, 49295, 49296, 49296, 49297, 49298, \n\t49298, 49299, 49299, 49300, 49301, 49301, 49302, 49303, \n\t49303, 49304, 49305, 49305, 49306, 49307, 49307, 49308, \n\t49309, 49309, 49310, 49311, 49311, 49312, 49313, 49313, \n\t49314, 49315, 49315, 49316, 49317, 49317, 49318, 49319, \n\t49319, 49320, 49321, 49321, 49322, 49323, 49323, 49324, \n\t49325, 49325, 49326, 49326, 49327, 49328, 49328, 49329, \n\t49330, 49330, 49331, 49332, 49332, 49333, 49334, 49334, \n\t49335, 49336, 49336, 49337, 49338, 49338, 49339, 49340, \n\t49340, 49341, 49342, 49342, 49343, 49344, 49344, 49345, \n\t49346, 49346, 49347, 49348, 49348, 49349, 49350, 49350, \n\t49351, 49351, 49352, 49353, 49353, 49354, 49355, 49355, \n\t49356, 49357, 49357, 49358, 49359, 49359, 49360, 49361, \n\t49361, 49362, 49363, 49363, 49364, 49365, 49365, 49366, \n\t49367, 49367, 49368, 49369, 49369, 49370, 49371, 49371, \n\t49372, 49373, 49373, 49374, 49375, 49375, 49376, 49376, \n\t49377, 49378, 49378, 49379, 49380, 49380, 49381, 49382, \n\t49382, 49383, 49384, 49384, 49385, 49386, 49386, 49387, \n\t49388, 49388, 49389, 49390, 49390, 49391, 49392, 49392, \n\t49393, 49394, 49394, 49395, 49396, 49396, 49397, 49398, \n\t49398, 49399, 49399, 49400, 49401, 49401, 49402, 49403, \n\t49403, 49404, 49405, 49405, 49406, 49407, 49407, 49408, \n\t49409, 49409, 49410, 49411, 49411, 49412, 49413, 49413, \n\t49414, 49415, 49415, 49416, 49417, 49417, 49418, 49419, \n\t49419, 49420, 49421, 49421, 49422, 49422, 49423, 49424, \n\t49424, 49425, 49426, 49426, 49427, 49428, 49428, 49429, \n\t49430, 49430, 49431, 49432, 49432, 49433, 49434, 49434, \n\t49435, 49436, 49436, 49437, 49438, 49438, 49439, 49440, \n\t49440, 49441, 49442, 49442, 49443, 49444, 49444, 49445, \n\t49445, 49446, 49447, 49447, 49448, 49449, 49449, 49450, \n\t49451, 49451, 49452, 49453, 49453, 49454, 49455, 49455, \n\t49456, 49457, 49457, 49458, 49459, 49459, 49460, 49461, \n\t49461, 49462, 49463, 49463, 49464, 49464, 49465, 49466, \n\t49466, 49467, 49468, 49468, 49469, 49470, 49470, 49471, \n\t49472, 49472, 49473, 49474, 49474, 49475, 49476, 49476, \n\t49477, 49478, 49478, 49479, 49480, 49480, 49481, 49482, \n\t49482, 49483, 49484, 49484, 49485, 49485, 49486, 49487, \n\t49487, 49488, 49489, 49489, 49490, 49491, 49491, 49492, \n\t49493, 49493, 49494, 49495, 49495, 49496, 49497, 49497, \n\t49498, 49499, 49499, 49500, 49501, 49501, 49502, 49503, \n\t49503, 49504, 49504, 49505, 49506, 49506, 49507, 49508, \n\t49508, 49509, 49510, 49510, 49511, 49512, 49512, 49513, \n\t49514, 49514, 49515, 49516, 49516, 49517, 49518, 49518, \n\t49519, 49520, 49520, 49521, 49522, 49522, 49523, 49523, \n\t49524, 49525, 49525, 49526, 49527, 49527, 49528, 49529, \n\t49529, 49530, 49531, 49531, 49532, 49533, 49533, 49534, \n\t49535, 49535, 49536, 49537, 49537, 49538, 49539, 49539, \n\t49540, 49541, 49541, 49542, 49542, 49543, 49544, 49544, \n\t49545, 49546, 49546, 49547, 49548, 49548, 49549, 49550, \n\t49550, 49551, 49552, 49552, 49553, 49554, 49554, 49555, \n\t49556, 49556, 49557, 49558, 49558, 49559, 49559, 49560, \n\t49561, 49561, 49562, 49563, 49563, 49564, 49565, 49565, \n\t49566, 49567, 49567, 49568, 49569, 49569, 49570, 49571, \n\t49571, 49572, 49573, 49573, 49574, 49575, 49575, 49576, \n\t49577, 49577, 49578, 49578, 49579, 49580, 49580, 49581, \n\t49582, 49582, 49583, 49584, 49584, 49585, 49586, 49586, \n\t49587, 49588, 49588, 49589, 49590, 49590, 49591, 49592, \n\t49592, 49593, 49594, 49594, 49595, 49595, 49596, 49597, \n\t49597, 49598, 49599, 49599, 49600, 49601, 49601, 49602, \n\t49603, 49603, 49604, 49605, 49605, 49606, 49607, 49607, \n\t49608, 49609, 49609, 49610, 49610, 49611, 49612, 49612, \n\t49613, 49614, 49614, 49615, 49616, 49616, 49617, 49618, \n\t49618, 49619, 49620, 49620, 49621, 49622, 49622, 49623, \n\t49624, 49624, 49625, 49626, 49626, 49627, 49627, 49628, \n\t49629, 49629, 49630, 49631, 49631, 49632, 49633, 49633, \n\t49634, 49635, 49635, 49636, 49637, 49637, 49638, 49639, \n\t49639, 49640, 49641, 49641, 49642, 49643, 49643, 49644, \n\t49644, 49645, 49646, 49646, 49647, 49648, 49648, 49649, \n\t49650, 49650, 49651, 49652, 49652, 49653, 49654, 49654, \n\t49655, 49656, 49656, 49657, 49658, 49658, 49659, 49659, \n\t49660, 49661, 49661, 49662, 49663, 49663, 49664, 49665, \n\t49665, 49666, 49667, 49667, 49668, 49669, 49669, 49670, \n\t49671, 49671, 49672, 49673, 49673, 49674, 49674, 49675, \n\t49676, 49676, 49677, 49678, 49678, 49679, 49680, 49680, \n\t49681, 49682, 49682, 49683, 49684, 49684, 49685, 49686, \n\t49686, 49687, 49688, 49688, 49689, 49689, 49690, 49691, \n\t49691, 49692, 49693, 49693, 49694, 49695, 49695, 49696, \n\t49697, 49697, 49698, 49699, 49699, 49700, 49701, 49701, \n\t49702, 49703, 49703, 49704, 49704, 49705, 49706, 49706, \n\t49707, 49708, 49708, 49709, 49710, 49710, 49711, 49712, \n\t49712, 49713, 49714, 49714, 49715, 49716, 49716, 49717, \n\t49718, 49718, 49719, 49719, 49720, 49721, 49721, 49722, \n\t49723, 49723, 49724, 49725, 49725, 49726, 49727, 49727, \n\t49728, 49729, 49729, 49730, 49731, 49731, 49732, 49732, \n\t49733, 49734, 49734, 49735, 49736, 49736, 49737, 49738, \n\t49738, 49739, 49740, 49740, 49741, 49742, 49742, 49743, \n\t49744, 49744, 49745, 49746, 49746, 49747, 49747, 49748, \n\t49749, 49749, 49750, 49751, 49751, 49752, 49753, 49753, \n\t49754, 49755, 49755, 49756, 49757, 49757, 49758, 49759, \n\t49759, 49760, 49760, 49761, 49762, 49762, 49763, 49764, \n\t49764, 49765, 49766, 49766, 49767, 49768, 49768, 49769, \n\t49770, 49770, 49771, 49772, 49772, 49773, 49773, 49774, \n\t49775, 49775, 49776, 49777, 49777, 49778, 49779, 49779, \n\t49780, 49781, 49781, 49782, 49783, 49783, 49784, 49785, \n\t49785, 49786, 49786, 49787, 49788, 49788, 49789, 49790, \n\t49790, 49791, 49792, 49792, 49793, 49794, 49794, 49795, \n\t49796, 49796, 49797, 49798, 49798, 49799, 49800, 49800, \n\t49801, 49801, 49802, 49803, 49803, 49804, 49805, 49805, \n\t49806, 49807, 49807, 49808, 49809, 49809, 49810, 49811, \n\t49811, 49812, 49813, 49813, 49814, 49814, 49815, 49816, \n\t49816, 49817, 49818, 49818, 49819, 49820, 49820, 49821, \n\t49822, 49822, 49823, 49824, 49824, 49825, 49825, 49826, \n\t49827, 49827, 49828, 49829, 49829, 49830, 49831, 49831, \n\t49832, 49833, 49833, 49834, 49835, 49835, 49836, 49837, \n\t49837, 49838, 49838, 49839, 49840, 49840, 49841, 49842, \n\t49842, 49843, 49844, 49844, 49845, 49846, 49846, 49847, \n\t49848, 49848, 49849, 49850, 49850, 49851, 49851, 49852, \n\t49853, 49853, 49854, 49855, 49855, 49856, 49857, 49857, \n\t49858, 49859, 49859, 49860, 49861, 49861, 49862, 49863, \n\t49863, 49864, 49864, 49865, 49866, 49866, 49867, 49868, \n\t49868, 49869, 49870, 49870, 49871, 49872, 49872, 49873, \n\t49874, 49874, 49875, 49875, 49876, 49877, 49877, 49878, \n\t49879, 49879, 49880, 49881, 49881, 49882, 49883, 49883, \n\t49884, 49885, 49885, 49886, 49887, 49887, 49888, 49888, \n\t49889, 49890, 49890, 49891, 49892, 49892, 49893, 49894, \n\t49894, 49895, 49896, 49896, 49897, 49898, 49898, 49899, \n\t49899, 49900, 49901, 49901, 49902, 49903, 49903, 49904, \n\t49905, 49905, 49906, 49907, 49907, 49908, 49909, 49909, \n\t49910, 49910, 49911, 49912, 49912, 49913, 49914, 49914, \n\t49915, 49916, 49916, 49917, 49918, 49918, 49919, 49920, \n\t49920, 49921, 49922, 49922, 49923, 49923, 49924, 49925, \n\t49925, 49926, 49927, 49927, 49928, 49929, 49929, 49930, \n\t49931, 49931, 49932, 49933, 49933, 49934, 49934, 49935, \n\t49936, 49936, 49937, 49938, 49938, 49939, 49940, 49940, \n\t49941, 49942, 49942, 49943, 49944, 49944, 49945, 49945, \n\t49946, 49947, 49947, 49948, 49949, 49949, 49950, 49951, \n\t49951, 49952, 49953, 49953, 49954, 49955, 49955, 49956, \n\t49956, 49957, 49958, 49958, 49959, 49960, 49960, 49961, \n\t49962, 49962, 49963, 49964, 49964, 49965, 49966, 49966, \n\t49967, 49967, 49968, 49969, 49969, 49970, 49971, 49971, \n\t49972, 49973, 49973, 49974, 49975, 49975, 49976, 49977, \n\t49977, 49978, 49978, 49979, 49980, 49980, 49981, 49982, \n\t49982, 49983, 49984, 49984, 49985, 49986, 49986, 49987, \n\t49988, 49988, 49989, 49989, 49990, 49991, 49991, 49992, \n\t49993, 49993, 49994, 49995, 49995, 49996, 49997, 49997, \n\t49998, 49999, 49999, 50000, 50000, 50001, 50002, 50002, \n\t50003, 50004, 50004, 50005, 50006, 50006, 50007, 50008, \n\t50008, 50009, 50010, 50010, 50011, 50011, 50012, 50013, \n\t50013, 50014, 50015, 50015, 50016, 50017, 50017, 50018, \n\t50019, 50019, 50020, 50020, 50021, 50022, 50022, 50023, \n\t50024, 50024, 50025, 50026, 50026, 50027, 50028, 50028, \n\t50029, 50030, 50030, 50031, 50031, 50032, 50033, 50033, \n\t50034, 50035, 50035, 50036, 50037, 50037, 50038, 50039, \n\t50039, 50040, 50041, 50041, 50042, 50042, 50043, 50044, \n\t50044, 50045, 50046, 50046, 50047, 50048, 50048, 50049, \n\t50050, 50050, 50051, 50051, 50052, 50053, 50053, 50054, \n\t50055, 50055, 50056, 50057, 50057, 50058, 50059, 50059, \n\t50060, 50061, 50061, 50062, 50062, 50063, 50064, 50064, \n\t50065, 50066, 50066, 50067, 50068, 50068, 50069, 50070, \n\t50070, 50071, 50072, 50072, 50073, 50073, 50074, 50075, \n\t50075, 50076, 50077, 50077, 50078, 50079, 50079, 50080, \n\t50081, 50081, 50082, 50082, 50083, 50084, 50084, 50085, \n\t50086, 50086, 50087, 50088, 50088, 50089, 50090, 50090, \n\t50091, 50091, 50092, 50093, 50093, 50094, 50095, 50095, \n\t50096, 50097, 50097, 50098, 50099, 50099, 50100, 50101, \n\t50101, 50102, 50102, 50103, 50104, 50104, 50105, 50106, \n\t50106, 50107, 50108, 50108, 50109, 50110, 50110, 50111, \n\t50111, 50112, 50113, 50113, 50114, 50115, 50115, 50116, \n\t50117, 50117, 50118, 50119, 50119, 50120, 50121, 50121, \n\t50122, 50122, 50123, 50124, 50124, 50125, 50126, 50126, \n\t50127, 50128, 50128, 50129, 50130, 50130, 50131, 50131, \n\t50132, 50133, 50133, 50134, 50135, 50135, 50136, 50137, \n\t50137, 50138, 50139, 50139, 50140, 50140, 50141, 50142, \n\t50142, 50143, 50144, 50144, 50145, 50146, 50146, 50147, \n\t50148, 50148, 50149, 50149, 50150, 50151, 50151, 50152, \n\t50153, 50153, 50154, 50155, 50155, 50156, 50157, 50157, \n\t50158, 50158, 50159, 50160, 50160, 50161, 50162, 50162, \n\t50163, 50164, 50164, 50165, 50166, 50166, 50167, 50168, \n\t50168, 50169, 50169, 50170, 50171, 50171, 50172, 50173, \n\t50173, 50174, 50175, 50175, 50176, 50177, 50177, 50178, \n\t50178, 50179, 50180, 50180, 50181, 50182, 50182, 50183, \n\t50184, 50184, 50185, 50186, 50186, 50187, 50187, 50188, \n\t50189, 50189, 50190, 50191, 50191, 50192, 50193, 50193, \n\t50194, 50195, 50195, 50196, 50196, 50197, 50198, 50198, \n\t50199, 50200, 50200, 50201, 50202, 50202, 50203, 50204, \n\t50204, 50205, 50205, 50206, 50207, 50207, 50208, 50209, \n\t50209, 50210, 50211, 50211, 50212, 50213, 50213, 50214, \n\t50214, 50215, 50216, 50216, 50217, 50218, 50218, 50219, \n\t50220, 50220, 50221, 50222, 50222, 50223, 50223, 50224, \n\t50225, 50225, 50226, 50227, 50227, 50228, 50229, 50229, \n\t50230, 50231, 50231, 50232, 50232, 50233, 50234, 50234, \n\t50235, 50236, 50236, 50237, 50238, 50238, 50239, 50239, \n\t50240, 50241, 50241, 50242, 50243, 50243, 50244, 50245, \n\t50245, 50246, 50247, 50247, 50248, 50248, 50249, 50250, \n\t50250, 50251, 50252, 50252, 50253, 50254, 50254, 50255, \n\t50256, 50256, 50257, 50257, 50258, 50259, 50259, 50260, \n\t50261, 50261, 50262, 50263, 50263, 50264, 50265, 50265, \n\t50266, 50266, 50267, 50268, 50268, 50269, 50270, 50270, \n\t50271, 50272, 50272, 50273, 50274, 50274, 50275, 50275, \n\t50276, 50277, 50277, 50278, 50279, 50279, 50280, 50281, \n\t50281, 50282, 50282, 50283, 50284, 50284, 50285, 50286, \n\t50286, 50287, 50288, 50288, 50289, 50290, 50290, 50291, \n\t50291, 50292, 50293, 50293, 50294, 50295, 50295, 50296, \n\t50297, 50297, 50298, 50299, 50299, 50300, 50300, 50301, \n\t50302, 50302, 50303, 50304, 50304, 50305, 50306, 50306, \n\t50307, 50307, 50308, 50309, 50309, 50310, 50311, 50311, \n\t50312, 50313, 50313, 50314, 50315, 50315, 50316, 50316, \n\t50317, 50318, 50318, 50319, 50320, 50320, 50321, 50322, \n\t50322, 50323, 50324, 50324, 50325, 50325, 50326, 50327, \n\t50327, 50328, 50329, 50329, 50330, 50331, 50331, 50332, \n\t50332, 50333, 50334, 50334, 50335, 50336, 50336, 50337, \n\t50338, 50338, 50339, 50340, 50340, 50341, 50341, 50342, \n\t50343, 50343, 50344, 50345, 50345, 50346, 50347, 50347, \n\t50348, 50348, 50349, 50350, 50350, 50351, 50352, 50352, \n\t50353, 50354, 50354, 50355, 50356, 50356, 50357, 50357, \n\t50358, 50359, 50359, 50360, 50361, 50361, 50362, 50363, \n\t50363, 50364, 50364, 50365, 50366, 50366, 50367, 50368, \n\t50368, 50369, 50370, 50370, 50371, 50372, 50372, 50373, \n\t50373, 50374, 50375, 50375, 50376, 50377, 50377, 50378, \n\t50379, 50379, 50380, 50380, 50381, 50382, 50382, 50383, \n\t50384, 50384, 50385, 50386, 50386, 50387, 50388, 50388, \n\t50389, 50389, 50390, 50391, 50391, 50392, 50393, 50393, \n\t50394, 50395, 50395, 50396, 50396, 50397, 50398, 50398, \n\t50399, 50400, 50400, 50401, 50402, 50402, 50403, 50404, \n\t50404, 50405, 50405, 50406, 50407, 50407, 50408, 50409, \n\t50409, 50410, 50411, 50411, 50412, 50412, 50413, 50414, \n\t50414, 50415, 50416, 50416, 50417, 50418, 50418, 50419, \n\t50419, 50420, 50421, 50421, 50422, 50423, 50423, 50424, \n\t50425, 50425, 50426, 50427, 50427, 50428, 50428, 50429, \n\t50430, 50430, 50431, 50432, 50432, 50433, 50434, 50434, \n\t50435, 50435, 50436, 50437, 50437, 50438, 50439, 50439, \n\t50440, 50441, 50441, 50442, 50442, 50443, 50444, 50444, \n\t50445, 50446, 50446, 50447, 50448, 50448, 50449, 50449, \n\t50450, 50451, 50451, 50452, 50453, 50453, 50454, 50455, \n\t50455, 50456, 50457, 50457, 50458, 50458, 50459, 50460, \n\t50460, 50461, 50462, 50462, 50463, 50464, 50464, 50465, \n\t50465, 50466, 50467, 50467, 50468, 50469, 50469, 50470, \n\t50471, 50471, 50472, 50472, 50473, 50474, 50474, 50475, \n\t50476, 50476, 50477, 50478, 50478, 50479, 50479, 50480, \n\t50481, 50481, 50482, 50483, 50483, 50484, 50485, 50485, \n\t50486, 50486, 50487, 50488, 50488, 50489, 50490, 50490, \n\t50491, 50492, 50492, 50493, 50494, 50494, 50495, 50495, \n\t50496, 50497, 50497, 50498, 50499, 50499, 50500, 50501, \n\t50501, 50502, 50502, 50503, 50504, 50504, 50505, 50506, \n\t50506, 50507, 50508, 50508, 50509, 50509, 50510, 50511, \n\t50511, 50512, 50513, 50513, 50514, 50515, 50515, 50516, \n\t50516, 50517, 50518, 50518, 50519, 50520, 50520, 50521, \n\t50522, 50522, 50523, 50523, 50524, 50525, 50525, 50526, \n\t50527, 50527, 50528, 50529, 50529, 50530, 50530, 50531, \n\t50532, 50532, 50533, 50534, 50534, 50535, 50536, 50536, \n\t50537, 50537, 50538, 50539, 50539, 50540, 50541, 50541, \n\t50542, 50543, 50543, 50544, 50544, 50545, 50546, 50546, \n\t50547, 50548, 50548, 50549, 50550, 50550, 50551, 50551, \n\t50552, 50553, 50553, 50554, 50555, 50555, 50556, 50557, \n\t50557, 50558, 50558, 50559, 50560, 50560, 50561, 50562, \n\t50562, 50563, 50564, 50564, 50565, 50565, 50566, 50567, \n\t50567, 50568, 50569, 50569, 50570, 50571, 50571, 50572, \n\t50572, 50573, 50574, 50574, 50575, 50576, 50576, 50577, \n\t50578, 50578, 50579, 50579, 50580, 50581, 50581, 50582, \n\t50583, 50583, 50584, 50585, 50585, 50586, 50586, 50587, \n\t50588, 50588, 50589, 50590, 50590, 50591, 50592, 50592, \n\t50593, 50593, 50594, 50595, 50595, 50596, 50597, 50597, \n\t50598, 50599, 50599, 50600, 50600, 50601, 50602, 50602, \n\t50603, 50604, 50604, 50605, 50606, 50606, 50607, 50607, \n\t50608, 50609, 50609, 50610, 50611, 50611, 50612, 50613, \n\t50613, 50614, 50614, 50615, 50616, 50616, 50617, 50618, \n\t50618, 50619, 50619, 50620, 50621, 50621, 50622, 50623, \n\t50623, 50624, 50625, 50625, 50626, 50626, 50627, 50628, \n\t50628, 50629, 50630, 50630, 50631, 50632, 50632, 50633, \n\t50633, 50634, 50635, 50635, 50636, 50637, 50637, 50638, \n\t50639, 50639, 50640, 50640, 50641, 50642, 50642, 50643, \n\t50644, 50644, 50645, 50646, 50646, 50647, 50647, 50648, \n\t50649, 50649, 50650, 50651, 50651, 50652, 50653, 50653, \n\t50654, 50654, 50655, 50656, 50656, 50657, 50658, 50658, \n\t50659, 50659, 50660, 50661, 50661, 50662, 50663, 50663, \n\t50664, 50665, 50665, 50666, 50666, 50667, 50668, 50668, \n\t50669, 50670, 50670, 50671, 50672, 50672, 50673, 50673, \n\t50674, 50675, 50675, 50676, 50677, 50677, 50678, 50679, \n\t50679, 50680, 50680, 50681, 50682, 50682, 50683, 50684, \n\t50684, 50685, 50685, 50686, 50687, 50687, 50688, 50689, \n\t50689, 50690, 50691, 50691, 50692, 50692, 50693, 50694, \n\t50694, 50695, 50696, 50696, 50697, 50698, 50698, 50699, \n\t50699, 50700, 50701, 50701, 50702, 50703, 50703, 50704, \n\t50704, 50705, 50706, 50706, 50707, 50708, 50708, 50709, \n\t50710, 50710, 50711, 50711, 50712, 50713, 50713, 50714, \n\t50715, 50715, 50716, 50717, 50717, 50718, 50718, 50719, \n\t50720, 50720, 50721, 50722, 50722, 50723, 50723, 50724, \n\t50725, 50725, 50726, 50727, 50727, 50728, 50729, 50729, \n\t50730, 50730, 50731, 50732, 50732, 50733, 50734, 50734, \n\t50735, 50736, 50736, 50737, 50737, 50738, 50739, 50739, \n\t50740, 50741, 50741, 50742, 50742, 50743, 50744, 50744, \n\t50745, 50746, 50746, 50747, 50748, 50748, 50749, 50749, \n\t50750, 50751, 50751, 50752, 50753, 50753, 50754, 50755, \n\t50755, 50756, 50756, 50757, 50758, 50758, 50759, 50760, \n\t50760, 50761, 50761, 50762, 50763, 50763, 50764, 50765, \n\t50765, 50766, 50767, 50767, 50768, 50768, 50769, 50770, \n\t50770, 50771, 50772, 50772, 50773, 50773, 50774, 50775, \n\t50775, 50776, 50777, 50777, 50778, 50779, 50779, 50780, \n\t50780, 50781, 50782, 50782, 50783, 50784, 50784, 50785, \n\t50785, 50786, 50787, 50787, 50788, 50789, 50789, 50790, \n\t50791, 50791, 50792, 50792, 50793, 50794, 50794, 50795, \n\t50796, 50796, 50797, 50798, 50798, 50799, 50799, 50800, \n\t50801, 50801, 50802, 50803, 50803, 50804, 50804, 50805, \n\t50806, 50806, 50807, 50808, 50808, 50809, 50810, 50810, \n\t50811, 50811, 50812, 50813, 50813, 50814, 50815, 50815, \n\t50816, 50816, 50817, 50818, 50818, 50819, 50820, 50820, \n\t50821, 50822, 50822, 50823, 50823, 50824, 50825, 50825, \n\t50826, 50827, 50827, 50828, 50828, 50829, 50830, 50830, \n\t50831, 50832, 50832, 50833, 50833, 50834, 50835, 50835, \n\t50836, 50837, 50837, 50838, 50839, 50839, 50840, 50840, \n\t50841, 50842, 50842, 50843, 50844, 50844, 50845, 50845, \n\t50846, 50847, 50847, 50848, 50849, 50849, 50850, 50851, \n\t50851, 50852, 50852, 50853, 50854, 50854, 50855, 50856, \n\t50856, 50857, 50857, 50858, 50859, 50859, 50860, 50861, \n\t50861, 50862, 50863, 50863, 50864, 50864, 50865, 50866, \n\t50866, 50867, 50868, 50868, 50869, 50869, 50870, 50871, \n\t50871, 50872, 50873, 50873, 50874, 50874, 50875, 50876, \n\t50876, 50877, 50878, 50878, 50879, 50880, 50880, 50881, \n\t50881, 50882, 50883, 50883, 50884, 50885, 50885, 50886, \n\t50886, 50887, 50888, 50888, 50889, 50890, 50890, 50891, \n\t50892, 50892, 50893, 50893, 50894, 50895, 50895, 50896, \n\t50897, 50897, 50898, 50898, 50899, 50900, 50900, 50901, \n\t50902, 50902, 50903, 50903, 50904, 50905, 50905, 50906, \n\t50907, 50907, 50908, 50909, 50909, 50910, 50910, 50911, \n\t50912, 50912, 50913, 50914, 50914, 50915, 50915, 50916, \n\t50917, 50917, 50918, 50919, 50919, 50920, 50920, 50921, \n\t50922, 50922, 50923, 50924, 50924, 50925, 50926, 50926, \n\t50927, 50927, 50928, 50929, 50929, 50930, 50931, 50931, \n\t50932, 50932, 50933, 50934, 50934, 50935, 50936, 50936, \n\t50937, 50937, 50938, 50939, 50939, 50940, 50941, 50941, \n\t50942, 50943, 50943, 50944, 50944, 50945, 50946, 50946, \n\t50947, 50948, 50948, 50949, 50949, 50950, 50951, 50951, \n\t50952, 50953, 50953, 50954, 50954, 50955, 50956, 50956, \n\t50957, 50958, 50958, 50959, 50959, 50960, 50961, 50961, \n\t50962, 50963, 50963, 50964, 50965, 50965, 50966, 50966, \n\t50967, 50968, 50968, 50969, 50970, 50970, 50971, 50971, \n\t50972, 50973, 50973, 50974, 50975, 50975, 50976, 50976, \n\t50977, 50978, 50978, 50979, 50980, 50980, 50981, 50981, \n\t50982, 50983, 50983, 50984, 50985, 50985, 50986, 50987, \n\t50987, 50988, 50988, 50989, 50990, 50990, 50991, 50992, \n\t50992, 50993, 50993, 50994, 50995, 50995, 50996, 50997, \n\t50997, 50998, 50998, 50999, 51000, 51000, 51001, 51002, \n\t51002, 51003, 51003, 51004, 51005, 51005, 51006, 51007, \n\t51007, 51008, 51009, 51009, 51010, 51010, 51011, 51012, \n\t51012, 51013, 51014, 51014, 51015, 51015, 51016, 51017, \n\t51017, 51018, 51019, 51019, 51020, 51020, 51021, 51022, \n\t51022, 51023, 51024, 51024, 51025, 51025, 51026, 51027, \n\t51027, 51028, 51029, 51029, 51030, 51030, 51031, 51032, \n\t51032, 51033, 51034, 51034, 51035, 51035, 51036, 51037, \n\t51037, 51038, 51039, 51039, 51040, 51041, 51041, 51042, \n\t51042, 51043, 51044, 51044, 51045, 51046, 51046, 51047, \n\t51047, 51048, 51049, 51049, 51050, 51051, 51051, 51052, \n\t51052, 51053, 51054, 51054, 51055, 51056, 51056, 51057, \n\t51057, 51058, 51059, 51059, 51060, 51061, 51061, 51062, \n\t51062, 51063, 51064, 51064, 51065, 51066, 51066, 51067, \n\t51067, 51068, 51069, 51069, 51070, 51071, 51071, 51072, \n\t51072, 51073, 51074, 51074, 51075, 51076, 51076, 51077, \n\t51077, 51078, 51079, 51079, 51080, 51081, 51081, 51082, \n\t51083, 51083, 51084, 51084, 51085, 51086, 51086, 51087, \n\t51088, 51088, 51089, 51089, 51090, 51091, 51091, 51092, \n\t51093, 51093, 51094, 51094, 51095, 51096, 51096, 51097, \n\t51098, 51098, 51099, 51099, 51100, 51101, 51101, 51102, \n\t51103, 51103, 51104, 51104, 51105, 51106, 51106, 51107, \n\t51108, 51108, 51109, 51109, 51110, 51111, 51111, 51112, \n\t51113, 51113, 51114, 51114, 51115, 51116, 51116, 51117, \n\t51118, 51118, 51119, 51119, 51120, 51121, 51121, 51122, \n\t51123, 51123, 51124, 51124, 51125, 51126, 51126, 51127, \n\t51128, 51128, 51129, 51129, 51130, 51131, 51131, 51132, \n\t51133, 51133, 51134, 51134, 51135, 51136, 51136, 51137, \n\t51138, 51138, 51139, 51139, 51140, 51141, 51141, 51142, \n\t51143, 51143, 51144, 51144, 51145, 51146, 51146, 51147, \n\t51148, 51148, 51149, 51149, 51150, 51151, 51151, 51152, \n\t51153, 51153, 51154, 51154, 51155, 51156, 51156, 51157, \n\t51158, 51158, 51159, 51159, 51160, 51161, 51161, 51162, \n\t51163, 51163, 51164, 51164, 51165, 51166, 51166, 51167, \n\t51168, 51168, 51169, 51169, 51170, 51171, 51171, 51172, \n\t51173, 51173, 51174, 51174, 51175, 51176, 51176, 51177, \n\t51178, 51178, 51179, 51179, 51180, 51181, 51181, 51182, \n\t51183, 51183, 51184, 51184, 51185, 51186, 51186, 51187, \n\t51188, 51188, 51189, 51189, 51190, 51191, 51191, 51192, \n\t51193, 51193, 51194, 51194, 51195, 51196, 51196, 51197, \n\t51198, 51198, 51199, 51199, 51200, 51201, 51201, 51202, \n\t51203, 51203, 51204, 51204, 51205, 51206, 51206, 51207, \n\t51208, 51208, 51209, 51209, 51210, 51211, 51211, 51212, \n\t51213, 51213, 51214, 51214, 51215, 51216, 51216, 51217, \n\t51218, 51218, 51219, 51219, 51220, 51221, 51221, 51222, \n\t51223, 51223, 51224, 51224, 51225, 51226, 51226, 51227, \n\t51228, 51228, 51229, 51229, 51230, 51231, 51231, 51232, \n\t51233, 51233, 51234, 51234, 51235, 51236, 51236, 51237, \n\t51237, 51238, 51239, 51239, 51240, 51241, 51241, 51242, \n\t51242, 51243, 51244, 51244, 51245, 51246, 51246, 51247, \n\t51247, 51248, 51249, 51249, 51250, 51251, 51251, 51252, \n\t51252, 51253, 51254, 51254, 51255, 51256, 51256, 51257, \n\t51257, 51258, 51259, 51259, 51260, 51261, 51261, 51262, \n\t51262, 51263, 51264, 51264, 51265, 51266, 51266, 51267, \n\t51267, 51268, 51269, 51269, 51270, 51271, 51271, 51272, \n\t51272, 51273, 51274, 51274, 51275, 51276, 51276, 51277, \n\t51277, 51278, 51279, 51279, 51280, 51280, 51281, 51282, \n\t51282, 51283, 51284, 51284, 51285, 51285, 51286, 51287, \n\t51287, 51288, 51289, 51289, 51290, 51290, 51291, 51292, \n\t51292, 51293, 51294, 51294, 51295, 51295, 51296, 51297, \n\t51297, 51298, 51299, 51299, 51300, 51300, 51301, 51302, \n\t51302, 51303, 51304, 51304, 51305, 51305, 51306, 51307, \n\t51307, 51308, 51309, 51309, 51310, 51310, 51311, 51312, \n\t51312, 51313, 51313, 51314, 51315, 51315, 51316, 51317, \n\t51317, 51318, 51318, 51319, 51320, 51320, 51321, 51322, \n\t51322, 51323, 51323, 51324, 51325, 51325, 51326, 51327, \n\t51327, 51328, 51328, 51329, 51330, 51330, 51331, 51332, \n\t51332, 51333, 51333, 51334, 51335, 51335, 51336, 51336, \n\t51337, 51338, 51338, 51339, 51340, 51340, 51341, 51341, \n\t51342, 51343, 51343, 51344, 51345, 51345, 51346, 51346, \n\t51347, 51348, 51348, 51349, 51350, 51350, 51351, 51351, \n\t51352, 51353, 51353, 51354, 51355, 51355, 51356, 51356, \n\t51357, 51358, 51358, 51359, 51359, 51360, 51361, 51361, \n\t51362, 51363, 51363, 51364, 51364, 51365, 51366, 51366, \n\t51367, 51368, 51368, 51369, 51369, 51370, 51371, 51371, \n\t51372, 51373, 51373, 51374, 51374, 51375, 51376, 51376, \n\t51377, 51377, 51378, 51379, 51379, 51380, 51381, 51381, \n\t51382, 51382, 51383, 51384, 51384, 51385, 51386, 51386, \n\t51387, 51387, 51388, 51389, 51389, 51390, 51391, 51391, \n\t51392, 51392, 51393, 51394, 51394, 51395, 51395, 51396, \n\t51397, 51397, 51398, 51399, 51399, 51400, 51400, 51401, \n\t51402, 51402, 51403, 51404, 51404, 51405, 51405, 51406, \n\t51407, 51407, 51408, 51409, 51409, 51410, 51410, 51411, \n\t51412, 51412, 51413, 51413, 51414, 51415, 51415, 51416, \n\t51417, 51417, 51418, 51418, 51419, 51420, 51420, 51421, \n\t51422, 51422, 51423, 51423, 51424, 51425, 51425, 51426, \n\t51426, 51427, 51428, 51428, 51429, 51430, 51430, 51431, \n\t51431, 51432, 51433, 51433, 51434, 51435, 51435, 51436, \n\t51436, 51437, 51438, 51438, 51439, 51440, 51440, 51441, \n\t51441, 51442, 51443, 51443, 51444, 51444, 51445, 51446, \n\t51446, 51447, 51448, 51448, 51449, 51449, 51450, 51451, \n\t51451, 51452, 51453, 51453, 51454, 51454, 51455, 51456, \n\t51456, 51457, 51457, 51458, 51459, 51459, 51460, 51461, \n\t51461, 51462, 51462, 51463, 51464, 51464, 51465, 51466, \n\t51466, 51467, 51467, 51468, 51469, 51469, 51470, 51470, \n\t51471, 51472, 51472, 51473, 51474, 51474, 51475, 51475, \n\t51476, 51477, 51477, 51478, 51479, 51479, 51480, 51480, \n\t51481, 51482, 51482, 51483, 51483, 51484, 51485, 51485, \n\t51486, 51487, 51487, 51488, 51488, 51489, 51490, 51490, \n\t51491, 51492, 51492, 51493, 51493, 51494, 51495, 51495, \n\t51496, 51496, 51497, 51498, 51498, 51499, 51500, 51500, \n\t51501, 51501, 51502, 51503, 51503, 51504, 51505, 51505, \n\t51506, 51506, 51507, 51508, 51508, 51509, 51509, 51510, \n\t51511, 51511, 51512, 51513, 51513, 51514, 51514, 51515, \n\t51516, 51516, 51517, 51517, 51518, 51519, 51519, 51520, \n\t51521, 51521, 51522, 51522, 51523, 51524, 51524, 51525, \n\t51526, 51526, 51527, 51527, 51528, 51529, 51529, 51530, \n\t51530, 51531, 51532, 51532, 51533, 51534, 51534, 51535, \n\t51535, 51536, 51537, 51537, 51538, 51538, 51539, 51540, \n\t51540, 51541, 51542, 51542, 51543, 51543, 51544, 51545, \n\t51545, 51546, 51547, 51547, 51548, 51548, 51549, 51550, \n\t51550, 51551, 51551, 51552, 51553, 51553, 51554, 51555, \n\t51555, 51556, 51556, 51557, 51558, 51558, 51559, 51559, \n\t51560, 51561, 51561, 51562, 51563, 51563, 51564, 51564, \n\t51565, 51566, 51566, 51567, 51568, 51568, 51569, 51569, \n\t51570, 51571, 51571, 51572, 51572, 51573, 51574, 51574, \n\t51575, 51576, 51576, 51577, 51577, 51578, 51579, 51579, \n\t51580, 51580, 51581, 51582, 51582, 51583, 51584, 51584, \n\t51585, 51585, 51586, 51587, 51587, 51588, 51588, 51589, \n\t51590, 51590, 51591, 51592, 51592, 51593, 51593, 51594, \n\t51595, 51595, 51596, 51597, 51597, 51598, 51598, 51599, \n\t51600, 51600, 51601, 51601, 51602, 51603, 51603, 51604, \n\t51605, 51605, 51606, 51606, 51607, 51608, 51608, 51609, \n\t51609, 51610, 51611, 51611, 51612, 51613, 51613, 51614, \n\t51614, 51615, 51616, 51616, 51617, 51617, 51618, 51619, \n\t51619, 51620, 51621, 51621, 51622, 51622, 51623, 51624, \n\t51624, 51625, 51625, 51626, 51627, 51627, 51628, 51629, \n\t51629, 51630, 51630, 51631, 51632, 51632, 51633, 51633, \n\t51634, 51635, 51635, 51636, 51637, 51637, 51638, 51638, \n\t51639, 51640, 51640, 51641, 51641, 51642, 51643, 51643, \n\t51644, 51645, 51645, 51646, 51646, 51647, 51648, 51648, \n\t51649, 51649, 51650, 51651, 51651, 51652, 51653, 51653, \n\t51654, 51654, 51655, 51656, 51656, 51657, 51657, 51658, \n\t51659, 51659, 51660, 51661, 51661, 51662, 51662, 51663, \n\t51664, 51664, 51665, 51665, 51666, 51667, 51667, 51668, \n\t51669, 51669, 51670, 51670, 51671, 51672, 51672, 51673, \n\t51673, 51674, 51675, 51675, 51676, 51677, 51677, 51678, \n\t51678, 51679, 51680, 51680, 51681, 51681, 51682, 51683, \n\t51683, 51684, 51685, 51685, 51686, 51686, 51687, 51688, \n\t51688, 51689, 51689, 51690, 51691, 51691, 51692, 51693, \n\t51693, 51694, 51694, 51695, 51696, 51696, 51697, 51697, \n\t51698, 51699, 51699, 51700, 51701, 51701, 51702, 51702, \n\t51703, 51704, 51704, 51705, 51705, 51706, 51707, 51707, \n\t51708, 51709, 51709, 51710, 51710, 51711, 51712, 51712, \n\t51713, 51713, 51714, 51715, 51715, 51716, 51717, 51717, \n\t51718, 51718, 51719, 51720, 51720, 51721, 51721, 51722, \n\t51723, 51723, 51724, 51724, 51725, 51726, 51726, 51727, \n\t51728, 51728, 51729, 51729, 51730, 51731, 51731, 51732, \n\t51732, 51733, 51734, 51734, 51735, 51736, 51736, 51737, \n\t51737, 51738, 51739, 51739, 51740, 51740, 51741, 51742, \n\t51742, 51743, 51744, 51744, 51745, 51745, 51746, 51747, \n\t51747, 51748, 51748, 51749, 51750, 51750, 51751, 51751, \n\t51752, 51753, 51753, 51754, 51755, 51755, 51756, 51756, \n\t51757, 51758, 51758, 51759, 51759, 51760, 51761, 51761, \n\t51762, 51763, 51763, 51764, 51764, 51765, 51766, 51766, \n\t51767, 51767, 51768, 51769, 51769, 51770, 51771, 51771, \n\t51772, 51772, 51773, 51774, 51774, 51775, 51775, 51776, \n\t51777, 51777, 51778, 51778, 51779, 51780, 51780, 51781, \n\t51782, 51782, 51783, 51783, 51784, 51785, 51785, 51786, \n\t51786, 51787, 51788, 51788, 51789, 51790, 51790, 51791, \n\t51791, 51792, 51793, 51793, 51794, 51794, 51795, 51796, \n\t51796, 51797, 51797, 51798, 51799, 51799, 51800, 51801, \n\t51801, 51802, 51802, 51803, 51804, 51804, 51805, 51805, \n\t51806, 51807, 51807, 51808, 51809, 51809, 51810, 51810, \n\t51811, 51812, 51812, 51813, 51813, 51814, 51815, 51815, \n\t51816, 51816, 51817, 51818, 51818, 51819, 51820, 51820, \n\t51821, 51821, 51822, 51823, 51823, 51824, 51824, 51825, \n\t51826, 51826, 51827, 51827, 51828, 51829, 51829, 51830, \n\t51831, 51831, 51832, 51832, 51833, 51834, 51834, 51835, \n\t51835, 51836, 51837, 51837, 51838, 51838, 51839, 51840, \n\t51840, 51841, 51842, 51842, 51843, 51843, 51844, 51845, \n\t51845, 51846, 51846, 51847, 51848, 51848, 51849, 51850, \n\t51850, 51851, 51851, 51852, 51853, 51853, 51854, 51854, \n\t51855, 51856, 51856, 51857, 51857, 51858, 51859, 51859, \n\t51860, 51861, 51861, 51862, 51862, 51863, 51864, 51864, \n\t51865, 51865, 51866, 51867, 51867, 51868, 51868, 51869, \n\t51870, 51870, 51871, 51872, 51872, 51873, 51873, 51874, \n\t51875, 51875, 51876, 51876, 51877, 51878, 51878, 51879, \n\t51879, 51880, 51881, 51881, 51882, 51883, 51883, 51884, \n\t51884, 51885, 51886, 51886, 51887, 51887, 51888, 51889, \n\t51889, 51890, 51890, 51891, 51892, 51892, 51893, 51894, \n\t51894, 51895, 51895, 51896, 51897, 51897, 51898, 51898, \n\t51899, 51900, 51900, 51901, 51901, 51902, 51903, 51903, \n\t51904, 51905, 51905, 51906, 51906, 51907, 51908, 51908, \n\t51909, 51909, 51910, 51911, 51911, 51912, 51912, 51913, \n\t51914, 51914, 51915, 51915, 51916, 51917, 51917, 51918, \n\t51919, 51919, 51920, 51920, 51921, 51922, 51922, 51923, \n\t51923, 51924, 51925, 51925, 51926, 51926, 51927, 51928, \n\t51928, 51929, 51930, 51930, 51931, 51931, 51932, 51933, \n\t51933, 51934, 51934, 51935, 51936, 51936, 51937, 51937, \n\t51938, 51939, 51939, 51940, 51941, 51941, 51942, 51942, \n\t51943, 51944, 51944, 51945, 51945, 51946, 51947, 51947, \n\t51948, 51948, 51949, 51950, 51950, 51951, 51951, 51952, \n\t51953, 51953, 51954, 51955, 51955, 51956, 51956, 51957, \n\t51958, 51958, 51959, 51959, 51960, 51961, 51961, 51962, \n\t51962, 51963, 51964, 51964, 51965, 51965, 51966, 51967, \n\t51967, 51968, 51969, 51969, 51970, 51970, 51971, 51972, \n\t51972, 51973, 51973, 51974, 51975, 51975, 51976, 51976, \n\t51977, 51978, 51978, 51979, 51980, 51980, 51981, 51981, \n\t51982, 51983, 51983, 51984, 51984, 51985, 51986, 51986, \n\t51987, 51987, 51988, 51989, 51989, 51990, 51990, 51991, \n\t51992, 51992, 51993, 51994, 51994, 51995, 51995, 51996, \n\t51997, 51997, 51998, 51998, 51999, 52000, 52000, 52001, \n\t52001, 52002, 52003, 52003, 52004, 52004, 52005, 52006, \n\t52006, 52007, 52008, 52008, 52009, 52009, 52010, 52011, \n\t52011, 52012, 52012, 52013, 52014, 52014, 52015, 52015, \n\t52016, 52017, 52017, 52018, 52018, 52019, 52020, 52020, \n\t52021, 52022, 52022, 52023, 52023, 52024, 52025, 52025, \n\t52026, 52026, 52027, 52028, 52028, 52029, 52029, 52030, \n\t52031, 52031, 52032, 52032, 52033, 52034, 52034, 52035, \n\t52035, 52036, 52037, 52037, 52038, 52039, 52039, 52040, \n\t52040, 52041, 52042, 52042, 52043, 52043, 52044, 52045, \n\t52045, 52046, 52046, 52047, 52048, 52048, 52049, 52049, \n\t52050, 52051, 52051, 52052, 52053, 52053, 52054, 52054, \n\t52055, 52056, 52056, 52057, 52057, 52058, 52059, 52059, \n\t52060, 52060, 52061, 52062, 52062, 52063, 52063, 52064, \n\t52065, 52065, 52066, 52066, 52067, 52068, 52068, 52069, \n\t52070, 52070, 52071, 52071, 52072, 52073, 52073, 52074, \n\t52074, 52075, 52076, 52076, 52077, 52077, 52078, 52079, \n\t52079, 52080, 52080, 52081, 52082, 52082, 52083, 52083, \n\t52084, 52085, 52085, 52086, 52087, 52087, 52088, 52088, \n\t52089, 52090, 52090, 52091, 52091, 52092, 52093, 52093, \n\t52094, 52094, 52095, 52096, 52096, 52097, 52097, 52098, \n\t52099, 52099, 52100, 52100, 52101, 52102, 52102, 52103, \n\t52103, 52104, 52105, 52105, 52106, 52107, 52107, 52108, \n\t52108, 52109, 52110, 52110, 52111, 52111, 52112, 52113, \n\t52113, 52114, 52114, 52115, 52116, 52116, 52117, 52117, \n\t52118, 52119, 52119, 52120, 52120, 52121, 52122, 52122, \n\t52123, 52124, 52124, 52125, 52125, 52126, 52127, 52127, \n\t52128, 52128, 52129, 52130, 52130, 52131, 52131, 52132, \n\t52133, 52133, 52134, 52134, 52135, 52136, 52136, 52137, \n\t52137, 52138, 52139, 52139, 52140, 52140, 52141, 52142, \n\t52142, 52143, 52144, 52144, 52145, 52145, 52146, 52147, \n\t52147, 52148, 52148, 52149, 52150, 52150, 52151, 52151, \n\t52152, 52153, 52153, 52154, 52154, 52155, 52156, 52156, \n\t52157, 52157, 52158, 52159, 52159, 52160, 52160, 52161, \n\t52162, 52162, 52163, 52163, 52164, 52165, 52165, 52166, \n\t52167, 52167, 52168, 52168, 52169, 52170, 52170, 52171, \n\t52171, 52172, 52173, 52173, 52174, 52174, 52175, 52176, \n\t52176, 52177, 52177, 52178, 52179, 52179, 52180, 52180, \n\t52181, 52182, 52182, 52183, 52183, 52184, 52185, 52185, \n\t52186, 52186, 52187, 52188, 52188, 52189, 52190, 52190, \n\t52191, 52191, 52192, 52193, 52193, 52194, 52194, 52195, \n\t52196, 52196, 52197, 52197, 52198, 52199, 52199, 52200, \n\t52200, 52201, 52202, 52202, 52203, 52203, 52204, 52205, \n\t52205, 52206, 52206, 52207, 52208, 52208, 52209, 52209, \n\t52210, 52211, 52211, 52212, 52212, 52213, 52214, 52214, \n\t52215, 52216, 52216, 52217, 52217, 52218, 52219, 52219, \n\t52220, 52220, 52221, 52222, 52222, 52223, 52223, 52224, \n\t52225, 52225, 52226, 52226, 52227, 52228, 52228, 52229, \n\t52229, 52230, 52231, 52231, 52232, 52232, 52233, 52234, \n\t52234, 52235, 52235, 52236, 52237, 52237, 52238, 52238, \n\t52239, 52240, 52240, 52241, 52241, 52242, 52243, 52243, \n\t52244, 52244, 52245, 52246, 52246, 52247, 52248, 52248, \n\t52249, 52249, 52250, 52251, 52251, 52252, 52252, 52253, \n\t52254, 52254, 52255, 52255, 52256, 52257, 52257, 52258, \n\t52258, 52259, 52260, 52260, 52261, 52261, 52262, 52263, \n\t52263, 52264, 52264, 52265, 52266, 52266, 52267, 52267, \n\t52268, 52269, 52269, 52270, 52270, 52271, 52272, 52272, \n\t52273, 52273, 52274, 52275, 52275, 52276, 52276, 52277, \n\t52278, 52278, 52279, 52279, 52280, 52281, 52281, 52282, \n\t52283, 52283, 52284, 52284, 52285, 52286, 52286, 52287, \n\t52287, 52288, 52289, 52289, 52290, 52290, 52291, 52292, \n\t52292, 52293, 52293, 52294, 52295, 52295, 52296, 52296, \n\t52297, 52298, 52298, 52299, 52299, 52300, 52301, 52301, \n\t52302, 52302, 52303, 52304, 52304, 52305, 52305, 52306, \n\t52307, 52307, 52308, 52308, 52309, 52310, 52310, 52311, \n\t52311, 52312, 52313, 52313, 52314, 52314, 52315, 52316, \n\t52316, 52317, 52317, 52318, 52319, 52319, 52320, 52320, \n\t52321, 52322, 52322, 52323, 52323, 52324, 52325, 52325, \n\t52326, 52326, 52327, 52328, 52328, 52329, 52330, 52330, \n\t52331, 52331, 52332, 52333, 52333, 52334, 52334, 52335, \n\t52336, 52336, 52337, 52337, 52338, 52339, 52339, 52340, \n\t52340, 52341, 52342, 52342, 52343, 52343, 52344, 52345, \n\t52345, 52346, 52346, 52347, 52348, 52348, 52349, 52349, \n\t52350, 52351, 52351, 52352, 52352, 52353, 52354, 52354, \n\t52355, 52355, 52356, 52357, 52357, 52358, 52358, 52359, \n\t52360, 52360, 52361, 52361, 52362, 52363, 52363, 52364, \n\t52364, 52365, 52366, 52366, 52367, 52367, 52368, 52369, \n\t52369, 52370, 52370, 52371, 52372, 52372, 52373, 52373, \n\t52374, 52375, 52375, 52376, 52376, 52377, 52378, 52378, \n\t52379, 52379, 52380, 52381, 52381, 52382, 52382, 52383, \n\t52384, 52384, 52385, 52385, 52386, 52387, 52387, 52388, \n\t52388, 52389, 52390, 52390, 52391, 52391, 52392, 52393, \n\t52393, 52394, 52394, 52395, 52396, 52396, 52397, 52397, \n\t52398, 52399, 52399, 52400, 52400, 52401, 52402, 52402, \n\t52403, 52403, 52404, 52405, 52405, 52406, 52406, 52407, \n\t52408, 52408, 52409, 52409, 52410, 52411, 52411, 52412, \n\t52412, 52413, 52414, 52414, 52415, 52415, 52416, 52417, \n\t52417, 52418, 52418, 52419, 52420, 52420, 52421, 52421, \n\t52422, 52423, 52423, 52424, 52424, 52425, 52426, 52426, \n\t52427, 52427, 52428, 52429, 52429, 52430, 52430, 52431, \n\t52432, 52432, 52433, 52433, 52434, 52435, 52435, 52436, \n\t52436, 52437, 52438, 52438, 52439, 52439, 52440, 52441, \n\t52441, 52442, 52442, 52443, 52444, 52444, 52445, 52445, \n\t52446, 52447, 52447, 52448, 52448, 52449, 52450, 52450, \n\t52451, 52451, 52452, 52453, 52453, 52454, 52454, 52455, \n\t52456, 52456, 52457, 52457, 52458, 52459, 52459, 52460, \n\t52460, 52461, 52462, 52462, 52463, 52463, 52464, 52465, \n\t52465, 52466, 52466, 52467, 52468, 52468, 52469, 52469, \n\t52470, 52471, 52471, 52472, 52472, 52473, 52474, 52474, \n\t52475, 52475, 52476, 52477, 52477, 52478, 52478, 52479, \n\t52480, 52480, 52481, 52481, 52482, 52483, 52483, 52484, \n\t52484, 52485, 52486, 52486, 52487, 52487, 52488, 52489, \n\t52489, 52490, 52490, 52491, 52492, 52492, 52493, 52493, \n\t52494, 52495, 52495, 52496, 52496, 52497, 52498, 52498, \n\t52499, 52499, 52500, 52501, 52501, 52502, 52502, 52503, \n\t52504, 52504, 52505, 52505, 52506, 52507, 52507, 52508, \n\t52508, 52509, 52510, 52510, 52511, 52511, 52512, 52513, \n\t52513, 52514, 52514, 52515, 52516, 52516, 52517, 52517, \n\t52518, 52519, 52519, 52520, 52520, 52521, 52522, 52522, \n\t52523, 52523, 52524, 52525, 52525, 52526, 52526, 52527, \n\t52528, 52528, 52529, 52529, 52530, 52530, 52531, 52532, \n\t52532, 52533, 52533, 52534, 52535, 52535, 52536, 52536, \n\t52537, 52538, 52538, 52539, 52539, 52540, 52541, 52541, \n\t52542, 52542, 52543, 52544, 52544, 52545, 52545, 52546, \n\t52547, 52547, 52548, 52548, 52549, 52550, 52550, 52551, \n\t52551, 52552, 52553, 52553, 52554, 52554, 52555, 52556, \n\t52556, 52557, 52557, 52558, 52559, 52559, 52560, 52560, \n\t52561, 52562, 52562, 52563, 52563, 52564, 52565, 52565, \n\t52566, 52566, 52567, 52568, 52568, 52569, 52569, 52570, \n\t52571, 52571, 52572, 52572, 52573, 52574, 52574, 52575, \n\t52575, 52576, 52576, 52577, 52578, 52578, 52579, 52579, \n\t52580, 52581, 52581, 52582, 52582, 52583, 52584, 52584, \n\t52585, 52585, 52586, 52587, 52587, 52588, 52588, 52589, \n\t52590, 52590, 52591, 52591, 52592, 52593, 52593, 52594, \n\t52594, 52595, 52596, 52596, 52597, 52597, 52598, 52599, \n\t52599, 52600, 52600, 52601, 52602, 52602, 52603, 52603, \n\t52604, 52605, 52605, 52606, 52606, 52607, 52608, 52608, \n\t52609, 52609, 52610, 52611, 52611, 52612, 52612, 52613, \n\t52613, 52614, 52615, 52615, 52616, 52616, 52617, 52618, \n\t52618, 52619, 52619, 52620, 52621, 52621, 52622, 52622, \n\t52623, 52624, 52624, 52625, 52625, 52626, 52627, 52627, \n\t52628, 52628, 52629, 52630, 52630, 52631, 52631, 52632, \n\t52633, 52633, 52634, 52634, 52635, 52636, 52636, 52637, \n\t52637, 52638, 52639, 52639, 52640, 52640, 52641, 52641, \n\t52642, 52643, 52643, 52644, 52644, 52645, 52646, 52646, \n\t52647, 52647, 52648, 52649, 52649, 52650, 52650, 52651, \n\t52652, 52652, 52653, 52653, 52654, 52655, 52655, 52656, \n\t52656, 52657, 52658, 52658, 52659, 52659, 52660, 52661, \n\t52661, 52662, 52662, 52663, 52664, 52664, 52665, 52665, \n\t52666, 52667, 52667, 52668, 52668, 52669, 52669, 52670, \n\t52671, 52671, 52672, 52672, 52673, 52674, 52674, 52675, \n\t52675, 52676, 52677, 52677, 52678, 52678, 52679, 52680, \n\t52680, 52681, 52681, 52682, 52683, 52683, 52684, 52684, \n\t52685, 52686, 52686, 52687, 52687, 52688, 52689, 52689, \n\t52690, 52690, 52691, 52691, 52692, 52693, 52693, 52694, \n\t52694, 52695, 52696, 52696, 52697, 52697, 52698, 52699, \n\t52699, 52700, 52700, 52701, 52702, 52702, 52703, 52703, \n\t52704, 52705, 52705, 52706, 52706, 52707, 52708, 52708, \n\t52709, 52709, 52710, 52711, 52711, 52712, 52712, 52713, \n\t52713, 52714, 52715, 52715, 52716, 52716, 52717, 52718, \n\t52718, 52719, 52719, 52720, 52721, 52721, 52722, 52722, \n\t52723, 52724, 52724, 52725, 52725, 52726, 52727, 52727, \n\t52728, 52728, 52729, 52730, 52730, 52731, 52731, 52732, \n\t52732, 52733, 52734, 52734, 52735, 52735, 52736, 52737, \n\t52737, 52738, 52738, 52739, 52740, 52740, 52741, 52741, \n\t52742, 52743, 52743, 52744, 52744, 52745, 52746, 52746, \n\t52747, 52747, 52748, 52749, 52749, 52750, 52750, 52751, \n\t52751, 52752, 52753, 52753, 52754, 52754, 52755, 52756, \n\t52756, 52757, 52757, 52758, 52759, 52759, 52760, 52760, \n\t52761, 52762, 52762, 52763, 52763, 52764, 52765, 52765, \n\t52766, 52766, 52767, 52767, 52768, 52769, 52769, 52770, \n\t52770, 52771, 52772, 52772, 52773, 52773, 52774, 52775, \n\t52775, 52776, 52776, 52777, 52778, 52778, 52779, 52779, \n\t52780, 52781, 52781, 52782, 52782, 52783, 52784, 52784, \n\t52785, 52785, 52786, 52786, 52787, 52788, 52788, 52789, \n\t52789, 52790, 52791, 52791, 52792, 52792, 52793, 52794, \n\t52794, 52795, 52795, 52796, 52797, 52797, 52798, 52798, \n\t52799, 52800, 52800, 52801, 52801, 52802, 52802, 52803, \n\t52804, 52804, 52805, 52805, 52806, 52807, 52807, 52808, \n\t52808, 52809, 52810, 52810, 52811, 52811, 52812, 52813, \n\t52813, 52814, 52814, 52815, 52815, 52816, 52817, 52817, \n\t52818, 52818, 52819, 52820, 52820, 52821, 52821, 52822, \n\t52823, 52823, 52824, 52824, 52825, 52826, 52826, 52827, \n\t52827, 52828, 52829, 52829, 52830, 52830, 52831, 52831, \n\t52832, 52833, 52833, 52834, 52834, 52835, 52836, 52836, \n\t52837, 52837, 52838, 52839, 52839, 52840, 52840, 52841, \n\t52842, 52842, 52843, 52843, 52844, 52844, 52845, 52846, \n\t52846, 52847, 52847, 52848, 52849, 52849, 52850, 52850, \n\t52851, 52852, 52852, 52853, 52853, 52854, 52855, 52855, \n\t52856, 52856, 52857, 52857, 52858, 52859, 52859, 52860, \n\t52860, 52861, 52862, 52862, 52863, 52863, 52864, 52865, \n\t52865, 52866, 52866, 52867, 52868, 52868, 52869, 52869, \n\t52870, 52871, 52871, 52872, 52872, 52873, 52873, 52874, \n\t52875, 52875, 52876, 52876, 52877, 52878, 52878, 52879, \n\t52879, 52880, 52881, 52881, 52882, 52882, 52883, 52883, \n\t52884, 52885, 52885, 52886, 52886, 52887, 52888, 52888, \n\t52889, 52889, 52890, 52891, 52891, 52892, 52892, 52893, \n\t52894, 52894, 52895, 52895, 52896, 52896, 52897, 52898, \n\t52898, 52899, 52899, 52900, 52901, 52901, 52902, 52902, \n\t52903, 52904, 52904, 52905, 52905, 52906, 52907, 52907, \n\t52908, 52908, 52909, 52909, 52910, 52911, 52911, 52912, \n\t52912, 52913, 52914, 52914, 52915, 52915, 52916, 52917, \n\t52917, 52918, 52918, 52919, 52920, 52920, 52921, 52921, \n\t52922, 52922, 52923, 52924, 52924, 52925, 52925, 52926, \n\t52927, 52927, 52928, 52928, 52929, 52930, 52930, 52931, \n\t52931, 52932, 52932, 52933, 52934, 52934, 52935, 52935, \n\t52936, 52937, 52937, 52938, 52938, 52939, 52940, 52940, \n\t52941, 52941, 52942, 52942, 52943, 52944, 52944, 52945, \n\t52945, 52946, 52947, 52947, 52948, 52948, 52949, 52950, \n\t52950, 52951, 52951, 52952, 52953, 52953, 52954, 52954, \n\t52955, 52955, 52956, 52957, 52957, 52958, 52958, 52959, \n\t52960, 52960, 52961, 52961, 52962, 52963, 52963, 52964, \n\t52964, 52965, 52965, 52966, 52967, 52967, 52968, 52968, \n\t52969, 52970, 52970, 52971, 52971, 52972, 52973, 52973, \n\t52974, 52974, 52975, 52975, 52976, 52977, 52977, 52978, \n\t52978, 52979, 52980, 52980, 52981, 52981, 52982, 52983, \n\t52983, 52984, 52984, 52985, 52985, 52986, 52987, 52987, \n\t52988, 52988, 52989, 52990, 52990, 52991, 52991, 52992, \n\t52993, 52993, 52994, 52994, 52995, 52995, 52996, 52997, \n\t52997, 52998, 52998, 52999, 53000, 53000, 53001, 53001, \n\t53002, 53003, 53003, 53004, 53004, 53005, 53005, 53006, \n\t53007, 53007, 53008, 53008, 53009, 53010, 53010, 53011, \n\t53011, 53012, 53013, 53013, 53014, 53014, 53015, 53015, \n\t53016, 53017, 53017, 53018, 53018, 53019, 53020, 53020, \n\t53021, 53021, 53022, 53023, 53023, 53024, 53024, 53025, \n\t53025, 53026, 53027, 53027, 53028, 53028, 53029, 53030, \n\t53030, 53031, 53031, 53032, 53033, 53033, 53034, 53034, \n\t53035, 53035, 53036, 53037, 53037, 53038, 53038, 53039, \n\t53040, 53040, 53041, 53041, 53042, 53043, 53043, 53044, \n\t53044, 53045, 53045, 53046, 53047, 53047, 53048, 53048, \n\t53049, 53050, 53050, 53051, 53051, 53052, 53053, 53053, \n\t53054, 53054, 53055, 53055, 53056, 53057, 53057, 53058, \n\t53058, 53059, 53060, 53060, 53061, 53061, 53062, 53062, \n\t53063, 53064, 53064, 53065, 53065, 53066, 53067, 53067, \n\t53068, 53068, 53069, 53070, 53070, 53071, 53071, 53072, \n\t53072, 53073, 53074, 53074, 53075, 53075, 53076, 53077, \n\t53077, 53078, 53078, 53079, 53079, 53080, 53081, 53081, \n\t53082, 53082, 53083, 53084, 53084, 53085, 53085, 53086, \n\t53087, 53087, 53088, 53088, 53089, 53089, 53090, 53091, \n\t53091, 53092, 53092, 53093, 53094, 53094, 53095, 53095, \n\t53096, 53096, 53097, 53098, 53098, 53099, 53099, 53100, \n\t53101, 53101, 53102, 53102, 53103, 53104, 53104, 53105, \n\t53105, 53106, 53106, 53107, 53108, 53108, 53109, 53109, \n\t53110, 53111, 53111, 53112, 53112, 53113, 53113, 53114, \n\t53115, 53115, 53116, 53116, 53117, 53118, 53118, 53119, \n\t53119, 53120, 53121, 53121, 53122, 53122, 53123, 53123, \n\t53124, 53125, 53125, 53126, 53126, 53127, 53128, 53128, \n\t53129, 53129, 53130, 53130, 53131, 53132, 53132, 53133, \n\t53133, 53134, 53135, 53135, 53136, 53136, 53137, 53138, \n\t53138, 53139, 53139, 53140, 53140, 53141, 53142, 53142, \n\t53143, 53143, 53144, 53145, 53145, 53146, 53146, 53147, \n\t53147, 53148, 53149, 53149, 53150, 53150, 53151, 53152, \n\t53152, 53153, 53153, 53154, 53154, 53155, 53156, 53156, \n\t53157, 53157, 53158, 53159, 53159, 53160, 53160, 53161, \n\t53161, 53162, 53163, 53163, 53164, 53164, 53165, 53166, \n\t53166, 53167, 53167, 53168, 53169, 53169, 53170, 53170, \n\t53171, 53171, 53172, 53173, 53173, 53174, 53174, 53175, \n\t53176, 53176, 53177, 53177, 53178, 53178, 53179, 53180, \n\t53180, 53181, 53181, 53182, 53183, 53183, 53184, 53184, \n\t53185, 53185, 53186, 53187, 53187, 53188, 53188, 53189, \n\t53190, 53190, 53191, 53191, 53192, 53192, 53193, 53194, \n\t53194, 53195, 53195, 53196, 53197, 53197, 53198, 53198, \n\t53199, 53199, 53200, 53201, 53201, 53202, 53202, 53203, \n\t53204, 53204, 53205, 53205, 53206, 53206, 53207, 53208, \n\t53208, 53209, 53209, 53210, 53211, 53211, 53212, 53212, \n\t53213, 53213, 53214, 53215, 53215, 53216, 53216, 53217, \n\t53218, 53218, 53219, 53219, 53220, 53220, 53221, 53222, \n\t53222, 53223, 53223, 53224, 53225, 53225, 53226, 53226, \n\t53227, 53227, 53228, 53229, 53229, 53230, 53230, 53231, \n\t53232, 53232, 53233, 53233, 53234, 53234, 53235, 53236, \n\t53236, 53237, 53237, 53238, 53239, 53239, 53240, 53240, \n\t53241, 53241, 53242, 53243, 53243, 53244, 53244, 53245, \n\t53246, 53246, 53247, 53247, 53248, 53248, 53249, 53250, \n\t53250, 53251, 53251, 53252, 53253, 53253, 53254, 53254, \n\t53255, 53255, 53256, 53257, 53257, 53258, 53258, 53259, \n\t53260, 53260, 53261, 53261, 53262, 53262, 53263, 53264, \n\t53264, 53265, 53265, 53266, 53267, 53267, 53268, 53268, \n\t53269, 53269, 53270, 53271, 53271, 53272, 53272, 53273, \n\t53274, 53274, 53275, 53275, 53276, 53276, 53277, 53278, \n\t53278, 53279, 53279, 53280, 53281, 53281, 53282, 53282, \n\t53283, 53283, 53284, 53285, 53285, 53286, 53286, 53287, \n\t53288, 53288, 53289, 53289, 53290, 53290, 53291, 53292, \n\t53292, 53293, 53293, 53294, 53295, 53295, 53296, 53296, \n\t53297, 53297, 53298, 53299, 53299, 53300, 53300, 53301, \n\t53301, 53302, 53303, 53303, 53304, 53304, 53305, 53306, \n\t53306, 53307, 53307, 53308, 53308, 53309, 53310, 53310, \n\t53311, 53311, 53312, 53313, 53313, 53314, 53314, 53315, \n\t53315, 53316, 53317, 53317, 53318, 53318, 53319, 53320, \n\t53320, 53321, 53321, 53322, 53322, 53323, 53324, 53324, \n\t53325, 53325, 53326, 53326, 53327, 53328, 53328, 53329, \n\t53329, 53330, 53331, 53331, 53332, 53332, 53333, 53333, \n\t53334, 53335, 53335, 53336, 53336, 53337, 53338, 53338, \n\t53339, 53339, 53340, 53340, 53341, 53342, 53342, 53343, \n\t53343, 53344, 53345, 53345, 53346, 53346, 53347, 53347, \n\t53348, 53349, 53349, 53350, 53350, 53351, 53351, 53352, \n\t53353, 53353, 53354, 53354, 53355, 53356, 53356, 53357, \n\t53357, 53358, 53358, 53359, 53360, 53360, 53361, 53361, \n\t53362, 53363, 53363, 53364, 53364, 53365, 53365, 53366, \n\t53367, 53367, 53368, 53368, 53369, 53369, 53370, 53371, \n\t53371, 53372, 53372, 53373, 53374, 53374, 53375, 53375, \n\t53376, 53376, 53377, 53378, 53378, 53379, 53379, 53380, \n\t53380, 53381, 53382, 53382, 53383, 53383, 53384, 53385, \n\t53385, 53386, 53386, 53387, 53387, 53388, 53389, 53389, \n\t53390, 53390, 53391, 53392, 53392, 53393, 53393, 53394, \n\t53394, 53395, 53396, 53396, 53397, 53397, 53398, 53398, \n\t53399, 53400, 53400, 53401, 53401, 53402, 53403, 53403, \n\t53404, 53404, 53405, 53405, 53406, 53407, 53407, 53408, \n\t53408, 53409, 53409, 53410, 53411, 53411, 53412, 53412, \n\t53413, 53414, 53414, 53415, 53415, 53416, 53416, 53417, \n\t53418, 53418, 53419, 53419, 53420, 53420, 53421, 53422, \n\t53422, 53423, 53423, 53424, 53425, 53425, 53426, 53426, \n\t53427, 53427, 53428, 53429, 53429, 53430, 53430, 53431, \n\t53431, 53432, 53433, 53433, 53434, 53434, 53435, 53436, \n\t53436, 53437, 53437, 53438, 53438, 53439, 53440, 53440, \n\t53441, 53441, 53442, 53442, 53443, 53444, 53444, 53445, \n\t53445, 53446, 53447, 53447, 53448, 53448, 53449, 53449, \n\t53450, 53451, 53451, 53452, 53452, 53453, 53453, 53454, \n\t53455, 53455, 53456, 53456, 53457, 53458, 53458, 53459, \n\t53459, 53460, 53460, 53461, 53462, 53462, 53463, 53463, \n\t53464, 53464, 53465, 53466, 53466, 53467, 53467, 53468, \n\t53469, 53469, 53470, 53470, 53471, 53471, 53472, 53473, \n\t53473, 53474, 53474, 53475, 53475, 53476, 53477, 53477, \n\t53478, 53478, 53479, 53480, 53480, 53481, 53481, 53482, \n\t53482, 53483, 53484, 53484, 53485, 53485, 53486, 53486, \n\t53487, 53488, 53488, 53489, 53489, 53490, 53490, 53491, \n\t53492, 53492, 53493, 53493, 53494, 53495, 53495, 53496, \n\t53496, 53497, 53497, 53498, 53499, 53499, 53500, 53500, \n\t53501, 53501, 53502, 53503, 53503, 53504, 53504, 53505, \n\t53506, 53506, 53507, 53507, 53508, 53508, 53509, 53510, \n\t53510, 53511, 53511, 53512, 53512, 53513, 53514, 53514, \n\t53515, 53515, 53516, 53516, 53517, 53518, 53518, 53519, \n\t53519, 53520, 53521, 53521, 53522, 53522, 53523, 53523, \n\t53524, 53525, 53525, 53526, 53526, 53527, 53527, 53528, \n\t53529, 53529, 53530, 53530, 53531, 53531, 53532, 53533, \n\t53533, 53534, 53534, 53535, 53536, 53536, 53537, 53537, \n\t53538, 53538, 53539, 53540, 53540, 53541, 53541, 53542, \n\t53542, 53543, 53544, 53544, 53545, 53545, 53546, 53546, \n\t53547, 53548, 53548, 53549, 53549, 53550, 53551, 53551, \n\t53552, 53552, 53553, 53553, 53554, 53555, 53555, 53556, \n\t53556, 53557, 53557, 53558, 53559, 53559, 53560, 53560, \n\t53561, 53561, 53562, 53563, 53563, 53564, 53564, 53565, \n\t53566, 53566, 53567, 53567, 53568, 53568, 53569, 53570, \n\t53570, 53571, 53571, 53572, 53572, 53573, 53574, 53574, \n\t53575, 53575, 53576, 53576, 53577, 53578, 53578, 53579, \n\t53579, 53580, 53580, 53581, 53582, 53582, 53583, 53583, \n\t53584, 53585, 53585, 53586, 53586, 53587, 53587, 53588, \n\t53589, 53589, 53590, 53590, 53591, 53591, 53592, 53593, \n\t53593, 53594, 53594, 53595, 53595, 53596, 53597, 53597, \n\t53598, 53598, 53599, 53599, 53600, 53601, 53601, 53602, \n\t53602, 53603, 53604, 53604, 53605, 53605, 53606, 53606, \n\t53607, 53608, 53608, 53609, 53609, 53610, 53610, 53611, \n\t53612, 53612, 53613, 53613, 53614, 53614, 53615, 53616, \n\t53616, 53617, 53617, 53618, 53618, 53619, 53620, 53620, \n\t53621, 53621, 53622, 53622, 53623, 53624, 53624, 53625, \n\t53625, 53626, 53627, 53627, 53628, 53628, 53629, 53629, \n\t53630, 53631, 53631, 53632, 53632, 53633, 53633, 53634, \n\t53635, 53635, 53636, 53636, 53637, 53637, 53638, 53639, \n\t53639, 53640, 53640, 53641, 53641, 53642, 53643, 53643, \n\t53644, 53644, 53645, 53645, 53646, 53647, 53647, 53648, \n\t53648, 53649, 53649, 53650, 53651, 53651, 53652, 53652, \n\t53653, 53654, 53654, 53655, 53655, 53656, 53656, 53657, \n\t53658, 53658, 53659, 53659, 53660, 53660, 53661, 53662, \n\t53662, 53663, 53663, 53664, 53664, 53665, 53666, 53666, \n\t53667, 53667, 53668, 53668, 53669, 53670, 53670, 53671, \n\t53671, 53672, 53672, 53673, 53674, 53674, 53675, 53675, \n\t53676, 53676, 53677, 53678, 53678, 53679, 53679, 53680, \n\t53680, 53681, 53682, 53682, 53683, 53683, 53684, 53684, \n\t53685, 53686, 53686, 53687, 53687, 53688, 53689, 53689, \n\t53690, 53690, 53691, 53691, 53692, 53693, 53693, 53694, \n\t53694, 53695, 53695, 53696, 53697, 53697, 53698, 53698, \n\t53699, 53699, 53700, 53701, 53701, 53702, 53702, 53703, \n\t53703, 53704, 53705, 53705, 53706, 53706, 53707, 53707, \n\t53708, 53709, 53709, 53710, 53710, 53711, 53711, 53712, \n\t53713, 53713, 53714, 53714, 53715, 53715, 53716, 53717, \n\t53717, 53718, 53718, 53719, 53719, 53720, 53721, 53721, \n\t53722, 53722, 53723, 53723, 53724, 53725, 53725, 53726, \n\t53726, 53727, 53727, 53728, 53729, 53729, 53730, 53730, \n\t53731, 53731, 53732, 53733, 53733, 53734, 53734, 53735, \n\t53735, 53736, 53737, 53737, 53738, 53738, 53739, 53740, \n\t53740, 53741, 53741, 53742, 53742, 53743, 53744, 53744, \n\t53745, 53745, 53746, 53746, 53747, 53748, 53748, 53749, \n\t53749, 53750, 53750, 53751, 53752, 53752, 53753, 53753, \n\t53754, 53754, 53755, 53756, 53756, 53757, 53757, 53758, \n\t53758, 53759, 53760, 53760, 53761, 53761, 53762, 53762, \n\t53763, 53764, 53764, 53765, 53765, 53766, 53766, 53767, \n\t53768, 53768, 53769, 53769, 53770, 53770, 53771, 53772, \n\t53772, 53773, 53773, 53774, 53774, 53775, 53776, 53776, \n\t53777, 53777, 53778, 53778, 53779, 53780, 53780, 53781, \n\t53781, 53782, 53782, 53783, 53784, 53784, 53785, 53785, \n\t53786, 53786, 53787, 53788, 53788, 53789, 53789, 53790, \n\t53790, 53791, 53792, 53792, 53793, 53793, 53794, 53794, \n\t53795, 53796, 53796, 53797, 53797, 53798, 53798, 53799, \n\t53800, 53800, 53801, 53801, 53802, 53802, 53803, 53804, \n\t53804, 53805, 53805, 53806, 53806, 53807, 53808, 53808, \n\t53809, 53809, 53810, 53810, 53811, 53812, 53812, 53813, \n\t53813, 53814, 53814, 53815, 53816, 53816, 53817, 53817, \n\t53818, 53818, 53819, 53820, 53820, 53821, 53821, 53822, \n\t53822, 53823, 53824, 53824, 53825, 53825, 53826, 53826, \n\t53827, 53827, 53828, 53829, 53829, 53830, 53830, 53831, \n\t53831, 53832, 53833, 53833, 53834, 53834, 53835, 53835, \n\t53836, 53837, 53837, 53838, 53838, 53839, 53839, 53840, \n\t53841, 53841, 53842, 53842, 53843, 53843, 53844, 53845, \n\t53845, 53846, 53846, 53847, 53847, 53848, 53849, 53849, \n\t53850, 53850, 53851, 53851, 53852, 53853, 53853, 53854, \n\t53854, 53855, 53855, 53856, 53857, 53857, 53858, 53858, \n\t53859, 53859, 53860, 53861, 53861, 53862, 53862, 53863, \n\t53863, 53864, 53865, 53865, 53866, 53866, 53867, 53867, \n\t53868, 53869, 53869, 53870, 53870, 53871, 53871, 53872, \n\t53873, 53873, 53874, 53874, 53875, 53875, 53876, 53877, \n\t53877, 53878, 53878, 53879, 53879, 53880, 53880, 53881, \n\t53882, 53882, 53883, 53883, 53884, 53884, 53885, 53886, \n\t53886, 53887, 53887, 53888, 53888, 53889, 53890, 53890, \n\t53891, 53891, 53892, 53892, 53893, 53894, 53894, 53895, \n\t53895, 53896, 53896, 53897, 53898, 53898, 53899, 53899, \n\t53900, 53900, 53901, 53902, 53902, 53903, 53903, 53904, \n\t53904, 53905, 53906, 53906, 53907, 53907, 53908, 53908, \n\t53909, 53910, 53910, 53911, 53911, 53912, 53912, 53913, \n\t53913, 53914, 53915, 53915, 53916, 53916, 53917, 53917, \n\t53918, 53919, 53919, 53920, 53920, 53921, 53921, 53922, \n\t53923, 53923, 53924, 53924, 53925, 53925, 53926, 53927, \n\t53927, 53928, 53928, 53929, 53929, 53930, 53931, 53931, \n\t53932, 53932, 53933, 53933, 53934, 53935, 53935, 53936, \n\t53936, 53937, 53937, 53938, 53938, 53939, 53940, 53940, \n\t53941, 53941, 53942, 53942, 53943, 53944, 53944, 53945, \n\t53945, 53946, 53946, 53947, 53948, 53948, 53949, 53949, \n\t53950, 53950, 53951, 53952, 53952, 53953, 53953, 53954, \n\t53954, 53955, 53956, 53956, 53957, 53957, 53958, 53958, \n\t53959, 53960, 53960, 53961, 53961, 53962, 53962, 53963, \n\t53963, 53964, 53965, 53965, 53966, 53966, 53967, 53967, \n\t53968, 53969, 53969, 53970, 53970, 53971, 53971, 53972, \n\t53973, 53973, 53974, 53974, 53975, 53975, 53976, 53977, \n\t53977, 53978, 53978, 53979, 53979, 53980, 53980, 53981, \n\t53982, 53982, 53983, 53983, 53984, 53984, 53985, 53986, \n\t53986, 53987, 53987, 53988, 53988, 53989, 53990, 53990, \n\t53991, 53991, 53992, 53992, 53993, 53994, 53994, 53995, \n\t53995, 53996, 53996, 53997, 53997, 53998, 53999, 53999, \n\t54000, 54000, 54001, 54001, 54002, 54003, 54003, 54004, \n\t54004, 54005, 54005, 54006, 54007, 54007, 54008, 54008, \n\t54009, 54009, 54010, 54011, 54011, 54012, 54012, 54013, \n\t54013, 54014, 54014, 54015, 54016, 54016, 54017, 54017, \n\t54018, 54018, 54019, 54020, 54020, 54021, 54021, 54022, \n\t54022, 54023, 54024, 54024, 54025, 54025, 54026, 54026, \n\t54027, 54028, 54028, 54029, 54029, 54030, 54030, 54031, \n\t54031, 54032, 54033, 54033, 54034, 54034, 54035, 54035, \n\t54036, 54037, 54037, 54038, 54038, 54039, 54039, 54040, \n\t54041, 54041, 54042, 54042, 54043, 54043, 54044, 54044, \n\t54045, 54046, 54046, 54047, 54047, 54048, 54048, 54049, \n\t54050, 54050, 54051, 54051, 54052, 54052, 54053, 54054, \n\t54054, 54055, 54055, 54056, 54056, 54057, 54057, 54058, \n\t54059, 54059, 54060, 54060, 54061, 54061, 54062, 54063, \n\t54063, 54064, 54064, 54065, 54065, 54066, 54067, 54067, \n\t54068, 54068, 54069, 54069, 54070, 54070, 54071, 54072, \n\t54072, 54073, 54073, 54074, 54074, 54075, 54076, 54076, \n\t54077, 54077, 54078, 54078, 54079, 54080, 54080, 54081, \n\t54081, 54082, 54082, 54083, 54083, 54084, 54085, 54085, \n\t54086, 54086, 54087, 54087, 54088, 54089, 54089, 54090, \n\t54090, 54091, 54091, 54092, 54093, 54093, 54094, 54094, \n\t54095, 54095, 54096, 54096, 54097, 54098, 54098, 54099, \n\t54099, 54100, 54100, 54101, 54102, 54102, 54103, 54103, \n\t54104, 54104, 54105, 54106, 54106, 54107, 54107, 54108, \n\t54108, 54109, 54109, 54110, 54111, 54111, 54112, 54112, \n\t54113, 54113, 54114, 54115, 54115, 54116, 54116, 54117, \n\t54117, 54118, 54118, 54119, 54120, 54120, 54121, 54121, \n\t54122, 54122, 54123, 54124, 54124, 54125, 54125, 54126, \n\t54126, 54127, 54128, 54128, 54129, 54129, 54130, 54130, \n\t54131, 54131, 54132, 54133, 54133, 54134, 54134, 54135, \n\t54135, 54136, 54137, 54137, 54138, 54138, 54139, 54139, \n\t54140, 54140, 54141, 54142, 54142, 54143, 54143, 54144, \n\t54144, 54145, 54146, 54146, 54147, 54147, 54148, 54148, \n\t54149, 54149, 54150, 54151, 54151, 54152, 54152, 54153, \n\t54153, 54154, 54155, 54155, 54156, 54156, 54157, 54157, \n\t54158, 54158, 54159, 54160, 54160, 54161, 54161, 54162, \n\t54162, 54163, 54164, 54164, 54165, 54165, 54166, 54166, \n\t54167, 54167, 54168, 54169, 54169, 54170, 54170, 54171, \n\t54171, 54172, 54173, 54173, 54174, 54174, 54175, 54175, \n\t54176, 54177, 54177, 54178, 54178, 54179, 54179, 54180, \n\t54180, 54181, 54182, 54182, 54183, 54183, 54184, 54184, \n\t54185, 54186, 54186, 54187, 54187, 54188, 54188, 54189, \n\t54189, 54190, 54191, 54191, 54192, 54192, 54193, 54193, \n\t54194, 54195, 54195, 54196, 54196, 54197, 54197, 54198, \n\t54198, 54199, 54200, 54200, 54201, 54201, 54202, 54202, \n\t54203, 54203, 54204, 54205, 54205, 54206, 54206, 54207, \n\t54207, 54208, 54209, 54209, 54210, 54210, 54211, 54211, \n\t54212, 54212, 54213, 54214, 54214, 54215, 54215, 54216, \n\t54216, 54217, 54218, 54218, 54219, 54219, 54220, 54220, \n\t54221, 54221, 54222, 54223, 54223, 54224, 54224, 54225, \n\t54225, 54226, 54227, 54227, 54228, 54228, 54229, 54229, \n\t54230, 54230, 54231, 54232, 54232, 54233, 54233, 54234, \n\t54234, 54235, 54236, 54236, 54237, 54237, 54238, 54238, \n\t54239, 54239, 54240, 54241, 54241, 54242, 54242, 54243, \n\t54243, 54244, 54244, 54245, 54246, 54246, 54247, 54247, \n\t54248, 54248, 54249, 54250, 54250, 54251, 54251, 54252, \n\t54252, 54253, 54253, 54254, 54255, 54255, 54256, 54256, \n\t54257, 54257, 54258, 54259, 54259, 54260, 54260, 54261, \n\t54261, 54262, 54262, 54263, 54264, 54264, 54265, 54265, \n\t54266, 54266, 54267, 54267, 54268, 54269, 54269, 54270, \n\t54270, 54271, 54271, 54272, 54273, 54273, 54274, 54274, \n\t54275, 54275, 54276, 54276, 54277, 54278, 54278, 54279, \n\t54279, 54280, 54280, 54281, 54282, 54282, 54283, 54283, \n\t54284, 54284, 54285, 54285, 54286, 54287, 54287, 54288, \n\t54288, 54289, 54289, 54290, 54290, 54291, 54292, 54292, \n\t54293, 54293, 54294, 54294, 54295, 54296, 54296, 54297, \n\t54297, 54298, 54298, 54299, 54299, 54300, 54301, 54301, \n\t54302, 54302, 54303, 54303, 54304, 54304, 54305, 54306, \n\t54306, 54307, 54307, 54308, 54308, 54309, 54310, 54310, \n\t54311, 54311, 54312, 54312, 54313, 54313, 54314, 54315, \n\t54315, 54316, 54316, 54317, 54317, 54318, 54318, 54319, \n\t54320, 54320, 54321, 54321, 54322, 54322, 54323, 54323, \n\t54324, 54325, 54325, 54326, 54326, 54327, 54327, 54328, \n\t54329, 54329, 54330, 54330, 54331, 54331, 54332, 54332, \n\t54333, 54334, 54334, 54335, 54335, 54336, 54336, 54337, \n\t54337, 54338, 54339, 54339, 54340, 54340, 54341, 54341, \n\t54342, 54343, 54343, 54344, 54344, 54345, 54345, 54346, \n\t54346, 54347, 54348, 54348, 54349, 54349, 54350, 54350, \n\t54351, 54351, 54352, 54353, 54353, 54354, 54354, 54355, \n\t54355, 54356, 54356, 54357, 54358, 54358, 54359, 54359, \n\t54360, 54360, 54361, 54362, 54362, 54363, 54363, 54364, \n\t54364, 54365, 54365, 54366, 54367, 54367, 54368, 54368, \n\t54369, 54369, 54370, 54370, 54371, 54372, 54372, 54373, \n\t54373, 54374, 54374, 54375, 54375, 54376, 54377, 54377, \n\t54378, 54378, 54379, 54379, 54380, 54380, 54381, 54382, \n\t54382, 54383, 54383, 54384, 54384, 54385, 54386, 54386, \n\t54387, 54387, 54388, 54388, 54389, 54389, 54390, 54391, \n\t54391, 54392, 54392, 54393, 54393, 54394, 54394, 54395, \n\t54396, 54396, 54397, 54397, 54398, 54398, 54399, 54399, \n\t54400, 54401, 54401, 54402, 54402, 54403, 54403, 54404, \n\t54404, 54405, 54406, 54406, 54407, 54407, 54408, 54408, \n\t54409, 54409, 54410, 54411, 54411, 54412, 54412, 54413, \n\t54413, 54414, 54415, 54415, 54416, 54416, 54417, 54417, \n\t54418, 54418, 54419, 54420, 54420, 54421, 54421, 54422, \n\t54422, 54423, 54423, 54424, 54425, 54425, 54426, 54426, \n\t54427, 54427, 54428, 54428, 54429, 54430, 54430, 54431, \n\t54431, 54432, 54432, 54433, 54433, 54434, 54435, 54435, \n\t54436, 54436, 54437, 54437, 54438, 54438, 54439, 54440, \n\t54440, 54441, 54441, 54442, 54442, 54443, 54443, 54444, \n\t54445, 54445, 54446, 54446, 54447, 54447, 54448, 54448, \n\t54449, 54450, 54450, 54451, 54451, 54452, 54452, 54453, \n\t54453, 54454, 54455, 54455, 54456, 54456, 54457, 54457, \n\t54458, 54458, 54459, 54460, 54460, 54461, 54461, 54462, \n\t54462, 54463, 54463, 54464, 54465, 54465, 54466, 54466, \n\t54467, 54467, 54468, 54469, 54469, 54470, 54470, 54471, \n\t54471, 54472, 54472, 54473, 54474, 54474, 54475, 54475, \n\t54476, 54476, 54477, 54477, 54478, 54479, 54479, 54480, \n\t54480, 54481, 54481, 54482, 54482, 54483, 54484, 54484, \n\t54485, 54485, 54486, 54486, 54487, 54487, 54488, 54489, \n\t54489, 54490, 54490, 54491, 54491, 54492, 54492, 54493, \n\t54494, 54494, 54495, 54495, 54496, 54496, 54497, 54497, \n\t54498, 54499, 54499, 54500, 54500, 54501, 54501, 54502, \n\t54502, 54503, 54504, 54504, 54505, 54505, 54506, 54506, \n\t54507, 54507, 54508, 54509, 54509, 54510, 54510, 54511, \n\t54511, 54512, 54512, 54513, 54514, 54514, 54515, 54515, \n\t54516, 54516, 54517, 54517, 54518, 54519, 54519, 54520, \n\t54520, 54521, 54521, 54522, 54522, 54523, 54523, 54524, \n\t54525, 54525, 54526, 54526, 54527, 54527, 54528, 54528, \n\t54529, 54530, 54530, 54531, 54531, 54532, 54532, 54533, \n\t54533, 54534, 54535, 54535, 54536, 54536, 54537, 54537, \n\t54538, 54538, 54539, 54540, 54540, 54541, 54541, 54542, \n\t54542, 54543, 54543, 54544, 54545, 54545, 54546, 54546, \n\t54547, 54547, 54548, 54548, 54549, 54550, 54550, 54551, \n\t54551, 54552, 54552, 54553, 54553, 54554, 54555, 54555, \n\t54556, 54556, 54557, 54557, 54558, 54558, 54559, 54560, \n\t54560, 54561, 54561, 54562, 54562, 54563, 54563, 54564, \n\t54565, 54565, 54566, 54566, 54567, 54567, 54568, 54568, \n\t54569, 54570, 54570, 54571, 54571, 54572, 54572, 54573, \n\t54573, 54574, 54574, 54575, 54576, 54576, 54577, 54577, \n\t54578, 54578, 54579, 54579, 54580, 54581, 54581, 54582, \n\t54582, 54583, 54583, 54584, 54584, 54585, 54586, 54586, \n\t54587, 54587, 54588, 54588, 54589, 54589, 54590, 54591, \n\t54591, 54592, 54592, 54593, 54593, 54594, 54594, 54595, \n\t54596, 54596, 54597, 54597, 54598, 54598, 54599, 54599, \n\t54600, 54600, 54601, 54602, 54602, 54603, 54603, 54604, \n\t54604, 54605, 54605, 54606, 54607, 54607, 54608, 54608, \n\t54609, 54609, 54610, 54610, 54611, 54612, 54612, 54613, \n\t54613, 54614, 54614, 54615, 54615, 54616, 54617, 54617, \n\t54618, 54618, 54619, 54619, 54620, 54620, 54621, 54622, \n\t54622, 54623, 54623, 54624, 54624, 54625, 54625, 54626, \n\t54626, 54627, 54628, 54628, 54629, 54629, 54630, 54630, \n\t54631, 54631, 54632, 54633, 54633, 54634, 54634, 54635, \n\t54635, 54636, 54636, 54637, 54638, 54638, 54639, 54639, \n\t54640, 54640, 54641, 54641, 54642, 54642, 54643, 54644, \n\t54644, 54645, 54645, 54646, 54646, 54647, 54647, 54648, \n\t54649, 54649, 54650, 54650, 54651, 54651, 54652, 54652, \n\t54653, 54654, 54654, 54655, 54655, 54656, 54656, 54657, \n\t54657, 54658, 54658, 54659, 54660, 54660, 54661, 54661, \n\t54662, 54662, 54663, 54663, 54664, 54665, 54665, 54666, \n\t54666, 54667, 54667, 54668, 54668, 54669, 54670, 54670, \n\t54671, 54671, 54672, 54672, 54673, 54673, 54674, 54674, \n\t54675, 54676, 54676, 54677, 54677, 54678, 54678, 54679, \n\t54679, 54680, 54681, 54681, 54682, 54682, 54683, 54683, \n\t54684, 54684, 54685, 54686, 54686, 54687, 54687, 54688, \n\t54688, 54689, 54689, 54690, 54690, 54691, 54692, 54692, \n\t54693, 54693, 54694, 54694, 54695, 54695, 54696, 54697, \n\t54697, 54698, 54698, 54699, 54699, 54700, 54700, 54701, \n\t54701, 54702, 54703, 54703, 54704, 54704, 54705, 54705, \n\t54706, 54706, 54707, 54708, 54708, 54709, 54709, 54710, \n\t54710, 54711, 54711, 54712, 54713, 54713, 54714, 54714, \n\t54715, 54715, 54716, 54716, 54717, 54717, 54718, 54719, \n\t54719, 54720, 54720, 54721, 54721, 54722, 54722, 54723, \n\t54724, 54724, 54725, 54725, 54726, 54726, 54727, 54727, \n\t54728, 54728, 54729, 54730, 54730, 54731, 54731, 54732, \n\t54732, 54733, 54733, 54734, 54735, 54735, 54736, 54736, \n\t54737, 54737, 54738, 54738, 54739, 54739, 54740, 54741, \n\t54741, 54742, 54742, 54743, 54743, 54744, 54744, 54745, \n\t54746, 54746, 54747, 54747, 54748, 54748, 54749, 54749, \n\t54750, 54750, 54751, 54752, 54752, 54753, 54753, 54754, \n\t54754, 54755, 54755, 54756, 54757, 54757, 54758, 54758, \n\t54759, 54759, 54760, 54760, 54761, 54761, 54762, 54763, \n\t54763, 54764, 54764, 54765, 54765, 54766, 54766, 54767, \n\t54767, 54768, 54769, 54769, 54770, 54770, 54771, 54771, \n\t54772, 54772, 54773, 54774, 54774, 54775, 54775, 54776, \n\t54776, 54777, 54777, 54778, 54778, 54779, 54780, 54780, \n\t54781, 54781, 54782, 54782, 54783, 54783, 54784, 54785, \n\t54785, 54786, 54786, 54787, 54787, 54788, 54788, 54789, \n\t54789, 54790, 54791, 54791, 54792, 54792, 54793, 54793, \n\t54794, 54794, 54795, 54795, 54796, 54797, 54797, 54798, \n\t54798, 54799, 54799, 54800, 54800, 54801, 54802, 54802, \n\t54803, 54803, 54804, 54804, 54805, 54805, 54806, 54806, \n\t54807, 54808, 54808, 54809, 54809, 54810, 54810, 54811, \n\t54811, 54812, 54812, 54813, 54814, 54814, 54815, 54815, \n\t54816, 54816, 54817, 54817, 54818, 54819, 54819, 54820, \n\t54820, 54821, 54821, 54822, 54822, 54823, 54823, 54824, \n\t54825, 54825, 54826, 54826, 54827, 54827, 54828, 54828, \n\t54829, 54829, 54830, 54831, 54831, 54832, 54832, 54833, \n\t54833, 54834, 54834, 54835, 54835, 54836, 54837, 54837, \n\t54838, 54838, 54839, 54839, 54840, 54840, 54841, 54842, \n\t54842, 54843, 54843, 54844, 54844, 54845, 54845, 54846, \n\t54846, 54847, 54848, 54848, 54849, 54849, 54850, 54850, \n\t54851, 54851, 54852, 54852, 54853, 54854, 54854, 54855, \n\t54855, 54856, 54856, 54857, 54857, 54858, 54858, 54859, \n\t54860, 54860, 54861, 54861, 54862, 54862, 54863, 54863, \n\t54864, 54864, 54865, 54866, 54866, 54867, 54867, 54868, \n\t54868, 54869, 54869, 54870, 54871, 54871, 54872, 54872, \n\t54873, 54873, 54874, 54874, 54875, 54875, 54876, 54877, \n\t54877, 54878, 54878, 54879, 54879, 54880, 54880, 54881, \n\t54881, 54882, 54883, 54883, 54884, 54884, 54885, 54885, \n\t54886, 54886, 54887, 54887, 54888, 54889, 54889, 54890, \n\t54890, 54891, 54891, 54892, 54892, 54893, 54893, 54894, \n\t54895, 54895, 54896, 54896, 54897, 54897, 54898, 54898, \n\t54899, 54899, 54900, 54901, 54901, 54902, 54902, 54903, \n\t54903, 54904, 54904, 54905, 54905, 54906, 54907, 54907, \n\t54908, 54908, 54909, 54909, 54910, 54910, 54911, 54911, \n\t54912, 54913, 54913, 54914, 54914, 54915, 54915, 54916, \n\t54916, 54917, 54917, 54918, 54919, 54919, 54920, 54920, \n\t54921, 54921, 54922, 54922, 54923, 54923, 54924, 54925, \n\t54925, 54926, 54926, 54927, 54927, 54928, 54928, 54929, \n\t54929, 54930, 54931, 54931, 54932, 54932, 54933, 54933, \n\t54934, 54934, 54935, 54935, 54936, 54937, 54937, 54938, \n\t54938, 54939, 54939, 54940, 54940, 54941, 54941, 54942, \n\t54943, 54943, 54944, 54944, 54945, 54945, 54946, 54946, \n\t54947, 54947, 54948, 54949, 54949, 54950, 54950, 54951, \n\t54951, 54952, 54952, 54953, 54953, 54954, 54955, 54955, \n\t54956, 54956, 54957, 54957, 54958, 54958, 54959, 54959, \n\t54960, 54961, 54961, 54962, 54962, 54963, 54963, 54964, \n\t54964, 54965, 54965, 54966, 54967, 54967, 54968, 54968, \n\t54969, 54969, 54970, 54970, 54971, 54971, 54972, 54973, \n\t54973, 54974, 54974, 54975, 54975, 54976, 54976, 54977, \n\t54977, 54978, 54979, 54979, 54980, 54980, 54981, 54981, \n\t54982, 54982, 54983, 54983, 54984, 54985, 54985, 54986, \n\t54986, 54987, 54987, 54988, 54988, 54989, 54989, 54990, \n\t54991, 54991, 54992, 54992, 54993, 54993, 54994, 54994, \n\t54995, 54995, 54996, 54996, 54997, 54998, 54998, 54999, \n\t54999, 55000, 55000, 55001, 55001, 55002, 55002, 55003, \n\t55004, 55004, 55005, 55005, 55006, 55006, 55007, 55007, \n\t55008, 55008, 55009, 55010, 55010, 55011, 55011, 55012, \n\t55012, 55013, 55013, 55014, 55014, 55015, 55016, 55016, \n\t55017, 55017, 55018, 55018, 55019, 55019, 55020, 55020, \n\t55021, 55021, 55022, 55023, 55023, 55024, 55024, 55025, \n\t55025, 55026, 55026, 55027, 55027, 55028, 55029, 55029, \n\t55030, 55030, 55031, 55031, 55032, 55032, 55033, 55033, \n\t55034, 55035, 55035, 55036, 55036, 55037, 55037, 55038, \n\t55038, 55039, 55039, 55040, 55040, 55041, 55042, 55042, \n\t55043, 55043, 55044, 55044, 55045, 55045, 55046, 55046, \n\t55047, 55048, 55048, 55049, 55049, 55050, 55050, 55051, \n\t55051, 55052, 55052, 55053, 55054, 55054, 55055, 55055, \n\t55056, 55056, 55057, 55057, 55058, 55058, 55059, 55059, \n\t55060, 55061, 55061, 55062, 55062, 55063, 55063, 55064, \n\t55064, 55065, 55065, 55066, 55067, 55067, 55068, 55068, \n\t55069, 55069, 55070, 55070, 55071, 55071, 55072, 55073, \n\t55073, 55074, 55074, 55075, 55075, 55076, 55076, 55077, \n\t55077, 55078, 55078, 55079, 55080, 55080, 55081, 55081, \n\t55082, 55082, 55083, 55083, 55084, 55084, 55085, 55086, \n\t55086, 55087, 55087, 55088, 55088, 55089, 55089, 55090, \n\t55090, 55091, 55091, 55092, 55093, 55093, 55094, 55094, \n\t55095, 55095, 55096, 55096, 55097, 55097, 55098, 55099, \n\t55099, 55100, 55100, 55101, 55101, 55102, 55102, 55103, \n\t55103, 55104, 55104, 55105, 55106, 55106, 55107, 55107, \n\t55108, 55108, 55109, 55109, 55110, 55110, 55111, 55111, \n\t55112, 55113, 55113, 55114, 55114, 55115, 55115, 55116, \n\t55116, 55117, 55117, 55118, 55119, 55119, 55120, 55120, \n\t55121, 55121, 55122, 55122, 55123, 55123, 55124, 55124, \n\t55125, 55126, 55126, 55127, 55127, 55128, 55128, 55129, \n\t55129, 55130, 55130, 55131, 55132, 55132, 55133, 55133, \n\t55134, 55134, 55135, 55135, 55136, 55136, 55137, 55137, \n\t55138, 55139, 55139, 55140, 55140, 55141, 55141, 55142, \n\t55142, 55143, 55143, 55144, 55144, 55145, 55146, 55146, \n\t55147, 55147, 55148, 55148, 55149, 55149, 55150, 55150, \n\t55151, 55152, 55152, 55153, 55153, 55154, 55154, 55155, \n\t55155, 55156, 55156, 55157, 55157, 55158, 55159, 55159, \n\t55160, 55160, 55161, 55161, 55162, 55162, 55163, 55163, \n\t55164, 55164, 55165, 55166, 55166, 55167, 55167, 55168, \n\t55168, 55169, 55169, 55170, 55170, 55171, 55171, 55172, \n\t55173, 55173, 55174, 55174, 55175, 55175, 55176, 55176, \n\t55177, 55177, 55178, 55178, 55179, 55180, 55180, 55181, \n\t55181, 55182, 55182, 55183, 55183, 55184, 55184, 55185, \n\t55186, 55186, 55187, 55187, 55188, 55188, 55189, 55189, \n\t55190, 55190, 55191, 55191, 55192, 55193, 55193, 55194, \n\t55194, 55195, 55195, 55196, 55196, 55197, 55197, 55198, \n\t55198, 55199, 55200, 55200, 55201, 55201, 55202, 55202, \n\t55203, 55203, 55204, 55204, 55205, 55205, 55206, 55207, \n\t55207, 55208, 55208, 55209, 55209, 55210, 55210, 55211, \n\t55211, 55212, 55212, 55213, 55214, 55214, 55215, 55215, \n\t55216, 55216, 55217, 55217, 55218, 55218, 55219, 55219, \n\t55220, 55221, 55221, 55222, 55222, 55223, 55223, 55224, \n\t55224, 55225, 55225, 55226, 55226, 55227, 55228, 55228, \n\t55229, 55229, 55230, 55230, 55231, 55231, 55232, 55232, \n\t55233, 55233, 55234, 55235, 55235, 55236, 55236, 55237, \n\t55237, 55238, 55238, 55239, 55239, 55240, 55240, 55241, \n\t55242, 55242, 55243, 55243, 55244, 55244, 55245, 55245, \n\t55246, 55246, 55247, 55247, 55248, 55249, 55249, 55250, \n\t55250, 55251, 55251, 55252, 55252, 55253, 55253, 55254, \n\t55254, 55255, 55256, 55256, 55257, 55257, 55258, 55258, \n\t55259, 55259, 55260, 55260, 55261, 55261, 55262, 55263, \n\t55263, 55264, 55264, 55265, 55265, 55266, 55266, 55267, \n\t55267, 55268, 55268, 55269, 55269, 55270, 55271, 55271, \n\t55272, 55272, 55273, 55273, 55274, 55274, 55275, 55275, \n\t55276, 55276, 55277, 55278, 55278, 55279, 55279, 55280, \n\t55280, 55281, 55281, 55282, 55282, 55283, 55283, 55284, \n\t55285, 55285, 55286, 55286, 55287, 55287, 55288, 55288, \n\t55289, 55289, 55290, 55290, 55291, 55292, 55292, 55293, \n\t55293, 55294, 55294, 55295, 55295, 55296, 55296, 55297, \n\t55297, 55298, 55298, 55299, 55300, 55300, 55301, 55301, \n\t55302, 55302, 55303, 55303, 55304, 55304, 55305, 55305, \n\t55306, 55307, 55307, 55308, 55308, 55309, 55309, 55310, \n\t55310, 55311, 55311, 55312, 55312, 55313, 55314, 55314, \n\t55315, 55315, 55316, 55316, 55317, 55317, 55318, 55318, \n\t55319, 55319, 55320, 55320, 55321, 55322, 55322, 55323, \n\t55323, 55324, 55324, 55325, 55325, 55326, 55326, 55327, \n\t55327, 55328, 55329, 55329, 55330, 55330, 55331, 55331, \n\t55332, 55332, 55333, 55333, 55334, 55334, 55335, 55335, \n\t55336, 55337, 55337, 55338, 55338, 55339, 55339, 55340, \n\t55340, 55341, 55341, 55342, 55342, 55343, 55344, 55344, \n\t55345, 55345, 55346, 55346, 55347, 55347, 55348, 55348, \n\t55349, 55349, 55350, 55350, 55351, 55352, 55352, 55353, \n\t55353, 55354, 55354, 55355, 55355, 55356, 55356, 55357, \n\t55357, 55358, 55359, 55359, 55360, 55360, 55361, 55361, \n\t55362, 55362, 55363, 55363, 55364, 55364, 55365, 55365, \n\t55366, 55367, 55367, 55368, 55368, 55369, 55369, 55370, \n\t55370, 55371, 55371, 55372, 55372, 55373, 55374, 55374, \n\t55375, 55375, 55376, 55376, 55377, 55377, 55378, 55378, \n\t55379, 55379, 55380, 55380, 55381, 55382, 55382, 55383, \n\t55383, 55384, 55384, 55385, 55385, 55386, 55386, 55387, \n\t55387, 55388, 55388, 55389, 55390, 55390, 55391, 55391, \n\t55392, 55392, 55393, 55393, 55394, 55394, 55395, 55395, \n\t55396, 55396, 55397, 55398, 55398, 55399, 55399, 55400, \n\t55400, 55401, 55401, 55402, 55402, 55403, 55403, 55404, \n\t55405, 55405, 55406, 55406, 55407, 55407, 55408, 55408, \n\t55409, 55409, 55410, 55410, 55411, 55411, 55412, 55413, \n\t55413, 55414, 55414, 55415, 55415, 55416, 55416, 55417, \n\t55417, 55418, 55418, 55419, 55419, 55420, 55421, 55421, \n\t55422, 55422, 55423, 55423, 55424, 55424, 55425, 55425, \n\t55426, 55426, 55427, 55427, 55428, 55429, 55429, 55430, \n\t55430, 55431, 55431, 55432, 55432, 55433, 55433, 55434, \n\t55434, 55435, 55435, 55436, 55437, 55437, 55438, 55438, \n\t55439, 55439, 55440, 55440, 55441, 55441, 55442, 55442, \n\t55443, 55443, 55444, 55445, 55445, 55446, 55446, 55447, \n\t55447, 55448, 55448, 55449, 55449, 55450, 55450, 55451, \n\t55451, 55452, 55453, 55453, 55454, 55454, 55455, 55455, \n\t55456, 55456, 55457, 55457, 55458, 55458, 55459, 55459, \n\t55460, 55461, 55461, 55462, 55462, 55463, 55463, 55464, \n\t55464, 55465, 55465, 55466, 55466, 55467, 55467, 55468, \n\t55469, 55469, 55470, 55470, 55471, 55471, 55472, 55472, \n\t55473, 55473, 55474, 55474, 55475, 55475, 55476, 55476, \n\t55477, 55478, 55478, 55479, 55479, 55480, 55480, 55481, \n\t55481, 55482, 55482, 55483, 55483, 55484, 55484, 55485, \n\t55486, 55486, 55487, 55487, 55488, 55488, 55489, 55489, \n\t55490, 55490, 55491, 55491, 55492, 55492, 55493, 55494, \n\t55494, 55495, 55495, 55496, 55496, 55497, 55497, 55498, \n\t55498, 55499, 55499, 55500, 55500, 55501, 55502, 55502, \n\t55503, 55503, 55504, 55504, 55505, 55505, 55506, 55506, \n\t55507, 55507, 55508, 55508, 55509, 55509, 55510, 55511, \n\t55511, 55512, 55512, 55513, 55513, 55514, 55514, 55515, \n\t55515, 55516, 55516, 55517, 55517, 55518, 55519, 55519, \n\t55520, 55520, 55521, 55521, 55522, 55522, 55523, 55523, \n\t55524, 55524, 55525, 55525, 55526, 55526, 55527, 55528, \n\t55528, 55529, 55529, 55530, 55530, 55531, 55531, 55532, \n\t55532, 55533, 55533, 55534, 55534, 55535, 55536, 55536, \n\t55537, 55537, 55538, 55538, 55539, 55539, 55540, 55540, \n\t55541, 55541, 55542, 55542, 55543, 55543, 55544, 55545, \n\t55545, 55546, 55546, 55547, 55547, 55548, 55548, 55549, \n\t55549, 55550, 55550, 55551, 55551, 55552, 55552, 55553, \n\t55554, 55554, 55555, 55555, 55556, 55556, 55557, 55557, \n\t55558, 55558, 55559, 55559, 55560, 55560, 55561, 55562, \n\t55562, 55563, 55563, 55564, 55564, 55565, 55565, 55566, \n\t55566, 55567, 55567, 55568, 55568, 55569, 55569, 55570, \n\t55571, 55571, 55572, 55572, 55573, 55573, 55574, 55574, \n\t55575, 55575, 55576, 55576, 55577, 55577, 55578, 55578, \n\t55579, 55580, 55580, 55581, 55581, 55582, 55582, 55583, \n\t55583, 55584, 55584, 55585, 55585, 55586, 55586, 55587, \n\t55587, 55588, 55589, 55589, 55590, 55590, 55591, 55591, \n\t55592, 55592, 55593, 55593, 55594, 55594, 55595, 55595, \n\t55596, 55596, 55597, 55598, 55598, 55599, 55599, 55600, \n\t55600, 55601, 55601, 55602, 55602, 55603, 55603, 55604, \n\t55604, 55605, 55605, 55606, 55607, 55607, 55608, 55608, \n\t55609, 55609, 55610, 55610, 55611, 55611, 55612, 55612, \n\t55613, 55613, 55614, 55614, 55615, 55616, 55616, 55617, \n\t55617, 55618, 55618, 55619, 55619, 55620, 55620, 55621, \n\t55621, 55622, 55622, 55623, 55623, 55624, 55625, 55625, \n\t55626, 55626, 55627, 55627, 55628, 55628, 55629, 55629, \n\t55630, 55630, 55631, 55631, 55632, 55632, 55633, 55634, \n\t55634, 55635, 55635, 55636, 55636, 55637, 55637, 55638, \n\t55638, 55639, 55639, 55640, 55640, 55641, 55641, 55642, \n\t55642, 55643, 55644, 55644, 55645, 55645, 55646, 55646, \n\t55647, 55647, 55648, 55648, 55649, 55649, 55650, 55650, \n\t55651, 55651, 55652, 55653, 55653, 55654, 55654, 55655, \n\t55655, 55656, 55656, 55657, 55657, 55658, 55658, 55659, \n\t55659, 55660, 55660, 55661, 55662, 55662, 55663, 55663, \n\t55664, 55664, 55665, 55665, 55666, 55666, 55667, 55667, \n\t55668, 55668, 55669, 55669, 55670, 55670, 55671, 55672, \n\t55672, 55673, 55673, 55674, 55674, 55675, 55675, 55676, \n\t55676, 55677, 55677, 55678, 55678, 55679, 55679, 55680, \n\t55681, 55681, 55682, 55682, 55683, 55683, 55684, 55684, \n\t55685, 55685, 55686, 55686, 55687, 55687, 55688, 55688, \n\t55689, 55689, 55690, 55691, 55691, 55692, 55692, 55693, \n\t55693, 55694, 55694, 55695, 55695, 55696, 55696, 55697, \n\t55697, 55698, 55698, 55699, 55699, 55700, 55701, 55701, \n\t55702, 55702, 55703, 55703, 55704, 55704, 55705, 55705, \n\t55706, 55706, 55707, 55707, 55708, 55708, 55709, 55709, \n\t55710, 55711, 55711, 55712, 55712, 55713, 55713, 55714, \n\t55714, 55715, 55715, 55716, 55716, 55717, 55717, 55718, \n\t55718, 55719, 55719, 55720, 55721, 55721, 55722, 55722, \n\t55723, 55723, 55724, 55724, 55725, 55725, 55726, 55726, \n\t55727, 55727, 55728, 55728, 55729, 55729, 55730, 55731, \n\t55731, 55732, 55732, 55733, 55733, 55734, 55734, 55735, \n\t55735, 55736, 55736, 55737, 55737, 55738, 55738, 55739, \n\t55739, 55740, 55741, 55741, 55742, 55742, 55743, 55743, \n\t55744, 55744, 55745, 55745, 55746, 55746, 55747, 55747, \n\t55748, 55748, 55749, 55749, 55750, 55751, 55751, 55752, \n\t55752, 55753, 55753, 55754, 55754, 55755, 55755, 55756, \n\t55756, 55757, 55757, 55758, 55758, 55759, 55759, 55760, \n\t55761, 55761, 55762, 55762, 55763, 55763, 55764, 55764, \n\t55765, 55765, 55766, 55766, 55767, 55767, 55768, 55768, \n\t55769, 55769, 55770, 55770, 55771, 55772, 55772, 55773, \n\t55773, 55774, 55774, 55775, 55775, 55776, 55776, 55777, \n\t55777, 55778, 55778, 55779, 55779, 55780, 55780, 55781, \n\t55782, 55782, 55783, 55783, 55784, 55784, 55785, 55785, \n\t55786, 55786, 55787, 55787, 55788, 55788, 55789, 55789, \n\t55790, 55790, 55791, 55791, 55792, 55793, 55793, 55794, \n\t55794, 55795, 55795, 55796, 55796, 55797, 55797, 55798, \n\t55798, 55799, 55799, 55800, 55800, 55801, 55801, 55802, \n\t55803, 55803, 55804, 55804, 55805, 55805, 55806, 55806, \n\t55807, 55807, 55808, 55808, 55809, 55809, 55810, 55810, \n\t55811, 55811, 55812, 55812, 55813, 55814, 55814, 55815, \n\t55815, 55816, 55816, 55817, 55817, 55818, 55818, 55819, \n\t55819, 55820, 55820, 55821, 55821, 55822, 55822, 55823, \n\t55823, 55824, 55825, 55825, 55826, 55826, 55827, 55827, \n\t55828, 55828, 55829, 55829, 55830, 55830, 55831, 55831, \n\t55832, 55832, 55833, 55833, 55834, 55834, 55835, 55836, \n\t55836, 55837, 55837, 55838, 55838, 55839, 55839, 55840, \n\t55840, 55841, 55841, 55842, 55842, 55843, 55843, 55844, \n\t55844, 55845, 55845, 55846, 55847, 55847, 55848, 55848, \n\t55849, 55849, 55850, 55850, 55851, 55851, 55852, 55852, \n\t55853, 55853, 55854, 55854, 55855, 55855, 55856, 55856, \n\t55857, 55858, 55858, 55859, 55859, 55860, 55860, 55861, \n\t55861, 55862, 55862, 55863, 55863, 55864, 55864, 55865, \n\t55865, 55866, 55866, 55867, 55867, 55868, 55868, 55869, \n\t55870, 55870, 55871, 55871, 55872, 55872, 55873, 55873, \n\t55874, 55874, 55875, 55875, 55876, 55876, 55877, 55877, \n\t55878, 55878, 55879, 55879, 55880, 55881, 55881, 55882, \n\t55882, 55883, 55883, 55884, 55884, 55885, 55885, 55886, \n\t55886, 55887, 55887, 55888, 55888, 55889, 55889, 55890, \n\t55890, 55891, 55891, 55892, 55893, 55893, 55894, 55894, \n\t55895, 55895, 55896, 55896, 55897, 55897, 55898, 55898, \n\t55899, 55899, 55900, 55900, 55901, 55901, 55902, 55902, \n\t55903, 55903, 55904, 55905, 55905, 55906, 55906, 55907, \n\t55907, 55908, 55908, 55909, 55909, 55910, 55910, 55911, \n\t55911, 55912, 55912, 55913, 55913, 55914, 55914, 55915, \n\t55915, 55916, 55917, 55917, 55918, 55918, 55919, 55919, \n\t55920, 55920, 55921, 55921, 55922, 55922, 55923, 55923, \n\t55924, 55924, 55925, 55925, 55926, 55926, 55927, 55927, \n\t55928, 55929, 55929, 55930, 55930, 55931, 55931, 55932, \n\t55932, 55933, 55933, 55934, 55934, 55935, 55935, 55936, \n\t55936, 55937, 55937, 55938, 55938, 55939, 55939, 55940, \n\t55940, 55941, 55942, 55942, 55943, 55943, 55944, 55944, \n\t55945, 55945, 55946, 55946, 55947, 55947, 55948, 55948, \n\t55949, 55949, 55950, 55950, 55951, 55951, 55952, 55952, \n\t55953, 55954, 55954, 55955, 55955, 55956, 55956, 55957, \n\t55957, 55958, 55958, 55959, 55959, 55960, 55960, 55961, \n\t55961, 55962, 55962, 55963, 55963, 55964, 55964, 55965, \n\t55965, 55966, 55967, 55967, 55968, 55968, 55969, 55969, \n\t55970, 55970, 55971, 55971, 55972, 55972, 55973, 55973, \n\t55974, 55974, 55975, 55975, 55976, 55976, 55977, 55977, \n\t55978, 55978, 55979, 55980, 55980, 55981, 55981, 55982, \n\t55982, 55983, 55983, 55984, 55984, 55985, 55985, 55986, \n\t55986, 55987, 55987, 55988, 55988, 55989, 55989, 55990, \n\t55990, 55991, 55991, 55992, 55993, 55993, 55994, 55994, \n\t55995, 55995, 55996, 55996, 55997, 55997, 55998, 55998, \n\t55999, 55999, 56000, 56000, 56001, 56001, 56002, 56002, \n\t56003, 56003, 56004, 56004, 56005, 56006, 56006, 56007, \n\t56007, 56008, 56008, 56009, 56009, 56010, 56010, 56011, \n\t56011, 56012, 56012, 56013, 56013, 56014, 56014, 56015, \n\t56015, 56016, 56016, 56017, 56017, 56018, 56018, 56019, \n\t56020, 56020, 56021, 56021, 56022, 56022, 56023, 56023, \n\t56024, 56024, 56025, 56025, 56026, 56026, 56027, 56027, \n\t56028, 56028, 56029, 56029, 56030, 56030, 56031, 56031, \n\t56032, 56033, 56033, 56034, 56034, 56035, 56035, 56036, \n\t56036, 56037, 56037, 56038, 56038, 56039, 56039, 56040, \n\t56040, 56041, 56041, 56042, 56042, 56043, 56043, 56044, \n\t56044, 56045, 56045, 56046, 56047, 56047, 56048, 56048, \n\t56049, 56049, 56050, 56050, 56051, 56051, 56052, 56052, \n\t56053, 56053, 56054, 56054, 56055, 56055, 56056, 56056, \n\t56057, 56057, 56058, 56058, 56059, 56059, 56060, 56060, \n\t56061, 56062, 56062, 56063, 56063, 56064, 56064, 56065, \n\t56065, 56066, 56066, 56067, 56067, 56068, 56068, 56069, \n\t56069, 56070, 56070, 56071, 56071, 56072, 56072, 56073, \n\t56073, 56074, 56074, 56075, 56076, 56076, 56077, 56077, \n\t56078, 56078, 56079, 56079, 56080, 56080, 56081, 56081, \n\t56082, 56082, 56083, 56083, 56084, 56084, 56085, 56085, \n\t56086, 56086, 56087, 56087, 56088, 56088, 56089, 56089, \n\t56090, 56091, 56091, 56092, 56092, 56093, 56093, 56094, \n\t56094, 56095, 56095, 56096, 56096, 56097, 56097, 56098, \n\t56098, 56099, 56099, 56100, 56100, 56101, 56101, 56102, \n\t56102, 56103, 56103, 56104, 56104, 56105, 56106, 56106, \n\t56107, 56107, 56108, 56108, 56109, 56109, 56110, 56110, \n\t56111, 56111, 56112, 56112, 56113, 56113, 56114, 56114, \n\t56115, 56115, 56116, 56116, 56117, 56117, 56118, 56118, \n\t56119, 56119, 56120, 56120, 56121, 56122, 56122, 56123, \n\t56123, 56124, 56124, 56125, 56125, 56126, 56126, 56127, \n\t56127, 56128, 56128, 56129, 56129, 56130, 56130, 56131, \n\t56131, 56132, 56132, 56133, 56133, 56134, 56134, 56135, \n\t56135, 56136, 56136, 56137, 56138, 56138, 56139, 56139, \n\t56140, 56140, 56141, 56141, 56142, 56142, 56143, 56143, \n\t56144, 56144, 56145, 56145, 56146, 56146, 56147, 56147, \n\t56148, 56148, 56149, 56149, 56150, 56150, 56151, 56151, \n\t56152, 56152, 56153, 56154, 56154, 56155, 56155, 56156, \n\t56156, 56157, 56157, 56158, 56158, 56159, 56159, 56160, \n\t56160, 56161, 56161, 56162, 56162, 56163, 56163, 56164, \n\t56164, 56165, 56165, 56166, 56166, 56167, 56167, 56168, \n\t56168, 56169, 56169, 56170, 56171, 56171, 56172, 56172, \n\t56173, 56173, 56174, 56174, 56175, 56175, 56176, 56176, \n\t56177, 56177, 56178, 56178, 56179, 56179, 56180, 56180, \n\t56181, 56181, 56182, 56182, 56183, 56183, 56184, 56184, \n\t56185, 56185, 56186, 56186, 56187, 56188, 56188, 56189, \n\t56189, 56190, 56190, 56191, 56191, 56192, 56192, 56193, \n\t56193, 56194, 56194, 56195, 56195, 56196, 56196, 56197, \n\t56197, 56198, 56198, 56199, 56199, 56200, 56200, 56201, \n\t56201, 56202, 56202, 56203, 56203, 56204, 56204, 56205, \n\t56206, 56206, 56207, 56207, 56208, 56208, 56209, 56209, \n\t56210, 56210, 56211, 56211, 56212, 56212, 56213, 56213, \n\t56214, 56214, 56215, 56215, 56216, 56216, 56217, 56217, \n\t56218, 56218, 56219, 56219, 56220, 56220, 56221, 56221, \n\t56222, 56222, 56223, 56224, 56224, 56225, 56225, 56226, \n\t56226, 56227, 56227, 56228, 56228, 56229, 56229, 56230, \n\t56230, 56231, 56231, 56232, 56232, 56233, 56233, 56234, \n\t56234, 56235, 56235, 56236, 56236, 56237, 56237, 56238, \n\t56238, 56239, 56239, 56240, 56240, 56241, 56241, 56242, \n\t56243, 56243, 56244, 56244, 56245, 56245, 56246, 56246, \n\t56247, 56247, 56248, 56248, 56249, 56249, 56250, 56250, \n\t56251, 56251, 56252, 56252, 56253, 56253, 56254, 56254, \n\t56255, 56255, 56256, 56256, 56257, 56257, 56258, 56258, \n\t56259, 56259, 56260, 56260, 56261, 56261, 56262, 56263, \n\t56263, 56264, 56264, 56265, 56265, 56266, 56266, 56267, \n\t56267, 56268, 56268, 56269, 56269, 56270, 56270, 56271, \n\t56271, 56272, 56272, 56273, 56273, 56274, 56274, 56275, \n\t56275, 56276, 56276, 56277, 56277, 56278, 56278, 56279, \n\t56279, 56280, 56280, 56281, 56281, 56282, 56283, 56283, \n\t56284, 56284, 56285, 56285, 56286, 56286, 56287, 56287, \n\t56288, 56288, 56289, 56289, 56290, 56290, 56291, 56291, \n\t56292, 56292, 56293, 56293, 56294, 56294, 56295, 56295, \n\t56296, 56296, 56297, 56297, 56298, 56298, 56299, 56299, \n\t56300, 56300, 56301, 56301, 56302, 56302, 56303, 56304, \n\t56304, 56305, 56305, 56306, 56306, 56307, 56307, 56308, \n\t56308, 56309, 56309, 56310, 56310, 56311, 56311, 56312, \n\t56312, 56313, 56313, 56314, 56314, 56315, 56315, 56316, \n\t56316, 56317, 56317, 56318, 56318, 56319, 56319, 56320, \n\t56320, 56321, 56321, 56322, 56322, 56323, 56323, 56324, \n\t56324, 56325, 56325, 56326, 56327, 56327, 56328, 56328, \n\t56329, 56329, 56330, 56330, 56331, 56331, 56332, 56332, \n\t56333, 56333, 56334, 56334, 56335, 56335, 56336, 56336, \n\t56337, 56337, 56338, 56338, 56339, 56339, 56340, 56340, \n\t56341, 56341, 56342, 56342, 56343, 56343, 56344, 56344, \n\t56345, 56345, 56346, 56346, 56347, 56347, 56348, 56348, \n\t56349, 56350, 56350, 56351, 56351, 56352, 56352, 56353, \n\t56353, 56354, 56354, 56355, 56355, 56356, 56356, 56357, \n\t56357, 56358, 56358, 56359, 56359, 56360, 56360, 56361, \n\t56361, 56362, 56362, 56363, 56363, 56364, 56364, 56365, \n\t56365, 56366, 56366, 56367, 56367, 56368, 56368, 56369, \n\t56369, 56370, 56370, 56371, 56371, 56372, 56372, 56373, \n\t56373, 56374, 56375, 56375, 56376, 56376, 56377, 56377, \n\t56378, 56378, 56379, 56379, 56380, 56380, 56381, 56381, \n\t56382, 56382, 56383, 56383, 56384, 56384, 56385, 56385, \n\t56386, 56386, 56387, 56387, 56388, 56388, 56389, 56389, \n\t56390, 56390, 56391, 56391, 56392, 56392, 56393, 56393, \n\t56394, 56394, 56395, 56395, 56396, 56396, 56397, 56397, \n\t56398, 56398, 56399, 56399, 56400, 56401, 56401, 56402, \n\t56402, 56403, 56403, 56404, 56404, 56405, 56405, 56406, \n\t56406, 56407, 56407, 56408, 56408, 56409, 56409, 56410, \n\t56410, 56411, 56411, 56412, 56412, 56413, 56413, 56414, \n\t56414, 56415, 56415, 56416, 56416, 56417, 56417, 56418, \n\t56418, 56419, 56419, 56420, 56420, 56421, 56421, 56422, \n\t56422, 56423, 56423, 56424, 56424, 56425, 56425, 56426, \n\t56426, 56427, 56427, 56428, 56428, 56429, 56430, 56430, \n\t56431, 56431, 56432, 56432, 56433, 56433, 56434, 56434, \n\t56435, 56435, 56436, 56436, 56437, 56437, 56438, 56438, \n\t56439, 56439, 56440, 56440, 56441, 56441, 56442, 56442, \n\t56443, 56443, 56444, 56444, 56445, 56445, 56446, 56446, \n\t56447, 56447, 56448, 56448, 56449, 56449, 56450, 56450, \n\t56451, 56451, 56452, 56452, 56453, 56453, 56454, 56454, \n\t56455, 56455, 56456, 56456, 56457, 56457, 56458, 56458, \n\t56459, 56459, 56460, 56461, 56461, 56462, 56462, 56463, \n\t56463, 56464, 56464, 56465, 56465, 56466, 56466, 56467, \n\t56467, 56468, 56468, 56469, 56469, 56470, 56470, 56471, \n\t56471, 56472, 56472, 56473, 56473, 56474, 56474, 56475, \n\t56475, 56476, 56476, 56477, 56477, 56478, 56478, 56479, \n\t56479, 56480, 56480, 56481, 56481, 56482, 56482, 56483, \n\t56483, 56484, 56484, 56485, 56485, 56486, 56486, 56487, \n\t56487, 56488, 56488, 56489, 56489, 56490, 56490, 56491, \n\t56491, 56492, 56492, 56493, 56493, 56494, 56494, 56495, \n\t56496, 56496, 56497, 56497, 56498, 56498, 56499, 56499, \n\t56500, 56500, 56501, 56501, 56502, 56502, 56503, 56503, \n\t56504, 56504, 56505, 56505, 56506, 56506, 56507, 56507, \n\t56508, 56508, 56509, 56509, 56510, 56510, 56511, 56511, \n\t56512, 56512, 56513, 56513, 56514, 56514, 56515, 56515, \n\t56516, 56516, 56517, 56517, 56518, 56518, 56519, 56519, \n\t56520, 56520, 56521, 56521, 56522, 56522, 56523, 56523, \n\t56524, 56524, 56525, 56525, 56526, 56526, 56527, 56527, \n\t56528, 56528, 56529, 56529, 56530, 56530, 56531, 56531, \n\t56532, 56532, 56533, 56533, 56534, 56534, 56535, 56536, \n\t56536, 56537, 56537, 56538, 56538, 56539, 56539, 56540, \n\t56540, 56541, 56541, 56542, 56542, 56543, 56543, 56544, \n\t56544, 56545, 56545, 56546, 56546, 56547, 56547, 56548, \n\t56548, 56549, 56549, 56550, 56550, 56551, 56551, 56552, \n\t56552, 56553, 56553, 56554, 56554, 56555, 56555, 56556, \n\t56556, 56557, 56557, 56558, 56558, 56559, 56559, 56560, \n\t56560, 56561, 56561, 56562, 56562, 56563, 56563, 56564, \n\t56564, 56565, 56565, 56566, 56566, 56567, 56567, 56568, \n\t56568, 56569, 56569, 56570, 56570, 56571, 56571, 56572, \n\t56572, 56573, 56573, 56574, 56574, 56575, 56575, 56576, \n\t56576, 56577, 56577, 56578, 56578, 56579, 56579, 56580, \n\t56580, 56581, 56581, 56582, 56582, 56583, 56583, 56584, \n\t56585, 56585, 56586, 56586, 56587, 56587, 56588, 56588, \n\t56589, 56589, 56590, 56590, 56591, 56591, 56592, 56592, \n\t56593, 56593, 56594, 56594, 56595, 56595, 56596, 56596, \n\t56597, 56597, 56598, 56598, 56599, 56599, 56600, 56600, \n\t56601, 56601, 56602, 56602, 56603, 56603, 56604, 56604, \n\t56605, 56605, 56606, 56606, 56607, 56607, 56608, 56608, \n\t56609, 56609, 56610, 56610, 56611, 56611, 56612, 56612, \n\t56613, 56613, 56614, 56614, 56615, 56615, 56616, 56616, \n\t56617, 56617, 56618, 56618, 56619, 56619, 56620, 56620, \n\t56621, 56621, 56622, 56622, 56623, 56623, 56624, 56624, \n\t56625, 56625, 56626, 56626, 56627, 56627, 56628, 56628, \n\t56629, 56629, 56630, 56630, 56631, 56631, 56632, 56632, \n\t56633, 56633, 56634, 56634, 56635, 56635, 56636, 56636, \n\t56637, 56637, 56638, 56638, 56639, 56639, 56640, 56640, \n\t56641, 56641, 56642, 56642, 56643, 56643, 56644, 56644, \n\t56645, 56645, 56646, 56646, 56647, 56647, 56648, 56648, \n\t56649, 56649, 56650, 56650, 56651, 56651, 56652, 56652, \n\t56653, 56653, 56654, 56655, 56655, 56656, 56656, 56657, \n\t56657, 56658, 56658, 56659, 56659, 56660, 56660, 56661, \n\t56661, 56662, 56662, 56663, 56663, 56664, 56664, 56665, \n\t56665, 56666, 56666, 56667, 56667, 56668, 56668, 56669, \n\t56669, 56670, 56670, 56671, 56671, 56672, 56672, 56673, \n\t56673, 56674, 56674, 56675, 56675, 56676, 56676, 56677, \n\t56677, 56678, 56678, 56679, 56679, 56680, 56680, 56681, \n\t56681, 56682, 56682, 56683, 56683, 56684, 56684, 56685, \n\t56685, 56686, 56686, 56687, 56687, 56688, 56688, 56689, \n\t56689, 56690, 56690, 56691, 56691, 56692, 56692, 56693, \n\t56693, 56694, 56694, 56695, 56695, 56696, 56696, 56697, \n\t56697, 56698, 56698, 56699, 56699, 56700, 56700, 56701, \n\t56701, 56702, 56702, 56703, 56703, 56704, 56704, 56705, \n\t56705, 56706, 56706, 56707, 56707, 56708, 56708, 56709, \n\t56709, 56710, 56710, 56711, 56711, 56712, 56712, 56713, \n\t56713, 56714, 56714, 56715, 56715, 56716, 56716, 56717, \n\t56717, 56718, 56718, 56719, 56719, 56720, 56720, 56721, \n\t56721, 56722, 56722, 56723, 56723, 56724, 56724, 56725, \n\t56725, 56726, 56726, 56727, 56727, 56728, 56728, 56729, \n\t56729, 56730, 56730, 56731, 56731, 56732, 56732, 56733, \n\t56733, 56734, 56734, 56735, 56735, 56736, 56736, 56737, \n\t56737, 56738, 56738, 56739, 56739, 56740, 56740, 56741, \n\t56741, 56742, 56742, 56743, 56743, 56744, 56744, 56745, \n\t56745, 56746, 56746, 56747, 56747, 56748, 56748, 56749, \n\t56749, 56750, 56750, 56751, 56751, 56752, 56752, 56753, \n\t56753, 56754, 56754, 56755, 56755, 56756, 56756, 56757, \n\t56757, 56758, 56758, 56759, 56759, 56760, 56760, 56761, \n\t56761, 56762, 56762, 56763, 56763, 56764, 56764, 56765, \n\t56765, 56766, 56766, 56767, 56767, 56768, 56768, 56769, \n\t56769, 56770, 56770, 56771, 56771, 56772, 56772, 56773, \n\t56773, 56774, 56774, 56775, 56775, 56776, 56776, 56777, \n\t56777, 56778, 56778, 56779, 56779, 56780, 56780, 56781, \n\t56781, 56782, 56782, 56783, 56783, 56784, 56784, 56785, \n\t56785, 56786, 56786, 56787, 56787, 56788, 56788, 56789, \n\t56789, 56790, 56790, 56791, 56791, 56792, 56792, 56793, \n\t56793, 56794, 56794, 56795, 56795, 56796, 56796, 56797, \n\t56797, 56798, 56798, 56799, 56799, 56800, 56800, 56801, \n\t56801, 56802, 56802, 56803, 56803, 56804, 56804, 56805, \n\t56805, 56806, 56806, 56807, 56807, 56808, 56808, 56809, \n\t56809, 56810, 56810, 56811, 56811, 56812, 56812, 56813, \n\t56813, 56814, 56814, 56815, 56815, 56816, 56816, 56817, \n\t56817, 56818, 56818, 56819, 56819, 56820, 56820, 56821, \n\t56821, 56822, 56822, 56823, 56823, 56824, 56824, 56825, \n\t56825, 56826, 56826, 56827, 56827, 56828, 56828, 56829, \n\t56829, 56830, 56830, 56831, 56831, 56832, 56832, 56833, \n\t56833, 56834, 56834, 56835, 56835, 56836, 56836, 56837, \n\t56837, 56838, 56838, 56839, 56839, 56840, 56840, 56841, \n\t56841, 56842, 56842, 56843, 56843, 56844, 56844, 56845, \n\t56845, 56846, 56846, 56847, 56847, 56848, 56848, 56849, \n\t56849, 56850, 56850, 56851, 56851, 56852, 56852, 56853, \n\t56853, 56854, 56854, 56855, 56855, 56856, 56856, 56857, \n\t56857, 56857, 56858, 56858, 56859, 56859, 56860, 56860, \n\t56861, 56861, 56862, 56862, 56863, 56863, 56864, 56864, \n\t56865, 56865, 56866, 56866, 56867, 56867, 56868, 56868, \n\t56869, 56869, 56870, 56870, 56871, 56871, 56872, 56872, \n\t56873, 56873, 56874, 56874, 56875, 56875, 56876, 56876, \n\t56877, 56877, 56878, 56878, 56879, 56879, 56880, 56880, \n\t56881, 56881, 56882, 56882, 56883, 56883, 56884, 56884, \n\t56885, 56885, 56886, 56886, 56887, 56887, 56888, 56888, \n\t56889, 56889, 56890, 56890, 56891, 56891, 56892, 56892, \n\t56893, 56893, 56894, 56894, 56895, 56895, 56896, 56896, \n\t56897, 56897, 56898, 56898, 56899, 56899, 56900, 56900, \n\t56901, 56901, 56902, 56902, 56903, 56903, 56904, 56904, \n\t56905, 56905, 56906, 56906, 56907, 56907, 56908, 56908, \n\t56909, 56909, 56910, 56910, 56911, 56911, 56912, 56912, \n\t56913, 56913, 56914, 56914, 56915, 56915, 56916, 56916, \n\t56917, 56917, 56918, 56918, 56919, 56919, 56920, 56920, \n\t56921, 56921, 56922, 56922, 56923, 56923, 56924, 56924, \n\t56925, 56925, 56926, 56926, 56926, 56927, 56927, 56928, \n\t56928, 56929, 56929, 56930, 56930, 56931, 56931, 56932, \n\t56932, 56933, 56933, 56934, 56934, 56935, 56935, 56936, \n\t56936, 56937, 56937, 56938, 56938, 56939, 56939, 56940, \n\t56940, 56941, 56941, 56942, 56942, 56943, 56943, 56944, \n\t56944, 56945, 56945, 56946, 56946, 56947, 56947, 56948, \n\t56948, 56949, 56949, 56950, 56950, 56951, 56951, 56952, \n\t56952, 56953, 56953, 56954, 56954, 56955, 56955, 56956, \n\t56956, 56957, 56957, 56958, 56958, 56959, 56959, 56960, \n\t56960, 56961, 56961, 56962, 56962, 56963, 56963, 56964, \n\t56964, 56965, 56965, 56966, 56966, 56967, 56967, 56968, \n\t56968, 56969, 56969, 56970, 56970, 56971, 56971, 56972, \n\t56972, 56973, 56973, 56974, 56974, 56974, 56975, 56975, \n\t56976, 56976, 56977, 56977, 56978, 56978, 56979, 56979, \n\t56980, 56980, 56981, 56981, 56982, 56982, 56983, 56983, \n\t56984, 56984, 56985, 56985, 56986, 56986, 56987, 56987, \n\t56988, 56988, 56989, 56989, 56990, 56990, 56991, 56991, \n\t56992, 56992, 56993, 56993, 56994, 56994, 56995, 56995, \n\t56996, 56996, 56997, 56997, 56998, 56998, 56999, 56999, \n\t57000, 57000, 57001, 57001, 57002, 57002, 57003, 57003, \n\t57004, 57004, 57005, 57005, 57006, 57006, 57007, 57007, \n\t57008, 57008, 57009, 57009, 57010, 57010, 57011, 57011, \n\t57012, 57012, 57013, 57013, 57013, 57014, 57014, 57015, \n\t57015, 57016, 57016, 57017, 57017, 57018, 57018, 57019, \n\t57019, 57020, 57020, 57021, 57021, 57022, 57022, 57023, \n\t57023, 57024, 57024, 57025, 57025, 57026, 57026, 57027, \n\t57027, 57028, 57028, 57029, 57029, 57030, 57030, 57031, \n\t57031, 57032, 57032, 57033, 57033, 57034, 57034, 57035, \n\t57035, 57036, 57036, 57037, 57037, 57038, 57038, 57039, \n\t57039, 57040, 57040, 57041, 57041, 57042, 57042, 57043, \n\t57043, 57044, 57044, 57045, 57045, 57046, 57046, 57046, \n\t57047, 57047, 57048, 57048, 57049, 57049, 57050, 57050, \n\t57051, 57051, 57052, 57052, 57053, 57053, 57054, 57054, \n\t57055, 57055, 57056, 57056, 57057, 57057, 57058, 57058, \n\t57059, 57059, 57060, 57060, 57061, 57061, 57062, 57062, \n\t57063, 57063, 57064, 57064, 57065, 57065, 57066, 57066, \n\t57067, 57067, 57068, 57068, 57069, 57069, 57070, 57070, \n\t57071, 57071, 57072, 57072, 57073, 57073, 57074, 57074, \n\t57075, 57075, 57076, 57076, 57077, 57077, 57077, 57078, \n\t57078, 57079, 57079, 57080, 57080, 57081, 57081, 57082, \n\t57082, 57083, 57083, 57084, 57084, 57085, 57085, 57086, \n\t57086, 57087, 57087, 57088, 57088, 57089, 57089, 57090, \n\t57090, 57091, 57091, 57092, 57092, 57093, 57093, 57094, \n\t57094, 57095, 57095, 57096, 57096, 57097, 57097, 57098, \n\t57098, 57099, 57099, 57100, 57100, 57101, 57101, 57102, \n\t57102, 57103, 57103, 57104, 57104, 57104, 57105, 57105, \n\t57106, 57106, 57107, 57107, 57108, 57108, 57109, 57109, \n\t57110, 57110, 57111, 57111, 57112, 57112, 57113, 57113, \n\t57114, 57114, 57115, 57115, 57116, 57116, 57117, 57117, \n\t57118, 57118, 57119, 57119, 57120, 57120, 57121, 57121, \n\t57122, 57122, 57123, 57123, 57124, 57124, 57125, 57125, \n\t57126, 57126, 57127, 57127, 57128, 57128, 57129, 57129, \n\t57129, 57130, 57130, 57131, 57131, 57132, 57132, 57133, \n\t57133, 57134, 57134, 57135, 57135, 57136, 57136, 57137, \n\t57137, 57138, 57138, 57139, 57139, 57140, 57140, 57141, \n\t57141, 57142, 57142, 57143, 57143, 57144, 57144, 57145, \n\t57145, 57146, 57146, 57147, 57147, 57148, 57148, 57149, \n\t57149, 57150, 57150, 57151, 57151, 57152, 57152, 57153, \n\t57153, 57153, 57154, 57154, 57155, 57155, 57156, 57156, \n\t57157, 57157, 57158, 57158, 57159, 57159, 57160, 57160, \n\t57161, 57161, 57162, 57162, 57163, 57163, 57164, 57164, \n\t57165, 57165, 57166, 57166, 57167, 57167, 57168, 57168, \n\t57169, 57169, 57170, 57170, 57171, 57171, 57172, 57172, \n\t57173, 57173, 57174, 57174, 57175, 57175, 57175, 57176, \n\t57176, 57177, 57177, 57178, 57178, 57179, 57179, 57180, \n\t57180, 57181, 57181, 57182, 57182, 57183, 57183, 57184, \n\t57184, 57185, 57185, 57186, 57186, 57187, 57187, 57188, \n\t57188, 57189, 57189, 57190, 57190, 57191, 57191, 57192, \n\t57192, 57193, 57193, 57194, 57194, 57195, 57195, 57196, \n\t57196, 57197, 57197, 57197, 57198, 57198, 57199, 57199, \n\t57200, 57200, 57201, 57201, 57202, 57202, 57203, 57203, \n\t57204, 57204, 57205, 57205, 57206, 57206, 57207, 57207, \n\t57208, 57208, 57209, 57209, 57210, 57210, 57211, 57211, \n\t57212, 57212, 57213, 57213, 57214, 57214, 57215, 57215, \n\t57216, 57216, 57217, 57217, 57217, 57218, 57218, 57219, \n\t57219, 57220, 57220, 57221, 57221, 57222, 57222, 57223, \n\t57223, 57224, 57224, 57225, 57225, 57226, 57226, 57227, \n\t57227, 57228, 57228, 57229, 57229, 57230, 57230, 57231, \n\t57231, 57232, 57232, 57233, 57233, 57234, 57234, 57235, \n\t57235, 57236, 57236, 57236, 57237, 57237, 57238, 57238, \n\t57239, 57239, 57240, 57240, 57241, 57241, 57242, 57242, \n\t57243, 57243, 57244, 57244, 57245, 57245, 57246, 57246, \n\t57247, 57247, 57248, 57248, 57249, 57249, 57250, 57250, \n\t57251, 57251, 57252, 57252, 57253, 57253, 57254, 57254, \n\t57255, 57255, 57255, 57256, 57256, 57257, 57257, 57258, \n\t57258, 57259, 57259, 57260, 57260, 57261, 57261, 57262, \n\t57262, 57263, 57263, 57264, 57264, 57265, 57265, 57266, \n\t57266, 57267, 57267, 57268, 57268, 57269, 57269, 57270, \n\t57270, 57271, 57271, 57272, 57272, 57272, 57273, 57273, \n\t57274, 57274, 57275, 57275, 57276, 57276, 57277, 57277, \n\t57278, 57278, 57279, 57279, 57280, 57280, 57281, 57281, \n\t57282, 57282, 57283, 57283, 57284, 57284, 57285, 57285, \n\t57286, 57286, 57287, 57287, 57288, 57288, 57289, 57289, \n\t57289, 57290, 57290, 57291, 57291, 57292, 57292, 57293, \n\t57293, 57294, 57294, 57295, 57295, 57296, 57296, 57297, \n\t57297, 57298, 57298, 57299, 57299, 57300, 57300, 57301, \n\t57301, 57302, 57302, 57303, 57303, 57304, 57304, 57305, \n\t57305, 57306, 57306, 57306, 57307, 57307, 57308, 57308, \n\t57309, 57309, 57310, 57310, 57311, 57311, 57312, 57312, \n\t57313, 57313, 57314, 57314, 57315, 57315, 57316, 57316, \n\t57317, 57317, 57318, 57318, 57319, 57319, 57320, 57320, \n\t57321, 57321, 57322, 57322, 57322, 57323, 57323, 57324, \n\t57324, 57325, 57325, 57326, 57326, 57327, 57327, 57328, \n\t57328, 57329, 57329, 57330, 57330, 57331, 57331, 57332, \n\t57332, 57333, 57333, 57334, 57334, 57335, 57335, 57336, \n\t57336, 57337, 57337, 57338, 57338, 57338, 57339, 57339, \n\t57340, 57340, 57341, 57341, 57342, 57342, 57343, 57343, \n\t57344, 57344, 57345, 57345, 57346, 57346, 57347, 57347, \n\t57348, 57348, 57349, 57349, 57350, 57350, 57351, 57351, \n\t57352, 57352, 57353, 57353, 57353, 57354, 57354, 57355, \n\t57355, 57356, 57356, 57357, 57357, 57358, 57358, 57359, \n\t57359, 57360, 57360, 57361, 57361, 57362, 57362, 57363, \n\t57363, 57364, 57364, 57365, 57365, 57366, 57366, 57367, \n\t57367, 57368, 57368, 57368, 57369, 57369, 57370, 57370, \n\t57371, 57371, 57372, 57372, 57373, 57373, 57374, 57374, \n\t57375, 57375, 57376, 57376, 57377, 57377, 57378, 57378, \n\t57379, 57379, 57380, 57380, 57381, 57381, 57382, 57382, \n\t57382, 57383, 57383, 57384, 57384, 57385, 57385, 57386, \n\t57386, 57387, 57387, 57388, 57388, 57389, 57389, 57390, \n\t57390, 57391, 57391, 57392, 57392, 57393, 57393, 57394, \n\t57394, 57395, 57395, 57396, 57396, 57396, 57397, 57397, \n\t57398, 57398, 57399, 57399, 57400, 57400, 57401, 57401, \n\t57402, 57402, 57403, 57403, 57404, 57404, 57405, 57405, \n\t57406, 57406, 57407, 57407, 57408, 57408, 57409, 57409, \n\t57410, 57410, 57410, 57411, 57411, 57412, 57412, 57413, \n\t57413, 57414, 57414, 57415, 57415, 57416, 57416, 57417, \n\t57417, 57418, 57418, 57419, 57419, 57420, 57420, 57421, \n\t57421, 57422, 57422, 57423, 57423, 57424, 57424, 57424, \n\t57425, 57425, 57426, 57426, 57427, 57427, 57428, 57428, \n\t57429, 57429, 57430, 57430, 57431, 57431, 57432, 57432, \n\t57433, 57433, 57434, 57434, 57435, 57435, 57436, 57436, \n\t57437, 57437, 57437, 57438, 57438, 57439, 57439, 57440, \n\t57440, 57441, 57441, 57442, 57442, 57443, 57443, 57444, \n\t57444, 57445, 57445, 57446, 57446, 57447, 57447, 57448, \n\t57448, 57449, 57449, 57450, 57450, 57450, 57451, 57451, \n\t57452, 57452, 57453, 57453, 57454, 57454, 57455, 57455, \n\t57456, 57456, 57457, 57457, 57458, 57458, 57459, 57459, \n\t57460, 57460, 57461, 57461, 57462, 57462, 57462, 57463, \n\t57463, 57464, 57464, 57465, 57465, 57466, 57466, 57467, \n\t57467, 57468, 57468, 57469, 57469, 57470, 57470, 57471, \n\t57471, 57472, 57472, 57473, 57473, 57474, 57474, 57475, \n\t57475, 57475, 57476, 57476, 57477, 57477, 57478, 57478, \n\t57479, 57479, 57480, 57480, 57481, 57481, 57482, 57482, \n\t57483, 57483, 57484, 57484, 57485, 57485, 57486, 57486, \n\t57487, 57487, 57487, 57488, 57488, 57489, 57489, 57490, \n\t57490, 57491, 57491, 57492, 57492, 57493, 57493, 57494, \n\t57494, 57495, 57495, 57496, 57496, 57497, 57497, 57498, \n\t57498, 57499, 57499, 57499, 57500, 57500, 57501, 57501, \n\t57502, 57502, 57503, 57503, 57504, 57504, 57505, 57505, \n\t57506, 57506, 57507, 57507, 57508, 57508, 57509, 57509, \n\t57510, 57510, 57511, 57511, 57511, 57512, 57512, 57513, \n\t57513, 57514, 57514, 57515, 57515, 57516, 57516, 57517, \n\t57517, 57518, 57518, 57519, 57519, 57520, 57520, 57521, \n\t57521, 57522, 57522, 57522, 57523, 57523, 57524, 57524, \n\t57525, 57525, 57526, 57526, 57527, 57527, 57528, 57528, \n\t57529, 57529, 57530, 57530, 57531, 57531, 57532, 57532, \n\t57533, 57533, 57534, 57534, 57534, 57535, 57535, 57536, \n\t57536, 57537, 57537, 57538, 57538, 57539, 57539, 57540, \n\t57540, 57541, 57541, 57542, 57542, 57543, 57543, 57544, \n\t57544, 57545, 57545, 57545, 57546, 57546, 57547, 57547, \n\t57548, 57548, 57549, 57549, 57550, 57550, 57551, 57551, \n\t57552, 57552, 57553, 57553, 57554, 57554, 57555, 57555, \n\t57556, 57556, 57556, 57557, 57557, 57558, 57558, 57559, \n\t57559, 57560, 57560, 57561, 57561, 57562, 57562, 57563, \n\t57563, 57564, 57564, 57565, 57565, 57566, 57566, 57567, \n\t57567, 57567, 57568, 57568, 57569, 57569, 57570, 57570, \n\t57571, 57571, 57572, 57572, 57573, 57573, 57574, 57574, \n\t57575, 57575, 57576, 57576, 57577, 57577, 57578, 57578, \n\t57578, 57579, 57579, 57580, 57580, 57581, 57581, 57582, \n\t57582, 57583, 57583, 57584, 57584, 57585, 57585, 57586, \n\t57586, 57587, 57587, 57588, 57588, 57588, 57589, 57589, \n\t57590, 57590, 57591, 57591, 57592, 57592, 57593, 57593, \n\t57594, 57594, 57595, 57595, 57596, 57596, 57597, 57597, \n\t57598, 57598, 57599, 57599, 57599, 57600, 57600, 57601, \n\t57601, 57602, 57602, 57603, 57603, 57604, 57604, 57605, \n\t57605, 57606, 57606, 57607, 57607, 57608, 57608, 57609, \n\t57609, 57609, 57610, 57610, 57611, 57611, 57612, 57612, \n\t57613, 57613, 57614, 57614, 57615, 57615, 57616, 57616, \n\t57617, 57617, 57618, 57618, 57619, 57619, 57619, 57620, \n\t57620, 57621, 57621, 57622, 57622, 57623, 57623, 57624, \n\t57624, 57625, 57625, 57626, 57626, 57627, 57627, 57628, \n\t57628, 57629, 57629, 57629, 57630, 57630, 57631, 57631, \n\t57632, 57632, 57633, 57633, 57634, 57634, 57635, 57635, \n\t57636, 57636, 57637, 57637, 57638, 57638, 57639, 57639, \n\t57639, 57640, 57640, 57641, 57641, 57642, 57642, 57643, \n\t57643, 57644, 57644, 57645, 57645, 57646, 57646, 57647, \n\t57647, 57648, 57648, 57649, 57649, 57649, 57650, 57650, \n\t57651, 57651, 57652, 57652, 57653, 57653, 57654, 57654, \n\t57655, 57655, 57656, 57656, 57657, 57657, 57658, 57658, \n\t57659, 57659, 57659, 57660, 57660, 57661, 57661, 57662, \n\t57662, 57663, 57663, 57664, 57664, 57665, 57665, 57666, \n\t57666, 57667, 57667, 57668, 57668, 57668, 57669, 57669, \n\t57670, 57670, 57671, 57671, 57672, 57672, 57673, 57673, \n\t57674, 57674, 57675, 57675, 57676, 57676, 57677, 57677, \n\t57678, 57678, 57678, 57679, 57679, 57680, 57680, 57681, \n\t57681, 57682, 57682, 57683, 57683, 57684, 57684, 57685, \n\t57685, 57686, 57686, 57687, 57687, 57687, 57688, 57688, \n\t57689, 57689, 57690, 57690, 57691, 57691, 57692, 57692, \n\t57693, 57693, 57694, 57694, 57695, 57695, 57696, 57696, \n\t57697, 57697, 57697, 57698, 57698, 57699, 57699, 57700, \n\t57700, 57701, 57701, 57702, 57702, 57703, 57703, 57704, \n\t57704, 57705, 57705, 57706, 57706, 57706, 57707, 57707, \n\t57708, 57708, 57709, 57709, 57710, 57710, 57711, 57711, \n\t57712, 57712, 57713, 57713, 57714, 57714, 57715, 57715, \n\t57715, 57716, 57716, 57717, 57717, 57718, 57718, 57719, \n\t57719, 57720, 57720, 57721, 57721, 57722, 57722, 57723, \n\t57723, 57724, 57724, 57724, 57725, 57725, 57726, 57726, \n\t57727, 57727, 57728, 57728, 57729, 57729, 57730, 57730, \n\t57731, 57731, 57732, 57732, 57733, 57733, 57733, 57734, \n\t57734, 57735, 57735, 57736, 57736, 57737, 57737, 57738, \n\t57738, 57739, 57739, 57740, 57740, 57741, 57741, 57741, \n\t57742, 57742, 57743, 57743, 57744, 57744, 57745, 57745, \n\t57746, 57746, 57747, 57747, 57748, 57748, 57749, 57749, \n\t57750, 57750, 57750, 57751, 57751, 57752, 57752, 57753, \n\t57753, 57754, 57754, 57755, 57755, 57756, 57756, 57757, \n\t57757, 57758, 57758, 57759, 57759, 57759, 57760, 57760, \n\t57761, 57761, 57762, 57762, 57763, 57763, 57764, 57764, \n\t57765, 57765, 57766, 57766, 57767, 57767, 57767, 57768, \n\t57768, 57769, 57769, 57770, 57770, 57771, 57771, 57772, \n\t57772, 57773, 57773, 57774, 57774, 57775, 57775, 57776, \n\t57776, 57776, 57777, 57777, 57778, 57778, 57779, 57779, \n\t57780, 57780, 57781, 57781, 57782, 57782, 57783, 57783, \n\t57784, 57784, 57784, 57785, 57785, 57786, 57786, 57787, \n\t57787, 57788, 57788, 57789, 57789, 57790, 57790, 57791, \n\t57791, 57792, 57792, 57793, 57793, 57793, 57794, 57794, \n\t57795, 57795, 57796, 57796, 57797, 57797, 57798, 57798, \n\t57799, 57799, 57800, 57800, 57801, 57801, 57801, 57802, \n\t57802, 57803, 57803, 57804, 57804, 57805, 57805, 57806, \n\t57806, 57807, 57807, 57808, 57808, 57809, 57809, 57809, \n\t57810, 57810, 57811, 57811, 57812, 57812, 57813, 57813, \n\t57814, 57814, 57815, 57815, 57816, 57816, 57817, 57817, \n\t57817, 57818, 57818, 57819, 57819, 57820, 57820, 57821, \n\t57821, 57822, 57822, 57823, 57823, 57824, 57824, 57825, \n\t57825, 57825, 57826, 57826, 57827, 57827, 57828, 57828, \n\t57829, 57829, 57830, 57830, 57831, 57831, 57832, 57832, \n\t57833, 57833, 57833, 57834, 57834, 57835, 57835, 57836, \n\t57836, 57837, 57837, 57838, 57838, 57839, 57839, 57840, \n\t57840, 57841, 57841, 57841, 57842, 57842, 57843, 57843, \n\t57844, 57844, 57845, 57845, 57846, 57846, 57847, 57847, \n\t57848, 57848, 57849, 57849, 57849, 57850, 57850, 57851, \n\t57851, 57852, 57852, 57853, 57853, 57854, 57854, 57855, \n\t57855, 57856, 57856, 57857, 57857, 57857, 57858, 57858, \n\t57859, 57859, 57860, 57860, 57861, 57861, 57862, 57862, \n\t57863, 57863, 57864, 57864, 57864, 57865, 57865, 57866, \n\t57866, 57867, 57867, 57868, 57868, 57869, 57869, 57870, \n\t57870, 57871, 57871, 57872, 57872, 57872, 57873, 57873, \n\t57874, 57874, 57875, 57875, 57876, 57876, 57877, 57877, \n\t57878, 57878, 57879, 57879, 57880, 57880, 57880, 57881, \n\t57881, 57882, 57882, 57883, 57883, 57884, 57884, 57885, \n\t57885, 57886, 57886, 57887, 57887, 57887, 57888, 57888, \n\t57889, 57889, 57890, 57890, 57891, 57891, 57892, 57892, \n\t57893, 57893, 57894, 57894, 57895, 57895, 57895, 57896, \n\t57896, 57897, 57897, 57898, 57898, 57899, 57899, 57900, \n\t57900, 57901, 57901, 57902, 57902, 57902, 57903, 57903, \n\t57904, 57904, 57905, 57905, 57906, 57906, 57907, 57907, \n\t57908, 57908, 57909, 57909, 57909, 57910, 57910, 57911, \n\t57911, 57912, 57912, 57913, 57913, 57914, 57914, 57915, \n\t57915, 57916, 57916, 57917, 57917, 57917, 57918, 57918, \n\t57919, 57919, 57920, 57920, 57921, 57921, 57922, 57922, \n\t57923, 57923, 57924, 57924, 57924, 57925, 57925, 57926, \n\t57926, 57927, 57927, 57928, 57928, 57929, 57929, 57930, \n\t57930, 57931, 57931, 57931, 57932, 57932, 57933, 57933, \n\t57934, 57934, 57935, 57935, 57936, 57936, 57937, 57937, \n\t57938, 57938, 57938, 57939, 57939, 57940, 57940, 57941, \n\t57941, 57942, 57942, 57943, 57943, 57944, 57944, 57945, \n\t57945, 57946, 57946, 57946, 57947, 57947, 57948, 57948, \n\t57949, 57949, 57950, 57950, 57951, 57951, 57952, 57952, \n\t57953, 57953, 57953, 57954, 57954, 57955, 57955, 57956, \n\t57956, 57957, 57957, 57958, 57958, 57959, 57959, 57960, \n\t57960, 57960, 57961, 57961, 57962, 57962, 57963, 57963, \n\t57964, 57964, 57965, 57965, 57966, 57966, 57967, 57967, \n\t57967, 57968, 57968, 57969, 57969, 57970, 57970, 57971, \n\t57971, 57972, 57972, 57973, 57973, 57974, 57974, 57974, \n\t57975, 57975, 57976, 57976, 57977, 57977, 57978, 57978, \n\t57979, 57979, 57980, 57980, 57981, 57981, 57981, 57982, \n\t57982, 57983, 57983, 57984, 57984, 57985, 57985, 57986, \n\t57986, 57987, 57987, 57987, 57988, 57988, 57989, 57989, \n\t57990, 57990, 57991, 57991, 57992, 57992, 57993, 57993, \n\t57994, 57994, 57994, 57995, 57995, 57996, 57996, 57997, \n\t57997, 57998, 57998, 57999, 57999, 58000, 58000, 58001, \n\t58001, 58001, 58002, 58002, 58003, 58003, 58004, 58004, \n\t58005, 58005, 58006, 58006, 58007, 58007, 58008, 58008, \n\t58008, 58009, 58009, 58010, 58010, 58011, 58011, 58012, \n\t58012, 58013, 58013, 58014, 58014, 58014, 58015, 58015, \n\t58016, 58016, 58017, 58017, 58018, 58018, 58019, 58019, \n\t58020, 58020, 58021, 58021, 58021, 58022, 58022, 58023, \n\t58023, 58024, 58024, 58025, 58025, 58026, 58026, 58027, \n\t58027, 58028, 58028, 58028, 58029, 58029, 58030, 58030, \n\t58031, 58031, 58032, 58032, 58033, 58033, 58034, 58034, \n\t58034, 58035, 58035, 58036, 58036, 58037, 58037, 58038, \n\t58038, 58039, 58039, 58040, 58040, 58041, 58041, 58041, \n\t58042, 58042, 58043, 58043, 58044, 58044, 58045, 58045, \n\t58046, 58046, 58047, 58047, 58047, 58048, 58048, 58049, \n\t58049, 58050, 58050, 58051, 58051, 58052, 58052, 58053, \n\t58053, 58054, 58054, 58054, 58055, 58055, 58056, 58056, \n\t58057, 58057, 58058, 58058, 58059, 58059, 58060, 58060, \n\t58060, 58061, 58061, 58062, 58062, 58063, 58063, 58064, \n\t58064, 58065, 58065, 58066, 58066, 58067, 58067, 58067, \n\t58068, 58068, 58069, 58069, 58070, 58070, 58071, 58071, \n\t58072, 58072, 58073, 58073, 58073, 58074, 58074, 58075, \n\t58075, 58076, 58076, 58077, 58077, 58078, 58078, 58079, \n\t58079, 58079, 58080, 58080, 58081, 58081, 58082, 58082, \n\t58083, 58083, 58084, 58084, 58085, 58085, 58086, 58086, \n\t58086, 58087, 58087, 58088, 58088, 58089, 58089, 58090, \n\t58090, 58091, 58091, 58092, 58092, 58092, 58093, 58093, \n\t58094, 58094, 58095, 58095, 58096, 58096, 58097, 58097, \n\t58098, 58098, 58098, 58099, 58099, 58100, 58100, 58101, \n\t58101, 58102, 58102, 58103, 58103, 58104, 58104, 58104, \n\t58105, 58105, 58106, 58106, 58107, 58107, 58108, 58108, \n\t58109, 58109, 58110, 58110, 58110, 58111, 58111, 58112, \n\t58112, 58113, 58113, 58114, 58114, 58115, 58115, 58116, \n\t58116, 58117, 58117, 58117, 58118, 58118, 58119, 58119, \n\t58120, 58120, 58121, 58121, 58122, 58122, 58123, 58123, \n\t58123, 58124, 58124, 58125, 58125, 58126, 58126, 58127, \n\t58127, 58128, 58128, 58129, 58129, 58129, 58130, 58130, \n\t58131, 58131, 58132, 58132, 58133, 58133, 58134, 58134, \n\t58135, 58135, 58135, 58136, 58136, 58137, 58137, 58138, \n\t58138, 58139, 58139, 58140, 58140, 58141, 58141, 58141, \n\t58142, 58142, 58143, 58143, 58144, 58144, 58145, 58145, \n\t58146, 58146, 58147, 58147, 58147, 58148, 58148, 58149, \n\t58149, 58150, 58150, 58151, 58151, 58152, 58152, 58153, \n\t58153, 58153, 58154, 58154, 58155, 58155, 58156, 58156, \n\t58157, 58157, 58158, 58158, 58159, 58159, 58159, 58160, \n\t58160, 58161, 58161, 58162, 58162, 58163, 58163, 58164, \n\t58164, 58164, 58165, 58165, 58166, 58166, 58167, 58167, \n\t58168, 58168, 58169, 58169, 58170, 58170, 58170, 58171, \n\t58171, 58172, 58172, 58173, 58173, 58174, 58174, 58175, \n\t58175, 58176, 58176, 58176, 58177, 58177, 58178, 58178, \n\t58179, 58179, 58180, 58180, 58181, 58181, 58182, 58182, \n\t58182, 58183, 58183, 58184, 58184, 58185, 58185, 58186, \n\t58186, 58187, 58187, 58188, 58188, 58188, 58189, 58189, \n\t58190, 58190, 58191, 58191, 58192, 58192, 58193, 58193, \n\t58193, 58194, 58194, 58195, 58195, 58196, 58196, 58197, \n\t58197, 58198, 58198, 58199, 58199, 58199, 58200, 58200, \n\t58201, 58201, 58202, 58202, 58203, 58203, 58204, 58204, \n\t58205, 58205, 58205, 58206, 58206, 58207, 58207, 58208, \n\t58208, 58209, 58209, 58210, 58210, 58211, 58211, 58211, \n\t58212, 58212, 58213, 58213, 58214, 58214, 58215, 58215, \n\t58216, 58216, 58216, 58217, 58217, 58218, 58218, 58219, \n\t58219, 58220, 58220, 58221, 58221, 58222, 58222, 58222, \n\t58223, 58223, 58224, 58224, 58225, 58225, 58226, 58226, \n\t58227, 58227, 58227, 58228, 58228, 58229, 58229, 58230, \n\t58230, 58231, 58231, 58232, 58232, 58233, 58233, 58233, \n\t58234, 58234, 58235, 58235, 58236, 58236, 58237, 58237, \n\t58238, 58238, 58239, 58239, 58239, 58240, 58240, 58241, \n\t58241, 58242, 58242, 58243, 58243, 58244, 58244, 58244, \n\t58245, 58245, 58246, 58246, 58247, 58247, 58248, 58248, \n\t58249, 58249, 58250, 58250, 58250, 58251, 58251, 58252, \n\t58252, 58253, 58253, 58254, 58254, 58255, 58255, 58255, \n\t58256, 58256, 58257, 58257, 58258, 58258, 58259, 58259, \n\t58260, 58260, 58261, 58261, 58261, 58262, 58262, 58263, \n\t58263, 58264, 58264, 58265, 58265, 58266, 58266, 58266, \n\t58267, 58267, 58268, 58268, 58269, 58269, 58270, 58270, \n\t58271, 58271, 58271, 58272, 58272, 58273, 58273, 58274, \n\t58274, 58275, 58275, 58276, 58276, 58277, 58277, 58277, \n\t58278, 58278, 58279, 58279, 58280, 58280, 58281, 58281, \n\t58282, 58282, 58282, 58283, 58283, 58284, 58284, 58285, \n\t58285, 58286, 58286, 58287, 58287, 58287, 58288, 58288, \n\t58289, 58289, 58290, 58290, 58291, 58291, 58292, 58292, \n\t58293, 58293, 58293, 58294, 58294, 58295, 58295, 58296, \n\t58296, 58297, 58297, 58298, 58298, 58298, 58299, 58299, \n\t58300, 58300, 58301, 58301, 58302, 58302, 58303, 58303, \n\t58303, 58304, 58304, 58305, 58305, 58306, 58306, 58307, \n\t58307, 58308, 58308, 58309, 58309, 58309, 58310, 58310, \n\t58311, 58311, 58312, 58312, 58313, 58313, 58314, 58314, \n\t58314, 58315, 58315, 58316, 58316, 58317, 58317, 58318, \n\t58318, 58319, 58319, 58319, 58320, 58320, 58321, 58321, \n\t58322, 58322, 58323, 58323, 58324, 58324, 58324, 58325, \n\t58325, 58326, 58326, 58327, 58327, 58328, 58328, 58329, \n\t58329, 58329, 58330, 58330, 58331, 58331, 58332, 58332, \n\t58333, 58333, 58334, 58334, 58335, 58335, 58335, 58336, \n\t58336, 58337, 58337, 58338, 58338, 58339, 58339, 58340, \n\t58340, 58340, 58341, 58341, 58342, 58342, 58343, 58343, \n\t58344, 58344, 58345, 58345, 58345, 58346, 58346, 58347, \n\t58347, 58348, 58348, 58349, 58349, 58350, 58350, 58350, \n\t58351, 58351, 58352, 58352, 58353, 58353, 58354, 58354, \n\t58355, 58355, 58355, 58356, 58356, 58357, 58357, 58358, \n\t58358, 58359, 58359, 58360, 58360, 58360, 58361, 58361, \n\t58362, 58362, 58363, 58363, 58364, 58364, 58365, 58365, \n\t58365, 58366, 58366, 58367, 58367, 58368, 58368, 58369, \n\t58369, 58370, 58370, 58370, 58371, 58371, 58372, 58372, \n\t58373, 58373, 58374, 58374, 58375, 58375, 58375, 58376, \n\t58376, 58377, 58377, 58378, 58378, 58379, 58379, 58380, \n\t58380, 58380, 58381, 58381, 58382, 58382, 58383, 58383, \n\t58384, 58384, 58385, 58385, 58385, 58386, 58386, 58387, \n\t58387, 58388, 58388, 58389, 58389, 58390, 58390, 58390, \n\t58391, 58391, 58392, 58392, 58393, 58393, 58394, 58394, \n\t58395, 58395, 58395, 58396, 58396, 58397, 58397, 58398, \n\t58398, 58399, 58399, 58400, 58400, 58400, 58401, 58401, \n\t58402, 58402, 58403, 58403, 58404, 58404, 58405, 58405, \n\t58405, 58406, 58406, 58407, 58407, 58408, 58408, 58409, \n\t58409, 58410, 58410, 58410, 58411, 58411, 58412, 58412, \n\t58413, 58413, 58414, 58414, 58415, 58415, 58415, 58416, \n\t58416, 58417, 58417, 58418, 58418, 58419, 58419, 58419, \n\t58420, 58420, 58421, 58421, 58422, 58422, 58423, 58423, \n\t58424, 58424, 58424, 58425, 58425, 58426, 58426, 58427, \n\t58427, 58428, 58428, 58429, 58429, 58429, 58430, 58430, \n\t58431, 58431, 58432, 58432, 58433, 58433, 58434, 58434, \n\t58434, 58435, 58435, 58436, 58436, 58437, 58437, 58438, \n\t58438, 58439, 58439, 58439, 58440, 58440, 58441, 58441, \n\t58442, 58442, 58443, 58443, 58443, 58444, 58444, 58445, \n\t58445, 58446, 58446, 58447, 58447, 58448, 58448, 58448, \n\t58449, 58449, 58450, 58450, 58451, 58451, 58452, 58452, \n\t58453, 58453, 58453, 58454, 58454, 58455, 58455, 58456, \n\t58456, 58457, 58457, 58458, 58458, 58458, 58459, 58459, \n\t58460, 58460, 58461, 58461, 58462, 58462, 58462, 58463, \n\t58463, 58464, 58464, 58465, 58465, 58466, 58466, 58467, \n\t58467, 58467, 58468, 58468, 58469, 58469, 58470, 58470, \n\t58471, 58471, 58472, 58472, 58472, 58473, 58473, 58474, \n\t58474, 58475, 58475, 58476, 58476, 58476, 58477, 58477, \n\t58478, 58478, 58479, 58479, 58480, 58480, 58481, 58481, \n\t58481, 58482, 58482, 58483, 58483, 58484, 58484, 58485, \n\t58485, 58486, 58486, 58486, 58487, 58487, 58488, 58488, \n\t58489, 58489, 58490, 58490, 58490, 58491, 58491, 58492, \n\t58492, 58493, 58493, 58494, 58494, 58495, 58495, 58495, \n\t58496, 58496, 58497, 58497, 58498, 58498, 58499, 58499, \n\t58499, 58500, 58500, 58501, 58501, 58502, 58502, 58503, \n\t58503, 58504, 58504, 58504, 58505, 58505, 58506, 58506, \n\t58507, 58507, 58508, 58508, 58509, 58509, 58509, 58510, \n\t58510, 58511, 58511, 58512, 58512, 58513, 58513, 58513, \n\t58514, 58514, 58515, 58515, 58516, 58516, 58517, 58517, \n\t58518, 58518, 58518, 58519, 58519, 58520, 58520, 58521, \n\t58521, 58522, 58522, 58522, 58523, 58523, 58524, 58524, \n\t58525, 58525, 58526, 58526, 58527, 58527, 58527, 58528, \n\t58528, 58529, 58529, 58530, 58530, 58531, 58531, 58531, \n\t58532, 58532, 58533, 58533, 58534, 58534, 58535, 58535, \n\t58536, 58536, 58536, 58537, 58537, 58538, 58538, 58539, \n\t58539, 58540, 58540, 58540, 58541, 58541, 58542, 58542, \n\t58543, 58543, 58544, 58544, 58545, 58545, 58545, 58546, \n\t58546, 58547, 58547, 58548, 58548, 58549, 58549, 58549, \n\t58550, 58550, 58551, 58551, 58552, 58552, 58553, 58553, \n\t58553, 58554, 58554, 58555, 58555, 58556, 58556, 58557, \n\t58557, 58558, 58558, 58558, 58559, 58559, 58560, 58560, \n\t58561, 58561, 58562, 58562, 58562, 58563, 58563, 58564, \n\t58564, 58565, 58565, 58566, 58566, 58567, 58567, 58567, \n\t58568, 58568, 58569, 58569, 58570, 58570, 58571, 58571, \n\t58571, 58572, 58572, 58573, 58573, 58574, 58574, 58575, \n\t58575, 58575, 58576, 58576, 58577, 58577, 58578, 58578, \n\t58579, 58579, 58580, 58580, 58580, 58581, 58581, 58582, \n\t58582, 58583, 58583, 58584, 58584, 58584, 58585, 58585, \n\t58586, 58586, 58587, 58587, 58588, 58588, 58588, 58589, \n\t58589, 58590, 58590, 58591, 58591, 58592, 58592, 58593, \n\t58593, 58593, 58594, 58594, 58595, 58595, 58596, 58596, \n\t58597, 58597, 58597, 58598, 58598, 58599, 58599, 58600, \n\t58600, 58601, 58601, 58601, 58602, 58602, 58603, 58603, \n\t58604, 58604, 58605, 58605, 58606, 58606, 58606, 58607, \n\t58607, 58608, 58608, 58609, 58609, 58610, 58610, 58610, \n\t58611, 58611, 58612, 58612, 58613, 58613, 58614, 58614, \n\t58614, 58615, 58615, 58616, 58616, 58617, 58617, 58618, \n\t58618, 58618, 58619, 58619, 58620, 58620, 58621, 58621, \n\t58622, 58622, 58623, 58623, 58623, 58624, 58624, 58625, \n\t58625, 58626, 58626, 58627, 58627, 58627, 58628, 58628, \n\t58629, 58629, 58630, 58630, 58631, 58631, 58631, 58632, \n\t58632, 58633, 58633, 58634, 58634, 58635, 58635, 58635, \n\t58636, 58636, 58637, 58637, 58638, 58638, 58639, 58639, \n\t58639, 58640, 58640, 58641, 58641, 58642, 58642, 58643, \n\t58643, 58643, 58644, 58644, 58645, 58645, 58646, 58646, \n\t58647, 58647, 58648, 58648, 58648, 58649, 58649, 58650, \n\t58650, 58651, 58651, 58652, 58652, 58652, 58653, 58653, \n\t58654, 58654, 58655, 58655, 58656, 58656, 58656, 58657, \n\t58657, 58658, 58658, 58659, 58659, 58660, 58660, 58660, \n\t58661, 58661, 58662, 58662, 58663, 58663, 58664, 58664, \n\t58664, 58665, 58665, 58666, 58666, 58667, 58667, 58668, \n\t58668, 58668, 58669, 58669, 58670, 58670, 58671, 58671, \n\t58672, 58672, 58672, 58673, 58673, 58674, 58674, 58675, \n\t58675, 58676, 58676, 58676, 58677, 58677, 58678, 58678, \n\t58679, 58679, 58680, 58680, 58681, 58681, 58681, 58682, \n\t58682, 58683, 58683, 58684, 58684, 58685, 58685, 58685, \n\t58686, 58686, 58687, 58687, 58688, 58688, 58689, 58689, \n\t58689, 58690, 58690, 58691, 58691, 58692, 58692, 58693, \n\t58693, 58693, 58694, 58694, 58695, 58695, 58696, 58696, \n\t58697, 58697, 58697, 58698, 58698, 58699, 58699, 58700, \n\t58700, 58701, 58701, 58701, 58702, 58702, 58703, 58703, \n\t58704, 58704, 58705, 58705, 58705, 58706, 58706, 58707, \n\t58707, 58708, 58708, 58709, 58709, 58709, 58710, 58710, \n\t58711, 58711, 58712, 58712, 58713, 58713, 58713, 58714, \n\t58714, 58715, 58715, 58716, 58716, 58717, 58717, 58717, \n\t58718, 58718, 58719, 58719, 58720, 58720, 58721, 58721, \n\t58721, 58722, 58722, 58723, 58723, 58724, 58724, 58725, \n\t58725, 58725, 58726, 58726, 58727, 58727, 58728, 58728, \n\t58729, 58729, 58729, 58730, 58730, 58731, 58731, 58732, \n\t58732, 58733, 58733, 58733, 58734, 58734, 58735, 58735, \n\t58736, 58736, 58736, 58737, 58737, 58738, 58738, 58739, \n\t58739, 58740, 58740, 58740, 58741, 58741, 58742, 58742, \n\t58743, 58743, 58744, 58744, 58744, 58745, 58745, 58746, \n\t58746, 58747, 58747, 58748, 58748, 58748, 58749, 58749, \n\t58750, 58750, 58751, 58751, 58752, 58752, 58752, 58753, \n\t58753, 58754, 58754, 58755, 58755, 58756, 58756, 58756, \n\t58757, 58757, 58758, 58758, 58759, 58759, 58760, 58760, \n\t58760, 58761, 58761, 58762, 58762, 58763, 58763, 58764, \n\t58764, 58764, 58765, 58765, 58766, 58766, 58767, 58767, \n\t58768, 58768, 58768, 58769, 58769, 58770, 58770, 58771, \n\t58771, 58771, 58772, 58772, 58773, 58773, 58774, 58774, \n\t58775, 58775, 58775, 58776, 58776, 58777, 58777, 58778, \n\t58778, 58779, 58779, 58779, 58780, 58780, 58781, 58781, \n\t58782, 58782, 58783, 58783, 58783, 58784, 58784, 58785, \n\t58785, 58786, 58786, 58787, 58787, 58787, 58788, 58788, \n\t58789, 58789, 58790, 58790, 58791, 58791, 58791, 58792, \n\t58792, 58793, 58793, 58794, 58794, 58794, 58795, 58795, \n\t58796, 58796, 58797, 58797, 58798, 58798, 58798, 58799, \n\t58799, 58800, 58800, 58801, 58801, 58802, 58802, 58802, \n\t58803, 58803, 58804, 58804, 58805, 58805, 58806, 58806, \n\t58806, 58807, 58807, 58808, 58808, 58809, 58809, 58809, \n\t58810, 58810, 58811, 58811, 58812, 58812, 58813, 58813, \n\t58813, 58814, 58814, 58815, 58815, 58816, 58816, 58817, \n\t58817, 58817, 58818, 58818, 58819, 58819, 58820, 58820, \n\t58821, 58821, 58821, 58822, 58822, 58823, 58823, 58824, \n\t58824, 58824, 58825, 58825, 58826, 58826, 58827, 58827, \n\t58828, 58828, 58828, 58829, 58829, 58830, 58830, 58831, \n\t58831, 58832, 58832, 58832, 58833, 58833, 58834, 58834, \n\t58835, 58835, 58836, 58836, 58836, 58837, 58837, 58838, \n\t58838, 58839, 58839, 58839, 58840, 58840, 58841, 58841, \n\t58842, 58842, 58843, 58843, 58843, 58844, 58844, 58845, \n\t58845, 58846, 58846, 58847, 58847, 58847, 58848, 58848, \n\t58849, 58849, 58850, 58850, 58850, 58851, 58851, 58852, \n\t58852, 58853, 58853, 58854, 58854, 58854, 58855, 58855, \n\t58856, 58856, 58857, 58857, 58858, 58858, 58858, 58859, \n\t58859, 58860, 58860, 58861, 58861, 58861, 58862, 58862, \n\t58863, 58863, 58864, 58864, 58865, 58865, 58865, 58866, \n\t58866, 58867, 58867, 58868, 58868, 58869, 58869, 58869, \n\t58870, 58870, 58871, 58871, 58872, 58872, 58872, 58873, \n\t58873, 58874, 58874, 58875, 58875, 58876, 58876, 58876, \n\t58877, 58877, 58878, 58878, 58879, 58879, 58879, 58880, \n\t58880, 58881, 58881, 58882, 58882, 58883, 58883, 58883, \n\t58884, 58884, 58885, 58885, 58886, 58886, 58887, 58887, \n\t58887, 58888, 58888, 58889, 58889, 58890, 58890, 58890, \n\t58891, 58891, 58892, 58892, 58893, 58893, 58894, 58894, \n\t58894, 58895, 58895, 58896, 58896, 58897, 58897, 58897, \n\t58898, 58898, 58899, 58899, 58900, 58900, 58901, 58901, \n\t58901, 58902, 58902, 58903, 58903, 58904, 58904, 58904, \n\t58905, 58905, 58906, 58906, 58907, 58907, 58908, 58908, \n\t58908, 58909, 58909, 58910, 58910, 58911, 58911, 58912, \n\t58912, 58912, 58913, 58913, 58914, 58914, 58915, 58915, \n\t58915, 58916, 58916, 58917, 58917, 58918, 58918, 58919, \n\t58919, 58919, 58920, 58920, 58921, 58921, 58922, 58922, \n\t58922, 58923, 58923, 58924, 58924, 58925, 58925, 58926, \n\t58926, 58926, 58927, 58927, 58928, 58928, 58929, 58929, \n\t58929, 58930, 58930, 58931, 58931, 58932, 58932, 58933, \n\t58933, 58933, 58934, 58934, 58935, 58935, 58936, 58936, \n\t58936, 58937, 58937, 58938, 58938, 58939, 58939, 58940, \n\t58940, 58940, 58941, 58941, 58942, 58942, 58943, 58943, \n\t58943, 58944, 58944, 58945, 58945, 58946, 58946, 58947, \n\t58947, 58947, 58948, 58948, 58949, 58949, 58950, 58950, \n\t58950, 58951, 58951, 58952, 58952, 58953, 58953, 58954, \n\t58954, 58954, 58955, 58955, 58956, 58956, 58957, 58957, \n\t58957, 58958, 58958, 58959, 58959, 58960, 58960, 58960, \n\t58961, 58961, 58962, 58962, 58963, 58963, 58964, 58964, \n\t58964, 58965, 58965, 58966, 58966, 58967, 58967, 58967, \n\t58968, 58968, 58969, 58969, 58970, 58970, 58971, 58971, \n\t58971, 58972, 58972, 58973, 58973, 58974, 58974, 58974, \n\t58975, 58975, 58976, 58976, 58977, 58977, 58978, 58978, \n\t58978, 58979, 58979, 58980, 58980, 58981, 58981, 58981, \n\t58982, 58982, 58983, 58983, 58984, 58984, 58984, 58985, \n\t58985, 58986, 58986, 58987, 58987, 58988, 58988, 58988, \n\t58989, 58989, 58990, 58990, 58991, 58991, 58991, 58992, \n\t58992, 58993, 58993, 58994, 58994, 58995, 58995, 58995, \n\t58996, 58996, 58997, 58997, 58998, 58998, 58998, 58999, \n\t58999, 59000, 59000, 59001, 59001, 59001, 59002, 59002, \n\t59003, 59003, 59004, 59004, 59005, 59005, 59005, 59006, \n\t59006, 59007, 59007, 59008, 59008, 59008, 59009, 59009, \n\t59010, 59010, 59011, 59011, 59011, 59012, 59012, 59013, \n\t59013, 59014, 59014, 59015, 59015, 59015, 59016, 59016, \n\t59017, 59017, 59018, 59018, 59018, 59019, 59019, 59020, \n\t59020, 59021, 59021, 59021, 59022, 59022, 59023, 59023, \n\t59024, 59024, 59025, 59025, 59025, 59026, 59026, 59027, \n\t59027, 59028, 59028, 59028, 59029, 59029, 59030, 59030, \n\t59031, 59031, 59031, 59032, 59032, 59033, 59033, 59034, \n\t59034, 59035, 59035, 59035, 59036, 59036, 59037, 59037, \n\t59038, 59038, 59038, 59039, 59039, 59040, 59040, 59041, \n\t59041, 59041, 59042, 59042, 59043, 59043, 59044, 59044, \n\t59044, 59045, 59045, 59046, 59046, 59047, 59047, 59048, \n\t59048, 59048, 59049, 59049, 59050, 59050, 59051, 59051, \n\t59051, 59052, 59052, 59053, 59053, 59054, 59054, 59054, \n\t59055, 59055, 59056, 59056, 59057, 59057, 59058, 59058, \n\t59058, 59059, 59059, 59060, 59060, 59061, 59061, 59061, \n\t59062, 59062, 59063, 59063, 59064, 59064, 59064, 59065, \n\t59065, 59066, 59066, 59067, 59067, 59067, 59068, 59068, \n\t59069, 59069, 59070, 59070, 59071, 59071, 59071, 59072, \n\t59072, 59073, 59073, 59074, 59074, 59074, 59075, 59075, \n\t59076, 59076, 59077, 59077, 59077, 59078, 59078, 59079, \n\t59079, 59080, 59080, 59080, 59081, 59081, 59082, 59082, \n\t59083, 59083, 59083, 59084, 59084, 59085, 59085, 59086, \n\t59086, 59087, 59087, 59087, 59088, 59088, 59089, 59089, \n\t59090, 59090, 59090, 59091, 59091, 59092, 59092, 59093, \n\t59093, 59093, 59094, 59094, 59095, 59095, 59096, 59096, \n\t59096, 59097, 59097, 59098, 59098, 59099, 59099, 59099, \n\t59100, 59100, 59101, 59101, 59102, 59102, 59103, 59103, \n\t59103, 59104, 59104, 59105, 59105, 59106, 59106, 59106, \n\t59107, 59107, 59108, 59108, 59109, 59109, 59109, 59110, \n\t59110, 59111, 59111, 59112, 59112, 59112, 59113, 59113, \n\t59114, 59114, 59115, 59115, 59115, 59116, 59116, 59117, \n\t59117, 59118, 59118, 59118, 59119, 59119, 59120, 59120, \n\t59121, 59121, 59122, 59122, 59122, 59123, 59123, 59124, \n\t59124, 59125, 59125, 59125, 59126, 59126, 59127, 59127, \n\t59128, 59128, 59128, 59129, 59129, 59130, 59130, 59131, \n\t59131, 59131, 59132, 59132, 59133, 59133, 59134, 59134, \n\t59134, 59135, 59135, 59136, 59136, 59137, 59137, 59137, \n\t59138, 59138, 59139, 59139, 59140, 59140, 59140, 59141, \n\t59141, 59142, 59142, 59143, 59143, 59144, 59144, 59144, \n\t59145, 59145, 59146, 59146, 59147, 59147, 59147, 59148, \n\t59148, 59149, 59149, 59150, 59150, 59150, 59151, 59151, \n\t59152, 59152, 59153, 59153, 59153, 59154, 59154, 59155, \n\t59155, 59156, 59156, 59156, 59157, 59157, 59158, 59158, \n\t59159, 59159, 59159, 59160, 59160, 59161, 59161, 59162, \n\t59162, 59162, 59163, 59163, 59164, 59164, 59165, 59165, \n\t59165, 59166, 59166, 59167, 59167, 59168, 59168, 59168, \n\t59169, 59169, 59170, 59170, 59171, 59171, 59171, 59172, \n\t59172, 59173, 59173, 59174, 59174, 59174, 59175, 59175, \n\t59176, 59176, 59177, 59177, 59177, 59178, 59178, 59179, \n\t59179, 59180, 59180, 59181, 59181, 59181, 59182, 59182, \n\t59183, 59183, 59184, 59184, 59184, 59185, 59185, 59186, \n\t59186, 59187, 59187, 59187, 59188, 59188, 59189, 59189, \n\t59190, 59190, 59190, 59191, 59191, 59192, 59192, 59193, \n\t59193, 59193, 59194, 59194, 59195, 59195, 59196, 59196, \n\t59196, 59197, 59197, 59198, 59198, 59199, 59199, 59199, \n\t59200, 59200, 59201, 59201, 59202, 59202, 59202, 59203, \n\t59203, 59204, 59204, 59205, 59205, 59205, 59206, 59206, \n\t59207, 59207, 59208, 59208, 59208, 59209, 59209, 59210, \n\t59210, 59211, 59211, 59211, 59212, 59212, 59213, 59213, \n\t59214, 59214, 59214, 59215, 59215, 59216, 59216, 59217, \n\t59217, 59217, 59218, 59218, 59219, 59219, 59220, 59220, \n\t59220, 59221, 59221, 59222, 59222, 59223, 59223, 59223, \n\t59224, 59224, 59225, 59225, 59226, 59226, 59226, 59227, \n\t59227, 59228, 59228, 59229, 59229, 59229, 59230, 59230, \n\t59231, 59231, 59232, 59232, 59232, 59233, 59233, 59234, \n\t59234, 59235, 59235, 59235, 59236, 59236, 59237, 59237, \n\t59238, 59238, 59238, 59239, 59239, 59240, 59240, 59241, \n\t59241, 59241, 59242, 59242, 59243, 59243, 59244, 59244, \n\t59244, 59245, 59245, 59246, 59246, 59246, 59247, 59247, \n\t59248, 59248, 59249, 59249, 59249, 59250, 59250, 59251, \n\t59251, 59252, 59252, 59252, 59253, 59253, 59254, 59254, \n\t59255, 59255, 59255, 59256, 59256, 59257, 59257, 59258, \n\t59258, 59258, 59259, 59259, 59260, 59260, 59261, 59261, \n\t59261, 59262, 59262, 59263, 59263, 59264, 59264, 59264, \n\t59265, 59265, 59266, 59266, 59267, 59267, 59267, 59268, \n\t59268, 59269, 59269, 59270, 59270, 59270, 59271, 59271, \n\t59272, 59272, 59273, 59273, 59273, 59274, 59274, 59275, \n\t59275, 59276, 59276, 59276, 59277, 59277, 59278, 59278, \n\t59279, 59279, 59279, 59280, 59280, 59281, 59281, 59282, \n\t59282, 59282, 59283, 59283, 59284, 59284, 59284, 59285, \n\t59285, 59286, 59286, 59287, 59287, 59287, 59288, 59288, \n\t59289, 59289, 59290, 59290, 59290, 59291, 59291, 59292, \n\t59292, 59293, 59293, 59293, 59294, 59294, 59295, 59295, \n\t59296, 59296, 59296, 59297, 59297, 59298, 59298, 59299, \n\t59299, 59299, 59300, 59300, 59301, 59301, 59302, 59302, \n\t59302, 59303, 59303, 59304, 59304, 59305, 59305, 59305, \n\t59306, 59306, 59307, 59307, 59307, 59308, 59308, 59309, \n\t59309, 59310, 59310, 59310, 59311, 59311, 59312, 59312, \n\t59313, 59313, 59313, 59314, 59314, 59315, 59315, 59316, \n\t59316, 59316, 59317, 59317, 59318, 59318, 59319, 59319, \n\t59319, 59320, 59320, 59321, 59321, 59322, 59322, 59322, \n\t59323, 59323, 59324, 59324, 59324, 59325, 59325, 59326, \n\t59326, 59327, 59327, 59327, 59328, 59328, 59329, 59329, \n\t59330, 59330, 59330, 59331, 59331, 59332, 59332, 59333, \n\t59333, 59333, 59334, 59334, 59335, 59335, 59336, 59336, \n\t59336, 59337, 59337, 59338, 59338, 59339, 59339, 59339, \n\t59340, 59340, 59341, 59341, 59341, 59342, 59342, 59343, \n\t59343, 59344, 59344, 59344, 59345, 59345, 59346, 59346, \n\t59347, 59347, 59347, 59348, 59348, 59349, 59349, 59350, \n\t59350, 59350, 59351, 59351, 59352, 59352, 59353, 59353, \n\t59353, 59354, 59354, 59355, 59355, 59355, 59356, 59356, \n\t59357, 59357, 59358, 59358, 59358, 59359, 59359, 59360, \n\t59360, 59361, 59361, 59361, 59362, 59362, 59363, 59363, \n\t59364, 59364, 59364, 59365, 59365, 59366, 59366, 59366, \n\t59367, 59367, 59368, 59368, 59369, 59369, 59369, 59370, \n\t59370, 59371, 59371, 59372, 59372, 59372, 59373, 59373, \n\t59374, 59374, 59375, 59375, 59375, 59376, 59376, 59377, \n\t59377, 59378, 59378, 59378, 59379, 59379, 59380, 59380, \n\t59380, 59381, 59381, 59382, 59382, 59383, 59383, 59383, \n\t59384, 59384, 59385, 59385, 59386, 59386, 59386, 59387, \n\t59387, 59388, 59388, 59389, 59389, 59389, 59390, 59390, \n\t59391, 59391, 59391, 59392, 59392, 59393, 59393, 59394, \n\t59394, 59394, 59395, 59395, 59396, 59396, 59397, 59397, \n\t59397, 59398, 59398, 59399, 59399, 59399, 59400, 59400, \n\t59401, 59401, 59402, 59402, 59402, 59403, 59403, 59404, \n\t59404, 59405, 59405, 59405, 59406, 59406, 59407, 59407, \n\t59408, 59408, 59408, 59409, 59409, 59410, 59410, 59410, \n\t59411, 59411, 59412, 59412, 59413, 59413, 59413, 59414, \n\t59414, 59415, 59415, 59416, 59416, 59416, 59417, 59417, \n\t59418, 59418, 59418, 59419, 59419, 59420, 59420, 59421, \n\t59421, 59421, 59422, 59422, 59423, 59423, 59424, 59424, \n\t59424, 59425, 59425, 59426, 59426, 59427, 59427, 59427, \n\t59428, 59428, 59429, 59429, 59429, 59430, 59430, 59431, \n\t59431, 59432, 59432, 59432, 59433, 59433, 59434, 59434, \n\t59435, 59435, 59435, 59436, 59436, 59437, 59437, 59437, \n\t59438, 59438, 59439, 59439, 59440, 59440, 59440, 59441, \n\t59441, 59442, 59442, 59443, 59443, 59443, 59444, 59444, \n\t59445, 59445, 59445, 59446, 59446, 59447, 59447, 59448, \n\t59448, 59448, 59449, 59449, 59450, 59450, 59451, 59451, \n\t59451, 59452, 59452, 59453, 59453, 59453, 59454, 59454, \n\t59455, 59455, 59456, 59456, 59456, 59457, 59457, 59458, \n\t59458, 59459, 59459, 59459, 59460, 59460, 59461, 59461, \n\t59461, 59462, 59462, 59463, 59463, 59464, 59464, 59464, \n\t59465, 59465, 59466, 59466, 59466, 59467, 59467, 59468, \n\t59468, 59469, 59469, 59469, 59470, 59470, 59471, 59471, \n\t59472, 59472, 59472, 59473, 59473, 59474, 59474, 59474, \n\t59475, 59475, 59476, 59476, 59477, 59477, 59477, 59478, \n\t59478, 59479, 59479, 59480, 59480, 59480, 59481, 59481, \n\t59482, 59482, 59482, 59483, 59483, 59484, 59484, 59485, \n\t59485, 59485, 59486, 59486, 59487, 59487, 59487, 59488, \n\t59488, 59489, 59489, 59490, 59490, 59490, 59491, 59491, \n\t59492, 59492, 59493, 59493, 59493, 59494, 59494, 59495, \n\t59495, 59495, 59496, 59496, 59497, 59497, 59498, 59498, \n\t59498, 59499, 59499, 59500, 59500, 59500, 59501, 59501, \n\t59502, 59502, 59503, 59503, 59503, 59504, 59504, 59505, \n\t59505, 59506, 59506, 59506, 59507, 59507, 59508, 59508, \n\t59508, 59509, 59509, 59510, 59510, 59511, 59511, 59511, \n\t59512, 59512, 59513, 59513, 59513, 59514, 59514, 59515, \n\t59515, 59516, 59516, 59516, 59517, 59517, 59518, 59518, \n\t59519, 59519, 59519, 59520, 59520, 59521, 59521, 59521, \n\t59522, 59522, 59523, 59523, 59524, 59524, 59524, 59525, \n\t59525, 59526, 59526, 59526, 59527, 59527, 59528, 59528, \n\t59529, 59529, 59529, 59530, 59530, 59531, 59531, 59531, \n\t59532, 59532, 59533, 59533, 59534, 59534, 59534, 59535, \n\t59535, 59536, 59536, 59536, 59537, 59537, 59538, 59538, \n\t59539, 59539, 59539, 59540, 59540, 59541, 59541, 59542, \n\t59542, 59542, 59543, 59543, 59544, 59544, 59544, 59545, \n\t59545, 59546, 59546, 59547, 59547, 59547, 59548, 59548, \n\t59549, 59549, 59549, 59550, 59550, 59551, 59551, 59552, \n\t59552, 59552, 59553, 59553, 59554, 59554, 59554, 59555, \n\t59555, 59556, 59556, 59557, 59557, 59557, 59558, 59558, \n\t59559, 59559, 59559, 59560, 59560, 59561, 59561, 59562, \n\t59562, 59562, 59563, 59563, 59564, 59564, 59564, 59565, \n\t59565, 59566, 59566, 59567, 59567, 59567, 59568, 59568, \n\t59569, 59569, 59569, 59570, 59570, 59571, 59571, 59572, \n\t59572, 59572, 59573, 59573, 59574, 59574, 59574, 59575, \n\t59575, 59576, 59576, 59577, 59577, 59577, 59578, 59578, \n\t59579, 59579, 59579, 59580, 59580, 59581, 59581, 59582, \n\t59582, 59582, 59583, 59583, 59584, 59584, 59584, 59585, \n\t59585, 59586, 59586, 59587, 59587, 59587, 59588, 59588, \n\t59589, 59589, 59589, 59590, 59590, 59591, 59591, 59592, \n\t59592, 59592, 59593, 59593, 59594, 59594, 59594, 59595, \n\t59595, 59596, 59596, 59597, 59597, 59597, 59598, 59598, \n\t59599, 59599, 59599, 59600, 59600, 59601, 59601, 59602, \n\t59602, 59602, 59603, 59603, 59604, 59604, 59604, 59605, \n\t59605, 59606, 59606, 59607, 59607, 59607, 59608, 59608, \n\t59609, 59609, 59609, 59610, 59610, 59611, 59611, 59612, \n\t59612, 59612, 59613, 59613, 59614, 59614, 59614, 59615, \n\t59615, 59616, 59616, 59616, 59617, 59617, 59618, 59618, \n\t59619, 59619, 59619, 59620, 59620, 59621, 59621, 59621, \n\t59622, 59622, 59623, 59623, 59624, 59624, 59624, 59625, \n\t59625, 59626, 59626, 59626, 59627, 59627, 59628, 59628, \n\t59629, 59629, 59629, 59630, 59630, 59631, 59631, 59631, \n\t59632, 59632, 59633, 59633, 59634, 59634, 59634, 59635, \n\t59635, 59636, 59636, 59636, 59637, 59637, 59638, 59638, \n\t59638, 59639, 59639, 59640, 59640, 59641, 59641, 59641, \n\t59642, 59642, 59643, 59643, 59643, 59644, 59644, 59645, \n\t59645, 59646, 59646, 59646, 59647, 59647, 59648, 59648, \n\t59648, 59649, 59649, 59650, 59650, 59650, 59651, 59651, \n\t59652, 59652, 59653, 59653, 59653, 59654, 59654, 59655, \n\t59655, 59655, 59656, 59656, 59657, 59657, 59658, 59658, \n\t59658, 59659, 59659, 59660, 59660, 59660, 59661, 59661, \n\t59662, 59662, 59663, 59663, 59663, 59664, 59664, 59665, \n\t59665, 59665, 59666, 59666, 59667, 59667, 59667, 59668, \n\t59668, 59669, 59669, 59670, 59670, 59670, 59671, 59671, \n\t59672, 59672, 59672, 59673, 59673, 59674, 59674, 59674, \n\t59675, 59675, 59676, 59676, 59677, 59677, 59677, 59678, \n\t59678, 59679, 59679, 59679, 59680, 59680, 59681, 59681, \n\t59682, 59682, 59682, 59683, 59683, 59684, 59684, 59684, \n\t59685, 59685, 59686, 59686, 59686, 59687, 59687, 59688, \n\t59688, 59689, 59689, 59689, 59690, 59690, 59691, 59691, \n\t59691, 59692, 59692, 59693, 59693, 59693, 59694, 59694, \n\t59695, 59695, 59696, 59696, 59696, 59697, 59697, 59698, \n\t59698, 59698, 59699, 59699, 59700, 59700, 59701, 59701, \n\t59701, 59702, 59702, 59703, 59703, 59703, 59704, 59704, \n\t59705, 59705, 59705, 59706, 59706, 59707, 59707, 59708, \n\t59708, 59708, 59709, 59709, 59710, 59710, 59710, 59711, \n\t59711, 59712, 59712, 59712, 59713, 59713, 59714, 59714, \n\t59715, 59715, 59715, 59716, 59716, 59717, 59717, 59717, \n\t59718, 59718, 59719, 59719, 59719, 59720, 59720, 59721, \n\t59721, 59722, 59722, 59722, 59723, 59723, 59724, 59724, \n\t59724, 59725, 59725, 59726, 59726, 59726, 59727, 59727, \n\t59728, 59728, 59729, 59729, 59729, 59730, 59730, 59731, \n\t59731, 59731, 59732, 59732, 59733, 59733, 59733, 59734, \n\t59734, 59735, 59735, 59736, 59736, 59736, 59737, 59737, \n\t59738, 59738, 59738, 59739, 59739, 59740, 59740, 59740, \n\t59741, 59741, 59742, 59742, 59743, 59743, 59743, 59744, \n\t59744, 59745, 59745, 59745, 59746, 59746, 59747, 59747, \n\t59747, 59748, 59748, 59749, 59749, 59750, 59750, 59750, \n\t59751, 59751, 59752, 59752, 59752, 59753, 59753, 59754, \n\t59754, 59754, 59755, 59755, 59756, 59756, 59756, 59757, \n\t59757, 59758, 59758, 59759, 59759, 59759, 59760, 59760, \n\t59761, 59761, 59761, 59762, 59762, 59763, 59763, 59763, \n\t59764, 59764, 59765, 59765, 59766, 59766, 59766, 59767, \n\t59767, 59768, 59768, 59768, 59769, 59769, 59770, 59770, \n\t59770, 59771, 59771, 59772, 59772, 59772, 59773, 59773, \n\t59774, 59774, 59775, 59775, 59775, 59776, 59776, 59777, \n\t59777, 59777, 59778, 59778, 59779, 59779, 59779, 59780, \n\t59780, 59781, 59781, 59782, 59782, 59782, 59783, 59783, \n\t59784, 59784, 59784, 59785, 59785, 59786, 59786, 59786, \n\t59787, 59787, 59788, 59788, 59788, 59789, 59789, 59790, \n\t59790, 59791, 59791, 59791, 59792, 59792, 59793, 59793, \n\t59793, 59794, 59794, 59795, 59795, 59795, 59796, 59796, \n\t59797, 59797, 59797, 59798, 59798, 59799, 59799, 59800, \n\t59800, 59800, 59801, 59801, 59802, 59802, 59802, 59803, \n\t59803, 59804, 59804, 59804, 59805, 59805, 59806, 59806, \n\t59806, 59807, 59807, 59808, 59808, 59809, 59809, 59809, \n\t59810, 59810, 59811, 59811, 59811, 59812, 59812, 59813, \n\t59813, 59813, 59814, 59814, 59815, 59815, 59815, 59816, \n\t59816, 59817, 59817, 59818, 59818, 59818, 59819, 59819, \n\t59820, 59820, 59820, 59821, 59821, 59822, 59822, 59822, \n\t59823, 59823, 59824, 59824, 59824, 59825, 59825, 59826, \n\t59826, 59826, 59827, 59827, 59828, 59828, 59829, 59829, \n\t59829, 59830, 59830, 59831, 59831, 59831, 59832, 59832, \n\t59833, 59833, 59833, 59834, 59834, 59835, 59835, 59835, \n\t59836, 59836, 59837, 59837, 59838, 59838, 59838, 59839, \n\t59839, 59840, 59840, 59840, 59841, 59841, 59842, 59842, \n\t59842, 59843, 59843, 59844, 59844, 59844, 59845, 59845, \n\t59846, 59846, 59846, 59847, 59847, 59848, 59848, 59849, \n\t59849, 59849, 59850, 59850, 59851, 59851, 59851, 59852, \n\t59852, 59853, 59853, 59853, 59854, 59854, 59855, 59855, \n\t59855, 59856, 59856, 59857, 59857, 59857, 59858, 59858, \n\t59859, 59859, 59860, 59860, 59860, 59861, 59861, 59862, \n\t59862, 59862, 59863, 59863, 59864, 59864, 59864, 59865, \n\t59865, 59866, 59866, 59866, 59867, 59867, 59868, 59868, \n\t59868, 59869, 59869, 59870, 59870, 59871, 59871, 59871, \n\t59872, 59872, 59873, 59873, 59873, 59874, 59874, 59875, \n\t59875, 59875, 59876, 59876, 59877, 59877, 59877, 59878, \n\t59878, 59879, 59879, 59879, 59880, 59880, 59881, 59881, \n\t59881, 59882, 59882, 59883, 59883, 59884, 59884, 59884, \n\t59885, 59885, 59886, 59886, 59886, 59887, 59887, 59888, \n\t59888, 59888, 59889, 59889, 59890, 59890, 59890, 59891, \n\t59891, 59892, 59892, 59892, 59893, 59893, 59894, 59894, \n\t59894, 59895, 59895, 59896, 59896, 59897, 59897, 59897, \n\t59898, 59898, 59899, 59899, 59899, 59900, 59900, 59901, \n\t59901, 59901, 59902, 59902, 59903, 59903, 59903, 59904, \n\t59904, 59905, 59905, 59905, 59906, 59906, 59907, 59907, \n\t59907, 59908, 59908, 59909, 59909, 59909, 59910, 59910, \n\t59911, 59911, 59912, 59912, 59912, 59913, 59913, 59914, \n\t59914, 59914, 59915, 59915, 59916, 59916, 59916, 59917, \n\t59917, 59918, 59918, 59918, 59919, 59919, 59920, 59920, \n\t59920, 59921, 59921, 59922, 59922, 59922, 59923, 59923, \n\t59924, 59924, 59924, 59925, 59925, 59926, 59926, 59926, \n\t59927, 59927, 59928, 59928, 59929, 59929, 59929, 59930, \n\t59930, 59931, 59931, 59931, 59932, 59932, 59933, 59933, \n\t59933, 59934, 59934, 59935, 59935, 59935, 59936, 59936, \n\t59937, 59937, 59937, 59938, 59938, 59939, 59939, 59939, \n\t59940, 59940, 59941, 59941, 59941, 59942, 59942, 59943, \n\t59943, 59943, 59944, 59944, 59945, 59945, 59946, 59946, \n\t59946, 59947, 59947, 59948, 59948, 59948, 59949, 59949, \n\t59950, 59950, 59950, 59951, 59951, 59952, 59952, 59952, \n\t59953, 59953, 59954, 59954, 59954, 59955, 59955, 59956, \n\t59956, 59956, 59957, 59957, 59958, 59958, 59958, 59959, \n\t59959, 59960, 59960, 59960, 59961, 59961, 59962, 59962, \n\t59962, 59963, 59963, 59964, 59964, 59964, 59965, 59965, \n\t59966, 59966, 59967, 59967, 59967, 59968, 59968, 59969, \n\t59969, 59969, 59970, 59970, 59971, 59971, 59971, 59972, \n\t59972, 59973, 59973, 59973, 59974, 59974, 59975, 59975, \n\t59975, 59976, 59976, 59977, 59977, 59977, 59978, 59978, \n\t59979, 59979, 59979, 59980, 59980, 59981, 59981, 59981, \n\t59982, 59982, 59983, 59983, 59983, 59984, 59984, 59985, \n\t59985, 59985, 59986, 59986, 59987, 59987, 59987, 59988, \n\t59988, 59989, 59989, 59989, 59990, 59990, 59991, 59991, \n\t59991, 59992, 59992, 59993, 59993, 59993, 59994, 59994, \n\t59995, 59995, 59996, 59996, 59996, 59997, 59997, 59998, \n\t59998, 59998, 59999, 59999, 60000, 60000, 60000, 60001, \n\t60001, 60002, 60002, 60002, 60003, 60003, 60004, 60004, \n\t60004, 60005, 60005, 60006, 60006, 60006, 60007, 60007, \n\t60008, 60008, 60008, 60009, 60009, 60010, 60010, 60010, \n\t60011, 60011, 60012, 60012, 60012, 60013, 60013, 60014, \n\t60014, 60014, 60015, 60015, 60016, 60016, 60016, 60017, \n\t60017, 60018, 60018, 60018, 60019, 60019, 60020, 60020, \n\t60020, 60021, 60021, 60022, 60022, 60022, 60023, 60023, \n\t60024, 60024, 60024, 60025, 60025, 60026, 60026, 60026, \n\t60027, 60027, 60028, 60028, 60028, 60029, 60029, 60030, \n\t60030, 60030, 60031, 60031, 60032, 60032, 60032, 60033, \n\t60033, 60034, 60034, 60034, 60035, 60035, 60036, 60036, \n\t60036, 60037, 60037, 60038, 60038, 60038, 60039, 60039, \n\t60040, 60040, 60040, 60041, 60041, 60042, 60042, 60042, \n\t60043, 60043, 60044, 60044, 60045, 60045, 60045, 60046, \n\t60046, 60047, 60047, 60047, 60048, 60048, 60049, 60049, \n\t60049, 60050, 60050, 60051, 60051, 60051, 60052, 60052, \n\t60053, 60053, 60053, 60054, 60054, 60055, 60055, 60055, \n\t60056, 60056, 60057, 60057, 60057, 60058, 60058, 60059, \n\t60059, 60059, 60060, 60060, 60061, 60061, 60061, 60062, \n\t60062, 60063, 60063, 60063, 60064, 60064, 60065, 60065, \n\t60065, 60066, 60066, 60067, 60067, 60067, 60068, 60068, \n\t60069, 60069, 60069, 60070, 60070, 60071, 60071, 60071, \n\t60072, 60072, 60073, 60073, 60073, 60074, 60074, 60075, \n\t60075, 60075, 60076, 60076, 60077, 60077, 60077, 60078, \n\t60078, 60079, 60079, 60079, 60080, 60080, 60081, 60081, \n\t60081, 60082, 60082, 60083, 60083, 60083, 60084, 60084, \n\t60085, 60085, 60085, 60086, 60086, 60086, 60087, 60087, \n\t60088, 60088, 60088, 60089, 60089, 60090, 60090, 60090, \n\t60091, 60091, 60092, 60092, 60092, 60093, 60093, 60094, \n\t60094, 60094, 60095, 60095, 60096, 60096, 60096, 60097, \n\t60097, 60098, 60098, 60098, 60099, 60099, 60100, 60100, \n\t60100, 60101, 60101, 60102, 60102, 60102, 60103, 60103, \n\t60104, 60104, 60104, 60105, 60105, 60106, 60106, 60106, \n\t60107, 60107, 60108, 60108, 60108, 60109, 60109, 60110, \n\t60110, 60110, 60111, 60111, 60112, 60112, 60112, 60113, \n\t60113, 60114, 60114, 60114, 60115, 60115, 60116, 60116, \n\t60116, 60117, 60117, 60118, 60118, 60118, 60119, 60119, \n\t60120, 60120, 60120, 60121, 60121, 60122, 60122, 60122, \n\t60123, 60123, 60124, 60124, 60124, 60125, 60125, 60126, \n\t60126, 60126, 60127, 60127, 60128, 60128, 60128, 60129, \n\t60129, 60130, 60130, 60130, 60131, 60131, 60132, 60132, \n\t60132, 60133, 60133, 60134, 60134, 60134, 60135, 60135, \n\t60135, 60136, 60136, 60137, 60137, 60137, 60138, 60138, \n\t60139, 60139, 60139, 60140, 60140, 60141, 60141, 60141, \n\t60142, 60142, 60143, 60143, 60143, 60144, 60144, 60145, \n\t60145, 60145, 60146, 60146, 60147, 60147, 60147, 60148, \n\t60148, 60149, 60149, 60149, 60150, 60150, 60151, 60151, \n\t60151, 60152, 60152, 60153, 60153, 60153, 60154, 60154, \n\t60155, 60155, 60155, 60156, 60156, 60157, 60157, 60157, \n\t60158, 60158, 60159, 60159, 60159, 60160, 60160, 60161, \n\t60161, 60161, 60162, 60162, 60162, 60163, 60163, 60164, \n\t60164, 60164, 60165, 60165, 60166, 60166, 60166, 60167, \n\t60167, 60168, 60168, 60168, 60169, 60169, 60170, 60170, \n\t60170, 60171, 60171, 60172, 60172, 60172, 60173, 60173, \n\t60174, 60174, 60174, 60175, 60175, 60176, 60176, 60176, \n\t60177, 60177, 60178, 60178, 60178, 60179, 60179, 60180, \n\t60180, 60180, 60181, 60181, 60182, 60182, 60182, 60183, \n\t60183, 60183, 60184, 60184, 60185, 60185, 60185, 60186, \n\t60186, 60187, 60187, 60187, 60188, 60188, 60189, 60189, \n\t60189, 60190, 60190, 60191, 60191, 60191, 60192, 60192, \n\t60193, 60193, 60193, 60194, 60194, 60195, 60195, 60195, \n\t60196, 60196, 60197, 60197, 60197, 60198, 60198, 60199, \n\t60199, 60199, 60200, 60200, 60201, 60201, 60201, 60202, \n\t60202, 60202, 60203, 60203, 60204, 60204, 60204, 60205, \n\t60205, 60206, 60206, 60206, 60207, 60207, 60208, 60208, \n\t60208, 60209, 60209, 60210, 60210, 60210, 60211, 60211, \n\t60212, 60212, 60212, 60213, 60213, 60214, 60214, 60214, \n\t60215, 60215, 60216, 60216, 60216, 60217, 60217, 60217, \n\t60218, 60218, 60219, 60219, 60219, 60220, 60220, 60221, \n\t60221, 60221, 60222, 60222, 60223, 60223, 60223, 60224, \n\t60224, 60225, 60225, 60225, 60226, 60226, 60227, 60227, \n\t60227, 60228, 60228, 60229, 60229, 60229, 60230, 60230, \n\t60231, 60231, 60231, 60232, 60232, 60232, 60233, 60233, \n\t60234, 60234, 60234, 60235, 60235, 60236, 60236, 60236, \n\t60237, 60237, 60238, 60238, 60238, 60239, 60239, 60240, \n\t60240, 60240, 60241, 60241, 60242, 60242, 60242, 60243, \n\t60243, 60243, 60244, 60244, 60245, 60245, 60245, 60246, \n\t60246, 60247, 60247, 60247, 60248, 60248, 60249, 60249, \n\t60249, 60250, 60250, 60251, 60251, 60251, 60252, 60252, \n\t60253, 60253, 60253, 60254, 60254, 60255, 60255, 60255, \n\t60256, 60256, 60256, 60257, 60257, 60258, 60258, 60258, \n\t60259, 60259, 60260, 60260, 60260, 60261, 60261, 60262, \n\t60262, 60262, 60263, 60263, 60264, 60264, 60264, 60265, \n\t60265, 60266, 60266, 60266, 60267, 60267, 60267, 60268, \n\t60268, 60269, 60269, 60269, 60270, 60270, 60271, 60271, \n\t60271, 60272, 60272, 60273, 60273, 60273, 60274, 60274, \n\t60275, 60275, 60275, 60276, 60276, 60277, 60277, 60277, \n\t60278, 60278, 60278, 60279, 60279, 60280, 60280, 60280, \n\t60281, 60281, 60282, 60282, 60282, 60283, 60283, 60284, \n\t60284, 60284, 60285, 60285, 60286, 60286, 60286, 60287, \n\t60287, 60288, 60288, 60288, 60289, 60289, 60289, 60290, \n\t60290, 60291, 60291, 60291, 60292, 60292, 60293, 60293, \n\t60293, 60294, 60294, 60295, 60295, 60295, 60296, 60296, \n\t60297, 60297, 60297, 60298, 60298, 60298, 60299, 60299, \n\t60300, 60300, 60300, 60301, 60301, 60302, 60302, 60302, \n\t60303, 60303, 60304, 60304, 60304, 60305, 60305, 60306, \n\t60306, 60306, 60307, 60307, 60307, 60308, 60308, 60309, \n\t60309, 60309, 60310, 60310, 60311, 60311, 60311, 60312, \n\t60312, 60313, 60313, 60313, 60314, 60314, 60315, 60315, \n\t60315, 60316, 60316, 60316, 60317, 60317, 60318, 60318, \n\t60318, 60319, 60319, 60320, 60320, 60320, 60321, 60321, \n\t60322, 60322, 60322, 60323, 60323, 60324, 60324, 60324, \n\t60325, 60325, 60325, 60326, 60326, 60327, 60327, 60327, \n\t60328, 60328, 60329, 60329, 60329, 60330, 60330, 60331, \n\t60331, 60331, 60332, 60332, 60333, 60333, 60333, 60334, \n\t60334, 60334, 60335, 60335, 60336, 60336, 60336, 60337, \n\t60337, 60338, 60338, 60338, 60339, 60339, 60340, 60340, \n\t60340, 60341, 60341, 60341, 60342, 60342, 60343, 60343, \n\t60343, 60344, 60344, 60345, 60345, 60345, 60346, 60346, \n\t60347, 60347, 60347, 60348, 60348, 60349, 60349, 60349, \n\t60350, 60350, 60350, 60351, 60351, 60352, 60352, 60352, \n\t60353, 60353, 60354, 60354, 60354, 60355, 60355, 60356, \n\t60356, 60356, 60357, 60357, 60357, 60358, 60358, 60359, \n\t60359, 60359, 60360, 60360, 60361, 60361, 60361, 60362, \n\t60362, 60363, 60363, 60363, 60364, 60364, 60364, 60365, \n\t60365, 60366, 60366, 60366, 60367, 60367, 60368, 60368, \n\t60368, 60369, 60369, 60370, 60370, 60370, 60371, 60371, \n\t60371, 60372, 60372, 60373, 60373, 60373, 60374, 60374, \n\t60375, 60375, 60375, 60376, 60376, 60377, 60377, 60377, \n\t60378, 60378, 60378, 60379, 60379, 60380, 60380, 60380, \n\t60381, 60381, 60382, 60382, 60382, 60383, 60383, 60384, \n\t60384, 60384, 60385, 60385, 60385, 60386, 60386, 60387, \n\t60387, 60387, 60388, 60388, 60389, 60389, 60389, 60390, \n\t60390, 60391, 60391, 60391, 60392, 60392, 60392, 60393, \n\t60393, 60394, 60394, 60394, 60395, 60395, 60396, 60396, \n\t60396, 60397, 60397, 60398, 60398, 60398, 60399, 60399, \n\t60399, 60400, 60400, 60401, 60401, 60401, 60402, 60402, \n\t60403, 60403, 60403, 60404, 60404, 60405, 60405, 60405, \n\t60406, 60406, 60406, 60407, 60407, 60408, 60408, 60408, \n\t60409, 60409, 60410, 60410, 60410, 60411, 60411, 60411, \n\t60412, 60412, 60413, 60413, 60413, 60414, 60414, 60415, \n\t60415, 60415, 60416, 60416, 60417, 60417, 60417, 60418, \n\t60418, 60418, 60419, 60419, 60420, 60420, 60420, 60421, \n\t60421, 60422, 60422, 60422, 60423, 60423, 60423, 60424, \n\t60424, 60425, 60425, 60425, 60426, 60426, 60427, 60427, \n\t60427, 60428, 60428, 60429, 60429, 60429, 60430, 60430, \n\t60430, 60431, 60431, 60432, 60432, 60432, 60433, 60433, \n\t60434, 60434, 60434, 60435, 60435, 60435, 60436, 60436, \n\t60437, 60437, 60437, 60438, 60438, 60439, 60439, 60439, \n\t60440, 60440, 60441, 60441, 60441, 60442, 60442, 60442, \n\t60443, 60443, 60444, 60444, 60444, 60445, 60445, 60446, \n\t60446, 60446, 60447, 60447, 60447, 60448, 60448, 60449, \n\t60449, 60449, 60450, 60450, 60451, 60451, 60451, 60452, \n\t60452, 60453, 60453, 60453, 60454, 60454, 60454, 60455, \n\t60455, 60456, 60456, 60456, 60457, 60457, 60458, 60458, \n\t60458, 60459, 60459, 60459, 60460, 60460, 60461, 60461, \n\t60461, 60462, 60462, 60463, 60463, 60463, 60464, 60464, \n\t60464, 60465, 60465, 60466, 60466, 60466, 60467, 60467, \n\t60468, 60468, 60468, 60469, 60469, 60469, 60470, 60470, \n\t60471, 60471, 60471, 60472, 60472, 60473, 60473, 60473, \n\t60474, 60474, 60474, 60475, 60475, 60476, 60476, 60476, \n\t60477, 60477, 60478, 60478, 60478, 60479, 60479, 60479, \n\t60480, 60480, 60481, 60481, 60481, 60482, 60482, 60483, \n\t60483, 60483, 60484, 60484, 60485, 60485, 60485, 60486, \n\t60486, 60486, 60487, 60487, 60488, 60488, 60488, 60489, \n\t60489, 60490, 60490, 60490, 60491, 60491, 60491, 60492, \n\t60492, 60493, 60493, 60493, 60494, 60494, 60495, 60495, \n\t60495, 60496, 60496, 60496, 60497, 60497, 60498, 60498, \n\t60498, 60499, 60499, 60500, 60500, 60500, 60501, 60501, \n\t60501, 60502, 60502, 60503, 60503, 60503, 60504, 60504, \n\t60505, 60505, 60505, 60506, 60506, 60506, 60507, 60507, \n\t60508, 60508, 60508, 60509, 60509, 60509, 60510, 60510, \n\t60511, 60511, 60511, 60512, 60512, 60513, 60513, 60513, \n\t60514, 60514, 60514, 60515, 60515, 60516, 60516, 60516, \n\t60517, 60517, 60518, 60518, 60518, 60519, 60519, 60519, \n\t60520, 60520, 60521, 60521, 60521, 60522, 60522, 60523, \n\t60523, 60523, 60524, 60524, 60524, 60525, 60525, 60526, \n\t60526, 60526, 60527, 60527, 60528, 60528, 60528, 60529, \n\t60529, 60529, 60530, 60530, 60531, 60531, 60531, 60532, \n\t60532, 60533, 60533, 60533, 60534, 60534, 60534, 60535, \n\t60535, 60536, 60536, 60536, 60537, 60537, 60537, 60538, \n\t60538, 60539, 60539, 60539, 60540, 60540, 60541, 60541, \n\t60541, 60542, 60542, 60542, 60543, 60543, 60544, 60544, \n\t60544, 60545, 60545, 60546, 60546, 60546, 60547, 60547, \n\t60547, 60548, 60548, 60549, 60549, 60549, 60550, 60550, \n\t60551, 60551, 60551, 60552, 60552, 60552, 60553, 60553, \n\t60554, 60554, 60554, 60555, 60555, 60555, 60556, 60556, \n\t60557, 60557, 60557, 60558, 60558, 60559, 60559, 60559, \n\t60560, 60560, 60560, 60561, 60561, 60562, 60562, 60562, \n\t60563, 60563, 60564, 60564, 60564, 60565, 60565, 60565, \n\t60566, 60566, 60567, 60567, 60567, 60568, 60568, 60568, \n\t60569, 60569, 60570, 60570, 60570, 60571, 60571, 60572, \n\t60572, 60572, 60573, 60573, 60573, 60574, 60574, 60575, \n\t60575, 60575, 60576, 60576, 60576, 60577, 60577, 60578, \n\t60578, 60578, 60579, 60579, 60580, 60580, 60580, 60581, \n\t60581, 60581, 60582, 60582, 60583, 60583, 60583, 60584, \n\t60584, 60585, 60585, 60585, 60586, 60586, 60586, 60587, \n\t60587, 60588, 60588, 60588, 60589, 60589, 60589, 60590, \n\t60590, 60591, 60591, 60591, 60592, 60592, 60593, 60593, \n\t60593, 60594, 60594, 60594, 60595, 60595, 60596, 60596, \n\t60596, 60597, 60597, 60597, 60598, 60598, 60599, 60599, \n\t60599, 60600, 60600, 60601, 60601, 60601, 60602, 60602, \n\t60602, 60603, 60603, 60604, 60604, 60604, 60605, 60605, \n\t60605, 60606, 60606, 60607, 60607, 60607, 60608, 60608, \n\t60609, 60609, 60609, 60610, 60610, 60610, 60611, 60611, \n\t60612, 60612, 60612, 60613, 60613, 60613, 60614, 60614, \n\t60615, 60615, 60615, 60616, 60616, 60616, 60617, 60617, \n\t60618, 60618, 60618, 60619, 60619, 60620, 60620, 60620, \n\t60621, 60621, 60621, 60622, 60622, 60623, 60623, 60623, \n\t60624, 60624, 60624, 60625, 60625, 60626, 60626, 60626, \n\t60627, 60627, 60628, 60628, 60628, 60629, 60629, 60629, \n\t60630, 60630, 60631, 60631, 60631, 60632, 60632, 60632, \n\t60633, 60633, 60634, 60634, 60634, 60635, 60635, 60635, \n\t60636, 60636, 60637, 60637, 60637, 60638, 60638, 60639, \n\t60639, 60639, 60640, 60640, 60640, 60641, 60641, 60642, \n\t60642, 60642, 60643, 60643, 60643, 60644, 60644, 60645, \n\t60645, 60645, 60646, 60646, 60646, 60647, 60647, 60648, \n\t60648, 60648, 60649, 60649, 60650, 60650, 60650, 60651, \n\t60651, 60651, 60652, 60652, 60653, 60653, 60653, 60654, \n\t60654, 60654, 60655, 60655, 60656, 60656, 60656, 60657, \n\t60657, 60657, 60658, 60658, 60659, 60659, 60659, 60660, \n\t60660, 60660, 60661, 60661, 60662, 60662, 60662, 60663, \n\t60663, 60664, 60664, 60664, 60665, 60665, 60665, 60666, \n\t60666, 60667, 60667, 60667, 60668, 60668, 60668, 60669, \n\t60669, 60670, 60670, 60670, 60671, 60671, 60671, 60672, \n\t60672, 60673, 60673, 60673, 60674, 60674, 60674, 60675, \n\t60675, 60676, 60676, 60676, 60677, 60677, 60678, 60678, \n\t60678, 60679, 60679, 60679, 60680, 60680, 60681, 60681, \n\t60681, 60682, 60682, 60682, 60683, 60683, 60684, 60684, \n\t60684, 60685, 60685, 60685, 60686, 60686, 60687, 60687, \n\t60687, 60688, 60688, 60688, 60689, 60689, 60690, 60690, \n\t60690, 60691, 60691, 60691, 60692, 60692, 60693, 60693, \n\t60693, 60694, 60694, 60694, 60695, 60695, 60696, 60696, \n\t60696, 60697, 60697, 60698, 60698, 60698, 60699, 60699, \n\t60699, 60700, 60700, 60701, 60701, 60701, 60702, 60702, \n\t60702, 60703, 60703, 60704, 60704, 60704, 60705, 60705, \n\t60705, 60706, 60706, 60707, 60707, 60707, 60708, 60708, \n\t60708, 60709, 60709, 60710, 60710, 60710, 60711, 60711, \n\t60711, 60712, 60712, 60713, 60713, 60713, 60714, 60714, \n\t60714, 60715, 60715, 60716, 60716, 60716, 60717, 60717, \n\t60717, 60718, 60718, 60719, 60719, 60719, 60720, 60720, \n\t60720, 60721, 60721, 60722, 60722, 60722, 60723, 60723, \n\t60723, 60724, 60724, 60725, 60725, 60725, 60726, 60726, \n\t60727, 60727, 60727, 60728, 60728, 60728, 60729, 60729, \n\t60730, 60730, 60730, 60731, 60731, 60731, 60732, 60732, \n\t60733, 60733, 60733, 60734, 60734, 60734, 60735, 60735, \n\t60736, 60736, 60736, 60737, 60737, 60737, 60738, 60738, \n\t60739, 60739, 60739, 60740, 60740, 60740, 60741, 60741, \n\t60742, 60742, 60742, 60743, 60743, 60743, 60744, 60744, \n\t60745, 60745, 60745, 60746, 60746, 60746, 60747, 60747, \n\t60748, 60748, 60748, 60749, 60749, 60749, 60750, 60750, \n\t60751, 60751, 60751, 60752, 60752, 60752, 60753, 60753, \n\t60754, 60754, 60754, 60755, 60755, 60755, 60756, 60756, \n\t60757, 60757, 60757, 60758, 60758, 60758, 60759, 60759, \n\t60760, 60760, 60760, 60761, 60761, 60761, 60762, 60762, \n\t60763, 60763, 60763, 60764, 60764, 60764, 60765, 60765, \n\t60766, 60766, 60766, 60767, 60767, 60767, 60768, 60768, \n\t60769, 60769, 60769, 60770, 60770, 60770, 60771, 60771, \n\t60772, 60772, 60772, 60773, 60773, 60773, 60774, 60774, \n\t60775, 60775, 60775, 60776, 60776, 60776, 60777, 60777, \n\t60778, 60778, 60778, 60779, 60779, 60779, 60780, 60780, \n\t60781, 60781, 60781, 60782, 60782, 60782, 60783, 60783, \n\t60783, 60784, 60784, 60785, 60785, 60785, 60786, 60786, \n\t60786, 60787, 60787, 60788, 60788, 60788, 60789, 60789, \n\t60789, 60790, 60790, 60791, 60791, 60791, 60792, 60792, \n\t60792, 60793, 60793, 60794, 60794, 60794, 60795, 60795, \n\t60795, 60796, 60796, 60797, 60797, 60797, 60798, 60798, \n\t60798, 60799, 60799, 60800, 60800, 60800, 60801, 60801, \n\t60801, 60802, 60802, 60803, 60803, 60803, 60804, 60804, \n\t60804, 60805, 60805, 60806, 60806, 60806, 60807, 60807, \n\t60807, 60808, 60808, 60809, 60809, 60809, 60810, 60810, \n\t60810, 60811, 60811, 60811, 60812, 60812, 60813, 60813, \n\t60813, 60814, 60814, 60814, 60815, 60815, 60816, 60816, \n\t60816, 60817, 60817, 60817, 60818, 60818, 60819, 60819, \n\t60819, 60820, 60820, 60820, 60821, 60821, 60822, 60822, \n\t60822, 60823, 60823, 60823, 60824, 60824, 60825, 60825, \n\t60825, 60826, 60826, 60826, 60827, 60827, 60828, 60828, \n\t60828, 60829, 60829, 60829, 60830, 60830, 60830, 60831, \n\t60831, 60832, 60832, 60832, 60833, 60833, 60833, 60834, \n\t60834, 60835, 60835, 60835, 60836, 60836, 60836, 60837, \n\t60837, 60838, 60838, 60838, 60839, 60839, 60839, 60840, \n\t60840, 60841, 60841, 60841, 60842, 60842, 60842, 60843, \n\t60843, 60844, 60844, 60844, 60845, 60845, 60845, 60846, \n\t60846, 60846, 60847, 60847, 60848, 60848, 60848, 60849, \n\t60849, 60849, 60850, 60850, 60851, 60851, 60851, 60852, \n\t60852, 60852, 60853, 60853, 60854, 60854, 60854, 60855, \n\t60855, 60855, 60856, 60856, 60857, 60857, 60857, 60858, \n\t60858, 60858, 60859, 60859, 60859, 60860, 60860, 60861, \n\t60861, 60861, 60862, 60862, 60862, 60863, 60863, 60864, \n\t60864, 60864, 60865, 60865, 60865, 60866, 60866, 60867, \n\t60867, 60867, 60868, 60868, 60868, 60869, 60869, 60869, \n\t60870, 60870, 60871, 60871, 60871, 60872, 60872, 60872, \n\t60873, 60873, 60874, 60874, 60874, 60875, 60875, 60875, \n\t60876, 60876, 60877, 60877, 60877, 60878, 60878, 60878, \n\t60879, 60879, 60879, 60880, 60880, 60881, 60881, 60881, \n\t60882, 60882, 60882, 60883, 60883, 60884, 60884, 60884, \n\t60885, 60885, 60885, 60886, 60886, 60887, 60887, 60887, \n\t60888, 60888, 60888, 60889, 60889, 60889, 60890, 60890, \n\t60891, 60891, 60891, 60892, 60892, 60892, 60893, 60893, \n\t60894, 60894, 60894, 60895, 60895, 60895, 60896, 60896, \n\t60896, 60897, 60897, 60898, 60898, 60898, 60899, 60899, \n\t60899, 60900, 60900, 60901, 60901, 60901, 60902, 60902, \n\t60902, 60903, 60903, 60904, 60904, 60904, 60905, 60905, \n\t60905, 60906, 60906, 60906, 60907, 60907, 60908, 60908, \n\t60908, 60909, 60909, 60909, 60910, 60910, 60911, 60911, \n\t60911, 60912, 60912, 60912, 60913, 60913, 60913, 60914, \n\t60914, 60915, 60915, 60915, 60916, 60916, 60916, 60917, \n\t60917, 60918, 60918, 60918, 60919, 60919, 60919, 60920, \n\t60920, 60920, 60921, 60921, 60922, 60922, 60922, 60923, \n\t60923, 60923, 60924, 60924, 60925, 60925, 60925, 60926, \n\t60926, 60926, 60927, 60927, 60927, 60928, 60928, 60929, \n\t60929, 60929, 60930, 60930, 60930, 60931, 60931, 60932, \n\t60932, 60932, 60933, 60933, 60933, 60934, 60934, 60934, \n\t60935, 60935, 60936, 60936, 60936, 60937, 60937, 60937, \n\t60938, 60938, 60939, 60939, 60939, 60940, 60940, 60940, \n\t60941, 60941, 60941, 60942, 60942, 60943, 60943, 60943, \n\t60944, 60944, 60944, 60945, 60945, 60946, 60946, 60946, \n\t60947, 60947, 60947, 60948, 60948, 60948, 60949, 60949, \n\t60950, 60950, 60950, 60951, 60951, 60951, 60952, 60952, \n\t60953, 60953, 60953, 60954, 60954, 60954, 60955, 60955, \n\t60955, 60956, 60956, 60957, 60957, 60957, 60958, 60958, \n\t60958, 60959, 60959, 60959, 60960, 60960, 60961, 60961, \n\t60961, 60962, 60962, 60962, 60963, 60963, 60964, 60964, \n\t60964, 60965, 60965, 60965, 60966, 60966, 60966, 60967, \n\t60967, 60968, 60968, 60968, 60969, 60969, 60969, 60970, \n\t60970, 60970, 60971, 60971, 60972, 60972, 60972, 60973, \n\t60973, 60973, 60974, 60974, 60975, 60975, 60975, 60976, \n\t60976, 60976, 60977, 60977, 60977, 60978, 60978, 60979, \n\t60979, 60979, 60980, 60980, 60980, 60981, 60981, 60981, \n\t60982, 60982, 60983, 60983, 60983, 60984, 60984, 60984, \n\t60985, 60985, 60986, 60986, 60986, 60987, 60987, 60987, \n\t60988, 60988, 60988, 60989, 60989, 60990, 60990, 60990, \n\t60991, 60991, 60991, 60992, 60992, 60992, 60993, 60993, \n\t60994, 60994, 60994, 60995, 60995, 60995, 60996, 60996, \n\t60996, 60997, 60997, 60998, 60998, 60998, 60999, 60999, \n\t60999, 61000, 61000, 61001, 61001, 61001, 61002, 61002, \n\t61002, 61003, 61003, 61003, 61004, 61004, 61005, 61005, \n\t61005, 61006, 61006, 61006, 61007, 61007, 61007, 61008, \n\t61008, 61009, 61009, 61009, 61010, 61010, 61010, 61011, \n\t61011, 61011, 61012, 61012, 61013, 61013, 61013, 61014, \n\t61014, 61014, 61015, 61015, 61015, 61016, 61016, 61017, \n\t61017, 61017, 61018, 61018, 61018, 61019, 61019, 61020, \n\t61020, 61020, 61021, 61021, 61021, 61022, 61022, 61022, \n\t61023, 61023, 61024, 61024, 61024, 61025, 61025, 61025, \n\t61026, 61026, 61026, 61027, 61027, 61028, 61028, 61028, \n\t61029, 61029, 61029, 61030, 61030, 61030, 61031, 61031, \n\t61032, 61032, 61032, 61033, 61033, 61033, 61034, 61034, \n\t61034, 61035, 61035, 61036, 61036, 61036, 61037, 61037, \n\t61037, 61038, 61038, 61038, 61039, 61039, 61040, 61040, \n\t61040, 61041, 61041, 61041, 61042, 61042, 61042, 61043, \n\t61043, 61044, 61044, 61044, 61045, 61045, 61045, 61046, \n\t61046, 61046, 61047, 61047, 61048, 61048, 61048, 61049, \n\t61049, 61049, 61050, 61050, 61050, 61051, 61051, 61052, \n\t61052, 61052, 61053, 61053, 61053, 61054, 61054, 61054, \n\t61055, 61055, 61056, 61056, 61056, 61057, 61057, 61057, \n\t61058, 61058, 61058, 61059, 61059, 61060, 61060, 61060, \n\t61061, 61061, 61061, 61062, 61062, 61062, 61063, 61063, \n\t61064, 61064, 61064, 61065, 61065, 61065, 61066, 61066, \n\t61066, 61067, 61067, 61068, 61068, 61068, 61069, 61069, \n\t61069, 61070, 61070, 61070, 61071, 61071, 61072, 61072, \n\t61072, 61073, 61073, 61073, 61074, 61074, 61074, 61075, \n\t61075, 61076, 61076, 61076, 61077, 61077, 61077, 61078, \n\t61078, 61078, 61079, 61079, 61080, 61080, 61080, 61081, \n\t61081, 61081, 61082, 61082, 61082, 61083, 61083, 61083, \n\t61084, 61084, 61085, 61085, 61085, 61086, 61086, 61086, \n\t61087, 61087, 61087, 61088, 61088, 61089, 61089, 61089, \n\t61090, 61090, 61090, 61091, 61091, 61091, 61092, 61092, \n\t61093, 61093, 61093, 61094, 61094, 61094, 61095, 61095, \n\t61095, 61096, 61096, 61097, 61097, 61097, 61098, 61098, \n\t61098, 61099, 61099, 61099, 61100, 61100, 61101, 61101, \n\t61101, 61102, 61102, 61102, 61103, 61103, 61103, 61104, \n\t61104, 61104, 61105, 61105, 61106, 61106, 61106, 61107, \n\t61107, 61107, 61108, 61108, 61108, 61109, 61109, 61110, \n\t61110, 61110, 61111, 61111, 61111, 61112, 61112, 61112, \n\t61113, 61113, 61114, 61114, 61114, 61115, 61115, 61115, \n\t61116, 61116, 61116, 61117, 61117, 61117, 61118, 61118, \n\t61119, 61119, 61119, 61120, 61120, 61120, 61121, 61121, \n\t61121, 61122, 61122, 61123, 61123, 61123, 61124, 61124, \n\t61124, 61125, 61125, 61125, 61126, 61126, 61127, 61127, \n\t61127, 61128, 61128, 61128, 61129, 61129, 61129, 61130, \n\t61130, 61130, 61131, 61131, 61132, 61132, 61132, 61133, \n\t61133, 61133, 61134, 61134, 61134, 61135, 61135, 61136, \n\t61136, 61136, 61137, 61137, 61137, 61138, 61138, 61138, \n\t61139, 61139, 61139, 61140, 61140, 61141, 61141, 61141, \n\t61142, 61142, 61142, 61143, 61143, 61143, 61144, 61144, \n\t61145, 61145, 61145, 61146, 61146, 61146, 61147, 61147, \n\t61147, 61148, 61148, 61148, 61149, 61149, 61150, 61150, \n\t61150, 61151, 61151, 61151, 61152, 61152, 61152, 61153, \n\t61153, 61154, 61154, 61154, 61155, 61155, 61155, 61156, \n\t61156, 61156, 61157, 61157, 61157, 61158, 61158, 61159, \n\t61159, 61159, 61160, 61160, 61160, 61161, 61161, 61161, \n\t61162, 61162, 61162, 61163, 61163, 61164, 61164, 61164, \n\t61165, 61165, 61165, 61166, 61166, 61166, 61167, 61167, \n\t61168, 61168, 61168, 61169, 61169, 61169, 61170, 61170, \n\t61170, 61171, 61171, 61171, 61172, 61172, 61173, 61173, \n\t61173, 61174, 61174, 61174, 61175, 61175, 61175, 61176, \n\t61176, 61176, 61177, 61177, 61178, 61178, 61178, 61179, \n\t61179, 61179, 61180, 61180, 61180, 61181, 61181, 61182, \n\t61182, 61182, 61183, 61183, 61183, 61184, 61184, 61184, \n\t61185, 61185, 61185, 61186, 61186, 61187, 61187, 61187, \n\t61188, 61188, 61188, 61189, 61189, 61189, 61190, 61190, \n\t61190, 61191, 61191, 61192, 61192, 61192, 61193, 61193, \n\t61193, 61194, 61194, 61194, 61195, 61195, 61195, 61196, \n\t61196, 61197, 61197, 61197, 61198, 61198, 61198, 61199, \n\t61199, 61199, 61200, 61200, 61200, 61201, 61201, 61202, \n\t61202, 61202, 61203, 61203, 61203, 61204, 61204, 61204, \n\t61205, 61205, 61205, 61206, 61206, 61207, 61207, 61207, \n\t61208, 61208, 61208, 61209, 61209, 61209, 61210, 61210, \n\t61210, 61211, 61211, 61212, 61212, 61212, 61213, 61213, \n\t61213, 61214, 61214, 61214, 61215, 61215, 61215, 61216, \n\t61216, 61217, 61217, 61217, 61218, 61218, 61218, 61219, \n\t61219, 61219, 61220, 61220, 61220, 61221, 61221, 61222, \n\t61222, 61222, 61223, 61223, 61223, 61224, 61224, 61224, \n\t61225, 61225, 61225, 61226, 61226, 61227, 61227, 61227, \n\t61228, 61228, 61228, 61229, 61229, 61229, 61230, 61230, \n\t61230, 61231, 61231, 61232, 61232, 61232, 61233, 61233, \n\t61233, 61234, 61234, 61234, 61235, 61235, 61235, 61236, \n\t61236, 61237, 61237, 61237, 61238, 61238, 61238, 61239, \n\t61239, 61239, 61240, 61240, 61240, 61241, 61241, 61242, \n\t61242, 61242, 61243, 61243, 61243, 61244, 61244, 61244, \n\t61245, 61245, 61245, 61246, 61246, 61247, 61247, 61247, \n\t61248, 61248, 61248, 61249, 61249, 61249, 61250, 61250, \n\t61250, 61251, 61251, 61251, 61252, 61252, 61253, 61253, \n\t61253, 61254, 61254, 61254, 61255, 61255, 61255, 61256, \n\t61256, 61256, 61257, 61257, 61258, 61258, 61258, 61259, \n\t61259, 61259, 61260, 61260, 61260, 61261, 61261, 61261, \n\t61262, 61262, 61263, 61263, 61263, 61264, 61264, 61264, \n\t61265, 61265, 61265, 61266, 61266, 61266, 61267, 61267, \n\t61267, 61268, 61268, 61269, 61269, 61269, 61270, 61270, \n\t61270, 61271, 61271, 61271, 61272, 61272, 61272, 61273, \n\t61273, 61274, 61274, 61274, 61275, 61275, 61275, 61276, \n\t61276, 61276, 61277, 61277, 61277, 61278, 61278, 61278, \n\t61279, 61279, 61280, 61280, 61280, 61281, 61281, 61281, \n\t61282, 61282, 61282, 61283, 61283, 61283, 61284, 61284, \n\t61285, 61285, 61285, 61286, 61286, 61286, 61287, 61287, \n\t61287, 61288, 61288, 61288, 61289, 61289, 61289, 61290, \n\t61290, 61291, 61291, 61291, 61292, 61292, 61292, 61293, \n\t61293, 61293, 61294, 61294, 61294, 61295, 61295, 61295, \n\t61296, 61296, 61297, 61297, 61297, 61298, 61298, 61298, \n\t61299, 61299, 61299, 61300, 61300, 61300, 61301, 61301, \n\t61301, 61302, 61302, 61303, 61303, 61303, 61304, 61304, \n\t61304, 61305, 61305, 61305, 61306, 61306, 61306, 61307, \n\t61307, 61308, 61308, 61308, 61309, 61309, 61309, 61310, \n\t61310, 61310, 61311, 61311, 61311, 61312, 61312, 61312, \n\t61313, 61313, 61314, 61314, 61314, 61315, 61315, 61315, \n\t61316, 61316, 61316, 61317, 61317, 61317, 61318, 61318, \n\t61318, 61319, 61319, 61320, 61320, 61320, 61321, 61321, \n\t61321, 61322, 61322, 61322, 61323, 61323, 61323, 61324, \n\t61324, 61324, 61325, 61325, 61326, 61326, 61326, 61327, \n\t61327, 61327, 61328, 61328, 61328, 61329, 61329, 61329, \n\t61330, 61330, 61330, 61331, 61331, 61331, 61332, 61332, \n\t61333, 61333, 61333, 61334, 61334, 61334, 61335, 61335, \n\t61335, 61336, 61336, 61336, 61337, 61337, 61337, 61338, \n\t61338, 61339, 61339, 61339, 61340, 61340, 61340, 61341, \n\t61341, 61341, 61342, 61342, 61342, 61343, 61343, 61343, \n\t61344, 61344, 61345, 61345, 61345, 61346, 61346, 61346, \n\t61347, 61347, 61347, 61348, 61348, 61348, 61349, 61349, \n\t61349, 61350, 61350, 61351, 61351, 61351, 61352, 61352, \n\t61352, 61353, 61353, 61353, 61354, 61354, 61354, 61355, \n\t61355, 61355, 61356, 61356, 61356, 61357, 61357, 61358, \n\t61358, 61358, 61359, 61359, 61359, 61360, 61360, 61360, \n\t61361, 61361, 61361, 61362, 61362, 61362, 61363, 61363, \n\t61364, 61364, 61364, 61365, 61365, 61365, 61366, 61366, \n\t61366, 61367, 61367, 61367, 61368, 61368, 61368, 61369, \n\t61369, 61369, 61370, 61370, 61371, 61371, 61371, 61372, \n\t61372, 61372, 61373, 61373, 61373, 61374, 61374, 61374, \n\t61375, 61375, 61375, 61376, 61376, 61376, 61377, 61377, \n\t61378, 61378, 61378, 61379, 61379, 61379, 61380, 61380, \n\t61380, 61381, 61381, 61381, 61382, 61382, 61382, 61383, \n\t61383, 61384, 61384, 61384, 61385, 61385, 61385, 61386, \n\t61386, 61386, 61387, 61387, 61387, 61388, 61388, 61388, \n\t61389, 61389, 61389, 61390, 61390, 61391, 61391, 61391, \n\t61392, 61392, 61392, 61393, 61393, 61393, 61394, 61394, \n\t61394, 61395, 61395, 61395, 61396, 61396, 61396, 61397, \n\t61397, 61398, 61398, 61398, 61399, 61399, 61399, 61400, \n\t61400, 61400, 61401, 61401, 61401, 61402, 61402, 61402, \n\t61403, 61403, 61403, 61404, 61404, 61404, 61405, 61405, \n\t61406, 61406, 61406, 61407, 61407, 61407, 61408, 61408, \n\t61408, 61409, 61409, 61409, 61410, 61410, 61410, 61411, \n\t61411, 61411, 61412, 61412, 61413, 61413, 61413, 61414, \n\t61414, 61414, 61415, 61415, 61415, 61416, 61416, 61416, \n\t61417, 61417, 61417, 61418, 61418, 61418, 61419, 61419, \n\t61420, 61420, 61420, 61421, 61421, 61421, 61422, 61422, \n\t61422, 61423, 61423, 61423, 61424, 61424, 61424, 61425, \n\t61425, 61425, 61426, 61426, 61426, 61427, 61427, 61428, \n\t61428, 61428, 61429, 61429, 61429, 61430, 61430, 61430, \n\t61431, 61431, 61431, 61432, 61432, 61432, 61433, 61433, \n\t61433, 61434, 61434, 61434, 61435, 61435, 61436, 61436, \n\t61436, 61437, 61437, 61437, 61438, 61438, 61438, 61439, \n\t61439, 61439, 61440, 61440, 61440, 61441, 61441, 61441, \n\t61442, 61442, 61442, 61443, 61443, 61444, 61444, 61444, \n\t61445, 61445, 61445, 61446, 61446, 61446, 61447, 61447, \n\t61447, 61448, 61448, 61448, 61449, 61449, 61449, 61450, \n\t61450, 61450, 61451, 61451, 61452, 61452, 61452, 61453, \n\t61453, 61453, 61454, 61454, 61454, 61455, 61455, 61455, \n\t61456, 61456, 61456, 61457, 61457, 61457, 61458, 61458, \n\t61458, 61459, 61459, 61460, 61460, 61460, 61461, 61461, \n\t61461, 61462, 61462, 61462, 61463, 61463, 61463, 61464, \n\t61464, 61464, 61465, 61465, 61465, 61466, 61466, 61466, \n\t61467, 61467, 61468, 61468, 61468, 61469, 61469, 61469, \n\t61470, 61470, 61470, 61471, 61471, 61471, 61472, 61472, \n\t61472, 61473, 61473, 61473, 61474, 61474, 61474, 61475, \n\t61475, 61475, 61476, 61476, 61477, 61477, 61477, 61478, \n\t61478, 61478, 61479, 61479, 61479, 61480, 61480, 61480, \n\t61481, 61481, 61481, 61482, 61482, 61482, 61483, 61483, \n\t61483, 61484, 61484, 61484, 61485, 61485, 61486, 61486, \n\t61486, 61487, 61487, 61487, 61488, 61488, 61488, 61489, \n\t61489, 61489, 61490, 61490, 61490, 61491, 61491, 61491, \n\t61492, 61492, 61492, 61493, 61493, 61493, 61494, 61494, \n\t61495, 61495, 61495, 61496, 61496, 61496, 61497, 61497, \n\t61497, 61498, 61498, 61498, 61499, 61499, 61499, 61500, \n\t61500, 61500, 61501, 61501, 61501, 61502, 61502, 61502, \n\t61503, 61503, 61504, 61504, 61504, 61505, 61505, 61505, \n\t61506, 61506, 61506, 61507, 61507, 61507, 61508, 61508, \n\t61508, 61509, 61509, 61509, 61510, 61510, 61510, 61511, \n\t61511, 61511, 61512, 61512, 61512, 61513, 61513, 61514, \n\t61514, 61514, 61515, 61515, 61515, 61516, 61516, 61516, \n\t61517, 61517, 61517, 61518, 61518, 61518, 61519, 61519, \n\t61519, 61520, 61520, 61520, 61521, 61521, 61521, 61522, \n\t61522, 61522, 61523, 61523, 61524, 61524, 61524, 61525, \n\t61525, 61525, 61526, 61526, 61526, 61527, 61527, 61527, \n\t61528, 61528, 61528, 61529, 61529, 61529, 61530, 61530, \n\t61530, 61531, 61531, 61531, 61532, 61532, 61532, 61533, \n\t61533, 61533, 61534, 61534, 61535, 61535, 61535, 61536, \n\t61536, 61536, 61537, 61537, 61537, 61538, 61538, 61538, \n\t61539, 61539, 61539, 61540, 61540, 61540, 61541, 61541, \n\t61541, 61542, 61542, 61542, 61543, 61543, 61543, 61544, \n\t61544, 61544, 61545, 61545, 61546, 61546, 61546, 61547, \n\t61547, 61547, 61548, 61548, 61548, 61549, 61549, 61549, \n\t61550, 61550, 61550, 61551, 61551, 61551, 61552, 61552, \n\t61552, 61553, 61553, 61553, 61554, 61554, 61554, 61555, \n\t61555, 61555, 61556, 61556, 61557, 61557, 61557, 61558, \n\t61558, 61558, 61559, 61559, 61559, 61560, 61560, 61560, \n\t61561, 61561, 61561, 61562, 61562, 61562, 61563, 61563, \n\t61563, 61564, 61564, 61564, 61565, 61565, 61565, 61566, \n\t61566, 61566, 61567, 61567, 61567, 61568, 61568, 61569, \n\t61569, 61569, 61570, 61570, 61570, 61571, 61571, 61571, \n\t61572, 61572, 61572, 61573, 61573, 61573, 61574, 61574, \n\t61574, 61575, 61575, 61575, 61576, 61576, 61576, 61577, \n\t61577, 61577, 61578, 61578, 61578, 61579, 61579, 61579, \n\t61580, 61580, 61581, 61581, 61581, 61582, 61582, 61582, \n\t61583, 61583, 61583, 61584, 61584, 61584, 61585, 61585, \n\t61585, 61586, 61586, 61586, 61587, 61587, 61587, 61588, \n\t61588, 61588, 61589, 61589, 61589, 61590, 61590, 61590, \n\t61591, 61591, 61591, 61592, 61592, 61592, 61593, 61593, \n\t61593, 61594, 61594, 61595, 61595, 61595, 61596, 61596, \n\t61596, 61597, 61597, 61597, 61598, 61598, 61598, 61599, \n\t61599, 61599, 61600, 61600, 61600, 61601, 61601, 61601, \n\t61602, 61602, 61602, 61603, 61603, 61603, 61604, 61604, \n\t61604, 61605, 61605, 61605, 61606, 61606, 61606, 61607, \n\t61607, 61607, 61608, 61608, 61609, 61609, 61609, 61610, \n\t61610, 61610, 61611, 61611, 61611, 61612, 61612, 61612, \n\t61613, 61613, 61613, 61614, 61614, 61614, 61615, 61615, \n\t61615, 61616, 61616, 61616, 61617, 61617, 61617, 61618, \n\t61618, 61618, 61619, 61619, 61619, 61620, 61620, 61620, \n\t61621, 61621, 61621, 61622, 61622, 61622, 61623, 61623, \n\t61624, 61624, 61624, 61625, 61625, 61625, 61626, 61626, \n\t61626, 61627, 61627, 61627, 61628, 61628, 61628, 61629, \n\t61629, 61629, 61630, 61630, 61630, 61631, 61631, 61631, \n\t61632, 61632, 61632, 61633, 61633, 61633, 61634, 61634, \n\t61634, 61635, 61635, 61635, 61636, 61636, 61636, 61637, \n\t61637, 61637, 61638, 61638, 61638, 61639, 61639, 61639, \n\t61640, 61640, 61641, 61641, 61641, 61642, 61642, 61642, \n\t61643, 61643, 61643, 61644, 61644, 61644, 61645, 61645, \n\t61645, 61646, 61646, 61646, 61647, 61647, 61647, 61648, \n\t61648, 61648, 61649, 61649, 61649, 61650, 61650, 61650, \n\t61651, 61651, 61651, 61652, 61652, 61652, 61653, 61653, \n\t61653, 61654, 61654, 61654, 61655, 61655, 61655, 61656, \n\t61656, 61656, 61657, 61657, 61657, 61658, 61658, 61658, \n\t61659, 61659, 61659, 61660, 61660, 61661, 61661, 61661, \n\t61662, 61662, 61662, 61663, 61663, 61663, 61664, 61664, \n\t61664, 61665, 61665, 61665, 61666, 61666, 61666, 61667, \n\t61667, 61667, 61668, 61668, 61668, 61669, 61669, 61669, \n\t61670, 61670, 61670, 61671, 61671, 61671, 61672, 61672, \n\t61672, 61673, 61673, 61673, 61674, 61674, 61674, 61675, \n\t61675, 61675, 61676, 61676, 61676, 61677, 61677, 61677, \n\t61678, 61678, 61678, 61679, 61679, 61679, 61680, 61680, \n\t61680, 61681, 61681, 61681, 61682, 61682, 61683, 61683, \n\t61683, 61684, 61684, 61684, 61685, 61685, 61685, 61686, \n\t61686, 61686, 61687, 61687, 61687, 61688, 61688, 61688, \n\t61689, 61689, 61689, 61690, 61690, 61690, 61691, 61691, \n\t61691, 61692, 61692, 61692, 61693, 61693, 61693, 61694, \n\t61694, 61694, 61695, 61695, 61695, 61696, 61696, 61696, \n\t61697, 61697, 61697, 61698, 61698, 61698, 61699, 61699, \n\t61699, 61700, 61700, 61700, 61701, 61701, 61701, 61702, \n\t61702, 61702, 61703, 61703, 61703, 61704, 61704, 61704, \n\t61705, 61705, 61705, 61706, 61706, 61706, 61707, 61707, \n\t61707, 61708, 61708, 61708, 61709, 61709, 61709, 61710, \n\t61710, 61710, 61711, 61711, 61712, 61712, 61712, 61713, \n\t61713, 61713, 61714, 61714, 61714, 61715, 61715, 61715, \n\t61716, 61716, 61716, 61717, 61717, 61717, 61718, 61718, \n\t61718, 61719, 61719, 61719, 61720, 61720, 61720, 61721, \n\t61721, 61721, 61722, 61722, 61722, 61723, 61723, 61723, \n\t61724, 61724, 61724, 61725, 61725, 61725, 61726, 61726, \n\t61726, 61727, 61727, 61727, 61728, 61728, 61728, 61729, \n\t61729, 61729, 61730, 61730, 61730, 61731, 61731, 61731, \n\t61732, 61732, 61732, 61733, 61733, 61733, 61734, 61734, \n\t61734, 61735, 61735, 61735, 61736, 61736, 61736, 61737, \n\t61737, 61737, 61738, 61738, 61738, 61739, 61739, 61739, \n\t61740, 61740, 61740, 61741, 61741, 61741, 61742, 61742, \n\t61742, 61743, 61743, 61743, 61744, 61744, 61744, 61745, \n\t61745, 61745, 61746, 61746, 61746, 61747, 61747, 61747, \n\t61748, 61748, 61748, 61749, 61749, 61749, 61750, 61750, \n\t61750, 61751, 61751, 61751, 61752, 61752, 61752, 61753, \n\t61753, 61753, 61754, 61754, 61754, 61755, 61755, 61755, \n\t61756, 61756, 61756, 61757, 61757, 61757, 61758, 61758, \n\t61758, 61759, 61759, 61759, 61760, 61760, 61760, 61761, \n\t61761, 61762, 61762, 61762, 61763, 61763, 61763, 61764, \n\t61764, 61764, 61765, 61765, 61765, 61766, 61766, 61766, \n\t61767, 61767, 61767, 61768, 61768, 61768, 61769, 61769, \n\t61769, 61770, 61770, 61770, 61771, 61771, 61771, 61772, \n\t61772, 61772, 61773, 61773, 61773, 61774, 61774, 61774, \n\t61775, 61775, 61775, 61776, 61776, 61776, 61777, 61777, \n\t61777, 61778, 61778, 61778, 61779, 61779, 61779, 61780, \n\t61780, 61780, 61781, 61781, 61781, 61782, 61782, 61782, \n\t61783, 61783, 61783, 61784, 61784, 61784, 61785, 61785, \n\t61785, 61786, 61786, 61786, 61787, 61787, 61787, 61788, \n\t61788, 61788, 61789, 61789, 61789, 61790, 61790, 61790, \n\t61791, 61791, 61791, 61792, 61792, 61792, 61793, 61793, \n\t61793, 61794, 61794, 61794, 61795, 61795, 61795, 61796, \n\t61796, 61796, 61797, 61797, 61797, 61798, 61798, 61798, \n\t61799, 61799, 61799, 61800, 61800, 61800, 61801, 61801, \n\t61801, 61802, 61802, 61802, 61803, 61803, 61803, 61804, \n\t61804, 61804, 61805, 61805, 61805, 61806, 61806, 61806, \n\t61807, 61807, 61807, 61808, 61808, 61808, 61809, 61809, \n\t61809, 61810, 61810, 61810, 61811, 61811, 61811, 61812, \n\t61812, 61812, 61813, 61813, 61813, 61814, 61814, 61814, \n\t61815, 61815, 61815, 61815, 61816, 61816, 61816, 61817, \n\t61817, 61817, 61818, 61818, 61818, 61819, 61819, 61819, \n\t61820, 61820, 61820, 61821, 61821, 61821, 61822, 61822, \n\t61822, 61823, 61823, 61823, 61824, 61824, 61824, 61825, \n\t61825, 61825, 61826, 61826, 61826, 61827, 61827, 61827, \n\t61828, 61828, 61828, 61829, 61829, 61829, 61830, 61830, \n\t61830, 61831, 61831, 61831, 61832, 61832, 61832, 61833, \n\t61833, 61833, 61834, 61834, 61834, 61835, 61835, 61835, \n\t61836, 61836, 61836, 61837, 61837, 61837, 61838, 61838, \n\t61838, 61839, 61839, 61839, 61840, 61840, 61840, 61841, \n\t61841, 61841, 61842, 61842, 61842, 61843, 61843, 61843, \n\t61844, 61844, 61844, 61845, 61845, 61845, 61846, 61846, \n\t61846, 61847, 61847, 61847, 61848, 61848, 61848, 61849, \n\t61849, 61849, 61850, 61850, 61850, 61851, 61851, 61851, \n\t61852, 61852, 61852, 61853, 61853, 61853, 61854, 61854, \n\t61854, 61855, 61855, 61855, 61856, 61856, 61856, 61857, \n\t61857, 61857, 61858, 61858, 61858, 61859, 61859, 61859, \n\t61860, 61860, 61860, 61861, 61861, 61861, 61862, 61862, \n\t61862, 61863, 61863, 61863, 61864, 61864, 61864, 61864, \n\t61865, 61865, 61865, 61866, 61866, 61866, 61867, 61867, \n\t61867, 61868, 61868, 61868, 61869, 61869, 61869, 61870, \n\t61870, 61870, 61871, 61871, 61871, 61872, 61872, 61872, \n\t61873, 61873, 61873, 61874, 61874, 61874, 61875, 61875, \n\t61875, 61876, 61876, 61876, 61877, 61877, 61877, 61878, \n\t61878, 61878, 61879, 61879, 61879, 61880, 61880, 61880, \n\t61881, 61881, 61881, 61882, 61882, 61882, 61883, 61883, \n\t61883, 61884, 61884, 61884, 61885, 61885, 61885, 61886, \n\t61886, 61886, 61887, 61887, 61887, 61888, 61888, 61888, \n\t61889, 61889, 61889, 61890, 61890, 61890, 61891, 61891, \n\t61891, 61892, 61892, 61892, 61892, 61893, 61893, 61893, \n\t61894, 61894, 61894, 61895, 61895, 61895, 61896, 61896, \n\t61896, 61897, 61897, 61897, 61898, 61898, 61898, 61899, \n\t61899, 61899, 61900, 61900, 61900, 61901, 61901, 61901, \n\t61902, 61902, 61902, 61903, 61903, 61903, 61904, 61904, \n\t61904, 61905, 61905, 61905, 61906, 61906, 61906, 61907, \n\t61907, 61907, 61908, 61908, 61908, 61909, 61909, 61909, \n\t61910, 61910, 61910, 61911, 61911, 61911, 61912, 61912, \n\t61912, 61913, 61913, 61913, 61914, 61914, 61914, 61914, \n\t61915, 61915, 61915, 61916, 61916, 61916, 61917, 61917, \n\t61917, 61918, 61918, 61918, 61919, 61919, 61919, 61920, \n\t61920, 61920, 61921, 61921, 61921, 61922, 61922, 61922, \n\t61923, 61923, 61923, 61924, 61924, 61924, 61925, 61925, \n\t61925, 61926, 61926, 61926, 61927, 61927, 61927, 61928, \n\t61928, 61928, 61929, 61929, 61929, 61930, 61930, 61930, \n\t61931, 61931, 61931, 61932, 61932, 61932, 61933, 61933, \n\t61933, 61933, 61934, 61934, 61934, 61935, 61935, 61935, \n\t61936, 61936, 61936, 61937, 61937, 61937, 61938, 61938, \n\t61938, 61939, 61939, 61939, 61940, 61940, 61940, 61941, \n\t61941, 61941, 61942, 61942, 61942, 61943, 61943, 61943, \n\t61944, 61944, 61944, 61945, 61945, 61945, 61946, 61946, \n\t61946, 61947, 61947, 61947, 61948, 61948, 61948, 61949, \n\t61949, 61949, 61949, 61950, 61950, 61950, 61951, 61951, \n\t61951, 61952, 61952, 61952, 61953, 61953, 61953, 61954, \n\t61954, 61954, 61955, 61955, 61955, 61956, 61956, 61956, \n\t61957, 61957, 61957, 61958, 61958, 61958, 61959, 61959, \n\t61959, 61960, 61960, 61960, 61961, 61961, 61961, 61962, \n\t61962, 61962, 61963, 61963, 61963, 61964, 61964, 61964, \n\t61964, 61965, 61965, 61965, 61966, 61966, 61966, 61967, \n\t61967, 61967, 61968, 61968, 61968, 61969, 61969, 61969, \n\t61970, 61970, 61970, 61971, 61971, 61971, 61972, 61972, \n\t61972, 61973, 61973, 61973, 61974, 61974, 61974, 61975, \n\t61975, 61975, 61976, 61976, 61976, 61977, 61977, 61977, \n\t61977, 61978, 61978, 61978, 61979, 61979, 61979, 61980, \n\t61980, 61980, 61981, 61981, 61981, 61982, 61982, 61982, \n\t61983, 61983, 61983, 61984, 61984, 61984, 61985, 61985, \n\t61985, 61986, 61986, 61986, 61987, 61987, 61987, 61988, \n\t61988, 61988, 61989, 61989, 61989, 61990, 61990, 61990, \n\t61990, 61991, 61991, 61991, 61992, 61992, 61992, 61993, \n\t61993, 61993, 61994, 61994, 61994, 61995, 61995, 61995, \n\t61996, 61996, 61996, 61997, 61997, 61997, 61998, 61998, \n\t61998, 61999, 61999, 61999, 62000, 62000, 62000, 62001, \n\t62001, 62001, 62002, 62002, 62002, 62002, 62003, 62003, \n\t62003, 62004, 62004, 62004, 62005, 62005, 62005, 62006, \n\t62006, 62006, 62007, 62007, 62007, 62008, 62008, 62008, \n\t62009, 62009, 62009, 62010, 62010, 62010, 62011, 62011, \n\t62011, 62012, 62012, 62012, 62013, 62013, 62013, 62013, \n\t62014, 62014, 62014, 62015, 62015, 62015, 62016, 62016, \n\t62016, 62017, 62017, 62017, 62018, 62018, 62018, 62019, \n\t62019, 62019, 62020, 62020, 62020, 62021, 62021, 62021, \n\t62022, 62022, 62022, 62023, 62023, 62023, 62024, 62024, \n\t62024, 62024, 62025, 62025, 62025, 62026, 62026, 62026, \n\t62027, 62027, 62027, 62028, 62028, 62028, 62029, 62029, \n\t62029, 62030, 62030, 62030, 62031, 62031, 62031, 62032, \n\t62032, 62032, 62033, 62033, 62033, 62034, 62034, 62034, \n\t62034, 62035, 62035, 62035, 62036, 62036, 62036, 62037, \n\t62037, 62037, 62038, 62038, 62038, 62039, 62039, 62039, \n\t62040, 62040, 62040, 62041, 62041, 62041, 62042, 62042, \n\t62042, 62043, 62043, 62043, 62044, 62044, 62044, 62044, \n\t62045, 62045, 62045, 62046, 62046, 62046, 62047, 62047, \n\t62047, 62048, 62048, 62048, 62049, 62049, 62049, 62050, \n\t62050, 62050, 62051, 62051, 62051, 62052, 62052, 62052, \n\t62053, 62053, 62053, 62053, 62054, 62054, 62054, 62055, \n\t62055, 62055, 62056, 62056, 62056, 62057, 62057, 62057, \n\t62058, 62058, 62058, 62059, 62059, 62059, 62060, 62060, \n\t62060, 62061, 62061, 62061, 62062, 62062, 62062, 62062, \n\t62063, 62063, 62063, 62064, 62064, 62064, 62065, 62065, \n\t62065, 62066, 62066, 62066, 62067, 62067, 62067, 62068, \n\t62068, 62068, 62069, 62069, 62069, 62070, 62070, 62070, \n\t62071, 62071, 62071, 62071, 62072, 62072, 62072, 62073, \n\t62073, 62073, 62074, 62074, 62074, 62075, 62075, 62075, \n\t62076, 62076, 62076, 62077, 62077, 62077, 62078, 62078, \n\t62078, 62079, 62079, 62079, 62079, 62080, 62080, 62080, \n\t62081, 62081, 62081, 62082, 62082, 62082, 62083, 62083, \n\t62083, 62084, 62084, 62084, 62085, 62085, 62085, 62086, \n\t62086, 62086, 62087, 62087, 62087, 62087, 62088, 62088, \n\t62088, 62089, 62089, 62089, 62090, 62090, 62090, 62091, \n\t62091, 62091, 62092, 62092, 62092, 62093, 62093, 62093, \n\t62094, 62094, 62094, 62095, 62095, 62095, 62095, 62096, \n\t62096, 62096, 62097, 62097, 62097, 62098, 62098, 62098, \n\t62099, 62099, 62099, 62100, 62100, 62100, 62101, 62101, \n\t62101, 62102, 62102, 62102, 62103, 62103, 62103, 62103, \n\t62104, 62104, 62104, 62105, 62105, 62105, 62106, 62106, \n\t62106, 62107, 62107, 62107, 62108, 62108, 62108, 62109, \n\t62109, 62109, 62110, 62110, 62110, 62111, 62111, 62111, \n\t62111, 62112, 62112, 62112, 62113, 62113, 62113, 62114, \n\t62114, 62114, 62115, 62115, 62115, 62116, 62116, 62116, \n\t62117, 62117, 62117, 62118, 62118, 62118, 62118, 62119, \n\t62119, 62119, 62120, 62120, 62120, 62121, 62121, 62121, \n\t62122, 62122, 62122, 62123, 62123, 62123, 62124, 62124, \n\t62124, 62125, 62125, 62125, 62125, 62126, 62126, 62126, \n\t62127, 62127, 62127, 62128, 62128, 62128, 62129, 62129, \n\t62129, 62130, 62130, 62130, 62131, 62131, 62131, 62132, \n\t62132, 62132, 62132, 62133, 62133, 62133, 62134, 62134, \n\t62134, 62135, 62135, 62135, 62136, 62136, 62136, 62137, \n\t62137, 62137, 62138, 62138, 62138, 62139, 62139, 62139, \n\t62139, 62140, 62140, 62140, 62141, 62141, 62141, 62142, \n\t62142, 62142, 62143, 62143, 62143, 62144, 62144, 62144, \n\t62145, 62145, 62145, 62146, 62146, 62146, 62146, 62147, \n\t62147, 62147, 62148, 62148, 62148, 62149, 62149, 62149, \n\t62150, 62150, 62150, 62151, 62151, 62151, 62152, 62152, \n\t62152, 62152, 62153, 62153, 62153, 62154, 62154, 62154, \n\t62155, 62155, 62155, 62156, 62156, 62156, 62157, 62157, \n\t62157, 62158, 62158, 62158, 62159, 62159, 62159, 62159, \n\t62160, 62160, 62160, 62161, 62161, 62161, 62162, 62162, \n\t62162, 62163, 62163, 62163, 62164, 62164, 62164, 62165, \n\t62165, 62165, 62165, 62166, 62166, 62166, 62167, 62167, \n\t62167, 62168, 62168, 62168, 62169, 62169, 62169, 62170, \n\t62170, 62170, 62171, 62171, 62171, 62171, 62172, 62172, \n\t62172, 62173, 62173, 62173, 62174, 62174, 62174, 62175, \n\t62175, 62175, 62176, 62176, 62176, 62177, 62177, 62177, \n\t62178, 62178, 62178, 62178, 62179, 62179, 62179, 62180, \n\t62180, 62180, 62181, 62181, 62181, 62182, 62182, 62182, \n\t62183, 62183, 62183, 62184, 62184, 62184, 62184, 62185, \n\t62185, 62185, 62186, 62186, 62186, 62187, 62187, 62187, \n\t62188, 62188, 62188, 62189, 62189, 62189, 62190, 62190, \n\t62190, 62190, 62191, 62191, 62191, 62192, 62192, 62192, \n\t62193, 62193, 62193, 62194, 62194, 62194, 62195, 62195, \n\t62195, 62195, 62196, 62196, 62196, 62197, 62197, 62197, \n\t62198, 62198, 62198, 62199, 62199, 62199, 62200, 62200, \n\t62200, 62201, 62201, 62201, 62201, 62202, 62202, 62202, \n\t62203, 62203, 62203, 62204, 62204, 62204, 62205, 62205, \n\t62205, 62206, 62206, 62206, 62207, 62207, 62207, 62207, \n\t62208, 62208, 62208, 62209, 62209, 62209, 62210, 62210, \n\t62210, 62211, 62211, 62211, 62212, 62212, 62212, 62212, \n\t62213, 62213, 62213, 62214, 62214, 62214, 62215, 62215, \n\t62215, 62216, 62216, 62216, 62217, 62217, 62217, 62218, \n\t62218, 62218, 62218, 62219, 62219, 62219, 62220, 62220, \n\t62220, 62221, 62221, 62221, 62222, 62222, 62222, 62223, \n\t62223, 62223, 62223, 62224, 62224, 62224, 62225, 62225, \n\t62225, 62226, 62226, 62226, 62227, 62227, 62227, 62228, \n\t62228, 62228, 62229, 62229, 62229, 62229, 62230, 62230, \n\t62230, 62231, 62231, 62231, 62232, 62232, 62232, 62233, \n\t62233, 62233, 62234, 62234, 62234, 62234, 62235, 62235, \n\t62235, 62236, 62236, 62236, 62237, 62237, 62237, 62238, \n\t62238, 62238, 62239, 62239, 62239, 62239, 62240, 62240, \n\t62240, 62241, 62241, 62241, 62242, 62242, 62242, 62243, \n\t62243, 62243, 62244, 62244, 62244, 62244, 62245, 62245, \n\t62245, 62246, 62246, 62246, 62247, 62247, 62247, 62248, \n\t62248, 62248, 62249, 62249, 62249, 62249, 62250, 62250, \n\t62250, 62251, 62251, 62251, 62252, 62252, 62252, 62253, \n\t62253, 62253, 62254, 62254, 62254, 62254, 62255, 62255, \n\t62255, 62256, 62256, 62256, 62257, 62257, 62257, 62258, \n\t62258, 62258, 62259, 62259, 62259, 62259, 62260, 62260, \n\t62260, 62261, 62261, 62261, 62262, 62262, 62262, 62263, \n\t62263, 62263, 62264, 62264, 62264, 62264, 62265, 62265, \n\t62265, 62266, 62266, 62266, 62267, 62267, 62267, 62268, \n\t62268, 62268, 62269, 62269, 62269, 62269, 62270, 62270, \n\t62270, 62271, 62271, 62271, 62272, 62272, 62272, 62273, \n\t62273, 62273, 62274, 62274, 62274, 62274, 62275, 62275, \n\t62275, 62276, 62276, 62276, 62277, 62277, 62277, 62278, \n\t62278, 62278, 62279, 62279, 62279, 62279, 62280, 62280, \n\t62280, 62281, 62281, 62281, 62282, 62282, 62282, 62283, \n\t62283, 62283, 62283, 62284, 62284, 62284, 62285, 62285, \n\t62285, 62286, 62286, 62286, 62287, 62287, 62287, 62288, \n\t62288, 62288, 62288, 62289, 62289, 62289, 62290, 62290, \n\t62290, 62291, 62291, 62291, 62292, 62292, 62292, 62293, \n\t62293, 62293, 62293, 62294, 62294, 62294, 62295, 62295, \n\t62295, 62296, 62296, 62296, 62297, 62297, 62297, 62297, \n\t62298, 62298, 62298, 62299, 62299, 62299, 62300, 62300, \n\t62300, 62301, 62301, 62301, 62302, 62302, 62302, 62302, \n\t62303, 62303, 62303, 62304, 62304, 62304, 62305, 62305, \n\t62305, 62306, 62306, 62306, 62306, 62307, 62307, 62307, \n\t62308, 62308, 62308, 62309, 62309, 62309, 62310, 62310, \n\t62310, 62311, 62311, 62311, 62311, 62312, 62312, 62312, \n\t62313, 62313, 62313, 62314, 62314, 62314, 62315, 62315, \n\t62315, 62315, 62316, 62316, 62316, 62317, 62317, 62317, \n\t62318, 62318, 62318, 62319, 62319, 62319, 62319, 62320, \n\t62320, 62320, 62321, 62321, 62321, 62322, 62322, 62322, \n\t62323, 62323, 62323, 62324, 62324, 62324, 62324, 62325, \n\t62325, 62325, 62326, 62326, 62326, 62327, 62327, 62327, \n\t62328, 62328, 62328, 62328, 62329, 62329, 62329, 62330, \n\t62330, 62330, 62331, 62331, 62331, 62332, 62332, 62332, \n\t62332, 62333, 62333, 62333, 62334, 62334, 62334, 62335, \n\t62335, 62335, 62336, 62336, 62336, 62336, 62337, 62337, \n\t62337, 62338, 62338, 62338, 62339, 62339, 62339, 62340, \n\t62340, 62340, 62340, 62341, 62341, 62341, 62342, 62342, \n\t62342, 62343, 62343, 62343, 62344, 62344, 62344, 62344, \n\t62345, 62345, 62345, 62346, 62346, 62346, 62347, 62347, \n\t62347, 62348, 62348, 62348, 62349, 62349, 62349, 62349, \n\t62350, 62350, 62350, 62351, 62351, 62351, 62352, 62352, \n\t62352, 62353, 62353, 62353, 62353, 62354, 62354, 62354, \n\t62355, 62355, 62355, 62356, 62356, 62356, 62357, 62357, \n\t62357, 62357, 62358, 62358, 62358, 62359, 62359, 62359, \n\t62360, 62360, 62360, 62361, 62361, 62361, 62361, 62362, \n\t62362, 62362, 62363, 62363, 62363, 62364, 62364, 62364, \n\t62365, 62365, 62365, 62365, 62366, 62366, 62366, 62367, \n\t62367, 62367, 62368, 62368, 62368, 62368, 62369, 62369, \n\t62369, 62370, 62370, 62370, 62371, 62371, 62371, 62372, \n\t62372, 62372, 62372, 62373, 62373, 62373, 62374, 62374, \n\t62374, 62375, 62375, 62375, 62376, 62376, 62376, 62376, \n\t62377, 62377, 62377, 62378, 62378, 62378, 62379, 62379, \n\t62379, 62380, 62380, 62380, 62380, 62381, 62381, 62381, \n\t62382, 62382, 62382, 62383, 62383, 62383, 62384, 62384, \n\t62384, 62384, 62385, 62385, 62385, 62386, 62386, 62386, \n\t62387, 62387, 62387, 62388, 62388, 62388, 62388, 62389, \n\t62389, 62389, 62390, 62390, 62390, 62391, 62391, 62391, \n\t62391, 62392, 62392, 62392, 62393, 62393, 62393, 62394, \n\t62394, 62394, 62395, 62395, 62395, 62395, 62396, 62396, \n\t62396, 62397, 62397, 62397, 62398, 62398, 62398, 62399, \n\t62399, 62399, 62399, 62400, 62400, 62400, 62401, 62401, \n\t62401, 62402, 62402, 62402, 62403, 62403, 62403, 62403, \n\t62404, 62404, 62404, 62405, 62405, 62405, 62406, 62406, \n\t62406, 62406, 62407, 62407, 62407, 62408, 62408, 62408, \n\t62409, 62409, 62409, 62410, 62410, 62410, 62410, 62411, \n\t62411, 62411, 62412, 62412, 62412, 62413, 62413, 62413, \n\t62413, 62414, 62414, 62414, 62415, 62415, 62415, 62416, \n\t62416, 62416, 62417, 62417, 62417, 62417, 62418, 62418, \n\t62418, 62419, 62419, 62419, 62420, 62420, 62420, 62421, \n\t62421, 62421, 62421, 62422, 62422, 62422, 62423, 62423, \n\t62423, 62424, 62424, 62424, 62424, 62425, 62425, 62425, \n\t62426, 62426, 62426, 62427, 62427, 62427, 62428, 62428, \n\t62428, 62428, 62429, 62429, 62429, 62430, 62430, 62430, \n\t62431, 62431, 62431, 62431, 62432, 62432, 62432, 62433, \n\t62433, 62433, 62434, 62434, 62434, 62435, 62435, 62435, \n\t62435, 62436, 62436, 62436, 62437, 62437, 62437, 62438, \n\t62438, 62438, 62438, 62439, 62439, 62439, 62440, 62440, \n\t62440, 62441, 62441, 62441, 62441, 62442, 62442, 62442, \n\t62443, 62443, 62443, 62444, 62444, 62444, 62445, 62445, \n\t62445, 62445, 62446, 62446, 62446, 62447, 62447, 62447, \n\t62448, 62448, 62448, 62448, 62449, 62449, 62449, 62450, \n\t62450, 62450, 62451, 62451, 62451, 62452, 62452, 62452, \n\t62452, 62453, 62453, 62453, 62454, 62454, 62454, 62455, \n\t62455, 62455, 62455, 62456, 62456, 62456, 62457, 62457, \n\t62457, 62458, 62458, 62458, 62458, 62459, 62459, 62459, \n\t62460, 62460, 62460, 62461, 62461, 62461, 62461, 62462, \n\t62462, 62462, 62463, 62463, 62463, 62464, 62464, 62464, \n\t62465, 62465, 62465, 62465, 62466, 62466, 62466, 62467, \n\t62467, 62467, 62468, 62468, 62468, 62468, 62469, 62469, \n\t62469, 62470, 62470, 62470, 62471, 62471, 62471, 62471, \n\t62472, 62472, 62472, 62473, 62473, 62473, 62474, 62474, \n\t62474, 62475, 62475, 62475, 62475, 62476, 62476, 62476, \n\t62477, 62477, 62477, 62478, 62478, 62478, 62478, 62479, \n\t62479, 62479, 62480, 62480, 62480, 62481, 62481, 62481, \n\t62481, 62482, 62482, 62482, 62483, 62483, 62483, 62484, \n\t62484, 62484, 62484, 62485, 62485, 62485, 62486, 62486, \n\t62486, 62487, 62487, 62487, 62487, 62488, 62488, 62488, \n\t62489, 62489, 62489, 62490, 62490, 62490, 62490, 62491, \n\t62491, 62491, 62492, 62492, 62492, 62493, 62493, 62493, \n\t62494, 62494, 62494, 62494, 62495, 62495, 62495, 62496, \n\t62496, 62496, 62497, 62497, 62497, 62497, 62498, 62498, \n\t62498, 62499, 62499, 62499, 62500, 62500, 62500, 62500, \n\t62501, 62501, 62501, 62502, 62502, 62502, 62503, 62503, \n\t62503, 62503, 62504, 62504, 62504, 62505, 62505, 62505, \n\t62506, 62506, 62506, 62506, 62507, 62507, 62507, 62508, \n\t62508, 62508, 62509, 62509, 62509, 62509, 62510, 62510, \n\t62510, 62511, 62511, 62511, 62512, 62512, 62512, 62512, \n\t62513, 62513, 62513, 62514, 62514, 62514, 62515, 62515, \n\t62515, 62515, 62516, 62516, 62516, 62517, 62517, 62517, \n\t62518, 62518, 62518, 62518, 62519, 62519, 62519, 62520, \n\t62520, 62520, 62521, 62521, 62521, 62521, 62522, 62522, \n\t62522, 62523, 62523, 62523, 62524, 62524, 62524, 62524, \n\t62525, 62525, 62525, 62526, 62526, 62526, 62527, 62527, \n\t62527, 62527, 62528, 62528, 62528, 62529, 62529, 62529, \n\t62530, 62530, 62530, 62530, 62531, 62531, 62531, 62532, \n\t62532, 62532, 62533, 62533, 62533, 62533, 62534, 62534, \n\t62534, 62535, 62535, 62535, 62536, 62536, 62536, 62536, \n\t62537, 62537, 62537, 62538, 62538, 62538, 62539, 62539, \n\t62539, 62539, 62540, 62540, 62540, 62541, 62541, 62541, \n\t62542, 62542, 62542, 62542, 62543, 62543, 62543, 62544, \n\t62544, 62544, 62544, 62545, 62545, 62545, 62546, 62546, \n\t62546, 62547, 62547, 62547, 62547, 62548, 62548, 62548, \n\t62549, 62549, 62549, 62550, 62550, 62550, 62550, 62551, \n\t62551, 62551, 62552, 62552, 62552, 62553, 62553, 62553, \n\t62553, 62554, 62554, 62554, 62555, 62555, 62555, 62556, \n\t62556, 62556, 62556, 62557, 62557, 62557, 62558, 62558, \n\t62558, 62559, 62559, 62559, 62559, 62560, 62560, 62560, \n\t62561, 62561, 62561, 62561, 62562, 62562, 62562, 62563, \n\t62563, 62563, 62564, 62564, 62564, 62564, 62565, 62565, \n\t62565, 62566, 62566, 62566, 62567, 62567, 62567, 62567, \n\t62568, 62568, 62568, 62569, 62569, 62569, 62570, 62570, \n\t62570, 62570, 62571, 62571, 62571, 62572, 62572, 62572, \n\t62573, 62573, 62573, 62573, 62574, 62574, 62574, 62575, \n\t62575, 62575, 62575, 62576, 62576, 62576, 62577, 62577, \n\t62577, 62578, 62578, 62578, 62578, 62579, 62579, 62579, \n\t62580, 62580, 62580, 62581, 62581, 62581, 62581, 62582, \n\t62582, 62582, 62583, 62583, 62583, 62583, 62584, 62584, \n\t62584, 62585, 62585, 62585, 62586, 62586, 62586, 62586, \n\t62587, 62587, 62587, 62588, 62588, 62588, 62589, 62589, \n\t62589, 62589, 62590, 62590, 62590, 62591, 62591, 62591, \n\t62591, 62592, 62592, 62592, 62593, 62593, 62593, 62594, \n\t62594, 62594, 62594, 62595, 62595, 62595, 62596, 62596, \n\t62596, 62597, 62597, 62597, 62597, 62598, 62598, 62598, \n\t62599, 62599, 62599, 62599, 62600, 62600, 62600, 62601, \n\t62601, 62601, 62602, 62602, 62602, 62602, 62603, 62603, \n\t62603, 62604, 62604, 62604, 62605, 62605, 62605, 62605, \n\t62606, 62606, 62606, 62607, 62607, 62607, 62607, 62608, \n\t62608, 62608, 62609, 62609, 62609, 62610, 62610, 62610, \n\t62610, 62611, 62611, 62611, 62612, 62612, 62612, 62613, \n\t62613, 62613, 62613, 62614, 62614, 62614, 62615, 62615, \n\t62615, 62615, 62616, 62616, 62616, 62617, 62617, 62617, \n\t62618, 62618, 62618, 62618, 62619, 62619, 62619, 62620, \n\t62620, 62620, 62620, 62621, 62621, 62621, 62622, 62622, \n\t62622, 62623, 62623, 62623, 62623, 62624, 62624, 62624, \n\t62625, 62625, 62625, 62625, 62626, 62626, 62626, 62627, \n\t62627, 62627, 62628, 62628, 62628, 62628, 62629, 62629, \n\t62629, 62630, 62630, 62630, 62630, 62631, 62631, 62631, \n\t62632, 62632, 62632, 62633, 62633, 62633, 62633, 62634, \n\t62634, 62634, 62635, 62635, 62635, 62635, 62636, 62636, \n\t62636, 62637, 62637, 62637, 62638, 62638, 62638, 62638, \n\t62639, 62639, 62639, 62640, 62640, 62640, 62640, 62641, \n\t62641, 62641, 62642, 62642, 62642, 62643, 62643, 62643, \n\t62643, 62644, 62644, 62644, 62645, 62645, 62645, 62645, \n\t62646, 62646, 62646, 62647, 62647, 62647, 62648, 62648, \n\t62648, 62648, 62649, 62649, 62649, 62650, 62650, 62650, \n\t62650, 62651, 62651, 62651, 62652, 62652, 62652, 62653, \n\t62653, 62653, 62653, 62654, 62654, 62654, 62655, 62655, \n\t62655, 62655, 62656, 62656, 62656, 62657, 62657, 62657, \n\t62658, 62658, 62658, 62658, 62659, 62659, 62659, 62660, \n\t62660, 62660, 62660, 62661, 62661, 62661, 62662, 62662, \n\t62662, 62663, 62663, 62663, 62663, 62664, 62664, 62664, \n\t62665, 62665, 62665, 62665, 62666, 62666, 62666, 62667, \n\t62667, 62667, 62667, 62668, 62668, 62668, 62669, 62669, \n\t62669, 62670, 62670, 62670, 62670, 62671, 62671, 62671, \n\t62672, 62672, 62672, 62672, 62673, 62673, 62673, 62674, \n\t62674, 62674, 62674, 62675, 62675, 62675, 62676, 62676, \n\t62676, 62677, 62677, 62677, 62677, 62678, 62678, 62678, \n\t62679, 62679, 62679, 62679, 62680, 62680, 62680, 62681, \n\t62681, 62681, 62682, 62682, 62682, 62682, 62683, 62683, \n\t62683, 62684, 62684, 62684, 62684, 62685, 62685, 62685, \n\t62686, 62686, 62686, 62686, 62687, 62687, 62687, 62688, \n\t62688, 62688, 62689, 62689, 62689, 62689, 62690, 62690, \n\t62690, 62691, 62691, 62691, 62691, 62692, 62692, 62692, \n\t62693, 62693, 62693, 62693, 62694, 62694, 62694, 62695, \n\t62695, 62695, 62696, 62696, 62696, 62696, 62697, 62697, \n\t62697, 62698, 62698, 62698, 62698, 62699, 62699, 62699, \n\t62700, 62700, 62700, 62700, 62701, 62701, 62701, 62702, \n\t62702, 62702, 62702, 62703, 62703, 62703, 62704, 62704, \n\t62704, 62705, 62705, 62705, 62705, 62706, 62706, 62706, \n\t62707, 62707, 62707, 62707, 62708, 62708, 62708, 62709, \n\t62709, 62709, 62709, 62710, 62710, 62710, 62711, 62711, \n\t62711, 62711, 62712, 62712, 62712, 62713, 62713, 62713, \n\t62714, 62714, 62714, 62714, 62715, 62715, 62715, 62716, \n\t62716, 62716, 62716, 62717, 62717, 62717, 62718, 62718, \n\t62718, 62718, 62719, 62719, 62719, 62720, 62720, 62720, \n\t62720, 62721, 62721, 62721, 62722, 62722, 62722, 62723, \n\t62723, 62723, 62723, 62724, 62724, 62724, 62725, 62725, \n\t62725, 62725, 62726, 62726, 62726, 62727, 62727, 62727, \n\t62727, 62728, 62728, 62728, 62729, 62729, 62729, 62729, \n\t62730, 62730, 62730, 62731, 62731, 62731, 62732, 62732, \n\t62732, 62732, 62733, 62733, 62733, 62734, 62734, 62734, \n\t62734, 62735, 62735, 62735, 62736, 62736, 62736, 62736, \n\t62737, 62737, 62737, 62738, 62738, 62738, 62738, 62739, \n\t62739, 62739, 62740, 62740, 62740, 62740, 62741, 62741, \n\t62741, 62742, 62742, 62742, 62742, 62743, 62743, 62743, \n\t62744, 62744, 62744, 62745, 62745, 62745, 62745, 62746, \n\t62746, 62746, 62747, 62747, 62747, 62747, 62748, 62748, \n\t62748, 62749, 62749, 62749, 62749, 62750, 62750, 62750, \n\t62751, 62751, 62751, 62751, 62752, 62752, 62752, 62753, \n\t62753, 62753, 62753, 62754, 62754, 62754, 62755, 62755, \n\t62755, 62755, 62756, 62756, 62756, 62757, 62757, 62757, \n\t62757, 62758, 62758, 62758, 62759, 62759, 62759, 62760, \n\t62760, 62760, 62760, 62761, 62761, 62761, 62762, 62762, \n\t62762, 62762, 62763, 62763, 62763, 62764, 62764, 62764, \n\t62764, 62765, 62765, 62765, 62766, 62766, 62766, 62766, \n\t62767, 62767, 62767, 62768, 62768, 62768, 62768, 62769, \n\t62769, 62769, 62770, 62770, 62770, 62770, 62771, 62771, \n\t62771, 62772, 62772, 62772, 62772, 62773, 62773, 62773, \n\t62774, 62774, 62774, 62774, 62775, 62775, 62775, 62776, \n\t62776, 62776, 62776, 62777, 62777, 62777, 62778, 62778, \n\t62778, 62778, 62779, 62779, 62779, 62780, 62780, 62780, \n\t62780, 62781, 62781, 62781, 62782, 62782, 62782, 62782, \n\t62783, 62783, 62783, 62784, 62784, 62784, 62785, 62785, \n\t62785, 62785, 62786, 62786, 62786, 62787, 62787, 62787, \n\t62787, 62788, 62788, 62788, 62789, 62789, 62789, 62789, \n\t62790, 62790, 62790, 62791, 62791, 62791, 62791, 62792, \n\t62792, 62792, 62793, 62793, 62793, 62793, 62794, 62794, \n\t62794, 62795, 62795, 62795, 62795, 62796, 62796, 62796, \n\t62797, 62797, 62797, 62797, 62798, 62798, 62798, 62799, \n\t62799, 62799, 62799, 62800, 62800, 62800, 62801, 62801, \n\t62801, 62801, 62802, 62802, 62802, 62803, 62803, 62803, \n\t62803, 62804, 62804, 62804, 62805, 62805, 62805, 62805, \n\t62806, 62806, 62806, 62807, 62807, 62807, 62807, 62808, \n\t62808, 62808, 62809, 62809, 62809, 62809, 62810, 62810, \n\t62810, 62811, 62811, 62811, 62811, 62812, 62812, 62812, \n\t62813, 62813, 62813, 62813, 62814, 62814, 62814, 62815, \n\t62815, 62815, 62815, 62816, 62816, 62816, 62817, 62817, \n\t62817, 62817, 62818, 62818, 62818, 62819, 62819, 62819, \n\t62819, 62820, 62820, 62820, 62821, 62821, 62821, 62821, \n\t62822, 62822, 62822, 62823, 62823, 62823, 62823, 62824, \n\t62824, 62824, 62825, 62825, 62825, 62825, 62826, 62826, \n\t62826, 62826, 62827, 62827, 62827, 62828, 62828, 62828, \n\t62828, 62829, 62829, 62829, 62830, 62830, 62830, 62830, \n\t62831, 62831, 62831, 62832, 62832, 62832, 62832, 62833, \n\t62833, 62833, 62834, 62834, 62834, 62834, 62835, 62835, \n\t62835, 62836, 62836, 62836, 62836, 62837, 62837, 62837, \n\t62838, 62838, 62838, 62838, 62839, 62839, 62839, 62840, \n\t62840, 62840, 62840, 62841, 62841, 62841, 62842, 62842, \n\t62842, 62842, 62843, 62843, 62843, 62844, 62844, 62844, \n\t62844, 62845, 62845, 62845, 62846, 62846, 62846, 62846, \n\t62847, 62847, 62847, 62848, 62848, 62848, 62848, 62849, \n\t62849, 62849, 62849, 62850, 62850, 62850, 62851, 62851, \n\t62851, 62851, 62852, 62852, 62852, 62853, 62853, 62853, \n\t62853, 62854, 62854, 62854, 62855, 62855, 62855, 62855, \n\t62856, 62856, 62856, 62857, 62857, 62857, 62857, 62858, \n\t62858, 62858, 62859, 62859, 62859, 62859, 62860, 62860, \n\t62860, 62861, 62861, 62861, 62861, 62862, 62862, 62862, \n\t62863, 62863, 62863, 62863, 62864, 62864, 62864, 62864, \n\t62865, 62865, 62865, 62866, 62866, 62866, 62866, 62867, \n\t62867, 62867, 62868, 62868, 62868, 62868, 62869, 62869, \n\t62869, 62870, 62870, 62870, 62870, 62871, 62871, 62871, \n\t62872, 62872, 62872, 62872, 62873, 62873, 62873, 62874, \n\t62874, 62874, 62874, 62875, 62875, 62875, 62876, 62876, \n\t62876, 62876, 62877, 62877, 62877, 62877, 62878, 62878, \n\t62878, 62879, 62879, 62879, 62879, 62880, 62880, 62880, \n\t62881, 62881, 62881, 62881, 62882, 62882, 62882, 62883, \n\t62883, 62883, 62883, 62884, 62884, 62884, 62885, 62885, \n\t62885, 62885, 62886, 62886, 62886, 62886, 62887, 62887, \n\t62887, 62888, 62888, 62888, 62888, 62889, 62889, 62889, \n\t62890, 62890, 62890, 62890, 62891, 62891, 62891, 62892, \n\t62892, 62892, 62892, 62893, 62893, 62893, 62894, 62894, \n\t62894, 62894, 62895, 62895, 62895, 62895, 62896, 62896, \n\t62896, 62897, 62897, 62897, 62897, 62898, 62898, 62898, \n\t62899, 62899, 62899, 62899, 62900, 62900, 62900, 62901, \n\t62901, 62901, 62901, 62902, 62902, 62902, 62903, 62903, \n\t62903, 62903, 62904, 62904, 62904, 62904, 62905, 62905, \n\t62905, 62906, 62906, 62906, 62906, 62907, 62907, 62907, \n\t62908, 62908, 62908, 62908, 62909, 62909, 62909, 62910, \n\t62910, 62910, 62910, 62911, 62911, 62911, 62911, 62912, \n\t62912, 62912, 62913, 62913, 62913, 62913, 62914, 62914, \n\t62914, 62915, 62915, 62915, 62915, 62916, 62916, 62916, \n\t62917, 62917, 62917, 62917, 62918, 62918, 62918, 62918, \n\t62919, 62919, 62919, 62920, 62920, 62920, 62920, 62921, \n\t62921, 62921, 62922, 62922, 62922, 62922, 62923, 62923, \n\t62923, 62924, 62924, 62924, 62924, 62925, 62925, 62925, \n\t62925, 62926, 62926, 62926, 62927, 62927, 62927, 62927, \n\t62928, 62928, 62928, 62929, 62929, 62929, 62929, 62930, \n\t62930, 62930, 62931, 62931, 62931, 62931, 62932, 62932, \n\t62932, 62932, 62933, 62933, 62933, 62934, 62934, 62934, \n\t62934, 62935, 62935, 62935, 62936, 62936, 62936, 62936, \n\t62937, 62937, 62937, 62937, 62938, 62938, 62938, 62939, \n\t62939, 62939, 62939, 62940, 62940, 62940, 62941, 62941, \n\t62941, 62941, 62942, 62942, 62942, 62942, 62943, 62943, \n\t62943, 62944, 62944, 62944, 62944, 62945, 62945, 62945, \n\t62946, 62946, 62946, 62946, 62947, 62947, 62947, 62948, \n\t62948, 62948, 62948, 62949, 62949, 62949, 62949, 62950, \n\t62950, 62950, 62951, 62951, 62951, 62951, 62952, 62952, \n\t62952, 62953, 62953, 62953, 62953, 62954, 62954, 62954, \n\t62954, 62955, 62955, 62955, 62956, 62956, 62956, 62956, \n\t62957, 62957, 62957, 62958, 62958, 62958, 62958, 62959, \n\t62959, 62959, 62959, 62960, 62960, 62960, 62961, 62961, \n\t62961, 62961, 62962, 62962, 62962, 62963, 62963, 62963, \n\t62963, 62964, 62964, 62964, 62964, 62965, 62965, 62965, \n\t62966, 62966, 62966, 62966, 62967, 62967, 62967, 62968, \n\t62968, 62968, 62968, 62969, 62969, 62969, 62969, 62970, \n\t62970, 62970, 62971, 62971, 62971, 62971, 62972, 62972, \n\t62972, 62972, 62973, 62973, 62973, 62974, 62974, 62974, \n\t62974, 62975, 62975, 62975, 62976, 62976, 62976, 62976, \n\t62977, 62977, 62977, 62977, 62978, 62978, 62978, 62979, \n\t62979, 62979, 62979, 62980, 62980, 62980, 62981, 62981, \n\t62981, 62981, 62982, 62982, 62982, 62982, 62983, 62983, \n\t62983, 62984, 62984, 62984, 62984, 62985, 62985, 62985, \n\t62985, 62986, 62986, 62986, 62987, 62987, 62987, 62987, \n\t62988, 62988, 62988, 62989, 62989, 62989, 62989, 62990, \n\t62990, 62990, 62990, 62991, 62991, 62991, 62992, 62992, \n\t62992, 62992, 62993, 62993, 62993, 62993, 62994, 62994, \n\t62994, 62995, 62995, 62995, 62995, 62996, 62996, 62996, \n\t62997, 62997, 62997, 62997, 62998, 62998, 62998, 62998, \n\t62999, 62999, 62999, 63000, 63000, 63000, 63000, 63001, \n\t63001, 63001, 63001, 63002, 63002, 63002, 63003, 63003, \n\t63003, 63003, 63004, 63004, 63004, 63005, 63005, 63005, \n\t63005, 63006, 63006, 63006, 63006, 63007, 63007, 63007, \n\t63008, 63008, 63008, 63008, 63009, 63009, 63009, 63009, \n\t63010, 63010, 63010, 63011, 63011, 63011, 63011, 63012, \n\t63012, 63012, 63012, 63013, 63013, 63013, 63014, 63014, \n\t63014, 63014, 63015, 63015, 63015, 63016, 63016, 63016, \n\t63016, 63017, 63017, 63017, 63017, 63018, 63018, 63018, \n\t63019, 63019, 63019, 63019, 63020, 63020, 63020, 63020, \n\t63021, 63021, 63021, 63022, 63022, 63022, 63022, 63023, \n\t63023, 63023, 63023, 63024, 63024, 63024, 63025, 63025, \n\t63025, 63025, 63026, 63026, 63026, 63026, 63027, 63027, \n\t63027, 63028, 63028, 63028, 63028, 63029, 63029, 63029, \n\t63030, 63030, 63030, 63030, 63031, 63031, 63031, 63031, \n\t63032, 63032, 63032, 63033, 63033, 63033, 63033, 63034, \n\t63034, 63034, 63034, 63035, 63035, 63035, 63036, 63036, \n\t63036, 63036, 63037, 63037, 63037, 63037, 63038, 63038, \n\t63038, 63039, 63039, 63039, 63039, 63040, 63040, 63040, \n\t63040, 63041, 63041, 63041, 63042, 63042, 63042, 63042, \n\t63043, 63043, 63043, 63043, 63044, 63044, 63044, 63045, \n\t63045, 63045, 63045, 63046, 63046, 63046, 63046, 63047, \n\t63047, 63047, 63048, 63048, 63048, 63048, 63049, 63049, \n\t63049, 63049, 63050, 63050, 63050, 63051, 63051, 63051, \n\t63051, 63052, 63052, 63052, 63052, 63053, 63053, 63053, \n\t63054, 63054, 63054, 63054, 63055, 63055, 63055, 63055, \n\t63056, 63056, 63056, 63057, 63057, 63057, 63057, 63058, \n\t63058, 63058, 63058, 63059, 63059, 63059, 63060, 63060, \n\t63060, 63060, 63061, 63061, 63061, 63061, 63062, 63062, \n\t63062, 63063, 63063, 63063, 63063, 63064, 63064, 63064, \n\t63064, 63065, 63065, 63065, 63066, 63066, 63066, 63066, \n\t63067, 63067, 63067, 63067, 63068, 63068, 63068, 63069, \n\t63069, 63069, 63069, 63070, 63070, 63070, 63070, 63071, \n\t63071, 63071, 63072, 63072, 63072, 63072, 63073, 63073, \n\t63073, 63073, 63074, 63074, 63074, 63075, 63075, 63075, \n\t63075, 63076, 63076, 63076, 63076, 63077, 63077, 63077, \n\t63077, 63078, 63078, 63078, 63079, 63079, 63079, 63079, \n\t63080, 63080, 63080, 63080, 63081, 63081, 63081, 63082, \n\t63082, 63082, 63082, 63083, 63083, 63083, 63083, 63084, \n\t63084, 63084, 63085, 63085, 63085, 63085, 63086, 63086, \n\t63086, 63086, 63087, 63087, 63087, 63088, 63088, 63088, \n\t63088, 63089, 63089, 63089, 63089, 63090, 63090, 63090, \n\t63090, 63091, 63091, 63091, 63092, 63092, 63092, 63092, \n\t63093, 63093, 63093, 63093, 63094, 63094, 63094, 63095, \n\t63095, 63095, 63095, 63096, 63096, 63096, 63096, 63097, \n\t63097, 63097, 63098, 63098, 63098, 63098, 63099, 63099, \n\t63099, 63099, 63100, 63100, 63100, 63100, 63101, 63101, \n\t63101, 63102, 63102, 63102, 63102, 63103, 63103, 63103, \n\t63103, 63104, 63104, 63104, 63105, 63105, 63105, 63105, \n\t63106, 63106, 63106, 63106, 63107, 63107, 63107, 63108, \n\t63108, 63108, 63108, 63109, 63109, 63109, 63109, 63110, \n\t63110, 63110, 63110, 63111, 63111, 63111, 63112, 63112, \n\t63112, 63112, 63113, 63113, 63113, 63113, 63114, 63114, \n\t63114, 63115, 63115, 63115, 63115, 63116, 63116, 63116, \n\t63116, 63117, 63117, 63117, 63117, 63118, 63118, 63118, \n\t63119, 63119, 63119, 63119, 63120, 63120, 63120, 63120, \n\t63121, 63121, 63121, 63122, 63122, 63122, 63122, 63123, \n\t63123, 63123, 63123, 63124, 63124, 63124, 63124, 63125, \n\t63125, 63125, 63126, 63126, 63126, 63126, 63127, 63127, \n\t63127, 63127, 63128, 63128, 63128, 63129, 63129, 63129, \n\t63129, 63130, 63130, 63130, 63130, 63131, 63131, 63131, \n\t63131, 63132, 63132, 63132, 63133, 63133, 63133, 63133, \n\t63134, 63134, 63134, 63134, 63135, 63135, 63135, 63135, \n\t63136, 63136, 63136, 63137, 63137, 63137, 63137, 63138, \n\t63138, 63138, 63138, 63139, 63139, 63139, 63140, 63140, \n\t63140, 63140, 63141, 63141, 63141, 63141, 63142, 63142, \n\t63142, 63142, 63143, 63143, 63143, 63144, 63144, 63144, \n\t63144, 63145, 63145, 63145, 63145, 63146, 63146, 63146, \n\t63146, 63147, 63147, 63147, 63148, 63148, 63148, 63148, \n\t63149, 63149, 63149, 63149, 63150, 63150, 63150, 63150, \n\t63151, 63151, 63151, 63152, 63152, 63152, 63152, 63153, \n\t63153, 63153, 63153, 63154, 63154, 63154, 63154, 63155, \n\t63155, 63155, 63156, 63156, 63156, 63156, 63157, 63157, \n\t63157, 63157, 63158, 63158, 63158, 63158, 63159, 63159, \n\t63159, 63160, 63160, 63160, 63160, 63161, 63161, 63161, \n\t63161, 63162, 63162, 63162, 63162, 63163, 63163, 63163, \n\t63164, 63164, 63164, 63164, 63165, 63165, 63165, 63165, \n\t63166, 63166, 63166, 63166, 63167, 63167, 63167, 63168, \n\t63168, 63168, 63168, 63169, 63169, 63169, 63169, 63170, \n\t63170, 63170, 63170, 63171, 63171, 63171, 63172, 63172, \n\t63172, 63172, 63173, 63173, 63173, 63173, 63174, 63174, \n\t63174, 63174, 63175, 63175, 63175, 63176, 63176, 63176, \n\t63176, 63177, 63177, 63177, 63177, 63178, 63178, 63178, \n\t63178, 63179, 63179, 63179, 63180, 63180, 63180, 63180, \n\t63181, 63181, 63181, 63181, 63182, 63182, 63182, 63182, \n\t63183, 63183, 63183, 63184, 63184, 63184, 63184, 63185, \n\t63185, 63185, 63185, 63186, 63186, 63186, 63186, 63187, \n\t63187, 63187, 63187, 63188, 63188, 63188, 63189, 63189, \n\t63189, 63189, 63190, 63190, 63190, 63190, 63191, 63191, \n\t63191, 63191, 63192, 63192, 63192, 63193, 63193, 63193, \n\t63193, 63194, 63194, 63194, 63194, 63195, 63195, 63195, \n\t63195, 63196, 63196, 63196, 63197, 63197, 63197, 63197, \n\t63198, 63198, 63198, 63198, 63199, 63199, 63199, 63199, \n\t63200, 63200, 63200, 63200, 63201, 63201, 63201, 63202, \n\t63202, 63202, 63202, 63203, 63203, 63203, 63203, 63204, \n\t63204, 63204, 63204, 63205, 63205, 63205, 63206, 63206, \n\t63206, 63206, 63207, 63207, 63207, 63207, 63208, 63208, \n\t63208, 63208, 63209, 63209, 63209, 63209, 63210, 63210, \n\t63210, 63211, 63211, 63211, 63211, 63212, 63212, 63212, \n\t63212, 63213, 63213, 63213, 63213, 63214, 63214, 63214, \n\t63214, 63215, 63215, 63215, 63216, 63216, 63216, 63216, \n\t63217, 63217, 63217, 63217, 63218, 63218, 63218, 63218, \n\t63219, 63219, 63219, 63219, 63220, 63220, 63220, 63221, \n\t63221, 63221, 63221, 63222, 63222, 63222, 63222, 63223, \n\t63223, 63223, 63223, 63224, 63224, 63224, 63224, 63225, \n\t63225, 63225, 63226, 63226, 63226, 63226, 63227, 63227, \n\t63227, 63227, 63228, 63228, 63228, 63228, 63229, 63229, \n\t63229, 63229, 63230, 63230, 63230, 63231, 63231, 63231, \n\t63231, 63232, 63232, 63232, 63232, 63233, 63233, 63233, \n\t63233, 63234, 63234, 63234, 63234, 63235, 63235, 63235, \n\t63236, 63236, 63236, 63236, 63237, 63237, 63237, 63237, \n\t63238, 63238, 63238, 63238, 63239, 63239, 63239, 63239, \n\t63240, 63240, 63240, 63241, 63241, 63241, 63241, 63242, \n\t63242, 63242, 63242, 63243, 63243, 63243, 63243, 63244, \n\t63244, 63244, 63244, 63245, 63245, 63245, 63246, 63246, \n\t63246, 63246, 63247, 63247, 63247, 63247, 63248, 63248, \n\t63248, 63248, 63249, 63249, 63249, 63249, 63250, 63250, \n\t63250, 63250, 63251, 63251, 63251, 63252, 63252, 63252, \n\t63252, 63253, 63253, 63253, 63253, 63254, 63254, 63254, \n\t63254, 63255, 63255, 63255, 63255, 63256, 63256, 63256, \n\t63257, 63257, 63257, 63257, 63258, 63258, 63258, 63258, \n\t63259, 63259, 63259, 63259, 63260, 63260, 63260, 63260, \n\t63261, 63261, 63261, 63261, 63262, 63262, 63262, 63263, \n\t63263, 63263, 63263, 63264, 63264, 63264, 63264, 63265, \n\t63265, 63265, 63265, 63266, 63266, 63266, 63266, 63267, \n\t63267, 63267, 63267, 63268, 63268, 63268, 63269, 63269, \n\t63269, 63269, 63270, 63270, 63270, 63270, 63271, 63271, \n\t63271, 63271, 63272, 63272, 63272, 63272, 63273, 63273, \n\t63273, 63273, 63274, 63274, 63274, 63275, 63275, 63275, \n\t63275, 63276, 63276, 63276, 63276, 63277, 63277, 63277, \n\t63277, 63278, 63278, 63278, 63278, 63279, 63279, 63279, \n\t63279, 63280, 63280, 63280, 63280, 63281, 63281, 63281, \n\t63282, 63282, 63282, 63282, 63283, 63283, 63283, 63283, \n\t63284, 63284, 63284, 63284, 63285, 63285, 63285, 63285, \n\t63286, 63286, 63286, 63286, 63287, 63287, 63287, 63288, \n\t63288, 63288, 63288, 63289, 63289, 63289, 63289, 63290, \n\t63290, 63290, 63290, 63291, 63291, 63291, 63291, 63292, \n\t63292, 63292, 63292, 63293, 63293, 63293, 63293, 63294, \n\t63294, 63294, 63295, 63295, 63295, 63295, 63296, 63296, \n\t63296, 63296, 63297, 63297, 63297, 63297, 63298, 63298, \n\t63298, 63298, 63299, 63299, 63299, 63299, 63300, 63300, \n\t63300, 63300, 63301, 63301, 63301, 63302, 63302, 63302, \n\t63302, 63303, 63303, 63303, 63303, 63304, 63304, 63304, \n\t63304, 63305, 63305, 63305, 63305, 63306, 63306, 63306, \n\t63306, 63307, 63307, 63307, 63307, 63308, 63308, 63308, \n\t63308, 63309, 63309, 63309, 63310, 63310, 63310, 63310, \n\t63311, 63311, 63311, 63311, 63312, 63312, 63312, 63312, \n\t63313, 63313, 63313, 63313, 63314, 63314, 63314, 63314, \n\t63315, 63315, 63315, 63315, 63316, 63316, 63316, 63317, \n\t63317, 63317, 63317, 63318, 63318, 63318, 63318, 63319, \n\t63319, 63319, 63319, 63320, 63320, 63320, 63320, 63321, \n\t63321, 63321, 63321, 63322, 63322, 63322, 63322, 63323, \n\t63323, 63323, 63323, 63324, 63324, 63324, 63324, 63325, \n\t63325, 63325, 63326, 63326, 63326, 63326, 63327, 63327, \n\t63327, 63327, 63328, 63328, 63328, 63328, 63329, 63329, \n\t63329, 63329, 63330, 63330, 63330, 63330, 63331, 63331, \n\t63331, 63331, 63332, 63332, 63332, 63332, 63333, 63333, \n\t63333, 63334, 63334, 63334, 63334, 63335, 63335, 63335, \n\t63335, 63336, 63336, 63336, 63336, 63337, 63337, 63337, \n\t63337, 63338, 63338, 63338, 63338, 63339, 63339, 63339, \n\t63339, 63340, 63340, 63340, 63340, 63341, 63341, 63341, \n\t63341, 63342, 63342, 63342, 63342, 63343, 63343, 63343, \n\t63344, 63344, 63344, 63344, 63345, 63345, 63345, 63345, \n\t63346, 63346, 63346, 63346, 63347, 63347, 63347, 63347, \n\t63348, 63348, 63348, 63348, 63349, 63349, 63349, 63349, \n\t63350, 63350, 63350, 63350, 63351, 63351, 63351, 63351, \n\t63352, 63352, 63352, 63352, 63353, 63353, 63353, 63354, \n\t63354, 63354, 63354, 63355, 63355, 63355, 63355, 63356, \n\t63356, 63356, 63356, 63357, 63357, 63357, 63357, 63358, \n\t63358, 63358, 63358, 63359, 63359, 63359, 63359, 63360, \n\t63360, 63360, 63360, 63361, 63361, 63361, 63361, 63362, \n\t63362, 63362, 63362, 63363, 63363, 63363, 63363, 63364, \n\t63364, 63364, 63364, 63365, 63365, 63365, 63366, 63366, \n\t63366, 63366, 63367, 63367, 63367, 63367, 63368, 63368, \n\t63368, 63368, 63369, 63369, 63369, 63369, 63370, 63370, \n\t63370, 63370, 63371, 63371, 63371, 63371, 63372, 63372, \n\t63372, 63372, 63373, 63373, 63373, 63373, 63374, 63374, \n\t63374, 63374, 63375, 63375, 63375, 63375, 63376, 63376, \n\t63376, 63376, 63377, 63377, 63377, 63377, 63378, 63378, \n\t63378, 63379, 63379, 63379, 63379, 63380, 63380, 63380, \n\t63380, 63381, 63381, 63381, 63381, 63382, 63382, 63382, \n\t63382, 63383, 63383, 63383, 63383, 63384, 63384, 63384, \n\t63384, 63385, 63385, 63385, 63385, 63386, 63386, 63386, \n\t63386, 63387, 63387, 63387, 63387, 63388, 63388, 63388, \n\t63388, 63389, 63389, 63389, 63389, 63390, 63390, 63390, \n\t63390, 63391, 63391, 63391, 63391, 63392, 63392, 63392, \n\t63392, 63393, 63393, 63393, 63394, 63394, 63394, 63394, \n\t63395, 63395, 63395, 63395, 63396, 63396, 63396, 63396, \n\t63397, 63397, 63397, 63397, 63398, 63398, 63398, 63398, \n\t63399, 63399, 63399, 63399, 63400, 63400, 63400, 63400, \n\t63401, 63401, 63401, 63401, 63402, 63402, 63402, 63402, \n\t63403, 63403, 63403, 63403, 63404, 63404, 63404, 63404, \n\t63405, 63405, 63405, 63405, 63406, 63406, 63406, 63406, \n\t63407, 63407, 63407, 63407, 63408, 63408, 63408, 63408, \n\t63409, 63409, 63409, 63409, 63410, 63410, 63410, 63410, \n\t63411, 63411, 63411, 63411, 63412, 63412, 63412, 63412, \n\t63413, 63413, 63413, 63413, 63414, 63414, 63414, 63415, \n\t63415, 63415, 63415, 63416, 63416, 63416, 63416, 63417, \n\t63417, 63417, 63417, 63418, 63418, 63418, 63418, 63419, \n\t63419, 63419, 63419, 63420, 63420, 63420, 63420, 63421, \n\t63421, 63421, 63421, 63422, 63422, 63422, 63422, 63423, \n\t63423, 63423, 63423, 63424, 63424, 63424, 63424, 63425, \n\t63425, 63425, 63425, 63426, 63426, 63426, 63426, 63427, \n\t63427, 63427, 63427, 63428, 63428, 63428, 63428, 63429, \n\t63429, 63429, 63429, 63430, 63430, 63430, 63430, 63431, \n\t63431, 63431, 63431, 63432, 63432, 63432, 63432, 63433, \n\t63433, 63433, 63433, 63434, 63434, 63434, 63434, 63435, \n\t63435, 63435, 63435, 63436, 63436, 63436, 63436, 63437, \n\t63437, 63437, 63437, 63438, 63438, 63438, 63438, 63439, \n\t63439, 63439, 63439, 63440, 63440, 63440, 63440, 63441, \n\t63441, 63441, 63441, 63442, 63442, 63442, 63442, 63443, \n\t63443, 63443, 63443, 63444, 63444, 63444, 63444, 63445, \n\t63445, 63445, 63445, 63446, 63446, 63446, 63446, 63447, \n\t63447, 63447, 63447, 63448, 63448, 63448, 63448, 63449, \n\t63449, 63449, 63449, 63450, 63450, 63450, 63450, 63451, \n\t63451, 63451, 63451, 63452, 63452, 63452, 63452, 63453, \n\t63453, 63453, 63453, 63454, 63454, 63454, 63454, 63455, \n\t63455, 63455, 63455, 63456, 63456, 63456, 63456, 63457, \n\t63457, 63457, 63457, 63458, 63458, 63458, 63458, 63459, \n\t63459, 63459, 63459, 63460, 63460, 63460, 63460, 63461, \n\t63461, 63461, 63461, 63462, 63462, 63462, 63462, 63463, \n\t63463, 63463, 63463, 63464, 63464, 63464, 63464, 63465, \n\t63465, 63465, 63465, 63466, 63466, 63466, 63466, 63467, \n\t63467, 63467, 63467, 63468, 63468, 63468, 63468, 63469, \n\t63469, 63469, 63469, 63470, 63470, 63470, 63470, 63471, \n\t63471, 63471, 63471, 63472, 63472, 63472, 63472, 63473, \n\t63473, 63473, 63473, 63474, 63474, 63474, 63474, 63475, \n\t63475, 63475, 63475, 63476, 63476, 63476, 63476, 63477, \n\t63477, 63477, 63477, 63478, 63478, 63478, 63478, 63479, \n\t63479, 63479, 63479, 63480, 63480, 63480, 63480, 63481, \n\t63481, 63481, 63481, 63482, 63482, 63482, 63482, 63483, \n\t63483, 63483, 63483, 63484, 63484, 63484, 63484, 63485, \n\t63485, 63485, 63485, 63486, 63486, 63486, 63486, 63487, \n\t63487, 63487, 63487, 63488, 63488, 63488, 63488, 63489, \n\t63489, 63489, 63489, 63490, 63490, 63490, 63490, 63491, \n\t63491, 63491, 63491, 63492, 63492, 63492, 63492, 63493, \n\t63493, 63493, 63493, 63494, 63494, 63494, 63494, 63495, \n\t63495, 63495, 63495, 63495, 63496, 63496, 63496, 63496, \n\t63497, 63497, 63497, 63497, 63498, 63498, 63498, 63498, \n\t63499, 63499, 63499, 63499, 63500, 63500, 63500, 63500, \n\t63501, 63501, 63501, 63501, 63502, 63502, 63502, 63502, \n\t63503, 63503, 63503, 63503, 63504, 63504, 63504, 63504, \n\t63505, 63505, 63505, 63505, 63506, 63506, 63506, 63506, \n\t63507, 63507, 63507, 63507, 63508, 63508, 63508, 63508, \n\t63509, 63509, 63509, 63509, 63510, 63510, 63510, 63510, \n\t63511, 63511, 63511, 63511, 63512, 63512, 63512, 63512, \n\t63513, 63513, 63513, 63513, 63514, 63514, 63514, 63514, \n\t63515, 63515, 63515, 63515, 63516, 63516, 63516, 63516, \n\t63516, 63517, 63517, 63517, 63517, 63518, 63518, 63518, \n\t63518, 63519, 63519, 63519, 63519, 63520, 63520, 63520, \n\t63520, 63521, 63521, 63521, 63521, 63522, 63522, 63522, \n\t63522, 63523, 63523, 63523, 63523, 63524, 63524, 63524, \n\t63524, 63525, 63525, 63525, 63525, 63526, 63526, 63526, \n\t63526, 63527, 63527, 63527, 63527, 63528, 63528, 63528, \n\t63528, 63529, 63529, 63529, 63529, 63530, 63530, 63530, \n\t63530, 63531, 63531, 63531, 63531, 63531, 63532, 63532, \n\t63532, 63532, 63533, 63533, 63533, 63533, 63534, 63534, \n\t63534, 63534, 63535, 63535, 63535, 63535, 63536, 63536, \n\t63536, 63536, 63537, 63537, 63537, 63537, 63538, 63538, \n\t63538, 63538, 63539, 63539, 63539, 63539, 63540, 63540, \n\t63540, 63540, 63541, 63541, 63541, 63541, 63542, 63542, \n\t63542, 63542, 63543, 63543, 63543, 63543, 63543, 63544, \n\t63544, 63544, 63544, 63545, 63545, 63545, 63545, 63546, \n\t63546, 63546, 63546, 63547, 63547, 63547, 63547, 63548, \n\t63548, 63548, 63548, 63549, 63549, 63549, 63549, 63550, \n\t63550, 63550, 63550, 63551, 63551, 63551, 63551, 63552, \n\t63552, 63552, 63552, 63553, 63553, 63553, 63553, 63554, \n\t63554, 63554, 63554, 63554, 63555, 63555, 63555, 63555, \n\t63556, 63556, 63556, 63556, 63557, 63557, 63557, 63557, \n\t63558, 63558, 63558, 63558, 63559, 63559, 63559, 63559, \n\t63560, 63560, 63560, 63560, 63561, 63561, 63561, 63561, \n\t63562, 63562, 63562, 63562, 63563, 63563, 63563, 63563, \n\t63564, 63564, 63564, 63564, 63564, 63565, 63565, 63565, \n\t63565, 63566, 63566, 63566, 63566, 63567, 63567, 63567, \n\t63567, 63568, 63568, 63568, 63568, 63569, 63569, 63569, \n\t63569, 63570, 63570, 63570, 63570, 63571, 63571, 63571, \n\t63571, 63572, 63572, 63572, 63572, 63573, 63573, 63573, \n\t63573, 63573, 63574, 63574, 63574, 63574, 63575, 63575, \n\t63575, 63575, 63576, 63576, 63576, 63576, 63577, 63577, \n\t63577, 63577, 63578, 63578, 63578, 63578, 63579, 63579, \n\t63579, 63579, 63580, 63580, 63580, 63580, 63581, 63581, \n\t63581, 63581, 63581, 63582, 63582, 63582, 63582, 63583, \n\t63583, 63583, 63583, 63584, 63584, 63584, 63584, 63585, \n\t63585, 63585, 63585, 63586, 63586, 63586, 63586, 63587, \n\t63587, 63587, 63587, 63588, 63588, 63588, 63588, 63589, \n\t63589, 63589, 63589, 63589, 63590, 63590, 63590, 63590, \n\t63591, 63591, 63591, 63591, 63592, 63592, 63592, 63592, \n\t63593, 63593, 63593, 63593, 63594, 63594, 63594, 63594, \n\t63595, 63595, 63595, 63595, 63596, 63596, 63596, 63596, \n\t63596, 63597, 63597, 63597, 63597, 63598, 63598, 63598, \n\t63598, 63599, 63599, 63599, 63599, 63600, 63600, 63600, \n\t63600, 63601, 63601, 63601, 63601, 63602, 63602, 63602, \n\t63602, 63603, 63603, 63603, 63603, 63603, 63604, 63604, \n\t63604, 63604, 63605, 63605, 63605, 63605, 63606, 63606, \n\t63606, 63606, 63607, 63607, 63607, 63607, 63608, 63608, \n\t63608, 63608, 63609, 63609, 63609, 63609, 63610, 63610, \n\t63610, 63610, 63610, 63611, 63611, 63611, 63611, 63612, \n\t63612, 63612, 63612, 63613, 63613, 63613, 63613, 63614, \n\t63614, 63614, 63614, 63615, 63615, 63615, 63615, 63616, \n\t63616, 63616, 63616, 63616, 63617, 63617, 63617, 63617, \n\t63618, 63618, 63618, 63618, 63619, 63619, 63619, 63619, \n\t63620, 63620, 63620, 63620, 63621, 63621, 63621, 63621, \n\t63622, 63622, 63622, 63622, 63622, 63623, 63623, 63623, \n\t63623, 63624, 63624, 63624, 63624, 63625, 63625, 63625, \n\t63625, 63626, 63626, 63626, 63626, 63627, 63627, 63627, \n\t63627, 63628, 63628, 63628, 63628, 63628, 63629, 63629, \n\t63629, 63629, 63630, 63630, 63630, 63630, 63631, 63631, \n\t63631, 63631, 63632, 63632, 63632, 63632, 63633, 63633, \n\t63633, 63633, 63634, 63634, 63634, 63634, 63634, 63635, \n\t63635, 63635, 63635, 63636, 63636, 63636, 63636, 63637, \n\t63637, 63637, 63637, 63638, 63638, 63638, 63638, 63639, \n\t63639, 63639, 63639, 63639, 63640, 63640, 63640, 63640, \n\t63641, 63641, 63641, 63641, 63642, 63642, 63642, 63642, \n\t63643, 63643, 63643, 63643, 63644, 63644, 63644, 63644, \n\t63644, 63645, 63645, 63645, 63645, 63646, 63646, 63646, \n\t63646, 63647, 63647, 63647, 63647, 63648, 63648, 63648, \n\t63648, 63649, 63649, 63649, 63649, 63649, 63650, 63650, \n\t63650, 63650, 63651, 63651, 63651, 63651, 63652, 63652, \n\t63652, 63652, 63653, 63653, 63653, 63653, 63654, 63654, \n\t63654, 63654, 63654, 63655, 63655, 63655, 63655, 63656, \n\t63656, 63656, 63656, 63657, 63657, 63657, 63657, 63658, \n\t63658, 63658, 63658, 63659, 63659, 63659, 63659, 63659, \n\t63660, 63660, 63660, 63660, 63661, 63661, 63661, 63661, \n\t63662, 63662, 63662, 63662, 63663, 63663, 63663, 63663, \n\t63664, 63664, 63664, 63664, 63664, 63665, 63665, 63665, \n\t63665, 63666, 63666, 63666, 63666, 63667, 63667, 63667, \n\t63667, 63668, 63668, 63668, 63668, 63669, 63669, 63669, \n\t63669, 63669, 63670, 63670, 63670, 63670, 63671, 63671, \n\t63671, 63671, 63672, 63672, 63672, 63672, 63673, 63673, \n\t63673, 63673, 63673, 63674, 63674, 63674, 63674, 63675, \n\t63675, 63675, 63675, 63676, 63676, 63676, 63676, 63677, \n\t63677, 63677, 63677, 63678, 63678, 63678, 63678, 63678, \n\t63679, 63679, 63679, 63679, 63680, 63680, 63680, 63680, \n\t63681, 63681, 63681, 63681, 63682, 63682, 63682, 63682, \n\t63682, 63683, 63683, 63683, 63683, 63684, 63684, 63684, \n\t63684, 63685, 63685, 63685, 63685, 63686, 63686, 63686, \n\t63686, 63686, 63687, 63687, 63687, 63687, 63688, 63688, \n\t63688, 63688, 63689, 63689, 63689, 63689, 63690, 63690, \n\t63690, 63690, 63690, 63691, 63691, 63691, 63691, 63692, \n\t63692, 63692, 63692, 63693, 63693, 63693, 63693, 63694, \n\t63694, 63694, 63694, 63694, 63695, 63695, 63695, 63695, \n\t63696, 63696, 63696, 63696, 63697, 63697, 63697, 63697, \n\t63698, 63698, 63698, 63698, 63698, 63699, 63699, 63699, \n\t63699, 63700, 63700, 63700, 63700, 63701, 63701, 63701, \n\t63701, 63702, 63702, 63702, 63702, 63702, 63703, 63703, \n\t63703, 63703, 63704, 63704, 63704, 63704, 63705, 63705, \n\t63705, 63705, 63706, 63706, 63706, 63706, 63706, 63707, \n\t63707, 63707, 63707, 63708, 63708, 63708, 63708, 63709, \n\t63709, 63709, 63709, 63710, 63710, 63710, 63710, 63710, \n\t63711, 63711, 63711, 63711, 63712, 63712, 63712, 63712, \n\t63713, 63713, 63713, 63713, 63714, 63714, 63714, 63714, \n\t63714, 63715, 63715, 63715, 63715, 63716, 63716, 63716, \n\t63716, 63717, 63717, 63717, 63717, 63717, 63718, 63718, \n\t63718, 63718, 63719, 63719, 63719, 63719, 63720, 63720, \n\t63720, 63720, 63721, 63721, 63721, 63721, 63721, 63722, \n\t63722, 63722, 63722, 63723, 63723, 63723, 63723, 63724, \n\t63724, 63724, 63724, 63724, 63725, 63725, 63725, 63725, \n\t63726, 63726, 63726, 63726, 63727, 63727, 63727, 63727, \n\t63728, 63728, 63728, 63728, 63728, 63729, 63729, 63729, \n\t63729, 63730, 63730, 63730, 63730, 63731, 63731, 63731, \n\t63731, 63731, 63732, 63732, 63732, 63732, 63733, 63733, \n\t63733, 63733, 63734, 63734, 63734, 63734, 63735, 63735, \n\t63735, 63735, 63735, 63736, 63736, 63736, 63736, 63737, \n\t63737, 63737, 63737, 63738, 63738, 63738, 63738, 63738, \n\t63739, 63739, 63739, 63739, 63740, 63740, 63740, 63740, \n\t63741, 63741, 63741, 63741, 63742, 63742, 63742, 63742, \n\t63742, 63743, 63743, 63743, 63743, 63744, 63744, 63744, \n\t63744, 63745, 63745, 63745, 63745, 63745, 63746, 63746, \n\t63746, 63746, 63747, 63747, 63747, 63747, 63748, 63748, \n\t63748, 63748, 63748, 63749, 63749, 63749, 63749, 63750, \n\t63750, 63750, 63750, 63751, 63751, 63751, 63751, 63751, \n\t63752, 63752, 63752, 63752, 63753, 63753, 63753, 63753, \n\t63754, 63754, 63754, 63754, 63754, 63755, 63755, 63755, \n\t63755, 63756, 63756, 63756, 63756, 63757, 63757, 63757, \n\t63757, 63758, 63758, 63758, 63758, 63758, 63759, 63759, \n\t63759, 63759, 63760, 63760, 63760, 63760, 63761, 63761, \n\t63761, 63761, 63761, 63762, 63762, 63762, 63762, 63763, \n\t63763, 63763, 63763, 63764, 63764, 63764, 63764, 63764, \n\t63765, 63765, 63765, 63765, 63766, 63766, 63766, 63766, \n\t63767, 63767, 63767, 63767, 63767, 63768, 63768, 63768, \n\t63768, 63769, 63769, 63769, 63769, 63770, 63770, 63770, \n\t63770, 63770, 63771, 63771, 63771, 63771, 63772, 63772, \n\t63772, 63772, 63773, 63773, 63773, 63773, 63773, 63774, \n\t63774, 63774, 63774, 63775, 63775, 63775, 63775, 63776, \n\t63776, 63776, 63776, 63776, 63777, 63777, 63777, 63777, \n\t63778, 63778, 63778, 63778, 63779, 63779, 63779, 63779, \n\t63779, 63780, 63780, 63780, 63780, 63781, 63781, 63781, \n\t63781, 63781, 63782, 63782, 63782, 63782, 63783, 63783, \n\t63783, 63783, 63784, 63784, 63784, 63784, 63784, 63785, \n\t63785, 63785, 63785, 63786, 63786, 63786, 63786, 63787, \n\t63787, 63787, 63787, 63787, 63788, 63788, 63788, 63788, \n\t63789, 63789, 63789, 63789, 63790, 63790, 63790, 63790, \n\t63790, 63791, 63791, 63791, 63791, 63792, 63792, 63792, \n\t63792, 63793, 63793, 63793, 63793, 63793, 63794, 63794, \n\t63794, 63794, 63795, 63795, 63795, 63795, 63795, 63796, \n\t63796, 63796, 63796, 63797, 63797, 63797, 63797, 63798, \n\t63798, 63798, 63798, 63798, 63799, 63799, 63799, 63799, \n\t63800, 63800, 63800, 63800, 63801, 63801, 63801, 63801, \n\t63801, 63802, 63802, 63802, 63802, 63803, 63803, 63803, \n\t63803, 63803, 63804, 63804, 63804, 63804, 63805, 63805, \n\t63805, 63805, 63806, 63806, 63806, 63806, 63806, 63807, \n\t63807, 63807, 63807, 63808, 63808, 63808, 63808, 63809, \n\t63809, 63809, 63809, 63809, 63810, 63810, 63810, 63810, \n\t63811, 63811, 63811, 63811, 63811, 63812, 63812, 63812, \n\t63812, 63813, 63813, 63813, 63813, 63814, 63814, 63814, \n\t63814, 63814, 63815, 63815, 63815, 63815, 63816, 63816, \n\t63816, 63816, 63816, 63817, 63817, 63817, 63817, 63818, \n\t63818, 63818, 63818, 63819, 63819, 63819, 63819, 63819, \n\t63820, 63820, 63820, 63820, 63821, 63821, 63821, 63821, \n\t63821, 63822, 63822, 63822, 63822, 63823, 63823, 63823, \n\t63823, 63824, 63824, 63824, 63824, 63824, 63825, 63825, \n\t63825, 63825, 63826, 63826, 63826, 63826, 63826, 63827, \n\t63827, 63827, 63827, 63828, 63828, 63828, 63828, 63829, \n\t63829, 63829, 63829, 63829, 63830, 63830, 63830, 63830, \n\t63831, 63831, 63831, 63831, 63831, 63832, 63832, 63832, \n\t63832, 63833, 63833, 63833, 63833, 63834, 63834, 63834, \n\t63834, 63834, 63835, 63835, 63835, 63835, 63836, 63836, \n\t63836, 63836, 63836, 63837, 63837, 63837, 63837, 63838, \n\t63838, 63838, 63838, 63838, 63839, 63839, 63839, 63839, \n\t63840, 63840, 63840, 63840, 63841, 63841, 63841, 63841, \n\t63841, 63842, 63842, 63842, 63842, 63843, 63843, 63843, \n\t63843, 63843, 63844, 63844, 63844, 63844, 63845, 63845, \n\t63845, 63845, 63845, 63846, 63846, 63846, 63846, 63847, \n\t63847, 63847, 63847, 63848, 63848, 63848, 63848, 63848, \n\t63849, 63849, 63849, 63849, 63850, 63850, 63850, 63850, \n\t63850, 63851, 63851, 63851, 63851, 63852, 63852, 63852, \n\t63852, 63852, 63853, 63853, 63853, 63853, 63854, 63854, \n\t63854, 63854, 63855, 63855, 63855, 63855, 63855, 63856, \n\t63856, 63856, 63856, 63857, 63857, 63857, 63857, 63857, \n\t63858, 63858, 63858, 63858, 63859, 63859, 63859, 63859, \n\t63859, 63860, 63860, 63860, 63860, 63861, 63861, 63861, \n\t63861, 63861, 63862, 63862, 63862, 63862, 63863, 63863, \n\t63863, 63863, 63863, 63864, 63864, 63864, 63864, 63865, \n\t63865, 63865, 63865, 63866, 63866, 63866, 63866, 63866, \n\t63867, 63867, 63867, 63867, 63868, 63868, 63868, 63868, \n\t63868, 63869, 63869, 63869, 63869, 63870, 63870, 63870, \n\t63870, 63870, 63871, 63871, 63871, 63871, 63872, 63872, \n\t63872, 63872, 63872, 63873, 63873, 63873, 63873, 63874, \n\t63874, 63874, 63874, 63874, 63875, 63875, 63875, 63875, \n\t63876, 63876, 63876, 63876, 63876, 63877, 63877, 63877, \n\t63877, 63878, 63878, 63878, 63878, 63879, 63879, 63879, \n\t63879, 63879, 63880, 63880, 63880, 63880, 63881, 63881, \n\t63881, 63881, 63881, 63882, 63882, 63882, 63882, 63883, \n\t63883, 63883, 63883, 63883, 63884, 63884, 63884, 63884, \n\t63885, 63885, 63885, 63885, 63885, 63886, 63886, 63886, \n\t63886, 63887, 63887, 63887, 63887, 63887, 63888, 63888, \n\t63888, 63888, 63889, 63889, 63889, 63889, 63889, 63890, \n\t63890, 63890, 63890, 63891, 63891, 63891, 63891, 63891, \n\t63892, 63892, 63892, 63892, 63893, 63893, 63893, 63893, \n\t63893, 63894, 63894, 63894, 63894, 63895, 63895, 63895, \n\t63895, 63895, 63896, 63896, 63896, 63896, 63897, 63897, \n\t63897, 63897, 63897, 63898, 63898, 63898, 63898, 63899, \n\t63899, 63899, 63899, 63899, 63900, 63900, 63900, 63900, \n\t63901, 63901, 63901, 63901, 63901, 63902, 63902, 63902, \n\t63902, 63903, 63903, 63903, 63903, 63903, 63904, 63904, \n\t63904, 63904, 63905, 63905, 63905, 63905, 63905, 63906, \n\t63906, 63906, 63906, 63907, 63907, 63907, 63907, 63907, \n\t63908, 63908, 63908, 63908, 63909, 63909, 63909, 63909, \n\t63909, 63910, 63910, 63910, 63910, 63911, 63911, 63911, \n\t63911, 63911, 63912, 63912, 63912, 63912, 63913, 63913, \n\t63913, 63913, 63913, 63914, 63914, 63914, 63914, 63915, \n\t63915, 63915, 63915, 63915, 63916, 63916, 63916, 63916, \n\t63916, 63917, 63917, 63917, 63917, 63918, 63918, 63918, \n\t63918, 63918, 63919, 63919, 63919, 63919, 63920, 63920, \n\t63920, 63920, 63920, 63921, 63921, 63921, 63921, 63922, \n\t63922, 63922, 63922, 63922, 63923, 63923, 63923, 63923, \n\t63924, 63924, 63924, 63924, 63924, 63925, 63925, 63925, \n\t63925, 63926, 63926, 63926, 63926, 63926, 63927, 63927, \n\t63927, 63927, 63928, 63928, 63928, 63928, 63928, 63929, \n\t63929, 63929, 63929, 63930, 63930, 63930, 63930, 63930, \n\t63931, 63931, 63931, 63931, 63931, 63932, 63932, 63932, \n\t63932, 63933, 63933, 63933, 63933, 63933, 63934, 63934, \n\t63934, 63934, 63935, 63935, 63935, 63935, 63935, 63936, \n\t63936, 63936, 63936, 63937, 63937, 63937, 63937, 63937, \n\t63938, 63938, 63938, 63938, 63939, 63939, 63939, 63939, \n\t63939, 63940, 63940, 63940, 63940, 63940, 63941, 63941, \n\t63941, 63941, 63942, 63942, 63942, 63942, 63942, 63943, \n\t63943, 63943, 63943, 63944, 63944, 63944, 63944, 63944, \n\t63945, 63945, 63945, 63945, 63946, 63946, 63946, 63946, \n\t63946, 63947, 63947, 63947, 63947, 63948, 63948, 63948, \n\t63948, 63948, 63949, 63949, 63949, 63949, 63949, 63950, \n\t63950, 63950, 63950, 63951, 63951, 63951, 63951, 63951, \n\t63952, 63952, 63952, 63952, 63953, 63953, 63953, 63953, \n\t63953, 63954, 63954, 63954, 63954, 63954, 63955, 63955, \n\t63955, 63955, 63956, 63956, 63956, 63956, 63956, 63957, \n\t63957, 63957, 63957, 63958, 63958, 63958, 63958, 63958, \n\t63959, 63959, 63959, 63959, 63960, 63960, 63960, 63960, \n\t63960, 63961, 63961, 63961, 63961, 63961, 63962, 63962, \n\t63962, 63962, 63963, 63963, 63963, 63963, 63963, 63964, \n\t63964, 63964, 63964, 63965, 63965, 63965, 63965, 63965, \n\t63966, 63966, 63966, 63966, 63966, 63967, 63967, 63967, \n\t63967, 63968, 63968, 63968, 63968, 63968, 63969, 63969, \n\t63969, 63969, 63970, 63970, 63970, 63970, 63970, 63971, \n\t63971, 63971, 63971, 63971, 63972, 63972, 63972, 63972, \n\t63973, 63973, 63973, 63973, 63973, 63974, 63974, 63974, \n\t63974, 63975, 63975, 63975, 63975, 63975, 63976, 63976, \n\t63976, 63976, 63976, 63977, 63977, 63977, 63977, 63978, \n\t63978, 63978, 63978, 63978, 63979, 63979, 63979, 63979, \n\t63980, 63980, 63980, 63980, 63980, 63981, 63981, 63981, \n\t63981, 63981, 63982, 63982, 63982, 63982, 63983, 63983, \n\t63983, 63983, 63983, 63984, 63984, 63984, 63984, 63984, \n\t63985, 63985, 63985, 63985, 63986, 63986, 63986, 63986, \n\t63986, 63987, 63987, 63987, 63987, 63988, 63988, 63988, \n\t63988, 63988, 63989, 63989, 63989, 63989, 63989, 63990, \n\t63990, 63990, 63990, 63991, 63991, 63991, 63991, 63991, \n\t63992, 63992, 63992, 63992, 63992, 63993, 63993, 63993, \n\t63993, 63994, 63994, 63994, 63994, 63994, 63995, 63995, \n\t63995, 63995, 63996, 63996, 63996, 63996, 63996, 63997, \n\t63997, 63997, 63997, 63997, 63998, 63998, 63998, 63998, \n\t63999, 63999, 63999, 63999, 63999, 64000, 64000, 64000, \n\t64000, 64000, 64001, 64001, 64001, 64001, 64002, 64002, \n\t64002, 64002, 64002, 64003, 64003, 64003, 64003, 64003, \n\t64004, 64004, 64004, 64004, 64005, 64005, 64005, 64005, \n\t64005, 64006, 64006, 64006, 64006, 64006, 64007, 64007, \n\t64007, 64007, 64008, 64008, 64008, 64008, 64008, 64009, \n\t64009, 64009, 64009, 64009, 64010, 64010, 64010, 64010, \n\t64011, 64011, 64011, 64011, 64011, 64012, 64012, 64012, \n\t64012, 64012, 64013, 64013, 64013, 64013, 64014, 64014, \n\t64014, 64014, 64014, 64015, 64015, 64015, 64015, 64015, \n\t64016, 64016, 64016, 64016, 64017, 64017, 64017, 64017, \n\t64017, 64018, 64018, 64018, 64018, 64018, 64019, 64019, \n\t64019, 64019, 64020, 64020, 64020, 64020, 64020, 64021, \n\t64021, 64021, 64021, 64021, 64022, 64022, 64022, 64022, \n\t64023, 64023, 64023, 64023, 64023, 64024, 64024, 64024, \n\t64024, 64024, 64025, 64025, 64025, 64025, 64026, 64026, \n\t64026, 64026, 64026, 64027, 64027, 64027, 64027, 64027, \n\t64028, 64028, 64028, 64028, 64029, 64029, 64029, 64029, \n\t64029, 64030, 64030, 64030, 64030, 64030, 64031, 64031, \n\t64031, 64031, 64032, 64032, 64032, 64032, 64032, 64033, \n\t64033, 64033, 64033, 64033, 64034, 64034, 64034, 64034, \n\t64034, 64035, 64035, 64035, 64035, 64036, 64036, 64036, \n\t64036, 64036, 64037, 64037, 64037, 64037, 64037, 64038, \n\t64038, 64038, 64038, 64039, 64039, 64039, 64039, 64039, \n\t64040, 64040, 64040, 64040, 64040, 64041, 64041, 64041, \n\t64041, 64041, 64042, 64042, 64042, 64042, 64043, 64043, \n\t64043, 64043, 64043, 64044, 64044, 64044, 64044, 64044, \n\t64045, 64045, 64045, 64045, 64046, 64046, 64046, 64046, \n\t64046, 64047, 64047, 64047, 64047, 64047, 64048, 64048, \n\t64048, 64048, 64048, 64049, 64049, 64049, 64049, 64050, \n\t64050, 64050, 64050, 64050, 64051, 64051, 64051, 64051, \n\t64051, 64052, 64052, 64052, 64052, 64053, 64053, 64053, \n\t64053, 64053, 64054, 64054, 64054, 64054, 64054, 64055, \n\t64055, 64055, 64055, 64055, 64056, 64056, 64056, 64056, \n\t64057, 64057, 64057, 64057, 64057, 64058, 64058, 64058, \n\t64058, 64058, 64059, 64059, 64059, 64059, 64059, 64060, \n\t64060, 64060, 64060, 64061, 64061, 64061, 64061, 64061, \n\t64062, 64062, 64062, 64062, 64062, 64063, 64063, 64063, \n\t64063, 64064, 64064, 64064, 64064, 64064, 64065, 64065, \n\t64065, 64065, 64065, 64066, 64066, 64066, 64066, 64066, \n\t64067, 64067, 64067, 64067, 64068, 64068, 64068, 64068, \n\t64068, 64069, 64069, 64069, 64069, 64069, 64070, 64070, \n\t64070, 64070, 64070, 64071, 64071, 64071, 64071, 64072, \n\t64072, 64072, 64072, 64072, 64073, 64073, 64073, 64073, \n\t64073, 64074, 64074, 64074, 64074, 64074, 64075, 64075, \n\t64075, 64075, 64075, 64076, 64076, 64076, 64076, 64077, \n\t64077, 64077, 64077, 64077, 64078, 64078, 64078, 64078, \n\t64078, 64079, 64079, 64079, 64079, 64079, 64080, 64080, \n\t64080, 64080, 64081, 64081, 64081, 64081, 64081, 64082, \n\t64082, 64082, 64082, 64082, 64083, 64083, 64083, 64083, \n\t64083, 64084, 64084, 64084, 64084, 64085, 64085, 64085, \n\t64085, 64085, 64086, 64086, 64086, 64086, 64086, 64087, \n\t64087, 64087, 64087, 64087, 64088, 64088, 64088, 64088, \n\t64088, 64089, 64089, 64089, 64089, 64090, 64090, 64090, \n\t64090, 64090, 64091, 64091, 64091, 64091, 64091, 64092, \n\t64092, 64092, 64092, 64092, 64093, 64093, 64093, 64093, \n\t64093, 64094, 64094, 64094, 64094, 64095, 64095, 64095, \n\t64095, 64095, 64096, 64096, 64096, 64096, 64096, 64097, \n\t64097, 64097, 64097, 64097, 64098, 64098, 64098, 64098, \n\t64098, 64099, 64099, 64099, 64099, 64100, 64100, 64100, \n\t64100, 64100, 64101, 64101, 64101, 64101, 64101, 64102, \n\t64102, 64102, 64102, 64102, 64103, 64103, 64103, 64103, \n\t64103, 64104, 64104, 64104, 64104, 64105, 64105, 64105, \n\t64105, 64105, 64106, 64106, 64106, 64106, 64106, 64107, \n\t64107, 64107, 64107, 64107, 64108, 64108, 64108, 64108, \n\t64108, 64109, 64109, 64109, 64109, 64110, 64110, 64110, \n\t64110, 64110, 64111, 64111, 64111, 64111, 64111, 64112, \n\t64112, 64112, 64112, 64112, 64113, 64113, 64113, 64113, \n\t64113, 64114, 64114, 64114, 64114, 64114, 64115, 64115, \n\t64115, 64115, 64116, 64116, 64116, 64116, 64116, 64117, \n\t64117, 64117, 64117, 64117, 64118, 64118, 64118, 64118, \n\t64118, 64119, 64119, 64119, 64119, 64119, 64120, 64120, \n\t64120, 64120, 64120, 64121, 64121, 64121, 64121, 64122, \n\t64122, 64122, 64122, 64122, 64123, 64123, 64123, 64123, \n\t64123, 64124, 64124, 64124, 64124, 64124, 64125, 64125, \n\t64125, 64125, 64125, 64126, 64126, 64126, 64126, 64126, \n\t64127, 64127, 64127, 64127, 64128, 64128, 64128, 64128, \n\t64128, 64129, 64129, 64129, 64129, 64129, 64130, 64130, \n\t64130, 64130, 64130, 64131, 64131, 64131, 64131, 64131, \n\t64132, 64132, 64132, 64132, 64132, 64133, 64133, 64133, \n\t64133, 64133, 64134, 64134, 64134, 64134, 64135, 64135, \n\t64135, 64135, 64135, 64136, 64136, 64136, 64136, 64136, \n\t64137, 64137, 64137, 64137, 64137, 64138, 64138, 64138, \n\t64138, 64138, 64139, 64139, 64139, 64139, 64139, 64140, \n\t64140, 64140, 64140, 64140, 64141, 64141, 64141, 64141, \n\t64141, 64142, 64142, 64142, 64142, 64143, 64143, 64143, \n\t64143, 64143, 64144, 64144, 64144, 64144, 64144, 64145, \n\t64145, 64145, 64145, 64145, 64146, 64146, 64146, 64146, \n\t64146, 64147, 64147, 64147, 64147, 64147, 64148, 64148, \n\t64148, 64148, 64148, 64149, 64149, 64149, 64149, 64149, \n\t64150, 64150, 64150, 64150, 64151, 64151, 64151, 64151, \n\t64151, 64152, 64152, 64152, 64152, 64152, 64153, 64153, \n\t64153, 64153, 64153, 64154, 64154, 64154, 64154, 64154, \n\t64155, 64155, 64155, 64155, 64155, 64156, 64156, 64156, \n\t64156, 64156, 64157, 64157, 64157, 64157, 64157, 64158, \n\t64158, 64158, 64158, 64158, 64159, 64159, 64159, 64159, \n\t64159, 64160, 64160, 64160, 64160, 64161, 64161, 64161, \n\t64161, 64161, 64162, 64162, 64162, 64162, 64162, 64163, \n\t64163, 64163, 64163, 64163, 64164, 64164, 64164, 64164, \n\t64164, 64165, 64165, 64165, 64165, 64165, 64166, 64166, \n\t64166, 64166, 64166, 64167, 64167, 64167, 64167, 64167, \n\t64168, 64168, 64168, 64168, 64168, 64169, 64169, 64169, \n\t64169, 64169, 64170, 64170, 64170, 64170, 64170, 64171, \n\t64171, 64171, 64171, 64172, 64172, 64172, 64172, 64172, \n\t64173, 64173, 64173, 64173, 64173, 64174, 64174, 64174, \n\t64174, 64174, 64175, 64175, 64175, 64175, 64175, 64176, \n\t64176, 64176, 64176, 64176, 64177, 64177, 64177, 64177, \n\t64177, 64178, 64178, 64178, 64178, 64178, 64179, 64179, \n\t64179, 64179, 64179, 64180, 64180, 64180, 64180, 64180, \n\t64181, 64181, 64181, 64181, 64181, 64182, 64182, 64182, \n\t64182, 64182, 64183, 64183, 64183, 64183, 64183, 64184, \n\t64184, 64184, 64184, 64184, 64185, 64185, 64185, 64185, \n\t64185, 64186, 64186, 64186, 64186, 64186, 64187, 64187, \n\t64187, 64187, 64187, 64188, 64188, 64188, 64188, 64188, \n\t64189, 64189, 64189, 64189, 64190, 64190, 64190, 64190, \n\t64190, 64191, 64191, 64191, 64191, 64191, 64192, 64192, \n\t64192, 64192, 64192, 64193, 64193, 64193, 64193, 64193, \n\t64194, 64194, 64194, 64194, 64194, 64195, 64195, 64195, \n\t64195, 64195, 64196, 64196, 64196, 64196, 64196, 64197, \n\t64197, 64197, 64197, 64197, 64198, 64198, 64198, 64198, \n\t64198, 64199, 64199, 64199, 64199, 64199, 64200, 64200, \n\t64200, 64200, 64200, 64201, 64201, 64201, 64201, 64201, \n\t64202, 64202, 64202, 64202, 64202, 64203, 64203, 64203, \n\t64203, 64203, 64204, 64204, 64204, 64204, 64204, 64205, \n\t64205, 64205, 64205, 64205, 64206, 64206, 64206, 64206, \n\t64206, 64207, 64207, 64207, 64207, 64207, 64208, 64208, \n\t64208, 64208, 64208, 64209, 64209, 64209, 64209, 64209, \n\t64210, 64210, 64210, 64210, 64210, 64211, 64211, 64211, \n\t64211, 64211, 64212, 64212, 64212, 64212, 64212, 64213, \n\t64213, 64213, 64213, 64213, 64214, 64214, 64214, 64214, \n\t64214, 64215, 64215, 64215, 64215, 64215, 64216, 64216, \n\t64216, 64216, 64216, 64217, 64217, 64217, 64217, 64217, \n\t64218, 64218, 64218, 64218, 64218, 64219, 64219, 64219, \n\t64219, 64219, 64220, 64220, 64220, 64220, 64220, 64221, \n\t64221, 64221, 64221, 64221, 64222, 64222, 64222, 64222, \n\t64222, 64223, 64223, 64223, 64223, 64223, 64224, 64224, \n\t64224, 64224, 64224, 64225, 64225, 64225, 64225, 64225, \n\t64226, 64226, 64226, 64226, 64226, 64227, 64227, 64227, \n\t64227, 64227, 64228, 64228, 64228, 64228, 64228, 64229, \n\t64229, 64229, 64229, 64229, 64230, 64230, 64230, 64230, \n\t64230, 64231, 64231, 64231, 64231, 64231, 64232, 64232, \n\t64232, 64232, 64232, 64233, 64233, 64233, 64233, 64233, \n\t64234, 64234, 64234, 64234, 64234, 64235, 64235, 64235, \n\t64235, 64235, 64235, 64236, 64236, 64236, 64236, 64236, \n\t64237, 64237, 64237, 64237, 64237, 64238, 64238, 64238, \n\t64238, 64238, 64239, 64239, 64239, 64239, 64239, 64240, \n\t64240, 64240, 64240, 64240, 64241, 64241, 64241, 64241, \n\t64241, 64242, 64242, 64242, 64242, 64242, 64243, 64243, \n\t64243, 64243, 64243, 64244, 64244, 64244, 64244, 64244, \n\t64245, 64245, 64245, 64245, 64245, 64246, 64246, 64246, \n\t64246, 64246, 64247, 64247, 64247, 64247, 64247, 64248, \n\t64248, 64248, 64248, 64248, 64249, 64249, 64249, 64249, \n\t64249, 64250, 64250, 64250, 64250, 64250, 64251, 64251, \n\t64251, 64251, 64251, 64252, 64252, 64252, 64252, 64252, \n\t64252, 64253, 64253, 64253, 64253, 64253, 64254, 64254, \n\t64254, 64254, 64254, 64255, 64255, 64255, 64255, 64255, \n\t64256, 64256, 64256, 64256, 64256, 64257, 64257, 64257, \n\t64257, 64257, 64258, 64258, 64258, 64258, 64258, 64259, \n\t64259, 64259, 64259, 64259, 64260, 64260, 64260, 64260, \n\t64260, 64261, 64261, 64261, 64261, 64261, 64262, 64262, \n\t64262, 64262, 64262, 64263, 64263, 64263, 64263, 64263, \n\t64263, 64264, 64264, 64264, 64264, 64264, 64265, 64265, \n\t64265, 64265, 64265, 64266, 64266, 64266, 64266, 64266, \n\t64267, 64267, 64267, 64267, 64267, 64268, 64268, 64268, \n\t64268, 64268, 64269, 64269, 64269, 64269, 64269, 64270, \n\t64270, 64270, 64270, 64270, 64271, 64271, 64271, 64271, \n\t64271, 64272, 64272, 64272, 64272, 64272, 64272, 64273, \n\t64273, 64273, 64273, 64273, 64274, 64274, 64274, 64274, \n\t64274, 64275, 64275, 64275, 64275, 64275, 64276, 64276, \n\t64276, 64276, 64276, 64277, 64277, 64277, 64277, 64277, \n\t64278, 64278, 64278, 64278, 64278, 64279, 64279, 64279, \n\t64279, 64279, 64280, 64280, 64280, 64280, 64280, 64280, \n\t64281, 64281, 64281, 64281, 64281, 64282, 64282, 64282, \n\t64282, 64282, 64283, 64283, 64283, 64283, 64283, 64284, \n\t64284, 64284, 64284, 64284, 64285, 64285, 64285, 64285, \n\t64285, 64286, 64286, 64286, 64286, 64286, 64287, 64287, \n\t64287, 64287, 64287, 64288, 64288, 64288, 64288, 64288, \n\t64288, 64289, 64289, 64289, 64289, 64289, 64290, 64290, \n\t64290, 64290, 64290, 64291, 64291, 64291, 64291, 64291, \n\t64292, 64292, 64292, 64292, 64292, 64293, 64293, 64293, \n\t64293, 64293, 64294, 64294, 64294, 64294, 64294, 64294, \n\t64295, 64295, 64295, 64295, 64295, 64296, 64296, 64296, \n\t64296, 64296, 64297, 64297, 64297, 64297, 64297, 64298, \n\t64298, 64298, 64298, 64298, 64299, 64299, 64299, 64299, \n\t64299, 64300, 64300, 64300, 64300, 64300, 64300, 64301, \n\t64301, 64301, 64301, 64301, 64302, 64302, 64302, 64302, \n\t64302, 64303, 64303, 64303, 64303, 64303, 64304, 64304, \n\t64304, 64304, 64304, 64305, 64305, 64305, 64305, 64305, \n\t64306, 64306, 64306, 64306, 64306, 64306, 64307, 64307, \n\t64307, 64307, 64307, 64308, 64308, 64308, 64308, 64308, \n\t64309, 64309, 64309, 64309, 64309, 64310, 64310, 64310, \n\t64310, 64310, 64311, 64311, 64311, 64311, 64311, 64311, \n\t64312, 64312, 64312, 64312, 64312, 64313, 64313, 64313, \n\t64313, 64313, 64314, 64314, 64314, 64314, 64314, 64315, \n\t64315, 64315, 64315, 64315, 64316, 64316, 64316, 64316, \n\t64316, 64316, 64317, 64317, 64317, 64317, 64317, 64318, \n\t64318, 64318, 64318, 64318, 64319, 64319, 64319, 64319, \n\t64319, 64320, 64320, 64320, 64320, 64320, 64321, 64321, \n\t64321, 64321, 64321, 64321, 64322, 64322, 64322, 64322, \n\t64322, 64323, 64323, 64323, 64323, 64323, 64324, 64324, \n\t64324, 64324, 64324, 64325, 64325, 64325, 64325, 64325, \n\t64325, 64326, 64326, 64326, 64326, 64326, 64327, 64327, \n\t64327, 64327, 64327, 64328, 64328, 64328, 64328, 64328, \n\t64329, 64329, 64329, 64329, 64329, 64329, 64330, 64330, \n\t64330, 64330, 64330, 64331, 64331, 64331, 64331, 64331, \n\t64332, 64332, 64332, 64332, 64332, 64333, 64333, 64333, \n\t64333, 64333, 64334, 64334, 64334, 64334, 64334, 64334, \n\t64335, 64335, 64335, 64335, 64335, 64336, 64336, 64336, \n\t64336, 64336, 64337, 64337, 64337, 64337, 64337, 64338, \n\t64338, 64338, 64338, 64338, 64338, 64339, 64339, 64339, \n\t64339, 64339, 64340, 64340, 64340, 64340, 64340, 64341, \n\t64341, 64341, 64341, 64341, 64341, 64342, 64342, 64342, \n\t64342, 64342, 64343, 64343, 64343, 64343, 64343, 64344, \n\t64344, 64344, 64344, 64344, 64345, 64345, 64345, 64345, \n\t64345, 64345, 64346, 64346, 64346, 64346, 64346, 64347, \n\t64347, 64347, 64347, 64347, 64348, 64348, 64348, 64348, \n\t64348, 64349, 64349, 64349, 64349, 64349, 64349, 64350, \n\t64350, 64350, 64350, 64350, 64351, 64351, 64351, 64351, \n\t64351, 64352, 64352, 64352, 64352, 64352, 64352, 64353, \n\t64353, 64353, 64353, 64353, 64354, 64354, 64354, 64354, \n\t64354, 64355, 64355, 64355, 64355, 64355, 64356, 64356, \n\t64356, 64356, 64356, 64356, 64357, 64357, 64357, 64357, \n\t64357, 64358, 64358, 64358, 64358, 64358, 64359, 64359, \n\t64359, 64359, 64359, 64359, 64360, 64360, 64360, 64360, \n\t64360, 64361, 64361, 64361, 64361, 64361, 64362, 64362, \n\t64362, 64362, 64362, 64363, 64363, 64363, 64363, 64363, \n\t64363, 64364, 64364, 64364, 64364, 64364, 64365, 64365, \n\t64365, 64365, 64365, 64366, 64366, 64366, 64366, 64366, \n\t64366, 64367, 64367, 64367, 64367, 64367, 64368, 64368, \n\t64368, 64368, 64368, 64369, 64369, 64369, 64369, 64369, \n\t64369, 64370, 64370, 64370, 64370, 64370, 64371, 64371, \n\t64371, 64371, 64371, 64372, 64372, 64372, 64372, 64372, \n\t64372, 64373, 64373, 64373, 64373, 64373, 64374, 64374, \n\t64374, 64374, 64374, 64375, 64375, 64375, 64375, 64375, \n\t64375, 64376, 64376, 64376, 64376, 64376, 64377, 64377, \n\t64377, 64377, 64377, 64378, 64378, 64378, 64378, 64378, \n\t64378, 64379, 64379, 64379, 64379, 64379, 64380, 64380, \n\t64380, 64380, 64380, 64381, 64381, 64381, 64381, 64381, \n\t64381, 64382, 64382, 64382, 64382, 64382, 64383, 64383, \n\t64383, 64383, 64383, 64384, 64384, 64384, 64384, 64384, \n\t64384, 64385, 64385, 64385, 64385, 64385, 64386, 64386, \n\t64386, 64386, 64386, 64386, 64387, 64387, 64387, 64387, \n\t64387, 64388, 64388, 64388, 64388, 64388, 64389, 64389, \n\t64389, 64389, 64389, 64389, 64390, 64390, 64390, 64390, \n\t64390, 64391, 64391, 64391, 64391, 64391, 64392, 64392, \n\t64392, 64392, 64392, 64392, 64393, 64393, 64393, 64393, \n\t64393, 64394, 64394, 64394, 64394, 64394, 64394, 64395, \n\t64395, 64395, 64395, 64395, 64396, 64396, 64396, 64396, \n\t64396, 64397, 64397, 64397, 64397, 64397, 64397, 64398, \n\t64398, 64398, 64398, 64398, 64399, 64399, 64399, 64399, \n\t64399, 64400, 64400, 64400, 64400, 64400, 64400, 64401, \n\t64401, 64401, 64401, 64401, 64402, 64402, 64402, 64402, \n\t64402, 64402, 64403, 64403, 64403, 64403, 64403, 64404, \n\t64404, 64404, 64404, 64404, 64405, 64405, 64405, 64405, \n\t64405, 64405, 64406, 64406, 64406, 64406, 64406, 64407, \n\t64407, 64407, 64407, 64407, 64407, 64408, 64408, 64408, \n\t64408, 64408, 64409, 64409, 64409, 64409, 64409, 64410, \n\t64410, 64410, 64410, 64410, 64410, 64411, 64411, 64411, \n\t64411, 64411, 64412, 64412, 64412, 64412, 64412, 64412, \n\t64413, 64413, 64413, 64413, 64413, 64414, 64414, 64414, \n\t64414, 64414, 64414, 64415, 64415, 64415, 64415, 64415, \n\t64416, 64416, 64416, 64416, 64416, 64417, 64417, 64417, \n\t64417, 64417, 64417, 64418, 64418, 64418, 64418, 64418, \n\t64419, 64419, 64419, 64419, 64419, 64419, 64420, 64420, \n\t64420, 64420, 64420, 64421, 64421, 64421, 64421, 64421, \n\t64421, 64422, 64422, 64422, 64422, 64422, 64423, 64423, \n\t64423, 64423, 64423, 64423, 64424, 64424, 64424, 64424, \n\t64424, 64425, 64425, 64425, 64425, 64425, 64426, 64426, \n\t64426, 64426, 64426, 64426, 64427, 64427, 64427, 64427, \n\t64427, 64428, 64428, 64428, 64428, 64428, 64428, 64429, \n\t64429, 64429, 64429, 64429, 64430, 64430, 64430, 64430, \n\t64430, 64430, 64431, 64431, 64431, 64431, 64431, 64432, \n\t64432, 64432, 64432, 64432, 64432, 64433, 64433, 64433, \n\t64433, 64433, 64434, 64434, 64434, 64434, 64434, 64434, \n\t64435, 64435, 64435, 64435, 64435, 64436, 64436, 64436, \n\t64436, 64436, 64436, 64437, 64437, 64437, 64437, 64437, \n\t64438, 64438, 64438, 64438, 64438, 64438, 64439, 64439, \n\t64439, 64439, 64439, 64440, 64440, 64440, 64440, 64440, \n\t64440, 64441, 64441, 64441, 64441, 64441, 64442, 64442, \n\t64442, 64442, 64442, 64442, 64443, 64443, 64443, 64443, \n\t64443, 64444, 64444, 64444, 64444, 64444, 64444, 64445, \n\t64445, 64445, 64445, 64445, 64446, 64446, 64446, 64446, \n\t64446, 64446, 64447, 64447, 64447, 64447, 64447, 64448, \n\t64448, 64448, 64448, 64448, 64448, 64449, 64449, 64449, \n\t64449, 64449, 64450, 64450, 64450, 64450, 64450, 64450, \n\t64451, 64451, 64451, 64451, 64451, 64452, 64452, 64452, \n\t64452, 64452, 64452, 64453, 64453, 64453, 64453, 64453, \n\t64454, 64454, 64454, 64454, 64454, 64454, 64455, 64455, \n\t64455, 64455, 64455, 64456, 64456, 64456, 64456, 64456, \n\t64456, 64457, 64457, 64457, 64457, 64457, 64458, 64458, \n\t64458, 64458, 64458, 64458, 64459, 64459, 64459, 64459, \n\t64459, 64460, 64460, 64460, 64460, 64460, 64460, 64461, \n\t64461, 64461, 64461, 64461, 64462, 64462, 64462, 64462, \n\t64462, 64462, 64463, 64463, 64463, 64463, 64463, 64463, \n\t64464, 64464, 64464, 64464, 64464, 64465, 64465, 64465, \n\t64465, 64465, 64465, 64466, 64466, 64466, 64466, 64466, \n\t64467, 64467, 64467, 64467, 64467, 64467, 64468, 64468, \n\t64468, 64468, 64468, 64469, 64469, 64469, 64469, 64469, \n\t64469, 64470, 64470, 64470, 64470, 64470, 64471, 64471, \n\t64471, 64471, 64471, 64471, 64472, 64472, 64472, 64472, \n\t64472, 64472, 64473, 64473, 64473, 64473, 64473, 64474, \n\t64474, 64474, 64474, 64474, 64474, 64475, 64475, 64475, \n\t64475, 64475, 64476, 64476, 64476, 64476, 64476, 64476, \n\t64477, 64477, 64477, 64477, 64477, 64477, 64478, 64478, \n\t64478, 64478, 64478, 64479, 64479, 64479, 64479, 64479, \n\t64479, 64480, 64480, 64480, 64480, 64480, 64481, 64481, \n\t64481, 64481, 64481, 64481, 64482, 64482, 64482, 64482, \n\t64482, 64483, 64483, 64483, 64483, 64483, 64483, 64484, \n\t64484, 64484, 64484, 64484, 64484, 64485, 64485, 64485, \n\t64485, 64485, 64486, 64486, 64486, 64486, 64486, 64486, \n\t64487, 64487, 64487, 64487, 64487, 64487, 64488, 64488, \n\t64488, 64488, 64488, 64489, 64489, 64489, 64489, 64489, \n\t64489, 64490, 64490, 64490, 64490, 64490, 64491, 64491, \n\t64491, 64491, 64491, 64491, 64492, 64492, 64492, 64492, \n\t64492, 64492, 64493, 64493, 64493, 64493, 64493, 64494, \n\t64494, 64494, 64494, 64494, 64494, 64495, 64495, 64495, \n\t64495, 64495, 64496, 64496, 64496, 64496, 64496, 64496, \n\t64497, 64497, 64497, 64497, 64497, 64497, 64498, 64498, \n\t64498, 64498, 64498, 64499, 64499, 64499, 64499, 64499, \n\t64499, 64500, 64500, 64500, 64500, 64500, 64500, 64501, \n\t64501, 64501, 64501, 64501, 64502, 64502, 64502, 64502, \n\t64502, 64502, 64503, 64503, 64503, 64503, 64503, 64503, \n\t64504, 64504, 64504, 64504, 64504, 64505, 64505, 64505, \n\t64505, 64505, 64505, 64506, 64506, 64506, 64506, 64506, \n\t64506, 64507, 64507, 64507, 64507, 64507, 64508, 64508, \n\t64508, 64508, 64508, 64508, 64509, 64509, 64509, 64509, \n\t64509, 64509, 64510, 64510, 64510, 64510, 64510, 64511, \n\t64511, 64511, 64511, 64511, 64511, 64512, 64512, 64512, \n\t64512, 64512, 64512, 64513, 64513, 64513, 64513, 64513, \n\t64514, 64514, 64514, 64514, 64514, 64514, 64515, 64515, \n\t64515, 64515, 64515, 64515, 64516, 64516, 64516, 64516, \n\t64516, 64517, 64517, 64517, 64517, 64517, 64517, 64518, \n\t64518, 64518, 64518, 64518, 64518, 64519, 64519, 64519, \n\t64519, 64519, 64519, 64520, 64520, 64520, 64520, 64520, \n\t64521, 64521, 64521, 64521, 64521, 64521, 64522, 64522, \n\t64522, 64522, 64522, 64522, 64523, 64523, 64523, 64523, \n\t64523, 64524, 64524, 64524, 64524, 64524, 64524, 64525, \n\t64525, 64525, 64525, 64525, 64525, 64526, 64526, 64526, \n\t64526, 64526, 64527, 64527, 64527, 64527, 64527, 64527, \n\t64528, 64528, 64528, 64528, 64528, 64528, 64529, 64529, \n\t64529, 64529, 64529, 64529, 64530, 64530, 64530, 64530, \n\t64530, 64531, 64531, 64531, 64531, 64531, 64531, 64532, \n\t64532, 64532, 64532, 64532, 64532, 64533, 64533, 64533, \n\t64533, 64533, 64533, 64534, 64534, 64534, 64534, 64534, \n\t64535, 64535, 64535, 64535, 64535, 64535, 64536, 64536, \n\t64536, 64536, 64536, 64536, 64537, 64537, 64537, 64537, \n\t64537, 64537, 64538, 64538, 64538, 64538, 64538, 64539, \n\t64539, 64539, 64539, 64539, 64539, 64540, 64540, 64540, \n\t64540, 64540, 64540, 64541, 64541, 64541, 64541, 64541, \n\t64541, 64542, 64542, 64542, 64542, 64542, 64543, 64543, \n\t64543, 64543, 64543, 64543, 64544, 64544, 64544, 64544, \n\t64544, 64544, 64545, 64545, 64545, 64545, 64545, 64545, \n\t64546, 64546, 64546, 64546, 64546, 64547, 64547, 64547, \n\t64547, 64547, 64547, 64548, 64548, 64548, 64548, 64548, \n\t64548, 64549, 64549, 64549, 64549, 64549, 64549, 64550, \n\t64550, 64550, 64550, 64550, 64550, 64551, 64551, 64551, \n\t64551, 64551, 64552, 64552, 64552, 64552, 64552, 64552, \n\t64553, 64553, 64553, 64553, 64553, 64553, 64554, 64554, \n\t64554, 64554, 64554, 64554, 64555, 64555, 64555, 64555, \n\t64555, 64555, 64556, 64556, 64556, 64556, 64556, 64557, \n\t64557, 64557, 64557, 64557, 64557, 64558, 64558, 64558, \n\t64558, 64558, 64558, 64559, 64559, 64559, 64559, 64559, \n\t64559, 64560, 64560, 64560, 64560, 64560, 64560, 64561, \n\t64561, 64561, 64561, 64561, 64562, 64562, 64562, 64562, \n\t64562, 64562, 64563, 64563, 64563, 64563, 64563, 64563, \n\t64564, 64564, 64564, 64564, 64564, 64564, 64565, 64565, \n\t64565, 64565, 64565, 64565, 64566, 64566, 64566, 64566, \n\t64566, 64566, 64567, 64567, 64567, 64567, 64567, 64568, \n\t64568, 64568, 64568, 64568, 64568, 64569, 64569, 64569, \n\t64569, 64569, 64569, 64570, 64570, 64570, 64570, 64570, \n\t64570, 64571, 64571, 64571, 64571, 64571, 64571, 64572, \n\t64572, 64572, 64572, 64572, 64572, 64573, 64573, 64573, \n\t64573, 64573, 64574, 64574, 64574, 64574, 64574, 64574, \n\t64575, 64575, 64575, 64575, 64575, 64575, 64576, 64576, \n\t64576, 64576, 64576, 64576, 64577, 64577, 64577, 64577, \n\t64577, 64577, 64578, 64578, 64578, 64578, 64578, 64578, \n\t64579, 64579, 64579, 64579, 64579, 64579, 64580, 64580, \n\t64580, 64580, 64580, 64580, 64581, 64581, 64581, 64581, \n\t64581, 64582, 64582, 64582, 64582, 64582, 64582, 64583, \n\t64583, 64583, 64583, 64583, 64583, 64584, 64584, 64584, \n\t64584, 64584, 64584, 64585, 64585, 64585, 64585, 64585, \n\t64585, 64586, 64586, 64586, 64586, 64586, 64586, 64587, \n\t64587, 64587, 64587, 64587, 64587, 64588, 64588, 64588, \n\t64588, 64588, 64588, 64589, 64589, 64589, 64589, 64589, \n\t64589, 64590, 64590, 64590, 64590, 64590, 64591, 64591, \n\t64591, 64591, 64591, 64591, 64592, 64592, 64592, 64592, \n\t64592, 64592, 64593, 64593, 64593, 64593, 64593, 64593, \n\t64594, 64594, 64594, 64594, 64594, 64594, 64595, 64595, \n\t64595, 64595, 64595, 64595, 64596, 64596, 64596, 64596, \n\t64596, 64596, 64597, 64597, 64597, 64597, 64597, 64597, \n\t64598, 64598, 64598, 64598, 64598, 64598, 64599, 64599, \n\t64599, 64599, 64599, 64599, 64600, 64600, 64600, 64600, \n\t64600, 64600, 64601, 64601, 64601, 64601, 64601, 64601, \n\t64602, 64602, 64602, 64602, 64602, 64602, 64603, 64603, \n\t64603, 64603, 64603, 64603, 64604, 64604, 64604, 64604, \n\t64604, 64605, 64605, 64605, 64605, 64605, 64605, 64606, \n\t64606, 64606, 64606, 64606, 64606, 64607, 64607, 64607, \n\t64607, 64607, 64607, 64608, 64608, 64608, 64608, 64608, \n\t64608, 64609, 64609, 64609, 64609, 64609, 64609, 64610, \n\t64610, 64610, 64610, 64610, 64610, 64611, 64611, 64611, \n\t64611, 64611, 64611, 64612, 64612, 64612, 64612, 64612, \n\t64612, 64613, 64613, 64613, 64613, 64613, 64613, 64614, \n\t64614, 64614, 64614, 64614, 64614, 64615, 64615, 64615, \n\t64615, 64615, 64615, 64616, 64616, 64616, 64616, 64616, \n\t64616, 64617, 64617, 64617, 64617, 64617, 64617, 64618, \n\t64618, 64618, 64618, 64618, 64618, 64619, 64619, 64619, \n\t64619, 64619, 64619, 64620, 64620, 64620, 64620, 64620, \n\t64620, 64621, 64621, 64621, 64621, 64621, 64621, 64622, \n\t64622, 64622, 64622, 64622, 64622, 64623, 64623, 64623, \n\t64623, 64623, 64623, 64624, 64624, 64624, 64624, 64624, \n\t64624, 64625, 64625, 64625, 64625, 64625, 64625, 64626, \n\t64626, 64626, 64626, 64626, 64626, 64627, 64627, 64627, \n\t64627, 64627, 64627, 64628, 64628, 64628, 64628, 64628, \n\t64628, 64629, 64629, 64629, 64629, 64629, 64629, 64630, \n\t64630, 64630, 64630, 64630, 64630, 64631, 64631, 64631, \n\t64631, 64631, 64631, 64632, 64632, 64632, 64632, 64632, \n\t64632, 64633, 64633, 64633, 64633, 64633, 64633, 64634, \n\t64634, 64634, 64634, 64634, 64634, 64634, 64635, 64635, \n\t64635, 64635, 64635, 64635, 64636, 64636, 64636, 64636, \n\t64636, 64636, 64637, 64637, 64637, 64637, 64637, 64637, \n\t64638, 64638, 64638, 64638, 64638, 64638, 64639, 64639, \n\t64639, 64639, 64639, 64639, 64640, 64640, 64640, 64640, \n\t64640, 64640, 64641, 64641, 64641, 64641, 64641, 64641, \n\t64642, 64642, 64642, 64642, 64642, 64642, 64643, 64643, \n\t64643, 64643, 64643, 64643, 64644, 64644, 64644, 64644, \n\t64644, 64644, 64645, 64645, 64645, 64645, 64645, 64645, \n\t64646, 64646, 64646, 64646, 64646, 64646, 64647, 64647, \n\t64647, 64647, 64647, 64647, 64648, 64648, 64648, 64648, \n\t64648, 64648, 64648, 64649, 64649, 64649, 64649, 64649, \n\t64649, 64650, 64650, 64650, 64650, 64650, 64650, 64651, \n\t64651, 64651, 64651, 64651, 64651, 64652, 64652, 64652, \n\t64652, 64652, 64652, 64653, 64653, 64653, 64653, 64653, \n\t64653, 64654, 64654, 64654, 64654, 64654, 64654, 64655, \n\t64655, 64655, 64655, 64655, 64655, 64656, 64656, 64656, \n\t64656, 64656, 64656, 64657, 64657, 64657, 64657, 64657, \n\t64657, 64657, 64658, 64658, 64658, 64658, 64658, 64658, \n\t64659, 64659, 64659, 64659, 64659, 64659, 64660, 64660, \n\t64660, 64660, 64660, 64660, 64661, 64661, 64661, 64661, \n\t64661, 64661, 64662, 64662, 64662, 64662, 64662, 64662, \n\t64663, 64663, 64663, 64663, 64663, 64663, 64664, 64664, \n\t64664, 64664, 64664, 64664, 64664, 64665, 64665, 64665, \n\t64665, 64665, 64665, 64666, 64666, 64666, 64666, 64666, \n\t64666, 64667, 64667, 64667, 64667, 64667, 64667, 64668, \n\t64668, 64668, 64668, 64668, 64668, 64669, 64669, 64669, \n\t64669, 64669, 64669, 64670, 64670, 64670, 64670, 64670, \n\t64670, 64671, 64671, 64671, 64671, 64671, 64671, 64671, \n\t64672, 64672, 64672, 64672, 64672, 64672, 64673, 64673, \n\t64673, 64673, 64673, 64673, 64674, 64674, 64674, 64674, \n\t64674, 64674, 64675, 64675, 64675, 64675, 64675, 64675, \n\t64676, 64676, 64676, 64676, 64676, 64676, 64676, 64677, \n\t64677, 64677, 64677, 64677, 64677, 64678, 64678, 64678, \n\t64678, 64678, 64678, 64679, 64679, 64679, 64679, 64679, \n\t64679, 64680, 64680, 64680, 64680, 64680, 64680, 64681, \n\t64681, 64681, 64681, 64681, 64681, 64681, 64682, 64682, \n\t64682, 64682, 64682, 64682, 64683, 64683, 64683, 64683, \n\t64683, 64683, 64684, 64684, 64684, 64684, 64684, 64684, \n\t64685, 64685, 64685, 64685, 64685, 64685, 64685, 64686, \n\t64686, 64686, 64686, 64686, 64686, 64687, 64687, 64687, \n\t64687, 64687, 64687, 64688, 64688, 64688, 64688, 64688, \n\t64688, 64689, 64689, 64689, 64689, 64689, 64689, 64690, \n\t64690, 64690, 64690, 64690, 64690, 64690, 64691, 64691, \n\t64691, 64691, 64691, 64691, 64692, 64692, 64692, 64692, \n\t64692, 64692, 64693, 64693, 64693, 64693, 64693, 64693, \n\t64694, 64694, 64694, 64694, 64694, 64694, 64694, 64695, \n\t64695, 64695, 64695, 64695, 64695, 64696, 64696, 64696, \n\t64696, 64696, 64696, 64697, 64697, 64697, 64697, 64697, \n\t64697, 64698, 64698, 64698, 64698, 64698, 64698, 64698, \n\t64699, 64699, 64699, 64699, 64699, 64699, 64700, 64700, \n\t64700, 64700, 64700, 64700, 64701, 64701, 64701, 64701, \n\t64701, 64701, 64701, 64702, 64702, 64702, 64702, 64702, \n\t64702, 64703, 64703, 64703, 64703, 64703, 64703, 64704, \n\t64704, 64704, 64704, 64704, 64704, 64705, 64705, 64705, \n\t64705, 64705, 64705, 64705, 64706, 64706, 64706, 64706, \n\t64706, 64706, 64707, 64707, 64707, 64707, 64707, 64707, \n\t64708, 64708, 64708, 64708, 64708, 64708, 64708, 64709, \n\t64709, 64709, 64709, 64709, 64709, 64710, 64710, 64710, \n\t64710, 64710, 64710, 64711, 64711, 64711, 64711, 64711, \n\t64711, 64711, 64712, 64712, 64712, 64712, 64712, 64712, \n\t64713, 64713, 64713, 64713, 64713, 64713, 64714, 64714, \n\t64714, 64714, 64714, 64714, 64714, 64715, 64715, 64715, \n\t64715, 64715, 64715, 64716, 64716, 64716, 64716, 64716, \n\t64716, 64717, 64717, 64717, 64717, 64717, 64717, 64717, \n\t64718, 64718, 64718, 64718, 64718, 64718, 64719, 64719, \n\t64719, 64719, 64719, 64719, 64720, 64720, 64720, 64720, \n\t64720, 64720, 64720, 64721, 64721, 64721, 64721, 64721, \n\t64721, 64722, 64722, 64722, 64722, 64722, 64722, 64723, \n\t64723, 64723, 64723, 64723, 64723, 64723, 64724, 64724, \n\t64724, 64724, 64724, 64724, 64725, 64725, 64725, 64725, \n\t64725, 64725, 64725, 64726, 64726, 64726, 64726, 64726, \n\t64726, 64727, 64727, 64727, 64727, 64727, 64727, 64728, \n\t64728, 64728, 64728, 64728, 64728, 64728, 64729, 64729, \n\t64729, 64729, 64729, 64729, 64730, 64730, 64730, 64730, \n\t64730, 64730, 64730, 64731, 64731, 64731, 64731, 64731, \n\t64731, 64732, 64732, 64732, 64732, 64732, 64732, 64733, \n\t64733, 64733, 64733, 64733, 64733, 64733, 64734, 64734, \n\t64734, 64734, 64734, 64734, 64735, 64735, 64735, 64735, \n\t64735, 64735, 64735, 64736, 64736, 64736, 64736, 64736, \n\t64736, 64737, 64737, 64737, 64737, 64737, 64737, 64738, \n\t64738, 64738, 64738, 64738, 64738, 64738, 64739, 64739, \n\t64739, 64739, 64739, 64739, 64740, 64740, 64740, 64740, \n\t64740, 64740, 64740, 64741, 64741, 64741, 64741, 64741, \n\t64741, 64742, 64742, 64742, 64742, 64742, 64742, 64742, \n\t64743, 64743, 64743, 64743, 64743, 64743, 64744, 64744, \n\t64744, 64744, 64744, 64744, 64745, 64745, 64745, 64745, \n\t64745, 64745, 64745, 64746, 64746, 64746, 64746, 64746, \n\t64746, 64747, 64747, 64747, 64747, 64747, 64747, 64747, \n\t64748, 64748, 64748, 64748, 64748, 64748, 64749, 64749, \n\t64749, 64749, 64749, 64749, 64749, 64750, 64750, 64750, \n\t64750, 64750, 64750, 64751, 64751, 64751, 64751, 64751, \n\t64751, 64751, 64752, 64752, 64752, 64752, 64752, 64752, \n\t64753, 64753, 64753, 64753, 64753, 64753, 64753, 64754, \n\t64754, 64754, 64754, 64754, 64754, 64755, 64755, 64755, \n\t64755, 64755, 64755, 64755, 64756, 64756, 64756, 64756, \n\t64756, 64756, 64757, 64757, 64757, 64757, 64757, 64757, \n\t64757, 64758, 64758, 64758, 64758, 64758, 64758, 64759, \n\t64759, 64759, 64759, 64759, 64759, 64759, 64760, 64760, \n\t64760, 64760, 64760, 64760, 64761, 64761, 64761, 64761, \n\t64761, 64761, 64761, 64762, 64762, 64762, 64762, 64762, \n\t64762, 64763, 64763, 64763, 64763, 64763, 64763, 64763, \n\t64764, 64764, 64764, 64764, 64764, 64764, 64765, 64765, \n\t64765, 64765, 64765, 64765, 64765, 64766, 64766, 64766, \n\t64766, 64766, 64766, 64767, 64767, 64767, 64767, 64767, \n\t64767, 64767, 64768, 64768, 64768, 64768, 64768, 64768, \n\t64768, 64769, 64769, 64769, 64769, 64769, 64769, 64770, \n\t64770, 64770, 64770, 64770, 64770, 64770, 64771, 64771, \n\t64771, 64771, 64771, 64771, 64772, 64772, 64772, 64772, \n\t64772, 64772, 64772, 64773, 64773, 64773, 64773, 64773, \n\t64773, 64774, 64774, 64774, 64774, 64774, 64774, 64774, \n\t64775, 64775, 64775, 64775, 64775, 64775, 64775, 64776, \n\t64776, 64776, 64776, 64776, 64776, 64777, 64777, 64777, \n\t64777, 64777, 64777, 64777, 64778, 64778, 64778, 64778, \n\t64778, 64778, 64779, 64779, 64779, 64779, 64779, 64779, \n\t64779, 64780, 64780, 64780, 64780, 64780, 64780, 64781, \n\t64781, 64781, 64781, 64781, 64781, 64781, 64782, 64782, \n\t64782, 64782, 64782, 64782, 64782, 64783, 64783, 64783, \n\t64783, 64783, 64783, 64784, 64784, 64784, 64784, 64784, \n\t64784, 64784, 64785, 64785, 64785, 64785, 64785, 64785, \n\t64785, 64786, 64786, 64786, 64786, 64786, 64786, 64787, \n\t64787, 64787, 64787, 64787, 64787, 64787, 64788, 64788, \n\t64788, 64788, 64788, 64788, 64789, 64789, 64789, 64789, \n\t64789, 64789, 64789, 64790, 64790, 64790, 64790, 64790, \n\t64790, 64790, 64791, 64791, 64791, 64791, 64791, 64791, \n\t64792, 64792, 64792, 64792, 64792, 64792, 64792, 64793, \n\t64793, 64793, 64793, 64793, 64793, 64793, 64794, 64794, \n\t64794, 64794, 64794, 64794, 64795, 64795, 64795, 64795, \n\t64795, 64795, 64795, 64796, 64796, 64796, 64796, 64796, \n\t64796, 64796, 64797, 64797, 64797, 64797, 64797, 64797, \n\t64798, 64798, 64798, 64798, 64798, 64798, 64798, 64799, \n\t64799, 64799, 64799, 64799, 64799, 64799, 64800, 64800, \n\t64800, 64800, 64800, 64800, 64801, 64801, 64801, 64801, \n\t64801, 64801, 64801, 64802, 64802, 64802, 64802, 64802, \n\t64802, 64802, 64803, 64803, 64803, 64803, 64803, 64803, \n\t64803, 64804, 64804, 64804, 64804, 64804, 64804, 64805, \n\t64805, 64805, 64805, 64805, 64805, 64805, 64806, 64806, \n\t64806, 64806, 64806, 64806, 64806, 64807, 64807, 64807, \n\t64807, 64807, 64807, 64808, 64808, 64808, 64808, 64808, \n\t64808, 64808, 64809, 64809, 64809, 64809, 64809, 64809, \n\t64809, 64810, 64810, 64810, 64810, 64810, 64810, 64810, \n\t64811, 64811, 64811, 64811, 64811, 64811, 64812, 64812, \n\t64812, 64812, 64812, 64812, 64812, 64813, 64813, 64813, \n\t64813, 64813, 64813, 64813, 64814, 64814, 64814, 64814, \n\t64814, 64814, 64814, 64815, 64815, 64815, 64815, 64815, \n\t64815, 64816, 64816, 64816, 64816, 64816, 64816, 64816, \n\t64817, 64817, 64817, 64817, 64817, 64817, 64817, 64818, \n\t64818, 64818, 64818, 64818, 64818, 64818, 64819, 64819, \n\t64819, 64819, 64819, 64819, 64820, 64820, 64820, 64820, \n\t64820, 64820, 64820, 64821, 64821, 64821, 64821, 64821, \n\t64821, 64821, 64822, 64822, 64822, 64822, 64822, 64822, \n\t64822, 64823, 64823, 64823, 64823, 64823, 64823, 64823, \n\t64824, 64824, 64824, 64824, 64824, 64824, 64825, 64825, \n\t64825, 64825, 64825, 64825, 64825, 64826, 64826, 64826, \n\t64826, 64826, 64826, 64826, 64827, 64827, 64827, 64827, \n\t64827, 64827, 64827, 64828, 64828, 64828, 64828, 64828, \n\t64828, 64828, 64829, 64829, 64829, 64829, 64829, 64829, \n\t64829, 64830, 64830, 64830, 64830, 64830, 64830, 64831, \n\t64831, 64831, 64831, 64831, 64831, 64831, 64832, 64832, \n\t64832, 64832, 64832, 64832, 64832, 64833, 64833, 64833, \n\t64833, 64833, 64833, 64833, 64834, 64834, 64834, 64834, \n\t64834, 64834, 64834, 64835, 64835, 64835, 64835, 64835, \n\t64835, 64835, 64836, 64836, 64836, 64836, 64836, 64836, \n\t64837, 64837, 64837, 64837, 64837, 64837, 64837, 64838, \n\t64838, 64838, 64838, 64838, 64838, 64838, 64839, 64839, \n\t64839, 64839, 64839, 64839, 64839, 64840, 64840, 64840, \n\t64840, 64840, 64840, 64840, 64841, 64841, 64841, 64841, \n\t64841, 64841, 64841, 64842, 64842, 64842, 64842, 64842, \n\t64842, 64842, 64843, 64843, 64843, 64843, 64843, 64843, \n\t64843, 64844, 64844, 64844, 64844, 64844, 64844, 64844, \n\t64845, 64845, 64845, 64845, 64845, 64845, 64846, 64846, \n\t64846, 64846, 64846, 64846, 64846, 64847, 64847, 64847, \n\t64847, 64847, 64847, 64847, 64848, 64848, 64848, 64848, \n\t64848, 64848, 64848, 64849, 64849, 64849, 64849, 64849, \n\t64849, 64849, 64850, 64850, 64850, 64850, 64850, 64850, \n\t64850, 64851, 64851, 64851, 64851, 64851, 64851, 64851, \n\t64852, 64852, 64852, 64852, 64852, 64852, 64852, 64853, \n\t64853, 64853, 64853, 64853, 64853, 64853, 64854, 64854, \n\t64854, 64854, 64854, 64854, 64854, 64855, 64855, 64855, \n\t64855, 64855, 64855, 64855, 64856, 64856, 64856, 64856, \n\t64856, 64856, 64856, 64857, 64857, 64857, 64857, 64857, \n\t64857, 64857, 64858, 64858, 64858, 64858, 64858, 64858, \n\t64858, 64859, 64859, 64859, 64859, 64859, 64859, 64859, \n\t64860, 64860, 64860, 64860, 64860, 64860, 64860, 64861, \n\t64861, 64861, 64861, 64861, 64861, 64861, 64862, 64862, \n\t64862, 64862, 64862, 64862, 64862, 64863, 64863, 64863, \n\t64863, 64863, 64863, 64863, 64864, 64864, 64864, 64864, \n\t64864, 64864, 64864, 64865, 64865, 64865, 64865, 64865, \n\t64865, 64865, 64866, 64866, 64866, 64866, 64866, 64866, \n\t64866, 64867, 64867, 64867, 64867, 64867, 64867, 64867, \n\t64868, 64868, 64868, 64868, 64868, 64868, 64868, 64869, \n\t64869, 64869, 64869, 64869, 64869, 64869, 64870, 64870, \n\t64870, 64870, 64870, 64870, 64870, 64871, 64871, 64871, \n\t64871, 64871, 64871, 64871, 64872, 64872, 64872, 64872, \n\t64872, 64872, 64872, 64873, 64873, 64873, 64873, 64873, \n\t64873, 64873, 64874, 64874, 64874, 64874, 64874, 64874, \n\t64874, 64875, 64875, 64875, 64875, 64875, 64875, 64875, \n\t64876, 64876, 64876, 64876, 64876, 64876, 64876, 64877, \n\t64877, 64877, 64877, 64877, 64877, 64877, 64878, 64878, \n\t64878, 64878, 64878, 64878, 64878, 64879, 64879, 64879, \n\t64879, 64879, 64879, 64879, 64880, 64880, 64880, 64880, \n\t64880, 64880, 64880, 64881, 64881, 64881, 64881, 64881, \n\t64881, 64881, 64882, 64882, 64882, 64882, 64882, 64882, \n\t64882, 64883, 64883, 64883, 64883, 64883, 64883, 64883, \n\t64883, 64884, 64884, 64884, 64884, 64884, 64884, 64884, \n\t64885, 64885, 64885, 64885, 64885, 64885, 64885, 64886, \n\t64886, 64886, 64886, 64886, 64886, 64886, 64887, 64887, \n\t64887, 64887, 64887, 64887, 64887, 64888, 64888, 64888, \n\t64888, 64888, 64888, 64888, 64889, 64889, 64889, 64889, \n\t64889, 64889, 64889, 64890, 64890, 64890, 64890, 64890, \n\t64890, 64890, 64891, 64891, 64891, 64891, 64891, 64891, \n\t64891, 64891, 64892, 64892, 64892, 64892, 64892, 64892, \n\t64892, 64893, 64893, 64893, 64893, 64893, 64893, 64893, \n\t64894, 64894, 64894, 64894, 64894, 64894, 64894, 64895, \n\t64895, 64895, 64895, 64895, 64895, 64895, 64896, 64896, \n\t64896, 64896, 64896, 64896, 64896, 64897, 64897, 64897, \n\t64897, 64897, 64897, 64897, 64897, 64898, 64898, 64898, \n\t64898, 64898, 64898, 64898, 64899, 64899, 64899, 64899, \n\t64899, 64899, 64899, 64900, 64900, 64900, 64900, 64900, \n\t64900, 64900, 64901, 64901, 64901, 64901, 64901, 64901, \n\t64901, 64902, 64902, 64902, 64902, 64902, 64902, 64902, \n\t64902, 64903, 64903, 64903, 64903, 64903, 64903, 64903, \n\t64904, 64904, 64904, 64904, 64904, 64904, 64904, 64905, \n\t64905, 64905, 64905, 64905, 64905, 64905, 64906, 64906, \n\t64906, 64906, 64906, 64906, 64906, 64907, 64907, 64907, \n\t64907, 64907, 64907, 64907, 64907, 64908, 64908, 64908, \n\t64908, 64908, 64908, 64908, 64909, 64909, 64909, 64909, \n\t64909, 64909, 64909, 64910, 64910, 64910, 64910, 64910, \n\t64910, 64910, 64911, 64911, 64911, 64911, 64911, 64911, \n\t64911, 64911, 64912, 64912, 64912, 64912, 64912, 64912, \n\t64912, 64913, 64913, 64913, 64913, 64913, 64913, 64913, \n\t64914, 64914, 64914, 64914, 64914, 64914, 64914, 64915, \n\t64915, 64915, 64915, 64915, 64915, 64915, 64915, 64916, \n\t64916, 64916, 64916, 64916, 64916, 64916, 64917, 64917, \n\t64917, 64917, 64917, 64917, 64917, 64918, 64918, 64918, \n\t64918, 64918, 64918, 64918, 64918, 64919, 64919, 64919, \n\t64919, 64919, 64919, 64919, 64920, 64920, 64920, 64920, \n\t64920, 64920, 64920, 64921, 64921, 64921, 64921, 64921, \n\t64921, 64921, 64921, 64922, 64922, 64922, 64922, 64922, \n\t64922, 64922, 64923, 64923, 64923, 64923, 64923, 64923, \n\t64923, 64924, 64924, 64924, 64924, 64924, 64924, 64924, \n\t64924, 64925, 64925, 64925, 64925, 64925, 64925, 64925, \n\t64926, 64926, 64926, 64926, 64926, 64926, 64926, 64927, \n\t64927, 64927, 64927, 64927, 64927, 64927, 64927, 64928, \n\t64928, 64928, 64928, 64928, 64928, 64928, 64929, 64929, \n\t64929, 64929, 64929, 64929, 64929, 64930, 64930, 64930, \n\t64930, 64930, 64930, 64930, 64930, 64931, 64931, 64931, \n\t64931, 64931, 64931, 64931, 64932, 64932, 64932, 64932, \n\t64932, 64932, 64932, 64933, 64933, 64933, 64933, 64933, \n\t64933, 64933, 64933, 64934, 64934, 64934, 64934, 64934, \n\t64934, 64934, 64935, 64935, 64935, 64935, 64935, 64935, \n\t64935, 64935, 64936, 64936, 64936, 64936, 64936, 64936, \n\t64936, 64937, 64937, 64937, 64937, 64937, 64937, 64937, \n\t64938, 64938, 64938, 64938, 64938, 64938, 64938, 64938, \n\t64939, 64939, 64939, 64939, 64939, 64939, 64939, 64940, \n\t64940, 64940, 64940, 64940, 64940, 64940, 64940, 64941, \n\t64941, 64941, 64941, 64941, 64941, 64941, 64942, 64942, \n\t64942, 64942, 64942, 64942, 64942, 64942, 64943, 64943, \n\t64943, 64943, 64943, 64943, 64943, 64944, 64944, 64944, \n\t64944, 64944, 64944, 64944, 64944, 64945, 64945, 64945, \n\t64945, 64945, 64945, 64945, 64946, 64946, 64946, 64946, \n\t64946, 64946, 64946, 64947, 64947, 64947, 64947, 64947, \n\t64947, 64947, 64947, 64948, 64948, 64948, 64948, 64948, \n\t64948, 64948, 64949, 64949, 64949, 64949, 64949, 64949, \n\t64949, 64949, 64950, 64950, 64950, 64950, 64950, 64950, \n\t64950, 64951, 64951, 64951, 64951, 64951, 64951, 64951, \n\t64951, 64952, 64952, 64952, 64952, 64952, 64952, 64952, \n\t64953, 64953, 64953, 64953, 64953, 64953, 64953, 64953, \n\t64954, 64954, 64954, 64954, 64954, 64954, 64954, 64955, \n\t64955, 64955, 64955, 64955, 64955, 64955, 64955, 64956, \n\t64956, 64956, 64956, 64956, 64956, 64956, 64957, 64957, \n\t64957, 64957, 64957, 64957, 64957, 64957, 64958, 64958, \n\t64958, 64958, 64958, 64958, 64958, 64958, 64959, 64959, \n\t64959, 64959, 64959, 64959, 64959, 64960, 64960, 64960, \n\t64960, 64960, 64960, 64960, 64960, 64961, 64961, 64961, \n\t64961, 64961, 64961, 64961, 64962, 64962, 64962, 64962, \n\t64962, 64962, 64962, 64962, 64963, 64963, 64963, 64963, \n\t64963, 64963, 64963, 64964, 64964, 64964, 64964, 64964, \n\t64964, 64964, 64964, 64965, 64965, 64965, 64965, 64965, \n\t64965, 64965, 64965, 64966, 64966, 64966, 64966, 64966, \n\t64966, 64966, 64967, 64967, 64967, 64967, 64967, 64967, \n\t64967, 64967, 64968, 64968, 64968, 64968, 64968, 64968, \n\t64968, 64969, 64969, 64969, 64969, 64969, 64969, 64969, \n\t64969, 64970, 64970, 64970, 64970, 64970, 64970, 64970, \n\t64970, 64971, 64971, 64971, 64971, 64971, 64971, 64971, \n\t64972, 64972, 64972, 64972, 64972, 64972, 64972, 64972, \n\t64973, 64973, 64973, 64973, 64973, 64973, 64973, 64973, \n\t64974, 64974, 64974, 64974, 64974, 64974, 64974, 64975, \n\t64975, 64975, 64975, 64975, 64975, 64975, 64975, 64976, \n\t64976, 64976, 64976, 64976, 64976, 64976, 64976, 64977, \n\t64977, 64977, 64977, 64977, 64977, 64977, 64978, 64978, \n\t64978, 64978, 64978, 64978, 64978, 64978, 64979, 64979, \n\t64979, 64979, 64979, 64979, 64979, 64979, 64980, 64980, \n\t64980, 64980, 64980, 64980, 64980, 64981, 64981, 64981, \n\t64981, 64981, 64981, 64981, 64981, 64982, 64982, 64982, \n\t64982, 64982, 64982, 64982, 64982, 64983, 64983, 64983, \n\t64983, 64983, 64983, 64983, 64984, 64984, 64984, 64984, \n\t64984, 64984, 64984, 64984, 64985, 64985, 64985, 64985, \n\t64985, 64985, 64985, 64985, 64986, 64986, 64986, 64986, \n\t64986, 64986, 64986, 64986, 64987, 64987, 64987, 64987, \n\t64987, 64987, 64987, 64988, 64988, 64988, 64988, 64988, \n\t64988, 64988, 64988, 64989, 64989, 64989, 64989, 64989, \n\t64989, 64989, 64989, 64990, 64990, 64990, 64990, 64990, \n\t64990, 64990, 64990, 64991, 64991, 64991, 64991, 64991, \n\t64991, 64991, 64992, 64992, 64992, 64992, 64992, 64992, \n\t64992, 64992, 64993, 64993, 64993, 64993, 64993, 64993, \n\t64993, 64993, 64994, 64994, 64994, 64994, 64994, 64994, \n\t64994, 64994, 64995, 64995, 64995, 64995, 64995, 64995, \n\t64995, 64995, 64996, 64996, 64996, 64996, 64996, 64996, \n\t64996, 64997, 64997, 64997, 64997, 64997, 64997, 64997, \n\t64997, 64998, 64998, 64998, 64998, 64998, 64998, 64998, \n\t64998, 64999, 64999, 64999, 64999, 64999, 64999, 64999, \n\t64999, 65000, 65000, 65000, 65000, 65000, 65000, 65000, \n\t65000, 65001, 65001, 65001, 65001, 65001, 65001, 65001, \n\t65002, 65002, 65002, 65002, 65002, 65002, 65002, 65002, \n\t65003, 65003, 65003, 65003, 65003, 65003, 65003, 65003, \n\t65004, 65004, 65004, 65004, 65004, 65004, 65004, 65004, \n\t65005, 65005, 65005, 65005, 65005, 65005, 65005, 65005, \n\t65006, 65006, 65006, 65006, 65006, 65006, 65006, 65006, \n\t65007, 65007, 65007, 65007, 65007, 65007, 65007, 65007, \n\t65008, 65008, 65008, 65008, 65008, 65008, 65008, 65008, \n\t65009, 65009, 65009, 65009, 65009, 65009, 65009, 65010, \n\t65010, 65010, 65010, 65010, 65010, 65010, 65010, 65011, \n\t65011, 65011, 65011, 65011, 65011, 65011, 65011, 65012, \n\t65012, 65012, 65012, 65012, 65012, 65012, 65012, 65013, \n\t65013, 65013, 65013, 65013, 65013, 65013, 65013, 65014, \n\t65014, 65014, 65014, 65014, 65014, 65014, 65014, 65015, \n\t65015, 65015, 65015, 65015, 65015, 65015, 65015, 65016, \n\t65016, 65016, 65016, 65016, 65016, 65016, 65016, 65017, \n\t65017, 65017, 65017, 65017, 65017, 65017, 65017, 65018, \n\t65018, 65018, 65018, 65018, 65018, 65018, 65018, 65019, \n\t65019, 65019, 65019, 65019, 65019, 65019, 65019, 65020, \n\t65020, 65020, 65020, 65020, 65020, 65020, 65020, 65021, \n\t65021, 65021, 65021, 65021, 65021, 65021, 65021, 65022, \n\t65022, 65022, 65022, 65022, 65022, 65022, 65022, 65023, \n\t65023, 65023, 65023, 65023, 65023, 65023, 65023, 65024, \n\t65024, 65024, 65024, 65024, 65024, 65024, 65024, 65025, \n\t65025, 65025, 65025, 65025, 65025, 65025, 65025, 65026, \n\t65026, 65026, 65026, 65026, 65026, 65026, 65026, 65027, \n\t65027, 65027, 65027, 65027, 65027, 65027, 65027, 65028, \n\t65028, 65028, 65028, 65028, 65028, 65028, 65028, 65029, \n\t65029, 65029, 65029, 65029, 65029, 65029, 65029, 65030, \n\t65030, 65030, 65030, 65030, 65030, 65030, 65030, 65031, \n\t65031, 65031, 65031, 65031, 65031, 65031, 65031, 65032, \n\t65032, 65032, 65032, 65032, 65032, 65032, 65032, 65033, \n\t65033, 65033, 65033, 65033, 65033, 65033, 65033, 65034, \n\t65034, 65034, 65034, 65034, 65034, 65034, 65034, 65035, \n\t65035, 65035, 65035, 65035, 65035, 65035, 65035, 65035, \n\t65036, 65036, 65036, 65036, 65036, 65036, 65036, 65036, \n\t65037, 65037, 65037, 65037, 65037, 65037, 65037, 65037, \n\t65038, 65038, 65038, 65038, 65038, 65038, 65038, 65038, \n\t65039, 65039, 65039, 65039, 65039, 65039, 65039, 65039, \n\t65040, 65040, 65040, 65040, 65040, 65040, 65040, 65040, \n\t65041, 65041, 65041, 65041, 65041, 65041, 65041, 65041, \n\t65042, 65042, 65042, 65042, 65042, 65042, 65042, 65042, \n\t65042, 65043, 65043, 65043, 65043, 65043, 65043, 65043, \n\t65043, 65044, 65044, 65044, 65044, 65044, 65044, 65044, \n\t65044, 65045, 65045, 65045, 65045, 65045, 65045, 65045, \n\t65045, 65046, 65046, 65046, 65046, 65046, 65046, 65046, \n\t65046, 65047, 65047, 65047, 65047, 65047, 65047, 65047, \n\t65047, 65048, 65048, 65048, 65048, 65048, 65048, 65048, \n\t65048, 65048, 65049, 65049, 65049, 65049, 65049, 65049, \n\t65049, 65049, 65050, 65050, 65050, 65050, 65050, 65050, \n\t65050, 65050, 65051, 65051, 65051, 65051, 65051, 65051, \n\t65051, 65051, 65052, 65052, 65052, 65052, 65052, 65052, \n\t65052, 65052, 65052, 65053, 65053, 65053, 65053, 65053, \n\t65053, 65053, 65053, 65054, 65054, 65054, 65054, 65054, \n\t65054, 65054, 65054, 65055, 65055, 65055, 65055, 65055, \n\t65055, 65055, 65055, 65056, 65056, 65056, 65056, 65056, \n\t65056, 65056, 65056, 65056, 65057, 65057, 65057, 65057, \n\t65057, 65057, 65057, 65057, 65058, 65058, 65058, 65058, \n\t65058, 65058, 65058, 65058, 65059, 65059, 65059, 65059, \n\t65059, 65059, 65059, 65059, 65059, 65060, 65060, 65060, \n\t65060, 65060, 65060, 65060, 65060, 65061, 65061, 65061, \n\t65061, 65061, 65061, 65061, 65061, 65062, 65062, 65062, \n\t65062, 65062, 65062, 65062, 65062, 65063, 65063, 65063, \n\t65063, 65063, 65063, 65063, 65063, 65063, 65064, 65064, \n\t65064, 65064, 65064, 65064, 65064, 65064, 65065, 65065, \n\t65065, 65065, 65065, 65065, 65065, 65065, 65065, 65066, \n\t65066, 65066, 65066, 65066, 65066, 65066, 65066, 65067, \n\t65067, 65067, 65067, 65067, 65067, 65067, 65067, 65068, \n\t65068, 65068, 65068, 65068, 65068, 65068, 65068, 65068, \n\t65069, 65069, 65069, 65069, 65069, 65069, 65069, 65069, \n\t65070, 65070, 65070, 65070, 65070, 65070, 65070, 65070, \n\t65071, 65071, 65071, 65071, 65071, 65071, 65071, 65071, \n\t65071, 65072, 65072, 65072, 65072, 65072, 65072, 65072, \n\t65072, 65073, 65073, 65073, 65073, 65073, 65073, 65073, \n\t65073, 65073, 65074, 65074, 65074, 65074, 65074, 65074, \n\t65074, 65074, 65075, 65075, 65075, 65075, 65075, 65075, \n\t65075, 65075, 65075, 65076, 65076, 65076, 65076, 65076, \n\t65076, 65076, 65076, 65077, 65077, 65077, 65077, 65077, \n\t65077, 65077, 65077, 65078, 65078, 65078, 65078, 65078, \n\t65078, 65078, 65078, 65078, 65079, 65079, 65079, 65079, \n\t65079, 65079, 65079, 65079, 65080, 65080, 65080, 65080, \n\t65080, 65080, 65080, 65080, 65080, 65081, 65081, 65081, \n\t65081, 65081, 65081, 65081, 65081, 65082, 65082, 65082, \n\t65082, 65082, 65082, 65082, 65082, 65082, 65083, 65083, \n\t65083, 65083, 65083, 65083, 65083, 65083, 65084, 65084, \n\t65084, 65084, 65084, 65084, 65084, 65084, 65084, 65085, \n\t65085, 65085, 65085, 65085, 65085, 65085, 65085, 65085, \n\t65086, 65086, 65086, 65086, 65086, 65086, 65086, 65086, \n\t65087, 65087, 65087, 65087, 65087, 65087, 65087, 65087, \n\t65087, 65088, 65088, 65088, 65088, 65088, 65088, 65088, \n\t65088, 65089, 65089, 65089, 65089, 65089, 65089, 65089, \n\t65089, 65089, 65090, 65090, 65090, 65090, 65090, 65090, \n\t65090, 65090, 65091, 65091, 65091, 65091, 65091, 65091, \n\t65091, 65091, 65091, 65092, 65092, 65092, 65092, 65092, \n\t65092, 65092, 65092, 65092, 65093, 65093, 65093, 65093, \n\t65093, 65093, 65093, 65093, 65094, 65094, 65094, 65094, \n\t65094, 65094, 65094, 65094, 65094, 65095, 65095, 65095, \n\t65095, 65095, 65095, 65095, 65095, 65096, 65096, 65096, \n\t65096, 65096, 65096, 65096, 65096, 65096, 65097, 65097, \n\t65097, 65097, 65097, 65097, 65097, 65097, 65097, 65098, \n\t65098, 65098, 65098, 65098, 65098, 65098, 65098, 65099, \n\t65099, 65099, 65099, 65099, 65099, 65099, 65099, 65099, \n\t65100, 65100, 65100, 65100, 65100, 65100, 65100, 65100, \n\t65100, 65101, 65101, 65101, 65101, 65101, 65101, 65101, \n\t65101, 65102, 65102, 65102, 65102, 65102, 65102, 65102, \n\t65102, 65102, 65103, 65103, 65103, 65103, 65103, 65103, \n\t65103, 65103, 65103, 65104, 65104, 65104, 65104, 65104, \n\t65104, 65104, 65104, 65104, 65105, 65105, 65105, 65105, \n\t65105, 65105, 65105, 65105, 65106, 65106, 65106, 65106, \n\t65106, 65106, 65106, 65106, 65106, 65107, 65107, 65107, \n\t65107, 65107, 65107, 65107, 65107, 65107, 65108, 65108, \n\t65108, 65108, 65108, 65108, 65108, 65108, 65108, 65109, \n\t65109, 65109, 65109, 65109, 65109, 65109, 65109, 65110, \n\t65110, 65110, 65110, 65110, 65110, 65110, 65110, 65110, \n\t65111, 65111, 65111, 65111, 65111, 65111, 65111, 65111, \n\t65111, 65112, 65112, 65112, 65112, 65112, 65112, 65112, \n\t65112, 65112, 65113, 65113, 65113, 65113, 65113, 65113, \n\t65113, 65113, 65113, 65114, 65114, 65114, 65114, 65114, \n\t65114, 65114, 65114, 65115, 65115, 65115, 65115, 65115, \n\t65115, 65115, 65115, 65115, 65116, 65116, 65116, 65116, \n\t65116, 65116, 65116, 65116, 65116, 65117, 65117, 65117, \n\t65117, 65117, 65117, 65117, 65117, 65117, 65118, 65118, \n\t65118, 65118, 65118, 65118, 65118, 65118, 65118, 65119, \n\t65119, 65119, 65119, 65119, 65119, 65119, 65119, 65119, \n\t65120, 65120, 65120, 65120, 65120, 65120, 65120, 65120, \n\t65120, 65121, 65121, 65121, 65121, 65121, 65121, 65121, \n\t65121, 65122, 65122, 65122, 65122, 65122, 65122, 65122, \n\t65122, 65122, 65123, 65123, 65123, 65123, 65123, 65123, \n\t65123, 65123, 65123, 65124, 65124, 65124, 65124, 65124, \n\t65124, 65124, 65124, 65124, 65125, 65125, 65125, 65125, \n\t65125, 65125, 65125, 65125, 65125, 65126, 65126, 65126, \n\t65126, 65126, 65126, 65126, 65126, 65126, 65127, 65127, \n\t65127, 65127, 65127, 65127, 65127, 65127, 65127, 65128, \n\t65128, 65128, 65128, 65128, 65128, 65128, 65128, 65128, \n\t65129, 65129, 65129, 65129, 65129, 65129, 65129, 65129, \n\t65129, 65130, 65130, 65130, 65130, 65130, 65130, 65130, \n\t65130, 65130, 65131, 65131, 65131, 65131, 65131, 65131, \n\t65131, 65131, 65131, 65132, 65132, 65132, 65132, 65132, \n\t65132, 65132, 65132, 65132, 65133, 65133, 65133, 65133, \n\t65133, 65133, 65133, 65133, 65133, 65134, 65134, 65134, \n\t65134, 65134, 65134, 65134, 65134, 65134, 65135, 65135, \n\t65135, 65135, 65135, 65135, 65135, 65135, 65135, 65136, \n\t65136, 65136, 65136, 65136, 65136, 65136, 65136, 65136, \n\t65137, 65137, 65137, 65137, 65137, 65137, 65137, 65137, \n\t65137, 65138, 65138, 65138, 65138, 65138, 65138, 65138, \n\t65138, 65138, 65139, 65139, 65139, 65139, 65139, 65139, \n\t65139, 65139, 65139, 65139, 65140, 65140, 65140, 65140, \n\t65140, 65140, 65140, 65140, 65140, 65141, 65141, 65141, \n\t65141, 65141, 65141, 65141, 65141, 65141, 65142, 65142, \n\t65142, 65142, 65142, 65142, 65142, 65142, 65142, 65143, \n\t65143, 65143, 65143, 65143, 65143, 65143, 65143, 65143, \n\t65144, 65144, 65144, 65144, 65144, 65144, 65144, 65144, \n\t65144, 65145, 65145, 65145, 65145, 65145, 65145, 65145, \n\t65145, 65145, 65146, 65146, 65146, 65146, 65146, 65146, \n\t65146, 65146, 65146, 65146, 65147, 65147, 65147, 65147, \n\t65147, 65147, 65147, 65147, 65147, 65148, 65148, 65148, \n\t65148, 65148, 65148, 65148, 65148, 65148, 65149, 65149, \n\t65149, 65149, 65149, 65149, 65149, 65149, 65149, 65150, \n\t65150, 65150, 65150, 65150, 65150, 65150, 65150, 65150, \n\t65151, 65151, 65151, 65151, 65151, 65151, 65151, 65151, \n\t65151, 65151, 65152, 65152, 65152, 65152, 65152, 65152, \n\t65152, 65152, 65152, 65153, 65153, 65153, 65153, 65153, \n\t65153, 65153, 65153, 65153, 65154, 65154, 65154, 65154, \n\t65154, 65154, 65154, 65154, 65154, 65155, 65155, 65155, \n\t65155, 65155, 65155, 65155, 65155, 65155, 65155, 65156, \n\t65156, 65156, 65156, 65156, 65156, 65156, 65156, 65156, \n\t65157, 65157, 65157, 65157, 65157, 65157, 65157, 65157, \n\t65157, 65158, 65158, 65158, 65158, 65158, 65158, 65158, \n\t65158, 65158, 65158, 65159, 65159, 65159, 65159, 65159, \n\t65159, 65159, 65159, 65159, 65160, 65160, 65160, 65160, \n\t65160, 65160, 65160, 65160, 65160, 65161, 65161, 65161, \n\t65161, 65161, 65161, 65161, 65161, 65161, 65161, 65162, \n\t65162, 65162, 65162, 65162, 65162, 65162, 65162, 65162, \n\t65163, 65163, 65163, 65163, 65163, 65163, 65163, 65163, \n\t65163, 65164, 65164, 65164, 65164, 65164, 65164, 65164, \n\t65164, 65164, 65164, 65165, 65165, 65165, 65165, 65165, \n\t65165, 65165, 65165, 65165, 65166, 65166, 65166, 65166, \n\t65166, 65166, 65166, 65166, 65166, 65166, 65167, 65167, \n\t65167, 65167, 65167, 65167, 65167, 65167, 65167, 65168, \n\t65168, 65168, 65168, 65168, 65168, 65168, 65168, 65168, \n\t65168, 65169, 65169, 65169, 65169, 65169, 65169, 65169, \n\t65169, 65169, 65170, 65170, 65170, 65170, 65170, 65170, \n\t65170, 65170, 65170, 65170, 65171, 65171, 65171, 65171, \n\t65171, 65171, 65171, 65171, 65171, 65172, 65172, 65172, \n\t65172, 65172, 65172, 65172, 65172, 65172, 65172, 65173, \n\t65173, 65173, 65173, 65173, 65173, 65173, 65173, 65173, \n\t65174, 65174, 65174, 65174, 65174, 65174, 65174, 65174, \n\t65174, 65174, 65175, 65175, 65175, 65175, 65175, 65175, \n\t65175, 65175, 65175, 65176, 65176, 65176, 65176, 65176, \n\t65176, 65176, 65176, 65176, 65176, 65177, 65177, 65177, \n\t65177, 65177, 65177, 65177, 65177, 65177, 65178, 65178, \n\t65178, 65178, 65178, 65178, 65178, 65178, 65178, 65178, \n\t65179, 65179, 65179, 65179, 65179, 65179, 65179, 65179, \n\t65179, 65180, 65180, 65180, 65180, 65180, 65180, 65180, \n\t65180, 65180, 65180, 65181, 65181, 65181, 65181, 65181, \n\t65181, 65181, 65181, 65181, 65181, 65182, 65182, 65182, \n\t65182, 65182, 65182, 65182, 65182, 65182, 65183, 65183, \n\t65183, 65183, 65183, 65183, 65183, 65183, 65183, 65183, \n\t65184, 65184, 65184, 65184, 65184, 65184, 65184, 65184, \n\t65184, 65184, 65185, 65185, 65185, 65185, 65185, 65185, \n\t65185, 65185, 65185, 65186, 65186, 65186, 65186, 65186, \n\t65186, 65186, 65186, 65186, 65186, 65187, 65187, 65187, \n\t65187, 65187, 65187, 65187, 65187, 65187, 65187, 65188, \n\t65188, 65188, 65188, 65188, 65188, 65188, 65188, 65188, \n\t65189, 65189, 65189, 65189, 65189, 65189, 65189, 65189, \n\t65189, 65189, 65190, 65190, 65190, 65190, 65190, 65190, \n\t65190, 65190, 65190, 65190, 65191, 65191, 65191, 65191, \n\t65191, 65191, 65191, 65191, 65191, 65191, 65192, 65192, \n\t65192, 65192, 65192, 65192, 65192, 65192, 65192, 65193, \n\t65193, 65193, 65193, 65193, 65193, 65193, 65193, 65193, \n\t65193, 65194, 65194, 65194, 65194, 65194, 65194, 65194, \n\t65194, 65194, 65194, 65195, 65195, 65195, 65195, 65195, \n\t65195, 65195, 65195, 65195, 65195, 65196, 65196, 65196, \n\t65196, 65196, 65196, 65196, 65196, 65196, 65196, 65197, \n\t65197, 65197, 65197, 65197, 65197, 65197, 65197, 65197, \n\t65198, 65198, 65198, 65198, 65198, 65198, 65198, 65198, \n\t65198, 65198, 65199, 65199, 65199, 65199, 65199, 65199, \n\t65199, 65199, 65199, 65199, 65200, 65200, 65200, 65200, \n\t65200, 65200, 65200, 65200, 65200, 65200, 65201, 65201, \n\t65201, 65201, 65201, 65201, 65201, 65201, 65201, 65201, \n\t65202, 65202, 65202, 65202, 65202, 65202, 65202, 65202, \n\t65202, 65202, 65203, 65203, 65203, 65203, 65203, 65203, \n\t65203, 65203, 65203, 65203, 65204, 65204, 65204, 65204, \n\t65204, 65204, 65204, 65204, 65204, 65204, 65205, 65205, \n\t65205, 65205, 65205, 65205, 65205, 65205, 65205, 65205, \n\t65206, 65206, 65206, 65206, 65206, 65206, 65206, 65206, \n\t65206, 65206, 65207, 65207, 65207, 65207, 65207, 65207, \n\t65207, 65207, 65207, 65207, 65208, 65208, 65208, 65208, \n\t65208, 65208, 65208, 65208, 65208, 65208, 65209, 65209, \n\t65209, 65209, 65209, 65209, 65209, 65209, 65209, 65209, \n\t65210, 65210, 65210, 65210, 65210, 65210, 65210, 65210, \n\t65210, 65210, 65211, 65211, 65211, 65211, 65211, 65211, \n\t65211, 65211, 65211, 65211, 65212, 65212, 65212, 65212, \n\t65212, 65212, 65212, 65212, 65212, 65212, 65213, 65213, \n\t65213, 65213, 65213, 65213, 65213, 65213, 65213, 65213, \n\t65214, 65214, 65214, 65214, 65214, 65214, 65214, 65214, \n\t65214, 65214, 65215, 65215, 65215, 65215, 65215, 65215, \n\t65215, 65215, 65215, 65215, 65216, 65216, 65216, 65216, \n\t65216, 65216, 65216, 65216, 65216, 65216, 65217, 65217, \n\t65217, 65217, 65217, 65217, 65217, 65217, 65217, 65217, \n\t65218, 65218, 65218, 65218, 65218, 65218, 65218, 65218, \n\t65218, 65218, 65218, 65219, 65219, 65219, 65219, 65219, \n\t65219, 65219, 65219, 65219, 65219, 65220, 65220, 65220, \n\t65220, 65220, 65220, 65220, 65220, 65220, 65220, 65221, \n\t65221, 65221, 65221, 65221, 65221, 65221, 65221, 65221, \n\t65221, 65222, 65222, 65222, 65222, 65222, 65222, 65222, \n\t65222, 65222, 65222, 65223, 65223, 65223, 65223, 65223, \n\t65223, 65223, 65223, 65223, 65223, 65223, 65224, 65224, \n\t65224, 65224, 65224, 65224, 65224, 65224, 65224, 65224, \n\t65225, 65225, 65225, 65225, 65225, 65225, 65225, 65225, \n\t65225, 65225, 65226, 65226, 65226, 65226, 65226, 65226, \n\t65226, 65226, 65226, 65226, 65227, 65227, 65227, 65227, \n\t65227, 65227, 65227, 65227, 65227, 65227, 65227, 65228, \n\t65228, 65228, 65228, 65228, 65228, 65228, 65228, 65228, \n\t65228, 65229, 65229, 65229, 65229, 65229, 65229, 65229, \n\t65229, 65229, 65229, 65230, 65230, 65230, 65230, 65230, \n\t65230, 65230, 65230, 65230, 65230, 65230, 65231, 65231, \n\t65231, 65231, 65231, 65231, 65231, 65231, 65231, 65231, \n\t65232, 65232, 65232, 65232, 65232, 65232, 65232, 65232, \n\t65232, 65232, 65232, 65233, 65233, 65233, 65233, 65233, \n\t65233, 65233, 65233, 65233, 65233, 65234, 65234, 65234, \n\t65234, 65234, 65234, 65234, 65234, 65234, 65234, 65235, \n\t65235, 65235, 65235, 65235, 65235, 65235, 65235, 65235, \n\t65235, 65235, 65236, 65236, 65236, 65236, 65236, 65236, \n\t65236, 65236, 65236, 65236, 65237, 65237, 65237, 65237, \n\t65237, 65237, 65237, 65237, 65237, 65237, 65237, 65238, \n\t65238, 65238, 65238, 65238, 65238, 65238, 65238, 65238, \n\t65238, 65239, 65239, 65239, 65239, 65239, 65239, 65239, \n\t65239, 65239, 65239, 65239, 65240, 65240, 65240, 65240, \n\t65240, 65240, 65240, 65240, 65240, 65240, 65241, 65241, \n\t65241, 65241, 65241, 65241, 65241, 65241, 65241, 65241, \n\t65241, 65242, 65242, 65242, 65242, 65242, 65242, 65242, \n\t65242, 65242, 65242, 65242, 65243, 65243, 65243, 65243, \n\t65243, 65243, 65243, 65243, 65243, 65243, 65244, 65244, \n\t65244, 65244, 65244, 65244, 65244, 65244, 65244, 65244, \n\t65244, 65245, 65245, 65245, 65245, 65245, 65245, 65245, \n\t65245, 65245, 65245, 65246, 65246, 65246, 65246, 65246, \n\t65246, 65246, 65246, 65246, 65246, 65246, 65247, 65247, \n\t65247, 65247, 65247, 65247, 65247, 65247, 65247, 65247, \n\t65247, 65248, 65248, 65248, 65248, 65248, 65248, 65248, \n\t65248, 65248, 65248, 65249, 65249, 65249, 65249, 65249, \n\t65249, 65249, 65249, 65249, 65249, 65249, 65250, 65250, \n\t65250, 65250, 65250, 65250, 65250, 65250, 65250, 65250, \n\t65250, 65251, 65251, 65251, 65251, 65251, 65251, 65251, \n\t65251, 65251, 65251, 65252, 65252, 65252, 65252, 65252, \n\t65252, 65252, 65252, 65252, 65252, 65252, 65253, 65253, \n\t65253, 65253, 65253, 65253, 65253, 65253, 65253, 65253, \n\t65253, 65254, 65254, 65254, 65254, 65254, 65254, 65254, \n\t65254, 65254, 65254, 65254, 65255, 65255, 65255, 65255, \n\t65255, 65255, 65255, 65255, 65255, 65255, 65255, 65256, \n\t65256, 65256, 65256, 65256, 65256, 65256, 65256, 65256, \n\t65256, 65257, 65257, 65257, 65257, 65257, 65257, 65257, \n\t65257, 65257, 65257, 65257, 65258, 65258, 65258, 65258, \n\t65258, 65258, 65258, 65258, 65258, 65258, 65258, 65259, \n\t65259, 65259, 65259, 65259, 65259, 65259, 65259, 65259, \n\t65259, 65259, 65260, 65260, 65260, 65260, 65260, 65260, \n\t65260, 65260, 65260, 65260, 65260, 65261, 65261, 65261, \n\t65261, 65261, 65261, 65261, 65261, 65261, 65261, 65261, \n\t65262, 65262, 65262, 65262, 65262, 65262, 65262, 65262, \n\t65262, 65262, 65262, 65263, 65263, 65263, 65263, 65263, \n\t65263, 65263, 65263, 65263, 65263, 65263, 65264, 65264, \n\t65264, 65264, 65264, 65264, 65264, 65264, 65264, 65264, \n\t65264, 65265, 65265, 65265, 65265, 65265, 65265, 65265, \n\t65265, 65265, 65265, 65265, 65266, 65266, 65266, 65266, \n\t65266, 65266, 65266, 65266, 65266, 65266, 65266, 65267, \n\t65267, 65267, 65267, 65267, 65267, 65267, 65267, 65267, \n\t65267, 65267, 65268, 65268, 65268, 65268, 65268, 65268, \n\t65268, 65268, 65268, 65268, 65268, 65269, 65269, 65269, \n\t65269, 65269, 65269, 65269, 65269, 65269, 65269, 65269, \n\t65270, 65270, 65270, 65270, 65270, 65270, 65270, 65270, \n\t65270, 65270, 65270, 65271, 65271, 65271, 65271, 65271, \n\t65271, 65271, 65271, 65271, 65271, 65271, 65272, 65272, \n\t65272, 65272, 65272, 65272, 65272, 65272, 65272, 65272, \n\t65272, 65273, 65273, 65273, 65273, 65273, 65273, 65273, \n\t65273, 65273, 65273, 65273, 65273, 65274, 65274, 65274, \n\t65274, 65274, 65274, 65274, 65274, 65274, 65274, 65274, \n\t65275, 65275, 65275, 65275, 65275, 65275, 65275, 65275, \n\t65275, 65275, 65275, 65276, 65276, 65276, 65276, 65276, \n\t65276, 65276, 65276, 65276, 65276, 65276, 65277, 65277, \n\t65277, 65277, 65277, 65277, 65277, 65277, 65277, 65277, \n\t65277, 65278, 65278, 65278, 65278, 65278, 65278, 65278, \n\t65278, 65278, 65278, 65278, 65278, 65279, 65279, 65279, \n\t65279, 65279, 65279, 65279, 65279, 65279, 65279, 65279, \n\t65280, 65280, 65280, 65280, 65280, 65280, 65280, 65280, \n\t65280, 65280, 65280, 65281, 65281, 65281, 65281, 65281, \n\t65281, 65281, 65281, 65281, 65281, 65281, 65281, 65282, \n\t65282, 65282, 65282, 65282, 65282, 65282, 65282, 65282, \n\t65282, 65282, 65283, 65283, 65283, 65283, 65283, 65283, \n\t65283, 65283, 65283, 65283, 65283, 65284, 65284, 65284, \n\t65284, 65284, 65284, 65284, 65284, 65284, 65284, 65284, \n\t65284, 65285, 65285, 65285, 65285, 65285, 65285, 65285, \n\t65285, 65285, 65285, 65285, 65286, 65286, 65286, 65286, \n\t65286, 65286, 65286, 65286, 65286, 65286, 65286, 65286, \n\t65287, 65287, 65287, 65287, 65287, 65287, 65287, 65287, \n\t65287, 65287, 65287, 65288, 65288, 65288, 65288, 65288, \n\t65288, 65288, 65288, 65288, 65288, 65288, 65288, 65289, \n\t65289, 65289, 65289, 65289, 65289, 65289, 65289, 65289, \n\t65289, 65289, 65290, 65290, 65290, 65290, 65290, 65290, \n\t65290, 65290, 65290, 65290, 65290, 65290, 65291, 65291, \n\t65291, 65291, 65291, 65291, 65291, 65291, 65291, 65291, \n\t65291, 65292, 65292, 65292, 65292, 65292, 65292, 65292, \n\t65292, 65292, 65292, 65292, 65292, 65293, 65293, 65293, \n\t65293, 65293, 65293, 65293, 65293, 65293, 65293, 65293, \n\t65293, 65294, 65294, 65294, 65294, 65294, 65294, 65294, \n\t65294, 65294, 65294, 65294, 65295, 65295, 65295, 65295, \n\t65295, 65295, 65295, 65295, 65295, 65295, 65295, 65295, \n\t65296, 65296, 65296, 65296, 65296, 65296, 65296, 65296, \n\t65296, 65296, 65296, 65296, 65297, 65297, 65297, 65297, \n\t65297, 65297, 65297, 65297, 65297, 65297, 65297, 65298, \n\t65298, 65298, 65298, 65298, 65298, 65298, 65298, 65298, \n\t65298, 65298, 65298, 65299, 65299, 65299, 65299, 65299, \n\t65299, 65299, 65299, 65299, 65299, 65299, 65299, 65300, \n\t65300, 65300, 65300, 65300, 65300, 65300, 65300, 65300, \n\t65300, 65300, 65300, 65301, 65301, 65301, 65301, 65301, \n\t65301, 65301, 65301, 65301, 65301, 65301, 65301, 65302, \n\t65302, 65302, 65302, 65302, 65302, 65302, 65302, 65302, \n\t65302, 65302, 65303, 65303, 65303, 65303, 65303, 65303, \n\t65303, 65303, 65303, 65303, 65303, 65303, 65304, 65304, \n\t65304, 65304, 65304, 65304, 65304, 65304, 65304, 65304, \n\t65304, 65304, 65305, 65305, 65305, 65305, 65305, 65305, \n\t65305, 65305, 65305, 65305, 65305, 65305, 65306, 65306, \n\t65306, 65306, 65306, 65306, 65306, 65306, 65306, 65306, \n\t65306, 65306, 65307, 65307, 65307, 65307, 65307, 65307, \n\t65307, 65307, 65307, 65307, 65307, 65307, 65308, 65308, \n\t65308, 65308, 65308, 65308, 65308, 65308, 65308, 65308, \n\t65308, 65308, 65309, 65309, 65309, 65309, 65309, 65309, \n\t65309, 65309, 65309, 65309, 65309, 65309, 65310, 65310, \n\t65310, 65310, 65310, 65310, 65310, 65310, 65310, 65310, \n\t65310, 65310, 65311, 65311, 65311, 65311, 65311, 65311, \n\t65311, 65311, 65311, 65311, 65311, 65311, 65312, 65312, \n\t65312, 65312, 65312, 65312, 65312, 65312, 65312, 65312, \n\t65312, 65312, 65313, 65313, 65313, 65313, 65313, 65313, \n\t65313, 65313, 65313, 65313, 65313, 65313, 65314, 65314, \n\t65314, 65314, 65314, 65314, 65314, 65314, 65314, 65314, \n\t65314, 65314, 65314, 65315, 65315, 65315, 65315, 65315, \n\t65315, 65315, 65315, 65315, 65315, 65315, 65315, 65316, \n\t65316, 65316, 65316, 65316, 65316, 65316, 65316, 65316, \n\t65316, 65316, 65316, 65317, 65317, 65317, 65317, 65317, \n\t65317, 65317, 65317, 65317, 65317, 65317, 65317, 65318, \n\t65318, 65318, 65318, 65318, 65318, 65318, 65318, 65318, \n\t65318, 65318, 65318, 65319, 65319, 65319, 65319, 65319, \n\t65319, 65319, 65319, 65319, 65319, 65319, 65319, 65319, \n\t65320, 65320, 65320, 65320, 65320, 65320, 65320, 65320, \n\t65320, 65320, 65320, 65320, 65321, 65321, 65321, 65321, \n\t65321, 65321, 65321, 65321, 65321, 65321, 65321, 65321, \n\t65322, 65322, 65322, 65322, 65322, 65322, 65322, 65322, \n\t65322, 65322, 65322, 65322, 65322, 65323, 65323, 65323, \n\t65323, 65323, 65323, 65323, 65323, 65323, 65323, 65323, \n\t65323, 65324, 65324, 65324, 65324, 65324, 65324, 65324, \n\t65324, 65324, 65324, 65324, 65324, 65324, 65325, 65325, \n\t65325, 65325, 65325, 65325, 65325, 65325, 65325, 65325, \n\t65325, 65325, 65326, 65326, 65326, 65326, 65326, 65326, \n\t65326, 65326, 65326, 65326, 65326, 65326, 65326, 65327, \n\t65327, 65327, 65327, 65327, 65327, 65327, 65327, 65327, \n\t65327, 65327, 65327, 65328, 65328, 65328, 65328, 65328, \n\t65328, 65328, 65328, 65328, 65328, 65328, 65328, 65328, \n\t65329, 65329, 65329, 65329, 65329, 65329, 65329, 65329, \n\t65329, 65329, 65329, 65329, 65330, 65330, 65330, 65330, \n\t65330, 65330, 65330, 65330, 65330, 65330, 65330, 65330, \n\t65330, 65331, 65331, 65331, 65331, 65331, 65331, 65331, \n\t65331, 65331, 65331, 65331, 65331, 65331, 65332, 65332, \n\t65332, 65332, 65332, 65332, 65332, 65332, 65332, 65332, \n\t65332, 65332, 65333, 65333, 65333, 65333, 65333, 65333, \n\t65333, 65333, 65333, 65333, 65333, 65333, 65333, 65334, \n\t65334, 65334, 65334, 65334, 65334, 65334, 65334, 65334, \n\t65334, 65334, 65334, 65334, 65335, 65335, 65335, 65335, \n\t65335, 65335, 65335, 65335, 65335, 65335, 65335, 65335, \n\t65335, 65336, 65336, 65336, 65336, 65336, 65336, 65336, \n\t65336, 65336, 65336, 65336, 65336, 65337, 65337, 65337, \n\t65337, 65337, 65337, 65337, 65337, 65337, 65337, 65337, \n\t65337, 65337, 65338, 65338, 65338, 65338, 65338, 65338, \n\t65338, 65338, 65338, 65338, 65338, 65338, 65338, 65339, \n\t65339, 65339, 65339, 65339, 65339, 65339, 65339, 65339, \n\t65339, 65339, 65339, 65339, 65340, 65340, 65340, 65340, \n\t65340, 65340, 65340, 65340, 65340, 65340, 65340, 65340, \n\t65340, 65341, 65341, 65341, 65341, 65341, 65341, 65341, \n\t65341, 65341, 65341, 65341, 65341, 65341, 65342, 65342, \n\t65342, 65342, 65342, 65342, 65342, 65342, 65342, 65342, \n\t65342, 65342, 65342, 65343, 65343, 65343, 65343, 65343, \n\t65343, 65343, 65343, 65343, 65343, 65343, 65343, 65343, \n\t65344, 65344, 65344, 65344, 65344, 65344, 65344, 65344, \n\t65344, 65344, 65344, 65344, 65344, 65345, 65345, 65345, \n\t65345, 65345, 65345, 65345, 65345, 65345, 65345, 65345, \n\t65345, 65345, 65346, 65346, 65346, 65346, 65346, 65346, \n\t65346, 65346, 65346, 65346, 65346, 65346, 65346, 65347, \n\t65347, 65347, 65347, 65347, 65347, 65347, 65347, 65347, \n\t65347, 65347, 65347, 65347, 65348, 65348, 65348, 65348, \n\t65348, 65348, 65348, 65348, 65348, 65348, 65348, 65348, \n\t65348, 65348, 65349, 65349, 65349, 65349, 65349, 65349, \n\t65349, 65349, 65349, 65349, 65349, 65349, 65349, 65350, \n\t65350, 65350, 65350, 65350, 65350, 65350, 65350, 65350, \n\t65350, 65350, 65350, 65350, 65351, 65351, 65351, 65351, \n\t65351, 65351, 65351, 65351, 65351, 65351, 65351, 65351, \n\t65351, 65352, 65352, 65352, 65352, 65352, 65352, 65352, \n\t65352, 65352, 65352, 65352, 65352, 65352, 65352, 65353, \n\t65353, 65353, 65353, 65353, 65353, 65353, 65353, 65353, \n\t65353, 65353, 65353, 65353, 65354, 65354, 65354, 65354, \n\t65354, 65354, 65354, 65354, 65354, 65354, 65354, 65354, \n\t65354, 65354, 65355, 65355, 65355, 65355, 65355, 65355, \n\t65355, 65355, 65355, 65355, 65355, 65355, 65355, 65356, \n\t65356, 65356, 65356, 65356, 65356, 65356, 65356, 65356, \n\t65356, 65356, 65356, 65356, 65356, 65357, 65357, 65357, \n\t65357, 65357, 65357, 65357, 65357, 65357, 65357, 65357, \n\t65357, 65357, 65358, 65358, 65358, 65358, 65358, 65358, \n\t65358, 65358, 65358, 65358, 65358, 65358, 65358, 65358, \n\t65359, 65359, 65359, 65359, 65359, 65359, 65359, 65359, \n\t65359, 65359, 65359, 65359, 65359, 65360, 65360, 65360, \n\t65360, 65360, 65360, 65360, 65360, 65360, 65360, 65360, \n\t65360, 65360, 65360, 65361, 65361, 65361, 65361, 65361, \n\t65361, 65361, 65361, 65361, 65361, 65361, 65361, 65361, \n\t65361, 65362, 65362, 65362, 65362, 65362, 65362, 65362, \n\t65362, 65362, 65362, 65362, 65362, 65362, 65363, 65363, \n\t65363, 65363, 65363, 65363, 65363, 65363, 65363, 65363, \n\t65363, 65363, 65363, 65363, 65364, 65364, 65364, 65364, \n\t65364, 65364, 65364, 65364, 65364, 65364, 65364, 65364, \n\t65364, 65364, 65365, 65365, 65365, 65365, 65365, 65365, \n\t65365, 65365, 65365, 65365, 65365, 65365, 65365, 65365, \n\t65366, 65366, 65366, 65366, 65366, 65366, 65366, 65366, \n\t65366, 65366, 65366, 65366, 65366, 65366, 65367, 65367, \n\t65367, 65367, 65367, 65367, 65367, 65367, 65367, 65367, \n\t65367, 65367, 65367, 65367, 65368, 65368, 65368, 65368, \n\t65368, 65368, 65368, 65368, 65368, 65368, 65368, 65368, \n\t65368, 65368, 65369, 65369, 65369, 65369, 65369, 65369, \n\t65369, 65369, 65369, 65369, 65369, 65369, 65369, 65369, \n\t65370, 65370, 65370, 65370, 65370, 65370, 65370, 65370, \n\t65370, 65370, 65370, 65370, 65370, 65370, 65371, 65371, \n\t65371, 65371, 65371, 65371, 65371, 65371, 65371, 65371, \n\t65371, 65371, 65371, 65371, 65372, 65372, 65372, 65372, \n\t65372, 65372, 65372, 65372, 65372, 65372, 65372, 65372, \n\t65372, 65372, 65373, 65373, 65373, 65373, 65373, 65373, \n\t65373, 65373, 65373, 65373, 65373, 65373, 65373, 65373, \n\t65374, 65374, 65374, 65374, 65374, 65374, 65374, 65374, \n\t65374, 65374, 65374, 65374, 65374, 65374, 65375, 65375, \n\t65375, 65375, 65375, 65375, 65375, 65375, 65375, 65375, \n\t65375, 65375, 65375, 65375, 65375, 65376, 65376, 65376, \n\t65376, 65376, 65376, 65376, 65376, 65376, 65376, 65376, \n\t65376, 65376, 65376, 65377, 65377, 65377, 65377, 65377, \n\t65377, 65377, 65377, 65377, 65377, 65377, 65377, 65377, \n\t65377, 65378, 65378, 65378, 65378, 65378, 65378, 65378, \n\t65378, 65378, 65378, 65378, 65378, 65378, 65378, 65378, \n\t65379, 65379, 65379, 65379, 65379, 65379, 65379, 65379, \n\t65379, 65379, 65379, 65379, 65379, 65379, 65380, 65380, \n\t65380, 65380, 65380, 65380, 65380, 65380, 65380, 65380, \n\t65380, 65380, 65380, 65380, 65380, 65381, 65381, 65381, \n\t65381, 65381, 65381, 65381, 65381, 65381, 65381, 65381, \n\t65381, 65381, 65381, 65382, 65382, 65382, 65382, 65382, \n\t65382, 65382, 65382, 65382, 65382, 65382, 65382, 65382, \n\t65382, 65382, 65383, 65383, 65383, 65383, 65383, 65383, \n\t65383, 65383, 65383, 65383, 65383, 65383, 65383, 65383, \n\t65384, 65384, 65384, 65384, 65384, 65384, 65384, 65384, \n\t65384, 65384, 65384, 65384, 65384, 65384, 65384, 65385, \n\t65385, 65385, 65385, 65385, 65385, 65385, 65385, 65385, \n\t65385, 65385, 65385, 65385, 65385, 65385, 65386, 65386, \n\t65386, 65386, 65386, 65386, 65386, 65386, 65386, 65386, \n\t65386, 65386, 65386, 65386, 65386, 65387, 65387, 65387, \n\t65387, 65387, 65387, 65387, 65387, 65387, 65387, 65387, \n\t65387, 65387, 65387, 65387, 65388, 65388, 65388, 65388, \n\t65388, 65388, 65388, 65388, 65388, 65388, 65388, 65388, \n\t65388, 65388, 65389, 65389, 65389, 65389, 65389, 65389, \n\t65389, 65389, 65389, 65389, 65389, 65389, 65389, 65389, \n\t65389, 65390, 65390, 65390, 65390, 65390, 65390, 65390, \n\t65390, 65390, 65390, 65390, 65390, 65390, 65390, 65390, \n\t65391, 65391, 65391, 65391, 65391, 65391, 65391, 65391, \n\t65391, 65391, 65391, 65391, 65391, 65391, 65391, 65392, \n\t65392, 65392, 65392, 65392, 65392, 65392, 65392, 65392, \n\t65392, 65392, 65392, 65392, 65392, 65392, 65392, 65393, \n\t65393, 65393, 65393, 65393, 65393, 65393, 65393, 65393, \n\t65393, 65393, 65393, 65393, 65393, 65393, 65394, 65394, \n\t65394, 65394, 65394, 65394, 65394, 65394, 65394, 65394, \n\t65394, 65394, 65394, 65394, 65394, 65395, 65395, 65395, \n\t65395, 65395, 65395, 65395, 65395, 65395, 65395, 65395, \n\t65395, 65395, 65395, 65395, 65396, 65396, 65396, 65396, \n\t65396, 65396, 65396, 65396, 65396, 65396, 65396, 65396, \n\t65396, 65396, 65396, 65397, 65397, 65397, 65397, 65397, \n\t65397, 65397, 65397, 65397, 65397, 65397, 65397, 65397, \n\t65397, 65397, 65397, 65398, 65398, 65398, 65398, 65398, \n\t65398, 65398, 65398, 65398, 65398, 65398, 65398, 65398, \n\t65398, 65398, 65399, 65399, 65399, 65399, 65399, 65399, \n\t65399, 65399, 65399, 65399, 65399, 65399, 65399, 65399, \n\t65399, 65399, 65400, 65400, 65400, 65400, 65400, 65400, \n\t65400, 65400, 65400, 65400, 65400, 65400, 65400, 65400, \n\t65400, 65401, 65401, 65401, 65401, 65401, 65401, 65401, \n\t65401, 65401, 65401, 65401, 65401, 65401, 65401, 65401, \n\t65401, 65402, 65402, 65402, 65402, 65402, 65402, 65402, \n\t65402, 65402, 65402, 65402, 65402, 65402, 65402, 65402, \n\t65403, 65403, 65403, 65403, 65403, 65403, 65403, 65403, \n\t65403, 65403, 65403, 65403, 65403, 65403, 65403, 65403, \n\t65404, 65404, 65404, 65404, 65404, 65404, 65404, 65404, \n\t65404, 65404, 65404, 65404, 65404, 65404, 65404, 65404, \n\t65405, 65405, 65405, 65405, 65405, 65405, 65405, 65405, \n\t65405, 65405, 65405, 65405, 65405, 65405, 65405, 65405, \n\t65406, 65406, 65406, 65406, 65406, 65406, 65406, 65406, \n\t65406, 65406, 65406, 65406, 65406, 65406, 65406, 65406, \n\t65407, 65407, 65407, 65407, 65407, 65407, 65407, 65407, \n\t65407, 65407, 65407, 65407, 65407, 65407, 65407, 65407, \n\t65408, 65408, 65408, 65408, 65408, 65408, 65408, 65408, \n\t65408, 65408, 65408, 65408, 65408, 65408, 65408, 65408, \n\t65409, 65409, 65409, 65409, 65409, 65409, 65409, 65409, \n\t65409, 65409, 65409, 65409, 65409, 65409, 65409, 65409, \n\t65410, 65410, 65410, 65410, 65410, 65410, 65410, 65410, \n\t65410, 65410, 65410, 65410, 65410, 65410, 65410, 65410, \n\t65411, 65411, 65411, 65411, 65411, 65411, 65411, 65411, \n\t65411, 65411, 65411, 65411, 65411, 65411, 65411, 65411, \n\t65412, 65412, 65412, 65412, 65412, 65412, 65412, 65412, \n\t65412, 65412, 65412, 65412, 65412, 65412, 65412, 65412, \n\t65413, 65413, 65413, 65413, 65413, 65413, 65413, 65413, \n\t65413, 65413, 65413, 65413, 65413, 65413, 65413, 65413, \n\t65413, 65414, 65414, 65414, 65414, 65414, 65414, 65414, \n\t65414, 65414, 65414, 65414, 65414, 65414, 65414, 65414, \n\t65414, 65415, 65415, 65415, 65415, 65415, 65415, 65415, \n\t65415, 65415, 65415, 65415, 65415, 65415, 65415, 65415, \n\t65415, 65416, 65416, 65416, 65416, 65416, 65416, 65416, \n\t65416, 65416, 65416, 65416, 65416, 65416, 65416, 65416, \n\t65416, 65416, 65417, 65417, 65417, 65417, 65417, 65417, \n\t65417, 65417, 65417, 65417, 65417, 65417, 65417, 65417, \n\t65417, 65417, 65417, 65418, 65418, 65418, 65418, 65418, \n\t65418, 65418, 65418, 65418, 65418, 65418, 65418, 65418, \n\t65418, 65418, 65418, 65419, 65419, 65419, 65419, 65419, \n\t65419, 65419, 65419, 65419, 65419, 65419, 65419, 65419, \n\t65419, 65419, 65419, 65419, 65420, 65420, 65420, 65420, \n\t65420, 65420, 65420, 65420, 65420, 65420, 65420, 65420, \n\t65420, 65420, 65420, 65420, 65420, 65421, 65421, 65421, \n\t65421, 65421, 65421, 65421, 65421, 65421, 65421, 65421, \n\t65421, 65421, 65421, 65421, 65421, 65421, 65422, 65422, \n\t65422, 65422, 65422, 65422, 65422, 65422, 65422, 65422, \n\t65422, 65422, 65422, 65422, 65422, 65422, 65422, 65423, \n\t65423, 65423, 65423, 65423, 65423, 65423, 65423, 65423, \n\t65423, 65423, 65423, 65423, 65423, 65423, 65423, 65423, \n\t65424, 65424, 65424, 65424, 65424, 65424, 65424, 65424, \n\t65424, 65424, 65424, 65424, 65424, 65424, 65424, 65424, \n\t65424, 65425, 65425, 65425, 65425, 65425, 65425, 65425, \n\t65425, 65425, 65425, 65425, 65425, 65425, 65425, 65425, \n\t65425, 65425, 65426, 65426, 65426, 65426, 65426, 65426, \n\t65426, 65426, 65426, 65426, 65426, 65426, 65426, 65426, \n\t65426, 65426, 65426, 65427, 65427, 65427, 65427, 65427, \n\t65427, 65427, 65427, 65427, 65427, 65427, 65427, 65427, \n\t65427, 65427, 65427, 65427, 65427, 65428, 65428, 65428, \n\t65428, 65428, 65428, 65428, 65428, 65428, 65428, 65428, \n\t65428, 65428, 65428, 65428, 65428, 65428, 65429, 65429, \n\t65429, 65429, 65429, 65429, 65429, 65429, 65429, 65429, \n\t65429, 65429, 65429, 65429, 65429, 65429, 65429, 65429, \n\t65430, 65430, 65430, 65430, 65430, 65430, 65430, 65430, \n\t65430, 65430, 65430, 65430, 65430, 65430, 65430, 65430, \n\t65430, 65431, 65431, 65431, 65431, 65431, 65431, 65431, \n\t65431, 65431, 65431, 65431, 65431, 65431, 65431, 65431, \n\t65431, 65431, 65431, 65432, 65432, 65432, 65432, 65432, \n\t65432, 65432, 65432, 65432, 65432, 65432, 65432, 65432, \n\t65432, 65432, 65432, 65432, 65432, 65433, 65433, 65433, \n\t65433, 65433, 65433, 65433, 65433, 65433, 65433, 65433, \n\t65433, 65433, 65433, 65433, 65433, 65433, 65434, 65434, \n\t65434, 65434, 65434, 65434, 65434, 65434, 65434, 65434, \n\t65434, 65434, 65434, 65434, 65434, 65434, 65434, 65434, \n\t65435, 65435, 65435, 65435, 65435, 65435, 65435, 65435, \n\t65435, 65435, 65435, 65435, 65435, 65435, 65435, 65435, \n\t65435, 65435, 65436, 65436, 65436, 65436, 65436, 65436, \n\t65436, 65436, 65436, 65436, 65436, 65436, 65436, 65436, \n\t65436, 65436, 65436, 65436, 65437, 65437, 65437, 65437, \n\t65437, 65437, 65437, 65437, 65437, 65437, 65437, 65437, \n\t65437, 65437, 65437, 65437, 65437, 65437, 65437, 65438, \n\t65438, 65438, 65438, 65438, 65438, 65438, 65438, 65438, \n\t65438, 65438, 65438, 65438, 65438, 65438, 65438, 65438, \n\t65438, 65439, 65439, 65439, 65439, 65439, 65439, 65439, \n\t65439, 65439, 65439, 65439, 65439, 65439, 65439, 65439, \n\t65439, 65439, 65439, 65440, 65440, 65440, 65440, 65440, \n\t65440, 65440, 65440, 65440, 65440, 65440, 65440, 65440, \n\t65440, 65440, 65440, 65440, 65440, 65440, 65441, 65441, \n\t65441, 65441, 65441, 65441, 65441, 65441, 65441, 65441, \n\t65441, 65441, 65441, 65441, 65441, 65441, 65441, 65441, \n\t65442, 65442, 65442, 65442, 65442, 65442, 65442, 65442, \n\t65442, 65442, 65442, 65442, 65442, 65442, 65442, 65442, \n\t65442, 65442, 65442, 65443, 65443, 65443, 65443, 65443, \n\t65443, 65443, 65443, 65443, 65443, 65443, 65443, 65443, \n\t65443, 65443, 65443, 65443, 65443, 65443, 65444, 65444, \n\t65444, 65444, 65444, 65444, 65444, 65444, 65444, 65444, \n\t65444, 65444, 65444, 65444, 65444, 65444, 65444, 65444, \n\t65444, 65445, 65445, 65445, 65445, 65445, 65445, 65445, \n\t65445, 65445, 65445, 65445, 65445, 65445, 65445, 65445, \n\t65445, 65445, 65445, 65445, 65446, 65446, 65446, 65446, \n\t65446, 65446, 65446, 65446, 65446, 65446, 65446, 65446, \n\t65446, 65446, 65446, 65446, 65446, 65446, 65446, 65447, \n\t65447, 65447, 65447, 65447, 65447, 65447, 65447, 65447, \n\t65447, 65447, 65447, 65447, 65447, 65447, 65447, 65447, \n\t65447, 65447, 65448, 65448, 65448, 65448, 65448, 65448, \n\t65448, 65448, 65448, 65448, 65448, 65448, 65448, 65448, \n\t65448, 65448, 65448, 65448, 65448, 65449, 65449, 65449, \n\t65449, 65449, 65449, 65449, 65449, 65449, 65449, 65449, \n\t65449, 65449, 65449, 65449, 65449, 65449, 65449, 65449, \n\t65449, 65450, 65450, 65450, 65450, 65450, 65450, 65450, \n\t65450, 65450, 65450, 65450, 65450, 65450, 65450, 65450, \n\t65450, 65450, 65450, 65450, 65451, 65451, 65451, 65451, \n\t65451, 65451, 65451, 65451, 65451, 65451, 65451, 65451, \n\t65451, 65451, 65451, 65451, 65451, 65451, 65451, 65451, \n\t65452, 65452, 65452, 65452, 65452, 65452, 65452, 65452, \n\t65452, 65452, 65452, 65452, 65452, 65452, 65452, 65452, \n\t65452, 65452, 65452, 65452, 65453, 65453, 65453, 65453, \n\t65453, 65453, 65453, 65453, 65453, 65453, 65453, 65453, \n\t65453, 65453, 65453, 65453, 65453, 65453, 65453, 65454, \n\t65454, 65454, 65454, 65454, 65454, 65454, 65454, 65454, \n\t65454, 65454, 65454, 65454, 65454, 65454, 65454, 65454, \n\t65454, 65454, 65454, 65455, 65455, 65455, 65455, 65455, \n\t65455, 65455, 65455, 65455, 65455, 65455, 65455, 65455, \n\t65455, 65455, 65455, 65455, 65455, 65455, 65455, 65455, \n\t65456, 65456, 65456, 65456, 65456, 65456, 65456, 65456, \n\t65456, 65456, 65456, 65456, 65456, 65456, 65456, 65456, \n\t65456, 65456, 65456, 65456, 65457, 65457, 65457, 65457, \n\t65457, 65457, 65457, 65457, 65457, 65457, 65457, 65457, \n\t65457, 65457, 65457, 65457, 65457, 65457, 65457, 65457, \n\t65458, 65458, 65458, 65458, 65458, 65458, 65458, 65458, \n\t65458, 65458, 65458, 65458, 65458, 65458, 65458, 65458, \n\t65458, 65458, 65458, 65458, 65458, 65459, 65459, 65459, \n\t65459, 65459, 65459, 65459, 65459, 65459, 65459, 65459, \n\t65459, 65459, 65459, 65459, 65459, 65459, 65459, 65459, \n\t65459, 65460, 65460, 65460, 65460, 65460, 65460, 65460, \n\t65460, 65460, 65460, 65460, 65460, 65460, 65460, 65460, \n\t65460, 65460, 65460, 65460, 65460, 65460, 65461, 65461, \n\t65461, 65461, 65461, 65461, 65461, 65461, 65461, 65461, \n\t65461, 65461, 65461, 65461, 65461, 65461, 65461, 65461, \n\t65461, 65461, 65461, 65462, 65462, 65462, 65462, 65462, \n\t65462, 65462, 65462, 65462, 65462, 65462, 65462, 65462, \n\t65462, 65462, 65462, 65462, 65462, 65462, 65462, 65462, \n\t65463, 65463, 65463, 65463, 65463, 65463, 65463, 65463, \n\t65463, 65463, 65463, 65463, 65463, 65463, 65463, 65463, \n\t65463, 65463, 65463, 65463, 65463, 65464, 65464, 65464, \n\t65464, 65464, 65464, 65464, 65464, 65464, 65464, 65464, \n\t65464, 65464, 65464, 65464, 65464, 65464, 65464, 65464, \n\t65464, 65464, 65464, 65465, 65465, 65465, 65465, 65465, \n\t65465, 65465, 65465, 65465, 65465, 65465, 65465, 65465, \n\t65465, 65465, 65465, 65465, 65465, 65465, 65465, 65465, \n\t65466, 65466, 65466, 65466, 65466, 65466, 65466, 65466, \n\t65466, 65466, 65466, 65466, 65466, 65466, 65466, 65466, \n\t65466, 65466, 65466, 65466, 65466, 65466, 65467, 65467, \n\t65467, 65467, 65467, 65467, 65467, 65467, 65467, 65467, \n\t65467, 65467, 65467, 65467, 65467, 65467, 65467, 65467, \n\t65467, 65467, 65467, 65467, 65468, 65468, 65468, 65468, \n\t65468, 65468, 65468, 65468, 65468, 65468, 65468, 65468, \n\t65468, 65468, 65468, 65468, 65468, 65468, 65468, 65468, \n\t65468, 65468, 65469, 65469, 65469, 65469, 65469, 65469, \n\t65469, 65469, 65469, 65469, 65469, 65469, 65469, 65469, \n\t65469, 65469, 65469, 65469, 65469, 65469, 65469, 65469, \n\t65470, 65470, 65470, 65470, 65470, 65470, 65470, 65470, \n\t65470, 65470, 65470, 65470, 65470, 65470, 65470, 65470, \n\t65470, 65470, 65470, 65470, 65470, 65470, 65471, 65471, \n\t65471, 65471, 65471, 65471, 65471, 65471, 65471, 65471, \n\t65471, 65471, 65471, 65471, 65471, 65471, 65471, 65471, \n\t65471, 65471, 65471, 65471, 65472, 65472, 65472, 65472, \n\t65472, 65472, 65472, 65472, 65472, 65472, 65472, 65472, \n\t65472, 65472, 65472, 65472, 65472, 65472, 65472, 65472, \n\t65472, 65472, 65472, 65473, 65473, 65473, 65473, 65473, \n\t65473, 65473, 65473, 65473, 65473, 65473, 65473, 65473, \n\t65473, 65473, 65473, 65473, 65473, 65473, 65473, 65473, \n\t65473, 65473, 65474, 65474, 65474, 65474, 65474, 65474, \n\t65474, 65474, 65474, 65474, 65474, 65474, 65474, 65474, \n\t65474, 65474, 65474, 65474, 65474, 65474, 65474, 65474, \n\t65474, 65475, 65475, 65475, 65475, 65475, 65475, 65475, \n\t65475, 65475, 65475, 65475, 65475, 65475, 65475, 65475, \n\t65475, 65475, 65475, 65475, 65475, 65475, 65475, 65475, \n\t65476, 65476, 65476, 65476, 65476, 65476, 65476, 65476, \n\t65476, 65476, 65476, 65476, 65476, 65476, 65476, 65476, \n\t65476, 65476, 65476, 65476, 65476, 65476, 65476, 65477, \n\t65477, 65477, 65477, 65477, 65477, 65477, 65477, 65477, \n\t65477, 65477, 65477, 65477, 65477, 65477, 65477, 65477, \n\t65477, 65477, 65477, 65477, 65477, 65477, 65477, 65478, \n\t65478, 65478, 65478, 65478, 65478, 65478, 65478, 65478, \n\t65478, 65478, 65478, 65478, 65478, 65478, 65478, 65478, \n\t65478, 65478, 65478, 65478, 65478, 65478, 65478, 65479, \n\t65479, 65479, 65479, 65479, 65479, 65479, 65479, 65479, \n\t65479, 65479, 65479, 65479, 65479, 65479, 65479, 65479, \n\t65479, 65479, 65479, 65479, 65479, 65479, 65479, 65480, \n\t65480, 65480, 65480, 65480, 65480, 65480, 65480, 65480, \n\t65480, 65480, 65480, 65480, 65480, 65480, 65480, 65480, \n\t65480, 65480, 65480, 65480, 65480, 65480, 65480, 65481, \n\t65481, 65481, 65481, 65481, 65481, 65481, 65481, 65481, \n\t65481, 65481, 65481, 65481, 65481, 65481, 65481, 65481, \n\t65481, 65481, 65481, 65481, 65481, 65481, 65481, 65482, \n\t65482, 65482, 65482, 65482, 65482, 65482, 65482, 65482, \n\t65482, 65482, 65482, 65482, 65482, 65482, 65482, 65482, \n\t65482, 65482, 65482, 65482, 65482, 65482, 65482, 65482, \n\t65483, 65483, 65483, 65483, 65483, 65483, 65483, 65483, \n\t65483, 65483, 65483, 65483, 65483, 65483, 65483, 65483, \n\t65483, 65483, 65483, 65483, 65483, 65483, 65483, 65483, \n\t65483, 65484, 65484, 65484, 65484, 65484, 65484, 65484, \n\t65484, 65484, 65484, 65484, 65484, 65484, 65484, 65484, \n\t65484, 65484, 65484, 65484, 65484, 65484, 65484, 65484, \n\t65484, 65484, 65485, 65485, 65485, 65485, 65485, 65485, \n\t65485, 65485, 65485, 65485, 65485, 65485, 65485, 65485, \n\t65485, 65485, 65485, 65485, 65485, 65485, 65485, 65485, \n\t65485, 65485, 65485, 65486, 65486, 65486, 65486, 65486, \n\t65486, 65486, 65486, 65486, 65486, 65486, 65486, 65486, \n\t65486, 65486, 65486, 65486, 65486, 65486, 65486, 65486, \n\t65486, 65486, 65486, 65486, 65486, 65487, 65487, 65487, \n\t65487, 65487, 65487, 65487, 65487, 65487, 65487, 65487, \n\t65487, 65487, 65487, 65487, 65487, 65487, 65487, 65487, \n\t65487, 65487, 65487, 65487, 65487, 65487, 65487, 65488, \n\t65488, 65488, 65488, 65488, 65488, 65488, 65488, 65488, \n\t65488, 65488, 65488, 65488, 65488, 65488, 65488, 65488, \n\t65488, 65488, 65488, 65488, 65488, 65488, 65488, 65488, \n\t65488, 65489, 65489, 65489, 65489, 65489, 65489, 65489, \n\t65489, 65489, 65489, 65489, 65489, 65489, 65489, 65489, \n\t65489, 65489, 65489, 65489, 65489, 65489, 65489, 65489, \n\t65489, 65489, 65489, 65490, 65490, 65490, 65490, 65490, \n\t65490, 65490, 65490, 65490, 65490, 65490, 65490, 65490, \n\t65490, 65490, 65490, 65490, 65490, 65490, 65490, 65490, \n\t65490, 65490, 65490, 65490, 65490, 65490, 65491, 65491, \n\t65491, 65491, 65491, 65491, 65491, 65491, 65491, 65491, \n\t65491, 65491, 65491, 65491, 65491, 65491, 65491, 65491, \n\t65491, 65491, 65491, 65491, 65491, 65491, 65491, 65491, \n\t65491, 65492, 65492, 65492, 65492, 65492, 65492, 65492, \n\t65492, 65492, 65492, 65492, 65492, 65492, 65492, 65492, \n\t65492, 65492, 65492, 65492, 65492, 65492, 65492, 65492, \n\t65492, 65492, 65492, 65492, 65493, 65493, 65493, 65493, \n\t65493, 65493, 65493, 65493, 65493, 65493, 65493, 65493, \n\t65493, 65493, 65493, 65493, 65493, 65493, 65493, 65493, \n\t65493, 65493, 65493, 65493, 65493, 65493, 65493, 65493, \n\t65494, 65494, 65494, 65494, 65494, 65494, 65494, 65494, \n\t65494, 65494, 65494, 65494, 65494, 65494, 65494, 65494, \n\t65494, 65494, 65494, 65494, 65494, 65494, 65494, 65494, \n\t65494, 65494, 65494, 65494, 65495, 65495, 65495, 65495, \n\t65495, 65495, 65495, 65495, 65495, 65495, 65495, 65495, \n\t65495, 65495, 65495, 65495, 65495, 65495, 65495, 65495, \n\t65495, 65495, 65495, 65495, 65495, 65495, 65495, 65495, \n\t65496, 65496, 65496, 65496, 65496, 65496, 65496, 65496, \n\t65496, 65496, 65496, 65496, 65496, 65496, 65496, 65496, \n\t65496, 65496, 65496, 65496, 65496, 65496, 65496, 65496, \n\t65496, 65496, 65496, 65496, 65496, 65497, 65497, 65497, \n\t65497, 65497, 65497, 65497, 65497, 65497, 65497, 65497, \n\t65497, 65497, 65497, 65497, 65497, 65497, 65497, 65497, \n\t65497, 65497, 65497, 65497, 65497, 65497, 65497, 65497, \n\t65497, 65497, 65498, 65498, 65498, 65498, 65498, 65498, \n\t65498, 65498, 65498, 65498, 65498, 65498, 65498, 65498, \n\t65498, 65498, 65498, 65498, 65498, 65498, 65498, 65498, \n\t65498, 65498, 65498, 65498, 65498, 65498, 65498, 65499, \n\t65499, 65499, 65499, 65499, 65499, 65499, 65499, 65499, \n\t65499, 65499, 65499, 65499, 65499, 65499, 65499, 65499, \n\t65499, 65499, 65499, 65499, 65499, 65499, 65499, 65499, \n\t65499, 65499, 65499, 65499, 65499, 65500, 65500, 65500, \n\t65500, 65500, 65500, 65500, 65500, 65500, 65500, 65500, \n\t65500, 65500, 65500, 65500, 65500, 65500, 65500, 65500, \n\t65500, 65500, 65500, 65500, 65500, 65500, 65500, 65500, \n\t65500, 65500, 65500, 65501, 65501, 65501, 65501, 65501, \n\t65501, 65501, 65501, 65501, 65501, 65501, 65501, 65501, \n\t65501, 65501, 65501, 65501, 65501, 65501, 65501, 65501, \n\t65501, 65501, 65501, 65501, 65501, 65501, 65501, 65501, \n\t65501, 65501, 65502, 65502, 65502, 65502, 65502, 65502, \n\t65502, 65502, 65502, 65502, 65502, 65502, 65502, 65502, \n\t65502, 65502, 65502, 65502, 65502, 65502, 65502, 65502, \n\t65502, 65502, 65502, 65502, 65502, 65502, 65502, 65502, \n\t65502, 65503, 65503, 65503, 65503, 65503, 65503, 65503, \n\t65503, 65503, 65503, 65503, 65503, 65503, 65503, 65503, \n\t65503, 65503, 65503, 65503, 65503, 65503, 65503, 65503, \n\t65503, 65503, 65503, 65503, 65503, 65503, 65503, 65503, \n\t65504, 65504, 65504, 65504, 65504, 65504, 65504, 65504, \n\t65504, 65504, 65504, 65504, 65504, 65504, 65504, 65504, \n\t65504, 65504, 65504, 65504, 65504, 65504, 65504, 65504, \n\t65504, 65504, 65504, 65504, 65504, 65504, 65504, 65504, \n\t65505, 65505, 65505, 65505, 65505, 65505, 65505, 65505, \n\t65505, 65505, 65505, 65505, 65505, 65505, 65505, 65505, \n\t65505, 65505, 65505, 65505, 65505, 65505, 65505, 65505, \n\t65505, 65505, 65505, 65505, 65505, 65505, 65505, 65505, \n\t65505, 65506, 65506, 65506, 65506, 65506, 65506, 65506, \n\t65506, 65506, 65506, 65506, 65506, 65506, 65506, 65506, \n\t65506, 65506, 65506, 65506, 65506, 65506, 65506, 65506, \n\t65506, 65506, 65506, 65506, 65506, 65506, 65506, 65506, \n\t65506, 65506, 65507, 65507, 65507, 65507, 65507, 65507, \n\t65507, 65507, 65507, 65507, 65507, 65507, 65507, 65507, \n\t65507, 65507, 65507, 65507, 65507, 65507, 65507, 65507, \n\t65507, 65507, 65507, 65507, 65507, 65507, 65507, 65507, \n\t65507, 65507, 65507, 65508, 65508, 65508, 65508, 65508, \n\t65508, 65508, 65508, 65508, 65508, 65508, 65508, 65508, \n\t65508, 65508, 65508, 65508, 65508, 65508, 65508, 65508, \n\t65508, 65508, 65508, 65508, 65508, 65508, 65508, 65508, \n\t65508, 65508, 65508, 65508, 65508, 65508, 65509, 65509, \n\t65509, 65509, 65509, 65509, 65509, 65509, 65509, 65509, \n\t65509, 65509, 65509, 65509, 65509, 65509, 65509, 65509, \n\t65509, 65509, 65509, 65509, 65509, 65509, 65509, 65509, \n\t65509, 65509, 65509, 65509, 65509, 65509, 65509, 65509, \n\t65510, 65510, 65510, 65510, 65510, 65510, 65510, 65510, \n\t65510, 65510, 65510, 65510, 65510, 65510, 65510, 65510, \n\t65510, 65510, 65510, 65510, 65510, 65510, 65510, 65510, \n\t65510, 65510, 65510, 65510, 65510, 65510, 65510, 65510, \n\t65510, 65510, 65510, 65510, 65511, 65511, 65511, 65511, \n\t65511, 65511, 65511, 65511, 65511, 65511, 65511, 65511, \n\t65511, 65511, 65511, 65511, 65511, 65511, 65511, 65511, \n\t65511, 65511, 65511, 65511, 65511, 65511, 65511, 65511, \n\t65511, 65511, 65511, 65511, 65511, 65511, 65511, 65511, \n\t65512, 65512, 65512, 65512, 65512, 65512, 65512, 65512, \n\t65512, 65512, 65512, 65512, 65512, 65512, 65512, 65512, \n\t65512, 65512, 65512, 65512, 65512, 65512, 65512, 65512, \n\t65512, 65512, 65512, 65512, 65512, 65512, 65512, 65512, \n\t65512, 65512, 65512, 65512, 65512, 65513, 65513, 65513, \n\t65513, 65513, 65513, 65513, 65513, 65513, 65513, 65513, \n\t65513, 65513, 65513, 65513, 65513, 65513, 65513, 65513, \n\t65513, 65513, 65513, 65513, 65513, 65513, 65513, 65513, \n\t65513, 65513, 65513, 65513, 65513, 65513, 65513, 65513, \n\t65513, 65513, 65513, 65514, 65514, 65514, 65514, 65514, \n\t65514, 65514, 65514, 65514, 65514, 65514, 65514, 65514, \n\t65514, 65514, 65514, 65514, 65514, 65514, 65514, 65514, \n\t65514, 65514, 65514, 65514, 65514, 65514, 65514, 65514, \n\t65514, 65514, 65514, 65514, 65514, 65514, 65514, 65514, \n\t65514, 65515, 65515, 65515, 65515, 65515, 65515, 65515, \n\t65515, 65515, 65515, 65515, 65515, 65515, 65515, 65515, \n\t65515, 65515, 65515, 65515, 65515, 65515, 65515, 65515, \n\t65515, 65515, 65515, 65515, 65515, 65515, 65515, 65515, \n\t65515, 65515, 65515, 65515, 65515, 65515, 65515, 65515, \n\t65515, 65516, 65516, 65516, 65516, 65516, 65516, 65516, \n\t65516, 65516, 65516, 65516, 65516, 65516, 65516, 65516, \n\t65516, 65516, 65516, 65516, 65516, 65516, 65516, 65516, \n\t65516, 65516, 65516, 65516, 65516, 65516, 65516, 65516, \n\t65516, 65516, 65516, 65516, 65516, 65516, 65516, 65516, \n\t65516, 65517, 65517, 65517, 65517, 65517, 65517, 65517, \n\t65517, 65517, 65517, 65517, 65517, 65517, 65517, 65517, \n\t65517, 65517, 65517, 65517, 65517, 65517, 65517, 65517, \n\t65517, 65517, 65517, 65517, 65517, 65517, 65517, 65517, \n\t65517, 65517, 65517, 65517, 65517, 65517, 65517, 65517, \n\t65517, 65517, 65517, 65518, 65518, 65518, 65518, 65518, \n\t65518, 65518, 65518, 65518, 65518, 65518, 65518, 65518, \n\t65518, 65518, 65518, 65518, 65518, 65518, 65518, 65518, \n\t65518, 65518, 65518, 65518, 65518, 65518, 65518, 65518, \n\t65518, 65518, 65518, 65518, 65518, 65518, 65518, 65518, \n\t65518, 65518, 65518, 65518, 65518, 65518, 65519, 65519, \n\t65519, 65519, 65519, 65519, 65519, 65519, 65519, 65519, \n\t65519, 65519, 65519, 65519, 65519, 65519, 65519, 65519, \n\t65519, 65519, 65519, 65519, 65519, 65519, 65519, 65519, \n\t65519, 65519, 65519, 65519, 65519, 65519, 65519, 65519, \n\t65519, 65519, 65519, 65519, 65519, 65519, 65519, 65519, \n\t65519, 65519, 65520, 65520, 65520, 65520, 65520, 65520, \n\t65520, 65520, 65520, 65520, 65520, 65520, 65520, 65520, \n\t65520, 65520, 65520, 65520, 65520, 65520, 65520, 65520, \n\t65520, 65520, 65520, 65520, 65520, 65520, 65520, 65520, \n\t65520, 65520, 65520, 65520, 65520, 65520, 65520, 65520, \n\t65520, 65520, 65520, 65520, 65520, 65520, 65520, 65521, \n\t65521, 65521, 65521, 65521, 65521, 65521, 65521, 65521, \n\t65521, 65521, 65521, 65521, 65521, 65521, 65521, 65521, \n\t65521, 65521, 65521, 65521, 65521, 65521, 65521, 65521, \n\t65521, 65521, 65521, 65521, 65521, 65521, 65521, 65521, \n\t65521, 65521, 65521, 65521, 65521, 65521, 65521, 65521, \n\t65521, 65521, 65521, 65521, 65521, 65521, 65522, 65522, \n\t65522, 65522, 65522, 65522, 65522, 65522, 65522, 65522, \n\t65522, 65522, 65522, 65522, 65522, 65522, 65522, 65522, \n\t65522, 65522, 65522, 65522, 65522, 65522, 65522, 65522, \n\t65522, 65522, 65522, 65522, 65522, 65522, 65522, 65522, \n\t65522, 65522, 65522, 65522, 65522, 65522, 65522, 65522, \n\t65522, 65522, 65522, 65522, 65522, 65522, 65523, 65523, \n\t65523, 65523, 65523, 65523, 65523, 65523, 65523, 65523, \n\t65523, 65523, 65523, 65523, 65523, 65523, 65523, 65523, \n\t65523, 65523, 65523, 65523, 65523, 65523, 65523, 65523, \n\t65523, 65523, 65523, 65523, 65523, 65523, 65523, 65523, \n\t65523, 65523, 65523, 65523, 65523, 65523, 65523, 65523, \n\t65523, 65523, 65523, 65523, 65523, 65523, 65523, 65523, \n\t65524, 65524, 65524, 65524, 65524, 65524, 65524, 65524, \n\t65524, 65524, 65524, 65524, 65524, 65524, 65524, 65524, \n\t65524, 65524, 65524, 65524, 65524, 65524, 65524, 65524, \n\t65524, 65524, 65524, 65524, 65524, 65524, 65524, 65524, \n\t65524, 65524, 65524, 65524, 65524, 65524, 65524, 65524, \n\t65524, 65524, 65524, 65524, 65524, 65524, 65524, 65524, \n\t65524, 65524, 65524, 65524, 65525, 65525, 65525, 65525, \n\t65525, 65525, 65525, 65525, 65525, 65525, 65525, 65525, \n\t65525, 65525, 65525, 65525, 65525, 65525, 65525, 65525, \n\t65525, 65525, 65525, 65525, 65525, 65525, 65525, 65525, \n\t65525, 65525, 65525, 65525, 65525, 65525, 65525, 65525, \n\t65525, 65525, 65525, 65525, 65525, 65525, 65525, 65525, \n\t65525, 65525, 65525, 65525, 65525, 65525, 65525, 65525, \n\t65525, 65525, 65525, 65526, 65526, 65526, 65526, 65526, \n\t65526, 65526, 65526, 65526, 65526, 65526, 65526, 65526, \n\t65526, 65526, 65526, 65526, 65526, 65526, 65526, 65526, \n\t65526, 65526, 65526, 65526, 65526, 65526, 65526, 65526, \n\t65526, 65526, 65526, 65526, 65526, 65526, 65526, 65526, \n\t65526, 65526, 65526, 65526, 65526, 65526, 65526, 65526, \n\t65526, 65526, 65526, 65526, 65526, 65526, 65526, 65526, \n\t65526, 65526, 65526, 65526, 65527, 65527, 65527, 65527, \n\t65527, 65527, 65527, 65527, 65527, 65527, 65527, 65527, \n\t65527, 65527, 65527, 65527, 65527, 65527, 65527, 65527, \n\t65527, 65527, 65527, 65527, 65527, 65527, 65527, 65527, \n\t65527, 65527, 65527, 65527, 65527, 65527, 65527, 65527, \n\t65527, 65527, 65527, 65527, 65527, 65527, 65527, 65527, \n\t65527, 65527, 65527, 65527, 65527, 65527, 65527, 65527, \n\t65527, 65527, 65527, 65527, 65527, 65527, 65527, 65527, \n\t65527, 65528, 65528, 65528, 65528, 65528, 65528, 65528, \n\t65528, 65528, 65528, 65528, 65528, 65528, 65528, 65528, \n\t65528, 65528, 65528, 65528, 65528, 65528, 65528, 65528, \n\t65528, 65528, 65528, 65528, 65528, 65528, 65528, 65528, \n\t65528, 65528, 65528, 65528, 65528, 65528, 65528, 65528, \n\t65528, 65528, 65528, 65528, 65528, 65528, 65528, 65528, \n\t65528, 65528, 65528, 65528, 65528, 65528, 65528, 65528, \n\t65528, 65528, 65528, 65528, 65528, 65528, 65528, 65528, \n\t65528, 65529, 65529, 65529, 65529, 65529, 65529, 65529, \n\t65529, 65529, 65529, 65529, 65529, 65529, 65529, 65529, \n\t65529, 65529, 65529, 65529, 65529, 65529, 65529, 65529, \n\t65529, 65529, 65529, 65529, 65529, 65529, 65529, 65529, \n\t65529, 65529, 65529, 65529, 65529, 65529, 65529, 65529, \n\t65529, 65529, 65529, 65529, 65529, 65529, 65529, 65529, \n\t65529, 65529, 65529, 65529, 65529, 65529, 65529, 65529, \n\t65529, 65529, 65529, 65529, 65529, 65529, 65529, 65529, \n\t65529, 65529, 65529, 65529, 65529, 65530, 65530, 65530, \n\t65530, 65530, 65530, 65530, 65530, 65530, 65530, 65530, \n\t65530, 65530, 65530, 65530, 65530, 65530, 65530, 65530, \n\t65530, 65530, 65530, 65530, 65530, 65530, 65530, 65530, \n\t65530, 65530, 65530, 65530, 65530, 65530, 65530, 65530, \n\t65530, 65530, 65530, 65530, 65530, 65530, 65530, 65530, \n\t65530, 65530, 65530, 65530, 65530, 65530, 65530, 65530, \n\t65530, 65530, 65530, 65530, 65530, 65530, 65530, 65530, \n\t65530, 65530, 65530, 65530, 65530, 65530, 65530, 65530, \n\t65530, 65530, 65530, 65530, 65530, 65530, 65530, 65531, \n\t65531, 65531, 65531, 65531, 65531, 65531, 65531, 65531, \n\t65531, 65531, 65531, 65531, 65531, 65531, 65531, 65531, \n\t65531, 65531, 65531, 65531, 65531, 65531, 65531, 65531, \n\t65531, 65531, 65531, 65531, 65531, 65531, 65531, 65531, \n\t65531, 65531, 65531, 65531, 65531, 65531, 65531, 65531, \n\t65531, 65531, 65531, 65531, 65531, 65531, 65531, 65531, \n\t65531, 65531, 65531, 65531, 65531, 65531, 65531, 65531, \n\t65531, 65531, 65531, 65531, 65531, 65531, 65531, 65531, \n\t65531, 65531, 65531, 65531, 65531, 65531, 65531, 65531, \n\t65531, 65531, 65531, 65531, 65531, 65531, 65531, 65531, \n\t65532, 65532, 65532, 65532, 65532, 65532, 65532, 65532, \n\t65532, 65532, 65532, 65532, 65532, 65532, 65532, 65532, \n\t65532, 65532, 65532, 65532, 65532, 65532, 65532, 65532, \n\t65532, 65532, 65532, 65532, 65532, 65532, 65532, 65532, \n\t65532, 65532, 65532, 65532, 65532, 65532, 65532, 65532, \n\t65532, 65532, 65532, 65532, 65532, 65532, 65532, 65532, \n\t65532, 65532, 65532, 65532, 65532, 65532, 65532, 65532, \n\t65532, 65532, 65532, 65532, 65532, 65532, 65532, 65532, \n\t65532, 65532, 65532, 65532, 65532, 65532, 65532, 65532, \n\t65532, 65532, 65532, 65532, 65532, 65532, 65532, 65532, \n\t65532, 65532, 65532, 65532, 65532, 65532, 65532, 65532, \n\t65532, 65532, 65532, 65533, 65533, 65533, 65533, 65533, \n\t65533, 65533, 65533, 65533, 65533, 65533, 65533, 65533, \n\t65533, 65533, 65533, 65533, 65533, 65533, 65533, 65533, \n\t65533, 65533, 65533, 65533, 65533, 65533, 65533, 65533, \n\t65533, 65533, 65533, 65533, 65533, 65533, 65533, 65533, \n\t65533, 65533, 65533, 65533, 65533, 65533, 65533, 65533, \n\t65533, 65533, 65533, 65533, 65533, 65533, 65533, 65533, \n\t65533, 65533, 65533, 65533, 65533, 65533, 65533, 65533, \n\t65533, 65533, 65533, 65533, 65533, 65533, 65533, 65533, \n\t65533, 65533, 65533, 65533, 65533, 65533, 65533, 65533, \n\t65533, 65533, 65533, 65533, 65533, 65533, 65533, 65533, \n\t65533, 65533, 65533, 65533, 65533, 65533, 65533, 65533, \n\t65533, 65533, 65533, 65533, 65533, 65533, 65533, 65533, \n\t65533, 65533, 65533, 65533, 65534, 65534, 65534, 65534, \n\t65534, 65534, 65534, 65534, 65534, 65534, 65534, 65534, \n\t65534, 65534, 65534, 65534, 65534, 65534, 65534, 65534, \n\t65534, 65534, 65534, 65534, 65534, 65534, 65534, 65534, \n\t65534, 65534, 65534, 65534, 65534, 65534, 65534, 65534, \n\t65534, 65534, 65534, 65534, 65534, 65534, 65534, 65534, \n\t65534, 65534, 65534, 65534, 65534, 65534, 65534, 65534, \n\t65534, 65534, 65534, 65534, 65534, 65534, 65534, 65534, \n\t65534, 65534, 65534, 65534, 65534, 65534, 65534, 65534, \n\t65534, 65534, 65534, 65534, 65534, 65534, 65534, 65534, \n\t65534, 65534, 65534, 65534, 65534, 65534, 65534, 65534, \n\t65534, 65534, 65534, 65534, 65534, 65534, 65534, 65534, \n\t65534, 65534, 65534, 65534, 65534, 65534, 65534, 65534, \n\t65534, 65534, 65534, 65534, 65534, 65534, 65534, 65534, \n\t65534, 65534, 65534, 65534, 65534, 65534, 65534, 65534, \n\t65534, 65534, 65534, 65534, 65534, 65534, 65534, 65534, \n\t65534, 65534, 65534, 65534, 65534, 65535, 65535, 65535, \n\t65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, \n\t65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, \n\t65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, \n\t65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, \n\t65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, \n\t65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, \n\t65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, \n\t65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, \n\t65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, \n\t65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, \n\t65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, \n\t65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, \n\t65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, \n\t65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, \n\t65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, \n\t65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, \n\t65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, \n\t65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, \n\t65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, \n\t65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, \n\t65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, \n\t65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, \n\t65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, \n\t};\n\n#endif\n"
  },
  {
    "path": "include/fixmath/fixmath.h",
    "content": "#ifndef __fixmath_fixmath_h__\n#define __fixmath_fixmath_h__\n\n#ifdef __cplusplus\nextern \"C\"\n{\n#endif\n\n/*!\n\t\\file fixmath.h\n\t\\brief Functions to perform fast accurate fixed-point math operations.\n*/\n\n#include \"uint32.h\"\n#include \"int64.h\"\n#include \"fract32.h\"\n#include \"fix16.h\"\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif\n"
  },
  {
    "path": "include/fixmath/fract32.h",
    "content": "#ifndef __fixmath_fract32_h__\n#define __fixmath_fract32_h__\n\n#ifdef __cplusplus\nextern \"C\"\n{\n#endif\n\n#include <stdint.h>\n\ntypedef uint32_t fract32_t;\n\n/*! Creates a fraction using unsigned integers.\n\t\\param inNumerator the unsigned integer numerator\n\t\\param inDenominator the unsigned integer denominator\n\t\\return a fraction using the given numerator and denominator\n*/\nextern fract32_t fract32_create(uint32_t inNumerator, uint32_t inDenominator);\n\n/*! Inverts the given fraction, swapping the numerator and the denominator.\n*/\nextern fract32_t fract32_invert(fract32_t inFract);\n\n#ifndef FIXMATH_NO_64BIT\n/*! Performs unsigned saturated (overflow-protected) multiplication with the two given fractions and returns the result as an unsigned integer.\n*/\nextern uint32_t  fract32_usmul(uint32_t inVal, fract32_t inFract);\n\n/*! Performs saturated (overflow-protected) multiplication with the two given fractions and returns the result as a signed integer.\n*/\nextern int32_t   fract32_smul(int32_t inVal, fract32_t inFract);\n#endif\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif\n"
  },
  {
    "path": "include/fixmath/int64.h",
    "content": "#ifndef __fixmath_int64_h__\n#define __fixmath_int64_h__\n\n#ifdef __cplusplus\nextern \"C\"\n{\n#endif\n\n#ifndef FIXMATH_NO_64BIT\nstatic inline  int64_t int64_const(int32_t hi, uint32_t lo) { return (((int64_t)hi << 32) | lo); }\nstatic inline  int64_t int64_from_int32(int32_t x) { return (int64_t)x; }\nstatic inline  int32_t int64_hi(int64_t x) { return (x >> 32); }\nstatic inline uint32_t int64_lo(int64_t x) { return (x & ((1ULL << 32) - 1)); }\n\nstatic inline int64_t int64_add(int64_t x, int64_t y)   { return (x + y);  }\nstatic inline int64_t int64_neg(int64_t x)              { return (-x);     }\nstatic inline int64_t int64_sub(int64_t x, int64_t y)   { return (x - y);  }\nstatic inline int64_t int64_shift(int64_t x, int8_t y)  { return (y < 0 ? (x >> -y) : (x << y)); }\n\nstatic inline int64_t int64_mul_i32_i32(int32_t x, int32_t y) { return (x * y);  }\nstatic inline int64_t int64_mul_i64_i32(int64_t x, int32_t y) { return (x * y);  }\n\nstatic inline int64_t int64_div_i64_i32(int64_t x, int32_t y) { return (x / y);  }\n\nstatic inline int int64_cmp_eq(int64_t x, int64_t y) { return (x == y); }\nstatic inline int int64_cmp_ne(int64_t x, int64_t y) { return (x != y); }\nstatic inline int int64_cmp_gt(int64_t x, int64_t y) { return (x >  y); }\nstatic inline int int64_cmp_ge(int64_t x, int64_t y) { return (x >= y); }\nstatic inline int int64_cmp_lt(int64_t x, int64_t y) { return (x <  y); }\nstatic inline int int64_cmp_le(int64_t x, int64_t y) { return (x <= y); }\n#else\n\ntypedef struct {\n\t int32_t hi;\n\tuint32_t lo;\n} __int64_t;\n\nstatic inline __int64_t int64_const(int32_t hi, uint32_t lo) { return (__int64_t){ hi, lo }; }\nstatic inline __int64_t int64_from_int32(int32_t x) { return (__int64_t){ (x < 0 ? -1 : 0), x }; }\nstatic inline   int32_t int64_hi(__int64_t x) { return x.hi; }\nstatic inline  uint32_t int64_lo(__int64_t x) { return x.lo; }\n\nstatic inline int int64_cmp_eq(__int64_t x, __int64_t y) { return ((x.hi == y.hi) && (x.lo == y.lo)); }\nstatic inline int int64_cmp_ne(__int64_t x, __int64_t y) { return ((x.hi != y.hi) || (x.lo != y.lo)); }\nstatic inline int int64_cmp_gt(__int64_t x, __int64_t y) { return ((x.hi > y.hi) || ((x.hi == y.hi) && (x.lo >  y.lo))); }\nstatic inline int int64_cmp_ge(__int64_t x, __int64_t y) { return ((x.hi > y.hi) || ((x.hi == y.hi) && (x.lo >= y.lo))); }\nstatic inline int int64_cmp_lt(__int64_t x, __int64_t y) { return ((x.hi < y.hi) || ((x.hi == y.hi) && (x.lo <  y.lo))); }\nstatic inline int int64_cmp_le(__int64_t x, __int64_t y) { return ((x.hi < y.hi) || ((x.hi == y.hi) && (x.lo <= y.lo))); }\n\nstatic inline __int64_t int64_add(__int64_t x, __int64_t y) {\n\t__int64_t ret;\n\tret.hi = x.hi + y.hi;\n\tret.lo = x.lo + y.lo;\n\tif((ret.lo < x.lo) || (ret.hi < y.hi))\n\t\tret.hi++;\n\treturn ret;\n}\n\nstatic inline __int64_t int64_neg(__int64_t x) {\n\t__int64_t ret;\n\tret.hi = ~x.hi;\n\tret.lo = ~x.lo + 1;\n\tif(ret.lo == 0)\n\t\tret.hi++;\n\treturn ret;\n}\n\nstatic inline __int64_t int64_sub(__int64_t x, __int64_t y) {\n\treturn int64_add(x, int64_neg(y));\n}\n\nstatic inline __int64_t int64_shift(__int64_t x, int8_t y) {\n\t__int64_t ret;\n\tif(y > 0) {\n\t\tif(y >= 32)\n\t\t\treturn (__int64_t){ 0, 0 };\n\t\tret.hi = (x.hi << y) | (x.lo >> (32 - y));\n\t\tret.lo = (x.lo << y);\n\t} else {\n\t\ty = -y;\n\t\tif(y >= 32)\n\t\t\treturn (__int64_t){ 0, 0 };\n\t\tret.lo = (x.lo >> y) | (x.hi << (32 - y));\n\t\tret.hi = (x.hi >> y);\n\t}\n\treturn ret;\n}\n\nstatic inline __int64_t int64_mul_i32_i32(int32_t x, int32_t y) {\n\t int16_t hi[2] = { (x >> 16), (y >> 16) };\n\tuint16_t lo[2] = { (x & 0xFFFF), (y & 0xFFFF) };\n\n\t int32_t r_hi = hi[0] * hi[1];\n\t int32_t r_md = (hi[0] * lo[1]) + (hi[1] * lo[0]);\n\tuint32_t r_lo = lo[0] * lo[1];\n\n\tr_hi += (r_md >> 16);\n\tr_lo += (r_md << 16);\n\n\treturn (__int64_t){ r_hi, r_lo };\n}\n\nstatic inline __int64_t int64_mul_i64_i32(__int64_t x, int32_t y) {\n\tint neg = ((x.hi ^ y) < 0);\n\tif(x.hi < 0)\n\t\tx = int64_neg(x);\n\tif(y < 0)\n\t\ty = -y;\n\n\tuint32_t _x[4] = { (x.hi >> 16), (x.hi & 0xFFFF), (x.lo >> 16), (x.lo & 0xFFFF) };\n\tuint32_t _y[2] = { (y >> 16), (y & 0xFFFF) };\n\n\tuint32_t r[4];\n\tr[0] = (_x[0] * _y[0]);\n\tr[1] = (_x[1] * _y[0]) + (_x[0] * _y[1]);\n\tr[2] = (_x[1] * _y[1]) + (_x[2] * _y[0]);\n\tr[3] = (_x[2] * _y[0]) + (_x[1] * _y[1]);\n\n\t__int64_t ret;\n\tret.lo = r[0] + (r[1] << 16);\n\tret.hi = (r[3] << 16) + r[2] + (r[1] >> 16);\n\treturn (neg ? int64_neg(ret) : ret);\n}\n\nstatic inline __int64_t int64_div_i64_i32(__int64_t x, int32_t y) {\n\tint neg = ((x.hi ^ y) < 0);\n\tif(x.hi < 0)\n\t\tx = int64_neg(x);\n\tif(y < 0)\n\t\ty = -y;\n\n\t__int64_t ret = { (x.hi / y) , (x.lo / y) };\n\tx.hi = x.hi % y;\n\tx.lo = x.lo % y;\n\n\t__int64_t _y = int64_from_int32(y);\n\n\t__int64_t i;\n\tfor(i = int64_from_int32(1); int64_cmp_lt(_y, x); _y = int64_shift(_y, 1), i = int64_shift(i, 1));\n\n\twhile(x.hi) {\n\t\t_y = int64_shift(_y, -1);\n\t\t i = int64_shift(i, -1);\n\t\tif(int64_cmp_ge(x, _y)) {\n\t\t\tx = int64_sub(x, _y);\n\t\t\tret = int64_add(ret, i);\n\t\t}\n\t}\n\n\tret = int64_add(ret, int64_from_int32(x.lo / y));\n\treturn (neg ? int64_neg(ret) : ret);\n}\n\n#define int64_t __int64_t\n\n#endif\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif\n"
  },
  {
    "path": "include/fixmath/uint32.h",
    "content": "#ifndef __fixmath_uint32_h__\n#define __fixmath_uint32_h__\n\n#ifdef __cplusplus\nextern \"C\"\n{\n#endif\n\n#include <stdint.h>\n\n/*! Performs an unsigned log-base2 on the specified unsigned integer and returns the result.\n*/\nextern uint32_t uint32_log2(uint32_t inVal);\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif\n"
  },
  {
    "path": "include/mini_std/ctype.h",
    "content": "#ifndef _DEIDARA_CTYPE\n#define _DEIDARA_CTYPE\n\n#ifdef __cplusplus\n#if !defined(restrict)\n#define restrict\n#endif\nextern \"C\" {\n#endif\n\n#define _U 0x01   // upper\n#define _L 0x02   // lower\n#define _D 0x04   // digit\n#define _C 0x08   // cntrl\n#define _P 0x10   // punct\n#define _S 0x20   // white space (space/lf/tab)\n#define _X 0x40   // hex digit\n#define _SP 0x80  // hard space (0x20)\n#define _HT 0x100 // horizontal tab (0x09)\n\nextern const unsigned short _ctype[];\nunsigned char __toupper(unsigned char c);\nunsigned char __tolower(unsigned char c);\n\n#define __ismask(x) (_ctype[(int)(unsigned char)(x)])\n\n#define isalnum(c) ((__ismask(c) & (_U | _L | _D)) != 0)\n#define isalpha(c) ((__ismask(c) & (_U | _L)) != 0)\n#define isblank(c) ((__ismask(c) & (_HT | _SP)) != 0)\n#define iscntrl(c) ((__ismask(c) & (_C)) != 0)\n#define isdigit(c) ((__ismask(c) & (_D)) != 0)\n#define isgraph(c) ((__ismask(c) & (_P | _U | _L | _D)) != 0)\n#define islower(c) ((__ismask(c) & (_L)) != 0)\n#define isprint(c) ((__ismask(c) & (_P | _U | _L | _D | _SP)) != 0)\n#define ispunct(c) ((__ismask(c) & (_P)) != 0)\n#define isspace(c) ((__ismask(c) & (_S)) != 0)\n#define isupper(c) ((__ismask(c) & (_U)) != 0)\n#define isxdigit(c) ((__ismask(c) & (_D | _X)) != 0)\n#define isascii(c) (((unsigned char)(c)) <= 0x7f)\n#define tolower(c) __tolower(c)\n#define toupper(c) __toupper(c)\n\n#ifdef __cplusplus\n}\n#undef restrict\n#endif\n\n#endif\n"
  },
  {
    "path": "include/mini_std/errno.h",
    "content": "/**\n * This file has no copyright assigned and is placed in the Public Domain.\n * This file is part of the mingw-w64 runtime package.\n * No warranty is given; refer to the file DISCLAIMER.PD within this package.\n */\n#ifndef _INC_ERRNO\n#define _INC_ERRNO\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\nextern int errno;\n\n#define EPERM 1\n#define ENOENT 2\n#define ENOFILE ENOENT\n#define ESRCH 3\n#define EINTR 4\n#define EIO 5\n#define ENXIO 6\n#define E2BIG 7\n#define ENOEXEC 8\n#define EBADF 9\n#define ECHILD 10\n#define EAGAIN 11\n#define ENOMEM 12\n#define EACCES 13\n#define EFAULT 14\n#define EBUSY 16\n#define EEXIST 17\n#define EXDEV 18\n#define ENODEV 19\n#define ENOTDIR 20\n#define EISDIR 21\n#define ENFILE 23\n#define EMFILE 24\n#define ENOTTY 25\n#define EFBIG 27\n#define ENOSPC 28\n#define ESPIPE 29\n#define EROFS 30\n#define EMLINK 31\n#define EPIPE 32\n#define EDOM 33\n#define EDEADLK 36\n#define ENAMETOOLONG 38\n#define ENOLCK 39\n#define ENOSYS 40\n#define ENOTEMPTY 41\n\n#ifndef RC_INVOKED\n#if !defined(_SECURECRT_ERRCODE_VALUES_DEFINED)\n#define _SECURECRT_ERRCODE_VALUES_DEFINED\n#define EINVAL 22\n#define ERANGE 34\n#define EILSEQ 42\n#define STRUNCATE 80\n#endif\n#endif\n\n#define EDEADLOCK EDEADLK\n\n/* Posix thread extensions.  */\n\n#ifndef ENOTSUP\n#define ENOTSUP         129\n#endif\n\n/* Extension defined as by report VC 10+ defines error-numbers.  */\n\n#ifndef EAFNOSUPPORT\n#define EAFNOSUPPORT 102\n#endif\n\n#ifndef EADDRINUSE\n#define EADDRINUSE 100\n#endif\n\n#ifndef EADDRNOTAVAIL\n#define EADDRNOTAVAIL 101\n#endif\n\n#ifndef EISCONN\n#define EISCONN 113\n#endif\n\n#ifndef ENOBUFS\n#define ENOBUFS 119\n#endif\n\n#ifndef ECONNABORTED\n#define ECONNABORTED 106\n#endif\n\n#ifndef EALREADY\n#define EALREADY 103\n#endif\n\n#ifndef ECONNREFUSED\n#define ECONNREFUSED 107\n#endif\n\n#ifndef ECONNRESET\n#define ECONNRESET 108\n#endif\n\n#ifndef EDESTADDRREQ\n#define EDESTADDRREQ 109\n#endif\n\n#ifndef EHOSTUNREACH\n#define EHOSTUNREACH 110\n#endif\n\n#ifndef EMSGSIZE\n#define EMSGSIZE 115\n#endif\n\n#ifndef ENETDOWN\n#define ENETDOWN 116\n#endif\n\n#ifndef ENETRESET\n#define ENETRESET 117\n#endif\n\n#ifndef ENETUNREACH\n#define ENETUNREACH 118\n#endif\n\n#ifndef ENOPROTOOPT\n#define ENOPROTOOPT 123\n#endif\n\n#ifndef ENOTSOCK\n#define ENOTSOCK 128\n#endif\n\n#ifndef ENOTCONN\n#define ENOTCONN 126\n#endif\n\n#ifndef ECANCELED\n#define ECANCELED 105\n#endif\n\n#ifndef EINPROGRESS\n#define EINPROGRESS 112\n#endif\n\n#ifndef EOPNOTSUPP\n#define EOPNOTSUPP 130\n#endif\n\n#ifndef EWOULDBLOCK\n#define EWOULDBLOCK 140\n#endif\n\n#ifndef EOWNERDEAD\n#define EOWNERDEAD 133\n#endif\n\n#ifndef EPROTO\n#define EPROTO 134\n#endif\n\n#ifndef EPROTONOSUPPORT\n#define EPROTONOSUPPORT 135\n#endif\n\n#ifndef EBADMSG\n#define EBADMSG 104\n#endif\n\n#ifndef EIDRM\n#define EIDRM 111\n#endif\n\n#ifndef ENODATA\n#define ENODATA 120\n#endif\n\n#ifndef ENOLINK\n#define ENOLINK 121\n#endif\n\n#ifndef ENOMSG\n#define ENOMSG 122\n#endif\n\n#ifndef ENOSR\n#define ENOSR 124\n#endif\n\n#ifndef ENOSTR\n#define ENOSTR 125\n#endif\n\n#ifndef ENOTRECOVERABLE\n#define ENOTRECOVERABLE 127\n#endif\n\n#ifndef ETIME\n#define ETIME 137\n#endif\n\n#ifndef ETXTBSY\n#define ETXTBSY 139\n#endif\n\n/* Defined as WSAETIMEDOUT.  */\n#ifndef ETIMEDOUT\n#define ETIMEDOUT 138\n#endif\n\n#ifndef ELOOP\n#define ELOOP 114\n#endif\n\n#ifndef EPROTOTYPE\n#define EPROTOTYPE 136\n#endif\n\n#ifndef EOVERFLOW\n#define EOVERFLOW 132\n#endif\n\n#ifdef __cplusplus\n}\n#endif\n#endif\n"
  },
  {
    "path": "include/mini_std/printf.h",
    "content": "///////////////////////////////////////////////////////////////////////////////\n// \\author (c) Marco Paland (info@paland.com)\n//             2014-2019, PALANDesign Hannover, Germany\n//\n// \\license The MIT License (MIT)\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy\n// of this software and associated documentation files (the \"Software\"), to deal\n// in the Software without restriction, including without limitation the rights\n// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n// copies of the Software, and to permit persons to whom the Software is\n// furnished to do so, subject to the following conditions:\n//\n// The above copyright notice and this permission notice shall be included in\n// all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n// THE SOFTWARE.\n//\n// \\brief Tiny printf, sprintf and snprintf implementation, optimized for speed on\n//        embedded systems with a very limited resources.\n//        Use this instead of bloated standard/newlib printf.\n//        These routines are thread safe and reentrant.\n//\n///////////////////////////////////////////////////////////////////////////////\n\n#ifndef _PRINTF_H_\n#define _PRINTF_H_\n\n#include <stdarg.h>\n#include <stddef.h>\n\n#if defined(PRINTF_USE_SUFFIX)\n#define PRINTF_FN(x) x ## _\n#define   sprintf   sprintf_\n#define    printf    printf_\n#define  snprintf  snprintf_\n#define vsnprintf vsnprintf_\n#define   vprintf   vprintf_\n#else\n#define PRINTF_FN(x) x\n#endif\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n\n/**\n * Output a character to a custom device like UART, used by the printf() function\n * This function is declared here only. You have to write your custom implementation somewhere\n * \\param character Character to output\n */\nvoid _putchar(char character);\n\n\n/**\n * Tiny printf implementation\n * You have to implement _putchar if you use printf()\n * To avoid conflicts with the regular printf() API it is overridden by macro defines\n * and internal underscore-appended functions like printf_() are used\n * \\param format A string that specifies the format of the output\n * \\return The number of characters that are written into the array, not counting the terminating null character\n */\nint PRINTF_FN(printf)(const char* format, ...) __attribute__((format(printf, 1, 2)));\n\n\n/**\n * Tiny sprintf implementation\n * Due to security reasons (buffer overflow) YOU SHOULD CONSIDER USING (V)SNPRINTF INSTEAD!\n * \\param buffer A pointer to the buffer where to store the formatted string. MUST be big enough to store the output!\n * \\param format A string that specifies the format of the output\n * \\return The number of characters that are WRITTEN into the buffer, not counting the terminating null character\n */\nint PRINTF_FN(sprintf)(char* buffer, const char* format, ...) __attribute__ ((format (printf, 2, 3)));\n\n/**\n * Tiny snprintf/vsnprintf implementation\n * \\param buffer A pointer to the buffer where to store the formatted string\n * \\param count The maximum number of characters to store in the buffer, including a terminating null character\n * \\param format A string that specifies the format of the output\n * \\param va A value identifying a variable arguments list\n * \\return The number of characters that COULD have been written into the buffer, not counting the terminating\n *         null character. A value equal or larger than count indicates truncation. Only when the returned value\n *         is non-negative and less than count, the string has been completely written.\n */\nint PRINTF_FN( snprintf)(char* buffer, size_t count, const char* format, ...) __attribute__ ((format (printf, 3, 4)));\nint PRINTF_FN(vsnprintf)(char* buffer, size_t count, const char* format, va_list va);\n\n\n/**\n * Tiny vprintf implementation\n * \\param format A string that specifies the format of the output\n * \\param va A value identifying a variable arguments list\n * \\return The number of characters that are WRITTEN into the buffer, not counting the terminating null character\n */\nint PRINTF_FN(vprintf)(const char* format, va_list va);\n\n/**\n * printf with output function\n * You may use this as dynamic alternative to printf() with its fixed _putchar() output\n * \\param out An output function which takes one character and an argument pointer\n * \\param arg An argument pointer for user data passed to output function\n * \\param format A string that specifies the format of the output\n * \\return The number of characters that are sent to the output function, not counting the terminating null character\n */\nint PRINTF_FN(fctprintf)(\n\tvoid (*out)(char character, void* arg), void* arg, const char* format, ...\n) __attribute__ ((format (printf, 3, 4)));\n\n#ifdef __cplusplus\n}\n#endif\n\n\n#endif  // _PRINTF_H_\n"
  },
  {
    "path": "include/mini_std/sort_r.h",
    "content": "/* Isaac Turner 29 April 2014 Public Domain */\n#ifndef SORT_R_H_\n#define SORT_R_H_\n\n#include <stdlib.h>\n#include <string.h>\n\n#ifdef __cplusplus\n#if !defined(restrict)\n#define restrict\n#endif\nextern \"C\" {\n#endif\n\n/*\n\nsort_r function to be exported.\n\nParameters:\n  base is the array to be sorted\n  nel is the number of elements in the array\n  width is the size in bytes of each element of the array\n  compar is the comparison function\n  arg is a pointer to be passed to the comparison function\n\nvoid sort_r(void *base, size_t nel, size_t width,\n            int (*compar)(const void *_a, const void *_b, void *_arg),\n            void *arg);\n\n*/\n\n#define _SORT_R_INLINE inline\n\n#if (defined __APPLE__ || defined __MACH__ || defined __DARWIN__ || \\\n     defined __FreeBSD__ || defined __DragonFly__)\n#  define _SORT_R_BSD\n#elif (defined _GNU_SOURCE || defined __gnu_hurd__ || defined __GNU__ || \\\n       defined __linux__ || defined __MINGW32__ || defined __GLIBC__)\n#  define _SORT_R_LINUX\n#elif (defined _WIN32 || defined _WIN64 || defined __WINDOWS__)\n#  define _SORT_R_WINDOWS\n#  undef _SORT_R_INLINE\n#  define _SORT_R_INLINE __inline\n#else\n  /* Using our own recursive quicksort sort_r_simple() */\n#endif\n\n#if (defined NESTED_QSORT && NESTED_QSORT == 0)\n#  undef NESTED_QSORT\n#endif\n\n#define SORT_R_SWAP(a,b,tmp) ((tmp) = (a), (a) = (b), (b) = (tmp))\n\n/* swap a and b */\n/* a and b must not be equal! */\nstatic _SORT_R_INLINE void sort_r_swap(char *__restrict a, char *__restrict b,\n                                       size_t w)\n{\n  char tmp, *end = a+w;\n  for(; a < end; a++, b++) { SORT_R_SWAP(*a, *b, tmp); }\n}\n\n/* swap a, b iff a>b */\n/* a and b must not be equal! */\n/* __restrict is same as restrict but better support on old machines */\nstatic _SORT_R_INLINE int sort_r_cmpswap(char *__restrict a,\n                                         char *__restrict b, size_t w,\n                                         int (*compar)(const void *_a,\n                                                       const void *_b,\n                                                       void *_arg),\n                                         void *arg)\n{\n  if(compar(a, b, arg) > 0) {\n    sort_r_swap(a, b, w);\n    return 1;\n  }\n  return 0;\n}\n\n/*\nSwap consecutive blocks of bytes of size na and nb starting at memory addr ptr,\nwith the smallest swap so that the blocks are in the opposite order. Blocks may\nbe internally re-ordered e.g.\n\n  12345ab  ->   ab34512\n  123abc   ->   abc123\n  12abcde  ->   deabc12\n*/\nstatic _SORT_R_INLINE void sort_r_swap_blocks(char *ptr, size_t na, size_t nb)\n{\n  if(na > 0 && nb > 0) {\n    if(na > nb) { sort_r_swap(ptr, ptr+na, nb); }\n    else { sort_r_swap(ptr, ptr+nb, na); }\n  }\n}\n\n/* Implement recursive quicksort ourselves */\n/* Note: quicksort is not stable, equivalent values may be swapped */\nstatic _SORT_R_INLINE void sort_r_simple(void *base, size_t nel, size_t w,\n                                         int (*compar)(const void *_a,\n                                                       const void *_b,\n                                                       void *_arg),\n                                         void *arg)\n{\n  char *b = (char *)base, *end = b + nel*w;\n\n  /* for(size_t i=0; i<nel; i++) {printf(\"%4i\", *(int*)(b + i*sizeof(int)));}\n  printf(\"\\n\"); */\n\n  if(nel < 10) {\n    /* Insertion sort for arbitrarily small inputs */\n    char *pi, *pj;\n    for(pi = b+w; pi < end; pi += w) {\n      for(pj = pi; pj > b && sort_r_cmpswap(pj-w,pj,w,compar,arg); pj -= w) {}\n    }\n  }\n  else\n  {\n    /* nel > 6; Quicksort */\n\n    int cmp;\n    char *pl, *ple, *pr, *pre, *pivot;\n    char *last = b+w*(nel-1), *tmp;\n\n    /*\n    Use median of second, middle and second-last items as pivot.\n    First and last may have been swapped with pivot and therefore be extreme\n    */\n    char *l[3];\n    l[0] = b + w;\n    l[1] = b+w*(nel/2);\n    l[2] = last - w;\n\n    /* printf(\"pivots: %i, %i, %i\\n\", *(int*)l[0], *(int*)l[1], *(int*)l[2]); */\n\n    if(compar(l[0],l[1],arg) > 0) { SORT_R_SWAP(l[0], l[1], tmp); }\n    if(compar(l[1],l[2],arg) > 0) {\n      SORT_R_SWAP(l[1], l[2], tmp);\n      if(compar(l[0],l[1],arg) > 0) { SORT_R_SWAP(l[0], l[1], tmp); }\n    }\n\n    /* swap mid value (l[1]), and last element to put pivot as last element */\n    if(l[1] != last) { sort_r_swap(l[1], last, w); }\n\n    /*\n    pl is the next item on the left to be compared to the pivot\n    pr is the last item on the right that was compared to the pivot\n    ple is the left position to put the next item that equals the pivot\n    ple is the last right position where we put an item that equals the pivot\n\n                                           v- end (beyond the array)\n      EEEEEELLLLLLLLuuuuuuuuGGGGGGGEEEEEEEE.\n      ^- b  ^- ple  ^- pl   ^- pr  ^- pre ^- last (where the pivot is)\n\n    Pivot comparison key:\n      E = equal, L = less than, u = unknown, G = greater than, E = equal\n    */\n    pivot = last;\n    ple = pl = b;\n    pre = pr = last;\n\n    /*\n    Strategy:\n    Loop into the list from the left and right at the same time to find:\n    - an item on the left that is greater than the pivot\n    - an item on the right that is less than the pivot\n    Once found, they are swapped and the loop continues.\n    Meanwhile items that are equal to the pivot are moved to the edges of the\n    array.\n    */\n    while(pl < pr) {\n      /* Move left hand items which are equal to the pivot to the far left.\n         break when we find an item that is greater than the pivot */\n      for(; pl < pr; pl += w) {\n        cmp = compar(pl, pivot, arg);\n        if(cmp > 0) { break; }\n        else if(cmp == 0) {\n          if(ple < pl) { sort_r_swap(ple, pl, w); }\n          ple += w;\n        }\n      }\n      /* break if last batch of left hand items were equal to pivot */\n      if(pl >= pr) { break; }\n      /* Move right hand items which are equal to the pivot to the far right.\n         break when we find an item that is less than the pivot */\n      for(; pl < pr; ) {\n        pr -= w; /* Move right pointer onto an unprocessed item */\n        cmp = compar(pr, pivot, arg);\n        if(cmp == 0) {\n          pre -= w;\n          if(pr < pre) { sort_r_swap(pr, pre, w); }\n        }\n        else if(cmp < 0) {\n          if(pl < pr) { sort_r_swap(pl, pr, w); }\n          pl += w;\n          break;\n        }\n      }\n    }\n\n    pl = pr; /* pr may have gone below pl */\n\n    /*\n    Now we need to go from: EEELLLGGGGEEEE\n                        to: LLLEEEEEEEGGGG\n\n    Pivot comparison key:\n      E = equal, L = less than, u = unknown, G = greater than, E = equal\n    */\n    sort_r_swap_blocks(b, ple-b, pl-ple);\n    sort_r_swap_blocks(pr, pre-pr, end-pre);\n\n    /*for(size_t i=0; i<nel; i++) {printf(\"%4i\", *(int*)(b + i*sizeof(int)));}\n    printf(\"\\n\");*/\n\n    sort_r_simple(b, (pl-ple)/w, w, compar, arg);\n    sort_r_simple(end-(pre-pr), (pre-pr)/w, w, compar, arg);\n  }\n}\n\n\n#if defined NESTED_QSORT\n\n  static _SORT_R_INLINE void sort_r(void *base, size_t nel, size_t width,\n                                    int (*compar)(const void *_a,\n                                                  const void *_b,\n                                                  void *aarg),\n                                    void *arg)\n  {\n    int nested_cmp(const void *a, const void *b)\n    {\n      return compar(a, b, arg);\n    }\n\n    qsort(base, nel, width, nested_cmp);\n  }\n\n#else /* !NESTED_QSORT */\n\n  /* Declare structs and functions */\n\n  #if defined _SORT_R_BSD\n\n    /* Ensure qsort_r is defined */\n    extern void qsort_r(void *base, size_t nel, size_t width, void *thunk,\n                        int (*compar)(void *_thunk,\n                                      const void *_a, const void *_b));\n\n  #endif\n\n  #if defined _SORT_R_BSD || defined _SORT_R_WINDOWS\n\n    /* BSD (qsort_r), Windows (qsort_s) require argument swap */\n\n    struct sort_r_data\n    {\n      void *arg;\n      int (*compar)(const void *_a, const void *_b, void *_arg);\n    };\n\n    static _SORT_R_INLINE int sort_r_arg_swap(void *s,\n                                              const void *a, const void *b)\n    {\n      struct sort_r_data *ss = (struct sort_r_data*)s;\n      return (ss->compar)(a, b, ss->arg);\n    }\n\n  #endif\n\n  #if defined _SORT_R_LINUX\n\n    typedef int(* __compar_d_fn_t)(const void *, const void *, void *);\n    extern void qsort_r(void *base, size_t nel, size_t width,\n                        __compar_d_fn_t __compar, void *arg)\n      __attribute__((nonnull (1, 4)));\n\n  #endif\n\n  /* implementation */\n\n  static _SORT_R_INLINE void sort_r(void *base, size_t nel, size_t width,\n                                    int (*compar)(const void *_a,\n                                                  const void *_b, void *_arg),\n                                    void *arg)\n  {\n    #if defined _SORT_R_LINUX\n\n      #if defined __GLIBC__ && ((__GLIBC__ < 2) || (__GLIBC__ == 2 && __GLIBC_MINOR__ < 8))\n\n        /* no qsort_r in glibc before 2.8, need to use nested qsort */\n        sort_r_simple(base, nel, width, compar, arg);\n\n      #else\n\n        qsort_r(base, nel, width, compar, arg);\n\n      #endif\n\n    #elif defined _SORT_R_BSD\n\n      struct sort_r_data tmp;\n      tmp.arg = arg;\n      tmp.compar = compar;\n      qsort_r(base, nel, width, &tmp, sort_r_arg_swap);\n\n    #elif defined _SORT_R_WINDOWS\n\n      struct sort_r_data tmp;\n      tmp.arg = arg;\n      tmp.compar = compar;\n      qsort_s(base, nel, width, sort_r_arg_swap, &tmp);\n\n    #else\n\n      /* Fall back to our own quicksort implementation */\n      sort_r_simple(base, nel, width, compar, arg);\n\n    #endif\n  }\n\n#endif /* !NESTED_QSORT */\n\n#undef _SORT_R_INLINE\n#undef _SORT_R_WINDOWS\n#undef _SORT_R_LINUX\n#undef _SORT_R_BSD\n\n#ifdef __cplusplus\n}\n#undef restrict\n#endif\n\n#endif /* SORT_R_H_ */\n"
  },
  {
    "path": "include/mini_std/stdint.h",
    "content": "#define MINISTD_STDINT_PATH <../../__GNUC__.__GNUC_MINOR__.__GNUC_PATCHLEVEL__/include/stdint-gcc.h>\n#include MINISTD_STDINT_PATH\n#undef MINISTD_STDINT_PATH\n"
  },
  {
    "path": "include/mini_std/stdio.h",
    "content": "#ifndef _MINI_STD_STDIO_H_\n#define _MINI_STD_STDIO_H_\n\n#include <stddef.h>\n#include <stdarg.h>\n#include \"printf.h\"\n\n#ifdef __cplusplus\n#if !defined(restrict)\n#define restrict\n#endif\nextern \"C\" {\n#endif\n\ntypedef int FILE; // Whatever, it's using pointer anyway\n\n#define SEEK_SET 0\n#define SEEK_CUR 1\n#define SEEK_END 2\n\n#define EOF -1\n#define FILENAME_MAX 1024\n\nFILE *fopen(const char *restrict filename, const char *restrict mode);\n\nsize_t fread(void *restrict buffer, size_t size, size_t count, FILE *restrict stream);\n\nsize_t fwrite(const void *restrict buffer, size_t size, size_t count, FILE *restrict stream);\n\nint fclose(FILE *stream);\n\nint fseek(FILE *stream, long offset, int origin);\n\nint fflush( FILE *stream );\n\nlong ftell( FILE *stream );\n\nint feof( FILE *stream );\n\nstatic inline int vsprintf(char *restrict buffer, const char *restrict format, va_list vlist) {\n\treturn vsnprintf(buffer, 65535, format, vlist);\n}\n\nint rename(const char *szSource, const char *szDestination);\n\nint remove(const char* szFilePath);\n\n#ifdef __cplusplus\n}\n#undef restrict\n#endif\n\n#endif // _MINI_STD_STDIO_H_\n"
  },
  {
    "path": "include/mini_std/stdlib.h",
    "content": "#ifndef _MINI_STD_STDLIB_H_\n#define _MINI_STD_STDLIB_H_\n\n#include <stddef.h>\n\n#ifdef __cplusplus\n#if !defined(restrict)\n#define restrict\n#endif\nextern \"C\" {\n#endif\n\n#define EXIT_SUCCESS 0\n#define EXIT_FAILURE 1\n\nvoid exit(int exit_code);\n\nvoid qsort(\n\tvoid *ptr, size_t count, size_t size, int (*comp)(const void *, const void *)\n);\n\n#ifdef __cplusplus\n}\n#undef restrict\n#endif\n\n#endif // _MINI_STD_STDLIB_H_\n"
  },
  {
    "path": "include/mini_std/string.h",
    "content": "#ifndef _MINI_STD_STRING_H_\n#define _MINI_STD_STRING_H_\n\n#include <stddef.h>\n#include <../sys-include/string.h>\n\n#ifdef __cplusplus\n#if !defined(restrict)\n#define restrict\n#endif\nextern \"C\" {\n#endif\n\nsize_t strlen(const char *str);\n\nchar *strncpy(char *restrict dest, const char *restrict src, size_t count);\n\nchar *strcpy(char *restrict dest, const char *restrict src);\n\nchar *strcat(char *restrict dest, const char *restrict src);\n\nchar *strchr(const char *szHaystack, int cNeedle);\n\nchar *strrchr(const char *szHaystack, int cNeedle);\n\nint memcmp(const void *lhs, const void *rhs, size_t count);\n\nunsigned long strtoul(const char *restrict str, char **restrict str_end, int base);\n\nint strcmp(const char *szA, const char *szB);\n\nchar *strncpy(char *restrict szDest, const char *restrict szSrc, size_t Count);\n\n#ifdef __cplusplus\n}\n#undef restrict\n#endif\n\n#endif // _MINI_STD_STRING_H_\n"
  },
  {
    "path": "showcase/CMakeLists.txt",
    "content": "cmake_minimum_required(VERSION 3.14)\r\nproject(showcase)\r\n\r\n# Lowercase project name for binaries and packaging\r\nstring(TOLOWER ${PROJECT_NAME} PROJECT_NAME_LOWER)\r\n\r\n# Version number in format X.Y.Z\r\nset(VER_X  0)\r\nset(VER_Y 0)\r\nset(VER_Z 1)\r\nset(VER_FULL \"${VER_X}.${VER_Y}.${VER_Z}\")\r\n\r\nif(NOT AMIGA)\r\n\tmessage(SEND_ERROR \"This project only compiles for Amiga\")\r\nendif()\r\n\r\nset(CMAKE_C_STANDARD 11)\r\nset(CMAKE_C_FLAGS \"${CMAKE_C_FLAGS} -DAMIGA -Wall -Wextra -fomit-frame-pointer\")\r\nset(CMAKE_C_FLAGS_DEBUG \"${CMAKE_C_FLAGS_DEBUG} -DACE_DEBUG\")\r\nfile(GLOB_RECURSE SOURCES src/*.c)\r\nfile(GLOB_RECURSE HEADERS src/*.h)\r\n\r\n\r\ninclude_directories(${PROJECT_SOURCE_DIR}/src)\r\n\r\nset(RES_DIR ${CMAKE_CURRENT_LIST_DIR}/res)\r\nset(DATA_DIR ${CMAKE_CURRENT_BINARY_DIR}/data)\r\n\r\n# ACE\r\nadd_subdirectory(.. ace)\r\ninclude_directories(../include)\r\n\r\n# Linux/other UNIX get a lower-case binary name\r\nset(TARGET_NAME ${PROJECT_NAME_LOWER})\r\n\r\nif(ELF2HUNK)\r\n  # Add elf2hunk step for Bartman compiler\r\n  set(GAME_EXECUTABLE ${TARGET_NAME}.elf) # Intermediate executable\r\n  set(GAME_OUTPUT_EXECUTABLE ${TARGET_NAME}.exe) # Use this to launch the game\r\n  add_executable(${GAME_EXECUTABLE} ${SOURCES} ${HEADERS})\r\n  add_custom_command(\r\n    TARGET ${GAME_EXECUTABLE} POST_BUILD\r\n    COMMAND ${ELF2HUNK} ${GAME_EXECUTABLE} ${GAME_OUTPUT_EXECUTABLE}\r\n  )\r\nelse()\r\n  # Just produce the executable with Bebbo compiler\r\n  SET(GAME_EXECUTABLE ${TARGET_NAME})\r\n  SET(GAME_OUTPUT_EXECUTABLE ${TARGET_NAME})\r\n  add_executable(${GAME_EXECUTABLE} ${SOURCES} ${HEADERS})\r\nendif()\r\n\r\ntarget_link_libraries(${GAME_EXECUTABLE} ace)\r\n\r\nset(RES_DIR ${CMAKE_CURRENT_LIST_DIR}/res)\r\nset(DATA_DIR ${CMAKE_CURRENT_BINARY_DIR}/data)\r\nfile(MAKE_DIRECTORY ${DATA_DIR})\r\n\r\nset(AMIDB32_PLT_PATH ${DATA_DIR}/amidb32.plt)\r\nconvertPalette(${GAME_EXECUTABLE} ${RES_DIR}/amidb32.gpl ${AMIDB32_PLT_PATH})\r\nconvertPalette(${GAME_EXECUTABLE} ${RES_DIR}/blitToSmall.gpl ${DATA_DIR}/blitToSmall.plt)\r\n\r\nconvertBitmaps(\r\n\tTARGET ${GAME_EXECUTABLE} PALETTE ${AMIDB32_PLT_PATH}\r\n\tSOURCES ${RES_DIR}/32c_pal.png DESTINATIONS ${DATA_DIR}/32c_pal.bm\r\n)\r\nconvertBitmaps(\r\n\tTARGET ${GAME_EXECUTABLE} PALETTE ${AMIDB32_PLT_PATH} INTERLEAVED\r\n\tSOURCES ${RES_DIR}/32c_pal_interleaved.png DESTINATIONS ${DATA_DIR}/32c_pal_interleaved.bm\r\n)\r\n\r\nconvertFont(\r\n  TARGET ${GAME_EXECUTABLE}\r\n\tSOURCE ${RES_DIR}/silkscreen DESTINATION ${DATA_DIR}/silkscreen.fnt\r\n)\r\n"
  },
  {
    "path": "showcase/README.md",
    "content": "# ACE Showcase\r\n\r\nUsed to test regressions and demonstrate features. If you're new to ACE,\r\nit's the best place to start analyzing and hacking it.\r\n\r\nThere will be no docs to it apart of comments in source, as code is simple\r\nand self-explanatory. Sources are very unoptimized to keep simplicity\r\nfor beginners. Quirks and clever use-cases may be shown in examples.\r\n\r\n## Building & running\r\n\r\nJust execute make in this directory. Executable \"showcase\" is produced\r\nin the process. To run it, directory 'data' must be present in current\r\nworking directory.\r\n\r\nYou can also run it using CMake - it will build ACE automatically:\r\n\r\n``` sh\r\nmkdir build && cd build\r\ncmake .. -DCMAKE_TOOLCHAIN_FILE=/path/to/AmigaCMakeCrossToolchains/m68k.cmake -DM68K_TOOLCHAIN_PATH=/path/to/toolchain -DM68K_CPU=68000 -DM68K_FPU=soft\r\nmake\r\n```\r\n\r\n## Adding tests & examples\r\n\r\nTo avoid .o name collisions, tests should be added in 'test' dir.\r\nEvery test should consist of single .c and .h file.\r\n\r\nSame thing refers to examples in 'example' dir."
  },
  {
    "path": "showcase/res/amidb32.gpl",
    "content": "GIMP Palette\r\nName: \\amidb32\r\nColumns: 4\r\n#\r\n  0   0   0 Index 0\r\n170 187 187 Index 1\r\n 85  85  34 Index 2\r\n102  68  51 Index 3\r\n119  68 153 Index 4\r\n221 136 204 Index 5\r\n 51  68  68 Index 6\r\n 51 153 119 Index 7\r\n 68  51  68 Index 8\r\n255 204 170 Index 9\r\n187  51  51 Index 10\r\n136 136 136 Index 11\r\n153 119  51 Index 12\r\n170 238  85 Index 13\r\n153 153  85 Index 14\r\n 85 119  51 Index 15\r\n153  85  68 Index 16\r\n119 119 119 Index 17\r\n221 238 255 Index 18\r\n238 170 102 Index 19\r\n 34  34  51 Index 20\r\n119 204  51 Index 21\r\n102 170 255 Index 22\r\n102  85  85 Index 23\r\n102 221 238 Index 24\r\n 51 102 136 Index 25\r\n255 255 255 Index 26\r\n238 119  34 Index 27\r\n102 119 238 Index 28\r\n255 255  51 Index 29\r\n 68  68 119 Index 30\r\n238  85 102 Index 31\r\n"
  },
  {
    "path": "showcase/res/blitToSmall.gpl",
    "content": "GIMP Palette\r\nName: \\blitToSmall\r\nColumns: 4\r\n#\r\n  0   0 255 Index 0\r\n255   0   0 Index 1\r\n255 255   0 Index 2\r\n187 221   0 Index 3\r\n 34 136   0 Index 4\r\n  0 136   0 Index 5\r\n 68 153   0 Index 6\r\n119 187   0 Index 7\r\n153 204   0 Index 8\r\n221 238   0 Index 9\r\n102 170   0 Index 10\r\n"
  },
  {
    "path": "showcase/res/pong.gpl",
    "content": "GIMP Palette\nName: pong\nColumns: 4\n#\n  0  17  34\tIndex 0\n255 255 255\tIndex 1\n 68   0  34\tIndex 2\n136   0  34\tIndex 3\n 34  51  68\tIndex 4\n  0  68  85\tIndex 5\n221  34  51\tIndex 6\n 17 153 170\tIndex 7\n102 136 136\tIndex 8\n255 102  85\tIndex 9\n187 187 187\tIndex 10\n119 221 187\tIndex 11\n"
  },
  {
    "path": "showcase/src/game.c",
    "content": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at http://mozilla.org/MPL/2.0/. */\n\n#include \"game.h\"\n#include <ace/managers/joy.h>\n#include <ace/managers/key.h>\n#include <ace/managers/game.h>\n#include \"menu/menu.h\"\n#include \"test/blit.h\"\n#include \"test/input.h\"\n#include \"test/copper.h\"\n#include \"test/font.h\"\n#include \"test/blitsmalldest.h\"\n#include \"test/interleaved.h\"\n#include \"test/lines.h\"\n#include \"test/buffer_scroll.h\"\n#include \"test/twister.h\"\n\ntStateManager *g_pGameStateManager = 0;\ntState g_pTestStates[TEST_STATE_COUNT] = {\n    [TEST_STATE_MENU] = {.cbCreate = gsMenuCreate, .cbLoop = gsMenuLoop, .cbDestroy = gsMenuDestroy},\n    [TEST_STATE_BLIT] = {.cbCreate = gsTestBlitCreate, .cbLoop = gsTestBlitLoop, .cbDestroy = gsTestBlitDestroy},\n    [TEST_STATE_INPUT] = {.cbCreate = gsTestInputCreate, .cbLoop = gsTestInputLoop, .cbDestroy = gsTestInputDestroy},\n    [TEST_STATE_FONT] = {.cbCreate = gsTestFontCreate, .cbLoop = gsTestFontTableLoop, .cbDestroy = gsTestFontDestroy},\n    [TEST_STATE_COPPER] = {.cbCreate = gsTestCopperCreate, .cbLoop = gsTestCopperLoop, .cbDestroy = gsTestCopperDestroy},\n    [TEST_STATE_LINES] = {.cbCreate = gsTestLinesCreate, .cbLoop = gsTestLinesLoop, .cbDestroy = gsTestLinesDestroy},\n    [TEST_STATE_BLIT_SMALL_DEST] = {.cbCreate = gsTestBlitSmallDestCreate, .cbLoop = gsTestBlitSmallDestLoop, .cbDestroy = gsTestBlitSmallDestDestroy},\n    [TEST_STATE_INTERLEAVED] = {.cbCreate = gsTestInterleavedCreate, .cbLoop = gsTestInterleavedLoop, .cbDestroy = gsTestInterleavedDestroy},\n    [TEST_STATE_BUFFER_SCROLL] = {.cbCreate = gsTestBufferScrollCreate, .cbLoop = gsTestBufferScrollLoop, .cbDestroy = gsTestBufferScrollDestroy},\n    [TEST_STATE_TWISTER] = {.cbCreate = gsTestTwisterCreate, .cbLoop = gsTestTwisterLoop, .cbDestroy = gsTestTwisterDestroy},\n};\n\n#define GENERIC_MAIN_LOOP_CONDITION gameIsRunning() && g_pGameStateManager->pCurrent\n#include <ace/generic/main.h>\n\nvoid genericCreate(void) {\n\tjoyOpen();\n\tkeyCreate();\n\n    createGameStates();\n    stateChange(g_pGameStateManager, &g_pTestStates[TEST_STATE_MENU]);\n}\n\nvoid genericProcess(void) {\n\tjoyProcess();\n\tkeyProcess();\n\n    stateProcess(g_pGameStateManager);\n}\n\nvoid genericDestroy(void) {\n    destroyGameStates();\n\n\tkeyDestroy();\n\tjoyClose();\n}\n\nvoid createGameStates(void) {\n    g_pGameStateManager = stateManagerCreate();\n}\n\nvoid destroyGameStates(void) {\n    stateManagerDestroy(g_pGameStateManager);\n}\n"
  },
  {
    "path": "showcase/src/game.h",
    "content": "/* This Source Code Form is subject to the terms of the Mozilla Public\r\n * License, v. 2.0. If a copy of the MPL was not distributed with this\r\n * file, You can obtain one at http://mozilla.org/MPL/2.0/. */\r\n\r\n#ifndef _SHOWCASE_GAME_H_\r\n#define _SHOWCASE_GAME_H_\r\n\r\n#include <ace/managers/state.h>\r\n\r\n//---------------------------------------------------------------------- DEFINES\r\n\r\n#define SHOWCASE_BPP 5\r\n\r\ntypedef enum tTestState {\r\n\tTEST_STATE_MENU,\r\n\tTEST_STATE_BLIT,\r\n\tTEST_STATE_INPUT,\r\n\tTEST_STATE_FONT,\r\n\tTEST_STATE_COPPER,\r\n\tTEST_STATE_LINES,\r\n\tTEST_STATE_BLIT_SMALL_DEST,\r\n\tTEST_STATE_INTERLEAVED,\r\n\tTEST_STATE_BUFFER_SCROLL,\r\n\tTEST_STATE_TWISTER,\r\n\tTEST_STATE_COUNT\r\n} tTestState;\r\n\r\n//------------------------------------------------------------------------ TYPES\r\n\r\n//---------------------------------------------------------------------- GLOBALS\r\n\r\nextern tStateManager *g_pGameStateManager;\r\nextern tState g_pTestStates[TEST_STATE_COUNT];\r\n\r\n//-------------------------------------------------------------------- FUNCTIONS\r\n\r\nvoid genericCreate(void);\r\nvoid genericProcess(void);\r\nvoid genericDestroy(void);\r\n\r\nvoid createGameStates(void);\r\nvoid destroyGameStates(void);\r\n\r\n//---------------------------------------------------------------------- INLINES\r\n\r\n//----------------------------------------------------------------------- MACROS\r\n\r\n#endif // _SHOWCASE_GAME_H_\r\n"
  },
  {
    "path": "showcase/src/menu/menu.c",
    "content": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at http://mozilla.org/MPL/2.0/. */\n\n#include \"menu/menu.h\"\n#include <ace/managers/viewport/simplebuffer.h>\n#include <ace/managers/key.h>\n#include <ace/managers/joy.h>\n#include <ace/managers/game.h>\n#include <ace/managers/state.h>\n#include <ace/managers/blit.h>\n#include <ace/managers/system.h>\n#include <ace/utils/extview.h>\n#include <ace/generic/screen.h>\n#include \"game.h\"\n#include \"menu/menulist.h\"\n\nstatic tView *s_pMenuView;\nstatic tVPort *s_pMenuVPort;\nstatic tSimpleBufferManager *s_pMenuBfr;\n\nstatic tFont *s_pMenuFont;\nstatic tTextBitMap *s_pTextBitMap;\nstatic tMenuList *s_pMenuList; /// Menu list\nstatic UBYTE s_ubMenuType;     /// Current menu list - see MENU_* macros\n\nvoid gsMenuCreate(void) {\n\tlogBlockBegin(\"gsMenuCreate\");\n\t// Prepare view & viewport\n\ts_pMenuView = viewCreate(0, TAG_DONE);\n\ts_pMenuVPort = vPortCreate(0,\n\t\tTAG_VPORT_VIEW, s_pMenuView,\n\t\tTAG_VPORT_BPP, SHOWCASE_BPP,\n\t\tTAG_DONE\n\t);\n\ts_pMenuBfr = simpleBufferCreate(0,\n\t\tTAG_SIMPLEBUFFER_VPORT, s_pMenuVPort,\n\t\tTAG_SIMPLEBUFFER_BITMAP_FLAGS, BMF_CLEAR,\n\t\tTAG_DONE\n\t);\n\n\t// Prepare palette\n\ts_pMenuVPort->pPalette[0] = 0x000;\n\ts_pMenuVPort->pPalette[1] = 0xAAA;\n\ts_pMenuVPort->pPalette[2] = 0x666;\n\ts_pMenuVPort->pPalette[3] = 0xFFF;\n\ts_pMenuVPort->pPalette[4] = 0x111;\n\n\t// Load font\n\ts_pMenuFont = fontCreateFromPath(\"data/silkscreen.fnt\");\n\ts_pTextBitMap = fontCreateTextBitMap(320, s_pMenuFont->uwHeight);\n\n\t// Prepare menu lists\n\ts_pMenuList = menuListCreate(\n\t\t160, 100, 10, 2,\n\t\ts_pMenuFont, FONT_HCENTER|FONT_COOKIE|FONT_SHADOW,\n\t\t1, 2, 3,\n\t\ts_pMenuBfr->pBack\n\t);\n\tmenuShowMain();\n\n\t// Display view with its viewports\n\tviewLoad(s_pMenuView);\n\tlogBlockEnd(\"gsMenuCreate\");\n\tsystemUnuse();\n}\n\nvoid gsMenuLoop(void) {\n\tUBYTE ubSelected;\n\n\tif (keyUse(KEY_ESCAPE)) {\n\t\tif(s_ubMenuType == MENU_MAIN) {\n\t\t\tgameExit();\n\t\t}\n\t\telse {\n\t\t\tmenuShowMain();\n\t\t}\n\t\treturn;\n\t}\n\n\t// Menu list nav - up & down\n\tif(keyUse(KEY_UP) || joyUse(JOY1_UP)) {\n\t\tmenuListMove(s_pMenuList, -1);\n\t}\n\telse if(keyUse(KEY_DOWN) || joyUse(JOY1_DOWN)) {\n\t\tmenuListMove(s_pMenuList, +1);\n\t}\n\n\t// Menu list selection\n\telse if(keyUse(KEY_RETURN) || joyUse(JOY1_FIRE)) {\n\t\tubSelected = s_pMenuList->ubSelected;\n\t\tif(s_pMenuList->pEntries[ubSelected].ubDisplayMode == MENULIST_ENABLED) {\n\t\t\tswitch(s_ubMenuType) {\n\t\t\t\tcase MENU_MAIN: menuSelectMain(); return;\n\t\t\t\tcase MENU_TESTS: menuSelectTests(); return;\n\t\t\t\tcase MENU_EXAMPLES: menuSelectExamples(); return;\n\t\t\t}\n\t\t}\n\t}\n\tvPortWaitForEnd(s_pMenuVPort);\n\n\tstatic UBYTE ubFrameCnt = 0;\n\tstatic UBYTE ubColor = 1;\n\tstatic BYTE bDir = 1;\n\t++ubFrameCnt;\n\tif(ubFrameCnt == 7) {\n\t\tif(ubColor >= 7) {\n\t\t\tbDir = -1;\n\t\t}\n\t\telse if(ubColor <= 1) {\n\t\t\tbDir = 1;\n\t\t}\n\t\tubColor += bDir;\n\t\tubFrameCnt = 0;\n\t}\n\tg_pCustom->color[4] = (ubColor << 8) | (ubColor << 4) | (ubColor);\n}\n\nvoid gsMenuDestroy(void) {\n\tsystemUse();\n\tlogBlockBegin(\"gsMenuDestroy()\");\n\n\tmenuListDestroy(s_pMenuList);\n\tfontDestroyTextBitMap(s_pTextBitMap);\n\tfontDestroy(s_pMenuFont);\n\tviewDestroy(s_pMenuView);\n\n\tlogBlockEnd(\"gsMenuDestroy()\");\n}\n\nvoid menuDrawBg(void) {\n\tlogBlockBegin(\"menuDrawBg()\");\n\tUWORD uwX, uwY;\n\tUBYTE isOdd = 0;\n\n\t// Draw checkerboard\n\tfor(uwY = 0; uwY <= s_pMenuBfr->uBfrBounds.uwY - 16; uwY += 16) {\n\t\tfor(uwX = 0; uwX <= s_pMenuBfr->uBfrBounds.uwX - 16; uwX += 16) {\n\t\t\tUBYTE ubColor = isOdd ? 0 : 4;\n\t\t\tblitRect(s_pMenuBfr->pBack, uwX, uwY, 16, 16, ubColor);\n\t\t\tisOdd = !isOdd;\n\t\t}\n\t\tisOdd = !isOdd;\n\t}\n\n\t// Draw border\n\tUWORD uwMaxX = s_pMenuBfr->uBfrBounds.uwX-1;\n\tUWORD uwMaxY = s_pMenuBfr->uBfrBounds.uwY-1;\n\tblitLine(s_pMenuBfr->pBack, 0, 0, uwMaxX, 0, 1, 0xFFFF, 0);\n\tblitLine(s_pMenuBfr->pBack, 0, uwMaxY, uwMaxX, uwMaxY, 1, 0xFFFF, 0);\n\tblitLine(s_pMenuBfr->pBack, 0, 0, 0, uwMaxY, 1, 0xFFFF, 0);\n\tblitLine(s_pMenuBfr->pBack, uwMaxX, 0, uwMaxX, uwMaxY, 1, 0xFFFF, 0);\n\tlogBlockEnd(\"menuDrawBg()\");\n}\n\n/******************************************************* Main menu definition */\n\nvoid menuShowMain(void) {\n\tsystemUse();\n\tlogWrite(\"menuShowMain\\n\");\n\t// Draw BG\n\tmenuDrawBg();\n\tfontDrawStr(\n\t\ts_pMenuFont, s_pMenuBfr->pBack, s_pMenuBfr->uBfrBounds.uwX >> 1, 80,\n\t\t\"ACE Showcase\", 1, FONT_COOKIE|FONT_CENTER|FONT_SHADOW, s_pTextBitMap\n\t);\n\n\t// Prepare new list\n\ts_pMenuList->sCoord.uwX = s_pMenuBfr->uBfrBounds.uwX >> 1;\n\ts_pMenuList->sCoord.uwY = 100;\n\tmenuListResetCount(s_pMenuList, 3);\n\tmenuListSetEntry(s_pMenuList, 0, MENULIST_ENABLED, \"Tests\");\n\tmenuListSetEntry(s_pMenuList, 1, MENULIST_DISABLED, \"Examples\");\n\tmenuListSetEntry(s_pMenuList, 2, MENULIST_ENABLED, \"Quit\");\n\ts_ubMenuType = MENU_MAIN;\n\n\t// Redraw list\n\tmenuListDraw(s_pMenuList);\n\tsystemUnuse();\n}\n\nvoid menuSelectMain(void) {\n\tswitch(s_pMenuList->ubSelected) {\n\t\tcase 0:\n\t\t\tmenuShowTests();\n\t\t\tbreak;\n\t\tcase 1:\n\t\t\tmenuShowExamples();\n\t\t\tbreak;\n\t\tcase 2:\n\t\t\tgameExit();\n\t\t\treturn;\n\t}\n}\n\n/******************************************************* Test menu definition */\n\nvoid menuShowTests(void) {\n\tsystemUse();\n\t// Draw BG\n\tmenuDrawBg();\n\tfontDrawStr(\n\t\ts_pMenuFont, s_pMenuBfr->pBack, s_pMenuBfr->uBfrBounds.uwX >> 1, 80,\n\t\t\"Tests\", 1, FONT_COOKIE|FONT_CENTER|FONT_SHADOW, s_pTextBitMap\n\t);\n\n\t// Prepare new list\n\ts_pMenuList->sCoord.uwX = s_pMenuBfr->uBfrBounds.uwX >> 1;\n\ts_pMenuList->sCoord.uwY = 100;\n\tmenuListResetCount(s_pMenuList, TEST_STATE_COUNT);\n\tmenuListSetEntry(s_pMenuList, TEST_STATE_MENU, MENULIST_ENABLED, \"Back\");\n\tmenuListSetEntry(s_pMenuList, TEST_STATE_BLIT, MENULIST_ENABLED, \"Blits\");\n\tmenuListSetEntry(s_pMenuList, TEST_STATE_INPUT, MENULIST_ENABLED, \"Input\");\n\tmenuListSetEntry(s_pMenuList, TEST_STATE_FONT, MENULIST_ENABLED, \"Fonts\");\n\tmenuListSetEntry(s_pMenuList, TEST_STATE_COPPER, MENULIST_ENABLED, \"Copper\");\n\tmenuListSetEntry(s_pMenuList, TEST_STATE_LINES, MENULIST_ENABLED, \"Blitter shapes\");\n\tmenuListSetEntry(s_pMenuList, TEST_STATE_BLIT_SMALL_DEST, MENULIST_ENABLED, \"Blits with small dst\");\n\tmenuListSetEntry(s_pMenuList, TEST_STATE_INTERLEAVED, MENULIST_ENABLED, \"Interleaved bitmaps\");\n\tmenuListSetEntry(s_pMenuList, TEST_STATE_BUFFER_SCROLL, MENULIST_ENABLED, \"Scroll buffer wrap\");\n\tmenuListSetEntry(s_pMenuList, TEST_STATE_TWISTER, MENULIST_ENABLED, \"Twister\");\n\ts_ubMenuType = MENU_TESTS;\n\n\t// Redraw list\n\tmenuListDraw(s_pMenuList);\n\tsystemUnuse();\n}\n\nvoid menuSelectTests(void) {\n\tif (s_pMenuList->ubSelected) {\n\t\tstateChange(g_pGameStateManager, &g_pTestStates[s_pMenuList->ubSelected]);\n\t}\n\telse {\n\t\tmenuShowMain();\n\t}\n}\n\n/*************************************************** Examples menu definition */\n\nvoid menuShowExamples(void) {\n\tsystemUse();\n\t// Draw BG\n\tmenuDrawBg();\n\tfontDrawStr(\n\t\ts_pMenuFont, s_pMenuBfr->pBack, s_pMenuBfr->uBfrBounds.uwX >> 1, 80,\n\t\t\"Examples\", 1, FONT_COOKIE|FONT_CENTER|FONT_SHADOW, s_pTextBitMap\n\t);\n\n\t// Prepare new list\n\ts_pMenuList->sCoord.uwX = s_pMenuBfr->uBfrBounds.uwX >> 1;\n\ts_pMenuList->sCoord.uwY = 100;\n\tmenuListResetCount(s_pMenuList, 1);\n\tmenuListSetEntry(s_pMenuList, 0, MENULIST_ENABLED, \"Back\");\n\ts_ubMenuType = MENU_EXAMPLES;\n\n\t// Redraw list\n\tmenuListDraw(s_pMenuList);\n\tsystemUnuse();\n}\n\nvoid menuSelectExamples(void) {\n\tswitch(s_pMenuList->ubSelected) {\n\t\tcase 0:\n\t\t\tmenuShowMain();\n\t\t\tbreak;\n\t}\n}\n"
  },
  {
    "path": "showcase/src/menu/menu.h",
    "content": "/* This Source Code Form is subject to the terms of the Mozilla Public\r\n * License, v. 2.0. If a copy of the MPL was not distributed with this\r\n * file, You can obtain one at http://mozilla.org/MPL/2.0/. */\r\n\r\n#ifndef _SHOWCASE_MENU_MENU_H_\r\n#define _SHOWCASE_MENU_MENU_H_\r\n\r\n#include <ace/types.h>\r\n\r\n//---------------------------------------------------------------------- DEFINES\r\n\r\n#define MENU_MAIN 0\r\n#define MENU_TESTS 1\r\n#define MENU_EXAMPLES 2\r\n\r\n#define MENU_TEST_BLITRECT 10\r\n\r\n#define MENU_EXAMPLES_PONG 20\r\n\r\n//------------------------------------------------------------------------ TYPES\r\n\r\n//---------------------------------------------------------------------- GLOBALS\r\n\r\n//-------------------------------------------------------------------- FUNCTIONS\r\n\r\nvoid gsMenuCreate(void);\r\nvoid gsMenuLoop(void);\r\nvoid gsMenuDestroy(void);\r\n\r\nvoid menuDrawBg(void);\r\n\r\nvoid menuShowMain(void);\r\nvoid menuSelectMain(void);\r\n\r\nvoid menuShowTests(void);\r\nvoid menuSelectTests(void);\r\n\r\nvoid menuShowExamples(void);\r\nvoid menuSelectExamples(void);\r\n\r\n//---------------------------------------------------------------------- INLINES\r\n\r\n//----------------------------------------------------------------------- MACROS\r\n\r\n#endif // _SHOWCASE_MENU_MENU_H_\r\n"
  },
  {
    "path": "showcase/src/menu/menulist.c",
    "content": "/* This Source Code Form is subject to the terms of the Mozilla Public\r\n * License, v. 2.0. If a copy of the MPL was not distributed with this\r\n * file, You can obtain one at http://mozilla.org/MPL/2.0/. */\r\n\r\n#include \"menu/menulist.h\"\r\n#include <ace/managers/log.h>\r\n#include <ace/utils/font.h>\r\n\r\ntMenuList *menuListCreate(\r\n\tUWORD uwX, UWORD uwY, UBYTE ubMaxCount, UBYTE ubSpacing,\r\n\ttFont *pFont, UBYTE ubFontFlags,\r\n\tUBYTE ubColor, UBYTE ubColorDisabled, UBYTE ubColorSelected,\r\n\ttBitMap *pDestBitMap\r\n) {\r\n\ttMenuList *pList;\r\n\r\n\tpList = memAllocFast(sizeof(tMenuList));\r\n\tpList->pEntries = memAllocFastClear(ubMaxCount*sizeof(tMenuEntry));\r\n\tpList->ubMaxCount = ubMaxCount;\r\n\tpList->ubCount = 0;\r\n\tpList->ubSelected = 0;\r\n\r\n\tpList->pDestBitMap = pDestBitMap;\r\n\r\n\t// Font & colors\r\n\tpList->pFont = pFont;\r\n\tpList->ubColor = ubColor;\r\n\tpList->ubColorDisabled = ubColorDisabled;\r\n\tpList->ubColorSelected = ubColorSelected;\r\n\tpList->ubFontFlags = ubFontFlags;\r\n\r\n\t// Positioning & spacing\r\n\tpList->sCoord.uwX = uwX;\r\n\tpList->sCoord.uwY = uwY;\r\n\tpList->ubSpacing = ubSpacing;\r\n\r\n\tfor(UBYTE i = 0; i < ubMaxCount; ++i) {\r\n\t\tpList->pEntries[i].pBitMap = fontCreateTextBitMap(\r\n\t\t\t192, pList->pFont->uwHeight\r\n\t\t);\r\n\t}\r\n\r\n\treturn pList;\r\n}\r\n\r\nvoid menuListDestroy(tMenuList *pList) {\r\n\tfor(UBYTE i = 0; i < pList->ubMaxCount; ++i) {\r\n\t\tfontDestroyTextBitMap(pList->pEntries[i].pBitMap);\r\n\t}\r\n\tmemFree(pList->pEntries, pList->ubMaxCount * sizeof(tMenuEntry));\r\n\tmemFree(pList, sizeof(tMenuList));\r\n}\r\n\r\nvoid menuListSetEntry(tMenuList *pList, UBYTE ubIdx, UBYTE ubDisplay, char *szText) {\r\n\ttMenuEntry *pEntry;\r\n\r\n\tpEntry = &pList->pEntries[ubIdx];\r\n\tpEntry->ubDisplayMode = ubDisplay;\r\n\tpEntry->szText = szText;\r\n\r\n\t// Update text bitmap\r\n\tfontFillTextBitMap(pList->pFont, pEntry->pBitMap, szText);\r\n}\r\n\r\nvoid menuListDrawPos(tMenuList *pList, UBYTE ubIdx) {\r\n\tUBYTE ubColor;\r\n\tUWORD uwX, uwY;\r\n\r\n\tif(pList->pEntries[ubIdx].ubDisplayMode == MENULIST_HIDDEN) {\r\n\t\treturn;\r\n\t}\r\n\r\n\tuwX = pList->sCoord.uwX;\r\n\tuwY = pList->sCoord.uwY + ubIdx*(pList->ubSpacing+pList->pFont->uwHeight);\r\n\r\n\t// Color\r\n\tif(pList->pEntries[ubIdx].ubDisplayMode == MENULIST_DISABLED) {\r\n\t\tubColor = pList->ubColorDisabled;\r\n\t}\r\n\telse if (pList->ubSelected == ubIdx) {\r\n\t\tubColor = pList->ubColorSelected;\r\n\t}\r\n\telse {\r\n\t\tubColor = pList->ubColor;\r\n\t}\r\n\r\n\t// Drawing\r\n\tfontDrawTextBitMap(\r\n\t\tpList->pDestBitMap,\r\n\t\tpList->pEntries[ubIdx].pBitMap,\r\n\t\tuwX, uwY, ubColor, pList->ubFontFlags\r\n\t);\r\n}\r\n\r\nvoid menuListDraw(tMenuList *pList) {\r\n\tUBYTE i;\r\n\r\n\tfor (i = 0; i != pList->ubCount; ++i) {\r\n\t\tmenuListDrawPos(pList, i);\r\n\t}\r\n}\r\n\r\nvoid menuListMove(tMenuList *pList, BYTE bMoveDir) {\r\n\tUBYTE ubOldIdx;\r\n\r\n\tubOldIdx = pList->ubSelected;\r\n\tdo {\r\n\t\t// Move cursor according to direction\r\n\t\tif(!pList->ubSelected && bMoveDir == -1) {\r\n\t\t\tpList->ubSelected = pList->ubCount-1;\r\n\t\t}\r\n\t\telse if(pList->ubSelected == pList->ubCount-1 && bMoveDir == 1) {\r\n\t\t\tpList->ubSelected = 0;\r\n\t\t}\r\n\t\telse {\r\n\t\t\tpList->ubSelected += bMoveDir;\r\n\t\t}\r\n\t} while(pList->pEntries[pList->ubSelected].ubDisplayMode != MENULIST_ENABLED);\r\n\t// Redraw positions: old and new\r\n\tmenuListDrawPos(pList, ubOldIdx);\r\n\tmenuListDrawPos(pList, pList->ubSelected);\r\n}\r\n\r\nvoid menuListResetCount(tMenuList *pList, UBYTE ubCount) {\r\n\tpList->ubCount = ubCount;\r\n\tpList->ubSelected = 0;\r\n}\r\n"
  },
  {
    "path": "showcase/src/menu/menulist.h",
    "content": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at http://mozilla.org/MPL/2.0/. */\n\n#ifndef _SHOWCASE_MENU_MENULIST_H_\n#define _SHOWCASE_MENU_MENULIST_H_\n\n#include <ace/types.h>\n#include <ace/types.h>\n#include <ace/utils/font.h>\n\n//---------------------------------------------------------------------- DEFINES\n\n#define MENULIST_HIDDEN 0\n#define MENULIST_DISABLED 1\n#define MENULIST_ENABLED 2\n\n//------------------------------------------------------------------------ TYPES\n\ntypedef void (*tMenuActivateCb)(void);\n\ntypedef struct _tMenuEntry {\n\tchar *szText;        ///< Displayed text\n\tUBYTE ubDisplayMode; ///< see MENULIST_* defines\n\ttTextBitMap *pBitMap;\n} tMenuEntry;\n\ntypedef struct _tMenuList {\n\ttUwCoordYX sCoord;     ///< Top-left point of list,\n\t                       ///< centering must be done by ubFontFlags\n\ttMenuEntry *pEntries;  ///< Entry array\n\ttBitMap *pDestBitMap;  ///< BitMap to redraw on\n\ttFont *pFont;          ///< Font for drawing list\n\tUBYTE ubFontFlags;     ///< Font flags for drawing list\n\tUBYTE ubColor;         ///< Color idx for drawing list\n\tUBYTE ubColorDisabled; ///< Ditto, disabled pos\n\tUBYTE ubColorSelected; ///< Ditto, selected pos\n\tUBYTE ubSpacing;       ///< Y-space between positions\n\tUBYTE ubCount;         ///< Entry count on list\n\tUBYTE ubMaxCount;\n\tUBYTE ubSelected;      ///< Currently selected entry\n} tMenuList;\n\ntypedef void (*tMenuSelectCb)(struct _tMenuList *pList, UBYTE ubPosIdx);\n\n//---------------------------------------------------------------------- GLOBALS\n\n//-------------------------------------------------------------------- FUNCTIONS\n\ntMenuList *menuListCreate(\n\tUWORD uwX, UWORD uwY, UBYTE ubCount, UBYTE ubSpacing,\n\ttFont *pFont, UBYTE ubFontFlags,\n\tUBYTE ubColor, UBYTE ubColorDisabled, UBYTE ubColorSelected,\n\ttBitMap *pDestBitMap\n);\n\nvoid menuListDestroy(tMenuList *pList);\n\nvoid menuListSetEntry(\n\ttMenuList *pList, UBYTE ubIdx, UBYTE ubDisplay, char *szText\n);\n\nvoid menuListDrawPos(tMenuList *pList, UBYTE ubIdx);\n\nvoid menuListDraw(tMenuList *pList);\n\nvoid menuListMove(tMenuList *pList, BYTE bMoveDir);\n\nvoid menuListResetCount(tMenuList *pList, UBYTE ubCount);\n\n//---------------------------------------------------------------------- INLINES\n\n//----------------------------------------------------------------------- MACROS\n\n#endif // _SHOWCASE_MENU_MENULIST_H_\n"
  },
  {
    "path": "showcase/src/test/blit.c",
    "content": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at http://mozilla.org/MPL/2.0/. */\n\n#include \"test/blit.h\"\n#include <ace/utils/extview.h>\n#include <ace/managers/blit.h>\n#include <ace/managers/key.h>\n#include <ace/managers/joy.h>\n#include <ace/managers/system.h>\n#include <ace/managers/viewport/simplebuffer.h>\n#include <ace/generic/screen.h>\n#include \"game.h\"\n\nstatic tView *s_pTestBlitView;\nstatic tVPort *s_pTestBlitVPort;\nstatic tSimpleBufferManager *s_pTestBlitBfr;\n\nstatic UWORD s_uwX, s_uwY;\nstatic UBYTE s_ubType;\nstatic UBYTE (*s_fnKeyPoll)(UBYTE ubKeyCode);\n\nvoid gsTestBlitCreate(void) {\n\t// Prepare view & viewport\n\ts_pTestBlitView = viewCreate(0, TAG_DONE);\n\ts_pTestBlitVPort = vPortCreate(0,\n\t\tTAG_VPORT_VIEW, s_pTestBlitView,\n\t\tTAG_VPORT_BPP, SHOWCASE_BPP,\n\t\tTAG_DONE\n\t);\n\ts_pTestBlitBfr = simpleBufferCreate(0,\n\t\tTAG_SIMPLEBUFFER_VPORT, s_pTestBlitVPort,\n\t\tTAG_SIMPLEBUFFER_BITMAP_FLAGS, BMF_CLEAR,\n\t\tTAG_DONE\n\t);\n\ts_pTestBlitVPort->pPalette[0] = 0x000;\n\ts_pTestBlitVPort->pPalette[1] = 0xAAA;\n\ts_pTestBlitVPort->pPalette[2] = 0x666;\n\ts_pTestBlitVPort->pPalette[3] = 0xFFF;\n\ts_pTestBlitVPort->pPalette[4] = 0x111;\n\n\t// Loop vars\n\ts_uwX = s_pTestBlitBfr->uBfrBounds.uwX >> 1;\n\ts_uwY = s_pTestBlitBfr->uBfrBounds.uwY >> 1;\n\ts_ubType = TYPE_RECT;\n\ts_fnKeyPoll = keyUse;\n\n\t// Display view with its viewports\n\tsystemUnuse();\n\tviewLoad(s_pTestBlitView);\n}\n\nvoid gsTestBlitLoop(void) {\n\tstatic BYTE bSpeedX = 0, bSpeedY = 0;\n\n\tif (keyUse(KEY_ESCAPE)) {\n\t\tstateChange(g_pGameStateManager, &g_pTestStates[TEST_STATE_MENU]);\n\t\treturn;\n\t}\n\n\t// Erase previous blit using old type & coords\n\tif(s_ubType & TYPE_SAVEBG) {\n\t\t//TODO: Restore BG\n\t}\n\telse {\n\t\tblitRect(s_pTestBlitBfr->pBack, s_uwX, s_uwY, 16, 16, 0);\n\t}\n\n\t// Update type\n\n\t// Rapid movement\n\tif(keyUse(KEY_R)) {\n\t\ts_ubType ^= TYPE_RAPID;\n\t\tif(s_ubType & TYPE_RAPID) {\n\t\t\ts_fnKeyPoll = keyCheck;\n\t\t}\n\t\telse {\n\t\t\ts_fnKeyPoll = keyUse;\n\t\t}\n\t}\n\n\t// Auto movement\n\tif(keyUse(KEY_A)) {\n\t\ts_ubType ^= TYPE_AUTO;\n\t\tif(s_ubType & TYPE_AUTO) {\n\t\t\tbSpeedX = 1;\n\t\t\tbSpeedY = 1;\n\t\t}\n\t}\n\n\t// Save BG\n\tif(keyUse(KEY_B)) {\n\t\ts_ubType ^= TYPE_SAVEBG;\n\t\tif(s_ubType & TYPE_SAVEBG) {\n\t\t\t// TODO: Draw whole BG\n\t\t}\n\t}\n\n\t// Rect mode\n\tif(keyUse(KEY_1)) {\n\t\ts_ubType = TYPE_RECT;\n\t}\n\n\tif(s_ubType & TYPE_AUTO) {\n\t\tif(bSpeedX > 0) {\n\t\t\tif(s_uwX < s_pTestBlitBfr->uBfrBounds.uwX - 16) {\n\t\t\t\t++s_uwX;\n\t\t\t}\n\t\t\telse {\n\t\t\t\tbSpeedX = -1;\n\t\t\t}\n\t\t}\n\t\telse if(bSpeedX < 0) {\n\t\t\tif(s_uwX) {\n\t\t\t\t--s_uwX;\n\t\t\t}\n\t\t\telse {\n\t\t\t\tbSpeedX = 1;\n\t\t\t}\n\t\t}\n\n\t\tif(bSpeedY > 0) {\n\t\t\tif(s_uwY < 256-16) {\n\t\t\t\t++s_uwY;\n\t\t\t}\n\t\t\telse {\n\t\t\t\tbSpeedY = -1;\n\t\t\t}\n\t\t}\n\t\telse if(bSpeedY < 0) {\n\t\t\tif(s_uwY) {\n\t\t\t\t--s_uwY;\n\t\t\t}\n\t\t\telse {\n\t\t\t\tbSpeedY = 1;\n\t\t\t}\n\t\t}\n\t}\n\telse {\n\t\tif(s_fnKeyPoll(KEY_UP) && s_uwY) {\n\t\t\t--s_uwY;\n\t\t}\n\t\tif(s_fnKeyPoll(KEY_DOWN) && s_uwY < s_pTestBlitBfr->uBfrBounds.uwY-16) {\n\t\t\t++s_uwY;\n\t\t}\n\t\tif(s_fnKeyPoll(KEY_LEFT) && s_uwX) {\n\t\t\t--s_uwX;\n\t\t}\n\t\tif(s_fnKeyPoll(KEY_RIGHT) && s_uwX < s_pTestBlitBfr->uBfrBounds.uwY-16) {\n\t\t\t++s_uwX;\n\t\t}\n\t}\n\n\t// Reblit using new type & coords\n\tif(s_ubType & TYPE_SAVEBG) {\n\t\t//TODO: Save BG beneath new bob\n\t}\n\t// if(s_ubType & TYPE_RECT) {\n\t\tblitRect(s_pTestBlitBfr->pBack, s_uwX, s_uwY, 16, 16, 3);\n\t// }\n\tvPortWaitForEnd(s_pTestBlitVPort);\n}\n\nvoid gsTestBlitDestroy(void) {\n\tviewLoad(0);\n\tsystemUse();\n\t// Destroy buffer, view & viewport\n\tviewDestroy(s_pTestBlitView);\n}\n"
  },
  {
    "path": "showcase/src/test/blit.h",
    "content": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at http://mozilla.org/MPL/2.0/. */\n\n#ifndef _SHOWCASE_TEST_BLIT_H_\n#define _SHOWCASE_TEST_BLIT_H_\n\n//---------------------------------------------------------------------- DEFINES\n\n#define TYPE_RECT 0\n#define TYPE_AUTO 128\n#define TYPE_RAPID 64\n#define TYPE_SAVEBG 32\n\n//------------------------------------------------------------------------ TYPES\n\n//---------------------------------------------------------------------- GLOBALS\n\n//-------------------------------------------------------------------- FUNCTIONS\n\nvoid gsTestBlitCreate(void);\nvoid gsTestBlitLoop(void);\nvoid gsTestBlitDestroy(void);\n\n//---------------------------------------------------------------------- INLINES\n\n//----------------------------------------------------------------------- MACROS\n\n#endif // _SHOWCASE_TEST_BLIT_H_\n"
  },
  {
    "path": "showcase/src/test/blitsmalldest.c",
    "content": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at http://mozilla.org/MPL/2.0/. */\n\n#include \"test/blitsmalldest.h\"\n#include <ace/utils/extview.h>\n#include <ace/utils/palette.h>\n#include <ace/managers/blit.h>\n#include <ace/managers/key.h>\n#include <ace/managers/joy.h>\n#include <ace/managers/viewport/simplebuffer.h>\n#include <ace/managers/system.h>\n#include <ace/generic/screen.h>\n#include \"game.h\"\n\nstatic tView *s_pTestBlitView;\nstatic tVPort *s_pTestBlitVPort;\nstatic tSimpleBufferManager *s_pTestBlitBfr;\n\nstatic tBitMap *s_pRefBitmap;\nstatic tBitMap *s_pDstBitmap;\nUBYTE ubFrameIdx;\n\nvoid prepareRefBitmap(void) {\n\tUBYTE ubBlockWidth = 32;\n\tUBYTE ubBlockHeight = 32;\n\tUBYTE ubImageCount = 16;\n\tUBYTE i;\n\n\ts_pRefBitmap = bitmapCreate(ubBlockWidth+ubImageCount, ubBlockHeight*ubImageCount, SHOWCASE_BPP, 0);\n\n\tfor(i = 0; i != ubImageCount; ++i) {\n\t\tblitRect(s_pRefBitmap, 0+i, 0+ubBlockHeight*i, ubBlockWidth, ubBlockHeight, 2);   // fill\n\t\tblitRect(s_pRefBitmap, 0+i, 0+ubBlockHeight*i, ubBlockWidth, 1, 1);               // top\n\t\tblitRect(s_pRefBitmap, 0+i, ubBlockHeight+ubBlockHeight*i-1, ubBlockWidth, 1, 1); // bottom\n\t\tblitRect(s_pRefBitmap, 0+i, 0+ubBlockHeight*i, 1, ubBlockHeight, 1);              // left\n\t\tblitRect(s_pRefBitmap, ubBlockWidth+i, 0+ubBlockHeight*i, 1, ubBlockHeight, 1);   // right\n\t}\n\n}\n\nvoid gsTestBlitSmallDestCreate(void) {\n\t// Prepare view & viewport\n\ts_pTestBlitView = viewCreate(0, TAG_DONE);\n\ts_pTestBlitVPort = vPortCreate(0,\n\t\tTAG_VPORT_VIEW, s_pTestBlitView,\n\t\tTAG_VPORT_BPP, SHOWCASE_BPP,\n\t\tTAG_DONE\n\t);\n\ts_pTestBlitBfr = simpleBufferCreate(0,\n\t\tTAG_SIMPLEBUFFER_VPORT, s_pTestBlitVPort,\n\t\tTAG_SIMPLEBUFFER_BITMAP_FLAGS, BMF_CLEAR,\n\t\tTAG_DONE\n\t);\n\tpaletteLoadFromPath(\"data/blitToSmall.plt\", s_pTestBlitVPort->pPalette, 1 << SHOWCASE_BPP);\n\n\ts_pDstBitmap = bitmapCreate(32, 32, SHOWCASE_BPP, 0);\n\tprepareRefBitmap();\n\tubFrameIdx = 0;\n\n\t// Display view with its viewports\n\tviewLoad(s_pTestBlitView);\n\tsystemUnuse();\n}\n\nvoid gsTestBlitSmallDestLoop(void) {\n\tBYTE bUpdate = 0;\n\n\tif (keyUse(KEY_ESCAPE)) {\n\t\tstateChange(g_pGameStateManager, &g_pTestStates[TEST_STATE_MENU]);\n\t\treturn;\n\t}\n\tif(keyUse(KEY_RIGHT)) {\n\t\tbUpdate += 1;\n\t}\n\tif(keyUse(KEY_LEFT)) {\n\t\tbUpdate -=1;\n\t}\n\n\tif(bUpdate && ubFrameIdx + bUpdate > -1 && ubFrameIdx + bUpdate < 16) {\n\t\tubFrameIdx += bUpdate;\n\t\tblitRect(\n\t\t\ts_pTestBlitBfr->pBack, 0, 0,\n\t\t\ts_pTestBlitBfr->uBfrBounds.uwX,\n\t\t\ts_pTestBlitBfr->uBfrBounds.uwY,\n\t\t\t0\n\t\t);\n\t\tblitCopy(s_pRefBitmap, ubFrameIdx, ubFrameIdx*32, s_pDstBitmap, 0, 0, 32, 32, 0xCA);\n\t\tblitCopyAligned(s_pDstBitmap, 0, 0, s_pTestBlitBfr->pBack, 16, 16, 32, 32);\n\t}\n\n\tvPortWaitForEnd(s_pTestBlitVPort);\n}\n\nvoid gsTestBlitSmallDestDestroy(void) {\n\tsystemUse();\n\t// Destroy buffer, view & viewport\n\tviewDestroy(s_pTestBlitView);\n\n\tbitmapDestroy(s_pDstBitmap);\n\tbitmapDestroy(s_pRefBitmap);\n}\n"
  },
  {
    "path": "showcase/src/test/blitsmalldest.h",
    "content": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at http://mozilla.org/MPL/2.0/. */\n\n#ifndef _SHOWCASE_TEST_BLITSMALLDEST_H_\n#define _SHOWCASE_TEST_BLITSMALLDEST_H_\n\n//---------------------------------------------------------------------- DEFINES\n\n//------------------------------------------------------------------------ TYPES\n\n//---------------------------------------------------------------------- GLOBALS\n\n//-------------------------------------------------------------------- FUNCTIONS\n\nvoid gsTestBlitSmallDestCreate(void);\nvoid gsTestBlitSmallDestLoop(void);\nvoid gsTestBlitSmallDestDestroy(void);\n\n//---------------------------------------------------------------------- INLINES\n\n//----------------------------------------------------------------------- MACROS\n\n#endif // _SHOWCASE_TEST_BLITSMALLDEST_H_\n"
  },
  {
    "path": "showcase/src/test/buffer_scroll.c",
    "content": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at http://mozilla.org/MPL/2.0/. */\n\n#include \"buffer_scroll.h\"\n#include <ace/managers/key.h>\n#include <ace/managers/system.h>\n#include <ace/managers/viewport/scrollbuffer.h>\n#include <ace/managers/viewport/simplebuffer.h>\n#include <ace/utils/palette.h>\n#include <ace/utils/font.h>\n#include \"game.h\"\n\n#define TEST_SCROLL_BPP 4\n\ntypedef enum tMode {\n\tMODE_SIMPLE_LORES,\n\tMODE_SIMPLE_HIRES,\n\tMODE_SCROLL_LORES,\n\tMODE_SCROLL_HIRES,\n\tMODE_COUNT\n} tMode;\n\nstatic const char *s_pModeNames[MODE_COUNT] = {\n\t[MODE_SIMPLE_LORES] = \"lores simplebuffer\",\n\t[MODE_SIMPLE_HIRES] = \"hires simplebuffer\",\n\t[MODE_SCROLL_LORES] = \"lores scrollbuffer\",\n\t[MODE_SCROLL_HIRES] = \"hires scrollbuffer\",\n};\n\nstatic tMode s_eCurrentMode;\nstatic tView *s_pView;\nstatic tVPort *s_pVPort;\nstatic tCameraManager *s_pCamera;\nstatic tFont *s_pFont;\nstatic tTextBitMap *s_pTextBitMap;\n\nstatic void drawModeInfo(tBitMap *pBfr, UWORD uwX, UWORD uwY) {\n\tchar szMsg[50];\n\tsprintf(szMsg, \"Current mode is %s\", s_pModeNames[s_eCurrentMode]);\n\tfontDrawStr(s_pFont, pBfr, uwX, uwY + 0 * 10, szMsg, 6, FONT_COOKIE, s_pTextBitMap);\n\tfontDrawStr(s_pFont, pBfr, uwX, uwY + 1 * 10, \"WSAD to navigate\", 6, FONT_COOKIE, s_pTextBitMap);\n\tfor(UBYTE i = 0; i < 4; ++i) {\n\t\tsprintf(szMsg, \"%d to %s\", i + 1, s_pModeNames[i]);\n\t\tfontDrawStr(s_pFont, pBfr, uwX, uwY + (2 + i) * 10, szMsg, 6, FONT_COOKIE, s_pTextBitMap);\n\t}\n}\n\nstatic void fillBfr(tBitMap *pBfr, UWORD uwWidth, UWORD uwHeight) {\n\tlogBlockBegin(\n\t\t\"fillBfr(pBfr: *%p, uwWidth: %hu, uwHeight: %hu)\",\n\t\tpBfr, uwWidth, uwHeight\n\t);\n\tuwWidth -= 1;\n\tuwHeight -= 1;\n\n\t// Short lines\n\tfor(UWORD x = 10; x <= uwWidth; x += 10) {\n\t\tblitRect(pBfr, x,          0, 1, 3, 7);\n\t\tblitRect(pBfr, x, uwHeight-3, 1, 3, 7);\n\t}\n\tfor(UWORD y = 10; y <= uwHeight; y += 10) {\n\t\tblitRect(pBfr,         0, y, 3, 1, 7);\n\t\tblitRect(pBfr, uwWidth-3, y, 3, 1, 7);\n\t}\n\n\t// Long lines\n\tfor(UWORD x = 100; x <= uwWidth; x += 100) {\n\t\tblitRect(pBfr, x,          0, 1, 5, 7);\n\t\tblitRect(pBfr, x, uwHeight-5, 1, 5, 7);\n\t}\n\tfor(UWORD y = 100; y <= uwHeight; y += 100) {\n\t\tblitRect(pBfr,         0, y, 5, 1, 7);\n\t\tblitRect(pBfr, uwWidth-5, y, 5, 1, 7);\n\t}\n\n\t// Border\n\tblitRect(pBfr,       0,        0, uwWidth,        1, 6);\n\tblitRect(pBfr,       0, uwHeight, uwWidth,        1, 6);\n\tblitRect(pBfr,       0,        0,       1, uwHeight, 6);\n\tblitRect(pBfr, uwWidth,        0,       1, uwHeight, 6);\n\n\tdrawModeInfo(pBfr, 50, 50);\n\tlogBlockEnd(\"fillBfr()\");\n}\n\nstatic void initSimpleBuffer(UBYTE isHires, UWORD uwWidth, UWORD uwHeight) {\n\tviewLoad(0);\n\tsystemUse();\n\tif(s_pView->pFirstVPort) {\n\t\tvPortDestroy(s_pView->pFirstVPort);\n\t}\n\n\ts_pVPort = vPortCreate(0,\n\t\tTAG_VPORT_VIEW, s_pView,\n\t\tTAG_VPORT_BPP, TEST_SCROLL_BPP,\n\t\tTAG_VPORT_HIRES, isHires,\n\tTAG_DONE);\n\tpaletteLoadFromPath(\"data/amidb32.plt\", s_pVPort->pPalette, 1 << SHOWCASE_BPP);\n\n\ttSimpleBufferManager *s_pBfr = simpleBufferCreate(0,\n\t\tTAG_SIMPLEBUFFER_VPORT, s_pVPort,\n\t\tTAG_SIMPLEBUFFER_BITMAP_FLAGS, BMF_CLEAR | BMF_INTERLEAVED,\n\t\tTAG_SIMPLEBUFFER_BOUND_WIDTH, uwWidth,\n\t\tTAG_SIMPLEBUFFER_BOUND_HEIGHT, uwHeight,\n\tTAG_DONE);\n\ts_pCamera = s_pBfr->pCamera;\n\n\tfillBfr(s_pBfr->pBack, uwWidth, uwHeight);\n\n\tviewLoad(s_pView);\n\tsystemUnuse();\n}\n\nstatic void initScrollBuffer(UBYTE isHires) {\n\tviewLoad(0);\n\tsystemUse();\n\tif(s_pView->pFirstVPort) {\n\t\tvPortDestroy(s_pView->pFirstVPort);\n\t}\n\n\ts_pVPort = vPortCreate(0,\n\t\tTAG_VPORT_VIEW, s_pView,\n\t\tTAG_VPORT_BPP, TEST_SCROLL_BPP,\n\t\tTAG_VPORT_HIRES, isHires,\n\tTAG_DONE);\n\tpaletteLoadFromPath(\"data/amidb32.plt\", s_pVPort->pPalette, 1 << SHOWCASE_BPP);\n\n\t// This will create buffer which is shorter than 640 with capability of\n\t// wrapped scrolling to simulate bigger buffer size\n\ttScrollBufferManager *s_pBfr = scrollBufferCreate(0,\n\t\tTAG_SCROLLBUFFER_VPORT, s_pVPort,\n\t\tTAG_SCROLLBUFFER_BITMAP_FLAGS, BMF_CLEAR | BMF_INTERLEAVED,\n\t\tTAG_SCROLLBUFFER_BOUND_WIDTH, 1024,\n\t\tTAG_SCROLLBUFFER_BOUND_HEIGHT, 600,\n\t\tTAG_SCROLLBUFFER_MARGIN_WIDTH, 32,\n\tTAG_DONE);\n\ts_pCamera = s_pBfr->pCamera;\n\n\tfillBfr(\n\t\ts_pBfr->pBack,\n\t\tbitmapGetByteWidth(s_pBfr->pBack) * 8, s_pBfr->uwBmAvailHeight\n\t);\n\n\t// Ensure that scroll buffer y-wraps nicely\n\tUBYTE ubColor = (1 << TEST_SCROLL_BPP) - 1;\n\tblitRect(s_pBfr->pBack, 0, 508, 1, 1, ubColor);\n\tblitRect(s_pBfr->pBack, 0, 509, 2, 1, ubColor);\n\tblitRect(s_pBfr->pBack, 0, 510, 3, 1, ubColor);\n\tblitRect(s_pBfr->pBack, 0, 511, 4, 1, ubColor);\n\tblitRect(s_pBfr->pBack, 0, 0, 5, 1, ubColor);\n\tblitRect(s_pBfr->pBack, 0, 1, 4, 1, ubColor);\n\tblitRect(s_pBfr->pBack, 0, 2, 3, 1, ubColor);\n\tblitRect(s_pBfr->pBack, 0, 3, 2, 1, ubColor);\n\tblitRect(s_pBfr->pBack, 0, 4, 1, 1, ubColor);\n\n\tblitRect(s_pBfr->pBack, 16, 16, 32, 32, 5);\n\n\tdrawModeInfo(s_pBfr->pBack, 50, 50);\n\n\tviewLoad(s_pView);\n\tsystemUnuse();\n}\n\nstatic void changeMode(tMode eMode) {\n\ts_eCurrentMode = eMode;\n\tswitch(eMode) {\n\t\tcase MODE_SIMPLE_LORES:\n\t\t\tinitSimpleBuffer(0, 400, 300);\n\t\t\tbreak;\n\t\tcase MODE_SIMPLE_HIRES:\n\t\t\tinitSimpleBuffer(1, 720, 300);\n\t\t\tbreak;\n\t\tcase MODE_SCROLL_LORES:\n\t\t\tinitScrollBuffer(0);\n\t\t\tbreak;\n\t\tcase MODE_SCROLL_HIRES:\n\t\t\tinitScrollBuffer(1);\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tbreak;\n\t}\n}\n\nvoid gsTestBufferScrollCreate(void) {\n\tlogBlockBegin(\"gsTestBufferScrollCreate()\");\n\n\ts_pView = viewCreate(0,\n\tTAG_DONE);\n\n\ts_pFont = fontCreateFromPath(\"data/silkscreen.fnt\");\n\ts_pTextBitMap = fontCreateTextBitMap(320, s_pFont->uwHeight);\n\ts_eCurrentMode = MODE_SIMPLE_LORES;\n\tchangeMode(s_eCurrentMode);\n\tlogBlockEnd(\"gsTestBufferScrollCreate()\");\n\tsystemUnuse();\n}\n\nvoid gsTestBufferScrollLoop(void) {\n\tif (keyUse(KEY_ESCAPE)) {\n\t\tstateChange(g_pGameStateManager, &g_pTestStates[TEST_STATE_MENU]);\n\t\treturn;\n\t}\n\n\tWORD wDx = 0, wDy = 0;\n\tif(keyCheck(KEY_W)) {\n\t\twDy = -1;\n\t}\n\telse if(keyCheck(KEY_S)) {\n\t\twDy = 1;\n\t}\n\tif(keyCheck(KEY_A)) {\n\t\twDx = -1;\n\t}\n\tif(keyCheck(KEY_D)) {\n\t\twDx = 1;\n\t}\n\n\tif(keyUse(KEY_1)) {\n\t\tchangeMode(MODE_SIMPLE_LORES);\n\t}\n\telse if(keyUse(KEY_2)) {\n\t\tchangeMode(MODE_SIMPLE_HIRES);\n\t}\n\telse if(keyUse(KEY_3)) {\n\t\tchangeMode(MODE_SCROLL_LORES);\n\t}\n\telse if(keyUse(KEY_4)) {\n\t\tchangeMode(MODE_SCROLL_HIRES);\n\t}\n\n\tcameraMoveBy(s_pCamera, wDx, wDy);\n\tviewProcessManagers(s_pView);\n\tcopProcessBlocks();\n\tvPortWaitForEnd(s_pVPort);\n}\n\nvoid gsTestBufferScrollDestroy(void) {\n\tlogBlockBegin(\"gsTestBufferScrollDestroy()\");\n\tsystemUse();\n\tviewDestroy(s_pView);\n\n\tfontDestroy(s_pFont);\n\tfontDestroyTextBitMap(s_pTextBitMap);\n\n\tlogBlockEnd(\"gsTestBufferScrollDestroy()\");\n}\n"
  },
  {
    "path": "showcase/src/test/buffer_scroll.h",
    "content": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at http://mozilla.org/MPL/2.0/. */\n\n#ifndef _SHOWCASE_TEST_BUFFER_SCROLL_H_\n#define _SHOWCASE_TEST_BUFFER_SCROLL_H_\n\n//---------------------------------------------------------------------- DEFINES\n\n//------------------------------------------------------------------------ TYPES\n\n//---------------------------------------------------------------------- GLOBALS\n\n//-------------------------------------------------------------------- FUNCTIONS\n\nvoid gsTestBufferScrollCreate(void);\nvoid gsTestBufferScrollLoop(void);\nvoid gsTestBufferScrollDestroy(void);\n\n//---------------------------------------------------------------------- INLINES\n\n//----------------------------------------------------------------------- MACROS\n\n#endif // _SHOWCASE_TEST_BUFFER_SCROLL_H_\n"
  },
  {
    "path": "showcase/src/test/copper.c",
    "content": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at http://mozilla.org/MPL/2.0/. */\n\n#include \"test/copper.h\"\n#include <ace/utils/extview.h>\n#include <ace/managers/copper.h>\n#include <ace/managers/blit.h>\n#include <ace/managers/key.h>\n#include <ace/managers/joy.h>\n#include <ace/managers/system.h>\n#include <ace/managers/viewport/simplebuffer.h>\n#include \"game.h\"\n\nstatic tView *s_pTestCopperView;\nstatic tVPort *s_pTestCopperVPort;\nstatic tSimpleBufferManager *s_pTestCopperBfr;\n\nstatic UBYTE s_isRawMode = 0;\nstatic UWORD s_uwCopRawOffs;\n\nstatic tCopBlock *s_pBarBlocks[32];\n\nstatic UWORD s_uwBarY = 160;\nstatic UBYTE s_ubBarHue = 0;\n\n/**\n * Converts 24-bit HSV to 12-bit RGB\n * This fn is messy copypasta from stackoverflow to make it run on 12-bit.\n */\nstatic UWORD colorHSV(UBYTE ubH, UBYTE ubS, UBYTE ubV) {\n\tUBYTE ubRegion, ubRem, p, q, t;\n\n\tif (ubS == 0) {\n\t\tubV >>= 4; // 12-bit fit\n\t\treturn (ubV << 8) | (ubV << 4) | ubV;\n\t}\n\n\tubRegion = ubH / 43;\n\tubRem = (ubH - (ubRegion * 43)) * 6;\n\n\tp = (ubV * (255 - ubS)) >> 8;\n\tq = (ubV * (255 - ((ubS * ubRem) >> 8))) >> 8;\n\tt = (ubV * (255 - ((ubS * (255 - ubRem)) >> 8))) >> 8;\n\n\tubV >>= 4; p >>= 4; q >>= 4; t >>= 4; // 12-bit fit\n\tswitch (ubRegion) {\n\t\tcase 0:\n\t\t\treturn (ubV << 8) | (t << 4) | p;\n\t\tcase 1:\n\t\t\treturn (q << 8) | (ubV << 4) | p;\n\t\tcase 2:\n\t\t\treturn (p << 8) | (ubV << 4) | t;\n\t\tcase 3:\n\t\t\treturn (p << 8) | (q << 4) | ubV;\n\t\tcase 4:\n\t\t\treturn (t << 8) | (p << 4) | ubV;\n\t\tdefault:\n\t\t\treturn (ubV << 8) | (p << 4) | q;\n\t}\n}\n\n#define TEST_COPPER_COLOR_INSIDE 1\n#define TEST_COPPER_COLOR_BORDER 2\n\nvoid gsTestCopperCreate(void) {\n\t// Prepare view & viewport\n\tULONG ulMode = VIEW_COPLIST_MODE_BLOCK;\n\tULONG ulRawSize = 0;\n\tif(s_isRawMode) {\n\t\tulMode = VIEW_COPLIST_MODE_RAW;\n\t\tulRawSize = (\n\t\t\tsimpleBufferGetRawCopperlistInstructionCount(SHOWCASE_BPP) +\n\t\t\t32 * 2 + // 32 bars - each consists of WAIT + MOVE instruction\n\t\t\t1 + // Final WAIT\n\t\t\t1 // Just to be sure\n\t\t);\n\t}\n\n\ts_pTestCopperView = viewCreate(0,\n\t\tTAG_VIEW_COPLIST_MODE, ulMode,         // <-- This is important in RAW mode\n\t\tTAG_VIEW_COPLIST_RAW_COUNT, ulRawSize, // <-- This is important in RAW mode\n\t\tTAG_DONE\n\t);\n\n\ts_pTestCopperVPort = vPortCreate(0,\n\t\tTAG_VPORT_VIEW, s_pTestCopperView,\n\t\tTAG_VPORT_BPP, SHOWCASE_BPP,\n\t\tTAG_DONE\n\t);\n\n\ts_uwCopRawOffs = 0;\n\ts_pTestCopperBfr = simpleBufferCreate(0,\n\t\tTAG_SIMPLEBUFFER_VPORT, s_pTestCopperVPort,\n\t\tTAG_SIMPLEBUFFER_BITMAP_FLAGS, BMF_CLEAR,\n\t\tTAG_SIMPLEBUFFER_COPLIST_OFFSET, s_uwCopRawOffs, // <-- Important in RAW mode\n\t\tTAG_DONE\n\t);\n\ts_uwCopRawOffs += simpleBufferGetRawCopperlistInstructionCount(SHOWCASE_BPP);\n\n\t// Some dummy palette for borders etc.\n\ts_pTestCopperVPort->pPalette[0] = 0x000;\n\ts_pTestCopperVPort->pPalette[TEST_COPPER_COLOR_INSIDE] = 0xAAA;\n\ts_pTestCopperVPort->pPalette[TEST_COPPER_COLOR_BORDER] = 0x666;\n\n\t// Clear viewport, draw border around it\n\tUWORD uwMaxX = s_pTestCopperBfr->uBfrBounds.uwX-1;\n\tUWORD uwMaxY = s_pTestCopperBfr->uBfrBounds.uwY-1;\n\tblitRect(\n\t\ts_pTestCopperBfr->pBack, 0,0,\n\t\ts_pTestCopperBfr->uBfrBounds.uwX,\n\t\ts_pTestCopperBfr->uBfrBounds.uwY,\n\t\tTEST_COPPER_COLOR_INSIDE\n\t);\n\tblitLine(\n\t\ts_pTestCopperBfr->pBack, 0, 0, uwMaxX, 0,\n\t\tTEST_COPPER_COLOR_BORDER, 0xFFFF, 0\n\t);\n\tblitLine(\n\t\ts_pTestCopperBfr->pBack, 0, uwMaxY, uwMaxX, uwMaxY,\n\t\tTEST_COPPER_COLOR_BORDER, 0xFFFF, 0\n\t);\n\tblitLine(\n\t\ts_pTestCopperBfr->pBack, 0, 0, 0, uwMaxY,\n\t\tTEST_COPPER_COLOR_BORDER, 0xFFFF, 0\n\t);\n\tblitLine(\n\t\ts_pTestCopperBfr->pBack, uwMaxX, 0, uwMaxX, uwMaxY,\n\t\tTEST_COPPER_COLOR_BORDER, 0xFFFF, 0\n\t);\n\n\t// Calculate colors for copper bar.\n\t// I used HSV - it's a nice color model to get different shades of same color.\n\t// The V component is brightness - make it go 0..255, 255..0\n\tUWORD pColors[32];\n\tfor(UBYTE i = 0; i < 16; ++i) {\n\t\tpColors[i] = colorHSV(s_ubBarHue, 255, i * 17);\n\t}\n\tfor(UBYTE i = 16; i < 32; ++i) {\n\t\tpColors[i] = colorHSV(s_ubBarHue, 255, (31-i) * 17);\n\t}\n\n\t// Create a shaded copperbar. This works by changing color every line.\n\t// This copperbar is 32px wide with color change in every line, so copper\n\t// needs to wait for each of 32 lines and change color in each one of them.\n\tif(s_isRawMode) {\n\t\t// This is how you do stuff in copperlist's RAW mode.\n\t\t// - Copperlist is double buffered, so you need to regenerate it each frame\n\t\t// on back buffer.\n\t\ttCopBfr *pCopBfr = s_pTestCopperView->pCopList->pBackBfr;\n\t\t// - Go to position directly after simple buffer's commands.\n\t\ttCopCmd *pBarCmds = &pCopBfr->pList[s_uwCopRawOffs];\n\t\t// - Write WAIT + MOVE commands for each line.\n\t\tfor(UBYTE i = 0; i < 32; ++i) {\n\t\t\tcopSetWait(&pBarCmds[i * 2 + 0].sWait, 0, s_uwBarY + i);\n\t\t\tcopSetMove(&pBarCmds[i * 2 + 1].sMove, &g_pCustom->color[1], pColors[i]);\n\t\t}\n\t\t// Copy the same thing to front buffer, so that copperlist has the same\n\t\t// structure on both buffers and we can just update parts we need\n\t\tfor(UWORD i = 0; i < pCopBfr->uwAllocSize; ++i) {\n\t\t\ts_pTestCopperView->pCopList->pFrontBfr->pList[i].ulCode = (\n\t\t\t\tpCopBfr->pList[i].ulCode\n\t\t\t);\n\t\t}\n\t}\n\telse {\n\t\t// This is how you do stuff in copperlist's BLOCK mode.\n\t\t// - Create a block for each WAIT + N x MOVE instructions,\n\t\t// - Set WAIT cmd's x,y in copBlockCreate()\n\t\tfor(UBYTE i = 0; i < 32; ++i) {\n\t\t\ts_pBarBlocks[i] = copBlockCreate(\n\t\t\t\ts_pTestCopperView->pCopList, 1, 0, s_uwBarY + i\n\t\t\t);\n\t\t}\n\n\t\t// - Use copMove() to append MOVE cmds to each block.\n\t\tfor(UBYTE i = 0; i < 32; ++i) {\n\t\t\tcopMove(\n\t\t\t\ts_pTestCopperView->pCopList, s_pBarBlocks[i],\n\t\t\t\t&g_pCustom->color[1], pColors[i]\n\t\t\t);\n\t\t}\n\n\t\t// Calling copMove() again on same copBlock would append next MOVE\n\t\t// instruction drectly after last one.\n\t}\n\n\t// Display view with its viewports\n\tviewLoad(s_pTestCopperView);\n\tsystemUnuse();\n}\n\nvoid gsTestCopperLoop(void) {\n\tstatic BYTE bDir = 1;\n\n\tif (keyUse(KEY_ESCAPE)) {\n\t\tstateChange(g_pGameStateManager, &g_pTestStates[TEST_STATE_MENU]);\n\t\treturn;\n\t}\n\n\tif(keyUse(KEY_M)) {\n\t\t// Change modes and restart\n\t\ts_isRawMode = !s_isRawMode;\n\t\tstateChange(g_pGameStateManager, &g_pTestStates[TEST_STATE_COPPER]);\n\t\treturn;\n\t}\n\n\t// Regenerate colors for different hue\n\t++s_ubBarHue;\n\tUWORD pColors[32];\n\tfor(UBYTE i = 0; i < 16; ++i) {\n\t\tpColors[i] = colorHSV(s_ubBarHue, 255, i * 17);\n\t}\n\tfor(UBYTE i = 16; i < 32; ++i) {\n\t\tpColors[i] = colorHSV(s_ubBarHue, 255, (31-i) * 17);\n\t}\n\n\t// We want to move our copperbar up or down.\n\t// In RAW mode, you need to take care of doing double WAIT for going past y=255,\n\t// In BLOCK mode this is done automatically.\n\tUWORD uwMaxY = s_isRawMode ? 220 : 280;\n\tif(s_uwBarY >= uwMaxY) {\n\t\tbDir = -1;\n\t\ts_uwBarY = uwMaxY;\n\t}\n\tif(s_uwBarY <= 30) {\n\t\tbDir = 1;\n\t\ts_uwBarY = 30;\n\t}\n\ts_uwBarY += 2 * bDir;\n\n\tif(s_isRawMode) {\n\t\ttCopBfr *pCopBfr = s_pTestCopperView->pCopList->pBackBfr;\n\t\ttCopCmd *pBarCmds = &pCopBfr->pList[s_uwCopRawOffs];\n\t\tfor(UBYTE i = 0; i < 32; ++i) {\n\t\t\t// Replace WAIT cmd's Y value.\n\t\t\tpBarCmds[i * 2 + 0].sWait.bfWaitY = s_uwBarY + i;\n\t\t\t// Replace color value\n\t\t\tpBarCmds[i * 2 + 1].sMove.bfValue = pColors[i];\n\t\t}\n\t}\n\telse {\n\t\tfor(UBYTE i = 0; i < 32; ++i) {\n\t\t\t// Replace WAIT cmd's Y value.\n\t\t\tcopBlockWait(s_pTestCopperView->pCopList, s_pBarBlocks[i], 0, s_uwBarY+i);\n\t\t\t// Replace color value\n\t\t\ts_pBarBlocks[i]->pCmds[0].sMove.bfValue = pColors[i];\n\t\t}\n\t}\n\n\t// For debugging, copDumpBfr() / copDumpBlocks() are your best friends.\n\t// Bind them to some key press and inspect copperlist often.\n\t// When using RAW mode, you really need to know what you're doing !\n\tif(keyUse(KEY_C)) {\n\t\tif(s_isRawMode) {\n\t\t\tlogWrite(\"Front:\\n\");\n\t\t\tcopDumpBfr(s_pTestCopperView->pCopList->pFrontBfr);\n\t\t\tlogWrite(\"Back:\\n\");\n\t\t\tcopDumpBfr(s_pTestCopperView->pCopList->pBackBfr);\n\t\t}\n\t\telse {\n\t\t\tcopDumpBlocks();\n\t\t}\n\t}\n\n\t// This regenerates copperlist parts for simpleBuffer in both modes,\n\t// but we don't need it since we're not using scrolling.\n\t// vPortProcessManagers();\n\n\t// Call copProcessBlocks even if you're in RAW mode - swaps copper buffers.\n\tcopProcessBlocks();\n\tvPortWaitForEnd(s_pTestCopperVPort);\n}\n\nvoid gsTestCopperDestroy(void) {\n\tsystemUse();\n\t// Destroy buffer, view & viewport\n\tviewDestroy(s_pTestCopperView);\n}\n"
  },
  {
    "path": "showcase/src/test/copper.h",
    "content": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at http://mozilla.org/MPL/2.0/. */\n\n#ifndef _SHOWCASE_TEST_COPPER_H_\n#define _SHOWCASE_TEST_COPPER_H_\n\n//---------------------------------------------------------------------- DEFINES\n\n//------------------------------------------------------------------------ TYPES\n\n//---------------------------------------------------------------------- GLOBALS\n\n//-------------------------------------------------------------------- FUNCTIONS\n\nvoid gsTestCopperCreate(void);\nvoid gsTestCopperLoop(void);\nvoid gsTestCopperDestroy(void);\n\n//---------------------------------------------------------------------- INLINES\n\n//----------------------------------------------------------------------- MACROS\n\n#endif // _SHOWCASE_TEST_COPPER_H_\n"
  },
  {
    "path": "showcase/src/test/font.c",
    "content": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at http://mozilla.org/MPL/2.0/. */\n\n#include \"test/font.h\"\n#include <ace/managers/blit.h>\n#include <ace/managers/key.h>\n#include <ace/managers/joy.h>\n#include <ace/managers/system.h>\n#include <ace/managers/viewport/simplebuffer.h>\n#include <ace/utils/extview.h>\n#include <ace/utils/font.h>\n#include <ace/generic/screen.h>\n#include \"game.h\"\n\nstatic tView *s_pTestFontView;\nstatic tVPort *s_pTestFontVPort;\nstatic tSimpleBufferManager *s_pTestFontBfr;\n\nstatic char s_szSentence[20];\nstatic tFont *s_pFontUI;\nstatic tTextBitMap *s_pGlyph, *s_pGlyphCode;\nstatic UBYTE s_ubPage;\n\nvoid gsTestFontCreate(void) {\n\t// Prepare view & viewport\n\ts_pTestFontView = viewCreate(0, TAG_DONE);\n\ts_pTestFontVPort = vPortCreate(0,\n\t\tTAG_VPORT_VIEW, s_pTestFontView,\n\t\tTAG_VPORT_BPP, SHOWCASE_BPP,\n\t\tTAG_DONE\n\t);\n\ts_pTestFontBfr = simpleBufferCreate(0,\n\t\tTAG_SIMPLEBUFFER_VPORT, s_pTestFontVPort,\n\t\tTAG_SIMPLEBUFFER_BITMAP_FLAGS, BMF_CLEAR,\n\t\tTAG_DONE\n\t);\n\ts_pTestFontVPort->pPalette[0] = 0x000;\n\ts_pTestFontVPort->pPalette[1] = 0xAAA;\n\ts_pTestFontVPort->pPalette[2] = 0x666;\n\ts_pTestFontVPort->pPalette[3] = 0xFFF;\n\ts_pTestFontVPort->pPalette[4] = 0x111;\n\n\t// Load fonts\n\ts_pFontUI = fontCreateFromPath(\"data/silkscreen.fnt\");\n\ts_pGlyph = 0;\n\ts_pGlyph = fontCreateTextBitMap(96, s_pFontUI->uwHeight);\n\ts_pGlyphCode = fontCreateTextBitMap(96, s_pFontUI->uwHeight);\n\n\t// Loop vars\n\ts_ubPage = 0;\n\ttestFontDrawTable();\n\tmemset(s_szSentence, 0, 20);\n\n\t// Display view with its viewports\n\tsystemUnuse();\n\tviewLoad(s_pTestFontView);\n}\n\nvoid gsTestFontTableLoop(void) {\n\tif (keyUse(KEY_ESCAPE)) {\n\t\tstateChange(g_pGameStateManager, &g_pTestStates[TEST_STATE_MENU]);\n\t\treturn;\n\t}\n\n\tif(keyUse(KEY_F2)) {\n\t\ttestFontDrawSentence();\n\t\tg_pGameStateManager->pCurrent->cbLoop = gsTestFontSentenceLoop;\n\t\treturn;\n\t}\n\n\tif((keyUse(KEY_RIGHT) || keyUse(KEY_DOWN))) {\n\t\tif(s_ubPage < 3) {\n\t\t\t\t++s_ubPage;\n\t\t}\n\t\telse {\n\t\t\ts_ubPage = 0;\n\t\t}\n\t\ttestFontDrawTable();\n\t}\n\tif((keyUse(KEY_LEFT) || keyUse(KEY_UP))) {\n\t\tif(s_ubPage) {\n\t\t\t--s_ubPage;\n\t\t}\n\t\telse {\n\t\t\ts_ubPage = 3;\n\t\t}\n\t\ttestFontDrawTable();\n\t}\n\n}\n\nvoid gsTestFontSentenceLoop(void) {\n\tUBYTE isRedrawNeeded = 0;\n\tstatic const char szAllowedChars[] =\n\t\t\"0123456789\" \"abcdefghijklmnopqrstuvwxyz\" \"ABCDEFGHIJKLMNOPQRSTUVWXYZ\";\n\tUBYTE ubAllowedCharsCount = strlen(szAllowedChars);\n\n\tif (keyUse(KEY_ESCAPE)) {\n\t\tstateChange(g_pGameStateManager, &g_pTestStates[TEST_STATE_MENU]);\n\t\treturn;\n\t}\n\n\tif(keyUse(KEY_F1)) {\n\t\ttestFontDrawTable();\n\t\tg_pGameStateManager->pCurrent->cbLoop = gsTestFontTableLoop;\n\t\treturn;\n\t}\n\n\tisRedrawNeeded = 0;\n\tif(keyUse(KEY_BACKSPACE)) {\n\t\tUBYTE ubSentenceLength = strlen(s_szSentence);\n\t\tif(ubSentenceLength) {\n\t\t\ts_szSentence[ubSentenceLength-1] = 0;\n\t\t\tisRedrawNeeded = 1;\n\t\t}\n\t}\n\n\tfor(UBYTE i = 0; i < ubAllowedCharsCount; ++i) {\n\t\tif(keyUse(szAllowedChars[i])) {\n\t\t\tUBYTE ubSentenceLength = strlen(s_szSentence);\n\t\t\tif(ubSentenceLength != 20) {\n\t\t\t\ts_szSentence[ubSentenceLength] = szAllowedChars[i];\n\t\t\t\tisRedrawNeeded = 1;\n\t\t\t}\n\t\t}\n\t}\n\n\tif(isRedrawNeeded) {\n\t\ttestFontDrawSentence();\n\t}\n}\n\nvoid gsTestFontDestroy(void) {\n\tsystemUse();\n\t// Free fonts\n\tfontDestroyTextBitMap(s_pGlyphCode);\n\tfontDestroyTextBitMap(s_pGlyph);\n\tfontDestroy(s_pFontUI);\n\n\t// Destroy buffer, view & viewport\n\tviewDestroy(s_pTestFontView);\n}\n\nvoid testFontDrawTable(void) {\n\ttFont *pFont;\n\tUWORD i;\n\tchar szCodeBfr[3];\n\n\tpFont = s_pFontUI;\n\n\t// Background\n\tblitRect(\n\t\ts_pTestFontBfr->pBack, 0,0,\n\t\ts_pTestFontBfr->uBfrBounds.uwX,\n\t\ts_pTestFontBfr->uBfrBounds.uwY, 2\n\t);\n\tUWORD uwMaxX = s_pTestFontBfr->uBfrBounds.uwX-1;\n\tUWORD uwMaxY = s_pTestFontBfr->uBfrBounds.uwY-1;\n\tfor(i = 0; i < 8; ++i) {\n\t\t// Vertical lines\n\t\tblitLine(s_pTestFontBfr->pBack, 40*i, 0, 40*i, uwMaxY, 0, 0xFFFF, 0);\n\t\t// Horizontal lines\n\t\tblitLine(s_pTestFontBfr->pBack, 0, 32*i, uwMaxX, 32*i, 0, 0xFFFF, 0);\n\t}\n\t// Last V line\n\tblitLine(s_pTestFontBfr->pBack, uwMaxX, 0, uwMaxX, uwMaxY, 0, 0xFFFF, 0);\n\t// Last H line\n\tblitLine(s_pTestFontBfr->pBack, 0, uwMaxY, uwMaxX, uwMaxY, 0, 0xFFFF, 0);\n\n\tfor(i = 0; i < 64; ++i) {\n\t\tUBYTE ubCharIdx = s_ubPage*64+i;\n\t\t// Char - crashes because of font rendering bugs\n\t\tif(\n\t\t\tubCharIdx && // Not a null char\n\t\t\tpFont->pCharOffsets[ubCharIdx] < pFont->pCharOffsets[ubCharIdx+1] &&\n\t\t\tubCharIdx < pFont->ubChars\n\t\t) {\n\t\t\tsprintf(szCodeBfr, \"%c\", ubCharIdx);\n\t\t\tfontDrawStr(\n\t\t\t\tpFont, s_pTestFontBfr->pBack, (i/8)*40+40/2, (i%8)*32+(32/2),\n\t\t\t\tszCodeBfr, 3, FONT_CENTER|FONT_COOKIE, s_pGlyph\n\t\t\t);\n\t\t}\n\n\t\t// Char code\n\t\tsprintf(szCodeBfr, \"%02X\", ubCharIdx);\n\t\tfontDrawStr(\n\t\t\ts_pFontUI, s_pTestFontBfr->pBack, (i/8)*40+40/2, (i%8)*32+32-2,\n\t\t\tszCodeBfr, 0, FONT_HCENTER|FONT_BOTTOM|FONT_COOKIE, s_pGlyphCode\n\t\t);\n\t}\n}\n\nvoid testFontDrawSentence(void) {\n\n}\n"
  },
  {
    "path": "showcase/src/test/font.h",
    "content": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at http://mozilla.org/MPL/2.0/. */\n\n#ifndef _SHOWCASE_TEST_FONT_H_\n#define _SHOWCASE_TEST_FONT_H_\n\n//---------------------------------------------------------------------- DEFINES\n\n//------------------------------------------------------------------------ TYPES\n\n//---------------------------------------------------------------------- GLOBALS\n\n//-------------------------------------------------------------------- FUNCTIONS\n\nvoid gsTestFontCreate(void);\nvoid gsTestFontTableLoop(void);\nvoid gsTestFontSentenceLoop(void);\nvoid gsTestFontDestroy(void);\n\nvoid testFontDrawTable(void);\nvoid testFontDrawSentence(void);\n\n//---------------------------------------------------------------------- INLINES\n\n//----------------------------------------------------------------------- MACROS\n\n#endif // _SHOWCASE_TEST_FONT_H_\n"
  },
  {
    "path": "showcase/src/test/input.c",
    "content": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at http://mozilla.org/MPL/2.0/. */\n\n#include \"test/blit.h\"\n#include <ace/utils/extview.h>\n#include <ace/utils/font.h>\n#include <ace/managers/blit.h>\n#include <ace/managers/key.h>\n#include <ace/managers/joy.h>\n#include <ace/managers/mouse.h>\n#include <ace/managers/system.h>\n#include <ace/managers/viewport/simplebuffer.h>\n#include <ace/generic/screen.h>\n#include \"game.h\"\n\n#define COLOR_PRESSED_NEVER 4\n#define COLOR_PRESSED_INACTIVE 2\n#define COLOR_PRESSED_ACTIVE 1\n\n#define OFFS_JOY1_X 0\n#define OFFS_JOY1_Y 0\n#define OFFS_JOY2_X 160\n#define OFFS_JOY2_Y 0\n#define OFFS_JOY3_X 0\n#define OFFS_JOY3_Y 80\n#define OFFS_JOY4_X 160\n#define OFFS_JOY4_Y 80\n\ntypedef enum tJoyInputState {\n\tJOY_PRESSED_NEVER,\n\tJOY_PRESSED_INACTIVE,\n\tJOY_PRESSED_ACTIVE,\n} tJoyInputState;\n\ntypedef struct tButtonDef {\n\tUWORD uwX;\n\tUWORD uwY;\n\tUBYTE ubWidth;\n\tUBYTE ubHeight;\n\tconst char *szLabel;\n} tButtonDef;\n\nstatic tView *s_pTestInputView;\nstatic tVPort *s_pTestInputVPort;\nstatic tSimpleBufferManager *s_pTestInputBfr;\nstatic tFont *s_pFont;\nstatic tTextBitMap *s_pTextBitMap;\nstatic tJoyInputState s_pJoyStates[4][6];\n\nstatic const tButtonDef s_pJoyButtonDefs[4][6] = {\n\t[0] = {\n\t\t[JOY_FIRE] = {.uwX = OFFS_JOY1_X + 4 * 20 + 2, .uwY = OFFS_JOY1_Y + 1 * 20 + 2, .ubWidth = 16, .ubHeight = 16, .szLabel = \"F1\"},\n\t\t[JOY_UP] = {.uwX = OFFS_JOY1_X + 1 * 20 + 2, .uwY = OFFS_JOY1_Y + 0 * 20 + 2, .ubWidth = 16, .ubHeight = 16, .szLabel = \"U\"},\n\t\t[JOY_DOWN] = {.uwX = OFFS_JOY1_X + 1 * 20 + 2, .uwY = OFFS_JOY1_Y + 2 * 20 + 2, .ubWidth = 16, .ubHeight = 16, .szLabel = \"D\"},\n\t\t[JOY_LEFT] = {.uwX = OFFS_JOY1_X + 0 * 20 + 2, .uwY = OFFS_JOY1_Y + 1 * 20 + 2, .ubWidth = 16, .ubHeight = 16, .szLabel = \"L\"},\n\t\t[JOY_RIGHT] = {.uwX = OFFS_JOY1_X + 2 * 20 + 2, .uwY = OFFS_JOY1_Y + 1 * 20 + 2, .ubWidth = 16, .ubHeight = 16, .szLabel = \"R\"},\n\t\t[JOY_FIRE2] = {.uwX = OFFS_JOY1_X + 5 * 20 + 2, .uwY = OFFS_JOY1_Y + 1 * 20 + 2, .ubWidth = 16, .ubHeight = 16, .szLabel = \"F2\"},\n\t},\n\t[1] = {\n\t\t[JOY_FIRE] = {.uwX = OFFS_JOY2_X + 4 * 20 + 2, .uwY = OFFS_JOY2_Y + 1 * 20 + 2, .ubWidth = 16, .ubHeight = 16, .szLabel = \"F1\"},\n\t\t[JOY_UP] = {.uwX = OFFS_JOY2_X + 1 * 20 + 2, .uwY = OFFS_JOY2_Y + 0 * 20 + 2, .ubWidth = 16, .ubHeight = 16, .szLabel = \"U\"},\n\t\t[JOY_DOWN] = {.uwX = OFFS_JOY2_X + 1 * 20 + 2, .uwY = OFFS_JOY2_Y + 2 * 20 + 2, .ubWidth = 16, .ubHeight = 16, .szLabel = \"D\"},\n\t\t[JOY_LEFT] = {.uwX = OFFS_JOY2_X + 0 * 20 + 2, .uwY = OFFS_JOY2_Y + 1 * 20 + 2, .ubWidth = 16, .ubHeight = 16, .szLabel = \"L\"},\n\t\t[JOY_RIGHT] = {.uwX = OFFS_JOY2_X + 2 * 20 + 2, .uwY = OFFS_JOY2_Y + 1 * 20 + 2, .ubWidth = 16, .ubHeight = 16, .szLabel = \"R\"},\n\t\t[JOY_FIRE2] = {.uwX = OFFS_JOY2_X + 5 * 20 + 2, .uwY = OFFS_JOY2_Y + 1 * 20 + 2, .ubWidth = 16, .ubHeight = 16, .szLabel = \"F2\"},\n\t},\n\t[2] = {\n\t\t[JOY_FIRE] = {.uwX = OFFS_JOY3_X + 4 * 20 + 2, .uwY = OFFS_JOY3_Y + 1 * 20 + 2, .ubWidth = 16, .ubHeight = 16, .szLabel = \"F1\"},\n\t\t[JOY_UP] = {.uwX = OFFS_JOY3_X + 1 * 20 + 2, .uwY = OFFS_JOY3_Y + 0 * 20 + 2, .ubWidth = 16, .ubHeight = 16, .szLabel = \"U\"},\n\t\t[JOY_DOWN] = {.uwX = OFFS_JOY3_X + 1 * 20 + 2, .uwY = OFFS_JOY3_Y + 2 * 20 + 2, .ubWidth = 16, .ubHeight = 16, .szLabel = \"D\"},\n\t\t[JOY_LEFT] = {.uwX = OFFS_JOY3_X + 0 * 20 + 2, .uwY = OFFS_JOY3_Y + 1 * 20 + 2, .ubWidth = 16, .ubHeight = 16, .szLabel = \"L\"},\n\t\t[JOY_RIGHT] = {.uwX = OFFS_JOY3_X + 2 * 20 + 2, .uwY = OFFS_JOY3_Y + 1 * 20 + 2, .ubWidth = 16, .ubHeight = 16, .szLabel = \"R\"},\n\t\t[JOY_FIRE2] = {.uwX = OFFS_JOY3_X + 5 * 20 + 2, .uwY = OFFS_JOY3_Y + 1 * 20 + 2, .ubWidth = 16, .ubHeight = 16, .szLabel = \"F2\"},\n\t},\n\t[3] = {\n\t\t[JOY_FIRE] = {.uwX = OFFS_JOY4_X + 4 * 20 + 2, .uwY = OFFS_JOY4_Y + 1 * 20 + 2, .ubWidth = 16, .ubHeight = 16, .szLabel = \"F1\"},\n\t\t[JOY_UP] = {.uwX = OFFS_JOY4_X + 1 * 20 + 2, .uwY = OFFS_JOY4_Y + 0 * 20 + 2, .ubWidth = 16, .ubHeight = 16, .szLabel = \"U\"},\n\t\t[JOY_DOWN] = {.uwX = OFFS_JOY4_X + 1 * 20 + 2, .uwY = OFFS_JOY4_Y + 2 * 20 + 2, .ubWidth = 16, .ubHeight = 16, .szLabel = \"D\"},\n\t\t[JOY_LEFT] = {.uwX = OFFS_JOY4_X + 0 * 20 + 2, .uwY = OFFS_JOY4_Y + 1 * 20 + 2, .ubWidth = 16, .ubHeight = 16, .szLabel = \"L\"},\n\t\t[JOY_RIGHT] = {.uwX = OFFS_JOY4_X + 2 * 20 + 2, .uwY = OFFS_JOY4_Y + 1 * 20 + 2, .ubWidth = 16, .ubHeight = 16, .szLabel = \"R\"},\n\t\t[JOY_FIRE2] = {.uwX = OFFS_JOY4_X + 5 * 20 + 2, .uwY = OFFS_JOY4_Y + 1 * 20 + 2, .ubWidth = 16, .ubHeight = 16, .szLabel = \"F2\"},\n\t},\n};\n\nstatic void drawButtonAt(const tButtonDef *pDef, UBYTE ubColor) {\n\tblitRect(s_pTestInputBfr->pBack, pDef->uwX, pDef->uwY, pDef->ubWidth, pDef->ubHeight, ubColor);\n\tif(pDef->szLabel) {\n\t\tfontDrawStr(\n\t\t\ts_pFont, s_pTestInputBfr->pBack, pDef->uwX + pDef->ubWidth / 2, pDef->uwY + pDef->ubHeight / 2,\n\t\t\tpDef->szLabel, 0, FONT_CENTER | FONT_COOKIE, s_pTextBitMap\n\t\t);\n\t}\n}\n\nstatic void updateJoyState(UBYTE ubJoyIndex) {\n\tstatic const UBYTE pPressToColor[] = {\n\t\t[JOY_PRESSED_NEVER] = COLOR_PRESSED_NEVER,\n\t\t[JOY_PRESSED_INACTIVE] = COLOR_PRESSED_INACTIVE,\n\t\t[JOY_PRESSED_ACTIVE] = COLOR_PRESSED_ACTIVE,\n\t};\n\n\tUBYTE ubJoy = ubJoyIndex * JOY2;\n\tfor(UBYTE ubDir = 0; ubDir < 6;  ++ubDir) {\n\t\tUBYTE ubButtonState = joyCheck(ubJoy + ubDir);\n\t\tif(ubButtonState) {\n\t\t\ts_pJoyStates[ubJoyIndex][ubDir] = JOY_PRESSED_ACTIVE;\n\t\t}\n\t\telse if(s_pJoyStates[ubJoyIndex][ubDir] != JOY_PRESSED_NEVER && ubButtonState == JOY_NACTIVE) {\n\t\t\ts_pJoyStates[ubJoyIndex][ubDir] = JOY_PRESSED_INACTIVE;\n\t\t}\n\n\t\tdrawButtonAt(&s_pJoyButtonDefs[ubJoyIndex][ubDir], pPressToColor[s_pJoyStates[ubJoyIndex][ubDir]]);\n\t}\n}\n\nstatic void showParallelStatus(void) {\n\tchar szMsg[40];\n\tsprintf(szMsg, \"Parallel joys are %s F1 to toggle\", joyIsParallelEnabled() ? \"ON\" : \"OFF\");\n\tblitRect(s_pTestInputBfr->pBack, 0, 256 - s_pFont->uwHeight, 320, s_pFont->uwHeight, 0);\n\tfontDrawStr(s_pFont, s_pTestInputBfr->pBack, 160, 256, szMsg, 3, FONT_BOTTOM|FONT_HCENTER, s_pTextBitMap);\n}\n\nvoid gsTestInputCreate(void) {\n\t// Prepare view & viewport\n\ts_pTestInputView = viewCreate(0, TAG_DONE);\n\ts_pTestInputVPort = vPortCreate(0,\n\t\tTAG_VPORT_VIEW, s_pTestInputView,\n\t\tTAG_VPORT_BPP, SHOWCASE_BPP,\n\t\tTAG_DONE\n\t);\n\ts_pTestInputBfr = simpleBufferCreate(0,\n\t\tTAG_SIMPLEBUFFER_VPORT, s_pTestInputVPort,\n\t\tTAG_SIMPLEBUFFER_BITMAP_FLAGS, BMF_CLEAR,\n\t\tTAG_DONE\n\t);\n\ts_pTestInputVPort->pPalette[0] = 0x000;\n\ts_pTestInputVPort->pPalette[1] = 0xAAA;\n\ts_pTestInputVPort->pPalette[2] = 0x666;\n\ts_pTestInputVPort->pPalette[3] = 0xFFF;\n\ts_pTestInputVPort->pPalette[4] = 0x333;\n\n\ts_pFont = fontCreateFromPath(\"data/silkscreen.fnt\");\n\ts_pTextBitMap = fontCreateTextBitMap(320, s_pFont->uwHeight);\n\n\tfontDrawStr(\n\t\ts_pFont, s_pTestInputBfr->pBack, 0 + 160 / 2, 10,\n\t\t\"Joy 1\", 1, FONT_CENTER, s_pTextBitMap\n\t);\n\tfontDrawStr(\n\t\ts_pFont, s_pTestInputBfr->pBack, 160 + 160 / 2, 10,\n\t\t\"Joy 2\", 1, FONT_CENTER, s_pTextBitMap\n\t);\n\tfontDrawStr(\n\t\ts_pFont, s_pTestInputBfr->pBack, 0 + 160 / 2, 80 + 10,\n\t\t\"Joy 3\", 1, FONT_CENTER, s_pTextBitMap\n\t);\n\tfontDrawStr(\n\t\ts_pFont, s_pTestInputBfr->pBack, 160 + 160 / 2, 80 + 10,\n\t\t\"Joy 4\", 1, FONT_CENTER, s_pTextBitMap\n\t);\n\n\tfor(UBYTE ubJoy = 0; ubJoy < 4; ++ubJoy) {\n\t\tfor(UBYTE ubButton = 0; ubButton < 6; ++ubButton) {\n\t\t\ts_pJoyStates[ubJoy][ubButton] = JOY_PRESSED_NEVER;\n\t\t}\n\t}\n\n\tfontDrawStr(s_pFont, s_pTestInputBfr->pBack, 0, 160, \"TODO Mouse 1\", 1, 0, s_pTextBitMap);\n\tfontDrawStr(s_pFont, s_pTestInputBfr->pBack, 0, 168, \"TODO Mouse 2\", 1, 0, s_pTextBitMap);\n\tfontDrawStr(s_pFont, s_pTestInputBfr->pBack, 0, 176, \"TODO Keyboard\", 1, 0, s_pTextBitMap);\n\tshowParallelStatus();\n\n\t// Display view with its viewports\n\tsystemUnuse();\n\tviewLoad(s_pTestInputView);\n}\n\nvoid gsTestInputLoop(void) {\n\tif (keyUse(KEY_ESCAPE)) {\n\t\tstateChange(g_pGameStateManager, &g_pTestStates[TEST_STATE_MENU]);\n\t\treturn;\n\t}\n\n\tif(keyUse(KEY_F1)) {\n\t\tif(joyIsParallelEnabled()) {\n\t\t\tjoyDisableParallel();\n\t\t}\n\t\telse {\n\t\t\tjoyEnableParallel();\n\t\t}\n\t\tshowParallelStatus();\n\t}\n\n\tupdateJoyState(0);\n\tupdateJoyState(1);\n\tupdateJoyState(2);\n\tupdateJoyState(3);\n\n\tvPortWaitForEnd(s_pTestInputVPort);\n}\n\nvoid gsTestInputDestroy(void) {\n\tviewLoad(0);\n\tsystemUse();\n\tjoyDisableParallel();\n\n\tfontDestroy(s_pFont);\n\tfontDestroyTextBitMap(s_pTextBitMap);\n\n\t// Destroy buffer, view & viewport\n\tviewDestroy(s_pTestInputView);\n}\n"
  },
  {
    "path": "showcase/src/test/input.h",
    "content": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at http://mozilla.org/MPL/2.0/. */\n\n#ifndef _SHOWCASE_TEST_INPUT_H_\n#define _SHOWCASE_TEST_INPUT_H_\n\n//---------------------------------------------------------------------- DEFINES\n\n//------------------------------------------------------------------------ TYPES\n\n//---------------------------------------------------------------------- GLOBALS\n\n//-------------------------------------------------------------------- FUNCTIONS\n\nvoid gsTestInputCreate(void);\nvoid gsTestInputLoop(void);\nvoid gsTestInputDestroy(void);\n\n//---------------------------------------------------------------------- INLINES\n\n//----------------------------------------------------------------------- MACROS\n\n#endif // _SHOWCASE_TEST_INPUT_H_\n"
  },
  {
    "path": "showcase/src/test/interleaved.c",
    "content": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at http://mozilla.org/MPL/2.0/. */\n\n#include \"test/interleaved.h\"\n#include <ace/utils/extview.h>\n#include <ace/utils/palette.h>\n#include <ace/managers/key.h>\n#include <ace/managers/blit.h>\n#include <ace/managers/system.h>\n#include <ace/managers/viewport/simplebuffer.h>\n#include \"game.h\"\n\n#define BOUNCE_MARGIN 32\n#define BOUNCE_RECT_WIDTH 32\n#define BOUNCE_RECT_HEIGHT 32\n\nstatic tView *s_pTestInterleavedView;\nstatic tVPort *s_pTestInterleavedVPort;\nstatic tSimpleBufferManager *s_pTestInterleavedBfr;\nstatic tBitMap *s_pSave;\nstatic tBitMap *s_pBouncer;\n\nstatic WORD wX, wY;\nstatic BYTE bDx, bDy;\n\nvoid gsTestInterleavedCreate(void) {\n\ts_pTestInterleavedView = viewCreate(0, TAG_DONE);\n\ts_pTestInterleavedVPort = vPortCreate(0,\n\t\tTAG_VPORT_VIEW, s_pTestInterleavedView,\n\t\tTAG_VPORT_BPP, SHOWCASE_BPP,\n\t\tTAG_DONE\n\t);\n\ts_pTestInterleavedBfr = simpleBufferCreate(0,\n\t\tTAG_SIMPLEBUFFER_VPORT, s_pTestInterleavedVPort,\n\t\tTAG_SIMPLEBUFFER_BITMAP_FLAGS, BMF_CLEAR | BMF_INTERLEAVED,\n\t\tTAG_DONE\n\t);\n\tpaletteLoadFromPath(\n\t\t\"data/amidb32.plt\", s_pTestInterleavedVPort->pPalette, 1 << SHOWCASE_BPP\n\t);\n\tbitmapLoadFromPath(\n\t\ts_pTestInterleavedBfr->pBack, \"data/32c_pal_interleaved.bm\", 0, 0\n\t);\n\n\ts_pSave = bitmapCreate(BOUNCE_RECT_WIDTH + 16, BOUNCE_RECT_HEIGHT, SHOWCASE_BPP, BMF_INTERLEAVED);\n\ts_pBouncer = bitmapCreate(BOUNCE_RECT_WIDTH, BOUNCE_RECT_HEIGHT, SHOWCASE_BPP, BMF_INTERLEAVED);\n\tblitRect(s_pBouncer, 0, 0, BOUNCE_RECT_WIDTH, BOUNCE_RECT_HEIGHT, 0b10110);\n\twX = 100;\n\twY = 50;\n\tbDx = 3;\n\tbDy = 1;\n\n\tblitCopyAligned(\n\t\ts_pTestInterleavedBfr->pBack, wX & 0xFFF0, wY, s_pSave, 0, 0,\n\t\tBOUNCE_RECT_WIDTH + 16, BOUNCE_RECT_HEIGHT\n\t);\n\n\tsystemUnuse();\n\tviewLoad(s_pTestInterleavedView);\n}\n\nvoid gsTestInterleavedLoop(void) {\n\tif (keyUse(KEY_ESCAPE)) {\n\t\tstateChange(g_pGameStateManager, &g_pTestStates[TEST_STATE_MENU]);\n\t\treturn;\n\t}\n\n\tblitCopyAligned(\n\t\ts_pSave, 0, 0, s_pTestInterleavedBfr->pBack, wX & 0xFFF0, wY,\n\t\tBOUNCE_RECT_WIDTH + 16, BOUNCE_RECT_HEIGHT\n\t);\n\twX += bDx;\n\twY += bDy;\n\tif(wX < BOUNCE_MARGIN) {\n\t\tbDx = -bDx;\n\t\twX = BOUNCE_MARGIN;\n\t}\n\tif(wY < BOUNCE_MARGIN) {\n\t\tbDy = -bDy;\n\t\twY = BOUNCE_MARGIN;\n\t}\n\tif(wX + BOUNCE_RECT_WIDTH >= 320 - BOUNCE_MARGIN) {\n\t\tbDx = -bDx;\n\t\twX = 320 - BOUNCE_MARGIN - BOUNCE_RECT_WIDTH;\n\t}\n\tif(wY + BOUNCE_RECT_HEIGHT >= 256 - BOUNCE_MARGIN) {\n\t\tbDy = -bDy;\n\t\twY = 256 - BOUNCE_MARGIN - BOUNCE_RECT_HEIGHT;\n\t}\n\tblitCopyAligned(\n\t\ts_pTestInterleavedBfr->pBack, wX & 0xFFF0, wY, s_pSave, 0, 0,\n\t\tBOUNCE_RECT_WIDTH + 16, BOUNCE_RECT_HEIGHT\n\t);\n\n\tblitCopy(\n\t\ts_pBouncer, 0, 0, s_pTestInterleavedBfr->pBack, wX, wY,\n\t\tBOUNCE_RECT_WIDTH, BOUNCE_RECT_HEIGHT, MINTERM_COOKIE\n\t);\n\n\tvPortWaitForPos(s_pTestInterleavedVPort, wY + BOUNCE_RECT_HEIGHT, 1);\n}\n\nvoid gsTestInterleavedDestroy(void) {\n\tsystemUse();\n\tviewDestroy(s_pTestInterleavedView);\n\tbitmapDestroy(s_pSave);\n\tbitmapDestroy(s_pBouncer);\n}\n"
  },
  {
    "path": "showcase/src/test/interleaved.h",
    "content": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at http://mozilla.org/MPL/2.0/. */\n\n#ifndef _SHOWCASE_TEST_INTERLEAVED_H_\n#define _SHOWCASE_TEST_INTERLEAVED_H_\n\n//---------------------------------------------------------------------- DEFINES\n\n//------------------------------------------------------------------------ TYPES\n\n//---------------------------------------------------------------------- GLOBALS\n\n//-------------------------------------------------------------------- FUNCTIONS\n\nvoid gsTestInterleavedCreate(void);\nvoid gsTestInterleavedLoop(void);\nvoid gsTestInterleavedDestroy(void);\n\n//---------------------------------------------------------------------- INLINES\n\n//----------------------------------------------------------------------- MACROS\n\n#endif // _SHOWCASE_TEST_INTERLEAVED_H_\n"
  },
  {
    "path": "showcase/src/test/lines.c",
    "content": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at http://mozilla.org/MPL/2.0/. */\n\n#include \"test/lines.h\"\n#include <ace/managers/blit.h>\n#include <ace/managers/key.h>\n#include <ace/managers/system.h>\n#include <ace/managers/viewport/simplebuffer.h>\n#include <ace/utils/custom.h>\n#include <fixmath/fixmath.h>\n#include \"game.h\"\n\n#define STAR_POSITION_COUNT 60\n#define STAR_ARM_COUNT 5\n#define STAR_DIVISION (STAR_POSITION_COUNT / (STAR_ARM_COUNT * 2));\n#define STAR_RADIUS 64\n#define STAR_CENTER_X 200\n#define STAR_CENTER_Y 100\n\nstatic tView *s_pView;\nstatic tVPort *s_pVPort;\nstatic tSimpleBufferManager *s_pBfrManager;\nstatic tWCoordYX s_pPositions[STAR_POSITION_COUNT];\nstatic UBYTE s_ubFirstPosIndex;\n\nvoid gsTestLinesCreate(void) {\n\ts_pView = viewCreate(0, TAG_END);\n\ts_pVPort = vPortCreate(0,\n\t\tTAG_VPORT_BPP, 2,\n\t\tTAG_VPORT_VIEW, s_pView,\n\t\tTAG_END\n\t);\n\ts_pBfrManager = simpleBufferCreate(0,\n\t\tTAG_SIMPLEBUFFER_VPORT, s_pVPort,\n\t\tTAG_SIMPLEBUFFER_BITMAP_FLAGS, BMF_CLEAR | BMF_INTERLEAVED,\n\t\tTAG_END\n\t);\n\n\ts_pVPort->pPalette[1] = 0xF00;\n\ts_pVPort->pPalette[2] = 0x0F0;\n\ts_pVPort->pPalette[3] = 0x00F;\n\n\tUWORD uwMinX = 0;\n\tUWORD uwMaxX = s_pBfrManager->uBfrBounds.uwX-1;\n\tUWORD uwMinY = 0;\n\tUWORD uwMaxY = s_pBfrManager->uBfrBounds.uwY-1;\n\n\tUWORD uwPattern = 0xFFFF;\n\n\tblitLine(s_pBfrManager->pBack, uwMinX, uwMinY, uwMinX, uwMaxY, 1, uwPattern, 0);\n\tblitLine(s_pBfrManager->pBack, uwMaxX, uwMinY, uwMaxX, uwMaxY, 1, uwPattern, 0);\n\tblitLine(s_pBfrManager->pBack, uwMinX, uwMinY, uwMaxX, uwMinY, 1, uwPattern, 0);\n\tblitLine(s_pBfrManager->pBack, uwMinX, uwMaxY, uwMaxX, uwMaxY, 1, uwPattern, 0);\n\n\tblitRect(s_pBfrManager->pBack, 32, 32, 32, 32, 2);\n\tblitLine(s_pBfrManager->pBack, 16, 16, 80, 80, 1, uwPattern, 0);\n\n\t// Prepare circle vertex positions.\n\t// For better accuracy, supply your own precalculated points or more accurate sin/cos table\n\tconst fix16_t fHalf = fix16_one / 2;\n\tfix16_t fAngle;\n\tfor(UBYTE ubPosIndex = 0; ubPosIndex != STAR_POSITION_COUNT; ++ubPosIndex) {\n\t\tfAngle = (fix16_pi*ubPosIndex*2) / STAR_POSITION_COUNT;\n\t\tWORD wSin = fix16_to_int(STAR_RADIUS * fix16_sin(fAngle) + fHalf);\n\t\tWORD wCos = fix16_to_int(STAR_RADIUS * fix16_cos(fAngle) + fHalf);\n\t\ts_pPositions[ubPosIndex].wX = wSin;\n\t\ts_pPositions[ubPosIndex].wY = wCos;\n\t}\n\n\ts_ubFirstPosIndex = 0;\n\n\n\tviewLoad(s_pView);\n\tsystemUnuse();\n}\n\nvoid gsTestLinesLoop(void) {\n\tif(keyUse(KEY_ESCAPE)) {\n\t\tstateChange(g_pGameStateManager, &g_pTestStates[TEST_STATE_MENU]);\n\t\treturn;\n\t}\n\n\tUWORD uwStartX = (STAR_CENTER_X - STAR_RADIUS - 1) & 0xFFF0;\n\tUWORD uwEndX = (STAR_CENTER_X + STAR_RADIUS + 1 + 15) & 0xFFF0;\n\n\t// Erase background\n\tvPortWaitForPos(s_pVPort, STAR_CENTER_Y + STAR_RADIUS, 0);\n\tblitRect(\n\t\ts_pBfrManager->pBack,\n\t\tuwStartX, STAR_CENTER_Y - STAR_RADIUS - 1,\n\t\tuwEndX - uwStartX, (STAR_RADIUS + 1) * 2 + 1, 0\n\t);\n\n\t// Draw circle\n\tUBYTE ubPosIndex = s_ubFirstPosIndex;\n\tfor(UBYTE ubVertexIndex = 0; ubVertexIndex < STAR_ARM_COUNT * 2; ++ubVertexIndex) {\n\t\tUBYTE ubNextPosIndex = ubPosIndex + STAR_DIVISION;\n\t\tif(ubNextPosIndex >= STAR_POSITION_COUNT) {\n\t\t\tubNextPosIndex -= STAR_POSITION_COUNT;\n\t\t}\n\n\t\ttWCoordYX sPoint, sNextPoint;\n\t\tif(ubVertexIndex & 1) {\n\t\t\tsPoint = (tWCoordYX){\n\t\t\t\t.wX = STAR_CENTER_X + s_pPositions[ubPosIndex].wX,\n\t\t\t\t.wY = STAR_CENTER_Y + s_pPositions[ubPosIndex].wY\n\t\t\t};\n\t\t\tsNextPoint = (tWCoordYX){\n\t\t\t\t.wX = STAR_CENTER_X + s_pPositions[ubNextPosIndex].wX / 2,\n\t\t\t\t.wY = STAR_CENTER_Y + s_pPositions[ubNextPosIndex].wY / 2\n\t\t\t};\n\t\t}\n\t\telse {\n\t\t\tsPoint = (tWCoordYX){\n\t\t\t\t.wX = STAR_CENTER_X + s_pPositions[ubPosIndex].wX / 2,\n\t\t\t\t.wY = STAR_CENTER_Y + s_pPositions[ubPosIndex].wY / 2\n\t\t\t};\n\t\t\tsNextPoint = (tWCoordYX){\n\t\t\t\t.wX = STAR_CENTER_X + s_pPositions[ubNextPosIndex].wX,\n\t\t\t\t.wY = STAR_CENTER_Y + s_pPositions[ubNextPosIndex].wY\n\t\t\t};\n\t\t}\n\n\t\tblitLinePlane(\n\t\t\ts_pBfrManager->pBack, sPoint.wX, sPoint.wY, sNextPoint.wX, sNextPoint.wY,\n\t\t\t0, 0xFFFF, BLIT_LINE_MODE_XOR, 1\n\t\t);\n\t\tubPosIndex = ubNextPosIndex;\n\t}\n\n\t// Fill\n\tif(keyCheck(KEY_F)) {\n\t\tblitFillAligned(\n\t\t\ts_pBfrManager->pBack, uwStartX, STAR_CENTER_Y - STAR_RADIUS - 1,\n\t\t\tuwEndX - uwStartX, (STAR_RADIUS + 1) * 2 + 1, 0, FILL_XOR\n\t\t);\n\t}\n\tif(keyCheck(KEY_G)) {\n\t\tblitFillAligned(\n\t\t\ts_pBfrManager->pBack, uwStartX, STAR_CENTER_Y - STAR_RADIUS - 1,\n\t\t\tuwEndX - uwStartX, (STAR_RADIUS + 1) * 2 + 1, 0, FILL_CARRYIN | FILL_XOR\n\t\t);\n\t}\n\n\tif(++s_ubFirstPosIndex >= STAR_POSITION_COUNT) {\n\t\ts_ubFirstPosIndex -= STAR_POSITION_COUNT;\n\t}\n\n\tvPortWaitForEnd(s_pVPort);\n}\n\nvoid gsTestLinesDestroy(void) {\n\tsystemUse();\n\tviewDestroy(s_pView);\n}\n"
  },
  {
    "path": "showcase/src/test/lines.h",
    "content": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at http://mozilla.org/MPL/2.0/. */\n\n#ifndef _SHOWCASE_TEST_LINES_H\n#define _SHOWCASE_TEST_LINES_H\n\n//---------------------------------------------------------------------- DEFINES\n\n//------------------------------------------------------------------------ TYPES\n\n//---------------------------------------------------------------------- GLOBALS\n\n//-------------------------------------------------------------------- FUNCTIONS\n\nvoid gsTestLinesCreate(void);\nvoid gsTestLinesLoop(void);\nvoid gsTestLinesDestroy(void);\n\n//---------------------------------------------------------------------- INLINES\n\n//----------------------------------------------------------------------- MACROS\n\n#endif // _SHOWCASE_TEST_LINES_H\n"
  },
  {
    "path": "showcase/src/test/twister.c",
    "content": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at http://mozilla.org/MPL/2.0/. */\n\n#include \"twister.h\"\n#include \"../game.h\"\n#include <ace/generic/screen.h>\n#include <ace/managers/viewport/simplebuffer.h>\n#include <ace/managers/key.h>\n#include <ace/managers/system.h>\n#include <ace/managers/rand.h>\n#include <ace/managers/blit.h>\n#include <ace/utils/chunky.h>\n\n#define CLIP_MARGIN_X 32\n#define CLIP_MARGIN_Y 16\n#define TWISTER_CENTER_X (86+32)\n#define TWISTER_CENTER_Y (128)\n#define TWISTER_CENTER_RADIUS 2\n#define TWISTER_BLOCK_SIZE 32\n#define TWISTER_MIN_BLOCK_X (-(((TWISTER_CENTER_X + TWISTER_BLOCK_SIZE - 1) / TWISTER_BLOCK_SIZE) + 2))\n#define TWISTER_MAX_BLOCK_X (+((((320 - TWISTER_CENTER_X) + TWISTER_BLOCK_SIZE - 1) / TWISTER_BLOCK_SIZE) + 0))\n#define TWISTER_MIN_BLOCK_Y (-(((TWISTER_CENTER_Y + TWISTER_BLOCK_SIZE - 1) / TWISTER_BLOCK_SIZE) + 2))\n#define TWISTER_MAX_BLOCK_Y (+((((256 - TWISTER_CENTER_Y) + TWISTER_BLOCK_SIZE - 1) / TWISTER_BLOCK_SIZE) + 0))\n#define TWISTER_BLOCKS_X (TWISTER_MAX_BLOCK_X - TWISTER_MIN_BLOCK_X)\n#define TWISTER_BLOCKS_Y (TWISTER_MAX_BLOCK_Y - TWISTER_MIN_BLOCK_Y)\n\nstatic tView *s_pView;\nstatic tVPort *s_pVPort;\nstatic tSimpleBufferManager *s_pBfr;\nstatic tRandManager s_sRand;\n\nstatic ULONG s_ps;\nstatic UBYTE s_isVectors;\nstatic UBYTE s_isAdvancePs;\n\nstatic void testGrid(UBYTE ubSize) {\n\tUBYTE ubColor = 0;\n\tfor(UWORD uwX = ubSize; uwX < 320; uwX += ubSize) {\n\t\tblitRect(s_pBfr->pBack, uwX, 0, 1, 256, 1 + (ubColor & 1));\n\t\t++ubColor;\n\t}\n\tfor(UWORD uwY = ubSize; uwY < 256; uwY += ubSize) {\n\t\tblitRect(s_pBfr->pBack, 0, uwY, 320, 1, 1 + (ubColor & 1));\n\t\t++ubColor;\n\t}\n}\n\nvoid gsTestTwisterCreate(void) {\n\t// Prepare view & viewport\n\ts_pView = viewCreate(0, TAG_DONE);\n\ts_pVPort = vPortCreate(0,\n\t\tTAG_VPORT_VIEW, s_pView,\n\t\tTAG_VPORT_BPP, 2,\n\t\tTAG_DONE\n\t);\n\ts_pBfr = simpleBufferCreate(0,\n\t\tTAG_SIMPLEBUFFER_VPORT, s_pVPort,\n\t\tTAG_SIMPLEBUFFER_BITMAP_FLAGS, BMF_CLEAR | BMF_INTERLEAVED,\n\t\tTAG_SIMPLEBUFFER_IS_DBLBUF, 1,\n\t\tTAG_SIMPLEBUFFER_BOUND_WIDTH, SCREEN_PAL_WIDTH + CLIP_MARGIN_X,\n\t\tTAG_SIMPLEBUFFER_BOUND_HEIGHT, SCREEN_PAL_HEIGHT + CLIP_MARGIN_Y,\n\t\tTAG_DONE\n\t);\n\n\t// Init stuff\n\ts_ps = 0;\n\ts_isVectors = 0;\n\ts_isAdvancePs = 1;\n\ts_pVPort->pPalette[0] = 0x000;\n\ts_pVPort->pPalette[1] = 0x057;\n\ts_pVPort->pPalette[2] = 0x49b;\n\ts_pVPort->pPalette[3] = 0x8df;\n\n\trandInit(&s_sRand, 1911, 2184);\n\n\t// Display view with its viewports\n\tsystemUnuse();\n\tviewLoad(s_pView);\n}\n\nvoid gsTestTwisterLoop(void) {\n\tif (keyUse(KEY_ESCAPE)) {\n\t\tstateChange(g_pGameStateManager, &g_pTestStates[TEST_STATE_MENU]);\n\t\treturn;\n\t}\n\telse if(keyUse(KEY_R)) {\n\t\tcameraSetCoord(s_pBfr->pCamera, 0, 0);\n\t}\n\telse if(keyUse(KEY_B)) {\n\t\tbitmapSaveBmp(s_pBfr->pFront, s_pVPort->pPalette, \"twister.bmp\");\n\t}\n\telse if(keyUse(KEY_I)) {\n\t\ts_isAdvancePs = !s_isAdvancePs;\n\t}\n\telse if(keyUse(KEY_O)) {\n\t\t--s_ps;\n\t\ts_isAdvancePs = 0;\n\t}\n\telse if(keyUse(KEY_P)) {\n\t\t++s_ps;\n\t\ts_isAdvancePs = 0;\n\t}\n\telse if(keyUse(KEY_V)) {\n\t\ts_isVectors = !s_isVectors;\n\t}\n\n\tif(s_isAdvancePs) {\n\t\t++s_ps;\n\t}\n\n\tUWORD uwShift = 0;\n\t// for(UBYTE i = 0; i <= 4; ++i) {\n\t\tuwShift = (uwShift << 1) | ((s_ps >> 0) & 1);\n\t\tuwShift = (uwShift << 1) | ((s_ps >> 1) & 1);\n\t\tuwShift = (uwShift << 1) | ((s_ps >> 2) & 1);\n\t\tuwShift = (uwShift << 1) | ((s_ps >> 3) & 1);\n\t\tuwShift = (uwShift << 1) | ((s_ps >> 4) & 1);\n\t// }\n\n\tfor(BYTE y = TWISTER_MIN_BLOCK_Y; y < TWISTER_MAX_BLOCK_Y; ++y) {\n\t\tWORD yy = TWISTER_CENTER_Y + y * TWISTER_BLOCK_SIZE + uwShift;\n\t\tfor(BYTE x = TWISTER_MIN_BLOCK_X; x < TWISTER_MAX_BLOCK_X; ++x) {\n\t\t\tWORD xx = TWISTER_CENTER_X + x * TWISTER_BLOCK_SIZE + uwShift;\n\n\t\t\tWORD wSrcX = xx - (y + 1) - (x + 1);\n\t\t\tWORD wSrcY = yy - (y + 1) + (x + 1);\n\t\t\tWORD wDstX = xx;\n\t\t\tWORD wDstY = yy;\n\t\t\tWORD wWidth = TWISTER_BLOCK_SIZE;\n\t\t\tWORD wHeight = TWISTER_BLOCK_SIZE;\n\n\t\t\tif(wDstX < 0) {\n\t\t\t\tWORD wDelta = -wDstX;\n\t\t\t\twSrcX += wDelta;\n\t\t\t\twWidth -= wDelta;\n\t\t\t\twDstX = 0;\n\t\t\t}\n\t\t\tif(wSrcX < 0) {\n\t\t\t\tWORD wDelta = -wSrcX;\n\t\t\t\twDstX += wDelta;\n\t\t\t\twWidth -= wDelta;\n\t\t\t\twSrcX = 0;\n\t\t\t}\n\t\t\tif(wSrcX + wWidth > SCREEN_PAL_WIDTH + CLIP_MARGIN_X) {\n\t\t\t\twWidth = SCREEN_PAL_WIDTH + CLIP_MARGIN_X - wSrcX;\n\t\t\t}\n\t\t\tif(wDstX + wWidth > SCREEN_PAL_WIDTH + CLIP_MARGIN_X) {\n\t\t\t\twWidth = SCREEN_PAL_WIDTH + CLIP_MARGIN_X - wDstX;\n\t\t\t}\n\n\t\t\tif(wDstY < 0) {\n\t\t\t\tWORD wDelta = -wDstY;\n\t\t\t\twSrcY += wDelta;\n\t\t\t\twHeight -= wDelta;\n\t\t\t\twDstY = 0;\n\t\t\t}\n\t\t\tif(wSrcY < 0) {\n\t\t\t\tWORD wDelta = -wSrcY;\n\t\t\t\twDstY += wDelta;\n\t\t\t\twWidth -= wDelta;\n\t\t\t\twSrcY = 0;\n\t\t\t}\n\t\t\tif(wSrcY + wHeight > 0 + SCREEN_PAL_HEIGHT + CLIP_MARGIN_Y) {\n\t\t\t\twHeight = 0 + SCREEN_PAL_HEIGHT + CLIP_MARGIN_Y - wSrcY;\n\t\t\t}\n\t\t\tif(wDstY + wHeight > 0 + SCREEN_PAL_HEIGHT + CLIP_MARGIN_Y) {\n\t\t\t\twHeight = 0 + SCREEN_PAL_HEIGHT + CLIP_MARGIN_Y - wDstY;\n\t\t\t}\n\n\t\t\tif(wWidth <= 0 || wHeight <= 0) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tif(s_isVectors) {\n\t\t\t\tblitLine(s_pBfr->pBack, wSrcX, wSrcY, wDstX, wDstY, 2, 0xFFFF, 0);\n\t\t\t\tchunkyToPlanar(1, wSrcX, wSrcY, s_pBfr->pBack);\n\t\t\t\tchunkyToPlanar(3, wDstX, wDstY, s_pBfr->pBack);\n\t\t\t}\n\t\t\telse {\n\t\t\t\tblitCopy(\n\t\t\t\t\ts_pBfr->pFront, wSrcX, wSrcY,\n\t\t\t\t\ts_pBfr->pBack, wDstX, wDstY, wWidth, wHeight, MINTERM_COOKIE\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t}\n\n\tfor(UWORD y = TWISTER_CENTER_Y - TWISTER_CENTER_RADIUS; y <= TWISTER_CENTER_Y + TWISTER_CENTER_RADIUS; ++y) {\n\t\tfor(UWORD x = TWISTER_CENTER_X - TWISTER_CENTER_RADIUS; x <= TWISTER_CENTER_X + TWISTER_CENTER_RADIUS; ++x) {\n\t\t\tUBYTE ubColor = randUw(&s_sRand) & 3;\n\t\t\tchunkyToPlanar(ubColor, x, y, s_pBfr->pBack);\n\t\t}\n\t}\n\n\tif(keyUse(KEY_G)) {\n\t\ttestGrid(16);\n\t}\n\telse if(keyUse(KEY_H)) {\n\t\ttestGrid(8);\n\t}\n\telse if(keyUse(KEY_J)) {\n\t\ttestGrid(4);\n\t}\n\n\tviewProcessManagers(s_pView);\n\tcopProcessBlocks();\n\tsystemIdleBegin();\n\tvPortWaitForEnd(s_pVPort);\n\tsystemIdleEnd();\n}\n\nvoid gsTestTwisterDestroy(void) {\n\tsystemUse();\n\t// Destroy buffer, view & viewport\n\tviewDestroy(s_pView);\n}\n"
  },
  {
    "path": "showcase/src/test/twister.h",
    "content": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at http://mozilla.org/MPL/2.0/. */\n\n#ifndef _SHOWCASE_TEST_TWISTER_H\n#define _SHOWCASE_TEST_TWISTER_H\n\nvoid gsTestTwisterCreate(void);\n\nvoid gsTestTwisterLoop(void);\n\nvoid gsTestTwisterDestroy(void);\n\n#endif // _SHOWCASE_TEST_TWISTER_H\n"
  },
  {
    "path": "src/ace/managers/advancedsprite.c",
    "content": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at http://mozilla.org/MPL/2.0/. */\n\n#include <ace/managers/advancedsprite.h>\n#include <ace/utils/bitmap.h>\n#include <ace/managers/blit.h>\n#include <ace/utils/sprite.h>\n#include <ace/managers/system.h>\n\n\n#define SPRITE_WIDTH 16\n#define TWOBPP_BYTEWIDTH 2\n\ntAdvancedSprite *advancedSpriteAdd(UBYTE ubChannelIndex, UWORD uwSpriteHeight,tBitMap *pSpriteVerticalStripBitmap1, tBitMap *pSpriteVerticalStripBitmap2 ) {\n    tAdvancedSprite *pAdvancedSprite = memAllocFastClear(sizeof(*pAdvancedSprite));\n    pAdvancedSprite->ubChannelIndex = ubChannelIndex;\n    pAdvancedSprite->isEnabled = 1;\n    pAdvancedSprite->uwHeight = uwSpriteHeight;\n\n\n    if(!(pSpriteVerticalStripBitmap1->Flags & BMF_INTERLEAVED) || (pSpriteVerticalStripBitmap1->Depth != 2  && (pSpriteVerticalStripBitmap1->Depth != 4 || (pAdvancedSprite->ubChannelIndex & 1) == 1))) {\n        logWrite(\n            \"ERR: Sprite channel %hhu bitmap %p isn't interleaved 2BPP(for any channel) or 4BPP(for an even channel)\\n\",\n            pAdvancedSprite->ubChannelIndex , pSpriteVerticalStripBitmap1\n        );\n        //return ;\n    }\n\n    pAdvancedSprite->ubByteWidth = bitmapGetByteWidth(pSpriteVerticalStripBitmap1);\n    if(pAdvancedSprite->ubByteWidth != 2 && pAdvancedSprite->ubByteWidth != 4) {\n        logWrite(\n            \"ERR: Unsupported sprite width: %hhu, expected 16 or 32\\n\",\n            pAdvancedSprite->ubByteWidth * 8\n        );\n        //return;\n    }\n\n    UWORD bStripe1NbAnim = pSpriteVerticalStripBitmap1->Rows / uwSpriteHeight;\n\n    UWORD bStripe2NbAnim = 0;\n    if (pSpriteVerticalStripBitmap2 != NULL) {\n        bStripe2NbAnim = pSpriteVerticalStripBitmap2->Rows / uwSpriteHeight;\n    }\n\n    pAdvancedSprite->uwAnimCount = bStripe1NbAnim + bStripe2NbAnim;\n\n    if(pSpriteVerticalStripBitmap1->Depth == 4) {\n        pAdvancedSprite->is4PP = 1;\n    } else {\n        pAdvancedSprite->is4PP = 0;\n    }\n\n    if(pAdvancedSprite->ubByteWidth == 2) {\n        if(pSpriteVerticalStripBitmap1->Depth == 2) {\n            pAdvancedSprite->ubSpriteCount=1;\n        } else if (pSpriteVerticalStripBitmap1->Depth == 4) {\n            pAdvancedSprite->ubSpriteCount=2;\n        }\n    }\n    if(pAdvancedSprite->ubByteWidth == 4) {\n        if(pSpriteVerticalStripBitmap1->Depth == 2) {\n            pAdvancedSprite->ubSpriteCount=2;\n        } else if (pSpriteVerticalStripBitmap1->Depth == 4) {\n            pAdvancedSprite->ubSpriteCount=4;\n        }\n    }\n\n    UWORD nbBitmap=pAdvancedSprite->uwAnimCount*pAdvancedSprite->ubSpriteCount;\n\n    UWORD nbBitmapLimit1=bStripe1NbAnim*pAdvancedSprite->ubSpriteCount;\n\n    pAdvancedSprite->pAnimBitmap= (tBitMap **)memAllocFastClear(nbBitmap*sizeof(tBitMap));\n\n    \n    tBitMap *tmpBitmap = bitmapCreate(\n        SPRITE_WIDTH, pAdvancedSprite->uwHeight,\n        4, BMF_CLEAR | BMF_INTERLEAVED\n    );\n    tBitMap *pointers_low;\n    tBitMap *pointers_high;\n\n    pointers_high = bitmapCreate(\n        TWOBPP_BYTEWIDTH*8, pAdvancedSprite->uwHeight,\n        2, BMF_CLEAR | BMF_INTERLEAVED);\n\n    pointers_low = bitmapCreate(\n        TWOBPP_BYTEWIDTH*8, pAdvancedSprite->uwHeight,\n        2, BMF_CLEAR | BMF_INTERLEAVED);\n\n    tBitMap *pSpriteVerticalStripBitmap;\n    pSpriteVerticalStripBitmap = pSpriteVerticalStripBitmap1;    \n    UWORD k = 0;\n    for (UWORD i = 0; i < nbBitmap;) {\n        if (i == nbBitmapLimit1) {\n            k=0;\n            pSpriteVerticalStripBitmap = pSpriteVerticalStripBitmap2;\n        }\n        // One time if 16 pixel wide, Two times if 32 pixel wide\n        for(unsigned j = 0; j < pAdvancedSprite->ubByteWidth/2; j++) {\n            if (pAdvancedSprite->is4PP) {\n                // Convert the 4bpp bitmap to 2bpp.\n                blitCopy(\n                    pSpriteVerticalStripBitmap, 0+j*SPRITE_WIDTH, k * pAdvancedSprite->uwHeight,\n                    tmpBitmap,\n                    0,0, // first line will be for sprite control data\n                    SPRITE_WIDTH, pAdvancedSprite->uwHeight,\n                    MINTERM_COOKIE\n                );\n                for (UWORD r = 0; r < tmpBitmap->Rows; r++)\n                {\n                    UWORD offetSrc = r * tmpBitmap->BytesPerRow;\n                    UWORD offetDst = r * pointers_low->BytesPerRow;\n                    memcpy(pointers_low->Planes[0] + offetDst, tmpBitmap->Planes[0] + offetSrc, TWOBPP_BYTEWIDTH);\n                    memcpy(pointers_low->Planes[1] + offetDst, tmpBitmap->Planes[1] + offetSrc, TWOBPP_BYTEWIDTH);\n                    memcpy(pointers_high->Planes[0] + offetDst, tmpBitmap->Planes[2] + offetSrc, TWOBPP_BYTEWIDTH);\n                    memcpy(pointers_high->Planes[1] + offetDst, tmpBitmap->Planes[3] + offetSrc, TWOBPP_BYTEWIDTH);\n                }\n                // Init +2 on height for sprite management data\n                pAdvancedSprite->pAnimBitmap[i] = bitmapCreate(\n                    SPRITE_WIDTH, pAdvancedSprite->uwHeight+2,\n                    2, BMF_CLEAR | BMF_INTERLEAVED\n                );\n                blitCopy(\n                    pointers_low, 0, 0,\n                    pAdvancedSprite->pAnimBitmap[i],\n                    0,1, // first line will be for sprite control data\n                    SPRITE_WIDTH, pAdvancedSprite->uwHeight,\n                    MINTERM_COOKIE\n                );\n                i++;\n                // Init +2 on height for sprite management data\n                pAdvancedSprite->pAnimBitmap[i] = bitmapCreate(\n                    SPRITE_WIDTH, pAdvancedSprite->uwHeight+2,\n                    2, BMF_CLEAR | BMF_INTERLEAVED\n                );\n                blitCopy(\n                    pointers_high, 0, 0,\n                    pAdvancedSprite->pAnimBitmap[i],\n                    0,1, // first line will be for sprite control data\n                    SPRITE_WIDTH, pAdvancedSprite->uwHeight,\n                    MINTERM_COOKIE\n                );\n                i++;\n            } else {\n                // Init +2 on height for sprite management data\n                pAdvancedSprite->pAnimBitmap[i] = bitmapCreate(\n                    SPRITE_WIDTH, pAdvancedSprite->uwHeight+2,\n                    pSpriteVerticalStripBitmap->Depth, BMF_CLEAR | BMF_INTERLEAVED\n                );\n                // Copy bitmap\n                blitCopy(\n                    pSpriteVerticalStripBitmap, 0+j*SPRITE_WIDTH, k * pAdvancedSprite->uwHeight,\n                    pAdvancedSprite->pAnimBitmap[i],\n                    0,1, // first line will be for sprite control data\n                    SPRITE_WIDTH, pAdvancedSprite->uwHeight,\n                    MINTERM_COOKIE\n                ); \n                i++;\n            }\n        }\n        k++;\n    }\n    bitmapDestroy(pointers_low);\n    bitmapDestroy(pointers_high);\n    bitmapDestroy(tmpBitmap);\n\n    pAdvancedSprite->pSprites = (tSprite **)memAllocFastClear(sizeof(tSprite*) * pAdvancedSprite->ubSpriteCount);\n\n    for (UWORD i = 0; i < pAdvancedSprite->ubSpriteCount; i++) {\n        if (pAdvancedSprite->is4PP) {\n            // 2 channels for 4bpp sprites\n            pAdvancedSprite->pSprites[i] = spriteAdd(ubChannelIndex+i, pAdvancedSprite->pAnimBitmap[i]);\n            i++;\n            //attached sprite\n            pAdvancedSprite->pSprites[i] = spriteAdd(ubChannelIndex+i, pAdvancedSprite->pAnimBitmap[i]);\n            spriteSetAttached(pAdvancedSprite->pSprites[i],1);\n        } else {\n            pAdvancedSprite->pSprites[i] = spriteAdd(ubChannelIndex+i, pAdvancedSprite->pAnimBitmap[i]);\n        }      \n    }\n\n    return pAdvancedSprite;\n}\n\nvoid advancedSpriteRemove(tAdvancedSprite *pAdvancedSprite) {\n    systemUse();\n    for (UWORD i = 0; i < pAdvancedSprite->ubSpriteCount; i++) {\n        spriteRemove(pAdvancedSprite->pSprites[i]);\n    }\n    for (UWORD i = 0; i < pAdvancedSprite->uwAnimCount; i++) {\n        bitmapDestroy(pAdvancedSprite->pAnimBitmap[i]);\n    }\n    memFree(pAdvancedSprite, sizeof(*pAdvancedSprite));\n    systemUnuse();\n}\n\nvoid advancedSpriteSetEnabled(tAdvancedSprite *pAdvancedSprite, UBYTE isEnabled) {\n    for (UWORD i = 0; i < pAdvancedSprite->ubSpriteCount; i++) {\n        spriteSetEnabled(pAdvancedSprite->pSprites[i], isEnabled);\n    }\n}\n\nvoid advancedSpriteSetPos(tAdvancedSprite *pAdvancedSprite,WORD wX, WORD wY) {\n    pAdvancedSprite->wX = wX;\n    pAdvancedSprite->wY = wY;\n    pAdvancedSprite->isHeaderToBeUpdated = 1;\n}\n\nvoid advancedSpriteSetPosX(tAdvancedSprite *pAdvancedSprite,WORD wX) {\n    pAdvancedSprite->wX = wX;\n    pAdvancedSprite->isHeaderToBeUpdated = 1;\n}\n\nvoid advancedSpriteSetPosY(tAdvancedSprite *pAdvancedSprite, WORD wY) {\n    pAdvancedSprite->wY = wY;\n    pAdvancedSprite->isHeaderToBeUpdated = 1;\n}\n\nvoid advancedSpriteSetFrame(tAdvancedSprite *pAdvancedSprite, UWORD animFrame) {\n    if (animFrame >= pAdvancedSprite->uwAnimCount) {\n        logWrite(\"ERR: Invalid animation index %hu\\n\", animFrame);\n        return;\n    }\n    pAdvancedSprite->uwAnimFrame=animFrame;\n    UWORD animIndex = animFrame << ((pAdvancedSprite->ubByteWidth == 4) + pAdvancedSprite->is4PP);\n    for (UWORD i = 0; i < pAdvancedSprite->ubSpriteCount; i++) {\n        spriteSetBitmap(pAdvancedSprite->pSprites[i], pAdvancedSprite->pAnimBitmap[animIndex+i]);\n        pAdvancedSprite->isHeaderToBeUpdated = 1; // To force header rewrite\n    }    \n}\n\nvoid advancedSpriteProcessChannel(tAdvancedSprite *pAdvancedSprite) {\n    for (UWORD i = 0; i < pAdvancedSprite->ubSpriteCount; i++) {\n        spriteProcessChannel(pAdvancedSprite->ubChannelIndex + i);\n    }\n}\n\n\nUWORD addAttachedX(tAdvancedSprite *pAdvancedSprite, UBYTE spriteindex) {\n    if (( pAdvancedSprite->ubByteWidth==4) && (( (spriteindex>1) && (pAdvancedSprite->is4PP== 1) ) || ( (spriteindex==1) && (pAdvancedSprite->is4PP==0) )))\n    {\n        return SPRITE_WIDTH;\n    }\n    return 0;\n}\n\nvoid advancedSpriteProcess(tAdvancedSprite *pAdvancedSprite) {\n    if(!pAdvancedSprite->isHeaderToBeUpdated) {\n        return;\n    }\n    for (UWORD i = 0; i < pAdvancedSprite->ubSpriteCount; i++) {\n        pAdvancedSprite->pSprites[i]->wX = pAdvancedSprite->wX + addAttachedX(pAdvancedSprite, i);\n\n        pAdvancedSprite->pSprites[i]->wY = pAdvancedSprite->wY;\n\n        pAdvancedSprite->pSprites[i]->isEnabled = pAdvancedSprite->isEnabled;\n\n        pAdvancedSprite->pSprites[i]->isHeaderToBeUpdated = 1;\n\n        spriteProcess(pAdvancedSprite->pSprites[i]);\n    }\n    pAdvancedSprite->isHeaderToBeUpdated=0;\n}\n"
  },
  {
    "path": "src/ace/managers/blit.c",
    "content": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at http://mozilla.org/MPL/2.0/. */\n\n#include <ace/managers/blit.h>\n#include <ace/managers/system.h>\n\nvoid blitManagerCreate(void) {\n\tlogBlockBegin(\"blitManagerCreate\");\n\tsystemSetDmaBit(DMAB_BLITTER, 1);\n\tlogBlockEnd(\"blitManagerCreate\");\n}\n\nvoid blitManagerDestroy(void) {\n\tlogBlockBegin(\"blitManagerDestroy\");\n\tsystemSetDmaBit(DMAB_BLITTER, 0);\n\tlogBlockEnd(\"blitManagerDestroy\");\n}\n\n#if defined(ACE_DEBUG)\nUBYTE _blitCheck(\n\tconst tBitMap *pSrc, WORD wSrcX, WORD wSrcY,\n\tconst tBitMap *pDst, WORD wDstX, WORD wDstY, WORD wWidth, WORD wHeight,\n\tUWORD uwLine, const char *szFile\n) {\n\tWORD wSrcWidth, wSrcHeight, wDstWidth, wDstHeight;\n\n\tUBYTE isErr = 0;\n\tif(pSrc) {\n\t\tif(!bitmapIsChip(pSrc)) {\n\t\t\tisErr = 1;\n\t\t\tlogWrite(\"ERR: Source is in FAST mem: %p (%p)\\n\", pSrc, pSrc->Planes[0]);\n\t\t}\n\t\twSrcWidth = pSrc->BytesPerRow << 3;\n\t\tif(bitmapIsInterleaved(pSrc)) {\n\t\t\twSrcWidth /= pSrc->Depth;\n\t\t}\n\t\twSrcHeight = pSrc->Rows;\n\t}\n\telse {\n\t\twSrcWidth = 0;\n\t\twSrcHeight = 0;\n\t}\n\n\tif(pDst) {\n\t\tif(!bitmapIsChip(pDst)) {\n\t\t\tisErr = 1;\n\t\t\tlogWrite(\"ERR: Dest is in FAST mem: %p (%p)\\n\", pDst, pDst->Planes[0]);\n\t\t}\n\t\twDstWidth = pDst->BytesPerRow << 3;\n\t\tif(bitmapIsInterleaved(pDst)) {\n\t\t\twDstWidth /= pDst->Depth;\n\t\t}\n\t\twDstHeight = pDst->Rows;\n\t}\n\telse {\n\t\twDstWidth = 0;\n\t\twDstHeight = 0;\n\t}\n\n\tif(isErr) {\n\t\treturn 1;\n\t}\n\n\tif(pSrc && (wSrcX < 0 || wSrcWidth < wSrcX + wWidth || wSrcHeight < wSrcY + wHeight)) {\n\t\tlogWrite(\n\t\t\t\"ERR: ILLEGAL BLIT Source out of range: \"\n\t\t\t\"source %p %dx%d, dest: %p %dx%d, blit: %d,%d -> %d,%d %dx%d (%s:%u)\\n\",\n\t\t\tpSrc,\twSrcWidth, wSrcHeight, pDst, wDstWidth, wDstHeight,\n\t\t\twSrcX, wSrcY, wDstX, wDstY, wWidth, wHeight, szFile, uwLine\n\t\t);\n\t\treturn 0;\n\t}\n\tif(pDst && (wDstY < 0 || wDstWidth < wDstX + wWidth || wDstHeight < wDstY + wHeight)) {\n\t\tlogWrite(\n\t\t\t\"ERR: ILLEGAL BLIT Dest out of range: \"\n\t\t\t\"source %p %dx%d, dest: %p %dx%d, blit: %d,%d -> %d,%d %dx%d (%s:%u)\\n\",\n\t\t\tpSrc,\twSrcWidth, wSrcHeight, pDst, wDstWidth, wDstHeight,\n\t\t\twSrcX, wSrcY, wDstX, wDstY, wWidth, wHeight, szFile, uwLine\n\t\t);\n\t\treturn 0;\n\t}\n\n#if defined(ACE_USE_ECS_FEATURES)\n\tUWORD uwMaxBlitWidth = 32768;\n#else\n\tUWORD uwMaxBlitWidth = 1024;\n#endif\n\n\tif(pSrc && pDst && bitmapIsInterleaved(pSrc) && bitmapIsInterleaved(pDst)) {\n\t\tif(wHeight * pSrc->Depth > uwMaxBlitWidth) {\n\t\t\tlogWrite(\n\t\t\t\t\"ERR: Blit too big: height %hd, depth: %hhu, interleaved: %d (%s:%u)\\n\",\n\t\t\t\twHeight, pSrc->Depth, wHeight * pSrc->Depth, szFile, uwLine\n\t\t\t);\n\t\t}\n\t}\n\n\treturn 1;\n}\n#endif // defined(ACE_DEBUG)\n\nvoid blitWait(void) {\n\t// A1000 Blitter done bug:\n\t// The solution is to read hardware register before testing the bit.\n\t(void)g_pCustom->dmaconr;\n\twhile(g_pCustom->dmaconr & DMAF_BLTDONE) continue;\n}\n\nUBYTE blitIsIdle(void) {\n\t// A1000 Blitter done bug:\n\t// The solution is to read hardware register before testing the bit.\n\t(void)g_pCustom->dmaconr;\n\tif(g_pCustom->dmaconr & DMAF_BLTDONE) {\n\t\treturn 0;\n\t}\n\treturn 1;\n}\n\nUBYTE blitUnsafeCopy(\n\tconst tBitMap *pSrc, WORD wSrcX, WORD wSrcY,\n\ttBitMap *pDst, WORD wDstX, WORD wDstY, WORD wWidth, WORD wHeight,\n\tUBYTE ubMinterm\n) {\n\t// Helper vars\n\tUWORD uwBlitWords, uwBlitWidth;\n\tULONG ulSrcOffs, ulDstOffs;\n\tUBYTE ubShift, ubSrcDelta, ubDstDelta, ubWidthDelta, ubMaskFShift, ubMaskLShift;\n\t// Blitter register values\n\tUWORD uwBltCon0, uwBltCon1, uwFirstMask, uwLastMask;\n\tWORD wSrcModulo, wDstModulo;\n\n\tubSrcDelta = wSrcX & 0xF;\n\tubDstDelta = wDstX & 0xF;\n\tubWidthDelta = (ubSrcDelta + wWidth) & 0xF;\n\tUBYTE isBlitInterleaved = (\n\t\tbitmapIsInterleaved(pSrc) && bitmapIsInterleaved(pDst) &&\n\t\tpSrc->Depth == pDst->Depth\n\t);\n\n\tif(ubSrcDelta > ubDstDelta || ((wWidth+ubDstDelta+15) & 0xFFF0)-(wWidth+ubSrcDelta) > 16) {\n\t\tuwBlitWidth = (wWidth+(ubSrcDelta>ubDstDelta?ubSrcDelta:ubDstDelta)+15) & 0xFFF0;\n\t\tuwBlitWords = uwBlitWidth >> 4;\n\n\t\tubMaskFShift = ((ubWidthDelta+15)&0xF0)-ubWidthDelta;\n\t\tubMaskLShift = uwBlitWidth - (wWidth+ubMaskFShift);\n\t\tuwFirstMask = 0xFFFF << ubMaskFShift;\n\t\tuwLastMask = 0xFFFF >> ubMaskLShift;\n\t\tif(ubMaskLShift > 16) { // Fix for 2-word blits\n\t\t\tuwFirstMask &= 0xFFFF >> (ubMaskLShift-16);\n\t\t}\n\n\t\tubShift = uwBlitWidth - (ubDstDelta+wWidth+ubMaskFShift);\n\t\tuwBltCon1 = (ubShift << BSHIFTSHIFT) | BLITREVERSE;\n\n\t\t// Position on the end of last row of the bitmap.\n\t\t// For interleaved, position on the last row of last bitplane.\n\t\tif(isBlitInterleaved) {\n\t\t\t// TODO: fix duplicating bitmapIsInterleaved() check inside bitmapGetByteWidth()\n\t\t\tulSrcOffs = pSrc->BytesPerRow * (wSrcY + wHeight) - bitmapGetByteWidth(pSrc) + ((wSrcX + wWidth + ubMaskFShift - 1) / 16) * 2;\n\t\t\tulDstOffs = pDst->BytesPerRow * (wDstY + wHeight) - bitmapGetByteWidth(pDst) + ((wDstX + wWidth + ubMaskFShift - 1) / 16) * 2;\n\t\t}\n\t\telse {\n\t\t\tulSrcOffs = pSrc->BytesPerRow * (wSrcY + wHeight - 1) + ((wSrcX + wWidth + ubMaskFShift - 1) / 16) * 2;\n\t\t\tulDstOffs = pDst->BytesPerRow * (wDstY + wHeight - 1) + ((wDstX + wWidth + ubMaskFShift - 1) / 16) * 2;\n\t\t}\n\t}\n\telse {\n\t\tuwBlitWidth = (wWidth+ubDstDelta+15) & 0xFFF0;\n\t\tuwBlitWords = uwBlitWidth >> 4;\n\n\t\tubMaskFShift = ubSrcDelta;\n\t\tubMaskLShift = uwBlitWidth-(wWidth+ubSrcDelta);\n\n\t\tuwFirstMask = 0xFFFF >> ubMaskFShift;\n\t\tuwLastMask = 0xFFFF << ubMaskLShift;\n\n\t\tubShift = ubDstDelta-ubSrcDelta;\n\t\tuwBltCon1 = ubShift << BSHIFTSHIFT;\n\n\t\tulSrcOffs = pSrc->BytesPerRow * wSrcY + (wSrcX >> 3);\n\t\tulDstOffs = pDst->BytesPerRow * wDstY + (wDstX >> 3);\n\t}\n\n\tuwBltCon0 = (ubShift << ASHIFTSHIFT) | USEB|USEC|USED | ubMinterm;\n\n\tif(isBlitInterleaved) {\n\t\twHeight *= pSrc->Depth;\n\t\twSrcModulo = bitmapGetByteWidth(pSrc) - uwBlitWords * 2;\n\t\twDstModulo = bitmapGetByteWidth(pDst) - uwBlitWords * 2;\n\n\t\tblitWait(); // Don't modify registers when other blit is in progress\n\t\tg_pCustom->bltcon0 = uwBltCon0;\n\t\tg_pCustom->bltcon1 = uwBltCon1;\n\t\tg_pCustom->bltafwm = uwFirstMask;\n\t\tg_pCustom->bltalwm = uwLastMask;\n\t\tg_pCustom->bltbmod = wSrcModulo;\n\t\tg_pCustom->bltcmod = wDstModulo;\n\t\tg_pCustom->bltdmod = wDstModulo;\n\t\tg_pCustom->bltadat = 0xFFFF;\n\t\tg_pCustom->bltbpt = &pSrc->Planes[0][ulSrcOffs];\n\t\tg_pCustom->bltcpt = &pDst->Planes[0][ulDstOffs];\n\t\tg_pCustom->bltdpt = &pDst->Planes[0][ulDstOffs];\n#if defined(ACE_USE_ECS_FEATURES)\n\t\tg_pCustom->bltsizv = wHeight;\n\t\tg_pCustom->bltsizh = uwBlitWords;\n#else\n\t\tg_pCustom->bltsize = (wHeight << HSIZEBITS) | uwBlitWords;\n#endif\n\t}\n\telse {\n\t\twSrcModulo = pSrc->BytesPerRow - uwBlitWords * 2;\n\t\twDstModulo = pDst->BytesPerRow - uwBlitWords * 2;\n\t\tUBYTE ubPlane = MIN(pSrc->Depth, pDst->Depth);\n\n\t\tblitWait(); // Don't modify registers when other blit is in progress\n\t\tg_pCustom->bltcon0 = uwBltCon0;\n\t\tg_pCustom->bltcon1 = uwBltCon1;\n\t\tg_pCustom->bltafwm = uwFirstMask;\n\t\tg_pCustom->bltalwm = uwLastMask;\n\t\tg_pCustom->bltbmod = wSrcModulo;\n\t\tg_pCustom->bltcmod = wDstModulo;\n\t\tg_pCustom->bltdmod = wDstModulo;\n\t\tg_pCustom->bltadat = 0xFFFF;\n\t\twhile(ubPlane--) {\n\t\t\tblitWait();\n\t\t\t// This hell of a casting must stay here or else large offsets get bugged!\n\t\t\tg_pCustom->bltbpt = &pSrc->Planes[ubPlane][ulSrcOffs];\n\t\t\tg_pCustom->bltcpt = &pDst->Planes[ubPlane][ulDstOffs];\n\t\t\tg_pCustom->bltdpt = &pDst->Planes[ubPlane][ulDstOffs];\n\n#if defined(ACE_USE_ECS_FEATURES)\n\t\t\tg_pCustom->bltsizv = wHeight;\n\t\t\tg_pCustom->bltsizh = uwBlitWords;\n#else\n\t\t\tg_pCustom->bltsize = (wHeight << HSIZEBITS) | uwBlitWords;\n#endif\n\t\t}\n\t}\n\n\treturn 1;\n}\n\nUBYTE blitSafeCopy(\n\tconst tBitMap *pSrc, WORD wSrcX, WORD wSrcY,\n\ttBitMap *pDst, WORD wDstX, WORD wDstY, WORD wWidth, WORD wHeight,\n\tUBYTE ubMinterm, UWORD uwLine, const char *szFile\n) {\n\tif(!blitCheck(pSrc, wSrcX, wSrcY, pDst, wDstX, wDstY, wWidth, wHeight, uwLine, szFile)) {\n\t\treturn 0;\n\t}\n\treturn blitUnsafeCopy(pSrc, wSrcX, wSrcY, pDst, wDstX, wDstY, wWidth, wHeight, ubMinterm);\n}\n\n/**\n * Very restrictive and fast blit variant\n * Works only with src/dst/width divisible by 16\n * Does not check if destination has less bitplanes than source\n * Best for drawing tilemaps\n */\nUBYTE blitUnsafeCopyAligned(\n\tconst tBitMap *pSrc, WORD wSrcX, WORD wSrcY,\n\ttBitMap *pDst, WORD wDstX, WORD wDstY, WORD wWidth, WORD wHeight\n) {\n\t// Use C channel instead of A - same speed, less regs to set up\n\tUWORD uwBlitWords = wWidth / 16;\n\tUWORD uwBltCon0 = USEC|USED | MINTERM_C;\n\tULONG ulSrcOffs = pSrc->BytesPerRow * wSrcY + (wSrcX / 8);\n\tULONG ulDstOffs = pDst->BytesPerRow * wDstY + (wDstX / 8);\n\n\tif(bitmapIsInterleaved(pSrc) && bitmapIsInterleaved(pDst)) {\n\t\tWORD wSrcModulo = bitmapGetByteWidth(pSrc) - uwBlitWords * 2;\n\t\tWORD wDstModulo = bitmapGetByteWidth(pDst) - uwBlitWords * 2;\n\t\twHeight *= pSrc->Depth;\n\n\t\tblitWait(); // Don't modify registers when other blit is in progress\n\t\tg_pCustom->bltcon0 = uwBltCon0;\n\t\tg_pCustom->bltcon1 = 0;\n\t\tg_pCustom->bltcmod = wSrcModulo;\n\t\tg_pCustom->bltdmod = wDstModulo;\n\t\tg_pCustom->bltcpt = &pSrc->Planes[0][ulSrcOffs];\n\t\tg_pCustom->bltdpt = &pDst->Planes[0][ulDstOffs];\n#if defined(ACE_USE_ECS_FEATURES)\n\t\tg_pCustom->bltsizv = wHeight;\n\t\tg_pCustom->bltsizh = uwBlitWords;\n#else\n\t\tg_pCustom->bltsize = (wHeight << HSIZEBITS) | uwBlitWords;\n#endif\n\n\t}\n\telse {\n\t\tif(bitmapIsInterleaved(pSrc) || bitmapIsInterleaved(pDst)) {\n\t\t\t// Since you're using this fn for speed\n\t\t\tlogWrite(\"WARN: Mixed interleaved - you're losing lots of performance here\\n\");\n\t\t}\n\n\t\tWORD wSrcModulo = pSrc->BytesPerRow - (uwBlitWords<<1);\n\t\tWORD wDstModulo = pDst->BytesPerRow - (uwBlitWords<<1);\n\t\tUBYTE ubPlane = pSrc->Depth;\n\n\t\tblitWait(); // Don't modify registers when other blit is in progress\n\t\tg_pCustom->bltcon0 = uwBltCon0;\n\t\tg_pCustom->bltcon1 = 0;\n\t\tg_pCustom->bltcmod = wSrcModulo;\n\t\tg_pCustom->bltdmod = wDstModulo;\n\t\twhile(ubPlane--) {\n\t\t\tblitWait();\n\t\t\tg_pCustom->bltcpt = &pSrc->Planes[ubPlane][ulSrcOffs];\n\t\t\tg_pCustom->bltdpt = &pDst->Planes[ubPlane][ulDstOffs];\n#if defined(ACE_USE_ECS_FEATURES)\n\t\t\tg_pCustom->bltsizv = wHeight;\n\t\t\tg_pCustom->bltsizh = uwBlitWords;\n#else\n\t\t\tg_pCustom->bltsize = (wHeight << HSIZEBITS) | uwBlitWords;\n#endif\n\t\t}\n\t}\n\n\treturn 1;\n}\n\nUBYTE blitSafeCopyAligned(\n\tconst tBitMap *pSrc, WORD wSrcX, WORD wSrcY,\n\ttBitMap *pDst, WORD wDstX, WORD wDstY, WORD wWidth, WORD wHeight,\n\tUWORD uwLine, const char *szFile\n) {\n\tif((wSrcX | wDstX | wWidth) & 0x000F) {\n\t\tlogWrite(\"ERR: Dimensions are not divisible by 16\\n\");\n\t\treturn 0;\n\t}\n\tif(!blitCheck(\n\t\tpSrc, wSrcX, wSrcY, pDst, wDstX, wDstY, wWidth, wHeight, uwLine, szFile\n\t)) {\n\t\treturn 0;\n\t}\n\n\tif(bitmapIsInterleaved(pSrc) && bitmapIsInterleaved(pDst) && pSrc->Depth != pDst->Depth) {\n\t\tlogWrite(\n\t\t\t\"ERR: bitmap BPP mismatch on interleaved blit! src: %hhu, dst: %hhu\\n\",\n\t\t\tpSrc->Depth, pDst->Depth\n\t\t);\n\t\treturn 0;\n\t}\n\n\treturn blitUnsafeCopyAligned(pSrc, wSrcX, wSrcY, pDst, wDstX, wDstY, wWidth, wHeight);\n}\n\n/**\n * Copies source data to destination over mask\n * Optimizations require following conditions:\n * - wSrcX <= wDstX (shifts to right)\n * - mask must have same dimensions as source bitplane\n */\nUBYTE blitUnsafeCopyMask(\n\tconst tBitMap *pSrc, WORD wSrcX, WORD wSrcY,\n\ttBitMap *pDst, WORD wDstX, WORD wDstY,\n\tWORD wWidth, WORD wHeight, const UBYTE *pMsk\n) {\n\t// Helper vars\n\tUWORD uwBlitWords, uwBlitWidth;\n\tULONG ulSrcOffs, ulDstOffs;\n\tUBYTE ubShift, ubSrcDelta, ubDstDelta, ubWidthDelta, ubMaskFShift, ubMaskLShift;\n\t// Blitter register values\n\tUWORD uwBltCon0, uwBltCon1, uwFirstMask, uwLastMask;\n\tWORD wSrcModulo, wDstModulo;\n\n\tubSrcDelta = wSrcX & 0xF;\n\tubDstDelta = wDstX & 0xF;\n\tubWidthDelta = (ubSrcDelta + wWidth) & 0xF;\n\tUBYTE isBlitInterleaved = (\n\t\tbitmapIsInterleaved(pSrc) && bitmapIsInterleaved(pDst) &&\n\t\tpSrc->Depth == pDst->Depth\n\t);\n\n\tif(ubSrcDelta > ubDstDelta || ((wWidth+ubDstDelta+15) & 0xFFF0)-(wWidth+ubSrcDelta) > 16) {\n\t\tuwBlitWidth = (wWidth+(ubSrcDelta>ubDstDelta?ubSrcDelta:ubDstDelta)+15) & 0xFFF0;\n\t\tuwBlitWords = uwBlitWidth >> 4;\n\n\t\tubMaskFShift = ((ubWidthDelta+15)&0xF0)-ubWidthDelta;\n\t\tubMaskLShift = uwBlitWidth - (wWidth+ubMaskFShift);\n\n\t\t// Position on the end of last row of the bitmap.\n\t\t// For interleaved, position on the last row of last bitplane.\n\t\tif(isBlitInterleaved) {\n\t\t\t// TODO: fix duplicating bitmapIsInterleaved() check inside bitmapGetByteWidth()\n\t\t\tulSrcOffs = pSrc->BytesPerRow * (wSrcY + wHeight) - bitmapGetByteWidth(pSrc) + ((wSrcX + wWidth + ubMaskFShift - 1) / 16) * 2;\n\t\t\tulDstOffs = pDst->BytesPerRow * (wDstY + wHeight) - bitmapGetByteWidth(pDst) + ((wDstX + wWidth + ubMaskFShift - 1) / 16) * 2;\n\t\t}\n\t\telse {\n\t\t\tulSrcOffs = pSrc->BytesPerRow * (wSrcY + wHeight - 1) + ((wSrcX + wWidth + ubMaskFShift - 1) / 16) * 2;\n\t\t\tulDstOffs = pDst->BytesPerRow * (wDstY + wHeight - 1) + ((wDstX + wWidth + ubMaskFShift - 1) / 16) * 2;\n\t\t}\n\n\t\tuwFirstMask = 0xFFFF << ubMaskFShift;\n\t\tuwLastMask = 0xFFFF >> ubMaskLShift;\n\t\tif(ubMaskLShift > 16) { // Fix for 2-word blits\n\t\t\tuwFirstMask &= 0xFFFF >> (ubMaskLShift-16);\n\t\t}\n\n\t\tubShift = uwBlitWidth - (ubDstDelta+wWidth+ubMaskFShift);\n\t\tuwBltCon1 = (ubShift << BSHIFTSHIFT) | BLITREVERSE;\n\t}\n\telse {\n\t\tuwBlitWidth = (wWidth+ubDstDelta+15) & 0xFFF0;\n\t\tuwBlitWords = uwBlitWidth >> 4;\n\n\t\tubMaskFShift = ubSrcDelta;\n\t\tubMaskLShift = uwBlitWidth-(wWidth+ubSrcDelta);\n\n\t\tuwFirstMask = 0xFFFF >> ubMaskFShift;\n\t\tuwLastMask = 0xFFFF << ubMaskLShift;\n\n\t\tubShift = ubDstDelta-ubSrcDelta;\n\t\tuwBltCon1 = ubShift << BSHIFTSHIFT;\n\n\t\tulSrcOffs = pSrc->BytesPerRow * wSrcY + (wSrcX >> 3);\n\t\tulDstOffs = pDst->BytesPerRow * wDstY + (wDstX >> 3);\n\t}\n\n\t uwBltCon0 = uwBltCon1 |USEA|USEB|USEC|USED | MINTERM_COOKIE;\n\n\tif(isBlitInterleaved) {\n\t\twHeight *= pSrc->Depth;\n\t\twSrcModulo = bitmapGetByteWidth(pSrc) - uwBlitWords * 2;\n\t\twDstModulo = bitmapGetByteWidth(pDst) - uwBlitWords * 2;\n\n\t\tblitWait(); // Don't modify registers when other blit is in progress\n\t\tg_pCustom->bltcon0 = uwBltCon0;\n\t\tg_pCustom->bltcon1 = uwBltCon1;\n\t\tg_pCustom->bltafwm = uwFirstMask;\n\t\tg_pCustom->bltalwm = uwLastMask;\n\t\tg_pCustom->bltamod = wSrcModulo;\n\t\tg_pCustom->bltbmod = wSrcModulo;\n\t\tg_pCustom->bltcmod = wDstModulo;\n\t\tg_pCustom->bltdmod = wDstModulo;\n\t\tg_pCustom->bltapt = (APTR)&pMsk[ulSrcOffs];\n\t\tg_pCustom->bltbpt = &pSrc->Planes[0][ulSrcOffs];\n\t\tg_pCustom->bltcpt = &pDst->Planes[0][ulDstOffs];\n\t\tg_pCustom->bltdpt = &pDst->Planes[0][ulDstOffs];\n#if defined(ACE_USE_ECS_FEATURES)\n\t\tg_pCustom->bltsizv = wHeight;\n\t\tg_pCustom->bltsizh = uwBlitWords;\n#else\n\t\tg_pCustom->bltsize = (wHeight << HSIZEBITS) | uwBlitWords;\n#endif\n\t}\n\telse {\n\t\twSrcModulo = pSrc->BytesPerRow - uwBlitWords * 2;\n\t\twDstModulo = pDst->BytesPerRow - uwBlitWords * 2;\n\t\tUBYTE ubPlane = MIN(pSrc->Depth, pDst->Depth);\n\n\t\tblitWait(); // Don't modify registers when other blit is in progress\n\t\tg_pCustom->bltcon0 = uwBltCon0;\n\t\tg_pCustom->bltcon1 = uwBltCon1;\n\t\tg_pCustom->bltafwm = uwFirstMask;\n\t\tg_pCustom->bltalwm = uwLastMask;\n\t\tg_pCustom->bltapt = (APTR)&pMsk[ulSrcOffs];\n\t\tg_pCustom->bltamod = wSrcModulo;\n\t\tg_pCustom->bltbmod = wSrcModulo;\n\t\tg_pCustom->bltcmod = wDstModulo;\n\t\tg_pCustom->bltdmod = wDstModulo;\n\n\t\twhile(ubPlane--) {\n\t\t\tblitWait();\n\t\t\t// This hell of a casting must stay here or else large offsets get bugged!\n\t\t\tg_pCustom->bltapt = (APTR)&pMsk[ulSrcOffs];\n\t\t\tg_pCustom->bltbpt = &pSrc->Planes[ubPlane][ulSrcOffs];\n\t\t\tg_pCustom->bltcpt = &pDst->Planes[ubPlane][ulDstOffs];\n\t\t\tg_pCustom->bltdpt = &pDst->Planes[ubPlane][ulDstOffs];\n\n#if defined(ACE_USE_ECS_FEATURES)\n\t\t\tg_pCustom->bltsizv = wHeight;\n\t\t\tg_pCustom->bltsizh = uwBlitWords;\n#else\n\t\t\tg_pCustom->bltsize = (wHeight << HSIZEBITS) | uwBlitWords;\n#endif\n\t\t}\n\t}\n\n\treturn 1;\n}\n\nUBYTE blitSafeCopyMask(\n\tconst tBitMap *pSrc, WORD wSrcX, WORD wSrcY,\n\ttBitMap *pDst, WORD wDstX, WORD wDstY,\n\tWORD wWidth, WORD wHeight, const UBYTE *pMsk, UWORD uwLine, const char *szFile\n) {\n\tif(!blitCheck(pSrc, wSrcX, wSrcY, pDst, wDstX, wDstY, wWidth, wHeight, uwLine, szFile)) {\n\t\treturn 0;\n\t}\n\treturn blitUnsafeCopyMask(pSrc, wSrcX, wSrcY, pDst, wDstX, wDstY, wWidth, wHeight, pMsk);\n}\n\nUBYTE blitUnsafeRect(\n\ttBitMap *pDst, WORD wDstX, WORD wDstY, WORD wWidth, WORD wHeight,\n\tUBYTE ubColor\n) {\n\t// Helper vars\n\tUWORD uwBlitWords, uwBlitWidth;\n\tULONG ulDstOffs;\n\tUBYTE ubDstDelta, ubMinterm, ubPlane;\n\t// Blitter register values\n\tUWORD uwBltCon0, uwBltCon1, uwFirstMask, uwLastMask;\n\tWORD wDstModulo;\n\n\tubDstDelta = wDstX & 0xF;\n\tuwBlitWidth = (wWidth+ubDstDelta+15) & 0xFFF0;\n\tuwBlitWords = uwBlitWidth >> 4;\n\n\tuwFirstMask = 0xFFFF >> ubDstDelta;\n\tuwLastMask = 0xFFFF << (uwBlitWidth-(wWidth+ubDstDelta));\n\tuwBltCon1 = 0;\n\tulDstOffs = pDst->BytesPerRow * wDstY + (wDstX>>3);\n\twDstModulo = pDst->BytesPerRow - (uwBlitWords<<1);\n\tuwBltCon0 = USEC|USED;\n\n\tblitWait(); // Don't modify registers when other blit is in progress\n\tg_pCustom->bltcon1 = uwBltCon1;\n\tg_pCustom->bltafwm = uwFirstMask;\n\tg_pCustom->bltalwm = uwLastMask;\n\n\tg_pCustom->bltcmod = wDstModulo;\n\tg_pCustom->bltdmod = wDstModulo;\n\tg_pCustom->bltadat = 0xFFFF;\n\tg_pCustom->bltbdat = 0;\n\tubPlane = 0;\n\n\tdo {\n\t\t// Assign minterm depending if bitplane area should be filled or erased\n\t\tubMinterm = (ubColor & 1) ? MINTERM_A_OR_C : MINTERM_NA_AND_C;\n\t\tblitWait();\n\t\tg_pCustom->bltcon0 = uwBltCon0 | ubMinterm;\n\t\t// This hell of a casting must stay here or else large offsets get bugged!\n\t\tg_pCustom->bltcpt = pDst->Planes[ubPlane] + ulDstOffs;\n\t\tg_pCustom->bltdpt = pDst->Planes[ubPlane] + ulDstOffs;\n#if defined(ACE_USE_ECS_FEATURES)\n\t\tg_pCustom->bltsizv = wHeight;\n\t\tg_pCustom->bltsizh = uwBlitWords;\n#else\n\t\tg_pCustom->bltsize = (wHeight << HSIZEBITS) | uwBlitWords;\n#endif\n\t\tubColor >>= 1;\n\t\t++ubPlane;\n\t}\twhile(ubPlane < pDst->Depth);\n\treturn 1;\n}\n\nUBYTE blitSafeRect(\n\ttBitMap *pDst, WORD wDstX, WORD wDstY, WORD wWidth, WORD wHeight,\n\tUBYTE ubColor, UWORD uwLine, const char *szFile\n) {\n\tif(!blitCheck(0,0,0,pDst, wDstX, wDstY, wWidth, wHeight, uwLine, szFile)) {\n\t\treturn 0;\n\t}\n\n\treturn blitUnsafeRect(pDst, wDstX, wDstY, wWidth, wHeight, ubColor);\n}\n\nvoid blitUnsafeFillAligned(\n\ttBitMap *pDst, WORD wDstX, WORD wDstY, WORD wWidth, WORD wHeight,\n\tUBYTE ubPlane, UBYTE ubFillMode\n) {\n\tUWORD uwBlitWords = wWidth / 16;\n\n\tUWORD uwWordMaskA = 0xFFFF;\n\tULONG ulDstOffs = pDst->BytesPerRow * (wDstY + wHeight - 1) + ((wDstX + wWidth) / 8) - sizeof(UWORD);\n\tWORD wDstModulo = pDst->BytesPerRow - (uwBlitWords * 2);\n\tUWORD uwBltCon0 = USEA | USED | MINTERM_A;\n\tUWORD uwBltCon1 = BLITREVERSE | ubFillMode;\n\tUBYTE *pPlaneOffset = pDst->Planes[ubPlane] + ulDstOffs;\n\n\tblitWait(); // Don't modify registers when other blit is in progress\n\tg_pCustom->bltcon1 = uwBltCon1;\n\tg_pCustom->bltafwm = uwWordMaskA;\n\tg_pCustom->bltalwm = uwWordMaskA;\n\n\tg_pCustom->bltamod = wDstModulo;\n\tg_pCustom->bltdmod = wDstModulo;\n\n\tg_pCustom->bltcon0 = uwBltCon0;\n\t// This hell of a casting must stay here or else large offsets get bugged!\n\tg_pCustom->bltapt = pPlaneOffset;\n\tg_pCustom->bltdpt = pPlaneOffset;\n#if defined(ACE_USE_ECS_FEATURES)\n\tg_pCustom->bltsizv = wHeight;\n\tg_pCustom->bltsizh = uwBlitWords;\n#else\n\tg_pCustom->bltsize = (wHeight << HSIZEBITS) | uwBlitWords;\n#endif\n}\n\nUBYTE blitSafeFillAligned(\n\ttBitMap *pDst, WORD wDstX, WORD wDstY, WORD wWidth, WORD wHeight,\n\tUBYTE ubPlane, UBYTE ubFillMode, UWORD uwLine, const char *szFile\n) {\n\tif((wDstX | wWidth) & 0x000F) {\n\t\tlogWrite(\"ERR: Dimensions are not divisible by 16\\n\");\n\t\treturn 0;\n\t}\n\tif(!blitCheck(0,0,0,pDst, wDstX, wDstY, wWidth, wHeight, uwLine, szFile)) {\n\t\treturn 0;\n\t}\n\n\tblitUnsafeFillAligned(pDst, wDstX, wDstY, wWidth, wHeight, ubPlane, ubFillMode);\n\treturn 1;\n}\n\nvoid blitLine(\n\ttBitMap *pDst, WORD wX1, WORD wY1, WORD wX2, WORD wY2,\n\tUBYTE ubColor, UWORD uwPattern, UBYTE isOneDot\n) {\n\t// Based on Cahir's function from:\n\t// https://github.com/cahirwpz/demoscene/blob/master/a500/base/libsys/blt-line.c\n\n\tUWORD uwBltCon1 = LINEMODE;\n\tif(isOneDot) {\n\t\tuwBltCon1 |= ONEDOT;\n\t}\n\n\t// Always draw the line downwards.\n\tif (wY1 > wY2) {\n\t\tSWAP(wX1, wX2);\n\t\tSWAP(wY1, wY2);\n\t}\n\n\t// Setup octant bits\n\tWORD wDx = wX2 - wX1;\n\tWORD wDy = wY2 - wY1;\n\tif (wDx < 0) {\n\t\twDx = -wDx;\n\t\tif (wDx >= wDy) {\n\t\t\tuwBltCon1 |= AUL | SUD;\n\t\t}\n\t\telse {\n\t\t\tuwBltCon1 |= SUL;\n\t\t\tSWAP(wDx, wDy);\n\t\t}\n\t}\n\telse {\n\t\tif (wDx >= wDy) {\n\t\t\tuwBltCon1 |= SUD;\n\t\t}\n\t\telse {\n\t\t\tSWAP(wDx, wDy);\n\t\t}\n\t}\n\n\tWORD wDerr = wDy + wDy - wDx;\n\tif (wDerr < 0) {\n\t\tuwBltCon1 |= SIGNFLAG;\n\t}\n\n\tUWORD uwBltSize = (wDx << HSIZEBITS) + 66;\n\tUWORD uwBltCon0 = ror16(wX1 & 15, 4);\n\tULONG ulDataOffs = pDst->BytesPerRow * wY1 + ((wX1 / 8) & ~1);\n\n\tblitWait(); // Don't modify registers when other blit is in progress\n\tg_pCustom->bltafwm = -1;\n\tg_pCustom->bltalwm = -1;\n\tg_pCustom->bltadat = 0x8000;\n\tg_pCustom->bltbdat = uwPattern;\n\tg_pCustom->bltamod = wDerr - wDx;\n\tg_pCustom->bltbmod = wDy + wDy;\n\tg_pCustom->bltcmod = pDst->BytesPerRow;\n\tg_pCustom->bltdmod = pDst->BytesPerRow;\n\tg_pCustom->bltcon1 = uwBltCon1;\n\tg_pCustom->bltapt = (APTR)(LONG)wDerr;\n\tfor(UBYTE ubPlane = 0; ubPlane != pDst->Depth; ++ubPlane) {\n\t\tUBYTE *pFirstLineWord = pDst->Planes[ubPlane] + ulDataOffs;\n\t\tUWORD uwOp = ((ubColor & BV(ubPlane)) ? BLIT_LINE_MODE_OR : BLIT_LINE_MODE_ERASE);\n\n\t\tblitWait();\n\t\tg_pCustom->bltcon0 = uwBltCon0 | uwOp;\n\t\tg_pCustom->bltcpt = pFirstLineWord;\n\t\tg_pCustom->bltdpt = (APTR)(isOneDot ? pDst->Planes[pDst->Depth] : pFirstLineWord);\n\t\tg_pCustom->bltsize = uwBltSize;\n\t}\n}\n\nvoid blitLinePlane(\n\ttBitMap *pDst, WORD wX1, WORD wY1, WORD wX2, WORD wY2,\n\tUBYTE ubPlane, UWORD uwPattern, tBlitLineMode eMode, UBYTE isOneDot\n) {\n\t// Based on Cahir's function from:\n\t// https://github.com/cahirwpz/demoscene/blob/master/a500/base/libsys/blt-line.c\n\tUWORD uwBltCon1 = LINEMODE;\n\tif(isOneDot) {\n\t\tuwBltCon1 |= ONEDOT;\n\t}\n\n\t// Always draw the line downwards.\n\tif (wY1 > wY2) {\n\t\tSWAP(wX1, wX2);\n\t\tSWAP(wY1, wY2);\n\t}\n\n\t// Setup octant bits\n\tWORD wDx = wX2 - wX1;\n\tWORD wDy = wY2 - wY1;\n\tif (wDx < 0) {\n\t\twDx = -wDx;\n\t\tif (wDx >= wDy) {\n\t\t\tuwBltCon1 |= AUL | SUD;\n\t\t}\n\t\telse {\n\t\t\tuwBltCon1 |= SUL;\n\t\t\tSWAP(wDx, wDy);\n\t\t}\n\t}\n\telse {\n\t\tif (wDx >= wDy) {\n\t\t\tuwBltCon1 |= SUD;\n\t\t}\n\t\telse {\n\t\t\tSWAP(wDx, wDy);\n\t\t}\n\t}\n\n\tWORD wDerr = wDy + wDy - wDx;\n\tif (wDerr < 0) {\n\t\tuwBltCon1 |= SIGNFLAG;\n\t}\n\n\tUWORD uwBltSize = (wDx << HSIZEBITS) + 66;\n\tUWORD uwBltCon0 = ror16(wX1 & 15, 4);\n\tULONG ulDataOffs = pDst->BytesPerRow * wY1 + ((wX1 / 8) & ~1);\n\tUBYTE *pFirstLineWord = pDst->Planes[ubPlane] + ulDataOffs;\n\tUBYTE *pD = (APTR)(isOneDot ? pDst->Planes[pDst->Depth] : pFirstLineWord);\n\n\tblitWait(); // Don't modify registers when other blit is in progress\n\tg_pCustom->bltafwm = -1;\n\tg_pCustom->bltalwm = -1;\n\tg_pCustom->bltadat = 0x8000;\n\tg_pCustom->bltbdat = uwPattern;\n\tg_pCustom->bltamod = wDerr - wDx;\n\tg_pCustom->bltbmod = wDy + wDy;\n\tg_pCustom->bltcmod = pDst->BytesPerRow;\n\tg_pCustom->bltdmod = pDst->BytesPerRow;\n\tg_pCustom->bltcon1 = uwBltCon1;\n\tg_pCustom->bltapt = (APTR)(LONG)wDerr;\n\tg_pCustom->bltcon0 = uwBltCon0 | (UWORD)eMode;\n\tg_pCustom->bltcpt = pFirstLineWord;\n\tg_pCustom->bltdpt = pD;\n\tg_pCustom->bltsize = uwBltSize;\n}\n"
  },
  {
    "path": "src/ace/managers/bob.c",
    "content": "/* This Source Code Form is subject to the terms of the Mozilla Public\r\n * License, v. 2.0. If a copy of the MPL was not distributed with this\r\n * file, You can obtain one at http://mozilla.org/MPL/2.0/. */\r\n\r\n#include <ace/managers/bob.h>\r\n#include <ace/managers/memory.h>\r\n#include <ace/managers/system.h>\r\n#include <ace/managers/blit.h>\r\n#include <ace/managers/viewport/scrollbuffer.h> // for SCROLLBUFFER_HEIGHT_MODULO, TODO: get rid of it somehow\r\n#include <ace/utils/custom.h>\r\n\r\n#if !defined(ACE_NO_BOB_WRAP_Y)\r\n// Enables support for Y-wrapping of bobs. Required for scroll- and tileBuffer.\r\n// Disable for extra performance in simplebuffer scenarios.\r\n// Making it a runtime flag wasn't giving enough performance boost,\r\n// needs to be define-driven/constexpr.\r\n#define BOB_WRAP_Y\r\n#endif\r\n\r\n// Undraw stack must be accessible during adding new bobs, so the most safe\r\n// approach is to have two lists - undraw list gets populated after draw\r\n// and depopulated during undraw\r\ntypedef struct tBobQueue {\r\n\ttBob **pBobs;\r\n\ttBitMap *pDst;\r\n#if !defined(ACE_BOB_PRISTINE_BUFFER)\r\n\ttBitMap *pBg;\r\n#endif\r\n\tUBYTE ubUndrawCount;\r\n} tBobQueue;\r\n\r\nstatic UBYTE s_ubBufferCurr;\r\nstatic UBYTE s_ubMaxBobCount;\r\n\r\nstatic UBYTE s_isPushingDone;\r\nstatic UBYTE s_ubBpp;\r\n\r\n// This can't be a decreasing counter such as in toSave/toDraw since after\r\n// decrease another bob may be pushed, which would trash bg saving\r\nstatic UBYTE s_ubBobsPushed;\r\nstatic UBYTE s_ubBobsDrawn;\r\nstatic UWORD s_uwAvailHeight;\r\nstatic UWORD s_uwDestByteWidth;\r\n#if defined(ACE_BOB_PRISTINE_BUFFER)\r\nstatic tBitMap *s_pPristineBuffer;\r\n#else\r\nstatic UWORD s_uwBgBufferLength;\r\nstatic UBYTE s_ubBobsSaved;\r\n#endif\r\n\r\ntBobQueue s_pQueues[2];\r\n\r\n//------------------------------------------------------------------ PRIVATE FNS\r\n\r\nstatic void bobCheckGood(const tBitMap *pBack) {\r\n\tif(s_pQueues[s_ubBufferCurr].pDst != pBack) {\r\n#if defined(ACE_DEBUG)\r\n\t\tlogWrite(\r\n\t\t\t\"ERR: bob manager operates on wrong buffer! Proper current: %p (%hhu), Other: %p, Arg: %p\\n\",\r\n\t\t\ts_pQueues[s_ubBufferCurr].pDst, s_ubBufferCurr, s_pQueues[!s_ubBufferCurr].pDst, pBack\r\n\t\t);\r\n\t\tif(s_pQueues[!s_ubBufferCurr].pDst == pBack) {\r\n\t\t\tlogWrite(\"ERR: Wrong bob buffer as curr\\n\");\r\n\t\t\ts_ubBufferCurr = !s_ubBufferCurr;\r\n\t\t}\r\n#endif\r\n\t}\r\n}\r\n\r\nstatic void bobDeallocBuffers(void) {\r\n\tblitWait();\r\n\tsystemUse();\r\n\tif(s_pQueues[0].pBobs && s_ubMaxBobCount) {\r\n\t\tmemFree(s_pQueues[0].pBobs, sizeof(tBob*) * s_ubMaxBobCount);\r\n\t\ts_pQueues[0].pBobs = 0;\r\n\t}\r\n\tif(s_pQueues[1].pBobs && s_ubMaxBobCount) {\r\n\t\tmemFree(s_pQueues[1].pBobs, sizeof(tBob*) * s_ubMaxBobCount);\r\n\t\ts_pQueues[1].pBobs = 0;\r\n\t}\r\n\ts_ubMaxBobCount = 0;\r\n#if !defined(ACE_BOB_PRISTINE_BUFFER)\r\n\tif(s_pQueues[0].pBg) {\r\n\t\tbitmapDestroy(s_pQueues[0].pBg);\r\n\t\ts_pQueues[0].pBg = 0;\r\n\t}\r\n\tif(s_pQueues[1].pBg) {\r\n\t\tbitmapDestroy(s_pQueues[1].pBg);\r\n\t\ts_pQueues[1].pBg = 0;\r\n\t}\r\n#endif\r\n\tsystemUnuse();\r\n}\r\n\r\nstatic ULONG bobCalculateBitplaneOffset(const tBob *pBob, tBitMap *pDestination) {\r\n\tULONG ulBitplaneOffset = (\r\n\t\tpDestination->BytesPerRow * (\r\n#if defined(BOB_WRAP_Y)\r\n\t\t\tSCROLLBUFFER_HEIGHT_MODULO(pBob->sPos.uwY, s_uwAvailHeight)\r\n#else\r\n\t\t\tpBob->sPos.uwY\r\n#endif\r\n\t\t) + pBob->sPos.uwX / 8\r\n\t);\r\n\treturn ulBitplaneOffset;\r\n}\r\n\r\n//------------------------------------------------------------------- PUBLIC FNS\r\n\r\nvoid bobManagerReset(void) {\r\n\tbobDeallocBuffers();\r\n\r\n\t// Don't reset s_ubBufferCurr - we still may need to keep track which buffer\r\n\t// is in the front and which in the back\r\n\t// E.g. multiple states in single buffer manager:\r\n\t// fade-out, reset bobs, fade-in, start display\r\n\r\n#if !defined(ACE_BOB_PRISTINE_BUFFER)\r\n\ts_uwBgBufferLength = 0;\r\n\ts_ubBobsSaved = 0;\r\n#endif\r\n\ts_isPushingDone = 0;\r\n\ts_ubBobsPushed = 0;\r\n\ts_ubBobsDrawn = 0;\r\n\tbobDiscardUndraw();\r\n}\r\n\r\nvoid bobManagerCreate(\r\n\ttBitMap *pFront, tBitMap *pBack,\r\n#if defined(ACE_BOB_PRISTINE_BUFFER)\r\n\ttBitMap *pPristineBuffer,\r\n#endif\r\n\tUWORD uwAvailHeight\r\n) {\r\n\tlogBlockBegin(\r\n\t\t\"bobManagerCreate(pFront: %p, pBack: %p, uwAvailHeight: %hu)\",\r\n\t\tpFront, pBack, uwAvailHeight\r\n\t);\r\n\r\n\tif(!bitmapIsInterleaved(pFront)) {\r\n\t\tlogWrite(\"ERR: front buffer bitmap %p isn't interleaved\\n\", pFront);\r\n\t}\r\n\r\n\tif(!bitmapIsInterleaved(pBack)) {\r\n\t\tlogWrite(\"ERR: back buffer bitmap %p isn't interleaved\\n\", pBack);\r\n\t}\r\n\r\n\ts_ubBpp = pFront->Depth;\r\n\ts_pQueues[0].pDst = pBack;\r\n\ts_pQueues[1].pDst = pFront;\r\n\r\n#if defined(ACE_BOB_PRISTINE_BUFFER)\r\n\ts_pPristineBuffer = pPristineBuffer;\r\n#else\r\n\ts_pQueues[0].pBg = 0;\r\n\ts_pQueues[1].pBg = 0;\r\n#endif\r\n\ts_pQueues[0].pBobs = 0;\r\n\ts_pQueues[1].pBobs = 0;\r\n\ts_ubMaxBobCount = 0;\r\n\tbobManagerReset();\r\n\ts_ubBufferCurr = 0;\r\n\ts_uwAvailHeight = uwAvailHeight;\r\n\ts_uwDestByteWidth = bitmapGetByteWidth(pBack);\r\n\r\n\tlogBlockEnd(\"bobManagerCreate()\");\r\n}\r\n\r\nvoid bobReallocateBuffers(void) {\r\n\tsystemUse();\r\n\tlogBlockBegin(\"bobReallocateBuffers()\");\r\n\r\n#if !defined(ACE_BOB_PRISTINE_BUFFER)\r\n\tif(s_pQueues[0].pBg) {\r\n\t\tbitmapDestroy(s_pQueues[0].pBg);\r\n\t}\r\n\tif(s_pQueues[1].pBg) {\r\n\t\tbitmapDestroy(s_pQueues[1].pBg);\r\n\t}\r\n#endif\r\n\r\n\tlogWrite(\"Max bobs: %hhu\\n\", s_ubMaxBobCount);\r\n\ts_pQueues[0].pBobs = memAllocFast(sizeof(tBob*) * s_ubMaxBobCount);\r\n\ts_pQueues[1].pBobs = memAllocFast(sizeof(tBob*) * s_ubMaxBobCount);\r\n#if !defined(ACE_BOB_PRISTINE_BUFFER)\r\n\ts_pQueues[0].pBg = bitmapCreate(16, s_uwBgBufferLength, s_ubBpp, BMF_INTERLEAVED);\r\n\ts_pQueues[1].pBg = bitmapCreate(16, s_uwBgBufferLength, s_ubBpp, BMF_INTERLEAVED);\r\n\tlogWrite(\"Undraw bg buffer length: %hu\\n\", s_uwBgBufferLength);\r\n#endif\r\n\tlogBlockEnd(\"bobReallocateBuffers()\");\r\n\tsystemUnuse();\r\n}\r\n\r\nvoid bobManagerDestroy(void) {\r\n\tbobDeallocBuffers();\r\n}\r\n\r\nvoid bobPush(tBob *pBob) {\r\n\ttBobQueue *pQueue = &s_pQueues[s_ubBufferCurr];\r\n\tpQueue->pBobs[s_ubBobsPushed] = pBob;\r\n\t++s_ubBobsPushed;\r\n\tif(blitIsIdle()) {\r\n\t\tbobProcessNext();\r\n\t}\r\n}\r\n\r\nvoid bobInit(\r\n\ttBob *pBob, UWORD uwWidth, UWORD uwHeight, UBYTE isUndrawRequired,\r\n\tUBYTE *pFrameData, UBYTE *pMaskData, UWORD uwX, UWORD uwY\r\n) {\r\n\tlogBlockBegin(\r\n\t\t\"bobInit(pBob: %p, uwWidth: %hu, uwHeight: %hu, isUndrawRequired: %hhu, pFrameData: %p, pMaskData: %p, uwX: %hu, uwY: %hu)\",\r\n\t\tpBob, uwWidth, uwHeight, isUndrawRequired, pFrameData, pMaskData, uwX, uwY\r\n\t);\r\n#if defined(ACE_DEBUG)\r\n\tpBob->_uwOriginalWidth = uwWidth;\r\n\tpBob->_uwOriginalHeight = uwHeight;\r\n#endif\r\n\tpBob->isUndrawRequired = isUndrawRequired;\r\n\tUWORD uwBlitWords = (uwWidth+15) / 16 + 1; // One word more for aligned copy\r\n\tpBob->_wModuloUndrawSave = s_uwDestByteWidth - uwBlitWords * 2;\r\n\tpBob->_uwBlitSize = uwBlitWords; // Height compontent is set later on\r\n\tbobSetFrame(pBob, pFrameData, pMaskData);\r\n\tbobSetWidth(pBob, uwWidth);\r\n\tbobSetHeight(pBob, uwHeight);\r\n\r\n\tpBob->sPos.uwX = uwX;\r\n\tpBob->sPos.uwY = uwY;\r\n\tpBob->pOldPositions[0].uwX = uwX;\r\n\tpBob->pOldPositions[0].uwY = uwY;\r\n\tpBob->pOldPositions[1].uwX = uwX;\r\n\tpBob->pOldPositions[1].uwY = uwY;\r\n\r\n#if defined(ACE_BOB_PRISTINE_BUFFER)\r\n\tpBob->_pSaveOffsets[0] = 0;\r\n\tpBob->_pSaveOffsets[1] = 0;\r\n#else\r\n\tpBob->_pBufferDrawPtrs[0] = 0;\r\n\tpBob->_pBufferDrawPtrs[1] = 0;\r\n\tif(isUndrawRequired) {\r\n\t\ts_uwBgBufferLength += uwBlitWords * pBob->_uwInterleavedHeight;\r\n\t}\r\n#endif\r\n\t++s_ubMaxBobCount;\r\n\tlogBlockEnd(\"bobInit()\");\r\n}\r\n\r\nvoid bobSetFrame(tBob *pBob, UBYTE *pFrameData, UBYTE *pMaskData) {\r\n\tpBob->pFrameData = pFrameData;\r\n\tpBob->pMaskData = pMaskData;\r\n}\r\n\r\nvoid bobSetWidth(tBob *pBob, UWORD uwWidth)\r\n{\r\n#if defined(ACE_DEBUG)\r\n\tif(pBob->isUndrawRequired && uwWidth > pBob->_uwOriginalWidth) {\r\n\t\t// NOTE: that could be valid behavior when other bobs get smaller in the same time\r\n\t\tlogWrite(\"WARN: Bob bigger than initial - bg buffer might be too small\\n\");\r\n\t\t// Change original width so that this warning gets issued only once\r\n\t\tpBob->_uwOriginalWidth = uwWidth;\r\n\t}\r\n#endif\r\n\r\n\tpBob->uwWidth = uwWidth;\r\n\tUWORD uwBlitWords = (uwWidth + 15) / 16 + 1; // One word more for aligned copy\r\n\tpBob->_uwBlitSize = (pBob->_uwBlitSize & VSIZEMASK) | uwBlitWords;\r\n}\r\n\r\nvoid bobSetHeight(tBob *pBob, UWORD uwHeight)\r\n{\r\n#if defined(ACE_DEBUG)\r\n\tif(pBob->isUndrawRequired && uwHeight > pBob->_uwOriginalHeight) {\r\n\t\t// NOTE: that could be valid behavior when other bobs get smaller in the same time\r\n\t\tlogWrite(\"WARN: Bob bigger than initial - bg buffer might be too small\\n\");\r\n\t\t// Change original height so that this warning gets issued only once\r\n\t\tpBob->_uwOriginalHeight = uwHeight;\r\n\t}\r\n#endif\r\n\r\n\tpBob->uwHeight = uwHeight;\r\n\tpBob->_uwInterleavedHeight = uwHeight * s_ubBpp;\r\n\tpBob->_uwBlitSize = ((pBob->_uwInterleavedHeight) << HSIZEBITS) | (pBob->_uwBlitSize & HSIZEMASK);\r\n}\r\n\r\nUBYTE *bobCalcFrameAddress(tBitMap *pBitmap, UWORD uwOffsetY) {\r\n\tif(uwOffsetY >= pBitmap->Rows) {\r\n\t\tlogWrite(\"ERR: bobCalcFrameAddress() OffsY %hu > bitmap height: %hu\", uwOffsetY, pBitmap->Rows);\r\n\t}\r\n\treturn &pBitmap->Planes[0][pBitmap->BytesPerRow * uwOffsetY];\r\n}\r\n\r\nUBYTE bobProcessNext(void) {\r\n#if !defined(ACE_BOB_PRISTINE_BUFFER)\r\n\tif(s_ubBobsSaved < s_ubBobsPushed) {\r\n\t\ttBobQueue *pQueue = &s_pQueues[s_ubBufferCurr];\r\n\t\tif(!s_ubBobsSaved) {\r\n\t\t\t// Prepare for saving.\r\n\t\t\t// Bltcon0/1, bltaxwm could be reset between Begin and ProcessNext.\r\n\t\t\t// I tried to change A->D to C->D bug afwm/alwm need to be set\r\n\t\t\t// for mask-copying bobs, so there's no perf to be gained.\r\n\t\t\tUWORD uwBltCon0 = USEA|USED | MINTERM_A;\r\n\t\t\tblitWait();\r\n\t\t\tg_pCustom->bltcon0 = uwBltCon0;\r\n\t\t\tg_pCustom->bltcon1 = 0;\r\n\t\t\tg_pCustom->bltafwm = 0xFFFF;\r\n\t\t\tg_pCustom->bltalwm = 0xFFFF;\r\n\r\n\t\t\tg_pCustom->bltdmod = 0;\r\n\t\t\tg_pCustom->bltdpt = pQueue->pBg->Planes[0];\r\n\t\t}\r\n\t\ttBob *pBob = pQueue->pBobs[s_ubBobsSaved];\r\n\t\t++s_ubBobsSaved;\r\n\r\n\t\t// TODO: for BOB_WRAP_Y and ACE_DEBUG check if bob blit fits s_uwAvailHeight\r\n\t\tULONG ulSrcOffs = bobCalculateBitplaneOffset(pBob, pQueue->pDst);\r\n\t\tUBYTE *pA = &pQueue->pDst->Planes[0][ulSrcOffs];\r\n\t\tpBob->_pBufferDrawPtrs[s_ubBufferCurr] = pA;\r\n\r\n\t\tif(pBob->isUndrawRequired) {\r\n#if defined(BOB_WRAP_Y)\r\n\t\t\tUWORD uwPartHeight = s_uwAvailHeight - SCROLLBUFFER_HEIGHT_MODULO(pBob->sPos.uwY, s_uwAvailHeight);\r\n#endif\r\n\t\t\tblitWait();\r\n\t\t\tg_pCustom->bltamod = pBob->_wModuloUndrawSave;\r\n\t\t\tg_pCustom->bltapt = (APTR)pA;\r\n#if defined(BOB_WRAP_Y)\r\n\t\t\tif(uwPartHeight >= pBob->uwHeight) {\r\n\t\t\t\tg_pCustom->bltsize = pBob->_uwBlitSize;\r\n\t\t\t}\r\n\t\t\telse {\r\n\t\t\t\tUWORD uwInterleavedPartHeight = uwPartHeight * s_ubBpp;\r\n\t\t\t\tUWORD uwBlitWords = (pBob->uwWidth+15) / 16 + 1;\r\n\t\t\t\tg_pCustom->bltsize =(uwInterleavedPartHeight << HSIZEBITS) | uwBlitWords;\r\n\t\t\t\tpA = &pQueue->pDst->Planes[0][pBob->sPos.uwX / 8];\r\n\t\t\t\tblitWait();\r\n\t\t\t\tg_pCustom->bltapt = pA;\r\n\t\t\t\tg_pCustom->bltsize =((pBob->_uwInterleavedHeight - uwInterleavedPartHeight) << HSIZEBITS) | uwBlitWords;\r\n\t\t\t}\r\n#else\r\n\t\t\tg_pCustom->bltsize = pBob->_uwBlitSize;\r\n#endif\r\n\t\t}\r\n\t\treturn 1;\r\n\t}\r\n\r\n\tif(!s_isPushingDone) {\r\n\t\treturn 1;\r\n\t}\r\n#endif\r\n\r\n\ttBobQueue *pQueue = &s_pQueues[s_ubBufferCurr];\r\n\tif(s_ubBobsDrawn < s_ubBobsPushed) {\r\n\t\t// Draw next\r\n\t\ttBob *pBob = pQueue->pBobs[s_ubBobsDrawn];\r\n\t\tconst tUwCoordYX * pPos = &pBob->sPos;\r\n\t\t++s_ubBobsDrawn;\r\n\t\tUBYTE ubDstOffs = pPos->uwX & 0xF;\r\n\t\tUWORD uwBlitWidth = (pBob->uwWidth + ubDstOffs + 15) & 0xFFF0;\r\n\t\tUWORD uwBlitWords = uwBlitWidth / 16;\r\n\t\tUWORD uwBlitSize = ((pBob->_uwInterleavedHeight) << HSIZEBITS) | uwBlitWords;\r\n\t\tWORD wSrcModulo = pBob->uwWidth / 8 - uwBlitWords * 2;\r\n\t\tUWORD uwBltCon1 = ubDstOffs << BSHIFTSHIFT;\r\n\t\tUWORD uwBltCon0;\r\n\t\tif(pBob->pMaskData) {\r\n\t\t\tuwBltCon0 = uwBltCon1 | USEA|USEB|USEC|USED | MINTERM_COOKIE;\r\n\t\t}\r\n\t\telse {\r\n\t\t\tuwBltCon0 = uwBltCon1 | USEB|USEC|USED | MINTERM_COOKIE;\r\n\t\t}\r\n\r\n\t\tWORD wDstModulo = s_uwDestByteWidth - uwBlitWords * 2;\r\n\t\tUBYTE *pB = pBob->pFrameData;\r\n#if defined(ACE_BOB_PRISTINE_BUFFER)\r\n\t\tULONG ulDestinationOffset = bobCalculateBitplaneOffset(pBob, pQueue->pDst);\r\n\t\tUBYTE *pCD = &pQueue->pDst->Planes[0][ulDestinationOffset];\r\n\t\tpBob->_pSaveOffsets[s_ubBufferCurr] = ulDestinationOffset;\r\n#else\r\n\t\tUBYTE *pCD = pBob->_pBufferDrawPtrs[s_ubBufferCurr];\r\n#endif\r\n#if defined(BOB_WRAP_Y)\r\n\t\tUWORD uwPartHeight = s_uwAvailHeight - SCROLLBUFFER_HEIGHT_MODULO(pBob->sPos.uwY, s_uwAvailHeight);\r\n#endif\r\n\r\n\t\tUWORD uwLastMask = 0xFFFF << (uwBlitWidth-pBob->uwWidth);\r\n\t\tblitWait();\r\n\t\tg_pCustom->bltcon0 = uwBltCon0;\r\n\t\tg_pCustom->bltcon1 = uwBltCon1;\r\n\r\n\t\tg_pCustom->bltalwm = uwLastMask;\r\n\t\tif(pBob->pMaskData) {\r\n\t\t\tUBYTE *pA = pBob->pMaskData;\r\n\t\t\tg_pCustom->bltamod = wSrcModulo;\r\n\t\t\tg_pCustom->bltapt = (APTR)pA;\r\n\t\t}\r\n\t\telse {\r\n\t\t\tg_pCustom->bltadat = 0xFFFF;\r\n\t\t}\r\n\r\n\t\tg_pCustom->bltbmod = wSrcModulo;\r\n\t\tg_pCustom->bltcmod = wDstModulo;\r\n\t\tg_pCustom->bltdmod = wDstModulo;\r\n\r\n\t\tg_pCustom->bltbpt = (APTR)pB;\r\n\t\tg_pCustom->bltcpt = (APTR)pCD;\r\n\t\tg_pCustom->bltdpt = (APTR)pCD;\r\n#if defined(BOB_WRAP_Y)\r\n\t\tif(uwPartHeight >= pBob->uwHeight) {\r\n\t\t\tg_pCustom->bltsize = uwBlitSize;\r\n\t\t}\r\n\t\telse {\r\n\t\t\tUWORD uwInterleavedPartHeight = uwPartHeight * s_ubBpp;\r\n\t\t\tg_pCustom->bltsize = (uwInterleavedPartHeight << HSIZEBITS) | uwBlitWords;\r\n\t\t\tpCD = &pQueue->pDst->Planes[0][pBob->sPos.uwX / 8];\r\n\t\t\tblitWait();\r\n\t\t\tg_pCustom->bltcpt = (APTR)pCD;\r\n\t\t\tg_pCustom->bltdpt = (APTR)pCD;\r\n\t\t\tg_pCustom->bltsize =((pBob->_uwInterleavedHeight - uwInterleavedPartHeight) << HSIZEBITS) | uwBlitWords;\r\n\t\t}\r\n#else\r\n\t\tg_pCustom->bltsize = uwBlitSize;\r\n#endif\r\n\t\tpBob->pOldPositions[s_ubBufferCurr].ulYX = pPos->ulYX;\r\n\t\treturn 1;\r\n\t}\r\n\r\n\treturn 0;\r\n}\r\n\r\nvoid bobBegin(tBitMap *pBuffer) {\r\n\tbobCheckGood(pBuffer);\r\n\ttBobQueue *pQueue = &s_pQueues[s_ubBufferCurr];\r\n\r\n#if defined(ACE_BOB_PRISTINE_BUFFER)\r\n\tUWORD uwBltCon0 = USEA|USED | MINTERM_A;\r\n\tblitWait();\r\n\tg_pCustom->bltcon0 = uwBltCon0;\r\n\tg_pCustom->bltcon1 = 0;\r\n\tg_pCustom->bltafwm = 0xFFFF;\r\n\tg_pCustom->bltalwm = 0xFFFF;\r\n\r\n\tfor(UBYTE i = 0; i < pQueue->ubUndrawCount; ++i) {\r\n\t\tconst tBob *pBob = pQueue->pBobs[i];\r\n\t\tif(!pBob->isUndrawRequired) {\r\n\t\t\tcontinue;\r\n\t\t}\r\n\r\n#if defined(BOB_WRAP_Y)\r\n\t\tUWORD uwPartHeight = s_uwAvailHeight - SCROLLBUFFER_HEIGHT_MODULO(\r\n\t\t\tpBob->pOldPositions[s_ubBufferCurr].uwY, s_uwAvailHeight\r\n\t\t);\r\n#endif\r\n\t\tULONG ulBitplaneOffset = pBob->_pSaveOffsets[s_ubBufferCurr];\r\n\t\tblitWait();\r\n\t\tg_pCustom->bltamod = pBob->_wModuloUndrawSave;\r\n\t\tg_pCustom->bltdmod = pBob->_wModuloUndrawSave;\r\n\t\tg_pCustom->bltapt = &s_pPristineBuffer->Planes[0][ulBitplaneOffset];\r\n\t\tg_pCustom->bltdpt = &pQueue->pDst->Planes[0][ulBitplaneOffset];\r\n#if defined(BOB_WRAP_Y)\r\n\t\tif(uwPartHeight >= pBob->uwHeight) {\r\n\t\t\tg_pCustom->bltsize = pBob->_uwBlitSize;\r\n\t\t}\r\n\t\telse {\r\n\t\t\tUWORD uwBlitWords = (pBob->uwWidth+15) / 16 + 1;\r\n\t\t\tUWORD uwInterleavedPartHeight = uwPartHeight * s_ubBpp;\r\n\t\t\tg_pCustom->bltsize = (uwInterleavedPartHeight << HSIZEBITS) | uwBlitWords;\r\n\t\t\tulBitplaneOffset = pBob->pOldPositions[s_ubBufferCurr].uwX / 8;\r\n\t\t\tblitWait();\r\n\t\t\tg_pCustom->bltapt = &s_pPristineBuffer->Planes[0][ulBitplaneOffset];\r\n\t\t\tg_pCustom->bltdpt = &pQueue->pDst->Planes[0][ulBitplaneOffset];\r\n\t\t\tg_pCustom->bltsize =((pBob->_uwInterleavedHeight - uwInterleavedPartHeight) << HSIZEBITS) | uwBlitWords;\r\n\t\t}\r\n#else\r\n\t\tg_pCustom->bltsize = pBob->_uwBlitSize;\r\n#endif\r\n\t}\r\n#else\r\n\t// Prepare for undraw\r\n\tUBYTE *pA = pQueue->pBg->Planes[0];\r\n\tblitWait();\r\n\tg_pCustom->bltcon0 = USEA|USED | MINTERM_A;\r\n\tg_pCustom->bltcon1 = 0;\r\n\tg_pCustom->bltafwm = 0xFFFF;\r\n\tg_pCustom->bltalwm = 0xFFFF;\r\n\tg_pCustom->bltamod = 0;\r\n\tg_pCustom->bltapt = pA;\r\n#ifdef GAME_DEBUG\r\n\tUWORD uwDrawnHeight = 0;\r\n#endif\r\n\r\n\tfor(UBYTE i = 0; i < pQueue->ubUndrawCount; ++i) {\r\n\t\tconst tBob *pBob = pQueue->pBobs[i];\r\n\t\tif(pBob->isUndrawRequired) {\r\n\t\t\t// Undraw next\r\n\t\t\tUBYTE *pD = pBob->_pBufferDrawPtrs[s_ubBufferCurr];\r\n#if defined(BOB_WRAP_Y)\r\n\t\t\tUWORD uwPartHeight = s_uwAvailHeight - SCROLLBUFFER_HEIGHT_MODULO(\r\n\t\t\t\tpBob->pOldPositions[s_ubBufferCurr].uwY, s_uwAvailHeight\r\n\t\t\t);\r\n#endif\r\n\t\t\tblitWait();\r\n\t\t\tg_pCustom->bltdmod = pBob->_wModuloUndrawSave;\r\n\t\t\tg_pCustom->bltdpt = (APTR)pD;\r\n#if defined(BOB_WRAP_Y)\r\n\t\t\tif(uwPartHeight >= pBob->uwHeight) {\r\n\t\t\t\tg_pCustom->bltsize = pBob->_uwBlitSize;\r\n\t\t\t}\r\n\t\t\telse {\r\n\t\t\t\tUWORD uwBlitWords = (pBob->uwWidth+15) / 16 + 1;\r\n\t\t\t\tUWORD uwInterleavedPartHeight = uwPartHeight * s_ubBpp;\r\n\t\t\t\tg_pCustom->bltsize =(uwInterleavedPartHeight << HSIZEBITS) | uwBlitWords;\r\n\t\t\t\tpD = &pQueue->pDst->Planes[0][pBob->pOldPositions[s_ubBufferCurr].uwX / 8];\r\n\t\t\t\tblitWait();\r\n\t\t\t\tg_pCustom->bltdpt = pD;\r\n\t\t\t\tg_pCustom->bltsize =((pBob->_uwInterleavedHeight - uwInterleavedPartHeight) << HSIZEBITS) | uwBlitWords;\r\n\t\t\t}\r\n#else\r\n\t\t\tg_pCustom->bltsize = pBob->_uwBlitSize;\r\n#endif\r\n\r\n#ifdef GAME_DEBUG\r\n\t\t\tUWORD uwBlitWords = (pBob->uwWidth+15) / 16 + 1;\r\n\t\t\tuwDrawnHeight += uwBlitWords * pBob->uwHeight;\r\n#endif\r\n\t\t}\r\n\t}\r\n\r\n\ts_ubBobsSaved = 0;\r\n#endif\r\n\r\n#ifdef GAME_DEBUG\r\n\tUWORD uwDrawLimit = s_pQueues[0].pBg->Rows * s_pQueues[0].pBg->Depth;\r\n\tif(uwDrawnHeight > uwDrawLimit) {\r\n\t\tlogWrite(\r\n\t\t\t\"ERR: BG restore out of bounds: used %hu, limit: %hu\",\r\n\t\t\tuwDrawnHeight, uwDrawLimit\r\n\t\t);\r\n\t}\r\n#endif\r\n\r\n\ts_ubBobsDrawn = 0;\r\n\ts_ubBobsPushed = 0;\r\n\ts_isPushingDone = 0;\r\n}\r\n\r\nvoid bobPushingDone(void) {\r\n\ts_isPushingDone = 1;\r\n}\r\n\r\nvoid bobProcessAll(void) {\r\n\twhile(bobProcessNext()) continue;\r\n}\r\n\r\nUBYTE bobGetCurrentBufferIndex(void) {\r\n\treturn s_ubBufferCurr;\r\n}\r\n\r\nvoid bobEnd(void) {\r\n\tbobPushingDone();\r\n\tbobProcessAll();\r\n\ts_pQueues[s_ubBufferCurr].ubUndrawCount = s_ubBobsPushed;\r\n\ts_ubBufferCurr = !s_ubBufferCurr;\r\n}\r\n\r\nvoid bobDiscardUndraw(void) {\r\n\ts_pQueues[0].ubUndrawCount = 0;\r\n\ts_pQueues[1].ubUndrawCount = 0;\r\n}\r\n\r\nvoid bobSetCurrentBuffer(tBitMap *pCurrent) {\r\n\tif(s_pQueues[!s_ubBufferCurr].pDst == pCurrent) {\r\n\t\ts_ubBufferCurr = !s_ubBufferCurr;\r\n\t}\r\n}\r\n"
  },
  {
    "path": "src/ace/managers/copper.c",
    "content": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at http://mozilla.org/MPL/2.0/. */\n\n#include <ace/managers/copper.h>\n#ifdef AMIGA\n#include <stdarg.h>\n#include <ace/managers/system.h>\n#include <limits.h>\n#include <proto/exec.h>\n\ntCopManager g_sCopManager;\n\nvoid copCreate(void) {\n\tlogBlockBegin(\"copCreate()\");\n\n\t// TODO: save previous copperlist\n\n\t// Create blank copperlist\n\tg_sCopManager.pBlankList = copListCreate(0, TAG_DONE);\n\n\t// Set both buffers to blank copperlist\n\tg_sCopManager.pCopList = g_sCopManager.pBlankList;\n\tcopProcessBlocks();\n\tcopProcessBlocks();\n\t// Update copper-related regs\n\tg_pCustom->copjmp1 = 1;\n\tsystemSetDmaBit(DMAB_COPPER, 1);\n\n\tlogBlockEnd(\"copCreate()\");\n}\n\nvoid copDestroy(void) {\n\tlogBlockBegin(\"copDestroy()\");\n\n\t// Load system copperlist\n\tsystemSetDmaBit(DMAB_COPPER, 0);\n\tg_pCustom->cop1lc = (ULONG)GfxBase->copinit;\n\tg_pCustom->copjmp1 = 1;\n\n\t// Free blank copperlist\n\t// All others should be freed by user\n\tcopListDestroy(g_sCopManager.pBlankList);\n\n\tlogBlockEnd(\"copDestroy()\");\n}\n\nvoid copSwapBuffers(void) {\n\ttCopBfr *pTmp;\n\ttCopList *pCopList;\n\n\tpCopList = g_sCopManager.pCopList;\n\tg_pCustom->cop1lc = (ULONG)((void *)pCopList->pBackBfr->pList);\n\tpTmp = pCopList->pFrontBfr;\n\tpCopList->pFrontBfr = pCopList->pBackBfr;\n\tpCopList->pBackBfr = pTmp;\n}\n\nvoid copDumpCmd(tCopCmd *pCmd) {\n\tif(pCmd->sWait.bfIsWait) {\n#ifdef ACE_DEBUG\n\t\tconst char* szCmd = pCmd->sWait.bfIsSkip ? \"SKIP\" : \"WAIT\";\n\t\tlogWrite(\n\t\t\t\"@%p: %08lX - %s: %hu,%hu%s\\n\",\n\t\t\tpCmd, pCmd->ulCode, szCmd, pCmd->sWait.bfWaitX << 1, pCmd->sWait.bfWaitY,\n\t\t\t!pCmd->sWait.bfBlitterIgnore ? \" & blit done\" : \"\"\n\t\t);\n#endif\n\t}\n\telse {\n#ifdef ACE_DEBUG\n\t\tstatic const char* pCustomRegNames[256] = {\n\t\t\t\"BLTDDAT\", \"DMACONR\", \"VPOSR\", \"VHPOSR\", \"DSKDATR\", \"JOY0DAT\",\n\t\t\t\"JOY1DAT\", \"CLXDAT\", \"ADKCONR\", \"POT0DAT\", \"POT1DAT\", \"POTGOR\",\n\t\t\t\"SERDATR\", \"DSKBYTR\", \"INTENAR\", \"INTREQR\", \"DSKPTH\", \"DSKPTL\",\n\t\t\t\"DSKLEN\", \"DSKDAT\", \"REFPTR\", \"VPOSW\", \"VHPOSW\", \"COPCON\",\n\t\t\t\"SERDAT\", \"SERPER\", \"POTGO\", \"JOYTEST\", \"STREQU\", \"STRVBL\",\n\t\t\t\"STRHOR\", \"STRLONG\", \"BLTCON0\", \"BLTCON1\", \"BLTAFWM\", \"BLTALWM\",\n\t\t\t\"BLTCPTH\", \"BLTCPTL\", \"BLTBPTH\", \"BLTBPTL\", \"BLTAPTH\", \"BLTAPTL\",\n\t\t\t\"BLTDPTH\", \"BLTDPTL\", \"BLTSIZE\", \"BLTCON0L\", \"BLTSIZV\", \"BLTSIZH\",\n\t\t\t\"BLTCMOD\", \"BLTBMOD\", \"BLTAMOD\", \"BLTDMOD\", NULL, NULL,\n\t\t\tNULL, NULL, \"BLTCDAT\", \"BLTBDAT\", \"BLTADAT\", NULL,\n\t\t\t\"SPRHDAT\", NULL, \"DENISEID\", \"DSKSYNC\", \"COP1LCH\", \"COP1LCL\",\n\t\t\t\"COP2LCH\", \"COP2LCL\", \"COPJMP1\", \"COPJMP2\", \"COPINS\", \"DIWSTRT\",\n\t\t\t\"DIWSTOP\", \"DDFSTRT\", \"DDFSTOP\", \"DMACON\", \"CLXCON\", \"INTENA\",\n\t\t\t\"INTREQ\", \"ADKCON\", \"AUD0LCH\", \"AUD0LCL\", \"AUD0LEN\", \"AUD0PER\",\n\t\t\t\"AUD0VOL\", \"AUD0DAT\", NULL, NULL, \"AUD1LCH\", \"AUD1LCL\",\n\t\t\t\"AUD1LEN\", \"AUD1PER\", \"AUD1VOL\", \"AUD1DAT\", NULL, NULL,\n\t\t\t\"AUD2LCH\", \"AUD2LCL\", \"AUD2LEN\", \"AUD2PER\", \"AUD2VOL\", \"AUD2DAT\",\n\t\t\tNULL, NULL, \"AUD3LCH\", \"AUD3LCL\", \"AUD3LEN\", \"AUD3PER\",\n\t\t\t\"AUD3VOL\", \"AUD3DAT\", NULL, NULL, \"BPL1PTH\", \"BPL1PTL\",\n\t\t\t\"BPL2PTH\", \"BPL2PTL\", \"BPL3PTH\", \"BPL3PTL\", \"BPL4PTH\", \"BPL4PTL\",\n\t\t\t\"BPL5PTH\", \"BPL5PTL\", \"BPL6PTH\", \"BPL6PTL\",\n\t\t\tNULL, NULL, NULL, NULL, \"BPLCON0\", \"BPLCON1\",\n\t\t\t\"BPLCON2\", \"BPLCON3\", \"BPL1MOD\", \"BPL2MOD\", NULL, NULL,\n\t\t\t\"BPL1DAT\", \"BPL2DAT\", \"BPL3DAT\", \"BPL4DAT\", \"BPL5DAT\", \"BPL6DAT\",\n\t\t\tNULL, NULL, \"SPR0PTH\", \"SPR0PTL\", \"SPR1PTH\", \"SPR1PTL\", \"SPR2PTH\",\n\t\t\t\"SPR2PTL\", \"SPR3PTH\", \"SPR3PTL\", \"SPR4PTH\", \"SPR4PTL\", \"SPR5PTH\",\n\t\t\t\"SPR5PTL\", \"SPR6PTH\", \"SPR6PTL\", \"SPR7PTH\", \"SPR7PTL\", \"SPR0POS\",\n\t\t\t\"SPR0CTL\", \"SPR0DATA\", \"SPR0DATB\", \"SPR1POS\", \"SPR1CTL\", \"SPR1DATA\",\n\t\t\t\"SPR1DATB\", \"SPR2POS\", \"SPR2CTL\", \"SPR2DATA\", \"SPR2DATB\", \"SPR3POS\",\n\t\t\t\"SPR3CTL\", \"SPR3DATA\", \"SPR3DATB\", \"SPR4POS\", \"SPR4CTL\", \"SPR4DATA\",\n\t\t\t\"SPR4DATB\", \"SPR5POS\", \"SPR5CTL\", \"SPR5DATA\", \"SPR5DATB\", \"SPR6POS\",\n\t\t\t\"SPR6CTL\", \"SPR6DATA\", \"SPR6DATB\", \"SPR7POS\", \"SPR7CTL\", \"SPR7DATA\",\n\t\t\t\"SPR7DATB\", \"COLOR00\", \"COLOR01\", \"COLOR02\", \"COLOR03\", \"COLOR04\",\n\t\t\t\"COLOR05\", \"COLOR06\", \"COLOR07\", \"COLOR08\", \"COLOR09\", \"COLOR10\",\n\t\t\t\"COLOR11\", \"COLOR12\", \"COLOR13\", \"COLOR14\", \"COLOR15\", \"COLOR16\",\n\t\t\t\"COLOR17\", \"COLOR18\", \"COLOR19\", \"COLOR20\", \"COLOR21\", \"COLOR22\",\n\t\t\t\"COLOR23\", \"COLOR24\", \"COLOR25\", \"COLOR26\", \"COLOR27\", \"COLOR28\",\n\t\t\t\"COLOR29\", \"COLOR30\", \"COLOR31\", \"HTOTAL\", \"HSSTOP\", \"HBSTRT\",\n\t\t\t\"HBSTOP\", \"VTOTAL\", \"VSSTOP\", \"VBSTRT\", \"VBSTOP\", NULL,\n\t\t\tNULL, NULL, NULL, NULL, NULL, \"BEAMCON0\",\n\t\t\t\"HSSTRT\", \"VSSTRT\", \"HCENTER\", \"DIWHIGH\", NULL\n\t\t};\n\n\t\tconst char* szRegName = pCustomRegNames[pCmd->sMove.bfDestAddr >> 1];\n\t\tif (szRegName) {\n\t\t\tlogWrite(\n\t\t\t\t\"@%p: %08lX - MOVE: %8s := %04X\\n\",\n\t\t\t\tpCmd, pCmd->ulCode, szRegName, pCmd->sMove.bfValue\n\t\t\t);\n\t\t}\n\t\telse {\n\t\t\tlogWrite(\n\t\t\t\t\"@%p: %08lX - MOVE:      %03X := %04X\\n\",\n\t\t\t\tpCmd, pCmd->ulCode, pCmd->sMove.bfDestAddr, pCmd->sMove.bfValue\n\t\t\t);\n\t\t}\n#endif\n\t}\n}\n\nvoid copDumpBlocks(void) {\n\tsystemUse();\n\tlogBlockBegin(\"copDumpBlocks()\");\n\n\ttCopList *pCopList = g_sCopManager.pCopList;\n\tlogWrite(\n\t\t\"Copperlist %p cmd count: %u/%u\\n\",\n\t\tpCopList, pCopList->pFrontBfr->uwCmdCount,\n\t\tpCopList->pFrontBfr->uwAllocSize / 4\n\t);\n\ttCopCmd *pCmds = pCopList->pFrontBfr->pList;\n\tfor(UWORD i = 0; i < pCopList->pFrontBfr->uwCmdCount; ++i) {\n\t\tcopDumpCmd(&pCmds[i]);\n\t}\n\n\tlogWrite(\"Copper block count: %u\\n\", pCopList->uwBlockCount);\n\ttCopBlock *pBlock = pCopList->pFirstBlock;\n\twhile(pBlock) {\n\t\tif(pBlock->ubDisabled) {\n\t\t\tlogWrite(\"DISABLED \");\n\t\t}\n\t\tlogWrite(\n\t\t\t\"Block %p starts at %u,%u and has %u/%u cmds:\\n\",\n\t\t\tpBlock, pBlock->uWaitPos.uwX, pBlock->uWaitPos.uwY,\n\t\t\tpBlock->uwCurrCount, pBlock->uwMaxCmds\n\t\t);\n\t\tlogPushIndent();\n\t\tpCmds = pBlock->pCmds;\n\t\tfor(UWORD i = 0; i < pBlock->uwCurrCount; ++i) {\n\t\t\tcopDumpCmd(&pCmds[i]);\n\t\t}\n\n\t\tlogPopIndent();\n\t\tpBlock = pBlock->pNext;\n\t}\n\n\tlogBlockEnd(\"copDumpBlocks()\");\n\tsystemUnuse();\n}\n\nvoid copDumpBfr(tCopBfr *pBfr) {\n\tUWORD i;\n\n\tsystemUse();\n\tlogBlockBegin(\"copDumpBfr(pBfr: %p)\", pBfr);\n\tlogWrite(\"Alloc size: %u, cmd count: %u\\n\", pBfr->uwAllocSize, pBfr->uwCmdCount);\n\tfor(i = 0; i != pBfr->uwCmdCount; ++i) {\n\t\tcopDumpCmd(&pBfr->pList[i]);\n\t}\n\n\tlogBlockEnd(\"copDumpBfr\");\n\tsystemUnuse();\n}\n\ntCopList *copListCreate(void *pTagList, ...) {\n\tva_list vaTags;\n\tva_start(vaTags, pTagList);\n\ttCopList *pCopList;\n\tlogBlockBegin(\"copListCreate()\");\n\n\t// Create copperlist stub\n\tpCopList = memAllocFastClear(sizeof(tCopList));\n\tlogWrite(\"Addr: %p\\n\", pCopList);\n\tpCopList->pFrontBfr = memAllocFastClear(sizeof(tCopBfr));\n\tpCopList->pBackBfr = memAllocFastClear(sizeof(tCopBfr));\n\n\t// Handle raw copperlist creation\n\t pCopList->ubMode = tagGet(pTagList, vaTags, TAG_COPPER_LIST_MODE, COPPER_MODE_BLOCK);\n\tif(pCopList->ubMode\t== COPPER_MODE_RAW) {\n\t\tconst ULONG ulInvalidSize = ULONG_MAX;\n\t\tULONG ulListSize = tagGet(\n\t\t\tpTagList, vaTags, TAG_COPPER_RAW_COUNT, ulInvalidSize\n\t\t);\n\t\tif(ulListSize == ulInvalidSize) {\n\t\t\tlogWrite(\"ERR: no size specified for raw list\\n\");\n\t\t\tgoto fail;\n\t\t}\n\t\tif(ulListSize > USHRT_MAX) {\n\t\t\tlogWrite(\n\t\t\t\t\"ERR: raw copperlist size too big: %lu, max is %u\\n\",\n\t\t\t\tulListSize, USHRT_MAX\n\t\t\t);\n\t\t\tgoto fail;\n\t\t}\n\t\tlogWrite(\"RAW mode, size: %lu + WAIT(0xFFFF)\\n\", ulListSize);\n\t\t// Front bfr\n\t\tpCopList->pFrontBfr->uwCmdCount = ulListSize+1;\n\t\tpCopList->pFrontBfr->uwAllocSize = (ulListSize+1)*sizeof(tCopCmd);\n\t\tpCopList->pFrontBfr->pList = memAllocChipClear(pCopList->pFrontBfr->uwAllocSize);\n\t\tcopSetWait(&pCopList->pFrontBfr->pList[ulListSize].sWait, 0xFF, 0xFF);\n\t\t// Back bfr\n\t\tpCopList->pBackBfr->uwCmdCount = ulListSize+1;\n\t\tpCopList->pBackBfr->uwAllocSize = (ulListSize+1)*sizeof(tCopCmd);\n\t\tpCopList->pBackBfr->pList = memAllocChipClear(pCopList->pBackBfr->uwAllocSize);\n\t\tcopSetWait(&pCopList->pBackBfr->pList[ulListSize].sWait, 0xFF, 0xFF);\n\t}\n\telse {\n\t\tlogWrite(\"BLOCK mode\\n\");\n\t}\n\n\tlogBlockEnd(\"copListCreate()\");\n\tva_end(vaTags);\n\treturn pCopList;\n\nfail:\n\tva_end(vaTags);\n\tcopListDestroy(pCopList);\n\tlogBlockEnd(\"copListCreate()\");\n\treturn 0;\n}\n\nvoid copListDestroy(tCopList *pCopList) {\n\tlogBlockBegin(\"copListDestroy(pCopList: %p)\", pCopList);\n\n\t// Free copperlist buffers\n\twhile(pCopList->pFirstBlock) {\n\t\tcopBlockDestroy(pCopList, pCopList->pFirstBlock);\n\t}\n\n\t// Free front buffer\n\tif(pCopList->pFrontBfr->uwAllocSize) {\n\t\tmemFree(pCopList->pFrontBfr->pList, pCopList->pFrontBfr->uwAllocSize);\n\t}\n\tmemFree(pCopList->pFrontBfr, sizeof(tCopBfr));\n\n\t// Free back buffer\n\tif(pCopList->pBackBfr->uwAllocSize) {\n\t\tmemFree(pCopList->pBackBfr->pList, pCopList->pBackBfr->uwAllocSize);\n\t}\n\tmemFree(pCopList->pBackBfr, sizeof(tCopBfr));\n\n\t// Free main struct\n\tmemFree(pCopList, sizeof(tCopList));\n\n\tlogBlockEnd(\"copListDestroy()\");\n}\n\ntCopBlock *copBlockCreate(tCopList *pCopList, UWORD uwMaxCmds, UWORD uwWaitX, UWORD uwWaitY) {\n\ttCopBlock *pBlock;\n\n\tlogBlockBegin(\"copBlockCreate(pCopList: %p, uwMaxCmds: %u, uwWaitX: %u, uwWaitY: %u)\", pCopList, uwMaxCmds, uwWaitX, uwWaitY);\n\tpBlock = memAllocFastClear(sizeof(tCopBlock));\n\tlogWrite(\"pAddr: %p\\n\", pBlock);\n\tpBlock->uwMaxCmds = uwMaxCmds; // MOVEs only\n\tpBlock->pCmds     = memAllocFast(sizeof(tCopCmd) * pBlock->uwMaxCmds);\n\n\tcopBlockWait(pCopList, pBlock, uwWaitX, uwWaitY);\n\n\t// Add to list\n\tlogWrite(\"Head: %p\\n\", pCopList->pFirstBlock);\n\tif(!pCopList->pFirstBlock || pBlock->uWaitPos.ulYX < pCopList->pFirstBlock->uWaitPos.ulYX) {\n\t\tpBlock->pNext = pCopList->pFirstBlock;\n\t\tpCopList->pFirstBlock = pBlock;\n\t\tlogWrite(\"Added as head, next: %p\\n\", pBlock->pNext);\n\t}\n\telse {\n\t\ttCopBlock *pPrev;\n\n\t\tpPrev = pCopList->pFirstBlock;\n\t\twhile(pPrev->pNext && pPrev->pNext->uWaitPos.ulYX < pBlock->uWaitPos.ulYX) {\n\t\t\tpPrev = pPrev->pNext;\n\t\t}\n\t\tpBlock->pNext = pPrev->pNext;\n\t\tpPrev->pNext = pBlock;\n\t}\n\tpCopList->ubStatus |= STATUS_REALLOC_CURR | STATUS_REORDER | STATUS_UPDATE_CURR;\n\t++pCopList->uwBlockCount;\n\n\tlogBlockEnd(\"copBlockCreate()\");\n\treturn pBlock;\n}\n\nvoid copBlockDestroy(tCopList *pCopList, tCopBlock *pBlock) {\n\tlogBlockBegin(\"copBlockDestroy(pCopList: %p, pBlock: %p)\", pCopList, pBlock);\n\n\t// Remove from list\n\tif(pBlock == pCopList->pFirstBlock) {\n\t\tpCopList->pFirstBlock = pBlock->pNext;\n\t}\n\telse {\n\t\ttCopBlock *pCurr;\n\n\t\tpCurr = pCopList->pFirstBlock;\n\t\twhile(pCurr->pNext && pCurr->pNext != pBlock) {\n\t\t\tpCurr = pCurr->pNext;\n\t\t}\n\n\t\tif(pCurr->pNext) {\n\t\t\tpCurr->pNext = pBlock->pNext;\n\t\t}\n\t\telse {\n\t\t\tlogWrite(\"ERR: Can't find block %p\\n\", pBlock);\n\t\t}\n\t}\n\n\t// Free mem\n\tmemFree(pBlock->pCmds, sizeof(tCopCmd)*pBlock->uwMaxCmds);\n\tmemFree(pBlock, sizeof(tCopBlock));\n\n\tpCopList->ubStatus |= STATUS_REALLOC_CURR;\n\t--pCopList->uwBlockCount;\n\n\tlogBlockEnd(\"copBlockDestroy()\");\n}\n\nvoid copBlockEnable(tCopList *pCopList, tCopBlock *pBlock) {\n\tpBlock->ubDisabled = 0;\n\tpBlock->ubUpdated = 2;\n\tpBlock->pNext->ubUpdated = 2;\n\tpCopList->ubStatus |= STATUS_UPDATE;\n}\n\nvoid copBlockDisable(tCopList *pCopList, tCopBlock *pBlock) {\n\tpBlock->ubDisabled = 1;\n\tpBlock->pNext->ubUpdated = 2;\n\tpCopList->ubStatus |= STATUS_UPDATE;\n}\n\nUBYTE copBfrRealloc(void) {\n\ttCopList *pCopList;\n\ttCopBfr *pBackBfr;\n\ttCopBlock *pBlock;\n\tUBYTE ubNewStatus;\n\n\tpCopList = g_sCopManager.pCopList;\n\tpBackBfr = pCopList->pBackBfr;\n\n\t// Free memory\n\tif(pBackBfr->uwAllocSize) {\n\t\tmemFree(pBackBfr->pList, pBackBfr->uwAllocSize);\n\t}\n\n\t// Calculate new list size\n\tif(pCopList->ubStatus & STATUS_REALLOC_CURR) {\n\n\t\tpBackBfr->uwAllocSize = 0;\n\t\tfor(pBlock = pCopList->pFirstBlock; pBlock; pBlock = pBlock->pNext) {\n\t\t\tpBackBfr->uwAllocSize += 1 + pBlock->uwMaxCmds; // WAIT + MOVEs\n\t\t}\n\t\tpBackBfr->uwAllocSize += 2; // final WAIT + room for double WAIT\n\t\tpBackBfr->uwAllocSize *= sizeof(tCopCmd);\n\t\t// Pass realloc to next buffer\n\t\tubNewStatus = STATUS_REALLOC_PREV;\n\t}\n\telse {\n\t\t// If realloc just propagates to next buffer, calculations aren't necessary\n\t\tpBackBfr->uwAllocSize = pCopList->pFrontBfr->uwAllocSize;\n\t\tubNewStatus = 0;\n\t}\n\n\t// Alloc memory\n\tpBackBfr->pList = memAllocChip(pBackBfr->uwAllocSize);\n\treturn ubNewStatus;\n}\n\nvoid copReorderBlocks(void) {\n\ttCopList *pCopList = g_sCopManager.pCopList;\n\tUBYTE ubDone;\n\tdo {\n\t\tubDone = 1;\n\t\ttCopBlock *pBlock = pCopList->pFirstBlock;\n\t\ttCopBlock *pPrev = 0;\n\t\twhile(pBlock->pNext) {\n\t\t\tif(pBlock->uWaitPos.ulYX > pBlock->pNext->uWaitPos.ulYX) {\n\t\t\t\tif(!pPrev) {\n\t\t\t\t\tpCopList->pFirstBlock = pBlock->pNext;\n\t\t\t\t\tpBlock->pNext = pCopList->pFirstBlock->pNext;\n\t\t\t\t\tpCopList->pFirstBlock->pNext = pBlock;\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tpPrev->pNext = pBlock->pNext;\n\t\t\t\t\tpBlock->pNext = pPrev->pNext->pNext;\n\t\t\t\t\tpPrev->pNext->pNext = pBlock;\n\t\t\t\t}\n\t\t\t\tubDone = 0;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tpPrev = pBlock;\n\t\t\tpBlock = pBlock->pNext;\n\t\t}\n\n\t} while(!ubDone);\n}\n\nUBYTE copUpdateFromBlocks(void) {\n\ttCopList *pCopList;\n\ttCopBlock *pBlock;\n\ttCopBfr *pBackBfr;\n\tUWORD uwListPos;\n\tUBYTE ubWasLimitY;\n\n\tpCopList = g_sCopManager.pCopList;\n\tpBackBfr = pCopList->pBackBfr;\n\n\tpBlock = pCopList->pFirstBlock;\n\tuwListPos = 0;\n\tubWasLimitY = 0;\n\n\t// Update buffers if their sizes haven't changed\n\t// ///////////////////////////////////////////////////////////////////////////\n\t// Disabled 'cuz it's broken\n\t// This part should update content of modified blocks, which sizes were\n\t// not changed. To test fix candidates, run copper test in ACE showcase.\n\t// ///////////////////////////////////////////////////////////////////////////\n\t/*\n\twhile(0 && pBlock && !pBlock->ubResized) {\n\t\tif(!pBlock->ubDisabled) {\n\t\t\tif(pBlock->ubUpdated) {\n\t\t\t\t// Update WAIT\n\t\t\t\tif(pBlock->uWaitPos.uwY > 0xFF) {\n\t\t\t\t\t// FIXME: double WAIT only when previous line ended before some pos\n\t\t\t\t\tif(!ubWasLimitY) {\n\t\t\t\t\t\t// FIXME: If copper block was moved down, so that WAIT suddenly\n\t\t\t\t\t\t// consists of 2 instructions instead of 1 AND is first y>0xFF,\n\t\t\t\t\t\t// such block should be treated as resized one. Same refers to\n\t\t\t\t\t\t// block, which changed from 2 WAITs to 1.\n\t\t\t\t\t\tcopSetWait((tCopWaitCmd*)&pBackBfr->pList[uwListPos], 0xDF, 0xFF);\n\t\t\t\t\t\t++uwListPos;\n\t\t\t\t\t\tubWasLimitY = 1;\n\t\t\t\t\t}\n\t\t\t\t\tcopSetWait((tCopWaitCmd*)&pBackBfr->pList[uwListPos], pBlock->uWaitPos.uwX, pBlock->uWaitPos.uwY & 0xFF);\n\t\t\t\t\t++uwListPos;\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tcopSetWait((tCopWaitCmd*)&pBackBfr->pList[uwListPos], pBlock->uWaitPos.uwX, pBlock->uWaitPos.uwY);\n\t\t\t\t\t++uwListPos;\n\t\t\t\t}\n\n\t\t\t\t// Copy MOVEs\n\t\t\t\tmemcpy(\n\t\t\t\t\t&pBackBfr->pList[uwListPos], pBlock->pCmds,\n\t\t\t\t\tpBlock->uwCurrCount * sizeof(tCopCmd)\n\t\t\t\t);\n\t\t\t\t--pBlock->ubUpdated;\n\t\t\t}\n\t\t\tuwListPos += pBlock->uwCurrCount;\n\t\t}\n\t\tpBlock = pBlock->pNext;\n\t}\n\t*/\n\t// ///////////////////////////////////////////////////////////////////////////\n\t// End of broken part\n\t// ///////////////////////////////////////////////////////////////////////////\n\n\t// Do full merge on remaining blocks\n\tfor(; pBlock; pBlock = pBlock->pNext) {\n\t\tif(pBlock->ubDisabled) {\n\t\t\tcontinue;\n\t\t}\n\t\tif(pBlock->ubResized) {\n\t\t\t--pBlock->ubResized;\n\t\t}\n\t\tif(pBlock->ubUpdated) {\n\t\t\t--pBlock->ubUpdated;\n\t\t}\n\t\tif(pBlock->uwCurrCount == 0) {\n\t\t\tcontinue;\n\t\t}\n\n\t\t// Update WAIT\n\t\tif(pBlock->uWaitPos.uwY >= 0xFF) {\n\t\t\t// FIXME: double WAIT only when previous line ended before some pos\n\t\t\tif(!ubWasLimitY) {\n\t\t\t\tcopSetWait((tCopWaitCmd*)&pBackBfr->pList[uwListPos], 0xDF, 0xFF);\n\t\t\t\t++uwListPos;\n\t\t\t\tubWasLimitY = 1;\n\t\t\t}\n\t\t\tif(pBlock->uWaitPos.uwY > 0xFF) {\n\t\t\t\tcopSetWait(\n\t\t\t\t\t(tCopWaitCmd*)&pBackBfr->pList[uwListPos],\n\t\t\t\t\tpBlock->uWaitPos.uwX, pBlock->uWaitPos.uwY & 0xFF\n\t\t\t\t);\n\t\t\t\t++uwListPos;\n\t\t\t}\n\t\t}\n\t\telse {\n\t\t\tcopSetWait(\n\t\t\t\t(tCopWaitCmd*)&pBackBfr->pList[uwListPos],\n\t\t\t\tpBlock->uWaitPos.uwX, pBlock->uWaitPos.uwY\n\t\t\t);\n\t\t\t++uwListPos;\n\t\t}\n\n\t\t// Copy MOVEs\n\t\tfor(UWORD i = pBlock->uwCurrCount; i--;) {\n\t\t\tpBackBfr->pList[uwListPos + i].ulCode = pBlock->pCmds[i].ulCode;\n\t\t}\n\t\tuwListPos += pBlock->uwCurrCount;\n\t}\n\n\t// Add 0xFFFF terminator\n\tcopSetWait((tCopWaitCmd*)&pBackBfr->pList[uwListPos], 0xFF, 0xFF);\n\t++uwListPos;\n\n\tpCopList->pBackBfr->uwCmdCount = uwListPos;\n\n\tif(pCopList->ubStatus & STATUS_UPDATE_CURR) {\n\t\treturn STATUS_UPDATE_PREV;\n\t}\n\treturn 0;\n}\n\nvoid copProcessBlocks(void) {\n\ttCopList *pCopList = g_sCopManager.pCopList;\n\tif(pCopList->ubMode == COPPER_MODE_BLOCK) {\n\t\tUBYTE ubNewStatus = 0;\n\t\t// Realloc buffer memeory\n\t\tif(pCopList->ubStatus & STATUS_REALLOC) {\n\t\t\tubNewStatus = copBfrRealloc();\n\t\t}\n\n\t\t// Sort blocks if needed\n\t\tif(pCopList->ubStatus & STATUS_REORDER) {\n\t\t\tcopReorderBlocks();\n\t\t}\n\n\t\t// Update buffer data\n\t\tif(pCopList->ubStatus & STATUS_UPDATE) {\n\t\t\tubNewStatus |= copUpdateFromBlocks();\n\t\t}\n\t\t// Update status code\n\t\tpCopList->ubStatus = ubNewStatus;\n\t}\n\n\t// Swap copper buffers\n\tcopSwapBuffers();\n}\n\nvoid copBlockWait(tCopList *pCopList, tCopBlock *pBlock, UWORD uwX, UWORD uwY) {\n\tpBlock->uWaitPos.uwY  = uwY;\n\tpBlock->uWaitPos.uwX  = uwX;\n\n\tpBlock->ubUpdated = 2;\n\tpCopList->ubStatus |= STATUS_UPDATE | STATUS_REORDER;\n}\n\nvoid copMove(tCopList *pCopList, tCopBlock *pBlock, volatile void *pAddr, UWORD uwValue) {\n\tcopSetMove((tCopMoveCmd*)&pBlock->pCmds[pBlock->uwCurrCount], pAddr, uwValue);\n\t++pBlock->uwCurrCount;\n\n\tpBlock->ubUpdated = 2;\n\tpBlock->ubResized = 2;\n\tpCopList->ubStatus |= STATUS_UPDATE;\n}\n\nvoid copSetWait(tCopWaitCmd *pWaitCmd, UBYTE ubX, UBYTE ubY) {\n\tpWaitCmd->bfWaitY         = ubY;\n\tpWaitCmd->bfWaitX         = ubX >> 1;\n\tpWaitCmd->bfIsWait        = 1;\n\tpWaitCmd->bfBlitterIgnore = 1;\n\tpWaitCmd->bfVE            = 0x7F;\n\tpWaitCmd->bfHE            = 0x7F;\n\tpWaitCmd->bfIsSkip        = 0;\n}\n\nvoid copSetMove(tCopMoveCmd *pMoveCmd, volatile void *pAddr, UWORD uwValue) {\n\tpMoveCmd->bfUnused = 0;\n\tpMoveCmd->bfDestAddr = (ULONG)pAddr - (ULONG)((UBYTE *)g_pCustom);\n\tcopSetMoveVal(pMoveCmd, uwValue);\n}\n\n#endif // AMIGA\n"
  },
  {
    "path": "src/ace/managers/game.c",
    "content": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at http://mozilla.org/MPL/2.0/. */\n\n#include <ace/managers/game.h>\n\nstatic UBYTE s_isGameRunning = 1;\n\n/* Functions */\n\nvoid gameExit(void) {\n\ts_isGameRunning = 0;\n}\n\nUBYTE gameIsRunning(void) {\n\treturn s_isGameRunning;\n}\n"
  },
  {
    "path": "src/ace/managers/joy.c",
    "content": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at http://mozilla.org/MPL/2.0/. */\n\n#include <proto/exec.h> // Bartman's compiler needs this\n#include <proto/misc.h> // Bartman's compiler needs this\n#include <resources/misc.h> // OS-friendly parallel joys: misc.resource\n#include <clib/misc_protos.h> // OS-friendly parallel joys: misc.resource\n#include <ace/managers/joy.h>\n#include <ace/managers/log.h>\n#include <ace/managers/system.h>\n#include <ace/utils/custom.h>\n\n#if defined ACE_DEBUG\nstatic UBYTE s_bInitCount = 0;\n#endif\n\n/* Globals */\ntJoyManager g_sJoyManager;\n\nstruct Library *MiscBase = 0;\nstatic UBYTE s_isParallelEnabled = 0;\nstatic UBYTE s_ubOldDataDdr, s_ubOldStatusDdr, s_ubOldDataVal, s_ubOldStatusVal;\n\n/* Functions */\n\n// Wrapper function to omit casting\nstatic inline const char *myAllocMiscResource(\n\tULONG ulUnitNum, const char *szOwner\n) {\n\treturn (const char*)AllocMiscResource(ulUnitNum, (CONST_STRPTR)szOwner);\n}\n\n\nvoid joyOpen(void) {\n#if defined(ACE_DEBUG)\n\tif(s_bInitCount++ != 0) {\n\t\t// You should call keyCreate() only once\n\t\tlogWrite(\"ERR: Joy already initialized\\n\");\n\t}\n#endif\n}\n\nvoid joyClose(void) {\n#if defined(ACE_DEBUG)\n\tif(s_bInitCount-- != 1) {\n\t\t// You should call joyClose() only once for each joyCreate()\n\t\tlogWrite(\"ERR: Joy was initialized multiple times\\n\");\n\t}\n#endif\n\tjoyDisableParallel();\n}\n\nvoid joySetState(UBYTE ubJoyCode, UBYTE ubJoyState) {\n\tg_sJoyManager.pStates[ubJoyCode] = ubJoyState;\n}\n\nUBYTE joyCheck(UBYTE ubJoyCode) {\n\treturn g_sJoyManager.pStates[ubJoyCode] != JOY_NACTIVE;\n}\n\nUBYTE joyUse(UBYTE ubJoyCode) {\n\tif (g_sJoyManager.pStates[ubJoyCode] == JOY_ACTIVE) {\n\t\tg_sJoyManager.pStates[ubJoyCode] = JOY_USED;\n\t\treturn 1;\n\t}\n\treturn 0;\n}\n\nvoid joyProcess(void) {\n\tUBYTE ubCiaAPra = g_pCia[CIA_A]->pra;\n\tUWORD uwJoyDataPort1 = g_pCustom->joy0dat;\n\tUWORD uwJoyDataPort2 = g_pCustom->joy1dat;\n\tUWORD uwInput = g_pCustom->potinp;\n\n\tUWORD pJoyLookup[24] = {\n\t\t!BTST(ubCiaAPra, 7),                           // Joy 1 fire  (PORT 2)\n\t\tBTST(uwJoyDataPort2 >> 1 ^ uwJoyDataPort2, 8), // Joy 1 up    (PORT 2)\n\t\tBTST(uwJoyDataPort2 >> 1 ^ uwJoyDataPort2, 0), // Joy 1 down  (PORT 2)\n\t\tBTST(uwJoyDataPort2, 9),                       // Joy 1 left  (PORT 2)\n\t\tBTST(uwJoyDataPort2, 1),                       // Joy 1 right (PORT 2)\n\t\t!BTST(uwInput, 14),                            // Joy 1 fire2 (PORT 2)\n\n\t\t!BTST(ubCiaAPra, 6),                           // Joy 2 fire  (PORT 1)\n\t\tBTST(uwJoyDataPort1 >> 1 ^ uwJoyDataPort1, 8), // Joy 2 up    (PORT 1)\n\t\tBTST(uwJoyDataPort1 >> 1 ^ uwJoyDataPort1, 0), // Joy 2 down  (PORT 1)\n\t\tBTST(uwJoyDataPort1, 9),                       // Joy 2 left  (PORT 1)\n\t\tBTST(uwJoyDataPort1, 1),                       // Joy 2 right (PORT 1)\n\t\t!BTST(uwInput, 10),                            // Joy 2 fire2 (PORT 1)\n\t};\n\n\tUBYTE ubJoyCode;\n\tif(s_isParallelEnabled) {\n\t\tubJoyCode = 24;\n\t\tUBYTE ubParData = g_pCia[CIA_A]->prb;\n\t\tUBYTE ubParStatus = g_pCia[CIA_B]->pra;\n\n\t\tpJoyLookup[12] = !BTST(ubParStatus, 2); // Joy 3 fire\n\t\tpJoyLookup[13] = !BTST(ubParData, 0);   // Joy 3 up\n\t\tpJoyLookup[14] = !BTST(ubParData, 1);   // Joy 3 down\n\t\tpJoyLookup[15] = !BTST(ubParData, 2);   // Joy 3 left\n\t\tpJoyLookup[16] = !BTST(ubParData, 3);   // Joy 3 right\n\t\tpJoyLookup[17] = 0;   // Joy 3 fire 2\n\n\t\tpJoyLookup[18] = !BTST(ubParStatus , 0); // Joy 4 fire\n\t\tpJoyLookup[19] = !BTST(ubParData , 4);   // Joy 4 up\n\t\tpJoyLookup[20] = !BTST(ubParData , 5);   // Joy 4 down\n\t\tpJoyLookup[21] = !BTST(ubParData , 6);   // Joy 4 left\n\t\tpJoyLookup[22] = !BTST(ubParData , 7);   // Joy 4 right\n\t\tpJoyLookup[23] = 0;   // Joy 4 fire 2\n\t}\n\telse {\n\t\tubJoyCode = 12;\n\t}\n\twhile (ubJoyCode--) {\n\t\tif (pJoyLookup[ubJoyCode]) {\n\t\t\tif (g_sJoyManager.pStates[ubJoyCode] == JOY_NACTIVE) {\n\t\t\t\tjoySetState(ubJoyCode, JOY_ACTIVE);\n\t\t\t}\n\t\t}\n\t\telse {\n\t\t\tjoySetState(ubJoyCode, JOY_NACTIVE);\n\t\t}\n\t}\n}\n\n//----------------------------------------------------------- PARALLEL PORT JOYS\n\nUBYTE joyEnableParallel(void) {\n\tif(s_isParallelEnabled) {\n\t\treturn 1;\n\t}\n\tsystemUse();\n\t// Open misc.resource for 3rd and 4th joy connected to parallel port\n\tstatic const char *szOwner = \"ACE joy manager\";\n\tMiscBase = (struct Library*)OpenResource((CONST_STRPTR)MISCNAME);\n\tif(!MiscBase) {\n\t\tlogWrite(\"ERR: Couldn't open '%s'\\n\", MISCNAME);\n\t\tsystemUnuse();\n\t\treturn 0;\n\t}\n\n\t// Are data/status line currently used?\n\tconst char *szCurrentOwner;\n\tszCurrentOwner = myAllocMiscResource(MR_PARALLELPORT, szOwner);\n\tif(szCurrentOwner) {\n\t\tlogWrite(\"ERR: Parallel data lines access blocked by: '%s'\\n\", szCurrentOwner);\n\t\tsystemUnuse();\n\t\treturn 0;\n\t}\n\tszCurrentOwner = myAllocMiscResource(MR_PARALLELBITS, szOwner);\n\tif(szCurrentOwner) {\n\t\tlogWrite(\"ERR: Parallel status lines access blocked by: '%s'\\n\", szCurrentOwner);\n\t\tFreeMiscResource(MR_PARALLELPORT);\n\t\tsystemUnuse();\n\t\treturn 0;\n\t}\n\n\t// Save old DDR & value regs\n\ts_ubOldDataDdr = g_pCia[CIA_A]->ddrb;\n\ts_ubOldStatusDdr = g_pCia[CIA_B]->ddra;\n\ts_ubOldDataVal = g_pCia[CIA_A]->prb;\n\ts_ubOldStatusVal = g_pCia[CIA_B]->pra;\n\n\t// Set data direction register to input.\n\tg_pCia[CIA_B]->ddra &= 0xFF ^ (BV(0) | BV(2)); // 0: BUSY, 2: SEL\n\tg_pCia[CIA_A]->ddrb = 0; // Data\n\n\t// Activate pull-ups for BUSY / SEL / data pins\n\tg_pCia[CIA_B]->pra |= BV(0) | BV(2); // Status lines values\n\tg_pCia[CIA_A]->prb = 0xFF; // Data lines values\n\n\ts_isParallelEnabled = 1;\n\tsystemUnuse();\n\treturn 1;\n}\n\nvoid joyDisableParallel(void) {\n\tif(!s_isParallelEnabled) {\n\t\treturn;\n\t}\n\n\t// Restore old status/data DDR/val regs\n\tg_pCia[CIA_A]->prb = s_ubOldDataVal;\n\tg_pCia[CIA_B]->pra = s_ubOldStatusVal;\n\tg_pCia[CIA_A]->ddrb = s_ubOldDataDdr;\n\tg_pCia[CIA_B]->ddra = s_ubOldStatusDdr;\n\n\t// Close misc.resource\n\tsystemUse();\n\tFreeMiscResource(MR_PARALLELBITS);\n\tFreeMiscResource(MR_PARALLELPORT);\n\tsystemUnuse();\n\ts_isParallelEnabled = 0;\n}\n\nUBYTE joyIsParallelEnabled(void) {\n\treturn s_isParallelEnabled;\n}\n"
  },
  {
    "path": "src/ace/managers/key.c",
    "content": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at http://mozilla.org/MPL/2.0/. */\n\n#include <ace/managers/key.h>\n#include <ace/managers/log.h>\n#include <ace/managers/memory.h>\n#include <ace/managers/system.h>\n#include <ace/utils/custom.h>\n#include <hardware/intbits.h> // INTB_PORTS\n#define KEY_INTERRUPT_RELEASED_BIT 1\n#define KEY_INPUT_HANDLER_RELEASED_MASK BV(7)\n\n#if defined ACE_DEBUG\nstatic UBYTE s_bInitCount = 0;\n#endif\n\nstatic inline void keyIntSetState(\n\ttKeyManager *pManager, UBYTE ubKeyCode, UBYTE ubKeyState\n) {\n\tpManager->pStates[ubKeyCode] = ubKeyState;\n\tif(ubKeyState == KEY_ACTIVE) {\n\t\tpManager->ubLastKey = ubKeyCode;\n\t}\n}\n\nstatic inline UBYTE keyIntCheck(const tKeyManager *pManager, UBYTE ubKeyCode) {\n\treturn pManager->pStates[ubKeyCode] != KEY_NACTIVE;\n}\n\nUBYTE keyCheck(UBYTE ubKeyCode) {\n\treturn keyIntCheck(&g_sKeyManager, ubKeyCode);\n}\n\nvoid keySetState(UBYTE ubKeyCode, UBYTE ubKeyState) {\n\tkeyIntSetState(&g_sKeyManager, ubKeyCode, ubKeyState);\n}\n\nvoid onRawKeyInput(UBYTE ubRawKey) {\n\tUBYTE isKeyReleased = ubRawKey & KEY_INPUT_HANDLER_RELEASED_MASK;\n\tubRawKey &= ~KEY_INPUT_HANDLER_RELEASED_MASK;\n\tkeySetState(ubRawKey, isKeyReleased ? KEY_NACTIVE : KEY_ACTIVE);\n}\n\n/**\n * Key interrupt server\n * Gets key press/release from kbd controller and confirms reception\n * by handshake\n */\nFN_HOTSPOT\nvoid INTERRUPT onKeyInterrupt(\n\tREGARG(volatile tCustom *pCustom, \"a0\"),\n\tREGARG(volatile void *pData, \"a1\")\n) {\n\ttKeyManager *pKeyManager = (tKeyManager*)pData;\n\tvolatile tRayPos *pRayPos = (tRayPos*)&pCustom->vposr;\n\n\t// Get the key code and start handshake\n\tUBYTE ubKeyCode = ~g_pCia[CIA_A]->sdr;\n\tg_pCia[CIA_A]->cra |= CIACRA_SPMODE;\n\tUWORD uwStart = pRayPos->bfPosY;\n\n\t// Get keypress flag and shift key code\n\tUBYTE ubKeyReleased = ubKeyCode & KEY_INTERRUPT_RELEASED_BIT;\n\tubKeyCode >>= 1;\n\tkeyIntSetState(\n\t\tpKeyManager, ubKeyCode, ubKeyReleased ? KEY_NACTIVE : KEY_ACTIVE\n\t);\n\n\t// End handshake\n\tUWORD uwDelta;\n\tdo {\n\t\tUWORD uwEnd = pRayPos->bfPosY;\n\t\tif(uwEnd >= uwStart) {\n\t\t\tuwDelta = uwEnd - uwStart;\n\t\t}\n\t\telse {\n\t\t\tuwDelta = 0xFFFF - uwStart + uwEnd;\n\t\t}\n\t} while(uwDelta < 3);\n\tg_pCia[CIA_A]->cra &= ~CIACRA_SPMODE;\n\tINTERRUPT_END;\n}\n\n/* Globals */\ntKeyManager g_sKeyManager;\n\nconst UBYTE g_pFromAscii[] = { 0\n\n};\nconst UBYTE g_pToAscii[] = {\n\t'`', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '-', '=', '\\\\', '\\0', '0',\n\t'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', '[', ']', '\\0', '1', '2', '3',\n\t'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', '\\'', '\\0', '\\0', '4', '5', '6',\n\t'\\0', 'z', 'x', 'c', 'v', 'b', 'n' ,'m', ',', '.', '/', '\\b', '.', '7', '8', '9',\n\t' ', '\\0', '\\t', '\\r', '\\r', '\\x1B', '\\0', '\\0', '\\0', '\\0', '\\0', '\\0', '\\0', '\\0', '\\0', '\\0',\n\t'\\0', '\\0', '\\0', '\\0', '\\0', '\\0', '\\0', '\\0', '\\0', '\\0', '(', ')', '/', '*', '+', '-',\n\t'\\0', '\\0', '\\0', '\\0', '\\0', '\\0', '\\0', '\\0',\n};\n\nvoid keyCreate(void) {\n\tlogBlockBegin(\"keyCreate()\");\n#if defined(ACE_DEBUG)\n\tif(s_bInitCount++ != 0) {\n\t\t// You should call keyCreate() only once\n\t\tlogWrite(\"ERR: Keyboard already initialized\\n\");\n\t}\n#endif\n\tsystemSetCiaInt(CIA_A, CIAICRB_SERIAL, onKeyInterrupt, &g_sKeyManager);\n\tsystemSetKeyInputHandler(onRawKeyInput);\n\tlogBlockEnd(\"keyCreate()\");\n}\n\nvoid keyDestroy(void) {\n\tlogBlockBegin(\"keyDestroy()\");\n#if defined(ACE_DEBUG)\n\tif(s_bInitCount-- != 1) {\n\t\t// You should call keyDestroy() only once for each keyCreate()\n\t\tlogWrite(\"ERR: Keyboard was initialized multiple times\\n\");\n\t}\n#endif\n\tsystemSetCiaInt(CIA_A, CIAICRB_SERIAL, 0, 0);\n\tsystemSetKeyInputHandler(0);\n\tlogBlockEnd(\"keyDestroy()\");\n}\n\nvoid keyProcess(void) {\n\t// This function is left out for other platforms - they will prob'ly not be\n\t// interrupt-driven.\n}\n"
  },
  {
    "path": "src/ace/managers/log.c",
    "content": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at http://mozilla.org/MPL/2.0/. */\n\n#include <ace/managers/log.h>\n#include <string.h>\n#include <ace/macros.h>\n#include <ace/managers/system.h>\n#include <ace/utils/disk_file.h>\n#ifdef ACE_DEBUG\n\n// Globals\ntLogManager g_sLogManager = {0};\n\n// This can't be created on stack because it's only 10k by default under ks1.3.\nstatic char s_szMsg[1024];\n\n#ifdef ACE_DEBUG_UAE\n\n\t#if defined(BARTMAN_GCC)\nlong (*bartmanLog)(long mode, const char *string) = (long (*)(long, const char *))0xf0ff60;\nstatic inline void uaeWrite(const char *szMsg) {\n\tif (*((UWORD *)bartmanLog) == 0x4eb9 || *((UWORD *)bartmanLog) == 0xa00e) {\n\t\tbartmanLog(86, szMsg);\n\t}\n}\n\t#else\nstatic inline void uaeWrite(const char *szMsg) {\n\tvolatile ULONG * const s_pUaeFmt = (ULONG *)0xBFFF04;\n\t*s_pUaeFmt = (ULONG)((UBYTE*)szMsg);\n}\n\t#endif\n\n#else\n#define uaeWrite(x)\n#endif\n\n// Functions\n\nstatic UBYTE isWritingToFileAllowed(void) {\n\treturn g_sLogManager.pFile && !g_sLogManager.wInterruptDepth;\n}\n\n/**\n * Base debug functions\n */\n\nvoid _logOpen(const char *szFilePath) {\n\tg_sLogManager.ubShutUp = 1; // Prevent log message for diskFileOpen()\n\tg_sLogManager.pFile = szFilePath ? diskFileOpen(szFilePath, DISK_FILE_MODE_WRITE, 0) : 0;\n\tg_sLogManager.ubIndent = 0;\n\tg_sLogManager.wasLastInline = 0;\n\tg_sLogManager.isBlockEmpty = 1;\n\tg_sLogManager.ubShutUp = 0;\n}\n\nvoid _logPushIndent(void) {\n\t++g_sLogManager.ubIndent;\n}\n\nvoid _logPopIndent(void) {\n\t--g_sLogManager.ubIndent;\n}\n\nvoid _logWrite(char *szFormat, ...) {\n\tva_list vaArgs;\n\tva_start(vaArgs, szFormat);\n\tlogWriteVa(szFormat, vaArgs);\n\tva_end(vaArgs);\n}\n\nvoid _logWriteVa(char *szFormat, va_list vaArgs) {\n\tif(g_sLogManager.ubShutUp) {\n\t\treturn;\n\t}\n\n\t// Prevent triggering logging by other log msg (e.g. turn on OS msg with\n\t// logging to file) due to static nature of the buffer.\n\t++g_sLogManager.ubShutUp;\n\n\t// Bartman's UAE logger appends newline to each print, so the message must\n\t// be emitted in one print with indentation.\n\tUWORD uwOffs = 0;\n\tg_sLogManager.isBlockEmpty = 0;\n\tif (!g_sLogManager.wasLastInline) {\n\t\tUBYTE ubLogIndent = g_sLogManager.ubIndent;\n\t\twhile (ubLogIndent--) {\n\t\t\ts_szMsg[uwOffs++] = '\\t';\n\t\t}\n\t}\n\n\tg_sLogManager.wasLastInline = szFormat[strlen(szFormat) - 1] != '\\n';\n\n\tvsprintf(&s_szMsg[uwOffs], szFormat, vaArgs);\n\tuaeWrite(s_szMsg);\n\tif(isWritingToFileAllowed()) {\n\t\tsystemUse();\n\t\tfileWrite(g_sLogManager.pFile, s_szMsg, strlen(s_szMsg));\n\t\tfileFlush(g_sLogManager.pFile);\n\t\tsystemUnuse();\n\t}\n\n\t--g_sLogManager.ubShutUp;\n}\n\nvoid _logClose(void) {\n\tlogWrite(\"Log closed successfully\\n\");\n\tif(g_sLogManager.pFile) {\n\t\tfileClose(g_sLogManager.pFile);\n\t\tg_sLogManager.pFile = 0;\n\t}\n}\n\n/**\n * Extended debug functions\n */\n\n// Log blocks\nvoid _logBlockBegin(char *szBlockName, ...) {\n\tif(g_sLogManager.ubShutUp) {\n\t\treturn;\n\t}\n\tif(isWritingToFileAllowed()) {\n\t\tsystemUse();\n\t}\n\n\tlogWrite(\"Block begin: \");\n\tva_list vaArgs;\n\tva_start(vaArgs, szBlockName);\n\tlogWriteVa(szBlockName, vaArgs);\n\tva_end(vaArgs);\n\tlogWrite(\"\\n\");\n\n\tg_sLogManager.pTimeStack[g_sLogManager.ubIndent] = timerGetPrec();\n\tlogPushIndent();\n\tg_sLogManager.isBlockEmpty = 1;\n\tmemCheckIntegrity();\n\n\tif(isWritingToFileAllowed()) {\n\t\tsystemUnuse();\n\t}\n}\n\nvoid _logBlockEnd(char *szBlockName) {\n\tif(g_sLogManager.ubShutUp) {\n\t\treturn;\n\t}\n\tif(isWritingToFileAllowed()) {\n\t\tsystemUse();\n\t}\n\n\tmemCheckIntegrity();\n\tlogPopIndent();\n\ttimerFormatPrec(\n\t\tg_sLogManager.szTimeBfr,\n\t\ttimerGetDelta(\n\t\t\tg_sLogManager.pTimeStack[g_sLogManager.ubIndent],\n\t\t\ttimerGetPrec()\n\t\t)\n\t);\n\tif(g_sLogManager.isBlockEmpty) {\n\t\t// empty block - collapse to single line\n\t\tg_sLogManager.wasLastInline = 1;\n\t\tif(g_sLogManager.pFile) {\n\t\t\tfileSeek(g_sLogManager.pFile, -1, SEEK_CUR);\n\t\t}\n\t\tlogWrite(\"...OK, time: %s\\n\", g_sLogManager.szTimeBfr);\n\t}\n\telse {\n\t\tlogWrite(\"Block end: %s, time: %s\\n\", szBlockName, g_sLogManager.szTimeBfr);\n\t}\n\tg_sLogManager.isBlockEmpty = 0;\n\tif(isWritingToFileAllowed()) {\n\t\tsystemUnuse();\n\t}\n}\n\n// Average logging\n\ntAvg *_logAvgCreate(char *szName, UWORD uwAllocCount) {\n\ttAvg *pAvg = memAllocFast(sizeof(tAvg));\n\tpAvg->szName = szName;\n\tpAvg->uwAllocCount = uwAllocCount;\n\tpAvg->uwCurrDelta = 0;\n\tpAvg->uwUsedCount = 0;\n\tpAvg->pDeltas = memAllocFast(uwAllocCount*sizeof(ULONG));\n\tpAvg->ulMin = 0xFFFFFFFF;\n\tpAvg->ulMax = 0;\n\treturn pAvg;\n}\n\nvoid _logAvgDestroy(tAvg *pAvg) {\n\tlogAvgWrite(pAvg);\n\tmemFree(pAvg->pDeltas, pAvg->uwAllocCount*sizeof(ULONG));\n\tmemFree(pAvg, sizeof(tAvg));\n}\n\nvoid _logAvgBegin(tAvg *pAvg) {\n\tpAvg->ulStartTime = timerGetPrec();\n}\n\nvoid _logAvgEnd(tAvg *pAvg) {\n\t// Calculate timestamp\n\tpAvg->pDeltas[pAvg->uwCurrDelta] = timerGetDelta(pAvg->ulStartTime, timerGetPrec());\n\t// Update min/max\n\tif(pAvg->pDeltas[pAvg->uwCurrDelta] > pAvg->ulMax) {\n\t\tpAvg->ulMax = pAvg->pDeltas[pAvg->uwCurrDelta];\n\t}\n\tif(pAvg->pDeltas[pAvg->uwCurrDelta] < pAvg->ulMin) {\n\t\tpAvg->ulMin = pAvg->pDeltas[pAvg->uwCurrDelta];\n\t}\n\t++pAvg->uwCurrDelta;\n\t// Roll\n\tif(pAvg->uwCurrDelta >= pAvg->uwAllocCount) {\n\t\tpAvg->uwCurrDelta = 0;\n\t}\n\tpAvg->uwUsedCount = MIN(pAvg->uwAllocCount, pAvg->uwUsedCount + 1);\n}\n\nvoid _logAvgWrite(tAvg *pAvg) {\n\tULONG ulAvg = 0;\n\tchar szAvg[15];\n\tchar szMin[15];\n\tchar szMax[15];\n\n\tif(!pAvg->uwUsedCount) {\n\t\tlogWrite(\"Avg %s: No measures taken\\n\", pAvg->szName);\n\t\treturn;\n\t}\n\t// Calculate average time\n\tfor(UWORD i = pAvg->uwUsedCount; i--;) {\n\t\tulAvg += pAvg->pDeltas[i];\n\t}\n\tulAvg /= pAvg->uwUsedCount;\n\n\t// Display info\n\ttimerFormatPrec(szAvg, ulAvg);\n\ttimerFormatPrec(szMin, pAvg->ulMin);\n\ttimerFormatPrec(szMax, pAvg->ulMax);\n\tlogWrite(\"Avg %s: %s, min: %s, max: %s\\n\", pAvg->szName, szAvg, szMin, szMax);\n}\n\nvoid _logPushInt(void) {\n\t++g_sLogManager.wInterruptDepth;\n}\n\nvoid _logPopInt(void) {\n\tif(--g_sLogManager.wInterruptDepth < 0) {\n\t\tlogWrite(\"ERR: INT DEPTH NEGATIVE\\n\");\n\t}\n}\n\n#endif // ACE_DEBUG\n"
  },
  {
    "path": "src/ace/managers/memory.c",
    "content": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at http://mozilla.org/MPL/2.0/. */\n\n#include <proto/exec.h> // Bartman's compiler needs this\n#include <proto/dos.h> // Bartman's compiler needs this\n#include <ace/managers/memory.h>\n#include <ace/managers/system.h>\n#include <ace/managers/log.h>\n\n#ifdef AMIGA\n#include <clib/exec_protos.h> // AvailMem, AllocMem, FreeMem, etc.\n#endif\n\n//------------------------------------------------------------------------ TYPES\n\ntypedef struct _tMemEntry {\n\tvoid *pAddr;\n\tULONG ulSize;\n\tUWORD uwId;\n\tstruct _tMemEntry *pNext;\n} tMemEntry;\n\n//----------------------------------------------------------------- PRIVATE VARS\n\nstatic UWORD s_uwLastId = 0;\nstatic tMemEntry *s_pMemTail;\nstatic ULONG s_ulChipUsage, s_ulChipPeakUsage, s_ulFastUsage, s_ulFastPeakUsage;\n\n//---------------------------------------------------------------- MEM ENTRY FNS\n\nstatic void _memEntryAdd(\n\tvoid *pAddr, ULONG ulSize, UWORD uwLine, const char *szFile\n) {\n\t// Ozzyboshi discovered that memory allocation works without re-enabling\n\t// the OS. After analyzing what's under the hood, it looks like there are only\n\t// Forbid/Permit calls inside OS mem fns and the rest is just plain code.\n\t// Still, OS mem fns can be patched by Snoopdos and/or newer OS versions,\n\t// so I guess the safest approach is not to assume anything and wake OS up\n\t// in case it needs other components on some exotic configs.\n\n\tsystemUse();\n\ttMemEntry *pNext;\n\t// Add mem usage entry\n\tpNext = s_pMemTail;\n\ts_pMemTail = _memAllocRls(sizeof(tMemEntry), MEMF_CLEAR);\n\ts_pMemTail->pAddr = pAddr;\n\ts_pMemTail->ulSize = ulSize;\n\ts_pMemTail->uwId = s_uwLastId++;\n\ts_pMemTail->pNext = pNext;\n\n\tlogWrite(\n\t\t\"[MEM] Allocated %s memory %hu@%p, size %lu (%s:%u)\\n\",\n\t\t(memType(pAddr) & MEMF_CHIP) ? \"CHIP\" : \"FAST\",\n\t\ts_pMemTail->uwId, pAddr, ulSize, szFile, uwLine\n\t);\n\n\t// Update mem usage counter\n\tif(memType(pAddr) & MEMF_CHIP) {\n\t\ts_ulChipUsage += ulSize;\n\t\tif(s_ulChipUsage > s_ulChipPeakUsage) {\n\t\t\ts_ulChipPeakUsage = s_ulChipUsage;\n\t\t}\n\t}\n\telse {\n\t\ts_ulFastUsage += ulSize;\n\t\tif(s_ulFastUsage > s_ulFastPeakUsage) {\n\t\t\ts_ulFastPeakUsage = s_ulFastUsage;\n\t\t}\n\t}\n\tsystemUnuse();\n}\n\nstatic ULONG _memEntryDelete(\n\tvoid *pAddr, ULONG ulSize, UWORD uwLine, const char *szFile\n) {\n\ttMemEntry *pPrev = 0;\n\ttMemEntry *pCurr = s_pMemTail;\n\n\t// find memory entry\n\twhile(pCurr && pCurr->pAddr != pAddr) {\n\t\tpPrev = pCurr;\n\t\tpCurr = pCurr->pNext;\n\t}\n\tif(!pCurr) {\n\t\tlogWrite(\n\t\t\t\"[MEM] ERR: can't find memory allocated at %p (%s:%u)\\n\", pAddr, szFile, uwLine\n\t\t);\n\t\treturn 0;\n\t}\n\n\t// unlink entry from list\n\tif(pPrev) {\n\t\tpPrev->pNext = pCurr->pNext;\n\t}\n\telse {\n\t\ts_pMemTail = pCurr->pNext;\n\t}\n\n\t// remove entry\n\tsystemUse();\n\tif(ulSize != pCurr->ulSize) {\n\t\tlogWrite(\n\t\t\t\"[MEM] ERR: memFree size mismatch at memory %hu@%p: %lu, should be %lu (%s:%u)\\n\",\n\t\t\tpCurr->uwId, pAddr, ulSize, pCurr->ulSize, szFile, uwLine\n\t\t);\n\t}\n\tlogWrite(\n\t\t\"[MEM] Freed memory %hu@%p, size %lu (%s:%u)\\n\",\n\t\tpCurr->uwId, pAddr, ulSize, szFile, uwLine\n\t);\n\n\t// Update mem usage counter\n\tif(memType(pAddr) & MEMF_CHIP) {\n\t\ts_ulChipUsage -= ulSize;\n\t}\n\telse {\n\t\ts_ulFastUsage -= ulSize;\n\t}\n\n\tsystemUnuse();\n\treturn pCurr->ulSize;\n}\n\nstatic void memEntryCheckTrash(\n\tconst tMemEntry *pEntry, UWORD uwLine, const char *szFile\n) {\n\tUBYTE *pCafe = (UBYTE*)(pEntry->pAddr - 4*sizeof(UBYTE));\n\tUBYTE *pDead = (UBYTE*)(pEntry->pAddr + pEntry->ulSize);\n\tif(pCafe[0] != 0xCA || pCafe[1] != 0xFE || pCafe[2] != 0xBA || pCafe[3] != 0xBE) {\n\t\tlogWrite(\n\t\t\t\"[MEM] ERR: Left mem trashed: %hu@%p (%s:%u)\\n\",\n\t\t\tpEntry->uwId, pEntry->pAddr, szFile, uwLine\n\t\t);\n\t}\n\tif(pDead[0] != 0xDE || pDead[1] != 0xAD || pDead[2] != 0xBE || pDead[3] != 0xEF) {\n\t\tlogWrite(\n\t\t\t\"[MEM] ERR: Right mem trashed: %hu@%p (%s:%u)\\n\",\n\t\t\tpEntry->uwId, pEntry->pAddr, szFile, uwLine\n\t\t);\n\t}\n}\n\n//---------------------------------------------------------------------- MEM FNS\n\nvoid _memCheckIntegrity(UWORD uwLine, const char *szFile) {\n\ttMemEntry *pEntry = s_pMemTail;\n\twhile(pEntry) {\n\t\tmemEntryCheckTrash(pEntry, uwLine, szFile);\n\t\tpEntry = pEntry->pNext;\n\t}\n\n\tsystemCheckStack();\n}\n\nvoid _memCreate(void) {\n\ts_pMemTail = 0;\n\ts_ulChipUsage = 0;\n\ts_ulChipPeakUsage = 0;\n\ts_ulFastUsage = 0;\n\ts_ulFastPeakUsage = 0;\n\ts_uwLastId = 0;\n}\n\nvoid _memDestroy(void) {\n\tsystemUse();\n\tlogWrite(\"\\n=============== MEMORY MANAGER DESTROY ==============\\n\");\n\tlogWrite(\"If something is deallocated past here, you're a wuss!\\n\");\n\twhile(s_pMemTail) {\n\t\t_memFreeDbg(s_pMemTail->pAddr, s_pMemTail->ulSize, 0, \"memoryDestroy\");\n\t}\n\tlogWrite(\n\t\t\"[MEM] Peak usage: CHIP: %lu, FAST: %lu\\n\",\n\t\ts_ulChipPeakUsage, s_ulFastPeakUsage\n\t);\n\tsystemUnuse();\n}\n\nvoid *_memAllocDbg(\n\tULONG ulSize, ULONG ulFlags, UWORD uwLine, const char *szFile\n) {\n\tif(!ulSize) {\n\t\tlogWrite(\"[MEM] ERR: zero alloc size! (%s:%u)\\n\", szFile, uwLine);\n\t\treturn 0;\n\t}\n\tvoid *pAddr;\n\tpAddr = _memAllocRls(ulSize + 2 * sizeof(ULONG), ulFlags);\n\tif(!pAddr) {\n\t\tlogWrite(\n\t\t\t\"[MEM] ERR: couldn't allocate %lu bytes! (%s:%u)\\n\",\n\t\t\tulSize, szFile, uwLine\n\t\t);\n\t\tmemLogPeak();\n#ifdef AMIGA\n\t\tlogWrite(\n\t\t\t\"[MEM] Largest available chunk of given type: %lu\\n\",\n\t\t\tAvailMem(ulFlags | MEMF_LARGEST)\n\t\t);\n#endif // AMIGA\n\t\treturn 0;\n\t}\n\tpAddr += sizeof(ULONG);\n\n\tUBYTE *pCafe = (UBYTE*)(pAddr - 4*sizeof(UBYTE));\n\tUBYTE *pDead = (UBYTE*)(pAddr + ulSize);\n\tpCafe[0] = 0xCA; pCafe[1] = 0xFE; pCafe[2] = 0xBA; pCafe[3] = 0xBE;\n\tpDead[0] = 0xDE; pDead[1] = 0xAD; pDead[2] = 0xBE; pDead[3] = 0xEF;\n\t_memEntryAdd(pAddr, ulSize, uwLine, szFile);\n\treturn pAddr;\n}\n\nvoid _memFreeDbg(\n\tvoid *pMem, ULONG ulSize, UWORD uwLine, const char *szFile\n) {\n\tsystemUse();\n\t_memCheckIntegrity(uwLine, szFile);\n\tulSize = _memEntryDelete(pMem, ulSize, uwLine, szFile);\n\tif(ulSize) {\n\t\t_memFreeRls(pMem - sizeof(ULONG), ulSize + 2 * sizeof(ULONG));\n\t}\n\tsystemUnuse();\n}\n\nvoid *_memAllocRls(ULONG ulSize, ULONG ulFlags) {\n\tsystemUse();\n\tvoid *pResult;\n\t#ifdef AMIGA\n\tpResult = AllocMem(ulSize, ulFlags);\n\tif(!(ulFlags & MEMF_CHIP) && !pResult) {\n\t\t// No FAST available - allocate CHIP instead\n\t\tlogWrite(\"[MEM] WARN: Couldn't allocate FAST mem\\r\\n\");\n\t\tpResult = AllocMem(ulSize, (ulFlags & ~MEMF_FAST) | MEMF_ANY);\n\t}\n\t#else\n\tpResult =  malloc(ulSize);\n\t#endif // AMIGA\n\tsystemUnuse();\n\treturn pResult;\n}\n\nvoid _memFreeRls(void *pMem, ULONG ulSize) {\n\tsystemUse();\n\t#ifdef AMIGA\n\tFreeMem(pMem, ulSize);\n\t#else\n\tfree(pMem);\n\t#endif // AMIGA\n\tsystemUnuse();\n}\n\nvoid _memCheckTrashAtAddr(void *pMem, UWORD uwLine, const char *szFile) {\n\t// find memory entry\n\ttMemEntry *pEntry = s_pMemTail;\n\twhile(pEntry && pEntry->pAddr != pMem) {\n\t\tpEntry = pEntry->pNext;\n\t}\n\tif(pEntry->pAddr != pMem) {\n\t\tlogWrite(\n\t\t\t\"[MEM] ERR: can't find memory allocated at %p (%s:%u)\\n\",\n\t\t\tpMem, szFile, uwLine\n\t\t);\n\t\treturn;\n\t}\n\tmemEntryCheckTrash(pEntry, uwLine, szFile);\n}\n\nvoid _memLogPeak(void) {\n\tlogWrite(\n\t\t\"[MEM] Peak usage: CHIP: %lu, FAST: %lu\\n\",\n\t\ts_ulChipPeakUsage, s_ulFastPeakUsage\n\t);\n}\n\nUBYTE memType(const void *pMem) {\n#ifdef AMIGA\n\tULONG ulOsType = TypeOfMem((void *)pMem);\n\tif(ulOsType & MEMF_FAST) {\n\t\treturn MEMF_FAST;\n\t}\n\treturn MEMF_CHIP;\n#else\n\treturn MEMF_FAST;\n#endif // AMIGA\n}\n\nULONG memGetFreeChipSize(void) {\n\treturn AvailMem(MEMF_CHIP);\n}\n\nULONG memGetFreeSize(void) {\n\treturn AvailMem(MEMF_ANY);\n}\n"
  },
  {
    "path": "src/ace/managers/mouse.c",
    "content": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at http://mozilla.org/MPL/2.0/. */\n\n#include <ace/managers/mouse.h>\n#include <ace/managers/log.h>\n#include <ace/utils/custom.h>\n#include <ace/generic/screen.h>\n\n/* Globals */\ntMouseManager g_sMouseManager;\n\n/* Functions */\nvoid mouseCreate(UBYTE ubPortFlags) {\n\tmemset(&g_sMouseManager, 0, sizeof(tMouseManager));\n\tg_sMouseManager.ubPortFlags = ubPortFlags;\n\n#ifdef AMIGA\n\tg_sMouseManager.uwPrevPotGo = g_pCustom->potinp;\n\tUWORD uwPotMask = 0;\n\n\t// Enable RMB & MMB\n\tif(ubPortFlags & MOUSE_PORT_1) {\n\t\tuwPotMask |= BV(11) | BV(10) | BV(9) | BV(8);\n\t}\n\tif(ubPortFlags & MOUSE_PORT_2) {\n\t\tuwPotMask |= BV(15) | BV(14) | BV(13) | BV(12);\n\t}\n\tg_pCustom->potgo = (g_pCustom->potinp & (0xFFFF ^ uwPotMask)) | uwPotMask;\n\n\t// Amiga Hardware Reference Manual suggests that pos should be polled every\n\t// vblank, so there could be some interrupt init.\n#endif // AMIGA\n\n\tif(ubPortFlags & MOUSE_PORT_1) {\n\t\tmouseSetBounds(MOUSE_PORT_1, 0, 0, SCREEN_PAL_WIDTH - 1, SCREEN_PAL_HEIGHT - 1);\n\t\tmouseResetPos(MOUSE_PORT_1);\n\t}\n\tif(ubPortFlags & MOUSE_PORT_2) {\n\t\tmouseSetBounds(MOUSE_PORT_2, 0, 0, SCREEN_PAL_WIDTH - 1, SCREEN_PAL_HEIGHT - 1);\n\t\tmouseResetPos(MOUSE_PORT_2);\n\t}\n}\n\nvoid mouseDestroy(void) {\n#ifdef AMIGA\n\t// Should mouse manager be interrupt driven, interrupt handler deletion will\n\t// be here.\n\tg_pCustom->potgo = g_sMouseManager.uwPrevPotGo;\n#endif // AMIGA\n}\n\nstatic void mouseProcessPort(\n\tUBYTE ubPort, UWORD uwPosReg,\n\tUBYTE ubStateLmb, UBYTE ubStateRmb, UBYTE ubStateMmb\n) {\n\t// Deltas are signed bytes even though underflows and overflows may occur.\n\t// It is expected behavior since it is encouraged in Amiga HRM as means to\n\t// determine mouse movement direction which takes into account joyxdat\n\t// underflows and overflows.\n\n\tUBYTE ubPosX = uwPosReg & 0xFF;\n\tUBYTE ubPosY = uwPosReg >> 8;\n\n\tBYTE bDx = ubPosX - g_sMouseManager.pMice[ubPort].ubPrevHwX;\n\tBYTE bDy = ubPosY - g_sMouseManager.pMice[ubPort].ubPrevHwY;\n\tmouseMoveBy(ubPort, bDx, bDy);\n\n\tg_sMouseManager.pMice[ubPort].ubPrevHwX = ubPosX;\n\tg_sMouseManager.pMice[ubPort].ubPrevHwY = ubPosY;\n\n\t// Left button state\n\tif(ubStateLmb) {\n\t\tmouseSetButton(ubPort, MOUSE_LMB, MOUSE_NACTIVE);\n\t}\n\telse if(!mouseCheck(ubPort, MOUSE_LMB)) {\n\t\tmouseSetButton(ubPort, MOUSE_LMB, MOUSE_ACTIVE);\n\t}\n\n\t// Right button state\n\tif(ubStateRmb) {\n\t\tmouseSetButton(ubPort, MOUSE_RMB, MOUSE_NACTIVE);\n\t}\n\telse if(!mouseCheck(ubPort, MOUSE_RMB)) {\n\t\tmouseSetButton(ubPort, MOUSE_RMB, MOUSE_ACTIVE);\n\t}\n\n\t// Middle button state\n\tif(ubStateMmb) {\n\t\tmouseSetButton(ubPort, MOUSE_MMB, MOUSE_NACTIVE);\n\t}\n\telse if(!mouseCheck(ubPort, MOUSE_MMB)) {\n\t\tmouseSetButton(ubPort, MOUSE_MMB, MOUSE_ACTIVE);\n\t}\n}\n\nvoid mouseProcess(void) {\n\t// Even if whole Amiga process will be moved to vbl interrupt, other platforms\n\t// will prob'ly use this fn anyway\n#ifdef AMIGA\n\n\tif(g_sMouseManager.ubPortFlags & MOUSE_PORT_1) {\n\t\tmouseProcessPort(\n\t\t\tMOUSE_PORT_1, g_pCustom->joy0dat,\n\t\t\tBTST(g_pCia[CIA_A]->pra, 6), BTST(g_pCustom->potinp, 10), BTST(g_pCustom->potinp, 8)\n\t\t);\n\t}\n\tif(g_sMouseManager.ubPortFlags & MOUSE_PORT_2) {\n\t\tmouseProcessPort(\n\t\t\tMOUSE_PORT_2, g_pCustom->joy1dat,\n\t\t\tBTST(g_pCia[CIA_A]->pra, 7), BTST(g_pCustom->potinp, 14), BTST(g_pCustom->potinp, 12)\n\t\t);\n\t}\n\n#endif // AMIGA\n}\n"
  },
  {
    "path": "src/ace/managers/ptplayer.c",
    "content": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at http://mozilla.org/MPL/2.0/. */\n\n// Info regarding MOD file format:\n// - https://www.fileformat.info/format/mod/corion.htm\n// - http://lclevy.free.fr/mo3/mod.txt\n// - https://www.stef.be/bassoontracker/docs/ProtrackerCommandReference.pdf\n// - http://coppershade.org/articles/More!/Topics/Protracker_Tempo\n// - http://coppershade.org/articles/More!/Topics/Protracker_File_Format/\n\n#include <ace/managers/ptplayer.h>\n#include <ace/managers/log.h>\n#include <ace/managers/system.h>\n#include <ace/utils/custom.h>\n#include <ace/utils/disk_file.h>\n#include <hardware/intbits.h>\n#include <hardware/dmabits.h>\n\n//----------------------------------------------------------------------- CONFIG\n\n// If set, uses VBL interrupt for processing playback, otherwise uses CIA timer.\n// Buggy!\n// #define PTPLAYER_USE_VBL\n\n// If set, interrupts are as short as possible, rest is done\n// in ptplayerProcess(). Buggy!\n// #define PTPLAYER_DEFER_INTERRUPTS\n\n// If set, uses audio interrupt handlers instead of polling intbits for checking\n// if channel is idle. May be better in the long run for os-friendly use. Buggy!\n// #define PTPLAYER_USE_AUDIO_INT_HANDLERS\n\n// TODO: ENABLE_SAWRECT from ptplayer 6.1?\n// TODO: MINIMAL from ptplayer?\n// TODO: VBL-friendly changes from ptplayer 6.2\n\n//---------------------------------------------------------------------- DEFINES\n\n#define PTPLAYER_SUPPORTED_SAMPLEPACK_VERSION 2\n\n/**\n * @brief Minimum safe CIA timer ticks count after which Paula channel regs can\n * be set for next sample.\n *\n * A raster line has a DMA slot for each audio channel. Depending on the current\n * AUDxPER of the audio channel some of these DMA slots are not used.\n * For example: when playing a very high frequency the DMA might have to read\n * a new sample every line. But when playing a very low frequency there might be\n * 10 or more raster lines without DMA activity for this channel.\n *\n * The problem is that changes like DMA-on/off, or setting a new sample-pointer\n * in AUDxLC, are only recognized by Paula when the next sample data are read\n * from Chip-RAM.\n *\n * So we have to be prepared for the worst case, which means that\n * up to 11 raster lines may pass without DMA-activity (reading a new sample),\n * when playing the lowest note from the lowest Protracker octave.\n */\n#define TIMERB_TICKS (576)\n\n// Patterns - each has 64 rows, each row has 4 notes, each note has 4 bytes.\n#define MOD_ROWS_IN_PATTERN 64\n#define MOD_NOTES_PER_ROW 4\n#define MOD_BYTES_PER_NOTE 4\n// Length of single pattern.\n#define MOD_PATTERN_BYTE_SIZE (MOD_ROWS_IN_PATTERN * MOD_NOTES_PER_ROW * MOD_BYTES_PER_NOTE)\n\n// Size of period table.\n#define MOD_PERIOD_TABLE_LENGTH 36\n\n/**\n * @brief Delay in CIA-ticks, which guarantees that at least one Audio-DMA\n * took place, even with the lowest periods.\n * 496 should be the correct value. But there are some A1200 which\n * need at least 550.\n */\n#define DMA_DELAY 576\n\n#define SFX_PRIORITY_LOOPED 0xFF\n\n//------------------------------------------------------------------------ TYPES\n\ntypedef struct AudChannel tChannelRegs;\n\n/**\n * Each pattern line consists of following data for each channel.\n */\ntypedef struct _tModVoice {\n\tunion {\n\t\tstruct {\n\t\t\tUWORD uwNote; // [instrumentHi:4] [period:12]\n\t\t\tunion {\n\t\t\t\tstruct {\n\t\t\t\t\tUBYTE ubCmdHi; // [instrumentLo:4] [cmdNo:4]\n\t\t\t\t\tUBYTE ubCmdLo; // [cmdArg:8] - special effects data\n\t\t\t\t};\n\t\t\t\tUWORD uwCmd; // [instrumentLo:4] [cmdNo:4] [cmdArg:8]\n\t\t\t};\n\t\t};\n\t\tULONG ulData; // All voice data for quick copy / comparison\n\t};\n} tModVoice;\n\ntypedef struct _tChannelStatus {\n\ttModVoice sVoice;\n\n\t/**\n\t * @brief Pointer to start of sample.\n\t */\n\tUWORD *n_start;\n\n\tUWORD *n_loopstart;\n\tUWORD n_length;\n\tUWORD n_replen;\n\tUWORD uwPeriod;\n\n\t/**\n\t * @brief Volume for channel (0..64)\n\t */\n\tUWORD uwVolume;\n\n\t/**\n\t * @brief Currently used period table - for arpeggio / fine-tune.\n\t */\n\tconst UWORD *pPeriodTable;\n\n\tUWORD uwDmaFlag; ///< Set with DMAF_AUDx\n\tUWORD n_noteoff; ///< TODO Later: convert it from byte offs to word offs (div by 2)\n\tUWORD n_toneportspeed;\n\tUWORD n_wantedperiod;\n\tUWORD n_pattpos;\n\n\tUWORD uwFunkSpeed;\n\n\tUBYTE *n_wavestart;\n\tUWORD n_reallength;\n#if defined(PTPLAYER_USE_AUDIO_INT_HANDLERS)\n\t/**\n\t * @brief Channel index.\n\t *\n\t * Original ptplayer name: n_index.\n\t */\n\tUBYTE ubChannelIndex;\n\n\tvolatile UBYTE *pDoneBit;\n#endif\n\n\t/**\n\t * @brief Pending sfx length. Set by player to 0 after registers are set\n\t * to play it.\n\t */\n\tUWORD uwSfxWordLength;\n\n\tUWORD *n_sfxptr;\n\tUWORD uwSfxPeriod;\n\n\t/**\n\t * @brief Volume for sample (0..64)\n\t */\n\tUWORD uwSfxVolume;\n\n\t/**\n\t * @brief Set to 1 if sample has repeat offset/length which is other value\n\t * than sample start / sample length - prevents from using channel for sfx\n\t * after first sample play.\n\t */\n\tUBYTE isLooped;\n\n\t/**\n\t * @brief Set to 1 to indicate that finetune value is negative.\n\t */\n\tUBYTE n_minusft;\n\n\tUBYTE n_vibratoamp;\n\tUBYTE n_vibratospd;\n\tUBYTE n_vibratopos;\n\tUBYTE n_vibratoctrl;\n\tUBYTE n_tremoloamp;\n\tUBYTE n_tremolospd;\n\tUBYTE n_tremolopos;\n\tUBYTE n_tremoloctrl;\n\tUBYTE n_gliss;\n\tUBYTE n_sampleoffset;\n\tBYTE n_loopcount;\n\tBYTE n_funkoffset;\n\tUBYTE n_retrigcount;\n\n\t/**\n\t * Priority of currently played SFX, MOD samples use 0. Cleared after sfx\n\t * has fully played back.\n\t */\n\tvolatile UBYTE ubSfxPriority;\n\n\tUBYTE n_freecnt;\n\n\t/**\n\t * @brief Set to non-zero if channel can only be used for music playback, zero = sfx+music.\n\t */\n\tUBYTE isOnlyForMusic;\n\n\t/**\n\t * @brief If enabled for ptplayer playback, set to 0xFF, otherwise set to 0.\n\t */\n\tUBYTE isEnabledForPlayer;\n} tChannelStatus;\n\ntypedef void (*tVoidFn)(void);\ntypedef void (*tFx)(\n\tUBYTE ubArgs, tChannelStatus *pChannelData,\n\tvolatile tChannelRegs *pChannelReg\n);\n\n/**\n * @brief E Command callback.\n *\n * @param ubArg - E command parameter, set to 0..F.\n */\ntypedef void (*tEFn)(\n\tUBYTE ubArg, tChannelStatus *pChannelData,\n\tvolatile tChannelRegs *pChannelReg\n);\n\ntypedef void (*tPreFx)(\n\tUWORD uwCmd, UWORD uwCmdArg, UWORD uwMaskedCmdE, const tModVoice *pVoice,\n\ttChannelStatus *pChannelData, volatile tChannelRegs *pChannelReg\n);\n\ntypedef union _tChannelDone {\n\tstruct {\n\t\tUBYTE pChannels[4]; ///< Used for getting/setting each channel separately.\n\t};\n\tULONG ulChannelMask; ///< Handy for query if any channel is active or clearing.\n} tChannelDone;\n\n//----------------------------------------------------------------- PRIVATE VARS\n\n/**\n * @brief Period tables for each finetune value.\n * Each period table consists of periods for notes:\n * C-1, C#1, D-1, D#1, E-1, F-1, F#1, G-1, G#1, A-1, A#1, B-1,\n * C-2, C#2, D-2, D#2, E-2, F-2, F#2, G-2, G#2, A-2, A#2, B-2,\n * C-3, C#3, D-3, D#3, E-3, F-3, F#3, G-3, G#3, A-3, A#3, B-3\n */\nstatic const UWORD mt_PeriodTables[][MOD_PERIOD_TABLE_LENGTH] = {\n\t{\n\t\t856, 808, 762, 720, 678, 640, 604, 570, 538, 508, 480, 453,\n\t\t428, 404, 381, 360, 339, 320, 302, 285, 269, 254, 240, 226,\n\t\t214, 202, 190, 180, 170, 160, 151, 143, 135, 127, 120, 113\n\t},\n\t{\n\t\t850, 802, 757, 715, 674, 637, 601, 567, 535, 505, 477, 450,\n\t\t425, 401, 379, 357, 337, 318, 300, 284, 268, 253, 239, 225,\n\t\t213, 201, 189, 179, 169, 159, 150, 142, 134, 126, 119, 113\n\t},\n\t{\n\t\t844, 796, 752, 709, 670, 632, 597, 563, 532, 502, 474, 447,\n\t\t422, 398, 376, 355, 335, 316, 298, 282, 266, 251, 237, 224,\n\t\t211, 199, 188, 177, 167, 158, 149, 141, 133, 125, 118, 112\n\t},\n\t{\n\t\t838, 791, 746, 704, 665, 628, 592, 559, 528, 498, 470, 444,\n\t\t419, 395, 373, 352, 332, 314, 296, 280, 264, 249, 235, 222,\n\t\t209, 198, 187, 176, 166, 157, 148, 140, 132, 125, 118, 111\n\t},\n\t{\n\t\t832, 785, 741, 699, 660, 623, 588, 555, 524, 495, 467, 441,\n\t\t416, 392, 370, 350, 330, 312, 294, 278, 262, 247, 233, 220,\n\t\t208, 196, 185, 175, 165, 156, 147, 139, 131, 124, 117, 110\n\t},\n\t{\n\t\t826, 779, 736, 694, 655, 619, 584, 551, 520, 491, 463, 437,\n\t\t413, 390, 368, 347, 328, 309, 292, 276, 260, 245, 232, 219,\n\t\t206, 195, 184, 174, 164, 155, 146, 138, 130, 123, 116, 109\n\t},\n\t{\n\t\t820, 774, 730, 689, 651, 614, 580, 547, 516, 487, 460, 434,\n\t\t410, 387, 365, 345, 325, 307, 290, 274, 258, 244, 230, 217,\n\t\t205, 193, 183, 172, 163, 154, 145, 137, 129, 122, 115, 109\n\t},\n\t{\n\t\t814, 768, 725, 684, 646, 610, 575, 543, 513, 484, 457, 431,\n\t\t407, 384, 363, 342, 323, 305, 288, 272, 256, 242, 228, 216,\n\t\t204, 192, 181, 171, 161, 152, 144, 136, 128, 121, 114, 108\n\t},\n\t{\n\t\t907, 856, 808, 762, 720, 678, 640, 604, 570, 538, 508, 480,\n\t\t453, 428, 404, 381, 360, 339, 320, 302, 285, 269, 254, 240,\n\t\t226, 214, 202, 190, 180, 170, 160, 151, 143, 135, 127, 120\n\t},\n\t{\n\t\t900, 850, 802, 757, 715, 675, 636, 601, 567, 535, 505, 477,\n\t\t450, 425, 401, 379, 357, 337, 318, 300, 284, 268, 253, 238,\n\t\t225, 212, 200, 189, 179, 169, 159, 150, 142, 134, 126, 119\n\t},\n\t{\n\t\t894, 844, 796, 752, 709, 670, 632, 597, 563, 532, 502, 474,\n\t\t447, 422, 398, 376, 355, 335, 316, 298, 282, 266, 251, 237,\n\t\t223, 211, 199, 188, 177, 167, 158, 149, 141, 133, 125, 118\n\t},\n\t{\n\t\t887, 838, 791, 746, 704, 665, 628, 592, 559, 528, 498, 470,\n\t\t444, 419, 395, 373, 352, 332, 314, 296, 280, 264, 249, 235,\n\t\t222, 209, 198, 187, 176, 166, 157, 148, 140, 132, 125, 118\n\t},\n\t{\n\t\t881, 832, 785, 741, 699, 660, 623, 588, 555, 524, 494, 467,\n\t\t441, 416, 392, 370, 350, 330, 312, 294, 278, 262, 247, 233,\n\t\t220, 208, 196, 185, 175, 165, 156, 147, 139, 131, 123, 117\n\t},\n\t{\n\t\t875, 826, 779, 736, 694, 655, 619, 584, 551, 520, 491, 463,\n\t\t437, 413, 390, 368, 347, 328, 309, 292, 276, 260, 245, 232,\n\t\t219, 206, 195, 184, 174, 164, 155, 146, 138, 130, 123, 116\n\t},\n\t{\n\t\t868, 820, 774, 730, 689, 651, 614, 580, 547, 516, 487, 460,\n\t\t434, 410, 387, 365, 345, 325, 307, 290, 274, 258, 244, 230,\n\t\t217, 205, 193, 183, 172, 163, 154, 145, 137, 129, 122, 115\n\t},\n\t{\n\t\t862, 814, 768, 725, 684, 646, 610, 575, 543, 513, 484, 457,\n\t\t431, 407, 384, 363, 342, 323, 305, 288, 272, 256, 242, 228,\n\t\t216, 203, 192, 181, 171, 161, 152, 144, 136, 128, 121, 114\n\t}\n};\n\nstatic const UBYTE MasterVolTab[][65] = {\n\t{\n\t\t0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n\t\t0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n\t\t0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n\t\t0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n\t\t0\n\t}, {\n\t\t0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n\t\t0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n\t\t0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n\t\t0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n\t\t1\n\t}, {\n\t\t0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n\t\t0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n\t\t1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,\n\t\t1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,\n\t\t2\n\t}, {\n\t\t0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n\t\t0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,\n\t\t1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,\n\t\t2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,\n\t\t3\n\t}, {\n\t\t0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n\t\t1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,\n\t\t2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,\n\t\t3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,\n\t\t4\n\t}, {\n\t\t0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,\n\t\t1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,\n\t\t2,2,2,2,2,2,2,3,3,3,3,3,3,3,3,3,\n\t\t3,3,3,3,4,4,4,4,4,4,4,4,4,4,4,4,\n\t\t5\n\t}, {\n\t\t0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,\n\t\t1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,\n\t\t3,3,3,3,3,3,3,3,3,3,3,4,4,4,4,4,\n\t\t4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,\n\t\t6\n\t}, {\n\t\t0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,\n\t\t1,1,1,2,2,2,2,2,2,2,2,2,3,3,3,3,\n\t\t3,3,3,3,3,4,4,4,4,4,4,4,4,4,5,5,\n\t\t5,5,5,5,5,5,5,6,6,6,6,6,6,6,6,6,\n\t\t7\n\t}, {\n\t\t0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,\n\t\t2,2,2,2,2,2,2,2,3,3,3,3,3,3,3,3,\n\t\t4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,\n\t\t6,6,6,6,6,6,6,6,7,7,7,7,7,7,7,7,\n\t\t8\n\t}, {\n\t\t0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,2,\n\t\t2,2,2,2,2,2,3,3,3,3,3,3,3,4,4,4,\n\t\t4,4,4,4,5,5,5,5,5,5,5,6,6,6,6,6,\n\t\t6,6,7,7,7,7,7,7,7,8,8,8,8,8,8,8,\n\t\t9\n\t}, {\n\t\t0,0,0,0,0,0,0,1,1,1,1,1,1,2,2,2,\n\t\t2,2,2,2,3,3,3,3,3,3,4,4,4,4,4,4,\n\t\t5,5,5,5,5,5,5,6,6,6,6,6,6,7,7,7,\n\t\t7,7,7,7,8,8,8,8,8,8,9,9,9,9,9,9,\n\t\t10\n\t}, {\n\t\t0,0,0,0,0,0,1,1,1,1,1,1,2,2,2,2,\n\t\t2,2,3,3,3,3,3,3,4,4,4,4,4,4,5,5,\n\t\t5,5,5,6,6,6,6,6,6,7,7,7,7,7,7,8,\n\t\t8,8,8,8,8,9,9,9,9,9,9,10,10,10,10,10,\n\t\t11\n\t}, {\n\t\t0,0,0,0,0,0,1,1,1,1,1,2,2,2,2,2,\n\t\t3,3,3,3,3,3,4,4,4,4,4,5,5,5,5,5,\n\t\t6,6,6,6,6,6,7,7,7,7,7,8,8,8,8,8,\n\t\t9,9,9,9,9,9,10,10,10,10,10,11,11,11,11,11,\n\t\t12\n\t}, {\n\t\t0,0,0,0,0,1,1,1,1,1,2,2,2,2,2,3,\n\t\t3,3,3,3,4,4,4,4,4,5,5,5,5,5,6,6,\n\t\t6,6,6,7,7,7,7,7,8,8,8,8,8,9,9,9,\n\t\t9,9,10,10,10,10,10,11,11,11,11,11,12,12,12,12,\n\t\t13\n\t}, {\n\t\t0,0,0,0,0,1,1,1,1,1,2,2,2,2,3,3,\n\t\t3,3,3,4,4,4,4,5,5,5,5,5,6,6,6,6,\n\t\t7,7,7,7,7,8,8,8,8,8,9,9,9,9,10,10,\n\t\t10,10,10,11,11,11,11,12,12,12,12,12,13,13,13,13,\n\t\t14\n\t}, {\n\t\t0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,\n\t\t3,3,4,4,4,4,5,5,5,5,6,6,6,6,7,7,\n\t\t7,7,7,8,8,8,8,9,9,9,9,10,10,10,10,11,\n\t\t11,11,11,11,12,12,12,12,13,13,13,13,14,14,14,14,\n\t\t15\n\t}, {\n\t\t0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,\n\t\t4,4,4,4,5,5,5,5,6,6,6,6,7,7,7,7,\n\t\t8,8,8,8,9,9,9,9,10,10,10,10,11,11,11,11,\n\t\t12,12,12,12,13,13,13,13,14,14,14,14,15,15,15,15,\n\t\t16\n\t}, {\n\t\t0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,\n\t\t4,4,4,5,5,5,5,6,6,6,6,7,7,7,7,8,\n\t\t8,8,9,9,9,9,10,10,10,10,11,11,11,11,12,12,\n\t\t12,13,13,13,13,14,14,14,14,15,15,15,15,16,16,16,\n\t\t17\n\t}, {\n\t\t0,0,0,0,1,1,1,1,2,2,2,3,3,3,3,4,\n\t\t4,4,5,5,5,5,6,6,6,7,7,7,7,8,8,8,\n\t\t9,9,9,9,10,10,10,10,11,11,11,12,12,12,12,13,\n\t\t13,13,14,14,14,14,15,15,15,16,16,16,16,17,17,17,\n\t\t18\n\t}, {\n\t\t0,0,0,0,1,1,1,2,2,2,2,3,3,3,4,4,\n\t\t4,5,5,5,5,6,6,6,7,7,7,8,8,8,8,9,\n\t\t9,9,10,10,10,10,11,11,11,12,12,12,13,13,13,13,\n\t\t14,14,14,15,15,15,16,16,16,16,17,17,17,18,18,18,\n\t\t19\n\t}, {\n\t\t0,0,0,0,1,1,1,2,2,2,3,3,3,4,4,4,\n\t\t5,5,5,5,6,6,6,7,7,7,8,8,8,9,9,9,\n\t\t10,10,10,10,11,11,11,12,12,12,13,13,13,14,14,14,\n\t\t15,15,15,15,16,16,16,17,17,17,18,18,18,19,19,19,\n\t\t20\n\t}, {\n\t\t0,0,0,0,1,1,1,2,2,2,3,3,3,4,4,4,\n\t\t5,5,5,6,6,6,7,7,7,8,8,8,9,9,9,10,\n\t\t10,10,11,11,11,12,12,12,13,13,13,14,14,14,15,15,\n\t\t15,16,16,16,17,17,17,18,18,18,19,19,19,20,20,20,\n\t\t21\n\t}, {\n\t\t0,0,0,1,1,1,2,2,2,3,3,3,4,4,4,5,\n\t\t5,5,6,6,6,7,7,7,8,8,8,9,9,9,10,10,\n\t\t11,11,11,12,12,12,13,13,13,14,14,14,15,15,15,16,\n\t\t16,16,17,17,17,18,18,18,19,19,19,20,20,20,21,21,\n\t\t22\n\t}, {\n\t\t0,0,0,1,1,1,2,2,2,3,3,3,4,4,5,5,\n\t\t5,6,6,6,7,7,7,8,8,8,9,9,10,10,10,11,\n\t\t11,11,12,12,12,13,13,14,14,14,15,15,15,16,16,16,\n\t\t17,17,17,18,18,19,19,19,20,20,20,21,21,21,22,22,\n\t\t23\n\t}, {\n\t\t0,0,0,1,1,1,2,2,3,3,3,4,4,4,5,5,\n\t\t6,6,6,7,7,7,8,8,9,9,9,10,10,10,11,11,\n\t\t12,12,12,13,13,13,14,14,15,15,15,16,16,16,17,17,\n\t\t18,18,18,19,19,19,20,20,21,21,21,22,22,22,23,23,\n\t\t24\n\t}, {\n\t\t0,0,0,1,1,1,2,2,3,3,3,4,4,5,5,5,\n\t\t6,6,7,7,7,8,8,8,9,9,10,10,10,11,11,12,\n\t\t12,12,13,13,14,14,14,15,15,16,16,16,17,17,17,18,\n\t\t18,19,19,19,20,20,21,21,21,22,22,23,23,23,24,24,\n\t\t25\n\t}, {\n\t\t0,0,0,1,1,2,2,2,3,3,4,4,4,5,5,6,\n\t\t6,6,7,7,8,8,8,9,9,10,10,10,11,11,12,12,\n\t\t13,13,13,14,14,15,15,15,16,16,17,17,17,18,18,19,\n\t\t19,19,20,20,21,21,21,22,22,23,23,23,24,24,25,25,\n\t\t26\n\t}, {\n\t\t0,0,0,1,1,2,2,2,3,3,4,4,5,5,5,6,\n\t\t6,7,7,8,8,8,9,9,10,10,10,11,11,12,12,13,\n\t\t13,13,14,14,15,15,16,16,16,17,17,18,18,18,19,19,\n\t\t20,20,21,21,21,22,22,23,23,24,24,24,25,25,26,26,\n\t\t27\n\t}, {\n\t\t0,0,0,1,1,2,2,3,3,3,4,4,5,5,6,6,\n\t\t7,7,7,8,8,9,9,10,10,10,11,11,12,12,13,13,\n\t\t14,14,14,15,15,16,16,17,17,17,18,18,19,19,20,20,\n\t\t21,21,21,22,22,23,23,24,24,24,25,25,26,26,27,27,\n\t\t28\n\t}, {\n\t\t0,0,0,1,1,2,2,3,3,4,4,4,5,5,6,6,\n\t\t7,7,8,8,9,9,9,10,10,11,11,12,12,13,13,14,\n\t\t14,14,15,15,16,16,17,17,18,18,19,19,19,20,20,21,\n\t\t21,22,22,23,23,24,24,24,25,25,26,26,27,27,28,28,\n\t\t29\n\t}, {\n\t\t0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,\n\t\t7,7,8,8,9,9,10,10,11,11,12,12,13,13,14,14,\n\t\t15,15,15,16,16,17,17,18,18,19,19,20,20,21,21,22,\n\t\t22,22,23,23,24,24,25,25,26,26,27,27,28,28,29,29,\n\t\t30\n\t}, {\n\t\t0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,\n\t\t7,8,8,9,9,10,10,11,11,12,12,13,13,14,14,15,\n\t\t15,15,16,16,17,17,18,18,19,19,20,20,21,21,22,22,\n\t\t23,23,24,24,25,25,26,26,27,27,28,28,29,29,30,30,\n\t\t31\n\t}, {\n\t\t0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,\n\t\t8,8,9,9,10,10,11,11,12,12,13,13,14,14,15,15,\n\t\t16,16,17,17,18,18,19,19,20,20,21,21,22,22,23,23,\n\t\t24,24,25,25,26,26,27,27,28,28,29,29,30,30,31,31,\n\t\t32\n\t}, {\n\t\t0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,\n\t\t8,8,9,9,10,10,11,11,12,12,13,13,14,14,15,15,\n\t\t16,17,17,18,18,19,19,20,20,21,21,22,22,23,23,24,\n\t\t24,25,25,26,26,27,27,28,28,29,29,30,30,31,31,32,\n\t\t33\n\t}, {\n\t\t0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,\n\t\t8,9,9,10,10,11,11,12,12,13,13,14,14,15,15,16,\n\t\t17,17,18,18,19,19,20,20,21,21,22,22,23,23,24,24,\n\t\t25,26,26,27,27,28,28,29,29,30,30,31,31,32,32,33,\n\t\t34\n\t}, {\n\t\t0,0,1,1,2,2,3,3,4,4,5,6,6,7,7,8,\n\t\t8,9,9,10,10,11,12,12,13,13,14,14,15,15,16,16,\n\t\t17,18,18,19,19,20,20,21,21,22,22,23,24,24,25,25,\n\t\t26,26,27,27,28,28,29,30,30,31,31,32,32,33,33,34,\n\t\t35\n\t}, {\n\t\t0,0,1,1,2,2,3,3,4,5,5,6,6,7,7,8,\n\t\t9,9,10,10,11,11,12,12,13,14,14,15,15,16,16,17,\n\t\t18,18,19,19,20,20,21,21,22,23,23,24,24,25,25,26,\n\t\t27,27,28,28,29,29,30,30,31,32,32,33,33,34,34,35,\n\t\t36\n\t}, {\n\t\t0,0,1,1,2,2,3,4,4,5,5,6,6,7,8,8,\n\t\t9,9,10,10,11,12,12,13,13,14,15,15,16,16,17,17,\n\t\t18,19,19,20,20,21,21,22,23,23,24,24,25,26,26,27,\n\t\t27,28,28,29,30,30,31,31,32,32,33,34,34,35,35,36,\n\t\t37\n\t}, {\n\t\t0,0,1,1,2,2,3,4,4,5,5,6,7,7,8,8,\n\t\t9,10,10,11,11,12,13,13,14,14,15,16,16,17,17,18,\n\t\t19,19,20,20,21,21,22,23,23,24,24,25,26,26,27,27,\n\t\t28,29,29,30,30,31,32,32,33,33,34,35,35,36,36,37,\n\t\t38\n\t}, {\n\t\t0,0,1,1,2,3,3,4,4,5,6,6,7,7,8,9,\n\t\t9,10,10,11,12,12,13,14,14,15,15,16,17,17,18,18,\n\t\t19,20,20,21,21,22,23,23,24,24,25,26,26,27,28,28,\n\t\t29,29,30,31,31,32,32,33,34,34,35,35,36,37,37,38,\n\t\t39\n\t}, {\n\t\t0,0,1,1,2,3,3,4,5,5,6,6,7,8,8,9,\n\t\t10,10,11,11,12,13,13,14,15,15,16,16,17,18,18,19,\n\t\t20,20,21,21,22,23,23,24,25,25,26,26,27,28,28,29,\n\t\t30,30,31,31,32,33,33,34,35,35,36,36,37,38,38,39,\n\t\t40\n\t}, {\n\t\t0,0,1,1,2,3,3,4,5,5,6,7,7,8,8,9,\n\t\t10,10,11,12,12,13,14,14,15,16,16,17,17,18,19,19,\n\t\t20,21,21,22,23,23,24,24,25,26,26,27,28,28,29,30,\n\t\t30,31,32,32,33,33,34,35,35,36,37,37,38,39,39,40,\n\t\t41\n\t}, {\n\t\t0,0,1,1,2,3,3,4,5,5,6,7,7,8,9,9,\n\t\t10,11,11,12,13,13,14,15,15,16,17,17,18,19,19,20,\n\t\t21,21,22,22,23,24,24,25,26,26,27,28,28,29,30,30,\n\t\t31,32,32,33,34,34,35,36,36,37,38,38,39,40,40,41,\n\t\t42\n\t}, {\n\t\t0,0,1,2,2,3,4,4,5,6,6,7,8,8,9,10,\n\t\t10,11,12,12,13,14,14,15,16,16,17,18,18,19,20,20,\n\t\t21,22,22,23,24,24,25,26,26,27,28,28,29,30,30,31,\n\t\t32,32,33,34,34,35,36,36,37,38,38,39,40,40,41,42,\n\t\t43\n\t}, {\n\t\t0,0,1,2,2,3,4,4,5,6,6,7,8,8,9,10,\n\t\t11,11,12,13,13,14,15,15,16,17,17,18,19,19,20,21,\n\t\t22,22,23,24,24,25,26,26,27,28,28,29,30,30,31,32,\n\t\t33,33,34,35,35,36,37,37,38,39,39,40,41,41,42,43,\n\t\t44\n\t}, {\n\t\t0,0,1,2,2,3,4,4,5,6,7,7,8,9,9,10,\n\t\t11,11,12,13,14,14,15,16,16,17,18,18,19,20,21,21,\n\t\t22,23,23,24,25,26,26,27,28,28,29,30,30,31,32,33,\n\t\t33,34,35,35,36,37,37,38,39,40,40,41,42,42,43,44,\n\t\t45\n\t}, {\n\t\t0,0,1,2,2,3,4,5,5,6,7,7,8,9,10,10,\n\t\t11,12,12,13,14,15,15,16,17,17,18,19,20,20,21,22,\n\t\t23,23,24,25,25,26,27,28,28,29,30,30,31,32,33,33,\n\t\t34,35,35,36,37,38,38,39,40,40,41,42,43,43,44,45,\n\t\t46\n\t}, {\n\t\t0,0,1,2,2,3,4,5,5,6,7,8,8,9,10,11,\n\t\t11,12,13,13,14,15,16,16,17,18,19,19,20,21,22,22,\n\t\t23,24,24,25,26,27,27,28,29,30,30,31,32,33,33,34,\n\t\t35,35,36,37,38,38,39,40,41,41,42,43,44,44,45,46,\n\t\t47\n\t}, {\n\t\t0,0,1,2,3,3,4,5,6,6,7,8,9,9,10,11,\n\t\t12,12,13,14,15,15,16,17,18,18,19,20,21,21,22,23,\n\t\t24,24,25,26,27,27,28,29,30,30,31,32,33,33,34,35,\n\t\t36,36,37,38,39,39,40,41,42,42,43,44,45,45,46,47,\n\t\t48\n\t}, {\n\t\t0,0,1,2,3,3,4,5,6,6,7,8,9,9,10,11,\n\t\t12,13,13,14,15,16,16,17,18,19,19,20,21,22,22,23,\n\t\t24,25,26,26,27,28,29,29,30,31,32,32,33,34,35,35,\n\t\t36,37,38,39,39,40,41,42,42,43,44,45,45,46,47,48,\n\t\t49\n\t}, {\n\t\t0,0,1,2,3,3,4,5,6,7,7,8,9,10,10,11,\n\t\t12,13,14,14,15,16,17,17,18,19,20,21,21,22,23,24,\n\t\t25,25,26,27,28,28,29,30,31,32,32,33,34,35,35,36,\n\t\t37,38,39,39,40,41,42,42,43,44,45,46,46,47,48,49,\n\t\t50\n\t}, {\n\t\t0,0,1,2,3,3,4,5,6,7,7,8,9,10,11,11,\n\t\t12,13,14,15,15,16,17,18,19,19,20,21,22,23,23,24,\n\t\t25,26,27,27,28,29,30,31,31,32,33,34,35,35,36,37,\n\t\t38,39,39,40,41,42,43,43,44,45,46,47,47,48,49,50,\n\t\t51\n\t}, {\n\t\t0,0,1,2,3,4,4,5,6,7,8,8,9,10,11,12,\n\t\t13,13,14,15,16,17,17,18,19,20,21,21,22,23,24,25,\n\t\t26,26,27,28,29,30,30,31,32,33,34,34,35,36,37,38,\n\t\t39,39,40,41,42,43,43,44,45,46,47,47,48,49,50,51,\n\t\t52\n\t}, {\n\t\t0,0,1,2,3,4,4,5,6,7,8,9,9,10,11,12,\n\t\t13,14,14,15,16,17,18,19,19,20,21,22,23,24,24,25,\n\t\t26,27,28,28,29,30,31,32,33,33,34,35,36,37,38,38,\n\t\t39,40,41,42,43,43,44,45,46,47,48,48,49,50,51,52,\n\t\t53\n\t}, {\n\t\t0,0,1,2,3,4,5,5,6,7,8,9,10,10,11,12,\n\t\t13,14,15,16,16,17,18,19,20,21,21,22,23,24,25,26,\n\t\t27,27,28,29,30,31,32,32,33,34,35,36,37,37,38,39,\n\t\t40,41,42,43,43,44,45,46,47,48,48,49,50,51,52,53,\n\t\t54\n\t}, {\n\t\t0,0,1,2,3,4,5,6,6,7,8,9,10,11,12,12,\n\t\t13,14,15,16,17,18,18,19,20,21,22,23,24,24,25,26,\n\t\t27,28,29,30,30,31,32,33,34,35,36,36,37,38,39,40,\n\t\t41,42,42,43,44,45,46,47,48,48,49,50,51,52,53,54,\n\t\t55\n\t}, {\n\t\t0,0,1,2,3,4,5,6,7,7,8,9,10,11,12,13,\n\t\t14,14,15,16,17,18,19,20,21,21,22,23,24,25,26,27,\n\t\t28,28,29,30,31,32,33,34,35,35,36,37,38,39,40,41,\n\t\t42,42,43,44,45,46,47,48,49,49,50,51,52,53,54,55,\n\t\t56\n\t}, {\n\t\t0,0,1,2,3,4,5,6,7,8,8,9,10,11,12,13,\n\t\t14,15,16,16,17,18,19,20,21,22,23,24,24,25,26,27,\n\t\t28,29,30,31,32,32,33,34,35,36,37,38,39,40,40,41,\n\t\t42,43,44,45,46,47,48,48,49,50,51,52,53,54,55,56,\n\t\t57\n\t}, {\n\t\t0,0,1,2,3,4,5,6,7,8,9,9,10,11,12,13,\n\t\t14,15,16,17,18,19,19,20,21,22,23,24,25,26,27,28,\n\t\t29,29,30,31,32,33,34,35,36,37,38,38,39,40,41,42,\n\t\t43,44,45,46,47,48,48,49,50,51,52,53,54,55,56,57,\n\t\t58\n\t}, {\n\t\t0,0,1,2,3,4,5,6,7,8,9,10,11,11,12,13,\n\t\t14,15,16,17,18,19,20,21,22,23,23,24,25,26,27,28,\n\t\t29,30,31,32,33,34,35,35,36,37,38,39,40,41,42,43,\n\t\t44,45,46,47,47,48,49,50,51,52,53,54,55,56,57,58,\n\t\t59\n\t}, {\n\t\t0,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,\n\t\t15,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,\n\t\t30,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,\n\t\t45,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,\n\t\t60\n\t}, {\n\t\t0,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,\n\t\t15,16,17,18,19,20,20,21,22,23,24,25,26,27,28,29,\n\t\t30,31,32,33,34,35,36,37,38,39,40,40,41,42,43,44,\n\t\t45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,\n\t\t61\n\t}, {\n\t\t0,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,\n\t\t15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,\n\t\t31,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,\n\t\t46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,\n\t\t62\n\t}, {\n\t\t0,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,\n\t\t15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,\n\t\t31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,\n\t\t47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,\n\t\t63\n\t}, {\n\t\t0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,\n\t\t16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,\n\t\t32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,\n\t\t48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,\n\t\t64\n\t}\n};\n\nstatic const UBYTE mt_FunkTable[] = {\n\t0, 5, 6, 7, 8, 10, 11, 13, 16, 19, 22, 26, 32, 43, 64, 128\n};\n\nstatic const BYTE mt_VibratoSineTable[] = {\n\t0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n\t0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n\t0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n\t0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n\t0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,\n\t1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,\n\t0,0,0,0,0,0,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,\n\t-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,0,0,0,0,0,\n\t0,0,0,1,1,1,2,2,2,3,3,3,3,3,3,3,\n\t3,3,3,3,3,3,3,3,2,2,2,1,1,1,0,0,\n\t0,0,0,-1,-1,-1,-2,-2,-2,-3,-3,-3,-3,-3,-3,-3,\n\t-3,-3,-3,-3,-3,-3,-3,-3,-2,-2,-2,-1,-1,-1,0,0,\n\t0,0,1,1,2,2,3,3,4,4,4,5,5,5,5,5,\n\t5,5,5,5,5,5,4,4,4,3,3,2,2,1,1,0,\n\t0,0,-1,-1,-2,-2,-3,-3,-4,-4,-4,-5,-5,-5,-5,-5,\n\t-5,-5,-5,-5,-5,-5,-4,-4,-4,-3,-3,-2,-2,-1,-1,0,\n\t0,0,1,2,3,3,4,5,5,6,6,7,7,7,7,7,\n\t7,7,7,7,7,7,6,6,5,5,4,3,3,2,1,0,\n\t0,0,-1,-2,-3,-3,-4,-5,-5,-6,-6,-7,-7,-7,-7,-7,\n\t-7,-7,-7,-7,-7,-7,-6,-6,-5,-5,-4,-3,-3,-2,-1,0,\n\t0,0,1,2,3,4,5,6,7,7,8,8,9,9,9,9,\n\t9,9,9,9,9,8,8,7,7,6,5,4,3,2,1,0,\n\t0,0,-1,-2,-3,-4,-5,-6,-7,-7,-8,-8,-9,-9,-9,-9,\n\t-9,-9,-9,-9,-9,-8,-8,-7,-7,-6,-5,-4,-3,-2,-1,0,\n\t0,1,2,3,4,5,6,7,8,9,9,10,11,11,11,11,\n\t11,11,11,11,11,10,9,9,8,7,6,5,4,3,2,1,\n\t0,-1,-2,-3,-4,-5,-6,-7,-8,-9,-9,-10,-11,-11,-11,-11,\n\t-11,-11,-11,-11,-11,-10,-9,-9,-8,-7,-6,-5,-4,-3,-2,-1,\n\t0,1,2,4,5,6,7,8,9,10,11,12,12,13,13,13,\n\t13,13,13,13,12,12,11,10,9,8,7,6,5,4,2,1,\n\t0,-1,-2,-4,-5,-6,-7,-8,-9,-10,-11,-12,-12,-13,-13,-13,\n\t-13,-13,-13,-13,-12,-12,-11,-10,-9,-8,-7,-6,-5,-4,-2,-1,\n\t0,1,3,4,6,7,8,10,11,12,13,14,14,15,15,15,\n\t15,15,15,15,14,14,13,12,11,10,8,7,6,4,3,1,\n\t0,-1,-3,-4,-6,-7,-8,-10,-11,-12,-13,-14,-14,-15,-15,-15,\n\t-15,-15,-15,-15,-14,-14,-13,-12,-11,-10,-8,-7,-6,-4,-3,-1,\n\t0,1,3,5,6,8,9,11,12,13,14,15,16,17,17,17,\n\t17,17,17,17,16,15,14,13,12,11,9,8,6,5,3,1,\n\t0,-1,-3,-5,-6,-8,-9,-11,-12,-13,-14,-15,-16,-17,-17,-17,\n\t-17,-17,-17,-17,-16,-15,-14,-13,-12,-11,-9,-8,-6,-5,-3,-1,\n\t0,1,3,5,7,9,11,12,14,15,16,17,18,19,19,19,\n\t19,19,19,19,18,17,16,15,14,12,11,9,7,5,3,1,\n\t0,-1,-3,-5,-7,-9,-11,-12,-14,-15,-16,-17,-18,-19,-19,-19,\n\t-19,-19,-19,-19,-18,-17,-16,-15,-14,-12,-11,-9,-7,-5,-3,-1,\n\t0,2,4,6,8,10,12,13,15,16,18,19,20,20,21,21,\n\t21,21,21,20,20,19,18,16,15,13,12,10,8,6,4,2,\n\t0,-2,-4,-6,-8,-10,-12,-13,-15,-16,-18,-19,-20,-20,-21,-21,\n\t-21,-21,-21,-20,-20,-19,-18,-16,-15,-13,-12,-10,-8,-6,-4,-2,\n\t0,2,4,6,9,11,13,15,16,18,19,21,22,22,23,23,\n\t23,23,23,22,22,21,19,18,16,15,13,11,9,6,4,2,\n\t0,-2,-4,-6,-9,-11,-13,-15,-16,-18,-19,-21,-22,-22,-23,-23,\n\t-23,-23,-23,-22,-22,-21,-19,-18,-16,-15,-13,-11,-9,-6,-4,-2,\n\t0,2,4,7,9,12,14,16,18,20,21,22,23,24,25,25,\n\t25,25,25,24,23,22,21,20,18,16,14,12,9,7,4,2,\n\t0,-2,-4,-7,-9,-12,-14,-16,-18,-20,-21,-22,-23,-24,-25,-25,\n\t-25,-25,-25,-24,-23,-22,-21,-20,-18,-16,-14,-12,-9,-7,-4,-2,\n\t0,2,5,8,10,13,15,17,19,21,23,24,25,26,27,27,\n\t27,27,27,26,25,24,23,21,19,17,15,13,10,8,5,2,\n\t0,-2,-5,-8,-10,-13,-15,-17,-19,-21,-23,-24,-25,-26,-27,-27,\n\t-27,-27,-27,-26,-25,-24,-23,-21,-19,-17,-15,-13,-10,-8,-5,-2,\n\t0,2,5,8,11,14,16,18,21,23,24,26,27,28,29,29,\n\t29,29,29,28,27,26,24,23,21,18,16,14,11,8,5,2,\n\t0,-2,-5,-8,-11,-14,-16,-18,-21,-23,-24,-26,-27,-28,-29,-29,\n\t-29,-29,-29,-28,-27,-26,-24,-23,-21,-18,-16,-14,-11,-8,-5,-2\n};\n\nstatic const BYTE mt_VibratoSawTable[] = {\n\t0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n\t0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n\t0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n\t0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n\t0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n\t1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,\n\t-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,\n\t0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n\t0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,\n\t2,2,2,2,2,2,2,2,3,3,3,3,3,3,3,3,\n\t-3,-3,-3,-3,-3,-3,-3,-3,-2,-2,-2,-2,-2,-2,-2,-2,\n\t-1,-1,-1,-1,-1,-1,-1,-1,0,0,0,0,0,0,0,0,\n\t0,0,0,0,0,0,1,1,1,1,1,2,2,2,2,2,\n\t3,3,3,3,3,3,4,4,4,4,4,5,5,5,5,5,\n\t-5,-5,-5,-5,-5,-5,-4,-4,-4,-4,-4,-3,-3,-3,-3,-3,\n\t-2,-2,-2,-2,-2,-2,-1,-1,-1,-1,-1,0,0,0,0,0,\n\t0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,\n\t4,4,4,4,5,5,5,5,6,6,6,6,7,7,7,7,\n\t-7,-7,-7,-7,-6,-6,-6,-6,-5,-5,-5,-5,-4,-4,-4,-4,\n\t-3,-3,-3,-3,-2,-2,-2,-2,-1,-1,-1,-1,0,0,0,0,\n\t0,0,0,0,1,1,1,2,2,2,3,3,3,4,4,4,\n\t5,5,5,5,6,6,6,7,7,7,8,8,8,9,9,9,\n\t-9,-9,-9,-9,-8,-8,-8,-7,-7,-7,-6,-6,-6,-5,-5,-5,\n\t-4,-4,-4,-4,-3,-3,-3,-2,-2,-2,-1,-1,-1,0,0,0,\n\t0,0,0,1,1,1,2,2,3,3,3,4,4,4,5,5,\n\t6,6,6,7,7,7,8,8,9,9,9,10,10,10,11,11,\n\t-11,-11,-11,-10,-10,-10,-9,-9,-8,-8,-8,-7,-7,-7,-6,-6,\n\t-5,-5,-5,-4,-4,-4,-3,-3,-2,-2,-2,-1,-1,-1,0,0,\n\t0,0,0,1,1,2,2,3,3,3,4,4,5,5,6,6,\n\t7,7,7,8,8,9,9,10,10,10,11,11,12,12,13,13,\n\t-13,-13,-13,-12,-12,-11,-11,-10,-10,-10,-9,-9,-8,-8,-7,-7,\n\t-6,-6,-6,-5,-5,-4,-4,-3,-3,-3,-2,-2,-1,-1,0,0,\n\t0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,\n\t8,8,9,9,10,10,11,11,12,12,13,13,14,14,15,15,\n\t-15,-15,-14,-14,-13,-13,-12,-12,-11,-11,-10,-10,-9,-9,-8,-8,\n\t-7,-7,-6,-6,-5,-5,-4,-4,-3,-3,-2,-2,-1,-1,0,0,\n\t0,0,1,1,2,2,3,3,4,5,5,6,6,7,7,8,\n\t9,9,10,10,11,11,12,12,13,14,14,15,15,16,16,17,\n\t-17,-17,-16,-16,-15,-15,-14,-13,-13,-12,-12,-11,-11,-10,-10,-9,\n\t-8,-8,-7,-7,-6,-6,-5,-4,-4,-3,-3,-2,-2,-1,-1,0,\n\t0,0,1,1,2,3,3,4,5,5,6,6,7,8,8,9,\n\t10,10,11,11,12,13,13,14,15,15,16,16,17,18,18,19,\n\t-19,-19,-18,-18,-17,-16,-16,-15,-14,-14,-13,-13,-12,-11,-11,-10,\n\t-9,-9,-8,-8,-7,-6,-6,-5,-4,-4,-3,-3,-2,-1,-1,0,\n\t0,0,1,2,2,3,4,4,5,6,6,7,8,8,9,10,\n\t11,11,12,13,13,14,15,15,16,17,17,18,19,19,20,21,\n\t-21,-21,-20,-19,-19,-18,-17,-17,-16,-15,-15,-14,-13,-12,-12,-11,\n\t-10,-10,-9,-8,-8,-7,-6,-6,-5,-4,-4,-3,-2,-1,-1,0,\n\t0,0,1,2,3,3,4,5,6,6,7,8,9,9,10,11,\n\t12,12,13,14,15,15,16,17,18,18,19,20,21,21,22,23,\n\t-23,-23,-22,-21,-20,-20,-19,-18,-17,-17,-16,-15,-14,-14,-13,-12,\n\t-11,-11,-10,-9,-8,-8,-7,-6,-5,-5,-4,-3,-2,-2,-1,0,\n\t0,0,1,2,3,4,4,5,6,7,8,8,9,10,11,12,\n\t13,13,14,15,16,17,17,18,19,20,21,21,22,23,24,25,\n\t-25,-25,-24,-23,-22,-21,-21,-20,-19,-18,-17,-16,-16,-15,-14,-13,\n\t-12,-12,-11,-10,-9,-8,-8,-7,-6,-5,-4,-3,-3,-2,-1,0,\n\t0,0,1,2,3,4,5,6,7,7,8,9,10,11,12,13,\n\t14,14,15,16,17,18,19,20,21,21,22,23,24,25,26,27,\n\t-27,-27,-26,-25,-24,-23,-22,-21,-20,-20,-19,-18,-17,-16,-15,-14,\n\t-13,-13,-12,-11,-10,-9,-8,-7,-6,-6,-5,-4,-3,-2,-1,0,\n\t0,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,\n\t15,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,\n\t-29,-28,-28,-27,-26,-25,-24,-23,-22,-21,-20,-19,-18,-17,-16,-15,\n\t-14,-13,-13,-12,-11,-10,-9,-8,-7,-6,-5,-4,-3,-2,-1,0\n};\n\nstatic const BYTE mt_VibratoRectTable[] = {\n\t0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n\t0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n\t0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n\t0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n\t1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,\n\t1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,\n\t-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,\n\t-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,\n\t3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,\n\t3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,\n\t-3,-3,-3,-3,-3,-3,-3,-3,-3,-3,-3,-3,-3,-3,-3,-3,\n\t-3,-3,-3,-3,-3,-3,-3,-3,-3,-3,-3,-3,-3,-3,-3,-3,\n\t5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,\n\t5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,\n\t-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,\n\t-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,\n\t7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,\n\t7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,\n\t-7,-7,-7,-7,-7,-7,-7,-7,-7,-7,-7,-7,-7,-7,-7,-7,\n\t-7,-7,-7,-7,-7,-7,-7,-7,-7,-7,-7,-7,-7,-7,-7,-7,\n\t9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,\n\t9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,\n\t-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,\n\t-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,\n\t11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,\n\t11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,\n\t-11,-11,-11,-11,-11,-11,-11,-11,-11,-11,-11,-11,-11,-11,-11,-11,\n\t-11,-11,-11,-11,-11,-11,-11,-11,-11,-11,-11,-11,-11,-11,-11,-11,\n\t13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,\n\t13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,\n\t-13,-13,-13,-13,-13,-13,-13,-13,-13,-13,-13,-13,-13,-13,-13,-13,\n\t-13,-13,-13,-13,-13,-13,-13,-13,-13,-13,-13,-13,-13,-13,-13,-13,\n\t15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,\n\t15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,\n\t-15,-15,-15,-15,-15,-15,-15,-15,-15,-15,-15,-15,-15,-15,-15,-15,\n\t-15,-15,-15,-15,-15,-15,-15,-15,-15,-15,-15,-15,-15,-15,-15,-15,\n\t17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,\n\t17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,\n\t-17,-17,-17,-17,-17,-17,-17,-17,-17,-17,-17,-17,-17,-17,-17,-17,\n\t-17,-17,-17,-17,-17,-17,-17,-17,-17,-17,-17,-17,-17,-17,-17,-17,\n\t19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,\n\t19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,\n\t-19,-19,-19,-19,-19,-19,-19,-19,-19,-19,-19,-19,-19,-19,-19,-19,\n\t-19,-19,-19,-19,-19,-19,-19,-19,-19,-19,-19,-19,-19,-19,-19,-19,\n\t21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,\n\t21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,\n\t-21,-21,-21,-21,-21,-21,-21,-21,-21,-21,-21,-21,-21,-21,-21,-21,\n\t-21,-21,-21,-21,-21,-21,-21,-21,-21,-21,-21,-21,-21,-21,-21,-21,\n\t23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,\n\t23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,\n\t-23,-23,-23,-23,-23,-23,-23,-23,-23,-23,-23,-23,-23,-23,-23,-23,\n\t-23,-23,-23,-23,-23,-23,-23,-23,-23,-23,-23,-23,-23,-23,-23,-23,\n\t25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,\n\t25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,\n\t-25,-25,-25,-25,-25,-25,-25,-25,-25,-25,-25,-25,-25,-25,-25,-25,\n\t-25,-25,-25,-25,-25,-25,-25,-25,-25,-25,-25,-25,-25,-25,-25,-25,\n\t27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,\n\t27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,\n\t-27,-27,-27,-27,-27,-27,-27,-27,-27,-27,-27,-27,-27,-27,-27,-27,\n\t-27,-27,-27,-27,-27,-27,-27,-27,-27,-27,-27,-27,-27,-27,-27,-27,\n\t29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,\n\t29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,\n\t-29,-29,-29,-29,-29,-29,-29,-29,-29,-29,-29,-29,-29,-29,-29,-29,\n\t-29,-29,-29,-29,-29,-29,-29,-29,-29,-29,-29,-29,-29,-29,-29,-29\n};\n\nstatic const tFx fx_tab[16];\nstatic const tFx morefx_tab[16];\nstatic const tFx blmorefx_tab[16];\nstatic const tEFn ecmd_tab[16];\nstatic const tEFn blecmd_tab[16];\nstatic const tPreFx prefx_tab[16];\n\n#if defined(PTPLAYER_DEFER_INTERRUPTS)\nstatic volatile UBYTE s_isPendingPlay, s_isPendingSetRep, s_isPendingDmaOn;\n#endif\nstatic UBYTE s_isRepeat;\nstatic tPtplayerCbSongEnd s_cbSongEnd;\nstatic tPtplayerCbE8 s_cbOnE8;\nstatic UBYTE s_isPal;\n\n#if defined(PTPLAYER_USE_AUDIO_INT_HANDLERS)\n/**\n * @brief Indicators for each channel being free to use. Channel is set to 1 if\n * it has done playback.\n */\nstatic volatile tChannelDone s_uChannelDone;\n\n/**\n * @brief Set to 1 for channel after it has been instructed to play back 1-word\n * null loop. Set to 0 on audio interrupt after finishing null loop playback and\n * disabling channel DMA to keep it from retriggering audio interrupt.\n */\nstatic volatile UBYTE s_pAudioChannelPendingDisable[4];\n#endif\n\nstatic void blocked_e_cmds(\n\tUBYTE ubArgs, tChannelStatus *pChannelData,\n\tvolatile tChannelRegs *pChannelReg\n);\n\nstatic void set_finetune(\n\tUWORD uwCmd, UWORD uwCmdArg, UWORD uwMaskedCmdE, const tModVoice *pVoice,\n\ttChannelStatus *pChannelData, volatile tChannelRegs *pChannelReg\n);\n\nstatic volatile UBYTE mt_MusicChannels = 0;\nstatic volatile UBYTE mt_E8Trigger = 0;\nstatic volatile UBYTE mt_Enable = 0;\n\n/**\n * @brief Used to determine what Timer B interrupt should do next.\n *\n * Original ptplayer variable name: TB_toggle.\n */\nstatic volatile UBYTE s_isNextTimerBSetRep;\n\nstatic tChannelStatus mt_chan[4];\nstatic UWORD *mt_SampleStarts[PTPLAYER_MOD_SAMPLE_COUNT]; ///< Start address of each sample\nstatic tPtplayerMod *s_pCurrentMod; ///< Currently played MOD.\nstatic ULONG mt_timerval; ///< Base interrupt frequency of CIA-B timer A used to advance the song. Equals 125*50Hz.\nstatic const UBYTE * mt_MasterVolTab;\nstatic UWORD mt_PatternPos;\nstatic UWORD mt_PBreakPos; ///< Pattern break pos\nstatic UBYTE mt_PosJumpFlag;\nstatic UBYTE mt_PBreakFlag;\nstatic UBYTE mt_Speed; ///< Number of times the main loop gets called per note step.\nstatic UBYTE mt_Counter; ///< Number of main loop iterations in current note step so far.\nstatic UBYTE mt_SongPos; ///< Position in arrangement.\nstatic UBYTE mt_PattDelTime;\nstatic UBYTE mt_PattDelTime2;\nstatic UBYTE mt_SilCntValid;\n\n/**\n * Each player loop generates this from scratch.\n *\n * Set with DMAF_AUD# when sfx is to be played, by retrigger/period cmds.\n *\n * Used in following DMA enable interrupt or in same loop pass to see\n * if channels are blocked. Also clears interrupt bits for set up channels\n * to indicate that they are busy.\n */\nstatic UWORD mt_dmaon = 0;\n\nstatic void clearAudioDone(void) {\n#if defined(PTPLAYER_USE_AUDIO_INT_HANDLERS)\n\t// When channel is idle, original ptplayer loops playback of the first word\n\t// and allows Paula to keep the intbit being set, so clearing here intreq\n\t// for all channels didn't permanently affected idle channel bits.\n\t// int-handler version disables channel's DMA when sfx played back to prevent\n\t// interrupt spamming, so they can't maintain the 'done' intbit.\n\ts_uChannelDone.ulChannelMask = 0;\n#else\n\t// for some reason I've had the following code here - why?\n\t// g_pCustom->intreq = INTF_AUD0 | INTF_AUD1 | INTF_AUD2 | INTF_AUD3;\n\t// KaiN's note: Audio dmaBits = 0b0001..0b1000, intBits = dmaBits << 7\n\tg_pCustom->intreq = (mt_dmaon << 7) | INTF_EXTER;\n#endif\n}\n\nstatic void setAudioDone(UNUSED_ARG tChannelStatus *pChannelData) {\n#if defined(PTPLAYER_USE_AUDIO_INT_HANDLERS)\n\tpChannelData->pDoneBit = 1;\n#endif\n}\n\nstatic UBYTE isChannelDone(tChannelStatus *pChannelData) {\n#if defined(PTPLAYER_USE_AUDIO_INT_HANDLERS)\n\treturn *pChannelData->pDoneBit;\n#else\n\tif (pChannelData->isLooped) {\n\t\t// Looping channels are not done\n\t\treturn 0;\n\t}\n\n\t// This doesn't work when nothing has yet played - check dmaconr for that\n\t// KaiN's note: Audio dmaBits = 0b0001..0b1000, intBits = dmaBits << 7\n\tUWORD uwIntReqr = g_pCustom->intreqr;\n\n\t// `!= 0` must be here, because downcasting to UBYTE may discard higher intbit\n\t// and channel will be busy indefinitely!\n\tUBYTE isBusy = (uwIntReqr & (pChannelData->uwDmaFlag << 7)) != 0;\n\treturn isBusy;\n#endif\n}\n\nstatic void printVoices(UNUSED_ARG const tModVoice *pVoices) {\n#if defined(ACE_DEBUG_PTPLAYER)\n\ttypedef struct _tPeriodNote {\n\t\tUWORD uwPeriod;\n\t\tconst char *szNote;\n\t} tPeriodNote;\n\n\t// Taken from https://www.fileformat.info/format/mod/corion.htm, table 5\n\tstatic const tPeriodNote pPeriod2Note[] = {\n\t\t{1712, \"C-0\"}, {1616, \"C#0\"}, {1524, \"D-0\"}, {1440, \"D#0\"},\n\t\t{1356, \"E-0\"}, {1280, \"F-0\"}, {1208, \"F#0\"}, {1140, \"G-0\"},\n\t\t{1076, \"G#0\"}, {1016, \"A-0\"}, { 960, \"A#0\"}, { 906, \"B-0\"},\n\n\t\t{ 856, \"C-1\"}, { 808, \"C#1\"}, { 762, \"D-1\"}, { 720, \"D#1\"},\n\t\t{ 678, \"E-1\"}, { 640, \"F-1\"}, { 604, \"F#1\"}, { 570, \"G-1\"},\n\t\t{ 538, \"G#1\"}, { 508, \"A-1\"}, { 480, \"A#1\"}, { 453, \"B-1\"},\n\n\t\t{ 428, \"C-2\"}, { 404, \"C#2\"}, { 381, \"D-2\"}, { 360, \"D#2\"},\n\t\t{ 339, \"E-2\"}, { 320, \"F-2\"}, { 302, \"F#2\"}, { 285, \"G-2\"},\n\t\t{ 269, \"G#2\"}, { 254, \"A-2\"}, { 240, \"A#2\"}, { 226, \"B-2\"},\n\n\t\t{ 214, \"C-3\"}, { 202, \"C#3\"}, { 190, \"D-3\"}, { 180, \"D#3\"},\n\t\t{ 170, \"E-3\"}, { 160, \"F-3\"}, { 151, \"F#3\"}, { 143, \"G-3\"},\n\t\t{ 135, \"G#3\"}, { 127, \"A-3\"}, { 120, \"A#3\"}, { 113, \"B-3I\"},\n\n\t\t{ 107, \"C-4\"}, { 101, \"C#4\"}, {  95, \"D-4\"}, {  90, \"D#4\"},\n\t\t{  85, \"E-4\"}, {  80, \"F-4\"}, {  75, \"F#4\"}, {  71, \"G-4\"},\n\t\t{  67, \"G#4\"}, {  63, \"A-4\"}, {  60, \"A#4\"}, {  56, \"B-4\"},\n\t\t{   0, \"   \"}\n\t};\n\n\t// logWrite(\n\t// \t\"Row (cmd.note): %04X.%04X, %04X.%04X, %04X.%04X, %04X.%04X\\n\",\n\t// \tpVoices[0].uwCmd, pVoices[0].uwNote,\n\t// \tpVoices[1].uwCmd, pVoices[1].uwNote,\n\t// \tpVoices[2].uwCmd, pVoices[2].uwNote,\n\t// \tpVoices[3].uwCmd, pVoices[3].uwNote\n\t// );\n\n\tconst char *pNotes[MOD_NOTES_PER_ROW];\n\tUBYTE pInstruments[MOD_NOTES_PER_ROW], pCmdIdx[MOD_NOTES_PER_ROW], pCmdArg[MOD_NOTES_PER_ROW];\n\tfor(UBYTE ubVoice = 0; ubVoice < MOD_NOTES_PER_ROW; ++ubVoice) {\n\t\tconst tModVoice *pVoice = &pVoices[ubVoice];\n\t\tUWORD uwPeriod = pVoice->uwNote & 0xFFF;\n\t\tpInstruments[ubVoice] = (pVoice->uwNote >> 8) | (pVoice->uwCmd >> 12);\n\t\tpCmdIdx[ubVoice] = (pVoice->uwCmd >> 8) & 0xF;\n\t\tpCmdArg[ubVoice] = pVoice->uwCmd & 0xFF;\n\n\t\t// Decode period -> note\n\t\tconst char *szNote = \"???\";\n\t\tfor(UBYTE i = 0; i < 61; ++i) {\n\t\t\tif(pPeriod2Note[i].uwPeriod == uwPeriod) {\n\t\t\t\tszNote = pPeriod2Note[i].szNote;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tpNotes[ubVoice] = szNote;\n\t}\n\tlogWrite(\n\t\t\"T %5lu note.instr.cmd.arg %s.%02hhX.%hhX.%02hhX  %s.%02hhX.%hhX.%02hhX  %s.%02hhX.%hhX.%02hhX  %s.%02hhX.%hhX.%02hhX\\n\",\n\t\ttimerGet(),\n\t\tpNotes[0], pInstruments[0], pCmdIdx[0], pCmdArg[0],\n\t\tpNotes[1], pInstruments[1], pCmdIdx[1], pCmdArg[1],\n\t\tpNotes[2], pInstruments[2], pCmdIdx[2], pCmdArg[2],\n\t\tpNotes[3], pInstruments[3], pCmdIdx[3], pCmdArg[3]\n\t);\n#endif\n}\n\nstatic inline UBYTE findPeriod(const UWORD *pPeriods, UWORD uwNote) {\n\t// Find nearest period for a note value\n\tfor(UBYTE ubPeriodPos = 0; ubPeriodPos < MOD_PERIOD_TABLE_LENGTH - 1; ++ubPeriodPos) {\n\t\tif (uwNote >= pPeriods[ubPeriodPos]) {\n\t\t\treturn ubPeriodPos;\n\t\t}\n\t}\n\n\treturn MOD_PERIOD_TABLE_LENGTH - 1;\n}\n\nstatic void ptSongStep(void) {\n\tmt_PatternPos = mt_PBreakPos;\n\tmt_PBreakPos = 0;\n\tmt_PosJumpFlag = 0;\n\n\t// Next position in song\n\tUBYTE ubNextPos = (mt_SongPos + 1) & 0x7F;\n\n\t// End of song reached?\n\tif(ubNextPos >= s_pCurrentMod->ubArrangementLength) {\n\t\tubNextPos = 0;\n\t\tif(!s_isRepeat) {\n\t\t\tptplayerEnableMusic(0);\n\t\t}\n\t\tif(s_cbSongEnd) {\n\t\t\ts_cbSongEnd();\n\t\t}\n\t}\n\tmt_SongPos = ubNextPos;\n\t// Should be a check of mt_PosJumpFlag here, but unlikely that something will\n\t// set it in the meantime\n}\n\nstatic void startSfx(\n\ttChannelStatus *pChannelData, volatile tChannelRegs *pChannelReg\n) {\n#if defined(ACE_DEBUG_PTPLAYER)\n\tlogWrite(\"startsfx: %p:%hu\\n\", pChannelData->n_sfxptr, pChannelData->uwSfxWordLength);\n#endif\n\t// play new sound effect on this channel\n\tsystemSetDmaMask(pChannelData->uwDmaFlag, 0);\n\tUWORD uwRepeatLength;\n\tvolatile UWORD *pSfxData = pChannelReg->ac_ptr = pChannelData->n_sfxptr;\n\tif(pChannelData->ubSfxPriority == SFX_PRIORITY_LOOPED) {\n\t\tpChannelData->isLooped = 1;\n\n\t\t// Skip first word which is used for idling\n\t\t++pSfxData;\n\t\tuwRepeatLength = pChannelData->uwSfxWordLength - 1;\n\t\tpChannelReg->ac_ptr = pSfxData;\n\t\tpChannelReg->ac_len = uwRepeatLength;\n\t}\n\telse {\n\t\tpChannelData->isLooped = 0;\n\t\tuwRepeatLength = 1;\n\t\tpChannelReg->ac_ptr = pSfxData;\n\t\tpChannelReg->ac_len = pChannelData->uwSfxWordLength;\n\t}\n\tpChannelReg->ac_per = pChannelData->uwSfxPeriod;\n\tpChannelReg->ac_vol = pChannelData->uwSfxVolume;\n\n\t// Save repeat and period for TimerB interrupt.\n\t// After the sample has fully played back and there is no repeat,\n\t// the channel's pointer will be set to first word of sample and play back\n\t// the first word continuously.\n\tpChannelData->n_loopstart = pChannelData->n_sfxptr;\n\tpChannelData->n_replen = uwRepeatLength;\n\tpChannelData->uwPeriod = pChannelData->uwPeriod;\n\tpChannelData->uwSfxWordLength = 0; // Don't call startSfx() again\n\n\tmt_dmaon |= pChannelData->uwDmaFlag; // DMA channel to enable on Timer B\n}\n\nvoid moreBlockedFx(\n\tUWORD uwCmd, tChannelStatus *pChannelData,\n\tvolatile tChannelRegs *pChannelReg\n) {\n\t// Get cmd idx. See tModVoice's type definition for details.\n\tUBYTE ubCmdIdx = (uwCmd >> 8) & 0x0F;\n#if defined(ACE_DEBUG_PTPLAYER)\n\tif(ubCmdIdx >= 16) {\n\t\tlogWrite(\"ERR: blmorefx_tab index out of range: cmd %hu -> %hu\\n\", uwCmd, uwCmd >> 8);\n\t}\n#endif\n\tblmorefx_tab[ubCmdIdx](uwCmd, pChannelData, pChannelReg);\n}\n\nstatic void mt_updatefunk(tChannelStatus *pChannelData) {\n\tUBYTE ubVal = mt_FunkTable[pChannelData->uwFunkSpeed];\n\tpChannelData->n_funkoffset += ubVal;\n\tif(pChannelData->n_funkoffset > 0) {\n\t\treturn;\n\t}\n\tpChannelData->n_funkoffset = 0;\n\tUBYTE *pOffs = (UBYTE*)&pChannelData->n_loopstart[pChannelData->n_replen];\n\tUBYTE *pWaveStart = &pChannelData->n_wavestart[1];\n\tif(pWaveStart >= pOffs) {\n\t\tpWaveStart = pOffs;\n\t}\n\tpChannelData->n_wavestart = pWaveStart;\n\t*pWaveStart = ~*pWaveStart;\n}\n\nstatic void checkmorefx(\n\tUWORD uwCmd, UWORD uwCmdArg,\n\ttChannelStatus *pChannelData, volatile tChannelRegs *pChannelReg\n) {\n\tif(pChannelData->uwFunkSpeed) {\n\t\tmt_updatefunk(pChannelData);\n\t}\n#if defined(ACE_DEBUG_PTPLAYER)\n\tif(uwCmd >= 16) {\n\t\tlogWrite(\"ERR: morefx_tab index out of range: cmd %hu\\n\", uwCmd);\n\t}\n#endif\n\tmorefx_tab[uwCmd](uwCmdArg, pChannelData, pChannelReg);\n}\n\nstatic void mt_playvoice(\n\ttChannelStatus *pChannelData, volatile tChannelRegs *pChannelReg,\n\tconst tModVoice *pVoice\n) {\n\tif(!pChannelData->isEnabledForPlayer) {\n\t\treturn;\n\t}\n\tif(pChannelData->ubSfxPriority) {\n\t\t// Channel is blocked by external sound effect\n\t\tif(pChannelData->uwSfxWordLength) {\n\t\t\t// There are pending sfx data to be written into channel regs\n\t\t\tstartSfx(pChannelData, pChannelReg);\n\t\t\tmoreBlockedFx(pVoice->uwCmd, pChannelData, pChannelReg);\n\t\t\treturn;\n\t\t}\n\t\tif(!isChannelDone(pChannelData) || (mt_dmaon & pChannelData->uwDmaFlag)) {\n\t\t\t// Channel interrupt is not triggered or DMA is still active - do only\n\t\t\t// some limited commands while sound effect is in progress\n\t\t\tmoreBlockedFx(pVoice->uwCmd, pChannelData, pChannelReg);\n\t\t\treturn;\n\t\t}\n\t\t// Sound effect sample is already scheduled to be played, so unblock\n\t\t// this channel again.\n\t\tpChannelData->ubSfxPriority = 0;\n\t}\n\t// n_note/cmd: any note or cmd set?\n\tif(!pChannelData->sVoice.ulData) {\n\t\tpChannelReg->ac_per = pChannelData->uwPeriod;\n\t}\n\tpChannelData->sVoice.ulData = pVoice->ulData;\n\n\tUWORD uwCmd = pChannelData->sVoice.ubCmdHi & 0x000F;\n\tUWORD uwCmdArg = pChannelData->sVoice.ubCmdLo;\n\tUWORD uwMaskedCmdE = pChannelData->sVoice.uwCmd & 0x0FF0;\n\n\t// Get sample start address from cmd/note - BA is sample number\n\tUWORD uwSampleIdx = ( // A...B... -> ......BA\n\t\t((pVoice->uwNote & 0xF000) >> 4) | (pVoice->ubCmdHi & 0xF0)\n\t) >> 4;\n\tif(uwSampleIdx) {\n\t\t// Samples are internally zero-based, in file 1-based\n\t\t--uwSampleIdx;\n\t\t// Read length, volume and repeat from sample info table\n\t\tUWORD *pSampleStart = mt_SampleStarts[uwSampleIdx];\n\t\ttPtplayerSampleHeader *pSampleDef = &s_pCurrentMod->pSampleHeaders[uwSampleIdx];\n\t\tUWORD uwSampleLength = pSampleDef->uwLength;\n\t\tif(!uwSampleLength) {\n\t\t\t// Use the first two bytes from the first sample for empty samples\n\t\t\tuwSampleIdx = 0;\n\t\t\tpSampleStart = mt_SampleStarts[uwSampleIdx];\n\t\t\tuwSampleLength = 1;\n\t\t}\n\n\t\tif(!pSampleStart) {\n\t\t\tlogWrite(\n\t\t\t\t\"ERR: Malformed MOD: start offset of sample %hu is zero\\n\",\n\t\t\t\tuwSampleIdx\n\t\t\t);\n\t\t}\n\n\t\t// logWrite(\"playvoice sample: %hu, length: %hu\\n\", uwSampleIdx, uwSampleLength);\n\t\tpChannelData->n_start = pSampleStart;\n\t\tpChannelData->n_reallength = uwSampleLength;\n\n\t\t// Determine period table from fine-tune parameter\n\t\t// TODO: sanitize this value to only have lower nibble set when loading MOD/samplepack\n\t\tUBYTE ubFineTune = pSampleDef->ubFineTune & 0xF;\n\t\tpChannelData->pPeriodTable = mt_PeriodTables[ubFineTune];\n\t\tpChannelData->n_minusft = (ubFineTune >= 8);\n\n\t\tpChannelData->uwVolume = pSampleDef->ubVolume;\n\t\t// MOD spec: repeat only if repeat length is bigger than 2 bytes.\n\t\tif(pSampleDef->uwRepeatLength <= 1) {\n\t\t\t// No repeat def - reload first empty sample word after playback,\n\t\t\t// then disable channel.\n\t\t\tpChannelData->isLooped = 0;\n\t\t\tpChannelData->n_replen = 1;\n\t\t}\n\t\telse {\n\t\t\t// Set repeat\n\t\t\tpChannelData->isLooped = 1;\n\t\t\tpChannelData->n_replen = pSampleDef->uwRepeatLength;\n\t\t\tuwSampleLength = pSampleDef->uwRepeatLength;\n\t\t\tpSampleStart += pSampleDef->uwRepeatOffs;\n\t\t}\n\n\t\t// set_loop:\n\t\tpChannelData->n_length = uwSampleLength;\n\t\tpChannelData->n_loopstart = pSampleStart;\n\t\tpChannelData->n_wavestart = (UBYTE*)pSampleStart;\n\t\tpChannelReg->ac_vol = mt_MasterVolTab[pSampleDef->ubVolume];\n\t}\n\n\t// inlined set_regs function here:\n\tif(!(pVoice->uwNote & 0xFFF)) {\n\t\tcheckmorefx(uwCmd, uwCmdArg, pChannelData, pChannelReg);\n\t}\n\telse if(uwMaskedCmdE == 0x0E50) {\n\t\tset_finetune(uwCmd, uwCmdArg, uwMaskedCmdE, pVoice, pChannelData, pChannelReg);\n\t}\n\telse {\n#if defined(ACE_DEBUG_PTPLAYER)\n\t\tif(uwCmd >= 16) {\n\t\t\tlogWrite(\"ERR: prefx_tab index out of range: cmd %hu\\n\", uwCmd);\n\t\t}\n#endif\n\t\tprefx_tab[uwCmd](\n\t\t\tuwCmd, uwCmdArg, uwMaskedCmdE, pVoice, pChannelData, pChannelReg\n\t\t);\n\t}\n}\n\nstatic void mt_checkfx(\n\ttChannelStatus *pChannelData, volatile tChannelRegs *pChannelReg\n) {\n\tif(!pChannelData->isEnabledForPlayer) {\n\t\treturn;\n\t}\n\tif(pChannelData->ubSfxPriority) {\n\t\tUWORD uwLen = pChannelData->uwSfxWordLength;\n\t\tif(uwLen) {\n\t\t\tstartSfx(pChannelData, pChannelReg);\n\t\t}\n\t\tif(\n\t\t\t// mt_dmaon should be checked here to see if channel will be busy by sfx\n\t\t\t// but uwLen check is used instead.\n\t\t\tuwLen || !isChannelDone(pChannelData) ||\n\t\t\t(g_pCustom->dmaconr & pChannelData->uwDmaFlag)\n\t\t) {\n\t\t\t// Channel is blocked, only check some E-commands\n\t\t\tUWORD uwCmd = pChannelData->sVoice.uwCmd & 0x0FFF;\n\t\t\tif((uwCmd & 0xF00) == 0xE00) {\n\t\t\t\tblocked_e_cmds(uwCmd, pChannelData, pChannelReg);\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\t// Sound effect sample has played, so unblock this channel again\n\t\tpChannelData->ubSfxPriority = 0;\n\t}\n\n\t// Do channel effects between notes\n\tif(pChannelData->uwFunkSpeed) {\n\t\tmt_updatefunk(pChannelData);\n\t}\n\tUWORD uwCmd = (pChannelData->sVoice.uwCmd & 0x0FFF);\n\tif(!uwCmd) {\n\t\t// Just set the current period - same as mt_pernop\n\t\tpChannelReg->ac_per = pChannelData->uwPeriod;\n\t}\n\telse {\n\t\tUBYTE ubCmdIndex = (pChannelData->sVoice.ubCmdHi & 0xF);\n#if defined(ACE_DEBUG_PTPLAYER)\n\t\tif(ubCmdIndex >= 16) {\n\t\t\tlogWrite(\"ERR: fx_tab index out of range: cmd %hhu\\n\", ubCmdIndex);\n\t\t}\n#endif\n\t\tfx_tab[ubCmdIndex](pChannelData->sVoice.ubCmdLo, pChannelData, pChannelReg);\n\t}\n}\n\nstatic void mt_sfxonly(void);\nstatic void mt_music(void);\n\nstatic void intPlay() {\n\t// it was a TA interrupt, do music when enabled\n\tif(mt_Enable) {\n\t\tmt_music();\n\t}\n\telse {\n\t\t// no music, only sfx\n\t\tmt_sfxonly();\n\t}\n}\n\n// TimerA interrupt calls _mt_music at a selectable tempo (Fxx command),\n// which defaults to 50 times per second.\nstatic void mt_TimerAInt(\n\tUNUSED_ARG REGARG(volatile tCustom *pCustom, \"a0\"),\n\tUNUSED_ARG REGARG(volatile void *pData, \"a1\")\n) {\n#if defined(PTPLAYER_DEFER_INTERRUPTS)\n\ts_isPendingPlay = 1;\n#else\n\tintPlay();\n#endif\n}\n\nstatic inline void ptplayerEnableMainHandler(UBYTE isEnabled) {\n#if defined(PTPLAYER_USE_VBL)\n\tif(isEnabled) {\n\t\tsystemSetInt(INTB_VERTB, mt_TimerAInt, 0);\n\t}\n\telse {\n\t\tsystemSetInt(INTB_VERTB, 0, 0);\n\t}\n#else\n\tif(isEnabled) {\n\t\tsystemSetCiaInt(CIA_B, CIAICRB_TIMER_A, mt_TimerAInt, 0);\n\t}\n\telse {\n\t\tsystemSetCiaInt(CIA_B, CIAICRB_TIMER_A, 0, 0);\n\t}\n#endif\n}\n\nstatic inline void setChannelRepeat(\n\tvolatile tChannelRegs *pChannelRegs, tChannelStatus *pChannelData\n) {\n#if defined(PTPLAYER_USE_AUDIO_INT_HANDLERS)\n\tif(pChannelData->n_replen == 1) {\n\t\t// Looped single word of sample - channel is to be set to idle mode\n\t\tif(mt_dmaon & pChannelData->uwDmaFlag) {\n\t\t\t// Channel is still on - give the audio interrupt signal that it should\n\t\t\t// disable channel DMA after playback of this one.\n\t\t\ts_pAudioChannelPendingDisable[pChannelData->ubChannelIndex] = 1;\n\t\t}\n\t}\n#endif\n\tif(!(mt_dmaon & pChannelData->uwDmaFlag)) {\n\t\t// Channel is already turned off - refresh 'done' bit.\n\t\tsetAudioDone(pChannelData);\n\t\t// Skip register setup\n\t\treturn;\n\t}\n\n\t// Paula reads new register values after it finishes current audio playback.\n\tpChannelRegs->ac_ptr = pChannelData->n_loopstart;\n\tpChannelRegs->ac_len = pChannelData->n_replen;\n}\n\nstatic void intSetRep(volatile tCustom *pCustom) {\n\t// check and clear CIAB interrupt flags\n\t// clear EXTER and possible audio interrupt flags\n\tclearAudioDone();\n\n\t// Set repeat sample pointers and lengths\n\tif(mt_chan[0].isEnabledForPlayer) {\n\t\tsetChannelRepeat(&pCustom->aud[0], &mt_chan[0]);\n\t}\n\tif(mt_chan[1].isEnabledForPlayer) {\n\t\tsetChannelRepeat(&pCustom->aud[1], &mt_chan[1]);\n\t}\n\tif(mt_chan[2].isEnabledForPlayer) {\n\t\tsetChannelRepeat(&pCustom->aud[2], &mt_chan[2]);\n\t}\n\tif(mt_chan[3].isEnabledForPlayer) {\n\t\tsetChannelRepeat(&pCustom->aud[3], &mt_chan[3]);\n\t}\n\n\t// restore TimerA music interrupt vector\n\tptplayerEnableMainHandler(1);\n}\n\nstatic void intDmaOn() {\n\t// Restart timer to set repeat, enable DMA\n\tsystemSetCiaCr(CIA_B, 1, CIACRB_LOAD | CIACRB_RUNMODE | CIACRB_START);\n\tsystemSetDmaMask(mt_dmaon, 1);\n\tptplayerEnableMainHandler(0);\n}\n\n// One-shot TimerB interrupt to enable audio DMA after DMA_DELAY ticks.\nstatic void mt_TimerBInt(\n\tREGARG(volatile tCustom *pCustom, \"a0\"),\n\tUNUSED_ARG REGARG(volatile void *pData, \"a1\")\n) {\n\t// Do DMA on first, then Set Repeat\n\tUBYTE isSetRep = s_isNextTimerBSetRep;\n\ts_isNextTimerBSetRep = !s_isNextTimerBSetRep;\n#if defined(PTPLAYER_DEFER_INTERRUPTS)\n\tif(isSetRep) {\n\t\ts_isPendingSetRep = 1;\n\t}\n\telse {\n\t\ts_isPendingDmaOn = 1;\n\t}\n#else\n\tif(isSetRep) {\n\t\tintSetRep(pCustom);\n\t}\n\telse {\n\t\tintDmaOn();\n\t}\n#endif\n}\n\nstatic void chan_sfx_only(\n\tvolatile tChannelRegs *pChannelReg, tChannelStatus *pChannelData\n) {\n\tif(pChannelData->ubSfxPriority) {\n\t\tif(pChannelData->uwSfxWordLength) {\n\t\t\tstartSfx(pChannelData, pChannelReg);\n\t\t}\n\t\telse if(isChannelDone(pChannelData) && !(mt_dmaon & pChannelData->uwDmaFlag)) {\n\t\t\t// Last sound effect sample has played, so unblock this channel again\n\t\t\tpChannelData->ubSfxPriority = 0;\n\t\t}\n\t}\n}\n\n// Called from interrupt.\n// Plays sound effects on free channels.\nvoid mt_sfxonly(void) {\n\tmt_dmaon = 0;\n\tchan_sfx_only(&g_pCustom->aud[0], &mt_chan[0]);\n\tchan_sfx_only(&g_pCustom->aud[1], &mt_chan[1]);\n\tchan_sfx_only(&g_pCustom->aud[2], &mt_chan[2]);\n\tchan_sfx_only(&g_pCustom->aud[3], &mt_chan[3]);\n\n\tif(mt_dmaon) {\n\t\tptplayerEnableMainHandler(0);\n\t\tsystemSetCiaCr(CIA_B, 1, CIACRB_LOAD | CIACRB_RUNMODE | CIACRB_START); // load/start timer B, one-shot\n\t}\n}\n\n/**\n * @brief The replayer routine.\n * Is called automatically from interrupt after ptplayerCreate().\n * Plays next position when Counter equals Speed. Effects are always handled.\n */\nstatic void mt_music(void) {\n\tmt_dmaon = 0;\n\tif(++mt_Counter < mt_Speed) {\n\t\t// no new note, just check effects, don't step to next position\n\t\tmt_checkfx(&mt_chan[0], &g_pCustom->aud[0]);\n\t\tmt_checkfx(&mt_chan[1], &g_pCustom->aud[1]);\n\t\tmt_checkfx(&mt_chan[2], &g_pCustom->aud[2]);\n\t\tmt_checkfx(&mt_chan[3], &g_pCustom->aud[3]);\n\n\t\t// set one-shot TimerB interrupt for enabling DMA, when needed\n\t\tif(mt_dmaon) {\n\t\t\tptplayerEnableMainHandler(0);\n\t\t\tsystemSetCiaCr(CIA_B, 1, CIACRB_LOAD | CIACRB_RUNMODE | CIACRB_START); // load/start timer B, one-shot\n\t\t}\n\t}\n\telse {\n\t\t// handle a new note\n\t\tmt_Counter = 0;\n\t\tif(mt_PattDelTime2 <= 0) {\n\t\t\t// determine pointer to current pattern line\n\t\t\tUBYTE *pPatternData = s_pCurrentMod->pPatterns;\n\t\t\tUBYTE *pArrangement = s_pCurrentMod->pArrangement;\n\t\t\tUBYTE ubPatternIdx = pArrangement[mt_SongPos];\n\t\t\tUBYTE *pCurrentPattern = &pPatternData[ubPatternIdx * 1024];\n\t\t\ttModVoice *pLineVoices = (tModVoice*)&pCurrentPattern[mt_PatternPos];\n\t\t\tprintVoices(pLineVoices);\n\n\t\t\t// play new note for each channel, apply some effects\n\t\t\tmt_playvoice(&mt_chan[0], &g_pCustom->aud[0], &pLineVoices[0]);\n\t\t\tmt_playvoice(&mt_chan[1], &g_pCustom->aud[1], &pLineVoices[1]);\n\t\t\tmt_playvoice(&mt_chan[2], &g_pCustom->aud[2], &pLineVoices[2]);\n\t\t\tmt_playvoice(&mt_chan[3], &g_pCustom->aud[3], &pLineVoices[3]);\n\t\t}\n\t\telse {\n\t\t\t// we have a pattern delay, check effects then step\n\t\t\tmt_checkfx(&mt_chan[0], &g_pCustom->aud[0]);\n\t\t\tmt_checkfx(&mt_chan[1], &g_pCustom->aud[1]);\n\t\t\tmt_checkfx(&mt_chan[2], &g_pCustom->aud[2]);\n\t\t\tmt_checkfx(&mt_chan[3], &g_pCustom->aud[3]);\n\t\t}\n\t\t// set one-shot TimerB interrupt for enabling DMA, when needed\n\t\tif(mt_dmaon) {\n\t\t\tptplayerEnableMainHandler(0);\n\t\t\tsystemSetCiaCr(CIA_B, 1, CIACRB_LOAD | CIACRB_RUNMODE | CIACRB_START); // load/start timer B, one-shot\n\t\t}\n\n\t\t// next pattern line, handle delay and break\n\t\tmt_SilCntValid = 0; // recalculate silence counters\n\t\tUBYTE ubOffs = 16; // Offset to next pattern line\n\t\tUBYTE ubPatternDelay = mt_PattDelTime2;\n\t\tif(mt_PattDelTime) {\n\t\t\tubPatternDelay = mt_PattDelTime;\n\t\t\tmt_PattDelTime = 0;\n\t\t}\n\t\t// logWrite(\"pattern delay: %hhu\\n\", ubPatternDelay);\n\t\tif(ubPatternDelay) {\n\t\t\t--ubPatternDelay;\n\t\t\tif(ubPatternDelay) {\n\t\t\t\tubOffs = 0; // Do not advance to next line\n\t\t\t}\n\t\t\telse {\n\t\t\t\t// logWrite(\"Advance to next line\\n\");\n\t\t\t}\n\t\t\tmt_PattDelTime2 = ubPatternDelay;\n\t\t}\n\t\tUWORD uwNextLinePos = mt_PatternPos + ubOffs;\n\n\t\t// Check for break\n\t\tif(mt_PBreakFlag) {\n\t\t\tmt_PBreakFlag = 0;\n\t\t\tuwNextLinePos = mt_PBreakPos;\n\t\t\tmt_PBreakPos = 0;\n\t\t}\n\n\t\t// Check whether end of pattern is reached\n\t\tmt_PatternPos = uwNextLinePos;\n\t\tif(uwNextLinePos >= 1024) {\n\t\t\tptSongStep();\n\t\t}\n\t}\n\tif(mt_PosJumpFlag) {\n\t\tptSongStep();\n\t}\n}\n\n/**\n * @brief Resets channel status. All registers are preserved!\n *\n * @param pChannel\n */\nstatic void resetChannel(tChannelStatus *pChannel) {\n\tpChannel->uwPeriod = 320; // make sure period is not illegal\n\tpChannel->uwVolume = 0;\n\tpChannel->uwSfxWordLength = 0;\n\tpChannel->uwFunkSpeed = 0;\n\tpChannel->ubSfxPriority = 0;\n\tpChannel->isLooped = 0;\n\tpChannel->n_gliss = 0;\n}\n\n// Stop playing current module.\nvoid ptplayerStop(void) {\n\tptplayerEnableMusic(0);\n\tfor(UBYTE i = 0; i < 4; ++i) {\n\t\tif(mt_chan[i].isEnabledForPlayer) {\n\t\t\tsystemSetDmaMask(mt_chan[i].uwDmaFlag, 0);\n\t\t}\n\t\tresetChannel(&mt_chan[i]);\n\t}\n\ts_pCurrentMod = 0;\n\n\t// Free the channels taken by SFX.\n\t// Typically they would release themselves but turning off DMA prevents this.\n\tmt_chan[0].ubSfxPriority = 0;\n\tmt_chan[1].ubSfxPriority = 0;\n\tmt_chan[2].ubSfxPriority = 0;\n\tmt_chan[3].ubSfxPriority = 0;\n}\n\nstatic inline void setTempo(UWORD uwTempo) {\n#if !defined(PTPLAYER_USE_VBL)\n\tsystemSetTimer(CIA_B, 0, mt_timerval / uwTempo);\n#endif\n}\n\nstatic void mt_reset(void) {\n\t// Load TimerA in continuous mode for the default tempo of 125.\n\t// Note to self: make sure this is called when changing MODs.\n\tsetTempo(125);\n#if !defined(PTPLAYER_USE_VBL)\n\tsystemSetCiaCr(CIA_B, 0, CIACRA_LOAD | CIACRA_START); // load timer, start continuous\n#endif\n\n\t// Load TimerB with DMA_DELAY ticks for setting DMA and repeat\n\tsystemSetTimer(CIA_B, 1, DMA_DELAY);\n\n\t// Enable CIA B interrupts\n\tg_pCustom->intena = INTF_SETCLR | INTF_EXTER;\n\n\t// reset speed and counters\n\tmt_Speed = 6;\n\tmt_Counter = 0;\n\tmt_PatternPos = 0;\n\tmt_SongPos = 0;\n\tmt_PattDelTime = 0;\n\tmt_PattDelTime2 = 0;\n\tmt_PBreakPos = 0;\n\tmt_PBreakFlag = 0;\n\tmt_PosJumpFlag = 0;\n\n#if defined(PTPLAYER_USE_AUDIO_INT_HANDLERS)\n\t// Set all channels as done in case of waiting for sfx before any have been\n\t// actually played.\n\ts_uChannelDone.ulChannelMask = 0x01010101;\n#endif\n\n\t// Disable the filter\n\tg_pCia[CIA_A]->pra |= BV(1);\n\n\t// initialise channel DMA, interrupt bits and audio register base\n\t// make sure uwPeriod doesn't start as 0\n\t// disable sound effects\n\tfor(UBYTE i = 4; i--;) {\n\t\tmt_chan[i].uwDmaFlag = 1 << (DMAB_AUD0 + i);\n\t#if defined(PTPLAYER_USE_AUDIO_INT_HANDLERS)\n\t\tmt_chan[i].ubChannelIndex = i;\n\t\tmt_chan[i].pDoneBit = &s_uChannelDone.pChannels[i];\n\t#endif\n\t}\n\n\tmt_SilCntValid = 0;\n\tmt_E8Trigger = 0;\n\ts_isNextTimerBSetRep = 0;\n\tptplayerStop();\n}\n\n#if defined(PTPLAYER_USE_AUDIO_INT_HANDLERS)\nstatic void INTERRUPT onAudio(\n\tREGARG(volatile tCustom *pCustom, \"a0\"),\n\tREGARG(volatile void *pData, \"a1\")\n) {\n\tUBYTE ubChannelIndex = (ULONG)pData;\n\ts_uChannelDone.pChannels[ubChannelIndex] = 1;\n\n\tif(s_pAudioChannelPendingDisable[ubChannelIndex]) {\n\t\t// This is to prevent repeatedly triggering audio interrupt and slowing\n\t\t// Amiga down after sfx playback.\n\t\ts_pAudioChannelPendingDisable[ubChannelIndex] = 0;\n\t\tsystemSetDmaMask(DMAF_AUD0 << ubChannelIndex, 0);\n\t\tpCustom->aud[ubChannelIndex].ac_dat = 0;\n\t}\n};\n#endif\n\nvoid ptplayerDestroy(void) {\n\tptplayerStop();\n\t// Disable handling of music\n\tptplayerEnableMusic(0);\n\tptplayerEnableMainHandler(0);\n\tsystemSetCiaInt(CIA_B, CIAICRB_TIMER_B, 0, 0);\n#if defined(PTPLAYER_USE_AUDIO_INT_HANDLERS)\n\tsystemSetInt(INTB_AUD0, 0, 0);\n\tsystemSetInt(INTB_AUD1, 0, 0);\n\tsystemSetInt(INTB_AUD2, 0, 0);\n\tsystemSetInt(INTB_AUD3, 0, 0);\n#endif\n}\n\nvoid ptplayerCreate(UBYTE isPal) {\n\ts_isRepeat = 1;\n\ts_cbSongEnd = 0;\n\ts_cbOnE8 = 0;\n\ts_pCurrentMod = 0;\n\tptplayerEnableMusic(0);\n#if defined(PTPLAYER_USE_AUDIO_INT_HANDLERS)\n\tfor(UBYTE i = sizeof(s_pAudioChannelPendingDisable); i--;) {\n\t\ts_pAudioChannelPendingDisable[i] = 0;\n\t}\n#endif\n#if defined(PTPLAYER_DEFER_INTERRUPTS)\n\ts_isPendingDmaOn = 0;\n\ts_isPendingPlay = 0;\n\ts_isPendingSetRep = 0;\n#endif\n\n\t// disable CIA B interrupts, set player interrupt vector\n\tg_pCustom->intena = INTF_EXTER;\n\tptplayerEnableMainHandler(1);\n\tsystemSetCiaInt(CIA_B, CIAICRB_TIMER_B, mt_TimerBInt, 0);\n#if defined(PTPLAYER_USE_AUDIO_INT_HANDLERS)\n\tsystemSetInt(INTB_AUD0, onAudio, (void*)0);\n\tsystemSetInt(INTB_AUD1, onAudio, (void*)1);\n\tsystemSetInt(INTB_AUD2, onAudio, (void*)2);\n\tsystemSetInt(INTB_AUD3, onAudio, (void*)3);\n#endif\n\n\tptplayerSetPal(isPal);\n\tmt_MasterVolTab = MasterVolTab[64];\n\tfor(UBYTE i = 0; i < 4; ++i) {\n\t\tmt_chan[i].isEnabledForPlayer = 1;\n\t}\n\tmt_reset();\n}\n\nvoid ptplayerSetPal(UBYTE isPal) {\n\t// determine if 02 clock for timers is based on PAL or NTSC\n\ts_isPal = isPal;\n\tif(s_isPal) {\n\t\t// Fcolor = 4.43361825 MHz (PAL color carrier frequency)\n\t\t// CPU Clock = Fcolor * 1.6 = 7.0937892 MHz\n\t\t// CIA Clock = Cpu Clock / 10 = 709.37892 kHz\n\t\t// 50 Hz Timer = CIA Clock / 50 = 14187.5784\n\t\t// Tempo num. = 50 Hz Timer*125 = 1773447\n\t\tmt_timerval = 1773447;\n\t}\n\telse {\n\t\tmt_timerval = 1789773;\n\t}\n}\n\nvoid ptplayerLoadMod(\n\ttPtplayerMod *pMod, tPtplayerSamplePack *pExternalSamples,\n\tUWORD uwInitialSongPos\n) {\n\tlogBlockBegin(\n\t\t\"ptplayerLoadMod(pMod: %p, pExternalSamples: %p, uwInitialSongPos: %hu)\",\n\t\tpMod, pExternalSamples, uwInitialSongPos\n\t);\n\n\t// Initialize new module.\n\t// Reset speed to 6, tempo to 125 and start at given song position.\n\t// Master volume is at 64 (maximum).\n\ts_pCurrentMod = pMod;\n\tlogWrite(\n\t\t\"Song name: '%s', arrangement length: %hhu, end pos: %hhu\\n\",\n\t\ts_pCurrentMod->szSongName, s_pCurrentMod->ubArrangementLength, s_pCurrentMod->ubSongEndPos\n\t);\n\n\t// set initial song position\n\tif(uwInitialSongPos >= 950) {\n\t\tuwInitialSongPos = 0;\n\t}\n\n\t// sample data location is given?\n\tif(pExternalSamples) {\n\t\tlogWrite(\"Using sample data from: %p\\n\", pExternalSamples);\n\t\tfor(UBYTE i = 0; i < PTPLAYER_MOD_SAMPLE_COUNT; ++i) {\n\t\t\tmt_SampleStarts[i] = pExternalSamples->pSamples[i].pData;\n\t\t};\n\t}\n\telse {\n\t\tfor(UBYTE i = 0; i < PTPLAYER_MOD_SAMPLE_COUNT; ++i) {\n\t\t\tmt_SampleStarts[i] = pMod->pSampleStarts[i];\n\t\t}\n\t}\n\n\tfor(UBYTE i = 0; i < PTPLAYER_MOD_SAMPLE_COUNT; ++i) {\n\t\tconst tPtplayerSampleHeader *pHeader = &s_pCurrentMod->pSampleHeaders[i];\n\t\tif(s_pCurrentMod->pSampleHeaders[i].uwLength > 0) {\n\t\t\t// Make sure each sample starts with two 0-bytes\n\t\t\tmt_SampleStarts[i][0] = 0;\n\t\t\tlogWrite(\n\t\t\t\t\"Sample %hhu name: '%.*s', word length: %hu, start: %p, repeat offs: %hu, repeat len:%hu\\n\",\n\t\t\t\ti, 22, pHeader->szName, pHeader->uwLength,\n\t\t\t\tmt_SampleStarts[i], pHeader->uwRepeatOffs, pHeader->uwRepeatLength\n\t\t\t);\n\t\t\tif(pHeader->uwRepeatOffs + pHeader->uwRepeatLength > pHeader->uwLength) {\n\t\t\t\tlogWrite(\"ERR: Repeat offs + repeat length > length\\n\");\n\t\t\t}\n\t\t}\n\t}\n\n\tmt_reset();\n\ts_pCurrentMod = pMod;\n\tmt_SongPos = uwInitialSongPos;\n\tlogBlockEnd(\"ptplayerLoadMod()\");\n}\n\nvoid ptplayerSetMusicChannelMask(UBYTE ChannelMask) {\n\tg_pCustom->intena = INTF_INTEN;\n\tmt_chan[0].isOnlyForMusic = BTST(ChannelMask, 0);\n\tmt_chan[1].isOnlyForMusic = BTST(ChannelMask, 1);\n\tmt_chan[2].isOnlyForMusic = BTST(ChannelMask, 2);\n\tmt_chan[3].isOnlyForMusic = BTST(ChannelMask, 3);\n\n\tg_pCustom->intena = INTF_SETCLR | INTF_INTEN;\n}\n\nstatic void setAllVolumes(void) {\n\t// Only set volume for channels used in MOD playback.\n\tif (!mt_chan[0].ubSfxPriority && mt_chan[0].isEnabledForPlayer) {\n\t\tg_pCustom->aud[0].ac_vol = mt_MasterVolTab[mt_chan[0].uwVolume];\n\t}\n\tif (!mt_chan[1].ubSfxPriority && mt_chan[1].isEnabledForPlayer) {\n\t\tg_pCustom->aud[1].ac_vol = mt_MasterVolTab[mt_chan[1].uwVolume];\n\t}\n\tif (!mt_chan[2].ubSfxPriority && mt_chan[2].isEnabledForPlayer) {\n\t\tg_pCustom->aud[2].ac_vol = mt_MasterVolTab[mt_chan[2].uwVolume];\n\t}\n\tif (!mt_chan[3].ubSfxPriority && mt_chan[3].isEnabledForPlayer) {\n\t\tg_pCustom->aud[3].ac_vol = mt_MasterVolTab[mt_chan[3].uwVolume];\n\t}\n}\n\nvoid ptplayerSetMasterVolume(UBYTE ubMasterVolume) {\n\t// TODO: expose define which would make this function calculate current volume\n\t// table instead of toring 4KB of table data.\n\tg_pCustom->intena = INTF_INTEN;\n\n\t// Set new table and adapt all channel volumes immediately\n\tmt_MasterVolTab = MasterVolTab[ubMasterVolume];\n\tsetAllVolumes();\n\n\tg_pCustom->intena = INTF_SETCLR | INTF_INTEN;\n}\n\nvoid ptplayerSetChannelsForPlayer(UBYTE ubChannelMask) {\n\tg_pCustom->intena = INTF_INTEN;\n\tmt_chan[0].isEnabledForPlayer = BTST(ubChannelMask, 0);\n\tmt_chan[1].isEnabledForPlayer = BTST(ubChannelMask, 1);\n\tmt_chan[2].isEnabledForPlayer = BTST(ubChannelMask, 2);\n\tmt_chan[3].isEnabledForPlayer = BTST(ubChannelMask, 3);\n\tsetAllVolumes();\n\tg_pCustom->intena = INTF_SETCLR | INTF_INTEN;\n}\n\n//-------------------------------------------------- COMMANDS WITHOUT CMD PASSED\n\nstatic void mt_toneporta_nc(\n\ttChannelStatus *pChannelData, volatile tChannelRegs *pChannelReg\n) {\n\tif(pChannelData->n_wantedperiod) {\n\t\tWORD wNew;\n\t\tif(pChannelData->uwPeriod > pChannelData->n_wantedperiod) {\n\t\t\t// tone porta up\n\t\t\twNew = pChannelData->uwPeriod - pChannelData->n_toneportspeed;\n\t\t\tif(wNew < pChannelData->n_wantedperiod) {\n\t\t\t\twNew = pChannelData->n_wantedperiod;\n\t\t\t\tpChannelData->n_wantedperiod = 0;\n\t\t\t}\n\t\t}\n\t\telse {\n\t\t\t// tone porta down\n\t\t\twNew = pChannelData->uwPeriod + pChannelData->n_toneportspeed;\n\t\t\tif(wNew > pChannelData->n_wantedperiod) {\n\t\t\t\twNew = pChannelData->n_wantedperiod;\n\t\t\t\tpChannelData->n_wantedperiod = 0;\n\t\t\t}\n\t\t}\n\t\tpChannelData->uwPeriod = wNew;\n\t\tif(pChannelData->n_gliss) {\n\t\t\t// glissando: find nearest note for new period\n\t\t\tconst UWORD *pPeriodTable = pChannelData->pPeriodTable;\n\t\t\tUWORD uwNoteOffs = 0;\n\t\t\tUBYTE ubPeriodPos = findPeriod(pChannelData->pPeriodTable, uwNoteOffs);\n\t\t\tpChannelData->n_noteoff = ubPeriodPos * 2;\n\t\t\twNew = pPeriodTable[ubPeriodPos];\n\t\t}\n\t\tpChannelReg->ac_per = wNew;\n\t}\n}\n\nstatic void mt_vibrato_nc(\n\ttChannelStatus *pChannelData, volatile tChannelRegs *pChannelReg,\n\tUBYTE ubAmplitude, UBYTE ubSpeed\n) {\n\t// calculate vibrato table offset\n\tUBYTE ubOffs = 64 * ubAmplitude + (pChannelData->n_vibratopos & 63);\n\n\t// select vibrato waveform\n\tconst BYTE *pTable;\n\tUBYTE ubCtl = pChannelData->n_vibratoctrl & 3;\n\tif(!ubCtl) {\n\t\tpTable = mt_VibratoSineTable;\n\t}\n\telse if(ubCtl == 1) {\n\t\tpTable = mt_VibratoSawTable;\n\t}\n\telse {\n\t\t// ctrl 2 & 3 select a rectangle vibrato\n\t\tpTable = mt_VibratoRectTable;\n\t}\n\n\t// add vibrato-offset to period\n\tpChannelReg->ac_per = pChannelData->uwPeriod + pTable[ubOffs];\n\n\t// Increase vibratopos by speed\n\tpChannelData->n_vibratopos += ubSpeed;\n}\n\n//-------------------------------------------------------- EFFECTS WITH CMD WORD\n\nstatic void mt_nop(\n\tUNUSED_ARG UBYTE ubArgs, UNUSED_ARG tChannelStatus *pChannelData,\n\tUNUSED_ARG volatile tChannelRegs *pChannelReg\n) {\n\n}\n\nstatic void mt_arpeggio(\n\tUBYTE ubArgs, tChannelStatus *pChannelData,\n\tvolatile tChannelRegs *pChannelReg\n) {\n\t// uwCmd: 0x00'XY (x = first arpeggio offset, y = second arpeggio offset)\n\tstatic const BYTE pArpTab[] = {\n\t\t0, 1, -1, 0, 1, -1, 0, 1, -1, 0, 1, -1, 0, 1, -1, 0,\n\t\t1, -1, 0, 1, -1, 0, 1, -1, 0, 1, -1, 0, 1, -1, 0, 1\n\t};\n\n\t// Step 0, just use normal period\n\tpChannelReg->ac_per = pChannelData->uwPeriod;\n\n\tUWORD uwVal;\n\tif(pArpTab[mt_Counter] >= 0) {\n\t\t// Step 1, arpeggio by left nibble\n\t\tuwVal = ubArgs >> 4;\n\t}\n\telse {\n\t\t// Step 2, arpeggio by right nibble\n\t\tuwVal = ubArgs & 0xF;\n\t}\n\t// offset current note\n\tuwVal *= 2;\n\tuwVal += pChannelData->n_noteoff;\n\tif(uwVal < 2 * 36) {\n\t\t// Set period with arpeggio offset from note table\n\t\tpChannelReg->ac_per = pChannelData->pPeriodTable[uwVal / 2];\n\t\t// TODO later: noteoff has byte offs from start of array, set it to divided\n\t\t// by 2 since we're using UWORD pointers, not UBYTE\n\t}\n}\n\nstatic void ptDoPortaUp(\n\tUBYTE ubVal, tChannelStatus *pChannelData,\n\tvolatile tChannelRegs *pChannelReg\n) {\n\tUWORD uwNewPer = MAX(113, pChannelData->uwPeriod - ubVal);\n\tpChannelData->uwPeriod = uwNewPer;\n\tpChannelReg->ac_per = uwNewPer;\n}\n\nstatic void mt_portaup(\n\tUBYTE ubArgs, tChannelStatus *pChannelData,\n\tvolatile tChannelRegs *pChannelReg\n) {\n\t// cmd 1 x x (subtract xx from period)\n\tptDoPortaUp(ubArgs, pChannelData, pChannelReg);\n}\n\nstatic void ptDoPortaDn(\n\tUBYTE ubVal, tChannelStatus *pChannelData,\n\tvolatile tChannelRegs *pChannelReg\n) {\n\tUWORD uwNewPer = MIN(pChannelData->uwPeriod + ubVal, 856);\n\tpChannelData->uwPeriod = uwNewPer;\n\tpChannelReg->ac_per = uwNewPer;\n}\n\nstatic void mt_portadown(\n\tUBYTE ubArgs, tChannelStatus *pChannelData,\n\tvolatile tChannelRegs *pChannelReg\n) {\n\t// cmd 2 x x (add xx to period)\n\tptDoPortaDn(ubArgs, pChannelData, pChannelReg);\n}\n\nstatic void mt_toneporta(\n\tUBYTE ubArgs, tChannelStatus *pChannelData,\n\tvolatile tChannelRegs *pChannelReg\n) {\n\t// uwCmd: 0x03'XY (xy = tone portamento speed)\n\tif(ubArgs) {\n\t\tpChannelData->n_toneportspeed = ubArgs;\n\t\tpChannelData->sVoice.ubCmdLo = 0;\n\t}\n\tmt_toneporta_nc(pChannelData, pChannelReg);\n}\n\nstatic void mt_vibrato(\n\tUBYTE ubArgs, tChannelStatus *pChannelData,\n\tvolatile tChannelRegs *pChannelReg\n) {\n\t// uwCmd: 0x04'XY (x = speed, y = amplitude)\n\tUBYTE ubAmplitude = ubArgs & 0xF;\n\tif(ubAmplitude) {\n\t\tpChannelData->n_vibratoamp = ubAmplitude;\n\t}\n\telse {\n\t\tubAmplitude = pChannelData->n_vibratoamp;\n\t}\n\tUBYTE ubSpeed = ubArgs >> 4;\n\tif(ubSpeed) {\n\t\tpChannelData->n_vibratospd = ubSpeed;\n\t}\n\telse {\n\t\tubSpeed = pChannelData->n_vibratospd;\n\t}\n\tmt_vibrato_nc(pChannelData, pChannelReg, ubAmplitude, ubSpeed);\n}\n\nstatic void ptVolSlide(\n\tBYTE bVolNew, tChannelStatus *pChannelData,\n\tvolatile tChannelRegs *pChannelReg\n) {\n\tbVolNew = CLAMP(bVolNew, 0, 64);\n\tpChannelData->uwVolume = bVolNew;\n\tpChannelReg->ac_per = pChannelData->uwPeriod;\n\tpChannelReg->ac_vol = mt_MasterVolTab[bVolNew];\n}\n\nstatic void mt_volumeslide(\n\tUBYTE ubArgs, tChannelStatus *pChannelData,\n\tvolatile tChannelRegs *pChannelReg\n) {\n\t// uwCmd: 0x0A'XY (x = volume-up, y = volume-down)\n\tUBYTE ubVolDn  = ubArgs & 0x0F;\n\tUBYTE ubVolUp = ubArgs >> 4;\n\n\tBYTE bVol = pChannelData->uwVolume;\n\tif(ubVolUp) {\n\t\t// Slide up, until 64\n\t\tptVolSlide(bVol + ubVolUp, pChannelData, pChannelReg);\n\t}\n\telse {\n\t\t// Slide down, until 0\n\t\tptVolSlide(bVol - ubVolDn, pChannelData, pChannelReg);\n\t}\n}\n\nstatic void mt_tonevolslide(\n\tUBYTE ubArgs, tChannelStatus *pChannelData,\n\tvolatile tChannelRegs *pChannelReg\n) {\n\t// uwCmd: 0x05'XY (x = volume up, y = volume down)\n\tmt_toneporta_nc(pChannelData, pChannelReg);\n\n\t// Do a volume slide with current cmd's args\n\tmt_volumeslide(ubArgs, pChannelData, pChannelReg);\n}\n\nstatic void mt_vibrvolslide(\n\tUBYTE ubArgs, tChannelStatus *pChannelData,\n\tvolatile tChannelRegs *pChannelReg\n) {\n\t// uwCmd: 0x06'XY (x = volume-up, y = volume-down)\n\n\t// Do vibrato with previously stored args\n\tmt_vibrato_nc(\n\t\tpChannelData, pChannelReg,\n\t\tpChannelData->n_vibratoamp, pChannelData->n_vibratospd\n\t);\n\n\t// Do a volume slide with current cmd's args\n\tmt_volumeslide(ubArgs, pChannelData, pChannelReg);\n}\n\nstatic void mt_tremolo(\n\tUBYTE ubArgs, tChannelStatus *pChannelData, volatile tChannelRegs *pChannelReg\n) {\n\t// uwCmd: 0x07'XY (x = speed, y = amplitude)\n\tUBYTE ubAmplitude = ubArgs & 0x0F;\n\tUBYTE ubSpeed = ubArgs >> 4;\n\tif(ubAmplitude) {\n\t\tpChannelData->n_tremoloamp = ubAmplitude;\n\t}\n\telse {\n\t\tubAmplitude = pChannelData->n_tremoloamp;\n\t}\n\tif(ubSpeed) {\n\t\tpChannelData->n_tremolospd = ubSpeed;\n\t}\n\telse {\n\t\tubSpeed = pChannelData->n_tremolospd;\n\t}\n\n\t// calculate tremolo table offset\n\tUWORD uwOffset = 64 * ubAmplitude + (pChannelData->n_tremolopos & 63);\n\n\t// select tremolo waveform\n\tUBYTE ubWaveformIdx = pChannelData->n_tremoloctrl & 3;\n\tconst BYTE *pWaveform;\n\tif(ubWaveformIdx == 0) {\n\t\t// ctrl 0 selects a sine tremolo\n\t\tpWaveform = mt_VibratoSineTable;\n\t}\n\telse if(ubWaveformIdx == 1) {\n\t\t// ctrl 1 selects a sawtooth tremolo\n\t\tpWaveform = mt_VibratoSawTable;\n\t}\n\telse {\n\t\t// ctrl 2 & 3 select a rectangle tremolo\n\t\tpWaveform = mt_VibratoRectTable;\n\t}\n\n\t// add tremolo-offset to volume\n\tWORD wNewVol = pChannelData->uwVolume + pWaveform[uwOffset];\n\twNewVol = CLAMP(wNewVol, 0, 64);\n\n\tpChannelReg->ac_per = pChannelData->uwPeriod;\n\tpChannelReg->ac_vol = wNewVol;\n\n\t// increase tremolopos by speed\n\tpChannelData->n_tremolopos += ubSpeed;\n}\n\nstatic void mt_e_cmds(\n\tUBYTE ubArgs, tChannelStatus *pChannelData,\n\tvolatile tChannelRegs *pChannelReg\n) {\n\t// uwCmd: 0x0E'XY (x = command, y = argument)\n\tUBYTE ubArgE = ubArgs & 0x0F;\n\tUBYTE ubCmdE = (ubArgs & 0xF0) >> 4;\n#if defined(ACE_DEBUG_PTPLAYER)\n\tif(ubCmdE >= 16) {\n\t\tlogWrite(\"ERR: ecmd_tab index out of range: cmd %hhu\\n\", ubCmdE);\n\t}\n#endif\n\tecmd_tab[ubCmdE](ubArgE, pChannelData, pChannelReg);\n}\n\n/**\n * @brief Protracker commands\n */\nstatic const tFx fx_tab[16] = {\n\tmt_arpeggio,\n\tmt_portaup,\n\tmt_portadown,\n\tmt_toneporta,\n\tmt_vibrato,\n\tmt_tonevolslide,\n\tmt_vibrvolslide,\n\tmt_tremolo,\n\tmt_nop,\n\tmt_nop,\n\tmt_volumeslide,\n\tmt_nop,\n\tmt_nop,\n\tmt_nop,\n\tmt_e_cmds,\n\tmt_nop\n};\n\n//---------------------------------------------------------------- MORE FX TABLE\n\nstatic void mt_posjump(\n\tUBYTE ubArgs, UNUSED_ARG tChannelStatus *pChannelData,\n\tUNUSED_ARG volatile tChannelRegs *pChannelReg\n) {\n\t// uwCmd: 0x0B'XY (xy = new song position)\n\tmt_SongPos = ubArgs - 1;\n\tmt_PBreakPos = 0;\n\tmt_PosJumpFlag = 1;\n}\n\nstatic void mt_patternbrk(\n\tUBYTE ubArgs, UNUSED_ARG tChannelStatus *pChannelData,\n\tUNUSED_ARG volatile tChannelRegs *pChannelReg\n) {\n\t// uwCmd: 0x0D'XY (xy = break pos in decimal)\n\n\tstatic const UBYTE pMult10[] = {\n\t\t0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 0, 0, 0, 0, 0, 0\n\t};\n\n\tUBYTE ubY = ubArgs & 0xF;\n\tUBYTE ubX = ubArgs >> 4;\n\tUBYTE ubVal = pMult10[ubX] + ubY;\n\n\tif(ubVal > 63) {\n\t\tmt_PBreakPos = 0;\n\t}\n\telse {\n\t\tmt_PBreakPos = ubVal << 4;\n\t}\n\tmt_PosJumpFlag = 1;\n}\n\nstatic void blocked_e_cmds(\n\tUBYTE ubArgs, tChannelStatus *pChannelData,\n\tvolatile tChannelRegs *pChannelReg\n) {\n\t// uwCmd: 0x0E'XY (x = command, y = argument)\n\tUBYTE ubArg = ubArgs & 0x0F;\n\tUBYTE ubCmdE = (ubArgs & 0xF0) >> 4;\n#if defined(ACE_DEBUG_PTPLAYER)\n\tif(ubCmdE >= 16) {\n\t\tlogWrite(\"ERR: blecmd_tab index out of range: cmd %hhu\\n\", ubCmdE);\n\t}\n#endif\n\tblecmd_tab[ubCmdE](ubArg, pChannelData, pChannelReg);\n}\n\nstatic void mt_setspeed(\n\tUBYTE ubArgs, UNUSED_ARG tChannelStatus *pChannelData,\n\tUNUSED_ARG volatile tChannelRegs *pChannelReg\n) {\n\t// uwCmd: 0x0F'XY (xy < 0x20: new speed, xy >= 0x20: new tempo)\n\tif(ubArgs < 0x20) {\n\t\tmt_Speed = ubArgs;\n\t\tif(!ubArgs) {\n\t\t\tptplayerStop();\n\t\t}\n\t}\n\telse {\n\t\t// Set tempo (CIA only)\n\t\tsetTempo(ubArgs);\n\t}\n}\n\nstatic void mt_pernop(\n\tUNUSED_ARG UBYTE ubArgs,\n\ttChannelStatus *pChannelData, volatile tChannelRegs *pChannelReg\n) {\n\t// just set the current period\n\tpChannelReg->ac_per = pChannelData->uwPeriod;\n}\n\nstatic void mt_volchange(\n\tUBYTE ubNewVolume,\n\tUNUSED_ARG tChannelStatus *pChannelData, volatile tChannelRegs *pChannelReg\n) {\n\t// cmd C x y (xy = new volume)\n\tif(ubNewVolume > 64) {\n\t\tubNewVolume = 64;\n\t}\n\tpChannelReg->ac_vol = mt_MasterVolTab[ubNewVolume];\n}\n\nstatic void mt_sampleoffset(\n\tUBYTE ubArg, tChannelStatus *pChannelData,\n\tUNUSED_ARG volatile tChannelRegs *pChannelReg\n) {\n\t// cmd 9 x y (xy = offset in 256's of bytes)\n\t// d4 = xy\n\tif(!ubArg) {\n\t\tubArg = pChannelData->n_sampleoffset;\n\t}\n\telse {\n\t\tpChannelData->n_sampleoffset = ubArg;\n\t}\n\n\t// Offset is in 256s of bytes, length is in words\n\tUWORD uwLength = ubArg * (256 / sizeof(UWORD));\n\tif(uwLength < pChannelData->n_length) {\n\t\tpChannelData->n_length -= uwLength;\n\t\tpChannelData->n_start += uwLength;\n\t}\n\telse {\n\t\tpChannelData->n_length = 1;\n\t}\n}\n\nstatic const tFx blmorefx_tab[16] = {\n\t[0 ... 0x0A] = mt_nop,\n\t[0x0B] = mt_posjump,\n\t[0x0C] = mt_nop,\n\t[0x0D] = mt_patternbrk,\n\t[0x0E] = blocked_e_cmds,\n\t[0x0F] = mt_setspeed,\n};\n\nstatic const tFx morefx_tab[16] = {\n\t[0 ... 0x08] = mt_pernop,\n\t[0x09] = mt_sampleoffset,\n\t[0x0A] = mt_pernop,\n\t[0x0B] = mt_posjump,\n\t[0x0C] = mt_volchange,\n\t[0x0D] = mt_patternbrk,\n\t[0x0E] = mt_e_cmds,\n\t[0x0F] = mt_setspeed\n};\n\n//----------------------------------------------------------------- E CMDS TABLE\n\nstatic void mt_filter(\n\tUBYTE ubArg, UNUSED_ARG tChannelStatus *pChannelData,\n\tUNUSED_ARG volatile tChannelRegs *pChannelReg\n) {\n\t// cmd 0x0E'0X (x=1 disable, x=0 enable)\n\tif(ubArg & 1) {\n\t\tg_pCia[CIA_A]->pra |= BV(1);\n\t}\n\telse {\n\t\tg_pCia[CIA_A]->pra &= ~BV(1);\n\t}\n}\n\nstatic void mt_fineportaup(\n\tUBYTE ubArg, tChannelStatus *pChannelData,\n\tvolatile tChannelRegs *pChannelReg\n) {\n\t// cmd 0x0E'1X (subtract x from period)\n\tif(!mt_Counter) {\n\t\tptDoPortaUp(ubArg, pChannelData, pChannelReg);\n\t}\n}\n\nstatic void mt_fineportadn(\n\tUBYTE ubArg, tChannelStatus *pChannelData,\n\tvolatile tChannelRegs *pChannelReg\n) {\n\t// cmd 0x0E'1X (subtract x from period)\n\tif(!mt_Counter) {\n\t\tptDoPortaDn(ubArg, pChannelData, pChannelReg);\n\t}\n}\n\nstatic void mt_glissctrl(\n\tUBYTE ubArg, tChannelStatus *pChannelData,\n\tUNUSED_ARG volatile tChannelRegs *pChannelReg\n) {\n\t// cmd 0x0E'3X (x = gliss)\n\tpChannelData->n_gliss = ubArg;\n}\n\nstatic void mt_vibratoctrl(\n\tUBYTE ubArg, tChannelStatus *pChannelData,\n\tUNUSED_ARG volatile tChannelRegs *pChannelReg\n) {\n\t// cmd 0x0E'4X (x = vibrato)\n\tpChannelData->n_vibratoctrl = ubArg;\n}\n\nstatic void mt_finetune(\n\tUBYTE ubArg, tChannelStatus *pChannelData,\n\tUNUSED_ARG volatile tChannelRegs *pChannelReg\n) {\n\t// cmd 0x0E'5X (x = finetune)\n\tpChannelData->pPeriodTable = mt_PeriodTables[ubArg];\n\tpChannelData->n_minusft = (ubArg >= 8);\n}\n\nstatic void mt_jumploop(\n\tUBYTE ubArg, tChannelStatus *pChannelData,\n\tUNUSED_ARG volatile tChannelRegs *pChannelReg\n) {\n\t// cmd 0x0E'6X (x = 0: loop start, else loop count)\n\tif(mt_Counter) {\n\t\treturn;\n\t}\n\tif(!ubArg) {\n\t\t// remember start of loop position\n\t\tpChannelData->n_pattpos = mt_PatternPos;\n\t\treturn;\n\t}\n\t// otherwise we are at the end of the loop\n\t--pChannelData->n_loopcount;\n\tif(!pChannelData->n_loopcount) {\n\t\t// loop finished\n\t\treturn;\n\t}\n\telse if(pChannelData->n_loopcount < 0) {\n\t\t// initialize loop counter\n\t\tpChannelData->n_loopcount  = ubArg;\n\t}\n\n\t// jump back to start of loop\n\tmt_PBreakPos = pChannelData->n_pattpos;\n\tmt_PBreakFlag = 1;\n}\n\nstatic void mt_tremoctrl(\n\tUBYTE ubArg, tChannelStatus *pChannelData,\n\tUNUSED_ARG volatile tChannelRegs *pChannelReg\n) {\n\t// cmd 0x0E'7X (x = tremolo)\n\tpChannelData->n_tremoloctrl = ubArg;\n}\n\nstatic void mt_e8(\n\tUBYTE ubArg, UNUSED_ARG tChannelStatus *pChannelData,\n\tUNUSED_ARG volatile tChannelRegs *pChannelReg\n) {\n\t// cmd 0x0E'8X (x = trigger value)\n\tmt_E8Trigger = ubArg;\n\tif(s_cbOnE8) {\n\t\ts_cbOnE8(ubArg);\n\t}\n}\n\nstatic void ptDoRetrigger(\n\ttChannelStatus *pChannelData, volatile tChannelRegs *pChannelReg\n) {\n\t// DMA off, set sample pointer and length\n\tsystemSetDmaMask(pChannelData->uwDmaFlag, 0);\n\t// logWrite(\"retrigger: %p:%hu\\n\", pChannelData->n_start, pChannelData->n_length);\n\tpChannelReg->ac_ptr = pChannelData->n_start;\n\tpChannelReg->ac_len = pChannelData->n_length;\n\tmt_dmaon |= pChannelData->uwDmaFlag;\n}\n\nstatic void mt_retrignote(\n\tUBYTE ubArg, tChannelStatus *pChannelData, volatile tChannelRegs *pChannelReg\n) {\n\t// cmd 0x0E'9X (x = retrigger count)\n\tif(!ubArg) {\n\t\treturn;\n\t}\n\n\t// set new retrigger count when Counter = 0\n\tif(!mt_Counter) {\n\t\tpChannelData->n_retrigcount = ubArg;\n\t\t// avoid double retrigger, when Counter=0 and a note was set\n\t\tif(pChannelData->sVoice.uwNote & 0x0FFF) {\n\t\t\treturn;\n\t\t}\n\t}\n\telse {\n\t\t// check if retrigger count is reached\n\t\t--pChannelData->n_retrigcount;\n\t\tif(pChannelData->n_retrigcount) {\n\t\t\treturn;\n\t\t}\n\t\t// reset\n\t\tpChannelData->n_retrigcount = ubArg;\n\t}\n\n\tptDoRetrigger(pChannelData, pChannelReg);\n}\n\nstatic void mt_volfineup(\n\tUBYTE ubArg, tChannelStatus *pChannelData, volatile tChannelRegs *pChannelReg\n) {\n\t// cmd 0x0E'AX (x = volume add)\n\tif(!mt_Counter) {\n\t\tptVolSlide(pChannelData->uwVolume + ubArg, pChannelData, pChannelReg);\n\t}\n}\n\nstatic void mt_volfinedn(\n\tUBYTE ubArg, tChannelStatus *pChannelData, volatile tChannelRegs *pChannelReg\n) {\n\t// cmd 0x0E'BX (x = volume subtract)\n\tif(!mt_Counter) {\n\t\tptVolSlide(pChannelData->uwVolume - ubArg, pChannelData, pChannelReg);\n\t}\n}\n\nstatic void mt_notecut(\n\tUBYTE ubArg, tChannelStatus *pChannelData, volatile tChannelRegs *pChannelReg\n) {\n\t// cmd 0x0E'CX (x = counter to cut at)\n\tif(mt_Counter == ubArg) {\n\t\tpChannelData->uwVolume = 0;\n\t\tpChannelReg->ac_vol = 0;\n\t}\n}\n\nstatic void mt_notedelay(\n\tUBYTE ubArg, tChannelStatus *pChannelData, volatile tChannelRegs *pChannelReg\n) {\n\t// cmd 0x0E'DX (x = counter to retrigger at)\n\tif(mt_Counter == ubArg) {\n\t\t// Trigger note when given\n\t\tif(pChannelData->sVoice.uwNote) {\n\t\t\tpChannelReg->ac_per = pChannelData->uwPeriod;\n\t\t\tptDoRetrigger(pChannelData, pChannelReg);\n\t\t}\n\t}\n}\n\nstatic void mt_patterndelay(\n\tUBYTE ubArg, UNUSED_ARG tChannelStatus *pChannelData,\n\tUNUSED_ARG volatile tChannelRegs *pChannelReg\n) {\n\t// cmd 0x0E'EX (x = delay count)\n\tif(!mt_Counter && !mt_PattDelTime2) {\n\t\tmt_PattDelTime = ubArg + 1;\n\t\t// logWrite(\"set pattern delay: %hu\\n\", mt_PattDelTime);\n\t}\n}\n\nstatic void mt_funk(\n\tUBYTE ubArg, tChannelStatus *pChannelData,\n\tUNUSED_ARG volatile tChannelRegs *pChannelReg\n) {\n\t// cmd 0x0E'FX (x = delay count)\n\tif(!mt_Counter) {\n\t\tpChannelData->uwFunkSpeed = ubArg;\n\t\tif(ubArg) {\n\t\t\tmt_updatefunk(pChannelData);\n\t\t}\n\t}\n}\n\nstatic const tEFn ecmd_tab[16] = {\n\tmt_filter,\n\tmt_fineportaup,\n\tmt_fineportadn,\n\tmt_glissctrl,\n\tmt_vibratoctrl,\n\tmt_finetune,\n\tmt_jumploop,\n\tmt_tremoctrl,\n\tmt_e8,\n\tmt_retrignote,\n\tmt_volfineup,\n\tmt_volfinedn,\n\tmt_notecut,\n\tmt_notedelay,\n\tmt_patterndelay,\n\tmt_funk\n};\n\nstatic const tEFn blecmd_tab[16] = {\n\tmt_filter,\n\tmt_nop, mt_nop,\n\tmt_glissctrl,\n\tmt_vibratoctrl,\n\tmt_finetune,\n\tmt_jumploop,\n\tmt_tremoctrl,\n\tmt_e8,\n\tmt_nop, mt_nop, mt_nop, mt_nop, mt_nop\n};\n\nstatic void set_period(\n\tUWORD uwCmd, UWORD uwCmdArg, UWORD uwMaskedCmdE, const tModVoice *pVoice,\n\ttChannelStatus *pChannelData, volatile tChannelRegs *pChannelReg\n) {\n\tUWORD uwNote = pVoice->uwNote & 0xFFF;\n\tUBYTE ubPeriodPos = findPeriod(mt_PeriodTables[0], uwNote);\n\n\t// Apply finetuning, set period and note-offset\n\tUWORD uwPeriod = pChannelData->pPeriodTable[ubPeriodPos];\n\tpChannelData->uwPeriod = uwPeriod;\n\tpChannelData->n_noteoff = ubPeriodPos * 2; // TODO later: convert to word offs (div by 2)\n\n\t// Check for notedelay\n\t// logWrite(\"cmd: %04X, masked E: %04X\\n\", uwCmd, uwMaskedCmdE);\n\t// Skip if notedelay\n\tif(uwMaskedCmdE != 0x0ED0) {\n\t\t// Disable DMA\n\t\tsystemSetDmaMask(pChannelData->uwDmaFlag, 0);\n\n\t\tif(!BTST(pChannelData->n_vibratoctrl, 2)) {\n\t\t\tpChannelData->n_vibratopos = 0;\n\t\t}\n\t\tif(!BTST(pChannelData->n_tremoloctrl, 2)) {\n\t\t\tpChannelData->n_tremolopos = 0;\n\t\t}\n\t\t// logWrite(\n\t\t// \t\"setperiod: ptr %p, len: %hu, period: %hu\\n\",\n\t\t// \tpChannelData->n_start, pChannelData->n_length, uwPeriod\n\t\t// );\n\n\t\tpChannelReg->ac_ptr = pChannelData->n_start;\n\t\tpChannelReg->ac_len = pChannelData->n_reallength;\n\t\tpChannelReg->ac_per = uwPeriod;\n\t\tmt_dmaon |= pChannelData->uwDmaFlag;\n\t}\n\tcheckmorefx(uwCmd, uwCmdArg, pChannelData, pChannelReg);\n}\n\nstatic void set_finetune(\n\tUWORD uwCmd, UWORD uwCmdArg, UWORD uwMaskedCmdE, const tModVoice *pVoice,\n\ttChannelStatus *pChannelData, volatile tChannelRegs *pChannelReg\n) {\n\t// logWrite(\"Set finetune\\n\");\n\tUBYTE ubFineTune = uwCmdArg & 0xF;\n\tpChannelData->pPeriodTable = mt_PeriodTables[ubFineTune];\n\tpChannelData->n_minusft = ubFineTune >= 8;\n\tset_period(uwCmd, uwCmdArg, uwMaskedCmdE, pVoice, pChannelData, pChannelReg);\n}\n\nstatic void set_sampleoffset(\n\tUWORD uwCmd, UWORD uwCmdArg, UWORD uwMaskedCmdE, const tModVoice *pVoice,\n\ttChannelStatus *pChannelData, volatile tChannelRegs *pChannelReg\n) {\n\t// logWrite(\"set_sampleoffset\\n\");\n\t// cmd 9 x y (xy = offset in 256 bytes)\n\t// d4 = xy\n\tmt_sampleoffset(uwCmdArg, pChannelData, pChannelReg);\n\tset_period(uwCmd, uwCmdArg, uwMaskedCmdE, pVoice, pChannelData, pChannelReg);\n}\n\nstatic void set_toneporta(\n\tUNUSED_ARG UWORD uwCmd, UNUSED_ARG UWORD uwCmdArg,\n\tUNUSED_ARG UWORD uwMaskedCmdE, const tModVoice *pVoice,\n\ttChannelStatus *pChannelData, volatile tChannelRegs *pChannelReg\n) {\n\t// Find first period which is less or equal the note in d6\n\tUWORD uwNote = pVoice->uwNote & 0xFFF;\n\tUBYTE ubPeriodPos = findPeriod(mt_PeriodTables[0], uwNote);\n\t// Original ASM code does something similar, but without those lines it sounds accurate and not out-of-tune\n\t// if(ubPeriodPos) {\n\t// \t// One before for less/equal\n\t// \t--ubPeriodPos;\n\t// }\n\n\t// if(pChannelData->n_minusft && ubPeriodPos) {\n\t// \t// Negative fine tune? Then take the previous period.\n\t// \t--ubPeriodPos;\n\t// }\n\n\t// Note offset in period table\n\tpChannelData->n_noteoff = ubPeriodPos * 2;\n\tUWORD uwPeriod = pChannelData->uwPeriod;\n\tUWORD uwNewPeriod = pChannelData->pPeriodTable[ubPeriodPos];\n\tif(uwNewPeriod == uwPeriod) {\n\t\tuwNewPeriod = 0;\n\t}\n\tpChannelData->n_wantedperiod = uwNewPeriod;\n\n\tif(pChannelData->uwFunkSpeed) {\n\t\tmt_updatefunk(pChannelData);\n\t}\n\n\tpChannelReg->ac_per = uwPeriod;\n}\n\nstatic const tPreFx prefx_tab[16] = {\n\t[0 ... 2] = set_period,\n\t[3] = set_toneporta,\n\t[4] = set_period,\n\t[5] = set_toneporta,\n\t[6 ... 8] = set_period,\n\t[9] = set_sampleoffset,\n\t[0xA ... 0xF] = set_period,\n};\n\n/**\n * @brief Get the Paula's Clock Constant.\n *\n * http://amigadev.elowar.com/read/ADCD_2.1/Hardware_Manual_guide/node00DE.html\n *\n * @return The current clock constant, dependent on PAL/NTSC mode.\n */\nstatic inline ULONG getClockConstant(void) {\n\treturn s_isPal ? 3546895 : 3579545;\n}\n\nstatic void ptplayerSfxDecompress(\n\tUBYTE *pCompressed, UBYTE *pDecompressed, ULONG ulDecompressedSize\n) {\n\tUBYTE *pRead = pCompressed;\n\tconst UBYTE *pDecompressedEnd = &pDecompressed[ulDecompressedSize];\n\tULONG ulCtl;\n\tBYTE bLastSample = 0;\n\twhile(1) {\n\t\tulCtl = *(pRead++);\n\t\tulCtl = (ulCtl << 8) | *(pRead++);\n\t\tulCtl = (ulCtl << 8) | *(pRead++);\n\t\tulCtl = (ulCtl << 8) | *(pRead++);\n\t\tfor(UBYTE i = 16; i--;) {\n\t\t\tUBYTE ubCtl = ulCtl & 0b11;\n\t\t\tif(ubCtl == 0) {\n\t\t\t\t*(pDecompressed++) = bLastSample;\n\t\t\t}\n\t\t\telse if(ubCtl == 0b11) {\n\t\t\t\tbLastSample = *(pRead++);\n\t\t\t\t*(pDecompressed++) = bLastSample;\n\t\t\t}\n\t\t\telse {\n\t\t\t\tUBYTE ubNibbles = *(pRead++);\n\n\t\t\t\tif(ubCtl == 0b01) {\n\t\t\t\t\tbLastSample += (ubNibbles & 0xF) + 1;\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tbLastSample -= (ubNibbles & 0xF) + 1;\n\t\t\t\t}\n\t\t\t\t*(pDecompressed++) = bLastSample;\n\n\t\t\t\tubNibbles >>= 4;\n\t\t\t\tulCtl >>= 2;\n\t\t\t\t--i;\n\t\t\t\tubCtl = ulCtl & 0b11;\n\t\t\t\tif(ubCtl == 0b01) {\n\t\t\t\t\tbLastSample += ubNibbles + 1;\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tbLastSample -= ubNibbles + 1;\n\t\t\t\t}\n\t\t\t\t*(pDecompressed++) = bLastSample;\n\t\t\t}\n\n\t\t\tif(pDecompressed >= pDecompressedEnd) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tulCtl >>= 2;\n\t\t}\n\t}\n}\n\nvoid ptplayerProcess(void) {\n#if defined(PTPLAYER_DEFER_INTERRUPTS)\n\tif(s_isPendingPlay) {\n\t\ts_isPendingPlay = 0;\n\t\tintPlay();\n\t}\n\tif(s_isPendingDmaOn) {\n\t\ts_isPendingDmaOn = 0;\n\t\tintDmaOn();\n\t}\n\tif(s_isPendingSetRep) {\n\t\ts_isPendingSetRep = 0;\n\t\tintSetRep(g_pCustom);\n\t}\n#endif\n}\n\nconst tModVoice *ptplayerGetCurrentVoices(void) {\n\tUBYTE *pPatternData = s_pCurrentMod->pPatterns;\n\tUBYTE *pArrangement = s_pCurrentMod->pArrangement;\n\tUBYTE ubPatternIdx = pArrangement[mt_SongPos];\n\tUBYTE *pCurrentPattern = &pPatternData[ubPatternIdx * 1024];\n\ttModVoice *pLineVoices = (tModVoice*)&pCurrentPattern[mt_PatternPos];\n\treturn pLineVoices;\n}\n\nvoid ptplayerGetVoiceProgress(UWORD *pCurr, UWORD *pMax) {\n\t*pCurr = mt_Counter;\n\t*pMax = mt_Speed;\n}\n\nvoid ptplayerEnableMusic(UBYTE isEnabled) {\n\tmt_Enable = isEnabled;\n\ts_isNextTimerBSetRep = 0;\n}\n\nUBYTE ptplayerGetE8(void) {\n\treturn mt_E8Trigger;\n}\n\nvoid ptplayerReserveChannelsForMusic(UBYTE ubChannelCount) {\n\tmt_MusicChannels = ubChannelCount;\n}\n\nvoid ptplayerSetSampleVolume(UBYTE ubSampleIndex, UBYTE ubVolume) {\n\ts_pCurrentMod->pSampleHeaders[ubSampleIndex].ubVolume = ubVolume;\n}\n\ntPtplayerMod *ptplayerModCreateFromPath(const char *szPath) {\n\treturn ptplayerModCreateFromFd(diskFileOpen(szPath, DISK_FILE_MODE_READ, 1));\n}\n\ntPtplayerMod *ptplayerModCreateFromFd(tFile *pFileMod) {\n\tlogBlockBegin(\"ptplayerModCreateFromFd(pFileMod: %p)\", pFileMod);\n\n\ttPtplayerMod *pMod = 0;\n\tLONG lSize = fileGetSize(pFileMod);\n\tif(lSize <= 0) {\n\t\tlogWrite(\"ERR: File doesn't exist\\n\");\n\t\tgoto fail;\n\t}\n\n\tpMod = memAllocFastClear(sizeof(*pMod));\n\tif(!pMod) {\n\t\treturn 0;\n\t}\n\n\t// Read header\n\tfileRead(pFileMod, pMod->szSongName, sizeof(pMod->szSongName));\n\t// TODO: read samples data field by field for portability\n\tfileRead(pFileMod, pMod->pSampleHeaders, sizeof(pMod->pSampleHeaders));\n\tfileRead(pFileMod, &pMod->ubArrangementLength, sizeof(pMod->ubArrangementLength));\n\tfileRead(pFileMod, &pMod->ubSongEndPos, sizeof(pMod->ubSongEndPos));\n\tfileRead(pFileMod, pMod->pArrangement, sizeof(pMod->pArrangement));\n\tfileRead(pFileMod, pMod->pFileFormatTag, sizeof(pMod->pFileFormatTag));\n\n\t// Get number of highest pattern\n\tUBYTE ubLastPattern = 0;\n\tfor(UBYTE i = 0; i < 127; ++i) {\n\t\tif(pMod->pArrangement[i] > ubLastPattern) {\n\t\t\tubLastPattern = pMod->pArrangement[i];\n\t\t}\n\t}\n\tUBYTE ubPatternCount = ubLastPattern + 1;\n\tlogWrite(\"Pattern count: %hhu\\n\", ubPatternCount);\n\n\t// Read pattern data\n\tpMod->ulPatternsSize = (ubPatternCount * MOD_PATTERN_BYTE_SIZE);\n\tpMod->pPatterns = memAllocFast(pMod->ulPatternsSize);\n\tif(!pMod->pPatterns) {\n\t\tlogWrite(\"ERR: Couldn't allocate memory for pattern data\");\n\t\tgoto fail;\n\t}\n\tfileRead(pFileMod, pMod->pPatterns, pMod->ulPatternsSize);\n\n\t// Read sample data\n\tULONG ulSampleStartPos = fileGetPos(pFileMod);\n\tULONG ulSamplesSize = lSize - ulSampleStartPos;\n\tif(ulSamplesSize) {\n\t\tfor(UBYTE ubSampleIndex = 0; ubSampleIndex < PTPLAYER_MOD_SAMPLE_COUNT; ++ubSampleIndex) {\n\t\t\tULONG ulSampleDataLength = pMod->pSampleHeaders[ubSampleIndex].uwLength * sizeof(UWORD);\n\t\t\tif(ulSampleDataLength) {\n\t\t\t\tpMod->pSampleStarts[ubSampleIndex] = memAllocChip(ulSampleDataLength);\n\t\t\t\tfileRead(pFileMod, pMod->pSampleStarts[ubSampleIndex], ulSampleDataLength);\n\t\t\t}\n\t\t}\n\t\tpMod->isOwningSamples = 1;\n\t}\n\telse {\n\t\tpMod->isOwningSamples = 0;\n\t\tlogWrite(\"MOD has no samples - be sure to pass sample pack to ptplayer\\n\");\n\t}\n\n\tfileClose(pFileMod);\n\tlogBlockEnd(\"ptplayerModCreateFromFd()\");\n\treturn pMod;\nfail:\n\tif(pMod) {\n\t\tif(pMod->pPatterns) {\n\t\t\tmemFree(pMod->pPatterns, pMod->ulPatternsSize);\n\t\t}\n\t\tif(pMod->isOwningSamples) {\n\t\t\tfor(UBYTE ubSampleIndex = 0; ubSampleIndex < PTPLAYER_MOD_SAMPLE_COUNT; ++ubSampleIndex) {\n\t\t\t\tULONG ulSampleDataLength = pMod->pSampleHeaders[ubSampleIndex].uwLength * sizeof(UWORD);\n\t\t\t\tif(ulSampleDataLength) {\n\t\t\t\t\tmemFree(pMod->pSampleStarts[ubSampleIndex], ulSampleDataLength);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tmemFree(pMod, sizeof(*pMod));\n\t}\n\n\tfileClose(pFileMod);\n\tlogBlockEnd(\"ptplayerModCreateFromFd()\");\n\treturn 0;\n}\n\nvoid ptplayerModDestroy(tPtplayerMod *pMod) {\n\tif(s_pCurrentMod == pMod) {\n\t\tptplayerStop();\n\t}\n\tmemFree(pMod->pPatterns, pMod->ulPatternsSize);\n\tif(pMod->isOwningSamples) {\n\t\tfor(UBYTE ubSampleIndex = 0; ubSampleIndex < PTPLAYER_MOD_SAMPLE_COUNT; ++ubSampleIndex) {\n\t\t\tULONG ulSampleDataLength = pMod->pSampleHeaders[ubSampleIndex].uwLength * sizeof(UWORD);\n\t\t\tif(ulSampleDataLength) {\n\t\t\t\tmemFree(pMod->pSampleStarts[ubSampleIndex], ulSampleDataLength);\n\t\t\t}\n\t\t}\n\t}\n\tmemFree(pMod, sizeof(*pMod));\n}\n\n//-------------------------------------------------------------------------- SFX\n\ntPtplayerSfx *ptplayerSfxCreateFromPath(const char *szPath, UBYTE isFast) {\n\treturn ptplayerSfxCreateFromFd(diskFileOpen(szPath, DISK_FILE_MODE_READ, 1), isFast);\n}\n\ntPtplayerSfx *ptplayerSfxCreateFromFd(tFile *pFileSfx, UBYTE isFast)\n{\n\tsystemUse();\n\tlogBlockBegin(\"ptplayerSfxCreateFromFd(pFileSfx: %p, isFast: %hhu)\", pFileSfx, isFast);\n\ttPtplayerSfx *pSfx = 0;\n\tif(!pFileSfx) {\n\t\tlogWrite(\"ERR: Null file handle\\n\");\n\t\tgoto fail;\n\t}\n\n\tpSfx = memAllocFastClear(sizeof(*pSfx));\n\tif(!pSfx) {\n\t\tgoto fail;\n\t}\n\tUBYTE ubVersion;\n\tfileRead(pFileSfx, &ubVersion, sizeof(ubVersion));\n\tif(ubVersion == 2) {\n\t\tfileRead(pFileSfx, &pSfx->uwWordLength, sizeof(pSfx->uwWordLength));\n\t\tULONG ulByteSize = pSfx->uwWordLength * sizeof(UWORD);\n\n\t\tUWORD uwSampleRateHz;\n\t\tfileRead(pFileSfx, &uwSampleRateHz, sizeof(uwSampleRateHz));\n\t\tpSfx->uwPeriod = (getClockConstant() + uwSampleRateHz/2) / uwSampleRateHz;\n\t\tULONG ulCompressedSize;\n\t\tfileRead(pFileSfx, &ulCompressedSize, sizeof(ulCompressedSize));\n\t\tlogWrite(\n\t\t\t\"Length: %lu, compressed: %lu, sample rate: %hu, period: %hu\\n\",\n\t\t\tulByteSize, ulCompressedSize, uwSampleRateHz, pSfx->uwPeriod\n\t\t);\n\n\t\tpSfx->pData = isFast ? memAllocFast(ulByteSize) : memAllocChip(ulByteSize);\n\t\tif(!pSfx->pData) {\n\t\t\tgoto fail;\n\t\t}\n\n\t\tif(ulCompressedSize) {\n\t\t\tUBYTE *pCompressed = memAllocFast(ulByteSize);\n\t\t\tfileRead(pFileSfx, pCompressed, ulCompressedSize);\n\t\t\tptplayerSfxDecompress(pCompressed, (UBYTE*)pSfx->pData, ulByteSize);\n\t\t\tmemFree(pCompressed, ulByteSize);\n\t\t}\n\t\telse {\n\t\t\tfileRead(pFileSfx, pSfx->pData, ulByteSize);\n\t\t}\n\n\t\t// Check if pData[0] is zeroed-out - it should be because after sfx playback\n\t\t// ptplayer sets the channel playback to looped first word. This should\n\t\t// be done on sfx converter side. If your samples are humming after playback,\n\t\t// fix your custom conversion tool or use latest ACE tools!\n\t\tif(pSfx->pData[0] != 0) {\n\t\t\tlogWrite(\"WARN: SFX's first word isn't zeroed-out - won't work properly with ptplayer\\n\");\n\t\t}\n\t}\n\telse {\n\t\tlogWrite(\"ERR: Unknown sample format version: %hhu\\n\", ubVersion);\n\t\tgoto fail;\n\t}\n\n\tfileClose(pFileSfx);\n\tlogBlockEnd(\"ptplayerSfxCreateFromFd()\");\n\tsystemUnuse();\n\treturn pSfx;\n\nfail:\n\tif(pFileSfx) {\n\t\tfileClose(pFileSfx);\n\t}\n\tptplayerSfxDestroy(pSfx);\n\tlogBlockEnd(\"ptplayerSfxCreateFromFd()\");\n\tsystemUnuse();\n\treturn 0;\n}\n\nvoid ptplayerSfxDestroy(tPtplayerSfx *pSfx) {\n\tlogBlockBegin(\"ptplayerSfxDestroy(pSfx: %p)\", pSfx);\n\tif(pSfx) {\n\t\tfor(UBYTE ubChannel = 0; ubChannel < 4; ++ubChannel) {\n\t\t\tif(mt_chan[ubChannel].n_sfxptr == pSfx->pData) {\n\t\t\t\t// ptplayer doesn't mute its channels after sfx playback to save cycles\n\t\t\t\tlogWrite(\"channel %hhu is still using the sample - muting...\\n\", ubChannel);\n\t\t\t\tg_pCustom->aud[ubChannel].ac_vol = 0;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\tsystemUse();\n\t\tif(pSfx->pData) {\n\t\t\tmemFree(pSfx->pData, pSfx->uwWordLength * sizeof(UWORD));\n\t\t}\n\t\tmemFree(pSfx, sizeof(*pSfx));\n\t\tsystemUnuse();\n\t}\n\tlogBlockEnd(\"ptplayerSfxDestroy()\");\n}\n\n/**\n * @brief Activates the sound effect on this channel.\n *\n * A looped sound effect has always highest priority and will\n * replace a previous effect on the same channel. No automatic channel\n * selection will be used.\n *\n * @param pChannel Channel to be used.\n * @param pSfx Sound effect to be played.\n * @param ubVolume Sound volume (0..63) - ignores mod master volume\n * @param ubPriority Playback priority, must be non-zero. The bigger the\n * more important. Set to SFX_PRIORITY_LOOPED for looped sfx.\n */\nstatic void channelSetSfx(\n\ttChannelStatus *pChannel, const tPtplayerSfx *pSfx, UBYTE ubVolume,\n\tUBYTE ubPriority\n) {\n\tpChannel->n_sfxptr = pSfx->pData;\n\tpChannel->uwSfxWordLength = pSfx->uwWordLength;\n\tpChannel->uwSfxPeriod = pSfx->uwPeriod;\n\tpChannel->uwSfxVolume = ubVolume;\n\tpChannel->ubSfxPriority = ubPriority;\n}\n\nvoid ptplayerSfxStopOnChannel(UBYTE ubChannel) {\n\tg_pCustom->intena = INTF_INTEN;\n\ttChannelStatus *pChannel = &mt_chan[ubChannel];\n\tif(pChannel->ubSfxPriority != 0) {\n\t\tpChannel->ubSfxPriority = 1;\n\t\tpChannel->uwSfxWordLength = 1; // Idle loop\n\t\tpChannel->uwSfxPeriod = 108; // Enter idle as quickly as possible\n\t\tpChannel->uwSfxVolume = 0;\n\t\tif(pChannel->isLooped) {\n\t\t\t// Looped sfx have first empty word skipped to prevent loop glitches\n\t\t\t// - bring it back.\n\t\t\tpChannel->isLooped = 0;\n\t\t\t--pChannel->n_sfxptr;\n\t\t}\n\t}\n\tg_pCustom->intena = INTF_SETCLR | INTF_INTEN;\n}\n\nvoid ptplayerSfxPlayLooped(\n\tconst tPtplayerSfx *pSfx, UBYTE ubChannel, UBYTE ubVolume\n) {\n\tif(memType(pSfx->pData) == MEMF_FAST) {\n\t\tlogWrite(\"ERR: ptplayer only supports samples located in CHIP mem\\n\");\n\t}\n\tg_pCustom->intena = INTF_INTEN;\n\ttChannelStatus *pChannel = &mt_chan[ubChannel];\n\tchannelSetSfx(pChannel, pSfx, ubVolume, SFX_PRIORITY_LOOPED);\n\tg_pCustom->intena = INTF_SETCLR | INTF_INTEN;\n}\n\nvoid ptplayerSfxPlay(\n\tconst tPtplayerSfx *pSfx, UBYTE ubChannel, UBYTE ubVolume, UBYTE ubPriority\n) {\n\tif(memType(pSfx->pData) == MEMF_FAST) {\n\t\tlogWrite(\"ERR: ptplayer only supports samples located in CHIP mem\\n\");\n\t}\n\tg_pCustom->intena = INTF_INTEN;\n\tif(ubChannel != PTPLAYER_SFX_CHANNEL_ANY) {\n\t\t// Use fixed channel for effect\n\t\ttChannelStatus *pChannel = &mt_chan[ubChannel];\n\n\t\t// Priority high enough to replace a present effect on this channel?\n\t\tif(ubPriority >= pChannel->ubSfxPriority) {\n\t\t\tchannelSetSfx(pChannel, pSfx, ubVolume, ubPriority);\n\t\t}\n\t\tg_pCustom->intena = INTF_SETCLR | INTF_INTEN;\n\t\treturn;\n\t}\n\n\t// Did we already calculate the n_freecnt values for all channels?\n\tif(!mt_SilCntValid && s_pCurrentMod) {\n\t\t// Look at the next 8 pattern steps to find the longest sequence\n\t\t// of silence (no new note or instrument).\n\t\tUBYTE ubSteps = 8;\n\n\t\t// remember which channels are not available for sound effects\n\t\tUBYTE pMusicOnly[4];\n\t\tfor(UBYTE ubChannel = 0; ubChannel < 4; ++ubChannel) {\n\t\t\tpMusicOnly[ubChannel] = mt_chan[ubChannel].isOnlyForMusic;\n\t\t}\n\n\t\t// reset freecnts for all channels\n\t\tmt_chan[0].n_freecnt = 0;\n\t\tmt_chan[1].n_freecnt = 0;\n\t\tmt_chan[2].n_freecnt = 0;\n\t\tmt_chan[3].n_freecnt = 0;\n\n\t\t// get pattern pointer\n\t\tUBYTE *pPatterns = s_pCurrentMod->pPatterns;\n\n\t\tUBYTE ubSongPos = mt_SongPos;\n\t\tUWORD uwPatternPos = mt_PatternPos;\n\t\tUBYTE isEnd = 0;\n\t\tUBYTE *pPatternStart = &pPatterns[\n\t\t\ts_pCurrentMod->pArrangement[ubSongPos] * MOD_PATTERN_BYTE_SIZE\n\t\t];\n\t\ttModVoice *pPatternEnd = (tModVoice*)(pPatternStart + MOD_PATTERN_BYTE_SIZE);\n\t\ttModVoice *pPatternPos = (tModVoice*)(pPatternStart + uwPatternPos);\n\t\tdo {\n\t\t\tUBYTE ubFreeChannelCnt = 4;\n\n\t\t\tfor(UBYTE ubChannel = 0; ubChannel < 4; ++ubChannel) {\n\t\t\t\tif(!pMusicOnly[ubChannel]) {\n\t\t\t\t\t++mt_chan[ubChannel].n_freecnt;\n\t\t\t\t\tif(pPatternPos->uwNote) {\n\t\t\t\t\t\t// The channel at current pattern pos has new note so it's not free\n\t\t\t\t\t\tpMusicOnly[ubChannel] = 1;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t// Skip to next channel\n\t\t\t\t++pPatternPos;\n\t\t\t\tubFreeChannelCnt -= pMusicOnly[ubChannel];\n\t\t\t}\n\n\t\t\t// break the loop when no channel has any more free pattern steps\n\t\t\t// otherwise break after 8 pattern steps\n\t\t\tisEnd = (ubFreeChannelCnt != 0 || --ubSteps == 0);\n\n\t\t\t// End of pattern reached? Then load next pattern pointer\n\t\t\tif(!isEnd && pPatternPos >= pPatternEnd) {\n\t\t\t\tuwPatternPos = 0;\n\t\t\t\tubSongPos = (mt_SongPos + 1) & 127;\n\t\t\t\tif(ubSongPos >= s_pCurrentMod->ubArrangementLength) {\n\t\t\t\t\tubSongPos = 0;\n\t\t\t\t}\n\t\t\t\tpPatternStart = &pPatterns[\n\t\t\t\t\ts_pCurrentMod->pArrangement[ubSongPos] * MOD_PATTERN_BYTE_SIZE\n\t\t\t\t];\n\t\t\t\tpPatternEnd = (tModVoice*)(pPatternStart + MOD_PATTERN_BYTE_SIZE);\n\t\t\t\tpPatternPos = (tModVoice*)pPatternStart;\n\t\t\t}\n\t\t} while(!isEnd);\n\t\tmt_SilCntValid = 1;\n\t}\n\n\t// Determine which channels are already allocated for sound\n\t// effects and check if the limit was reached. In this case only\n\t// replace sound effect channels by higher priority.\n\tBYTE bFreeChannels = 4 - mt_MusicChannels;\n\tif(mt_chan[0].ubSfxPriority) {\n\t\tbFreeChannels -= 1;\n\t}\n\tif(mt_chan[1].ubSfxPriority) {\n\t\tbFreeChannels -= 1;\n\t}\n\tif(mt_chan[2].ubSfxPriority) {\n\t\tbFreeChannels -= 1;\n\t}\n\tif(mt_chan[3].ubSfxPriority) {\n\t\tbFreeChannels -= 1;\n\t}\n\ttChannelStatus *pBestChannel = 0;\n\tUBYTE ubBestFreeCnt = 0;\n\tif(bFreeChannels >= 0) {\n\t\t// Exclude channels which have set a repeat loop. Try not to break them!\n\t\t// We will prefer a music channel which had pDoneBit set, because that means\n\t\t// the last instrument sample has been played completely, and the channel\n\t\t// is now idle.\n\t\tUWORD uwChannelsToCheck = 0;\n\t\tUWORD uwChannelsNonLooped = 0;\n\t\tUWORD uwIntFlag = INTF_AUD0;\n\t\tfor(UBYTE i = 0; i < 4; ++i) {\n\t\t\tif(!mt_chan[i].isLooped) {\n\t\t\t\tuwChannelsNonLooped |= uwIntFlag;\n\t\t\t\tif(isChannelDone(&mt_chan[i])) {\n\t\t\t\t\tuwChannelsToCheck |= uwIntFlag;\n\t\t\t\t}\n\t\t\t}\n\t\t\tuwIntFlag <<= 1;\n\t\t}\n\n\t\tif(!uwChannelsToCheck) {\n\t\t\t// All channels are busy, then break the non-looped ones first...\n\t\t\tuwChannelsToCheck = uwChannelsNonLooped;\n\t\t}\n\n\t\tif(!uwChannelsToCheck) {\n\t\t\t// ...except there are none. Then it doesn't matter.\n\t\t\tuwChannelsToCheck = INTF_AUD0 | INTF_AUD1 | INTF_AUD2 | INTF_AUD3;\n\t\t}\n\n\t\t// First look for the best unused channel\n\t\tuwIntFlag = INTF_AUD0;\n\t\tfor(UBYTE i = 0; i < 4; ++i) {\n\t\t\tif((uwChannelsToCheck & uwIntFlag) && !mt_chan[i].ubSfxPriority) {\n\t\t\t\t// When all channels freecnt is 0, use any - otherwise it won't play\n\t\t\t\tif(mt_chan[i].n_freecnt >= ubBestFreeCnt) {\n\t\t\t\t\tubBestFreeCnt = mt_chan[i].n_freecnt;\n\t\t\t\t\tpBestChannel = &mt_chan[i];\n\t\t\t\t}\n\t\t\t}\n\t\t\tuwIntFlag <<= 1;\n\t\t}\n\t}\n\tif(!ubBestFreeCnt) {\n\t\t// All channels reserved/playing effects.\n\t\t// Finally try to overwrite a sound effect with lower/equal priority.\n\t\tUBYTE ubBestFreeCnt = 0;\n\t\tfor(UBYTE i = 0; i < 4; ++i) {\n\t\t\tif(\n\t\t\t\t0 < mt_chan[i].ubSfxPriority && mt_chan[i].ubSfxPriority < ubPriority &&\n\t\t\t\tmt_chan[i].n_freecnt > ubBestFreeCnt\n\t\t\t) {\n\t\t\t\tubBestFreeCnt = mt_chan[i].n_freecnt;\n\t\t\t\tpBestChannel = &mt_chan[i];\n\t\t\t}\n\t\t}\n\t}\n\tif(pBestChannel) {\n#if defined(ACE_DEBUG_PTPLAYER)\n\tlogWrite(\"Selected channel %ld for sfx playback\\n\", pBestChannel - mt_chan);\n#endif\n\t\tchannelSetSfx(pBestChannel, pSfx, ubVolume, ubPriority);\n\t}\n\tg_pCustom->intena = INTF_SETCLR | INTF_INTEN;\n}\n\nvoid ptplayerWaitForSfx(void) {\n\tUBYTE isAnyChannelBusy;\n\tdo {\n\t\tisAnyChannelBusy = 0;\n\t\tfor(UBYTE i = 0; i < 4; ++i) {\n\t\t\t// Wait only for sfx to end - mod is looping ad infinitum anyway.\n\t\t\tif(mt_chan[i].ubSfxPriority) {\n\t\t\t\tlogWrite(\"sfx ptplayerWaitForSfx\\n\");\n\t\t\t\t// channel is busy by sfx\n\t\t\t\tisAnyChannelBusy = 1;\n\t\t\t\t// logWrite(\"channel busy %hhu\", i);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t} while(isAnyChannelBusy);\n}\n\nvoid ptplayerConfigureSongRepeat(UBYTE isRepeat, tPtplayerCbSongEnd cbSongEnd) {\n\ts_isRepeat = isRepeat;\n\ts_cbSongEnd = cbSongEnd;\n}\n\nUBYTE ptplayerSfxLengthInFrames(const tPtplayerSfx *pSfx) {\n\t// Get rounded sampling rate.\n\tUWORD uwSamplingRateHz = (getClockConstant() + (pSfx->uwPeriod / 2)) / pSfx->uwPeriod;\n\t// Get frame count - round it up.\n\tUWORD uwFrameCount = (pSfx->uwWordLength * 2 * 50 + uwSamplingRateHz - 1) / uwSamplingRateHz;\n\treturn uwFrameCount;\n}\n\ntPtplayerSamplePack *ptplayerSampleDataCreateFromPath(const char *szPath) {\n\treturn ptplayerSampleDataCreateFromFd(diskFileOpen(szPath, DISK_FILE_MODE_READ, 1));\n}\n\ntPtplayerSamplePack *ptplayerSampleDataCreateFromFd(tFile *pFileSamples)\n{\n\tlogBlockBegin(\"ptplayerSampleDataCreateFromFd(pFileSamples: %p)\", pFileSamples);\n\tsystemUse();\n\n\tUBYTE ubVersion;\n\ttPtplayerSamplePack *pSamplePack = 0;\n\tfileRead(pFileSamples, &ubVersion, sizeof(ubVersion));\n\tif(ubVersion != PTPLAYER_SUPPORTED_SAMPLEPACK_VERSION) {\n\t\t// ACE only supports most up to date file version to limit its size\n\t\tlogWrite(\n\t\t\t\"ERR: Unsupported sample pack format version: %hu, expected %hu\",\n\t\t\tubVersion, PTPLAYER_SUPPORTED_SAMPLEPACK_VERSION\n\t\t);\n\t\tgoto fail;\n\t}\n\n\tpSamplePack = memAllocFastClear(sizeof(*pSamplePack));\n\tif(!pSamplePack) {\n\t\tgoto fail;\n\t}\n\tlogWrite(\"Addr: %p\\n\", pSamplePack);\n\tfileRead(pFileSamples, &pSamplePack->ubSampleCount, sizeof(pSamplePack->ubSampleCount));\n\n\tfor(UBYTE i = 0; i < pSamplePack->ubSampleCount; ++i) {\n\t\ttPtplayerSfx *pSample = &pSamplePack->pSamples[i];\n\t\tULONG ulCompressedLength;\n\t\tfileRead(pFileSamples, &pSample->uwWordLength, sizeof(pSample->uwWordLength));\n\t\tfileRead(pFileSamples, &ulCompressedLength, sizeof(ulCompressedLength));\n\t\tpSample->pData = memAllocChip(pSample->uwWordLength * sizeof(UWORD));\n\t\tif(!pSample->pData) {\n\t\t\tgoto fail;\n\t\t}\n\t\tif(ulCompressedLength) {\n\t\t\tUBYTE *pCompressed = memAllocFast(ulCompressedLength);\n\t\t\tif(!pCompressed) {\n\t\t\t\tgoto fail;\n\t\t\t}\n\t\t\tfileRead(pFileSamples, pCompressed, ulCompressedLength);\n\t\t\tptplayerSfxDecompress(pCompressed, (UBYTE*)pSample->pData, pSample->uwWordLength * sizeof(UWORD));\n\t\t\tmemFree(pCompressed, ulCompressedLength);\n\t\t}\n\t\telse {\n\t\t\tfileRead(pFileSamples, pSample->pData, pSample->uwWordLength * sizeof(UWORD));\n\t\t}\n\t}\n\n\tfileClose(pFileSamples);\n\tsystemUnuse();\n\tlogBlockEnd(\"ptplayerSampleDataCreateFromFd()\");\n\treturn pSamplePack;\nfail:\n\tif(pFileSamples) {\n\t\tfileClose(pFileSamples);\n\t}\n\tif(pSamplePack) {\n\t\tfor(UBYTE i = 0; i < pSamplePack->ubSampleCount; ++i) {\n\t\t\ttPtplayerSfx *pSample = &pSamplePack->pSamples[i];\n\t\t\tif(pSample->pData) {\n\t\t\t\tmemFree(pSample->pData, pSample->uwWordLength * sizeof(UWORD));\n\t\t\t}\n\t\t}\n\t\tmemFree(pSamplePack, sizeof(*pSamplePack));\n\t}\n\n\tsystemUnuse();\n\tlogBlockEnd(\"ptplayerSampleDataCreateFromFd()\");\n\treturn 0;\n}\n\nvoid ptplayerSamplePackDestroy(tPtplayerSamplePack *pSamplePack) {\n\tlogBlockBegin(\"ptplayerSamplePackDestroy(pSamplePack: %p)\", pSamplePack);\n\tfor(UBYTE i = 0; i < pSamplePack->ubSampleCount; ++i) {\n\t\ttPtplayerSfx *pSample = &pSamplePack->pSamples[i];\n\t\tmemFree(pSample->pData, pSample->uwWordLength * sizeof(UWORD));\n\t}\n\tmemFree(pSamplePack, sizeof(*pSamplePack));\n\tlogBlockEnd(\"ptplayerSamplePackDestroy()\");\n}\n\nvoid ptplayerSetE8Callback(tPtplayerCbE8 cbOnE8) {\n\ts_cbOnE8 = cbOnE8;\n}\n"
  },
  {
    "path": "src/ace/managers/rand.c",
    "content": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at http://mozilla.org/MPL/2.0/. */\n\n// Based on RNG from http://b2d-f9r.blogspot.com/2010/08/16-bit-xorshift-rng-now-with-more.html\n// The other considered alternative was xoroshiro64/32 (https://prng.di.unimi.it),\n// but it contains multiplications which are way slower than adds and shifts.\n\n#include <ace/managers/rand.h>\n#include <ace/managers/memory.h>\n#include <ace/managers/log.h>\n\n// Coefficients are chosen from the table of original post, with restriction\n// to use shifts lesser than 8 in order to let compiler use \"shift immediate\"\n// asm instructions.\n// According to comments on said page, (5,3,1) is busted so use (5,7,4) instead.\n// Other available tuple is (6,3,8).\n#define RAND_COEFF_A 5\n#define RAND_COEFF_B 7\n#define RAND_COEFF_C 4\n\n//-------------------------------------------------------------------- FUNCTIONS\n\ntRandManager *randCreate(UWORD uwSeed1, UWORD uwSeed2) {\n\ttRandManager *pRand = memAllocFast(sizeof(*pRand));\n\trandInit(pRand, uwSeed1, uwSeed2);\n\treturn pRand;\n}\n\nvoid randDestroy(tRandManager *pRand) {\n\tmemFree(pRand, sizeof(*pRand));\n}\n\nvoid randInit(tRandManager *pRand, UWORD uwSeed1, UWORD uwSeed2) {\n\tlogBlockBegin(\n\t\t\"randInit(pRand: %p, uwSeed1: %hu, uwSeed2: %hu)\", pRand, uwSeed1, uwSeed2\n\t);\n\tif(uwSeed1 == 0 || uwSeed2 == 0) {\n\t\tlogWrite(\"ERR: Seeds can't be zero\\n\");\n\t\tlogBlockEnd(\"randInit()\");\n\t\treturn;\n\t}\n\n\tpRand->uwState1 = uwSeed1;\n\tpRand->uwState2 = uwSeed2;\n\tlogBlockEnd(\"randInit()\");\n}\n\nUWORD randUw(tRandManager *pRand) {\n  UWORD t = (pRand->uwState1 ^ (pRand->uwState1 << RAND_COEFF_A));\n  pRand->uwState1 = pRand->uwState2;\n\tpRand->uwState2 = (pRand->uwState2 ^ (pRand->uwState2 >> RAND_COEFF_C)) ^ (t ^ (t >> RAND_COEFF_B));\n  return pRand->uwState2;\n}\n\nUWORD randUwMax(tRandManager *pRand, UWORD uwMax) {\n\treturn randUw(pRand) % (uwMax + 1);\n}\n\nUWORD randUwMinMax(tRandManager *pRand, UWORD uwMin, UWORD uwMax) {\n\treturn uwMin + randUwMax(pRand, uwMax - uwMin);\n}\n\nULONG randUl(tRandManager *pRand) {\n\tUWORD uwUpper = randUw(pRand);\n\tUWORD uwLower = randUw(pRand);\n\treturn (uwUpper << 16) | (uwLower);\n}\n\nULONG randUlMax(tRandManager *pRand, ULONG ulMax) {\n\treturn randUl(pRand) % (ulMax + 1);\n}\n\nULONG randUlMinMax(tRandManager *pRand, ULONG ulMin, ULONG ulMax) {\n\treturn ulMin + randUlMax(pRand, ulMax - ulMin);\n}\n\n//---------------------------------------------------------------------- GLOBALS\n"
  },
  {
    "path": "src/ace/managers/sprite.c",
    "content": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at http://mozilla.org/MPL/2.0/. */\n\n#include <ace/managers/sprite.h>\n#include <ace/macros.h>\n#include <ace/generic/screen.h>\n#include <ace/managers/system.h>\n#include <ace/managers/mouse.h>\n#include <ace/managers/log.h>\n#include <ace/utils/custom.h>\n#include <ace/utils/sprite.h>\n\n#define SPRITE_VPOS_BITS 9\n#define SPRITE_HEIGHT_MAX ((1 << SPRITE_VPOS_BITS) - 1)\n\ntypedef struct tSpriteChannel {\n\ttSprite *pFirstSprite; ///< First sprite on the chained list in channel.\n\ttCopBlock *pCopBlock;\n\tUWORD uwRawCopPos; ///< Offset for channel's first sprite fetch copper cmd.\n\tUBYTE ubCopperRegenCount;\n} tSpriteChannel;\n\nstatic const tView *s_pView;\nstatic tSpriteChannel s_pChannelsData[HARDWARE_SPRITE_CHANNEL_COUNT];\nstatic ULONG *s_pBlankSprite;\nstatic UBYTE s_isOwningBlankSprite;\nstatic tCopBlock *s_pInitialClearCopBlock;\n\nstatic void spriteChannelRequestCopperUpdate(tSpriteChannel *pChannel) {\n\tpChannel->ubCopperRegenCount = 2; // for front/back buffers in raw mode\n}\n\nvoid spriteManagerCreate(const tView *pView, UWORD uwRawCopPos, ULONG pBlankSprite[1]) {\n\tif (pBlankSprite) {\n#ifdef ACE_DEBUG\n\t\tif (!(memType(pBlankSprite) & MEMF_CHIP)) {\n\t\t\tlogWrite(\"ERR: ILLEGAL NON-CHIP memory location for blank sprite!\");\n\t\t}\n#endif\n\t\ts_isOwningBlankSprite = 0;\n\t\ts_pBlankSprite = pBlankSprite;\n\t} else {\n\t\ts_isOwningBlankSprite = 1;\n\t\ts_pBlankSprite = memAllocChipClear(sizeof(ULONG));\n\t\t// Just to make sure we don't accidentally mismatch the control words size\n\t\t_Static_assert(sizeof(ULONG) == sizeof(tHardwareSpriteHeader), \"We expect a Hardware sprite to have a ULONG sized header\");\n\t}\n\t// TODO: add support for non-chained mode (setting sprxdat with copper)?\n\ts_pView = pView;\n\tfor(UBYTE i = HARDWARE_SPRITE_CHANNEL_COUNT; i--;) {\n\t\ts_pChannelsData[i] = (tSpriteChannel){\n\t\t\t.uwRawCopPos = uwRawCopPos + 2 * i\n\t\t};\n\t}\n\n\t// Initially disable all sprites so that no garbage will be fed on screen\n\t// before actual sprites.\n\tif(pView->pCopList->ubMode == COPPER_MODE_BLOCK) {\n\t\ts_pInitialClearCopBlock = spriteDisableInCopBlockMode(\n\t\t\ts_pView->pCopList,\n\t\t\tSPRITE_0 | SPRITE_1 | SPRITE_2 | SPRITE_3 |\n\t\t\tSPRITE_4 | SPRITE_5 | SPRITE_6 | SPRITE_7,\n\t\t\ts_pBlankSprite\n\t\t);\n\t}\n\telse {\n\t\ts_pInitialClearCopBlock = 0;\n\t\tspriteDisableInCopRawMode(\n\t\t\ts_pView->pCopList,\n\t\t\tSPRITE_0 | SPRITE_1 | SPRITE_2 | SPRITE_3 |\n\t\t\tSPRITE_4 | SPRITE_5 | SPRITE_6 | SPRITE_7, uwRawCopPos,\n\t\t\ts_pBlankSprite\n\t\t);\n\t}\n}\n\nvoid spriteManagerDestroy(void) {\n\tsystemUse();\n\tfor(UBYTE i = HARDWARE_SPRITE_CHANNEL_COUNT; i--;) {\n\t\ttSprite *pSprite = s_pChannelsData[i].pFirstSprite;\n\t\tif(pSprite) {\n\t\t\tspriteRemove(pSprite);\n\t\t}\n\t}\n\tif(s_pInitialClearCopBlock) {\n\t\tcopBlockDestroy(s_pView->pCopList, s_pInitialClearCopBlock);\n\t}\n\tif (s_isOwningBlankSprite) {\n\t\tmemFree(s_pBlankSprite, sizeof(ULONG));\n\t}\n\tsystemUnuse();\n}\n\ntSprite *spriteAdd(UBYTE ubChannelIndex, tBitMap *pBitmap) {\n\tsystemUse();\n\t// TODO: add support for attaching next sprite to the chain.\n\t// TODO: add support for attached sprites (16-color)\n\ttSprite *pSprite = memAllocFastClear(sizeof(*pSprite));\n\tpSprite->ubChannelIndex = ubChannelIndex;\n\tpSprite->isEnabled = 1;\n\n\ttSpriteChannel *pChannel = &s_pChannelsData[ubChannelIndex];\n\tif(pChannel->pFirstSprite) {\n\t\t// TODO: add support for chaining sprites\n\t\tlogWrite(\"ERR: Sprite channel %hhu is already used\\n\", ubChannelIndex);\n\t}\n\telse {\n\t\tspriteChannelRequestCopperUpdate(pChannel);\n\t\tpChannel->pFirstSprite = pSprite;\n\n\t\tif(s_pView->pCopList->ubMode == COPPER_MODE_BLOCK) {\n#if defined(ACE_DEBUG)\n\t\t\tif(pChannel->pCopBlock) {\n\t\t\t\tlogWrite(\"ERR: Sprite channel %hhu already has copBlock\\n\", ubChannelIndex);\n\t\t\t\tsystemUnuse();\n\t\t\t\treturn 0;\n\t\t\t}\n#endif\n\t\t\tpChannel->pCopBlock = copBlockCreate(s_pView->pCopList, 2, 0, 1);\n\t\t}\n\t}\n\n\tspriteSetBitmap(pSprite, pBitmap);\n\tsystemUnuse();\n\treturn pSprite;\n}\n\nvoid spriteRemove(tSprite *pSprite) {\n\tsystemUse();\n\ttSpriteChannel *pChannel = &s_pChannelsData[pSprite->ubChannelIndex];\n\n\tif(pChannel->pFirstSprite == pSprite) {\n\t\t// TODO: Move sprite next in chain to be the first one?\n\t\tpChannel->pFirstSprite = 0;\n\t\tspriteChannelRequestCopperUpdate(pChannel);\n\n\t\tif(s_pView->pCopList->ubMode == COPPER_MODE_BLOCK) {\n\t\t\ttCopBlock *pCopBlock = pChannel->pCopBlock;\n\t\t\tif(pCopBlock) {\n\t\t\t\tcopBlockDestroy(s_pView->pCopList, pCopBlock);\n\t\t\t\tpChannel->pCopBlock = 0;\n\t\t\t}\n\t\t}\n\t}\n\n\tmemFree(pSprite, sizeof(*pSprite));\n\tsystemUnuse();\n}\n\nvoid spriteSetEnabled(tSprite *pSprite, UBYTE isEnabled) {\n\tpSprite->isEnabled = isEnabled;\n\t// TODO: only after modifying first sprite in chain, change next sprite ptr in the prior one\n\ts_pChannelsData[pSprite->ubChannelIndex].ubCopperRegenCount = 2; // for front/back buffers\n}\n\nvoid spriteSetAttached(tSprite *pSprite, UBYTE isAttached) {\n#if defined(ACE_DEBUG)\n\tif(pSprite->ubChannelIndex % 2 == 0) {\n\t\tlogWrite(\n\t\t\t\"ERR: Invalid sprite to set attachment on. %hhu is not an odd sprite\\n\",\n\t\t\tpSprite->ubChannelIndex\n\t\t);\n\t\tisAttached = 0;\n\t}\n#endif\n\tpSprite->isAttached = isAttached;\n\tpSprite->isHeaderToBeUpdated = 1;\n}\n\nvoid spriteRequestMetadataUpdate(tSprite *pSprite) {\n\tpSprite->isHeaderToBeUpdated = 1;\n}\n\nvoid spriteSetBitmap(tSprite *pSprite, tBitMap *pBitmap) {\n\tif(!(pBitmap->Flags & BMF_INTERLEAVED) || pBitmap->Depth != 2) {\n\t\tlogWrite(\n\t\t\t\"ERR: Sprite channel %hhu bitmap %p isn't interleaved 2BPP\\n\",\n\t\t\tpSprite->ubChannelIndex, pBitmap\n\t\t);\n\t\treturn;\n\t}\n#if defined(ACE_USE_AGA_FEATURES)\n\tUBYTE uwMaxSpriteWidth = 8;\n#else\n\tUBYTE uwMaxSpriteWidth = 2;\n#endif\n\tUBYTE ubByteWidth = bitmapGetByteWidth(pBitmap);\n\tif(ubByteWidth > uwMaxSpriteWidth) {\n\t\tlogWrite(\n\t\t\t\"ERR: Unsupported sprite width: %hhu, expected %hhu\\n\",\n\t\t\tubByteWidth * 8, uwMaxSpriteWidth\n\t\t);\n\t\treturn;\n\t}\n\n\tpSprite->pBitmap = pBitmap;\n\tspriteSetHeight(pSprite, pBitmap->Rows - 2);\n\n\ttSpriteChannel *pChannel = &s_pChannelsData[pSprite->ubChannelIndex];\n\tspriteChannelRequestCopperUpdate(pChannel);\n}\n\nvoid spriteProcessChannel(UBYTE ubChannelIndex) {\n\ttSpriteChannel *pChannel = &s_pChannelsData[ubChannelIndex];\n\tif(!pChannel->ubCopperRegenCount) {\n\t\treturn;\n\t}\n\n\t// Update relevant part of current raw copperlist\n\tconst tSprite *pSprite = pChannel->pFirstSprite;\n\tif(s_pView->pCopList->ubMode == COPPER_MODE_BLOCK && pChannel->pCopBlock) {\n\t\tpChannel->ubCopperRegenCount = 0;\n\t\ttCopBlock *pCopBlock = pChannel->pCopBlock;\n\t\tpCopBlock->uwCurrCount = 0;\n\t\tULONG ulSprAddr = (\n\t\t\tpSprite->isEnabled ?\n\t\t\t(ULONG)(pSprite->pBitmap->Planes[0]) : (ULONG)s_pBlankSprite\n\t\t);\n\t\tcopMove(\n\t\t\ts_pView->pCopList, pCopBlock,\n\t\t\t&g_pSprFetch[pSprite->ubChannelIndex].uwHi, ulSprAddr >> 16\n\t\t);\n\t\tcopMove(\n\t\t\ts_pView->pCopList, pCopBlock,\n\t\t\t&g_pSprFetch[pSprite->ubChannelIndex].uwLo, ulSprAddr & 0xFFFF\n\t\t);\n\t}\n\telse {\n\t\t--pChannel->ubCopperRegenCount;\n\t\tUWORD uwRawCopPos = pChannel->uwRawCopPos;\n\t\ttCopCmd *pList = &s_pView->pCopList->pBackBfr->pList[uwRawCopPos];\n\n\t\tULONG ulSprAddr = (\n\t\t\tpSprite && pSprite->isEnabled ?\n\t\t\t(ULONG)(pSprite->pBitmap->Planes[0]) : (ULONG)s_pBlankSprite\n\t\t);\n\t\tcopSetMoveVal(&pList[0].sMove, ulSprAddr >> 16);\n\t\tcopSetMoveVal(&pList[1].sMove, ulSprAddr & 0xFFFF);\n\t}\n}\n\nvoid spriteProcess(tSprite *pSprite) {\n\tif(!pSprite->isHeaderToBeUpdated) {\n\t\treturn;\n\t}\n\tUBYTE isAttached = pSprite->isAttached;\n\t#if defined(ACE_DEBUG)\n\t\tif(pSprite->ubChannelIndex % 2 == 0 && pSprite->isAttached) {\n\t\t\tlogWrite(\n\t\t\t\t\"ERR: Invalid sprite to set attachment on. %hhu is not an odd sprite\\n\",\n\t\t\t\tpSprite->ubChannelIndex\n\t\t\t);\n\t\t\tisAttached = 0;\n\t\t}\n\t#endif\n\t// Sprite in list mode has 2-word header before and after data, each\n\t// occupies 1 line of the bitmap.\n\tUWORD uwVStart = s_pView->ubPosY + pSprite->wY;\n\tUWORD uwVStop = uwVStart + pSprite->uwHeight;\n\tUWORD uwHStart = s_pView->ubPosX - 1 + pSprite->wX; // For diwstrt 0x81, x offset equal to 128 worked fine, hence -1\n\n\ttHardwareSpriteHeader *pHeader = (tHardwareSpriteHeader*)(pSprite->pBitmap->Planes[0]);\n\tpHeader->uwRawPos = ((uwVStart << 8) | ((uwHStart) >> 1));\n\tpHeader->uwRawCtl = (UWORD) (\n\t\t(uwVStop << 8) |\n\t\t(isAttached << 7) |\n\t\t(BTST(uwVStart, 8) << 2) |\n\t\t(BTST(uwVStop, 8) << 1) |\n\t\tBTST(uwHStart, 0)\n\t);\n\n}\n\nvoid spriteSetHeight(tSprite *pSprite, UWORD uwHeight) {\n#if defined(ACE_DEBUG)\n\tUWORD uwVStart = s_pView->ubPosY + pSprite->wY;\n\tUWORD uwMaxHeight = SPRITE_HEIGHT_MAX - uwVStart;\n\tif(uwHeight >= uwMaxHeight) {\n\t\tlogWrite(\n\t\t\t\"ERR: Invalid sprite %hhu height %hu, max is %hu\\n\",\n\t\t\tpSprite->ubChannelIndex, uwHeight, uwMaxHeight\n\t\t);\n\t\tuwHeight = uwMaxHeight;\n\t}\n#endif\n\n\tpSprite->uwHeight = uwHeight;\n\tpSprite->isHeaderToBeUpdated = 1;\n}\n"
  },
  {
    "path": "src/ace/managers/state.c",
    "content": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at http://mozilla.org/MPL/2.0/. */\n\n#include <ace/managers/state.h>\n#include <ace/managers/log.h>\n\n/* Functions */\n\n#ifdef ACE_DEBUG\n\n#define checkNull(pPointer) _checkNull(pPointer, \"##pPointer\", __FILE__, __LINE__)\nstatic void _checkNull(\n\tvoid *pPointer, const char *szPointerName, const char *szFile, UWORD uwLine\n) {\n\tif (!pPointer) {\n\t\tlogWrite(\n\t\t\t\"ERR: Pointer %s is zero at %s:%u! Crash imminent\\n\",\n\t\t\tszPointerName, szFile, uwLine\n\t\t);\n\t}\n}\n\n#else\n#define checkNull(pPointer) do {} while(0)\n#endif\n\ntStateManager *stateManagerCreate(void) {\n\tlogBlockBegin(\"stateManagerCreate()\");\n\n\ttStateManager *pStateManager = memAllocFastClear(sizeof(tStateManager));\n\n\tlogBlockEnd(\"stateManagerCreate()\");\n\n\treturn pStateManager;\n}\n\nvoid stateManagerDestroy(tStateManager *pStateManager) {\n\tlogBlockBegin(\"stateManagerDestroy(pStateManager: %p)\", pStateManager);\n\n\tcheckNull(pStateManager);\n\n\tstatePopAll(pStateManager);\n\n\tmemFree(pStateManager, sizeof(tStateManager));\n\n\tlogBlockEnd(\"stateManagerDestroy()\");\n}\n\ntState *stateCreate(\n\ttStateCb cbCreate, tStateCb cbLoop, tStateCb cbDestroy,\n\ttStateCb cbSuspend, tStateCb cbResume\n) {\n\tlogBlockBegin(\n\t\t\"stateCreate(cbCreate: %p, cbLoop: %p, cbDestroy: %p, cbSuspend: %p, cbResume: %p)\",\n\t\tcbCreate, cbLoop, cbDestroy, cbSuspend, cbResume\n\t);\n\n\ttState *pState = memAllocFast(sizeof(tState));\n\n\tpState->cbCreate = cbCreate;\n\tpState->cbLoop = cbLoop;\n\tpState->cbDestroy = cbDestroy;\n\tpState->cbSuspend = cbSuspend;\n\tpState->cbResume = cbResume;\n\tpState->pPrev = 0;\n\n\tlogBlockEnd(\"stateCreate()\");\n\n\treturn pState;\n}\n\nvoid stateDestroy(tState *pState) {\n\tlogBlockBegin(\"stateDestroy(pState: %p)\", pState);\n\n\tcheckNull(pState);\n\n\tmemFree(pState, sizeof(tState));\n\n\tlogBlockEnd(\"stateDestroy()\");\n}\n\nvoid statePush(tStateManager *pStateManager, tState *pState) {\n\tlogBlockBegin(\n\t\t\"statePush(pStateManager: %p, pState: %p)\",\n\t\tpStateManager, pState\n\t);\n\n\tcheckNull(pStateManager);\n\tcheckNull(pState);\n\n\tif (pStateManager->pCurrent && pStateManager->pCurrent->cbSuspend) {\n\t\tpStateManager->pCurrent->cbSuspend();\n\t}\n\n\tpState->pPrev = pStateManager->pCurrent;\n\tpStateManager->pCurrent = pState;\n\tif(pState->pPrev == pState) {\n\t\tlogWrite(\"ERR: Malformed state, pState == pState->pPrev\\n\");\n\t}\n\n\tif (pStateManager->pCurrent && pStateManager->pCurrent->cbCreate) {\n\t\tpStateManager->pCurrent->cbCreate();\n\t}\n\n\tlogBlockEnd(\"statePush()\");\n}\n\nvoid statePop(tStateManager *pStateManager) {\n\tlogBlockBegin(\"statePop(pStateManager: %p)\", pStateManager);\n\n\tcheckNull(pStateManager);\n\n\tif (pStateManager->pCurrent && pStateManager->pCurrent->cbDestroy) {\n\t\tpStateManager->pCurrent->cbDestroy();\n\t}\n\n\ttState *pOldState = pStateManager->pCurrent;\n\tpStateManager->pCurrent = pOldState->pPrev;\n\n\tif (pStateManager->pCurrent && pStateManager->pCurrent->cbResume) {\n\t\tpStateManager->pCurrent->cbResume();\n\t}\n\n\tlogBlockEnd(\"statePop()\");\n}\n\nvoid statePopAll(tStateManager *pStateManager) {\n\tlogBlockBegin(\"statePopAll(pStateManager: %p)\", pStateManager);\n\n\tcheckNull(pStateManager);\n\n\twhile (pStateManager->pCurrent) {\n\t\tif (pStateManager->pCurrent->cbDestroy) {\n\t\t\tpStateManager->pCurrent->cbDestroy();\n\t\t}\n\n\t\tpStateManager->pCurrent = pStateManager->pCurrent->pPrev;\n\t}\n\n\tlogBlockEnd(\"statePopAll()\");\n}\n\nvoid stateChange(tStateManager *pStateManager, tState *pState) {\n\tlogBlockBegin(\n\t\t\"stateChange(pStateManager: %p, pState: %p)\",\n\t\tpStateManager, pState\n\t);\n\n\tcheckNull(pStateManager);\n\tcheckNull(pState);\n\n\tif (pStateManager->pCurrent && pStateManager->pCurrent->cbDestroy) {\n\t\tpStateManager->pCurrent->cbDestroy();\n\t}\n\n\tif (pStateManager->pCurrent) {\n\t\tpState->pPrev = pStateManager->pCurrent->pPrev;\n\t\tif(pState->pPrev == pState) {\n\t\t\tlogWrite(\"ERR: Malformed state, pState == pState->pPrev\\n\");\n\t\t}\n\t}\n\telse {\n\t\tpState->pPrev = 0;\n\t}\n\n\tpStateManager->pCurrent = pState;\n\n\tif (pStateManager->pCurrent && pStateManager->pCurrent->cbCreate) {\n\t\tpStateManager->pCurrent->cbCreate();\n\t}\n\n\tlogBlockEnd(\"stateChange()\");\n}\n\nvoid stateProcess(tStateManager *pStateManager) {\n\tcheckNull(pStateManager);\n\n\tif (pStateManager->pCurrent && pStateManager->pCurrent->cbLoop) {\n\t\tpStateManager->pCurrent->cbLoop();\n\t}\n}\n"
  },
  {
    "path": "src/ace/managers/system.c",
    "content": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at http://mozilla.org/MPL/2.0/. */\n\n#include <ace/managers/system.h>\n#include <stdlib.h>\n#include <clib/graphics_protos.h>\n#include <clib/dos_protos.h>\n#include <hardware/intbits.h>\n#include <hardware/dmabits.h>\n#include <devices/audio.h>\n#include <devices/input.h>\n#include <devices/inputevent.h>\n#include <ace/utils/custom.h>\n#include <ace/managers/log.h>\n#include <ace/managers/timer.h>\n#include <ace/managers/key.h>\n#include <exec/execbase.h>\n#include <exec/lists.h>\n#include <resources/cia.h>\n#include <proto/exec.h> // Bartman's compiler needs this\n#include <proto/dos.h> // Bartman's compiler needs this\n#include <proto/graphics.h> // Bartman's compiler needs this\n#include <proto/cia.h>\n#include <workbench/startup.h>\n#if defined(BARTMAN_GCC)\n#include <bartman/gcc8_c_support.h> // Idle measurement\n#endif\n\n// There are hardware interrupt vectors\n// Some may be triggered by more than one event - there are 15 events\n// http://eab.abime.net/showthread.php?p=1081007\n// http://ada.untergrund.net/?p=boardthread&id=31\n// http://palbo.dk/dataskolen/maskinsprog/english/letter_09.pdf\n// Clearing bit is done twice for some high end configs\n// http://eab.abime.net/showthread.php?t=95263\n\n//---------------------------------------------------------------------- DEFINES\n\n// First OS interrupt is at offset 0x64 - each is 4 bytes wide\n#define SYSTEM_INT_VECTOR_FIRST (0x64/4)\n#define SYSTEM_INT_VECTOR_COUNT 7\n#define SYSTEM_INT_HANDLER_COUNT 15\n#define SYSTEM_STACK_CANARY '\\xBA'\n\n#define SYSTEM_ACE_MIN_NO_OS_INTERRUPTS (INTF_VERTB | INTF_PORTS | INTF_EXTER)\n#define SYSTEM_ACE_MIN_OS_INTERRUPTS (INTF_VERTB | INTF_EXTER)\n\n//------------------------------------------------------------------------ TYPES\n\ntypedef void (*tHwIntVector)(void);\n\ntypedef struct _tAceInterrupt {\n\ttAceIntHandler pHandler;\n\tvoid *pData;\n} tAceInterrupt;\n\n//---------------------------------------------------------------------- GLOBALS\n\n// Store VBR query code in .text so that it plays nice with instruction cache\n// TODO: move to .s file after vasm support gets merged into cmake\n// Instructions: movec vbr,d0; rte\n__attribute__((section(\"text\")))\nstatic const UWORD s_pGetVbrCode[] = {0x4e7a, 0x0801, 0x4e73};\n\n// Get cache control register contents (020+).\n// Instructions: movec cacr,d0; rte\n__attribute__((section(\"text\")))\nstatic const UWORD s_pGetCacr[] = {0x4e7a, 0x0002, 0x4e73};\n\n// Get processor configuration register contents (060+).\n// Instructions: movec pcr,d0; rte\n__attribute__((section(\"text\")))\nstatic const UWORD s_pGetPcr[] = {0x4e7a, 0x0801, 0x4e73};\n\n// Move d0 into the cache control register\n// movec d0,cacr; rte\n__attribute__((section(\"text\")))\nstatic const UWORD s_pSetCacr[] = {0x4e7b, 0x0002, 0x4e73};\n\n// Move d0 into the cache control register and flush caches\n// movec d0,cacr; cpusha ic+dc; rte\n__attribute__((section(\"text\")))\nstatic const UWORD s_pSetCacr040[] = {0x4e7b, 0x0002, 0xf4f8, 0x4e73};\n\n// Move d0 into the processor configuration register\n__attribute__((section(\"text\")))\nstatic const UWORD s_pSetPcr[] = {0x4e7b, 0x801, 0x4e73};\n\n// Saved regs\nstatic UWORD s_uwOsIntEna;\nstatic UWORD s_uwOsInitialIntEna; ///< Before ACE's OS handlers got installed\nstatic UWORD s_uwOsDmaCon;\nstatic UWORD s_uwAceDmaCon = 0;\nstatic UWORD s_uwOsInitialDma;\n\nstatic UWORD s_uwOsCiaATimerA;\nstatic UWORD s_uwOsCiaBTimerB;\nstatic UBYTE s_pOsCiaIcr[CIA_COUNT], s_pOsCiaCra[CIA_COUNT], s_pOsCiaCrb[CIA_COUNT];\nstatic UWORD s_pAceCiaTimerA[CIA_COUNT] = {0xFFFF, 0xFFFF}; // as long as possible\nstatic UWORD s_pAceCiaTimerB[CIA_COUNT] = {0xFFFF, 0xFFFF};\nstatic UBYTE s_pAceCiaCra[CIA_COUNT] = {0, 0};\nstatic UBYTE s_pAceCiaCrb[CIA_COUNT] = {0, 0};\n\n// Interrupts\nstatic void HWINTERRUPT int1Handler(void);\nstatic void HWINTERRUPT int2Handler(void);\nstatic void HWINTERRUPT int3Handler(void);\nstatic void HWINTERRUPT int4Handler(void);\nstatic void HWINTERRUPT int5Handler(void);\nstatic void HWINTERRUPT int6Handler(void);\nstatic void HWINTERRUPT int7Handler(void);\nstatic const tHwIntVector s_pAceHwInterrupts[SYSTEM_INT_VECTOR_COUNT] = {\n\tint1Handler, int2Handler, int3Handler, int4Handler,\n\tint5Handler, int6Handler, int7Handler\n};\nstatic volatile tHwIntVector * s_pHwVectors = 0;\nstatic tHwIntVector s_pOsHwInterrupts[SYSTEM_INT_VECTOR_COUNT] = {0};\nstatic tAceInterrupt s_pAceInterrupts[SYSTEM_INT_HANDLER_COUNT] = {{0}};\nstatic tAceInterrupt s_pAceCiaInterrupts[CIA_COUNT][5] = {{{0}}};\nstatic UWORD s_uwAceIntEna = 0;\nstatic tKeyInputHandler s_cbKeyInputHandler;\n\n// Manager logic vars\nstatic WORD s_wSystemUses;\nstatic WORD s_wSystemBlitterUses;\n\ntypedef struct tCpuCacheFlags {\n    ULONG ulCacr;\n    ULONG ulPcr;\n    WORD wDisabledCount;\n} tCpuCacheFlags;\n\nstatic tCpuCacheFlags s_sCpuCacheFlags;\n\nstruct GfxBase *GfxBase = 0;\nstruct View *s_pOsView;\nstatic const UWORD s_uwOsMinDma = DMAF_DISK | DMAF_BLITTER;\nstatic struct IOAudio s_sIoAudio = {0};\nstatic struct IOStdReq s_sIoRequestInput = {0};\nstatic struct Library *s_pCiaResource[CIA_COUNT];\nstatic struct Process *s_pProcess;\nstatic struct MsgPort *s_pCdtvIOPort;\nstatic struct IOStdReq *s_pCdtvIOReq;\nstatic struct Interrupt s_sOsHandlerIo;\nstatic struct Interrupt s_pOsCiaIcrHandlers[CIA_COUNT][5];\nstatic struct Interrupt *s_pOsOldInterruptHandlers[14];\nstatic struct Interrupt s_pOsInterruptHandlers[14];\nstatic UWORD s_uwOsVectorInts = (\n\tINTF_TBE | INTF_DSKBLK | INTF_SOFTINT |\n\tINTF_AUD0 | INTF_AUD1 | INTF_AUD2 | INTF_AUD3 | INTF_RBF | INTF_DSKSYNC\n);\n\n#if defined(BARTMAN_GCC)\nstruct DosLibrary *DOSBase = 0;\nstruct ExecBase *SysBase = 0;\nstatic struct Message *s_pReturnMsg = 0;\n#else // Bebbo\nextern struct WBStartup *_WBenchMsg;\n#endif\n\nstatic BPTR s_bpStartLock = 0;\nstatic void *s_pOldWindow;\n\n//----------------------------------------------------------- INTERRUPT HANDLERS\n\n// All interrupt handlers should clear their flags twice\n// http://eab.abime.net/showthread.php?p=834185#post834185\n\nFN_HOTSPOT\nvoid HWINTERRUPT int1Handler(void) {\n\tlogPushInt();\n\t// Soft / diskBlk / TBE (RS232 TX end)\n\tlogPopInt();\n}\n\nFN_HOTSPOT\nvoid HWINTERRUPT int2Handler(void) {\n\tlogPushInt();\n\tUWORD uwIntReq = g_pCustom->intreqr;\n\tif(uwIntReq & INTF_PORTS) {\n\t\t// CIA A interrupt - Parallel, keyboard\n\t\tUBYTE ubIcr = g_pCia[CIA_A]->icr; // Read clears interrupt flags\n\t\tif(ubIcr & CIAICRF_SERIAL) {\n\t\t\t// Keyboard\n\t\t\tif(s_pAceCiaInterrupts[CIA_A][CIAICRB_SERIAL].pHandler) {\n\t\t\t\ts_pAceCiaInterrupts[CIA_A][CIAICRB_SERIAL].pHandler(\n\t\t\t\t\tg_pCustom, s_pAceCiaInterrupts[CIA_A][CIAICRB_SERIAL].pData\n\t\t\t\t);\n\t\t\t}\n\t\t\tif(ubIcr & CIAICRF_TIMER_A) {\n\t\t\t\tif(s_pAceCiaInterrupts[CIA_A][CIAICRB_TIMER_A].pHandler) {\n\t\t\t\t\ts_pAceCiaInterrupts[CIA_A][CIAICRB_TIMER_A].pHandler(\n\t\t\t\t\t\tg_pCustom, s_pAceCiaInterrupts[CIA_A][CIAICRB_TIMER_A].pData\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\t\t\t// CIA-A timer A is used for keyboard, timer B for exec task switch\n\t\t\t// For some reason after save/restore A.ta is used without problems,\n\t\t\t// but A.tb makes OS unstable - we don't use it until it gets fixed\n\t\t\t// if(ubIcr & CIAICRF_TIMER_B) {\n\t\t\t// \tif(s_pAceCiaInterrupts[CIA_A][CIAICRB_TIMER_B].pHandler) {\n\t\t\t// \t\ts_pAceCiaInterrupts[CIA_A][CIAICRB_TIMER_B].pHandler(\n\t\t\t// \t\t\tg_pCustom, s_pAceCiaInterrupts[CIA_A][CIAICRB_TIMER_B].pData\n\t\t\t// \t\t);\n\t\t\t// \t}\n\t\t\t// }\n\t\t\t// TODO: this could be re-enabled in vblank since we don't need it\n\t\t\t// to retrigger during same frame. Or perhaps it's needed so that kbd\n\t\t\t// controller won't overflow its queue\n\t\t}\n\t\tg_pCustom->intreq = INTF_PORTS;\n\t\tg_pCustom->intreq = INTF_PORTS;\n\t}\n\t// TODO: handle \"mouse, some of disk functions\"\n\tlogPopInt();\n}\n\nFN_HOTSPOT\nvoid HWINTERRUPT int3Handler(void) {\n\tlogPushInt();\n\t// VBL / Copper / Blitter\n\tUWORD uwIntReq = g_pCustom->intreqr;\n\tUWORD uwReqClr = 0;\n\n\t// Vertical blanking\n\tif(uwIntReq & INTF_VERTB) {\n\t\t// Do ACE-specific stuff\n\t\t// TODO when ACE gets ported to C++ this could be constexpr if'ed\n\t\ttimerOnInterrupt();\n\n\t\t// Process handlers\n\t\tif(s_pAceInterrupts[INTB_VERTB].pHandler) {\n\t\t\ts_pAceInterrupts[INTB_VERTB].pHandler(\n\t\t\t\tg_pCustom, s_pAceInterrupts[INTB_VERTB].pData\n\t\t\t);\n\t\t}\n\t\tuwReqClr = INTF_VERTB;\n\t}\n\n\t// Copper\n\tif((uwIntReq & INTF_COPER) && s_pAceInterrupts[INTB_COPER].pHandler) {\n\t\ts_pAceInterrupts[INTB_COPER].pHandler(\n\t\t\tg_pCustom, s_pAceInterrupts[INTB_VERTB].pData\n\t\t);\n\t\tuwReqClr |= INTF_COPER;\n\t}\n\n\t// Blitter\n\tif((uwIntReq & INTF_BLIT) && s_pAceInterrupts[INTB_BLIT].pHandler) {\n\t\ts_pAceInterrupts[INTB_BLIT].pHandler(\n\t\t\tg_pCustom, s_pAceInterrupts[INTB_VERTB].pData\n\t\t);\n\t\tuwReqClr |= INTF_BLIT;\n\t}\n\tlogPopInt();\n\tg_pCustom->intreq = uwReqClr;\n\tg_pCustom->intreq = uwReqClr;\n}\n\nFN_HOTSPOT\nvoid HWINTERRUPT int4Handler(void) {\n\tlogPushInt();\n\tUWORD uwIntReq = g_pCustom->intreqr;\n\tUWORD uwReqClr = 0;\n\n\t// Audio channel 0\n\tif((uwIntReq & INTF_AUD0) && s_pAceInterrupts[INTB_AUD0].pHandler) {\n\t\ts_pAceInterrupts[INTB_AUD0].pHandler(\n\t\t\tg_pCustom, s_pAceInterrupts[INTB_AUD0].pData\n\t\t);\n\t\tuwReqClr |= INTF_AUD0;\n\t}\n\n\t// Audio channel 1\n\tif((uwIntReq & INTF_AUD1) && s_pAceInterrupts[INTB_AUD1].pHandler) {\n\t\ts_pAceInterrupts[INTB_AUD1].pHandler(\n\t\t\tg_pCustom, s_pAceInterrupts[INTB_AUD1].pData\n\t\t);\n\t\tuwReqClr |= INTF_AUD1;\n\t}\n\n\t// Audio channel 2\n\tif((uwIntReq & INTF_AUD2) && s_pAceInterrupts[INTB_AUD2].pHandler) {\n\t\ts_pAceInterrupts[INTB_AUD2].pHandler(\n\t\t\tg_pCustom, s_pAceInterrupts[INTB_AUD2].pData\n\t\t);\n\t\tuwReqClr |= INTF_AUD2;\n\t}\n\n\t// Audio channel 3\n\tif((uwIntReq & INTF_AUD3) && s_pAceInterrupts[INTB_AUD3].pHandler) {\n\t\ts_pAceInterrupts[INTB_AUD3].pHandler(\n\t\t\tg_pCustom, s_pAceInterrupts[INTB_AUD3].pData\n\t\t);\n\t\tuwReqClr |= INTF_AUD3;\n\t}\n\tlogPopInt();\n\tg_pCustom->intreq = uwReqClr;\n\tg_pCustom->intreq = uwReqClr;\n}\n\nFN_HOTSPOT\nvoid HWINTERRUPT int5Handler(void) {\n\tlogPushInt();\n\t// DskSyn / RBF\n\tlogPopInt();\n}\n\nFN_HOTSPOT\nvoid HWINTERRUPT int6Handler(void) {\n\tlogPushInt();\n\t// TODO: perhaps I should disable CIA interrupts while I process them?\n\tUWORD uwIntReq = g_pCustom->intreqr;\n\tUWORD uwReqClr = 0;\n\n\tif(uwIntReq & INTF_EXTER) {\n\t\t// INTF_EXTER - CIA B\n\t\t// Check and clear CIA interrupt flags\n\t\tUBYTE ubIcr = g_pCia[CIA_B]->icr;\n\t\tif(ubIcr & CIAICRF_SERIAL) {\n\t\t\tif(s_pAceCiaInterrupts[CIA_B][CIAICRB_SERIAL].pHandler) {\n\t\t\t\ts_pAceCiaInterrupts[CIA_B][CIAICRB_SERIAL].pHandler(\n\t\t\t\t\tg_pCustom, s_pAceCiaInterrupts[CIA_B][CIAICRB_SERIAL].pData\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t\tif(ubIcr & CIAICRF_TIMER_A) {\n\t\t\tif(s_pAceCiaInterrupts[CIA_B][CIAICRB_TIMER_A].pHandler) {\n\t\t\t\ts_pAceCiaInterrupts[CIA_B][CIAICRB_TIMER_A].pHandler(\n\t\t\t\t\tg_pCustom, s_pAceCiaInterrupts[CIA_B][CIAICRB_TIMER_A].pData\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t\tif(ubIcr & CIAICRF_TIMER_B) {\n\t\t\tif(s_pAceCiaInterrupts[CIA_B][CIAICRB_TIMER_B].pHandler) {\n\t\t\t\ts_pAceCiaInterrupts[CIA_B][CIAICRB_TIMER_B].pHandler(\n\t\t\t\t\tg_pCustom, s_pAceCiaInterrupts[CIA_B][CIAICRB_TIMER_B].pData\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\t// Zorro/Clockport/other expansions can trigger this interrupt and it sets\n\t\t// the EXTER bit too. But you can't reliably detect and handle those devices\n\t\t// unless you exactly know that they are present and how to poll their status.\n\t\t// Leave the EXTER bit check in place since it should be cleared anyway.\n\t\tuwReqClr |= INTF_EXTER;\n\t}\n\n\tlogPopInt();\n\t// Clear int flags\n\tg_pCustom->intreq = uwReqClr;\n\tg_pCustom->intreq = uwReqClr;\n}\n\nFN_HOTSPOT\nvoid HWINTERRUPT int7Handler(void) {\n\tlogPushInt();\n\t// EXTERNAL\n\tlogPopInt();\n}\n\n//------------------------------------------------------------------ OS HANDLERS\n\nstatic ULONG aceInputHandler(void) {\n\tregister volatile ULONG regOldEventChain __asm(\"a0\");\n\t// register volatile ULONG regData __asm(\"a1\");\n\n\tif(s_cbKeyInputHandler) {\n\t\tstruct InputEvent *pEvent = (struct InputEvent *)regOldEventChain;\n\t\twhile(pEvent) {\n\t\t\tif(pEvent->ie_Class == IECLASS_RAWKEY) {\n\t\t\t\t// logWrite(\"OS key event: %hu\\n\", pEvent->ie_Code);\n\t\t\t\ts_cbKeyInputHandler(pEvent->ie_Code);\n\t\t\t}\n\t\t\t// TODO: handle IECLASS_DISKREMOVED, IECLASS_DISKINSERTED ?\n\n\t\t\tpEvent = pEvent->ie_NextEvent;\n\t\t}\n\t}\n\n\t// Don't propagate any input events to other stuff - ensure full takeover by clearing d0\n\treturn 0;\n}\n\nULONG ciaIcrHandler(void) {\n\tregister volatile ULONG regData __asm(\"a1\");\n\n\ttAceInterrupt *pAceInt = (tAceInterrupt *)regData;\n\tif(pAceInt->pHandler) {\n\t\tpAceInt->pHandler(g_pCustom, pAceInt->pData);\n\t}\n\n\t// set the Z flag\n\treturn 0;\n}\n\nvoid osIntVector(void) {\n\tregister volatile ULONG regData __asm(\"a1\");\n\n\tUBYTE ubIntBit = regData;\n\tif(s_pAceInterrupts[ubIntBit].pHandler) {\n\t\ts_pAceInterrupts[ubIntBit].pHandler(\n\t\t\tg_pCustom, s_pAceInterrupts[ubIntBit].pData\n\t\t);\n\t}\n\n\tUWORD uwIntMask = BV(ubIntBit);\n\tg_pCustom->intreq = uwIntMask;\n\tg_pCustom->intreq = uwIntMask;\n}\n\nULONG osIntServer(void) {\n\tregister volatile ULONG regData __asm(\"a1\");\n\n\tUBYTE ubIntBit = regData;\n\tif(ubIntBit == INTB_VERTB) {\n\t\t// Do ACE-specific stuff\n\t\t// TODO when ACE gets ported to C++ this could be constexpr if'ed\n\t\ttimerOnInterrupt();\n\t}\n\n\tif(s_pAceInterrupts[ubIntBit].pHandler) {\n\t\ts_pAceInterrupts[ubIntBit].pHandler(\n\t\t\tg_pCustom, s_pAceInterrupts[ubIntBit].pData\n\t\t);\n\t}\n\n\tUWORD uwIntMask = BV(ubIntBit);\n\tg_pCustom->intreq = uwIntMask;\n\tg_pCustom->intreq = uwIntMask;\n\n\t// End chain for non-VERTB ints\n\treturn ubIntBit == INTB_VERTB ? 0 : 1;\n}\n\n//-------------------------------------------------------------------- FUNCTIONS\n\n// Messageport creation for KS1.3\n// http://amigadev.elowar.com/read/ADCD_2.1/Libraries_Manual_guide/node02EC.html\nstatic struct MsgPort *msgPortCreate(char *name, LONG pri) {\n\tLONG sigBit;\n\tstruct MsgPort *mp;\n\n\tif((sigBit = AllocSignal(-1L)) == -1) {\n\t\treturn NULL;\n\t}\n\n\tmp = (struct MsgPort *) AllocMem(sizeof(*mp), MEMF_PUBLIC | MEMF_CLEAR);\n\tif (!mp) {\n\t\tFreeSignal(sigBit);\n\t\treturn NULL;\n\t}\n\tmp->mp_Node.ln_Name = name;\n\tmp->mp_Node.ln_Pri = pri;\n\tmp->mp_Node.ln_Type = NT_MSGPORT;\n\tmp->mp_Flags = PA_SIGNAL;\n\tmp->mp_SigBit = sigBit;\n\tmp->mp_SigTask = (struct Task *)s_pProcess;\n\n\t// NewList(&(mp->mp_MsgList)); // Init message list - not in headers\n\tmp->mp_MsgList.lh_Head = (struct Node*)&mp->mp_MsgList.lh_Tail;\n\tmp->mp_MsgList.lh_Tail = NULL;\n\tmp->mp_MsgList.lh_TailPred = (struct Node*)&mp->mp_MsgList.lh_Head;\n\treturn mp;\n}\n\n// http://amigadev.elowar.com/read/ADCD_2.1/Libraries_Manual_guide/node02ED.html\nstatic void msgPortDelete(struct MsgPort *mp) {\n\tmp->mp_SigTask = (struct Task *) -1; // Make it difficult to re-use the port\n\tmp->mp_MsgList.lh_Head = (struct Node *) -1;\n\n\tFreeSignal(mp->mp_SigBit);\n\tFreeMem(mp, sizeof(*mp));\n}\n\nstatic void ioRequestInitialize(struct IORequest *pIoReq, struct MsgPort *pMsgPort, UWORD uwLen) {\n\tpIoReq->io_Message.mn_Node.ln_Type = NT_MESSAGE;\n\tpIoReq->io_Message.mn_ReplyPort = pMsgPort;\n\tpIoReq->io_Message.mn_Length = uwLen;\n}\n\nstatic struct IORequest *ioRequestCreate(struct MsgPort *pMsgPort, UWORD uwLen) {\n\tstruct IORequest *pIoReq = (struct IORequest *) AllocMem(uwLen, MEMF_PUBLIC | MEMF_CLEAR);\n\tif (!pIoReq) {\n\t\treturn NULL;\n\t}\n\tioRequestInitialize(pIoReq, pMsgPort, uwLen);\n\treturn pIoReq;\n}\n\nstatic void ioRequestDestroy(struct IORequest *pIoReq) {\n\tFreeMem(pIoReq, pIoReq->io_Message.mn_Length);\n}\n\nstatic UBYTE audioChannelAlloc(void) {\n\tstruct MsgPort *pMsgPort = msgPortCreate(\"audio alloc\", ADALLOC_MAXPREC);\n\tif(!pMsgPort) {\n\t\tlogWrite(\"ERR: Couldn't open message port for audio alloc\\n\");\n\t\tgoto fail;\n\t}\n\n\tmemset(&s_sIoAudio, 0, sizeof(s_sIoAudio));\n\tioRequestInitialize(&s_sIoAudio.ioa_Request, pMsgPort, sizeof(s_sIoAudio));\n\n\tUBYTE isError = OpenDevice(\n\t\t(CONST_STRPTR)\"audio.device\", 0, (struct IORequest *)&s_sIoAudio, 0\n\t);\n\tif(isError) {\n\t\tlogWrite(\n\t\t\t\"ERR: Couldn't alloc Audio channels, code: %d\\n\",\n\t\t\ts_sIoAudio.ioa_Request.io_Error\n\t\t);\n\t\tgoto fail;\n\t}\n\n\tUBYTE ubChannelMask = 0b1111; // Allocate all 4 channels.\n\ts_sIoAudio.ioa_Data = &ubChannelMask;\n\ts_sIoAudio.ioa_Length = sizeof(ubChannelMask);\n\ts_sIoAudio.ioa_Request.io_Command = ADCMD_ALLOCATE;\n\ts_sIoAudio.ioa_Request.io_Flags = ADIOF_NOWAIT;\n\tisError = DoIO((struct IORequest *)&s_sIoAudio);\n\n\tif(isError) {\n\t\tlogWrite(\n\t\t\t\"ERR: io audio request fail, code: %d\\n\", s_sIoAudio.ioa_Request.io_Error\n\t\t);\n\t\tgoto fail;\n\t}\n\treturn 1;\n\nfail:\n\tif(pMsgPort) {\n\t\tmsgPortDelete(pMsgPort);\n\t}\n\treturn 0;\n}\n\nstatic void audioChannelFree(void) {\n\tstruct MsgPort *pMsgPort = s_sIoAudio.ioa_Request.io_Message.mn_ReplyPort;\n\n\ts_sIoAudio.ioa_Request.io_Command = ADCMD_FINISH;\n\ts_sIoAudio.ioa_Request.io_Flags = 0;\n\ts_sIoAudio.ioa_Request.io_Unit = (APTR)1;\n\tUBYTE isError = DoIO((struct IORequest *)&s_sIoAudio);\n\tif(isError) {\n\t\tlogWrite(\n\t\t\t\"ERR: io audio request fail, code: %d\\n\", s_sIoAudio.ioa_Request.io_Error\n\t\t);\n\t}\n\n\tCloseDevice((struct IORequest *)&s_sIoAudio);\n\tmsgPortDelete(pMsgPort);\n}\n\nstatic void cdtvCdCommand(UWORD cmd) {\n\tif (s_pCdtvIOReq) {\n\t\ts_pCdtvIOReq->io_Command = cmd;\n\t\ts_pCdtvIOReq->io_Offset  = 0;\n\t\ts_pCdtvIOReq->io_Length  = 0;\n\t\ts_pCdtvIOReq->io_Data    = NULL;\n\t\tDoIO((struct IORequest *)s_pCdtvIOReq);\n\t}\n}\n\nstatic void cdtvPortAlloc(void) {\n\tif (!(s_pCdtvIOPort = msgPortCreate(NULL, ADALLOC_MAXPREC))) {\n\t\tlogWrite(\"ERR: Couldn't allocate message port for cdtv alloc\\n\");\n\t\treturn;\n\t}\n\n\tif (!(s_pCdtvIOReq = (struct IOStdReq *)ioRequestCreate(s_pCdtvIOPort, sizeof(struct IOStdReq)))) {\n\t\tlogWrite(\"ERR: Couldn't allocate io request for cdtv messages\\n\");\n\t\tmsgPortDelete(s_pCdtvIOPort);\n\t\ts_pCdtvIOPort = NULL;\n\t\treturn;\n\t}\n\n\tif (OpenDevice((CONST_STRPTR)\"cdtv.device\", 0, (struct IORequest *) s_pCdtvIOReq, 0)) {\n\t\tmsgPortDelete(s_pCdtvIOPort);\n\t\ts_pCdtvIOPort = NULL;\n\t\tioRequestDestroy((struct IORequest*)s_pCdtvIOReq);\n\t\ts_pCdtvIOReq = NULL;\n\t\treturn;\n\t}\n}\n\nstatic void cdtvPortFree(void) {\n\tif (s_pCdtvIOPort) {\n\t\tmsgPortDelete(s_pCdtvIOPort);\n\t}\n\tif (s_pCdtvIOReq) {\n\t\tioRequestDestroy((struct IORequest *)s_pCdtvIOReq);\n\t}\n}\n\nstatic UBYTE inputHandlerAdd(void) {\n\tstruct MsgPort *pMsgPort = msgPortCreate(\"input handler register\", ADALLOC_MAXPREC);\n\tif(!pMsgPort) {\n\t\tlogWrite(\"ERR: Couldn't open message port for audio alloc\\n\");\n\t\tgoto fail;\n\t}\n\n\t// We don't have CreateIORequest on ks1.3, so just zero stuff\n\tmemset(&s_sIoRequestInput, 0, sizeof(s_sIoRequestInput));\n\tUBYTE isError = OpenDevice(\n\t\t(CONST_STRPTR)\"input.device\", 0, (struct IORequest *)&s_sIoRequestInput, 0\n\t);\n\tif(isError) {\n\t\tlogWrite(\n\t\t\t\"ERR: Couldn't open input device, code: %d\\n\",\n\t\t\ts_sIoRequestInput.io_Error\n\t\t);\n\t\tgoto fail;\n\t}\n\n\tmemset(&s_sOsHandlerIo, 0, sizeof(s_sOsHandlerIo));\n\ts_sOsHandlerIo.is_Code = (void(*)(void))aceInputHandler;\n\ts_sOsHandlerIo.is_Data = 0;\n\ts_sOsHandlerIo.is_Node.ln_Pri = 127;\n\ts_sOsHandlerIo.is_Node.ln_Name = \"ACE Input handler\";\n\ts_sIoRequestInput.io_Data = (APTR)&s_sOsHandlerIo;\n\ts_sIoRequestInput.io_Command = IND_ADDHANDLER;\n\ts_sIoRequestInput.io_Message.mn_ReplyPort = pMsgPort;\n\tisError = DoIO((struct IORequest *)&s_sIoRequestInput);\n\n\tif(isError) {\n\t\tlogWrite(\n\t\t\t\"ERR: io audio request fail, code: %d\\n\", s_sIoRequestInput.io_Error\n\t\t);\n\t\tgoto fail;\n\t}\n\treturn 1;\n\nfail:\n\tif(pMsgPort) {\n\t\tmsgPortDelete(pMsgPort);\n\t}\n\treturn 0;\n}\n\nstatic void inputHandlerRemove(void) {\n\t// http://amigadev.elowar.com/read/ADCD_2.1/Includes_and_Autodocs_2._guide/node04E2.html\n\n\tstruct MsgPort *pMsgPort = s_sIoRequestInput.io_Message.mn_ReplyPort;\n\n\ts_sIoRequestInput.io_Command = IND_REMHANDLER;\n\ts_sIoRequestInput.io_Data=(APTR)&s_sOsHandlerIo;\n\tUBYTE isError = DoIO((struct IORequest *)&s_sIoRequestInput);\n\tif(isError) {\n\t\tlogWrite(\n\t\t\t\"ERR: io audio request fail, code: %d\\n\", s_sIoRequestInput.io_Error\n\t\t);\n\t}\n\n\t// NOTE: IND_REMHANDLER is not immediate\n\n\tCloseDevice((struct IORequest *)&s_sIoRequestInput);\n\tmsgPortDelete(pMsgPort);\n}\n\nstatic void interruptHandlerAdd(UBYTE ubIntBit) {\n\tstruct Interrupt *pInterrupt = &s_pOsInterruptHandlers[ubIntBit];\n\tmemset(pInterrupt, 0, sizeof(*pInterrupt));\n\tpInterrupt->is_Data = (void*)(ULONG)ubIntBit;\n\tpInterrupt->is_Node.ln_Name = \"ACE interrupt handler\";\n\tpInterrupt->is_Node.ln_Type = NT_INTERRUPT;\n\tif(BV(ubIntBit) & s_uwOsVectorInts) {\n\t\tpInterrupt->is_Code = osIntVector;\n\n\t\t// Disable interrupt and swap the int vector\n\t\tg_pCustom->intena = BV(ubIntBit);\n\t\ts_pOsOldInterruptHandlers[ubIntBit] = SetIntVector(ubIntBit, pInterrupt);\n\t}\n\telse {\n\t\t// VERTB servers should always return Z set and can't be sole handler\n\t\t// NOTE: VERTB server with priority of 10 or greater must set a0 to 0xDFF000\n\t\tpInterrupt->is_Code = (void(*)(void))osIntServer;\n\t\tpInterrupt->is_Node.ln_Pri = (ubIntBit == INTB_VERTB) ? 9 : 127;\n\t\t// Auto-enables intena bit if first server is adder\n\t\tAddIntServer(ubIntBit, pInterrupt);\n\t}\n}\n\nstatic void interruptHandlerRemove(UBYTE ubIntBit) {\n\tif(BV(ubIntBit) & s_uwOsVectorInts) {\n\t\t// Disable interrupt in case handler is set to null\n\t\tg_pCustom->intena = BV(ubIntBit);\n\t\tSetIntVector(ubIntBit, s_pOsOldInterruptHandlers[ubIntBit]);\n\n\t\t// A 3rd party handler could be installed but be inactive\n\t\tif(s_uwOsInitialIntEna & BV(ubIntBit)) {\n\t\t\tg_pCustom->intena = INTF_SETCLR | BV(ubIntBit);\n\t\t}\n\t}\n\telse {\n\t\t// Auto-disables intena bit if sole server is removed\n\t\tRemIntServer(ubIntBit, &s_pOsInterruptHandlers[ubIntBit]);\n\t}\n}\n\nstatic void systemOsDisable(void) {\n\t\t// Disable interrupts (this is the actual \"kill system/OS\" part)\n\t\tg_pCustom->intena = 0x7FFF;\n\t\tg_pCustom->intreq = 0x7FFF;\n\n\t\t// Query CIA ICR bits set by OS for later CIA takeover restore\n\t\ts_pOsCiaIcr[CIA_A] = AbleICR(s_pCiaResource[CIA_A], 0);\n\t\ts_pOsCiaIcr[CIA_B] = AbleICR(s_pCiaResource[CIA_B], 0);\n\n\t\t// Disable CIA interrupts\n\t\tg_pCia[CIA_A]->icr = 0x7F;\n\t\tg_pCia[CIA_B]->icr = 0x7F;\n\n\t\t// Save CRA bits\n\t\ts_pOsCiaCra[CIA_A] = g_pCia[CIA_A]->cra;\n\t\ts_pOsCiaCrb[CIA_A] = g_pCia[CIA_A]->crb;\n\t\ts_pOsCiaCra[CIA_B] = g_pCia[CIA_B]->cra;\n\t\ts_pOsCiaCrb[CIA_B] = g_pCia[CIA_B]->crb;\n\n\t\t// Disable timers and trigger reload of value to read preset val\n\t\tg_pCia[CIA_A]->cra = CIACRA_LOAD; // CIACRA_START=0, timer is stopped\n\t\tg_pCia[CIA_A]->crb = CIACRB_LOAD;\n\t\tg_pCia[CIA_B]->cra = CIACRA_LOAD; // CIACRA_START=0, timer is stopped\n\t\tg_pCia[CIA_B]->crb = CIACRB_LOAD;\n\n\t\t// Save OS CIA timer values\n\t\ts_uwOsCiaATimerA = ciaGetTimerA(g_pCia[CIA_A]);\n\t\ts_uwOsCiaBTimerB = ciaGetTimerB(g_pCia[CIA_A]);\n\n\t\t// set ACE CIA timers\n\t\tciaSetTimerA(g_pCia[CIA_A], s_pAceCiaTimerA[CIA_A]);\n\t\tciaSetTimerB(g_pCia[CIA_A], s_pAceCiaTimerB[CIA_A]);\n\t\tciaSetTimerA(g_pCia[CIA_B], s_pAceCiaTimerA[CIA_B]);\n\t\tciaSetTimerB(g_pCia[CIA_B], s_pAceCiaTimerB[CIA_B]);\n\n\t\t// Enable ACE CIA interrupts\n\t\tg_pCia[CIA_A]->icr = (\n\t\t\tCIAICRF_SETCLR | CIAICRF_SERIAL | CIAICRF_TIMER_A | CIAICRF_TIMER_B\n\t\t);\n\t\tg_pCia[CIA_B]->icr = (\n\t\t\tCIAICRF_SETCLR | CIAICRF_SERIAL | CIAICRF_TIMER_A | CIAICRF_TIMER_B\n\t\t);\n\n\t\t// Restore ACE CIA CRA/CRB state\n\t\tg_pCia[CIA_A]->cra = CIACRA_LOAD | s_pAceCiaCra[CIA_A];\n\t\tg_pCia[CIA_A]->crb = CIACRA_LOAD | s_pAceCiaCrb[CIA_A];\n\t\tg_pCia[CIA_B]->cra = CIACRA_LOAD | s_pAceCiaCra[CIA_B];\n\t\tg_pCia[CIA_B]->crb = CIACRA_LOAD | s_pAceCiaCrb[CIA_B];\n\n\t\t// Game's bitplanes & copperlists are still used so don't disable them\n\t\t// Wait for vbl before disabling sprite DMA\n\t\twhile (!(g_pCustom->intreqr & INTF_VERTB)) continue;\n\t\tg_pCustom->dmacon = s_uwOsMinDma;\n\n\t\t// Save OS interrupt vectors and enable ACE's\n\t\tg_pCustom->intreq = 0x7FFF;\n\t\tfor(UWORD i = 0; i < SYSTEM_INT_VECTOR_COUNT; ++i) {\n\t\t\ts_pOsHwInterrupts[i] = s_pHwVectors[SYSTEM_INT_VECTOR_FIRST + i];\n\t\t\ts_pHwVectors[SYSTEM_INT_VECTOR_FIRST + i] = s_pAceHwInterrupts[i];\n\t\t}\n\n\t\t// Enable needed DMA (and interrupt) channels\n\t\tg_pCustom->dmacon = DMAF_SETCLR | DMAF_MASTER | s_uwAceDmaCon;\n\t\tg_pCustom->intena = INTF_SETCLR | INTF_INTEN | s_uwAceIntEna | SYSTEM_ACE_MIN_NO_OS_INTERRUPTS;\n\n\t\t// HACK: OS resets potgo in vblank int, preventing scanning fire2 on most joysticks.\n\t\t// TODO: make sure this doesn't break anything, e.g. mice\n\t\t// TODO: add setting this value to OS-friendly vblank handler with proper priority\n\t\t// https://eab.abime.net/showthread.php?t=74981\n\t\tg_pCustom->potgo = 0xFF00;\n}\n\nvoid ciaIcrHandlerAdd(UBYTE ubCia, UBYTE ubIcrBit) {\n\t// https://wiki.amigaos.net/wiki/CIA_Resource\n\tmemset(&s_pOsCiaIcrHandlers[ubCia][ubIcrBit], 0, sizeof(s_pOsCiaIcrHandlers[ubCia][ubIcrBit]));\n\ts_pOsCiaIcrHandlers[ubCia][ubIcrBit].is_Code = (void(*)(void))ciaIcrHandler;\n\ts_pOsCiaIcrHandlers[ubCia][ubIcrBit].is_Data = (void*)&s_pAceCiaInterrupts[ubCia][ubIcrBit];\n\ts_pOsCiaIcrHandlers[ubCia][ubIcrBit].is_Node.ln_Name = \"ACE CIA ICR handler\";\n\ts_pOsCiaIcrHandlers[ubCia][ubIcrBit].is_Node.ln_Pri = 127;\n\ts_pOsCiaIcrHandlers[ubCia][ubIcrBit].is_Node.ln_Type = NT_INTERRUPT;\n\t// AddICRVector auto-activates ints, leave it be to mimic what ACE does on no-os side\n\tif(AddICRVector(s_pCiaResource[ubCia], ubIcrBit, &s_pOsCiaIcrHandlers[ubCia][ubIcrBit])) {\n\t\tlogWrite(\"CIA %c ICR %d add failed\", (ubCia == CIA_A) ? 'A' : 'B', ubIcrBit);\n\t}\n\t// TODO: check if AddICRVector allocated the same timer as desired using\n\t// private fields of CIA Resource (beware of changed layout in v36)\n\n\t// Set timeout as long as possible, to be reconfigured by int handler registrar\n\tif(ubIcrBit == CIAICRB_TIMER_A) {\n\t\tciaSetTimerA(g_pCia[ubCia], 0xFFFF);\n\t}\n\telse {\n\t\tciaSetTimerB(g_pCia[ubCia], 0xFFFF);\n\t}\n}\n\nvoid ciaIcrHandlerRemove(UBYTE ubCia, UBYTE ubIcrBit) {\n\tRemICRVector(s_pCiaResource[ubCia], ubIcrBit, &s_pOsCiaIcrHandlers[ubCia][ubIcrBit]);\n}\n\n/**\n * @brief Flushes FDD disk activity.\n * Originally written by Asman in asm, known as osflush\n * Rewritten by Asman for issue #76, reformatted for ACE codestyle\n * More explanation about how it works:\n * http://eab.abime.net/showthread.php?t=87202&page=2\n */\nstatic void systemFlushIo(void) {\n\tstruct StandardPacket *pPacket = (struct StandardPacket*)AllocMem(\n\t\tsizeof(struct StandardPacket), MEMF_CLEAR\n\t);\n\n\tif(!pPacket) {\n\t\treturn;\n\t}\n\n\t// Get filesystem message port\n\tstruct MsgPort *pMsgPort = DeviceProc((CONST_STRPTR)\"sys\");\n\tif (pMsgPort) {\n\t\t// Get our message port\n\t\tstruct MsgPort *pProcessMsgPort = &s_pProcess->pr_MsgPort;\n\n\t\t// Fill in packet\n\t\tstruct DosPacket *pDosPacket = &pPacket->sp_Pkt;\n\t\tstruct Message *pMsg = &pPacket->sp_Msg;\n\n\t\t// It is how Tripos packet system was hacked to exec messaging system\n\t\tpMsg->mn_Node.ln_Name = (char*)pDosPacket;\n\t\tpMsg->mn_ReplyPort = pProcessMsgPort;\n\n\t\tpDosPacket->dp_Link = pMsg;\n\t\tpDosPacket->dp_Port = pProcessMsgPort;\n\t\tpDosPacket->dp_Type = ACTION_FLUSH;\n\n\t\t// Send packet\n\t\tPutMsg(pMsgPort, pMsg);\n\n\t\t// Wait for reply\n\t\tWaitPort(pProcessMsgPort);\n\t\tGetMsg(pProcessMsgPort);\n\t}\n\n\tFreeMem(pPacket, sizeof(struct StandardPacket));\n}\n\nvoid systemKill(const char *szMsg) {\n\tlogWrite(\"ERR: ACE SYSKILL: '%s'\", szMsg);\n\tif(DOSBase) {\n\t\tBPTR lOut = Output();\n\t\tWrite(lOut, \"ERR: ACE SYSKILL: \", sizeof(\"ERR: ACE SYSKILL: \"));\n\t\tWrite(lOut, (char*)szMsg, strlen(szMsg));\n\t}\n\n\tif(GfxBase) {\n\t\tCloseLibrary((struct Library *) GfxBase);\n\t}\n\tif(DOSBase) {\n\t\tCloseLibrary((struct Library *) DOSBase);\n\t}\n\texit(EXIT_FAILURE);\n}\n\nvoid systemCreate(void) {\n#if defined(BARTMAN_GCC)\n\t// Bartman's startup code doesn't initialize anything\n\tSysBase = *((struct ExecBase**)4UL);\n#endif\n\n\tDOSBase = (struct DosLibrary*)OpenLibrary((CONST_STRPTR)\"dos.library\", 0);\n\tif (!DOSBase) {\n\t\tsystemKill(\"Can't open DOS Library\\n\");\n\t\treturn;\n\t}\n\n\tGfxBase = (struct GfxBase *)OpenLibrary((CONST_STRPTR)\"graphics.library\", 0L);\n\tif (!GfxBase) {\n\t\tsystemKill(\"Can't open Gfx Library\\n\");\n\t\treturn;\n\t}\n\n\ts_pProcess = (struct Process *)FindTask(NULL);\n#if defined(BARTMAN_GCC)\n\tif(!s_pProcess->pr_CLI) {\n\t\t// Called from the workbench - get the message for later reply\n\t\t// Taken from https://github.com/alpine9000/EWGM/blob/master/game/wbstartup.i\n\t\tWaitPort(&s_pProcess->pr_MsgPort); // Wait for the message\n\t\ts_pReturnMsg = GetMsg(&s_pProcess->pr_MsgPort); // Get the message for later reply\n\t\ts_bpStartLock = CurrentDir(((struct WBStartup*)s_pReturnMsg)->sm_ArgList[0].wa_Lock);\n\t}\n#else // Bebbo\n\ts_bpStartLock = CurrentDir(_WBenchMsg->sm_ArgList[0].wa_Lock);\n#endif\n\n\t// Disable system requesters on write protected/drive full etc when trying to create files\n\ts_pOldWindow = s_pProcess->pr_WindowPtr;\n\ts_pProcess->pr_WindowPtr = (void*)-1;\n\n\t// Determine original stack size\n\tchar *pStackLower = (char *)s_pProcess->pr_Task.tc_SPLower;\n\tULONG ulStackSize = (char *)s_pProcess->pr_Task.tc_SPUpper - pStackLower;\n\tif(s_pProcess->pr_CLI) {\n\t\tulStackSize = *(ULONG *)s_pProcess->pr_ReturnAddr;\n\t}\n\tlogWrite(\"Stack size: %lu\\n\", ulStackSize);\n\t*pStackLower = SYSTEM_STACK_CANARY;\n\n\t// Reserve all audio channels - apparantly this allows for int flag polling\n\t// From https://gist.github.com/johngirvin/8fb0c4bb83b7c80427e2f439bb074e95\n\taudioChannelAlloc();\n\n\t// prepare disabling/enabling CDTV device as per Alpine9000 code\n\t// from https://eab.abime.net/showthread.php?t=89836\n\tcdtvPortAlloc();\n\t// immediately disable CDTV device, it gets re-enabled\n\t// at the end of this function in systemUse()\n\tcdtvCdCommand(CMD_STOP);\n\n\tinputHandlerAdd();\n\n\ts_uwOsInitialIntEna = g_pCustom->intenar;\n\tinterruptHandlerAdd(INTB_AUD0);\n\tinterruptHandlerAdd(INTB_AUD1);\n\tinterruptHandlerAdd(INTB_AUD2);\n\tinterruptHandlerAdd(INTB_AUD3);\n\tinterruptHandlerAdd(INTB_VERTB);\n\n\ts_pCiaResource[CIA_A] = OpenResource((CONST_STRPTR)CIAANAME);\n\ts_pCiaResource[CIA_B] = OpenResource((CONST_STRPTR)CIABNAME);\n\n\t// Allocate CIA-B timers for exclusive use\n\tciaIcrHandlerAdd(CIA_B, CIAICRB_TIMER_A);\n\tciaIcrHandlerAdd(CIA_B, CIAICRB_TIMER_B);\n\n\t// Disable as much of OS stuff as possible so that it won't trash stuff when\n\t// re-enabled periodically.\n\t// Save the system copperlists and flush the view\n\n\ts_pOsView = GfxBase->ActiView;\n\tWaitTOF();\n\tLoadView(0);\n\tWaitTOF();\n\tWaitTOF(); // Wait for interlaced screen to finish\n\n\t// get VBR location on 68010+ machine\n\t// http://eab.abime.net/showthread.php?t=65430&page=3\n\tif (SysBase->AttnFlags & AFF_68010) {\n\t\ts_pHwVectors = (tHwIntVector *)Supervisor((void *)s_pGetVbrCode);\n\t}\n\n\t// Finish disk activity\n\tsystemFlushIo();\n\n\t// save the state of the hardware registers (INTENA, DMA, ADKCON etc.)\n\ts_uwOsIntEna = g_pCustom->intenar;\n\ts_uwOsDmaCon = g_pCustom->dmaconr;\n\ts_uwOsInitialDma = s_uwOsDmaCon;\n\n\t// Disable interrupts (this is the actual \"kill system/OS\" part)\n\tg_pCustom->intena = 0x7FFF;\n\tg_pCustom->intreq = 0x7FFF;\n\n\t// Disable all DMA - only once\n\t// Wait for vbl before disabling sprite DMA\n\twhile (!(g_pCustom->intreqr & INTF_VERTB)) continue;\n\tg_pCustom->dmacon = 0x07FF;\n\n\t// Disable system so that it gets backed up once, skip saving intena from systemUnuse()\n\ts_wSystemUses = 0;\n\ts_wSystemBlitterUses = 1;\n\n\t// Query processor cache settings.\n\tif (SysBase->AttnFlags & AFF_68020) {\n\t\ts_sCpuCacheFlags.ulCacr = (ULONG)Supervisor((void *)s_pGetCacr);\n\t} else {\n\t\ts_sCpuCacheFlags.ulCacr = 0;\n\t}\n\t// Query PCR to check if superscalar dispatch is enabled (bit 0). Older Kickstarts may not\n\t// support detecting the 68060, but in that case the Kickstart also won't enable it.\n\t// If we ever do run into the problem that someone enables superscalar dispatch on KS1.3,\n\t// we can adapt https://github.com/keirf/flashfloppy-autoswap/blob/master/shared/disable_caches.S\n\t// (which itself is based on code from ross https://eab.abime.net/showpost.php?p=1303326&postcount=3)\n\t// and execute the instructions to get the PCR under a trap handler that skips it.\n\tif (SysBase->AttnFlags & AFF_68060) {\n\t\ts_sCpuCacheFlags.ulPcr = (ULONG)Supervisor((void *)s_pGetPcr);\n\t} else {\n\t\ts_sCpuCacheFlags.ulPcr = 0;\n\t}\n\ts_sCpuCacheFlags.wDisabledCount = 0;\n\tif (!s_sCpuCacheFlags.ulCacr && !s_sCpuCacheFlags.ulPcr) {\n\t\t// no caches enabled, treat as always disabled\n\t\t++s_sCpuCacheFlags.wDisabledCount;\n\t}\n\n\tsystemOsDisable();\n\tsystemUse(); // Re-enable as little as needed\n\n\tsystemGetBlitterFromOs();\n}\n\nvoid systemDestroy(void) {\n\t// Disable all interrupts\n\tg_pCustom->intena = 0x7FFF;\n\tg_pCustom->intreq = 0x7FFF;\n\n\t// Wait for vbl before disabling sprite DMA\n\twhile (!(g_pCustom->intreqr & INTF_VERTB)) continue;\n\tg_pCustom->dmacon = 0x07FF;\n\tg_pCustom->intreq = 0x7FFF;\n\n\tif(s_sCpuCacheFlags.wDisabledCount != 0) {\n\t\tif(s_sCpuCacheFlags.ulCacr == 0 && s_sCpuCacheFlags.ulPcr == 0) {\n\t\t\tif(s_sCpuCacheFlags.wDisabledCount != 1) {\n\t\t\t\tlogWrite(\"ERR: unclosed/overclosed cpu cache count: %hd\\n\", s_sCpuCacheFlags.wDisabledCount - 1);\n\t\t\t}\n\t\t} else {\n\t\t\tlogWrite(\"ERR: unclosed/overclosed cpu cache count: %hd\\n\", s_sCpuCacheFlags.wDisabledCount);\n\t\t}\n\t}\n\n\t// Start waking up OS\n\tif(s_wSystemUses != 1) {\n\t\tlogWrite(\"ERR: unclosed/overclosed system usage count: %hd\\n\", s_wSystemUses);\n\t\t// Ensure that OS gets restured - along with\n\t}\n\n\t// Restore every single OS DMA & interrupt\n\ts_wSystemUses = 0;\n\tsystemUse();\n\tsystemReleaseBlitterToOs();\n\tg_pCustom->dmacon = DMAF_SETCLR | DMAF_MASTER | s_uwOsInitialDma;\n\n\tciaIcrHandlerRemove(CIA_B, CIAICRB_TIMER_A);\n\tciaIcrHandlerRemove(CIA_B, CIAICRB_TIMER_B);\n\n\taudioChannelFree();\n\tcdtvPortFree();\n\n\tinputHandlerRemove();\n\n\tinterruptHandlerRemove(INTB_AUD0);\n\tinterruptHandlerRemove(INTB_AUD1);\n\tinterruptHandlerRemove(INTB_AUD2);\n\tinterruptHandlerRemove(INTB_AUD3);\n\tinterruptHandlerRemove(INTB_VERTB);\n\n\t// restore old view\n\tWaitTOF();\n\tLoadView(s_pOsView);\n\tWaitTOF();\n\n\tsystemCheckStack();\n\n\tif(s_bpStartLock) {\n\t\tCurrentDir(s_bpStartLock);\n\t}\n\n\ts_pProcess->pr_WindowPtr = s_pOldWindow;\n\n\tlogWrite(\"Closing graphics.library...\\n\");\n\tCloseLibrary((struct Library *) GfxBase);\n\tlogWrite(\"Closing dos.library...\\n\");\n\tCloseLibrary((struct Library *) DOSBase);\n\n#if defined(BARTMAN_GCC)\n\tif(s_pReturnMsg) {\n\t\tReplyMsg(s_pReturnMsg);\n\t}\n#endif\n}\n\nvoid systemUnuse(void) {\n\tif(s_wSystemUses == 1) {\n\t\t// Do before counter is decreased, otherwise it'll fall into infinite loop!\n\t\tlogWrite(\"Turning off the system...\\n\");\n\t}\n\n\t--s_wSystemUses;\n\tif(!s_wSystemUses) {\n\t\tif(g_pCustom->dmaconr & DMAF_DISK) {\n\t\t\t// Flush disk activity if it was used\n\t\t\t// This 'if' is here because otherwise systemUnuse() called\n\t\t\t// by systemCreate() would indefinitely wait for OS when it's killed.\n\t\t\t// systemUse() restores disk DMA, so it's an easy check if OS was\n\t\t\t// actually restored.\n\t\t\tsystemFlushIo();\n\t\t}\n\n\t\t// Disable CDTV CD drive if present\n\t\tcdtvCdCommand(CMD_STOP);\n\n\t\t// save the state of the hardware registers (INTENA)\n\t\ts_uwOsIntEna = g_pCustom->intenar;\n\n\t\tsystemOsDisable();\n\t}\n#if defined(ACE_DEBUG)\n\tif(s_wSystemUses < 0) {\n\t\tlogWrite(\"ERR: System uses less than 0\\n\");\n\t\ts_wSystemUses = 0;\n\t}\n#endif\n}\n\nvoid systemUse(void) {\n\tif(!s_wSystemUses) {\n\t\t// Disable app interrupts/dma, keep display-related DMA\n\t\tg_pCustom->intena = 0x7FFF;\n\t\tg_pCustom->intreq = 0x7FFF;\n\t\tg_pCustom->dmacon = s_uwOsMinDma;\n\t\twhile(!(g_pCustom->intreqr & INTF_VERTB)) continue;\n\n\t\t// Disable CIA interrupts\n\t\tg_pCia[CIA_A]->icr = 0x7F;\n\t\tg_pCia[CIA_B]->icr = 0x7F;\n\n\t\t// Restore interrupt vectors - also CIA\n\t\tfor(UWORD i = 0; i < SYSTEM_INT_VECTOR_COUNT; ++i) {\n\t\t\ts_pHwVectors[SYSTEM_INT_VECTOR_FIRST + i] = s_pOsHwInterrupts[i];\n\t\t}\n\n\t\t// Stop the timers\n\t\tg_pCia[CIA_A]->cra = 0;\n\t\tg_pCia[CIA_A]->crb = 0;\n\t\tg_pCia[CIA_B]->cra = 0;\n\t\tg_pCia[CIA_B]->crb = 0;\n\n\t\t// Restore old CIA timer A values\n\t\tciaSetTimerA(g_pCia[CIA_A], s_uwOsCiaATimerA);\n\t\tciaSetTimerB(g_pCia[CIA_A], s_uwOsCiaBTimerB);\n\n\t\t// Restore OS's CIA interrupts\n\t\t// According to UAE debugger there's nothing in CIA_A\n\t\tg_pCia[CIA_A]->icr = CIAICRF_SETCLR | s_pOsCiaIcr[CIA_A];\n\t\tg_pCia[CIA_B]->icr = CIAICRF_SETCLR | s_pOsCiaIcr[CIA_B];\n\n\t\t// Restore CRA/CRB registers, load the timers again\n\t\tg_pCia[CIA_A]->cra = CIACRA_LOAD | s_pOsCiaCra[CIA_A];\n\t\tg_pCia[CIA_A]->crb = CIACRB_LOAD | s_pOsCiaCrb[CIA_A];\n\t\tg_pCia[CIA_B]->cra = CIACRA_LOAD | s_pOsCiaCra[CIA_B];\n\t\tg_pCia[CIA_B]->crb = CIACRB_LOAD | s_pOsCiaCrb[CIA_B];\n\n\t\t// restore old DMA/INTENA/ADKCON etc. settings\n\t\t// All interrupts but only needed DMA\n\t\tg_pCustom->dmacon = DMAF_SETCLR | DMAF_MASTER | (s_uwOsDmaCon & s_uwOsMinDma);\n\t\tg_pCustom->intena = INTF_SETCLR | INTF_INTEN  | s_uwOsIntEna | s_uwAceIntEna | SYSTEM_ACE_MIN_OS_INTERRUPTS;\n\n\t\t// Nasty keyboard hack - if any key gets pressed / released while system is\n\t\t// inactive, we won't be able to catch it.\n\t\tkeyReset();\n\n\t\t// Re-enable CDTV CD drive if present\n\t\tcdtvCdCommand(CMD_START);\n\t}\n\t++s_wSystemUses;\n\n\tif(s_wSystemUses == 1) {\n\t\t// It should be \"turned\" but I prefer the message being consistent.\n\t\tlogWrite(\"Turning on the system...\\n\");\n\t}\n}\n\nUBYTE systemIsUsed(void) {\n\treturn s_wSystemUses > 0;\n}\n\nvoid systemGetBlitterFromOs(void) {\n\tif(s_wSystemBlitterUses == 1) {\n\t\t// Make OS finish its pending operations before it loses blitter!\n\t\tsystemFlushIo();\n\t\tOwnBlitter();\n\t\tWaitBlit();\n\t}\n\t// This must be decremented after OwnBlitter() so that systemBlitterIsReleasedToOs()\n\t// checked in interrupt won't return 0 during OS blitter op still in progress.\n\t--s_wSystemBlitterUses;\n\n#if defined(ACE_DEBUG)\n\tif(s_wSystemBlitterUses < 0) {\n\t\tlogWrite(\"ERR: System Blitter uses less than 0\\n\");\n\t\ts_wSystemUses = 0;\n\t}\n#endif\n}\n\nvoid systemReleaseBlitterToOs(void) {\n\tif (!s_wSystemBlitterUses){\n\t\tWaitBlit();\n\t\tDisownBlitter();\n\t}\n\t++s_wSystemBlitterUses;\n}\n\nUBYTE systemBlitterIsReleasedToOs(void) {\n\treturn s_wSystemBlitterUses > 0;\n}\n\nvoid systemSetKeyInputHandler(tKeyInputHandler cbKeyInputHandler) {\n\ts_cbKeyInputHandler = cbKeyInputHandler;\n}\n\nvoid systemSetInt(\n\tUBYTE ubIntNumber, tAceIntHandler pHandler, void *pIntData\n) {\n\t// Disable interrupt during data swap to not get stuck inside ACE's ISR\n\tg_pCustom->intena = BV(ubIntNumber);\n\n\t// Disable handler or re-enable it if 0 was passed\n\tif(pHandler == 0) {\n\t\ts_pAceInterrupts[ubIntNumber].pHandler = 0;\n\t\ts_uwAceIntEna &= ~BV(ubIntNumber);\n\t}\n\telse {\n\t\ts_pAceInterrupts[ubIntNumber].pHandler = pHandler;\n\t\ts_pAceInterrupts[ubIntNumber].pData = pIntData;\n\t\ts_uwAceIntEna |= BV(ubIntNumber);\n\t\tg_pCustom->intena = INTF_SETCLR | BV(ubIntNumber);\n\t}\n}\n\nvoid systemSetCiaInt(\n\tUBYTE ubCia, UBYTE ubIntBit, tAceIntHandler pHandler, void *pIntData\n) {\n\t// Disable ACE handler during data swap to ensure atomic op\n\ts_pAceCiaInterrupts[ubCia][ubIntBit].pHandler = 0;\n\ts_pAceCiaInterrupts[ubCia][ubIntBit].pData = pIntData;\n\n\t// Re-enable handler or disable it if 0 was passed\n\ts_pAceCiaInterrupts[ubCia][ubIntBit].pHandler = pHandler;\n}\n\nvoid systemSetCiaCr(UBYTE ubCia, UBYTE isCrB, UBYTE ubCrValue) {\n\tif(isCrB) {\n\t\ts_pAceCiaCrb[ubCia] = ubCrValue;\n\t\ts_pOsCiaCrb[ubCia] = ubCrValue;\n\t\tg_pCia[ubCia]->crb = ubCrValue;\n\t}\n\telse {\n\t\ts_pAceCiaCra[ubCia] = ubCrValue;\n\t\ts_pOsCiaCra[ubCia] = ubCrValue;\n\t\tg_pCia[ubCia]->cra = ubCrValue;\n\t}\n}\n\nvoid systemSetDmaBit(UBYTE ubDmaBit, UBYTE isEnabled) {\n\tUWORD uwDmaFlag = BV(ubDmaBit);\n\tsystemSetDmaMask(uwDmaFlag, isEnabled);\n}\n\nvoid systemSetDmaMask(UWORD uwDmaMask, UBYTE isEnabled) {\n\tif(isEnabled) {\n\t\ts_uwAceDmaCon |= uwDmaMask;\n\t\ts_uwOsDmaCon |= uwDmaMask;\n\t\tif(!s_wSystemUses || !(uwDmaMask & s_uwOsMinDma)) {\n\t\t\t// Enable right now if OS is asleep or it's not critical for it to live\n\t\t\tg_pCustom->dmacon = DMAF_SETCLR | uwDmaMask;\n\t\t}\n\t}\n\telse {\n\t\ts_uwAceDmaCon &= ~uwDmaMask;\n\t\tif(!(uwDmaMask & s_uwOsMinDma)) {\n\t\t\ts_uwOsDmaCon &= ~uwDmaMask;\n\t\t}\n\t\tif(!s_wSystemUses || !(uwDmaMask & s_uwOsMinDma)) {\n\t\t\t// Disable right now if OS is asleep or it's not critical for it to live\n\t\t\tg_pCustom->dmacon = uwDmaMask;\n\t\t}\n\t}\n}\n\nvoid systemSetTimer(UBYTE ubCia, UBYTE ubTimer, UWORD uwTicks) {\n\t// Save timer values since backing them up on the fly in continuous mode\n\t// is impossible\n\tUWORD *pTimers = ((ubTimer == 0) ? s_pAceCiaTimerA : s_pAceCiaTimerB);\n\tpTimers[ubCia] = uwTicks;\n\n\tif(!ubTimer) {\n\t\tciaSetTimerA(g_pCia[ubCia], uwTicks);\n\t}\n\telse {\n\t\tciaSetTimerB(g_pCia[ubCia], uwTicks);\n\t}\n}\n\nvoid systemDump(void) {\n\t// logBlockBegin(\"systemDump()\");\n\n\tlogWrite(\"OS Usage counter: %hd\\n\", s_wSystemUses);\n\n\t// Print handlers\n\t// logWrite(\"ACE handlers:\\n\");\n\t// for(UWORD i = 0; i < SYSTEM_INT_HANDLER_COUNT; ++i) {\n\t// \tlogWrite(\n\t// \t\t\"Int %hu: code %p, data %p\\n\",\n\t// \t\ti, s_pAceInterrupts[i].pHandler, s_pAceInterrupts[i].pData\n\t// \t);\n\t// }\n\n\t// Print vectors\n\t// logWrite(\"Vectors:\\n\");\n\t// for(UWORD i = 0; i < SYSTEM_INT_VECTOR_COUNT; ++i) {\n\t// \tlogWrite(\n\t// \t\t\"vec %hu: ACE %p, OS %p, curr %p\\n\",\n\t// \t\ti, s_pAceHwInterrupts[i], s_pOsHwInterrupts[i],\n\t// \t\ts_pHwVectors[SYSTEM_INT_VECTOR_FIRST+ i]\n\t// \t);\n\t// }\n\n\t// logBlockEnd(\"systemDump()\");\n}\n\nvoid systemIdleBegin(void) {\n#if defined(BARTMAN_GCC)\n\tdebug_start_idle();\n#endif\n}\n\nvoid systemIdleEnd(void) {\n#if defined(BARTMAN_GCC)\n\tdebug_stop_idle();\n#endif\n}\n\nUBYTE systemGetVerticalBlankFrequency(void){\n\treturn SysBase->VBlankFrequency;\n}\n\nUBYTE systemIsPal(void) {\n\n\tUBYTE ubVBlankFreq = systemGetVerticalBlankFrequency();\n\tif (ubVBlankFreq == 60) {\n\t\treturn 0; // NTSC\n\t}\n\n\treturn 1; // PAL\n}\n\nvoid systemCheckStack(void) {\n\tchar *pStackLower = (char *)s_pProcess->pr_Task.tc_SPLower;\n\tregister ULONG *pCurrentStackPos __asm(\"sp\");\n\n\tif(*pStackLower != SYSTEM_STACK_CANARY) {\n\t\tlogWrite(\"ERR: Stack has probably overflown\");\n\t\twhile(1) {}\n\t}\n\n\tif((ULONG)pCurrentStackPos < (ULONG)(pStackLower)) {\n\t\tlogWrite(\"ERR: out of stack bounds\\n\");\n\t\twhile(1) {}\n\t}\n}\n\nUWORD systemGetVersion(void) {\n\treturn SysBase->LibNode.lib_Version;\n}\n\nUBYTE systemIsStartVolumeWritable(void) {\n\tsystemUse();\n\tsystemReleaseBlitterToOs();\n\tstruct InfoData sInfoData;\n\tUBYTE isWritable = 0;\n\tif(\n\t\tInfo((BPTR)s_bpStartLock, &sInfoData) &&\n\t\tsInfoData.id_DiskState != ID_WRITE_PROTECTED\n\t) {\n\t\tisWritable = 1;\n\t}\n\tsystemGetBlitterFromOs();\n\tsystemUnuse();\n\treturn isWritable;\n}\n\nvoid systemDisableCpuCaches() {\n\t++s_sCpuCacheFlags.wDisabledCount;\n\tif (s_sCpuCacheFlags.wDisabledCount > 1) {\n\t\treturn;\n\t}\n\n\tregister volatile ULONG cacheDisable __asm(\"d0\");\n\tif (UNLIKELY(s_sCpuCacheFlags.ulCacr & 0x80008000)) {\n\t\t// on 68040+, bits 31 and 15 control if the caches are enabled,\n\t\t// flushing is done via the CPUSHA instruction\n\t\tcacheDisable = s_sCpuCacheFlags.ulCacr & ~(0x80008000);\n\t\tSupervisor((void *)s_pSetCacr040);\n\t} else if (UNLIKELY(s_sCpuCacheFlags.ulCacr & 0x101)) {\n\t\t// on 68020+, bit 1 is the instruction cache, writing bit 3 as 1 flushes it\n\t\t// on 68030+, bit 8 is the data cache, writing bit 11 as 1 flushes it\n\t\tcacheDisable = 0x808;\n\t\tSupervisor((void *)s_pSetCacr);\n\t}\n\tif (UNLIKELY(s_sCpuCacheFlags.ulPcr & 0x1)) {\n\t\t// clear low bit, the superscalar dispatch bit\n\t\tcacheDisable = s_sCpuCacheFlags.ulPcr & ~0x1;\n\t\tSupervisor((void *)s_pSetPcr);\n\t}\n}\n\nvoid systemRestoreCpuCaches() {\n\t--s_sCpuCacheFlags.wDisabledCount;\n\tif (s_sCpuCacheFlags.wDisabledCount > 0) {\n\t\treturn;\n\t}\n#if defined(ACE_DEBUG)\n\tif (s_sCpuCacheFlags.wDisabledCount < 0) {\n\t\tlogWrite(\"ERR: systemRestoreCpuCaches called more often than systemDisableCpuCaches\\n\");\n\t\ts_sCpuCacheFlags.wDisabledCount = 0;\n\t}\n#endif\n\n\tregister volatile ULONG cacheEnable __asm(\"d0\");\n\tif (s_sCpuCacheFlags.ulCacr) {\n\t\tcacheEnable = s_sCpuCacheFlags.ulCacr;\n\t\tSupervisor((void *)s_pSetCacr);\n\t}\n\tif (s_sCpuCacheFlags.ulPcr) {\n\t\tcacheEnable = s_sCpuCacheFlags.ulPcr;\n\t\tSupervisor((void *)s_pSetPcr);\n\t}\n}\n"
  },
  {
    "path": "src/ace/managers/timer.c",
    "content": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at http://mozilla.org/MPL/2.0/. */\n\n#include <ace/managers/timer.h>\n#include <ace/managers/log.h>\n#include <ace/managers/system.h>\n\n/* Globals */\ntTimerManager g_sTimerManager = {0};\n\n/* Functions */\n\nvoid timerCreate(void) {\n\tg_sTimerManager.uwFrameCounter = 0;\n}\n\nvoid timerDestroy(void) {\n\t// systemSetInt(INTB_VERTB, 0, 0);\n}\n\nULONG timerGet(void) {\n\treturn g_sTimerManager.uwFrameCounter;\n}\n\nvoid timerOnInterrupt(void) {\n\t++g_sTimerManager.uwFrameCounter;\n}\n\nULONG timerGetPrec(void) {\n#ifdef AMIGA\n\t// There are 4 cases how measurments may take place:\n\t// a) uwFr1, pRay, uwFr2 on frame A\n\t// b) uwFr1, pRay on frame A; uwFr2 on frame B\n\t// c) uwFr1 on frame A; pRay, uwFr2 on frame B\n\t// d) uwFr2, pRay, uwFr2 on frame B\n\t// So if pRay took place at low Y pos, it must be on frame B so use uwFr2,\n\t// Otherwise, pRay took place on A, so use uwFr1\n\tUWORD uwFr1 = g_sTimerManager.uwFrameCounter;\n\ttRayPos sRay = getRayPos();\n\tUWORD uwFr2 = g_sTimerManager.uwFrameCounter;\n\tif(sRay.bfPosY < 100) {\n\t\treturn (uwFr2 * 160 * 313 + sRay.bfPosY * 160 + sRay.bfPosX);\n\t}\n\telse {\n\t\treturn (uwFr1 * 160 * 313 + sRay.bfPosY * 160 + sRay.bfPosX);\n\t}\n#else\n\treturn 0;\n#endif\n}\n\nULONG timerGetDelta(ULONG ulStart, ULONG ulStop) {\n\tif(ulStop >= ulStart) {\n\t\treturn ulStop-ulStart;\n\t}\n\treturn (0xFFFFFFFF - ulStart) + ulStop;\n}\n\nUBYTE timerPeek(ULONG *pTimer, ULONG ulTimerDelay) {\n\treturn (*pTimer + ulTimerDelay) <= g_sTimerManager.ulGameTicks;\n}\n\nUBYTE timerCheck(ULONG *pTimer, ULONG ulTimerDelay) {\n\tif (timerPeek(pTimer, ulTimerDelay)) {\n\t\t*pTimer = g_sTimerManager.ulGameTicks;\n\t\treturn 1;\n\t}\n\treturn 0;\n}\n\nvoid timerProcess(void) {\n\tULONG ulCurrentTime;\n\n\tulCurrentTime = timerGet();\n\tif(!g_sTimerManager.ubPaused) {\n\t\tif(ulCurrentTime > g_sTimerManager.ulLastTime) {\n\t\t\tg_sTimerManager.ulGameTicks += ulCurrentTime - g_sTimerManager.ulLastTime;\n\t\t}\n\t\telse {\n\t\t\tg_sTimerManager.ulGameTicks += (0xFFFF - g_sTimerManager.ulLastTime) + ulCurrentTime + 1;\n\t\t}\n\t}\n\tg_sTimerManager.ulLastTime = ulCurrentTime;\n}\n\nvoid timerFormatPrec(char *szBfr, ULONG ulPrecTime) {\n\tULONG ulResult, ulRest;\n\tif(ulPrecTime > 0xFFFFFFFF>>2) {\n\t\tsprintf(szBfr, \">7min\");\n\t\treturn;\n\t}\n\t// ulResult [us]\n\tulResult = ulPrecTime*4;\n\tulRest = ulResult % 10;\n\tulResult = ulResult / 10;\n\tif(ulResult < 1000) {\n\t\tsprintf(szBfr, \"%3lu.%01lu us\", ulResult, ulRest);\n\t\treturn;\n\t}\n\t// ulResult [ms]\n\tulRest = ulResult % 1000;\n\tulResult /= 1000;\n\tif(ulResult < 1000) {\n\t\tsprintf(szBfr, \"%3lu.%03lu ms\", ulResult, ulRest);\n\t\treturn;\n\t}\n\t// ulResult [s]\n\tulRest = ulResult % 1000;\n\tulResult /= 1000;\n\tsprintf(szBfr, \"%lu.%03lu s\", ulResult, ulRest);\n}\n\nvoid timerWaitUs(UWORD uwUsCnt) {\n\t// timerGetPrec(): One tick equals: PAL - 0.40us, NTSC - 0.45us\n\tULONG ulStart = timerGetPrec();\n\tUWORD uwTickCnt = uwUsCnt*2/5;\n\twhile(timerGetPrec() - ulStart < uwTickCnt) continue;\n}\n"
  },
  {
    "path": "src/ace/managers/viewport/camera.c",
    "content": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at http://mozilla.org/MPL/2.0/. */\n\n#include <ace/managers/viewport/camera.h>\n#include <ace/macros.h>\n\ntCameraManager *cameraCreate(\n\ttVPort *pVPort, UWORD uwPosX, UWORD uwPosY, UWORD uwMaxX, UWORD uwMaxY,\n\tUBYTE isDblBfr\n) {\n\tlogBlockBegin(\n\t\t\"cameraCreate(pVPort: %p, uwPosX: %u, uwPosY: %u, uwMaxX: %u, uwMaxY: %u, isDblBfr: %hhu)\",\n\t\tpVPort, uwPosX, uwPosY, uwMaxX, uwMaxY, isDblBfr\n\t);\n\ttCameraManager *pManager;\n\n\tpManager = memAllocFastClear(sizeof(tCameraManager));\n\tlogWrite(\"Addr: %p\\n\", pManager);\n\tpManager->sCommon.process = (tVpManagerFn)cameraProcess;\n\tpManager->sCommon.destroy = (tVpManagerFn)cameraDestroy;\n\tpManager->sCommon.pVPort = pVPort;\n\tpManager->sCommon.ubId = VPM_CAMERA;\n\n\tlogWrite(\"Resetting camera bounds...\\n\");\n\tcameraReset(pManager, uwPosX, uwPosY, uwMaxX, uwMaxY, isDblBfr);\n\n\tlogWrite(\"Attaching camera to VPort...\\n\");\n\tvPortAddManager(pVPort, (tVpManager*)pManager);\n\tlogBlockEnd(\"cameraCreate()\");\n\treturn pManager;\n}\n\nvoid cameraDestroy(tCameraManager *pManager) {\n\tlogWrite(\"cameraManagerDestroy...\");\n\tmemFree(pManager, sizeof(tCameraManager));\n\tlogWrite(\"OK! \\n\");\n}\n\nvoid cameraProcess(tCameraManager *pManager) {\n\tpManager->uLastPos[pManager->ubBfr].ulYX = pManager->uPos.ulYX;\n\tif(pManager->isDblBfr) {\n\t\tpManager->ubBfr = !pManager->ubBfr;\n\t}\n}\n\nvoid cameraReset(\n\ttCameraManager *pManager,\n\tUWORD uwStartX, UWORD uwStartY, UWORD uwWidth, UWORD uwHeight, UBYTE isDblBfr\n) {\n\tlogBlockBegin(\n\t\t\"cameraReset(pManager: %p, uwStartX: %u, uwStartY: %u, uwWidth: %u, uwHeight: %u, isDblBfr: %hhu)\",\n\t\tpManager, uwStartX, uwStartY, uwWidth, uwHeight, isDblBfr\n\t);\n\n\tpManager->uPos.uwX = uwStartX;\n\tpManager->uPos.uwY = uwStartY;\n\tpManager->uLastPos[0].uwX = uwStartX;\n\tpManager->uLastPos[0].uwY = uwStartY;\n\tpManager->uLastPos[1].uwX = uwStartX;\n\tpManager->uLastPos[1].uwY = uwStartY;\n\tpManager->isDblBfr = isDblBfr;\n\tpManager->ubBfr = 0;\n\n\t// Max camera coords based on viewport size\n\tpManager->uMaxPos.uwX = uwWidth - pManager->sCommon.pVPort->uwWidth;\n\tpManager->uMaxPos.uwY = uwHeight - pManager->sCommon.pVPort->uwHeight;\n\tlogWrite(\"Camera max coord: %u,%u\\n\", pManager->uMaxPos.uwX, pManager->uMaxPos.uwY);\n\n\tlogBlockEnd(\"cameraReset()\");\n}\n\nvoid cameraSetCoord(tCameraManager *pManager, UWORD uwX, UWORD uwY) {\n\tpManager->uPos.uwX = uwX;\n\tpManager->uPos.uwY = uwY;\n\t// logWrite(\"New camera pos: %u,%u\\n\", uwX, uwY);\n}\n\nvoid cameraMoveBy(tCameraManager *pManager, WORD wDx, WORD wDy) {\n\tpManager->uPos.uwX = CLAMP(pManager->uPos.uwX+wDx, 0, pManager->uMaxPos.uwX);\n\tpManager->uPos.uwY = CLAMP(pManager->uPos.uwY+wDy, 0, pManager->uMaxPos.uwY);\n}\n\nvoid cameraCenterAt(tCameraManager *pManager, UWORD uwAvgX, UWORD uwAvgY) {\n\ttVPort *pVPort;\n\n\tpVPort = pManager->sCommon.pVPort;\n\tpManager->uPos.uwX = CLAMP(uwAvgX - (pVPort->uwWidth>>1), 0, pManager->uMaxPos.uwX);\n\tpManager->uPos.uwY = CLAMP(uwAvgY - (pVPort->uwHeight>>1), 0, pManager->uMaxPos.uwY);\n}\n\nUBYTE cameraIsMoved(const tCameraManager *pManager) {\n\treturn pManager->uPos.ulYX != pManager->uLastPos[pManager->ubBfr].ulYX;\n}\n\nUWORD cameraGetXDiff(const tCameraManager *pManager) {\n\treturn ABS(cameraGetDeltaX(pManager));\n}\n\nUWORD cameraGetYDiff(const tCameraManager *pManager) {\n\treturn ABS(cameraGetDeltaX(pManager));\n}\n\nWORD cameraGetDeltaX(const tCameraManager *pManager) {\n\treturn (pManager->uPos.uwX - pManager->uLastPos[pManager->ubBfr].uwX);\n}\n\nWORD cameraGetDeltaY(const tCameraManager *pManager) {\n\treturn (pManager->uPos.uwY - pManager->uLastPos[pManager->ubBfr].uwY);\n}\n"
  },
  {
    "path": "src/ace/managers/viewport/scrollbuffer.c",
    "content": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at http://mozilla.org/MPL/2.0/. */\n\n#include <ace/managers/viewport/scrollbuffer.h>\n#include <ace/utils/tag.h>\n#include <ace/generic/screen.h> // Has the look up table for the COPPER_X_WAIT values.\n#include <limits.h>\n\nstatic UWORD nearestPowerOf2(UWORD uwVal) {\n\t// https://graphics.stanford.edu/~seander/bithacks.html#RoundUpPowerOf2\n\t// Decrease by one and fill result with ones, then increase by one\n\t--uwVal;\n\tuwVal |= uwVal >> 1;\n\tuwVal |= uwVal >> 2;\n\tuwVal |= uwVal >> 4;\n\tuwVal |= uwVal >> 8;\n\t++uwVal;\n\treturn uwVal;\n}\n\n#ifdef ACE_USE_AGA_FEATURES\nstatic UWORD scrollBufferGetDDfStep(const tScrollBufferManager *pManager) {\n\tUWORD uwWidth = pManager->sCommon.pVPort->pView->uwWidth;\n\tUBYTE ubBitplaneFmode = pManager->sCommon.pVPort->ubFmode & 0x03;\n\n\tif(ubBitplaneFmode == 1 || ubBitplaneFmode == 2) {\n\t\treturn ((uwWidth / 32) - 1) * 16;\n\t}\n\n\tif(ubBitplaneFmode == 3) {\n\t\treturn ((uwWidth / 16) - 1) * 6;\n\t}\n\n\treturn ((uwWidth / 16) - 1) * 8;\n}\n#endif\n\ntScrollBufferManager *scrollBufferCreate(void *pTags, ...) {\n\tlogBlockBegin(\"scrollBufferCreate(pTags: %p, ...)\", pTags);\n\n\tva_list vaTags;\n\tva_start(vaTags, pTags);\n\n\t// Init manager\n\ttScrollBufferManager *pManager = memAllocFastClear(sizeof(tScrollBufferManager));\n\tpManager->sCommon.process = (tVpManagerFn)scrollBufferProcess;\n\tpManager->sCommon.destroy = (tVpManagerFn)scrollBufferDestroy;\n\tpManager->sCommon.ubId = VPM_SCROLL;\n\tlogWrite(\"Addr: %p\\n\", pManager);\n\n\tUBYTE isCameraCreated = 0;\n\ttCopList *pCopList = 0;\n\ttVPort *pVPort = (tVPort*)tagGet(pTags, vaTags, TAG_SCROLLBUFFER_VPORT, 0);\n\tif(!pVPort) {\n\t\tlogWrite(\"ERR: No parent viewport (TAG_SCROLLBUFFER_VPORT) specified\\n\");\n\t\tgoto fail;\n\t}\n\tpManager->sCommon.pVPort = pVPort;\n\tlogWrite(\"Parent VPort: %p\\n\", pVPort);\n\n\tUBYTE ubMarginWidth = tagGet(\n\t\tpTags, vaTags, TAG_SCROLLBUFFER_MARGIN_WIDTH, UCHAR_MAX\n\t);\n\tif(ubMarginWidth == UCHAR_MAX) {\n\t\tlogWrite(\n\t\t\t\"ERR: No margin width (TAG_SCROLLBUFFER_MARGIN_WIDTH) specified\\n\"\n\t\t);\n\t\tgoto fail;\n\t}\n\n\t// Buffer bitmap\n\tUWORD uwBoundWidth = tagGet(\n\t\tpTags, vaTags, TAG_SCROLLBUFFER_BOUND_WIDTH, pVPort->uwWidth\n\t);\n\tUWORD uwBoundHeight = tagGet(\n\t\tpTags, vaTags, TAG_SCROLLBUFFER_BOUND_HEIGHT, pVPort->uwHeight\n\t);\n\tUBYTE ubBitmapFlags = tagGet(\n\t\tpTags, vaTags, TAG_SCROLLBUFFER_BITMAP_FLAGS, BMF_CLEAR\n\t);\n\tlogWrite(\"Bounds: %ux%u\\n\", uwBoundWidth, uwBoundHeight);\n\n\tUBYTE isDblBuf = tagGet(pTags, vaTags, TAG_SCROLLBUFFER_IS_DBLBUF, 0);\n\n\t// Create copperlist entries\n\tpCopList = pVPort->pView->pCopList;\n\tif(pCopList->ubMode == COPPER_MODE_BLOCK) {\n\t\tpManager->pStartBlock = copBlockCreate(\n\t\t\tpVPort->pView->pCopList, 2 * pVPort->ubBpp + 8,\n\t\t\t// Vertically addition from DiWStrt, horizontally just so that 6bpp can be set up.\n\t\t\t// First to set are ddf, modulos & shift so they are changed during fetch.\n\t\t\ts_pCopperWaitXByBitplanes[pVPort->ubBpp], pVPort->uwOffsY + pVPort->pView->ubPosY -1\n\t\t);\n\t\tpManager->pBreakBlock = copBlockCreate(\n\t\t\tpVPort->pView->pCopList, 2 * pVPort->ubBpp + 2,\n\t\t\t// Dummy position - will be updated\n\t\t\t0x7F, 0xFF\n\t\t);\n\t}\n\telse {\n\t\tconst UWORD uwInvalidCopOffs = -1;\n\t\tpManager->ubFlags |= SCROLLBUFFER_FLAG_COPLIST_RAW;\n\t\tpManager->uwCopperOffsetStart = tagGet(\n\t\t\tpTags, vaTags, TAG_SCROLLBUFFER_COPLIST_OFFSET_START, uwInvalidCopOffs\n\t\t);\n\t\tif(pManager->uwCopperOffsetStart == uwInvalidCopOffs) {\n\t\t\tlogWrite(\n\t\t\t\t\"ERR: Copperlist offset (TAG_SCROLLBUFFER_COPLIST_OFFSET_START) not specified\\n\"\n\t\t\t);\n\t\t\tgoto fail;\n\t\t}\n\t\tpManager->uwCopperOffsetBreak = tagGet(\n\t\t\tpTags, vaTags, TAG_SCROLLBUFFER_COPLIST_OFFSET_BREAK, uwInvalidCopOffs\n\t\t);\n\t\tif(pManager->uwCopperOffsetBreak == uwInvalidCopOffs) {\n\t\t\tlogWrite(\n\t\t\t\t\"ERR: Copperlist offset (TAG_SCROLLBUFFER_COPLIST_OFFSET_BREAK) not specified\\n\"\n\t\t\t);\n\t\t\tgoto fail;\n\t\t}\n\t\tlogWrite(\"Copperlist offsets: start: %u, break: %u\\n\",\n\t\t\t\t pManager->uwCopperOffsetStart,\n\t\t\t\t pManager->uwCopperOffsetBreak);\n\t}\n\n\tscrollBufferReset(\n\t\tpManager, ubMarginWidth, uwBoundWidth, uwBoundHeight,\n\t\tubBitmapFlags, isDblBuf\n\t);\n\n\t// Must be before camera? Shouldn't be as there are priorities on manager list\n\tvPortAddManager(pVPort, (tVpManager*)pManager);\n\n\t// Find camera manager, create if not exists\n\tpManager->pCamera = (tCameraManager*)vPortGetManager(pVPort, VPM_CAMERA);\n\tif(!pManager->pCamera) {\n\t\tpManager->pCamera = cameraCreate(\n\t\t\tpVPort, 0, 0, uwBoundWidth, uwBoundHeight, isDblBuf\n\t\t);\n\t\tisCameraCreated = 1;\n\t}\n\telse {\n\t\tcameraReset(pManager->pCamera, 0,0, uwBoundWidth, uwBoundHeight, isDblBuf);\n\t}\n\n\t// TODO: Update copperlist with current camera pos?\n\n\tva_end(vaTags);\n\tlogBlockEnd(\"scrollBufferCreate\");\n\treturn pManager;\nfail:\n\tif(isCameraCreated) {\n\t\tcameraDestroy(pManager->pCamera);\n\t}\n\tif(pCopList && pCopList->ubMode == COPPER_MODE_BLOCK && pManager->pStartBlock) {\n\t\tcopBlockDestroy(pCopList, pManager->pStartBlock);\n\t\tif(pManager->pBreakBlock) {\n\t\t\tcopBlockDestroy(pCopList, pManager->pBreakBlock);\n\t\t}\n\t}\n\n\tmemFree(pManager, sizeof(tScrollBufferManager));\n\tva_end(vaTags);\n\tlogBlockEnd(\"scrollBufferCreate\");\n\treturn 0;\n}\n\nvoid scrollBufferDestroy(tScrollBufferManager *pManager) {\n\tlogBlockBegin(\"scrollBufferDestroy(pManager: %p)\", pManager);\n\n\tif(!(pManager->ubFlags & SCROLLBUFFER_FLAG_COPLIST_RAW)) {\n\t\tcopBlockDestroy(pManager->sCommon.pVPort->pView->pCopList, pManager->pStartBlock);\n\t\tcopBlockDestroy(pManager->sCommon.pVPort->pView->pCopList, pManager->pBreakBlock);\n\t}\n\n\tif(pManager->pFront && pManager->pFront != pManager->pBack) {\n\t\tbitmapDestroy(pManager->pFront);\n\t}\n\tif(pManager->pBack) {\n\t\tbitmapDestroy(pManager->pBack);\n\t}\n\tmemFree(pManager, sizeof(tScrollBufferManager));\n\n\tlogBlockEnd(\"scrollBufferDestroy()\");\n}\n\n// All functions to update the raw copperlist below must be matched for the copperlist layout and size\n\nUBYTE scrollBufferGetRawCopperlistInstructionCountStart(UBYTE ubBpp) {\n\treturn (\n\t\t1 + // initial WAIT\n\t \t1 + 2 * ubBpp + // bitplane ptrs & bplcon commands\n\t\t4 // After bitplane ptrs & bplcon\n\t);\n}\n\nUBYTE scrollBufferGetRawCopperlistInstructionCountBreak(UBYTE ubBpp) {\n\treturn (\n\t\t4 + // copper jump location, skip, strobe\n\t \t1 + 2 * ubBpp // WAIT & bitplane ptrs\n\t);\n}\n\nstatic void resetStartCopperlist(tCopCmd *pCmds, tScrollBufferManager *pManager) {\n\tUWORD uwOffsY = (\n\t\tpManager->sCommon.pVPort->pView->ubPosY +\n\t\tpManager->sCommon.pVPort->uwOffsY -1\n\t);\n\tUBYTE ubBpp = pManager->sCommon.pVPort->ubBpp;\n\tUBYTE i = 0;\n\tcopSetWait(&pCmds[i++].sWait, s_pCopperWaitXByBitplanes[ubBpp], uwOffsY);\n\t// prepare bitplane ptrs & bplcon commands. will be updated in process\n\tcopSetMove(&pCmds[i++].sMove, &g_pCustom->bplcon1, 0);\n\tfor(UBYTE j = 0; j < ubBpp; j++) {\n\t\tcopSetMove(&pCmds[i++].sMove, &g_pBplFetch[j].uwHi, 0);\n\t\tcopSetMove(&pCmds[i++].sMove, &g_pBplFetch[j].uwLo, 0);\n\t}\n\t// After bitplane ptrs & bplcon\n\tcopSetMove(&pCmds[i++].sMove, &g_pCustom->ddfstrt, pManager->uwDDfStrt); // Fetch start\n\tcopSetMove(&pCmds[i++].sMove, &g_pCustom->bpl1mod, pManager->uwModulo); // Odd planes modulo\n\tcopSetMove(&pCmds[i++].sMove, &g_pCustom->bpl2mod, pManager->uwModulo); // Even planes modulo\n\tcopSetMove(&pCmds[i++].sMove, &g_pCustom->ddfstop, pManager->uwDDfStop); // Fetch stop\n}\n\nstatic void updateStartCopperlist(tCopCmd *pCmds, const tBitMap *pBitmap, const UWORD uwShift, const ULONG ulPlaneOffs) {\n\tUBYTE i = 1; // the wait at the beginning of the start block doesn't change\n\tcopSetMoveVal(&pCmds[i++].sMove, uwShift);\n\tfor(UBYTE j = 0; j < pBitmap->Depth; j++) {\n\t\tULONG ulPlaneAddr = (ULONG)(pBitmap->Planes[j]) + ulPlaneOffs;\n\t\tcopSetMoveVal(&pCmds[i++].sMove, ulPlaneAddr >> 16);\n\t\tcopSetMoveVal(&pCmds[i++].sMove, ulPlaneAddr & 0xFFFF);\n\t}\n}\n\nstatic void resetBreakCopperlist(tCopCmd *pCmds, const UWORD uwOffsY, const UBYTE ubBpp) {\n\tUBYTE i = 0;\n\t// copper jump location & strobe to jump past the break block\n\tUBYTE offset = scrollBufferGetRawCopperlistInstructionCountBreak(ubBpp);\n\tcopSetMove(&pCmds[i++].sMove, &g_pCop2Lc->uwHi, (ULONG)(pCmds + offset) >> 16);\n\tcopSetMove(&pCmds[i++].sMove, &g_pCop2Lc->uwLo, (ULONG)(pCmds + offset) & 0xFFFF);\n\t// prepare a wait/skip instruction that will always be true immediately\n\tcopSetWait(&pCmds[i++].sWait, 0, 0);\n\t// strobe\n\tcopSetMove(&pCmds[i++].sMove, &g_pCustom->copjmp2, 1);\n\n\t// wait & bitplane ptrs\n\tcopSetWait(&pCmds[i++].sWait, 0, uwOffsY);\n\tfor(UBYTE j = 0; j < ubBpp; j++) {\n\t\tcopSetMove(&pCmds[i++].sMove, &g_pBplFetch[j].uwHi, 0);\n\t\tcopSetMove(&pCmds[i++].sMove, &g_pBplFetch[j].uwLo, 0);\n\t}\n}\n\nstatic void updateBreakCopperlist(tCopCmd *pCmds, const tBitMap *pBitmap, const UWORD uwSplitPos, const ULONG ulBplAddX) {\n\tpCmds[2].sWait.bfIsSkip = 1; // skip the jump so we have this block enabled\n\n\tUBYTE i = 4; // the first 4 bytes are cop2lch, cop2lcl, SKIP/WAIT, cop2jmp\n\tpCmds[i++].sWait.bfWaitY = uwSplitPos;\n\tfor(UBYTE j = 0; j < pBitmap->Depth; j++) {\n\t\tULONG ulPlaneAddr = (ULONG)(pBitmap->Planes[j]) + ulBplAddX;\n\t\tcopSetMoveVal(&pCmds[i++].sMove, ulPlaneAddr >> 16);\n\t\tcopSetMoveVal(&pCmds[i++].sMove, ulPlaneAddr & 0xFFFF);\n\t}\n}\n\nstatic void disableBreakCopperlist(tCopCmd *pCmds) {\n\t// disable the block by setting the block to skip the jump if we're past the beginning\n\t// of the start block (which we always are)\n\tpCmds[2].sWait.bfIsSkip = 0; // do not skip the jump\n}\n\nFN_HOTSPOT\nvoid scrollBufferProcess(tScrollBufferManager *pManager) {\n\tUWORD uwVpHeight = pManager->sCommon.pVPort->uwHeight;\n\n\t// TODO: use deltaX and deltaY to decide if we need to update anything\n\n\t// convert camera pos to scroll pos\n\tUWORD uwScrollX = pManager->pCamera->uPos.uwX;\n\tUWORD uwScrollY = SCROLLBUFFER_HEIGHT_MODULO(\n\t\tpManager->pCamera->uPos.uwY, pManager->uwBmAvailHeight\n\t);\n\n\t// preparations for new copperlist\n\tUWORD uwShift = (16 - (uwScrollX & 0xF)) & 0xF; // Bitplane shift - single\n\tULONG ulBplAddX = ((uwScrollX - 1) >> 4) << 1;  // must be ULONG!\n\tif(pManager->sCommon.pVPort->eFlags & VP_FLAG_HIRES) {\n\t\tuwShift >>= 1; // Usable scroll values are 0..7, shifts 2 pixels per value\n\t\tulBplAddX -= 2; // Fetch 4 bytes (2 words) in scrolling instead of 2 (4)\n\t}\n#ifdef ACE_USE_AGA_FEATURES\n\telse if((pManager->sCommon.pVPort->ubFmode & 0x03) == 1 || (pManager->sCommon.pVPort->ubFmode & 0x03) == 2) {\n\t\tulBplAddX -= 2; // FMODE 1/2 prefetch one extra word\n\t}\n#endif\n\tuwShift = (uwShift << 4) | uwShift;             // Bitplane shift - PF1 | PF2\n\n\ttCopList *pCopList = pManager->sCommon.pVPort->pView->pCopList;\n\n\tULONG ulPlaneOffs = ulBplAddX + (pManager->pBack->BytesPerRow*uwScrollY);\n\tif(pManager->ubFlags & SCROLLBUFFER_FLAG_COPLIST_RAW) {\n\t\tupdateStartCopperlist(&pCopList->pBackBfr->pList[pManager->uwCopperOffsetStart], pManager->pBack, uwShift, ulPlaneOffs);\n\n\t\ttCopCmd *pCmdListBreak = &pCopList->pBackBfr->pList[pManager->uwCopperOffsetBreak];\n\t\tif(pManager->uwBmAvailHeight - uwScrollY < uwVpHeight) {\n\t\t\tupdateBreakCopperlist(\n\t\t\t\tpCmdListBreak, pManager->pBack,\n\t\t\t\tpManager->sCommon.pVPort->pView->ubPosY +\n\t\t\t\tpManager->sCommon.pVPort->uwOffsY +\n\t\t\t\tpManager->uwBmAvailHeight - uwScrollY - 1,\n\t\t\t\tulBplAddX\n\t\t\t);\n\t\t}\n\t\telse {\n\t\t\tdisableBreakCopperlist(pCmdListBreak);\n\t\t}\n\t}\n\telse {\n\t\t// Initial copper block\n\t\ttCopBlock *pBlock = pManager->pStartBlock;\n\t\tpBlock->uwCurrCount = 0; // Rewind copBlock\n\t\tcopMove(pCopList, pBlock, &g_pCustom->bplcon1, uwShift);\n\t\tfor(UBYTE i = pManager->sCommon.pVPort->ubBpp; i--;) {\n\t\t\tULONG ulPlaneAddr = (ULONG)(pManager->pBack->Planes[i]) + ulPlaneOffs;\n\t\t\tcopMove(pCopList, pBlock, &g_pBplFetch[i].uwHi, ulPlaneAddr >> 16);\n\t\t\tcopMove(pCopList, pBlock, &g_pBplFetch[i].uwLo, ulPlaneAddr & 0xFFFF);\n\t\t}\n\t\t// NOTE trying to set colors before and after copper instructions made vport\n\t\t// move one line lower on 4bpp - there will be problem on 5 & 6bpp\n\t\tpBlock->uwCurrCount += 4; // Add constant part\n\n\t\t// Copper block after Y-break\n\t\tpBlock = pManager->pBreakBlock;\n\n\t\tpBlock->uwCurrCount = 0; // Rewind copBlock\n\t\tif(pManager->uwBmAvailHeight - uwScrollY < uwVpHeight) {\n\t\t\tif(pBlock->ubDisabled) {\n\t\t\t\tcopBlockEnable(pCopList, pBlock);\n\t\t\t}\n\t\t\tcopBlockWait(pCopList, pBlock, s_pCopperWaitXByBitplanes[pManager->sCommon.pVPort->ubBpp], (\n\t\t\t\tpManager->sCommon.pVPort->pView->ubPosY +\n\t\t\t\tpManager->sCommon.pVPort->uwOffsY +\n\t\t\t\tpManager->uwBmAvailHeight - uwScrollY - 1\n\t\t\t));\n\t\t\tfor(UBYTE i = pManager->sCommon.pVPort->ubBpp; i--;) {\n\t\t\t\tULONG ulPlaneAddr = (ULONG)(pManager->pBack->Planes[i]) + ulBplAddX;\n\t\t\t\tcopMove(pCopList, pBlock, &g_pBplFetch[i].uwHi, ulPlaneAddr >> 16);\n\t\t\t\tcopMove(pCopList, pBlock, &g_pBplFetch[i].uwLo, ulPlaneAddr & 0xFFFF);\n\t\t\t}\n\t\t}\n\t\telse {\n\t\t\tcopBlockDisable(pCopList, pBlock);\n\t\t}\n\t}\n\n\tpManager->uwVpHeightPrev = uwVpHeight;\n\n\t// Swap buffers if needed\n\tif(pManager->pBack != pManager->pFront) {\n\t\ttBitMap *pTmp = pManager->pBack;\n\t\tpManager->pBack = pManager->pFront;\n\t\tpManager->pFront = pTmp;\n\t}\n}\n\nvoid scrollBufferReset(\n\ttScrollBufferManager *pManager, UBYTE ubMarginWidth,\n\tUWORD uwBoundWidth, UWORD uwBoundHeight, UBYTE ubBitmapFlags, UBYTE isDblBuf\n) {\n\tlogBlockBegin(\n\t\t\"scrollBufferReset(pManager: %p, ubMarginWidth: %hu, uwBoundWidth: %u, uwBoundHeight: %u)\",\n\t\tpManager, ubMarginWidth, uwBoundWidth, uwBoundHeight\n\t);\n\t// Helper vars\n\tUWORD uwVpWidth = pManager->sCommon.pVPort->uwWidth;\n\tUWORD uwVpHeight = pManager->sCommon.pVPort->uwHeight;\n\n\t// Reset manager fields\n\tpManager->uwVpHeightPrev = 0;\n\tpManager->uBfrBounds.uwX = uwBoundWidth;\n\tpManager->uBfrBounds.uwY = uwBoundHeight;\n\t// Optimize avail height to power of two so that modulo can be an AND\n\tpManager->uwBmAvailHeight =\n\t\tubMarginWidth * (blockCountCeil(uwVpHeight, ubMarginWidth) + 2 * (ACE_SCROLLBUFFER_Y_MARGIN_SIZE + SCROLLBUFFER_Y_DRAW_MARGIN_SIZE));\n#if defined(ACE_SCROLLBUFFER_POT_BITMAP_HEIGHT)\n\tpManager->uwBmAvailHeight = nearestPowerOf2(pManager->uwBmAvailHeight);\n#endif\n\n\t// Destroy old buffer bitmap\n\tif(pManager->pFront && pManager->pFront != pManager->pBack) {\n\t\tbitmapDestroy(pManager->pFront);\n\t}\n\tif(pManager->pBack) {\n\t\tbitmapDestroy(pManager->pBack);\n\t}\n\n\t// Create new buffer bitmap\n\tUWORD uwCalcWidth = uwVpWidth + ubMarginWidth * 2 * (ACE_SCROLLBUFFER_X_MARGIN_SIZE + SCROLLBUFFER_X_DRAW_MARGIN_SIZE);\n\tUWORD uwCalcHeight = pManager->uwBmAvailHeight + blockCountCeil(uwBoundWidth, uwVpWidth) - 1;\n\tpManager->pBack = bitmapCreate(\n\t\tuwCalcWidth, uwCalcHeight, pManager->sCommon.pVPort->ubBpp, ubBitmapFlags\n\t);\n\tif(isDblBuf) {\n\t\tpManager->pFront = bitmapCreate(\n\t\t\tuwCalcWidth, uwCalcHeight, pManager->sCommon.pVPort->ubBpp, ubBitmapFlags\n\t\t);\n\t}\n\telse {\n\t\tpManager->pFront = pManager->pBack;\n\t}\n\t// Base modulo is row stride minus visible fetch width.\n\t// Extra prefetch words are applied per-mode below.\n\tpManager->uwModulo = pManager->pBack->BytesPerRow - (uwVpWidth >> 3);\n\n\tpManager->uwDDfStrt = (pManager->sCommon.pVPort->pView->ubPosX + 15) / 2 - 16;\n\tpManager->uwDDfStop = pManager->uwDDfStrt + ((pManager->sCommon.pVPort->pView->uwWidth / 16) - 1) * 8;\n#ifdef ACE_USE_AGA_FEATURES\n\tpManager->uwDDfStop = pManager->uwDDfStrt + scrollBufferGetDDfStep(pManager);\n#endif\n\tif(pManager->sCommon.pVPort->eFlags & VP_FLAG_HIRES) {\n\t\tpManager->uwDDfStrt -= 8; // for scroll reasons\n\t\t// Start/stop one 4-step bitplane fetch pattern later: 3120\n\t\tpManager->uwDDfStrt += 4;\n\t\tpManager->uwDDfStop += 4;\n\n\t\t// One word more for fetch\n\t\tpManager->uwModulo -= 2;\n\t}\n\telse {\n#ifdef ACE_USE_AGA_FEATURES\n\t\tif((pManager->sCommon.pVPort->ubFmode & 0x03) == 1 || (pManager->sCommon.pVPort->ubFmode & 0x03) == 2) {\n\t\t\tpManager->uwDDfStrt -= 16;\n\t\t\tpManager->uwModulo -= 4;\n\t\t}\n\t\telse\n#endif\n\t\t{\n\t\t\tpManager->uwDDfStrt -= 8; // for scroll reasons\n\t\t\tpManager->uwModulo -= 2;\n\t\t}\n\t}\n\tlogWrite(\"DDFSTRT: %04X, DDFSTOP: %04X, Modulo: %u\\n\", pManager->uwDDfStrt, pManager->uwDDfStop, pManager->uwModulo);\n\n\t// Constant stuff in copperlist\n\ttCopList *pCopList = pManager->sCommon.pVPort->pView->pCopList;\n\tif(pManager->ubFlags & SCROLLBUFFER_FLAG_COPLIST_RAW) {\n\t\tresetStartCopperlist(\n\t\t\t&pCopList->pBackBfr->pList[pManager->uwCopperOffsetStart],\n\t\t\tpManager\n\t\t);\n\t\tresetBreakCopperlist(\n\t\t\t&pCopList->pBackBfr->pList[pManager->uwCopperOffsetBreak],\n\t\t\tpManager->sCommon.pVPort->pView->ubPosY +\n\t\t\tpManager->sCommon.pVPort->uwOffsY - 1,\n\t\t\tpManager->sCommon.pVPort->ubBpp);\n\t\t// again for double bufferred\n\t\tresetStartCopperlist(\n\t\t\t&pCopList->pFrontBfr->pList[pManager->uwCopperOffsetStart],\n\t\t\tpManager\n\t\t);\n\t\tresetBreakCopperlist(\n\t\t\t&pCopList->pFrontBfr->pList[pManager->uwCopperOffsetBreak],\n\t\t\tpManager->sCommon.pVPort->pView->ubPosY +\n\t\t\tpManager->sCommon.pVPort->uwOffsY - 1,\n\t\t\tpManager->sCommon.pVPort->ubBpp\n\t\t);\n\t}\n\telse {\n\t\ttCopBlock *pBlock = pManager->pStartBlock;\n\t\t// Set initial WAIT\n\t\tcopBlockWait(pCopList, pBlock, s_pCopperWaitXByBitplanes[pManager->sCommon.pVPort->ubBpp], (\n\t\t\tpManager->sCommon.pVPort->pView->ubPosY +\n\t\t\tpManager->sCommon.pVPort->uwOffsY - 1\n\t\t));\n\t\t// After bitplane ptrs & bplcon\n\t\tpBlock->uwCurrCount = 2 * pManager->sCommon.pVPort->ubBpp + 1;\n\t\tcopMove(pCopList, pBlock, &g_pCustom->ddfstrt, pManager->uwDDfStrt); // Fetch start\n\t\tcopMove(pCopList, pBlock, &g_pCustom->bpl1mod, pManager->uwModulo);  // Odd planes modulo\n\t\tcopMove(pCopList, pBlock, &g_pCustom->bpl2mod, pManager->uwModulo);  // Even planes modulo\n\t\tcopMove(pCopList, pBlock, &g_pCustom->ddfstop, pManager->uwDDfStop); // Fetch stop\n\t}\n\n\t// Refresh bitplane pointers in copperlist - 2x for double buffered and with swapped cop front and back buffers\n\tscrollBufferProcess(pManager);\n\ttCopBfr *pBackBfr = pCopList->pBackBfr;\n\tpCopList->pBackBfr = pCopList->pFrontBfr;\n\tscrollBufferProcess(pManager);\n\tpCopList->pBackBfr = pBackBfr;\n\n\tlogBlockEnd(\"scrollBufferReset()\");\n}\n\nvoid scrollBufferBlitMask(\n\ttBitMap *pSrc, WORD wSrcX, WORD wSrcY,\n\ttScrollBufferManager *pDstManager, WORD wDstX, WORD wDstY,\n\tWORD wWidth, WORD wHeight, UWORD *pMsk\n) {\n\t// TODO: if area is visible\n\twDstY %= pDstManager->uwBmAvailHeight;\n\twDstY %= (pDstManager->pBack->BytesPerRow<<3);\n\n\tif(wDstY + wHeight <= pDstManager->uwBmAvailHeight) {\n\t\t// single blit\n\t\tblitUnsafeCopyMask(\n\t\t\tpSrc, wSrcX, wSrcY,\n\t\t\tpDstManager->pBack, wDstX, wDstY,\n\t\t\twWidth, wHeight, (UBYTE*)pMsk\n\t\t);\n\t}\n\telse {\n\t\t// split blit in two\n\t\tWORD wPartHeight;\n\t\twPartHeight = pDstManager->uwBmAvailHeight - wDstY;\n\t\tblitUnsafeCopyMask(\n\t\t\tpSrc, wSrcX, wSrcY,\n\t\t\tpDstManager->pBack, wDstX, wDstY,\n\t\t\twWidth, wPartHeight, (UBYTE*)pMsk\n\t\t);\n\t\tblitUnsafeCopyMask(\n\t\t\tpSrc, wSrcX, wSrcY + wPartHeight,\n\t\t\tpDstManager->pBack, wDstX, 0,\n\t\t\twWidth, wHeight - wPartHeight, (UBYTE*)pMsk\n\t\t);\n\t}\n}\n"
  },
  {
    "path": "src/ace/managers/viewport/simplebuffer.c",
    "content": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at http://mozilla.org/MPL/2.0/. */\n\n#include <ace/managers/viewport/simplebuffer.h>\n#include <proto/exec.h>\n#include <ace/utils/tag.h>\n#include <ace/utils/extview.h>\n#include <ace/generic/screen.h> // Has the look up table for the COPPER_X_WAIT values.\n#ifdef AMIGA\n\n\n// Flags for internal usage.\n#define SIMPLEBUFFER_FLAG_X_SCROLLABLE 1\n#define SIMPLEBUFFER_FLAG_COPLIST_RAW  2\n\nstatic void setBitplanePtrs(tCopCmd *pCmds, const tBitMap *pBitmap, LONG lBplOffs) {\n\tfor(UBYTE i = 0; i < pBitmap->Depth; ++i) {\n\t\tULONG ulPlaneAddr = (ULONG)pBitmap->Planes[i] + lBplOffs;\n\t\tcopSetMove(&(pCmds++)->sMove, &g_pBplFetch[i].uwHi, ulPlaneAddr >> 16);\n\t\tcopSetMove(&(pCmds++)->sMove, &g_pBplFetch[i].uwLo, ulPlaneAddr & 0xFFFF);\n\t}\n}\n\nstatic void updateBitplanePtrs(\n\ttCopCmd *pCmds, const tBitMap *pBitmap, LONG lBplOffs\n) {\n\tfor(UBYTE i = 0; i < pBitmap->Depth; ++i) {\n\t\tULONG ulPlaneAddr = ((ULONG)pBitmap->Planes[i]) + lBplOffs;\n\t\tcopSetMoveVal(&(pCmds++)->sMove, ulPlaneAddr >> 16);\n\t\tcopSetMoveVal(&(pCmds++)->sMove, ulPlaneAddr & 0xFFFF);\n\t}\n}\n\n#ifdef ACE_USE_AGA_FEATURES\nstatic UWORD simpleBufferGetDDfStep(const tSimpleBufferManager *pManager) {\n\tUWORD uwWidth = pManager->sCommon.pVPort->pView->uwWidth;\n\tUBYTE ubBitplaneFmode = pManager->sCommon.pVPort->ubFmode & 0x03;\n\n\tif(ubBitplaneFmode == 1 || ubBitplaneFmode == 2) {\n\t\treturn ((uwWidth / 32) - 1) * 16;\n\t}\n\n\tif(ubBitplaneFmode == 3) {\n\t\treturn ((uwWidth / 16) - 1) * 6;\n\t}\n\n\treturn ((uwWidth / 16) - 1) * 8;\n}\n#endif\n\nstatic void simpleBufferInitializeCopperList(\n\ttSimpleBufferManager *pManager, UBYTE isScrollX\n) {\n\tpManager->uBfrBounds.uwX = bitmapGetByteWidth(pManager->pFront) << 3;\n\tpManager->uBfrBounds.uwY = pManager->pFront->Rows;\n\tUWORD uwModulo = pManager->pFront->BytesPerRow - (pManager->sCommon.pVPort->uwWidth >> 3);\n\n\t// http://amigadev.elowar.com/read/ADCD_2.1/Hardware_Manual_guide/node0085.html\n\tUWORD uwDDfStrt = (pManager->sCommon.pVPort->pView->ubPosX + 15) / 2 - 16;\n\tUWORD uwDDFStep = ((pManager->sCommon.pVPort->pView->uwWidth / 16)-1)*8;\n#ifdef ACE_USE_AGA_FEATURES\n\tuwDDFStep = simpleBufferGetDDfStep(pManager);\n#endif\n\tUWORD uwDDfStop = uwDDfStrt + uwDDFStep;\n\tif(pManager->sCommon.pVPort->eFlags & VP_FLAG_HIRES) {\n\t\tuwDDfStrt += 4;\n\t\tuwDDfStop += 4;\n\t}\n\n\tif(\n\t\t!isScrollX || pManager->uBfrBounds.uwX <= pManager->sCommon.pVPort->uwWidth\n\t) {\n\t\tpManager->ubFlags &= ~SIMPLEBUFFER_FLAG_X_SCROLLABLE;\n\t}\n\telse {\n\t\tpManager->ubFlags |= SIMPLEBUFFER_FLAG_X_SCROLLABLE;\n\t\tif(pManager->sCommon.pVPort->eFlags & VP_FLAG_HIRES) {\n\t\t\tuwDDfStrt -= 8; // two more hires 4-part bitplane fetch pattern: 3120\n\t\t\tuwModulo -= 4;\n\t\t}\n\t\telse {\n#ifdef ACE_USE_AGA_FEATURES\n\t\t\tif((pManager->sCommon.pVPort->ubFmode & 0x03) == 1 || (pManager->sCommon.pVPort->ubFmode & 0x03) == 2) {\n\t\t\t\tuwDDfStrt -= 16;\n\t\t\t\tuwModulo -= 4;\n\t\t\t}\n\t\t\telse\n#endif\n\t\t\t{\n\t\t\t\tuwDDfStrt -= 8; // one more lores 8-part bitplane fetch pattern: x351x240\n\t\t\t\tuwModulo -= 2;\n\t\t\t}\n\t\t}\n\t}\n\tlogWrite(\"DDFSTRT: %04X, DDFSTOP: %04X, Modulo: %u\\n\", uwDDfStrt, uwDDfStop, uwModulo);\n\n\t// if X scroll is enabled then it needs to start one word early\n\tULONG ulBplOffs = 0;\n\tif(pManager->ubFlags & SIMPLEBUFFER_FLAG_X_SCROLLABLE) {\n\t\tif(pManager->sCommon.pVPort->eFlags & VP_FLAG_HIRES) {\n\t\t\tulBplOffs = -4;\n\t\t}\n\t\telse {\n#ifdef ACE_USE_AGA_FEATURES\n\t\t\tif((pManager->sCommon.pVPort->ubFmode & 0x03) == 1 || (pManager->sCommon.pVPort->ubFmode & 0x03) == 2) {\n\t\t\t\tulBplOffs = -4;\n\t\t\t}\n\t\t\telse\n#endif\n\t\t\t{\n\t\t\t\tulBplOffs = -2;\n\t\t\t}\n\t\t}\n\t}\n\t// Update (rewrite) copperlist\n\t// TODO this could be unified with copBlock being set with copSetMove too\n\ttCopList *pCopList = pManager->sCommon.pVPort->pView->pCopList;\n\tif(pManager->ubFlags & SIMPLEBUFFER_FLAG_COPLIST_RAW) {\n\t\t// Since simpleBufferProcess only updates bitplane ptrs and shift,\n\t\t// copperlist must be shaped here.\n\t\t// WAIT is calc'd in same way as in copBlockCreate in simpleBufferCreate().\n\t\ttCopCmd *pCmdList = &pCopList->pBackBfr->pList[pManager->uwCopperOffset];\n\t\tlogWrite(\n\t\t\t\"Setting copperlist %p at offs %u\\n\",\n\t\t\tpCopList->pBackBfr, pManager->uwCopperOffset\n\t\t);\n\t\tcopSetWait(&pCmdList[0].sWait, s_pCopperWaitXByBitplanes[pManager->sCommon.pVPort->ubBpp], (\n\t\t\tpManager->sCommon.pVPort->uwOffsY +\n\t\t\tpManager->sCommon.pVPort->pView->ubPosY -1\n\t\t));\n\t\tcopSetMove(&pCmdList[1].sMove, &g_pCustom->ddfstop, uwDDfStop); // Data fetch\n\t\tcopSetMove(&pCmdList[2].sMove, &g_pCustom->ddfstrt, uwDDfStrt);\n\t\tcopSetMove(&pCmdList[3].sMove, &g_pCustom->bpl1mod, uwModulo); // Bitplane modulo\n\t\tcopSetMove(&pCmdList[4].sMove, &g_pCustom->bpl2mod, uwModulo);\n\t\tcopSetMove(&pCmdList[5].sMove, &g_pCustom->bplcon1, 0); // Shift: 0\n\n\t\t// Copy to front buffer since it needs initialization there too\n\t\tfor(UWORD i = pManager->uwCopperOffset; i < pManager->uwCopperOffset + 6; ++i) {\n\t\t\tpCopList->pFrontBfr->pList[i].ulCode = pCopList->pBackBfr->pList[i].ulCode;\n\t\t}\n\n\t\t// Proper back buffer pointers\n\t\tsetBitplanePtrs(&pCmdList[6], pManager->pFront, ulBplOffs);\n\n\t\t// Proper front buffer pointers\n\t\tpCmdList = &pCopList->pFrontBfr->pList[pManager->uwCopperOffset];\n\t\tsetBitplanePtrs(&pCmdList[6], pManager->pBack, ulBplOffs);\n\t}\n\telse {\n\t\ttCopBlock *pBlock = pManager->pCopBlock;\n\t\tpBlock->uwCurrCount = 0; // Rewind to beginning\n\t\tcopMove(pCopList, pBlock, &g_pCustom->ddfstop, uwDDfStop); // Data fetch\n\t\tcopMove(pCopList, pBlock, &g_pCustom->ddfstrt, uwDDfStrt);\n\t\tcopMove(pCopList, pBlock, &g_pCustom->bpl1mod, uwModulo); // Bitplane modulo\n\t\tcopMove(pCopList, pBlock, &g_pCustom->bpl2mod, uwModulo);\n\t\tcopMove(pCopList, pBlock, &g_pCustom->bplcon1, 0); // Shift: 0\n\t\tfor (UBYTE i = 0; i < pManager->sCommon.pVPort->ubBpp; ++i) {\n\t\t\tULONG ulPlaneAddr = (ULONG)pManager->pBack->Planes[i] + ulBplOffs;\n\t\t\tcopMove(pCopList, pBlock, &g_pBplFetch[i].uwHi, ulPlaneAddr >> 16);\n\t\t\tcopMove(pCopList, pBlock, &g_pBplFetch[i].uwLo, ulPlaneAddr & 0xFFFF);\n\t\t}\n\t}\n}\n\nstatic void simpleBufferSetBack(tSimpleBufferManager *pManager, tBitMap *pBack) {\n#if defined(ACE_DEBUG)\n\tif(pManager->pBack && pManager->pBack->Depth != pBack->Depth) {\n\t\tlogWrite(\"ERR: buffer bitmaps differ in BPP\\n\");\n\t\treturn;\n\t}\n#endif\n\tpManager->pBack = pBack;\n}\n\nstatic UWORD simpleBufferCalcBplOffsAndShift(tSimpleBufferManager *pManager, ULONG *pBplOffs) {\n\t// Calculate X movement: bitplane shift, starting word to fetch\n\tUWORD uwShift;\n\tif(pManager->ubFlags & SIMPLEBUFFER_FLAG_X_SCROLLABLE) {\n\t\tuwShift = (16 - (pManager->pCamera->uPos.uwX & 0xF)) & 0xF; // Bitplane shift - single\n\t\t*pBplOffs = ((pManager->pCamera->uPos.uwX - 1) >> 4) << 1;  // Must be ULONG!\n\t\tif(pManager->sCommon.pVPort->eFlags & VP_FLAG_HIRES) {\n\t\t\tuwShift >>= 1; // Usable scroll values are 0..7, shifts 2 pixels per value\n\t\t\t*pBplOffs -= 2; // Fetch 4 bytes (2 words) in scrolling instead of 2 (4)\n\t\t}\n\t\tuwShift = (uwShift << 4) | uwShift; // Convert to bplcon format - PF1 | PF2\n\t}\n\telse {\n\t\tuwShift = 0;\n\t\t*pBplOffs = (pManager->pCamera->uPos.uwX >> 4) << 1;\n\t}\n\n\t// Calculate Y movement\n\t*pBplOffs += pManager->pBack->BytesPerRow * pManager->pCamera->uPos.uwY;\n\treturn uwShift;\n}\n\nvoid simpleBufferSetFront(tSimpleBufferManager *pManager, tBitMap *pFront) {\n\tlogBlockBegin(\n\t\t\"simpleBufferSetFront(pManager: %p, pFront: %p)\",\n\t\tpManager, pFront\n\t);\n#if defined(ACE_DEBUG)\n\tif(pManager->pFront && pManager->pFront->Depth != pFront->Depth) {\n\t\tlogWrite(\"ERR: buffer bitmaps differ in BPP\\n\");\n\t\treturn;\n\t}\n#endif\n\tpManager->pFront = pFront;\n\tlogBlockEnd(\"simplebufferSetFront()\");\n}\n\ntSimpleBufferManager *simpleBufferCreate(void *pTags, ...) {\n\tva_list vaTags;\n\ttCopList *pCopList;\n\ttSimpleBufferManager *pManager;\n\tUWORD uwBoundWidth, uwBoundHeight;\n\tUBYTE ubBitmapFlags;\n\ttBitMap *pFront = 0, *pBack = 0;\n\tUBYTE isCameraCreated = 0;\n\n\tlogBlockBegin(\"simpleBufferCreate(pTags: %p, ...)\", pTags);\n\tva_start(vaTags, pTags);\n\n\t// Init manager\n\tpManager = memAllocFastClear(sizeof(tSimpleBufferManager));\n\tpManager->sCommon.process = (tVpManagerFn)simpleBufferProcess;\n\tpManager->sCommon.destroy = (tVpManagerFn)simpleBufferDestroy;\n\tpManager->sCommon.ubId = VPM_SCROLL;\n\tlogWrite(\"Addr: %p\\n\", pManager);\n\n\ttVPort *pVPort = (tVPort*)tagGet(pTags, vaTags, TAG_SIMPLEBUFFER_VPORT, 0);\n\tif(!pVPort) {\n\t\tlogWrite(\"ERR: No parent viewport (TAG_SIMPLEBUFFER_VPORT) specified\\n\");\n\t\tgoto fail;\n\t}\n\tpManager->sCommon.pVPort = pVPort;\n\tlogWrite(\"Parent VPort: %p\\n\", pVPort);\n\n\t// Buffer bitmap\n\tuwBoundWidth = tagGet(\n\t\tpTags, vaTags, TAG_SIMPLEBUFFER_BOUND_WIDTH, pVPort->uwWidth\n\t);\n\tuwBoundHeight = tagGet(\n\t\tpTags, vaTags, TAG_SIMPLEBUFFER_BOUND_HEIGHT, pVPort->uwHeight\n\t);\n\tubBitmapFlags = tagGet(\n\t\tpTags, vaTags, TAG_SIMPLEBUFFER_BITMAP_FLAGS, BMF_CLEAR\n\t);\n\tlogWrite(\"Bounds: %ux%u\\n\", uwBoundWidth, uwBoundHeight);\n\tpFront = bitmapCreate(\n\t\tuwBoundWidth, uwBoundHeight, pVPort->ubBpp, ubBitmapFlags\n\t);\n\tif(!pFront) {\n\t\tlogWrite(\"ERR: Can't alloc buffer bitmap\\n\");\n\t\tgoto fail;\n\t}\n\n\tUBYTE isDblBfr = tagGet(pTags, vaTags, TAG_SIMPLEBUFFER_IS_DBLBUF, 0);\n\tif(isDblBfr) {\n\t\tpBack = bitmapCreate(\n\t\t\tuwBoundWidth, uwBoundHeight, pVPort->ubBpp, ubBitmapFlags\n\t\t);\n\t\tif(!pBack) {\n\t\t\tlogWrite(\"ERR: Can't alloc buffer bitmap\\n\");\n\t\t\tgoto fail;\n\t\t}\n\t}\n\n\t// Find camera manager, create if not exists\n\tpManager->pCamera = (tCameraManager*)vPortGetManager(pVPort, VPM_CAMERA);\n\tif(!pManager->pCamera) {\n\t\tisCameraCreated = 1;\n\t\tpManager->pCamera = cameraCreate(\n\t\t\tpVPort, 0, 0, uwBoundWidth, uwBoundHeight, isDblBfr\n\t\t);\n\t}\n\n\tpCopList = pVPort->pView->pCopList;\n\tif(pCopList->ubMode == COPPER_MODE_BLOCK) {\n\t\t// CopBlock contains: bitplanes + shiftX\n\t\tpManager->pCopBlock = copBlockCreate(\n\t\t\t// WAIT is already in copBlock so 1 instruction less\n\t\t\tpCopList, simpleBufferGetRawCopperlistInstructionCount(pVPort->ubBpp) - 1,\n\t\t\t// Vertically addition from DiWStrt, horizontally just so that 6bpp can be set up.\n\t\t\t// First to set are ddf, modulos & shift so they are changed during fetch.\n\t\t\ts_pCopperWaitXByBitplanes[pVPort->ubBpp],\n\t\t\t pVPort->uwOffsY + pVPort->pView->ubPosY - 1\n\t\t);\n\t}\n\telse {\n\t\tconst UWORD uwInvalidCopOffs = -1;\n\t\tpManager->ubFlags |= SIMPLEBUFFER_FLAG_COPLIST_RAW;\n\t\tpManager->uwCopperOffset = tagGet(\n\t\t\tpTags, vaTags, TAG_SIMPLEBUFFER_COPLIST_OFFSET, uwInvalidCopOffs\n\t\t);\n\t\tif(pManager->uwCopperOffset == uwInvalidCopOffs) {\n\t\t\tlogWrite(\n\t\t\t\t\"ERR: Copperlist offset (TAG_SIMPLEBUFFER_COPLIST_OFFSET) not specified\\n\"\n\t\t\t);\n\t\t\tgoto fail;\n\t\t}\n\t\tlogWrite(\"Copperlist offset: %u\\n\", pManager->uwCopperOffset);\n\t}\n\n\tUBYTE isScrollX = tagGet(pTags, vaTags, TAG_SIMPLEBUFFER_USE_X_SCROLLING, 1);\n\tsimpleBufferSetFront(pManager, pFront);\n\tsimpleBufferSetBack(pManager, pBack ? pBack : pFront);\n\tsimpleBufferInitializeCopperList(pManager, isScrollX);\n\n\t// Add manager to VPort\n\tvPortAddManager(pVPort, (tVpManager*)pManager);\n\tlogBlockEnd(\"simpleBufferCreate()\");\n\tva_end(vaTags);\n\treturn pManager;\n\nfail:\n\tif(pBack && pBack != pFront) {\n\t\tbitmapDestroy(pBack);\n\t}\n\tif(pFront) {\n\t\tbitmapDestroy(pFront);\n\t}\n\tif(pManager) {\n\t\tif(pManager->pCamera && isCameraCreated) {\n\t\t\tcameraDestroy(pManager->pCamera);\n\t\t}\n\t\tmemFree(pManager, sizeof(tSimpleBufferManager));\n\t}\n\tlogBlockEnd(\"simpleBufferCreate()\");\n\tva_end(vaTags);\n\treturn 0;\n}\n\nvoid simpleBufferDestroy(tSimpleBufferManager *pManager) {\n\tlogBlockBegin(\"simpleBufferDestroy()\");\n\tif(!(pManager->ubFlags & SIMPLEBUFFER_FLAG_COPLIST_RAW)) {\n\t\tcopBlockDestroy(\n\t\t\tpManager->sCommon.pVPort->pView->pCopList, pManager->pCopBlock\n\t\t);\n\t}\n\tif(pManager->pBack != pManager->pFront) {\n\t\tbitmapDestroy(pManager->pBack);\n\t}\n\tbitmapDestroy(pManager->pFront);\n\tmemFree(pManager, sizeof(tSimpleBufferManager));\n\tlogBlockEnd(\"simpleBufferDestroy()\");\n}\n\nvoid simpleBufferProcess(tSimpleBufferManager *pManager) {\n\tconst tCameraManager *pCamera = pManager->pCamera;\n\ttCopList *pCopList = pManager->sCommon.pVPort->pView->pCopList;\n\n\t// Copperlist - regen bitplane ptrs, update shift\n\t// TODO could be unified by using copSetMove in copBlock\n\tif((pManager->ubFlags & SIMPLEBUFFER_FLAG_COPLIST_RAW)) {\n\t\tif(cameraIsMoved(pCamera)) {\n\t\t\t// At least two updates in the row - double-buffered copperlist\n\t\t\t// must update two buffers with state of single-buffered vport manager.\n\t\t\tpManager->ubDirtyCounter = 2;\n\t\t}\n\t\tif(pManager->ubDirtyCounter) {\n\t\t\tULONG ulBplOffs;\n\t\t\tUWORD uwShift = simpleBufferCalcBplOffsAndShift(pManager, &ulBplOffs);\n\t\t\ttCopCmd *pCmdList = &pCopList->pBackBfr->pList[pManager->uwCopperOffset];\n\t\t\tcopSetMoveVal(&pCmdList[5].sMove, uwShift);\n\t\t\tupdateBitplanePtrs(&pCmdList[6], pManager->pBack, ulBplOffs);\n\t\t\t--pManager->ubDirtyCounter;\n\t\t}\n\t}\n\telse if(pManager->pBack != pManager->pFront || cameraIsMoved(pCamera)) {\n\t\t// In double buffering, we can't really check for camera being moved, since\n\t\t// copBlock needs to change its bitplane pointers value each frame and\n\t\t// copperlist needs refreshing.\n\t\tULONG ulBplOffs;\n\t\tUWORD uwShift = simpleBufferCalcBplOffsAndShift(pManager, &ulBplOffs);\n\t\tpManager->pCopBlock->uwCurrCount = 4; // Rewind to shift cmd pos\n\t\tcopMove(pCopList, pManager->pCopBlock, &g_pCustom->bplcon1, uwShift);\n\t\tfor(UBYTE i = 0; i < pManager->pBack->Depth; ++i) {\n\t\t\tULONG ulPlaneAddr = ((ULONG)pManager->pBack->Planes[i]) + ulBplOffs;\n\t\t\tcopMove(pCopList, pManager->pCopBlock, &g_pBplFetch[i].uwHi, ulPlaneAddr >> 16);\n\t\t\tcopMove(pCopList, pManager->pCopBlock, &g_pBplFetch[i].uwLo, ulPlaneAddr & 0xFFFF);\n\t\t}\n\t}\n\n\t// Swap buffers if needed\n\tif(pManager->pBack != pManager->pFront) {\n\t\ttBitMap *pTmp = pManager->pBack;\n\t\tpManager->pBack = pManager->pFront;\n\t\tpManager->pFront = pTmp;\n\t}\n}\n\nUBYTE simpleBufferIsRectVisible(\n\ttSimpleBufferManager *pManager,\n\tUWORD uwX, UWORD uwY, UWORD uwWidth, UWORD uwHeight\n) {\n\treturn (\n\t\tuwX >= pManager->pCamera->uPos.uwX - uwWidth &&\n\t\tuwX <= pManager->pCamera->uPos.uwX + pManager->sCommon.pVPort->uwWidth &&\n\t\tuwY >= pManager->pCamera->uPos.uwY - uwHeight &&\n\t\tuwY <= pManager->pCamera->uPos.uwY + pManager->sCommon.pVPort->uwHeight\n\t);\n}\n\nUBYTE simpleBufferGetRawCopperlistInstructionCount(UBYTE ubBpp) {\n\tUBYTE ubInstructionCount = (\n\t\t1 +       // WAIT cmd\n\t\t2 +       // DDFSTOP / DDFSTART setup\n\t\t2 +       // Odd / even modulos\n\t\t1 +       // X-shift setup in bplcon\n\t\t2 * ubBpp // 2 * 16-bit MOVE for each bitplane\n\t);\n\treturn ubInstructionCount;\n}\n\n#endif // AMIGA\n"
  },
  {
    "path": "src/ace/managers/viewport/tilebuffer.c",
    "content": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at http://mozilla.org/MPL/2.0/. */\n\n#include <ace/managers/viewport/tilebuffer.h>\n#include <ace/macros.h>\n#include <ace/managers/blit.h>\n#include <ace/managers/system.h>\n#include <ace/utils/tag.h>\n#include <ace/generic/screen.h> // Has the look up table for the COPPER_X_WAIT values.\n#include <proto/exec.h> // Bartman's compiler needs this\n\n#define TILEBUFFER_MAX_TILESET_SIZE (1 << (8 * sizeof(tTileBufferTileIndex)))\n\n#if !defined(ACE_DEBUG)\n#define TILEBUFFER_REDRAW_HOG 1\n#else\n#define TILEBUFFER_REDRAW_HOG 0\n#endif\n\n// Zero the ACE_SCROLLBUFFER_X_MARGIN_SIZE/ACE_SCROLLBUFFER_Y_MARGIN_SIZE to see the undraw\n\nstatic UBYTE shiftFromPowerOfTwo(UWORD uwPot) {\n\tUBYTE ubPower = 0;\n\twhile(uwPot > 1) {\n\t\tuwPot >>= 1;\n\t\t++ubPower;\n\t}\n\treturn ubPower;\n}\n\n#define BLIT_WORDS_NON_INTERLEAVED_BIT (0b1 << 5) // tileSize is UBYTE, top bit of width is definitely free\n\nstatic void tileBufferResetRedrawState(\n\ttRedrawState *pState, WORD wStartX, WORD wEndX, WORD wStartY, WORD wEndY\n) {\n#if defined(ACE_SCROLLBUFFER_ENABLE_SCROLL_X)\n\tmemset(&pState->sMarginL, 0, sizeof(tMarginState));\n\tmemset(&pState->sMarginR, 0, sizeof(tMarginState));\n\tpState->sMarginL.wTilePos = wStartX;\n\tpState->sMarginR.wTilePos = wEndX;\n\tpState->pMarginX = &pState->sMarginR;\n\tpState->pMarginOppositeX = &pState->sMarginL;\n#else\n\t(void)wStartX;\n\t(void)wEndX;\n#endif\n\n#if defined(ACE_SCROLLBUFFER_ENABLE_SCROLL_Y)\n\tmemset(&pState->sMarginU, 0, sizeof(tMarginState));\n\tmemset(&pState->sMarginD, 0, sizeof(tMarginState));\n\tpState->sMarginU.wTilePos = wStartY;\n\tpState->sMarginD.wTilePos = wEndY;\n\tpState->pMarginY = &pState->sMarginD;\n\tpState->pMarginOppositeY = &pState->sMarginU;\n#else\n\t(void)wStartY;\n\t(void)wEndY;\n#endif\n\n\tpState->ubPendingCount = 0;\n}\n\nstatic void tileBufferQueueAdd(\n\ttTileBufferManager *pManager, UWORD uwTileX, UWORD uwTileY\n) {\n\t// Add two times so that they're drawn properly in double buffering\n#if defined ACE_DEBUG\n\tif(\n\t\tpManager->pRedrawStates[0].ubPendingCount > pManager->ubQueueSize - 2 ||\n\t\tpManager->pRedrawStates[1].ubPendingCount > pManager->ubQueueSize - 2\n\t) {\n\t\tlogWrite(\"ERR: No more space in redraw queue\");\n\t\treturn;\n\t}\n#endif\n\ttRedrawState *pState = &pManager->pRedrawStates[0];\n\tif(pState->ubPendingCount >= pManager->ubQueueSize) {\n\t\tlogWrite(\"ERR: Pending tiles queue overflow\\n\");\n\t}\n\tpState->pPendingQueue[pState->ubPendingCount].uwX = uwTileX;\n\tpState->pPendingQueue[pState->ubPendingCount].uwY = uwTileY;\n\t++pState->ubPendingCount;\n\n\tpState = &pManager->pRedrawStates[1];\n\tif(pState->ubPendingCount >= pManager->ubQueueSize) {\n\t\tlogWrite(\"ERR: Pending tiles queue overflow\\n\");\n\t}\n\tpState->pPendingQueue[pState->ubPendingCount].uwX = uwTileX;\n\tpState->pPendingQueue[pState->ubPendingCount].uwY = uwTileY;\n\t++pState->ubPendingCount;\n}\n\nvoid tileBufferQueueProcess(tTileBufferManager *pManager) {\n\ttRedrawState *pState = &pManager->pRedrawStates[pManager->ubStateIdx];\n\tif(pState->ubPendingCount) {\n\t\t--pState->ubPendingCount;\n\t\tUBYTE ubPendingCount = pState->ubPendingCount;\n\t\tconst tUwCoordYX *pTile = &pState->pPendingQueue[ubPendingCount];\n\t\ttileBufferDrawTile(pManager, pTile->uwX, pTile->uwY);\n\t}\n}\n\ntTileBufferManager *tileBufferCreate(void *pTags, ...) {\n\tva_list vaTags;\n\ttTileBufferManager *pManager;\n\tUWORD uwTileX, uwTileY;\n\tUBYTE ubBitmapFlags, isDblBuf;\n\tUWORD uwCoplistOffStart, uwCoplistOffBreak;\n\n\tlogBlockBegin(\"tileBufferCreate(pTags: %p, ...)\", pTags);\n\tva_start(vaTags, pTags);\n\n\t// Feed struct with args\n\tpManager = memAllocFastClear(sizeof(tTileBufferManager));\n\tpManager->sCommon.process = (tVpManagerFn)tileBufferProcess;\n\tpManager->sCommon.destroy = (tVpManagerFn)tileBufferDestroy;\n\tpManager->sCommon.ubId = VPM_TILEBUFFER;\n\n\ttVPort *pVPort = (tVPort*)tagGet(pTags, vaTags, TAG_TILEBUFFER_VPORT, 0);\n\tif(!pVPort) {\n\t\tlogWrite(\"ERR: No parent viewport (TAG_TILEBUFFER_VPORT) specified!\\n\");\n\t\tgoto fail;\n\t}\n\tpManager->sCommon.pVPort = pVPort;\n\tlogWrite(\"Parent VPort: %p\\n\", pVPort);\n\n\tUBYTE ubTileShift = tagGet(pTags, vaTags, TAG_TILEBUFFER_TILE_SHIFT, 0);\n\tif(!ubTileShift) {\n\t\tlogWrite(\"ERR: No tile shift (TAG_TILEBUFFER_TILE_SHIFT) specified!\\n\");\n\t\tgoto fail;\n\t}\n\tpManager->ubTileShift = ubTileShift;\n\tpManager->ubTileSize = 1 << ubTileShift;\n\n\tpManager->cbTileDraw = (tTileDrawCallback)tagGet(\n\t\tpTags, vaTags, TAG_TILEBUFFER_CALLBACK_TILE_DRAW, 0\n\t);\n\n\tpManager->pTileSet = (tBitMap*)tagGet(pTags, vaTags, TAG_TILEBUFFER_TILESET, 0);\n\tif(!pManager->pTileSet) {\n\t\tlogWrite(\"ERR: No tileset (TAG_TILEBUFFER_TILESET) specified!\\n\");\n\t\tgoto fail;\n\t}\n\tuwTileX = tagGet(pTags, vaTags, TAG_TILEBUFFER_BOUND_TILE_X, 0);\n\tuwTileY = tagGet(pTags, vaTags, TAG_TILEBUFFER_BOUND_TILE_Y, 0);\n\tif(!uwTileX || !uwTileY) {\n\t\tlogWrite(\n\t\t\t\"ERR: No tile boundaries (TAG_TILEBUFFER_BOUND_TILE_X or _Y) specified!\\n\"\n\t\t);\n\t\tgoto fail;\n\t}\n\n\tpManager->pTileData = 0;\n\tubBitmapFlags = tagGet(pTags, vaTags, TAG_TILEBUFFER_BITMAP_FLAGS, BMF_CLEAR);\n\tisDblBuf = tagGet(pTags, vaTags, TAG_TILEBUFFER_IS_DBLBUF, 0);\n\tuwCoplistOffStart = tagGet(pTags, vaTags, TAG_TILEBUFFER_COPLIST_OFFSET_START, -1);\n\tuwCoplistOffBreak = tagGet(pTags, vaTags, TAG_TILEBUFFER_COPLIST_OFFSET_BREAK, -1);\n\tpManager->ulMaxTilesetSize = tagGet(\n\t\tpTags, vaTags, TAG_TILEBUFFER_MAX_TILESET_SIZE, TILEBUFFER_MAX_TILESET_SIZE\n\t);\n\ttileBufferReset(pManager, uwTileX, uwTileY, ubBitmapFlags, isDblBuf, uwCoplistOffStart, uwCoplistOffBreak);\n\n\tpManager->ubQueueSize = tagGet(\n\t\tpTags, vaTags, TAG_TILEBUFFER_REDRAW_QUEUE_LENGTH, 0\n\t);\n\tif(!pManager->ubQueueSize) {\n\t\tlogWrite(\n\t\t\t\"ERR: No queue size (TAG_TILEBUFFER_REDRAW_QUEUE_LENGTH) specified!\\n\"\n\t\t);\n\t\tgoto fail;\n\t}\n\t// This alloc could be checked in regard of double buffering\n\t// but I want process to be as quick as possible (one 'if' less)\n\t// and redraw queue has no mem footprint at all (256 bytes max?)\n\tpManager->pRedrawStates[0].pPendingQueue = memAllocFast(pManager->ubQueueSize * sizeof(pManager->pRedrawStates[0].pPendingQueue[0]));\n\tpManager->pRedrawStates[1].pPendingQueue = memAllocFast(pManager->ubQueueSize * sizeof(pManager->pRedrawStates[0].pPendingQueue[0]));\n\tif(\n\t\t!pManager->pRedrawStates[0].pPendingQueue ||\n\t\t!pManager->pRedrawStates[1].pPendingQueue\n\t) {\n\t\tgoto fail;\n\t}\n\n\tvPortAddManager(pVPort, (tVpManager*)pManager);\n\n\t// find camera manager, create if not exists\n\t// camera created in scroll bfr\n\tpManager->pCamera = (tCameraManager*)vPortGetManager(pVPort, VPM_CAMERA);\n\n\t// Redraw shouldn't take place here because camera is not in proper pos yet,\n\t// also pTileData is empty\n\n\tva_end(vaTags);\n\tlogBlockEnd(\"tileBufferCreate\");\n\treturn pManager;\nfail:\n\t// TODO: proper fail\n\tif(pManager->pRedrawStates[0].pPendingQueue) {\n\t\tmemFree(pManager->pRedrawStates[0].pPendingQueue, pManager->ubQueueSize * sizeof(pManager->pRedrawStates[0].pPendingQueue[0]));\n\t}\n\tif(pManager->pRedrawStates[1].pPendingQueue) {\n\t\tmemFree(pManager->pRedrawStates[1].pPendingQueue, pManager->ubQueueSize * sizeof(pManager->pRedrawStates[0].pPendingQueue[0]));\n\t}\n\tva_end(vaTags);\n\tlogBlockEnd(\"tileBufferCreate\");\n\treturn 0;\n}\n\nvoid tileBufferDestroy(tTileBufferManager *pManager) {\n\tUWORD uwCol;\n\tlogBlockBegin(\"tileBufferDestroy(pManager: %p)\", pManager);\n\n\t// Free tile data\n\tfor(uwCol = pManager->uTileBounds.uwX; uwCol--;) {\n\t\tmemFree(pManager->pTileData[uwCol], pManager->uTileBounds.uwY * sizeof(pManager->pTileData[uwCol][0]));\n\t}\n\tmemFree(pManager->pTileData, pManager->uTileBounds.uwX * sizeof(pManager->pTileData[0]));\n\n\t// Free tile offset lookup table\n\tif(pManager->pTileSetOffsets) {\n\t\tmemFree(pManager->pTileSetOffsets, sizeof(pManager->pTileSetOffsets[0]) * pManager->ulMaxTilesetSize);\n\t}\n\n\tif(pManager->pRedrawStates[0].pPendingQueue) {\n\t\tmemFree(pManager->pRedrawStates[0].pPendingQueue, pManager->ubQueueSize * sizeof(pManager->pRedrawStates[0].pPendingQueue[0]));\n\t}\n\tif(pManager->pRedrawStates[1].pPendingQueue) {\n\t\tmemFree(pManager->pRedrawStates[1].pPendingQueue, pManager->ubQueueSize * sizeof(pManager->pRedrawStates[0].pPendingQueue[0]));\n\t}\n\n\t// Free manager\n\tmemFree(pManager, sizeof(tTileBufferManager));\n\n\tlogBlockEnd(\"tileBufferDestroy\");\n}\n\nvoid tileBufferReset(\n\ttTileBufferManager *pManager, UWORD uwTileX, UWORD uwTileY,\n\tUBYTE ubBitmapFlags, UBYTE isDblBuf, UWORD uwCoplistOffStart, UWORD uwCoplistOffBreak\n) {\n\tlogBlockBegin(\n\t\t\"tileBufferReset(pManager: %p, uwTileX: %hu, uwTileY: %hu, ubBitmapFlags: %hhu, isDblBuf: %hhu)\",\n\t\tpManager, uwTileX, uwTileY, ubBitmapFlags, isDblBuf\n\t);\n\n\t// Free old tile data\n\tif(pManager->pTileData) {\n\t\tfor(UWORD uwCol = pManager->uTileBounds.uwX; uwCol--;) {\n\t\t\tmemFree(pManager->pTileData[uwCol], pManager->uTileBounds.uwY * sizeof(pManager->pTileData[uwCol][0]));\n\t\t}\n\t\tmemFree(pManager->pTileData, pManager->uTileBounds.uwX * sizeof(pManager->pTileData[0]));\n\t\tpManager->pTileData = 0;\n\t}\n\n\t// Free old tile offset lookup table\n\tif(pManager->pTileSetOffsets) {\n\t\tmemFree(pManager->pTileSetOffsets, sizeof(pManager->pTileSetOffsets[0]) * pManager->ulMaxTilesetSize);\n\t}\n\n\t// Init new tile data\n\tpManager->uTileBounds.uwX = uwTileX;\n\tpManager->uTileBounds.uwY = uwTileY;\n\tif(uwTileX && uwTileY) {\n\t\tpManager->pTileData = memAllocFast(uwTileX * sizeof(pManager->pTileData[0]));\n\t\tfor(UWORD uwCol = uwTileX; uwCol--;) {\n\t\t\tpManager->pTileData[uwCol] = memAllocFastClear(uwTileY * sizeof(pManager->pTileData[uwCol][0]));\n\t\t}\n\t}\n\n\t// Init tile offset lookup table\n\tpManager->pTileSetOffsets = memAllocFast(sizeof(pManager->pTileSetOffsets[0]) * pManager->ulMaxTilesetSize);\n\tfor (ULONG i = 0; i < pManager->ulMaxTilesetSize; ++i) {\n\t\tpManager->pTileSetOffsets[i] = pManager->pTileSet->Planes[0] + (pManager->pTileSet->BytesPerRow * (i << pManager->ubTileShift));\n\t}\n\n\t// Reset scrollManager, create if not exists\n\tUBYTE ubTileShift = pManager->ubTileShift;\n\tpManager->pScroll = (tScrollBufferManager*)vPortGetManager(\n\t\tpManager->sCommon.pVPort, VPM_SCROLL\n\t);\n\tif(!(pManager->pScroll)) {\n\t\tpManager->pScroll = scrollBufferCreate(0,\n\t\t\tTAG_SCROLLBUFFER_VPORT, pManager->sCommon.pVPort,\n\t\t\tTAG_SCROLLBUFFER_MARGIN_WIDTH, pManager->ubTileSize,\n\t\t\tTAG_SCROLLBUFFER_BOUND_WIDTH, uwTileX << ubTileShift,\n\t\t\tTAG_SCROLLBUFFER_BOUND_HEIGHT, uwTileY << ubTileShift,\n\t\t\tTAG_SCROLLBUFFER_IS_DBLBUF, isDblBuf,\n\t\t\tTAG_SCROLLBUFFER_BITMAP_FLAGS, ubBitmapFlags,\n\t\t\tTAG_SCROLLBUFFER_COPLIST_OFFSET_START, uwCoplistOffStart,\n\t\t\tTAG_SCROLLBUFFER_COPLIST_OFFSET_BREAK, uwCoplistOffBreak,\n\t\tTAG_DONE);\n\t}\n\telse {\n\t\tscrollBufferReset(\n\t\t\tpManager->pScroll, pManager->ubTileSize,\n\t\t\tuwTileX << ubTileShift, uwTileY << ubTileShift, ubBitmapFlags, isDblBuf\n\t\t);\n\t}\n\n\t// Scrollin on one of dirs may be disabled - less redraw on other axis margin\n\tpManager->uwMarginedWidth = bitmapGetByteWidth(pManager->pScroll->pFront) * 8;\n\tpManager->uwMarginedHeight = pManager->pScroll->uwBmAvailHeight;\n\tpManager->ubMarginXLength = MIN(\n\t\tpManager->uTileBounds.uwY,\n\t\t(pManager->sCommon.pVPort->uwHeight >> ubTileShift) + 2 * (ACE_SCROLLBUFFER_Y_MARGIN_SIZE + SCROLLBUFFER_Y_DRAW_MARGIN_SIZE)\n\t);\n\tpManager->ubMarginYLength = MIN(\n\t\tpManager->uTileBounds.uwX,\n\t\t(pManager->sCommon.pVPort->uwWidth >> ubTileShift) + 2 * (ACE_SCROLLBUFFER_X_MARGIN_SIZE + SCROLLBUFFER_X_DRAW_MARGIN_SIZE)\n\t);\n\tlogWrite(\n\t\t\"Margin sizes: %hhu,%hhu\\n\",\n\t\tpManager->ubMarginXLength, pManager->ubMarginYLength\n\t);\n\n\t// Reset margin redraw structs - margin positions will be set correctly\n\t// by tileBufferRedrawAll()\n\ttileBufferResetRedrawState(&pManager->pRedrawStates[0], 0, 0, 0, 0);\n\ttileBufferResetRedrawState(&pManager->pRedrawStates[1], 0, 0, 0, 0);\n\n\tlogBlockEnd(\"tileBufferReset()\");\n}\n\n/**\n * Prepare quick drawing of tiles by setting up all blitter\n * registers that stay constant when blitting multiple tiles\n * quickly. To be followed by a loop of tileBufferContinueTileDraw\n * calls.\n *\n * @return bltsize - to use in tileBufferContinueTileDraw\n */\nstatic UWORD tileBufferSetupTileDraw(const tTileBufferManager *pManager) {\n\tWORD wDstModulo, wSrcModulo;\n\n\tUWORD uwBlitWords = pManager->ubTileSize / 16;\n\tUWORD uwBltCon0 = USEA|USED|MINTERM_A;\n\n\twSrcModulo = bitmapGetByteWidth(pManager->pTileSet) - uwBlitWords * sizeof(UWORD);\n\twDstModulo = bitmapGetByteWidth(pManager->pScroll->pBack) - uwBlitWords * sizeof(UWORD);\n\n\tUBYTE ubSrcInterleaved = bitmapIsInterleaved(pManager->pTileSet);\n\tUBYTE ubDstInterleaved = bitmapIsInterleaved(pManager->pScroll->pBack);\n\n\tUWORD uwHeight = pManager->ubTileSize;\n\n\tif(ubSrcInterleaved && ubDstInterleaved) {\n\t\tuwHeight *= pManager->pTileSet->Depth;\n\t}\n\telse {\n\t\t// XXX: misuse uwBlitWords to store the flag for non-interleaved\n\t\tuwBlitWords |= BLIT_WORDS_NON_INTERLEAVED_BIT;\n\t\tif (ubSrcInterleaved ^ ubDstInterleaved) {\n\t\t\t// Since you're using this fn for speed\n\t\t\tlogWrite(\"WARN: Mixed interleaved - you're losing lots of performance here!\\n\");\n\t\t}\n\t\tif(ubSrcInterleaved) {\n\t\t\twSrcModulo += pManager->pTileSet->BytesPerRow * (pManager->pTileSet->Depth-1);\n\t\t}\n\t\telse if(ubDstInterleaved) {\n\t\t\twDstModulo += pManager->pScroll->pBack->BytesPerRow * (pManager->pScroll->pBack->Depth-1);\n\t\t}\n\t}\n\n\tblitWait(); // Don't modify registers when other blit is in progress\n\tg_pCustom->bltcon0 = uwBltCon0;\n\tg_pCustom->bltcon1 = 0;\n\tg_pCustom->bltafwm = 0xFFFF;\n\tg_pCustom->bltalwm = 0xFFFF;\n\tg_pCustom->bltamod = wSrcModulo;\n\tg_pCustom->bltdmod = wDstModulo;\n\n\treturn (uwHeight << 6) | uwBlitWords;\n}\n\n/**\n * Quickly draw a tile. This is used after the blitter was set up\n * with a call to tileBufferSetupTileDraw, to draw multiple tiles\n * as quickly as possible. The fastest path by far is for interleaved\n * bitmaps, but it works for non-interleaved bitmaps, too, with\n * a slightly larger performance hit.\n */\nALWAYS_INLINE\nstatic inline void tileBufferContinueTileDraw(\n\tconst tTileBufferManager *pManager, const tTileBufferTileIndex *pTileDataColumn,\n\tUWORD uwTileY, UWORD uwBltsize, ULONG ulDstOffs, PLANEPTR pDstPlane, UBYTE isSetDst,\n\tUBYTE isWaitForBlit, UBYTE isInterleaved\n) {\n\ttTileBufferTileIndex TileToDraw = pTileDataColumn[uwTileY];\n\n\tif (isInterleaved) {\n\t\t// this function should be inlined into the caller, where\n\t\t// isInterleaved should be a *constant* argument, so\n\t\t// this check folds away\n\t\tUBYTE *pUbBltapt = pManager->pTileSetOffsets[TileToDraw];\n\t\tUBYTE *pUbBltdpt;\n\t\tif (isSetDst) {\n\t\t\t// this function should be inlined into the caller, where\n\t\t\t// isSetDst should be a *constant* argument, so this check\n\t\t\t// folds away\n\t\t\tpUbBltdpt = pDstPlane + ulDstOffs;\n\t\t}\n\t\tif (isWaitForBlit || !TILEBUFFER_REDRAW_HOG) {\n\t\t\t// this function should be inlined into the caller, where\n\t\t\t// ubBlitWait should be a constant argument, so this check\n\t\t\t// folds away\n\t\t\tblitWait(); // Don't modify registers when other blit is in progress\n\t\t}\n\t\tg_pCustom->bltapt = pUbBltapt;\n\t\tif (isSetDst) {\n\t\t\tg_pCustom->bltdpt = pUbBltdpt;\n\t\t}\n\t\tg_pCustom->bltsize = uwBltsize;\n\t}\n\telse {\n\t\tULONG ulSrcOffs = (ULONG)pManager->pTileSetOffsets[TileToDraw] - (ULONG)pManager->pTileSet->Planes[0];\n\t\tfor(UBYTE ubPlane = pManager->pTileSet->Depth; ubPlane--;) {\n\t\t\tUBYTE *pUbBltapt = pManager->pTileSet->Planes[ubPlane] + ulSrcOffs;\n\t\t\tUBYTE *pUbBltdpt = pManager->pScroll->pBack->Planes[ubPlane] + ulDstOffs;\n\t\t\tif (isWaitForBlit || !TILEBUFFER_REDRAW_HOG) {\n\t\t\t\t// this function should be inlined into the caller, where\n\t\t\t\t// ubBlitWait should be a constant argument, so this check\n\t\t\t\t// folds away\n\t\t\t\tblitWait(); // Don't modify registers when other blit is in progress\n\t\t\t}\n\t\t\tg_pCustom->bltapt = pUbBltapt;\n\t\t\tg_pCustom->bltdpt = pUbBltdpt;\n\t\t\tg_pCustom->bltsize = uwBltsize & ~BLIT_WORDS_NON_INTERLEAVED_BIT;\n\t\t}\n\t}\n}\n\nFN_HOTSPOT\nvoid tileBufferProcess(tTileBufferManager *pManager) {\n#if defined(ACE_SCROLLBUFFER_ENABLE_SCROLL_X) || defined(ACE_SCROLLBUFFER_ENABLE_SCROLL_Y)\n\ttRedrawState *pState = &pManager->pRedrawStates[pManager->ubStateIdx];\n\tUBYTE ubTileSize = pManager->ubTileSize;\n\tUBYTE ubTileShift = pManager->ubTileShift;\n#endif\n\n#if defined(ACE_SCROLLBUFFER_ENABLE_SCROLL_X)\n\t// X movement\n\tWORD wMarginXPos;\n\tWORD wDeltaX = cameraGetDeltaX(pManager->pCamera);\n\tif (wDeltaX) {\n\t\t// determine movement direction - right or left\n\t\tif (wDeltaX > 0) {\n\t\t\twMarginXPos = ((\n\t\t\t\tpManager->pCamera->uPos.uwX + pManager->sCommon.pVPort->uwWidth\n\t\t\t) >> ubTileShift) + ACE_SCROLLBUFFER_X_MARGIN_SIZE;\n\t\t\tpState->pMarginX = &pState->sMarginR;\n\t\t\tpState->pMarginOppositeX = &pState->sMarginL;\n\t\t}\n\t\telse {\n\t\t\twMarginXPos = (pManager->pCamera->uPos.uwX >> ubTileShift) - ACE_SCROLLBUFFER_X_MARGIN_SIZE;\n\t\t\tpState->pMarginX = &pState->sMarginL;\n\t\t\tpState->pMarginOppositeX = &pState->sMarginR;\n\t\t}\n\t\t// Not redrawing same column on movement side?\n\t\tif (wMarginXPos != pState->pMarginX->wTilePos) {\n\t\t\t// Not finished redrawing all column tiles?\n\t\t\tif(pState->pMarginX->wTileCurr < pState->pMarginX->wTileEnd) {\n\t\t\t\tUWORD uwTileOffsY = SCROLLBUFFER_HEIGHT_MODULO(\n\t\t\t\t\tpState->pMarginX->wTileCurr << ubTileShift, pManager->uwMarginedHeight\n\t\t\t\t);\n\t\t\t\tUWORD uwTileOffsX = (pState->pMarginX->wTilePos << ubTileShift);\n\t\t\t\t// Redraw remaining tiles\n\t\t\t\tUWORD uwBltsize = tileBufferSetupTileDraw(pManager);\n\t\t\t\tUBYTE isInterleaved = !(uwBltsize & BLIT_WORDS_NON_INTERLEAVED_BIT);\n\t\t\t\tUWORD uwTileCurr = pState->pMarginX->wTileCurr;\n\t\t\t\tUWORD uwTileEnd = pState->pMarginX->wTileEnd;\n\t\t\t\tUWORD uwMarginedHeight = pManager->uwMarginedHeight;\n\t\t\t\tUWORD uwTilePos = pState->pMarginX->wTilePos;\n\t\t\t\tconst tTileBufferTileIndex *pTileColumn = pManager->pTileData[uwTilePos];\n\t\t\t\tUWORD uwDstBytesPerRow = pManager->pScroll->pBack->BytesPerRow;\n\t\t\t\tPLANEPTR pDstPlane = pManager->pScroll->pBack->Planes[0];\n\t\t\t\tULONG ulDstOffs = uwDstBytesPerRow * uwTileOffsY + uwTileOffsX / 8;\n\t\t\t\tUWORD uwDstOffsStep = uwDstBytesPerRow * ubTileSize;\n\t\t\t\t// set up the first bltdpt for an interleaved blit. if this isn't\n\t\t\t\t// interleaved, this is wasted, but interleaved will be faster with\n\t\t\t\t// this. we can just do this here, since tileBufferSetupTileDraw\n\t\t\t\t// already waited for the blitter to be idle\n\t\t\t\tg_pCustom->bltdpt = pDstPlane + ulDstOffs;\n\t\t\t\twhile (uwTileCurr < uwTileEnd) {\n\t\t\t\t\ttileBufferContinueTileDraw(\n\t\t\t\t\t\tpManager, pTileColumn, uwTileCurr,\n\t\t\t\t\t\tuwBltsize, ulDstOffs, pDstPlane,\n\t\t\t\t\t\t// do not set bltdpt, it was left at the right place by the previous blit\n\t\t\t\t\t\t0, 1, isInterleaved\n\t\t\t\t\t);\n\t\t\t\t\t++uwTileCurr;\n\t\t\t\t\tuwTileOffsY += ubTileSize;\n\t\t\t\t\tif(uwTileOffsY >= uwMarginedHeight) {\n\t\t\t\t\t\tuwTileOffsY -= uwMarginedHeight;\n\t\t\t\t\t\tulDstOffs = uwDstBytesPerRow * uwTileOffsY + uwTileOffsX / 8;\n\t\t\t\t\t\tblitWait(); // this happens at most once in a column, so we take the hit\n\t\t\t\t\t\tg_pCustom->bltdpt = pDstPlane + ulDstOffs;\n\t\t\t\t\t}\n\t\t\t\t\telse {\n\t\t\t\t\t\tulDstOffs += uwDstOffsStep;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (pManager->cbTileDraw) {\n\t\t\t\t\tuwTileOffsY = SCROLLBUFFER_HEIGHT_MODULO(\n\t\t\t\t\t\tpState->pMarginX->wTileCurr << ubTileShift, pManager->uwMarginedHeight\n\t\t\t\t\t);\n\t\t\t\t\tuwTileCurr = pState->pMarginX->wTileCurr;\n\t\t\t\t\twhile (uwTileCurr < uwTileEnd) {\n\t\t\t\t\t\tpManager->cbTileDraw(uwTilePos, uwTileCurr, pManager->pScroll->pBack, uwTileOffsX, uwTileOffsY);\n\t\t\t\t\t\t++uwTileCurr;\n\t\t\t\t\t\tuwTileOffsY = SCROLLBUFFER_HEIGHT_MODULO(\n\t\t\t\t\t\t\tuwTileOffsY + ubTileSize, uwMarginedHeight\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tpState->pMarginX->wTileCurr = pState->pMarginX->wTileEnd;\n\t\t\t}\n\t\t\t// Prepare new column redraw data\n\t\t\tpState->pMarginX->wTilePos = wMarginXPos;\n\t\t\tif (wMarginXPos < 0 || wMarginXPos >= pManager->uTileBounds.uwX) {\n\t\t\t\t// Don't redraw if new column is out of map bounds\n\t\t\t\tpState->pMarginX->wTileCurr = 0;\n\t\t\t\tpState->pMarginX->wTileEnd = 0;\n\t\t\t}\n\t\t\telse {\n\t\t\t\t// Prepare new column for redraw\n\t\t\t\tpState->pMarginX->wTileCurr = MAX(\n\t\t\t\t\t0, (pManager->pCamera->uPos.uwY >> ubTileShift) - (ACE_SCROLLBUFFER_Y_MARGIN_SIZE + SCROLLBUFFER_Y_DRAW_MARGIN_SIZE)\n\t\t\t\t);\n\t\t\t\tpState->pMarginX->wTileEnd = MIN(\n\t\t\t\t\tpState->pMarginX->wTileCurr + pManager->ubMarginXLength,\n\t\t\t\t\tpManager->uTileBounds.uwY\n\t\t\t\t);\n\t\t\t}\n\t\t\t// Modify margin data on opposite side\n\t\t\tif(wDeltaX < 0) {\n\t\t\t\t--pState->pMarginOppositeX->wTilePos;\n\t\t\t}\n\t\t\telse {\n\t\t\t\t++pState->pMarginOppositeX->wTilePos;\n\t\t\t}\n\t\t\tpState->pMarginOppositeX->wTileCurr = 0;\n\t\t\tpState->pMarginOppositeX->wTileEnd = 0;\n\t\t}\n\t}\n\n\t// Redraw another X tile - regardless of movement in that direction\n\tif (pState->pMarginX->wTileCurr < pState->pMarginX->wTileEnd) {\n\t\ttileBufferDrawTile(\n\t\t\tpManager, pState->pMarginX->wTilePos, pState->pMarginX->wTileCurr\n\t\t);\n\t\t++pState->pMarginX->wTileCurr;\n\t}\n#endif // defined(ACE_SCROLLBUFFER_ENABLE_SCROLL_X)\n\n#if defined(ACE_SCROLLBUFFER_ENABLE_SCROLL_Y)\n\t// Y movement\n\tWORD wMarginYPos;\n\tWORD wDeltaY = cameraGetDeltaY(pManager->pCamera);\n\tif (wDeltaY) {\n\t\t// determine redraw row - down or up\n\t\tif (wDeltaY > 0) {\n\t\t\twMarginYPos = ((\n\t\t\t\tpManager->pCamera->uPos.uwY + pManager->sCommon.pVPort->uwHeight\n\t\t\t) >> ubTileShift) + ACE_SCROLLBUFFER_Y_MARGIN_SIZE;\n\t\t\tpState->pMarginY = &pState->sMarginD;\n\t\t\tpState->pMarginOppositeY = &pState->sMarginU;\n\t\t}\n\t\telse {\n\t\t\twMarginYPos = (pManager->pCamera->uPos.uwY >> ubTileShift) - ACE_SCROLLBUFFER_Y_MARGIN_SIZE;\n\t\t\tpState->pMarginY = &pState->sMarginU;\n\t\t\tpState->pMarginOppositeY = &pState->sMarginD;\n\t\t}\n\t\t// Not drawing same row?\n\t\tif (wMarginYPos != pState->pMarginY->wTilePos) {\n\t\t\t// Not finished redrawing all row tiles?\n\t\t\tif(pState->pMarginY->wTileCurr < pState->pMarginY->wTileEnd) {\n\t\t\t\tUWORD uwTileOffsY = SCROLLBUFFER_HEIGHT_MODULO(\n\t\t\t\t\tpState->pMarginY->wTilePos << ubTileShift, pManager->uwMarginedHeight\n\t\t\t\t);\n\t\t\t\tUWORD uwTileOffsX = (pState->pMarginY->wTileCurr << ubTileShift);\n\t\t\t\t// Redraw remaining tiles\n\t\t\t\tUWORD uwBltsize = tileBufferSetupTileDraw(pManager);\n\t\t\t\tUBYTE isInterleaved = !(uwBltsize & BLIT_WORDS_NON_INTERLEAVED_BIT);\n\t\t\t\tUWORD uwTileCurr = pState->pMarginY->wTileCurr;\n\t\t\t\tUWORD uwTileEnd = pState->pMarginY->wTileEnd;\n\t\t\t\tUWORD uwTilePos = pState->pMarginY->wTilePos;\n\t\t\t\ttTileBufferTileIndex **pTileData = pManager->pTileData;\n\t\t\t\tPLANEPTR pDstPlane = pManager->pScroll->pBack->Planes[0];\n\t\t\t\tULONG ulDstOffs = pManager->pScroll->pBack->BytesPerRow * uwTileOffsY + uwTileOffsX / 8;\n\t\t\t\tUWORD uwDstOffsStep = ubTileSize / 8;\n\t\t\t\twhile(uwTileCurr < uwTileEnd) {\n\t\t\t\t\ttileBufferContinueTileDraw(\n\t\t\t\t\t\tpManager, pTileData[uwTileCurr], uwTilePos,\n\t\t\t\t\t\tuwBltsize, ulDstOffs, pDstPlane, 1, 1,\n\t\t\t\t\t\tisInterleaved\n\t\t\t\t\t);\n\t\t\t\t\t++uwTileCurr;\n\t\t\t\t\tulDstOffs += uwDstOffsStep;\n\t\t\t\t}\n\t\t\t\tif (pManager->cbTileDraw) {\n\t\t\t\t\tuwTileCurr = pState->pMarginY->wTileCurr;\n\t\t\t\t\twhile (uwTileCurr < uwTileEnd) {\n\t\t\t\t\t\tpManager->cbTileDraw(uwTileCurr, uwTilePos, pManager->pScroll->pBack, uwTileOffsX, uwTileOffsY);\n\t\t\t\t\t\t++uwTileCurr;\n\t\t\t\t\t\tuwTileOffsX += ubTileSize;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tpState->pMarginY->wTileCurr = pState->pMarginY->wTileEnd;\n\t\t\t}\n\t\t\t// Prepare new row redraw data\n\t\t\tpState->pMarginY->wTilePos = wMarginYPos;\n\t\t\tif (wMarginYPos < 0 || wMarginYPos >= pManager->uTileBounds.uwY) {\n\t\t\t\t// Don't redraw if new row is out of map bounds\n\t\t\t\tpState->pMarginY->wTileCurr = 0;\n\t\t\t\tpState->pMarginY->wTileEnd = 0;\n\t\t\t}\n\t\t\telse {\n\t\t\t\t// Prepare new row for redraw\n\t\t\t\tpState->pMarginY->wTileCurr = MAX(\n\t\t\t\t\t0, (pManager->pCamera->uPos.uwX >> ubTileShift) - (ACE_SCROLLBUFFER_X_MARGIN_SIZE + SCROLLBUFFER_X_DRAW_MARGIN_SIZE)\n\t\t\t\t);\n\t\t\t\tpState->pMarginY->wTileEnd = MIN(\n\t\t\t\t\tpState->pMarginY->wTileCurr + pManager->ubMarginYLength,\n\t\t\t\t\tpManager->uTileBounds.uwX\n\t\t\t\t);\n\t\t\t}\n\t\t\t// Modify opposite margin data\n\t\t\tif(wDeltaY > 0) {\n\t\t\t\t++pState->pMarginOppositeY->wTilePos;\n\t\t\t}\n\t\t\telse {\n\t\t\t\t--pState->pMarginOppositeY->wTilePos;\n\t\t\t}\n\t\t\tpState->pMarginOppositeY->wTileCurr = 0;\n\t\t\tpState->pMarginOppositeY->wTileEnd = 0;\n\t\t}\n\t}\n\n\t// Redraw another Y tile - regardless of movement in that direction\n\tif (pState->pMarginY->wTileCurr < pState->pMarginY->wTileEnd) {\n\t\ttileBufferDrawTile(\n\t\t\tpManager, pState->pMarginY->wTileCurr, pState->pMarginY->wTilePos\n\t\t);\n\t\t++pState->pMarginY->wTileCurr;\n\t}\n#endif // defined(ACE_SCROLLBUFFER_ENABLE_SCROLL_Y)\n\n\tpManager->ubStateIdx = !pManager->ubStateIdx;\n}\n\n// This is used below with isInterleaved either 0 or 1, so with the inlining this is\n// a poor man's function template specialization...\nALWAYS_INLINE\nstatic inline void tileBufferRedrawAllInternal(tTileBufferManager *pManager, UBYTE isInterleaved) {\n\tUBYTE ubTileSize = pManager->ubTileSize;\n\tUBYTE ubTileShift = pManager->ubTileShift;\n\tUWORD uwMarginedHeight = pManager->uwMarginedHeight;\n\n\t// Calculate the range in tile coordinates\n\tUWORD uwStartX = MAX(0, (pManager->pCamera->uPos.uwX >> ubTileShift) - ACE_SCROLLBUFFER_X_MARGIN_SIZE);\n\tUWORD uwStartY = MAX(0, (pManager->pCamera->uPos.uwY >> ubTileShift) - ACE_SCROLLBUFFER_Y_MARGIN_SIZE);\n\t// One of bounds may be smaller than viewport + margin size\n\tUWORD uwEndX = MIN(\n\t\tpManager->uTileBounds.uwX,\n\t\tuwStartX + (pManager->uwMarginedWidth >> ubTileShift)\n\t);\n\tUWORD uwEndY = MIN(\n\t\tpManager->uTileBounds.uwY,\n\t\tuwStartY + (uwMarginedHeight >> ubTileShift)\n\t);\n\n\t// Reset margin redraw structs as we're redrawing everything anyway\n\ttileBufferResetRedrawState(\n\t\t&pManager->pRedrawStates[pManager->ubStateIdx], uwStartX, uwEndX, uwStartY, uwEndY\n\t);\n\n\t// Convert to pixel coordinates. uwBfrOffsX coord may overflow dimensions but that's\n\t// since we want to draw offset by N bitplanes for the corkscrew trick as we move right\n\tPLANEPTR pDstPlane = pManager->pScroll->pBack->Planes[0];\n\tUWORD uwDstBytesPerRow = pManager->pScroll->pBack->BytesPerRow;\n\tUWORD uwBfrOffsX = (uwStartX << ubTileShift);\n\tUWORD uwBfrOffsY = SCROLLBUFFER_HEIGHT_MODULO(uwStartY << ubTileShift, uwMarginedHeight);\n\n\t// Now we can calculate at which tile index we will jump from the bottom of the\n\t// viewport to the top\n\tUWORD uwWrapAroundY = (((uwStartY << ubTileShift) + uwMarginedHeight) - uwBfrOffsY) >> ubTileShift;\n\n\t// Now we can calculate the Y contribution to the total offset into the buffer bitmap\n\tULONG ulDstYOffset = uwDstBytesPerRow * uwBfrOffsY;\n\n\t// Draw\n\tUWORD uwBltsize = tileBufferSetupTileDraw(pManager);\n\ttTileBufferTileIndex **pTileData = pManager->pTileData;\n\tsystemSetDmaBit(DMAB_BLITHOG, 1);\n#if defined ACE_DEBUG\n\tif (systemBlitterIsReleasedToOs()) {\n\t\tlogWrite(\"ERR: you called tileBufferRedrawAll but the blitter is not owned!\");\n\t}\n#endif\n\tsystemDisableCpuCaches();\n\tfor (UWORD uwTileX = uwStartX; uwTileX < uwEndX; ++uwTileX) {\n\t\tUWORD uwDstXOffset = uwTileX << ubTileShift >> 3;\n\t\ttTileBufferTileIndex *pTileDataColumn = pTileData[uwTileX];\n\t\tULONG ulDstOffs = ulDstYOffset + uwDstXOffset;\n\t\tif (isInterleaved) {\n\t\t\tif (!TILEBUFFER_REDRAW_HOG) {\n\t\t\t\tblitWait();\n\t\t\t}\n\t\t\tg_pCustom->bltdpt = pDstPlane + ulDstOffs;\n\t\t}\n\t\tUWORD uwTileY = uwStartY;\n\t\tfor (; uwTileY < uwWrapAroundY; ++uwTileY) {\n\t\t\ttileBufferContinueTileDraw(\n\t\t\t\tpManager, pTileDataColumn, uwTileY,\n\t\t\t\tuwBltsize, ulDstOffs, pDstPlane,\n\t\t\t\t0, 0, isInterleaved\n\t\t\t);\n\t\t\tif (!isInterleaved) {\n\t\t\t\tulDstOffs += (uwDstBytesPerRow << ubTileShift);\n\t\t\t}\n\t\t}\n\t\tulDstOffs = uwDstXOffset;\n\t\tif (isInterleaved) {\n\t\t\tif (!TILEBUFFER_REDRAW_HOG) {\n\t\t\t\tblitWait();\n\t\t\t}\n\t\t\tg_pCustom->bltdpt = pDstPlane + ulDstOffs;\n\t\t}\n\t\tfor (; uwTileY < uwEndY; ++uwTileY) {\n\t\t\ttileBufferContinueTileDraw(\n\t\t\t\tpManager, pTileDataColumn, uwTileY,\n\t\t\t\tuwBltsize, ulDstOffs, pDstPlane,\n\t\t\t\t0, 0, isInterleaved\n\t\t\t);\n\t\t\tif (!isInterleaved) {\n\t\t\t\tulDstOffs += (uwDstBytesPerRow << ubTileShift);\n\t\t\t}\n\t\t}\n\t}\n\tsystemRestoreCpuCaches();\n\tsystemSetDmaBit(DMAB_BLITHOG, 0);\n\n\tif (pManager->cbTileDraw) {\n\t\tfor (UWORD uwTileY = uwStartY; uwTileY < uwEndY; ++uwTileY) {\n\t\t\tuwBfrOffsX = (uwStartX << ubTileShift);\n\t\t\tUWORD uwTileCurr = uwStartX;\n\t\t\twhile (uwTileCurr < uwEndX) {\n\t\t\t\tpManager->cbTileDraw(\n\t\t\t\t\tuwTileCurr, uwTileY, pManager->pScroll->pBack,\n\t\t\t\t\tuwBfrOffsX, uwBfrOffsY\n\t\t\t\t);\n\t\t\t\t++uwTileCurr;\n\t\t\t\tuwBfrOffsX += ubTileSize;\n\t\t\t}\n\t\t\tuwBfrOffsY = SCROLLBUFFER_HEIGHT_MODULO(\n\t\t\t\tuwBfrOffsY + ubTileSize, pManager->uwMarginedHeight\n\t\t\t);\n\t\t}\n\t}\n}\n\nvoid tileBufferRedrawAll(tTileBufferManager *pManager) {\n\tlogBlockBegin(\"tileBufferRedrawAll(pManager: %p)\", pManager);\n\n\ttileBufferRedrawBack(pManager);\n\n\t// Reset margin redraw structs for front buffer, too\n\tWORD wStartX = 0, wStartY = 0;\n\tUWORD uwEndX = 0, uwEndY = 0;\n#if defined(ACE_SCROLLBUFFER_ENABLE_SCROLL_X)\n\twStartX = pManager->pRedrawStates[pManager->ubStateIdx].sMarginL.wTilePos;\n\tuwEndX = pManager->pRedrawStates[pManager->ubStateIdx].sMarginR.wTilePos;\n#endif\n#if defined(ACE_SCROLLBUFFER_ENABLE_SCROLL_Y)\n\twStartY = pManager->pRedrawStates[pManager->ubStateIdx].sMarginU.wTilePos;\n\tuwEndY = pManager->pRedrawStates[pManager->ubStateIdx].sMarginD.wTilePos;\n#endif\n\ttileBufferResetRedrawState(\n\t\t&pManager->pRedrawStates[!pManager->ubStateIdx], wStartX, uwEndX, wStartY, uwEndY\n\t);\n\n\t// Copy from back buffer to front buffer.\n\t// Width is always a multiple of 16, so use WORD copy.\n\t// TODO: this could be done using blitter.\n\tUWORD *pSrc = (UWORD*)pManager->pScroll->pBack->Planes[0];\n\tUWORD *pDst = (UWORD*)pManager->pScroll->pFront->Planes[0];\n\tULONG ulWordsToCopy = (\n\t\tpManager->pScroll->pFront->BytesPerRow * pManager->pScroll->pFront->Rows\n\t) / sizeof(UWORD);\n\twhile(ulWordsToCopy--) {\n\t\t*(pDst++) = *(pSrc++);\n\t}\n\n\t// Refresh bitplane pointers in scrollBuffer's copprtlist - 2x for dbl bfr\n\tscrollBufferProcess(pManager->pScroll);\n\tscrollBufferProcess(pManager->pScroll);\n\n\tlogBlockEnd(\"tileBufferRedrawAll()\");\n}\n\n/*\n * We forcibly place this function in chipmem and we disable any CPU caches\n * when we are executing tileBufferRedrawAllInternal, so the CPU is actually\n * blocked by the blitter and we can save the extra instructions for waiting.\n */\n#if !defined(ACE_DEBUG) && defined(BARTMAN_GCC)\nCHIP_CODE // stepping into chipmem annotated functions is a bit wonky on bartman's vscode plugin\n#endif\nvoid tileBufferRedrawBack(tTileBufferManager *pManager) {\n\tUBYTE ubSrcInterleaved = bitmapIsInterleaved(pManager->pTileSet);\n\tUBYTE ubDstInterleaved = bitmapIsInterleaved(pManager->pScroll->pBack);\n\t// This duplicates a bit of code, but when I introduced this gcc de-\n\t// duplicated the shared code before the branch on isInterleaved comes\n\t// and so the only dupicated part is the common code to run the cbTileDraw\n\t// callback, which in my compilation was 142 bytes, and the code to call\n\t// the scrollBufferProcess twice, which was 30 bytes for me. Even if this\n\t// a bit worse sometime with other GCC versions, I think it's not worth\n\t// adding another #define to save ~170 bytes of duplicated code. If\n\t// we ever decide to completely omit interleaved or non-interleaved support\n\t// in some project, that'll be a bigger refactoring anyway.\n\tif (LIKELY(ubSrcInterleaved && ubDstInterleaved)) {\n\t\ttileBufferRedrawAllInternal(pManager, 1);\n\t} else {\n\t\ttileBufferRedrawAllInternal(pManager, 0);\n\t}\n}\n\nvoid tileBufferDrawTile(\n\tconst tTileBufferManager *pManager, UWORD uwTileIdxX, UWORD uwTileIdxY\n) {\n\t// Buffer X coord will overflow dimensions but that's fine 'cuz we need to\n\t// draw on bitplane 1 as if it is part of bitplane 0.\n\tUWORD uwBfrY = SCROLLBUFFER_HEIGHT_MODULO(\n\t\tuwTileIdxY << pManager->ubTileShift, pManager->uwMarginedHeight\n\t);\n\tUWORD uwBfrX = (uwTileIdxX << pManager->ubTileShift);\n\n\ttileBufferDrawTileQuick(pManager, uwTileIdxX, uwTileIdxY, uwBfrX, uwBfrY);\n}\n\nvoid tileBufferDrawTileQuick(\n\tconst tTileBufferManager *pManager, UWORD uwTileX, UWORD uwTileY,\n\tUWORD uwBfrX, UWORD uwBfrY\n) {\n\ttTileBufferTileIndex TileToDraw = pManager->pTileData[uwTileX][uwTileY];\n\tUBYTE ubTileShift = pManager->ubTileShift;\n\t// This can't use safe blit fn because when scrolling in X direction,\n\t// we need to draw on bitplane 1 as if it is part of bitplane 0.\n\tblitUnsafeCopyAligned(\n\t\tpManager->pTileSet,\n\t\t0, TileToDraw << ubTileShift,\n\t\tpManager->pScroll->pBack, uwBfrX, uwBfrY,\n\t\tpManager->ubTileSize, pManager->ubTileSize\n\t);\n\tif(pManager->cbTileDraw) {\n\t\tpManager->cbTileDraw(\n\t\t\tuwTileX, uwTileY, pManager->pScroll->pBack, uwBfrX, uwBfrY\n\t\t);\n\t}\n}\n\nvoid tileBufferInvalidateRect(\n\ttTileBufferManager *pManager, UWORD uwX, UWORD uwY,\n\tUWORD uwWidth, UWORD uwHeight\n) {\n\t// Tile x/y ranges in given coord\n\tUWORD uwStartX = uwX >> pManager->ubTileShift;\n\tUWORD uwEndX = (uwX+uwWidth) >> pManager->ubTileShift;\n\tUWORD uwStartY = uwY >> pManager->ubTileShift;\n\tUWORD uwEndY = (uwY+uwHeight) >> pManager->ubTileShift;\n\n\tfor(uwX = uwStartX; uwX <= uwEndX; ++uwX) {\n\t\tfor(uwY = uwStartY; uwY <= uwEndY; ++uwY) {\n\t\t\ttileBufferInvalidateTile(pManager, uwX, uwY);\n\t\t}\n\t}\n}\n\nvoid tileBufferInvalidateTile(\n\ttTileBufferManager *pManager, UWORD uwTileX, UWORD uwTileY\n) {\n\t// FIXME it ain't working right yet\n\t// if(!tileBufferIsTileOnBuffer(pManager, uwTileX, uwTileY)) {\n\t// \treturn;\n\t// }\n\n\t// Previous state will have one more tile to draw, so only check smaller range\n\t// omit if not yet drawn on redraw margin - let manager draw it when it\n\t// will be that tile's turn\n\t// const tRedrawState *pState = &pManager->pRedrawStates[pManager->ubStateIdx];\n\t// if(\n\t// \tpState->pMarginX->wTilePos == uwTileX &&\n\t// \tpState->pMarginX->wTileCurr <= uwTileY &&\n\t// \tuwTileY <= pState->pMarginX->wTileEnd\n\t// ) {\n\t// \treturn;\n\t// }\n\t// if(\n\t// \tpState->pMarginY->wTilePos == uwTileY &&\n\t// \tpState->pMarginY->wTileCurr <= uwTileX &&\n\t// \tuwTileX <= pState->pMarginY->wTileEnd\n\t// ) {\n\t// \treturn;\n\t// }\n\n\t// Add to queue\n\ttileBufferQueueAdd(pManager, uwTileX, uwTileY);\n}\n\nUBYTE tileBufferIsTileOnBuffer(\n\tconst tTileBufferManager *pManager, UWORD uwTileX, UWORD uwTileY\n) {\n\tUBYTE ubTileShift = pManager->ubTileShift;\n\tUWORD uwStartX = MAX(0, pManager->pCamera->uPos.uwX - 1) >> ubTileShift;\n\tUWORD uwEndX = (pManager->pCamera->uPos.uwX + pManager->sCommon.pVPort->uwWidth) >> ubTileShift;\n\tUWORD uwStartY = MAX(0, pManager->pCamera->uPos.uwY - 1) >> ubTileShift;\n\tUWORD uwEndY = (pManager->pCamera->uPos.uwY + pManager->sCommon.pVPort->uwHeight) >> ubTileShift;\n\n\tUBYTE isOnBuffer = (\n\t\tuwStartX <= uwTileX && uwTileX <= uwEndX &&\n\t\tuwStartY <= uwTileY && uwTileY <= uwEndY\n\t);\n\treturn isOnBuffer;\n}\n\nUBYTE tileBufferIsRectFullyOnBuffer(\n\tconst tTileBufferManager *pManager, UWORD uwX, UWORD uwY, UWORD uwWidth, UWORD uwHeight\n) {\n\tUBYTE ubTileShift = pManager->ubTileShift;\n\tUWORD uwStartX = MAX(0, pManager->pCamera->uPos.uwX - 1) >> ubTileShift;\n\tUWORD uwEndX = (pManager->pCamera->uPos.uwX + pManager->sCommon.pVPort->uwWidth) >> ubTileShift;\n\tUWORD uwStartY = MAX(0, pManager->pCamera->uPos.uwY - 1) >> ubTileShift;\n\tUWORD uwEndY = (pManager->pCamera->uPos.uwY + pManager->sCommon.pVPort->uwHeight) >> ubTileShift;\n\n\tUWORD uwX1 = uwX >> ubTileShift;\n\tUWORD uwY1 = uwY >> ubTileShift;\n\tUWORD uwX2 = (uwX + uwWidth) >> ubTileShift;\n\tUWORD uwY2 = (uwY + uwHeight) >> ubTileShift;\n\tUBYTE isOnBuffer = (\n\t\tuwStartX <= uwX1 && uwX2 <= uwEndX &&\n\t\tuwStartY <= uwY1 && uwY2 <= uwEndY\n\t);\n\treturn isOnBuffer;\n}\n\nvoid tileBufferSetTile(\n\ttTileBufferManager *pManager, UWORD uwX, UWORD uwY, tTileBufferTileIndex Index\n) {\n \tpManager->pTileData[uwX][uwY] = Index;\n\ttileBufferInvalidateTile(pManager, uwX, uwY);\n}\n"
  },
  {
    "path": "src/ace/utils/bitmap.c",
    "content": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at http://mozilla.org/MPL/2.0/. */\n\n#include <ace/utils/bitmap.h>\n#include <ace/managers/blit.h>\n#include <ace/managers/log.h>\n#include <ace/managers/memory.h>\n#include <ace/managers/system.h>\n#include <ace/utils/endian.h>\n#include <ace/utils/chunky.h>\n#include <ace/utils/custom.h>\n#include <ace/utils/disk_file.h>\n\n#if defined(ACE_USE_AGA_FEATURES) && defined(ACE_DEBUG)\nstatic PLANEPTR bitmapAllocChipAligned(ULONG ulSize) {\n\t// In ACE_DEBUG, memAllocChip user pointer is shifted by one ULONG due to\n\t// debug guards; shift once more so CHIP bitplane data keeps expected\n\t// alignment for AGA FMODE 3 fetch.\n\tUBYTE *pMem = (UBYTE *)memAllocChip(ulSize + sizeof(ULONG));\n\tif(!pMem) {\n\t\treturn 0;\n\t}\n\treturn (PLANEPTR)(pMem + sizeof(ULONG));\n}\n\nstatic void bitmapFreeChipAligned(void *pMem, ULONG ulSize) {\n\tmemFree((UBYTE *)pMem - sizeof(ULONG), ulSize + sizeof(ULONG));\n}\n#else\nstatic PLANEPTR bitmapAllocChipAligned(ULONG ulSize) {\n\treturn (PLANEPTR)memAllocChip(ulSize);\n}\n\nstatic void bitmapFreeChipAligned(void *pMem, ULONG ulSize) {\n\tmemFree(pMem, ulSize);\n}\n#endif\n\n/* Globals */\n\n/* Functions */\n\ntBitMap *bitmapCreate(\n\tUWORD uwWidth, UWORD uwHeight, UBYTE ubDepth, UBYTE ubFlags\n) {\n#ifdef AMIGA\n\ttBitMap *pBitMap;\n\tUBYTE i;\n\n\tsystemUse();\n\tlogBlockBegin(\n\t\t\"bitmapCreate(uwWidth: %hu, uwHeight: %hu, ubDepth: %hhu, ubFlags: %hhu)\",\n\t\tuwWidth, uwHeight, ubDepth, ubFlags\n\t);\n\n\tif(uwWidth == 0 || uwHeight == 0) {\n\t\tlogWrite(\"ERR: invalid bitmap dimensions\\n\");\n\t\tsystemUnuse();\n\t\treturn 0;\n\t}\n\n\tif((uwWidth & 0xF) != 0) {\n\t\t// Needed for blitter!\n\t\tlogWrite(\"ERR: bitmap width is not multiple of 16\\n\");\n\t\tsystemUnuse();\n\t\treturn 0;\n\t}\n\n\tpBitMap = (tBitMap*) memAllocFastClear(sizeof(tBitMap));\n\tlogWrite(\"addr: %p\\n\", pBitMap);\n\n\tpBitMap->BytesPerRow = uwWidth / 8;\n\tpBitMap->Rows = uwHeight;\n\tpBitMap->Flags = 0;\n\tpBitMap->Depth = ubDepth;\n\n\tif(ubFlags & BMF_INTERLEAVED) {\n\t\tpBitMap->Flags |= BMF_INTERLEAVED;\n\t\tUWORD uwRealWidth;\n\t\tuwRealWidth = pBitMap->BytesPerRow;\n\t\tpBitMap->BytesPerRow *= ubDepth;\n\n\t\tif(ubFlags & BMF_FASTMEM) {\n\t\t\tpBitMap->Planes[0] = (PLANEPTR) memAlloc(\n\t\t\t\tpBitMap->BytesPerRow * uwHeight,\n\t\t\t\tMEMF_ANY\n\t\t\t);\n\t\t}\n\t\telse {\n\t\t\tpBitMap->Planes[0] = bitmapAllocChipAligned(\n\t\t\t\tpBitMap->BytesPerRow * uwHeight\n\t\t\t);\n\t\t}\n\t\tif(!pBitMap->Planes[0]) {\n\t\t\tlogWrite(\"ERR: Can't alloc interleaved bitplanes\\n\");\n\t\t\tgoto fail;\n\t\t}\n\t\tfor(i = 1; i != ubDepth; ++i) {\n\t\t\tpBitMap->Planes[i] = pBitMap->Planes[i-1] + uwRealWidth;\n\t\t}\n\n\t\tif (ubFlags & BMF_CLEAR) {\n\t\t\tmemset(pBitMap->Planes[0], 0, pBitMap->Rows * pBitMap->BytesPerRow);\n\t\t}\n\t}\n\telse if(ubFlags & BMF_CONTIGUOUS) {\n\t\tpBitMap->Flags |= BMF_CONTIGUOUS;\n\t\tULONG ulPlaneSize = pBitMap->BytesPerRow * uwHeight;\n\t\tpBitMap->Planes[0] = bitmapAllocChipAligned(ulPlaneSize * ubDepth);\n\t\tif(!pBitMap->Planes[0]) {\n\t\t\t\tlogWrite(\"ERR: Can't alloc contiguous bitplanes\\n\");\n\t\t\t\tgoto fail;\n\t\t}\n\t\tfor(i = 1; i < ubDepth; ++i) {\n\t\t\t\tpBitMap->Planes[i] = &pBitMap->Planes[i - 1][ulPlaneSize];\n\t\t}\n\t\tif (ubFlags & BMF_CLEAR) {\n\t\t\t\tmemset(pBitMap->Planes[0], 0, ulPlaneSize * ubDepth);\n\t\t}\n\t}\n\telse {\n\t\tfor(i = ubDepth; i--;) {\n\t\t\tpBitMap->Planes[i] = bitmapAllocChipAligned(\n\t\t\t\tpBitMap->BytesPerRow * uwHeight\n\t\t\t);\n\t\t\tif(!pBitMap->Planes[i]) {\n\t\t\t\tlogWrite(\"ERR: Can't alloc bitplane %hu/%hu\\n\", ubDepth - i + 1,ubDepth);\n\t\t\t\twhile(++i != ubDepth) {\n\t\t\t\t\tbitmapFreeChipAligned(\n\t\t\t\t\t\tpBitMap->Planes[i],\n\t\t\t\t\t\tpBitMap->BytesPerRow * uwHeight\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tgoto fail;\n\t\t\t}\n\t\t\tif (ubFlags & BMF_CLEAR) {\n\t\t\t\tmemset(pBitMap->Planes[i], 0, pBitMap->Rows * pBitMap->BytesPerRow);\n\t\t\t}\n\t\t}\n\t}\n\n\tlogBlockEnd(\"bitmapCreate()\");\n\tsystemUnuse();\n\treturn pBitMap;\n\nfail:\n\tif(pBitMap) {\n\t\tmemFree(pBitMap, sizeof(tBitMap));\n\t}\n\tlogBlockEnd(\"bitmapCreate()\");\n\tsystemUnuse();\n\treturn 0;\n\n#else\n\treturn 0;\n#endif // AMIGA\n}\n\nvoid bitmapLoadFromPath(tBitMap *pBitMap, const char *szPath, UWORD uwStartX, UWORD uwStartY) {\n\treturn bitmapLoadFromFd(pBitMap, diskFileOpen(szPath, DISK_FILE_MODE_READ, 1), uwStartX, uwStartY);\n}\n\nvoid bitmapLoadFromFd(\n\t\ttBitMap *pBitMap, tFile *pFile, UWORD uwStartX, UWORD uwStartY)\n{\n\tUWORD uwSrcWidth, uwDstWidth, uwSrcHeight;\n\tUBYTE ubSrcFlags, ubSrcBpp, ubSrcVersion;\n\tUWORD y;\n\tUWORD uwWidth;\n\tUBYTE ubPlane;\n\n\tsystemUse();\n\tlogBlockBegin(\n\t\t\"bitmapLoadFromFd(pBitMap: %p, pFile: %p, uwStartX: %u, uwStartY: %u)\",\n\t\tpBitMap, pFile, uwStartX, uwStartY\n\t);\n\n\tif(!pBitMap) {\n\t\tlogWrite(\"ERR: pBitMap is 0\\n\");\n\t\tsystemUnuse();\n\t\treturn;\n\t}\n\n\t// Open source bitmap\n\tif(!pFile) {\n\t\tlogWrite(\"ERR: Null file handle\\n\");\n\t\tlogBlockEnd(\"bitmapLoadFromFd()\");\n\t\tsystemUnuse();\n\t\treturn;\n\t}\n\n\t// Read header\n\tfileRead(pFile, &uwSrcWidth, sizeof(UWORD));\n\tfileRead(pFile, &uwSrcHeight, sizeof(UWORD));\n\tfileRead(pFile, &ubSrcBpp, sizeof(UBYTE));\n\tfileRead(pFile, &ubSrcVersion, sizeof(UBYTE));\n\tfileRead(pFile, &ubSrcFlags, sizeof(UBYTE));\n\tfileSeek(pFile, 2 * sizeof(UBYTE), FILE_SEEK_CURRENT); // Skip unused 2 bytes\n\tif(ubSrcVersion != 0) {\n\t\tfileClose(pFile);\n\t\tlogWrite(\"ERR: Unknown file version: %hu\\n\", ubSrcVersion);\n\t\tlogBlockEnd(\"bitmapLoadFromFd()\");\n\t\tsystemUnuse();\n\t\treturn;\n\t}\n\tlogWrite(\"Source dimensions: %ux%u\\n\", uwSrcWidth, uwSrcHeight);\n\n\t// Interleaved check\n\tif(!!(ubSrcFlags & BITMAP_INTERLEAVED) != bitmapIsInterleaved(pBitMap)) {\n\t\tlogWrite(\n\t\t\t\"ERR: Interleaved flag conflict (file: %d, bm: %hhu)\\n\",\n\t\t\t!!(ubSrcFlags & BITMAP_INTERLEAVED), bitmapIsInterleaved(pBitMap)\n\t\t);\n\t\tfileClose(pFile);\n\t\tlogBlockEnd(\"bitmapLoadFromFd()\");\n\t\tsystemUnuse();\n\t\treturn;\n\t}\n\n\t// Depth check\n\tif(ubSrcBpp > pBitMap->Depth) {\n\t\tlogWrite(\n\t\t\t\"ERR: Source has greater BPP than destination: %hu > %hu\\n\",\n\t\t\tubSrcBpp, pBitMap->Depth\n\t\t);\n\t\tfileClose(pFile);\n\t\tlogBlockEnd(\"bitmapLoadFromFd()\");\n\t\tsystemUnuse();\n\t\treturn;\n\t}\n\n\t// Check bitmap dimensions\n\tuwDstWidth = bitmapGetByteWidth(pBitMap) << 3;\n\tif(uwStartX + uwSrcWidth > uwDstWidth || uwStartY + uwSrcHeight > (pBitMap->Rows)) {\n\t\tlogWrite(\n\t\t\t\"ERR: Source doesn't fit on dest: %ux%u @%u,%u > %ux%u\\n\",\n\t\t\tuwSrcWidth, uwSrcHeight,\n\t\t\tuwStartX, uwStartY,\n\t\t\tuwDstWidth, pBitMap->Rows\n\t\t);\n\t\tfileClose(pFile);\n\t\tlogBlockEnd(\"bitmapLoadFromFd()\");\n\t\tsystemUnuse();\n\t\treturn;\n\t}\n\n\t// Read data\n\tuwWidth = bitmapGetByteWidth(pBitMap);\n\tUWORD uwReadBytesPerRow = (uwSrcWidth + 7) / 8;\n\tif(bitmapIsInterleaved(pBitMap)) {\n\t\tUWORD uwDestOffs = uwWidth * (uwStartY * pBitMap->Depth) + (uwStartX / 8);\n\t\tif(uwStartX == 0 && uwSrcWidth == uwDstWidth) {\n\t\t\tfileRead(\n\t\t\t\tpFile,\n\t\t\t\t&pBitMap->Planes[0][uwDestOffs],\n\t\t\t\tpBitMap->BytesPerRow * uwSrcHeight\n\t\t\t);\n\t\t}\n\t\telse {\n\t\t\tfor(y = 0; y < uwSrcHeight; ++y) {\n\t\t\t\tfor(ubPlane = 0; ubPlane != pBitMap->Depth; ++ubPlane) {\n\t\t\t\t\tfileRead(\n\t\t\t\t\t\tpFile,\n\t\t\t\t\t\t&pBitMap->Planes[0][uwDestOffs],\n\t\t\t\t\t\tuwReadBytesPerRow\n\t\t\t\t\t);\n\t\t\t\t\tuwDestOffs += uwWidth;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\telse {\n\t\tfor(ubPlane = 0; ubPlane != pBitMap->Depth; ++ubPlane) {\n\t\t\tfor(y = 0; y != uwSrcHeight; ++y) {\n\t\t\t\tUWORD uwDestOffs = uwWidth * uwStartY + (uwStartX / 8);\n\t\t\t\tfileRead(\n\t\t\t\t\tpFile,\n\t\t\t\t\t&pBitMap->Planes[ubPlane][uwDestOffs],\n\t\t\t\t\tuwReadBytesPerRow\n\t\t\t\t);\n\t\t\t\tuwDestOffs += uwWidth;\n\t\t\t}\n\t\t}\n\t}\n\tfileClose(pFile);\n\tlogBlockEnd(\"bitmapLoadFromFd()\");\n\tsystemUnuse();\n}\n\ntBitMap *bitmapCreateFromPath(const char *szPath, UBYTE isFast) {\n\treturn bitmapCreateFromFd(diskFileOpen(szPath, DISK_FILE_MODE_READ, 1), isFast);\n}\n\ntBitMap *bitmapCreateFromFd(tFile *pFile, UBYTE isFast) {\n\ttBitMap *pBitMap;\n\tUWORD uwWidth, uwHeight;  // Image dimensions\n\tUBYTE ubVersion, ubFlags; // Format version & flags\n\tUBYTE ubPlaneCount;       // Bitplane count\n\tUBYTE i;\n\n\tsystemUse();\n\tlogBlockBegin(\"bitmapCreateFromFd(pFile: %p)\", pFile);\n\tif(!pFile) {\n\t\tlogWrite(\"ERR: Null file handle\\n\");\n\t\tlogBlockEnd(\"bitmapCreateFromFd()\");\n\t\tsystemUnuse();\n\t\treturn 0;\n\t}\n\n\t// Read header\n\tfileRead(pFile, &uwWidth, sizeof(UWORD));\n\tfileRead(pFile, &uwHeight, sizeof(UWORD));\n\tfileRead(pFile, &ubPlaneCount, sizeof(UBYTE));\n\tfileRead(pFile, &ubVersion, sizeof(UBYTE));\n\tfileRead(pFile, &ubFlags, sizeof(UBYTE));\n\tfileSeek(pFile, 2 * sizeof(UBYTE), SEEK_CUR); // Skip unused 2 bytes\n\tif(ubVersion != 0) {\n\t\tlogWrite(\"ERR: Unknown file version: %hu\\n\", ubVersion);\n\t\tfileClose(pFile);\n\t\tlogBlockEnd(\"bitmapCreateFromFd()\");\n\t\tsystemUnuse();\n\t\treturn 0;\n\t}\n\n\t// Init bitmap\n\tUBYTE ubBitmapFlags = 0;\n\tif(isFast) {\n\t\tubBitmapFlags |= BMF_FASTMEM;\n\t}\n\tif(ubFlags & BITMAP_INTERLEAVED) {\n\t\tpBitMap = bitmapCreate(\n\t\t\tuwWidth, uwHeight, ubPlaneCount, ubBitmapFlags | BMF_INTERLEAVED\n\t\t);\n\t\tfileRead(pFile, pBitMap->Planes[0], (uwWidth >> 3) * uwHeight * ubPlaneCount);\n\t}\n\telse {\n\t\tpBitMap = bitmapCreate(uwWidth, uwHeight, ubPlaneCount, ubBitmapFlags);\n\t\tfor (i = 0; i != ubPlaneCount; ++i) {\n\t\t\tfileRead(pFile, pBitMap->Planes[i], (uwWidth >> 3) * uwHeight);\n\t\t}\n\t}\n\tfileClose(pFile);\n\n\tlogWrite(\n\t\t\"Dimensions: %ux%u@%uBPP, version: %hu, flags: %hu\\n\",\n\t\tuwWidth, uwHeight, ubPlaneCount, ubVersion, ubFlags\n\t);\n\tlogBlockEnd(\"bitmapCreateFromFd()\");\n\tsystemUnuse();\n\treturn pBitMap;\n}\n\nvoid bitmapDestroy(tBitMap *pBitMap) {\n\tlogBlockBegin(\"bitmapDestroy(pBitMap: %p)\", pBitMap);\n\tif(pBitMap) {\n#ifdef AMIGA\n\t\tblitWait();\n#endif\n\t\tsystemUse();\n\t\tif(bitmapIsInterleaved(pBitMap)) {\n\t\t\tif(bitmapIsChip(pBitMap)) {\n\t\t\t\tbitmapFreeChipAligned(\n\t\t\t\t\tpBitMap->Planes[0],\n\t\t\t\t\tpBitMap->BytesPerRow * pBitMap->Rows\n\t\t\t\t);\n\t\t\t}\n\t\t\telse {\n\t\t\t\tmemFree(\n\t\t\t\t\tpBitMap->Planes[0],\n\t\t\t\t\tpBitMap->BytesPerRow * pBitMap->Rows\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t\telse if(pBitMap->Flags & BMF_CONTIGUOUS) {\n\t\t\tbitmapFreeChipAligned(\n\t\t\t\tpBitMap->Planes[0],\n\t\t\t\tpBitMap->BytesPerRow * pBitMap->Rows * pBitMap->Depth\n\t\t\t);\n\t\t}\n\t\telse {\n\t\t\tfor(UBYTE i = pBitMap->Depth; i--;) {\n\t\t\t\tbitmapFreeChipAligned(\n\t\t\t\t\tpBitMap->Planes[i],\n\t\t\t\t\tpBitMap->BytesPerRow * pBitMap->Rows\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t\tmemFree(pBitMap, sizeof(tBitMap));\n\t\tsystemUnuse();\n\t}\n\tlogBlockEnd(\"bitmapDestroy()\");\n}\n\nUBYTE bitmapIsInterleaved(const tBitMap *pBitMap) {\n\t// The check for depth is because of how bitmapGetByteWidth() works\n\t// if byte width were to be stored in bitmap struct, the depth check can be skipped.\n\treturn (pBitMap->Depth > 1) && (pBitMap->Flags & BMF_INTERLEAVED);\n}\n\nUBYTE bitmapIsChip(const tBitMap *pBitMap) {\n\treturn memType(pBitMap->Planes[0]) == MEMF_CHIP;\n}\n\nvoid bitmapDump(const tBitMap *pBitMap) {\n\tUBYTE i;\n\n\tlogBlockBegin(\"bitmapDump(pBitMap: %p)\", pBitMap);\n\n\tlogWrite(\n\t\t\"BytesPerRow: %u, Rows: %u, Flags: %hu, Depth: %hu, pad: %u\\n\",\n\t\tpBitMap->BytesPerRow, pBitMap->Rows, pBitMap->Flags,\n\t\tpBitMap->Depth, pBitMap->pad\n\t);\n\t// since Planes is always 8-long, dump all its entries\n\tfor(i = 0; i != pBitMap->Depth; ++i) {\n\t\tlogWrite(\"Bitplane %hu addr: %p\\n\", i, pBitMap->Planes[i]);\n\t}\n\n\tlogBlockEnd(\"bitmapDump()\");\n}\n\nvoid bitmapSave(const tBitMap *pBitMap, const char *szPath) {\n\tsystemUse();\n\tlogBlockBegin(\"bitmapSave(pBitMap: %p, szPath: '%s')\", pBitMap, szPath);\n\n\ttFile *pFile = diskFileOpen(szPath, DISK_FILE_MODE_WRITE, 1);\n\tif(!pFile) {\n\t\tlogWrite(\"ERR: Couldn't save bitmap at '%s'\\n\", szPath);\n\t\tlogBlockEnd(\"bitmapSave()\");\n\t\treturn;\n\t}\n\n\t// TODO check free space on disk\n\n\t// Header\n\tUWORD uwWidth = bitmapGetByteWidth(pBitMap) << 3;\n\tUWORD uwHeight = pBitMap->Rows;\n\tUBYTE ubPlaneCount = pBitMap->Depth;\n\tUBYTE ubVersion = 0;\n\tUBYTE ubFlags = bitmapIsInterleaved(pBitMap) ? BITMAP_INTERLEAVED : 0;\n\tUWORD uwUnused = 0;\n\tfileWrite(pFile, &uwWidth, sizeof(UWORD));\n\tfileWrite(pFile, &uwHeight, sizeof(UWORD));\n\tfileWrite(pFile, &ubPlaneCount, sizeof(UBYTE));\n\tfileWrite(pFile, &ubVersion, sizeof(UBYTE));\n\tfileWrite(pFile, &ubFlags, sizeof(UBYTE));\n\tfileWrite(pFile, &uwUnused, sizeof(UWORD)); // Unused 2 bytes\n\n\t// Data\n\tif(ubFlags & BITMAP_INTERLEAVED) {\n\t\tfileWrite(pFile, pBitMap->Planes[0], (uwWidth >> 3) * uwHeight * ubPlaneCount);\n\t}\n\telse {\n\t\tfor (FUBYTE i = 0; i != ubPlaneCount; ++i) {\n\t\t\tfileWrite(pFile, pBitMap->Planes[i], (uwWidth >> 3) * uwHeight);\n\t\t}\n\t}\n\n\tfileClose(pFile);\n\tlogBlockEnd(\"bitmapSave()\");\n\tsystemUnuse();\n}\n\nvoid bitmapSaveBmp(\n\tconst tBitMap *pBitMap, const UWORD *pPalette, const char *szFilePath\n) {\n\t// TODO: EHB support\n\n\tsystemUse();\n\tUWORD uwWidth = bitmapGetByteWidth(pBitMap) << 3;\n\ttFile *pOut = diskFileOpen(szFilePath, DISK_FILE_MODE_WRITE, 1);\n\tif(!pOut) {\n\t\tlogWrite(\"ERR: Couldn't save bmp at '%s'\\n\", szFilePath);\n\t\tlogBlockEnd(\"bitmapSaveBmp()\");\n\t\treturn;\n\t}\n\n\t// BMP header\n\tfileWrite(pOut, \"BM\", 2);\n\n\tULONG ulOut = endianLittle32((pBitMap->BytesPerRow<<3) * pBitMap->Rows + 14+40+256*4);\n\tfileWrite(pOut, &ulOut, sizeof(ULONG)); // BMP file size\n\n\tulOut = 0;\n\tfileWrite(pOut, &ulOut, sizeof(ULONG)); // Reserved\n\n\tulOut = endianLittle32(14+40+256*4);\n\tfileWrite(pOut, &ulOut, sizeof(ULONG)); // Bitmap data starting addr\n\n\n\t// Bitmap info header\n\tulOut = endianLittle32(40);\n\tfileWrite(pOut, &ulOut, sizeof(ULONG)); // Core header size\n\n\tulOut = endianLittle32(uwWidth);\n\tfileWrite(pOut, &ulOut, sizeof(ULONG)); // Image width\n\n\tulOut = endianLittle32(pBitMap->Rows);\n\tfileWrite(pOut, &ulOut, sizeof(ULONG)); // Image height\n\n\tUWORD uwOut = endianLittle16(1);\n\tfileWrite(pOut, &uwOut, sizeof(UWORD)); // Color plane count\n\n\tuwOut = endianLittle16(8);\n\tfileWrite(pOut, &uwOut, sizeof(UWORD)); // Image BPP - 8bit indexed\n\n\tulOut = endianLittle32(0);\n\tfileWrite(pOut, &ulOut, sizeof(ULONG)); // Compression method - none\n\n\tulOut = endianLittle32(uwWidth * pBitMap->Rows);\n\tfileWrite(pOut, &ulOut, sizeof(ULONG)); // Image size\n\n\tulOut = endianLittle32(100);\n\tfileWrite(pOut, &ulOut, sizeof(ULONG)); // Horizontal resolution - px/m\n\n\tulOut = endianLittle32(100);\n\tfileWrite(pOut, &ulOut, sizeof(ULONG)); // Vertical resolution - px/m\n\n\tulOut = endianLittle32(0);\n\tfileWrite(pOut, &ulOut, sizeof(ULONG)); // Palette length\n\n\tulOut = endianLittle32(0);\n\tfileWrite(pOut, &ulOut, sizeof(ULONG)); // Number of important colors - all\n\n\t// Global palette\n\tUWORD c;\n\tfor(c = 0; c != (1 << pBitMap->Depth); ++c) {\n\t\tUBYTE ubOut = pPalette[c] & 0xF;\n\t\tubOut |= ubOut << 4;\n\t\tfileWrite(pOut, &ubOut, sizeof(UBYTE)); // B\n\n\t\tubOut = (pPalette[c] >> 4) & 0xF;\n\t\tubOut |= ubOut << 4;\n\t\tfileWrite(pOut, &ubOut, sizeof(UBYTE)); // G\n\n\t\tubOut = pPalette[c] >> 8;\n\t\tubOut |= ubOut << 4;\n\t\tfileWrite(pOut, &ubOut, sizeof(UBYTE)); // R\n\n\t\tubOut = 0;\n\t\tfileWrite(pOut, &ubOut, sizeof(UBYTE)); // 0\n\t}\n\t// Dummy fill up to 255 indices\n\tulOut = 0;\n\twhile(c < 256) {\n\t\tfileWrite(pOut, &ulOut, sizeof(ULONG));\n\t\t++c;\n\t}\n\n\t// Image data\n\tUBYTE pIndicesChunk[16];\n\tfor(UWORD uwY = pBitMap->Rows; uwY--;) {\n\t\tUWORD uwX;\n\t\tfor(uwX = 0; uwX < uwWidth; uwX += 16) {\n\t\t\tchunkyFromPlanar16(pBitMap, uwX, uwY, pIndicesChunk);\n\t\t\tfileWrite(pOut, pIndicesChunk, 16*sizeof(UBYTE));\n\t\t}\n\t\tUBYTE ubOut = 0;\n\t\twhile(uwX & 0x3) {// 4-byte row padding\n\t\t\tfileWrite(pOut, &ubOut, sizeof(UBYTE));\n\t\t\t++uwX;\n\t\t}\n\t}\n\n\tfileClose(pOut);\n\tsystemUnuse();\n}\n\nUWORD bitmapGetByteWidth(const tBitMap *pBitMap) {\n\tif(bitmapIsInterleaved(pBitMap)) {\n\t\treturn ((ULONG)pBitMap->Planes[1] - (ULONG)pBitMap->Planes[0]);\n\t}\n\treturn pBitMap->BytesPerRow;\n}\n"
  },
  {
    "path": "src/ace/utils/bmframe.c",
    "content": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at http://mozilla.org/MPL/2.0/. */\n\n#include <ace/utils/bmframe.h>\n\ntypedef enum _tBorderTile {\n\tBORDER_TILE_NW = 0,\n\tBORDER_TILE_N = 1,\n\tBORDER_TILE_NE = 2,\n\tBORDER_TILE_W = 3,\n\tBORDER_TILE_MID = 4,\n\tBORDER_TILE_E = 5,\n\tBORDER_TILE_SW = 6,\n\tBORDER_TILE_S = 7,\n\tBORDER_TILE_SE = 8,\n} _tBorderTile;\n\nvoid bmFrameDraw(\n\tconst tBitMap *pFrameSet, tBitMap *pDest,\n\tUWORD uwX, UWORD uwY, UBYTE ubCols, UBYTE ubRows, UBYTE ubTileSize\n) {\n\t// Vertices\n\tblitCopyAligned(\n\t\tpFrameSet, 0, BORDER_TILE_NW * ubTileSize, pDest,\n\t\tuwX, uwY, ubTileSize, ubTileSize\n\t);\n\tblitCopyAligned(\n\t\tpFrameSet, 0, BORDER_TILE_NE * ubTileSize, pDest,\n\t\tuwX + ((ubCols - 1) * ubTileSize), uwY, ubTileSize, ubTileSize\n\t);\n\tblitCopyAligned(\n\t\tpFrameSet, 0, BORDER_TILE_SW * ubTileSize, pDest,\n\t\tuwX, uwY + ((ubRows - 1) * ubTileSize), ubTileSize, ubTileSize\n\t);\n\tblitCopyAligned(\n\t\tpFrameSet, 0, BORDER_TILE_SE * ubTileSize, pDest,\n\t\tuwX + ((ubCols - 1) * ubTileSize), uwY + ((ubRows - 1) * ubTileSize),\n\t\tubTileSize, ubTileSize\n\t);\n\n\t// Horizontal edges\n\tfor(UBYTE i = 1; i < ubCols-1; ++i) {\n\t\tblitCopyAligned(\n\t\t\tpFrameSet, 0, BORDER_TILE_N * ubTileSize, pDest,\n\t\t\tuwX + (i * ubTileSize), uwY,\n\t\t\tubTileSize, ubTileSize\n\t\t);\n\t\tblitCopyAligned(\n\t\t\tpFrameSet, 0, BORDER_TILE_S * ubTileSize, pDest,\n\t\t\tuwX + (i * ubTileSize), uwY + ((ubRows - 1) * ubTileSize),\n\t\t\tubTileSize, ubTileSize\n\t\t);\n\t}\n\n\t// Middle rows\n\tif(ubRows > 2) {\n\t\t// Draw only first row\n\t\tblitCopyAligned(\n\t\t\tpFrameSet, 0, BORDER_TILE_W * ubTileSize, pDest,\n\t\t\tuwX, uwY + ubTileSize, ubTileSize, ubTileSize\n\t\t);\n\t\tblitCopyAligned(\n\t\t\tpFrameSet, 0, BORDER_TILE_E * ubTileSize, pDest,\n\t\t\tuwX + ((ubCols-1) * ubTileSize), uwY + ubTileSize, ubTileSize, ubTileSize\n\t\t);\n\t\tfor(UBYTE i = 1; i < ubCols-1; ++i) {\n\t\t\tblitCopyAligned(\n\t\t\t\tpFrameSet, 0, BORDER_TILE_MID * ubTileSize, pDest,\n\t\t\t\tuwX + (i * ubTileSize), uwY + ubTileSize, ubTileSize, ubTileSize\n\t\t\t);\n\t\t}\n\n\t\t// Fill rest of rows with the first one\n\t\tfor(UBYTE i = 2; i < ubRows - 1; ++i) {\n\t\t\tblitCopyAligned(\n\t\t\t\tpDest, uwX, uwY+ubTileSize, pDest, uwX, uwY+(i * ubTileSize),\n\t\t\t\tubCols * ubTileSize, ubTileSize\n\t\t\t);\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "src/ace/utils/chunky.c",
    "content": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at http://mozilla.org/MPL/2.0/. */\n\n#include <ace/types.h>\n#include <ace/managers/log.h>\n#include <ace/utils/chunky.h>\n#include <ace/utils/bitmap.h>\n#include <fixmath/fix16.h>\n\nvoid chunkyFromPlanar16(\n\tconst tBitMap *pBitMap, UWORD uwX, UWORD uwY, UBYTE *pOut\n) {\n\tUWORD uwChunk, uwMask;\n\tUBYTE i, ubPx;\n\tmemset(pOut, 0, 16*sizeof(*pOut));\n\t// From highest to lowest color idx bit\n\tfor(i = pBitMap->Depth; i--;) {\n\t\t// Obtain WORD from bitplane - 16 pixels\n\t\tuwChunk = ((UWORD*)(pBitMap->Planes[i]))[(pBitMap->BytesPerRow>>1)*uwY + (uwX>>4)];\n\t\tuwMask = 0x8000; // Start obtaining pixel values from left\n\t\tfor(ubPx = 0; ubPx != 16; ++ubPx) { // Insert read pixel bit to right\n\t\t\tpOut[ubPx] = (pOut[ubPx] << 1) | ((uwChunk & uwMask) != 0);\n\t\t\tuwMask >>= 1; // Shift pixel mask right\n\t\t}\n\t}\n}\n\nUBYTE chunkyFromPlanar(const tBitMap *pBitMap, UWORD uwX, UWORD uwY) {\n\tUBYTE pIndicesChunk[16];\n\tchunkyFromPlanar16(pBitMap, uwX, uwY, pIndicesChunk);\n\treturn pIndicesChunk[uwX&0xF];\n}\n\nvoid chunkyToPlanar16(const UBYTE *pIn, UWORD uwX, UWORD uwY, tBitMap *pOut) {\n\tUWORD uwPlanarBuffer = 0;\n\tULONG ulOffset = uwY * (pOut->BytesPerRow / 2) + (uwX / 16);\n\tfor(UBYTE ubPlane = 0; ubPlane < pOut->Depth; ++ubPlane) {\n\t\tfor(UBYTE ubPixel = 0; ubPixel < 16; ++ubPixel) {\n\t\t\tuwPlanarBuffer <<= 1;\n\t\t\tif(pIn[ubPixel] & (1<<ubPlane)) {\n\t\t\t\tuwPlanarBuffer |= 1;\n\t\t\t}\n\t\t}\n\t\tUWORD *pPlane = (UWORD*)(pOut->Planes[ubPlane]);\n\t\tpPlane[ulOffset] = uwPlanarBuffer;\n\t}\n}\n\nvoid chunkyToPlanar(UBYTE ubColor, UWORD uwX, UWORD uwY, tBitMap *pOut) {\n\tULONG ulOffset = uwY * (pOut->BytesPerRow / 2) + (uwX / 16);\n\tUWORD uwMask = BV(15) >> (uwX & 0xF);\n\tfor(UBYTE ubPlane = 0; ubPlane < pOut->Depth; ++ubPlane) {\n\t\tUWORD *pPlane = (UWORD*)pOut->Planes[ubPlane];\n\t\tif(ubColor & 1) {\n\t\t\tpPlane[ulOffset] |= uwMask;\n\t\t}\n\t\telse {\n\t\t\tpPlane[ulOffset] &= ~uwMask;\n\t\t}\n\t\tubColor >>= 1;\n\t}\n}\n\nvoid chunkyRotate(\n\tconst UBYTE *pSource, UBYTE *pDest, fix16_t fSin, fix16_t fCos,\n\tUBYTE ubBgColor, WORD wWidth, WORD wHeight\n) {\n\tfix16_t fCx, fCy;\n\tfix16_t fHalf = fix16_one>>1;\n\tWORD x,y;\n\tWORD u,v;\n\n\tfCx = fix16_div(fix16_from_int(wWidth), fix16_from_int(2));\n\tfCy = fix16_div(fix16_from_int(wHeight), fix16_from_int(2));\n\n\t// For each of new bitmap's pixel sample color from rotated source x,y\n\tfix16_t fDx, fDy;\n\tfor(y = 0; y != wHeight; ++y) {\n\t\tfDy = fix16_from_int(y) - fCy;\n\t\tfor(x = 0; x != wWidth; ++x) {\n\t\t\tfDx = fix16_from_int(x) - fCx;\n\t\t\t// u = round(fCos*(x-fCx) - fSin*(y-fCy) +(fCx));\n\t\t\t// v = fix16_to_int(fSin*(x-fCx) + fCos*(y-fCy) +(fCy));\n\t\t\tu = fix16_to_int(fix16_mul(fCos, fDx) - fix16_mul(fSin, fDy) + fCx + fHalf);\n\t\t\tv = fix16_to_int(fix16_mul(fSin, fDx) + fix16_mul(fCos, fDy) + fCy + fHalf);\n\n\t\t\tif(u < 0 || v < 0 || u >= wWidth || v >= wHeight) {\n\t\t\t\tpDest[y*wWidth + x] = ubBgColor;\n\t\t\t}\n\t\t\telse {\n\t\t\t\tpDest[y*wWidth + x] = pSource[v*wWidth + u];\n\t\t\t}\n\t\t}\n\t}\n}\n\nvoid chunkyFromBitmap(\n\tconst tBitMap *pBitmap, UBYTE *pChunky,\n\tUWORD uwSrcOffsX, UWORD uwSrcOffsY, UWORD uwWidth, UWORD uwHeight\n) {\n\tfor(UWORD y = 0; y < uwHeight; ++y) {\n\t\tfor(UWORD x = 0; x < uwWidth; x += 16) {\n\t\t\tchunkyFromPlanar16(\n\t\t\t\tpBitmap, uwSrcOffsX + x, uwSrcOffsY + y, &pChunky[y*uwWidth + x]\n\t\t\t);\n\t\t}\n\t}\n}\n\nvoid chunkyToBitmap(\n\tconst UBYTE *pChunky, tBitMap *pBitmap,\n\tUWORD uwDstOffsX, UWORD uwDstOffsY, UWORD uwWidth, UWORD uwHeight\n) {\n\tfor(UWORD y = 0; y < uwHeight; ++y) {\n\t\tfor(UWORD x = 0; x < uwWidth; x += 16)\n\t\t\tchunkyToPlanar16(\n\t\t\t\t&pChunky[(y*uwWidth) + x],\n\t\t\t\tuwDstOffsX + x, uwDstOffsY + y,\n\t\t\t\tpBitmap\n\t\t\t);\n\t}\n}\n"
  },
  {
    "path": "src/ace/utils/custom.c",
    "content": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at http://mozilla.org/MPL/2.0/. */\n\n#include <ace/utils/custom.h>\n#include <stddef.h>\n\n#ifdef AMIGA\n\n#define CUSTOM_BASE 0xDFF000\n\ntCustom FAR REGPTR g_pCustom = (tCustom REGPTR)CUSTOM_BASE;\n\ntCopperUlong FAR REGPTR g_pBplFetch = (tCopperUlong REGPTR)(\n\tCUSTOM_BASE + offsetof(tCustom, bplpt)\n);\ntCopperUlong FAR REGPTR g_pSprFetch = (tCopperUlong REGPTR)(\n\tCUSTOM_BASE + offsetof(tCustom, sprpt)\n);\ntCopperUlong FAR REGPTR g_pCopLc = (tCopperUlong REGPTR)(\n\tCUSTOM_BASE + offsetof(tCustom, cop1lc)\n);\ntCopperUlong FAR REGPTR g_pCop2Lc = (tCopperUlong REGPTR)(\n\tCUSTOM_BASE + offsetof(tCustom, cop2lc)\n);\n\ntCia FAR REGPTR g_pCia[CIA_COUNT] = {(tCia*)0xBFE001, (tCia*)0xBFD000};\n\nUWORD ciaGetTimerA(tCia REGPTR pCia) {\n\tUBYTE ubHi, ubLo;\n\tdo {\n\t\tubHi = pCia->tahi;\n\t\tubLo = pCia->talo;\n\t} while(ubHi != pCia->tahi);\n\treturn (ubHi << 8) | ubLo;\n}\n\nvoid ciaSetTimerA(tCia REGPTR pCia, UWORD uwTicks) {\n\t// The latches should be loaded, low byte first, as a write access\n\t// to the high register causes the timer to be stopped and reloaded with the\n\t// latch value unless the LOAD bit in the control register is set, in which case\n\t// the latch value is transferred to the timers regardless of the timer state\n\tpCia->talo = uwTicks & 0xFF;\n\tpCia->tahi = uwTicks >> 8;\n}\n\nUWORD ciaGetTimerB(tCia REGPTR pCia) {\n\tUBYTE ubHi, ubLo;\n\tdo {\n\t\tubHi = pCia->tbhi;\n\t\tubLo = pCia->tblo;\n\t} while(ubHi != pCia->tbhi);\n\treturn (ubHi << 8) | ubLo;\n}\n\nvoid ciaSetTimerB(tCia REGPTR pCia, UWORD uwTicks) {\n\t// The latches should be loaded, low byte first, as a write access\n\t// to the high register causes the timer to be stopped and reloaded with the\n\t// latch value unless the LOAD bit in the control register is set, in which case\n\t// the latch value is transferred to the timers regardless of the timer state\n\tpCia->tblo = uwTicks & 0xFF;\n\tpCia->tbhi = uwTicks >> 8;\n}\n\ntRayPos getRayPos(void) {\n\t// Even the 32-bit read via mov.l is split into 16-bit reads, so whe need\n\t// to read it as 2 16-bit vals and check for consistency.\n\tUWORD uwHiY, uwLoY, uwHiY2;\n\tdo {\n\t\tuwHiY = g_pCustom->vposr;\n\t\tuwLoY = g_pCustom->vhposr;\n\t\tuwHiY2 = g_pCustom->vposr;\n\t} while(uwHiY2 != uwHiY);\n\n\ttRayPos sPos = {.ulValue = (uwHiY2 << 16) | uwLoY};\n\treturn sPos;\n}\n\n#endif // AMIGA\n"
  },
  {
    "path": "src/ace/utils/dir.c",
    "content": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at http://mozilla.org/MPL/2.0/. */\n\n#include <ace/utils/dir.h>\n#include <string.h>\n#include <ace/macros.h>\n#include <ace/managers/system.h>\n#include <ace/managers/memory.h>\n#include <ace/managers/log.h>\n#include <proto/dos.h> // Bartman's compiler needs this\n\ntDir *dirOpen(const char *szPath) {\n\tsystemUse();\n\ttDir *pDir = memAllocFast(sizeof(tDir));\n\tpDir->pLock = Lock((unsigned char*)szPath, ACCESS_READ);\n\tif(\n\t\t!pDir->pLock || (Examine(pDir->pLock, &pDir->sFileBlock) == DOSFALSE) ||\n\t\t(pDir->sFileBlock.fib_DirEntryType  <= 0)\n\t) {\n\t\tUnLock(pDir->pLock);\n\t\tmemFree(pDir, sizeof(tDir));\n\t\tsystemUnuse();\n\t\treturn 0;\n\t}\n\tsystemUnuse();\n\treturn pDir;\n}\n\nUBYTE dirRead(tDir *pDir, char *szFileName, UWORD uwFileNameMax) {\n\tsystemUse();\n\tLONG lResult = ExNext(pDir->pLock, &pDir->sFileBlock);\n\tif(lResult == DOSFALSE) {\n\t\tsystemUnuse();\n\t\treturn 0;\n\t}\n\n\tstrncpy(szFileName, pDir->sFileBlock.fib_FileName, uwFileNameMax-1);\n\tszFileName[uwFileNameMax-1] = '\\0';\n\tsystemUnuse();\n\treturn 1;\n}\n\nvoid dirClose(tDir *pDir) {\n\tsystemUse();\n\tUnLock(pDir->pLock);\n\tmemFree(pDir, sizeof(tDir));\n\tsystemUnuse();\n}\n\nUBYTE dirExists(const char *szPath) {\n\tsystemUse();\n\ttDir *pDir = dirOpen(szPath);\n\tif(pDir) {\n\t\tdirClose(pDir);\n\t}\n\tsystemUnuse();\n\treturn pDir != 0;\n}\n\nUBYTE dirCreate(const char *szName) {\n\tsystemUse();\n\tLONG lResult = CreateDir((STRPTR)szName);\n\tUnLock(lResult);\n\tsystemUnuse();\n\treturn (lResult != 0);\n}\n\nUBYTE dirCreatePath(const char *szPath) {\n\tsystemUse();\n\tBYTE bPrevSlash = -1;\n\tchar szSubPath[108];\n\tchar *pSlash;\n\tUBYTE isCreated = 1;\n\twhile((pSlash = strchr(&szPath[bPrevSlash+1], '/'))) {\n\t\tmemcpy(&szSubPath[bPrevSlash], &szPath[bPrevSlash], pSlash-szPath - bPrevSlash);\n\t\tszSubPath[pSlash-szPath] = '\\0';\n\t\tif(dirExists(szSubPath)) {\n\t\t\t// This level exists - skip\n\t\t\tisCreated = 1;\n\t\t}\n\t\telse if(!dirCreate(szSubPath))  {\n\t\t\tsystemUnuse();\n\t\t\treturn 0;\n\t\t}\n\t\tbPrevSlash = pSlash-szPath;\n\t}\n\tif(szPath[strlen(szPath)-1] != '/' && !dirExists(szPath)) {\n\t\t// Path doesn't end with directory - create once again\n\t\tisCreated = dirCreate(szPath);\n\t}\n\tsystemUnuse();\n\treturn isCreated;\n}\n"
  },
  {
    "path": "src/ace/utils/disk_file.c",
    "content": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at http://mozilla.org/MPL/2.0/. */\n\n#include <ace/utils/disk_file.h>\n#include <ace/managers/system.h>\n#include <ace/managers/memory.h>\n#include <ace/managers/log.h>\n#include <ace/utils/disk_file_private.h>\n\n#define DISK_FILE_BUFFER_SIZE 512\n\ntypedef struct tDiskFileData {\n\tFILE *pFileHandle;\n\ttDiskFileMode eMode;\n\tUBYTE pBuffer[DISK_FILE_BUFFER_SIZE];\n\tUWORD uwBufferFill;\n\tUWORD uwBufferReadPos;\n\tUBYTE isUninterrupted;\n} tDiskFileData;\n\n#if !defined(ACE_FILE_USE_ONLY_DISK)\nstatic const tFileCallbacks s_sDiskFileCallbacks = {\n\t.cbFileClose = diskFileClose,\n\t.cbFileRead = diskFileRead,\n\t.cbFileWrite = diskFileWrite,\n\t.cbFileSeek = diskFileSeek,\n\t.cbFileGetPos = diskFileGetPos,\n\t.cbFileGetSize = diskFileGetSize,\n\t.cbFileIsEof = diskFileIsEof,\n\t.cbFileFlush = diskFileFlush,\n};\n#endif\n\n//------------------------------------------------------------------ PRIVATE FNS\n\n// TODO: move to system to be able to use for dir functions?\n\nstatic void fileAccessEnable(void) {\n\tsystemUse();\n\n\t// Blitter is needed for floppy drive access NOT only on KS1.3!\n\t// Apparently, Aminer crashes on KS3.1 on trying to save the settings\n\t// when blitter isn't released and also during in-gameplay loadings.\n\t// TODO: Investigate if it's only needed for writes in >= v36,\n\t/// and add isWrite param to decide on blitter release\n\t// TODO: do only when reading from floppy\n\t// if(systemGetVersion() < 36) {\n\tsystemReleaseBlitterToOs();\n\t// }\n}\n\nstatic void fileAccessDisable(void) {\n\t// if(systemGetVersion() < 36) {\n\tsystemGetBlitterFromOs();\n\t// }\n\n\tsystemUnuse();\n}\n\nDISKFILE_PRIVATE void diskFileClose(void *pData) {\n\ttDiskFileData *pDiskFileData = (tDiskFileData*)pData;\n\n\tif(!pDiskFileData->isUninterrupted) {\n\t\tfileAccessEnable();\n\t}\n\n\tif(pDiskFileData->eMode == DISK_FILE_MODE_WRITE) {\n\t\t// write remaining data\n\t\tfwrite(\n\t\t\tpDiskFileData->pBuffer, pDiskFileData->uwBufferFill, 1,\n\t\t\tpDiskFileData->pFileHandle\n\t\t);\n\t\tfflush(pDiskFileData->pFileHandle);\n\t}\n\n\tfclose(pDiskFileData->pFileHandle);\n\tmemFree(pDiskFileData, sizeof(*pDiskFileData));\n\tfileAccessDisable();\n}\n\nDISKFILE_PRIVATE ULONG diskFileRead(void *pData, void *pDest, ULONG ulSize) {\n\ttDiskFileData *pDiskFileData = (tDiskFileData*)pData;\n\tUBYTE *pDestBytes = (UBYTE*)pDest;\n\tULONG ulReadCount = 0;\n\n\tif(pDiskFileData->eMode != DISK_FILE_MODE_READ) {\n\t\tlogWrite(\"ERR: Attempting to read file not opened for read\\n\");\n\t}\n\n\t// copy some data from buffer\n\tUWORD uwReadyBytes = pDiskFileData->uwBufferFill - pDiskFileData->uwBufferReadPos;\n\tUWORD uwBytesToCopy = MIN(uwReadyBytes, ulSize);\n\tif(uwBytesToCopy) {\n\t\tfor(UWORD i = 0; i < uwBytesToCopy; ++i) {\n\t\t\t*(pDestBytes++) = pDiskFileData->pBuffer[pDiskFileData->uwBufferReadPos + i];\n\t\t}\n\t\tulReadCount += uwBytesToCopy;\n\t\tpDiskFileData->uwBufferReadPos += uwBytesToCopy;\n\t\tulSize -= uwBytesToCopy;\n\t}\n\n\tif(ulSize && ulSize > DISK_FILE_BUFFER_SIZE) {\n\t\t// if remaining data is bigger than buffer, read rest directly\n\t\tif(!pDiskFileData->isUninterrupted) {\n\t\t\tfileAccessEnable();\n\t\t}\n\t\tULONG ulReadPartSize = fread(pDestBytes, ulSize, 1, pDiskFileData->pFileHandle);\n\t\tpDestBytes += ulReadPartSize;\n\t\tulReadCount += ulReadPartSize;\n\t\tulSize -= ulReadPartSize;\n\n\t\tif(!pDiskFileData->isUninterrupted) {\n\t\t\tfileAccessDisable();\n\t\t}\n\t}\n\n\tif(ulSize) {\n\t\t// if not, fill the buffer and read remaining data from buffer\n\t\tif(pDiskFileData->uwBufferFill == pDiskFileData->uwBufferReadPos) {\n\t\t\tif(!pDiskFileData->isUninterrupted) {\n\t\t\t\tfileAccessEnable();\n\t\t\t}\n\n\t\t\tpDiskFileData->uwBufferFill = fread(\n\t\t\t\tpDiskFileData->pBuffer, DISK_FILE_BUFFER_SIZE, 1,\n\t\t\t\tpDiskFileData->pFileHandle\n\t\t\t);\n\n\t\t\tif(!pDiskFileData->isUninterrupted) {\n\t\t\t\tfileAccessDisable();\n\t\t\t}\n\t\t\tpDiskFileData->uwBufferReadPos = 0;\n\t\t}\n\n\t\tuwReadyBytes = pDiskFileData->uwBufferFill - pDiskFileData->uwBufferReadPos;\n\t\tuwBytesToCopy = MIN(uwReadyBytes, ulSize);\n\t\tif(uwBytesToCopy) {\n\t\t\tfor(UWORD i = 0; i < uwBytesToCopy; ++i) {\n\t\t\t\t*(pDestBytes++) = pDiskFileData->pBuffer[i];\n\t\t\t}\n\t\t\tulReadCount += uwBytesToCopy;\n\t\t\tulSize -= uwBytesToCopy;\n\t\t\tpDiskFileData->uwBufferReadPos += uwBytesToCopy;\n\t\t}\n\t}\n\n\treturn ulReadCount;\n}\n\nDISKFILE_PRIVATE ULONG diskFileWrite(void *pData, const void *pSrc, ULONG ulSize) {\n\ttDiskFileData *pDiskFileData = (tDiskFileData*)pData;\n\tULONG ulWritten;\n\n\tif(pDiskFileData->eMode != DISK_FILE_MODE_WRITE) {\n\t\tlogWrite(\"ERR: Attempting to write file not opened for write\\n\");\n\t}\n\n\tif(pDiskFileData->uwBufferFill + ulSize < DISK_FILE_BUFFER_SIZE) {\n\t\tmemcpy(&pDiskFileData->pBuffer[pDiskFileData->uwBufferFill], pSrc, ulSize);\n\t\tpDiskFileData->uwBufferFill += ulSize;\n\t\tulWritten = ulSize;\n\t}\n\telse {\n\t\tif(!pDiskFileData->isUninterrupted) {\n\t\t\tfileAccessEnable();\n\t\t}\n\n\t\t// NOTE: Don't take previously buffered data into account in return value.\n\t\t// TODO: Make sure that all was written here?\n\t\tfwrite(\n\t\t\tpDiskFileData->pBuffer, pDiskFileData->uwBufferFill, 1,\n\t\t\tpDiskFileData->pFileHandle\n\t\t);\n\t\tpDiskFileData->uwBufferFill = 0;\n\n\t\t// Only allow small read here so that big write will go to the file directly\n\t\tif(ulSize < 100) {\n\t\t\tmemcpy(&pDiskFileData->pBuffer[pDiskFileData->uwBufferFill], pSrc, ulSize);\n\t\t\tpDiskFileData->uwBufferFill = ulSize;\n\t\t\tulWritten = ulSize;\n\t\t}\n\t\telse {\n\t\t\tulWritten = fwrite(pSrc, ulSize, 1, pDiskFileData->pFileHandle);\n\t\t}\n\n\t\tif(!pDiskFileData->isUninterrupted) {\n\t\t\tfflush(pDiskFileData->pFileHandle);\n\t\t\tfileAccessDisable();\n\t\t}\n\t}\n\treturn ulWritten;\n}\n\nDISKFILE_PRIVATE ULONG diskFileSeek(void *pData, LONG lPos, WORD wMode) {\n\ttDiskFileData *pDiskFileData = (tDiskFileData*)pData;\n\n\tif(wMode == SEEK_SET) {\n\t\tLONG lDelta = lPos - diskFileGetPos(pData);\n\t\tif(\n\t\t\t(lDelta <= 0 && -lDelta < pDiskFileData->uwBufferReadPos) ||\n\t\t\t(lDelta > 0 && lDelta < pDiskFileData->uwBufferFill - pDiskFileData->uwBufferReadPos)\n\t\t) {\n\t\t\tpDiskFileData->uwBufferReadPos += lDelta;\n\t\t\treturn 0;\n\t\t}\n\t}\n\n\tif(wMode == SEEK_CUR && (\n\t\t(lPos > 0 && lPos < pDiskFileData->uwBufferFill - pDiskFileData->uwBufferReadPos) ||\n\t\t(lPos < pDiskFileData->uwBufferReadPos)\n\t)) {\n\t\tpDiskFileData->uwBufferReadPos += lPos;\n\t\treturn 0;\n\t}\n\n\tif(!pDiskFileData->isUninterrupted) {\n\t\tfileAccessEnable();\n\t}\n\n\t// Failsafe for buffering\n\tif(wMode == SEEK_CUR) {\n\t\twMode = SEEK_SET;\n\t\tlPos += diskFileGetPos(pData);\n\t}\n\n\tULONG ulResult = fseek(pDiskFileData->pFileHandle, lPos, wMode);\n\tif(pDiskFileData->uwBufferFill) {\n\t\tlogWrite(\"WARN: slow - read buffer discard\\n\");\n\t\tpDiskFileData->uwBufferReadPos = 0;\n\t\tpDiskFileData->uwBufferFill = 0;\n\t}\n\n\tif(!pDiskFileData->isUninterrupted) {\n\t\tfileAccessDisable();\n\t}\n\n\treturn ulResult;\n}\n\nDISKFILE_PRIVATE ULONG diskFileGetPos(void *pData) {\n\ttDiskFileData *pDiskFileData = (tDiskFileData*)pData;\n\n\tif(!pDiskFileData->isUninterrupted) {\n\t\tfileAccessEnable();\n\t}\n\n\tULONG ulResult = ftell(pDiskFileData->pFileHandle);\n\tulResult -= pDiskFileData->uwBufferFill - pDiskFileData->uwBufferReadPos;\n\n\tif(!pDiskFileData->isUninterrupted) {\n\t\tfileAccessDisable();\n\t}\n\n\treturn ulResult;\n}\n\nDISKFILE_PRIVATE ULONG diskFileGetSize(void *pData) {\n\t// One could use std library to seek to end of file and use ftell,\n\t// but SEEK_END is not guaranteed to work.\n\t// http://www.cplusplus.com/reference/cstdio/fseek/\n\t// On the other hand, Lock/UnLock is bugged on KS1.3 and doesn't allow\n\t// for doing Open() on same file after using it.\n\t// So I ultimately do it using fseek.\n\ttDiskFileData *pDiskFileData = (tDiskFileData*)pData;\n\tif(!pDiskFileData->isUninterrupted) {\n\t\tfileAccessEnable();\n\t}\n\n\tLONG lOldPos = diskFileGetPos(pData);\n\tdiskFileSeek(pData, 0, SEEK_END);\n\tLONG lSize = diskFileGetPos(pData);\n\tdiskFileSeek(pData, lOldPos, SEEK_SET);\n\n\tif(!pDiskFileData->isUninterrupted) {\n\t\tfileAccessDisable();\n\t}\n\n\treturn lSize;\n}\n\nDISKFILE_PRIVATE UBYTE diskFileIsEof(void *pData) {\n\ttDiskFileData *pDiskFileData = (tDiskFileData*)pData;\n\n\tif(!pDiskFileData->isUninterrupted) {\n\t\tfileAccessEnable();\n\t}\n\n\tUBYTE isEof = (\n\t\t(pDiskFileData->uwBufferReadPos == pDiskFileData->uwBufferFill) &&\n\t\tfeof(pDiskFileData->pFileHandle)\n\t);\n\n\tif(!pDiskFileData->isUninterrupted) {\n\t\tfileAccessDisable();\n\t}\n\n\treturn isEof;\n}\n\nDISKFILE_PRIVATE void diskFileFlush(void *pData) {\n\ttDiskFileData *pDiskFileData = (tDiskFileData*)pData;\n\n\tif(!pDiskFileData->isUninterrupted) {\n\t\tfileAccessEnable();\n\t}\n\n\tfflush(pDiskFileData->pFileHandle);\n\n\tif(!pDiskFileData->isUninterrupted) {\n\t\tfileAccessDisable();\n\t}\n}\n\n//------------------------------------------------------------------- PUBLIC FNS\n\ntFile *diskFileOpen(const char *szPath, tDiskFileMode eMode, UBYTE isUninterrupted) {\n\tlogBlockBegin(\n\t\t\"diskFileOpen(szPath: '%s', eMode: %d, isUninterrupted: %hhu)\",\n\t\tszPath, eMode, isUninterrupted\n\t);\n\t// TODO check if disk is read protected when szMode has 'a'/'r'/'x'\n\t// TODO: disable buffering in a/w/x modes\n\tfileAccessEnable();\n\ttFile *pFile = 0;\n\tFILE *pFileHandle = fopen(szPath, eMode == DISK_FILE_MODE_WRITE ? \"wb\" : \"rb\");\n\tif(pFileHandle == 0) {\n\t\tlogWrite(\"ERR: Can't open file\\n\");\n\t\tfileAccessDisable();\n\t}\n\telse {\n\t\ttDiskFileData *pData = memAllocFast(sizeof(*pData));\n\t\tpData->pFileHandle = pFileHandle;\n\t\tpData->eMode = eMode;\n\t\tpData->uwBufferFill = 0;\n\t\tpData->uwBufferReadPos = 0;\n\t\tpData->isUninterrupted = isUninterrupted;\n#if defined(ACE_FILE_USE_ONLY_DISK) // TODO: verify if still viable\n\t\tpFile = (tFile*)pData;\n#else\n\t\tpFile = memAllocFast(sizeof(*pFile));\n\t\tpFile->pCallbacks = &s_sDiskFileCallbacks;\n\t\tpFile->pData = pData;\n\t\tlogWrite(\"File handle: %p, data: %p\\n\", pFile, pFile->pData);\n#endif\n\t\tif(!pData->isUninterrupted) {\n\t\t\tfileAccessDisable();\n\t\t}\n\t}\n\tlogBlockEnd(\"diskFileOpen()\");\n\treturn pFile;\n}\n\nUBYTE diskFileExists(const char *szPath) {\n\tfileAccessEnable();\n\tUBYTE isExisting = 0;\n\tFILE *pFileHandle = fopen(szPath, \"rb\");\n\tif(pFileHandle) {\n\t\tisExisting = 1;\n\t\tfclose(pFileHandle);\n\t}\n\tfileAccessDisable();\n\n\treturn isExisting;\n}\n\nUBYTE diskFileDelete(const char *szFilePath) {\n\tfileAccessEnable();\n\tUBYTE isSuccess = remove(szFilePath);\n\tfileAccessDisable();\n\treturn isSuccess;\n}\n\nUBYTE diskFileMove(const char *szSource, const char *szDest) {\n\tfileAccessEnable();\n\tUBYTE isSuccess = rename(szSource, szDest);\n\tfileAccessDisable();\n\treturn isSuccess;\n}\n"
  },
  {
    "path": "src/ace/utils/extview.c",
    "content": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at http://mozilla.org/MPL/2.0/. */\n\n#include <ace/utils/extview.h>\n#include <limits.h>\n#include <ace/managers/system.h>\n#include <ace/utils/tag.h>\n#include <ace/generic/screen.h>\n\nstatic UBYTE s_isPAL;\n\ntView *viewCreate(void *pTags, ...) {\n\n\tlogBlockBegin(\"viewCreate(pTags: %p)\", pTags);\n#ifdef AMIGA\n\n\ts_isPAL = systemIsPal();\n\n\t// Create view stub\n\ttView *pView = memAllocFastClear(sizeof(tView));\n\tlogWrite(\"created %s viewport addr: %p\\n\", s_isPAL ? \"PAL\" : \"NTSC\", pView);\n\n\tva_list vaTags;\n\tva_start(vaTags, pTags);\n\n\t// Process copperlist raw/block tags\n\tif(\n\t\ttagGet(pTags, vaTags, TAG_VIEW_COPLIST_MODE, VIEW_COPLIST_MODE_BLOCK)\n\t\t== VIEW_COPLIST_MODE_RAW\n\t) {\n\t\tULONG ulCopListSize = tagGet(pTags, vaTags, TAG_VIEW_COPLIST_RAW_COUNT, -1);\n\t\tpView->pCopList = copListCreate(0,\n\t\t\tTAG_COPPER_LIST_MODE, COPPER_MODE_RAW,\n\t\t\tTAG_COPPER_RAW_COUNT, ulCopListSize,\n\t\t\tTAG_DONE\n\t\t);\n\t\tpView->uwFlags |= VIEW_FLAG_COPLIST_RAW;\n\t}\n\telse {\n\t\tpView->pCopList = copListCreate(0, TAG_DONE);\n\t}\n\n\t// Global display mode tags\n\tif(tagGet(pTags, vaTags, TAG_VIEW_GLOBAL_PALETTE, 1)) {\n\t\tpView->uwFlags |= VIEW_FLAG_GLOBAL_PALETTE;\n\t}\n\tif(tagGet(pTags, vaTags, TAG_VIEW_GLOBAL_HRES, 1)) {\n\t\tpView->uwFlags |= VIEW_FLAG_GLOBAL_HRES;\n\t}\n\tif(tagGet(pTags, vaTags, TAG_VIEW_GLOBAL_BPP, 1)) {\n\t\tpView->uwFlags |= VIEW_FLAG_GLOBAL_BPP;\n\t}\n#ifdef ACE_USE_AGA_FEATURES\n\tif(tagGet(pTags, vaTags, TAG_VIEW_USES_AGA, 1)) {\n\t\tpView->uwFlags |= VIEW_FLAG_GLOBAL_AGA;\n\t}\n\tlogWrite(\n\t\t\"Extra flags: %s%s%s%s\\n\",\n\t\t(pView->uwFlags & VIEW_FLAG_GLOBAL_PALETTE) ? \"GLOBAL_PALETTE \" : \"\",\n\t\t(pView->uwFlags & VIEW_FLAG_GLOBAL_BPP) ? \"GLOBAL_BPP \" : \"\",\n\t\t(pView->uwFlags & VIEW_FLAG_GLOBAL_HRES) ? \"GLOBAL_HRES \" : \"\",\n\t\t(pView->uwFlags & VIEW_FLAG_GLOBAL_AGA) ? \"GLOBAL_AGA \" : \"\"\n\t);\n#else\n\tlogWrite(\n\t\t\"Extra flags: %s%s%s\\n\",\n\t\t(pView->uwFlags & VIEW_FLAG_GLOBAL_PALETTE) ? \"GLOBAL_PALETTE \" : \"\",\n\t\t(pView->uwFlags & VIEW_FLAG_GLOBAL_BPP) ? \"GLOBAL_BPP \" : \"\",\n\t\t(pView->uwFlags & VIEW_FLAG_GLOBAL_HRES) ? \"GLOBAL_HRES \" : \"\"\n\t);\n#endif\n\n\t// Get the Y pos and height\n\tconst UWORD uwDefaultHeight = -1;\n\tconst UBYTE ubDefaultPosY = -1;\n\tUWORD uwHeight = tagGet(pTags, vaTags, TAG_VIEW_WINDOW_HEIGHT, uwDefaultHeight);\n\tUBYTE ubPosY = tagGet(pTags, vaTags, TAG_VIEW_WINDOW_START_Y, ubDefaultPosY);\n\tif(uwHeight != uwDefaultHeight && ubPosY == ubDefaultPosY) {\n\t\t// Only height is passed - calculate Y pos so that display is centered\n\t\tpView->uwHeight = uwHeight;\n\t\tif (s_isPAL) {\n\t\t\tpView->ubPosY = SCREEN_PAL_YOFFSET + (SCREEN_PAL_HEIGHT - uwHeight) / 2;\n\t\t}\n\t\telse{\n\t\t\tpView->ubPosY = SCREEN_NTSC_YOFFSET + (SCREEN_NTSC_HEIGHT - uwHeight) / 2;\n\t\t}\n\t}\n\telse if(uwHeight == uwDefaultHeight && ubPosY != ubDefaultPosY) {\n\t\t// Only Y pos is passed - calculate height as the remaining area of PAL display\n\t\tpView->ubPosY = ubPosY;\n\t\tif (s_isPAL) {\n\t\t\tpView->uwHeight = SCREEN_PAL_YOFFSET + SCREEN_PAL_HEIGHT - ubPosY;\n\t\t}\n\t\telse{\n\t\t\tpView->uwHeight = SCREEN_NTSC_YOFFSET + SCREEN_NTSC_HEIGHT - ubPosY;\n\t\t}\n\t}\n\telse if(uwHeight == uwDefaultHeight && ubPosY == ubDefaultPosY) {\n\t\t// All default - use PAL\n\t\tif (s_isPAL) {\n\t\t\tpView->ubPosY = SCREEN_PAL_YOFFSET;\n\t\t\tpView->uwHeight = SCREEN_PAL_HEIGHT;\n\t\t}\n\t\telse {\n\t\t\tpView->ubPosY = SCREEN_NTSC_YOFFSET;\n\t\t\tpView->uwHeight = SCREEN_NTSC_HEIGHT;\n\t\t}\n\t}\n\telse {\n\t\t// Use passed values\n\t\tpView->ubPosY = ubPosY;\n\t\tpView->uwHeight = uwHeight;\n\t}\n\tpView->ubPosX = tagGet(pTags, vaTags, TAG_VIEW_WINDOW_START_X, SCREEN_XOFFSET);\n\tpView->uwWidth = tagGet(pTags, vaTags, TAG_VIEW_WINDOW_WIDTH, SCREEN_PAL_WIDTH);\n\n\tlogWrite(\n\t\t\"Display pos: %hhu,%hhu, size: %hu,%hu\\n\",\n\t\tpView->ubPosX, pView->ubPosY, pView->uwWidth, pView->uwHeight\n\t);\n\n\tva_end(vaTags);\n\tlogBlockEnd(\"viewCreate()\");\n\treturn pView;\n#else\n\tlogBlockEnd(\"viewCreate()\");\n\treturn 0;\n#endif // AMIGA\n}\n\nvoid viewDestroy(tView *pView) {\n\tlogBlockBegin(\"viewDestroy(pView: %p)\", pView);\n#ifdef AMIGA\n\tif(g_sCopManager.pCopList == pView->pCopList) {\n\t\tviewLoad(0);\n\t}\n\n\t// Free all attached viewports\n\twhile(pView->pFirstVPort) {\n\t\tvPortDestroy(pView->pFirstVPort);\n\t}\n\n\t// Free view\n\tlogWrite(\"Freeing copperlists...\\n\");\n\tcopListDestroy(pView->pCopList);\n\tmemFree(pView, sizeof(tView));\n#endif // AMIGA\n\tlogBlockEnd(\"viewDestroy()\");\n}\n\nvoid vPortProcessManagers(tVPort *pVPort) {\n\ttVpManager *pManager = pVPort->pFirstManager;\n\twhile(pManager) {\n\t\tpManager->process(pManager);\n\t\tpManager = pManager->pNext;\n\t}\n}\n\nvoid viewProcessManagers(tView *pView) {\n\ttVPort *pVPort = pView->pFirstVPort;\n\twhile(pVPort) {\n\t\tvPortProcessManagers(pVPort);\n\t\tpVPort = pVPort->pNext;\n\t}\n}\n\nvoid viewUpdateGlobalPalette(const tView *pView) {\n#ifdef AMIGA\n\tif(pView->uwFlags & VIEW_FLAG_GLOBAL_PALETTE) {\n#ifdef ACE_USE_AGA_FEATURES\n\t\tif(pView->pFirstVPort->eFlags & VP_FLAG_AGA) {\n\t\t\tWORD colorBanks = (1 << pView->pFirstVPort->ubBpp) / 32;\n\t\t\tULONG *pPaletteAGA = (ULONG *)pView->pFirstVPort->pPalette;\n\t\t\tfor(UBYTE p = 0; p < colorBanks; ++p) {\n\t\t\t\tfor(UBYTE i = 0; i < 32; ++i) {\n\t\t\t\t\tUBYTE r = pPaletteAGA[(p * 32) + i] >> 16;\n\t\t\t\t\tUBYTE g = pPaletteAGA[(p * 32) + i] >> 8;\n\t\t\t\t\tUBYTE b = pPaletteAGA[(p * 32) + i];\n\t\t\t\t\tg_pCustom->bplcon3 = p << 13; // Set palette bank LOW.\n\t\t\t\t\tg_pCustom->color[i] = (r >> 4) << 8 | (g >> 4) << 4 | (b >> 4) << 0;\n\t\t\t\t\tg_pCustom->bplcon3 = p << 13 | BV(9); // Set palette bank High.\n\t\t\t\t\tg_pCustom->color[i] = (0x0F & r) << 8 | (0x0F & g) << 4 | (0x0F & b) << 0;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\telse {\n\t\t\tfor(UBYTE i = 0; i < 32; ++i) {\n\t\t\t\tg_pCustom->color[i] = pView->pFirstVPort->pPalette[i];\n\t\t\t}\n\t\t}\n#else\n\t\tfor(UBYTE i = 0; i < 32; ++i) {\n\t\t\tg_pCustom->color[i] = pView->pFirstVPort->pPalette[i];\n\t\t}\n#endif\n\t}\n#endif // AMIGA\n}\n\n/**\n *  @todo bplcon0 BPP is set up globally - make it only when all vports\n *        are truly of same BPP.\n */\nvoid viewLoad(tView *pView) {\n\tlogBlockBegin(\"viewLoad(pView: %p)\", pView);\n\n\ts_isPAL = systemIsPal();\n\tUWORD uwWaitPos = (s_isPAL == 1) ? 300 : 260;\n\t// if we are setting a NULL viewport we need to know if pal/NTSC\n\twhile(getRayPos().bfPosY < uwWaitPos) continue;\n#if defined(AMIGA)\n\tif(!pView) {\n\t\tg_sCopManager.pCopList = g_sCopManager.pBlankList;\n\t\tg_pCustom->bplcon0 = 0; // No output\n\t\tg_pCustom->fmode = 0;   // AGA fix\n\t\tg_pCustom->bplcon3 = 0; // AGA fix\n\t\tg_pCustom->bplcon4 = 0x0011; // AGA fix\n#ifdef ACE_USE_AGA_FEATURES\n\t\tfor(UBYTE i = 0; i < 8; ++i) {\n\t\t\tg_pCustom->bplpt[i] = 0;\n\t\t}\n#else\n\t\tfor(UBYTE i = 0; i < 6; ++i) {\n\t\t\tg_pCustom->bplpt[i] = 0;\n\t\t}\n#endif\n\t\tg_pCustom->bpl1mod = 0;\n\t\tg_pCustom->bpl2mod = 0;\n\t}\n\telse {\n#if defined(ACE_DEBUG)\n\t\t{\n\t\t\t// Check if view size matches size of last vport\n\t\t\ttVPort *pVp = pView->pFirstVPort;\n\t\t\twhile(pVp->pNext) {\n\t\t\t\tpVp = pVp->pNext;\n\t\t\t}\n\t\t\tif(pVp->uwOffsY + pVp->uwHeight != pView->uwHeight) {\n\t\t\t\tlogWrite(\n\t\t\t\t\t\"ERR: View height %hu doesn't match the total VPort area: %hu\",\n\t\t\t\t\tpView->uwHeight, pVp->uwOffsY + pVp->uwHeight\n\t\t\t\t);\n\t\t\t}\n\t\t}\n#endif\n\t\tpView->uwBplCon0 = 0;\n\t\tif(pView->uwFlags & VIEW_FLAG_GLOBAL_BPP) {\n\t\t\tpView->uwBplCon0 |= pView->pFirstVPort->ubBpp << 12;\n\t\t}\n\t\tif(pView->uwFlags & VIEW_FLAG_GLOBAL_HRES) {\n\t\t\tpView->uwBplCon0 |= ((pView->pFirstVPort->eFlags & VP_FLAG_HIRES) != 0) << 15;\n\t\t}\n\t\tpView->uwBplCon0 |= BV(9); // composite output\n\t\t// TODO: set uwBplCon2 in viewCreate, make the playfield/sprite priority\n\t\t// configurable via tags\n\n\t\tg_sCopManager.pCopList = pView->pCopList;\n#ifdef ACE_USE_AGA_FEATURES\n\t\tif(pView->pFirstVPort->eFlags & VP_FLAG_AGA) {\n\t\t\tUWORD uwBplCon0 = ((0x07 & pView->pFirstVPort->ubBpp) << 12) | BV(9); // BPP + composite output\n\t\t\tif(pView->pFirstVPort->ubBpp & 0x08) {\n\t\t\t\tuwBplCon0 |= BV(4);\n\t\t\t}\n\t\t\tg_pCustom->bplcon0 = uwBplCon0;\n\n\t\t\tif(pView->pFirstVPort->ubBpp == 6) {\n\t\t\t\t/* KILLEHB + Kickstart-style PF/sprite priority (BV(2)|BV(5) == 0x24) */\n\t\t\t\tg_pCustom->bplcon2 = (UWORD)(BV(2) | BV(5) | BV(9));\n\t\t\t}\n\t\t}\n\t\telse {\n\t\t\tg_pCustom->bplcon0 = (pView->pFirstVPort->ubBpp << 12) | BV(9); // BPP + composite output\n\t\t\tg_pCustom->bplcon2 = (UWORD)(BV(2) | BV(5));\n\t\t}\n\t\tg_pCustom->fmode = pView->pFirstVPort->ubFmode;\n\t\tg_pCustom->bplcon3 = 0; // AGA fix\n#else\n\t\tg_pCustom->bplcon0 = (pView->pFirstVPort->ubBpp << 12) | BV(9); // BPP + composite output\n\t\tg_pCustom->bplcon2 = (UWORD)(BV(2) | BV(5));\n\t\tg_pCustom->fmode = 0; // AGA fix\n\t\tg_pCustom->bplcon3 = 0; // AGA fix\n#endif\n\t\tg_pCustom->bplcon4 = 0x0011; // AGA fix\n\n\t\tUWORD uwDiwStartX = pView->ubPosX;\n\t\tUWORD uwDiwStopX = uwDiwStartX + pView->uwWidth - 256;\n\t\tUWORD uwDiwStopY = pView->ubPosY + pView->uwHeight;\n\t\tif(BTST(uwDiwStopY, 8) == BTST(uwDiwStopY, 7)) {\n\t\t\tlogWrite(\n\t\t\t\t\"ERR: DiwStopY (%hu) bit 8 (%hhu) must be different than bit 7 (%hhu)\\n\",\n\t\t\t\tuwDiwStopY, BTST(uwDiwStopY, 8), BTST(uwDiwStopY, 7)\n\t\t\t);\n\t\t}\n\t\tg_pCustom->diwstrt = (pView->ubPosY << 8) | uwDiwStartX; // HSTART: 0x81\n\t\tg_pCustom->diwstop = ((uwDiwStopY & 0xFF) << 8) | uwDiwStopX; // HSTOP: 0xC1\n\t\tviewUpdateGlobalPalette(pView);\n\t}\n\tcopProcessBlocks();\n\tg_pCustom->copjmp1 = 1;\n\tsystemSetDmaBit(DMAB_RASTER, pView != 0);\n\n\t// if we are setting a NULL viewport we need to know if pal/NTSC\n\twhile(getRayPos().bfPosY < uwWaitPos) continue;\n\n#endif // AMIGA\n\tlogBlockEnd(\"viewLoad()\");\n}\n\ntVPort *vPortCreate(void *pTagList, ...) {\n\tlogBlockBegin(\"vPortCreate(pTagList: %p)\", pTagList);\n\tva_list vaTags;\n\tva_start(vaTags, pTagList);\n#ifdef AMIGA\n\ts_isPAL = systemIsPal();\n\n\ttVPort *pVPort = memAllocFastClear(sizeof(tVPort));\n\tlogWrite(\"Addr: %p\\n\", pVPort);\n\n\t// Determine parent view\n\ttView *pView = (tView*)tagGet(pTagList, vaTags, TAG_VPORT_VIEW, 0);\n\tif(!pView) {\n\t\tlogWrite(\"ERR: no view ptr in TAG_VPORT_VIEW specified\\n\");\n\t\tgoto fail;\n\t}\n\tpVPort->pView = pView;\n\tlogWrite(\"Parent view: %p\\n\", pView);\n\n\t// Calculate Y offset - beneath previous ViewPort\n\tpVPort->uwOffsY = 0;\n\ttVPort *pPrevVPort = pView->pFirstVPort;\n\twhile(pPrevVPort) {\n\t\tpVPort->uwOffsY += pPrevVPort->uwHeight;\n\t\tpPrevVPort = pPrevVPort->pNext;\n\t}\n\tif(pVPort->uwOffsY && !(pView->uwFlags & VIEW_FLAG_GLOBAL_PALETTE)) {\n\t\tpVPort->uwOffsY += 2; // TODO: not always required?\n\t}\n\tULONG ulAddOffsY = tagGet(pTagList, vaTags, TAG_VPORT_OFFSET_TOP, 0);\n\tpVPort->uwOffsY += ulAddOffsY;\n\tlogWrite(\"Offsets: %ux%u\\n\", pVPort->uwOffsX, pVPort->uwOffsY);\n\n\tif(\n\t\ttagGet(pTagList, vaTags, TAG_VPORT_HIRES, 0) ||\n\t\t((pView->uwFlags & VIEW_FLAG_GLOBAL_HRES) && pPrevVPort && pPrevVPort->eFlags & VP_FLAG_HIRES)\n\t) {\n\t\tpVPort->eFlags |= VP_FLAG_HIRES;\n\t}\n\tconst UWORD uwDefaultBpp = 4; // 'Cuz copper is slower on 5bpp+ in OCS\n\tpVPort->ubBpp = tagGet(pTagList, vaTags, TAG_VPORT_BPP, uwDefaultBpp);\n\n#ifdef ACE_USE_AGA_FEATURES\n\tif(\n\t\ttagGet(pTagList, vaTags, TAG_VPORT_USES_AGA, 0) ||\n\t\t((pView->uwFlags & VIEW_FLAG_GLOBAL_AGA) && pPrevVPort && pPrevVPort->eFlags & VP_FLAG_AGA)\n\t) {\n\t\tpVPort->eFlags |= VP_FLAG_AGA;\n\t}\n\tconst UBYTE ubDefaultFmode = 0;\n\tpVPort->ubFmode = tagGet(pTagList, vaTags, TAG_VPORT_FMODE, ubDefaultFmode);\n#endif\n\n\t// Get dimensions\n\t// FIXME: this doesn't work correctly due to diwstrt/stop being set globally\n\t// in view, but is needed for vport manger bitmap default size calcs.\n\tUWORD uwDefaultWidth = pView->uwWidth;\n\tif(pVPort->eFlags & VP_FLAG_HIRES) {\n\t\tuwDefaultWidth *= 2;\n\t}\n\tconst UWORD uwDefaultHeight = -1;\n\n\tpVPort->uwWidth = tagGet(pTagList, vaTags, TAG_VPORT_WIDTH, uwDefaultWidth);\n\tpVPort->uwHeight = tagGet(pTagList, vaTags, TAG_VPORT_HEIGHT, uwDefaultHeight);\n\tif(pVPort->uwHeight == uwDefaultHeight) {\n\t\tpVPort->uwHeight = pView->uwHeight - pVPort->uwOffsY;\n\t}\n\n\tlogWrite(\n\t\t\"Dimensions: %ux%u@%hu (%s)\\n\",\n\t\tpVPort->uwWidth, pVPort->uwHeight, pVPort->ubBpp,\n\t\t((pVPort->eFlags & VP_FLAG_HIRES) ? \"HIRES\" : \"LORES\")\n\t);\n\n\t// Update view - add to vPort list\n\t++pView->ubVpCount;\n\tif(!pView->pFirstVPort) {\n\t\tpView->pFirstVPort = pVPort;\n\t\tlogWrite(\"No prev VPorts - added to head\\n\");\n\t}\n\telse {\n\t\tpPrevVPort = pView->pFirstVPort;\n\t\twhile(pPrevVPort->pNext) {\n\t\t\tpPrevVPort = pPrevVPort->pNext;\n\t\t}\n\t\tpPrevVPort->pNext = pVPort;\n\t\tlogWrite(\"VPort added after %p\\n\", pPrevVPort);\n\t}\n\n\t// Palette tag\n#ifdef ACE_USE_AGA_FEATURES\n\tif(pVPort->eFlags & VP_FLAG_AGA) {\n\t\tpVPort->pPalette = memAllocFastClear(sizeof(ULONG) * (1 << pVPort->ubBpp));\n\t\tUWORD *pSrcPalette = (UWORD *)tagGet(pTagList, vaTags, TAG_VPORT_PALETTE_PTR, 0);\n\t\tif(pSrcPalette) {\n\t\t\tUWORD uwPaletteSize = tagGet(pTagList, vaTags, TAG_VPORT_PALETTE_SIZE, 0xFFFF);\n\t\t\tif(uwPaletteSize == 0xFFFF) {\n\t\t\t\tlogWrite(\"WARN: you must specify palette size in TAG_VPORT_PALETTE_SIZE\\n\");\n\t\t\t}\n\t\t\telse if(!uwPaletteSize || uwPaletteSize > 256) {\n\t\t\t\tlogWrite(\"ERR: Wrong palette size: %hu\\n\", uwPaletteSize);\n\t\t\t}\n\t\t\telse {\n\t\t\t\tmemcpy(pVPort->pPalette, pSrcPalette, uwPaletteSize * sizeof(ULONG));\n\t\t\t}\n\t\t}\n\t}\n\telse\n#endif\n\t{\n\t\tpVPort->pPalette = memAllocFastClear(sizeof(UWORD) * 32);\n\t\tUWORD *pSrcPalette = (UWORD *)tagGet(pTagList, vaTags, TAG_VPORT_PALETTE_PTR, 0);\n\t\tif(pSrcPalette) {\n\t\t\tUWORD uwPaletteSize = tagGet(pTagList, vaTags, TAG_VPORT_PALETTE_SIZE, 0xFFFF);\n\t\t\tif(uwPaletteSize == 0xFFFF) {\n\t\t\t\tlogWrite(\"WARN: you must specify palette size in TAG_VPORT_PALETTE_SIZE\\n\");\n\t\t\t}\n\t\t\telse if(!uwPaletteSize || uwPaletteSize > 32) {\n\t\t\t\tlogWrite(\"ERR: Wrong palette size: %hu\\n\", uwPaletteSize);\n\t\t\t}\n\t\t\telse {\n\t\t\t\tmemcpy(pVPort->pPalette, pSrcPalette, uwPaletteSize * sizeof(UWORD));\n\t\t\t}\n\t\t}\n\t}\n\n\tva_end(vaTags);\n\tlogBlockEnd(\"vPortCreate()\");\n\treturn pVPort;\n#endif // AMIGA\nfail:\n\tva_end(vaTags);\n\tlogBlockEnd(\"vPortCreate()\");\n\treturn 0;\n}\n\nvoid vPortDestroy(tVPort *pVPort) {\n\tlogBlockBegin(\"vPortDestroy(pVPort: %p)\", pVPort);\n\ttView *pView;\n\ttVPort *pPrevVPort, *pCurrVPort;\n\n\tpView = pVPort->pView;\n\tlogWrite(\"Parent view: %p\\n\", pView);\n\tpPrevVPort = 0;\n\tpCurrVPort = pView->pFirstVPort;\n\twhile(pCurrVPort) {\n\t\tlogWrite(\"found VP: %p...\", pCurrVPort);\n\t\tif(pCurrVPort == pVPort) {\n\t\t\tlogWrite(\" gotcha!\\n\");\n\n\t\t\t// Remove from list\n\t\t\tif(pPrevVPort) {\n\t\t\t\tpPrevVPort->pNext = pCurrVPort->pNext;\n\t\t\t}\n\t\t\telse {\n\t\t\t\tpView->pFirstVPort = pCurrVPort->pNext;\n\t\t\t}\n\t\t\t--pView->ubVpCount;\n\n\t\t\t// Destroy managers\n\t\t\tlogBlockBegin(\"Destroying managers\");\n\t\t\twhile(pCurrVPort->pFirstManager) {\n\t\t\t\tvPortRmManager(pCurrVPort, pCurrVPort->pFirstManager);\n\t\t\t}\n\t\t\tlogBlockEnd(\"Destroying managers\");\n\n#ifdef ACE_USE_AGA_FEATURES\n\t\t\tif(pVPort->eFlags & VP_FLAG_AGA) {\n\t\t\t\tmemFree(pVPort->pPalette, sizeof(ULONG) * (1 << pVPort->ubBpp));\n\t\t\t}\n\t\t\telse {\n\t\t\t\tmemFree(pVPort->pPalette, sizeof(UWORD) * 32);\n\t\t\t}\n#else\n\t\t\tmemFree(pVPort->pPalette, sizeof(UWORD) * 32);\n#endif\n\n\t\t\tmemFree(pVPort, sizeof(tVPort));\n\t\t\tbreak;\n\t\t}\n\t\telse {\n\t\t\tlogWrite(\"\\n\");\n\t\t}\n\t\tpPrevVPort = pCurrVPort;\n\t\tpCurrVPort = pCurrVPort->pNext;\n\t}\n\tlogBlockEnd(\"vPortDestroy()\");\n}\n\nvoid vPortUpdatePalette(tVPort *pVPort) {\n\t// TODO: If not same palettes on all vports, there are 2 strategies to do them:\n\t// 1) Using the copperlist (copblock/raw copper instructions)\n\t// 2) By using CPU\n\t// 1st approach is better since it will always work, doesn't require any waits\n\t// So the only problem is implementing it using copblocks or raw copperlist.\n\t// Also some viewports which are one after another may use shared pallette, so\n\t// adding palette copper instructions between them is unnecessary.\n\t// I propose following implementation:\n\t// - for quick check, view contains flag VIEW_GLOBAL_PALETTE if all viewports\n\t// use same palette\n\t// - if VIEW_GLOBAL_PALETTE is not found, every vport is checked for\n\t// VPORT_HAS_OWN_PALETTE and if it's present then cop instructions are created\n\t// during vport creation and updated using this fn.\n\t// There is a problem that VPorts may change vertical size and position\n\t// (like expanding HUD to fullscreen like we did in Goblin Villages).\n\t// On copblocks implementing it is somewhat easy, but on raw copperlist\n\t// something clever must be done.\n\tif(pVPort->eFlags & VP_FLAG_HAS_OWN_PALETTE) {\n\t\tlogWrite(\"TODO: implement vPortUpdatePalette!\\n\");\n\t}\n}\n\nvoid vPortWaitForPos(const tVPort *pVPort, UWORD uwPosY, UBYTE isExact) {\n#ifdef AMIGA\n\t// Determine VPort end position\n\tUWORD uwEndPos = pVPort->uwOffsY + uwPosY;\n\tuwEndPos += pVPort->pView->ubPosY; // Addition from DiWStrt\n#if defined(ACE_DEBUG)\n\tUWORD yPos = s_isPAL ? 312 : 272;\n\tif(uwEndPos >= yPos) {\n\t\tlogWrite(\"ERR: vPortWaitForPos - too big wait pos: %04hx (%hu)\\n\", uwEndPos, uwEndPos);\n\t\tlogWrite(\"\\tVPort offs: %hu, pos: %hu\\n\", pVPort->uwOffsY, uwPosY);\n\t}\n#endif\n\n\tif(isExact) {\n\t\t// If current beam pos is on or past end pos, wait for start of next frame\n\t\twhile (getRayPos().bfPosY >= uwEndPos) continue;\n\t}\n\t// If current beam pos is before end pos, wait for it\n\twhile (getRayPos().bfPosY < uwEndPos) continue;\n#endif // AMIGA\n}\n\nvoid vPortWaitUntilEnd(const tVPort *pVPort) {\n\tvPortWaitForPos(pVPort, pVPort->uwHeight, 0);\n}\n\nvoid vPortWaitForEnd(const tVPort *pVPort) {\n\tvPortWaitForPos(pVPort, pVPort->uwHeight, 1);\n}\n\nvoid vPortAddManager(tVPort *pVPort, tVpManager *pVpManager) {\n\t// Check if we have any other manager - if not, attach as head\n\tif(!pVPort->pFirstManager) {\n\t\tpVPort->pFirstManager = pVpManager;\n\t\tlogWrite(\"Manager %p attached to head of VP %p\\n\", pVpManager, pVPort);\n\t\treturn;\n\t}\n\n\t// Check if current manager has lesser priority number than head\n\tif(pVPort->pFirstManager->ubId > pVpManager->ubId) {\n\t\tlogWrite(\n\t\t\t\"Manager %p attached as head of VP %p before %p\\n\",\n\t\t\tpVpManager, pVPort, pVPort->pFirstManager\n\t\t);\n\t\tpVpManager->pNext = pVPort->pFirstManager;\n\t\tpVPort->pFirstManager = pVpManager;\n\t\treturn;\n\t}\n\n\t// Insert before manager of bigger priority number\n\ttVpManager *pVpCurr = pVPort->pFirstManager;\n\twhile(pVpCurr->pNext && pVpCurr->pNext->ubId <= pVpManager->ubId) {\n\t\tif(pVpCurr->ubId <= pVpManager->ubId) {\n\t\t\tpVpCurr = pVpCurr->pNext;\n\t\t}\n\t}\n\tpVpManager->pNext = pVpCurr->pNext;\n\tpVpCurr->pNext = pVpManager;\n\tlogWrite(\n\t\t\"Manager %p attached after manager %p of VP %p\\n\",\n\t\tpVpManager, pVpCurr, pVPort\n\t);\n}\n\nvoid vPortRmManager(tVPort *pVPort, tVpManager *pVpManager) {\n\tif(!pVPort->pFirstManager) {\n\t\tlogWrite(\"ERR: vPort %p has no managers\\n\", pVPort);\n\t\treturn;\n\t}\n\tif(pVPort->pFirstManager == pVpManager) {\n\t\tlogWrite(\"Destroying manager %u @addr: %p\\n\", pVpManager->ubId, pVpManager);\n\t\tpVPort->pFirstManager = pVpManager->pNext;\n\t\tpVpManager->destroy(pVpManager);\n\t\treturn;\n\t}\n\ttVpManager *pParent = pVPort->pFirstManager;\n\twhile(pParent->pNext) {\n\t\tif(pParent->pNext == pVpManager) {\n\t\t\tlogWrite(\"Destroying manager %u @addr: %p\\n\", pVpManager->ubId, pVpManager);\n\t\t\tpParent->pNext = pVpManager->pNext;\n\t\t\tpVpManager->destroy(pVpManager);\n\t\t\treturn;\n\t\t}\n\t}\n\tlogWrite(\"ERR: vPort %p manager %p not found\\n\", pVPort, pVpManager);\n}\n\ntVpManager *vPortGetManager(tVPort *pVPort, UBYTE ubId) {\n\ttVpManager *pManager;\n\n\tpManager = pVPort->pFirstManager;\n\twhile(pManager) {\n\t\tif(pManager->ubId == ubId) {\n\t\t\treturn pManager;\n\t\t}\n\t\tpManager = pManager->pNext;\n\t}\n\treturn 0;\n}\n"
  },
  {
    "path": "src/ace/utils/file.c",
    "content": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at http://mozilla.org/MPL/2.0/. */\n\n#include <ace/utils/file.h>\n#include <stdarg.h>\n#include <ace/managers/system.h>\n#include <ace/managers/log.h>\n\nvoid fileWriteStr(tFile *pFile, const char *szLine) {\n\tif(!pFile) {\n\t\tlogWrite(\"ERR: Null file handle\\n\");\n\t}\n\tfileWrite(pFile, szLine, strlen(szLine));\n}\n\n#if defined(ACE_FILE_USE_ONLY_DISK)\n#include <ace/utils/disk_file_private.h>\n\nvoid fileClose(tFile *pFile) {\n\tdiskFileClose(pFile);\n}\n\nULONG fileRead(tFile *pFile, void *pDest, ULONG ulSize) {\n\treturn diskFileRead(pFile, pDest, ulSize);\n}\n\nULONG fileWrite(tFile *pFile, const void *pSrc, ULONG ulSize) {\n\treturn diskFileWrite(pFile, pSrc, ulSize);\n}\n\nULONG fileSeek(tFile *pFile, LONG lPos, WORD wMode) {\n\treturn diskFileSeek(pFile, lPos, wMode);\n}\n\nULONG fileGetPos(tFile *pFile) {\n\treturn diskFileGetPos(pFile);\n}\n\nULONG fileGetSize(tFile *pFile) {\n\treturn diskFileGetSize(pFile);\n}\n\nUBYTE fileIsEof(tFile *pFile) {\n\treturn diskFileIsEof(pFile);\n}\n\nvoid fileFlush(tFile *pFile) {\n\tdiskFileFlush(pFile);\n}\n\n#else\nvoid fileClose(tFile *pFile) {\n\tlogWrite(\"Closing file %p\\n\", pFile);\n\tif(!pFile) {\n\t\tlogWrite(\"ERR: Null file handle\\n\");\n\t\treturn;\n\t}\n\tpFile->pCallbacks->cbFileClose(pFile->pData);\n\tmemFree(pFile, sizeof(*pFile));\n}\n\nULONG fileRead(tFile *pFile, void *pDest, ULONG ulSize) {\n\tif(!pFile) {\n\t\tlogWrite(\"ERR: Null file handle\\n\");\n\t}\n\tif(!ulSize) {\n\t\tlogWrite(\"ERR: File read size = 0\\n\");\n\t}\n\treturn pFile->pCallbacks->cbFileRead(pFile->pData, pDest, ulSize);\n}\n\nULONG fileWrite(tFile *pFile, const void *pSrc, ULONG ulSize) {\n\tif(!pFile) {\n\t\tlogWrite(\"ERR: Null file handle\\n\");\n\t}\n\treturn pFile->pCallbacks->cbFileWrite(pFile->pData, pSrc, ulSize);\n}\n\nULONG fileSeek(tFile *pFile, LONG lPos, WORD wMode) {\n\tif(!pFile) {\n\t\tlogWrite(\"ERR: Null file handle\\n\");\n\t}\n\treturn pFile->pCallbacks->cbFileSeek(pFile->pData, lPos, wMode);\n}\n\nULONG fileGetPos(tFile *pFile) {\n\tif(!pFile) {\n\t\tlogWrite(\"ERR: Null file handle\\n\");\n\t}\n\treturn pFile->pCallbacks->cbFileGetPos(pFile->pData);\n}\n\nLONG fileGetSize(tFile *pFile) {\n\tif(!pFile) {\n\t\tlogWrite(\"ERR: Null file handle\\n\");\n\t}\n\treturn pFile->pCallbacks->cbFileGetSize(pFile->pData);\n}\n\nUBYTE fileIsEof(tFile *pFile) {\n\tif(!pFile) {\n\t\tlogWrite(\"ERR: Null file handle\\n\");\n\t}\n\treturn pFile->pCallbacks->cbFileIsEof(pFile->pData);\n}\n\nvoid fileFlush(tFile *pFile) {\n\tif(!pFile) {\n\t\tlogWrite(\"ERR: Null file handle\\n\");\n\t}\n\tpFile->pCallbacks->cbFileFlush(pFile->pData);\n}\n#endif\n"
  },
  {
    "path": "src/ace/utils/font.c",
    "content": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at http://mozilla.org/MPL/2.0/. */\n\n#include <proto/graphics.h> // Bartman's compiler needs this\n#include <ace/macros.h>\n#include <ace/managers/system.h>\n#include <ace/utils/font.h>\n#include <ace/utils/disk_file.h>\n\n/* Globals */\n\nstatic tBitMap s_sTmpDest; // Temp bitmap for drawing text on single bitplane\n\n/* Functions */\n\nUBYTE fontGlyphWidth(const tFont *pFont, char c) {\n\tUBYTE ubIdx = (UBYTE)c;\n\treturn pFont->pCharOffsets[ubIdx + 1] - pFont->pCharOffsets[ubIdx];\n}\n\ntFont *fontCreateFromPath(const char *szPath) {\n\treturn fontCreateFromFd(diskFileOpen(szPath, DISK_FILE_MODE_READ, 1));\n}\n\ntFont *fontCreateFromFd(tFile *pFontFile) {\n\n\tlogBlockBegin(\"fontCreateFromFd(pFontFile: %p)\", pFontFile);\n\n\tif (!pFontFile) {\n\t\tlogWrite(\"ERR: Null file handle\\n\");\n\t\tlogBlockEnd(\"fontCreateFromFd()\");\n\t\treturn 0;\n\t}\n\n\ttFont *pFont = (tFont *) memAllocFast(sizeof(tFont));\n\tif (!pFont) {\n\t\tfileClose(pFontFile);\n\t\tlogWrite(\"ERR: Couldn't alloc mem\\n\");\n\t\tlogBlockEnd(\"fontCreateFromFd()\");\n\t\treturn 0;\n\t}\n\n\tfileRead(pFontFile, &pFont->uwWidth, sizeof(UWORD));\n\tfileRead(pFontFile, &pFont->uwHeight, sizeof(UWORD));\n\tfileRead(pFontFile, &pFont->ubChars, sizeof(UBYTE));\n\tlogWrite(\n\t\t\"Addr: %p, data width: %upx, chars: %u, font height: %upx\\n\",\n\t\tpFont, pFont->uwWidth, pFont->ubChars, pFont->uwHeight\n\t);\n\n\tpFont->pCharOffsets = memAllocFast(sizeof(UWORD) * pFont->ubChars);\n\tfileRead(pFontFile, pFont->pCharOffsets, sizeof(UWORD) * pFont->ubChars);\n\n\tpFont->pRawData = bitmapCreate(pFont->uwWidth, pFont->uwHeight, 1, 0);\n#ifdef AMIGA\n\tUWORD uwPlaneByteSize = ((pFont->uwWidth+15)/16) * 2 * pFont->uwHeight;\n\tfileRead(pFontFile, pFont->pRawData->Planes[0], uwPlaneByteSize);\n#else\n\tlogWrite(\"ERR: Unimplemented\\n\");\n\tmemFree(pFont, sizeof(tFont));\n\tfileClose(pFontFile);\n\tlogBlockEnd(\"fontCreateFromFd()\");\n\treturn 0;\n#endif // AMIGA\n\n\tfileClose(pFontFile);\n\tlogBlockEnd(\"fontCreateFromFd()\");\n\treturn pFont;\n}\n\nvoid fontDestroy(tFont *pFont) {\n\tsystemUse();\n\tlogBlockBegin(\"fontDestroy(pFont: %p)\", pFont);\n\tif (pFont) {\n\t\tbitmapDestroy(pFont->pRawData);\n\t\tmemFree(pFont->pCharOffsets, sizeof(UWORD) * pFont->ubChars);\n\t\tmemFree(pFont, sizeof(tFont));\n\t}\n\tlogBlockEnd(\"fontDestroy()\");\n\tsystemUnuse();\n}\n\ntTextBitMap *fontCreateTextBitMap(UWORD uwWidth, UWORD uwHeight) {\n\tsystemUse();\n\tlogBlockBegin(\n\t\t\"fontCreateTextBitMap(uwWidth: %hu, uwHeight: %hu)\", uwWidth, uwHeight\n\t);\n\n\ttTextBitMap *pTextBitMap = memAllocFast(sizeof(*pTextBitMap));\n\tif(!pTextBitMap) {\n\t\tgoto fail;\n\t}\n\n\tpTextBitMap->pBitMap = bitmapCreate(uwWidth, uwHeight, 1, BMF_CLEAR);\n\tif(!pTextBitMap->pBitMap) {\n\t\tgoto fail;\n\t}\n\n\t// Mark pTextBitMap as without any text\n\tpTextBitMap->uwActualWidth = 0;\n\tpTextBitMap->uwActualHeight = 0;\n\tlogBlockEnd(\"fontCreateTextBitmap()\");\n\tsystemUnuse();\n\treturn pTextBitMap;\n\nfail:\n\tif(pTextBitMap) {\n\t\tif(pTextBitMap->pBitMap) {\n\t\t\tbitmapDestroy(pTextBitMap->pBitMap);\n\t\t}\n\t\tmemFree(pTextBitMap, sizeof(*pTextBitMap));\n\t}\n\tlogBlockEnd(\"fontCreateTextBitmap()\");\n\tsystemUnuse();\n\treturn 0;\n}\n\nUBYTE fontTextFitsInTextBitmap(\n\tconst tFont *pFont, const tTextBitMap *pTextBitmap, const char *szText\n) {\n\ttUwCoordYX sBounds = fontMeasureText(pFont, szText);\n\tif(\n\t\tsBounds.uwX <= bitmapGetByteWidth(pTextBitmap->pBitMap) * 8 &&\n\t\tsBounds.uwY <= pTextBitmap->pBitMap->Rows\n\t) {\n\t\treturn 1;\n\t}\n\treturn 0;\n}\n\ntUwCoordYX fontMeasureText(const tFont *pFont, const char *szText) {\n\tUWORD uwWidth = 0, uwHeight = 0, uwMaxWidth = 0;\n\tfor (const char *p = szText; *p; ++p) {\n\t\tif(*p == '\\n') {\n\t\t\tuwHeight += pFont->uwHeight;\n\t\t\tuwWidth = 0;\n\t\t}\n\t\telse {\n\t\t\tUBYTE ubGlyphWidth = fontGlyphWidth(pFont, *p);\n#if defined(ACE_DEBUG)\n\t\t\tif(ubGlyphWidth == 0) {\n\t\t\t\tlogWrite(\n\t\t\t\t\t\"ERR: Missing glyph for char '%c' (code %hhu, 0x%hhX), \"\n\t\t\t\t\t\"pos %ld in string '%s'\\n\", *p, *p, *p, p - szText, szText\n\t\t\t\t);\n\t\t\t}\n#endif\n\t\t\tuwWidth += ubGlyphWidth + 1;\n\t\t\tuwMaxWidth = MAX(uwMaxWidth, uwWidth);\n\t\t}\n\t}\n\tuwHeight += pFont->uwHeight; // Add height of last line\n\ttUwCoordYX sBounds = {.uwX = uwMaxWidth, .uwY = uwHeight};\n\treturn sBounds;\n}\n\ntTextBitMap *fontCreateTextBitMapFromStr(const tFont *pFont, const char *szText) {\n\tlogBlockBegin(\n\t\t\"fontCreateTextBitMapFromStr(pFont: %p, szText: '%s')\", pFont, szText\n\t);\n\ttUwCoordYX sBounds = fontMeasureText(pFont, szText);\n\t// If bitmap is too tight then blitter goes nuts with bltXdat caching when\n\t// going into next line of blit\n\ttTextBitMap *pTextBitMap = fontCreateTextBitMap(\n\t\t(blockCountCeil(sBounds.uwX, 16) + 1) * 16, sBounds.uwY\n\t);\n\tfontFillTextBitMap(pFont, pTextBitMap, szText);\n\tlogBlockEnd(\"fontCreateTextBitMapFromStr()\");\n\treturn pTextBitMap;\n}\n\ntUwCoordYX fontDrawStr1bpp(\n\tconst tFont *pFont, tBitMap *pBitMap, UWORD uwStartX, UWORD uwStartY,\n\tconst char *szText\n) {\n\tUWORD uwX = uwStartX;\n\tUWORD uwY = uwStartY;\n\tUWORD uwBoundX = 0;\n\tfor(const char *p = szText; *p; ++p) {\n\t\tif(*p == '\\n') {\n\t\t\tuwBoundX = MAX(uwBoundX, uwX);\n\t\t\tuwX = uwStartX;\n\t\t\tuwY += pFont->uwHeight;\n\t\t}\n\t\telse {\n\t\t\tUBYTE ubGlyphWidth = fontGlyphWidth(pFont, *p);\n#if defined(ACE_DEBUG)\n\t\t\tif(ubGlyphWidth == 0) {\n\t\t\t\tlogWrite(\n\t\t\t\t\t\"ERR: Missing glyph for char '%c' (code %hhu, 0x%hhX), \"\n\t\t\t\t\t\"pos %ld in string '%s'\\n\", *p, *p, *p, p - szText, szText\n\t\t\t\t);\n\t\t\t\tcontinue;\n\t\t\t}\n#endif\n\t\t\tblitCopy(\n\t\t\t\tpFont->pRawData, pFont->pCharOffsets[(UBYTE)*p], 0, pBitMap, uwX, uwY,\n\t\t\t\tubGlyphWidth, pFont->uwHeight, MINTERM_COOKIE\n\t\t\t);\n\t\t\tuwX += ubGlyphWidth + 1;\n\t\t}\n\t}\n\ttUwCoordYX sBounds = {.uwX = MAX(uwBoundX, uwX), .uwY = uwY + pFont->uwHeight};\n\treturn sBounds;\n}\n\nvoid fontFillTextBitMap(\n\tconst tFont *pFont, tTextBitMap *pTextBitMap, const char *szText\n) {\n\tif(pTextBitMap->uwActualWidth) {\n\t\t// Clear old contents\n\t\t// TODO: we could remove this clear if letter spacing would be\n\t\t// part of glyphs, but it may cause some problems when drawing last letter.\n\t\tblitRect(\n\t\t\tpTextBitMap->pBitMap, 0, 0,\n\t\t\tpTextBitMap->uwActualWidth, pTextBitMap->pBitMap->Rows, 0\n\t\t);\n\t}\n\n#if defined(ACE_DEBUG)\n\tif(!fontTextFitsInTextBitmap(pFont, pTextBitMap, szText)) {\n\t\ttUwCoordYX sNeededDimensions = fontMeasureText(pFont, szText);\n\t\tlogWrite(\n\t\t\t\"ERR: Text '%s' doesn't fit in text bitmap, text needs: %hu,%hu, bitmap size: %hu,%hu\\n\",\n\t\t\tszText, sNeededDimensions.uwX, sNeededDimensions.uwY,\n\t\t\tbitmapGetByteWidth(pTextBitMap->pBitMap) * 8, pTextBitMap->pBitMap->Rows\n\t\t);\n\t\treturn;\n\t}\n#endif\n\n\ttUwCoordYX sBounds = fontDrawStr1bpp(pFont, pTextBitMap->pBitMap, 0, 0, szText);\n\tpTextBitMap->uwActualWidth = sBounds.uwX;\n\tpTextBitMap->uwActualHeight = sBounds.uwY;\n}\n\nvoid fontDestroyTextBitMap(tTextBitMap *pTextBitMap) {\n\tsystemUse();\n\tbitmapDestroy(pTextBitMap->pBitMap);\n\tmemFree(pTextBitMap, sizeof(tTextBitMap));\n\tsystemUnuse();\n}\n\nvoid fontDrawTextBitMap(\n\ttBitMap *pDest, tTextBitMap *pTextBitMap,\n\tUWORD uwX, UWORD uwY, UBYTE ubColor, UBYTE ubFlags\n) {\n#if defined(ACE_DEBUG)\n\tif(!pTextBitMap->uwActualWidth) {\n\t\t// you can usually figure that out and skip this call before even doing fontDrawStr() or fontFillTextBitMap()\n\t\tlogWrite(\"ERR: pTextBitMap %p has text of zero width - do the check beforehand\\n\", pTextBitMap);\n\t\treturn;\n\t}\n#endif\n\n\t// Alignment flags\n\tif (ubFlags & FONT_RIGHT) {\n\t\tuwX -= pTextBitMap->uwActualWidth;\n\t}\n\telse if (ubFlags & FONT_HCENTER) {\n\t\tuwX -= pTextBitMap->uwActualWidth>>1;\n\t}\n\tif(ubFlags & FONT_BOTTOM) {\n\t\tuwY -= pTextBitMap->uwActualHeight;\n\t}\n\telse if(ubFlags & FONT_VCENTER) {\n\t\tuwY -= pTextBitMap->uwActualHeight>>1;\n\t}\n\n\tif(ubFlags & FONT_SHADOW) {\n\t\tfontDrawTextBitMap(pDest, pTextBitMap, uwX, uwY+1, 0, FONT_COOKIE);\n\t}\n\n\t// Helper destination bitmap\n#if defined(AMIGA)\n\ts_sTmpDest.BytesPerRow = pDest->BytesPerRow;\n\ts_sTmpDest.Rows = pDest->Rows;\n\ts_sTmpDest.Depth = 1;\n#else\n#error \"Something is missing here!\"\n#endif\n\n\t// Text-drawing loop\n\tUBYTE isCookie = ubFlags & FONT_COOKIE;\n\tUBYTE isLazy = ubFlags & FONT_LAZY;\n\tUBYTE ubMinterm;\n\tfor (UBYTE i = 0; i != pDest->Depth; ++i) {\n\t\t// Determine minterm for given bitplane\n\t\tif(isCookie) {\n\t\t\tubMinterm = ubColor & 1 ? 0xEA : 0x2A;\n\t\t}\n\t\telse {\n\t\t\tif(ubColor & 1) {\n\t\t\t\tubMinterm = MINTERM_COPY;\n\t\t\t}\n\t\t\telse {\n\t\t\t\tif(isLazy) {\n\t\t\t\t\tubColor >>= 1;\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tubMinterm = 0x00;\n\t\t\t}\n\t\t}\n\n\t\t// Blit on given bitplane\n\t\t// OPTIMIZE: blitCopy does lots of calculations which are essentially the\n\t\t// same for all bitplanes since they share dimensions. Get rid of it.\n\t\ts_sTmpDest.Planes[0] = pDest->Planes[i];\n\t\tblitCopy(\n\t\t\tpTextBitMap->pBitMap, 0, 0, &s_sTmpDest, uwX, uwY,\n\t\t\tpTextBitMap->uwActualWidth, pTextBitMap->uwActualHeight, ubMinterm\n\t\t);\n\t\tubColor >>= 1;\n\t}\n}\n\nvoid fontDrawStr(\n\tconst tFont *pFont, tBitMap *pDest, UWORD uwX, UWORD uwY,\n\tconst char *szText, UBYTE ubColor, UBYTE ubFlags, tTextBitMap *pTextBitMap\n) {\n\tif(!pTextBitMap) {\n\t\tlogWrite(\"ERR: pTextBitMap must be non-null\\n\");\n\t}\n\tfontFillTextBitMap(pFont, pTextBitMap, szText);\n\tfontDrawTextBitMap(pDest, pTextBitMap, uwX, uwY, ubColor, ubFlags);\n}\n"
  },
  {
    "path": "src/ace/utils/pak_file.c",
    "content": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at http://mozilla.org/MPL/2.0/. */\n\n#include <ace/utils/pak_file.h>\n#include <string.h>\n#include <ace/utils/disk_file.h>\n#include <ace/managers/memory.h>\n#include <ace/managers/log.h>\n\n#if !defined(ACE_FILE_USE_ONLY_DISK)\n#define ADLER32_MODULO 65521\n\ntypedef UBYTE (*tCbCompressReadByte)(UBYTE *pOut, void *pData);\n\ntypedef enum tCompressUnpackStateKind {\n\tCOMPRESS_UNPACK_STATE_KIND_READ_CTL,\n\tCOMPRESS_UNPACK_STATE_KIND_PROCESS_CTL_BIT,\n\tCOMPRESS_UNPACK_STATE_KIND_END_CTL,\n\tCOMPRESS_UNPACK_STATE_KIND_WRITE_RLE,\n\tCOMPRESS_UNPACK_STATE_KIND_DONE,\n} tCompressUnpackStateKind;\n\n#define UNPACKER_CTL_BITS 8\n#define UNPACKER_RLE_CTL_BYTES 2\n#define UNPACKER_RLE_MAX_LENGTH (15 + 3)\n#define UNPACKER_PACKED_BUFFER_SIZE (UNPACKER_CTL_BITS * UNPACKER_RLE_CTL_BYTES + (UNPACKER_CTL_BITS / 8))\n#define UNPACKER_UNPACKED_BUFFER_SIZE (UNPACKER_CTL_BITS * UNPACKER_RLE_MAX_LENGTH)\n\ntypedef struct tCompressUnpacker {\n\tvoid *pSubfileData;\n\tULONG ulCompressedSize;\n\tULONG ulUncompressedSize;\n\tULONG ulUnpackedCount;\n\tUWORD uwLookupPos;\n\n\tUBYTE ubUnpackedChunkPos;\n\tUBYTE ubUnpackedChunkSize;\n\tUBYTE *pPackedCurrent;\n\tUBYTE pLookup[0x1000];\n\tUBYTE pUnpacked[UNPACKER_UNPACKED_BUFFER_SIZE];\n\tUBYTE pPacked[UNPACKER_PACKED_BUFFER_SIZE];\n} tCompressUnpacker;\n\ntypedef struct tPakFileSubfileData {\n\ttPakFile *pPak;\n\ttPakFileEntry *pEntry;\n\tULONG ulPos;\n} tPakFileSubfileData;\n\ntypedef struct tPakFileCompressedData {\n\ttCompressUnpacker sUnpacker;\n\ttFile *pSubfile;\n} tPakFileCompressedData;\n\nstatic void pakSubfileClose(void *pData);\nstatic ULONG pakSubfileRead(void *pData, void *pDest, ULONG ulSize);\nstatic ULONG pakSubfileWrite(UNUSED_ARG void *pData, UNUSED_ARG const void *pSrc, UNUSED_ARG ULONG ulSize);\nstatic ULONG pakSubfileSeek(void *pData, LONG lPos, WORD wMode);\nstatic ULONG pakSubfileGetPos(void *pData);\nstatic ULONG pakSubfileGetSize(void *pData);\nstatic UBYTE pakSubfileIsEof(void *pData);\nstatic void pakSubfileFlush(UNUSED_ARG void *pData);\n\nstatic void pakCompressedClose(void *pData);\nstatic ULONG pakCompressedRead(void *pData, void *pDest, ULONG ulSize);\nstatic ULONG pakCompressedWrite(UNUSED_ARG void *pData, UNUSED_ARG const void *pSrc, UNUSED_ARG ULONG ulSize);\nstatic ULONG pakCompressedSeek(void *pData, LONG lPos, WORD wMode);\nstatic ULONG pakCompressedGetPos(void *pData);\nstatic ULONG pakCompressedGetSize(void *pData);\nstatic UBYTE pakCompressedIsEof(void *pData);\nstatic void pakCompressedFlush(UNUSED_ARG void *pData);\n\nstatic const tFileCallbacks s_sPakSubfileCallbacks = {\n\t.cbFileClose = pakSubfileClose,\n\t.cbFileRead = pakSubfileRead,\n\t.cbFileWrite = pakSubfileWrite,\n\t.cbFileSeek = pakSubfileSeek,\n\t.cbFileGetPos = pakSubfileGetPos,\n\t.cbFileGetSize = pakSubfileGetSize,\n\t.cbFileIsEof = pakSubfileIsEof,\n\t.cbFileFlush = pakSubfileFlush,\n};\n\nstatic const tFileCallbacks s_sPakCompressedCallbacks = {\n\t.cbFileClose = pakCompressedClose,\n\t.cbFileRead = pakCompressedRead,\n\t.cbFileWrite = pakCompressedWrite,\n\t.cbFileSeek = pakCompressedSeek,\n\t.cbFileGetPos = pakCompressedGetPos,\n\t.cbFileGetSize = pakCompressedGetSize,\n\t.cbFileIsEof = pakCompressedIsEof,\n\t.cbFileFlush = pakCompressedFlush,\n};\n\n//------------------------------------------------------------------ PRIVATE FNS\n\nvoid compressUnpackerInit(\n\ttCompressUnpacker *pUnpacker, ULONG ulCompressedSize, size_t ulUncompressedSize,\n\tvoid *pSubfileData\n) {\n\tpUnpacker->ulUnpackedCount = 0;\n\tpUnpacker->uwLookupPos = 0;\n\tpUnpacker->ubUnpackedChunkPos = 0;\n\tpUnpacker->ubUnpackedChunkSize = 0;\n\n\tpUnpacker->ulCompressedSize = ulCompressedSize;\n\tpUnpacker->ulUncompressedSize = ulUncompressedSize;\n\tpUnpacker->pSubfileData = pSubfileData;\n\tpUnpacker->pPackedCurrent = &pUnpacker->pPacked[UNPACKER_PACKED_BUFFER_SIZE];\n}\n\nstatic void rleTableWrite(UBYTE *pTable, UWORD *pPos, UBYTE ubData) {\n\tpTable[*pPos] = ubData;\n\t(*pPos)++;\n\t(*pPos) &= 0xfff;\n}\n\nstatic UBYTE rleTableRead(const UBYTE *pTable, UWORD *pPos) {\n\tUBYTE ubData;\n\n\tubData = pTable[*pPos];\n\t(*pPos)++;\n\t(*pPos) &= 0xfff;\n\n\treturn ubData;\n}\n\nstatic WORD compressUnpackerReadNext(tCompressUnpacker *pUnpacker, UBYTE *pOut, ULONG ulReadSize) {\n\tUBYTE ubReadSize = MIN((UBYTE)(pUnpacker->ubUnpackedChunkSize - pUnpacker->ubUnpackedChunkPos), ulReadSize);\n\tUBYTE ubReadPos = pUnpacker->ubUnpackedChunkPos;\n\tfor(UWORD i = 0; i < ubReadSize; ++i) {\n\t\t*(pOut++) = pUnpacker->pUnpacked[ubReadPos++];\n\t}\n\tif(ubReadSize) {\n\t\tpUnpacker->ulUnpackedCount += ubReadSize;\n\t\tpUnpacker->ubUnpackedChunkPos = ubReadPos;\n\t\treturn ubReadSize;\n\t}\n\n\tif(pUnpacker->ulUnpackedCount >= pUnpacker->ulUncompressedSize) {\n\t\treturn -1;\n\t}\n\n\t// Move unparsed bytes to beginning, fill up the packed buffer\n\tUBYTE *pPackedCurrent = pUnpacker->pPackedCurrent;\n\tUBYTE *pDst = &pUnpacker->pPacked[0];\n\tUBYTE *pEnd = &pUnpacker->pPacked[UNPACKER_PACKED_BUFFER_SIZE];\n\twhile(pPackedCurrent < pEnd) {\n\t\t*(pDst++) = *(pPackedCurrent++);\n\t}\n\n\t// Read might return 0 if only unparsed bytes are remaining to process\n\tpEnd = pDst + pakSubfileRead(pUnpacker->pSubfileData, pDst, pEnd - pDst);\n\n\t// Decode next portion of data\n\tpPackedCurrent = &pUnpacker->pPacked[0];\n\tUBYTE ubCtl = *(pPackedCurrent++);\n\tUBYTE ubBits = UNPACKER_CTL_BITS;\n\tUBYTE *pUnpacked = pUnpacker->pUnpacked;\n\n\twhile(ubBits--) {\n\t\tif(ubCtl & 1) {\n\t\t\tUBYTE ubRawByte = *(pPackedCurrent++);\n\t\t\trleTableWrite(pUnpacker->pLookup, &pUnpacker->uwLookupPos, ubRawByte);\n\t\t\t*(pUnpacked++) = ubRawByte;\n\t\t}\n\t\telse {\n\t\t\tUBYTE ubHi = *(pPackedCurrent++);\n\t\t\tUBYTE ubLo = *(pPackedCurrent++);\n\t\t\tULONG ulRleCtl = (ubHi << 8) | ubLo;\n\n\t\t\tUWORD uwRleLength = (ulRleCtl & 0xF) + 3;\n\t\t\tUWORD uwRlePos = ulRleCtl >> 4;\n\t\t\twhile(uwRleLength--) {\n\t\t\t\tUBYTE ubRawByte = rleTableRead(pUnpacker->pLookup, &uwRlePos);\n\t\t\t\trleTableWrite(pUnpacker->pLookup, &pUnpacker->uwLookupPos, ubRawByte);\n\t\t\t\t*(pUnpacked++) = ubRawByte;\n\t\t\t}\n\t\t}\n\t\tif(pPackedCurrent == pEnd) {\n\t\t\t// TODO: optimize packing so that there are always 8 bits to process\n\t\t\t// at the end - would allow removing this cmp.\n\t\t\t// Might be impossible for some files? E.g. one with no RLE sequences -\n\t\t\t// perhaps don't ever use compression for them.\n\t\t\tbreak;\n\t\t}\n\t\tubCtl >>= 1;\n\t}\n\tpUnpacker->ubUnpackedChunkSize = pUnpacked - pUnpacker->pUnpacked;\n\tpUnpacker->pPackedCurrent = pPackedCurrent;\n\tpUnpacker->ubUnpackedChunkPos = 0;\n\treturn 0;\n}\n\nstatic ULONG adler32Buffer(const UBYTE *pData, ULONG ulDataSize) {\n\tULONG a = 1, b = 0;\n\tfor(ULONG i = 0; i < ulDataSize; ++i) {\n\t\ta += pData[i];\n\t\tif(a >= ADLER32_MODULO) {\n\t\t\ta -= ADLER32_MODULO;\n\t\t}\n\t\tb += a;\n\t\tif(b >= ADLER32_MODULO) {\n\t\t\tb -= ADLER32_MODULO;\n\t\t}\n\t}\n\treturn (b << 16) | a;\n}\n\nstatic void pakSubfileClose(void *pData) {\n\ttPakFileSubfileData *pSubfileData = (tPakFileSubfileData*)pData;\n\n\tmemFree(pSubfileData, sizeof(*pSubfileData));\n}\n\nstatic ULONG pakSubfileRead(void *pData, void *pDest, ULONG ulSize) {\n\ttPakFileSubfileData *pSubfileData = (tPakFileSubfileData*)pData;\n\ttPakFile *pPak = pSubfileData->pPak;\n\n\tif(pPak->pPrevReadSubfile != pSubfileData) {\n\t\t// Other file was accessed or there was a seek recently - seek back\n\t\tfileSeek(\n\t\t\tpPak->pFile,\n\t\t\tpSubfileData->pEntry->ulOffs + pSubfileData->ulPos,\n\t\t\tFILE_SEEK_SET\n\t\t);\n\t\tpPak->pPrevReadSubfile = pSubfileData;\n\t}\n\n\t// Enforce upper bound of the file size\n\tULONG ulRemaining = pSubfileData->pEntry->ulSizeData - pSubfileData->ulPos;\n\tif(ulRemaining < ulSize) {\n\t\tulSize = ulRemaining;\n\t\tif(!ulSize) {\n\t\t\treturn 0;\n\t\t}\n\t}\n\n\tULONG ulRead = fileRead(pPak->pFile, pDest, ulSize);\n\tpSubfileData->ulPos += ulRead;\n\treturn ulRead;\n}\n\nstatic ULONG pakSubfileWrite(\n\tUNUSED_ARG void *pData, UNUSED_ARG const void *pSrc, UNUSED_ARG ULONG ulSize\n) {\n\tlogWrite(\"ERR: Unsupported: pakSubfileWrite()\\n\");\n\treturn 0;\n}\n\nstatic ULONG pakSubfileSeek(void *pData, LONG lPos, WORD wMode) {\n\ttPakFileSubfileData *pSubfileData = (tPakFileSubfileData*)pData;\n\tULONG ulSizeData = pSubfileData->pEntry->ulSizeData;\n\n\tif(wMode == FILE_SEEK_SET) {\n\t\tpSubfileData->ulPos = lPos;\n\t}\n\telse if(wMode == FILE_SEEK_CURRENT) {\n\t\tpSubfileData->ulPos += lPos;\n\t}\n\telse if(wMode == FILE_SEEK_END) {\n\t\tpSubfileData->ulPos = ulSizeData + lPos;\n\t}\n\tpSubfileData->pPak->pPrevReadSubfile = 0; // Invalidate cache\n\n\tif(pSubfileData->ulPos > ulSizeData) {\n\t\tlogWrite(\"ERR: Seek position %lu out of range %lu for pakFile data %p\\n\",\n\t\t\tpSubfileData->ulPos, ulSizeData, pSubfileData\n\t\t);\n\t\tpSubfileData->ulPos = ulSizeData;\n\t\treturn 0;\n\t}\n\treturn 1;\n}\n\nstatic ULONG pakSubfileGetPos(void *pData) {\n\ttPakFileSubfileData *pSubfileData = (tPakFileSubfileData*)pData;\n\n\treturn pSubfileData->ulPos;\n}\n\nstatic ULONG pakSubfileGetSize(void *pData) {\n\ttPakFileSubfileData *pSubfileData = (tPakFileSubfileData*)pData;\n\n\treturn pSubfileData->pEntry->ulSizeData;\n}\n\nstatic UBYTE pakSubfileIsEof(void *pData) {\n\ttPakFileSubfileData *pSubfileData = (tPakFileSubfileData*)pData;\n\n\treturn pSubfileData->ulPos >= pakSubfileGetSize(pData);\n}\n\nstatic void pakSubfileFlush(UNUSED_ARG void *pData) {\n\t// no-op\n}\n\nstatic void pakCompressedClose(void *pData) {\n\ttPakFileCompressedData *pCompressedData = (tPakFileCompressedData*)pData;\n\tfileClose(pCompressedData->pSubfile);\n\tmemFree(pCompressedData, sizeof(*pCompressedData));\n}\n\nstatic ULONG pakCompressedRead(void *pData, void *pDest, ULONG ulSize) {\n\ttPakFileCompressedData *pCompressedData = (tPakFileCompressedData*)pData;\n\ttCompressUnpacker *pUnpacker = &pCompressedData->sUnpacker;\n\tULONG ulRemaining = ulSize;\n\tUBYTE *pDestByte = pDest;\n\n\twhile(ulRemaining) {\n\t\tWORD wRead = compressUnpackerReadNext(pUnpacker, pDestByte, ulRemaining);\n\t\tif(wRead < 0) {\n\t\t\tbreak;\n\t\t}\n\t\tpDestByte += wRead;\n\t\tulRemaining -= wRead;\n\t}\n\treturn ulSize - ulRemaining;\n}\n\nstatic ULONG pakCompressedWrite(\n\tUNUSED_ARG void *pData, UNUSED_ARG const void *pSrc, UNUSED_ARG ULONG ulSize\n) {\n\tlogWrite(\"ERR: Unsupported: pakCompressedWrite()\\n\");\n\treturn 0;\n}\n\nstatic ULONG pakCompressedSeek(void *pData, LONG lPos, WORD wMode) {\n\ttPakFileCompressedData *pCompressedData = (tPakFileCompressedData*)pData;\n\t// seek forward: unpack some bytes to void\n\t// seek backward: restart unpacker and unpack some bytes to void\n\n\tULONG ulPosCurrent = pCompressedData->sUnpacker.ulUnpackedCount;\n\tULONG ulPosTarget;\n\tULONG ulFileSize = pCompressedData->sUnpacker.ulUncompressedSize;\n\tif(wMode == SEEK_CUR) {\n\t\tulPosTarget = ulPosCurrent + lPos;\n\t}\n\telse if(wMode == SEEK_END) {\n\t\tulPosTarget = ulFileSize + lPos;\n\t}\n\telse { // (wMode == SEEK_SET)\n\t\tulPosTarget = lPos;\n\t}\n\n\tif(ulPosTarget > pCompressedData->sUnpacker.ulUncompressedSize) {\n\t\tlogWrite(\n\t\t\t\"ERR: Seek position %lu out of range %lu for compressed pakFile\\n\",\n\t\t\tulPosTarget, pCompressedData->sUnpacker.ulUncompressedSize\n\t\t);\n\t\treturn 0;\n\t}\n\n\tif(ulPosTarget == ulFileSize) {\n\t\tpCompressedData->sUnpacker.ulUnpackedCount = ulFileSize;\n\t\treturn 1;\n\t}\n\n\tif(ulPosTarget < ulPosCurrent) {\n\t\tlogWrite(\"WARN: Huge performance penalty due to going back in compressed file. Do you *really* need to do it?\\n\");\n\t\tcompressUnpackerInit(\n\t\t\t&pCompressedData->sUnpacker,\n\t\t\tpCompressedData->sUnpacker.ulCompressedSize,\n\t\t\tpCompressedData->sUnpacker.ulUncompressedSize,\n\t\t\tpCompressedData->pSubfile->pData\n\t\t);\n\t}\n\n\twhile(pCompressedData->sUnpacker.ulUnpackedCount < ulPosTarget) {\n\t\tUBYTE ubDummy;\n\t\tpakCompressedRead(pData, &ubDummy, 1);\n\t}\n\n\treturn 1;\n}\n\nstatic ULONG pakCompressedGetPos(void *pData) {\n\ttPakFileCompressedData *pCompressedData = (tPakFileCompressedData*)pData;\n\treturn pCompressedData->sUnpacker.ulUnpackedCount;\n}\n\nstatic ULONG pakCompressedGetSize(void *pData) {\n\ttPakFileCompressedData *pCompressedData = (tPakFileCompressedData*)pData;\n\treturn pCompressedData->sUnpacker.ulUncompressedSize;\n}\n\nstatic UBYTE pakCompressedIsEof(void *pData) {\n\ttPakFileCompressedData *pCompressedData = (tPakFileCompressedData*)pData;\n\treturn pCompressedData->sUnpacker.ulUnpackedCount >= pCompressedData->sUnpacker.ulUncompressedSize;\n}\n\nstatic void pakCompressedFlush(UNUSED_ARG void *pData) {\n\t// no-op\n}\n\nstatic UWORD pakFileGetFileIndex(const tPakFile *pPakFile, const char *szPath) {\n\tULONG ulPathHash = adler32Buffer((UBYTE*)szPath, strlen(szPath)); // TODO: Calculate path hash\n\tfor(UWORD i = 0; i < pPakFile->uwFileCount; ++i) {\n\t\tif(pPakFile->pEntries[i].ulPathChecksum == ulPathHash) {\n\t\t\treturn i;\n\t\t}\n\t}\n\treturn UWORD_MAX;\n}\n\n//------------------------------------------------------------------- PUBLIC FNS\n\ntPakFile *pakFileOpen(const char *szPath, UBYTE isUninterrupted) {\n\tlogBlockBegin(\"pakFileOpen(szPath: '%s')\", szPath);\n\ttFile *pMainFile = diskFileOpen(szPath, DISK_FILE_MODE_READ, isUninterrupted);\n\tif(!pMainFile) {\n\t\tlogBlockEnd(\"pakFileOpen()\");\n\t\treturn 0;\n\t}\n\n\ttPakFile *pPakFile = memAllocFast(sizeof(*pPakFile));\n\tpPakFile->pFile = pMainFile;\n\tpPakFile->pPrevReadSubfile = 0;\n\tfileRead(pMainFile, &pPakFile->uwFileCount, sizeof(pPakFile->uwFileCount));\n\tpPakFile->pEntries = memAllocFast(sizeof(pPakFile->pEntries[0]) * pPakFile->uwFileCount);\n\tfor(UWORD i = 0; i < pPakFile->uwFileCount; ++i) {\n\t\tfileRead(pMainFile, &pPakFile->pEntries[i].ulPathChecksum, sizeof(pPakFile->pEntries[i].ulPathChecksum));\n\t\tfileRead(pMainFile, &pPakFile->pEntries[i].ulOffs, sizeof(pPakFile->pEntries[i].ulOffs));\n\t\tfileRead(pMainFile, &pPakFile->pEntries[i].ulSizeUncompressed, sizeof(pPakFile->pEntries[i].ulSizeUncompressed));\n\t\tfileRead(pMainFile, &pPakFile->pEntries[i].ulSizeData, sizeof(pPakFile->pEntries[i].ulSizeData));\n\t}\n\tlogWrite(\"Pak file: %p, file count: %hu\\n\", pPakFile, pPakFile->uwFileCount);\n\n\tlogBlockEnd(\"pakFileOpen()\");\n\treturn pPakFile;\n}\n\nvoid pakFileClose(tPakFile *pPakFile) {\n\tlogBlockBegin(\"pakFileClose(pPakFile: %p)\", pPakFile);\n\tfileClose(pPakFile->pFile);\n\tmemFree(pPakFile->pEntries, sizeof(pPakFile->pEntries[0]) * pPakFile->uwFileCount);\n\tmemFree(pPakFile, sizeof(*pPakFile));\n\tlogBlockEnd(\"pakFileClose()\");\n}\n\ntFile *pakFileGetFile(tPakFile *pPakFile, const char *szInternalPath) {\n\tlogBlockBegin(\"pakFileGetFile(pPakFile: %p, szInternalPath: '%s')\", pPakFile, szInternalPath);\n\tUWORD uwFileIndex = pakFileGetFileIndex(pPakFile, szInternalPath);\n\tif(uwFileIndex == UWORD_MAX) {\n\t\tlogWrite(\"ERR: Can't find subfile in pakfile\\n\");\n\t\tlogBlockEnd(\"pakFileGetFile()\");\n\t\treturn 0;\n\t}\n\tUBYTE isCompressed = pPakFile->pEntries[uwFileIndex].ulSizeUncompressed != pPakFile->pEntries[uwFileIndex].ulSizeData;\n\tlogWrite(\n\t\t\"Subfile index: %hu, offset: %lu, size: %lu, compressed: %hhu\\n\",\n\t\tuwFileIndex,\n\t\tpPakFile->pEntries[uwFileIndex].ulOffs,\n\t\tpPakFile->pEntries[uwFileIndex].ulSizeUncompressed,\n\t\tisCompressed\n\t);\n\n\t// Create tFile, fill subfileData\n\ttPakFileSubfileData *pSubfileData = memAllocFast(sizeof(*pSubfileData));\n\tpSubfileData->pPak = pPakFile;\n\tpSubfileData->pEntry = &pPakFile->pEntries[uwFileIndex];\n\tpSubfileData->ulPos = 0;\n\t// Prevent reading from same place if pSubfileData gets mem from recently closed file\n\tpPakFile->pPrevReadSubfile = 0;\n\n\ttFile *pFile = memAllocFast(sizeof(*pFile));\n\tpFile->pCallbacks = &s_sPakSubfileCallbacks;\n\tpFile->pData = pSubfileData;\n\n\tif(isCompressed) {\n\t\ttPakFileCompressedData *pCompressedData = memAllocFast(sizeof(*pCompressedData));\n\t\tpCompressedData->pSubfile = pFile;\n\t\tcompressUnpackerInit(\n\t\t\t&pCompressedData->sUnpacker,\n\t\t\tpPakFile->pEntries[uwFileIndex].ulSizeData,\n\t\t\tpPakFile->pEntries[uwFileIndex].ulSizeUncompressed,\n\t\t\tpCompressedData->pSubfile->pData\n\t\t);\n\n\t\ttFile *pCompressedFile = memAllocFast(sizeof(*pCompressedFile));\n\t\tpCompressedFile->pCallbacks = &s_sPakCompressedCallbacks;\n\t\tpCompressedFile->pData = pCompressedData;\n\t\tpFile = pCompressedFile;\n\t}\n\n\tlogBlockEnd(\"pakFileGetFile()\");\n\treturn pFile;\n}\n\n#endif\n"
  },
  {
    "path": "src/ace/utils/palette.c",
    "content": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at http://mozilla.org/MPL/2.0/. */\n\n#include <ace/utils/palette.h>\n#include <ace/macros.h>\n#include <ace/managers/blit.h>\n#include <ace/managers/log.h>\n#include <ace/managers/memory.h>\n#include <ace/utils/bitmap.h>\n#include <ace/utils/disk_file.h>\n#include <ace/utils/endian.h>\n\n/** .plt v2 first-byte values (wire format; not part of public API). */\nenum { PLT_V2_ECS = 0, PLT_V2_AGA = 1 };\n\nvoid paletteLoadFromPath(const char *szPath, UWORD *pPalette, UWORD uwMaxLength) {\n\treturn paletteLoadFromFd(diskFileOpen(szPath, DISK_FILE_MODE_READ, 1), pPalette, uwMaxLength);\n}\n\nvoid paletteLoadFromFd(tFile *pFile, UWORD *pPalette, UWORD uwMaxLength) {\n\tlogBlockBegin(\n\t\t\"paletteLoadFromFd(pFile: %p, pPalette: %p, uwMaxLength: %hu)\",\n\t\tpFile, pPalette, uwMaxLength\n\t);\n\n\tif(!pFile) {\n\t\tlogWrite(\"ERR: Null file handle\\n\");\n\t\tlogBlockEnd(\"paletteLoadFromFd()\");\n\t\treturn;\n\t}\n\n\tUBYTE ubFirst;\n\tfileRead(pFile, &ubFirst, sizeof(UBYTE));\n\n\tif(ubFirst > 1) {\n#ifdef ACE_DEBUG\n\t\tlogWrite(\n\t\t\t\"ERR: Unsupported legacy .plt (v1); first byte 0x%02x. \"\n\t\t\t\"Reconvert the asset with palette_conv.\\n\",\n\t\t\tubFirst\n\t\t);\n#endif\n\t\tfileClose(pFile);\n\t\tlogBlockEnd(\"paletteLoadFromFd()\");\n\t\treturn;\n\t}\n\n\tUWORD uwNumInFile;\n\tfileRead(pFile, &uwNumInFile, sizeof(UWORD));\n\tuwNumInFile = endianBig16(uwNumInFile);\n\tUWORD uwColorsRead = MIN(uwNumInFile, uwMaxLength);\n\n\tlogWrite(\n\t\t\".plt v2 mode %hhu, file colors: %hu, reading: %hu\\n\",\n\t\tubFirst, uwNumInFile, uwColorsRead\n\t);\n\n\tif(ubFirst == PLT_V2_ECS) {\n\t\tfileRead(pFile, pPalette, sizeof(UWORD) * uwColorsRead);\n\t}\n\telse {\n\t\tfileRead(pFile, pPalette, sizeof(ULONG) * uwColorsRead);\n\t}\n\n\tfileClose(pFile);\n\n\tlogBlockEnd(\"paletteLoadFromFd()\");\n}\n\n/**\n * Writes ECS/OCS v2 .plt (e.g. from in-game tooling or external conversion pipelines\n * such as the Lands of Lore asset converter).\n */\nvoid paletteSaveOcs(const UWORD *pPalette, UWORD uwColorCnt, char *szPath) {\n\tlogBlockBegin(\n\t\t\"paletteSaveOcs(pPalette: %p, uwColorCnt: %hu, szPath: '%s')\",\n\t\tpPalette, uwColorCnt, szPath\n\t);\n\n\ttFile *pFile = diskFileOpen(szPath, DISK_FILE_MODE_WRITE, 1);\n\tif(!pFile) {\n\t\tlogWrite(\"ERR: Can't write file\\n\");\n\t\tlogBlockEnd(\"paletteSaveOcs()\");\n\t\treturn;\n\t}\n\n\tUBYTE ubSentinel = PLT_V2_ECS;\n\n\tfileWrite(pFile, &ubSentinel, sizeof(UBYTE));\n\t{\n\t\tUWORD uwWire = endianBig16(uwColorCnt);\n\t\tfileWrite(pFile, &uwWire, sizeof(UWORD));\n\t}\n\tfileWrite(pFile, pPalette, sizeof(UWORD) * uwColorCnt);\n\tfileClose(pFile);\n\n\tlogBlockEnd(\"paletteSaveOcs()\");\n}\n\n#ifdef ACE_USE_AGA_FEATURES\nvoid paletteSaveAga(const ULONG *pPalette, UWORD uwColorCnt, char *szPath) {\n\tlogBlockBegin(\n\t\t\"paletteSaveAga(pPalette: %p, uwColorCnt: %hu, szPath: '%s')\",\n\t\tpPalette, uwColorCnt, szPath\n\t);\n\n\ttFile *pFile = diskFileOpen(szPath, DISK_FILE_MODE_WRITE, 1);\n\tif(!pFile) {\n\t\tlogWrite(\"ERR: Can't write file\\n\");\n\t\tlogBlockEnd(\"paletteSaveAga()\");\n\t\treturn;\n\t}\n\n\tUBYTE ubSentinel = PLT_V2_AGA;\n\n\tfileWrite(pFile, &ubSentinel, sizeof(UBYTE));\n\t{\n\t\tUWORD uwWire = endianBig16(uwColorCnt);\n\t\tfileWrite(pFile, &uwWire, sizeof(UWORD));\n\t}\n\n\tfor(UWORD i = 0; i < uwColorCnt; ++i) {\n\t\tULONG ul = pPalette[i];\n\t\tUBYTE ubA = 0;\n\t\tUBYTE ubR = (ul >> 16) & 0xFF;\n\t\tUBYTE ubG = (ul >> 8) & 0xFF;\n\t\tUBYTE ubB = ul & 0xFF;\n\n\t\tfileWrite(pFile, &ubA, sizeof(UBYTE));\n\t\tfileWrite(pFile, &ubR, sizeof(UBYTE));\n\t\tfileWrite(pFile, &ubG, sizeof(UBYTE));\n\t\tfileWrite(pFile, &ubB, sizeof(UBYTE));\n\t}\n\n\tfileClose(pFile);\n\n\tlogBlockEnd(\"paletteSaveAga()\");\n}\n#endif\n\nvoid paletteDimOcs(\n\tUWORD *pSource, volatile UWORD *pDest, UWORD uwColorCount, UBYTE ubLevel\n) {\n\tfor(UWORD c = 0; c < uwColorCount; ++c) {\n\t\tpDest[c] = paletteColorDimOcs(pSource[c], ubLevel);\n\t}\n}\n\n#ifdef ACE_USE_AGA_FEATURES\nvoid paletteDimAga(ULONG *pSource, volatile ULONG *pDest, UWORD uwColorCount, UBYTE ubLevel) {\n\tfor(UWORD c = 0; c < uwColorCount; ++c) {\n\t\tpDest[c] = paletteColorDimAga(pSource[c], ubLevel);\n\t}\n}\n#endif\n\nUWORD paletteColorDimOcs(UWORD uwFullColor, UBYTE ubLevel) {\n\tUBYTE r, g, b;\n\n\tr = (uwFullColor >> 8) & 0xF;\n\tg = (uwFullColor >> 4) & 0xF;\n\tb = (uwFullColor)      & 0xF;\n\n\t// Dim color\n\tr = ((r * ubLevel)/15) & 0xF;\n\tg = ((g * ubLevel)/15) & 0xF;\n\tb = ((b * ubLevel)/15) & 0xF;\n\n\t// Output\n\treturn (r << 8) | (g << 4) | b;\n}\n\n#ifdef ACE_USE_AGA_FEATURES\nULONG paletteColorDimAga(ULONG ulFullColor, UBYTE ubLevel) {\n\tUBYTE r, g, b;\n\n\tr = (ulFullColor >> 16) & 0xFF;\n\tg = (ulFullColor >> 8) & 0xFF;\n\tb = (ulFullColor)      & 0xFF;\n\n\t// Dim color\n\tr = ((r * ubLevel)/255) & 0xFF;\n\tg = ((g * ubLevel)/255) & 0xFF;\n\tb = ((b * ubLevel)/255) & 0xFF;\n\n\t// Output\n\treturn (r << 16) | (g << 8) | b;\n}\n#endif\n\nUWORD paletteColorMixOcs(\n\tUWORD uwColorPrimary, UWORD uwColorSecondary, UBYTE ubLevel\n) {\n\tUBYTE r1, g1, b1;\n\tUBYTE r2, g2, b2;\n\n\tr1 = (uwColorPrimary >> 8) & 0xF;\n\tg1 = (uwColorPrimary >> 4) & 0xF;\n\tb1 = (uwColorPrimary)      & 0xF;\n\tr2 = (uwColorSecondary >> 8) & 0xF;\n\tg2 = (uwColorSecondary >> 4) & 0xF;\n\tb2 = (uwColorSecondary)      & 0xF;\n\n\t// Dim color\n\tr1 = ((r1 * ubLevel + (r2 * (0xF - ubLevel)))/15) & 0xF;\n\tg1 = ((g1 * ubLevel + (g2 * (0xF - ubLevel)))/15) & 0xF;\n\tb1 = ((b1 * ubLevel + (b2 * (0xF - ubLevel)))/15) & 0xF;\n\n\t// Output\n\treturn (r1 << 8) | (g1 << 4) | b1;\n}\n\n#ifdef ACE_USE_AGA_FEATURES\nULONG paletteColorMixAga(ULONG ulColorPrimary, ULONG ulColorSecondary, UBYTE ubLevel) {\n\tULONG r1, g1, b1;\n\tULONG r2, g2, b2;\n\n\tr1 = (ulColorPrimary >> 16) & 0xFF;\n\tg1 = (ulColorPrimary >> 8) & 0xFF;\n\tb1 = (ulColorPrimary) & 0xFF;\n\tr2 = (ulColorSecondary >> 16) & 0xFF;\n\tg2 = (ulColorSecondary >> 8) & 0xFF;\n\tb2 = (ulColorSecondary) & 0xFF;\n\n\tr1 = ((r1 * ubLevel + (r2 * (255 - ubLevel)))/255) & 0xFF;\n\tg1 = ((g1 * ubLevel + (g2 * (255 - ubLevel)))/255) & 0xFF;\n\tb1 = ((b1 * ubLevel + (b2 * (255 - ubLevel)))/255) & 0xFF;\n\n\treturn (r1 << 16) | (g1 << 8) | b1;\n}\n\nvoid paletteDumpAga(ULONG *pPalette, UWORD uwColorCnt, char *szPath) {\n\tUWORD uwLastColor = uwColorCnt - 1;\n\tUBYTE ubBpp = 0;\n\n\twhile(uwLastColor) {\n\t\tuwLastColor >>= 1;\n\t\t++ubBpp;\n\t}\n\n\ttBitMap *pBm = bitmapCreate(\n\t\tCEIL_TO_FACTOR((1+8)*uwColorCnt + 1, 16), 10, ubBpp, BMF_CLEAR\n\t);\n\n\tUWORD *pUwTmp = memAllocFast(sizeof(UWORD) * uwColorCnt);\n\n\tfor(UWORD i = 0; i < uwColorCnt; ++i) {\n\t\tULONG ul = pPalette[i];\n\n\t\tUBYTE r = (ul >> 16) & 0xFF;\n\t\tUBYTE g = (ul >> 8) & 0xFF;\n\t\tUBYTE b = ul & 0xFF;\n\n\t\tpUwTmp[i] =\n\t\t\t(((UWORD)(r >> 4)) << 8) |\n\t\t\t(((UWORD)(g >> 4)) << 4) |\n\t\t\t((UWORD)(b >> 4));\n\t}\n\n\tfor(UWORD i = 0; i < uwColorCnt; ++i) {\n\t\tblitRect(pBm, 1+(8+1)*i, 1, 8, 8, i);\n\t}\n\n\tbitmapSaveBmp(pBm, pUwTmp, szPath);\n\tmemFree(pUwTmp, sizeof(UWORD) * uwColorCnt);\n\tbitmapDestroy(pBm);\n}\n#endif\n\nvoid paletteDumpOcs(UWORD *pPalette, UWORD uwColorCnt, char *szPath) {\n\tUWORD uwLastColor = uwColorCnt - 1;\n\tUBYTE ubBpp = 0;\n\twhile(uwLastColor) {\n\t\tuwLastColor >>= 1;\n\t\t++ubBpp;\n\t}\n\ttBitMap *pBm = bitmapCreate(\n\t\tCEIL_TO_FACTOR((1+8)*uwColorCnt + 1, 16), 10, ubBpp, BMF_CLEAR\n\t);\n\tfor(UWORD i = 0; i < uwColorCnt; ++i) {\n\t\tblitRect(pBm, 1+(8+1)*i, 1, 8, 8, i);\n\t}\n\tbitmapSaveBmp(pBm, pPalette, szPath);\n\tbitmapDestroy(pBm);\n}\n"
  },
  {
    "path": "src/ace/utils/sprite.c",
    "content": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at http://mozilla.org/MPL/2.0/. */\n\n#include <ace/utils/sprite.h>\n#include <ace/utils/custom.h>\n\ntCopBlock *spriteDisableInCopBlockMode(tCopList *pList, tSpriteMask eSpriteMask, ULONG pBlankSprite[1]) {\n\t// TODO: move to sprite manager?\n\tUBYTE ubCmdCount = 0;\n\ttSpriteMask eMask = eSpriteMask;\n\n\t// Determine instruction count\n\tfor(UBYTE i = HARDWARE_SPRITE_CHANNEL_COUNT; i--;) {\n\t\tif(eMask & 1) {\n\t\t\tubCmdCount += 2;\n\t\t}\n\t\teMask >>= 1;\n\t}\n\n\t// Set instructions\n\tULONG ulBlank = (ULONG)pBlankSprite;\n\ttCopBlock *pBlock = copBlockCreate(pList, ubCmdCount, 0, 0);\n\teMask = eSpriteMask;\n\tfor(UBYTE i = 0; i < HARDWARE_SPRITE_CHANNEL_COUNT; ++i) {\n\t\tif(eMask & 1) {\n\t\t\tcopMove(pList, pBlock, &g_pSprFetch[i].uwHi, ulBlank >> 16);\n\t\t\tcopMove(pList, pBlock, &g_pSprFetch[i].uwLo, ulBlank & 0xFFFF);\n\t\t}\n\t\teMask >>= 1;\n\t}\n\treturn pBlock;\n}\n\nUBYTE spriteDisableInCopRawMode(\n\ttCopList *pList, tSpriteMask eSpriteMask, UWORD uwCmdOffs, ULONG pBlankSprite[1]\n) {\n\t// TODO: move to sprite\n\tUBYTE ubCmdCount = 0;\n\tULONG ulBlank = (ULONG)pBlankSprite;\n\n\t// No WAIT - could be done earlier by other stuff\n\ttCopMoveCmd *pCmd = &pList->pBackBfr->pList[uwCmdOffs].sMove;\n\tfor(UBYTE i = 0; i < HARDWARE_SPRITE_CHANNEL_COUNT; ++i) {\n\t\tif(eSpriteMask & 1) {\n\t\t\tcopSetMove(pCmd++, &g_pSprFetch[i].uwHi, ulBlank >> 16);\n\t\t\tcopSetMove(pCmd++, &g_pSprFetch[i].uwLo, ulBlank & 0xFFFF);\n\t\t\tubCmdCount += 2;\n\t\t}\n\t\teSpriteMask >>= 1;\n\t}\n\n\t// Copy to front buffer\n\tfor(UWORD i = uwCmdOffs; i < uwCmdOffs + ubCmdCount; ++i) {\n\t\tpList->pFrontBfr->pList[i].ulCode = pList->pBackBfr->pList[i].ulCode;\n\t}\n\n\treturn ubCmdCount;\n}\n\n#ifdef ACE_USE_AGA_FEATURES\n/**\n * BPLCON4 bits 0-3: odd sprite color bank; bits 4-7: even sprite color bank.\n * Bits 8-15 are unrelated (color table); preserve them when updating nibbles.\n */\nvoid spriteSetOddColorPaletteBank(UBYTE ubIndex) {\n\tUWORD uw = g_pCustom->bplcon4;\n\tUWORD uwLow = (uw & 0xF0) | (ubIndex & 0x0F);\n\n\tg_pCustom->bplcon4 = (uw & 0xFF00) | uwLow;\n}\n\nvoid spriteSetEvenColorPaletteBank(UBYTE ubIndex) {\n\tUWORD uw = g_pCustom->bplcon4;\n\tUWORD uwLow = (uw & 0x0F) | (((UWORD)(ubIndex & 0x0F)) << 4);\n\n\tg_pCustom->bplcon4 = (uw & 0xFF00) | uwLow;\n}\n#endif"
  },
  {
    "path": "src/ace/utils/string.c",
    "content": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at http://mozilla.org/MPL/2.0/. */\n\n#include <ace/utils/string.h>\n#include <ace/managers/log.h>\n\nchar *stringDecimalFromULong(ULONG ulVal, char *pDst) {\n\t// Modified from https://github.com/german-one/itostr/blob/master/itostr.c\n\t// Relies on prior verification that buffer != NULL and bufsize != 0\n\t// TODO: add ACE checks for that\n\n\tchar* pEnd = pDst; // Pointer to the position to write\n\tdo {\n\t\t// Get the value of the rightmost digit\n\t\t// (avoid modulo, it would perform another slow division)\n\t\tULONG ulQuot = ulVal / 10;\n\t\tULONG digitval = ulVal - ulQuot * 10;\n\t\tulVal = ulQuot;\n\t\t*pEnd++ = '0' + digitval; // Convert it to the representing character\n\t} while (ulVal); // Iterate as long as digits are leftover\n\tchar *pWriteEnd = pEnd;\n\n\t// Assign the terminating null and decrease the pointer in order to point\n\t// To the last digit written\n\t*pEnd-- = '\\0';\n\twhile (pDst < pEnd) {\n\t\t// Reverse the digits (only the digits) in the array because they are\n\t\t// LTR written but we need them in RTL order\n\t\tchar transfer = *pEnd;\n\t\t*pEnd-- = *pDst;\n\t\t*pDst++ = transfer;\n\t}\n\treturn pWriteEnd;\n}\n\nchar charToUpper(char c) {\n\tif('a' <= c && c <= 'z') {\n\t\tc -= 'a' - 'A';\n\t}\n\treturn c;\n}\n\nvoid strToUpper(const char *szSrc, char *szDst) {\n\twhile(*szSrc) {\n\t\tchar c = *(szSrc++);\n\t\tc = charToUpper(c);\n\t\t*(szDst++) = c;\n\t}\n\t*szDst = '\\0';\n}\n\nUBYTE stringIsEmpty(const char *szStr) {\n\tUBYTE isEmpty = (szStr[0] == '\\0');\n\treturn isEmpty;\n}\n\nchar *stringCopy(const char *szSrc, char *szDest) {\n\twhile(*szSrc != '\\0') {\n\t\t*(szDest++) = *(szSrc++);\n\t};\n\t*szDest = '\\0';\n\treturn szDest;\n}\n\nchar *stringCopyLimited(const char *szSrc, char *szDest, UWORD uwMaxLength) {\n\tif(uwMaxLength == 0) {\n\t\tlogWrite(\"ERR: stringCopyLimited(szSrc: '%s') uwMaxLength is zero\\n\", szSrc);\n\t}\n\n\twhile(*szSrc != '\\0' && --uwMaxLength > 0) {\n\t\t*(szDest++) = *(szSrc++);\n\t\t--uwMaxLength;\n\t};\n\t*szDest = '\\0';\n\treturn szDest;\n}\n"
  },
  {
    "path": "src/ace/utils/tag.c",
    "content": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at http://mozilla.org/MPL/2.0/. */\n\n#include <ace/utils/tag.h>\n#include <ace/managers/log.h>\n\nULONG tagGet(void *pTagListPtr, va_list vaSrcList, tTag ulTagToFind, ULONG ulOnNotFound) {\n\tif(pTagListPtr) {\n\t\t// TODO\n\t\tlogWrite(\"ERR: Unimplemented in tagFindString()\");\n\t\treturn ulOnNotFound;\n\t}\n\n\tva_list vaWorkList;\n\tva_copy(vaWorkList, vaSrcList);\n\ttTag ulTagName;\n\tdo {\n\t\tulTagName = va_arg(vaWorkList, tTag);\n\t\tif(ulTagName == ulTagToFind) {\n\t\t\tULONG ulOut = va_arg(vaWorkList, ULONG);\n\t\t\tva_end(vaWorkList);\n\t\t\treturn ulOut;\n\t\t}\n\t\telse if(ulTagName == TAG_SKIP) {\n\t\t\t// Ignore this & next\n\t\t\tva_arg(vaWorkList, ULONG);\n\t\t\tva_arg(vaWorkList, ULONG);\n\t\t\tva_arg(vaWorkList, ULONG);\n\t\t}\n\t\telse if(ulTagName == TAG_MORE) {\n\t\t\t// This list is finished - parse next one\n\t\t\tvoid *pNext = va_arg(vaWorkList, void*);\n\t\t\tva_end(vaWorkList);\n\t\t\treturn tagGet(pNext, 0, ulTagToFind, ulOnNotFound);\n\t\t}\n\t\telse {\n\t\t\tva_arg(vaWorkList, ULONG);\n\t\t}\n\t} while(ulTagName != TAG_DONE);\n\tva_end(vaWorkList);\n\treturn ulOnNotFound;\n}\n"
  },
  {
    "path": "src/fixmath/fix16.c",
    "content": "#include <fixmath/fix16.h>\n#include <fixmath/int64.h>\n\n/* Subtraction and addition with overflow detection.\n * The versions without overflow detection are inlined in the header.\n */\n#ifndef FIXMATH_NO_OVERFLOW\nfix16_t fix16_add(fix16_t a, fix16_t b)\n{\n\t// Use unsigned integers because overflow with signed integers is\n\t// an undefined operation (http://www.airs.com/blog/archives/120).\n\tuint32_t _a = a, _b = b;\n\tuint32_t sum = _a + _b;\n\n\t// Overflow can only happen if sign of a == sign of b, and then\n\t// it causes sign of sum != sign of a.\n\tif (!((_a ^ _b) & 0x80000000) && ((_a ^ sum) & 0x80000000))\n\t\treturn fix16_overflow;\n\t\n\treturn sum;\n}\n\nfix16_t fix16_sub(fix16_t a, fix16_t b)\n{\n\tuint32_t _a = a, _b = b;\n\tuint32_t diff = _a - _b;\n\n\t// Overflow can only happen if sign of a != sign of b, and then\n\t// it causes sign of diff != sign of a.\n\tif (((_a ^ _b) & 0x80000000) && ((_a ^ diff) & 0x80000000))\n\t\treturn fix16_overflow;\n\t\n\treturn diff;\n}\n\n/* Saturating arithmetic */\nfix16_t fix16_sadd(fix16_t a, fix16_t b)\n{\n\tfix16_t result = fix16_add(a, b);\n\n\tif (result == fix16_overflow)\n\t\treturn (a >= 0) ? fix16_maximum : fix16_minimum;\n\n\treturn result;\n}\t\n\nfix16_t fix16_ssub(fix16_t a, fix16_t b)\n{\n\tfix16_t result = fix16_sub(a, b);\n\n\tif (result == fix16_overflow)\n\t\treturn (a >= 0) ? fix16_maximum : fix16_minimum;\n\n\treturn result;\n}\n#endif\n\n\n\n/* 64-bit implementation for fix16_mul. Fastest version for e.g. ARM Cortex M3.\n * Performs a 32*32 -> 64bit multiplication. The middle 32 bits are the result,\n * bottom 16 bits are used for rounding, and upper 16 bits are used for overflow\n * detection.\n */\n \n#if !defined(FIXMATH_NO_64BIT) && !defined(FIXMATH_OPTIMIZE_8BIT)\nfix16_t fix16_mul(fix16_t inArg0, fix16_t inArg1)\n{\n\tint64_t product = (int64_t)inArg0 * inArg1;\n\t\n\t#ifndef FIXMATH_NO_OVERFLOW\n\t// The upper 17 bits should all be the same (the sign).\n\tuint32_t upper = (product >> 47);\n\t#endif\n\t\n\tif (product < 0)\n\t{\n\t\t#ifndef FIXMATH_NO_OVERFLOW\n\t\tif (~upper)\n\t\t\t\treturn fix16_overflow;\n\t\t#endif\n\t\t\n\t\t#ifndef FIXMATH_NO_ROUNDING\n\t\t// This adjustment is required in order to round -1/2 correctly\n\t\tproduct--;\n\t\t#endif\n\t}\n\telse\n\t{\n\t\t#ifndef FIXMATH_NO_OVERFLOW\n\t\tif (upper)\n\t\t\t\treturn fix16_overflow;\n\t\t#endif\n\t}\n\t\n\t#ifdef FIXMATH_NO_ROUNDING\n\treturn product >> 16;\n\t#else\n\tfix16_t result = product >> 16;\n\tresult += (product & 0x8000) >> 15;\n\t\n\treturn result;\n\t#endif\n}\n#endif\n\n/* 32-bit implementation of fix16_mul. Potentially fast on 16-bit processors,\n * and this is a relatively good compromise for compilers that do not support\n * uint64_t. Uses 16*16->32bit multiplications.\n */\n#if defined(FIXMATH_NO_64BIT) && !defined(FIXMATH_OPTIMIZE_8BIT)\nfix16_t fix16_mul(fix16_t inArg0, fix16_t inArg1)\n{\n\t// Each argument is divided to 16-bit parts.\n\t//\t\t\t\t\tAB\n\t//\t\t\t*\t CD\n\t// -----------\n\t//\t\t\t\t\tBD\t16 * 16 -> 32 bit products\n\t//\t\t\t\t CB\n\t//\t\t\t\t AD\n\t//\t\t\t\tAC\n\t//\t\t\t |----| 64 bit product\n\tint32_t A = (inArg0 >> 16), C = (inArg1 >> 16);\n\tuint32_t B = (inArg0 & 0xFFFF), D = (inArg1 & 0xFFFF);\n\t\n\tint32_t AC = A*C;\n\tint32_t AD_CB = A*D + C*B;\n\tuint32_t BD = B*D;\n\t\n\tint32_t product_hi = AC + (AD_CB >> 16);\n\t\n\t// Handle carry from lower 32 bits to upper part of result.\n\tuint32_t ad_cb_temp = AD_CB << 16;\n\tuint32_t product_lo = BD + ad_cb_temp;\n\tif (product_lo < BD)\n\t\tproduct_hi++;\n\t\n#ifndef FIXMATH_NO_OVERFLOW\n\t// The upper 17 bits should all be the same (the sign).\n\tif (product_hi >> 31 != product_hi >> 15)\n\t\treturn fix16_overflow;\n#endif\n\t\n#ifdef FIXMATH_NO_ROUNDING\n\treturn (product_hi << 16) | (product_lo >> 16);\n#else\n\t// Subtracting 0x8000 (= 0.5) and then using signed right shift\n\t// achieves proper rounding to result-1, except in the corner\n\t// case of negative numbers and lowest word = 0x8000.\n\t// To handle that, we also have to subtract 1 for negative numbers.\n\tuint32_t product_lo_tmp = product_lo;\n\tproduct_lo -= 0x8000;\n\tproduct_lo -= (uint32_t)product_hi >> 31;\n\tif (product_lo > product_lo_tmp)\n\t\tproduct_hi--;\n\t\n\t// Discard the lowest 16 bits. Note that this is not exactly the same\n\t// as dividing by 0x10000. For example if product = -1, result will\n\t// also be -1 and not 0. This is compensated by adding +1 to the result\n\t// and compensating this in turn in the rounding above.\n\tfix16_t result = (product_hi << 16) | (product_lo >> 16);\n\tresult += 1;\n\treturn result;\n#endif\n}\n#endif\n\n/* 8-bit implementation of fix16_mul. Fastest on e.g. Atmel AVR.\n * Uses 8*8->16bit multiplications, and also skips any bytes that\n * are zero.\n */\n#if defined(FIXMATH_OPTIMIZE_8BIT)\nfix16_t fix16_mul(fix16_t inArg0, fix16_t inArg1)\n{\n\tuint32_t _a = (inArg0 >= 0) ? inArg0 : (-inArg0);\n\tuint32_t _b = (inArg1 >= 0) ? inArg1 : (-inArg1);\n\t\n\tuint8_t va[4] = {_a, (_a >> 8), (_a >> 16), (_a >> 24)};\n\tuint8_t vb[4] = {_b, (_b >> 8), (_b >> 16), (_b >> 24)};\n\t\n\tuint32_t low = 0;\n\tuint32_t mid = 0;\n\t\n\t// Result column i depends on va[0..i] and vb[i..0]\n\n\t#ifndef FIXMATH_NO_OVERFLOW\n\t// i = 6\n\tif (va[3] && vb[3]) return fix16_overflow;\n\t#endif\n\t\n\t// i = 5\n\tif (va[2] && vb[3]) mid += (uint16_t)va[2] * vb[3];\n\tif (va[3] && vb[2]) mid += (uint16_t)va[3] * vb[2];\n\tmid <<= 8;\n\t\n\t// i = 4\n\tif (va[1] && vb[3]) mid += (uint16_t)va[1] * vb[3];\n\tif (va[2] && vb[2]) mid += (uint16_t)va[2] * vb[2];\n\tif (va[3] && vb[1]) mid += (uint16_t)va[3] * vb[1];\n\t\n\t#ifndef FIXMATH_NO_OVERFLOW\n\tif (mid & 0xFF000000) return fix16_overflow;\n\t#endif\n\tmid <<= 8;\n\t\n\t// i = 3\n\tif (va[0] && vb[3]) mid += (uint16_t)va[0] * vb[3];\n\tif (va[1] && vb[2]) mid += (uint16_t)va[1] * vb[2];\n\tif (va[2] && vb[1]) mid += (uint16_t)va[2] * vb[1];\n\tif (va[3] && vb[0]) mid += (uint16_t)va[3] * vb[0];\n\t\n\t#ifndef FIXMATH_NO_OVERFLOW\n\tif (mid & 0xFF000000) return fix16_overflow;\n\t#endif\n\tmid <<= 8;\n\t\n\t// i = 2\n\tif (va[0] && vb[2]) mid += (uint16_t)va[0] * vb[2];\n\tif (va[1] && vb[1]) mid += (uint16_t)va[1] * vb[1];\n\tif (va[2] && vb[0]) mid += (uint16_t)va[2] * vb[0];\t\t\n\t\n\t// i = 1\n\tif (va[0] && vb[1]) low += (uint16_t)va[0] * vb[1];\n\tif (va[1] && vb[0]) low += (uint16_t)va[1] * vb[0];\n\tlow <<= 8;\n\t\n\t// i = 0\n\tif (va[0] && vb[0]) low += (uint16_t)va[0] * vb[0];\n\t\n\t#ifndef FIXMATH_NO_ROUNDING\n\tlow += 0x8000;\n\t#endif\n\tmid += (low >> 16);\n\t\n\t#ifndef FIXMATH_NO_OVERFLOW\n\tif (mid & 0x80000000)\n\t\treturn fix16_overflow;\n\t#endif\n\t\n\tfix16_t result = mid;\n\t\n\t/* Figure out the sign of result */\n\tif ((inArg0 >= 0) != (inArg1 >= 0))\n\t{\n\t\tresult = -result;\n\t}\n\t\n\treturn result;\n}\n#endif\n\n#ifndef FIXMATH_NO_OVERFLOW\n/* Wrapper around fix16_mul to add saturating arithmetic. */\nfix16_t fix16_smul(fix16_t inArg0, fix16_t inArg1)\n{\n\tfix16_t result = fix16_mul(inArg0, inArg1);\n\t\n\tif (result == fix16_overflow)\n\t{\n\t\tif ((inArg0 >= 0) == (inArg1 >= 0))\n\t\t\treturn fix16_maximum;\n\t\telse\n\t\t\treturn fix16_minimum;\n\t}\n\t\n\treturn result;\n}\n#endif\n\n/* 32-bit implementation of fix16_div. Fastest version for e.g. ARM Cortex M3.\n * Performs 32-bit divisions repeatedly to reduce the remainder. For this to\n * be efficient, the processor has to have 32-bit hardware division.\n */\n#if !defined(FIXMATH_OPTIMIZE_8BIT)\n#ifdef __GNUC__\n// Count leading zeros, using processor-specific instruction if available.\n#define clz(x) (__builtin_clzl(x) - (8 * sizeof(long) - 32))\n#else\nstatic uint8_t clz(uint32_t x)\n{\n\tuint8_t result = 0;\n\tif (x == 0) return 32;\n\twhile (!(x & 0xF0000000)) { result += 4; x <<= 4; }\n\twhile (!(x & 0x80000000)) { result += 1; x <<= 1; }\n\treturn result;\n}\n#endif\n\nfix16_t fix16_div(fix16_t a, fix16_t b)\n{\n\t// This uses a hardware 32/32 bit division multiple times, until we have\n\t// computed all the bits in (a<<17)/b. Usually this takes 1-3 iterations.\n\t\n\tif (b == 0)\n\t\t\treturn fix16_minimum;\n\t\n\tuint32_t remainder = (a >= 0) ? a : (-a);\n\tuint32_t divider = (b >= 0) ? b : (-b);\n\tuint32_t quotient = 0;\n\tint bit_pos = 17;\n\t\n\t// Kick-start the division a bit.\n\t// This improves speed in the worst-case scenarios where N and D are large\n\t// It gets a lower estimate for the result by N/(D >> 17 + 1).\n\tif (divider & 0xFFF00000)\n\t{\n\t\tuint32_t shifted_div = ((divider >> 17) + 1);\n\t\tquotient = remainder / shifted_div;\n\t\tremainder -= ((uint64_t)quotient * divider) >> 17;\n\t}\n\t\n\t// If the divider is divisible by 2^n, take advantage of it.\n\twhile (!(divider & 0xF) && bit_pos >= 4)\n\t{\n\t\tdivider >>= 4;\n\t\tbit_pos -= 4;\n\t}\n\t\n\twhile (remainder && bit_pos >= 0)\n\t{\n\t\t// Shift remainder as much as we can without overflowing\n\t\tint shift = clz(remainder);\n\t\tif (shift > bit_pos) shift = bit_pos;\n\t\tremainder <<= shift;\n\t\tbit_pos -= shift;\n\t\t\n\t\tuint32_t div = remainder / divider;\n\t\tremainder = remainder % divider;\n\t\tquotient += div << bit_pos;\n\n\t\t#ifndef FIXMATH_NO_OVERFLOW\n\t\tif (div & ~(0xFFFFFFFF >> bit_pos))\n\t\t\t\treturn fix16_overflow;\n\t\t#endif\n\t\t\n\t\tremainder <<= 1;\n\t\tbit_pos--;\n\t}\n\t\n\t#ifndef FIXMATH_NO_ROUNDING\n\t// Quotient is always positive so rounding is easy\n\tquotient++;\n\t#endif\n\t\n\tfix16_t result = quotient >> 1;\n\t\n\t// Figure out the sign of the result\n\tif ((a ^ b) & 0x80000000)\n\t{\n\t\t#ifndef FIXMATH_NO_OVERFLOW\n\t\tif (result == fix16_minimum)\n\t\t\t\treturn fix16_overflow;\n\t\t#endif\n\t\t\n\t\tresult = -result;\n\t}\n\t\n\treturn result;\n}\n#endif\n\n/* Alternative 32-bit implementation of fix16_div. Fastest on e.g. Atmel AVR.\n * This does the division manually, and is therefore good for processors that\n * do not have hardware division.\n */\n#if defined(FIXMATH_OPTIMIZE_8BIT)\nfix16_t fix16_div(fix16_t a, fix16_t b)\n{\n\t// This uses the basic binary restoring division algorithm.\n\t// It appears to be faster to do the whole division manually than\n\t// trying to compose a 64-bit divide out of 32-bit divisions on\n\t// platforms without hardware divide.\n\t\n\tif (b == 0)\n\t\treturn fix16_minimum;\n\t\n\tuint32_t remainder = (a >= 0) ? a : (-a);\n\tuint32_t divider = (b >= 0) ? b : (-b);\n\n\tuint32_t quotient = 0;\n\tuint32_t bit = 0x10000;\n\t\n\t/* The algorithm requires D >= R */\n\twhile (divider < remainder)\n\t{\n\t\tdivider <<= 1;\n\t\tbit <<= 1;\n\t}\n\t\n\t#ifndef FIXMATH_NO_OVERFLOW\n\tif (!bit)\n\t\treturn fix16_overflow;\n\t#endif\n\t\n\tif (divider & 0x80000000)\n\t{\n\t\t// Perform one step manually to avoid overflows later.\n\t\t// We know that divider's bottom bit is 0 here.\n\t\tif (remainder >= divider)\n\t\t{\n\t\t\t\tquotient |= bit;\n\t\t\t\tremainder -= divider;\n\t\t}\n\t\tdivider >>= 1;\n\t\tbit >>= 1;\n\t}\n\t\n\t/* Main division loop */\n\twhile (bit && remainder)\n\t{\n\t\tif (remainder >= divider)\n\t\t{\n\t\t\t\tquotient |= bit;\n\t\t\t\tremainder -= divider;\n\t\t}\n\t\t\n\t\tremainder <<= 1;\n\t\tbit >>= 1;\n\t}\t \n\t\t\t\n\t#ifndef FIXMATH_NO_ROUNDING\n\tif (remainder >= divider)\n\t{\n\t\tquotient++;\n\t}\n\t#endif\n\t\n\tfix16_t result = quotient;\n\t\n\t/* Figure out the sign of result */\n\tif ((a ^ b) & 0x80000000)\n\t{\n\t\t#ifndef FIXMATH_NO_OVERFLOW\n\t\tif (result == fix16_minimum)\n\t\t\t\treturn fix16_overflow;\n\t\t#endif\n\t\t\n\t\tresult = -result;\n\t}\n\t\n\treturn result;\n}\n#endif\n\n#ifndef FIXMATH_NO_OVERFLOW\n/* Wrapper around fix16_div to add saturating arithmetic. */\nfix16_t fix16_sdiv(fix16_t inArg0, fix16_t inArg1)\n{\n\tfix16_t result = fix16_div(inArg0, inArg1);\n\t\n\tif (result == fix16_overflow)\n\t{\n\t\tif ((inArg0 >= 0) == (inArg1 >= 0))\n\t\t\treturn fix16_maximum;\n\t\telse\n\t\t\treturn fix16_minimum;\n\t}\n\t\n\treturn result;\n}\n#endif\n\nfix16_t fix16_mod(fix16_t x, fix16_t y)\n{\n\t#ifdef FIXMATH_OPTIMIZE_8BIT\n\t\t/* The reason we do this, rather than use a modulo operator\n\t\t * is that if you don't have a hardware divider, this will result\n\t\t * in faster operations when the angles are close to the bounds. \n\t\t */\n\t\twhile(x >=  y) x -= y;\n\t\twhile(x <= -y) x += y;\n\t#else\n\t\t/* Note that in C90, the sign of result of the modulo operation is\n\t\t * undefined. in C99, it's the same as the dividend (aka numerator).\n\t\t */\n\t\tx %= y;\n\t#endif\n\n\treturn x;\n}\n\n\n#ifndef FIXMATH_NO_64BIT\n\nfix16_t fix16_lerp8(fix16_t inArg0, fix16_t inArg1, uint8_t inFract)\n{\n\tint64_t tempOut = int64_mul_i32_i32(inArg0, ((1 << 8) - inFract));\n\ttempOut = int64_add(tempOut, int64_mul_i32_i32(inArg1, inFract));\n\ttempOut = int64_shift(tempOut, -8);\n\treturn (fix16_t)int64_lo(tempOut);\n}\n\nfix16_t fix16_lerp16(fix16_t inArg0, fix16_t inArg1, uint16_t inFract)\n{\n\tint64_t tempOut = int64_mul_i32_i32(inArg0, (((int32_t)1 << 16) - inFract));\n\ttempOut = int64_add(tempOut, int64_mul_i32_i32(inArg1, inFract));\n\ttempOut = int64_shift(tempOut, -16);\n\treturn (fix16_t)int64_lo(tempOut);\n}\n\nfix16_t fix16_lerp32(fix16_t inArg0, fix16_t inArg1, uint32_t inFract)\n{\n\tint64_t tempOut;\n\ttempOut  = ((int64_t)inArg0 * (0 - inFract));\n\ttempOut\t+= ((int64_t)inArg1 * inFract);\n\ttempOut >>= 32;\n\treturn (fix16_t)tempOut;\n}\n#endif\n"
  },
  {
    "path": "src/fixmath/fix16_exp.c",
    "content": "#include <fixmath/fix16.h>\n#include <stdbool.h>\n\n#ifndef FIXMATH_NO_CACHE\nstatic fix16_t _fix16_exp_cache_index[4096]  = { 0 };\nstatic fix16_t _fix16_exp_cache_value[4096]  = { 0 };\n#endif\n\n\n\nfix16_t fix16_exp(fix16_t inValue) {\n\tif(inValue == 0        ) return fix16_one;\n\tif(inValue == fix16_one) return fix16_e;\n\tif(inValue >= 681391   ) return fix16_maximum;\n\tif(inValue <= -772243  ) return 0;\n\n\t#ifndef FIXMATH_NO_CACHE\n\tfix16_t tempIndex = (inValue ^ (inValue >> 16));\n\ttempIndex = (inValue ^ (inValue >> 4)) & 0x0FFF;\n\tif(_fix16_exp_cache_index[tempIndex] == inValue)\n\t\treturn _fix16_exp_cache_value[tempIndex];\n\t#endif\n                        \n\t/* The algorithm is based on the power series for exp(x):\n\t * http://en.wikipedia.org/wiki/Exponential_function#Formal_definition\n\t * \n\t * From term n, we get term n+1 by multiplying with x/n.\n\t * When the sum term drops to zero, we can stop summing.\n\t */\n            \n\t// The power-series converges much faster on positive values\n\t// and exp(-x) = 1/exp(x).\n\tbool neg = (inValue < 0);\n\tif (neg) inValue = -inValue;\n            \n\tfix16_t result = inValue + fix16_one;\n\tfix16_t term = inValue;\n\n\tuint_fast8_t i;        \n\tfor (i = 2; i < 30; i++)\n\t{\n\t\tterm = fix16_mul(term, fix16_div(inValue, fix16_from_int(i)));\n\t\tresult += term;\n                \n\t\tif ((term < 500) && ((i > 15) || (term < 20)))\n\t\t\tbreak;\n\t}\n            \n\tif (neg) result = fix16_div(fix16_one, result);\n            \n\t#ifndef FIXMATH_NO_CACHE\n\t_fix16_exp_cache_index[tempIndex] = inValue;\n\t_fix16_exp_cache_value[tempIndex] = result;\n\t#endif\n\n\treturn result;\n}\n\n\n\nfix16_t fix16_log(fix16_t inValue)\n{\n\tfix16_t guess = fix16_from_int(2);\n\tfix16_t delta;\n\tint scaling = 0;\n\tint count = 0;\n\t\n\tif (inValue <= 0)\n\t\treturn fix16_minimum;\n\t\n\t// Bring the value to the most accurate range (1 < x < 100)\n\tconst fix16_t e_to_fourth = 3578144;\n\twhile (inValue > fix16_from_int(100))\n\t{\n\t\tinValue = fix16_div(inValue, e_to_fourth);\n\t\tscaling += 4;\n\t}\n\t\n\twhile (inValue < fix16_one)\n\t{\n\t\tinValue = fix16_mul(inValue, e_to_fourth);\n\t\tscaling -= 4;\n\t}\n\t\n\tdo\n\t{\n\t\t// Solving e(x) = y using Newton's method\n\t\t// f(x) = e(x) - y\n\t\t// f'(x) = e(x)\n\t\tfix16_t e = fix16_exp(guess);\n\t\tdelta = fix16_div(inValue - e, e);\n\t\t\n\t\t// It's unlikely that logarithm is very large, so avoid overshooting.\n\t\tif (delta > fix16_from_int(3))\n\t\t\tdelta = fix16_from_int(3);\n\t\t\n\t\tguess += delta;\n\t} while ((count++ < 10)\n\t\t&& ((delta > 1) || (delta < -1)));\n\t\n\treturn guess + fix16_from_int(scaling);\n}\n\n\n\nstatic inline fix16_t fix16_rs(fix16_t x)\n{\n\t#ifdef FIXMATH_NO_ROUNDING\n\t\treturn (x >> 1);\n\t#else\n\t\tfix16_t y = (x >> 1) + (x & 1);\n\t\treturn y;\n\t#endif\n}\n\n/**\n * This assumes that the input value is >= 1.\n * \n * Note that this is only ever called with inValue >= 1 (because it has a wrapper to check. \n * As such, the result is always less than the input. \n */\nstatic fix16_t fix16__log2_inner(fix16_t x)\n{\n\tfix16_t result = 0;\n\t\n\twhile(x >= fix16_from_int(2))\n\t{\n\t\tresult++;\n\t\tx = fix16_rs(x);\n\t}\n\n\tif(x == 0) return (result << 16);\n\n\tuint_fast8_t i;\n\tfor(i = 16; i > 0; i--)\n\t{\n\t\tx = fix16_mul(x, x);\n\t\tresult <<= 1;\n\t\tif(x >= fix16_from_int(2))\n\t\t{\n\t\t\tresult |= 1;\n\t\t\tx = fix16_rs(x);\n\t\t}\n\t}\n\t#ifndef FIXMATH_NO_ROUNDING\n\t\tx = fix16_mul(x, x);\n\t\tif(x >= fix16_from_int(2)) result++;\n\t#endif\n\t\n\treturn result;\n}\n\n\n\n/**\n * calculates the log base 2 of input.\n * Note that negative inputs are invalid! (will return fix16_overflow, since there are no exceptions)\n * \n * i.e. 2 to the power output = input.\n * It's equivalent to the log or ln functions, except it uses base 2 instead of base 10 or base e.\n * This is useful as binary things like this are easy for binary devices, like modern microprocessros, to calculate.\n * \n * This can be used as a helper function to calculate powers with non-integer powers and/or bases.\n */\nfix16_t fix16_log2(fix16_t x)\n{\n\t// Note that a negative x gives a non-real result.\n\t// If x == 0, the limit of log2(x)  as x -> 0 = -infinity.\n\t// log2(-ve) gives a complex result.\n\tif (x <= 0) return fix16_overflow;\n\n\t// If the input is less than one, the result is -log2(1.0 / in)\n\tif (x < fix16_one)\n\t{\n\t\t// Note that the inverse of this would overflow.\n\t\t// This is the exact answer for log2(1.0 / 65536)\n\t\tif (x == 1) return fix16_from_int(-16);\n\n\t\tfix16_t inverse = fix16_div(fix16_one, x);\n\t\treturn -fix16__log2_inner(inverse);\n\t}\n\n\t// If input >= 1, just proceed as normal.\n\t// Note that x == fix16_one is a special case, where the answer is 0.\n\treturn fix16__log2_inner(x);\n}\n\n/**\n * This is a wrapper for fix16_log2 which implements saturation arithmetic.\n */\nfix16_t fix16_slog2(fix16_t x)\n{\n\tfix16_t retval = fix16_log2(x);\n\t// The only overflow possible is when the input is negative.\n\tif(retval == fix16_overflow)\n\t\treturn fix16_minimum;\n\treturn retval;\n}\n"
  },
  {
    "path": "src/fixmath/fix16_sqrt.c",
    "content": "#include <fixmath/fix16.h>\n\n/* The square root algorithm is quite directly from\n * http://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Binary_numeral_system_.28base_2.29\n * An important difference is that it is split to two parts\n * in order to use only 32-bit operations.\n *\n * Note that for negative numbers we return -sqrt(-inValue).\n * Not sure if someone relies on this behaviour, but not going\n * to break it for now. It doesn't slow the code much overall.\n */\nfix16_t fix16_sqrt(fix16_t inValue)\n{\n\tuint8_t  neg = (inValue < 0);\n\tuint32_t num = (neg ? -inValue : inValue);\n\tuint32_t result = 0;\n\tuint32_t bit;\n\tuint8_t  n;\n\n\t// Many numbers will be less than 15, so\n\t// this gives a good balance between time spent\n\t// in if vs. time spent in the while loop\n\t// when searching for the starting value.\n\tif (num & 0xFFF00000)\n\t\tbit = (uint32_t)1 << 30;\n\telse\n\t\tbit = (uint32_t)1 << 18;\n\n\twhile (bit > num) bit >>= 2;\n\n\t// The main part is executed twice, in order to avoid\n\t// using 64 bit values in computations.\n\tfor (n = 0; n < 2; n++)\n\t{\n\t\t// First we get the top 24 bits of the answer.\n\t\twhile (bit)\n\t\t{\n\t\t\tif (num >= result + bit)\n\t\t\t{\n\t\t\t\tnum -= result + bit;\n\t\t\t\tresult = (result >> 1) + bit;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tresult = (result >> 1);\n\t\t\t}\n\t\t\tbit >>= 2;\n\t\t}\n\n\t\tif (n == 0)\n\t\t{\n\t\t\t// Then process it again to get the lowest 8 bits.\n\t\t\tif (num > 65535)\n\t\t\t{\n\t\t\t\t// The remainder 'num' is too large to be shifted left\n\t\t\t\t// by 16, so we have to add 1 to result manually and\n\t\t\t\t// adjust 'num' accordingly.\n\t\t\t\t// num = a - (result + 0.5)^2\n\t\t\t\t//\t = num + result^2 - (result + 0.5)^2\n\t\t\t\t//\t = num - result - 0.5\n\t\t\t\tnum -= result;\n\t\t\t\tnum = (num << 16) - 0x8000;\n\t\t\t\tresult = (result << 16) + 0x8000;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tnum <<= 16;\n\t\t\t\tresult <<= 16;\n\t\t\t}\n\n\t\t\tbit = 1 << 14;\n\t\t}\n\t}\n\n#ifndef FIXMATH_NO_ROUNDING\n\t// Finally, if next bit would have been 1, round the result upwards.\n\tif (num > result)\n\t{\n\t\tresult++;\n\t}\n#endif\n\n\treturn (neg ? -(fix16_t)result : (fix16_t)result);\n}\n"
  },
  {
    "path": "src/fixmath/fix16_str.c",
    "content": "#include <fixmath/fix16.h>\n#include <stdbool.h>\n#include <ctype.h>\n\nstatic const uint32_t scales[8] = {\n    /* 5 decimals is enough for full fix16_t precision */\n    1, 10, 100, 1000, 10000, 100000, 100000, 100000\n};\n\nstatic char *itoa_loop(char *buf, uint32_t scale, uint32_t value, bool skip)\n{\n    while (scale)\n    {\n        unsigned digit = (value / scale);\n    \n        if (!skip || digit || scale == 1)\n        {\n            skip = false;\n            *buf++ = '0' + digit;\n            value %= scale;\n        }\n        \n        scale /= 10;\n    }\n    return buf;\n}\n\nvoid fix16_to_str(fix16_t value, char *buf, int decimals)\n{\n    uint32_t uvalue = (value >= 0) ? value : -value;\n    if (value < 0)\n        *buf++ = '-';\n\n    /* Separate the integer and decimal parts of the value */\n    unsigned intpart = uvalue >> 16;\n    uint32_t fracpart = uvalue & 0xFFFF;\n    uint32_t scale = scales[decimals & 7];\n    fracpart = fix16_mul(fracpart, scale);\n    \n    if (fracpart >= scale)\n    {\n        /* Handle carry from decimal part */\n        intpart++;\n        fracpart -= scale;    \n    }\n    \n    /* Format integer part */\n    buf = itoa_loop(buf, 10000, intpart, true);\n    \n    /* Format decimal part (if any) */\n    if (scale != 1)\n    {\n        *buf++ = '.';\n        buf = itoa_loop(buf, scale / 10, fracpart, false);\n    }\n    \n    *buf = '\\0';\n}\n\nfix16_t fix16_from_str(const char *buf)\n{\n    while (isspace(*buf))\n        buf++;\n    \n    /* Decode the sign */\n    bool negative = (*buf == '-');\n    if (*buf == '+' || *buf == '-')\n        buf++;\n\n    /* Decode the integer part */\n    uint32_t intpart = 0;\n    int count = 0;\n    while (isdigit(*buf))\n    {\n        intpart *= 10;\n        intpart += *buf++ - '0';\n        count++;\n    }\n    \n    if (count == 0 || count > 5\n        || intpart > 32768 || (!negative && intpart > 32767))\n        return fix16_overflow;\n    \n    fix16_t value = intpart << 16;\n    \n    /* Decode the decimal part */\n    if (*buf == '.' || *buf == ',')\n    {\n        buf++;\n        \n        uint32_t fracpart = 0;\n        uint32_t scale = 1;\n        while (isdigit(*buf) && scale < 100000)\n        {\n            scale *= 10;\n            fracpart *= 10;\n            fracpart += *buf++ - '0';\n        }\n        \n        value += fix16_div(fracpart, scale);\n    }\n    \n    /* Verify that there is no garbage left over */\n    while (*buf != '\\0')\n    {\n        if (!isdigit(*buf) && !isspace(*buf))\n            return fix16_overflow;\n        \n        buf++;\n    }\n    \n    return negative ? -value : value;\n}\n\n"
  },
  {
    "path": "src/fixmath/fix16_trig.c",
    "content": "#include <limits.h>\n#include <fixmath/fix16.h>\n\n#if defined(FIXMATH_SIN_LUT)\n#include <fixmath/fix16_trig_sin_lut.h>\n#elif !defined(FIXMATH_NO_CACHE)\nstatic fix16_t _fix16_sin_cache_index[4096]  = { 0 };\nstatic fix16_t _fix16_sin_cache_value[4096]  = { 0 };\n#endif\n\n#ifndef FIXMATH_NO_CACHE\nstatic fix16_t _fix16_atan_cache_index[2][4096] = { { 0 }, { 0 } };\nstatic fix16_t _fix16_atan_cache_value[4096] = { 0 };\n#endif\n\n\nfix16_t fix16_sin_parabola(fix16_t inAngle)\n{\n\tfix16_t abs_inAngle, retval;\n\tfix16_t mask;\n\n\t/* Absolute function */\n\tmask = (inAngle >> (sizeof(fix16_t)*CHAR_BIT-1));\n\tabs_inAngle = (inAngle + mask) ^ mask;\n\n\t/* On 0->PI, sin looks like x² that is :\n\t   - centered on PI/2,\n\t   - equals 1 on PI/2,\n\t   - equals 0 on 0 and PI\n\t  that means :  4/PI * x  - 4/PI² * x²\n\t  Use abs(x) to handle (-PI) -> 0 zone.\n\t */\n\tretval = fix16_mul(FOUR_DIV_PI, inAngle) + fix16_mul( fix16_mul(_FOUR_DIV_PI2, inAngle), abs_inAngle );\n\t/* At this point, retval equals sin(inAngle) on important points ( -PI, -PI/2, 0, PI/2, PI),\n\t   but is not very precise between these points\n\t */\n\t#ifndef FIXMATH_FAST_SIN\n\t/* Absolute value of retval */\n\tmask = (retval >> (sizeof(fix16_t)*CHAR_BIT-1));\n\tfix16_t abs_retval = (retval + mask) ^ mask;\n\t/* So improve its precision by adding some x^4 component to retval */\n\tretval += fix16_mul(X4_CORRECTION_COMPONENT, fix16_mul(retval, abs_retval) - retval );\n\t#endif\n\treturn retval;\n}\n\nfix16_t fix16_sin(fix16_t inAngle)\n{\n\tfix16_t tempAngle = inAngle % (fix16_pi << 1);\n\n\t#ifdef FIXMATH_SIN_LUT\n\tif(tempAngle < 0)\n\t\ttempAngle += (fix16_pi << 1);\n\n\tfix16_t tempOut;\n\tif(tempAngle >= fix16_pi) {\n\t\ttempAngle -= fix16_pi;\n\t\tif(tempAngle >= (fix16_pi >> 1))\n\t\t\ttempAngle = fix16_pi - tempAngle;\n\t\ttempOut = -(tempAngle >= _fix16_sin_lut_count ? fix16_one : _fix16_sin_lut[tempAngle]);\n\t} else {\n\t\tif(tempAngle >= (fix16_pi >> 1))\n\t\t\ttempAngle = fix16_pi - tempAngle;\n\t\ttempOut = (tempAngle >= _fix16_sin_lut_count ? fix16_one : _fix16_sin_lut[tempAngle]);\n\t}\n\t#else\n\tif(tempAngle > fix16_pi)\n\t\ttempAngle -= (fix16_pi << 1);\n\telse if(tempAngle < -fix16_pi)\n\t\ttempAngle += (fix16_pi << 1);\n\n\t#ifndef FIXMATH_NO_CACHE\n\tfix16_t tempIndex = ((inAngle >> 5) & 0x00000FFF);\n\tif(_fix16_sin_cache_index[tempIndex] == inAngle)\n\t\treturn _fix16_sin_cache_value[tempIndex];\n\t#endif\n\n\tfix16_t tempAngleSq = fix16_mul(tempAngle, tempAngle);\n\n\t#ifndef FIXMATH_FAST_SIN // Most accurate version, accurate to ~2.1%\n\tfix16_t tempOut = tempAngle;\n\ttempAngle = fix16_mul(tempAngle, tempAngleSq);\n\ttempOut -= (tempAngle / 6);\n\ttempAngle = fix16_mul(tempAngle, tempAngleSq);\n\ttempOut += (tempAngle / 120);\n\ttempAngle = fix16_mul(tempAngle, tempAngleSq);\n\ttempOut -= (tempAngle / 5040);\n\ttempAngle = fix16_mul(tempAngle, tempAngleSq);\n\ttempOut += (tempAngle / 362880);\n\ttempAngle = fix16_mul(tempAngle, tempAngleSq);\n\ttempOut -= (tempAngle / 39916800);\n\t#else // Fast implementation, runs at 159% the speed of above 'accurate' version with an slightly lower accuracy of ~2.3%\n\tfix16_t tempOut;\n\ttempOut = fix16_mul(-13, tempAngleSq) + 546;\n\ttempOut = fix16_mul(tempOut, tempAngleSq) - 10923;\n\ttempOut = fix16_mul(tempOut, tempAngleSq) + 65536;\n\ttempOut = fix16_mul(tempOut, tempAngle);\n\t#endif\n\n\t#ifndef FIXMATH_NO_CACHE\n\t_fix16_sin_cache_index[tempIndex] = inAngle;\n\t_fix16_sin_cache_value[tempIndex] = tempOut;\n\t#endif\n\t#endif\n\n\treturn tempOut;\n}\n\nfix16_t fix16_cos(fix16_t inAngle)\n{\n\treturn fix16_sin(inAngle + (fix16_pi >> 1));\n}\n\nfix16_t fix16_tan(fix16_t inAngle)\n{\n\treturn fix16_sdiv(fix16_sin(inAngle), fix16_cos(inAngle));\n}\n\nfix16_t fix16_asin(fix16_t x)\n{\n\tif((x > fix16_one)\n\t\t|| (x < -fix16_one))\n\t\treturn 0;\n\n\tfix16_t out;\n\tout = (fix16_one - fix16_mul(x, x));\n\tout = fix16_div(x, fix16_sqrt(out));\n\tout = fix16_atan(out);\n\treturn out;\n}\n\nfix16_t fix16_acos(fix16_t x)\n{\n\treturn ((fix16_pi >> 1) - fix16_asin(x));\n}\n\nfix16_t fix16_atan2(fix16_t inY , fix16_t inX)\n{\n\tfix16_t abs_inY, mask, angle, r, r_3;\n\n\t#ifndef FIXMATH_NO_CACHE\n\tuintptr_t hash = (inX ^ inY);\n\thash ^= hash >> 20;\n\thash &= 0x0FFF;\n\tif((_fix16_atan_cache_index[0][hash] == inX) && (_fix16_atan_cache_index[1][hash] == inY))\n\t\treturn _fix16_atan_cache_value[hash];\n\t#endif\n\n\t/* Absolute inY */\n\tmask = (inY >> (sizeof(fix16_t)*CHAR_BIT-1));\n\tabs_inY = (inY + mask) ^ mask;\n\n\tif (inX >= 0)\n\t{\n\t\tr = fix16_div( (inX - abs_inY), (inX + abs_inY));\n\t\tr_3 = fix16_mul(fix16_mul(r, r),r);\n\t\tangle = fix16_mul(0x00003240 , r_3) - fix16_mul(0x0000FB50,r) + PI_DIV_4;\n\t} else {\n\t\tr = fix16_div( (inX + abs_inY), (abs_inY - inX));\n\t\tr_3 = fix16_mul(fix16_mul(r, r),r);\n\t\tangle = fix16_mul(0x00003240 , r_3)\n\t\t\t- fix16_mul(0x0000FB50,r)\n\t\t\t+ THREE_PI_DIV_4;\n\t}\n\tif (inY < 0)\n\t{\n\t\tangle = -angle;\n\t}\n\n\t#ifndef FIXMATH_NO_CACHE\n\t_fix16_atan_cache_index[0][hash] = inX;\n\t_fix16_atan_cache_index[1][hash] = inY;\n\t_fix16_atan_cache_value[hash] = angle;\n\t#endif\n\n\treturn angle;\n}\n\nfix16_t fix16_atan(fix16_t x)\n{\n\treturn fix16_atan2(x, fix16_one);\n}\n"
  },
  {
    "path": "src/fixmath/fract32.c",
    "content": "#include <fixmath/fract32.h>\n\n\n\nfract32_t fract32_create(uint32_t inNumerator, uint32_t inDenominator) {\n\tif(inDenominator <= inNumerator)\n\t\treturn 0xFFFFFFFF;\n\tuint32_t tempMod = (inNumerator % inDenominator);\n\tuint32_t tempDiv = (0xFFFFFFFF / (inDenominator - 1));\n\treturn (tempMod * tempDiv);\n}\n\nfract32_t fract32_invert(fract32_t inFract) {\n\treturn (0xFFFFFFFF - inFract);\n}\n\n#ifndef FIXMATH_NO_64BIT\nuint32_t fract32_usmul(uint32_t inVal, fract32_t inFract) {\n\treturn (uint32_t)(((uint64_t)inVal * (uint64_t)inFract) >> 32);\n}\n\nint32_t fract32_smul(int32_t inVal, fract32_t inFract) {\n\tif(inVal < 0)\n        return -(int32_t)fract32_usmul(-inVal, inFract);\n\treturn fract32_usmul(inVal, inFract);\n}\n#endif\n"
  },
  {
    "path": "src/fixmath/uint32.c",
    "content": "#include <fixmath/uint32.h>\n\nuint32_t uint32_log2(uint32_t inVal) {\n\tif(inVal == 0)\n\t\treturn 0;\n\tuint32_t tempOut = 0;\n\tif(inVal >= (1 << 16)) { inVal >>= 16; tempOut += 16; }\n\tif(inVal >= (1 <<  8)) { inVal >>=  8; tempOut +=  8; }\n\tif(inVal >= (1 <<  4)) { inVal >>=  4; tempOut +=  4; }\n\tif(inVal >= (1 <<  2)) { inVal >>=  2; tempOut +=  2; }\n\tif(inVal >= (1 <<  1)) {               tempOut +=  1; }\n\treturn tempOut;\n}\n"
  },
  {
    "path": "src/mini_std/ctype.c",
    "content": "#include \"ctype.h\"\n\nconst unsigned short _ctype[] = {\n    _C, _C, _C, _C, _C, _C, _C, _C,                                // 0-7\n    _C, _C | _S | _HT, _C | _S, _C | _S, _C | _S, _C | _S, _C, _C, // 8-15\n    _C, _C, _C, _C, _C, _C, _C, _C,                                // 16-23\n    _C, _C, _C, _C, _C, _C, _C, _C,                                // 24-31\n    _S | _SP, _P, _P, _P, _P, _P, _P, _P,                          // 32-39\n    _P, _P, _P, _P, _P, _P, _P, _P,                                // 40-47\n    _D, _D, _D, _D, _D, _D, _D, _D,                                // 48-55\n    _D, _D, _P, _P, _P, _P, _P, _P,                                // 56-63\n    _P, _U | _X, _U | _X, _U | _X, _U | _X, _U | _X, _U | _X, _U,  // 64-71\n    _U, _U, _U, _U, _U, _U, _U, _U,                                // 72-79\n    _U, _U, _U, _U, _U, _U, _U, _U,                                // 80-87\n    _U, _U, _U, _P, _P, _P, _P, _P,                                // 88-95\n    _P, _L | _X, _L | _X, _L | _X, _L | _X, _L | _X, _L | _X, _L,  // 96-103\n    _L, _L, _L, _L, _L, _L, _L, _L,                                // 104-111\n    _L, _L, _L, _L, _L, _L, _L, _L,                                // 112-119\n    _L, _L, _L, _P, _P, _P, _P, _C,                                // 120-127\n    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,                // 128-143\n    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,                // 144-159\n    _S | _SP, _P, _P, _P, _P, _P, _P, _P, _P, _P, _P, _P, _P, _P, _P,\n    _P, // 160-175\n    _P, _P, _P, _P, _P, _P, _P, _P, _P, _P, _P, _P, _P, _P, _P,\n    _P, // 176-191\n    _U, _U, _U, _U, _U, _U, _U, _U, _U, _U, _U, _U, _U, _U, _U,\n    _U, // 192-207\n    _U, _U, _U, _U, _U, _U, _U, _P, _U, _U, _U, _U, _U, _U, _U,\n    _L, // 208-223\n    _L, _L, _L, _L, _L, _L, _L, _L, _L, _L, _L, _L, _L, _L, _L,\n    _L,                                                              // 224-239\n    _L, _L, _L, _L, _L, _L, _L, _P, _L, _L, _L, _L, _L, _L, _L, _L}; // 240-255\n\nunsigned char __tolower(unsigned char c) {\n  if (isupper(c)) {\n    c -= 'A' - 'a';\n  }\n\n  return c;\n}\n\nunsigned char __toupper(unsigned char c) {\n  if (islower(c)) {\n    c -= 'a' - 'A';\n  }\n\n  return c;\n}\n"
  },
  {
    "path": "src/mini_std/errno.c",
    "content": "#include <errno.h>\n\nint errno;\n"
  },
  {
    "path": "src/mini_std/intrin.c",
    "content": "#include <stdint.h>\n\n__attribute__ ((used))\nint __clzsi2 (unsigned x) {\n\t// https://en.wikipedia.org/wiki/Find_first_set#CLZ - using clz3\n\tif(x == 0) {\n\t\treturn 32;\n\t}\n\tint n = 0;\n\tif((x & 0xFFFF0000) == 0){\n\t\tn += 16;\n\t\tx <<= 16;\n\t}\n\tif((x & 0xFF000000) == 0){\n\t\tn += 8;\n\t\tx <<= 8;\n\t}\n\tif((x & 0xF0000000) == 0){\n\t\tn += 4;\n\t\tx <<= 4;\n\t}\n\tif((x & 0xC0000000) == 0){\n\t\tn += 2;\n\t\tx <<= 2;\n\t}\n\tif((x & 0x80000000) == 0){\n\t\tn += 1;\n\t}\n\treturn n;\n}\n\n// https://elixir.bootlin.com/linux/latest/source/include/linux/compiler_attributes.h#L173\n#define mode(x) __attribute__((__mode__(x)))\n\n// https://elixir.bootlin.com/linux/latest/source/arch/m68k/lib/muldi3.c\n#define SI_TYPE_SIZE 32\n#define BITS4 (SI_TYPE_SIZE / 4)\n#define ll_B (1L << (SI_TYPE_SIZE / 2))\n#define ll_lowpart(t) ((USItype) (t) % ll_B)\n#define ll_highpart(t) ((USItype) (t) / ll_B)\n\n#define umul_ppmm(w1, w0, u, v) do {                            \\\n\tUSItype x0, x1, x2, x3;                                       \\\n\tUSItype ul, vl, uh, vh;                                       \\\n\t                                                              \\\n\tul = ll_lowpart (u);\t                                        \\\n\tuh = ll_highpart (u);                                         \\\n\tvl = ll_lowpart (v);                                          \\\n\tvh = ll_highpart (v);                                         \\\n\t                                                              \\\n\tx0 = (USItype) ul * vl;                                       \\\n\tx1 = (USItype) ul * vh;                                       \\\n\tx2 = (USItype) uh * vl;                                       \\\n\tx3 = (USItype) uh * vh;                                       \\\n\t                                                              \\\n\tx1 += ll_highpart (x0); /* this can't give carry */           \\\n\tx1 += x2;\t\t            /* but this indeed can */\t\t          \\\n\tif (x1 < x2)\t\t        /* did we get it? */\t\t\t            \\\n\t\tx3 += ll_B;\t\t        /* yes, add it in the proper pos. */\t\\\n\t                                                              \\\n\t(w1) = x3 + ll_highpart (x1);                                 \\\n\t(w0) = ll_lowpart (x1) * ll_B + ll_lowpart (x0);              \\\n} while (0)\n\n#define __umulsidi3(u, v) ({           \\\n\tDIunion w;                           \\\n  umul_ppmm (w.s.high, w.s.low, u, v); \\\n  w.ll;                                \\\n})\n\ntypedef int SItype mode(SI);\ntypedef unsigned int USItype mode(SI);\ntypedef int DItype mode(DI);\ntypedef int word_type mode(__word__);\n\ntypedef union {\n\tstruct {SItype high, low;} s;\n\tDItype ll;\n} DIunion;\n\n__attribute__ ((used))\nDItype __muldi3 (DItype u, DItype v) {\n  DIunion w, uu, vv;\n\n  uu.ll = u,\n  vv.ll = v;\n\n  w.ll = __umulsidi3 (uu.s.low, vv.s.low);\n  w.s.high += (\n\t\t(USItype) uu.s.low * (USItype) vv.s.high +\n\t\t(USItype) uu.s.high * (USItype) vv.s.low\n\t);\n\n  return w.ll;\n}\n"
  },
  {
    "path": "src/mini_std/printf.c",
    "content": "///////////////////////////////////////////////////////////////////////////////\n// \\author (c) Marco Paland (info@paland.com)\n//             2014-2019, PALANDesign Hannover, Germany\n//\n// \\license The MIT License (MIT)\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy\n// of this software and associated documentation files (the \"Software\"), to deal\n// in the Software without restriction, including without limitation the rights\n// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n// copies of the Software, and to permit persons to whom the Software is\n// furnished to do so, subject to the following conditions:\n//\n// The above copyright notice and this permission notice shall be included in\n// all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n// THE SOFTWARE.\n//\n// \\brief Tiny printf, sprintf and (v)snprintf implementation, optimized for speed on\n//        embedded systems with a very limited resources. These routines are thread\n//        safe and reentrant!\n//        Use this instead of the bloated standard/newlib printf cause these use\n//        malloc for printf (and may not be thread safe).\n//\n///////////////////////////////////////////////////////////////////////////////\n\n#include <stdbool.h>\n#include <stdint.h>\n\n#include \"printf.h\"\n\n\n// define this globally (e.g. gcc -DPRINTF_INCLUDE_CONFIG_H ...) to include the\n// printf_config.h header file\n// default: undefined\n#ifdef PRINTF_INCLUDE_CONFIG_H\n#include \"printf_config.h\"\n#endif\n\n\n// 'ntoa' conversion buffer size, this must be big enough to hold one converted\n// numeric number including padded zeros (dynamically created on stack)\n// default: 32 byte\n#ifndef PRINTF_NTOA_BUFFER_SIZE\n#define PRINTF_NTOA_BUFFER_SIZE    32U\n#endif\n\n// 'ftoa' conversion buffer size, this must be big enough to hold one converted\n// float number including padded zeros (dynamically created on stack)\n// default: 32 byte\n#ifndef PRINTF_FTOA_BUFFER_SIZE\n#define PRINTF_FTOA_BUFFER_SIZE    32U\n#endif\n\n// support for the floating point type (%f)\n// default: activated\n#ifndef PRINTF_DISABLE_SUPPORT_FLOAT\n#define PRINTF_SUPPORT_FLOAT\n#endif\n\n// support for exponential floating point notation (%e/%g)\n// default: activated\n#ifndef PRINTF_DISABLE_SUPPORT_EXPONENTIAL\n#define PRINTF_SUPPORT_EXPONENTIAL\n#endif\n\n// define the default floating point precision\n// default: 6 digits\n#ifndef PRINTF_DEFAULT_FLOAT_PRECISION\n#define PRINTF_DEFAULT_FLOAT_PRECISION  6U\n#endif\n\n// define the largest float suitable to print with %f\n// default: 1e9\n#ifndef PRINTF_MAX_FLOAT\n#define PRINTF_MAX_FLOAT  1e9\n#endif\n\n// support for the long long types (%llu or %p)\n// default: activated\n#ifndef PRINTF_DISABLE_SUPPORT_LONG_LONG\n#define PRINTF_SUPPORT_LONG_LONG\n#endif\n\n// support for the ptrdiff_t type (%t)\n// ptrdiff_t is normally defined in <stddef.h> as long or long long type\n// default: activated\n#ifndef PRINTF_DISABLE_SUPPORT_PTRDIFF_T\n#define PRINTF_SUPPORT_PTRDIFF_T\n#endif\n\n///////////////////////////////////////////////////////////////////////////////\n\n// internal flag definitions\n#define FLAGS_ZEROPAD   (1U <<  0U)\n#define FLAGS_LEFT      (1U <<  1U)\n#define FLAGS_PLUS      (1U <<  2U)\n#define FLAGS_SPACE     (1U <<  3U)\n#define FLAGS_HASH      (1U <<  4U)\n#define FLAGS_UPPERCASE (1U <<  5U)\n#define FLAGS_CHAR      (1U <<  6U)\n#define FLAGS_SHORT     (1U <<  7U)\n#define FLAGS_LONG      (1U <<  8U)\n#define FLAGS_LONG_LONG (1U <<  9U)\n#define FLAGS_PRECISION (1U << 10U)\n#define FLAGS_ADAPT_EXP (1U << 11U)\n\n\n// import float.h for DBL_MAX\n#if defined(PRINTF_SUPPORT_FLOAT)\n#include <float.h>\n#endif\n\n\n// output function type\ntypedef void (*out_fct_type)(char character, void* buffer, size_t idx, size_t maxlen);\n\n\n// wrapper (used as buffer) for output function type\ntypedef struct {\n  void  (*fct)(char character, void* arg);\n  void* arg;\n} out_fct_wrap_type;\n\n\n// internal buffer output\nstatic inline void _out_buffer(char character, void* buffer, size_t idx, size_t maxlen)\n{\n  if (idx < maxlen) {\n    ((char*)buffer)[idx] = character;\n  }\n}\n\n\n// internal null output\nstatic inline void _out_null(char character, void* buffer, size_t idx, size_t maxlen)\n{\n  (void)character; (void)buffer; (void)idx; (void)maxlen;\n}\n\n\n// internal _putchar wrapper\nstatic inline void _out_char(char character, void* buffer, size_t idx, size_t maxlen)\n{\n  (void)buffer; (void)idx; (void)maxlen;\n  if (character) {\n    _putchar(character);\n  }\n}\n\n\n// internal output function wrapper\nstatic inline void _out_fct(char character, void* buffer, size_t idx, size_t maxlen)\n{\n  (void)idx; (void)maxlen;\n  if (character) {\n    // buffer is the output fct pointer\n    ((out_fct_wrap_type*)buffer)->fct(character, ((out_fct_wrap_type*)buffer)->arg);\n  }\n}\n\n\n// internal secure strlen\n// \\return The length of the string (excluding the terminating 0) limited by 'maxsize'\nstatic inline unsigned int _strnlen_s(const char* str, size_t maxsize)\n{\n  const char* s;\n  for (s = str; *s && maxsize--; ++s);\n  return (unsigned int)(s - str);\n}\n\n\n// internal test if char is a digit (0-9)\n// \\return true if char is a digit\nstatic inline bool _is_digit(char ch)\n{\n  return (ch >= '0') && (ch <= '9');\n}\n\n\n// internal ASCII string to unsigned int conversion\nstatic unsigned int _atoi(const char** str)\n{\n  unsigned int i = 0U;\n  while (_is_digit(**str)) {\n    i = i * 10U + (unsigned int)(*((*str)++) - '0');\n  }\n  return i;\n}\n\n\n// output the specified string in reverse, taking care of any zero-padding\nstatic size_t _out_rev(out_fct_type out, char* buffer, size_t idx, size_t maxlen, const char* buf, size_t len, unsigned int width, unsigned int flags)\n{\n  const size_t start_idx = idx;\n\n  // pad spaces up to given width\n  if (!(flags & FLAGS_LEFT) && !(flags & FLAGS_ZEROPAD)) {\n    for (size_t i = len; i < width; i++) {\n      out(' ', buffer, idx++, maxlen);\n    }\n  }\n\n  // reverse string\n  while (len) {\n    out(buf[--len], buffer, idx++, maxlen);\n  }\n\n  // append pad spaces up to given width\n  if (flags & FLAGS_LEFT) {\n    while (idx - start_idx < width) {\n      out(' ', buffer, idx++, maxlen);\n    }\n  }\n\n  return idx;\n}\n\n\n// internal itoa format\nstatic size_t _ntoa_format(out_fct_type out, char* buffer, size_t idx, size_t maxlen, char* buf, size_t len, bool negative, unsigned int base, unsigned int prec, unsigned int width, unsigned int flags)\n{\n  // pad leading zeros\n  if (!(flags & FLAGS_LEFT)) {\n    if (width && (flags & FLAGS_ZEROPAD) && (negative || (flags & (FLAGS_PLUS | FLAGS_SPACE)))) {\n      width--;\n    }\n    while ((len < prec) && (len < PRINTF_NTOA_BUFFER_SIZE)) {\n      buf[len++] = '0';\n    }\n    while ((flags & FLAGS_ZEROPAD) && (len < width) && (len < PRINTF_NTOA_BUFFER_SIZE)) {\n      buf[len++] = '0';\n    }\n  }\n\n  // handle hash\n  if (flags & FLAGS_HASH) {\n    if (!(flags & FLAGS_PRECISION) && len && ((len == prec) || (len == width))) {\n      len--;\n      if (len && (base == 16U)) {\n        len--;\n      }\n    }\n    if ((base == 16U) && !(flags & FLAGS_UPPERCASE) && (len < PRINTF_NTOA_BUFFER_SIZE)) {\n      buf[len++] = 'x';\n    }\n    else if ((base == 16U) && (flags & FLAGS_UPPERCASE) && (len < PRINTF_NTOA_BUFFER_SIZE)) {\n      buf[len++] = 'X';\n    }\n    else if ((base == 2U) && (len < PRINTF_NTOA_BUFFER_SIZE)) {\n      buf[len++] = 'b';\n    }\n    if (len < PRINTF_NTOA_BUFFER_SIZE) {\n      buf[len++] = '0';\n    }\n  }\n\n  if (len < PRINTF_NTOA_BUFFER_SIZE) {\n    if (negative) {\n      buf[len++] = '-';\n    }\n    else if (flags & FLAGS_PLUS) {\n      buf[len++] = '+';  // ignore the space if the '+' exists\n    }\n    else if (flags & FLAGS_SPACE) {\n      buf[len++] = ' ';\n    }\n  }\n\n  return _out_rev(out, buffer, idx, maxlen, buf, len, width, flags);\n}\n\n\n// internal itoa for 'long' type\nstatic size_t _ntoa_long(out_fct_type out, char* buffer, size_t idx, size_t maxlen, unsigned long value, bool negative, unsigned long base, unsigned int prec, unsigned int width, unsigned int flags)\n{\n  char buf[PRINTF_NTOA_BUFFER_SIZE];\n  size_t len = 0U;\n\n  // no hash for 0 values\n  if (!value) {\n    flags &= ~FLAGS_HASH;\n  }\n\n  // write if precision != 0 and value is != 0\n  if (!(flags & FLAGS_PRECISION) || value) {\n    do {\n      const char digit = (char)(value % base);\n      buf[len++] = digit < 10 ? '0' + digit : (flags & FLAGS_UPPERCASE ? 'A' : 'a') + digit - 10;\n      value /= base;\n    } while (value && (len < PRINTF_NTOA_BUFFER_SIZE));\n  }\n\n  return _ntoa_format(out, buffer, idx, maxlen, buf, len, negative, (unsigned int)base, prec, width, flags);\n}\n\n\n// internal itoa for 'long long' type\n#if defined(PRINTF_SUPPORT_LONG_LONG)\nstatic size_t _ntoa_long_long(out_fct_type out, char* buffer, size_t idx, size_t maxlen, unsigned long long value, bool negative, unsigned long long base, unsigned int prec, unsigned int width, unsigned int flags)\n{\n  char buf[PRINTF_NTOA_BUFFER_SIZE];\n  size_t len = 0U;\n\n  // no hash for 0 values\n  if (!value) {\n    flags &= ~FLAGS_HASH;\n  }\n\n  // write if precision != 0 and value is != 0\n  if (!(flags & FLAGS_PRECISION) || value) {\n    do {\n      const char digit = (char)(value % base);\n      buf[len++] = digit < 10 ? '0' + digit : (flags & FLAGS_UPPERCASE ? 'A' : 'a') + digit - 10;\n      value /= base;\n    } while (value && (len < PRINTF_NTOA_BUFFER_SIZE));\n  }\n\n  return _ntoa_format(out, buffer, idx, maxlen, buf, len, negative, (unsigned int)base, prec, width, flags);\n}\n#endif  // PRINTF_SUPPORT_LONG_LONG\n\n\n#if defined(PRINTF_SUPPORT_FLOAT)\n\n#if defined(PRINTF_SUPPORT_EXPONENTIAL)\n// forward declaration so that _ftoa can switch to exp notation for values > PRINTF_MAX_FLOAT\nstatic size_t _etoa(out_fct_type out, char* buffer, size_t idx, size_t maxlen, double value, unsigned int prec, unsigned int width, unsigned int flags);\n#endif\n\n\n// internal ftoa for fixed decimal floating point\nstatic size_t _ftoa(out_fct_type out, char* buffer, size_t idx, size_t maxlen, double value, unsigned int prec, unsigned int width, unsigned int flags)\n{\n  char buf[PRINTF_FTOA_BUFFER_SIZE];\n  size_t len  = 0U;\n  double diff = 0.0;\n\n  // powers of 10\n  static const double pow10[] = { 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000 };\n\n  // test for special values\n  if (value != value)\n    return _out_rev(out, buffer, idx, maxlen, \"nan\", 3, width, flags);\n  if (value < -DBL_MAX)\n    return _out_rev(out, buffer, idx, maxlen, \"fni-\", 4, width, flags);\n  if (value > DBL_MAX)\n    return _out_rev(out, buffer, idx, maxlen, (flags & FLAGS_PLUS) ? \"fni+\" : \"fni\", (flags & FLAGS_PLUS) ? 4U : 3U, width, flags);\n\n  // test for very large values\n  // standard printf behavior is to print EVERY whole number digit -- which could be 100s of characters overflowing your buffers == bad\n  if ((value > PRINTF_MAX_FLOAT) || (value < -PRINTF_MAX_FLOAT)) {\n#if defined(PRINTF_SUPPORT_EXPONENTIAL)\n    return _etoa(out, buffer, idx, maxlen, value, prec, width, flags);\n#else\n    return 0U;\n#endif\n  }\n\n  // test for negative\n  bool negative = false;\n  if (value < 0) {\n    negative = true;\n    value = 0 - value;\n  }\n\n  // set default precision, if not set explicitly\n  if (!(flags & FLAGS_PRECISION)) {\n    prec = PRINTF_DEFAULT_FLOAT_PRECISION;\n  }\n  // limit precision to 9, cause a prec >= 10 can lead to overflow errors\n  while ((len < PRINTF_FTOA_BUFFER_SIZE) && (prec > 9U)) {\n    buf[len++] = '0';\n    prec--;\n  }\n\n  int whole = (int)value;\n  double tmp = (value - whole) * pow10[prec];\n  unsigned long frac = (unsigned long)tmp;\n  diff = tmp - frac;\n\n  if (diff > 0.5) {\n    ++frac;\n    // handle rollover, e.g. case 0.99 with prec 1 is 1.0\n    if (frac >= pow10[prec]) {\n      frac = 0;\n      ++whole;\n    }\n  }\n  else if (diff < 0.5) {\n  }\n  else if ((frac == 0U) || (frac & 1U)) {\n    // if halfway, round up if odd OR if last digit is 0\n    ++frac;\n  }\n\n  if (prec == 0U) {\n    diff = value - (double)whole;\n    if ((!(diff < 0.5) || (diff > 0.5)) && (whole & 1)) {\n      // exactly 0.5 and ODD, then round up\n      // 1.5 -> 2, but 2.5 -> 2\n      ++whole;\n    }\n  }\n  else {\n    unsigned int count = prec;\n    // now do fractional part, as an unsigned number\n    while (len < PRINTF_FTOA_BUFFER_SIZE) {\n      --count;\n      buf[len++] = (char)(48U + (frac % 10U));\n      if (!(frac /= 10U)) {\n        break;\n      }\n    }\n    // add extra 0s\n    while ((len < PRINTF_FTOA_BUFFER_SIZE) && (count-- > 0U)) {\n      buf[len++] = '0';\n    }\n    if (len < PRINTF_FTOA_BUFFER_SIZE) {\n      // add decimal\n      buf[len++] = '.';\n    }\n  }\n\n  // do whole part, number is reversed\n  while (len < PRINTF_FTOA_BUFFER_SIZE) {\n    buf[len++] = (char)(48 + (whole % 10));\n    if (!(whole /= 10)) {\n      break;\n    }\n  }\n\n  // pad leading zeros\n  if (!(flags & FLAGS_LEFT) && (flags & FLAGS_ZEROPAD)) {\n    if (width && (negative || (flags & (FLAGS_PLUS | FLAGS_SPACE)))) {\n      width--;\n    }\n    while ((len < width) && (len < PRINTF_FTOA_BUFFER_SIZE)) {\n      buf[len++] = '0';\n    }\n  }\n\n  if (len < PRINTF_FTOA_BUFFER_SIZE) {\n    if (negative) {\n      buf[len++] = '-';\n    }\n    else if (flags & FLAGS_PLUS) {\n      buf[len++] = '+';  // ignore the space if the '+' exists\n    }\n    else if (flags & FLAGS_SPACE) {\n      buf[len++] = ' ';\n    }\n  }\n\n  return _out_rev(out, buffer, idx, maxlen, buf, len, width, flags);\n}\n\n\n#if defined(PRINTF_SUPPORT_EXPONENTIAL)\n// internal ftoa variant for exponential floating-point type, contributed by Martijn Jasperse <m.jasperse@gmail.com>\nstatic size_t _etoa(out_fct_type out, char* buffer, size_t idx, size_t maxlen, double value, unsigned int prec, unsigned int width, unsigned int flags)\n{\n  // check for NaN and special values\n  if ((value != value) || (value > DBL_MAX) || (value < -DBL_MAX)) {\n    return _ftoa(out, buffer, idx, maxlen, value, prec, width, flags);\n  }\n\n  // determine the sign\n  const bool negative = value < 0;\n  if (negative) {\n    value = -value;\n  }\n\n  // default precision\n  if (!(flags & FLAGS_PRECISION)) {\n    prec = PRINTF_DEFAULT_FLOAT_PRECISION;\n  }\n\n  // determine the decimal exponent\n  // based on the algorithm by David Gay (https://www.ampl.com/netlib/fp/dtoa.c)\n  union {\n    uint64_t U;\n    double   F;\n  } conv;\n\n  conv.F = value;\n  int exp2 = (int)((conv.U >> 52U) & 0x07FFU) - 1023;           // effectively log2\n  conv.U = (conv.U & ((1ULL << 52U) - 1U)) | (1023ULL << 52U);  // drop the exponent so conv.F is now in [1,2)\n  // now approximate log10 from the log2 integer part and an expansion of ln around 1.5\n  int expval = (int)(0.1760912590558 + exp2 * 0.301029995663981 + (conv.F - 1.5) * 0.289529654602168);\n  // now we want to compute 10^expval but we want to be sure it won't overflow\n  exp2 = (int)(expval * 3.321928094887362 + 0.5);\n  const double z  = expval * 2.302585092994046 - exp2 * 0.6931471805599453;\n  const double z2 = z * z;\n  conv.U = (uint64_t)(exp2 + 1023) << 52U;\n  // compute exp(z) using continued fractions, see https://en.wikipedia.org/wiki/Exponential_function#Continued_fractions_for_ex\n  conv.F *= 1 + 2 * z / (2 - z + (z2 / (6 + (z2 / (10 + z2 / 14)))));\n  // correct for rounding errors\n  if (value < conv.F) {\n    expval--;\n    conv.F /= 10;\n  }\n\n  // the exponent format is \"%+03d\" and largest value is \"307\", so set aside 4-5 characters\n  unsigned int minwidth = ((expval < 100) && (expval > -100)) ? 4U : 5U;\n\n  // in \"%g\" mode, \"prec\" is the number of *significant figures* not decimals\n  if (flags & FLAGS_ADAPT_EXP) {\n    // do we want to fall-back to \"%f\" mode?\n    if ((value >= 1e-4) && (value < 1e6)) {\n      if ((int)prec > expval) {\n        prec = (unsigned)((int)prec - expval - 1);\n      }\n      else {\n        prec = 0;\n      }\n      flags |= FLAGS_PRECISION;   // make sure _ftoa respects precision\n      // no characters in exponent\n      minwidth = 0U;\n      expval   = 0;\n    }\n    else {\n      // we use one sigfig for the whole part\n      if ((prec > 0) && (flags & FLAGS_PRECISION)) {\n        --prec;\n      }\n    }\n  }\n\n  // will everything fit?\n  unsigned int fwidth = width;\n  if (width > minwidth) {\n    // we didn't fall-back so subtract the characters required for the exponent\n    fwidth -= minwidth;\n  } else {\n    // not enough characters, so go back to default sizing\n    fwidth = 0U;\n  }\n  if ((flags & FLAGS_LEFT) && minwidth) {\n    // if we're padding on the right, DON'T pad the floating part\n    fwidth = 0U;\n  }\n\n  // rescale the float value\n  if (expval) {\n    value /= conv.F;\n  }\n\n  // output the floating part\n  const size_t start_idx = idx;\n  idx = _ftoa(out, buffer, idx, maxlen, negative ? -value : value, prec, fwidth, flags & ~FLAGS_ADAPT_EXP);\n\n  // output the exponent part\n  if (minwidth) {\n    // output the exponential symbol\n    out((flags & FLAGS_UPPERCASE) ? 'E' : 'e', buffer, idx++, maxlen);\n    // output the exponent value\n    idx = _ntoa_long(out, buffer, idx, maxlen, (expval < 0) ? -expval : expval, expval < 0, 10, 0, minwidth-1, FLAGS_ZEROPAD | FLAGS_PLUS);\n    // might need to right-pad spaces\n    if (flags & FLAGS_LEFT) {\n      while (idx - start_idx < width) out(' ', buffer, idx++, maxlen);\n    }\n  }\n  return idx;\n}\n#endif  // PRINTF_SUPPORT_EXPONENTIAL\n#endif  // PRINTF_SUPPORT_FLOAT\n\n\n// internal vsnprintf\nstatic int _vsnprintf(out_fct_type out, char* buffer, const size_t maxlen, const char* format, va_list va)\n{\n  unsigned int flags, width, precision, n;\n  size_t idx = 0U;\n\n  if (!buffer) {\n    // use null output function\n    out = _out_null;\n  }\n\n  while (*format)\n  {\n    // format specifier?  %[flags][width][.precision][length]\n    if (*format != '%') {\n      // no\n      out(*format, buffer, idx++, maxlen);\n      format++;\n      continue;\n    }\n    else {\n      // yes, evaluate it\n      format++;\n    }\n\n    // evaluate flags\n    flags = 0U;\n    do {\n      switch (*format) {\n        case '0': flags |= FLAGS_ZEROPAD; format++; n = 1U; break;\n        case '-': flags |= FLAGS_LEFT;    format++; n = 1U; break;\n        case '+': flags |= FLAGS_PLUS;    format++; n = 1U; break;\n        case ' ': flags |= FLAGS_SPACE;   format++; n = 1U; break;\n        case '#': flags |= FLAGS_HASH;    format++; n = 1U; break;\n        default :                                   n = 0U; break;\n      }\n    } while (n);\n\n    // evaluate width field\n    width = 0U;\n    if (_is_digit(*format)) {\n      width = _atoi(&format);\n    }\n    else if (*format == '*') {\n      const int w = va_arg(va, int);\n      if (w < 0) {\n        flags |= FLAGS_LEFT;    // reverse padding\n        width = (unsigned int)-w;\n      }\n      else {\n        width = (unsigned int)w;\n      }\n      format++;\n    }\n\n    // evaluate precision field\n    precision = 0U;\n    if (*format == '.') {\n      flags |= FLAGS_PRECISION;\n      format++;\n      if (_is_digit(*format)) {\n        precision = _atoi(&format);\n      }\n      else if (*format == '*') {\n        const int prec = (int)va_arg(va, int);\n        precision = prec > 0 ? (unsigned int)prec : 0U;\n        format++;\n      }\n    }\n\n    // evaluate length field\n    switch (*format) {\n      case 'l' :\n        flags |= FLAGS_LONG;\n        format++;\n        if (*format == 'l') {\n          flags |= FLAGS_LONG_LONG;\n          format++;\n        }\n        break;\n      case 'h' :\n        flags |= FLAGS_SHORT;\n        format++;\n        if (*format == 'h') {\n          flags |= FLAGS_CHAR;\n          format++;\n        }\n        break;\n#if defined(PRINTF_SUPPORT_PTRDIFF_T)\n      case 't' :\n        flags |= (sizeof(ptrdiff_t) == sizeof(long) ? FLAGS_LONG : FLAGS_LONG_LONG);\n        format++;\n        break;\n#endif\n      case 'j' :\n        flags |= (sizeof(intmax_t) == sizeof(long) ? FLAGS_LONG : FLAGS_LONG_LONG);\n        format++;\n        break;\n      case 'z' :\n        flags |= (sizeof(size_t) == sizeof(long) ? FLAGS_LONG : FLAGS_LONG_LONG);\n        format++;\n        break;\n      default :\n        break;\n    }\n\n    // evaluate specifier\n    switch (*format) {\n      case 'd' :\n      case 'i' :\n      case 'u' :\n      case 'x' :\n      case 'X' :\n      case 'o' :\n      case 'b' : {\n        // set the base\n        unsigned int base;\n        if (*format == 'x' || *format == 'X') {\n          base = 16U;\n        }\n        else if (*format == 'o') {\n          base =  8U;\n        }\n        else if (*format == 'b') {\n          base =  2U;\n        }\n        else {\n          base = 10U;\n          flags &= ~FLAGS_HASH;   // no hash for dec format\n        }\n        // uppercase\n        if (*format == 'X') {\n          flags |= FLAGS_UPPERCASE;\n        }\n\n        // no plus or space flag for u, x, X, o, b\n        if ((*format != 'i') && (*format != 'd')) {\n          flags &= ~(FLAGS_PLUS | FLAGS_SPACE);\n        }\n\n        // ignore '0' flag when precision is given\n        if (flags & FLAGS_PRECISION) {\n          flags &= ~FLAGS_ZEROPAD;\n        }\n\n        // convert the integer\n        if ((*format == 'i') || (*format == 'd')) {\n          // signed\n          if (flags & FLAGS_LONG_LONG) {\n#if defined(PRINTF_SUPPORT_LONG_LONG)\n            const long long value = va_arg(va, long long);\n            idx = _ntoa_long_long(out, buffer, idx, maxlen, (unsigned long long)(value > 0 ? value : 0 - value), value < 0, base, precision, width, flags);\n#endif\n          }\n          else if (flags & FLAGS_LONG) {\n            const long value = va_arg(va, long);\n            idx = _ntoa_long(out, buffer, idx, maxlen, (unsigned long)(value > 0 ? value : 0 - value), value < 0, base, precision, width, flags);\n          }\n          else {\n            const int value = (flags & FLAGS_CHAR) ? (char)va_arg(va, int) : (flags & FLAGS_SHORT) ? (short int)va_arg(va, int) : va_arg(va, int);\n            idx = _ntoa_long(out, buffer, idx, maxlen, (unsigned int)(value > 0 ? value : 0 - value), value < 0, base, precision, width, flags);\n          }\n        }\n        else {\n          // unsigned\n          if (flags & FLAGS_LONG_LONG) {\n#if defined(PRINTF_SUPPORT_LONG_LONG)\n            idx = _ntoa_long_long(out, buffer, idx, maxlen, va_arg(va, unsigned long long), false, base, precision, width, flags);\n#endif\n          }\n          else if (flags & FLAGS_LONG) {\n            idx = _ntoa_long(out, buffer, idx, maxlen, va_arg(va, unsigned long), false, base, precision, width, flags);\n          }\n          else {\n            const unsigned int value = (flags & FLAGS_CHAR) ? (unsigned char)va_arg(va, unsigned int) : (flags & FLAGS_SHORT) ? (unsigned short int)va_arg(va, unsigned int) : va_arg(va, unsigned int);\n            idx = _ntoa_long(out, buffer, idx, maxlen, value, false, base, precision, width, flags);\n          }\n        }\n        format++;\n        break;\n      }\n#if defined(PRINTF_SUPPORT_FLOAT)\n      case 'f' :\n      case 'F' :\n        if (*format == 'F') flags |= FLAGS_UPPERCASE;\n        idx = _ftoa(out, buffer, idx, maxlen, va_arg(va, double), precision, width, flags);\n        format++;\n        break;\n#if defined(PRINTF_SUPPORT_EXPONENTIAL)\n      case 'e':\n      case 'E':\n      case 'g':\n      case 'G':\n        if ((*format == 'g')||(*format == 'G')) flags |= FLAGS_ADAPT_EXP;\n        if ((*format == 'E')||(*format == 'G')) flags |= FLAGS_UPPERCASE;\n        idx = _etoa(out, buffer, idx, maxlen, va_arg(va, double), precision, width, flags);\n        format++;\n        break;\n#endif  // PRINTF_SUPPORT_EXPONENTIAL\n#endif  // PRINTF_SUPPORT_FLOAT\n      case 'c' : {\n        unsigned int l = 1U;\n        // pre padding\n        if (!(flags & FLAGS_LEFT)) {\n          while (l++ < width) {\n            out(' ', buffer, idx++, maxlen);\n          }\n        }\n        // char output\n        out((char)va_arg(va, int), buffer, idx++, maxlen);\n        // post padding\n        if (flags & FLAGS_LEFT) {\n          while (l++ < width) {\n            out(' ', buffer, idx++, maxlen);\n          }\n        }\n        format++;\n        break;\n      }\n\n      case 's' : {\n        const char* p = va_arg(va, char*);\n        unsigned int l = _strnlen_s(p, precision ? precision : (size_t)-1);\n        // pre padding\n        if (flags & FLAGS_PRECISION) {\n          l = (l < precision ? l : precision);\n        }\n        if (!(flags & FLAGS_LEFT)) {\n          while (l++ < width) {\n            out(' ', buffer, idx++, maxlen);\n          }\n        }\n        // string output\n        while ((*p != 0) && (!(flags & FLAGS_PRECISION) || precision--)) {\n          out(*(p++), buffer, idx++, maxlen);\n        }\n        // post padding\n        if (flags & FLAGS_LEFT) {\n          while (l++ < width) {\n            out(' ', buffer, idx++, maxlen);\n          }\n        }\n        format++;\n        break;\n      }\n\n      case 'p' : {\n        width = sizeof(void*) * 2U;\n        flags |= FLAGS_ZEROPAD | FLAGS_UPPERCASE;\n#if defined(PRINTF_SUPPORT_LONG_LONG)\n        const bool is_ll = sizeof(uintptr_t) == sizeof(long long);\n        if (is_ll) {\n          idx = _ntoa_long_long(out, buffer, idx, maxlen, (uintptr_t)va_arg(va, void*), false, 16U, precision, width, flags);\n        }\n        else {\n#endif\n          idx = _ntoa_long(out, buffer, idx, maxlen, (unsigned long)((uintptr_t)va_arg(va, void*)), false, 16U, precision, width, flags);\n#if defined(PRINTF_SUPPORT_LONG_LONG)\n        }\n#endif\n        format++;\n        break;\n      }\n\n      case '%' :\n        out('%', buffer, idx++, maxlen);\n        format++;\n        break;\n\n      default :\n        out(*format, buffer, idx++, maxlen);\n        format++;\n        break;\n    }\n  }\n\n  // termination\n  out((char)0, buffer, idx < maxlen ? idx : maxlen - 1U, maxlen);\n\n  // return written chars without terminating \\0\n  return (int)idx;\n}\n\n\n///////////////////////////////////////////////////////////////////////////////\n\nint PRINTF_FN(printf)(const char* format, ...)\n{\n  va_list va;\n  va_start(va, format);\n  char buffer[1];\n  const int ret = _vsnprintf(_out_char, buffer, (size_t)-1, format, va);\n  va_end(va);\n  return ret;\n}\n\n\nint PRINTF_FN(sprintf)(char* buffer, const char* format, ...)\n{\n  va_list va;\n  va_start(va, format);\n  const int ret = _vsnprintf(_out_buffer, buffer, (size_t)-1, format, va);\n  va_end(va);\n  return ret;\n}\n\n\nint PRINTF_FN(snprintf)(char* buffer, size_t count, const char* format, ...)\n{\n  va_list va;\n  va_start(va, format);\n  const int ret = _vsnprintf(_out_buffer, buffer, count, format, va);\n  va_end(va);\n  return ret;\n}\n\n\nint PRINTF_FN(vprintf)(const char* format, va_list va)\n{\n  char buffer[1];\n  return _vsnprintf(_out_char, buffer, (size_t)-1, format, va);\n}\n\n\nint PRINTF_FN(vsnprintf)(char* buffer, size_t count, const char* format, va_list va)\n{\n  return _vsnprintf(_out_buffer, buffer, count, format, va);\n}\n\n\nint PRINTF_FN(fctprintf)(void (*out)(char character, void* arg), void* arg, const char* format, ...)\n{\n  va_list va;\n  va_start(va, format);\n  const out_fct_wrap_type out_fct_wrap = { out, arg };\n  const int ret = _vsnprintf(_out_fct, (char*)(uintptr_t)&out_fct_wrap, (size_t)-1, format, va);\n  va_end(va);\n  return ret;\n}\n"
  },
  {
    "path": "src/mini_std/stdio_file.c",
    "content": "#include <stdio.h>\n#include <ace/types.h>\n#include <proto/dos.h>\n\n// Some things are implemented from scratch, some are based on:\n// https://github.com/deplinenoise/amiga-sdk/blob/master/netinclude/stdio.h\n\nFILE *fopen(const char *restrict szFileName, const char *restrict szMode) {\n\t// http://amigadev.elowar.com/read/ADCD_2.1/Includes_and_Autodocs_3._guide/node0196.html\n\tif(!szMode) {\n\t\treturn 0;\n\t}\n\n\tLONG lAccessMode = 0;\n\twhile(*szMode != '\\0') {\n\t\tswitch(*szMode) {\n\t\t\tcase 'r':\n\t\t\t\tlAccessMode |= MODE_OLDFILE;\n\t\t\t\tbreak;\n\t\t\tcase 'w':\n\t\t\t\tlAccessMode |= MODE_NEWFILE;\n\t\t\t\tbreak;\n\t\t\tcase 'b':\n\t\t\t\t// Binary - ignore, no difference here\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\t// Unsupported\n\t\t\t\treturn 0;\n\t\t}\n\t\t++szMode;\n\t}\n\n\tBPTR bpFile = Open((CONST_STRPTR)szFileName, lAccessMode);\n\treturn (FILE *)bpFile;\n}\n\nsize_t fread(void *restrict pBuffer, size_t Size, size_t Count, FILE *restrict pStream) {\n\t// http://amigadev.elowar.com/read/ADCD_2.1/Includes_and_Autodocs_3._guide/node01A0.html\n\tunsigned char *pByteBuffer = (unsigned char *)pBuffer;\n\tsize_t BytesRead = 0;\n\twhile(Count--) {\n\t\t// FIXME: handle 0/negative vals\n\t\tBytesRead += Read((BPTR)pStream, pByteBuffer, Size);\n\t\tpByteBuffer += Size;\n\t}\n\treturn BytesRead;\n}\n\nsize_t fwrite(const void *restrict pBuffer, size_t Size, size_t Count, FILE *restrict pStream) {\n\t// http://amigadev.elowar.com/read/ADCD_2.1/Includes_and_Autodocs_3._guide/node01D1.html\n\tunsigned char *pByteBuffer = (unsigned char *)pBuffer;\n\tsize_t BytesWritten = 0;\n\twhile(Count--) {\n\t\tBytesWritten += Write((BPTR)pStream, pByteBuffer, Size);\n\t\tpByteBuffer += Size;\n\t}\n\treturn BytesWritten;\n}\n\nint fclose(FILE *pStream) {\n\t// http://www.cplusplus.com/reference/cstdio/fclose/\n\t// http://amigadev.elowar.com/read/ADCD_2.1/Includes_and_Autodocs_3._guide/node0149.html\n\t// NOTE: Close() doesn't return anything in ks1.3! So we'll just return success.\n\tClose((BPTR)pStream);\n\treturn 0;\n}\n\nint fseek(FILE *pStream, long Offset, int Origin) {\n\t// http://amigadev.elowar.com/read/ADCD_2.1/Includes_and_Autodocs_3._guide/node01AD.html\n\tLONG lOriginDos = OFFSET_CURRENT;\n\tif(Origin == SEEK_SET) {\n\t\tlOriginDos = OFFSET_BEGINNING;\n\t}\n\telse if(Origin == SEEK_END) {\n\t\tlOriginDos = OFFSET_END;\n\t}\n\tSeek((BPTR)pStream, Offset, lOriginDos);\n\t// FIXME: proper check for result\n\treturn 0;\n}\n\nint fflush(UNUSED_ARG FILE *pStream) {\n\t// http://amigadev.elowar.com/read/ADCD_2.1/Includes_and_Autodocs_3._guide/node016A.html\n\t// Write is unbuffered so no need for flushing\n\treturn 0;\n}\n\nlong ftell(FILE *pStream) {\n\tLONG lPos = Seek((BPTR)pStream, 0L, OFFSET_CURRENT);\n\treturn lPos;\n}\n\nint feof(FILE *pStream) {\n\t/* Seek returns previous position; seek-to-end moves to EOF and reports prior offset. */\n\tLONG lSavedPos = Seek((BPTR)pStream, 0L, OFFSET_END);\n\tLONG lEnd = Seek((BPTR)pStream, 0L, OFFSET_CURRENT);\n\tSeek((BPTR)pStream, lSavedPos, OFFSET_BEGINNING);\n\treturn lSavedPos == lEnd;\n}\n\nint rename(const char *szSource, const char *szDestination) {\n\treturn Rename((CONST_STRPTR)szSource, (CONST_STRPTR)szDestination) != 0;\n}\n\nint remove(const char *szFilePath) {\n\treturn DeleteFile((CONST_STRPTR)szFilePath) != 0;\n}\n"
  },
  {
    "path": "src/mini_std/stdio_putchar.c",
    "content": "#include <stdio.h>\n#include <proto/dos.h>\n\nvoid _putchar(char character) {\n\tWrite(Output(), &character, 1);\n}\n"
  },
  {
    "path": "src/mini_std/stdlib.c",
    "content": "#include <proto/dos.h>\n#include <sort_r.h>\n\nstatic int (*s_qsortComp)(const void *, const void *);\n\nvoid exit(int exit_code) {\n\t// FIXME: implement better, Exit() shouldn't be used.\n\t// http://amigadev.elowar.com/read/ADCD_2.1/Includes_and_Autodocs_2._guide/node029F.html\n\t// This is what Bartman's project template uses.\n\n\tExit(exit_code);\n\twhile(1) continue;\n}\n\nint qsortEmu(const void *_a, const void *_b, __attribute__((unused)) void *_arg) {\n\treturn s_qsortComp(_a, _b);\n}\n\nvoid qsort(\n\tvoid *ptr, size_t count, size_t size, int (*comp)(const void *, const void *)\n) {\n\t// sort_r requires extra arg so call fixed callback which calls regular qsort cb\n\n\ts_qsortComp = comp;\n\tsort_r(ptr, count, size, qsortEmu, 0);\n}\n"
  },
  {
    "path": "src/mini_std/string.c",
    "content": "#include <string.h>\n\nint memcmp(const void *pLhs, const void *pRhs, size_t count) {\n\t// https://en.cppreference.com/w/c/string/byte/memcmp\n\tunsigned char *pLeft = (unsigned char *)pLhs;\n\tunsigned char *pRight = (unsigned char *)pRhs;\n\twhile(count--) {\n\t\tint delta = *pLeft - *pRight;\n\t\tif(delta != 0) {\n\t\t\treturn delta;\n\t\t}\n\t\t++pLeft;\n\t\t++pRight;\n\t}\n\treturn 0;\n}\n\nunsigned long strtoul(const char *restrict str, char **restrict str_end, int base);\n\nchar *strchr(const char *szHaystack, int cNeedle) {\n\t// https://en.cppreference.com/w/c/string/byte/strchr\n\twhile(*szHaystack != '\\0') {\n\t\tif(*szHaystack == cNeedle) {\n\t\t\treturn (char*)szHaystack;\n\t\t}\n\t\t++szHaystack;\n\t}\n\treturn 0;\n}\n\nchar *strrchr(const char *szHaystack, int cNeedle) {\n\t// https://en.cppreference.com/w/c/string/byte/strrchr\n\tchar *pLast = 0;\n\twhile(*szHaystack != '\\0') {\n\t\tif(*szHaystack == cNeedle) {\n\t\t\tpLast = (char*)szHaystack;\n\t\t}\n\t\t++szHaystack;\n\t}\n\treturn pLast;\n}\n\nchar *strcpy(char *restrict szDest, const char *restrict szSrc) {\n\t// Also copy null terminator\n\tmemcpy(szDest, szSrc, strlen(szSrc) + 1);\n\treturn szDest;\n}\n\nchar *strcat(char *restrict szDest, const char *restrict szSrc) {\n\tstrcpy(&szDest[strlen(szDest)], szSrc);\n\treturn szDest;\n}\n\nint strcmp(const char *szA, const char *szB) {\n\t// https://en.cppreference.com/w/c/string/byte/strcmp\n\n\t// It's ok to check only bounds of szA since if szB is shorter then its null\n\t// terminator won't be the same as szA's char on same pos.\n\twhile(*szA) {\n\t\t// If chars are not the same, return the difference.\n\t\tif(*szA != *szB) {\n\t\t\treturn *szA - *szB;\n\t\t}\n\t\t++szA;\n\t\t++szB;\n\t}\n\n\t// szB is longer or equal to szA - return the difference.\n\treturn *szA - *szB;\n}\n\nchar *strncpy(char *restrict szDest, const char *restrict szSrc, size_t Count) {\n\t// https://en.cppreference.com/w/c/string/byte/strncpy\n\n\t// Calculate actual copy length.\n\tsize_t Len = strlen(szSrc);\n\tif(Len > Count) {\n\t\tLen = Count;\n\t}\n\n\t// If the first count characters were non-null, dest will not contain a null\n\t// terminated string!\n\tmemcpy(szDest, szSrc, Len);\n\n\t// Zeroes out the rest of the destination buffer, which can be\n\t// a performance concern.\n\tmemset(&szDest[Len], 0, Count - Len);\n\treturn szDest;\n}\n"
  },
  {
    "path": "src/mini_std/strtoul.c",
    "content": "#include <ctype.h>\n#include <errno.h>\n#include <limits.h>\n#include <stdlib.h>\n#include \"stdio.h\"\n\nunsigned long strtoul(const char *nptr, char **endptr, int base)\n{\n\tconst char *p = nptr, *q;\n\tchar c = 0;\n\tunsigned long r = 0;\n\tif (base < 0 || base == 1 || base > 36)\n\t{\n\t\tif (endptr != NULL)\n\t\t\t*endptr = (char *)nptr;\n\t\terrno = EINVAL;\n\t\treturn 0;\n\t}\n\tif (!(nptr && *nptr))\n\t{\n\t\terrno = EINVAL;\n\t\treturn 0;\n\t}\n\twhile (isspace((int)*p))\n\t\tp++;\n\tif (*p == '-' || *p == '+')\n\t\tc = *p++;\n\tif (base == 0)\n\t{\n\t\tif (p[0] == '0')\n\t\t{\n\t\t\tif (tolower((int)p[1]) == 'x' && isxdigit((int)p[2]))\n\t\t\t{\n\t\t\t\tp += 2;\n\t\t\t\tbase = 16;\n\t\t\t}\n\t\t\telse\n\t\t\t\tbase = 8;\n\t\t}\n\t\telse\n\t\t\tbase = 10;\n\t}\n\telse\n\t{\n\t\tif (base == 16 && p[0] == '0' && p[1] == 'x' && isxdigit(p[2]))\n\t\t\tp += 2;\n\t}\n\tq = p;\n\tfor (;;)\n\t{\n\t\tint a;\n\t\tif (!isalnum((int)*q))\n\t\t\tbreak;\n\t\ta = isdigit((int)*q) ? *q - '0' : tolower((int)*q) - ('a' - 10);\n\t\tif (a >= base)\n\t\t\tbreak;\n\t\tif (r > (ULONG_MAX - a) / base || r * base > ULONG_MAX - a)\n\t\t{\n\t\t\terrno = ERANGE; /* overflow */\n\t\t\tr = ULONG_MAX;\n\t\t\tc = 0;\n\t\t}\n\t\telse\n\t\t\tr = r * base + a;\n\t\tq++;\n\t}\n\tif (q == p) /* Not a single number read */\n\t{\n\t\tif (endptr != NULL)\n\t\t\t*endptr = (char *)nptr;\n\t\treturn 0;\n\t}\n\tif (c == '-')\n\t\tr = -r;\n\tif (endptr != NULL)\n\t\t*endptr = (char *)q;\n\treturn r;\n}\n"
  },
  {
    "path": "tools/.gitignore",
    "content": "# C compiler intermediate files\n*.o\n\n# Input file types\n*.jpg\n*.png\n*.gpl\n\n# Output file types\n*.plt\n*.bm\n\n# Varia\n*.lnk"
  },
  {
    "path": "tools/CMakeLists.txt",
    "content": "cmake_minimum_required(VERSION 3.14.0)\n# Generator expression skips Debug/Release/... directories for MSVC\nset(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/bin/$<0:>)\nproject(ACE_tools)\n\n# Adhere to GNU filesystem layout conventions\ninclude(GNUInstallDirs)\ninclude(../cmake/CPM.cmake)\nset(CMAKE_CXX_STANDARD 20)\n\n# MSVC needs a few defines to be GNU compatible\nif(MSVC)\n    add_compile_definitions(_USE_MATH_DEFINES=1 NOMINMAX=1)\nendif()\n\nCPMAddPackage(\"gh:fmtlib/fmt#10.0.0\")\nCPMAddPackage(\n\tNAME freetype\n\tVERSION 2.14.1\n\tGITHUB_REPOSITORY freetype/freetype\n\tGIT_TAG VER-2-14-1\n\tOPTIONS \"FT_DISABLE_HARFBUZZ 1\" \"FT_DISABLE_BROTLI 1\"\n)\n#TODO: lodepng\n\n# Common\nfile(GLOB COMMON_src src/common/*.cpp src/common/*.c)\nfile(GLOB_RECURSE COMMON_hdr src/common/*.h src/common/*.hpp)\nadd_library(common STATIC ${COMMON_src} ${COMMON_hdr})\nif(MINGW)\n\tmessage(STATUS \"Building STATIC executables\")\n\ttarget_link_libraries(common PUBLIC -static)\nendif()\ntarget_link_libraries(common PUBLIC freetype fmt::fmt)\ntarget_include_directories(common PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/../include)\n\n# App-related\nfile(GLOB FONT_CONV_src src/font_conv.cpp)\nfile(GLOB PALETTE_CONV_src src/palette_conv.cpp)\nfile(GLOB BITMAP_TRANSFORM_src src/bitmap_transform.cpp)\nfile(GLOB TILESET_CONV_src src/tileset_conv.cpp)\nfile(GLOB BITMAP_CONV_src src/bitmap_conv.cpp)\nfile(GLOB AUDIO_CONV_src src/audio_conv.cpp)\nfile(GLOB MOD_TOOL_src src/mod_tool.cpp)\nfile(GLOB PAK_TOOL_src src/pak_tool.cpp)\n\nadd_executable(font_conv ${FONT_CONV_src})\nadd_executable(palette_conv ${PALETTE_CONV_src})\nadd_executable(bitmap_transform ${BITMAP_TRANSFORM_src})\nadd_executable(tileset_conv ${TILESET_CONV_src})\nadd_executable(bitmap_conv ${BITMAP_CONV_src})\nadd_executable(audio_conv ${AUDIO_CONV_src})\nadd_executable(mod_tool ${MOD_TOOL_src})\nadd_executable(pak_tool ${PAK_TOOL_src})\n\ntarget_link_libraries(font_conv common)\ntarget_link_libraries(palette_conv common)\ntarget_link_libraries(bitmap_transform common)\ntarget_link_libraries(tileset_conv common)\ntarget_link_libraries(bitmap_conv common)\ntarget_link_libraries(audio_conv common)\ntarget_link_libraries(mod_tool common)\ntarget_link_libraries(pak_tool common)\n"
  },
  {
    "path": "tools/src/audio_conv.cpp",
    "content": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at http://mozilla.org/MPL/2.0/. */\n\n#include <optional>\n#include \"common/logging.h\"\n#include \"common/fs.h\"\n#include \"common/sfx.h\"\n#include \"common/wav.h\"\n#include \"common/math.h\"\n\nvoid printUsage(const std::string &szAppName) {\n\tusing fmt::print;\n\tprint(\"Usage:\\n\\t{} inPath [extraOpts]\\n\\n\", szAppName);\n\tprint(\"Required arguments:\\n\");\n\tprint(\"\\tinPath      Path to supported file format\\n\");\n\tprint(\"Extra options:\\n\");\n\tprint(\"\\t-o outPath  Specify output file path. If ommited, it will perform default conversion\\n\");\n\tprint(\"\\t-c          Enable compression for output file\\n\");\n\tprint(\"\\t-d N        Specify amplitude division. Useful for some audio-mixing libraries\\n\");\n\tprint(\"\\t-cd N       Check if sound effect fits max amplitude divided by specified factor and raise error otherwise. Useful for some audio-mixing libraries\\n\");\n\tprint(\"\\t-strict     Treat warinings as errors (recommended)\\n\");\n\tprint(\"\\t-n          Normalize audio files\\n\");\n\tprint(\"\\t-fpt        Enforce ptplayer-friendly mode: adds empty sample at the beginning, if missing\\n\");\n\tprint(\"\\t-fpad N     Force given byte-padding\\n\");\n\tprint(\"\\t-sa N       Split sample after every given number of bytes, or kbytes if value ends with k\\n\");\n\tprint(\"Default conversions:\\n\");\n\tprint(\"\\t.wav -> .sfx\\n\");\n\tprint(\"\\t.sfx -> .wav\\n\");\n}\n\nint main(int lArgCount, const char *pArgs[]) {\n\tusing namespace std::string_view_literals;\n\n\tstd::uint8_t ubMandatoryArgCnt = 2;\n\n\tif(lArgCount - 1 < ubMandatoryArgCnt) {\n\t\tnLog::error(\"Too few arguments, expected {}\", ubMandatoryArgCnt);\n\t\tprintUsage(pArgs[0]);\n\t\treturn EXIT_FAILURE;\n\t}\n\n\tbool isCompressed = false;\n\tbool isStrict = false;\n\tbool isNormalizing = false;\n\tstd::uint8_t ubDivisor = 1;\n\tstd::uint8_t ubFitDivisor = 1;\n\tstd::string szInput(pArgs[1]);\n\tstd::string szOutput;\n\tbool isForcePt = false;\n\tstd::optional<uint8_t> oForcePad;\n\tstd::optional<uint32_t> oSplitAfter;\n\tfor(auto ArgIndex = 2; ArgIndex < lArgCount; ++ArgIndex) {\n\t\tstd::string_view Arg = pArgs[ArgIndex];\n\t\tif(Arg == \"-o\"sv && ArgIndex < lArgCount -1) {\n\t\t\tszOutput = pArgs[++ArgIndex];\n\t\t}\n\t\telse if(Arg == \"-c\"sv) {\n\t\t\tisCompressed = true;\n\t\t}\n\t\telse if(Arg == \"-d\"sv && ArgIndex < lArgCount -1) {\n\t\t\tubDivisor = uint8_t(std::stoul(pArgs[++ArgIndex]));\n\t\t\tif(ubDivisor == 0) {\n\t\t\t\tnLog::error(\"Illegal -d value: '{}'\", ubDivisor);\n\t\t\t\treturn EXIT_FAILURE;\n\t\t\t}\n\t\t}\n\t\telse if(Arg == \"-cd\"sv && ArgIndex < lArgCount -1) {\n\t\t\tubFitDivisor = uint8_t(std::stoul(pArgs[++ArgIndex]));\n\t\t\tif(ubFitDivisor == 0) {\n\t\t\t\tnLog::error(\"Illegal -cd value: '{}'\", ubFitDivisor);\n\t\t\t\treturn EXIT_FAILURE;\n\t\t\t}\n\t\t}\n\t\telse if(Arg == \"-n\"sv) {\n\t\t\tisNormalizing = true;\n\t\t}\n\t\telse if(Arg == \"-strict\"sv) {\n\t\t\tisStrict = true;\n\t\t}\n\t\telse if(Arg == \"-fpt\"sv) {\n\t\t\tisForcePt = true;\n\t\t\toForcePad = std::min<uint8_t>(oForcePad.value_or(0), 2);\n\t\t}\n\t\telse if(Arg == \"-fpad\"sv && ArgIndex < lArgCount -1) {\n\t\t\toForcePad = uint8_t(std::stoul(pArgs[++ArgIndex]));\n\t\t\tif(oForcePad.value() < 1 || 4 < oForcePad.value()) {\n\t\t\t\tnLog::error(\"Illegal -fpad value: '{}'\", oForcePad.value());\n\t\t\t\treturn EXIT_FAILURE;\n\t\t\t}\n\t\t}\n\t\telse if(Arg == \"-sa\"sv && ArgIndex < lArgCount -1) {\n\t\t\tstd::string_view Value(pArgs[++ArgIndex]);\n\t\t\tstd::size_t CharsParsed = 0;\n\t\t\tauto ValueEnd = Value.end();\n\t\t\toSplitAfter = uint32_t(std::stoul(Value.data(), &CharsParsed));\n\t\t\tif(CharsParsed < Value.size() && Value[CharsParsed] == 'k') {\n\t\t\t\toSplitAfter = oSplitAfter.value() * 1024;\n\t\t\t}\n\t\t}\n\t\telse {\n\t\t\tnLog::error(\"Unknown arg or missing value: '{}'\", pArgs[ArgIndex]);\n\t\t\tprintUsage(pArgs[0]);\n\t\t\treturn EXIT_FAILURE;\n\t\t}\n\t}\n\n\t// Determine output path and extension\n\tstd::string szInExt = nFs::getExt(szInput);\n\tif(szInExt != \"wav\") {\n\t\tnLog::error(\"Input file type not supported: {}\", szInExt);\n\t\tprintUsage(pArgs[0]);\n\t\treturn EXIT_FAILURE;\n\t}\n\n\tif(szOutput.empty()) {\n\t\tszOutput = nFs::removeExt(szInput);\n\t\tif(szInExt == \"wav\") {\n\t\t\tszOutput += \".sfx\";\n\t\t}\n\t}\n\tstd::string szOutExt = nFs::getExt(szOutput);\n\n\t// Load input\n\ttSfx In;\n\tif(szInExt == \"wav\") {\n\t\ttWav Wav(szInput);\n\t\tif(Wav.getData().empty()) {\n\t\t\tnLog::error(\"No data read from WAV file\");\n\t\t\treturn EXIT_FAILURE;\n\t\t}\n\t\tIn = tSfx(Wav, isStrict);\n\t\tif(In.isEmpty()) {\n\t\t\tnLog::error(\"No valid data to convert\");\n\t\t\treturn EXIT_FAILURE;\n\t\t}\n\t}\n\telse {\n\t\tnLog::error(\"Input file type not supported: {}\", szInExt);\n\t\treturn EXIT_FAILURE;\n\t}\n\n\t// Ptplayer-like requirements\n\tif(isForcePt) {\n\t\tIn.enforceEmptyFirstWord();\n\t}\n\n\t// Mixer-like requirements\n\tif(isNormalizing) {\n\t\tIn.normalize();\n\t}\n\tif(ubDivisor != 1) {\n\t\tIn.divideAmplitude(ubDivisor);\n\t}\n\n\tstd::int8_t bMaxAmplitude = std::numeric_limits<int8_t>::max() / ubFitDivisor;\n\tif(!In.isFittingMaxAmplitude(bMaxAmplitude)) {\n\t\tnLog::error(\n\t\t\t\"Sound effect doesn't fit the amplitude divisor {}, max amplitude: {}\",\n\t\t\tubFitDivisor, bMaxAmplitude\n\t\t);\n\t}\n\n\tif(oForcePad.has_value()) {\n\t\tIn.padContents(oForcePad.value());\n\t}\n\n\tif(oSplitAfter.has_value()) {\n\t\tauto PartCount = (In.getLength() + oSplitAfter.value() - 1) / oSplitAfter.value();\n\t\tfmt::print(\"Splitting to {} parts, {} bytes each\\n\", PartCount, oSplitAfter.value());\n\t\tstd::uint8_t ubPart = 0;\n\t\ttSfx SfxRemaining;\n\t\tauto BaseOutputPath = nFs::removeExt(szOutput);\n\t\tdo {\n\t\t\tSfxRemaining = In.splitAfter(oSplitAfter.value());\n\t\t\tauto PartOutPath = fmt::format(FMT_STRING(\"{}_{}.{}\"), BaseOutputPath, ubPart, szOutExt);\n\t\t\tfmt::print(\"Writing to {}\\n\", PartOutPath);\n\t\t\tif(szOutExt == \"sfx\") {\n\t\t\t\tif(!In.toSfx(PartOutPath, isCompressed)) {\n\t\t\t\t\treturn EXIT_FAILURE;\n\t\t\t\t}\n\t\t\t}\n\t\t\telse {\n\t\t\t\tnLog::error(\"Output file type not supported: {}\", szInExt);\n\t\t\t\treturn EXIT_FAILURE;\n\t\t\t}\n\n\t\t\tIn = SfxRemaining;\n\t\t\t++ubPart;\n\t\t} while(!SfxRemaining.isEmpty());\n\t}\n\telse {\n\t\t// Save to output\n\t\tfmt::print(\"Writing to {}...\\n\", szOutput);\n\t\tif(szOutExt == \"sfx\") {\n\t\t\tif(!In.toSfx(szOutput, isCompressed)) {\n\t\t\t\treturn EXIT_FAILURE;\n\t\t\t}\n\t\t}\n\t\telse {\n\t\t\tnLog::error(\"Output file type not supported: {}\", szInExt);\n\t\t\treturn EXIT_FAILURE;\n\t\t}\n\t}\n\n\n\tfmt::print(\"All done!\\n\");\n}\n"
  },
  {
    "path": "tools/src/bitmap_conv.cpp",
    "content": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at http://mozilla.org/MPL/2.0/. */\n\n#include \"common/logging.h\"\n#include \"common/fs.h\"\n#include \"common/rgb.h\"\n#include \"common/bitmap.h\"\n\nvoid printUsage(const std::string &szAppName)\n{\n\tusing fmt::print;\n\tprint(\"Usage:\\n\\t{} palPath inPath [extraOpts]\\n\\n\", szAppName);\n\tprint(\"palPath\\t - path to supported palette file\\n\");\n\tprint(\"inPath\\t - path to supported input bitmap file\\n\");\n\tprint(\"extraOpts:\\n\");\n\tprint(\"\\t-o outPath\\tSpecify output file path. If ommited, it will perform default conversion\\n\");\n\tprint(\"\\t-i\\t\\tEnable interleaved mode\\n\");\n\tprint(\"\\t-ehb\\t\\tExtend palette with EHB colors\\n\");\n\tprint(\"\\t-mc #RRGGBB\\tTreat color #RRGGBB as mask\\n\");\n\tprint(\"\\t-mf outMaskPath\\tSpecify path for mask.bm file. If omitted, it will try\\n\");\n\tprint(\"\\t\\t\\tto use same path as .bm with \\\"_mask.bm\\\" suffix\\n\");\n\tprint(\"\\t-nmo\\t\\tDon't generate mask output file\\n\");\n\tprint(\"\\t-no\\t\\tDon't generate bitplane output file\\n\");\n\tprint(\"Default conversions:\\n\");\n\tprint(\"\\t.bm -> .png (will try to read mask from inPath_mask.bm)\\n\");\n\tprint(\"\\t.png -> .bm (will write mask to outPath_mask.bm if -mc was specified)\\n\");\n}\n\nint main(int lArgCount, const char *pArgs[])\n{\n\tconst std::uint8_t ubMandatoryArgCnt = 2;\n\tif(lArgCount - 1 < ubMandatoryArgCnt) {\n\t\tnLog::error(\"Too few arguments, expected {}\", ubMandatoryArgCnt);\n\t\tprintUsage(pArgs[0]);\n\t\treturn EXIT_FAILURE;\n\t}\n\n\tstd::string szPalette = pArgs[1], szInput = pArgs[2];\n\tstd::string szOutput = \"\", szMask = \"\";\n\tbool isWriteInterleaved = false;\n\tbool isEhb = false;\n\tbool isEnabledOutputMask = true;\n\tbool isEnabledOutput = true;\n\tbool isMaskColor = false;\n\ttRgb MaskColor;\n\n\tfor(auto ArgIndex = ubMandatoryArgCnt + 1; ArgIndex < lArgCount; ++ArgIndex) {\n\t\tif(pArgs[ArgIndex] == std::string(\"-o\")) {\n\t\t\tauto &Value = pArgs[++ArgIndex];\n\t\t\tszOutput = Value;\n\t\t}\n\t\telse if(pArgs[ArgIndex] == std::string(\"-i\")) {\n\t\t\tisWriteInterleaved = true;\n\t\t}\n\t\telse if(pArgs[ArgIndex] == std::string(\"-ehb\")) {\n\t\t\tisEhb = true;\n\t\t}\n\t\telse if(pArgs[ArgIndex] == std::string(\"-mc\") && ArgIndex < lArgCount - 1) {\n\t\t\tisMaskColor = true;\n\t\t\tauto &Value = pArgs[++ArgIndex];\n\t\t\tMaskColor = tRgb(Value);\n\t\t}\n\t\telse if(pArgs[ArgIndex] == std::string(\"-mf\") && ArgIndex < lArgCount - 1) {\n\t\t\tauto &Value = pArgs[++ArgIndex];\n\t\t\tszMask = Value;\n\t\t}\n\t\telse if(pArgs[ArgIndex] == std::string(\"-nmo\")) {\n\t\t\tisEnabledOutputMask = false;\n\t\t}\n\t\telse if(pArgs[ArgIndex] == std::string(\"-no\")) {\n\t\t\tisEnabledOutput = false;\n\t\t}\n\t\telse {\n\t\t\tnLog::error(\"Unknown arg or missing value: '{}'\", pArgs[ArgIndex]);\n\t\t\tprintUsage(pArgs[0]);\n\t\t\treturn EXIT_FAILURE;\n\t\t}\n\t}\n\n\tstd::string szInExt = nFs::getExt(szInput);\n\tif(szInExt != \"png\" && szInExt != \"bm\") {\n\t\tnLog::error(\"Input file type not supported: {}\", szInExt);\n\t\tprintUsage(pArgs[0]);\n\t\treturn EXIT_FAILURE;\n\t}\n\tif(szOutput.empty()) {\n\t\tszOutput = nFs::removeExt(szInput);\n\t\tif(szInExt == \"png\") {\n\t\t\tszOutput += \".bm\";\n\t\t}\n\t\telse if(szInExt == \"bm\") {\n\t\t\tszOutput += \".png\";\n\t\t}\n\t}\n\tstd::string szOutExt = nFs::getExt(szOutput);\n\n\tif(szMask == \"\" && isMaskColor) {\n\t\tif(szOutExt == \"bm\") {\n\t\t\tszMask = nFs::removeExt(szOutput) + \"_mask.\" + szOutExt;\n\t\t}\n\t\telse if(szInExt == \"bm\") {\n\t\t\tszMask = nFs::removeExt(szInput) + \"_mask.\" + szInExt;\n\t\t}\n\t}\n\n\t// Load palette\n\tauto Palette = tPalette::fromFile(szPalette);\n\tif(!Palette.isValid()) {\n\t\tnLog::error(\"Couldn't read palette '{}'\", szPalette);\n\t\treturn EXIT_FAILURE;\n\t}\n\tif(isEhb) {\n\t\tif(!Palette.convertToEhb()) {\n\t\t\tnLog::error(\"Couldn't convert palette to EHB! Does it have at most 32 colors?\");\n\t\t}\n\t}\n\n\n\t// Load input\n\ttChunkyBitmap In;\n\tif(szInExt == \"bm\") {\n\t\tauto InPlanar = tPlanarBitmap::fromBm(szInput);\n\t\tif(!InPlanar.m_uwWidth) {\n\t\t\tnLog::error(\"Couldn't load input: '{}'\", szInput);\n\t\t}\n\t\tIn = tChunkyBitmap(InPlanar, Palette);\n\t\tif(isMaskColor) {\n\t\t\ttPalette PaletteMask;\n\t\t\tPaletteMask.m_vColors.push_back(tRgb(0,0,0));\n\t\t\tfor(std::uint16_t i = 1; i < 256; ++i) {\n\t\t\t\tPaletteMask.m_vColors.push_back(MaskColor);\n\t\t\t}\n\t\t\tauto szInMask = nFs::removeExt(szInput) + \"_mask.\" + szInExt;\n\t\t\tauto InMask = tChunkyBitmap(tPlanarBitmap::fromBm(szInMask), PaletteMask);\n\t\t\tif(!In.mergeWithMask(InMask)) {\n\t\t\t\tnLog::error(\"Mask incompatible with bitmap\");\n\t\t\t\treturn EXIT_FAILURE;\n\t\t\t}\n\t\t}\n\t}\n\telse if(szInExt == \"png\") {\n\t\tIn = tChunkyBitmap::fromPng(szInput);\n\t}\n\telse {\n\t\tnLog::error(\"Input file type not supported: {}\", szInExt);\n\t\treturn EXIT_FAILURE;\n\t}\n\n\t// Save to output\n\tif(szOutExt == \"bm\") {\n\t\ttPalette PaletteMask;\n\t\tif(isMaskColor) {\n\t\t\ttRgb MaskAntiColor(~MaskColor.ubR, ~MaskColor.ubG, ~MaskColor.ubB);\n\t\t\t// Generate mask palette - 0 is transparent, everything else is not\n\t\t\tif(isWriteInterleaved) {\n\t\t\t\tauto PaletteSize = 1u << Palette.getBpp();\n\t\t\t\tPaletteMask.m_vColors.resize(PaletteSize, tRgb(1, 1, 1));\n\t\t\t\tPaletteMask.m_vColors.front() = MaskColor;\n\t\t\t\tPaletteMask.m_vColors.back() = MaskAntiColor;\n\t\t\t}\n\t\t\telse {\n\t\t\t\tPaletteMask.m_vColors.push_back(MaskColor);\n\t\t\t\tPaletteMask.m_vColors.push_back(MaskAntiColor);\n\t\t\t}\n\t\t\tif(isEnabledOutputMask) {\n\t\t\t\tconst auto Mask = In.filterColors(PaletteMask, MaskAntiColor);\n\t\t\t\ttPlanarBitmap(Mask, PaletteMask).toBm(szMask, isWriteInterleaved);\n\t\t\t}\n\t\t}\n\t\tauto Planar = tPlanarBitmap(In, Palette, PaletteMask);\n\t\tif(!Planar.m_uwWidth) {\n\t\t\treturn EXIT_FAILURE;\n\t\t}\n\t\tif(isEnabledOutput) {\n\t\t\tPlanar.toBm(szOutput, isWriteInterleaved);\n\t\t}\n\t}\n\telse if(szOutExt == \"png\") {\n\t\tIn.toPng(szOutput);\n\t}\n\n\treturn EXIT_SUCCESS;\n}\n"
  },
  {
    "path": "tools/src/bitmap_transform.cpp",
    "content": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at http://mozilla.org/MPL/2.0/. */\n\n#include <memory>\n#include \"common/bitmap.h\"\n#include \"common/logging.h\"\n#include \"common/parse.h\"\n\nclass tOp {\npublic:\n\tvirtual tChunkyBitmap execute(const tChunkyBitmap &Src) = 0;\n\tvirtual std::string toString(void) = 0;\n};\n\nclass tOpExtract: public tOp {\npublic:\n\ttOpExtract(std::uint16_t uwX, std::uint16_t uwY, std::uint16_t uwW, std::uint16_t uwH);\n\tvirtual tChunkyBitmap execute(const tChunkyBitmap &Src);\n\tvirtual std::string toString(void);\nprivate:\n\tstd::uint16_t m_uwX, m_uwY, m_uwW, m_uwH;\n};\n\nclass tOpRotate: public tOp {\npublic:\n\ttOpRotate(\n\t\tdouble dDeg, tRgb Bg,\n\t\tdouble dCenterX, double dCenterY\n\t);\n\tvirtual tChunkyBitmap execute(const tChunkyBitmap &Src);\n\tvirtual std::string toString(void);\nprivate:\n\tdouble m_dDeg;\n\ttRgb m_Bg;\n\tdouble m_dCenterX;\n\tdouble m_dCenterY;\n};\n\nclass tOpMirror: public tOp {\npublic:\n\tenum class tAxis {\n\t\tX, Y\n\t};\n\n\ttOpMirror(tAxis eAxis);\n\tvirtual tChunkyBitmap execute(const tChunkyBitmap &Src);\n\tvirtual std::string toString(void);\nprivate:\n\ttAxis m_eAxis;\n};\n\nvoid printUsage(const std::string &szAppName)\n{\n\tusing fmt::print;\n\tprint(\"Usage:\\n\\t{} in.png out.png [transforms]\\n\", szAppName);\n\tprint(\"\\nAvailable transforms, done in passed order:\\n\");\n\tprint(\"\\t-extract x y width height\\tExtract rectangle at x,y of size width*height.\\n\");\n\tprint(\"\\t-rotate deg bgcolor cx cy\\tRotate clockwise by given number of degrees around cx,cy. Values can be floats/negative.\\n\");\n\tprint(\"\\t-mirror x|y              \\tMirror image along x or y axis.\\n\");\n\tprint(\"\\nCurrently only PNG is supported, sorry!\\n\");\n}\n\nint main(int lArgCount, char *pArgs[])\n{\n\tif(lArgCount - 1 < 2) {\n\t\tnLog::error(\n\t\t\t\"Invalid number of arguments, got {}, expected at least 2\", lArgCount - 1\n\t\t);\n\t\tprintUsage(pArgs[0]);\n\t\treturn EXIT_FAILURE;\n\t}\n\n\tstd::string szSrcPath = pArgs[1];\n\tauto Img = tChunkyBitmap::fromPng(szSrcPath);\n\tif(!Img.m_uwHeight) {\n\t\tnLog::error(\"Couldn't open image '{}'\", szSrcPath);\n\t\treturn EXIT_FAILURE;\n\t}\n\n\tstd::vector<std::unique_ptr<tOp>> vOps;\n\n\tfor(auto ArgIndex = 3; ArgIndex < lArgCount; ++ArgIndex) {\n\t\tconst std::string_view szOp = pArgs[ArgIndex];\n\t\tif(szOp == \"-extract\") {\n\t\t\tif(ArgIndex + 4 >= lArgCount) {\n\t\t\t\tnLog::error(\n\t\t\t\t\t\"Too few args for {} - first arg at pos {}, arg count: {}\",\n\t\t\t\t\tszOp, ArgIndex + 1, lArgCount\n\t\t\t\t);\n\t\t\t\treturn EXIT_FAILURE;\n\t\t\t}\n\t\t\tauto ArgStart = ArgIndex + 1;\n\t\t\ttry {\n\t\t\t\tauto X = uint16_t(std::stoul(pArgs[++ArgIndex]));\n\t\t\t\tauto Y = uint16_t(std::stoul(pArgs[++ArgIndex]));\n\t\t\t\tauto W = uint16_t(std::stoul(pArgs[++ArgIndex]));\n\t\t\t\tauto H = uint16_t(std::stoul(pArgs[++ArgIndex]));\n\t\t\t\tvOps.push_back(std::make_unique<tOpExtract>(X, Y, W, H));\n\t\t\t}\n\t\t\tcatch(std::exception Ex) {\n\t\t\t\tnLog::error(\n\t\t\t\t\t\"Couldn't parse extract args: x:'{}' y:'{}' w:'{}' h:'{}'\",\n\t\t\t\t\tpArgs[ArgStart + 0], pArgs[ArgStart + 1],\n\t\t\t\t\tpArgs[ArgStart + 2], pArgs[ArgStart + 3]\n\t\t\t\t);\n\t\t\t\treturn EXIT_FAILURE;\n\t\t\t}\n\t\t}\n\t\telse if(szOp == \"-rotate\") {\n\t\t\tif(ArgIndex + 4 >= lArgCount) {\n\t\t\t\tnLog::error(\n\t\t\t\t\t\"Too few args for {} - first arg at pos {}, arg count: {}\",\n\t\t\t\t\tszOp, ArgIndex + 1, lArgCount\n\t\t\t\t);\n\t\t\t\treturn EXIT_FAILURE;\n\t\t\t}\n\t\t\ttry {\n\t\t\t\tauto Deg = std::stod(pArgs[++ArgIndex]);\n\t\t\t\tauto Bg = tRgb(pArgs[++ArgIndex]);\n\t\t\t\tauto CenterX = std::stod(pArgs[++ArgIndex]);\n\t\t\t\tauto CenterY = std::stod(pArgs[++ArgIndex]);\n\t\t\t\tvOps.push_back(std::make_unique<tOpRotate>(Deg, Bg, CenterX, CenterY));\n\t\t\t}\n\t\t\tcatch(std::exception Ex) {\n\t\t\t\tnLog::error(\"Couldn't parse arg: '{}'\", pArgs[ArgIndex]);\n\t\t\t\treturn EXIT_FAILURE;\n\t\t\t}\n\t\t}\n\t\telse if(szOp == \"-mirror\") {\n\t\t\tif(ArgIndex + 1 >= lArgCount) {\n\t\t\t\tnLog::error(\"Too few args for {}\", szOp);\n\t\t\t\treturn EXIT_FAILURE;\n\t\t\t}\n\t\t\tstd::string_view szAxis = pArgs[++ArgIndex];\n\t\t\tif(szAxis != \"x\" && szAxis != \"y\") {\n\t\t\t\tnLog::error(\"Unknown mirror axis specified: '{}'\", szAxis);\n\t\t\t\treturn EXIT_FAILURE;\n\t\t\t}\n\t\t\tvOps.push_back(std::make_unique<tOpMirror>(\n\t\t\t\tszAxis == \"x\" ? tOpMirror::tAxis::X : tOpMirror::tAxis::Y\n\t\t\t));\n\t\t}\n\t\telse {\n\t\t\tnLog::error(\"Unknown argument: '{}'\", szOp);\n\t\t\treturn EXIT_FAILURE;\n\t\t}\n\t}\n\n\tfor(const auto &Op: vOps) {\n\t\tImg = Op->execute(Img);\n\t\tif(!Img.m_uwWidth) {\n\t\t\tnLog::error(\"Operation {} failed!\", Op->toString());\n\t\t\treturn EXIT_FAILURE;\n\t\t}\n\t}\n\n\tstd::string szDstPath = pArgs[2];\n\tbool isOk = Img.toPng(szDstPath);\n\tif(!isOk) {\n\t\tnLog::error(\"Couldn't write to '{}'\", szDstPath);\n\t\treturn EXIT_FAILURE;\n\t}\n\n\tfmt::print(\"All done!\\n\");\n\treturn EXIT_SUCCESS;\n}\n\n//--------------------------------------------------------------------OP EXTRACT\n\ntOpExtract::tOpExtract(std::uint16_t uwX, std::uint16_t uwY, std::uint16_t uwW, std::uint16_t uwH):\n\tm_uwX(uwX), m_uwY(uwY), m_uwW(uwW), m_uwH(uwH)\n{\n\t// Nothing here for now\n}\n\ntChunkyBitmap tOpExtract::execute(const tChunkyBitmap &Source)\n{\n\tfmt::print(\n\t\t\"Extracting rectangle {}x{} at {},{}\\n\", m_uwW, m_uwH, m_uwX, m_uwY\n\t);\n\ttChunkyBitmap Dst(m_uwW, m_uwH);\n\tbool isOk = Source.copyRect(m_uwX, m_uwY, Dst, 0, 0, m_uwW, m_uwH);\n\tif(!isOk) {\n\t\tnLog::error(\"Couldn't extract given rectangle from source image\");\n\t\tDst = tChunkyBitmap();\n\t}\n\treturn Dst;\n}\n\nstd::string tOpExtract::toString(void)\n{\n\treturn fmt::format(\n\t\t\"extract(x: {}, y: {}, w: {}, h: {})\", m_uwX, m_uwY, m_uwW, m_uwH\n\t);\n}\n\n//---------------------------------------------------------------------OP MIRROR\n\ntOpMirror::tOpMirror(tOpMirror::tAxis eAxis):\n\tm_eAxis(eAxis)\n{\n\t// Nothing here for now\n}\n\ntChunkyBitmap tOpMirror::execute(const tChunkyBitmap &Source)\n{\n\ttChunkyBitmap Dst(Source.m_uwWidth, Source.m_uwHeight);\n\tif(m_eAxis == tAxis::X) {\n\t\tfor(auto X = 0; X < Source.m_uwWidth; ++X) {\n\t\t\tfor(auto Y = 0; Y < Source.m_uwHeight; ++Y) {\n\t\t\t\tDst.pixelAt(X, Y) = Source.pixelAt(X, (Source.m_uwHeight - 1) - Y);\n\t\t\t}\n\t\t}\n\t}\n\telse {\n\t\tfor(auto X = 0; X < Source.m_uwWidth; ++X) {\n\t\t\tfor(auto Y = 0; Y < Source.m_uwHeight; ++Y) {\n\t\t\t\tDst.pixelAt(X, Y) = Source.pixelAt((Source.m_uwWidth - 1) - X, Y);\n\t\t\t}\n\t\t}\n\t}\n\treturn Dst;\n}\n\nstd::string tOpMirror::toString(void)\n{\n\treturn fmt::format(\"mirror(axis: {})\", m_eAxis == tAxis::X ? 'X' : 'Y');\n}\n\n//---------------------------------------------------------------------OP ROTATE\n\ntOpRotate::tOpRotate(\n\tdouble dDeg, tRgb Bg,\n\tdouble dCenterX, double dCenterY\n):\n\tm_dDeg(dDeg), m_Bg(Bg), m_dCenterX(dCenterX), m_dCenterY(dCenterY)\n{\n\t// Nothing here for now\n}\n\ntChunkyBitmap tOpRotate::execute(const tChunkyBitmap &Source) {\n\ttChunkyBitmap Dst(Source.m_uwWidth, Source.m_uwHeight);\n\n\tauto Rad = (m_dDeg * 2 * M_PI) / 360;\n\tauto CalcCos = cos(Rad);\n\tauto CalcSin = sin(Rad);\n\n\t// For each of new bitmap's pixel sample color from rotated source x,y\n\tfor(auto Y = 0; Y < Dst.m_uwHeight; ++Y) {\n\t\tauto Dy = Y - m_dCenterY;\n\t\tfor(auto X = 0; X < Dst.m_uwWidth; ++X) {\n\t\t\tauto Dx = X - m_dCenterX;\n\t\t\tauto U = uint16_t(round(CalcCos * Dx + CalcSin * Dy + (m_dCenterX)));\n\t\t\tauto V = uint16_t(round(-CalcSin * Dx + CalcCos * Dy + (m_dCenterY)));\n\n\t\t\tif(U < 0 || V < 0 || U >= Dst.m_uwWidth || V >= Dst.m_uwHeight) {\n\t\t\t\t// fmt::print(\"can't sample for {:2d},{:2d} from {:.1f},{:.1f}\\n\", X, Y, U, V);\n\t\t\t\tDst.pixelAt(X, Y) = m_Bg;\n\t\t\t}\n\t\t\telse {\n\t\t\t\tDst.pixelAt(X, Y) = Source.pixelAt(U, V);\n\t\t\t}\n\t\t}\n\t}\n\n\treturn Dst;\n}\n\nstd::string tOpRotate::toString(void)\n{\n\treturn fmt::format(\"rotate(deg: {}, bg: {})\", m_dDeg, m_Bg.toString());\n}\n"
  },
  {
    "path": "tools/src/common/bitmap.cpp",
    "content": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at http://mozilla.org/MPL/2.0/. */\n\n#include \"bitmap.h\"\n#include <fstream>\n#include <algorithm>\n#include \"../common/logging.h\"\n#include \"../common/lodepng.h\"\n#include \"../common/endian.h\"\n#include \"../common/flags/flags.hpp\"\n\nenum class tBmFlags: std::uint8_t {\n\tNONE = 0,\n\tINTERLEAVED = 1\n};\nALLOW_FLAGS_FOR_ENUM(tBmFlags);\n\ntChunkyBitmap::tChunkyBitmap(\n\tconst tPlanarBitmap &Planar, const tPalette &Palette\n):\n\tm_uwWidth(Planar.m_uwWidth), m_uwHeight(Planar.m_uwHeight)\n{\n\tif(!Planar.m_pPlanes[0].size()) {\n\t\tm_uwWidth = 0;\n\t\tm_uwHeight = 0;\n\t\treturn;\n\t}\n\tm_vData.resize(m_uwWidth * m_uwHeight, Palette.m_vColors[0]);\n\tauto PxPerCell = sizeof(Planar.m_pPlanes[0][0]) * 8;\n\tfor(std::uint32_t ulY = 0; ulY < m_uwHeight; ++ulY) {\n\t\tfor(std::uint32_t ulX = 0; ulX < m_uwWidth; ++ulX) {\n\t\t\tstd::uint8_t ubColorIdx = 0;\n\t\t\tstd::uint32_t ulOffs = (ulY * m_uwWidth + ulX) / PxPerCell;\n\t\t\tfor(std::uint8_t ubPlane = Planar.m_ubDepth; ubPlane--;) {\n\t\t\t\tauto &Plane = Planar.m_pPlanes[ubPlane];\n\t\t\t\tubColorIdx <<= 1;\n\t\t\t\tubColorIdx |= (Plane.at(ulOffs) >> (15 - (ulX & 15))) & 1;\n\t\t\t}\n\t\t\tif(ubColorIdx >= Palette.m_vColors.size()) {\n\t\t\t\tnLog::error(\n\t\t\t\t\t\"Attempted to read color {} from palette of size {}\",\n\t\t\t\t\tubColorIdx, Palette.m_vColors.size()\n\t\t\t\t);\n\t\t\t\tm_uwWidth = 0;\n\t\t\t\tm_uwHeight = 0;\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tauto Color = Palette.m_vColors.at(ubColorIdx);\n\t\t\tthis->pixelAt(ulX, ulY) = Color;\n\t\t}\n\t}\n}\n\ntChunkyBitmap::tChunkyBitmap(std::uint16_t uwWidth, std::uint16_t uwHeight, tRgb Bg):\n\tm_uwWidth(uwWidth), m_uwHeight(uwHeight), m_vData(m_uwWidth * m_uwHeight, Bg)\n{\n\n}\n\ntChunkyBitmap::tChunkyBitmap(\n\tstd::uint16_t uwWidth, std::uint16_t uwHeight, const std::uint8_t *pData\n):\n\tm_uwWidth(uwWidth), m_uwHeight(uwHeight)\n{\n\tauto *pRgbData = reinterpret_cast<const tRgb*>(pData);\n\tauto *pRgbDataEnd = &pRgbData[uwWidth * uwHeight];\n\tm_vData = std::vector<tRgb>(pRgbData, pRgbDataEnd);\n}\n\ntChunkyBitmap tChunkyBitmap::fromPng(const std::string &szPath)\n{\n\tunsigned uWidth, uHeight;\n\tstd::uint8_t *pData;\n\tauto LodeError = lodepng_decode24_file(&pData, &uWidth, &uHeight, szPath.c_str());\n\tif(LodeError) {\n\t\treturn tChunkyBitmap();\n\t}\n\n\ttChunkyBitmap Chunky(uWidth, uHeight, pData);\n\tfree(pData);\n\treturn Chunky;\n}\n\nbool tChunkyBitmap::toPng(const std::string &szPngPath) const\n{\n\tauto LodeErr = lodepng_encode_file(\n\t\tszPngPath.c_str(), reinterpret_cast<const std::uint8_t*>(m_vData.data()),\n\t\tm_uwWidth, m_uwHeight, LCT_RGB, 8\n\t);\n\n\treturn LodeErr == 0;\n}\n\ntPlanarBitmap::tPlanarBitmap(\n\tstd::uint16_t uwWidth, std::uint16_t uwHeight, std::uint8_t ubDepth\n)\n{\n\tif(uwWidth & 0xF) {\n\t\tnLog::error(\"Width is not divisible by 16\");\n\t\treturn;\n\t}\n\tif(ubDepth > 8) {\n\t\tnLog::error(\"More than 8bpp not supported, got {}\", m_ubDepth);\n\t\treturn;\n\t}\n\n\tm_uwWidth = uwWidth;\n\tm_uwHeight = uwHeight;\n\tm_ubDepth = ubDepth;\n\n\tfor(std::uint8_t i = 0; i < ubDepth; ++i) {\n\t\tm_pPlanes[i].resize(uwWidth * uwHeight / sizeof(m_pPlanes[0][0]));\n\t}\n}\n\ntPlanarBitmap::tPlanarBitmap(\n\tconst tChunkyBitmap &Chunky, const tPalette &Palette,\n\tconst tPalette &PaletteIgnore\n):\n\tm_uwWidth(0),\n\tm_uwHeight(0),\n\tm_ubDepth(0)\n{\n\tif(Chunky.m_uwWidth & 0xF) {\n\t\tnLog::error(\"Width is not divisible by 16\");\n\t\treturn;\n\t}\n\n\t// Determine depth\n\tstd::uint8_t ubDepth = Palette.getBpp();\n\tif(ubDepth > 8) {\n\t\tnLog::error(\"More than 8bpp not supported, got {}\", ubDepth);\n\t\treturn;\n\t}\n\n\t// Write bitplanes - from LSB to MSB\n\tstd::uint16_t uwPixelBuffer;\n\tstd::uint32_t ulPos;\n\tfor(std::uint8_t ubPlane = 0; ubPlane != ubDepth; ++ubPlane) {\n\t\tfor(std::uint16_t y = 0; y != Chunky.m_uwHeight; ++y) {\n\t\t\tuwPixelBuffer = 0;\n\t\t\tfor(std::uint16_t x = 0; x != Chunky.m_uwWidth; ++x) {\n\t\t\t\t// Determine bit value for given color at specified bitplane's pos\n\t\t\t\tauto Color = Chunky.pixelAt(x, y);\n\t\t\t\tstd::int16_t wIdx = Palette.getColorIdx(Color);\n\t\t\t\tstd::uint8_t ubBit = 0;\n\t\t\t\tif(wIdx == -1) {\n\t\t\t\t\tif(PaletteIgnore.getColorIdx(Color) == -1) {\n\t\t\t\t\t\tnLog::error(\n\t\t\t\t\t\t\t\"Unexpected color: {0}, {1}, {2} (#{0:02X}{1:02X}{2:02X}) @{3},{4}\",\n\t\t\t\t\t\t\tColor.ubR, Color.ubG,\tColor.ubB, x, y\n\t\t\t\t\t\t);\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse if(wIdx & (1 << ubPlane)) {\n\t\t\t\t\tubBit = 1;\n\t\t\t\t}\n\n\t\t\t\tuwPixelBuffer <<= 1;\n\t\t\t\tuwPixelBuffer |= ubBit;\n\t\t\t\tif((x & 0xF) == 0xF) {\n\t\t\t\t\tm_pPlanes[ubPlane].push_back(uwPixelBuffer);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// Everything's okay - write dimensions to apropriate fields\n\tm_uwWidth = Chunky.m_uwWidth;\n\tm_uwHeight = Chunky.m_uwHeight;\n\tm_ubDepth = ubDepth;\n}\n\nbool tPlanarBitmap::toBm(const std::string &szPath, bool isInterleaved)\n{\n\tflags::flags<tBmFlags> eFlags(tBmFlags::NONE);\n\tif(isInterleaved) {\n\t\teFlags |= tBmFlags::INTERLEAVED;\n\t}\n\n\tstd::ofstream OutFile(szPath.c_str(), std::ios::out | std::ios::binary);\n\tif(!OutFile.is_open()) {\n\t\treturn false;\n\t}\n\n\t// Write .bm header\n\tstd::uint16_t uwOut = nEndian::toBig16(m_uwWidth);\n\tOutFile.write(reinterpret_cast<char*>(&uwOut), 2);\n\tuwOut = nEndian::toBig16(m_uwHeight);\n\tOutFile.write(reinterpret_cast<char*>(&uwOut), 2);\n\tOutFile.write(reinterpret_cast<char*>(&m_ubDepth), 1);\n\n\tstd::uint8_t ubOut = 0;\n\tOutFile.write(reinterpret_cast<char*>(&ubOut), 1); // Version\n\tOutFile.write(reinterpret_cast<char*>(&eFlags), 1); // Flags\n\tOutFile.write(reinterpret_cast<char*>(&ubOut), 1); // Reserved 1\n\tOutFile.write(reinterpret_cast<char*>(&ubOut), 1); // Reserved 2\n\n\t// Write bitplanes\n\tstd::uint16_t uwRowWordCount = m_uwWidth / 16;\n\tif(isInterleaved) {\n\t\tfor(std::uint16_t y = 0; y < m_uwHeight; ++y) {\n\t\t\tfor(std::uint8_t ubPlane = 0; ubPlane < m_ubDepth; ++ubPlane) {\n\t\t\t\tfor(std::uint16_t x = 0; x < uwRowWordCount; ++x) {\n\t\t\t\t\tstd::uint16_t uwData = nEndian::toBig16(\n\t\t\t\t\t\tm_pPlanes[ubPlane].at(y * uwRowWordCount + x)\n\t\t\t\t\t);\n\t\t\t\t\tOutFile.write(reinterpret_cast<char*>(&uwData), sizeof(uint16_t));\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\telse {\n\t\tfor(std::uint8_t ubPlane = 0; ubPlane < m_ubDepth; ++ubPlane) {\n\t\t\tfor(std::uint16_t y = 0; y < m_uwHeight; ++y) {\n\t\t\t\tfor(std::uint16_t x = 0; x < uwRowWordCount; ++x) {\n\t\t\t\t\tstd::uint16_t uwData = nEndian::toBig16(\n\t\t\t\t\t\tm_pPlanes[ubPlane].at(y * uwRowWordCount + x)\n\t\t\t\t\t);\n\t\t\t\t\tOutFile.write(reinterpret_cast<char*>(&uwData), sizeof(uint16_t));\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\tOutFile.close();\n\treturn true;\n}\n\ntPlanarBitmap tPlanarBitmap::fromBm(const std::string &szPath)\n{\n\tstd::ifstream File(szPath, std::ios::in | std::ios::binary);\n\tif(!File.is_open()) {\n\t\treturn tPlanarBitmap(0, 0, 0);\n\t}\n\n\tstd::uint16_t uwWidth, uwHeight;\n\tstd::uint8_t ubBpp, ubVersion, ubReserved1, ubReserved2;\n\ttBmFlags eFlags;\n\tFile.read(reinterpret_cast<char*>(&uwWidth), sizeof(uwWidth));\n\tFile.read(reinterpret_cast<char*>(&uwHeight), sizeof(uwHeight));\n\tFile.read(reinterpret_cast<char*>(&ubBpp), sizeof(ubBpp));\n\tFile.read(reinterpret_cast<char*>(&ubVersion), sizeof(ubVersion));\n\tFile.read(reinterpret_cast<char*>(&eFlags), sizeof(eFlags));\n\tFile.read(reinterpret_cast<char*>(&ubReserved1), sizeof(ubReserved1));\n\tFile.read(reinterpret_cast<char*>(&ubReserved2), sizeof(ubReserved2));\n\n\tuwWidth = nEndian::fromBig16(uwWidth);\n\tuwHeight = nEndian::fromBig16(uwHeight);\n\n\tif(ubVersion == 0) {\n\t\ttPlanarBitmap Bm(uwWidth, uwHeight, ubBpp);\n\t\tfor(std::uint8_t i = 0; i < ubBpp; ++i) {\n\t\t\tBm.m_pPlanes[i].resize(uwWidth * uwHeight / sizeof(Bm.m_pPlanes[0][0]));\n\t\t}\n\t\tif(eFlags & tBmFlags::INTERLEAVED) {\n\t\t\tfor(std::uint32_t y = 0; y < uwHeight; ++y) {\n\t\t\t\tfor(std::uint8_t i = 0; i < ubBpp; ++i) {\n\t\t\t\t\tFile.read(\n\t\t\t\t\t\t&(reinterpret_cast<char*>(Bm.m_pPlanes[i].data())[y * uwWidth / 8]),\n\t\t\t\t\t\tuwWidth / 8\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\telse {\n\t\t\tfor(std::uint8_t i = 0; i < ubBpp; ++i) {\n\t\t\t\tFile.read(\n\t\t\t\t\treinterpret_cast<char*>(Bm.m_pPlanes[i].data()),\n\t\t\t\t\t(uwWidth / 8) * uwHeight\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\t// Convert endianness on data\n\t\tfor(std::uint8_t i = ubBpp; i--;) {\n\t\t\tfor(auto &Cell: Bm.m_pPlanes[i]) {\n\t\t\t\tCell = nEndian::fromBig16(Cell);\n\t\t\t}\n\t\t}\n\n\t\tBm.m_uwWidth = uwWidth;\n\t\tBm.m_uwHeight = uwHeight;\n\t\tBm.m_ubDepth = ubBpp;\n\t\treturn Bm;\n\t}\n\telse {\n\t\tnLog::error(\"Unsupported bitmap file version: 0x{:02X}\", ubVersion);\n\t\treturn tPlanarBitmap(0, 0, 0);\n\t}\n}\n\ntRgb &tChunkyBitmap::pixelAt(std::uint16_t uwX, std::uint16_t uwY)\n{\n\tstd::uint32_t ulPos = m_uwWidth * (uwY) + uwX;\n\treturn m_vData[ulPos];\n}\n\nconst tRgb &tChunkyBitmap::pixelAt(std::uint16_t uwX, std::uint16_t uwY) const\n{\n\tstd::uint32_t ulPos = m_uwWidth * (uwY) + uwX;\n\treturn m_vData[ulPos];\n}\n\nbool tChunkyBitmap::copyRect(\n\tstd::uint16_t uwSrcX, std::uint16_t uwSrcY, tChunkyBitmap &Dst,\n\tstd::uint16_t uwDstX, std::uint16_t uwDstY, std::uint16_t uwWidth, std::uint16_t uwHeight\n) const\n{\n\tif(uwSrcX + uwWidth > m_uwWidth || uwSrcY + uwHeight > m_uwHeight) {\n\t\t// Source out of range\n\t\treturn false;\n\t}\n\tif(uwDstX + uwWidth > Dst.m_uwWidth || uwDstY + uwHeight > Dst.m_uwHeight) {\n\t\t// Dest out of range\n\t\treturn false;\n\t}\n\n\tfor(std::uint16_t uwY = 0; uwY < uwHeight; ++uwY) {\n\t\tfor(std::uint16_t uwX = 0; uwX < uwWidth; ++uwX) {\n\t\t\tDst.pixelAt(uwDstX + uwX, uwDstY + uwY) = pixelAt(uwSrcX + uwX, uwSrcY + uwY);\n\t\t}\n\t}\n\n\treturn true;\n}\n\nbool tChunkyBitmap::fillRect(\n\tstd::uint16_t uwDstX, std::uint16_t uwDstY, std::uint16_t uwWidth, std::uint16_t uwHeight,\n\tconst tRgb &Color\n) {\n\tif(uwDstX + uwWidth > m_uwWidth || uwDstY + uwHeight > m_uwHeight) {\n\t\t// Source out of range\n\t\treturn false;\n\t}\n\n\tfor(std::uint16_t uwY = 0; uwY < uwHeight; ++uwY) {\n\t\tfor(std::uint16_t uwX = 0; uwX < uwWidth; ++uwX) {\n\t\t\tpixelAt(uwDstX + uwX, uwDstY + uwY) = Color;\n\t\t}\n\t}\n\n\treturn true;\n}\n\nbool tChunkyBitmap::mergeWithMask(const tChunkyBitmap &Mask)\n{\n\tif(Mask.m_uwHeight != m_uwHeight || Mask.m_uwWidth != m_uwWidth) {\n\t\treturn false;\n\t}\n\n\tfor(std::uint16_t uwY = 0; uwY < m_uwHeight; ++uwY) {\n\t\tfor(std::uint16_t uwX = 0; uwX < m_uwWidth; ++uwX) {\n\t\t\tauto & MaskPixel = Mask.pixelAt(uwX, uwY);\n\t\t\tif(MaskPixel != tRgb(0)) {\n\t\t\t\tpixelAt(uwX, uwY) = MaskPixel;\n\t\t\t}\n\t\t}\n\t}\n\treturn true;\n}\n\ntChunkyBitmap tChunkyBitmap::filterColors(\n\tconst tPalette &Palette, const tRgb &ColorDefault\n)\n{\n\tconst auto &Colors = Palette.m_vColors;\n\ttChunkyBitmap Out(m_uwWidth, m_uwHeight);\n\tfor(std::uint16_t uwY = 0; uwY < m_uwHeight; ++uwY) {\n\t\tfor(std::uint16_t uwX = 0; uwX < m_uwWidth; ++uwX) {\n\t\t\tconst auto &Ref = pixelAt(uwX, uwY);\n\t\t\tif(std::find(Colors.begin(), Colors.end(), Ref) != Colors.end()) {\n\t\t\t\tOut.pixelAt(uwX, uwY) = Ref;\n\t\t\t}\n\t\t\telse {\n\t\t\t\tOut.pixelAt(uwX, uwY) = ColorDefault;\n\t\t\t}\n\t\t}\n\t}\n\treturn Out;\n}\n"
  },
  {
    "path": "tools/src/common/bitmap.h",
    "content": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at http://mozilla.org/MPL/2.0/. */\n\n#ifndef _ACE_TOOLS_COMMON_BITMAP_H_\n#define _ACE_TOOLS_COMMON_BITMAP_H_\n\n#include <cstdint>\n#include <vector>\n#include <string>\n#include \"../common/rgb.h\"\n#include \"palette.h\"\n\nclass tPlanarBitmap;\n\nclass tChunkyBitmap {\npublic:\n\tstd::uint16_t m_uwWidth = 0;\n\tstd::uint16_t m_uwHeight = 0;\n\tstd::vector<tRgb> m_vData;\n\n\ttChunkyBitmap(const tPlanarBitmap &Planar, const tPalette &Palette);\n\n\ttChunkyBitmap(std::uint16_t uwWidth, std::uint16_t uwHeight, tRgb Bg = tRgb(0));\n\n\ttChunkyBitmap(std::uint16_t uwWidth, std::uint16_t uwHeight, const std::uint8_t *pData);\n\n\ttChunkyBitmap(void) { };\n\n\tbool toPng(const std::string &szPngPath) const;\n\n\tstatic tChunkyBitmap fromPng(const std::string &szPath);\n\n\ttRgb &pixelAt(std::uint16_t uwX, std::uint16_t uwY);\n\tconst tRgb &pixelAt(std::uint16_t uwX, std::uint16_t uwY) const;\n\n\tbool copyRect(\n\t\tstd::uint16_t uwSrcX, std::uint16_t uwSrcY, tChunkyBitmap &Dst,\n\t\tstd::uint16_t uwDstX, std::uint16_t uwDstY, std::uint16_t uwWidth, std::uint16_t uwHeight\n\t) const;\n\n\tbool fillRect(\n\t\tstd::uint16_t uwDstX, std::uint16_t uwDstY, std::uint16_t uwWidth, std::uint16_t uwHeight,\n\t\tconst tRgb &Color\n\t);\n\n\tbool mergeWithMask(const tChunkyBitmap &Mask);\n\n\ttChunkyBitmap filterColors(const tPalette &Palette, const tRgb &ColorDefault);\n};\n\nclass tPlanarBitmap {\npublic:\n\tstd::uint16_t m_uwWidth;\n\tstd::uint16_t m_uwHeight;\n\tstd::uint8_t m_ubDepth;\n\tstd::vector<uint16_t> m_pPlanes[8];\n\n\ttPlanarBitmap(\n\t\tconst tChunkyBitmap &Chunky, const tPalette &Palette,\n\t\tconst tPalette &PaletteIgnore = tPalette()\n\t);\n\n\ttPlanarBitmap(std::uint16_t uwWidth, std::uint16_t uwHeight, std::uint8_t ubDepth);\n\n\tbool toBm(const std::string &szPath, bool isInterleaved);\n\n\tstatic tPlanarBitmap fromBm(const std::string &szPath);\n};\n\n#endif // _ACE_TOOLS_COMMON_BITMAP_H_\n"
  },
  {
    "path": "tools/src/common/compress.cpp",
    "content": "#include \"../common/compress.hpp\"\n#include <cmath>\n#include <fmt/format.h>\n#include <fmt/ranges.h>\n\nstatic constexpr auto s_RleMinLength = 3u;\nstatic constexpr auto s_RleMaxLength = 18u;\n\nstatic uint8_t rleTableRead(const uint8_t *table, std::uint16_t *index)\n{\n\tuint8_t byte;\n\n\tbyte = table[*index];\n\t(*index)++;\n\t(*index) &= 0xfff;\n\n\treturn byte;\n}\n\nstatic bool rleTableFind(\n\tconst uint8_t *pLookup, std::uint16_t uwLookupLength,\n\tstd::uint16_t uwLookupWritePos, const uint8_t *pData, std::uint32_t ulMatchLimit,\n\tstd::uint16_t *pMatchPosition, std::uint8_t *pMatchLength\n)\n{\n\t*pMatchPosition = 0;\n\t*pMatchLength = 0;\n\tstd::uint32_t ulMatchedLength;\n\tbool isFound = false;\n\tfor (auto i = 0u; i < uwLookupLength; i++) {\n\t\tstd::uint32_t ulLimit = ulMatchLimit;\n\t\tif(uwLookupLength < 0x1000) {\n\t\t\tulLimit = std::min(ulLimit, uwLookupLength - i);\n\t\t}\n\t\tfor (ulMatchedLength = 0u; ulMatchedLength < ulLimit; ulMatchedLength++) {\n\t\t\tauto offset = i + ulMatchedLength;\n\t\t\tif (pLookup[offset & 0xfff] != pData[ulMatchedLength]) {\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\t // Don't return RLE runs that are in the area of the table that\n\t\t\t // will be written to, since the values will change.\n\t\t\tif (\n\t\t\t\t(i >= uwLookupWritePos && i <= uwLookupWritePos + ulMatchedLength) ||\n\t\t\t\t(offset >= uwLookupWritePos && offset <= uwLookupWritePos + ulMatchedLength)\n\t\t\t) {\n\t\t\t\tulMatchedLength = 0;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tif (ulMatchedLength >= s_RleMinLength) {\n\t\t\tif(ulMatchedLength > *pMatchLength) {\n\t\t\t\t*pMatchPosition = i;\n\t\t\t\t*pMatchLength = ulMatchedLength;\n\t\t\t\tisFound = true;\n\t\t\t}\n\t\t}\n\t}\n\n\treturn isFound;\n}\n\nstatic void rleTableWrite(uint8_t *table, std::uint16_t *index, uint8_t byte)\n{\n\ttable[*index] = byte;\n\t(*index)++;\n\t(*index) &= 0xfff;\n}\n\nvoid compressUnpackerInit(\n\ttCompressUnpacker *pUnpacker, const uint8_t *pCompressed, size_t ulCompressedSize,\n\tsize_t ulUncompressedSize, bool isVerbose\n)\n{\n\tmemset(pUnpacker, 0, sizeof(*pUnpacker));\n\tfor(std::uint16_t i = 0; i < 0x1000; ++i) {\n\t\tpUnpacker->pLookup[i] = rand();\n\t}\n\tpUnpacker->pCompressed = pCompressed;\n\tpUnpacker->ulCompressedSize = ulCompressedSize;\n\tpUnpacker->ulUncompressedSize = ulUncompressedSize;\n\tpUnpacker->isVerbose = isVerbose;\n\tif(pUnpacker->isVerbose) fmt::println(\"Decompress start\");\n}\n\ntCompressUnpackResult compressUnpackerProcess(\n\ttCompressUnpacker *pUnpacker, std::uint8_t *pOut\n)\n{\n\tswitch(pUnpacker->eCurrentState) {\n\t\tcase COMPRESS_UNPACK_STATE_KIND_READ_CTL:\n\t\t\tpUnpacker->ulCtlOffset = pUnpacker->ulReadOffset;\n\t\t\tpUnpacker->ubCtlByte = pUnpacker->pCompressed[pUnpacker->ulReadOffset++];\n\t\t\tpUnpacker->ubCtlBitIndex = 0;\n\t\t\tpUnpacker->eCurrentState = COMPRESS_UNPACK_STATE_KIND_PROCESS_CTL_BIT;\n\t\t\tbreak;\n\n\t\tcase COMPRESS_UNPACK_STATE_KIND_PROCESS_CTL_BIT:\n\t\t\tif(pUnpacker->ubCtlBitIndex < 8 && pUnpacker->ulWriteOffset < pUnpacker->ulUncompressedSize) {\n\t\t\t\tstd::uint8_t ubBitValue = pUnpacker->ubCtlByte & (1 << pUnpacker->ubCtlBitIndex);\n\t\t\t\tpUnpacker->ubCtlBitIndex++;\n\t\t\t\tif (ubBitValue) {\n\t\t\t\t\t// Output the next byte and store it in the table\n\t\t\t\t\tstd::uint8_t ubRawByte = pUnpacker->pCompressed[pUnpacker->ulReadOffset++];\n\t\t\t\t\tif(pUnpacker->isVerbose) fmt::println(\"byte at {}: {:02X}\", pUnpacker->ulReadOffset - 1, ubRawByte);\n\t\t\t\t\trleTableWrite(pUnpacker->pLookup, &pUnpacker->uwLookupPos, ubRawByte);\n\t\t\t\t\t*pOut = ubRawByte;\n\t\t\t\t\tpUnpacker->ulWriteOffset++;\n\t\t\t\t\treturn COMPRESS_UNPACK_RESULT_BUSY_WROTE_BYTE;\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tstd::uint16_t uwRleCtl = (\n\t\t\t\t\t\t(pUnpacker->pCompressed[pUnpacker->ulReadOffset + 0] << 8) |\n\t\t\t\t\t\t(pUnpacker->pCompressed[pUnpacker->ulReadOffset + 1] << 0)\n\t\t\t\t\t);\n\t\t\t\t\tpUnpacker->ulReadOffset += 2;\n\n\t\t\t\t\tpUnpacker->ubRleLength = (uwRleCtl & 0xf) + 3;\n\t\t\t\t\tpUnpacker->uwRleStart = uwRleCtl >> 4;\n\n\t\t\t\t\tif(pUnpacker->isVerbose) fmt::print(\n\t\t\t\t\t\t\"sequence at {}, word: {:04X}, len: {}, index: {}, sequence:\",\n\t\t\t\t\t\tpUnpacker->ulReadOffset - 2, uwRleCtl, pUnpacker->ubRleLength, pUnpacker->uwRleStart\n\t\t\t\t\t);\n\t\t\t\t\tpUnpacker->ubRlePos = 0;\n\t\t\t\t\tpUnpacker->eCurrentState = COMPRESS_UNPACK_STATE_KIND_WRITE_RLE;\n\t\t\t\t}\n\t\t\t}\n\t\t\telse {\n\t\t\t\tpUnpacker->eCurrentState = COMPRESS_UNPACK_STATE_KIND_END_CTL;\n\t\t\t}\n\t\t\tbreak;\n\n\t\tcase COMPRESS_UNPACK_STATE_KIND_END_CTL:\n\t\t\tif(pUnpacker->isVerbose) fmt::println(\"used ctl at {}: {:02X}\", pUnpacker->ulCtlOffset, pUnpacker->ubCtlByte);\n\t\t\tif (pUnpacker->ulWriteOffset >= pUnpacker->ulUncompressedSize) {\n\t\t\t\tpUnpacker->eCurrentState = COMPRESS_UNPACK_STATE_KIND_DONE;\n\t\t\t}\n\t\t\telse {\n\t\t\t\tpUnpacker->eCurrentState = COMPRESS_UNPACK_STATE_KIND_READ_CTL;\n\t\t\t}\n\t\t\tbreak;\n\n\t\tcase COMPRESS_UNPACK_STATE_KIND_WRITE_RLE:\n\t\t\tif(pUnpacker->ubRlePos < pUnpacker->ubRleLength) {\n\t\t\t\tstd::uint8_t ubRawByte = rleTableRead(pUnpacker->pLookup, &pUnpacker->uwRleStart);\n\t\t\t\tif(pUnpacker->isVerbose) fmt::print(\" {:02X}\", ubRawByte);\n\t\t\t\trleTableWrite(pUnpacker->pLookup, &pUnpacker->uwLookupPos, ubRawByte);\n\t\t\t\t*pOut = ubRawByte;\n\t\t\t\tpUnpacker->ulWriteOffset++;\n\t\t\t\t++pUnpacker->ubRlePos;\n\t\t\t\treturn COMPRESS_UNPACK_RESULT_BUSY_WROTE_BYTE;\n\t\t\t}\n\t\t\telse {\n\t\t\t\tif(pUnpacker->isVerbose) fmt::print(\"\\n\");\n\t\t\t\tpUnpacker->eCurrentState = COMPRESS_UNPACK_STATE_KIND_PROCESS_CTL_BIT;\n\t\t\t}\n\t\t\tbreak;\n\n\t\tcase COMPRESS_UNPACK_STATE_KIND_DONE:\n\t\t\tif(pUnpacker->isVerbose) fmt::println(\"Decompress done\");\n\t\t\treturn COMPRESS_UNPACK_RESULT_DONE;\n\t\t\tbreak;\n\t}\n\n\treturn COMPRESS_UNPACK_RESULT_BUSY;\n}\n\nstd::uint32_t compressPack(\n\tconst uint8_t *pSrc, std::uint32_t ulSrcSize,\n\tuint8_t *pDest, bool isVerbose\n) {\n\tif(isVerbose) fmt::println(\"Compress start, size {}\", ulSrcSize);\n\tstd::uint8_t pLookup[0x1000] = {0};\n\tstd::uint32_t ulSrcOffset = 0, ulDestOffset = 0, ulCtrlByteOffset;\n\tstd::uint16_t uwLookupWritePos = 0;\n\tstd::uint16_t uwRleMatchPosition;\n\tstd::uint8_t ubRleMatchLength;\n\tstd::uint16_t uwLookupLength = 0;\n\tstd::uint16_t uwRleCtl;\n\n\twhile (ulSrcOffset < ulSrcSize) {\n\t\t// Write a place-holder control byte\n\t\tulCtrlByteOffset = ulDestOffset++;\n\t\tpDest[ulCtrlByteOffset] = 0;\n\n\t\tfor (std::uint8_t ubBit = 0; ubBit < 8; ubBit++) {\n\t\t\tif (ulSrcOffset >= ulSrcSize) {\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\t// Try to find an repeated sequence\n\t\t\tbool isFound = rleTableFind(\n\t\t\t\tpLookup, uwLookupLength, uwLookupWritePos, &pSrc[ulSrcOffset],\n\t\t\t\tstd::min(ulSrcSize - ulSrcOffset, s_RleMaxLength),\n\t\t\t\t&uwRleMatchPosition, &ubRleMatchLength\n\t\t\t);\n\t\t\tif (isFound) {\n\t\t\t\t// RLE sequence found. Encode a 16-bit word for length\n\t\t\t\t// and index. Control byte flag is not set.\n\t\t\t\tuwRleCtl = (ubRleMatchLength - 3) & 0xf;\n\t\t\t\tuwRleCtl |= (uwRleMatchPosition & 0xfff) << 4;\n\n\t\t\t\tif(isVerbose) fmt::println(\n\t\t\t\t\t\"sequence at {}, word: {:04X}, len: {}, index: {}, sequence: {:02X}\",\n\t\t\t\t\tulDestOffset, uwRleCtl, ubRleMatchLength, uwRleMatchPosition,\n\t\t\t\t\tfmt::join(&pSrc[ulSrcOffset], &pSrc[ulSrcOffset + ubRleMatchLength], \" \")\n\t\t\t\t);\n\t\t\t\tpDest[ulDestOffset++] = uwRleCtl >> 8;\n\t\t\t\tpDest[ulDestOffset++] = std::uint8_t(uwRleCtl);\n\n\t\t\t\tfor (std::uint8_t i = 0; i < ubRleMatchLength; i++) {\n\t\t\t\t\trleTableWrite(pLookup, &uwLookupWritePos, pSrc[ulSrcOffset++]);\n\t\t\t\t\tuwLookupLength = std::min(0x1000, uwLookupLength + 1);\n\t\t\t\t}\n\t\t\t}\n\t\t\telse {\n\t\t\t\t// No sequence found. Encode the byte directly.\n\t\t\t\t// Control byte flag is set.\n\t\t\t\tpDest[ulCtrlByteOffset] |= (1 << ubBit);\n\t\t\t\tauto RawByte = pSrc[ulSrcOffset++];\n\t\t\t\tif(isVerbose) fmt::println(\"byte at {}: {:02X}\", ulDestOffset, RawByte);\n\t\t\t\tpDest[ulDestOffset++] = RawByte;\n\t\t\t\trleTableWrite(pLookup, &uwLookupWritePos, RawByte);\n\t\t\t\tuwLookupLength = std::min(0x1000, uwLookupLength + 1);\n\t\t\t}\n\t\t}\n\t\tif(isVerbose) fmt::println(\"used ctl at {}: {:02X}\", ulCtrlByteOffset, pDest[ulCtrlByteOffset]);\n\t}\n\n\tif(isVerbose) fmt::println(\"compress done, length: {}\", ulDestOffset);\n\treturn ulDestOffset;\n}\n"
  },
  {
    "path": "tools/src/common/compress.hpp",
    "content": "#ifndef _ACE_TOOLS_COMMON_COMPRESS_H_\n#define _ACE_TOOLS_COMMON_COMPRESS_H_\n\n#include <cstdint>\n#include <cstddef>\n\nenum tCompressUnpackStateKind {\n\tCOMPRESS_UNPACK_STATE_KIND_READ_CTL,\n\tCOMPRESS_UNPACK_STATE_KIND_PROCESS_CTL_BIT,\n\tCOMPRESS_UNPACK_STATE_KIND_END_CTL,\n\tCOMPRESS_UNPACK_STATE_KIND_WRITE_RLE,\n\tCOMPRESS_UNPACK_STATE_KIND_DONE,\n};\n\nenum tCompressUnpackResult {\n\tCOMPRESS_UNPACK_RESULT_BUSY,\n\tCOMPRESS_UNPACK_RESULT_BUSY_WROTE_BYTE,\n\tCOMPRESS_UNPACK_RESULT_DONE,\n};\n\nstruct tCompressUnpacker {\n\ttCompressUnpackStateKind eCurrentState;\n\tstd::uint8_t pLookup[0x1000];\n\tconst std::uint8_t *pCompressed;\n\tstd::size_t ulCompressedSize;\n\tstd::size_t ulUncompressedSize;\n\tbool isVerbose;\n\tstd::uint8_t ubCtlByte;\n\tstd::uint8_t ubCtlBitIndex;\n\tstd::uint8_t ubRlePos;\n\tstd::uint8_t ubRleLength;\n\tstd::uint16_t uwRleStart;\n\tstd::uint16_t uwLookupPos;\n\tstd::uint32_t ulReadOffset;\n\tstd::uint32_t ulWriteOffset;\n\tstd::uint32_t ulCtlOffset;\n};\n\nstd::uint32_t compressPack(\n\tconst uint8_t *pSrc, std::uint32_t ulSrcSize,\n\tuint8_t *pDest, bool isVerbose = false\n);\n\nvoid compressUnpackerInit(\n\ttCompressUnpacker *pUnpacker, const uint8_t *pCompressed, size_t ulCompressedSize,\n\tsize_t ulUncompressedSize, bool isVerbose = false\n);\n\ntCompressUnpackResult compressUnpackerProcess(\n\ttCompressUnpacker *State, std::uint8_t *pOut\n);\n\n#endif // _ACE_TOOLS_COMMON_COMPRESS_H_\n"
  },
  {
    "path": "tools/src/common/endian.h",
    "content": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at http://mozilla.org/MPL/2.0/. */\n\n#ifndef _ACE_TOOLS_COMMON_ENDIAN_H_\n#define _ACE_TOOLS_COMMON_ENDIAN_H_\n\n#include <cstdint>\n#include <bit>\n\nnamespace nEndian {\n\tconstexpr bool isBig(void)\n\t{\n\t\treturn std::endian::native == std::endian::big;\n\t}\n\n\tconstexpr std::uint16_t toBig16(std::uint16_t uwIn)\n\t{\n\t\tif(isBig()) {\n\t\t\treturn uwIn;\n\t\t}\n\t\treturn (\n\t\t\t((uwIn & 0xFF'00) >> 8) |\n\t\t\t((uwIn & 0x00'FF) << 8)\n\t\t);\n\t}\n\n\tconstexpr std::uint16_t fromBig16(std::uint16_t uwIn)\n\t{\n\t\treturn toBig16(uwIn);\n\t}\n\n\tconstexpr std::uint32_t toBig32(std::uint32_t ulIn)\n\t{\n\t\tif(isBig()) {\n\t\t\treturn ulIn;\n\t\t}\n\t\treturn (\n\t\t\t((ulIn & 0xFF'00'00'00) >> 24) |\n\t\t\t((ulIn & 0x00'FF'00'00) >>  8) |\n\t\t\t((ulIn & 0x00'00'FF'00) <<  8) |\n\t\t\t((ulIn & 0x00'00'00'FF) << 24)\n\t\t);\n\t}\n\n\tconstexpr std::uint32_t fromBig32(std::uint32_t uwIn)\n\t{\n\t\treturn toBig32(uwIn);\n\t}\n}\n\n#endif // _ACE_TOOLS_COMMON_ENDIAN_H_\n"
  },
  {
    "path": "tools/src/common/exception.cpp",
    "content": "#include \"exception.h\"\n\nvoid exceptionHandle(\n\tconst std::exception &Ex, const std::string &szOperation\n)\n{\n\t\tauto Message = Ex.what();\n\t\tif(Message == nullptr) {\n\t\t\tnLog::error(\"Exception while {}\", szOperation);\n\t\t}\n\t\telse {\n\t\t\tnLog::error(\"Exception while {}: {}\", szOperation, Message);\n\t\t}\n};\n"
  },
  {
    "path": "tools/src/common/exception.h",
    "content": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at http://mozilla.org/MPL/2.0/. */\n\n#ifndef _ACE_TOOLS_COMMON_EXCEPTION_H_\n#define _ACE_TOOLS_COMMON_EXCEPTION_H_\n\n#include <exception>\n#include <string>\n#include \"logging.h\"\n\nvoid exceptionHandle(\n\tconst std::exception &Ex, const std::string &szOperation\n);\n\n#endif // _ACE_TOOLS_COMMON_EXCEPTION_H_\n"
  },
  {
    "path": "tools/src/common/flags/allow_flags.hpp",
    "content": "#ifndef ENUM_CLASS_ALLOW_FLAGS_HPP\n#define ENUM_CLASS_ALLOW_FLAGS_HPP\n\n\n#include <type_traits>\n\n\nnamespace flags {\n\n\ntemplate <class E, class Enabler = void> struct is_flags\n: public std::false_type {};\n\n\n} // namespace flags\n\n\n#define ALLOW_FLAGS_FOR_ENUM(name) \\\nnamespace flags { \\\ntemplate <> struct is_flags< name > : std::true_type {}; \\\n}\n\n\n#endif // ENUM_CLASS_ALLOW_FLAGS_HPP\n"
  },
  {
    "path": "tools/src/common/flags/flags.hpp",
    "content": "#ifndef ENUM_CLASS_FLAGS_HPP\n#define ENUM_CLASS_FLAGS_HPP\n\n\n#include \"allow_flags.hpp\"\n#include \"iterator.hpp\"\n\n#include <bitset>\n#include <initializer_list>\n#include <numeric>\n#include <utility>\n\n\nnamespace flags {\n\n\nconstexpr struct empty_t {\n  constexpr empty_t() noexcept = default;\n} empty;\n\n\ntemplate <class E> class flags {\npublic:\n  static_assert(is_flags<E>::value,\n                \"flags::flags is disallowed for this type; \"\n                \"use ALLOW_FLAGS_FOR_ENUM macro.\");\n\n  using enum_type = typename std::decay<E>::type;\n  using underlying_type = typename std::underlying_type<enum_type>::type;\n  using impl_type = typename std::make_unsigned<underlying_type>::type;\n\n  using iterator = FlagsIterator<enum_type>;\n  using const_iterator = iterator;\n  using value_type = typename iterator::value_type;\n  using reference = typename iterator::reference;\n  using const_reference = typename iterator::reference;\n  using pointer = enum_type *;\n  using const_pointer = const enum_type *;\n  using size_type = std::size_t;\n  using difference_type = typename iterator::difference_type;\n\n\n  constexpr static std::size_t bit_size() { return sizeof(impl_type) * 8; }\n\n\nprivate:\n  template <class T, class Res = std::nullptr_t>\n  using convertible = std::enable_if<std::is_convertible<T, enum_type>::value,\n                                     Res>;\n\n\npublic:\n  flags() noexcept = default;\n  flags(const flags &fl) noexcept = default;\n  flags &operator=(const flags &fl) noexcept = default;\n  flags(flags &&fl) noexcept = default;\n  flags &operator=(flags &&fl) noexcept= default;\n\n\n  explicit constexpr flags(empty_t) noexcept : val_(0) {}\n\n\n#ifdef ENUM_CLASS_FLAGS_FORBID_IMPLICT_CONVERSION\n  explicit\n#endif\n  constexpr flags(enum_type e) noexcept\n  : val_(static_cast<impl_type>(e)) {}\n\n  flags &operator=(enum_type e) noexcept {\n    val_ = static_cast<impl_type>(e);\n    return *this;\n  }\n\n\n  flags(std::initializer_list<enum_type> il) noexcept : val_(0) { insert(il); }\n\n  flags &operator=(std::initializer_list<enum_type> il) noexcept {\n    clear();\n    insert(il);\n    return *this;\n  }\n\n  template <class ... Args>\n  flags(enum_type e, Args ... args) noexcept : flags{e, args...} {}\n\n\n  template <class FwIter>\n  flags(FwIter b, FwIter e,\n        typename convertible<decltype(FwIter::operator *)>::type = nullptr)\n  noexcept(noexcept(std::declval<flags>().insert(std::declval<FwIter>(),\n                                                 std::declval<FwIter>())))\n  : val_(0)\n  { insert(b, e); }\n\n\n  constexpr explicit operator bool() const noexcept { return val_ != 0; }\n\n  constexpr bool operator!() const noexcept { return !val_; }\n\n  friend constexpr bool operator==(flags fl1, flags fl2) {\n    return fl1.val_ == fl2.val_;\n  }\n\n  friend constexpr bool operator!=(flags fl1, flags fl2) {\n    return fl1.val_ != fl2.val_;\n  }\n\n\n  constexpr flags operator~() const noexcept { return flags(~val_); }\n\n  flags &operator|=(const flags &fl) noexcept {\n    val_ |= fl.val_;\n    return *this;\n  }\n\n  flags &operator&=(const flags &fl) noexcept {\n    val_ &= fl.val_;\n    return *this;\n  }\n\n  flags &operator^=(const flags &fl) noexcept {\n    val_ ^= fl.val_;\n    return *this;\n  }\n\n\n  flags &operator|=(enum_type e) noexcept {\n    val_ |= static_cast<impl_type>(e);\n    return *this;\n  }\n\n  flags &operator&=(enum_type e) noexcept {\n    val_ &= static_cast<impl_type>(e);\n    return *this;\n  }\n\n  flags &operator^=(enum_type e) noexcept {\n    val_ ^= static_cast<impl_type>(e);\n    return *this;\n  }\n\n  friend constexpr flags operator|(flags f1, flags f2) noexcept {\n    return flags{static_cast<impl_type>(f1.val_ | f2.val_)};\n  }\n\n  friend constexpr flags operator&(flags f1, flags f2) noexcept {\n    return flags{static_cast<impl_type>(f1.val_ & f2.val_)};\n  }\n\n  friend  constexpr flags operator^(flags f1, flags f2) noexcept {\n    return flags{static_cast<impl_type>(f1.val_ ^ f2.val_)};\n  }\n\n\n  void swap(flags &fl) noexcept { std::swap(val_, fl.val_); }\n\n\n  constexpr underlying_type underlying_value() const noexcept {\n    return static_cast<underlying_type>(val_);\n  }\n\n  void set_underlying_value(underlying_type newval) noexcept {\n    val_ = static_cast<impl_type>(newval);\n  }\n\n\n  constexpr explicit operator std::bitset<flags<E>::bit_size()>() const noexcept {\n    return to_bitset();\n  }\n\n  constexpr std::bitset<flags<E>::bit_size()> to_bitset() const noexcept {\n    return {val_};\n  }\n\n\n  constexpr bool empty() const noexcept { return !val_; }\n\n  size_type size() const noexcept {\n    return std::distance(this->begin(), this->end());\n  }\n\n  constexpr size_type max_size() const noexcept { return bit_size(); }\n\n\n  iterator begin() const noexcept { return cbegin(); }\n  iterator cbegin() const noexcept { return iterator{val_}; }\n\n  constexpr iterator end() const noexcept { return cend(); }\n  constexpr iterator cend() const noexcept { return {}; }\n\n\n  constexpr iterator find(enum_type e) const noexcept { return {val_, e}; }\n\n  constexpr size_type count(enum_type e) const noexcept {\n    return find(e) != end() ? 1 : 0;\n  }\n\n\n  std::pair<iterator, iterator> equal_range(enum_type e) const noexcept {\n    auto i = find(e);\n    auto j = i;\n    return {i, ++j};\n  }\n\n\n  template <class... Args>\n  std::pair<iterator, bool> emplace(Args && ... args) noexcept {\n    return insert(enum_type{args...});\n  }\n\n  template <class... Args>\n  iterator emplace_hint(iterator, Args && ... args) noexcept {\n    return emplace(args...).first;\n  }\n\n\n  std::pair<iterator, bool> insert(enum_type e) noexcept {\n    auto i = find(e);\n    if (i == end()) {\n      i.mask_ = static_cast<impl_type>(e);\n      val_ |= i.mask_;\n      update_uvalue(i);\n      return {i, true};\n    }\n    return {i, false};\n  }\n\n  std::pair<iterator, bool> insert(iterator, enum_type e) noexcept {\n    return insert(e);\n  }\n\n  template <class FwIter>\n  auto insert(FwIter i1, FwIter i2)\n  noexcept(noexcept(++i1) && noexcept(*i1) && noexcept(i1 == i2))\n  -> typename convertible<decltype(*i1), void>::type {\n    val_ |= std::accumulate(i1, i2, impl_type{0}, [](impl_type i, enum_type e) {\n      return i | static_cast<impl_type>(e);\n    });\n  }\n\n  template <class Container>\n  auto insert(const Container &ctn) noexcept\n  -> decltype(std::begin(ctn), std::end(ctn), void()) {\n    insert(std::begin(ctn), std::end(ctn));\n  }\n\n\n  iterator erase(iterator i) noexcept {\n    val_ ^= i.mask_;\n    update_uvalue(i);\n    return ++i;\n  }\n\n  size_type erase(enum_type e) noexcept {\n    auto e_count = count(e);\n    val_ &= ~static_cast<impl_type>(e);\n    return e_count;\n  }\n\n  iterator erase(iterator i1, iterator i2) noexcept {\n    val_ ^= flags(i1, i2).val_;\n    update_uvalue(i2);\n    return i2;\n  }\n\n\n  void clear() noexcept { val_ = 0; }\n\nprivate:\n  constexpr explicit flags(impl_type val) noexcept : val_(val) {}\n\n  void update_uvalue(iterator &it) const noexcept { it.uvalue_ = val_; }\n\n  impl_type val_;\n};\n\n\ntemplate <class E>\nvoid swap(flags<E> &fl1, flags<E> &fl2) noexcept { fl1.swap(fl2); }\n\n\n} // namespace flags\n\n\ntemplate <class E>\nconstexpr auto operator|(E e1, E e2) noexcept\n-> typename std::enable_if<flags::is_flags<E>::value,\n                           flags::flags<E>>::type {\n  return flags::flags<E>(e1) | e2;\n}\n\n\ntemplate <class E>\nconstexpr auto operator&(E e1, E e2) noexcept\n-> typename std::enable_if<flags::is_flags<E>::value,\n                           flags::flags<E>>::type {\n  return flags::flags<E>(e1) & e2;\n}\n\n\ntemplate <class E>\nconstexpr auto operator^(E e1, E e2) noexcept\n-> typename std::enable_if<flags::is_flags<E>::value,\n                           flags::flags<E>>::type {\n  return flags::flags<E>(e1) ^ e2;\n}\n\n\n#endif // ENUM_CLASS_FLAGS_HPP\n"
  },
  {
    "path": "tools/src/common/flags/flagsfwd.hpp",
    "content": "#ifndef ENUM_CLASS_FLAGSFWD_HPP\n#define ENUM_CLASS_FLAGSFWD_HPP\n\n\nnamespace flags { template <class E> class flags; }\n\n\n#endif // ENUM_CLASS_FLAGSFWD_HPP\n"
  },
  {
    "path": "tools/src/common/flags/iterator.hpp",
    "content": "#ifndef ENUM_CLASS_ITERATOR_HPP\n#define ENUM_CLASS_ITERATOR_HPP\n\n\n#include \"flagsfwd.hpp\"\n\n#include <iterator>\n\n\nnamespace flags {\n\n\ntemplate <class E>\nclass FlagsIterator {\npublic:\n  using flags_type = flags<E>;\n  using difference_type = std::ptrdiff_t;\n  using value_type = E;\n  using pointer = value_type *;\n  using reference = const value_type;\n  using iterator_category = std::forward_iterator_tag;\n\n\n  constexpr FlagsIterator() noexcept : uvalue_(0), mask_(0) {}\n\n  constexpr FlagsIterator(const FlagsIterator &other) noexcept\n  : uvalue_(other.uvalue_), mask_(other.mask_) {}\n\n\n  FlagsIterator &operator++() noexcept {\n    nextMask();\n    return *this;\n  }\n  FlagsIterator operator++(int) noexcept {\n    auto copy = *this;\n    ++(*this);\n    return copy;\n  }\n\n\n  constexpr reference operator*() const noexcept {\n    return static_cast<value_type>(mask_);\n  }\n\n\n  friend inline constexpr bool operator==(const FlagsIterator &i,\n                                          const FlagsIterator &j) noexcept {\n    return i.mask_ == j.mask_;\n  }\n\n  friend inline constexpr bool operator!=(const FlagsIterator &i,\n                                          const FlagsIterator &j) noexcept {\n    return i.mask_ != j.mask_;\n  }\n\n\nprivate:\n  template <class E_> friend class flags;\n\n  using impl_type = typename flags_type::impl_type;\n\n\n  explicit FlagsIterator(impl_type uv) noexcept : uvalue_(uv), mask_(1) {\n    if (!(mask_ & uvalue_)) { nextMask(); }\n  }\n\n  constexpr FlagsIterator(impl_type uv, E e) noexcept\n  : uvalue_(uv)\n  , mask_(static_cast<impl_type>(static_cast<impl_type>(e) & uv))\n  {}\n\n\n  void nextMask() noexcept {\n    do { mask_ <<= 1; } while (mask_ && !(mask_ & uvalue_));\n  }\n\n\n  impl_type uvalue_;\n  impl_type mask_;\n};\n\n\n} // namespace flags\n\n\n#endif // ENUM_CLASS_ITERATOR_HPP\n"
  },
  {
    "path": "tools/src/common/fs.cpp",
    "content": "// C++17 deprecation for codecvt still doesn't have substitute\n#define _SILENCE_CXX17_CODECVT_HEADER_DEPRECATION_WARNING\n\n/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at http://mozilla.org/MPL/2.0/. */\n\n#include \"fs.h\"\n#include <sys/types.h>\n#include <sys/stat.h>\n\n#if defined(_WIN32)\n#include <direct.h>\n#include <windows.h>\n#include <locale>\n#include <codecvt>\n#else\n#include <dirent.h>\n#endif\n\nnamespace nFs {\n\nbool dirCreate(const std::string &szPath)\n{\n\t#if defined(_WIN32)\n\t\tauto Error = _mkdir(szPath.c_str());\n\t#else\n\t\tauto Error = mkdir(szPath.c_str(),0733);\n\t#endif\n\n\treturn Error != 0;\n}\n\nbool isDir(const std::string &szPath)\n{\n\tstruct stat info;\n\n\tif(stat( szPath.c_str(), &info ) != 0) {\n\t\t\treturn false;\n\t}\n\tif(info.st_mode & S_IFDIR) {  // S_ISDIR() doesn't exist on my windows\n\t\t\treturn true;\n\t}\n\treturn false;\n}\n\nstd::string getExt(const std::string &szPath)\n{\n\tauto DotPos = szPath.find_last_of('.');\n\tif(DotPos == std::string::npos) {\n\t\treturn \"\";\n\t}\n\treturn szPath.substr(DotPos + 1);\n}\n\nstd::string removeExt(const std::string &szPath)\n{\n\tauto DotPos = szPath.find_last_of('.');\n\tif(DotPos == std::string::npos) {\n\t\treturn \"\";\n\t}\n\treturn szPath.substr(0, DotPos);\n}\n\nstd::string getBaseName(const std::string &szPath)\n{\n\tauto LastSlash = szPath.find_last_of('/');\n\tif(LastSlash == std::string::npos) {\n\t\tLastSlash = 0;\n\t}\n\tauto LastBackslash = szPath.find_last_of('\\\\');\n\tif(LastBackslash == std::string::npos) {\n\t\tLastBackslash = 0;\n\t}\n\treturn szPath.substr(std::max(LastSlash, LastBackslash));\n}\n\nvoid iterateDirectory(const std::string &szPath, std::function<void(const std::string &)> onFile) {\n#if defined(_WIN32)\n\tstd::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> converter;\n\n\tWIN32_FIND_DATAW ffd;\n\tHANDLE hFind = FindFirstFileW(converter.from_bytes(szPath + \"\\\\*\").c_str(), &ffd);\n\tdo {\n\t\tonFile(std::string(converter.to_bytes(reinterpret_cast<wchar_t*>(ffd.cFileName))));\n\t} while (FindNextFileW(hFind, &ffd) != 0);\n#else\n\tDIR *pDir = opendir(szPath.c_str());\n  if (pDir != nullptr) {\n\t\tdirent *pDirent;\n    while ((pDirent = readdir(pDir)) != NULL) {\n\t\t\tonFile(std::string(pDirent->d_name));\n    }\n    closedir(pDir);\n  }\n#endif\n}\n\n} // namespace nFs\n"
  },
  {
    "path": "tools/src/common/fs.h",
    "content": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at http://mozilla.org/MPL/2.0/. */\n\n// C++17 has <filesystem> but it ain't working on GCC7 so we need something else\n\n#ifndef _ACE_TOOLS_COMMON_FS_H_\n#define _ACE_TOOLS_COMMON_FS_H_\n\n#include <string>\n#include <functional>\n\nnamespace nFs {\n\nbool dirCreate(const std::string &szPath);\n\nbool isDir(const std::string &szPath);\n\nstd::string getExt(const std::string &szPath);\n\nstd::string removeExt(const std::string &szPath);\n\nstd::string getBaseName(const std::string &szPath);\n\nvoid iterateDirectory(const std::string &szPath, std::function<void(const std::string &)> onFile);\n\n} // namespace nFs\n\n#endif // _ACE_TOOLS_COMMON_FS_H_\n"
  },
  {
    "path": "tools/src/common/glyph_set.cpp",
    "content": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at http://mozilla.org/MPL/2.0/. */\n\n#include \"glyph_set.h\"\n#include <fstream>\n#include <fmt/format.h>\n#include <freetype/freetype.h>\n#include \"../common/lodepng.h\"\n#include \"../common/endian.h\"\n#include \"../common/rgb.h\"\n#include \"../common/fs.h\"\n#include \"../common/bitmap.h\"\n#include \"../common/logging.h\"\n#include \"utf8.h\"\n\ntGlyphSet tGlyphSet::fromPmng(const std::string &szPngPath, std::uint8_t ubStartIdx)\n{\n\ttGlyphSet GlyphSet;\n\n\tauto Bitmap = tChunkyBitmap::fromPng(szPngPath);\n\tif(!Bitmap.m_uwHeight) {\n\t\tnLog::error(\"Couldn't open image '{}'\", szPngPath);\n\t\treturn GlyphSet;\n\t}\n\n\tconst auto &Delimiter = Bitmap.pixelAt(0, 0);\n\tconst auto &Bg = Bitmap.pixelAt(0, 1);\n\tstd::uint16_t uwStart = 0;\n\tstd::uint16_t uwCurrChar = ubStartIdx;\n\n\tfor(std::uint16_t i = 1; i < Bitmap.m_uwWidth; ++i) {\n\t\tif(Bitmap.pixelAt(i, 0) == Delimiter) {\n\t\t\tstd::uint16_t uwStop = i;\n\n\t\t\ttGlyphSet::tBitmapGlyph Glyph;\n\t\t\tGlyph.m_ubWidth = (uwStop - uwStart) - 1;\n\t\t\tGlyph.m_ubHeight = Bitmap.m_uwHeight;\n\t\t\tGlyph.m_ubBearing = 0;\n\t\t\tGlyph.m_vData.reserve(Glyph.m_ubWidth * Glyph.m_ubHeight);\n\n\t\t\tfor(std::uint16_t y = 0; y < Bitmap.m_uwHeight; ++y) {\n\t\t\t\tfor(std::uint16_t x = uwStart + 1; x < uwStop; ++x) {\n\t\t\t\t\tconst auto &Pixel = Bitmap.pixelAt(x, y);\n\t\t\t\t\tGlyph.m_vData.push_back((Pixel == Bg ? 0 : 0xFF));\n\t\t\t\t}\n\t\t\t}\n\t\t\tGlyphSet.m_mGlyphs.insert(std::make_pair(uwCurrChar, Glyph));\n\t\t\t++uwCurrChar;\n\n\t\t\tuwStart = uwStop;\n\t\t}\n\t}\n\treturn GlyphSet;\n}\n\ntGlyphSet tGlyphSet::fromAceFont(const std::string &szFntPath)\n{\n\ttGlyphSet GlyphSet;\n\tstd::ifstream FileFnt(szFntPath, std::ifstream::binary);\n\tif(!FileFnt.good()) {\n\t\tnLog::error(\"Couldn't open image '{}'\", szFntPath);\n\t\treturn GlyphSet;\n\t}\n\n\t// Read header\n\tstd::uint8_t ubCharCount;\n\tstd::uint16_t uwBitmapWidth, uwBitmapHeight;\n\tFileFnt.read(reinterpret_cast<char*>(&uwBitmapWidth), sizeof(uwBitmapWidth));\n\tFileFnt.read(reinterpret_cast<char*>(&uwBitmapHeight), sizeof(uwBitmapHeight));\n\tFileFnt.read(reinterpret_cast<char*>(&ubCharCount), sizeof(ubCharCount));\n\tuwBitmapWidth = nEndian::fromBig16(uwBitmapWidth);\n\tuwBitmapHeight = nEndian::fromBig16(uwBitmapHeight);\n\n\t// Read char offsets - read offset of one more to get last char's width\n\tstd::vector<uint16_t> vCharOffsets;\n\tvCharOffsets.reserve(ubCharCount);\n\tfor(std::uint16_t c = 0; c < ubCharCount; ++c) {\n\t\tstd::uint16_t uwOffs;\n\t\tFileFnt.read(reinterpret_cast<char*>(&uwOffs), sizeof(uwOffs));\n\t\tuwOffs = nEndian::fromBig16(uwOffs);\n\t\tvCharOffsets.push_back(uwOffs);\n\t}\n\n\ttPlanarBitmap GlyphBitmapPlanar(uwBitmapWidth, uwBitmapHeight, 1);\n\tstd::uint32_t ulOffs = 0;\n\tfor(std::uint16_t uwY = 0; uwY < uwBitmapHeight; ++uwY) {\n\t\tfor(std::uint16_t uwX = 0; uwX < uwBitmapWidth / 16; ++uwX) {\n\t\t\tstd::uint16_t uwData;\n\t\t\tFileFnt.read(reinterpret_cast<char*>(&uwData), sizeof(uwData));\n\t\t\tuwData = nEndian::fromBig16(uwData);\n\t\t\tGlyphBitmapPlanar.m_pPlanes[0][ulOffs++] = uwData;\n\t\t}\n\t}\n\tFileFnt.close();\n\n\ttPalette Palette;\n\tPalette.m_vColors.push_back(tRgb(0));\n\tPalette.m_vColors.push_back(tRgb(0xFF));\n\ttChunkyBitmap Chunky(GlyphBitmapPlanar, Palette);\n\tfor(std::uint16_t c = 0; c < ubCharCount - 1; ++c) {\n\t\tstd::uint8_t ubGlyphWidth = vCharOffsets[c + 1] - vCharOffsets[c];\n\t\tif(ubGlyphWidth) {\n\t\t\ttBitmapGlyph Glyph;\n\t\t\tGlyph.m_vData.resize(uwBitmapHeight * ubGlyphWidth);\n\t\t\tfor(std::uint8_t ubY = 0; ubY < uwBitmapHeight; ++ubY) {\n\t\t\t\tfor(std::uint8_t ubX = 0; ubX < ubGlyphWidth; ++ubX) {\n\t\t\t\t\t// Since filled in Chunky is (FF,FF,FF), use data from any channel.\n\t\t\t\t\tGlyph.m_vData[ubY * ubGlyphWidth + ubX] = Chunky.pixelAt(vCharOffsets[c] + ubX, ubY).ubR;\n\t\t\t\t}\n\t\t\t}\n\t\t\tGlyph.m_ubWidth =  ubGlyphWidth;\n\t\t\tGlyph.m_ubHeight = uwBitmapHeight;\n\t\t\tGlyph.m_ubBearing = 0;\n\t\t\tGlyphSet.m_mGlyphs.emplace(std::make_pair(c, std::move(Glyph)));\n\t\t}\n\t}\n\treturn GlyphSet;\n}\n\ntGlyphSet tGlyphSet::fromTtf(\n\tconst std::string &szTtfPath, std::uint8_t ubSize, const std::string &szCharSet,\n\tstd::uint8_t ubThreshold\n)\n{\n\ttGlyphSet GlyphSet;\n\n\tFT_Library FreeType;\n\tauto Error = FT_Init_FreeType(&FreeType);\n\tif(Error) {\n\t\tfmt::print(\"Couldn't open FreeType\\n\");\n\t\treturn GlyphSet;\n\t}\n\n\tFT_Face Face;\n\tError = FT_New_Face(FreeType, szTtfPath.c_str(), 0, &Face);\n\tif(Error) {\n\t\tfmt::print(\"Couldn't open font '{}'\\n\", szTtfPath);\n\t\treturn GlyphSet;\n\t}\n\n\tFT_Set_Pixel_Sizes(Face, 0, ubSize);\n\n\tstd::uint8_t ubMaxBearing = 0, ubMaxAddHeight = 0;\n  std::uint32_t ulCodepoint, ulState = 0;\n\tfor(const auto &c: szCharSet) {\n\t\tauto CharCode = *reinterpret_cast<const uint8_t*>(&c);\n\t\tif (\n\t\t\tdecode(&ulState, &ulCodepoint, CharCode) != UTF8_ACCEPT ||\n\t\t\tulCodepoint == '\\n' || ulCodepoint == '\\r'\n\t\t) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tFT_Load_Char(Face, ulCodepoint, FT_LOAD_RENDER);\n\n\t\tstd::uint8_t ubWidth = Face->glyph->bitmap.width;\n\t\tstd::uint8_t ubHeight = Face->glyph->bitmap.rows;\n\n\t\tGlyphSet.m_mGlyphs[ulCodepoint] = {\n\t\t\tstatic_cast<uint8_t>(Face->glyph->metrics.horiBearingY / 64),\n\t\t\tubWidth, ubHeight, std::vector<uint8_t>(ubWidth * ubHeight, 0)\n\t\t};\n\t\tauto &Glyph = GlyphSet.m_mGlyphs[ulCodepoint];\n\n\t\t// Copy bitmap graphics with threshold\n\t\tfor(std::uint32_t ulPos = 0; ulPos < Glyph.m_vData.size(); ++ulPos) {\n\t\t\tstd::uint8_t ubVal = (Face->glyph->bitmap.buffer[ulPos] >= ubThreshold) ? 0xFF : 0;\n\t\t\tGlyph.m_vData[ulPos] = ubVal;\n\t\t}\n\n\t\t// Trim left & right\n\t\tif(ubWidth != 0 && ubWidth != 0) {\n\t\t\tGlyph.trimHorz(false);\n\t\t\tGlyph.trimHorz(true);\n\t\t}\n\t\telse {\n\t\t\t// At least write proper width\n\t\t\tGlyph.m_ubWidth = Face->glyph->metrics.horiAdvance / 64;\n\t\t}\n\n\t\tubMaxBearing = std::max(ubMaxBearing, Glyph.m_ubBearing);\n\t\tubMaxAddHeight = std::max(\n\t\t\tubMaxAddHeight,\n\t\t\tstatic_cast<uint8_t>(std::max(0, Glyph.m_ubHeight - Glyph.m_ubBearing))\n\t\t);\n\t}\n\tFT_Done_Face(Face);\n\tFT_Done_FreeType(FreeType);\n\n\tstd::uint8_t ubBmHeight = ubMaxBearing + ubMaxAddHeight;\n\n\t// Normalize Glyph height\n\tfor(auto &GlyphPair: GlyphSet.m_mGlyphs) {\n\t\tauto &Glyph = GlyphPair.second;\n\t\tstd::vector<uint8_t> vNewData(Glyph.m_ubWidth * ubBmHeight, 0);\n\t\tauto Dst = vNewData.begin() + Glyph.m_ubWidth * (ubMaxBearing - Glyph.m_ubBearing);\n\t\tfor(auto Src = Glyph.m_vData.begin(); Src != Glyph.m_vData.end(); ++Src, ++Dst) {\n\t\t\t*Dst = *Src;\n\t\t}\n\t\tGlyph.m_vData = vNewData;\n\t\tGlyph.m_ubHeight = ubBmHeight;\n\t}\n\n\treturn GlyphSet;\n}\n\ntGlyphSet tGlyphSet::fromDir(const std::string &szDirPath)\n{\n\ttGlyphSet GlyphSet;\n\tfor(std::uint16_t c = 0; c <= 255; ++c) {\n\t\tauto Chunky = tChunkyBitmap::fromPng(fmt::format(\"{}/{}.png\", szDirPath, c));\n\t\tif(Chunky.m_uwHeight) {\n\t\t\ttGlyphSet::tBitmapGlyph Glyph;\n\t\t\tGlyph.m_ubWidth = Chunky.m_uwWidth;\n\t\t\tGlyph.m_ubHeight = Chunky.m_uwHeight;\n\t\t\tGlyph.m_ubBearing = 0;\n\t\t\tGlyph.m_vData.reserve(Glyph.m_ubWidth * Glyph.m_ubHeight);\n\t\t\t// It's sufficient to base on R channel\n\t\t\tfor(const auto &Pixel: Chunky.m_vData) {\n\t\t\t\tGlyph.m_vData.push_back(Pixel.ubR ? 0xFF : 0x00);\n\t\t\t}\n\t\t\tGlyphSet.m_mGlyphs.emplace(std::make_pair(c, std::move(Glyph)));\n\t\t}\n\t}\n\treturn GlyphSet;\n}\n\nbool tGlyphSet::toDir(const std::string &szDirPath)\n{\n\tnFs::dirCreate(szDirPath);\n\tfor(const auto &GlyphPair: m_mGlyphs) {\n\t\tauto Glyph = GlyphPair.second;\n\t\tstd::vector<tRgb> vImage(Glyph.m_ubWidth * Glyph.m_ubHeight, tRgb(0));\n\n\t\tfor(auto y = 0; y < Glyph.m_ubHeight; ++y) {\n\t\t\tfor(auto x = 0; x < Glyph.m_ubWidth; ++x) {\n\t\t\t\tauto Val = Glyph.m_vData[y * Glyph.m_ubWidth + x];\n\t\t\t\tvImage[y * Glyph.m_ubWidth + x] = tRgb(Val);\n\t\t\t}\n\t\t}\n\n\t\tauto LodeErr = lodepng_encode_file(\n\t\t\tfmt::format(\"{}/{}.png\", szDirPath, static_cast<unsigned char>(GlyphPair.first)).c_str(),\n\t\t\treinterpret_cast<uint8_t*>(vImage.data()),\n\t\t\tGlyph.m_ubWidth, Glyph.m_ubHeight, LCT_RGB, 8\n\t\t);\n\n\t\tif(LodeErr) {\n\t\t\tfmt::print(\"Lode Err: {}\", LodeErr);\n\t\t\treturn false;\n\t\t}\n\t}\n\treturn true;\n}\n\ntChunkyBitmap tGlyphSet::toPackedBitmap(bool isPmng)\n{\n\tstd::uint8_t ubHeight = m_mGlyphs.begin()->second.m_ubHeight;\n\n\t// Calculate total width & round up to multiple of 16\n\tstd::uint16_t uwWidth = 0;\n\tfor(const auto &[Key, Glyph]: m_mGlyphs) {\n\t\tuwWidth += Glyph.m_ubWidth + (isPmng ? 1 : 0);\n\t}\n\tuwWidth = ((uwWidth + 15) / 16) * 16;\n\n\ttChunkyBitmap Chunky(uwWidth, ubHeight, tRgb(0));\n\tstd::uint16_t uwOffsX = 0;\n\tfor(const auto &[Key, Glyph]: m_mGlyphs) {\n\t\tif(isPmng) {\n\t\t\t// Add start marker\n\t\t\tChunky.pixelAt(uwOffsX, 0) = tRgb(0xFF, 0, 0);\n\t\t\tuwOffsX += 1;\n\t\t}\n\t\tfor(auto y = 0; y < Glyph.m_ubHeight; ++y) {\n\t\t\tfor(auto x = 0; x < Glyph.m_ubWidth; ++x) {\n\t\t\t\tauto Val = Glyph.m_vData[y * Glyph.m_ubWidth + x];\n\t\t\t\tChunky.pixelAt(uwOffsX + x, y) = tRgb(Val);\n\t\t\t}\n\t\t}\n\t\tuwOffsX += Glyph.m_ubWidth;\n\t}\n\treturn Chunky;\n}\n\nstd::uint8_t tGlyphSet::tBitmapGlyph::getValueAt(std::uint8_t ubX, std::uint8_t ubY)\n{\n\tstd::uint8_t ubValue = this->m_vData[ubY * this->m_ubWidth + ubY];\n\treturn ubValue;\n}\n\nbool tGlyphSet::tBitmapGlyph::hasEmptyColumn(std::uint8_t ubX)\n{\n\tfor(std::uint8_t ubY = 0; ubY < this->m_ubHeight; ++ubY) {\n\t\tif(getValueAt(ubX, ubY) != 0) {\n\t\t\treturn false;\n\t\t}\n\t}\n\treturn true;\n}\n\nbool tGlyphSet::tBitmapGlyph::isEmpty(void)\n{\n\tfor(std::uint8_t ubX = 0; ubX < this->m_ubWidth; ++ubX) {\n\t\tif(!hasEmptyColumn(ubX)) {\n\t\t\treturn false;\n\t\t}\n\t}\n\treturn true;\n}\n\nvoid tGlyphSet::tBitmapGlyph::trimHorz(bool isRight)\n{\n\tif(isEmpty()) {\n\t\treturn;\n\t}\n\n\tstd::uint8_t ubNewWidth;\n\tstd::uint8_t ubNewStart;\n\tif(isRight) {\n\t\tubNewStart = 0;\n\t\tfor(ubNewWidth = m_ubWidth; ubNewWidth > 0; --ubNewWidth) {\n\t\t\tif(!hasEmptyColumn(ubNewWidth - 1)) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\telse {\n\t\tfor(ubNewStart = 0; ubNewStart < m_ubWidth; ++ubNewStart) {\n\t\t\tif(!hasEmptyColumn(ubNewStart)) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tubNewWidth = m_ubWidth - ubNewStart;\n\t}\n\n\tstd::vector<uint8_t> vNew(ubNewWidth * m_ubHeight);\n\tfor(std::uint8_t ubNewX = 0; ubNewX < ubNewWidth; ++ubNewX) {\n\t\tfor(std::uint8_t ubNewY = 0; ubNewY < m_ubHeight; ++ubNewY) {\n\t\t\tvNew[ubNewY * ubNewWidth + ubNewX] = this->m_vData[ubNewY * m_ubWidth + ubNewStart + ubNewX];\n\t\t}\n\t}\n\tm_vData = vNew;\n\tm_ubWidth = ubNewWidth;\n}\n\nvoid tGlyphSet::toAceFont(const std::string &szFontPath)\n{\n\tstd::uint16_t uwOffs = 0;\n\tstd::uint8_t ubCharCount = 0;\n\tfor(const auto &GlyphPair: m_mGlyphs) {\n\t\tif(GlyphPair.first > ubCharCount) {\n\t\t\tubCharCount = GlyphPair.first;\n\t\t}\n\t}\n\t++ubCharCount;\n\t// Generate char offsets\n\tstd::vector<uint16_t> vCharOffsets(256);\n\tfor(std::uint16_t c = 0; c < ubCharCount; ++c) {\n\t\tvCharOffsets[c] = nEndian::toBig16(uwOffs);\n\t\tif(m_mGlyphs.count(c) != 0) {\n\t\t\tconst auto &Glyph = m_mGlyphs.at(c);\n\t\t\tuwOffs += Glyph.m_ubWidth;\n\t\t}\n\t}\n\t// This allows drawing of last char\n\tvCharOffsets[ubCharCount] = nEndian::toBig16(uwOffs);\n\t++ubCharCount;\n\n\ttPlanarBitmap Planar(\n\t\tthis->toPackedBitmap(false), tPalette({tRgb(0), tRgb(0xFF)}), tPalette()\n\t);\n\n\tstd::ofstream Out(szFontPath, std::ofstream::out | std::ofstream::binary);\n\t// Write header\n\tstd::uint16_t uwBitmapWidth = nEndian::toBig16(Planar.m_uwWidth);\n\tOut.write(reinterpret_cast<char*>(&uwBitmapWidth), sizeof(uint16_t));\n\tstd::uint16_t uwBitmapHeight = nEndian::toBig16(m_mGlyphs.begin()->second.m_ubHeight);\n\tOut.write(reinterpret_cast<char*>(&uwBitmapHeight), sizeof(uint16_t));\n\tOut.write(reinterpret_cast<char*>(&ubCharCount), sizeof(uint8_t));\n\n\t// Write char offsets\n\tOut.write(\n\t\treinterpret_cast<char*>(vCharOffsets.data()), sizeof(uint16_t) * ubCharCount\n\t);\n\n\t// Write font bitplane\n\tstd::uint16_t uwRowWords = Planar.m_uwWidth / 16;\n\tfor(std::uint16_t y = 0; y < Planar.m_uwHeight; ++y) {\n\t\tfor(std::uint16_t x = 0; x < uwRowWords; ++x) {\n\t\t\tstd::uint16_t uwData = nEndian::toBig16(Planar.m_pPlanes[0][y * uwRowWords + x]);\n\t\t\tOut.write(reinterpret_cast<char*>(&uwData), sizeof(uint16_t));\n\t\t}\n\t}\n\n\tOut.close();\n}\n\nbool tGlyphSet::isOk(void)\n{\n\treturn m_mGlyphs.size() != 0;\n}\n\nvoid tGlyphSet::remapGlyphs(const std::vector<std::pair<uint32_t, uint32_t>> &vFromTo)\n{\n\t// Extract one by one and replace key so that other elements won't\n\t// be overwritten before key changing\n\t// This allows 'a' <=> 'b' replacement in one go\n\tstd::vector<decltype(m_mGlyphs)::node_type> vExtracted;\n\tfor(const auto &FromTo: vFromTo) {\n\t\tauto Pos = m_mGlyphs.find(FromTo.first);\n\t\tif(Pos != m_mGlyphs.end()) {\n\t\t\tauto Node = m_mGlyphs.extract(Pos);\n\t\t\tNode.key() = FromTo.second;\n\t\t\tvExtracted.push_back(std::move(Node));\n\t\t}\n\t}\n\n\tfor(auto &Node: vExtracted) {\n\t\tm_mGlyphs.insert(std::move(Node));\n\t}\n}\n"
  },
  {
    "path": "tools/src/common/glyph_set.h",
    "content": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at http://mozilla.org/MPL/2.0/. */\n\n#ifndef _ACE_TOOLS_COMMON_GLYPH_SET_H_\n#define _ACE_TOOLS_COMMON_GLYPH_SET_H_\n\n#include <vector>\n#include <map>\n#include <cstdint>\n#include \"bitmap.h\"\n\nclass tGlyphSet {\npublic:\n\tstatic tGlyphSet fromTtf(\n\t\tconst std::string &szTtfPath, std::uint8_t ubSize, const std::string &szCharSet,\n\t\tstd::uint8_t ubThreshold\n\t);\n\n\t/**\n\t * @brief Creates glyph set based on ProMotion NG's PNG font file.\n\t *\n\t * @param szPngPath Path to png file saved in PMNG's way of saving fonts.\n\t * @param ubStartIdx ASCII index of first glyph in PMNG file.\n\t * @return Glyph set filled with characters from file.\n\t */\n\tstatic tGlyphSet fromPmng(const std::string &szPngPath, std::uint8_t ubStartIdx = 33);\n\n\t/**\n\t * @brief Creates glyph set based on ACE font (.fnt) file.\n\t *\n\t * @param szFntPath Path to fnt file.\n\t * @return Glyph set filled with characters from file.\n\t */\n\tstatic tGlyphSet fromAceFont(const std::string &szFntPath);\n\n\tstatic tGlyphSet fromDir(const std::string &szDirPath);\n\n\tbool toDir(const std::string &szDirPath);\n\n\tvoid toAceFont(const std::string &szFontPath);\n\n\ttChunkyBitmap toPackedBitmap(bool isPmng);\n\n\tbool isOk(void);\n\n\tvoid remapGlyphs(const std::vector<std::pair<uint32_t, uint32_t>> &vFromTo);\n\nprivate:\n\tstruct tBitmapGlyph {\n\t\tstd::uint8_t m_ubBearing;\n\t\tstd::uint8_t m_ubWidth, m_ubHeight;\n\t\tstd::vector<uint8_t> m_vData; ///< One byte per pixel, 0 for bg, 0xFF otherwise.\n\n\t\tvoid trimHorz(bool isRight);\n\n\t\tstd::uint8_t getValueAt(std::uint8_t ubX, std::uint8_t ubY);\n\t\tbool isEmpty(void);\n\t\tbool hasEmptyColumn(std::uint8_t ubX);\n\t};\n\n\tstd::map<uint16_t, tBitmapGlyph> m_mGlyphs;\n};\n\n#endif // _ACE_TOOLS_COMMON_GLYPH_SET_H_\n"
  },
  {
    "path": "tools/src/common/jsmn.c",
    "content": "#include \"jsmn.h\"\n\n/**\n * Allocates a fresh unused token from the token pull.\n */\nstatic jsmntok_t *jsmn_alloc_token(jsmn_parser *parser,\n\t\tjsmntok_t *tokens, size_t num_tokens) {\n\tjsmntok_t *tok;\n\tif (parser->toknext >= num_tokens) {\n\t\treturn NULL;\n\t}\n\ttok = &tokens[parser->toknext++];\n\ttok->start = tok->end = -1;\n\ttok->size = 0;\n#ifdef JSMN_PARENT_LINKS\n\ttok->parent = -1;\n#endif\n\treturn tok;\n}\n\n/**\n * Fills token type and boundaries.\n */\nstatic void jsmn_fill_token(jsmntok_t *token, jsmntype_t type,\n                            int start, int end) {\n\ttoken->type = type;\n\ttoken->start = start;\n\ttoken->end = end;\n\ttoken->size = 0;\n}\n\n/**\n * Fills next available token with JSON primitive.\n */\nstatic int jsmn_parse_primitive(jsmn_parser *parser, const char *js,\n\t\tsize_t len, jsmntok_t *tokens, size_t num_tokens) {\n\tjsmntok_t *token;\n\tint start;\n\n\tstart = parser->pos;\n\n\tfor (; parser->pos < len && js[parser->pos] != '\\0'; parser->pos++) {\n\t\tswitch (js[parser->pos]) {\n#ifndef JSMN_STRICT\n\t\t\t/* In strict mode primitive must be followed by \",\" or \"}\" or \"]\" */\n\t\t\tcase ':':\n#endif\n\t\t\tcase '\\t' : case '\\r' : case '\\n' : case ' ' :\n\t\t\tcase ','  : case ']'  : case '}' :\n\t\t\t\tgoto found;\n\t\t}\n\t\tif (js[parser->pos] < 32 || js[parser->pos] >= 127) {\n\t\t\tparser->pos = start;\n\t\t\treturn JSMN_ERROR_INVAL;\n\t\t}\n\t}\n#ifdef JSMN_STRICT\n\t/* In strict mode primitive must be followed by a comma/object/array */\n\tparser->pos = start;\n\treturn JSMN_ERROR_PART;\n#endif\n\nfound:\n\tif (tokens == NULL) {\n\t\tparser->pos--;\n\t\treturn 0;\n\t}\n\ttoken = jsmn_alloc_token(parser, tokens, num_tokens);\n\tif (token == NULL) {\n\t\tparser->pos = start;\n\t\treturn JSMN_ERROR_NOMEM;\n\t}\n\tjsmn_fill_token(token, JSMN_PRIMITIVE, start, parser->pos);\n#ifdef JSMN_PARENT_LINKS\n\ttoken->parent = parser->toksuper;\n#endif\n\tparser->pos--;\n\treturn 0;\n}\n\n/**\n * Fills next token with JSON string.\n */\nstatic int jsmn_parse_string(jsmn_parser *parser, const char *js,\n\t\tsize_t len, jsmntok_t *tokens, size_t num_tokens) {\n\tjsmntok_t *token;\n\n\tint start = parser->pos;\n\n\tparser->pos++;\n\n\t/* Skip starting quote */\n\tfor (; parser->pos < len && js[parser->pos] != '\\0'; parser->pos++) {\n\t\tchar c = js[parser->pos];\n\n\t\t/* Quote: end of string */\n\t\tif (c == '\\\"') {\n\t\t\tif (tokens == NULL) {\n\t\t\t\treturn 0;\n\t\t\t}\n\t\t\ttoken = jsmn_alloc_token(parser, tokens, num_tokens);\n\t\t\tif (token == NULL) {\n\t\t\t\tparser->pos = start;\n\t\t\t\treturn JSMN_ERROR_NOMEM;\n\t\t\t}\n\t\t\tjsmn_fill_token(token, JSMN_STRING, start+1, parser->pos);\n#ifdef JSMN_PARENT_LINKS\n\t\t\ttoken->parent = parser->toksuper;\n#endif\n\t\t\treturn 0;\n\t\t}\n\n\t\t/* Backslash: Quoted symbol expected */\n\t\tif (c == '\\\\' && parser->pos + 1 < len) {\n\t\t\tint i;\n\t\t\tparser->pos++;\n\t\t\tswitch (js[parser->pos]) {\n\t\t\t\t/* Allowed escaped symbols */\n\t\t\t\tcase '\\\"': case '/' : case '\\\\' : case 'b' :\n\t\t\t\tcase 'f' : case 'r' : case 'n'  : case 't' :\n\t\t\t\t\tbreak;\n\t\t\t\t/* Allows escaped symbol \\uXXXX */\n\t\t\t\tcase 'u':\n\t\t\t\t\tparser->pos++;\n\t\t\t\t\tfor(i = 0; i < 4 && parser->pos < len && js[parser->pos] != '\\0'; i++) {\n\t\t\t\t\t\t/* If it isn't a hex character we have an error */\n\t\t\t\t\t\tif(!((js[parser->pos] >= 48 && js[parser->pos] <= 57) || /* 0-9 */\n\t\t\t\t\t\t\t\t\t(js[parser->pos] >= 65 && js[parser->pos] <= 70) || /* A-F */\n\t\t\t\t\t\t\t\t\t(js[parser->pos] >= 97 && js[parser->pos] <= 102))) { /* a-f */\n\t\t\t\t\t\t\tparser->pos = start;\n\t\t\t\t\t\t\treturn JSMN_ERROR_INVAL;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tparser->pos++;\n\t\t\t\t\t}\n\t\t\t\t\tparser->pos--;\n\t\t\t\t\tbreak;\n\t\t\t\t/* Unexpected symbol */\n\t\t\t\tdefault:\n\t\t\t\t\tparser->pos = start;\n\t\t\t\t\treturn JSMN_ERROR_INVAL;\n\t\t\t}\n\t\t}\n\t}\n\tparser->pos = start;\n\treturn JSMN_ERROR_PART;\n}\n\n/**\n * Parse JSON string and fill tokens.\n */\nint jsmn_parse(jsmn_parser *parser, const char *js, size_t len,\n\t\tjsmntok_t *tokens, unsigned int num_tokens) {\n\tint r;\n\tint i;\n\tjsmntok_t *token;\n\tint count = parser->toknext;\n\n\tfor (; parser->pos < len && js[parser->pos] != '\\0'; parser->pos++) {\n\t\tchar c;\n\t\tjsmntype_t type;\n\n\t\tc = js[parser->pos];\n\t\tswitch (c) {\n\t\t\tcase '{': case '[':\n\t\t\t\tcount++;\n\t\t\t\tif (tokens == NULL) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\ttoken = jsmn_alloc_token(parser, tokens, num_tokens);\n\t\t\t\tif (token == NULL)\n\t\t\t\t\treturn JSMN_ERROR_NOMEM;\n\t\t\t\tif (parser->toksuper != -1) {\n\t\t\t\t\ttokens[parser->toksuper].size++;\n#ifdef JSMN_PARENT_LINKS\n\t\t\t\t\ttoken->parent = parser->toksuper;\n#endif\n\t\t\t\t}\n\t\t\t\ttoken->type = (c == '{' ? JSMN_OBJECT : JSMN_ARRAY);\n\t\t\t\ttoken->start = parser->pos;\n\t\t\t\tparser->toksuper = parser->toknext - 1;\n\t\t\t\tbreak;\n\t\t\tcase '}': case ']':\n\t\t\t\tif (tokens == NULL)\n\t\t\t\t\tbreak;\n\t\t\t\ttype = (c == '}' ? JSMN_OBJECT : JSMN_ARRAY);\n#ifdef JSMN_PARENT_LINKS\n\t\t\t\tif (parser->toknext < 1) {\n\t\t\t\t\treturn JSMN_ERROR_INVAL;\n\t\t\t\t}\n\t\t\t\ttoken = &tokens[parser->toknext - 1];\n\t\t\t\tfor (;;) {\n\t\t\t\t\tif (token->start != -1 && token->end == -1) {\n\t\t\t\t\t\tif (token->type != type) {\n\t\t\t\t\t\t\treturn JSMN_ERROR_INVAL;\n\t\t\t\t\t\t}\n\t\t\t\t\t\ttoken->end = parser->pos + 1;\n\t\t\t\t\t\tparser->toksuper = token->parent;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tif (token->parent == -1) {\n\t\t\t\t\t\tif(token->type != type || parser->toksuper == -1) {\n\t\t\t\t\t\t\treturn JSMN_ERROR_INVAL;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\ttoken = &tokens[token->parent];\n\t\t\t\t}\n#else\n\t\t\t\tfor (i = parser->toknext - 1; i >= 0; i--) {\n\t\t\t\t\ttoken = &tokens[i];\n\t\t\t\t\tif (token->start != -1 && token->end == -1) {\n\t\t\t\t\t\tif (token->type != type) {\n\t\t\t\t\t\t\treturn JSMN_ERROR_INVAL;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tparser->toksuper = -1;\n\t\t\t\t\t\ttoken->end = parser->pos + 1;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t/* Error if unmatched closing bracket */\n\t\t\t\tif (i == -1) return JSMN_ERROR_INVAL;\n\t\t\t\tfor (; i >= 0; i--) {\n\t\t\t\t\ttoken = &tokens[i];\n\t\t\t\t\tif (token->start != -1 && token->end == -1) {\n\t\t\t\t\t\tparser->toksuper = i;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n#endif\n\t\t\t\tbreak;\n\t\t\tcase '\\\"':\n\t\t\t\tr = jsmn_parse_string(parser, js, len, tokens, num_tokens);\n\t\t\t\tif (r < 0) return r;\n\t\t\t\tcount++;\n\t\t\t\tif (parser->toksuper != -1 && tokens != NULL)\n\t\t\t\t\ttokens[parser->toksuper].size++;\n\t\t\t\tbreak;\n\t\t\tcase '\\t' : case '\\r' : case '\\n' : case ' ':\n\t\t\t\tbreak;\n\t\t\tcase ':':\n\t\t\t\tparser->toksuper = parser->toknext - 1;\n\t\t\t\tbreak;\n\t\t\tcase ',':\n\t\t\t\tif (tokens != NULL && parser->toksuper != -1 &&\n\t\t\t\t\t\ttokens[parser->toksuper].type != JSMN_ARRAY &&\n\t\t\t\t\t\ttokens[parser->toksuper].type != JSMN_OBJECT) {\n#ifdef JSMN_PARENT_LINKS\n\t\t\t\t\tparser->toksuper = tokens[parser->toksuper].parent;\n#else\n\t\t\t\t\tfor (i = parser->toknext - 1; i >= 0; i--) {\n\t\t\t\t\t\tif (tokens[i].type == JSMN_ARRAY || tokens[i].type == JSMN_OBJECT) {\n\t\t\t\t\t\t\tif (tokens[i].start != -1 && tokens[i].end == -1) {\n\t\t\t\t\t\t\t\tparser->toksuper = i;\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n#endif\n\t\t\t\t}\n\t\t\t\tbreak;\n#ifdef JSMN_STRICT\n\t\t\t/* In strict mode primitives are: numbers and booleans */\n\t\t\tcase '-': case '0': case '1' : case '2': case '3' : case '4':\n\t\t\tcase '5': case '6': case '7' : case '8': case '9':\n\t\t\tcase 't': case 'f': case 'n' :\n\t\t\t\t/* And they must not be keys of the object */\n\t\t\t\tif (tokens != NULL && parser->toksuper != -1) {\n\t\t\t\t\tjsmntok_t *t = &tokens[parser->toksuper];\n\t\t\t\t\tif (t->type == JSMN_OBJECT ||\n\t\t\t\t\t\t\t(t->type == JSMN_STRING && t->size != 0)) {\n\t\t\t\t\t\treturn JSMN_ERROR_INVAL;\n\t\t\t\t\t}\n\t\t\t\t}\n#else\n\t\t\t/* In non-strict mode every unquoted value is a primitive */\n\t\t\tdefault:\n#endif\n\t\t\t\tr = jsmn_parse_primitive(parser, js, len, tokens, num_tokens);\n\t\t\t\tif (r < 0) return r;\n\t\t\t\tcount++;\n\t\t\t\tif (parser->toksuper != -1 && tokens != NULL)\n\t\t\t\t\ttokens[parser->toksuper].size++;\n\t\t\t\tbreak;\n\n#ifdef JSMN_STRICT\n\t\t\t/* Unexpected char in strict mode */\n\t\t\tdefault:\n\t\t\t\treturn JSMN_ERROR_INVAL;\n#endif\n\t\t}\n\t}\n\n\tif (tokens != NULL) {\n\t\tfor (i = parser->toknext - 1; i >= 0; i--) {\n\t\t\t/* Unmatched opened object or array */\n\t\t\tif (tokens[i].start != -1 && tokens[i].end == -1) {\n\t\t\t\treturn JSMN_ERROR_PART;\n\t\t\t}\n\t\t}\n\t}\n\n\treturn count;\n}\n\n/**\n * Creates a new parser based over a given  buffer with an array of tokens\n * available.\n */\nvoid jsmn_init(jsmn_parser *parser) {\n\tparser->pos = 0;\n\tparser->toknext = 0;\n\tparser->toksuper = -1;\n}\n\n"
  },
  {
    "path": "tools/src/common/jsmn.h",
    "content": "#ifndef __JSMN_H_\n#define __JSMN_H_\n\n#include <stddef.h>\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n/**\n * JSON type identifier. Basic types are:\n * \to Object\n * \to Array\n * \to String\n * \to Other primitive: number, boolean (true/false) or null\n */\ntypedef enum {\n\tJSMN_UNDEFINED = 0,\n\tJSMN_OBJECT = 1,\n\tJSMN_ARRAY = 2,\n\tJSMN_STRING = 3,\n\tJSMN_PRIMITIVE = 4\n} jsmntype_t;\n\nenum jsmnerr {\n\t/* Not enough tokens were provided */\n\tJSMN_ERROR_NOMEM = -1,\n\t/* Invalid character inside JSON string */\n\tJSMN_ERROR_INVAL = -2,\n\t/* The string is not a full JSON packet, more bytes expected */\n\tJSMN_ERROR_PART = -3\n};\n\n/**\n * JSON token description.\n * type\t\ttype (object, array, string etc.)\n * start\tstart position in JSON data string\n * end\t\tend position in JSON data string\n */\ntypedef struct {\n\tjsmntype_t type;\n\tint start;\n\tint end;\n\tint size;\n#ifdef JSMN_PARENT_LINKS\n\tint parent;\n#endif\n} jsmntok_t;\n\n/**\n * JSON parser. Contains an array of token blocks available. Also stores\n * the string being parsed now and current position in that string\n */\ntypedef struct {\n\tunsigned int pos; /* offset in the JSON string */\n\tunsigned int toknext; /* next token to allocate */\n\tint toksuper; /* superior token node, e.g parent object or array */\n} jsmn_parser;\n\n/**\n * Create JSON parser over an array of tokens\n */\nvoid jsmn_init(jsmn_parser *parser);\n\n/**\n * Run JSON parser. It parses a JSON data string into and array of tokens, each describing\n * a single JSON object.\n */\nint jsmn_parse(jsmn_parser *parser, const char *js, size_t len,\n\t\tjsmntok_t *tokens, unsigned int num_tokens);\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif /* __JSMN_H_ */\n"
  },
  {
    "path": "tools/src/common/json.c",
    "content": "#include \"json.h\"\r\n#include <stdio.h>\r\n#include <stdlib.h>\r\n#include <string.h>\r\n#include \"utf8.h\"\r\n\r\ntJson *jsonCreate(const char *szFilePath) {\r\n\r\n\t// Read whole file to string\r\n\tFILE *pFile = fopen(szFilePath, \"rb\");\r\n\tif(!pFile) {\r\n\t\treturn 0;\r\n\t}\r\n\r\n\tfseek(pFile, 0, SEEK_END);\r\n\tint32_t lFileSize = ftell(pFile);\r\n\tfseek(pFile, 0, SEEK_SET);\r\n\r\n\ttJson *pJson = malloc(sizeof(tJson));\r\n\tpJson->szData = malloc(lFileSize+1);\r\n\r\n\tfread(pJson->szData, lFileSize, 1, pFile);\r\n\tpJson->szData[lFileSize] = '\\0';\r\n\tfclose(pFile);\r\n\r\n\tjsmn_parser sJsonParser;\r\n\tjsmn_init(&sJsonParser);\r\n\r\n\t// Count tokens & alloc\r\n\tpJson->uwTokenCount = jsmn_parse(&sJsonParser, pJson->szData, lFileSize+1, 0, 0);\r\n\tif(pJson->uwTokenCount < 0) {\r\n\t\treturn 0;\r\n\t}\r\n\tpJson->pTokens = malloc(pJson->uwTokenCount * sizeof(jsmntok_t));\r\n\r\n\t// Read tokens\r\n\tjsmn_init(&sJsonParser);\r\n\tuint16_t uwResult = jsmn_parse(\r\n\t\t&sJsonParser, pJson->szData, lFileSize+1, pJson->pTokens, pJson->uwTokenCount\r\n\t);\r\n\tif(uwResult < 0) {\r\n\t\treturn 0;\r\n\t}\r\n\r\n\treturn pJson;\r\n}\r\n\r\nvoid jsonDestroy(tJson *pJson) {\r\n\tfree(pJson->pTokens);\r\n\tfree(pJson->szData);\r\n\tfree(pJson);\r\n}\r\n\r\nuint16_t jsonGetElementInArray(\r\n\tconst tJson *pJson, uint16_t uwParentIdx, uint16_t uwIdx\r\n) {\r\n\tuint16_t uwCurrIdx = 0;\r\n\tif(pJson->pTokens[uwParentIdx].type != JSMN_ARRAY) {\r\n\t\treturn 0;\r\n\t}\r\n\tfor(uint16_t i = uwParentIdx+1; i < pJson->uwTokenCount; ++i) {\r\n\t\tif(pJson->pTokens[i].start > pJson->pTokens[uwParentIdx].end) {\r\n\t\t\t// We're outside of parent - nothing found\r\n\t\t\treturn 0;\r\n\t\t}\r\n\t\tif(uwCurrIdx == uwIdx) {\r\n\t\t\treturn i;\r\n\t\t}\r\n\t\telse {\r\n\t\t\t// Something else - skip it\r\n\t\t\tuint16_t uwSkipPos = pJson->pTokens[i].end;\r\n\t\t\twhile(pJson->pTokens[i+1].start < uwSkipPos) {\r\n\t\t\t\t++i;\r\n\t\t\t}\r\n\t\t}\r\n\t\t++uwCurrIdx;\r\n\t}\r\n\t// Unxepected end of JSON\r\n\treturn 0;\r\n}\r\n\r\nuint16_t jsonGetElementInStruct(\r\n\tconst tJson *pJson, uint16_t uwParentIdx, const char *szElement\r\n) {\r\n\tfor(uint16_t i = uwParentIdx+1; i < pJson->uwTokenCount; ++i) {\r\n\t\tif(pJson->pTokens[i].start > pJson->pTokens[uwParentIdx].end) {\r\n\t\t\t// We're outside of parent - nothing found\r\n\t\t\treturn 0;\r\n\t\t}\r\n\t\tconst char *pNextElementName = pJson->szData + pJson->pTokens[i].start;\r\n\t\tif(\r\n\t\t\t!memcmp(pNextElementName, szElement, strlen(szElement)) &&\r\n\t\t\tpNextElementName[strlen(szElement)] == '\"'\r\n\t\t) {\r\n\t\t\t// Found label - next is content\r\n\t\t\treturn i+1;\r\n\t\t}\r\n\t\telse {\r\n\t\t\t// Something else - skip it\r\n\t\t\tuint16_t uwSkipPos = pJson->pTokens[++i].end;\r\n\t\t\twhile(pJson->pTokens[i+1].start < uwSkipPos) {\r\n\t\t\t\t++i;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\t// Unxepected end of JSON\r\n\treturn 0;\r\n}\r\n\r\nuint16_t jsonGetDom(const tJson *pJson, const char *szPattern) {\r\n\t// \"first.second.third\" or \"first\" or \"first[1].third\"\r\n\tuint16_t uwParentTok = 0;\r\n\tconst char *c = szPattern;\r\n\tdo {\r\n\t\tif(*c == '[') {\r\n\t\t\t// Array element - read number\r\n\t\t\tuint16_t uwIdx = 0;\r\n\t\t\twhile(*(++c) != ']') {\r\n\t\t\t\tif(*c < '0' || *c > '9') {\r\n\t\t\t\t\treturn 0;\r\n\t\t\t\t}\r\n\t\t\t\tuwIdx = uwIdx*10 + (*c - '0');\r\n\t\t\t}\r\n\t\t\tuwParentTok = jsonGetElementInArray(pJson, uwParentTok, uwIdx);\r\n\t\t\t++c;\r\n\t\t}\r\n\t\telse {\r\n\t\t\t// Struct element - read name\r\n\t\t\tchar szElementName[200];\r\n\t\t\tuint16_t uwElementNameLength = 0;\r\n\t\t\twhile(*c != '.' && *c != '[' && *c != '\\0') {\r\n\t\t\t\tszElementName[uwElementNameLength] = *c;\r\n\t\t\t\t++uwElementNameLength;\r\n\t\t\t\t++c;\r\n\t\t\t}\r\n\t\t\tszElementName[uwElementNameLength] = '\\0';\r\n\t\t\tuwParentTok = jsonGetElementInStruct(pJson, uwParentTok, szElementName);\r\n\t\t\tif(*c == '.') {\r\n\t\t\t\t++c;\r\n\t\t\t}\r\n\t\t}\r\n\t\tif(!uwParentTok) {\r\n\t\t\treturn 0;\r\n\t\t}\r\n\r\n\t} while(*c != '\\0');\r\n\treturn uwParentTok;\r\n}\r\n\r\nuint32_t jsonTokToUlong(const tJson *pJson, uint16_t uwTok) {\r\n\treturn strtoul(pJson->szData + pJson->pTokens[uwTok].start, 0, 10);\r\n}\r\n\r\nuint16_t jsonStrLen(const tJson *pJson, uint16_t uwTok) {\r\n  uint32_t ulCodepoint, ulState = 0;\r\n\tuint16_t uwLength = 0;\r\n\tfor(uint16_t i = pJson->pTokens[uwTok].start; i < pJson->pTokens[uwTok].end; ++i) {\r\n\t\tuint8_t ubCharCode = (uint8_t)pJson->szData[i];\r\n\t\tif(decode(&ulState, &ulCodepoint, ubCharCode) != UTF8_ACCEPT) {\r\n\t\t\tcontinue;\r\n\t\t}\r\n\t\t++uwLength;\r\n\t}\r\n\treturn uwLength;\r\n}\r\n\r\nuint16_t jsonTokStrCpy(\r\n\tconst tJson *pJson, uint16_t uwTok, char *pDst, uint16_t uwMaxBytes\r\n) {\r\n\tuint16_t uwLength = 0;\r\n\tuint32_t ulCodepoint, ulState = 0;\r\n\tfor(uint16_t i = pJson->pTokens[uwTok].start; i < pJson->pTokens[uwTok].end; ++i) {\r\n\t\tuint8_t ubCharCode = (uint8_t)pJson->szData[i];\r\n\t\tif(decode(&ulState, &ulCodepoint, ubCharCode) != UTF8_ACCEPT) {\r\n\t\t\tcontinue;\r\n\t\t}\r\n\t\tpDst[uwLength] = ulCodepoint;\r\n\t\tif(++uwLength >= uwMaxBytes - 1) {\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n\tpDst[uwLength] = '\\0';\r\n\treturn uwLength;\r\n}\r\n"
  },
  {
    "path": "tools/src/common/json.h",
    "content": "#ifndef GUARD_OF_JSON_H\r\n#define GUARD_OF_JSON_H\r\n\r\n#ifdef __cplusplus\r\nextern \"C\" {\r\n#endif\r\n\r\n#include <stdint.h>\r\n\r\n#define JSMN_STRICT       /* Strict JSON parsing */\r\n// JSMN_PARENT_LINKS breaks things up!\r\n// #define JSMN_PARENT_LINKS /* Speeds things up */\r\n#include \"jsmn.h\"\r\n\r\ntypedef struct _tJson {\r\n\tchar *szData;\r\n\tjsmntok_t *pTokens;\r\n\tuint16_t uwTokenCount;\r\n} tJson;\r\n\r\ntJson *jsonCreate(const char *szFilePath);\r\n\r\nvoid jsonDestroy(tJson *pJson);\r\n\r\nuint16_t jsonGetElementInArray(const tJson *pJson,uint16_t uwParentIdx,uint16_t uwIdx);\r\n\r\nuint16_t jsonGetElementInStruct(\r\n\tconst tJson *pJson,uint16_t uwParentIdx,const char *szElement\r\n);\r\n\r\nuint16_t jsonGetDom(const tJson *pJson,const char *szPattern);\r\n\r\nuint32_t jsonTokToUlong(const tJson *pJson,uint16_t uwTok);\r\n\r\nuint16_t jsonStrLen(const tJson *pJson, uint16_t uwTok);\r\n\r\nuint16_t jsonTokStrCpy(\r\n\tconst tJson *pJson, uint16_t uwTok, char *pDst, uint16_t uwMaxBytes\r\n);\r\n\r\n#ifdef __cplusplus\r\n}\r\n#endif\r\n\r\n#endif // GUARD_OF_JSON_H\r\n"
  },
  {
    "path": "tools/src/common/lodepng.cpp",
    "content": "/*\nLodePNG version 20160501\n\nCopyright (c) 2005-2016 Lode Vandevenne\n\nThis software is provided 'as-is', without any express or implied\nwarranty. In no event will the authors be held liable for any damages\narising from the use of this software.\n\nPermission is granted to anyone to use this software for any purpose,\nincluding commercial applications, and to alter it and redistribute it\nfreely, subject to the following restrictions:\n\n    1. The origin of this software must not be misrepresented; you must not\n    claim that you wrote the original software. If you use this software\n    in a product, an acknowledgment in the product documentation would be\n    appreciated but is not required.\n\n    2. Altered source versions must be plainly marked as such, and must not be\n    misrepresented as being the original software.\n\n    3. This notice may not be removed or altered from any source\n    distribution.\n*/\n\n/*\nThe manual and changelog are in the header file \"lodepng.h\"\nRename this file to lodepng.cpp to use it for C++, or to lodepng.c to use it for C.\n*/\n\n#include \"lodepng.h\"\n\n#include <limits.h>\n#include <stdio.h>\n#include <stdlib.h>\n\n#if defined(_MSC_VER) && (_MSC_VER >= 1310) /*Visual Studio: A few warning types are not desired here.*/\n#pragma warning( disable : 4244 ) /*implicit conversions: not warned by gcc -Wall -Wextra and requires too much casts*/\n#pragma warning( disable : 4996 ) /*VS does not like fopen, but fopen_s is not standard C so unusable here*/\n#endif /*_MSC_VER */\n\nconst char* LODEPNG_VERSION_STRING = \"20160501\";\n\n/*\nThis source file is built up in the following large parts. The code sections\nwith the \"LODEPNG_COMPILE_\" #defines divide this up further in an intermixed way.\n-Tools for C and common code for PNG and Zlib\n-C Code for Zlib (huffman, deflate, ...)\n-C Code for PNG (file format chunks, adam7, PNG filters, color conversions, ...)\n-The C++ wrapper around all of the above\n*/\n\n/*The malloc, realloc and free functions defined here with \"lodepng_\" in front\nof the name, so that you can easily change them to others related to your\nplatform if needed. Everything else in the code calls these. Pass\n-DLODEPNG_NO_COMPILE_ALLOCATORS to the compiler, or comment out\n#define LODEPNG_COMPILE_ALLOCATORS in the header, to disable the ones here and\ndefine them in your own project's source files without needing to change\nlodepng source code. Don't forget to remove \"static\" if you copypaste them\nfrom here.*/\n\n#ifdef LODEPNG_COMPILE_ALLOCATORS\nstatic void* lodepng_malloc(size_t size)\n{\n  return malloc(size);\n}\n\nstatic void* lodepng_realloc(void* ptr, size_t new_size)\n{\n  return realloc(ptr, new_size);\n}\n\nstatic void lodepng_free(void* ptr)\n{\n  free(ptr);\n}\n#else /*LODEPNG_COMPILE_ALLOCATORS*/\nvoid* lodepng_malloc(size_t size);\nvoid* lodepng_realloc(void* ptr, size_t new_size);\nvoid lodepng_free(void* ptr);\n#endif /*LODEPNG_COMPILE_ALLOCATORS*/\n\n/* ////////////////////////////////////////////////////////////////////////// */\n/* ////////////////////////////////////////////////////////////////////////// */\n/* // Tools for C, and common code for PNG and Zlib.                       // */\n/* ////////////////////////////////////////////////////////////////////////// */\n/* ////////////////////////////////////////////////////////////////////////// */\n\n/*\nOften in case of an error a value is assigned to a variable and then it breaks\nout of a loop (to go to the cleanup phase of a function). This macro does that.\nIt makes the error handling code shorter and more readable.\n\nExample: if(!uivector_resizev(&frequencies_ll, 286, 0)) ERROR_BREAK(83);\n*/\n#define CERROR_BREAK(errorvar, code)\\\n{\\\n  errorvar = code;\\\n  break;\\\n}\n\n/*version of CERROR_BREAK that assumes the common case where the error variable is named \"error\"*/\n#define ERROR_BREAK(code) CERROR_BREAK(error, code)\n\n/*Set error var to the error code, and return it.*/\n#define CERROR_RETURN_ERROR(errorvar, code)\\\n{\\\n  errorvar = code;\\\n  return code;\\\n}\n\n/*Try the code, if it returns error, also return the error.*/\n#define CERROR_TRY_RETURN(call)\\\n{\\\n  unsigned error = call;\\\n  if(error) return error;\\\n}\n\n/*Set error var to the error code, and return from the void function.*/\n#define CERROR_RETURN(errorvar, code)\\\n{\\\n  errorvar = code;\\\n  return;\\\n}\n\n/*\nAbout uivector, ucvector and string:\n-All of them wrap dynamic arrays or text strings in a similar way.\n-LodePNG was originally written in C++. The vectors replace the std::vectors that were used in the C++ version.\n-The string tools are made to avoid problems with compilers that declare things like strncat as deprecated.\n-They're not used in the interface, only internally in this file as static functions.\n-As with many other structs in this file, the init and cleanup functions serve as ctor and dtor.\n*/\n\n#ifdef LODEPNG_COMPILE_ZLIB\n/*dynamic vector of unsigned ints*/\ntypedef struct uivector\n{\n  unsigned* data;\n  size_t size; /*size in number of unsigned longs*/\n  size_t allocsize; /*allocated size in bytes*/\n} uivector;\n\nstatic void uivector_cleanup(void* p)\n{\n  ((uivector*)p)->size = ((uivector*)p)->allocsize = 0;\n  lodepng_free(((uivector*)p)->data);\n  ((uivector*)p)->data = NULL;\n}\n\n/*returns 1 if success, 0 if failure ==> nothing done*/\nstatic unsigned uivector_reserve(uivector* p, size_t allocsize)\n{\n  if(allocsize > p->allocsize)\n  {\n    size_t newsize = (allocsize > p->allocsize * 2) ? allocsize : (allocsize * 3 / 2);\n    void* data = lodepng_realloc(p->data, newsize);\n    if(data)\n    {\n      p->allocsize = newsize;\n      p->data = (unsigned*)data;\n    }\n    else return 0; /*error: not enough memory*/\n  }\n  return 1;\n}\n\n/*returns 1 if success, 0 if failure ==> nothing done*/\nstatic unsigned uivector_resize(uivector* p, size_t size)\n{\n  if(!uivector_reserve(p, size * sizeof(unsigned))) return 0;\n  p->size = size;\n  return 1; /*success*/\n}\n\n/*resize and give all new elements the value*/\nstatic unsigned uivector_resizev(uivector* p, size_t size, unsigned value)\n{\n  size_t oldsize = p->size, i;\n  if(!uivector_resize(p, size)) return 0;\n  for(i = oldsize; i < size; ++i) p->data[i] = value;\n  return 1;\n}\n\nstatic void uivector_init(uivector* p)\n{\n  p->data = NULL;\n  p->size = p->allocsize = 0;\n}\n\n#ifdef LODEPNG_COMPILE_ENCODER\n/*returns 1 if success, 0 if failure ==> nothing done*/\nstatic unsigned uivector_push_back(uivector* p, unsigned c)\n{\n  if(!uivector_resize(p, p->size + 1)) return 0;\n  p->data[p->size - 1] = c;\n  return 1;\n}\n#endif /*LODEPNG_COMPILE_ENCODER*/\n#endif /*LODEPNG_COMPILE_ZLIB*/\n\n/* /////////////////////////////////////////////////////////////////////////// */\n\n/*dynamic vector of unsigned chars*/\ntypedef struct ucvector\n{\n  unsigned char* data;\n  size_t size; /*used size*/\n  size_t allocsize; /*allocated size*/\n} ucvector;\n\n/*returns 1 if success, 0 if failure ==> nothing done*/\nstatic unsigned ucvector_reserve(ucvector* p, size_t allocsize)\n{\n  if(allocsize > p->allocsize)\n  {\n    size_t newsize = (allocsize > p->allocsize * 2) ? allocsize : (allocsize * 3 / 2);\n    void* data = lodepng_realloc(p->data, newsize);\n    if(data)\n    {\n      p->allocsize = newsize;\n      p->data = (unsigned char*)data;\n    }\n    else return 0; /*error: not enough memory*/\n  }\n  return 1;\n}\n\n/*returns 1 if success, 0 if failure ==> nothing done*/\nstatic unsigned ucvector_resize(ucvector* p, size_t size)\n{\n  if(!ucvector_reserve(p, size * sizeof(unsigned char))) return 0;\n  p->size = size;\n  return 1; /*success*/\n}\n\n#ifdef LODEPNG_COMPILE_PNG\n\nstatic void ucvector_cleanup(void* p)\n{\n  ((ucvector*)p)->size = ((ucvector*)p)->allocsize = 0;\n  lodepng_free(((ucvector*)p)->data);\n  ((ucvector*)p)->data = NULL;\n}\n\nstatic void ucvector_init(ucvector* p)\n{\n  p->data = NULL;\n  p->size = p->allocsize = 0;\n}\n#endif /*LODEPNG_COMPILE_PNG*/\n\n#ifdef LODEPNG_COMPILE_ZLIB\n/*you can both convert from vector to buffer&size and vica versa. If you use\ninit_buffer to take over a buffer and size, it is not needed to use cleanup*/\nstatic void ucvector_init_buffer(ucvector* p, unsigned char* buffer, size_t size)\n{\n  p->data = buffer;\n  p->allocsize = p->size = size;\n}\n#endif /*LODEPNG_COMPILE_ZLIB*/\n\n#if (defined(LODEPNG_COMPILE_PNG) && defined(LODEPNG_COMPILE_ANCILLARY_CHUNKS)) || defined(LODEPNG_COMPILE_ENCODER)\n/*returns 1 if success, 0 if failure ==> nothing done*/\nstatic unsigned ucvector_push_back(ucvector* p, unsigned char c)\n{\n  if(!ucvector_resize(p, p->size + 1)) return 0;\n  p->data[p->size - 1] = c;\n  return 1;\n}\n#endif /*defined(LODEPNG_COMPILE_PNG) || defined(LODEPNG_COMPILE_ENCODER)*/\n\n\n/* ////////////////////////////////////////////////////////////////////////// */\n\n#ifdef LODEPNG_COMPILE_PNG\n#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS\n/*returns 1 if success, 0 if failure ==> nothing done*/\nstatic unsigned string_resize(char** out, size_t size)\n{\n  char* data = (char*)lodepng_realloc(*out, size + 1);\n  if(data)\n  {\n    data[size] = 0; /*null termination char*/\n    *out = data;\n  }\n  return data != 0;\n}\n\n/*init a {char*, size_t} pair for use as string*/\nstatic void string_init(char** out)\n{\n  *out = NULL;\n  string_resize(out, 0);\n}\n\n/*free the above pair again*/\nstatic void string_cleanup(char** out)\n{\n  lodepng_free(*out);\n  *out = NULL;\n}\n\nstatic void string_set(char** out, const char* in)\n{\n  size_t insize = strlen(in), i;\n  if(string_resize(out, insize))\n  {\n    for(i = 0; i != insize; ++i)\n    {\n      (*out)[i] = in[i];\n    }\n  }\n}\n#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/\n#endif /*LODEPNG_COMPILE_PNG*/\n\n/* ////////////////////////////////////////////////////////////////////////// */\n\nunsigned lodepng_read32bitInt(const unsigned char* buffer)\n{\n  return (unsigned)((buffer[0] << 24) | (buffer[1] << 16) | (buffer[2] << 8) | buffer[3]);\n}\n\n#if defined(LODEPNG_COMPILE_PNG) || defined(LODEPNG_COMPILE_ENCODER)\n/*buffer must have at least 4 allocated bytes available*/\nstatic void lodepng_set32bitInt(unsigned char* buffer, unsigned value)\n{\n  buffer[0] = (unsigned char)((value >> 24) & 0xff);\n  buffer[1] = (unsigned char)((value >> 16) & 0xff);\n  buffer[2] = (unsigned char)((value >>  8) & 0xff);\n  buffer[3] = (unsigned char)((value      ) & 0xff);\n}\n#endif /*defined(LODEPNG_COMPILE_PNG) || defined(LODEPNG_COMPILE_ENCODER)*/\n\n#ifdef LODEPNG_COMPILE_ENCODER\nstatic void lodepng_add32bitInt(ucvector* buffer, unsigned value)\n{\n  ucvector_resize(buffer, buffer->size + 4); /*todo: give error if resize failed*/\n  lodepng_set32bitInt(&buffer->data[buffer->size - 4], value);\n}\n#endif /*LODEPNG_COMPILE_ENCODER*/\n\n/* ////////////////////////////////////////////////////////////////////////// */\n/* / File IO                                                                / */\n/* ////////////////////////////////////////////////////////////////////////// */\n\n#ifdef LODEPNG_COMPILE_DISK\n\n/* returns negative value on error. This should be pure C compatible, so no fstat. */\nstatic long lodepng_filesize(const char* filename)\n{\n  FILE* file;\n  long size;\n  file = fopen(filename, \"rb\");\n  if(!file) return -1;\n\n  if(fseek(file, 0, SEEK_END) != 0)\n  {\n    fclose(file);\n    return -1;\n  }\n\n  size = ftell(file);\n  /* It may give LONG_MAX as directory size, this is invalid for us. */\n  if(size == LONG_MAX) size = -1;\n\n  fclose(file);\n  return size;\n}\n\n/* load file into buffer that already has the correct allocated size. Returns error code.*/\nstatic unsigned lodepng_buffer_file(unsigned char* out, size_t size, const char* filename)\n{\n  FILE* file;\n  size_t readsize;\n  file = fopen(filename, \"rb\");\n  if(!file) return 78;\n\n  readsize = fread(out, 1, size, file);\n  fclose(file);\n\n  if (readsize != size) return 78;\n  return 0;\n}\n\nunsigned lodepng_load_file(unsigned char** out, size_t* outsize, const char* filename)\n{\n  long size = lodepng_filesize(filename);\n  if (size < 0) return 78;\n  *outsize = (size_t)size;\n\n  *out = (unsigned char*)lodepng_malloc((size_t)size);\n  if(!(*out) && size > 0) return 83; /*the above malloc failed*/\n\n  return lodepng_buffer_file(*out, (size_t)size, filename);\n}\n\n/*write given buffer to the file, overwriting the file, it doesn't append to it.*/\nunsigned lodepng_save_file(const unsigned char* buffer, size_t buffersize, const char* filename)\n{\n  FILE* file;\n  file = fopen(filename, \"wb\" );\n  if(!file) return 79;\n  fwrite((char*)buffer , 1 , buffersize, file);\n  fclose(file);\n  return 0;\n}\n\n#endif /*LODEPNG_COMPILE_DISK*/\n\n/* ////////////////////////////////////////////////////////////////////////// */\n/* ////////////////////////////////////////////////////////////////////////// */\n/* // End of common code and tools. Begin of Zlib related code.            // */\n/* ////////////////////////////////////////////////////////////////////////// */\n/* ////////////////////////////////////////////////////////////////////////// */\n\n#ifdef LODEPNG_COMPILE_ZLIB\n#ifdef LODEPNG_COMPILE_ENCODER\n/*TODO: this ignores potential out of memory errors*/\n#define addBitToStream(/*size_t**/ bitpointer, /*ucvector**/ bitstream, /*unsigned char*/ bit)\\\n{\\\n  /*add a new byte at the end*/\\\n  if(((*bitpointer) & 7) == 0) ucvector_push_back(bitstream, (unsigned char)0);\\\n  /*earlier bit of huffman code is in a lesser significant bit of an earlier byte*/\\\n  (bitstream->data[bitstream->size - 1]) |= (bit << ((*bitpointer) & 0x7));\\\n  ++(*bitpointer);\\\n}\n\nstatic void addBitsToStream(size_t* bitpointer, ucvector* bitstream, unsigned value, size_t nbits)\n{\n  size_t i;\n  for(i = 0; i != nbits; ++i) addBitToStream(bitpointer, bitstream, (unsigned char)((value >> i) & 1));\n}\n\nstatic void addBitsToStreamReversed(size_t* bitpointer, ucvector* bitstream, unsigned value, size_t nbits)\n{\n  size_t i;\n  for(i = 0; i != nbits; ++i) addBitToStream(bitpointer, bitstream, (unsigned char)((value >> (nbits - 1 - i)) & 1));\n}\n#endif /*LODEPNG_COMPILE_ENCODER*/\n\n#ifdef LODEPNG_COMPILE_DECODER\n\n#define READBIT(bitpointer, bitstream) ((bitstream[bitpointer >> 3] >> (bitpointer & 0x7)) & (unsigned char)1)\n\nstatic unsigned char readBitFromStream(size_t* bitpointer, const unsigned char* bitstream)\n{\n  unsigned char result = (unsigned char)(READBIT(*bitpointer, bitstream));\n  ++(*bitpointer);\n  return result;\n}\n\nstatic unsigned readBitsFromStream(size_t* bitpointer, const unsigned char* bitstream, size_t nbits)\n{\n  unsigned result = 0, i;\n  for(i = 0; i != nbits; ++i)\n  {\n    result += ((unsigned)READBIT(*bitpointer, bitstream)) << i;\n    ++(*bitpointer);\n  }\n  return result;\n}\n#endif /*LODEPNG_COMPILE_DECODER*/\n\n/* ////////////////////////////////////////////////////////////////////////// */\n/* / Deflate - Huffman                                                      / */\n/* ////////////////////////////////////////////////////////////////////////// */\n\n#define FIRST_LENGTH_CODE_INDEX 257\n#define LAST_LENGTH_CODE_INDEX 285\n/*256 literals, the end code, some length codes, and 2 unused codes*/\n#define NUM_DEFLATE_CODE_SYMBOLS 288\n/*the distance codes have their own symbols, 30 used, 2 unused*/\n#define NUM_DISTANCE_SYMBOLS 32\n/*the code length codes. 0-15: code lengths, 16: copy previous 3-6 times, 17: 3-10 zeros, 18: 11-138 zeros*/\n#define NUM_CODE_LENGTH_CODES 19\n\n/*the base lengths represented by codes 257-285*/\nstatic const unsigned LENGTHBASE[29]\n  = {3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, 35, 43, 51, 59,\n     67, 83, 99, 115, 131, 163, 195, 227, 258};\n\n/*the extra bits used by codes 257-285 (added to base length)*/\nstatic const unsigned LENGTHEXTRA[29]\n  = {0, 0, 0, 0, 0, 0, 0,  0,  1,  1,  1,  1,  2,  2,  2,  2,  3,  3,  3,  3,\n      4,  4,  4,   4,   5,   5,   5,   5,   0};\n\n/*the base backwards distances (the bits of distance codes appear after length codes and use their own huffman tree)*/\nstatic const unsigned DISTANCEBASE[30]\n  = {1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, 257, 385, 513,\n     769, 1025, 1537, 2049, 3073, 4097, 6145, 8193, 12289, 16385, 24577};\n\n/*the extra bits of backwards distances (added to base)*/\nstatic const unsigned DISTANCEEXTRA[30]\n  = {0, 0, 0, 0, 1, 1, 2,  2,  3,  3,  4,  4,  5,  5,   6,   6,   7,   7,   8,\n       8,    9,    9,   10,   10,   11,   11,   12,    12,    13,    13};\n\n/*the order in which \"code length alphabet code lengths\" are stored, out of this\nthe huffman tree of the dynamic huffman tree lengths is generated*/\nstatic const unsigned CLCL_ORDER[NUM_CODE_LENGTH_CODES]\n  = {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15};\n\n/* ////////////////////////////////////////////////////////////////////////// */\n\n/*\nHuffman tree struct, containing multiple representations of the tree\n*/\ntypedef struct HuffmanTree\n{\n  unsigned* tree2d;\n  unsigned* tree1d;\n  unsigned* lengths; /*the lengths of the codes of the 1d-tree*/\n  unsigned maxbitlen; /*maximum number of bits a single code can get*/\n  unsigned numcodes; /*number of symbols in the alphabet = number of codes*/\n} HuffmanTree;\n\n/*function used for debug purposes to draw the tree in ascii art with C++*/\n/*\nstatic void HuffmanTree_draw(HuffmanTree* tree)\n{\n  std::cout << \"tree. length: \" << tree->numcodes << \" maxbitlen: \" << tree->maxbitlen << std::endl;\n  for(size_t i = 0; i != tree->tree1d.size; ++i)\n  {\n    if(tree->lengths.data[i])\n      std::cout << i << \" \" << tree->tree1d.data[i] << \" \" << tree->lengths.data[i] << std::endl;\n  }\n  std::cout << std::endl;\n}*/\n\nstatic void HuffmanTree_init(HuffmanTree* tree)\n{\n  tree->tree2d = 0;\n  tree->tree1d = 0;\n  tree->lengths = 0;\n}\n\nstatic void HuffmanTree_cleanup(HuffmanTree* tree)\n{\n  lodepng_free(tree->tree2d);\n  lodepng_free(tree->tree1d);\n  lodepng_free(tree->lengths);\n}\n\n/*the tree representation used by the decoder. return value is error*/\nstatic unsigned HuffmanTree_make2DTree(HuffmanTree* tree)\n{\n  unsigned nodefilled = 0; /*up to which node it is filled*/\n  unsigned treepos = 0; /*position in the tree (1 of the numcodes columns)*/\n  unsigned n, i;\n\n  tree->tree2d = (unsigned*)lodepng_malloc(tree->numcodes * 2 * sizeof(unsigned));\n  if(!tree->tree2d) return 83; /*alloc fail*/\n\n  /*\n  convert tree1d[] to tree2d[][]. In the 2D array, a value of 32767 means\n  uninited, a value >= numcodes is an address to another bit, a value < numcodes\n  is a code. The 2 rows are the 2 possible bit values (0 or 1), there are as\n  many columns as codes - 1.\n  A good huffman tree has N * 2 - 1 nodes, of which N - 1 are internal nodes.\n  Here, the internal nodes are stored (what their 0 and 1 option point to).\n  There is only memory for such good tree currently, if there are more nodes\n  (due to too long length codes), error 55 will happen\n  */\n  for(n = 0; n < tree->numcodes * 2; ++n)\n  {\n    tree->tree2d[n] = 32767; /*32767 here means the tree2d isn't filled there yet*/\n  }\n\n  for(n = 0; n < tree->numcodes; ++n) /*the codes*/\n  {\n    for(i = 0; i != tree->lengths[n]; ++i) /*the bits for this code*/\n    {\n      unsigned char bit = (unsigned char)((tree->tree1d[n] >> (tree->lengths[n] - i - 1)) & 1);\n      /*oversubscribed, see comment in lodepng_error_text*/\n      if(treepos > 2147483647 || treepos + 2 > tree->numcodes) return 55;\n      if(tree->tree2d[2 * treepos + bit] == 32767) /*not yet filled in*/\n      {\n        if(i + 1 == tree->lengths[n]) /*last bit*/\n        {\n          tree->tree2d[2 * treepos + bit] = n; /*put the current code in it*/\n          treepos = 0;\n        }\n        else\n        {\n          /*put address of the next step in here, first that address has to be found of course\n          (it's just nodefilled + 1)...*/\n          ++nodefilled;\n          /*addresses encoded with numcodes added to it*/\n          tree->tree2d[2 * treepos + bit] = nodefilled + tree->numcodes;\n          treepos = nodefilled;\n        }\n      }\n      else treepos = tree->tree2d[2 * treepos + bit] - tree->numcodes;\n    }\n  }\n\n  for(n = 0; n < tree->numcodes * 2; ++n)\n  {\n    if(tree->tree2d[n] == 32767) tree->tree2d[n] = 0; /*remove possible remaining 32767's*/\n  }\n\n  return 0;\n}\n\n/*\nSecond step for the ...makeFromLengths and ...makeFromFrequencies functions.\nnumcodes, lengths and maxbitlen must already be filled in correctly. return\nvalue is error.\n*/\nstatic unsigned HuffmanTree_makeFromLengths2(HuffmanTree* tree)\n{\n  uivector blcount;\n  uivector nextcode;\n  unsigned error = 0;\n  unsigned bits, n;\n\n  uivector_init(&blcount);\n  uivector_init(&nextcode);\n\n  tree->tree1d = (unsigned*)lodepng_malloc(tree->numcodes * sizeof(unsigned));\n  if(!tree->tree1d) error = 83; /*alloc fail*/\n\n  if(!uivector_resizev(&blcount, tree->maxbitlen + 1, 0)\n  || !uivector_resizev(&nextcode, tree->maxbitlen + 1, 0))\n    error = 83; /*alloc fail*/\n\n  if(!error)\n  {\n    /*step 1: count number of instances of each code length*/\n    for(bits = 0; bits != tree->numcodes; ++bits) ++blcount.data[tree->lengths[bits]];\n    /*step 2: generate the nextcode values*/\n    for(bits = 1; bits <= tree->maxbitlen; ++bits)\n    {\n      nextcode.data[bits] = (nextcode.data[bits - 1] + blcount.data[bits - 1]) << 1;\n    }\n    /*step 3: generate all the codes*/\n    for(n = 0; n != tree->numcodes; ++n)\n    {\n      if(tree->lengths[n] != 0) tree->tree1d[n] = nextcode.data[tree->lengths[n]]++;\n    }\n  }\n\n  uivector_cleanup(&blcount);\n  uivector_cleanup(&nextcode);\n\n  if(!error) return HuffmanTree_make2DTree(tree);\n  else return error;\n}\n\n/*\ngiven the code lengths (as stored in the PNG file), generate the tree as defined\nby Deflate. maxbitlen is the maximum bits that a code in the tree can have.\nreturn value is error.\n*/\nstatic unsigned HuffmanTree_makeFromLengths(HuffmanTree* tree, const unsigned* bitlen,\n                                            size_t numcodes, unsigned maxbitlen)\n{\n  unsigned i;\n  tree->lengths = (unsigned*)lodepng_malloc(numcodes * sizeof(unsigned));\n  if(!tree->lengths) return 83; /*alloc fail*/\n  for(i = 0; i != numcodes; ++i) tree->lengths[i] = bitlen[i];\n  tree->numcodes = (unsigned)numcodes; /*number of symbols*/\n  tree->maxbitlen = maxbitlen;\n  return HuffmanTree_makeFromLengths2(tree);\n}\n\n#ifdef LODEPNG_COMPILE_ENCODER\n\n/*BPM: Boundary Package Merge, see \"A Fast and Space-Economical Algorithm for Length-Limited Coding\",\nJyrki Katajainen, Alistair Moffat, Andrew Turpin, 1995.*/\n\n/*chain node for boundary package merge*/\ntypedef struct BPMNode\n{\n  int weight; /*the sum of all weights in this chain*/\n  unsigned index; /*index of this leaf node (called \"count\" in the paper)*/\n  struct BPMNode* tail; /*the next nodes in this chain (null if last)*/\n  int in_use;\n} BPMNode;\n\n/*lists of chains*/\ntypedef struct BPMLists\n{\n  /*memory pool*/\n  unsigned memsize;\n  BPMNode* memory;\n  unsigned numfree;\n  unsigned nextfree;\n  BPMNode** freelist;\n  /*two heads of lookahead chains per list*/\n  unsigned listsize;\n  BPMNode** chains0;\n  BPMNode** chains1;\n} BPMLists;\n\n/*creates a new chain node with the given parameters, from the memory in the lists */\nstatic BPMNode* bpmnode_create(BPMLists* lists, int weight, unsigned index, BPMNode* tail)\n{\n  unsigned i;\n  BPMNode* result;\n\n  /*memory full, so garbage collect*/\n  if(lists->nextfree >= lists->numfree)\n  {\n    /*mark only those that are in use*/\n    for(i = 0; i != lists->memsize; ++i) lists->memory[i].in_use = 0;\n    for(i = 0; i != lists->listsize; ++i)\n    {\n      BPMNode* node;\n      for(node = lists->chains0[i]; node != 0; node = node->tail) node->in_use = 1;\n      for(node = lists->chains1[i]; node != 0; node = node->tail) node->in_use = 1;\n    }\n    /*collect those that are free*/\n    lists->numfree = 0;\n    for(i = 0; i != lists->memsize; ++i)\n    {\n      if(!lists->memory[i].in_use) lists->freelist[lists->numfree++] = &lists->memory[i];\n    }\n    lists->nextfree = 0;\n  }\n\n  result = lists->freelist[lists->nextfree++];\n  result->weight = weight;\n  result->index = index;\n  result->tail = tail;\n  return result;\n}\n\n/*sort the leaves with stable mergesort*/\nstatic void bpmnode_sort(BPMNode* leaves, size_t num)\n{\n  BPMNode* mem = (BPMNode*)lodepng_malloc(sizeof(*leaves) * num);\n  size_t width, counter = 0;\n  for(width = 1; width < num; width *= 2)\n  {\n    BPMNode* a = (counter & 1) ? mem : leaves;\n    BPMNode* b = (counter & 1) ? leaves : mem;\n    size_t p;\n    for(p = 0; p < num; p += 2 * width)\n    {\n      size_t q = (p + width > num) ? num : (p + width);\n      size_t r = (p + 2 * width > num) ? num : (p + 2 * width);\n      size_t i = p, j = q, k;\n      for(k = p; k < r; k++)\n      {\n        if(i < q && (j >= r || a[i].weight <= a[j].weight)) b[k] = a[i++];\n        else b[k] = a[j++];\n      }\n    }\n    counter++;\n  }\n  if(counter & 1) memcpy(leaves, mem, sizeof(*leaves) * num);\n  lodepng_free(mem);\n}\n\n/*Boundary Package Merge step, numpresent is the amount of leaves, and c is the current chain.*/\nstatic void boundaryPM(BPMLists* lists, BPMNode* leaves, size_t numpresent, int c, int num)\n{\n  unsigned lastindex = lists->chains1[c]->index;\n\n  if(c == 0)\n  {\n    if(lastindex >= numpresent) return;\n    lists->chains0[c] = lists->chains1[c];\n    lists->chains1[c] = bpmnode_create(lists, leaves[lastindex].weight, lastindex + 1, 0);\n  }\n  else\n  {\n    /*sum of the weights of the head nodes of the previous lookahead chains.*/\n    int sum = lists->chains0[c - 1]->weight + lists->chains1[c - 1]->weight;\n    lists->chains0[c] = lists->chains1[c];\n    if(lastindex < numpresent && sum > leaves[lastindex].weight)\n    {\n      lists->chains1[c] = bpmnode_create(lists, leaves[lastindex].weight, lastindex + 1, lists->chains1[c]->tail);\n      return;\n    }\n    lists->chains1[c] = bpmnode_create(lists, sum, lastindex, lists->chains1[c - 1]);\n    /*in the end we are only interested in the chain of the last list, so no\n    need to recurse if we're at the last one (this gives measurable speedup)*/\n    if(num + 1 < (int)(2 * numpresent - 2))\n    {\n      boundaryPM(lists, leaves, numpresent, c - 1, num);\n      boundaryPM(lists, leaves, numpresent, c - 1, num);\n    }\n  }\n}\n\nunsigned lodepng_huffman_code_lengths(unsigned* lengths, const unsigned* frequencies,\n                                      size_t numcodes, unsigned maxbitlen)\n{\n  unsigned error = 0;\n  unsigned i;\n  size_t numpresent = 0; /*number of symbols with non-zero frequency*/\n  BPMNode* leaves; /*the symbols, only those with > 0 frequency*/\n\n  if(numcodes == 0) return 80; /*error: a tree of 0 symbols is not supposed to be made*/\n  if((1u << maxbitlen) < numcodes) return 80; /*error: represent all symbols*/\n\n  leaves = (BPMNode*)lodepng_malloc(numcodes * sizeof(*leaves));\n  if(!leaves) return 83; /*alloc fail*/\n\n  for(i = 0; i != numcodes; ++i)\n  {\n    if(frequencies[i] > 0)\n    {\n      leaves[numpresent].weight = (int)frequencies[i];\n      leaves[numpresent].index = i;\n      ++numpresent;\n    }\n  }\n\n  for(i = 0; i != numcodes; ++i) lengths[i] = 0;\n\n  /*ensure at least two present symbols. There should be at least one symbol\n  according to RFC 1951 section 3.2.7. Some decoders incorrectly require two. To\n  make these work as well ensure there are at least two symbols. The\n  Package-Merge code below also doesn't work correctly if there's only one\n  symbol, it'd give it the theoritical 0 bits but in practice zlib wants 1 bit*/\n  if(numpresent == 0)\n  {\n    lengths[0] = lengths[1] = 1; /*note that for RFC 1951 section 3.2.7, only lengths[0] = 1 is needed*/\n  }\n  else if(numpresent == 1)\n  {\n    lengths[leaves[0].index] = 1;\n    lengths[leaves[0].index == 0 ? 1 : 0] = 1;\n  }\n  else\n  {\n    BPMLists lists;\n    BPMNode* node;\n\n    bpmnode_sort(leaves, numpresent);\n\n    lists.listsize = maxbitlen;\n    lists.memsize = 2 * maxbitlen * (maxbitlen + 1);\n    lists.nextfree = 0;\n    lists.numfree = lists.memsize;\n    lists.memory = (BPMNode*)lodepng_malloc(lists.memsize * sizeof(*lists.memory));\n    lists.freelist = (BPMNode**)lodepng_malloc(lists.memsize * sizeof(BPMNode*));\n    lists.chains0 = (BPMNode**)lodepng_malloc(lists.listsize * sizeof(BPMNode*));\n    lists.chains1 = (BPMNode**)lodepng_malloc(lists.listsize * sizeof(BPMNode*));\n    if(!lists.memory || !lists.freelist || !lists.chains0 || !lists.chains1) error = 83; /*alloc fail*/\n\n    if(!error)\n    {\n      for(i = 0; i != lists.memsize; ++i) lists.freelist[i] = &lists.memory[i];\n\n      bpmnode_create(&lists, leaves[0].weight, 1, 0);\n      bpmnode_create(&lists, leaves[1].weight, 2, 0);\n\n      for(i = 0; i != lists.listsize; ++i)\n      {\n        lists.chains0[i] = &lists.memory[0];\n        lists.chains1[i] = &lists.memory[1];\n      }\n\n      /*each boundaryPM call adds one chain to the last list, and we need 2 * numpresent - 2 chains.*/\n      for(i = 2; i != 2 * numpresent - 2; ++i) boundaryPM(&lists, leaves, numpresent, (int)maxbitlen - 1, (int)i);\n\n      for(node = lists.chains1[maxbitlen - 1]; node; node = node->tail)\n      {\n        for(i = 0; i != node->index; ++i) ++lengths[leaves[i].index];\n      }\n    }\n\n    lodepng_free(lists.memory);\n    lodepng_free(lists.freelist);\n    lodepng_free(lists.chains0);\n    lodepng_free(lists.chains1);\n  }\n\n  lodepng_free(leaves);\n  return error;\n}\n\n/*Create the Huffman tree given the symbol frequencies*/\nstatic unsigned HuffmanTree_makeFromFrequencies(HuffmanTree* tree, const unsigned* frequencies,\n                                                size_t mincodes, size_t numcodes, unsigned maxbitlen)\n{\n  unsigned error = 0;\n  while(!frequencies[numcodes - 1] && numcodes > mincodes) --numcodes; /*trim zeroes*/\n  tree->maxbitlen = maxbitlen;\n  tree->numcodes = (unsigned)numcodes; /*number of symbols*/\n  tree->lengths = (unsigned*)lodepng_realloc(tree->lengths, numcodes * sizeof(unsigned));\n  if(!tree->lengths) return 83; /*alloc fail*/\n  /*initialize all lengths to 0*/\n  memset(tree->lengths, 0, numcodes * sizeof(unsigned));\n\n  error = lodepng_huffman_code_lengths(tree->lengths, frequencies, numcodes, maxbitlen);\n  if(!error) error = HuffmanTree_makeFromLengths2(tree);\n  return error;\n}\n\nstatic unsigned HuffmanTree_getCode(const HuffmanTree* tree, unsigned index)\n{\n  return tree->tree1d[index];\n}\n\nstatic unsigned HuffmanTree_getLength(const HuffmanTree* tree, unsigned index)\n{\n  return tree->lengths[index];\n}\n#endif /*LODEPNG_COMPILE_ENCODER*/\n\n/*get the literal and length code tree of a deflated block with fixed tree, as per the deflate specification*/\nstatic unsigned generateFixedLitLenTree(HuffmanTree* tree)\n{\n  unsigned i, error = 0;\n  unsigned* bitlen = (unsigned*)lodepng_malloc(NUM_DEFLATE_CODE_SYMBOLS * sizeof(unsigned));\n  if(!bitlen) return 83; /*alloc fail*/\n\n  /*288 possible codes: 0-255=literals, 256=endcode, 257-285=lengthcodes, 286-287=unused*/\n  for(i =   0; i <= 143; ++i) bitlen[i] = 8;\n  for(i = 144; i <= 255; ++i) bitlen[i] = 9;\n  for(i = 256; i <= 279; ++i) bitlen[i] = 7;\n  for(i = 280; i <= 287; ++i) bitlen[i] = 8;\n\n  error = HuffmanTree_makeFromLengths(tree, bitlen, NUM_DEFLATE_CODE_SYMBOLS, 15);\n\n  lodepng_free(bitlen);\n  return error;\n}\n\n/*get the distance code tree of a deflated block with fixed tree, as specified in the deflate specification*/\nstatic unsigned generateFixedDistanceTree(HuffmanTree* tree)\n{\n  unsigned i, error = 0;\n  unsigned* bitlen = (unsigned*)lodepng_malloc(NUM_DISTANCE_SYMBOLS * sizeof(unsigned));\n  if(!bitlen) return 83; /*alloc fail*/\n\n  /*there are 32 distance codes, but 30-31 are unused*/\n  for(i = 0; i != NUM_DISTANCE_SYMBOLS; ++i) bitlen[i] = 5;\n  error = HuffmanTree_makeFromLengths(tree, bitlen, NUM_DISTANCE_SYMBOLS, 15);\n\n  lodepng_free(bitlen);\n  return error;\n}\n\n#ifdef LODEPNG_COMPILE_DECODER\n\n/*\nreturns the code, or (unsigned)(-1) if error happened\ninbitlength is the length of the complete buffer, in bits (so its byte length times 8)\n*/\nstatic unsigned huffmanDecodeSymbol(const unsigned char* in, size_t* bp,\n                                    const HuffmanTree* codetree, size_t inbitlength)\n{\n  unsigned treepos = 0, ct;\n  for(;;)\n  {\n    if(*bp >= inbitlength) return (unsigned)(-1); /*error: end of input memory reached without endcode*/\n    /*\n    decode the symbol from the tree. The \"readBitFromStream\" code is inlined in\n    the expression below because this is the biggest bottleneck while decoding\n    */\n    ct = codetree->tree2d[(treepos << 1) + READBIT(*bp, in)];\n    ++(*bp);\n    if(ct < codetree->numcodes) return ct; /*the symbol is decoded, return it*/\n    else treepos = ct - codetree->numcodes; /*symbol not yet decoded, instead move tree position*/\n\n    if(treepos >= codetree->numcodes) return (unsigned)(-1); /*error: it appeared outside the codetree*/\n  }\n}\n#endif /*LODEPNG_COMPILE_DECODER*/\n\n#ifdef LODEPNG_COMPILE_DECODER\n\n/* ////////////////////////////////////////////////////////////////////////// */\n/* / Inflator (Decompressor)                                                / */\n/* ////////////////////////////////////////////////////////////////////////// */\n\n/*get the tree of a deflated block with fixed tree, as specified in the deflate specification*/\nstatic void getTreeInflateFixed(HuffmanTree* tree_ll, HuffmanTree* tree_d)\n{\n  /*TODO: check for out of memory errors*/\n  generateFixedLitLenTree(tree_ll);\n  generateFixedDistanceTree(tree_d);\n}\n\n/*get the tree of a deflated block with dynamic tree, the tree itself is also Huffman compressed with a known tree*/\nstatic unsigned getTreeInflateDynamic(HuffmanTree* tree_ll, HuffmanTree* tree_d,\n                                      const unsigned char* in, size_t* bp, size_t inlength)\n{\n  /*make sure that length values that aren't filled in will be 0, or a wrong tree will be generated*/\n  unsigned error = 0;\n  unsigned n, HLIT, HDIST, HCLEN, i;\n  size_t inbitlength = inlength * 8;\n\n  /*see comments in deflateDynamic for explanation of the context and these variables, it is analogous*/\n  unsigned* bitlen_ll = 0; /*lit,len code lengths*/\n  unsigned* bitlen_d = 0; /*dist code lengths*/\n  /*code length code lengths (\"clcl\"), the bit lengths of the huffman tree used to compress bitlen_ll and bitlen_d*/\n  unsigned* bitlen_cl = 0;\n  HuffmanTree tree_cl; /*the code tree for code length codes (the huffman tree for compressed huffman trees)*/\n\n  if((*bp) + 14 > (inlength << 3)) return 49; /*error: the bit pointer is or will go past the memory*/\n\n  /*number of literal/length codes + 257. Unlike the spec, the value 257 is added to it here already*/\n  HLIT =  readBitsFromStream(bp, in, 5) + 257;\n  /*number of distance codes. Unlike the spec, the value 1 is added to it here already*/\n  HDIST = readBitsFromStream(bp, in, 5) + 1;\n  /*number of code length codes. Unlike the spec, the value 4 is added to it here already*/\n  HCLEN = readBitsFromStream(bp, in, 4) + 4;\n\n  if((*bp) + HCLEN * 3 > (inlength << 3)) return 50; /*error: the bit pointer is or will go past the memory*/\n\n  HuffmanTree_init(&tree_cl);\n\n  while(!error)\n  {\n    /*read the code length codes out of 3 * (amount of code length codes) bits*/\n\n    bitlen_cl = (unsigned*)lodepng_malloc(NUM_CODE_LENGTH_CODES * sizeof(unsigned));\n    if(!bitlen_cl) ERROR_BREAK(83 /*alloc fail*/);\n\n    for(i = 0; i != NUM_CODE_LENGTH_CODES; ++i)\n    {\n      if(i < HCLEN) bitlen_cl[CLCL_ORDER[i]] = readBitsFromStream(bp, in, 3);\n      else bitlen_cl[CLCL_ORDER[i]] = 0; /*if not, it must stay 0*/\n    }\n\n    error = HuffmanTree_makeFromLengths(&tree_cl, bitlen_cl, NUM_CODE_LENGTH_CODES, 7);\n    if(error) break;\n\n    /*now we can use this tree to read the lengths for the tree that this function will return*/\n    bitlen_ll = (unsigned*)lodepng_malloc(NUM_DEFLATE_CODE_SYMBOLS * sizeof(unsigned));\n    bitlen_d = (unsigned*)lodepng_malloc(NUM_DISTANCE_SYMBOLS * sizeof(unsigned));\n    if(!bitlen_ll || !bitlen_d) ERROR_BREAK(83 /*alloc fail*/);\n    for(i = 0; i != NUM_DEFLATE_CODE_SYMBOLS; ++i) bitlen_ll[i] = 0;\n    for(i = 0; i != NUM_DISTANCE_SYMBOLS; ++i) bitlen_d[i] = 0;\n\n    /*i is the current symbol we're reading in the part that contains the code lengths of lit/len and dist codes*/\n    i = 0;\n    while(i < HLIT + HDIST)\n    {\n      unsigned code = huffmanDecodeSymbol(in, bp, &tree_cl, inbitlength);\n      if(code <= 15) /*a length code*/\n      {\n        if(i < HLIT) bitlen_ll[i] = code;\n        else bitlen_d[i - HLIT] = code;\n        ++i;\n      }\n      else if(code == 16) /*repeat previous*/\n      {\n        unsigned replength = 3; /*read in the 2 bits that indicate repeat length (3-6)*/\n        unsigned value; /*set value to the previous code*/\n\n        if(i == 0) ERROR_BREAK(54); /*can't repeat previous if i is 0*/\n\n        if((*bp + 2) > inbitlength) ERROR_BREAK(50); /*error, bit pointer jumps past memory*/\n        replength += readBitsFromStream(bp, in, 2);\n\n        if(i < HLIT + 1) value = bitlen_ll[i - 1];\n        else value = bitlen_d[i - HLIT - 1];\n        /*repeat this value in the next lengths*/\n        for(n = 0; n < replength; ++n)\n        {\n          if(i >= HLIT + HDIST) ERROR_BREAK(13); /*error: i is larger than the amount of codes*/\n          if(i < HLIT) bitlen_ll[i] = value;\n          else bitlen_d[i - HLIT] = value;\n          ++i;\n        }\n      }\n      else if(code == 17) /*repeat \"0\" 3-10 times*/\n      {\n        unsigned replength = 3; /*read in the bits that indicate repeat length*/\n        if((*bp + 3) > inbitlength) ERROR_BREAK(50); /*error, bit pointer jumps past memory*/\n        replength += readBitsFromStream(bp, in, 3);\n\n        /*repeat this value in the next lengths*/\n        for(n = 0; n < replength; ++n)\n        {\n          if(i >= HLIT + HDIST) ERROR_BREAK(14); /*error: i is larger than the amount of codes*/\n\n          if(i < HLIT) bitlen_ll[i] = 0;\n          else bitlen_d[i - HLIT] = 0;\n          ++i;\n        }\n      }\n      else if(code == 18) /*repeat \"0\" 11-138 times*/\n      {\n        unsigned replength = 11; /*read in the bits that indicate repeat length*/\n        if((*bp + 7) > inbitlength) ERROR_BREAK(50); /*error, bit pointer jumps past memory*/\n        replength += readBitsFromStream(bp, in, 7);\n\n        /*repeat this value in the next lengths*/\n        for(n = 0; n < replength; ++n)\n        {\n          if(i >= HLIT + HDIST) ERROR_BREAK(15); /*error: i is larger than the amount of codes*/\n\n          if(i < HLIT) bitlen_ll[i] = 0;\n          else bitlen_d[i - HLIT] = 0;\n          ++i;\n        }\n      }\n      else /*if(code == (unsigned)(-1))*/ /*huffmanDecodeSymbol returns (unsigned)(-1) in case of error*/\n      {\n        if(code == (unsigned)(-1))\n        {\n          /*return error code 10 or 11 depending on the situation that happened in huffmanDecodeSymbol\n          (10=no endcode, 11=wrong jump outside of tree)*/\n          error = (*bp) > inbitlength ? 10 : 11;\n        }\n        else error = 16; /*unexisting code, this can never happen*/\n        break;\n      }\n    }\n    if(error) break;\n\n    if(bitlen_ll[256] == 0) ERROR_BREAK(64); /*the length of the end code 256 must be larger than 0*/\n\n    /*now we've finally got HLIT and HDIST, so generate the code trees, and the function is done*/\n    error = HuffmanTree_makeFromLengths(tree_ll, bitlen_ll, NUM_DEFLATE_CODE_SYMBOLS, 15);\n    if(error) break;\n    error = HuffmanTree_makeFromLengths(tree_d, bitlen_d, NUM_DISTANCE_SYMBOLS, 15);\n\n    break; /*end of error-while*/\n  }\n\n  lodepng_free(bitlen_cl);\n  lodepng_free(bitlen_ll);\n  lodepng_free(bitlen_d);\n  HuffmanTree_cleanup(&tree_cl);\n\n  return error;\n}\n\n/*inflate a block with dynamic of fixed Huffman tree*/\nstatic unsigned inflateHuffmanBlock(ucvector* out, const unsigned char* in, size_t* bp,\n                                    size_t* pos, size_t inlength, unsigned btype)\n{\n  unsigned error = 0;\n  HuffmanTree tree_ll; /*the huffman tree for literal and length codes*/\n  HuffmanTree tree_d; /*the huffman tree for distance codes*/\n  size_t inbitlength = inlength * 8;\n\n  HuffmanTree_init(&tree_ll);\n  HuffmanTree_init(&tree_d);\n\n  if(btype == 1) getTreeInflateFixed(&tree_ll, &tree_d);\n  else if(btype == 2) error = getTreeInflateDynamic(&tree_ll, &tree_d, in, bp, inlength);\n\n  while(!error) /*decode all symbols until end reached, breaks at end code*/\n  {\n    /*code_ll is literal, length or end code*/\n    unsigned code_ll = huffmanDecodeSymbol(in, bp, &tree_ll, inbitlength);\n    if(code_ll <= 255) /*literal symbol*/\n    {\n      /*ucvector_push_back would do the same, but for some reason the two lines below run 10% faster*/\n      if(!ucvector_resize(out, (*pos) + 1)) ERROR_BREAK(83 /*alloc fail*/);\n      out->data[*pos] = (unsigned char)code_ll;\n      ++(*pos);\n    }\n    else if(code_ll >= FIRST_LENGTH_CODE_INDEX && code_ll <= LAST_LENGTH_CODE_INDEX) /*length code*/\n    {\n      unsigned code_d, distance;\n      unsigned numextrabits_l, numextrabits_d; /*extra bits for length and distance*/\n      size_t start, forward, backward, length;\n\n      /*part 1: get length base*/\n      length = LENGTHBASE[code_ll - FIRST_LENGTH_CODE_INDEX];\n\n      /*part 2: get extra bits and add the value of that to length*/\n      numextrabits_l = LENGTHEXTRA[code_ll - FIRST_LENGTH_CODE_INDEX];\n      if((*bp + numextrabits_l) > inbitlength) ERROR_BREAK(51); /*error, bit pointer will jump past memory*/\n      length += readBitsFromStream(bp, in, numextrabits_l);\n\n      /*part 3: get distance code*/\n      code_d = huffmanDecodeSymbol(in, bp, &tree_d, inbitlength);\n      if(code_d > 29)\n      {\n        if(code_ll == (unsigned)(-1)) /*huffmanDecodeSymbol returns (unsigned)(-1) in case of error*/\n        {\n          /*return error code 10 or 11 depending on the situation that happened in huffmanDecodeSymbol\n          (10=no endcode, 11=wrong jump outside of tree)*/\n          error = (*bp) > inlength * 8 ? 10 : 11;\n        }\n        else error = 18; /*error: invalid distance code (30-31 are never used)*/\n        break;\n      }\n      distance = DISTANCEBASE[code_d];\n\n      /*part 4: get extra bits from distance*/\n      numextrabits_d = DISTANCEEXTRA[code_d];\n      if((*bp + numextrabits_d) > inbitlength) ERROR_BREAK(51); /*error, bit pointer will jump past memory*/\n      distance += readBitsFromStream(bp, in, numextrabits_d);\n\n      /*part 5: fill in all the out[n] values based on the length and dist*/\n      start = (*pos);\n      if(distance > start) ERROR_BREAK(52); /*too long backward distance*/\n      backward = start - distance;\n\n      if(!ucvector_resize(out, (*pos) + length)) ERROR_BREAK(83 /*alloc fail*/);\n      if (distance < length) {\n        for(forward = 0; forward < length; ++forward)\n        {\n          out->data[(*pos)++] = out->data[backward++];\n        }\n      } else {\n        memcpy(out->data + *pos, out->data + backward, length);\n        *pos += length;\n      }\n    }\n    else if(code_ll == 256)\n    {\n      break; /*end code, break the loop*/\n    }\n    else /*if(code == (unsigned)(-1))*/ /*huffmanDecodeSymbol returns (unsigned)(-1) in case of error*/\n    {\n      /*return error code 10 or 11 depending on the situation that happened in huffmanDecodeSymbol\n      (10=no endcode, 11=wrong jump outside of tree)*/\n      error = ((*bp) > inlength * 8) ? 10 : 11;\n      break;\n    }\n  }\n\n  HuffmanTree_cleanup(&tree_ll);\n  HuffmanTree_cleanup(&tree_d);\n\n  return error;\n}\n\nstatic unsigned inflateNoCompression(ucvector* out, const unsigned char* in, size_t* bp, size_t* pos, size_t inlength)\n{\n  size_t p;\n  unsigned LEN, NLEN, n, error = 0;\n\n  /*go to first boundary of byte*/\n  while(((*bp) & 0x7) != 0) ++(*bp);\n  p = (*bp) / 8; /*byte position*/\n\n  /*read LEN (2 bytes) and NLEN (2 bytes)*/\n  if(p + 4 >= inlength) return 52; /*error, bit pointer will jump past memory*/\n  LEN = in[p] + 256u * in[p + 1]; p += 2;\n  NLEN = in[p] + 256u * in[p + 1]; p += 2;\n\n  /*check if 16-bit NLEN is really the one's complement of LEN*/\n  if(LEN + NLEN != 65535) return 21; /*error: NLEN is not one's complement of LEN*/\n\n  if(!ucvector_resize(out, (*pos) + LEN)) return 83; /*alloc fail*/\n\n  /*read the literal data: LEN bytes are now stored in the out buffer*/\n  if(p + LEN > inlength) return 23; /*error: reading outside of in buffer*/\n  for(n = 0; n < LEN; ++n) out->data[(*pos)++] = in[p++];\n\n  (*bp) = p * 8;\n\n  return error;\n}\n\nstatic unsigned lodepng_inflatev(ucvector* out,\n                                 const unsigned char* in, size_t insize,\n                                 const LodePNGDecompressSettings* settings)\n{\n  /*bit pointer in the \"in\" data, current byte is bp >> 3, current bit is bp & 0x7 (from lsb to msb of the byte)*/\n  size_t bp = 0;\n  unsigned BFINAL = 0;\n  size_t pos = 0; /*byte position in the out buffer*/\n  unsigned error = 0;\n\n  (void)settings;\n\n  while(!BFINAL)\n  {\n    unsigned BTYPE;\n    if(bp + 2 >= insize * 8) return 52; /*error, bit pointer will jump past memory*/\n    BFINAL = readBitFromStream(&bp, in);\n    BTYPE = 1u * readBitFromStream(&bp, in);\n    BTYPE += 2u * readBitFromStream(&bp, in);\n\n    if(BTYPE == 3) return 20; /*error: invalid BTYPE*/\n    else if(BTYPE == 0) error = inflateNoCompression(out, in, &bp, &pos, insize); /*no compression*/\n    else error = inflateHuffmanBlock(out, in, &bp, &pos, insize, BTYPE); /*compression, BTYPE 01 or 10*/\n\n    if(error) return error;\n  }\n\n  return error;\n}\n\nunsigned lodepng_inflate(unsigned char** out, size_t* outsize,\n                         const unsigned char* in, size_t insize,\n                         const LodePNGDecompressSettings* settings)\n{\n  unsigned error;\n  ucvector v;\n  ucvector_init_buffer(&v, *out, *outsize);\n  error = lodepng_inflatev(&v, in, insize, settings);\n  *out = v.data;\n  *outsize = v.size;\n  return error;\n}\n\nstatic unsigned inflate(unsigned char** out, size_t* outsize,\n                        const unsigned char* in, size_t insize,\n                        const LodePNGDecompressSettings* settings)\n{\n  if(settings->custom_inflate)\n  {\n    return settings->custom_inflate(out, outsize, in, insize, settings);\n  }\n  else\n  {\n    return lodepng_inflate(out, outsize, in, insize, settings);\n  }\n}\n\n#endif /*LODEPNG_COMPILE_DECODER*/\n\n#ifdef LODEPNG_COMPILE_ENCODER\n\n/* ////////////////////////////////////////////////////////////////////////// */\n/* / Deflator (Compressor)                                                  / */\n/* ////////////////////////////////////////////////////////////////////////// */\n\nstatic const size_t MAX_SUPPORTED_DEFLATE_LENGTH = 258;\n\n/*bitlen is the size in bits of the code*/\nstatic void addHuffmanSymbol(size_t* bp, ucvector* compressed, unsigned code, unsigned bitlen)\n{\n  addBitsToStreamReversed(bp, compressed, code, bitlen);\n}\n\n/*search the index in the array, that has the largest value smaller than or equal to the given value,\ngiven array must be sorted (if no value is smaller, it returns the size of the given array)*/\nstatic size_t searchCodeIndex(const unsigned* array, size_t array_size, size_t value)\n{\n  /*binary search (only small gain over linear). TODO: use CPU log2 instruction for getting symbols instead*/\n  size_t left = 1;\n  size_t right = array_size - 1;\n\n  while(left <= right) {\n    size_t mid = (left + right) >> 1;\n    if (array[mid] >= value) right = mid - 1;\n    else left = mid + 1;\n  }\n  if(left >= array_size || array[left] > value) left--;\n  return left;\n}\n\nstatic void addLengthDistance(uivector* values, size_t length, size_t distance)\n{\n  /*values in encoded vector are those used by deflate:\n  0-255: literal bytes\n  256: end\n  257-285: length/distance pair (length code, followed by extra length bits, distance code, extra distance bits)\n  286-287: invalid*/\n\n  unsigned length_code = (unsigned)searchCodeIndex(LENGTHBASE, 29, length);\n  unsigned extra_length = (unsigned)(length - LENGTHBASE[length_code]);\n  unsigned dist_code = (unsigned)searchCodeIndex(DISTANCEBASE, 30, distance);\n  unsigned extra_distance = (unsigned)(distance - DISTANCEBASE[dist_code]);\n\n  uivector_push_back(values, length_code + FIRST_LENGTH_CODE_INDEX);\n  uivector_push_back(values, extra_length);\n  uivector_push_back(values, dist_code);\n  uivector_push_back(values, extra_distance);\n}\n\n/*3 bytes of data get encoded into two bytes. The hash cannot use more than 3\nbytes as input because 3 is the minimum match length for deflate*/\nstatic const unsigned HASH_NUM_VALUES = 65536;\nstatic const unsigned HASH_BIT_MASK = 65535; /*HASH_NUM_VALUES - 1, but C90 does not like that as initializer*/\n\ntypedef struct Hash\n{\n  int* head; /*hash value to head circular pos - can be outdated if went around window*/\n  /*circular pos to prev circular pos*/\n  unsigned short* chain;\n  int* val; /*circular pos to hash value*/\n\n  /*TODO: do this not only for zeros but for any repeated byte. However for PNG\n  it's always going to be the zeros that dominate, so not important for PNG*/\n  int* headz; /*similar to head, but for chainz*/\n  unsigned short* chainz; /*those with same amount of zeros*/\n  unsigned short* zeros; /*length of zeros streak, used as a second hash chain*/\n} Hash;\n\nstatic unsigned hash_init(Hash* hash, unsigned windowsize)\n{\n  unsigned i;\n  hash->head = (int*)lodepng_malloc(sizeof(int) * HASH_NUM_VALUES);\n  hash->val = (int*)lodepng_malloc(sizeof(int) * windowsize);\n  hash->chain = (unsigned short*)lodepng_malloc(sizeof(unsigned short) * windowsize);\n\n  hash->zeros = (unsigned short*)lodepng_malloc(sizeof(unsigned short) * windowsize);\n  hash->headz = (int*)lodepng_malloc(sizeof(int) * (MAX_SUPPORTED_DEFLATE_LENGTH + 1));\n  hash->chainz = (unsigned short*)lodepng_malloc(sizeof(unsigned short) * windowsize);\n\n  if(!hash->head || !hash->chain || !hash->val  || !hash->headz|| !hash->chainz || !hash->zeros)\n  {\n    return 83; /*alloc fail*/\n  }\n\n  /*initialize hash table*/\n  for(i = 0; i != HASH_NUM_VALUES; ++i) hash->head[i] = -1;\n  for(i = 0; i != windowsize; ++i) hash->val[i] = -1;\n  for(i = 0; i != windowsize; ++i) hash->chain[i] = i; /*same value as index indicates uninitialized*/\n\n  for(i = 0; i <= MAX_SUPPORTED_DEFLATE_LENGTH; ++i) hash->headz[i] = -1;\n  for(i = 0; i != windowsize; ++i) hash->chainz[i] = i; /*same value as index indicates uninitialized*/\n\n  return 0;\n}\n\nstatic void hash_cleanup(Hash* hash)\n{\n  lodepng_free(hash->head);\n  lodepng_free(hash->val);\n  lodepng_free(hash->chain);\n\n  lodepng_free(hash->zeros);\n  lodepng_free(hash->headz);\n  lodepng_free(hash->chainz);\n}\n\n\n\nstatic unsigned getHash(const unsigned char* data, size_t size, size_t pos)\n{\n  unsigned result = 0;\n  if(pos + 2 < size)\n  {\n    /*A simple shift and xor hash is used. Since the data of PNGs is dominated\n    by zeroes due to the filters, a better hash does not have a significant\n    effect on speed in traversing the chain, and causes more time spend on\n    calculating the hash.*/\n    result ^= (unsigned)(data[pos + 0] << 0u);\n    result ^= (unsigned)(data[pos + 1] << 4u);\n    result ^= (unsigned)(data[pos + 2] << 8u);\n  } else {\n    size_t amount, i;\n    if(pos >= size) return 0;\n    amount = size - pos;\n    for(i = 0; i != amount; ++i) result ^= (unsigned)(data[pos + i] << (i * 8u));\n  }\n  return result & HASH_BIT_MASK;\n}\n\nstatic unsigned countZeros(const unsigned char* data, size_t size, size_t pos)\n{\n  const unsigned char* start = data + pos;\n  const unsigned char* end = start + MAX_SUPPORTED_DEFLATE_LENGTH;\n  if(end > data + size) end = data + size;\n  data = start;\n  while(data != end && *data == 0) ++data;\n  /*subtracting two addresses returned as 32-bit number (max value is MAX_SUPPORTED_DEFLATE_LENGTH)*/\n  return (unsigned)(data - start);\n}\n\n/*wpos = pos & (windowsize - 1)*/\nstatic void updateHashChain(Hash* hash, size_t wpos, unsigned hashval, unsigned short numzeros)\n{\n  hash->val[wpos] = (int)hashval;\n  if(hash->head[hashval] != -1) hash->chain[wpos] = hash->head[hashval];\n  hash->head[hashval] = wpos;\n\n  hash->zeros[wpos] = numzeros;\n  if(hash->headz[numzeros] != -1) hash->chainz[wpos] = hash->headz[numzeros];\n  hash->headz[numzeros] = wpos;\n}\n\n/*\nLZ77-encode the data. Return value is error code. The input are raw bytes, the output\nis in the form of unsigned integers with codes representing for example literal bytes, or\nlength/distance pairs.\nIt uses a hash table technique to let it encode faster. When doing LZ77 encoding, a\nsliding window (of windowsize) is used, and all past bytes in that window can be used as\nthe \"dictionary\". A brute force search through all possible distances would be slow, and\nthis hash technique is one out of several ways to speed this up.\n*/\nstatic unsigned encodeLZ77(uivector* out, Hash* hash,\n                           const unsigned char* in, size_t inpos, size_t insize, unsigned windowsize,\n                           unsigned minmatch, unsigned nicematch, unsigned lazymatching)\n{\n  size_t pos;\n  unsigned i, error = 0;\n  /*for large window lengths, assume the user wants no compression loss. Otherwise, max hash chain length speedup.*/\n  unsigned maxchainlength = windowsize >= 8192 ? windowsize : windowsize / 8;\n  unsigned maxlazymatch = windowsize >= 8192 ? MAX_SUPPORTED_DEFLATE_LENGTH : 64;\n\n  unsigned usezeros = 1; /*not sure if setting it to false for windowsize < 8192 is better or worse*/\n  unsigned numzeros = 0;\n\n  unsigned offset; /*the offset represents the distance in LZ77 terminology*/\n  unsigned length;\n  unsigned lazy = 0;\n  unsigned lazylength = 0, lazyoffset = 0;\n  unsigned hashval;\n  unsigned current_offset, current_length;\n  unsigned prev_offset;\n  const unsigned char *lastptr, *foreptr, *backptr;\n  unsigned hashpos;\n\n  if(windowsize == 0 || windowsize > 32768) return 60; /*error: windowsize smaller/larger than allowed*/\n  if((windowsize & (windowsize - 1)) != 0) return 90; /*error: must be power of two*/\n\n  if(nicematch > MAX_SUPPORTED_DEFLATE_LENGTH) nicematch = MAX_SUPPORTED_DEFLATE_LENGTH;\n\n  for(pos = inpos; pos < insize; ++pos)\n  {\n    size_t wpos = pos & (windowsize - 1); /*position for in 'circular' hash buffers*/\n    unsigned chainlength = 0;\n\n    hashval = getHash(in, insize, pos);\n\n    if(usezeros && hashval == 0)\n    {\n      if(numzeros == 0) numzeros = countZeros(in, insize, pos);\n      else if(pos + numzeros > insize || in[pos + numzeros - 1] != 0) --numzeros;\n    }\n    else\n    {\n      numzeros = 0;\n    }\n\n    updateHashChain(hash, wpos, hashval, numzeros);\n\n    /*the length and offset found for the current position*/\n    length = 0;\n    offset = 0;\n\n    hashpos = hash->chain[wpos];\n\n    lastptr = &in[insize < pos + MAX_SUPPORTED_DEFLATE_LENGTH ? insize : pos + MAX_SUPPORTED_DEFLATE_LENGTH];\n\n    /*search for the longest string*/\n    prev_offset = 0;\n    for(;;)\n    {\n      if(chainlength++ >= maxchainlength) break;\n      current_offset = hashpos <= wpos ? wpos - hashpos : wpos - hashpos + windowsize;\n\n      if(current_offset < prev_offset) break; /*stop when went completely around the circular buffer*/\n      prev_offset = current_offset;\n      if(current_offset > 0)\n      {\n        /*test the next characters*/\n        foreptr = &in[pos];\n        backptr = &in[pos - current_offset];\n\n        /*common case in PNGs is lots of zeros. Quickly skip over them as a speedup*/\n        if(numzeros >= 3)\n        {\n          unsigned skip = hash->zeros[hashpos];\n          if(skip > numzeros) skip = numzeros;\n          backptr += skip;\n          foreptr += skip;\n        }\n\n        while(foreptr != lastptr && *backptr == *foreptr) /*maximum supported length by deflate is max length*/\n        {\n          ++backptr;\n          ++foreptr;\n        }\n        current_length = (unsigned)(foreptr - &in[pos]);\n\n        if(current_length > length)\n        {\n          length = current_length; /*the longest length*/\n          offset = current_offset; /*the offset that is related to this longest length*/\n          /*jump out once a length of max length is found (speed gain). This also jumps\n          out if length is MAX_SUPPORTED_DEFLATE_LENGTH*/\n          if(current_length >= nicematch) break;\n        }\n      }\n\n      if(hashpos == hash->chain[hashpos]) break;\n\n      if(numzeros >= 3 && length > numzeros)\n      {\n        hashpos = hash->chainz[hashpos];\n        if(hash->zeros[hashpos] != numzeros) break;\n      }\n      else\n      {\n        hashpos = hash->chain[hashpos];\n        /*outdated hash value, happens if particular value was not encountered in whole last window*/\n        if(hash->val[hashpos] != (int)hashval) break;\n      }\n    }\n\n    if(lazymatching)\n    {\n      if(!lazy && length >= 3 && length <= maxlazymatch && length < MAX_SUPPORTED_DEFLATE_LENGTH)\n      {\n        lazy = 1;\n        lazylength = length;\n        lazyoffset = offset;\n        continue; /*try the next byte*/\n      }\n      if(lazy)\n      {\n        lazy = 0;\n        if(pos == 0) ERROR_BREAK(81);\n        if(length > lazylength + 1)\n        {\n          /*push the previous character as literal*/\n          if(!uivector_push_back(out, in[pos - 1])) ERROR_BREAK(83 /*alloc fail*/);\n        }\n        else\n        {\n          length = lazylength;\n          offset = lazyoffset;\n          hash->head[hashval] = -1; /*the same hashchain update will be done, this ensures no wrong alteration*/\n          hash->headz[numzeros] = -1; /*idem*/\n          --pos;\n        }\n      }\n    }\n    if(length >= 3 && offset > windowsize) ERROR_BREAK(86 /*too big (or overflown negative) offset*/);\n\n    /*encode it as length/distance pair or literal value*/\n    if(length < 3) /*only lengths of 3 or higher are supported as length/distance pair*/\n    {\n      if(!uivector_push_back(out, in[pos])) ERROR_BREAK(83 /*alloc fail*/);\n    }\n    else if(length < minmatch || (length == 3 && offset > 4096))\n    {\n      /*compensate for the fact that longer offsets have more extra bits, a\n      length of only 3 may be not worth it then*/\n      if(!uivector_push_back(out, in[pos])) ERROR_BREAK(83 /*alloc fail*/);\n    }\n    else\n    {\n      addLengthDistance(out, length, offset);\n      for(i = 1; i < length; ++i)\n      {\n        ++pos;\n        wpos = pos & (windowsize - 1);\n        hashval = getHash(in, insize, pos);\n        if(usezeros && hashval == 0)\n        {\n          if(numzeros == 0) numzeros = countZeros(in, insize, pos);\n          else if(pos + numzeros > insize || in[pos + numzeros - 1] != 0) --numzeros;\n        }\n        else\n        {\n          numzeros = 0;\n        }\n        updateHashChain(hash, wpos, hashval, numzeros);\n      }\n    }\n  } /*end of the loop through each character of input*/\n\n  return error;\n}\n\n/* /////////////////////////////////////////////////////////////////////////// */\n\nstatic unsigned deflateNoCompression(ucvector* out, const unsigned char* data, size_t datasize)\n{\n  /*non compressed deflate block data: 1 bit BFINAL,2 bits BTYPE,(5 bits): it jumps to start of next byte,\n  2 bytes LEN, 2 bytes NLEN, LEN bytes literal DATA*/\n\n  size_t i, j, numdeflateblocks = (datasize + 65534) / 65535;\n  unsigned datapos = 0;\n  for(i = 0; i != numdeflateblocks; ++i)\n  {\n    unsigned BFINAL, BTYPE, LEN, NLEN;\n    unsigned char firstbyte;\n\n    BFINAL = (i == numdeflateblocks - 1);\n    BTYPE = 0;\n\n    firstbyte = (unsigned char)(BFINAL + ((BTYPE & 1) << 1) + ((BTYPE & 2) << 1));\n    ucvector_push_back(out, firstbyte);\n\n    LEN = 65535;\n    if(datasize - datapos < 65535) LEN = (unsigned)datasize - datapos;\n    NLEN = 65535 - LEN;\n\n    ucvector_push_back(out, (unsigned char)(LEN & 255));\n    ucvector_push_back(out, (unsigned char)(LEN >> 8));\n    ucvector_push_back(out, (unsigned char)(NLEN & 255));\n    ucvector_push_back(out, (unsigned char)(NLEN >> 8));\n\n    /*Decompressed data*/\n    for(j = 0; j < 65535 && datapos < datasize; ++j)\n    {\n      ucvector_push_back(out, data[datapos++]);\n    }\n  }\n\n  return 0;\n}\n\n/*\nwrite the lz77-encoded data, which has lit, len and dist codes, to compressed stream using huffman trees.\ntree_ll: the tree for lit and len codes.\ntree_d: the tree for distance codes.\n*/\nstatic void writeLZ77data(size_t* bp, ucvector* out, const uivector* lz77_encoded,\n                          const HuffmanTree* tree_ll, const HuffmanTree* tree_d)\n{\n  size_t i = 0;\n  for(i = 0; i != lz77_encoded->size; ++i)\n  {\n    unsigned val = lz77_encoded->data[i];\n    addHuffmanSymbol(bp, out, HuffmanTree_getCode(tree_ll, val), HuffmanTree_getLength(tree_ll, val));\n    if(val > 256) /*for a length code, 3 more things have to be added*/\n    {\n      unsigned length_index = val - FIRST_LENGTH_CODE_INDEX;\n      unsigned n_length_extra_bits = LENGTHEXTRA[length_index];\n      unsigned length_extra_bits = lz77_encoded->data[++i];\n\n      unsigned distance_code = lz77_encoded->data[++i];\n\n      unsigned distance_index = distance_code;\n      unsigned n_distance_extra_bits = DISTANCEEXTRA[distance_index];\n      unsigned distance_extra_bits = lz77_encoded->data[++i];\n\n      addBitsToStream(bp, out, length_extra_bits, n_length_extra_bits);\n      addHuffmanSymbol(bp, out, HuffmanTree_getCode(tree_d, distance_code),\n                       HuffmanTree_getLength(tree_d, distance_code));\n      addBitsToStream(bp, out, distance_extra_bits, n_distance_extra_bits);\n    }\n  }\n}\n\n/*Deflate for a block of type \"dynamic\", that is, with freely, optimally, created huffman trees*/\nstatic unsigned deflateDynamic(ucvector* out, size_t* bp, Hash* hash,\n                               const unsigned char* data, size_t datapos, size_t dataend,\n                               const LodePNGCompressSettings* settings, unsigned final)\n{\n  unsigned error = 0;\n\n  /*\n  A block is compressed as follows: The PNG data is lz77 encoded, resulting in\n  literal bytes and length/distance pairs. This is then huffman compressed with\n  two huffman trees. One huffman tree is used for the lit and len values (\"ll\"),\n  another huffman tree is used for the dist values (\"d\"). These two trees are\n  stored using their code lengths, and to compress even more these code lengths\n  are also run-length encoded and huffman compressed. This gives a huffman tree\n  of code lengths \"cl\". The code lenghts used to describe this third tree are\n  the code length code lengths (\"clcl\").\n  */\n\n  /*The lz77 encoded data, represented with integers since there will also be length and distance codes in it*/\n  uivector lz77_encoded;\n  HuffmanTree tree_ll; /*tree for lit,len values*/\n  HuffmanTree tree_d; /*tree for distance codes*/\n  HuffmanTree tree_cl; /*tree for encoding the code lengths representing tree_ll and tree_d*/\n  uivector frequencies_ll; /*frequency of lit,len codes*/\n  uivector frequencies_d; /*frequency of dist codes*/\n  uivector frequencies_cl; /*frequency of code length codes*/\n  uivector bitlen_lld; /*lit,len,dist code lenghts (int bits), literally (without repeat codes).*/\n  uivector bitlen_lld_e; /*bitlen_lld encoded with repeat codes (this is a rudemtary run length compression)*/\n  /*bitlen_cl is the code length code lengths (\"clcl\"). The bit lengths of codes to represent tree_cl\n  (these are written as is in the file, it would be crazy to compress these using yet another huffman\n  tree that needs to be represented by yet another set of code lengths)*/\n  uivector bitlen_cl;\n  size_t datasize = dataend - datapos;\n\n  /*\n  Due to the huffman compression of huffman tree representations (\"two levels\"), there are some anologies:\n  bitlen_lld is to tree_cl what data is to tree_ll and tree_d.\n  bitlen_lld_e is to bitlen_lld what lz77_encoded is to data.\n  bitlen_cl is to bitlen_lld_e what bitlen_lld is to lz77_encoded.\n  */\n\n  unsigned BFINAL = final;\n  size_t numcodes_ll, numcodes_d, i;\n  unsigned HLIT, HDIST, HCLEN;\n\n  uivector_init(&lz77_encoded);\n  HuffmanTree_init(&tree_ll);\n  HuffmanTree_init(&tree_d);\n  HuffmanTree_init(&tree_cl);\n  uivector_init(&frequencies_ll);\n  uivector_init(&frequencies_d);\n  uivector_init(&frequencies_cl);\n  uivector_init(&bitlen_lld);\n  uivector_init(&bitlen_lld_e);\n  uivector_init(&bitlen_cl);\n\n  /*This while loop never loops due to a break at the end, it is here to\n  allow breaking out of it to the cleanup phase on error conditions.*/\n  while(!error)\n  {\n    if(settings->use_lz77)\n    {\n      error = encodeLZ77(&lz77_encoded, hash, data, datapos, dataend, settings->windowsize,\n                         settings->minmatch, settings->nicematch, settings->lazymatching);\n      if(error) break;\n    }\n    else\n    {\n      if(!uivector_resize(&lz77_encoded, datasize)) ERROR_BREAK(83 /*alloc fail*/);\n      for(i = datapos; i < dataend; ++i) lz77_encoded.data[i - datapos] = data[i]; /*no LZ77, but still will be Huffman compressed*/\n    }\n\n    if(!uivector_resizev(&frequencies_ll, 286, 0)) ERROR_BREAK(83 /*alloc fail*/);\n    if(!uivector_resizev(&frequencies_d, 30, 0)) ERROR_BREAK(83 /*alloc fail*/);\n\n    /*Count the frequencies of lit, len and dist codes*/\n    for(i = 0; i != lz77_encoded.size; ++i)\n    {\n      unsigned symbol = lz77_encoded.data[i];\n      ++frequencies_ll.data[symbol];\n      if(symbol > 256)\n      {\n        unsigned dist = lz77_encoded.data[i + 2];\n        ++frequencies_d.data[dist];\n        i += 3;\n      }\n    }\n    frequencies_ll.data[256] = 1; /*there will be exactly 1 end code, at the end of the block*/\n\n    /*Make both huffman trees, one for the lit and len codes, one for the dist codes*/\n    error = HuffmanTree_makeFromFrequencies(&tree_ll, frequencies_ll.data, 257, frequencies_ll.size, 15);\n    if(error) break;\n    /*2, not 1, is chosen for mincodes: some buggy PNG decoders require at least 2 symbols in the dist tree*/\n    error = HuffmanTree_makeFromFrequencies(&tree_d, frequencies_d.data, 2, frequencies_d.size, 15);\n    if(error) break;\n\n    numcodes_ll = tree_ll.numcodes; if(numcodes_ll > 286) numcodes_ll = 286;\n    numcodes_d = tree_d.numcodes; if(numcodes_d > 30) numcodes_d = 30;\n    /*store the code lengths of both generated trees in bitlen_lld*/\n    for(i = 0; i != numcodes_ll; ++i) uivector_push_back(&bitlen_lld, HuffmanTree_getLength(&tree_ll, (unsigned)i));\n    for(i = 0; i != numcodes_d; ++i) uivector_push_back(&bitlen_lld, HuffmanTree_getLength(&tree_d, (unsigned)i));\n\n    /*run-length compress bitlen_ldd into bitlen_lld_e by using repeat codes 16 (copy length 3-6 times),\n    17 (3-10 zeroes), 18 (11-138 zeroes)*/\n    for(i = 0; i != (unsigned)bitlen_lld.size; ++i)\n    {\n      unsigned j = 0; /*amount of repititions*/\n      while(i + j + 1 < (unsigned)bitlen_lld.size && bitlen_lld.data[i + j + 1] == bitlen_lld.data[i]) ++j;\n\n      if(bitlen_lld.data[i] == 0 && j >= 2) /*repeat code for zeroes*/\n      {\n        ++j; /*include the first zero*/\n        if(j <= 10) /*repeat code 17 supports max 10 zeroes*/\n        {\n          uivector_push_back(&bitlen_lld_e, 17);\n          uivector_push_back(&bitlen_lld_e, j - 3);\n        }\n        else /*repeat code 18 supports max 138 zeroes*/\n        {\n          if(j > 138) j = 138;\n          uivector_push_back(&bitlen_lld_e, 18);\n          uivector_push_back(&bitlen_lld_e, j - 11);\n        }\n        i += (j - 1);\n      }\n      else if(j >= 3) /*repeat code for value other than zero*/\n      {\n        size_t k;\n        unsigned num = j / 6, rest = j % 6;\n        uivector_push_back(&bitlen_lld_e, bitlen_lld.data[i]);\n        for(k = 0; k < num; ++k)\n        {\n          uivector_push_back(&bitlen_lld_e, 16);\n          uivector_push_back(&bitlen_lld_e, 6 - 3);\n        }\n        if(rest >= 3)\n        {\n          uivector_push_back(&bitlen_lld_e, 16);\n          uivector_push_back(&bitlen_lld_e, rest - 3);\n        }\n        else j -= rest;\n        i += j;\n      }\n      else /*too short to benefit from repeat code*/\n      {\n        uivector_push_back(&bitlen_lld_e, bitlen_lld.data[i]);\n      }\n    }\n\n    /*generate tree_cl, the huffmantree of huffmantrees*/\n\n    if(!uivector_resizev(&frequencies_cl, NUM_CODE_LENGTH_CODES, 0)) ERROR_BREAK(83 /*alloc fail*/);\n    for(i = 0; i != bitlen_lld_e.size; ++i)\n    {\n      ++frequencies_cl.data[bitlen_lld_e.data[i]];\n      /*after a repeat code come the bits that specify the number of repetitions,\n      those don't need to be in the frequencies_cl calculation*/\n      if(bitlen_lld_e.data[i] >= 16) ++i;\n    }\n\n    error = HuffmanTree_makeFromFrequencies(&tree_cl, frequencies_cl.data,\n                                            frequencies_cl.size, frequencies_cl.size, 7);\n    if(error) break;\n\n    if(!uivector_resize(&bitlen_cl, tree_cl.numcodes)) ERROR_BREAK(83 /*alloc fail*/);\n    for(i = 0; i != tree_cl.numcodes; ++i)\n    {\n      /*lenghts of code length tree is in the order as specified by deflate*/\n      bitlen_cl.data[i] = HuffmanTree_getLength(&tree_cl, CLCL_ORDER[i]);\n    }\n    while(bitlen_cl.data[bitlen_cl.size - 1] == 0 && bitlen_cl.size > 4)\n    {\n      /*remove zeros at the end, but minimum size must be 4*/\n      if(!uivector_resize(&bitlen_cl, bitlen_cl.size - 1)) ERROR_BREAK(83 /*alloc fail*/);\n    }\n    if(error) break;\n\n    /*\n    Write everything into the output\n\n    After the BFINAL and BTYPE, the dynamic block consists out of the following:\n    - 5 bits HLIT, 5 bits HDIST, 4 bits HCLEN\n    - (HCLEN+4)*3 bits code lengths of code length alphabet\n    - HLIT + 257 code lenghts of lit/length alphabet (encoded using the code length\n      alphabet, + possible repetition codes 16, 17, 18)\n    - HDIST + 1 code lengths of distance alphabet (encoded using the code length\n      alphabet, + possible repetition codes 16, 17, 18)\n    - compressed data\n    - 256 (end code)\n    */\n\n    /*Write block type*/\n    addBitToStream(bp, out, BFINAL);\n    addBitToStream(bp, out, 0); /*first bit of BTYPE \"dynamic\"*/\n    addBitToStream(bp, out, 1); /*second bit of BTYPE \"dynamic\"*/\n\n    /*write the HLIT, HDIST and HCLEN values*/\n    HLIT = (unsigned)(numcodes_ll - 257);\n    HDIST = (unsigned)(numcodes_d - 1);\n    HCLEN = (unsigned)bitlen_cl.size - 4;\n    /*trim zeroes for HCLEN. HLIT and HDIST were already trimmed at tree creation*/\n    while(!bitlen_cl.data[HCLEN + 4 - 1] && HCLEN > 0) --HCLEN;\n    addBitsToStream(bp, out, HLIT, 5);\n    addBitsToStream(bp, out, HDIST, 5);\n    addBitsToStream(bp, out, HCLEN, 4);\n\n    /*write the code lenghts of the code length alphabet*/\n    for(i = 0; i != HCLEN + 4; ++i) addBitsToStream(bp, out, bitlen_cl.data[i], 3);\n\n    /*write the lenghts of the lit/len AND the dist alphabet*/\n    for(i = 0; i != bitlen_lld_e.size; ++i)\n    {\n      addHuffmanSymbol(bp, out, HuffmanTree_getCode(&tree_cl, bitlen_lld_e.data[i]),\n                       HuffmanTree_getLength(&tree_cl, bitlen_lld_e.data[i]));\n      /*extra bits of repeat codes*/\n      if(bitlen_lld_e.data[i] == 16) addBitsToStream(bp, out, bitlen_lld_e.data[++i], 2);\n      else if(bitlen_lld_e.data[i] == 17) addBitsToStream(bp, out, bitlen_lld_e.data[++i], 3);\n      else if(bitlen_lld_e.data[i] == 18) addBitsToStream(bp, out, bitlen_lld_e.data[++i], 7);\n    }\n\n    /*write the compressed data symbols*/\n    writeLZ77data(bp, out, &lz77_encoded, &tree_ll, &tree_d);\n    /*error: the length of the end code 256 must be larger than 0*/\n    if(HuffmanTree_getLength(&tree_ll, 256) == 0) ERROR_BREAK(64);\n\n    /*write the end code*/\n    addHuffmanSymbol(bp, out, HuffmanTree_getCode(&tree_ll, 256), HuffmanTree_getLength(&tree_ll, 256));\n\n    break; /*end of error-while*/\n  }\n\n  /*cleanup*/\n  uivector_cleanup(&lz77_encoded);\n  HuffmanTree_cleanup(&tree_ll);\n  HuffmanTree_cleanup(&tree_d);\n  HuffmanTree_cleanup(&tree_cl);\n  uivector_cleanup(&frequencies_ll);\n  uivector_cleanup(&frequencies_d);\n  uivector_cleanup(&frequencies_cl);\n  uivector_cleanup(&bitlen_lld_e);\n  uivector_cleanup(&bitlen_lld);\n  uivector_cleanup(&bitlen_cl);\n\n  return error;\n}\n\nstatic unsigned deflateFixed(ucvector* out, size_t* bp, Hash* hash,\n                             const unsigned char* data,\n                             size_t datapos, size_t dataend,\n                             const LodePNGCompressSettings* settings, unsigned final)\n{\n  HuffmanTree tree_ll; /*tree for literal values and length codes*/\n  HuffmanTree tree_d; /*tree for distance codes*/\n\n  unsigned BFINAL = final;\n  unsigned error = 0;\n  size_t i;\n\n  HuffmanTree_init(&tree_ll);\n  HuffmanTree_init(&tree_d);\n\n  generateFixedLitLenTree(&tree_ll);\n  generateFixedDistanceTree(&tree_d);\n\n  addBitToStream(bp, out, BFINAL);\n  addBitToStream(bp, out, 1); /*first bit of BTYPE*/\n  addBitToStream(bp, out, 0); /*second bit of BTYPE*/\n\n  if(settings->use_lz77) /*LZ77 encoded*/\n  {\n    uivector lz77_encoded;\n    uivector_init(&lz77_encoded);\n    error = encodeLZ77(&lz77_encoded, hash, data, datapos, dataend, settings->windowsize,\n                       settings->minmatch, settings->nicematch, settings->lazymatching);\n    if(!error) writeLZ77data(bp, out, &lz77_encoded, &tree_ll, &tree_d);\n    uivector_cleanup(&lz77_encoded);\n  }\n  else /*no LZ77, but still will be Huffman compressed*/\n  {\n    for(i = datapos; i < dataend; ++i)\n    {\n      addHuffmanSymbol(bp, out, HuffmanTree_getCode(&tree_ll, data[i]), HuffmanTree_getLength(&tree_ll, data[i]));\n    }\n  }\n  /*add END code*/\n  if(!error) addHuffmanSymbol(bp, out, HuffmanTree_getCode(&tree_ll, 256), HuffmanTree_getLength(&tree_ll, 256));\n\n  /*cleanup*/\n  HuffmanTree_cleanup(&tree_ll);\n  HuffmanTree_cleanup(&tree_d);\n\n  return error;\n}\n\nstatic unsigned lodepng_deflatev(ucvector* out, const unsigned char* in, size_t insize,\n                                 const LodePNGCompressSettings* settings)\n{\n  unsigned error = 0;\n  size_t i, blocksize, numdeflateblocks;\n  size_t bp = 0; /*the bit pointer*/\n  Hash hash;\n\n  if(settings->btype > 2) return 61;\n  else if(settings->btype == 0) return deflateNoCompression(out, in, insize);\n  else if(settings->btype == 1) blocksize = insize;\n  else /*if(settings->btype == 2)*/\n  {\n    /*on PNGs, deflate blocks of 65-262k seem to give most dense encoding*/\n    blocksize = insize / 8 + 8;\n    if(blocksize < 65536) blocksize = 65536;\n    if(blocksize > 262144) blocksize = 262144;\n  }\n\n  numdeflateblocks = (insize + blocksize - 1) / blocksize;\n  if(numdeflateblocks == 0) numdeflateblocks = 1;\n\n  error = hash_init(&hash, settings->windowsize);\n  if(error) return error;\n\n  for(i = 0; i != numdeflateblocks && !error; ++i)\n  {\n    unsigned final = (i == numdeflateblocks - 1);\n    size_t start = i * blocksize;\n    size_t end = start + blocksize;\n    if(end > insize) end = insize;\n\n    if(settings->btype == 1) error = deflateFixed(out, &bp, &hash, in, start, end, settings, final);\n    else if(settings->btype == 2) error = deflateDynamic(out, &bp, &hash, in, start, end, settings, final);\n  }\n\n  hash_cleanup(&hash);\n\n  return error;\n}\n\nunsigned lodepng_deflate(unsigned char** out, size_t* outsize,\n                         const unsigned char* in, size_t insize,\n                         const LodePNGCompressSettings* settings)\n{\n  unsigned error;\n  ucvector v;\n  ucvector_init_buffer(&v, *out, *outsize);\n  error = lodepng_deflatev(&v, in, insize, settings);\n  *out = v.data;\n  *outsize = v.size;\n  return error;\n}\n\nstatic unsigned deflate(unsigned char** out, size_t* outsize,\n                        const unsigned char* in, size_t insize,\n                        const LodePNGCompressSettings* settings)\n{\n  if(settings->custom_deflate)\n  {\n    return settings->custom_deflate(out, outsize, in, insize, settings);\n  }\n  else\n  {\n    return lodepng_deflate(out, outsize, in, insize, settings);\n  }\n}\n\n#endif /*LODEPNG_COMPILE_DECODER*/\n\n/* ////////////////////////////////////////////////////////////////////////// */\n/* / Adler32                                                                  */\n/* ////////////////////////////////////////////////////////////////////////// */\n\nstatic unsigned update_adler32(unsigned adler, const unsigned char* data, unsigned len)\n{\n   unsigned s1 = adler & 0xffff;\n   unsigned s2 = (adler >> 16) & 0xffff;\n\n  while(len > 0)\n  {\n    /*at least 5550 sums can be done before the sums overflow, saving a lot of module divisions*/\n    unsigned amount = len > 5550 ? 5550 : len;\n    len -= amount;\n    while(amount > 0)\n    {\n      s1 += (*data++);\n      s2 += s1;\n      --amount;\n    }\n    s1 %= 65521;\n    s2 %= 65521;\n  }\n\n  return (s2 << 16) | s1;\n}\n\n/*Return the adler32 of the bytes data[0..len-1]*/\nstatic unsigned adler32(const unsigned char* data, unsigned len)\n{\n  return update_adler32(1L, data, len);\n}\n\n/* ////////////////////////////////////////////////////////////////////////// */\n/* / Zlib                                                                   / */\n/* ////////////////////////////////////////////////////////////////////////// */\n\n#ifdef LODEPNG_COMPILE_DECODER\n\nunsigned lodepng_zlib_decompress(unsigned char** out, size_t* outsize, const unsigned char* in,\n                                 size_t insize, const LodePNGDecompressSettings* settings)\n{\n  unsigned error = 0;\n  unsigned CM, CINFO, FDICT;\n\n  if(insize < 2) return 53; /*error, size of zlib data too small*/\n  /*read information from zlib header*/\n  if((in[0] * 256 + in[1]) % 31 != 0)\n  {\n    /*error: 256 * in[0] + in[1] must be a multiple of 31, the FCHECK value is supposed to be made that way*/\n    return 24;\n  }\n\n  CM = in[0] & 15;\n  CINFO = (in[0] >> 4) & 15;\n  /*FCHECK = in[1] & 31;*/ /*FCHECK is already tested above*/\n  FDICT = (in[1] >> 5) & 1;\n  /*FLEVEL = (in[1] >> 6) & 3;*/ /*FLEVEL is not used here*/\n\n  if(CM != 8 || CINFO > 7)\n  {\n    /*error: only compression method 8: inflate with sliding window of 32k is supported by the PNG spec*/\n    return 25;\n  }\n  if(FDICT != 0)\n  {\n    /*error: the specification of PNG says about the zlib stream:\n      \"The additional flags shall not specify a preset dictionary.\"*/\n    return 26;\n  }\n\n  error = inflate(out, outsize, in + 2, insize - 2, settings);\n  if(error) return error;\n\n  if(!settings->ignore_adler32)\n  {\n    unsigned ADLER32 = lodepng_read32bitInt(&in[insize - 4]);\n    unsigned checksum = adler32(*out, (unsigned)(*outsize));\n    if(checksum != ADLER32) return 58; /*error, adler checksum not correct, data must be corrupted*/\n  }\n\n  return 0; /*no error*/\n}\n\nstatic unsigned zlib_decompress(unsigned char** out, size_t* outsize, const unsigned char* in,\n                                size_t insize, const LodePNGDecompressSettings* settings)\n{\n  if(settings->custom_zlib)\n  {\n    return settings->custom_zlib(out, outsize, in, insize, settings);\n  }\n  else\n  {\n    return lodepng_zlib_decompress(out, outsize, in, insize, settings);\n  }\n}\n\n#endif /*LODEPNG_COMPILE_DECODER*/\n\n#ifdef LODEPNG_COMPILE_ENCODER\n\nunsigned lodepng_zlib_compress(unsigned char** out, size_t* outsize, const unsigned char* in,\n                               size_t insize, const LodePNGCompressSettings* settings)\n{\n  /*initially, *out must be NULL and outsize 0, if you just give some random *out\n  that's pointing to a non allocated buffer, this'll crash*/\n  ucvector outv;\n  size_t i;\n  unsigned error;\n  unsigned char* deflatedata = 0;\n  size_t deflatesize = 0;\n\n  /*zlib data: 1 byte CMF (CM+CINFO), 1 byte FLG, deflate data, 4 byte ADLER32 checksum of the Decompressed data*/\n  unsigned CMF = 120; /*0b01111000: CM 8, CINFO 7. With CINFO 7, any window size up to 32768 can be used.*/\n  unsigned FLEVEL = 0;\n  unsigned FDICT = 0;\n  unsigned CMFFLG = 256 * CMF + FDICT * 32 + FLEVEL * 64;\n  unsigned FCHECK = 31 - CMFFLG % 31;\n  CMFFLG += FCHECK;\n\n  /*ucvector-controlled version of the output buffer, for dynamic array*/\n  ucvector_init_buffer(&outv, *out, *outsize);\n\n  ucvector_push_back(&outv, (unsigned char)(CMFFLG >> 8));\n  ucvector_push_back(&outv, (unsigned char)(CMFFLG & 255));\n\n  error = deflate(&deflatedata, &deflatesize, in, insize, settings);\n\n  if(!error)\n  {\n    unsigned ADLER32 = adler32(in, (unsigned)insize);\n    for(i = 0; i != deflatesize; ++i) ucvector_push_back(&outv, deflatedata[i]);\n    lodepng_free(deflatedata);\n    lodepng_add32bitInt(&outv, ADLER32);\n  }\n\n  *out = outv.data;\n  *outsize = outv.size;\n\n  return error;\n}\n\n/* compress using the default or custom zlib function */\nstatic unsigned zlib_compress(unsigned char** out, size_t* outsize, const unsigned char* in,\n                              size_t insize, const LodePNGCompressSettings* settings)\n{\n  if(settings->custom_zlib)\n  {\n    return settings->custom_zlib(out, outsize, in, insize, settings);\n  }\n  else\n  {\n    return lodepng_zlib_compress(out, outsize, in, insize, settings);\n  }\n}\n\n#endif /*LODEPNG_COMPILE_ENCODER*/\n\n#else /*no LODEPNG_COMPILE_ZLIB*/\n\n#ifdef LODEPNG_COMPILE_DECODER\nstatic unsigned zlib_decompress(unsigned char** out, size_t* outsize, const unsigned char* in,\n                                size_t insize, const LodePNGDecompressSettings* settings)\n{\n  if(!settings->custom_zlib) return 87; /*no custom zlib function provided */\n  return settings->custom_zlib(out, outsize, in, insize, settings);\n}\n#endif /*LODEPNG_COMPILE_DECODER*/\n#ifdef LODEPNG_COMPILE_ENCODER\nstatic unsigned zlib_compress(unsigned char** out, size_t* outsize, const unsigned char* in,\n                              size_t insize, const LodePNGCompressSettings* settings)\n{\n  if(!settings->custom_zlib) return 87; /*no custom zlib function provided */\n  return settings->custom_zlib(out, outsize, in, insize, settings);\n}\n#endif /*LODEPNG_COMPILE_ENCODER*/\n\n#endif /*LODEPNG_COMPILE_ZLIB*/\n\n/* ////////////////////////////////////////////////////////////////////////// */\n\n#ifdef LODEPNG_COMPILE_ENCODER\n\n/*this is a good tradeoff between speed and compression ratio*/\n#define DEFAULT_WINDOWSIZE 2048\n\nvoid lodepng_compress_settings_init(LodePNGCompressSettings* settings)\n{\n  /*compress with dynamic huffman tree (not in the mathematical sense, just not the predefined one)*/\n  settings->btype = 2;\n  settings->use_lz77 = 1;\n  settings->windowsize = DEFAULT_WINDOWSIZE;\n  settings->minmatch = 3;\n  settings->nicematch = 128;\n  settings->lazymatching = 1;\n\n  settings->custom_zlib = 0;\n  settings->custom_deflate = 0;\n  settings->custom_context = 0;\n}\n\nconst LodePNGCompressSettings lodepng_default_compress_settings = {2, 1, DEFAULT_WINDOWSIZE, 3, 128, 1, 0, 0, 0};\n\n\n#endif /*LODEPNG_COMPILE_ENCODER*/\n\n#ifdef LODEPNG_COMPILE_DECODER\n\nvoid lodepng_decompress_settings_init(LodePNGDecompressSettings* settings)\n{\n  settings->ignore_adler32 = 0;\n\n  settings->custom_zlib = 0;\n  settings->custom_inflate = 0;\n  settings->custom_context = 0;\n}\n\nconst LodePNGDecompressSettings lodepng_default_decompress_settings = {0, 0, 0, 0};\n\n#endif /*LODEPNG_COMPILE_DECODER*/\n\n/* ////////////////////////////////////////////////////////////////////////// */\n/* ////////////////////////////////////////////////////////////////////////// */\n/* // End of Zlib related code. Begin of PNG related code.                 // */\n/* ////////////////////////////////////////////////////////////////////////// */\n/* ////////////////////////////////////////////////////////////////////////// */\n\n#ifdef LODEPNG_COMPILE_PNG\n\n/* ////////////////////////////////////////////////////////////////////////// */\n/* / CRC32                                                                  / */\n/* ////////////////////////////////////////////////////////////////////////// */\n\n\n#ifndef LODEPNG_NO_COMPILE_CRC\n/* CRC polynomial: 0xedb88320 */\nstatic unsigned lodepng_crc32_table[256] = {\n           0u, 1996959894u, 3993919788u, 2567524794u,  124634137u, 1886057615u, 3915621685u, 2657392035u,\n   249268274u, 2044508324u, 3772115230u, 2547177864u,  162941995u, 2125561021u, 3887607047u, 2428444049u,\n   498536548u, 1789927666u, 4089016648u, 2227061214u,  450548861u, 1843258603u, 4107580753u, 2211677639u,\n   325883990u, 1684777152u, 4251122042u, 2321926636u,  335633487u, 1661365465u, 4195302755u, 2366115317u,\n   997073096u, 1281953886u, 3579855332u, 2724688242u, 1006888145u, 1258607687u, 3524101629u, 2768942443u,\n   901097722u, 1119000684u, 3686517206u, 2898065728u,  853044451u, 1172266101u, 3705015759u, 2882616665u,\n   651767980u, 1373503546u, 3369554304u, 3218104598u,  565507253u, 1454621731u, 3485111705u, 3099436303u,\n   671266974u, 1594198024u, 3322730930u, 2970347812u,  795835527u, 1483230225u, 3244367275u, 3060149565u,\n  1994146192u,   31158534u, 2563907772u, 4023717930u, 1907459465u,  112637215u, 2680153253u, 3904427059u,\n  2013776290u,  251722036u, 2517215374u, 3775830040u, 2137656763u,  141376813u, 2439277719u, 3865271297u,\n  1802195444u,  476864866u, 2238001368u, 4066508878u, 1812370925u,  453092731u, 2181625025u, 4111451223u,\n  1706088902u,  314042704u, 2344532202u, 4240017532u, 1658658271u,  366619977u, 2362670323u, 4224994405u,\n  1303535960u,  984961486u, 2747007092u, 3569037538u, 1256170817u, 1037604311u, 2765210733u, 3554079995u,\n  1131014506u,  879679996u, 2909243462u, 3663771856u, 1141124467u,  855842277u, 2852801631u, 3708648649u,\n  1342533948u,  654459306u, 3188396048u, 3373015174u, 1466479909u,  544179635u, 3110523913u, 3462522015u,\n  1591671054u,  702138776u, 2966460450u, 3352799412u, 1504918807u,  783551873u, 3082640443u, 3233442989u,\n  3988292384u, 2596254646u,   62317068u, 1957810842u, 3939845945u, 2647816111u,   81470997u, 1943803523u,\n  3814918930u, 2489596804u,  225274430u, 2053790376u, 3826175755u, 2466906013u,  167816743u, 2097651377u,\n  4027552580u, 2265490386u,  503444072u, 1762050814u, 4150417245u, 2154129355u,  426522225u, 1852507879u,\n  4275313526u, 2312317920u,  282753626u, 1742555852u, 4189708143u, 2394877945u,  397917763u, 1622183637u,\n  3604390888u, 2714866558u,  953729732u, 1340076626u, 3518719985u, 2797360999u, 1068828381u, 1219638859u,\n  3624741850u, 2936675148u,  906185462u, 1090812512u, 3747672003u, 2825379669u,  829329135u, 1181335161u,\n  3412177804u, 3160834842u,  628085408u, 1382605366u, 3423369109u, 3138078467u,  570562233u, 1426400815u,\n  3317316542u, 2998733608u,  733239954u, 1555261956u, 3268935591u, 3050360625u,  752459403u, 1541320221u,\n  2607071920u, 3965973030u, 1969922972u,   40735498u, 2617837225u, 3943577151u, 1913087877u,   83908371u,\n  2512341634u, 3803740692u, 2075208622u,  213261112u, 2463272603u, 3855990285u, 2094854071u,  198958881u,\n  2262029012u, 4057260610u, 1759359992u,  534414190u, 2176718541u, 4139329115u, 1873836001u,  414664567u,\n  2282248934u, 4279200368u, 1711684554u,  285281116u, 2405801727u, 4167216745u, 1634467795u,  376229701u,\n  2685067896u, 3608007406u, 1308918612u,  956543938u, 2808555105u, 3495958263u, 1231636301u, 1047427035u,\n  2932959818u, 3654703836u, 1088359270u,  936918000u, 2847714899u, 3736837829u, 1202900863u,  817233897u,\n  3183342108u, 3401237130u, 1404277552u,  615818150u, 3134207493u, 3453421203u, 1423857449u,  601450431u,\n  3009837614u, 3294710456u, 1567103746u,  711928724u, 3020668471u, 3272380065u, 1510334235u,  755167117u\n};\n\n/*Return the CRC of the bytes buf[0..len-1].*/\nunsigned lodepng_crc32(const unsigned char* data, size_t length)\n{\n  unsigned r = 0xffffffffu;\n  size_t i;\n  for(i = 0; i < length; ++i)\n  {\n    r = lodepng_crc32_table[(r ^ data[i]) & 0xff] ^ (r >> 8);\n  }\n  return r ^ 0xffffffffu;\n}\n#else /* !LODEPNG_NO_COMPILE_CRC */\nunsigned lodepng_crc32(const unsigned char* data, size_t length);\n#endif /* !LODEPNG_NO_COMPILE_CRC */\n\n/* ////////////////////////////////////////////////////////////////////////// */\n/* / Reading and writing single bits and bytes from/to stream for LodePNG   / */\n/* ////////////////////////////////////////////////////////////////////////// */\n\nstatic unsigned char readBitFromReversedStream(size_t* bitpointer, const unsigned char* bitstream)\n{\n  unsigned char result = (unsigned char)((bitstream[(*bitpointer) >> 3] >> (7 - ((*bitpointer) & 0x7))) & 1);\n  ++(*bitpointer);\n  return result;\n}\n\nstatic unsigned readBitsFromReversedStream(size_t* bitpointer, const unsigned char* bitstream, size_t nbits)\n{\n  unsigned result = 0;\n  size_t i;\n  for(i = 0 ; i < nbits; ++i)\n  {\n    result <<= 1;\n    result |= (unsigned)readBitFromReversedStream(bitpointer, bitstream);\n  }\n  return result;\n}\n\n#ifdef LODEPNG_COMPILE_DECODER\nstatic void setBitOfReversedStream0(size_t* bitpointer, unsigned char* bitstream, unsigned char bit)\n{\n  /*the current bit in bitstream must be 0 for this to work*/\n  if(bit)\n  {\n    /*earlier bit of huffman code is in a lesser significant bit of an earlier byte*/\n    bitstream[(*bitpointer) >> 3] |= (bit << (7 - ((*bitpointer) & 0x7)));\n  }\n  ++(*bitpointer);\n}\n#endif /*LODEPNG_COMPILE_DECODER*/\n\nstatic void setBitOfReversedStream(size_t* bitpointer, unsigned char* bitstream, unsigned char bit)\n{\n  /*the current bit in bitstream may be 0 or 1 for this to work*/\n  if(bit == 0) bitstream[(*bitpointer) >> 3] &=  (unsigned char)(~(1 << (7 - ((*bitpointer) & 0x7))));\n  else         bitstream[(*bitpointer) >> 3] |=  (1 << (7 - ((*bitpointer) & 0x7)));\n  ++(*bitpointer);\n}\n\n/* ////////////////////////////////////////////////////////////////////////// */\n/* / PNG chunks                                                             / */\n/* ////////////////////////////////////////////////////////////////////////// */\n\nunsigned lodepng_chunk_length(const unsigned char* chunk)\n{\n  return lodepng_read32bitInt(&chunk[0]);\n}\n\nvoid lodepng_chunk_type(char type[5], const unsigned char* chunk)\n{\n  unsigned i;\n  for(i = 0; i != 4; ++i) type[i] = (char)chunk[4 + i];\n  type[4] = 0; /*null termination char*/\n}\n\nunsigned char lodepng_chunk_type_equals(const unsigned char* chunk, const char* type)\n{\n  if(strlen(type) != 4) return 0;\n  return (chunk[4] == type[0] && chunk[5] == type[1] && chunk[6] == type[2] && chunk[7] == type[3]);\n}\n\nunsigned char lodepng_chunk_ancillary(const unsigned char* chunk)\n{\n  return((chunk[4] & 32) != 0);\n}\n\nunsigned char lodepng_chunk_private(const unsigned char* chunk)\n{\n  return((chunk[6] & 32) != 0);\n}\n\nunsigned char lodepng_chunk_safetocopy(const unsigned char* chunk)\n{\n  return((chunk[7] & 32) != 0);\n}\n\nunsigned char* lodepng_chunk_data(unsigned char* chunk)\n{\n  return &chunk[8];\n}\n\nconst unsigned char* lodepng_chunk_data_const(const unsigned char* chunk)\n{\n  return &chunk[8];\n}\n\nunsigned lodepng_chunk_check_crc(const unsigned char* chunk)\n{\n  unsigned length = lodepng_chunk_length(chunk);\n  unsigned CRC = lodepng_read32bitInt(&chunk[length + 8]);\n  /*the CRC is taken of the data and the 4 chunk type letters, not the length*/\n  unsigned checksum = lodepng_crc32(&chunk[4], length + 4);\n  if(CRC != checksum) return 1;\n  else return 0;\n}\n\nvoid lodepng_chunk_generate_crc(unsigned char* chunk)\n{\n  unsigned length = lodepng_chunk_length(chunk);\n  unsigned CRC = lodepng_crc32(&chunk[4], length + 4);\n  lodepng_set32bitInt(chunk + 8 + length, CRC);\n}\n\nunsigned char* lodepng_chunk_next(unsigned char* chunk)\n{\n  unsigned total_chunk_length = lodepng_chunk_length(chunk) + 12;\n  return &chunk[total_chunk_length];\n}\n\nconst unsigned char* lodepng_chunk_next_const(const unsigned char* chunk)\n{\n  unsigned total_chunk_length = lodepng_chunk_length(chunk) + 12;\n  return &chunk[total_chunk_length];\n}\n\nunsigned lodepng_chunk_append(unsigned char** out, size_t* outlength, const unsigned char* chunk)\n{\n  unsigned i;\n  unsigned total_chunk_length = lodepng_chunk_length(chunk) + 12;\n  unsigned char *chunk_start, *new_buffer;\n  size_t new_length = (*outlength) + total_chunk_length;\n  if(new_length < total_chunk_length || new_length < (*outlength)) return 77; /*integer overflow happened*/\n\n  new_buffer = (unsigned char*)lodepng_realloc(*out, new_length);\n  if(!new_buffer) return 83; /*alloc fail*/\n  (*out) = new_buffer;\n  (*outlength) = new_length;\n  chunk_start = &(*out)[new_length - total_chunk_length];\n\n  for(i = 0; i != total_chunk_length; ++i) chunk_start[i] = chunk[i];\n\n  return 0;\n}\n\nunsigned lodepng_chunk_create(unsigned char** out, size_t* outlength, unsigned length,\n                              const char* type, const unsigned char* data)\n{\n  unsigned i;\n  unsigned char *chunk, *new_buffer;\n  size_t new_length = (*outlength) + length + 12;\n  if(new_length < length + 12 || new_length < (*outlength)) return 77; /*integer overflow happened*/\n  new_buffer = (unsigned char*)lodepng_realloc(*out, new_length);\n  if(!new_buffer) return 83; /*alloc fail*/\n  (*out) = new_buffer;\n  (*outlength) = new_length;\n  chunk = &(*out)[(*outlength) - length - 12];\n\n  /*1: length*/\n  lodepng_set32bitInt(chunk, (unsigned)length);\n\n  /*2: chunk name (4 letters)*/\n  chunk[4] = (unsigned char)type[0];\n  chunk[5] = (unsigned char)type[1];\n  chunk[6] = (unsigned char)type[2];\n  chunk[7] = (unsigned char)type[3];\n\n  /*3: the data*/\n  for(i = 0; i != length; ++i) chunk[8 + i] = data[i];\n\n  /*4: CRC (of the chunkname characters and the data)*/\n  lodepng_chunk_generate_crc(chunk);\n\n  return 0;\n}\n\n/* ////////////////////////////////////////////////////////////////////////// */\n/* / Color types and such                                                   / */\n/* ////////////////////////////////////////////////////////////////////////// */\n\n/*return type is a LodePNG error code*/\nstatic unsigned checkColorValidity(LodePNGColorType colortype, unsigned bd) /*bd = bitdepth*/\n{\n  switch(colortype)\n  {\n    case 0: if(!(bd == 1 || bd == 2 || bd == 4 || bd == 8 || bd == 16)) return 37; break; /*grey*/\n    case 2: if(!(                                 bd == 8 || bd == 16)) return 37; break; /*RGB*/\n    case 3: if(!(bd == 1 || bd == 2 || bd == 4 || bd == 8            )) return 37; break; /*palette*/\n    case 4: if(!(                                 bd == 8 || bd == 16)) return 37; break; /*grey + alpha*/\n    case 6: if(!(                                 bd == 8 || bd == 16)) return 37; break; /*RGBA*/\n    default: return 31;\n  }\n  return 0; /*allowed color type / bits combination*/\n}\n\nstatic unsigned getNumColorChannels(LodePNGColorType colortype)\n{\n  switch(colortype)\n  {\n    case 0: return 1; /*grey*/\n    case 2: return 3; /*RGB*/\n    case 3: return 1; /*palette*/\n    case 4: return 2; /*grey + alpha*/\n    case 6: return 4; /*RGBA*/\n  }\n  return 0; /*unexisting color type*/\n}\n\nstatic unsigned lodepng_get_bpp_lct(LodePNGColorType colortype, unsigned bitdepth)\n{\n  /*bits per pixel is amount of channels * bits per channel*/\n  return getNumColorChannels(colortype) * bitdepth;\n}\n\n/* ////////////////////////////////////////////////////////////////////////// */\n\nvoid lodepng_color_mode_init(LodePNGColorMode* info)\n{\n  info->key_defined = 0;\n  info->key_r = info->key_g = info->key_b = 0;\n  info->colortype = LCT_RGBA;\n  info->bitdepth = 8;\n  info->palette = 0;\n  info->palettesize = 0;\n}\n\nvoid lodepng_color_mode_cleanup(LodePNGColorMode* info)\n{\n  lodepng_palette_clear(info);\n}\n\nunsigned lodepng_color_mode_copy(LodePNGColorMode* dest, const LodePNGColorMode* source)\n{\n  size_t i;\n  lodepng_color_mode_cleanup(dest);\n  *dest = *source;\n  if(source->palette)\n  {\n    dest->palette = (unsigned char*)lodepng_malloc(1024);\n    if(!dest->palette && source->palettesize) return 83; /*alloc fail*/\n    for(i = 0; i != source->palettesize * 4; ++i) dest->palette[i] = source->palette[i];\n  }\n  return 0;\n}\n\nstatic int lodepng_color_mode_equal(const LodePNGColorMode* a, const LodePNGColorMode* b)\n{\n  size_t i;\n  if(a->colortype != b->colortype) return 0;\n  if(a->bitdepth != b->bitdepth) return 0;\n  if(a->key_defined != b->key_defined) return 0;\n  if(a->key_defined)\n  {\n    if(a->key_r != b->key_r) return 0;\n    if(a->key_g != b->key_g) return 0;\n    if(a->key_b != b->key_b) return 0;\n  }\n  /*if one of the palette sizes is 0, then we consider it to be the same as the\n  other: it means that e.g. the palette was not given by the user and should be\n  considered the same as the palette inside the PNG.*/\n  if(1/*a->palettesize != 0 && b->palettesize != 0*/) {\n    if(a->palettesize != b->palettesize) return 0;\n    for(i = 0; i != a->palettesize * 4; ++i)\n    {\n      if(a->palette[i] != b->palette[i]) return 0;\n    }\n  }\n  return 1;\n}\n\nvoid lodepng_palette_clear(LodePNGColorMode* info)\n{\n  if(info->palette) lodepng_free(info->palette);\n  info->palette = 0;\n  info->palettesize = 0;\n}\n\nunsigned lodepng_palette_add(LodePNGColorMode* info,\n                             unsigned char r, unsigned char g, unsigned char b, unsigned char a)\n{\n  unsigned char* data;\n  /*the same resize technique as C++ std::vectors is used, and here it's made so that for a palette with\n  the max of 256 colors, it'll have the exact alloc size*/\n  if(!info->palette) /*allocate palette if empty*/\n  {\n    /*room for 256 colors with 4 bytes each*/\n    data = (unsigned char*)lodepng_realloc(info->palette, 1024);\n    if(!data) return 83; /*alloc fail*/\n    else info->palette = data;\n  }\n  info->palette[4 * info->palettesize + 0] = r;\n  info->palette[4 * info->palettesize + 1] = g;\n  info->palette[4 * info->palettesize + 2] = b;\n  info->palette[4 * info->palettesize + 3] = a;\n  ++info->palettesize;\n  return 0;\n}\n\nunsigned lodepng_get_bpp(const LodePNGColorMode* info)\n{\n  /*calculate bits per pixel out of colortype and bitdepth*/\n  return lodepng_get_bpp_lct(info->colortype, info->bitdepth);\n}\n\nunsigned lodepng_get_channels(const LodePNGColorMode* info)\n{\n  return getNumColorChannels(info->colortype);\n}\n\nunsigned lodepng_is_greyscale_type(const LodePNGColorMode* info)\n{\n  return info->colortype == LCT_GREY || info->colortype == LCT_GREY_ALPHA;\n}\n\nunsigned lodepng_is_alpha_type(const LodePNGColorMode* info)\n{\n  return (info->colortype & 4) != 0; /*4 or 6*/\n}\n\nunsigned lodepng_is_palette_type(const LodePNGColorMode* info)\n{\n  return info->colortype == LCT_PALETTE;\n}\n\nunsigned lodepng_has_palette_alpha(const LodePNGColorMode* info)\n{\n  size_t i;\n  for(i = 0; i != info->palettesize; ++i)\n  {\n    if(info->palette[i * 4 + 3] < 255) return 1;\n  }\n  return 0;\n}\n\nunsigned lodepng_can_have_alpha(const LodePNGColorMode* info)\n{\n  return info->key_defined\n      || lodepng_is_alpha_type(info)\n      || lodepng_has_palette_alpha(info);\n}\n\nsize_t lodepng_get_raw_size(unsigned w, unsigned h, const LodePNGColorMode* color)\n{\n  /*will not overflow for any color type if roughly w * h < 268435455*/\n  size_t bpp = lodepng_get_bpp(color);\n  size_t n = w * h;\n  return ((n / 8) * bpp) + ((n & 7) * bpp + 7) / 8;\n}\n\nsize_t lodepng_get_raw_size_lct(unsigned w, unsigned h, LodePNGColorType colortype, unsigned bitdepth)\n{\n  /*will not overflow for any color type if roughly w * h < 268435455*/\n  size_t bpp = lodepng_get_bpp_lct(colortype, bitdepth);\n  size_t n = w * h;\n  return ((n / 8) * bpp) + ((n & 7) * bpp + 7) / 8;\n}\n\n\n#ifdef LODEPNG_COMPILE_PNG\n#ifdef LODEPNG_COMPILE_DECODER\n/*in an idat chunk, each scanline is a multiple of 8 bits, unlike the lodepng output buffer*/\nstatic size_t lodepng_get_raw_size_idat(unsigned w, unsigned h, const LodePNGColorMode* color)\n{\n  /*will not overflow for any color type if roughly w * h < 268435455*/\n  size_t bpp = lodepng_get_bpp(color);\n  size_t line = ((w / 8) * bpp) + ((w & 7) * bpp + 7) / 8;\n  return h * line;\n}\n#endif /*LODEPNG_COMPILE_DECODER*/\n#endif /*LODEPNG_COMPILE_PNG*/\n\n#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS\n\nstatic void LodePNGUnknownChunks_init(LodePNGInfo* info)\n{\n  unsigned i;\n  for(i = 0; i != 3; ++i) info->unknown_chunks_data[i] = 0;\n  for(i = 0; i != 3; ++i) info->unknown_chunks_size[i] = 0;\n}\n\nstatic void LodePNGUnknownChunks_cleanup(LodePNGInfo* info)\n{\n  unsigned i;\n  for(i = 0; i != 3; ++i) lodepng_free(info->unknown_chunks_data[i]);\n}\n\nstatic unsigned LodePNGUnknownChunks_copy(LodePNGInfo* dest, const LodePNGInfo* src)\n{\n  unsigned i;\n\n  LodePNGUnknownChunks_cleanup(dest);\n\n  for(i = 0; i != 3; ++i)\n  {\n    size_t j;\n    dest->unknown_chunks_size[i] = src->unknown_chunks_size[i];\n    dest->unknown_chunks_data[i] = (unsigned char*)lodepng_malloc(src->unknown_chunks_size[i]);\n    if(!dest->unknown_chunks_data[i] && dest->unknown_chunks_size[i]) return 83; /*alloc fail*/\n    for(j = 0; j < src->unknown_chunks_size[i]; ++j)\n    {\n      dest->unknown_chunks_data[i][j] = src->unknown_chunks_data[i][j];\n    }\n  }\n\n  return 0;\n}\n\n/******************************************************************************/\n\nstatic void LodePNGText_init(LodePNGInfo* info)\n{\n  info->text_num = 0;\n  info->text_keys = NULL;\n  info->text_strings = NULL;\n}\n\nstatic void LodePNGText_cleanup(LodePNGInfo* info)\n{\n  size_t i;\n  for(i = 0; i != info->text_num; ++i)\n  {\n    string_cleanup(&info->text_keys[i]);\n    string_cleanup(&info->text_strings[i]);\n  }\n  lodepng_free(info->text_keys);\n  lodepng_free(info->text_strings);\n}\n\nstatic unsigned LodePNGText_copy(LodePNGInfo* dest, const LodePNGInfo* source)\n{\n  size_t i = 0;\n  dest->text_keys = 0;\n  dest->text_strings = 0;\n  dest->text_num = 0;\n  for(i = 0; i != source->text_num; ++i)\n  {\n    CERROR_TRY_RETURN(lodepng_add_text(dest, source->text_keys[i], source->text_strings[i]));\n  }\n  return 0;\n}\n\nvoid lodepng_clear_text(LodePNGInfo* info)\n{\n  LodePNGText_cleanup(info);\n}\n\nunsigned lodepng_add_text(LodePNGInfo* info, const char* key, const char* str)\n{\n  char** new_keys = (char**)(lodepng_realloc(info->text_keys, sizeof(char*) * (info->text_num + 1)));\n  char** new_strings = (char**)(lodepng_realloc(info->text_strings, sizeof(char*) * (info->text_num + 1)));\n  if(!new_keys || !new_strings)\n  {\n    lodepng_free(new_keys);\n    lodepng_free(new_strings);\n    return 83; /*alloc fail*/\n  }\n\n  ++info->text_num;\n  info->text_keys = new_keys;\n  info->text_strings = new_strings;\n\n  string_init(&info->text_keys[info->text_num - 1]);\n  string_set(&info->text_keys[info->text_num - 1], key);\n\n  string_init(&info->text_strings[info->text_num - 1]);\n  string_set(&info->text_strings[info->text_num - 1], str);\n\n  return 0;\n}\n\n/******************************************************************************/\n\nstatic void LodePNGIText_init(LodePNGInfo* info)\n{\n  info->itext_num = 0;\n  info->itext_keys = NULL;\n  info->itext_langtags = NULL;\n  info->itext_transkeys = NULL;\n  info->itext_strings = NULL;\n}\n\nstatic void LodePNGIText_cleanup(LodePNGInfo* info)\n{\n  size_t i;\n  for(i = 0; i != info->itext_num; ++i)\n  {\n    string_cleanup(&info->itext_keys[i]);\n    string_cleanup(&info->itext_langtags[i]);\n    string_cleanup(&info->itext_transkeys[i]);\n    string_cleanup(&info->itext_strings[i]);\n  }\n  lodepng_free(info->itext_keys);\n  lodepng_free(info->itext_langtags);\n  lodepng_free(info->itext_transkeys);\n  lodepng_free(info->itext_strings);\n}\n\nstatic unsigned LodePNGIText_copy(LodePNGInfo* dest, const LodePNGInfo* source)\n{\n  size_t i = 0;\n  dest->itext_keys = 0;\n  dest->itext_langtags = 0;\n  dest->itext_transkeys = 0;\n  dest->itext_strings = 0;\n  dest->itext_num = 0;\n  for(i = 0; i != source->itext_num; ++i)\n  {\n    CERROR_TRY_RETURN(lodepng_add_itext(dest, source->itext_keys[i], source->itext_langtags[i],\n                                        source->itext_transkeys[i], source->itext_strings[i]));\n  }\n  return 0;\n}\n\nvoid lodepng_clear_itext(LodePNGInfo* info)\n{\n  LodePNGIText_cleanup(info);\n}\n\nunsigned lodepng_add_itext(LodePNGInfo* info, const char* key, const char* langtag,\n                           const char* transkey, const char* str)\n{\n  char** new_keys = (char**)(lodepng_realloc(info->itext_keys, sizeof(char*) * (info->itext_num + 1)));\n  char** new_langtags = (char**)(lodepng_realloc(info->itext_langtags, sizeof(char*) * (info->itext_num + 1)));\n  char** new_transkeys = (char**)(lodepng_realloc(info->itext_transkeys, sizeof(char*) * (info->itext_num + 1)));\n  char** new_strings = (char**)(lodepng_realloc(info->itext_strings, sizeof(char*) * (info->itext_num + 1)));\n  if(!new_keys || !new_langtags || !new_transkeys || !new_strings)\n  {\n    lodepng_free(new_keys);\n    lodepng_free(new_langtags);\n    lodepng_free(new_transkeys);\n    lodepng_free(new_strings);\n    return 83; /*alloc fail*/\n  }\n\n  ++info->itext_num;\n  info->itext_keys = new_keys;\n  info->itext_langtags = new_langtags;\n  info->itext_transkeys = new_transkeys;\n  info->itext_strings = new_strings;\n\n  string_init(&info->itext_keys[info->itext_num - 1]);\n  string_set(&info->itext_keys[info->itext_num - 1], key);\n\n  string_init(&info->itext_langtags[info->itext_num - 1]);\n  string_set(&info->itext_langtags[info->itext_num - 1], langtag);\n\n  string_init(&info->itext_transkeys[info->itext_num - 1]);\n  string_set(&info->itext_transkeys[info->itext_num - 1], transkey);\n\n  string_init(&info->itext_strings[info->itext_num - 1]);\n  string_set(&info->itext_strings[info->itext_num - 1], str);\n\n  return 0;\n}\n#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/\n\nvoid lodepng_info_init(LodePNGInfo* info)\n{\n  lodepng_color_mode_init(&info->color);\n  info->interlace_method = 0;\n  info->compression_method = 0;\n  info->filter_method = 0;\n#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS\n  info->background_defined = 0;\n  info->background_r = info->background_g = info->background_b = 0;\n\n  LodePNGText_init(info);\n  LodePNGIText_init(info);\n\n  info->time_defined = 0;\n  info->phys_defined = 0;\n\n  LodePNGUnknownChunks_init(info);\n#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/\n}\n\nvoid lodepng_info_cleanup(LodePNGInfo* info)\n{\n  lodepng_color_mode_cleanup(&info->color);\n#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS\n  LodePNGText_cleanup(info);\n  LodePNGIText_cleanup(info);\n\n  LodePNGUnknownChunks_cleanup(info);\n#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/\n}\n\nunsigned lodepng_info_copy(LodePNGInfo* dest, const LodePNGInfo* source)\n{\n  lodepng_info_cleanup(dest);\n  *dest = *source;\n  lodepng_color_mode_init(&dest->color);\n  CERROR_TRY_RETURN(lodepng_color_mode_copy(&dest->color, &source->color));\n\n#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS\n  CERROR_TRY_RETURN(LodePNGText_copy(dest, source));\n  CERROR_TRY_RETURN(LodePNGIText_copy(dest, source));\n\n  LodePNGUnknownChunks_init(dest);\n  CERROR_TRY_RETURN(LodePNGUnknownChunks_copy(dest, source));\n#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/\n  return 0;\n}\n\nvoid lodepng_info_swap(LodePNGInfo* a, LodePNGInfo* b)\n{\n  LodePNGInfo temp = *a;\n  *a = *b;\n  *b = temp;\n}\n\n/* ////////////////////////////////////////////////////////////////////////// */\n\n/*index: bitgroup index, bits: bitgroup size(1, 2 or 4), in: bitgroup value, out: octet array to add bits to*/\nstatic void addColorBits(unsigned char* out, size_t index, unsigned bits, unsigned in)\n{\n  unsigned m = bits == 1 ? 7 : bits == 2 ? 3 : 1; /*8 / bits - 1*/\n  /*p = the partial index in the byte, e.g. with 4 palettebits it is 0 for first half or 1 for second half*/\n  unsigned p = index & m;\n  in &= (1u << bits) - 1u; /*filter out any other bits of the input value*/\n  in = in << (bits * (m - p));\n  if(p == 0) out[index * bits / 8] = in;\n  else out[index * bits / 8] |= in;\n}\n\ntypedef struct ColorTree ColorTree;\n\n/*\nOne node of a color tree\nThis is the data structure used to count the number of unique colors and to get a palette\nindex for a color. It's like an octree, but because the alpha channel is used too, each\nnode has 16 instead of 8 children.\n*/\nstruct ColorTree\n{\n  ColorTree* children[16]; /*up to 16 pointers to ColorTree of next level*/\n  int index; /*the payload. Only has a meaningful value if this is in the last level*/\n};\n\nstatic void color_tree_init(ColorTree* tree)\n{\n  int i;\n  for(i = 0; i != 16; ++i) tree->children[i] = 0;\n  tree->index = -1;\n}\n\nstatic void color_tree_cleanup(ColorTree* tree)\n{\n  int i;\n  for(i = 0; i != 16; ++i)\n  {\n    if(tree->children[i])\n    {\n      color_tree_cleanup(tree->children[i]);\n      lodepng_free(tree->children[i]);\n    }\n  }\n}\n\n/*returns -1 if color not present, its index otherwise*/\nstatic int color_tree_get(ColorTree* tree, unsigned char r, unsigned char g, unsigned char b, unsigned char a)\n{\n  int bit = 0;\n  for(bit = 0; bit < 8; ++bit)\n  {\n    int i = 8 * ((r >> bit) & 1) + 4 * ((g >> bit) & 1) + 2 * ((b >> bit) & 1) + 1 * ((a >> bit) & 1);\n    if(!tree->children[i]) return -1;\n    else tree = tree->children[i];\n  }\n  return tree ? tree->index : -1;\n}\n\n#ifdef LODEPNG_COMPILE_ENCODER\nstatic int color_tree_has(ColorTree* tree, unsigned char r, unsigned char g, unsigned char b, unsigned char a)\n{\n  return color_tree_get(tree, r, g, b, a) >= 0;\n}\n#endif /*LODEPNG_COMPILE_ENCODER*/\n\n/*color is not allowed to already exist.\nIndex should be >= 0 (it's signed to be compatible with using -1 for \"doesn't exist\")*/\nstatic void color_tree_add(ColorTree* tree,\n                           unsigned char r, unsigned char g, unsigned char b, unsigned char a, unsigned index)\n{\n  int bit;\n  for(bit = 0; bit < 8; ++bit)\n  {\n    int i = 8 * ((r >> bit) & 1) + 4 * ((g >> bit) & 1) + 2 * ((b >> bit) & 1) + 1 * ((a >> bit) & 1);\n    if(!tree->children[i])\n    {\n      tree->children[i] = (ColorTree*)lodepng_malloc(sizeof(ColorTree));\n      color_tree_init(tree->children[i]);\n    }\n    tree = tree->children[i];\n  }\n  tree->index = (int)index;\n}\n\n/*put a pixel, given its RGBA color, into image of any color type*/\nstatic unsigned rgba8ToPixel(unsigned char* out, size_t i,\n                             const LodePNGColorMode* mode, ColorTree* tree /*for palette*/,\n                             unsigned char r, unsigned char g, unsigned char b, unsigned char a)\n{\n  if(mode->colortype == LCT_GREY)\n  {\n    unsigned char grey = r; /*((unsigned short)r + g + b) / 3*/;\n    if(mode->bitdepth == 8) out[i] = grey;\n    else if(mode->bitdepth == 16) out[i * 2 + 0] = out[i * 2 + 1] = grey;\n    else\n    {\n      /*take the most significant bits of grey*/\n      grey = (grey >> (8 - mode->bitdepth)) & ((1 << mode->bitdepth) - 1);\n      addColorBits(out, i, mode->bitdepth, grey);\n    }\n  }\n  else if(mode->colortype == LCT_RGB)\n  {\n    if(mode->bitdepth == 8)\n    {\n      out[i * 3 + 0] = r;\n      out[i * 3 + 1] = g;\n      out[i * 3 + 2] = b;\n    }\n    else\n    {\n      out[i * 6 + 0] = out[i * 6 + 1] = r;\n      out[i * 6 + 2] = out[i * 6 + 3] = g;\n      out[i * 6 + 4] = out[i * 6 + 5] = b;\n    }\n  }\n  else if(mode->colortype == LCT_PALETTE)\n  {\n    int index = color_tree_get(tree, r, g, b, a);\n    if(index < 0) return 82; /*color not in palette*/\n    if(mode->bitdepth == 8) out[i] = index;\n    else addColorBits(out, i, mode->bitdepth, (unsigned)index);\n  }\n  else if(mode->colortype == LCT_GREY_ALPHA)\n  {\n    unsigned char grey = r; /*((unsigned short)r + g + b) / 3*/;\n    if(mode->bitdepth == 8)\n    {\n      out[i * 2 + 0] = grey;\n      out[i * 2 + 1] = a;\n    }\n    else if(mode->bitdepth == 16)\n    {\n      out[i * 4 + 0] = out[i * 4 + 1] = grey;\n      out[i * 4 + 2] = out[i * 4 + 3] = a;\n    }\n  }\n  else if(mode->colortype == LCT_RGBA)\n  {\n    if(mode->bitdepth == 8)\n    {\n      out[i * 4 + 0] = r;\n      out[i * 4 + 1] = g;\n      out[i * 4 + 2] = b;\n      out[i * 4 + 3] = a;\n    }\n    else\n    {\n      out[i * 8 + 0] = out[i * 8 + 1] = r;\n      out[i * 8 + 2] = out[i * 8 + 3] = g;\n      out[i * 8 + 4] = out[i * 8 + 5] = b;\n      out[i * 8 + 6] = out[i * 8 + 7] = a;\n    }\n  }\n\n  return 0; /*no error*/\n}\n\n/*put a pixel, given its RGBA16 color, into image of any color 16-bitdepth type*/\nstatic void rgba16ToPixel(unsigned char* out, size_t i,\n                         const LodePNGColorMode* mode,\n                         unsigned short r, unsigned short g, unsigned short b, unsigned short a)\n{\n  if(mode->colortype == LCT_GREY)\n  {\n    unsigned short grey = r; /*((unsigned)r + g + b) / 3*/;\n    out[i * 2 + 0] = (grey >> 8) & 255;\n    out[i * 2 + 1] = grey & 255;\n  }\n  else if(mode->colortype == LCT_RGB)\n  {\n    out[i * 6 + 0] = (r >> 8) & 255;\n    out[i * 6 + 1] = r & 255;\n    out[i * 6 + 2] = (g >> 8) & 255;\n    out[i * 6 + 3] = g & 255;\n    out[i * 6 + 4] = (b >> 8) & 255;\n    out[i * 6 + 5] = b & 255;\n  }\n  else if(mode->colortype == LCT_GREY_ALPHA)\n  {\n    unsigned short grey = r; /*((unsigned)r + g + b) / 3*/;\n    out[i * 4 + 0] = (grey >> 8) & 255;\n    out[i * 4 + 1] = grey & 255;\n    out[i * 4 + 2] = (a >> 8) & 255;\n    out[i * 4 + 3] = a & 255;\n  }\n  else if(mode->colortype == LCT_RGBA)\n  {\n    out[i * 8 + 0] = (r >> 8) & 255;\n    out[i * 8 + 1] = r & 255;\n    out[i * 8 + 2] = (g >> 8) & 255;\n    out[i * 8 + 3] = g & 255;\n    out[i * 8 + 4] = (b >> 8) & 255;\n    out[i * 8 + 5] = b & 255;\n    out[i * 8 + 6] = (a >> 8) & 255;\n    out[i * 8 + 7] = a & 255;\n  }\n}\n\n/*Get RGBA8 color of pixel with index i (y * width + x) from the raw image with given color type.*/\nstatic void getPixelColorRGBA8(unsigned char* r, unsigned char* g,\n                               unsigned char* b, unsigned char* a,\n                               const unsigned char* in, size_t i,\n                               const LodePNGColorMode* mode)\n{\n  if(mode->colortype == LCT_GREY)\n  {\n    if(mode->bitdepth == 8)\n    {\n      *r = *g = *b = in[i];\n      if(mode->key_defined && *r == mode->key_r) *a = 0;\n      else *a = 255;\n    }\n    else if(mode->bitdepth == 16)\n    {\n      *r = *g = *b = in[i * 2 + 0];\n      if(mode->key_defined && 256U * in[i * 2 + 0] + in[i * 2 + 1] == mode->key_r) *a = 0;\n      else *a = 255;\n    }\n    else\n    {\n      unsigned highest = ((1U << mode->bitdepth) - 1U); /*highest possible value for this bit depth*/\n      size_t j = i * mode->bitdepth;\n      unsigned value = readBitsFromReversedStream(&j, in, mode->bitdepth);\n      *r = *g = *b = (value * 255) / highest;\n      if(mode->key_defined && value == mode->key_r) *a = 0;\n      else *a = 255;\n    }\n  }\n  else if(mode->colortype == LCT_RGB)\n  {\n    if(mode->bitdepth == 8)\n    {\n      *r = in[i * 3 + 0]; *g = in[i * 3 + 1]; *b = in[i * 3 + 2];\n      if(mode->key_defined && *r == mode->key_r && *g == mode->key_g && *b == mode->key_b) *a = 0;\n      else *a = 255;\n    }\n    else\n    {\n      *r = in[i * 6 + 0];\n      *g = in[i * 6 + 2];\n      *b = in[i * 6 + 4];\n      if(mode->key_defined && 256U * in[i * 6 + 0] + in[i * 6 + 1] == mode->key_r\n         && 256U * in[i * 6 + 2] + in[i * 6 + 3] == mode->key_g\n         && 256U * in[i * 6 + 4] + in[i * 6 + 5] == mode->key_b) *a = 0;\n      else *a = 255;\n    }\n  }\n  else if(mode->colortype == LCT_PALETTE)\n  {\n    unsigned index;\n    if(mode->bitdepth == 8) index = in[i];\n    else\n    {\n      size_t j = i * mode->bitdepth;\n      index = readBitsFromReversedStream(&j, in, mode->bitdepth);\n    }\n\n    if(index >= mode->palettesize)\n    {\n      /*This is an error according to the PNG spec, but common PNG decoders make it black instead.\n      Done here too, slightly faster due to no error handling needed.*/\n      *r = *g = *b = 0;\n      *a = 255;\n    }\n    else\n    {\n      *r = mode->palette[index * 4 + 0];\n      *g = mode->palette[index * 4 + 1];\n      *b = mode->palette[index * 4 + 2];\n      *a = mode->palette[index * 4 + 3];\n    }\n  }\n  else if(mode->colortype == LCT_GREY_ALPHA)\n  {\n    if(mode->bitdepth == 8)\n    {\n      *r = *g = *b = in[i * 2 + 0];\n      *a = in[i * 2 + 1];\n    }\n    else\n    {\n      *r = *g = *b = in[i * 4 + 0];\n      *a = in[i * 4 + 2];\n    }\n  }\n  else if(mode->colortype == LCT_RGBA)\n  {\n    if(mode->bitdepth == 8)\n    {\n      *r = in[i * 4 + 0];\n      *g = in[i * 4 + 1];\n      *b = in[i * 4 + 2];\n      *a = in[i * 4 + 3];\n    }\n    else\n    {\n      *r = in[i * 8 + 0];\n      *g = in[i * 8 + 2];\n      *b = in[i * 8 + 4];\n      *a = in[i * 8 + 6];\n    }\n  }\n}\n\n/*Similar to getPixelColorRGBA8, but with all the for loops inside of the color\nmode test cases, optimized to convert the colors much faster, when converting\nto RGBA or RGB with 8 bit per cannel. buffer must be RGBA or RGB output with\nenough memory, if has_alpha is true the output is RGBA. mode has the color mode\nof the input buffer.*/\nstatic void getPixelColorsRGBA8(unsigned char* buffer, size_t numpixels,\n                                unsigned has_alpha, const unsigned char* in,\n                                const LodePNGColorMode* mode)\n{\n  unsigned num_channels = has_alpha ? 4 : 3;\n  size_t i;\n  if(mode->colortype == LCT_GREY)\n  {\n    if(mode->bitdepth == 8)\n    {\n      for(i = 0; i != numpixels; ++i, buffer += num_channels)\n      {\n        buffer[0] = buffer[1] = buffer[2] = in[i];\n        if(has_alpha) buffer[3] = mode->key_defined && in[i] == mode->key_r ? 0 : 255;\n      }\n    }\n    else if(mode->bitdepth == 16)\n    {\n      for(i = 0; i != numpixels; ++i, buffer += num_channels)\n      {\n        buffer[0] = buffer[1] = buffer[2] = in[i * 2];\n        if(has_alpha) buffer[3] = mode->key_defined && 256U * in[i * 2 + 0] + in[i * 2 + 1] == mode->key_r ? 0 : 255;\n      }\n    }\n    else\n    {\n      unsigned highest = ((1U << mode->bitdepth) - 1U); /*highest possible value for this bit depth*/\n      size_t j = 0;\n      for(i = 0; i != numpixels; ++i, buffer += num_channels)\n      {\n        unsigned value = readBitsFromReversedStream(&j, in, mode->bitdepth);\n        buffer[0] = buffer[1] = buffer[2] = (value * 255) / highest;\n        if(has_alpha) buffer[3] = mode->key_defined && value == mode->key_r ? 0 : 255;\n      }\n    }\n  }\n  else if(mode->colortype == LCT_RGB)\n  {\n    if(mode->bitdepth == 8)\n    {\n      for(i = 0; i != numpixels; ++i, buffer += num_channels)\n      {\n        buffer[0] = in[i * 3 + 0];\n        buffer[1] = in[i * 3 + 1];\n        buffer[2] = in[i * 3 + 2];\n        if(has_alpha) buffer[3] = mode->key_defined && buffer[0] == mode->key_r\n           && buffer[1]== mode->key_g && buffer[2] == mode->key_b ? 0 : 255;\n      }\n    }\n    else\n    {\n      for(i = 0; i != numpixels; ++i, buffer += num_channels)\n      {\n        buffer[0] = in[i * 6 + 0];\n        buffer[1] = in[i * 6 + 2];\n        buffer[2] = in[i * 6 + 4];\n        if(has_alpha) buffer[3] = mode->key_defined\n           && 256U * in[i * 6 + 0] + in[i * 6 + 1] == mode->key_r\n           && 256U * in[i * 6 + 2] + in[i * 6 + 3] == mode->key_g\n           && 256U * in[i * 6 + 4] + in[i * 6 + 5] == mode->key_b ? 0 : 255;\n      }\n    }\n  }\n  else if(mode->colortype == LCT_PALETTE)\n  {\n    unsigned index;\n    size_t j = 0;\n    for(i = 0; i != numpixels; ++i, buffer += num_channels)\n    {\n      if(mode->bitdepth == 8) index = in[i];\n      else index = readBitsFromReversedStream(&j, in, mode->bitdepth);\n\n      if(index >= mode->palettesize)\n      {\n        /*This is an error according to the PNG spec, but most PNG decoders make it black instead.\n        Done here too, slightly faster due to no error handling needed.*/\n        buffer[0] = buffer[1] = buffer[2] = 0;\n        if(has_alpha) buffer[3] = 255;\n      }\n      else\n      {\n        buffer[0] = mode->palette[index * 4 + 0];\n        buffer[1] = mode->palette[index * 4 + 1];\n        buffer[2] = mode->palette[index * 4 + 2];\n        if(has_alpha) buffer[3] = mode->palette[index * 4 + 3];\n      }\n    }\n  }\n  else if(mode->colortype == LCT_GREY_ALPHA)\n  {\n    if(mode->bitdepth == 8)\n    {\n      for(i = 0; i != numpixels; ++i, buffer += num_channels)\n      {\n        buffer[0] = buffer[1] = buffer[2] = in[i * 2 + 0];\n        if(has_alpha) buffer[3] = in[i * 2 + 1];\n      }\n    }\n    else\n    {\n      for(i = 0; i != numpixels; ++i, buffer += num_channels)\n      {\n        buffer[0] = buffer[1] = buffer[2] = in[i * 4 + 0];\n        if(has_alpha) buffer[3] = in[i * 4 + 2];\n      }\n    }\n  }\n  else if(mode->colortype == LCT_RGBA)\n  {\n    if(mode->bitdepth == 8)\n    {\n      for(i = 0; i != numpixels; ++i, buffer += num_channels)\n      {\n        buffer[0] = in[i * 4 + 0];\n        buffer[1] = in[i * 4 + 1];\n        buffer[2] = in[i * 4 + 2];\n        if(has_alpha) buffer[3] = in[i * 4 + 3];\n      }\n    }\n    else\n    {\n      for(i = 0; i != numpixels; ++i, buffer += num_channels)\n      {\n        buffer[0] = in[i * 8 + 0];\n        buffer[1] = in[i * 8 + 2];\n        buffer[2] = in[i * 8 + 4];\n        if(has_alpha) buffer[3] = in[i * 8 + 6];\n      }\n    }\n  }\n}\n\n/*Get RGBA16 color of pixel with index i (y * width + x) from the raw image with\ngiven color type, but the given color type must be 16-bit itself.*/\nstatic void getPixelColorRGBA16(unsigned short* r, unsigned short* g, unsigned short* b, unsigned short* a,\n                                const unsigned char* in, size_t i, const LodePNGColorMode* mode)\n{\n  if(mode->colortype == LCT_GREY)\n  {\n    *r = *g = *b = 256 * in[i * 2 + 0] + in[i * 2 + 1];\n    if(mode->key_defined && 256U * in[i * 2 + 0] + in[i * 2 + 1] == mode->key_r) *a = 0;\n    else *a = 65535;\n  }\n  else if(mode->colortype == LCT_RGB)\n  {\n    *r = 256u * in[i * 6 + 0] + in[i * 6 + 1];\n    *g = 256u * in[i * 6 + 2] + in[i * 6 + 3];\n    *b = 256u * in[i * 6 + 4] + in[i * 6 + 5];\n    if(mode->key_defined\n       && 256u * in[i * 6 + 0] + in[i * 6 + 1] == mode->key_r\n       && 256u * in[i * 6 + 2] + in[i * 6 + 3] == mode->key_g\n       && 256u * in[i * 6 + 4] + in[i * 6 + 5] == mode->key_b) *a = 0;\n    else *a = 65535;\n  }\n  else if(mode->colortype == LCT_GREY_ALPHA)\n  {\n    *r = *g = *b = 256u * in[i * 4 + 0] + in[i * 4 + 1];\n    *a = 256u * in[i * 4 + 2] + in[i * 4 + 3];\n  }\n  else if(mode->colortype == LCT_RGBA)\n  {\n    *r = 256u * in[i * 8 + 0] + in[i * 8 + 1];\n    *g = 256u * in[i * 8 + 2] + in[i * 8 + 3];\n    *b = 256u * in[i * 8 + 4] + in[i * 8 + 5];\n    *a = 256u * in[i * 8 + 6] + in[i * 8 + 7];\n  }\n}\n\nunsigned lodepng_convert(unsigned char* out, const unsigned char* in,\n                         const LodePNGColorMode* mode_out, const LodePNGColorMode* mode_in,\n                         unsigned w, unsigned h)\n{\n  size_t i;\n  ColorTree tree;\n  size_t numpixels = w * h;\n\n  if(lodepng_color_mode_equal(mode_out, mode_in))\n  {\n    size_t numbytes = lodepng_get_raw_size(w, h, mode_in);\n    for(i = 0; i != numbytes; ++i) out[i] = in[i];\n    return 0;\n  }\n\n  if(mode_out->colortype == LCT_PALETTE)\n  {\n    size_t palettesize = mode_out->palettesize;\n    const unsigned char* palette = mode_out->palette;\n    size_t palsize = 1u << mode_out->bitdepth;\n    /*if the user specified output palette but did not give the values, assume\n    they want the values of the input color type (assuming that one is palette).\n    Note that we never create a new palette ourselves.*/\n    if(palettesize == 0)\n    {\n      palettesize = mode_in->palettesize;\n      palette = mode_in->palette;\n    }\n    if(palettesize < palsize) palsize = palettesize;\n    color_tree_init(&tree);\n    for(i = 0; i != palsize; ++i)\n    {\n      const unsigned char* p = &palette[i * 4];\n      color_tree_add(&tree, p[0], p[1], p[2], p[3], i);\n    }\n  }\n\n  if(mode_in->bitdepth == 16 && mode_out->bitdepth == 16)\n  {\n    for(i = 0; i != numpixels; ++i)\n    {\n      unsigned short r = 0, g = 0, b = 0, a = 0;\n      getPixelColorRGBA16(&r, &g, &b, &a, in, i, mode_in);\n      rgba16ToPixel(out, i, mode_out, r, g, b, a);\n    }\n  }\n  else if(mode_out->bitdepth == 8 && mode_out->colortype == LCT_RGBA)\n  {\n    getPixelColorsRGBA8(out, numpixels, 1, in, mode_in);\n  }\n  else if(mode_out->bitdepth == 8 && mode_out->colortype == LCT_RGB)\n  {\n    getPixelColorsRGBA8(out, numpixels, 0, in, mode_in);\n  }\n  else\n  {\n    unsigned char r = 0, g = 0, b = 0, a = 0;\n    for(i = 0; i != numpixels; ++i)\n    {\n      getPixelColorRGBA8(&r, &g, &b, &a, in, i, mode_in);\n      CERROR_TRY_RETURN(rgba8ToPixel(out, i, mode_out, &tree, r, g, b, a));\n    }\n  }\n\n  if(mode_out->colortype == LCT_PALETTE)\n  {\n    color_tree_cleanup(&tree);\n  }\n\n  return 0; /*no error*/\n}\n\n#ifdef LODEPNG_COMPILE_ENCODER\n\nvoid lodepng_color_profile_init(LodePNGColorProfile* profile)\n{\n  profile->colored = 0;\n  profile->key = 0;\n  profile->alpha = 0;\n  profile->key_r = profile->key_g = profile->key_b = 0;\n  profile->numcolors = 0;\n  profile->bits = 1;\n}\n\n/*function used for debug purposes with C++*/\n/*void printColorProfile(LodePNGColorProfile* p)\n{\n  std::cout << \"colored: \" << (int)p->colored << \", \";\n  std::cout << \"key: \" << (int)p->key << \", \";\n  std::cout << \"key_r: \" << (int)p->key_r << \", \";\n  std::cout << \"key_g: \" << (int)p->key_g << \", \";\n  std::cout << \"key_b: \" << (int)p->key_b << \", \";\n  std::cout << \"alpha: \" << (int)p->alpha << \", \";\n  std::cout << \"numcolors: \" << (int)p->numcolors << \", \";\n  std::cout << \"bits: \" << (int)p->bits << std::endl;\n}*/\n\n/*Returns how many bits needed to represent given value (max 8 bit)*/\nstatic unsigned getValueRequiredBits(unsigned char value)\n{\n  if(value == 0 || value == 255) return 1;\n  /*The scaling of 2-bit and 4-bit values uses multiples of 85 and 17*/\n  if(value % 17 == 0) return value % 85 == 0 ? 2 : 4;\n  return 8;\n}\n\n/*profile must already have been inited with mode.\nIt's ok to set some parameters of profile to done already.*/\nunsigned lodepng_get_color_profile(LodePNGColorProfile* profile,\n                                   const unsigned char* in, unsigned w, unsigned h,\n                                   const LodePNGColorMode* mode)\n{\n  unsigned error = 0;\n  size_t i;\n  ColorTree tree;\n  size_t numpixels = w * h;\n\n  unsigned colored_done = lodepng_is_greyscale_type(mode) ? 1 : 0;\n  unsigned alpha_done = lodepng_can_have_alpha(mode) ? 0 : 1;\n  unsigned numcolors_done = 0;\n  unsigned bpp = lodepng_get_bpp(mode);\n  unsigned bits_done = bpp == 1 ? 1 : 0;\n  unsigned maxnumcolors = 257;\n  unsigned sixteen = 0;\n  if(bpp <= 8) maxnumcolors = bpp == 1 ? 2 : (bpp == 2 ? 4 : (bpp == 4 ? 16 : 256));\n\n  color_tree_init(&tree);\n\n  /*Check if the 16-bit input is truly 16-bit*/\n  if(mode->bitdepth == 16)\n  {\n    unsigned short r, g, b, a;\n    for(i = 0; i != numpixels; ++i)\n    {\n      getPixelColorRGBA16(&r, &g, &b, &a, in, i, mode);\n      if((r & 255) != ((r >> 8) & 255) || (g & 255) != ((g >> 8) & 255) ||\n         (b & 255) != ((b >> 8) & 255) || (a & 255) != ((a >> 8) & 255)) /*first and second byte differ*/\n      {\n        sixteen = 1;\n        break;\n      }\n    }\n  }\n\n  if(sixteen)\n  {\n    unsigned short r = 0, g = 0, b = 0, a = 0;\n    profile->bits = 16;\n    bits_done = numcolors_done = 1; /*counting colors no longer useful, palette doesn't support 16-bit*/\n\n    for(i = 0; i != numpixels; ++i)\n    {\n      getPixelColorRGBA16(&r, &g, &b, &a, in, i, mode);\n\n      if(!colored_done && (r != g || r != b))\n      {\n        profile->colored = 1;\n        colored_done = 1;\n      }\n\n      if(!alpha_done)\n      {\n        unsigned matchkey = (r == profile->key_r && g == profile->key_g && b == profile->key_b);\n        if(a != 65535 && (a != 0 || (profile->key && !matchkey)))\n        {\n          profile->alpha = 1;\n          alpha_done = 1;\n          if(profile->bits < 8) profile->bits = 8; /*PNG has no alphachannel modes with less than 8-bit per channel*/\n        }\n        else if(a == 0 && !profile->alpha && !profile->key)\n        {\n          profile->key = 1;\n          profile->key_r = r;\n          profile->key_g = g;\n          profile->key_b = b;\n        }\n        else if(a == 65535 && profile->key && matchkey)\n        {\n          /* Color key cannot be used if an opaque pixel also has that RGB color. */\n          profile->alpha = 1;\n          alpha_done = 1;\n        }\n      }\n      if(alpha_done && numcolors_done && colored_done && bits_done) break;\n    }\n\n    if(profile->key && !profile->alpha)\n    {\n      for(i = 0; i != numpixels; ++i)\n      {\n        getPixelColorRGBA16(&r, &g, &b, &a, in, i, mode);\n        if(a != 0 && r == profile->key_r && g == profile->key_g && b == profile->key_b)\n        {\n          /* Color key cannot be used if an opaque pixel also has that RGB color. */\n          profile->alpha = 1;\n          alpha_done = 1;\n        }\n      }\n    }\n  }\n  else /* < 16-bit */\n  {\n    unsigned char r = 0, g = 0, b = 0, a = 0;\n    for(i = 0; i != numpixels; ++i)\n    {\n      getPixelColorRGBA8(&r, &g, &b, &a, in, i, mode);\n\n      if(!bits_done && profile->bits < 8)\n      {\n        /*only r is checked, < 8 bits is only relevant for greyscale*/\n        unsigned bits = getValueRequiredBits(r);\n        if(bits > profile->bits) profile->bits = bits;\n      }\n      bits_done = (profile->bits >= bpp);\n\n      if(!colored_done && (r != g || r != b))\n      {\n        profile->colored = 1;\n        colored_done = 1;\n        if(profile->bits < 8) profile->bits = 8; /*PNG has no colored modes with less than 8-bit per channel*/\n      }\n\n      if(!alpha_done)\n      {\n        unsigned matchkey = (r == profile->key_r && g == profile->key_g && b == profile->key_b);\n        if(a != 255 && (a != 0 || (profile->key && !matchkey)))\n        {\n          profile->alpha = 1;\n          alpha_done = 1;\n          if(profile->bits < 8) profile->bits = 8; /*PNG has no alphachannel modes with less than 8-bit per channel*/\n        }\n        else if(a == 0 && !profile->alpha && !profile->key)\n        {\n          profile->key = 1;\n          profile->key_r = r;\n          profile->key_g = g;\n          profile->key_b = b;\n        }\n        else if(a == 255 && profile->key && matchkey)\n        {\n          /* Color key cannot be used if an opaque pixel also has that RGB color. */\n          profile->alpha = 1;\n          alpha_done = 1;\n          if(profile->bits < 8) profile->bits = 8; /*PNG has no alphachannel modes with less than 8-bit per channel*/\n        }\n      }\n\n      if(!numcolors_done)\n      {\n        if(!color_tree_has(&tree, r, g, b, a))\n        {\n          color_tree_add(&tree, r, g, b, a, profile->numcolors);\n          if(profile->numcolors < 256)\n          {\n            unsigned char* p = profile->palette;\n            unsigned n = profile->numcolors;\n            p[n * 4 + 0] = r;\n            p[n * 4 + 1] = g;\n            p[n * 4 + 2] = b;\n            p[n * 4 + 3] = a;\n          }\n          ++profile->numcolors;\n          numcolors_done = profile->numcolors >= maxnumcolors;\n        }\n      }\n\n      if(alpha_done && numcolors_done && colored_done && bits_done) break;\n    }\n\n    if(profile->key && !profile->alpha)\n    {\n      for(i = 0; i != numpixels; ++i)\n      {\n        getPixelColorRGBA8(&r, &g, &b, &a, in, i, mode);\n        if(a != 0 && r == profile->key_r && g == profile->key_g && b == profile->key_b)\n        {\n          /* Color key cannot be used if an opaque pixel also has that RGB color. */\n          profile->alpha = 1;\n          alpha_done = 1;\n        }\n      }\n    }\n\n    /*make the profile's key always 16-bit for consistency - repeat each byte twice*/\n    profile->key_r += (profile->key_r << 8);\n    profile->key_g += (profile->key_g << 8);\n    profile->key_b += (profile->key_b << 8);\n  }\n\n  color_tree_cleanup(&tree);\n  return error;\n}\n\n/*Automatically chooses color type that gives smallest amount of bits in the\noutput image, e.g. grey if there are only greyscale pixels, palette if there\nare less than 256 colors, ...\nUpdates values of mode with a potentially smaller color model. mode_out should\ncontain the user chosen color model, but will be overwritten with the new chosen one.*/\nunsigned lodepng_auto_choose_color(LodePNGColorMode* mode_out,\n                                   const unsigned char* image, unsigned w, unsigned h,\n                                   const LodePNGColorMode* mode_in)\n{\n  LodePNGColorProfile prof;\n  unsigned error = 0;\n  unsigned i, n, palettebits, grey_ok, palette_ok;\n\n  lodepng_color_profile_init(&prof);\n  error = lodepng_get_color_profile(&prof, image, w, h, mode_in);\n  if(error) return error;\n  mode_out->key_defined = 0;\n\n  if(prof.key && w * h <= 16)\n  {\n    prof.alpha = 1; /*too few pixels to justify tRNS chunk overhead*/\n    if(prof.bits < 8) prof.bits = 8; /*PNG has no alphachannel modes with less than 8-bit per channel*/\n  }\n  grey_ok = !prof.colored && !prof.alpha; /*grey without alpha, with potentially low bits*/\n  n = prof.numcolors;\n  palettebits = n <= 2 ? 1 : (n <= 4 ? 2 : (n <= 16 ? 4 : 8));\n  palette_ok = n <= 256 && (n * 2 < w * h) && prof.bits <= 8;\n  if(w * h < n * 2) palette_ok = 0; /*don't add palette overhead if image has only a few pixels*/\n  if(grey_ok && prof.bits <= palettebits) palette_ok = 0; /*grey is less overhead*/\n\n  if(palette_ok)\n  {\n    unsigned char* p = prof.palette;\n    lodepng_palette_clear(mode_out); /*remove potential earlier palette*/\n    for(i = 0; i != prof.numcolors; ++i)\n    {\n      error = lodepng_palette_add(mode_out, p[i * 4 + 0], p[i * 4 + 1], p[i * 4 + 2], p[i * 4 + 3]);\n      if(error) break;\n    }\n\n    mode_out->colortype = LCT_PALETTE;\n    mode_out->bitdepth = palettebits;\n\n    if(mode_in->colortype == LCT_PALETTE && mode_in->palettesize >= mode_out->palettesize\n        && mode_in->bitdepth == mode_out->bitdepth)\n    {\n      /*If input should have same palette colors, keep original to preserve its order and prevent conversion*/\n      lodepng_color_mode_cleanup(mode_out);\n      lodepng_color_mode_copy(mode_out, mode_in);\n    }\n  }\n  else /*8-bit or 16-bit per channel*/\n  {\n    mode_out->bitdepth = prof.bits;\n    mode_out->colortype = prof.alpha ? (prof.colored ? LCT_RGBA : LCT_GREY_ALPHA)\n                                     : (prof.colored ? LCT_RGB : LCT_GREY);\n\n    if(prof.key && !prof.alpha)\n    {\n      unsigned mask = (1u << mode_out->bitdepth) - 1u; /*profile always uses 16-bit, mask converts it*/\n      mode_out->key_r = prof.key_r & mask;\n      mode_out->key_g = prof.key_g & mask;\n      mode_out->key_b = prof.key_b & mask;\n      mode_out->key_defined = 1;\n    }\n  }\n\n  return error;\n}\n\n#endif /* #ifdef LODEPNG_COMPILE_ENCODER */\n\n/*\nPaeth predicter, used by PNG filter type 4\nThe parameters are of type short, but should come from unsigned chars, the shorts\nare only needed to make the paeth calculation correct.\n*/\nstatic unsigned char paethPredictor(short a, short b, short c)\n{\n  short pa = abs(b - c);\n  short pb = abs(a - c);\n  short pc = abs(a + b - c - c);\n\n  if(pc < pa && pc < pb) return (unsigned char)c;\n  else if(pb < pa) return (unsigned char)b;\n  else return (unsigned char)a;\n}\n\n/*shared values used by multiple Adam7 related functions*/\n\nstatic const unsigned ADAM7_IX[7] = { 0, 4, 0, 2, 0, 1, 0 }; /*x start values*/\nstatic const unsigned ADAM7_IY[7] = { 0, 0, 4, 0, 2, 0, 1 }; /*y start values*/\nstatic const unsigned ADAM7_DX[7] = { 8, 8, 4, 4, 2, 2, 1 }; /*x delta values*/\nstatic const unsigned ADAM7_DY[7] = { 8, 8, 8, 4, 4, 2, 2 }; /*y delta values*/\n\n/*\nOutputs various dimensions and positions in the image related to the Adam7 reduced images.\npassw: output containing the width of the 7 passes\npassh: output containing the height of the 7 passes\nfilter_passstart: output containing the index of the start and end of each\n reduced image with filter bytes\npadded_passstart output containing the index of the start and end of each\n reduced image when without filter bytes but with padded scanlines\npassstart: output containing the index of the start and end of each reduced\n image without padding between scanlines, but still padding between the images\nw, h: width and height of non-interlaced image\nbpp: bits per pixel\n\"padded\" is only relevant if bpp is less than 8 and a scanline or image does not\n end at a full byte\n*/\nstatic void Adam7_getpassvalues(unsigned passw[7], unsigned passh[7], size_t filter_passstart[8],\n                                size_t padded_passstart[8], size_t passstart[8], unsigned w, unsigned h, unsigned bpp)\n{\n  /*the passstart values have 8 values: the 8th one indicates the byte after the end of the 7th (= last) pass*/\n  unsigned i;\n\n  /*calculate width and height in pixels of each pass*/\n  for(i = 0; i != 7; ++i)\n  {\n    passw[i] = (w + ADAM7_DX[i] - ADAM7_IX[i] - 1) / ADAM7_DX[i];\n    passh[i] = (h + ADAM7_DY[i] - ADAM7_IY[i] - 1) / ADAM7_DY[i];\n    if(passw[i] == 0) passh[i] = 0;\n    if(passh[i] == 0) passw[i] = 0;\n  }\n\n  filter_passstart[0] = padded_passstart[0] = passstart[0] = 0;\n  for(i = 0; i != 7; ++i)\n  {\n    /*if passw[i] is 0, it's 0 bytes, not 1 (no filtertype-byte)*/\n    filter_passstart[i + 1] = filter_passstart[i]\n                            + ((passw[i] && passh[i]) ? passh[i] * (1 + (passw[i] * bpp + 7) / 8) : 0);\n    /*bits padded if needed to fill full byte at end of each scanline*/\n    padded_passstart[i + 1] = padded_passstart[i] + passh[i] * ((passw[i] * bpp + 7) / 8);\n    /*only padded at end of reduced image*/\n    passstart[i + 1] = passstart[i] + (passh[i] * passw[i] * bpp + 7) / 8;\n  }\n}\n\n#ifdef LODEPNG_COMPILE_DECODER\n\n/* ////////////////////////////////////////////////////////////////////////// */\n/* / PNG Decoder                                                            / */\n/* ////////////////////////////////////////////////////////////////////////// */\n\n/*read the information from the header and store it in the LodePNGInfo. return value is error*/\nunsigned lodepng_inspect(unsigned* w, unsigned* h, LodePNGState* state,\n                         const unsigned char* in, size_t insize)\n{\n  LodePNGInfo* info = &state->info_png;\n  if(insize == 0 || in == 0)\n  {\n    CERROR_RETURN_ERROR(state->error, 48); /*error: the given data is empty*/\n  }\n  if(insize < 33)\n  {\n    CERROR_RETURN_ERROR(state->error, 27); /*error: the data length is smaller than the length of a PNG header*/\n  }\n\n  /*when decoding a new PNG image, make sure all parameters created after previous decoding are reset*/\n  lodepng_info_cleanup(info);\n  lodepng_info_init(info);\n\n  if(in[0] != 137 || in[1] != 80 || in[2] != 78 || in[3] != 71\n     || in[4] != 13 || in[5] != 10 || in[6] != 26 || in[7] != 10)\n  {\n    CERROR_RETURN_ERROR(state->error, 28); /*error: the first 8 bytes are not the correct PNG signature*/\n  }\n  if(lodepng_chunk_length(in + 8) != 13)\n  {\n    CERROR_RETURN_ERROR(state->error, 94); /*error: header size must be 13 bytes*/\n  }\n  if(!lodepng_chunk_type_equals(in + 8, \"IHDR\"))\n  {\n    CERROR_RETURN_ERROR(state->error, 29); /*error: it doesn't start with a IHDR chunk!*/\n  }\n\n  /*read the values given in the header*/\n  *w = lodepng_read32bitInt(&in[16]);\n  *h = lodepng_read32bitInt(&in[20]);\n  info->color.bitdepth = in[24];\n  info->color.colortype = (LodePNGColorType)in[25];\n  info->compression_method = in[26];\n  info->filter_method = in[27];\n  info->interlace_method = in[28];\n\n  if(*w == 0 || *h == 0)\n  {\n    CERROR_RETURN_ERROR(state->error, 93);\n  }\n\n  if(!state->decoder.ignore_crc)\n  {\n    unsigned CRC = lodepng_read32bitInt(&in[29]);\n    unsigned checksum = lodepng_crc32(&in[12], 17);\n    if(CRC != checksum)\n    {\n      CERROR_RETURN_ERROR(state->error, 57); /*invalid CRC*/\n    }\n  }\n\n  /*error: only compression method 0 is allowed in the specification*/\n  if(info->compression_method != 0) CERROR_RETURN_ERROR(state->error, 32);\n  /*error: only filter method 0 is allowed in the specification*/\n  if(info->filter_method != 0) CERROR_RETURN_ERROR(state->error, 33);\n  /*error: only interlace methods 0 and 1 exist in the specification*/\n  if(info->interlace_method > 1) CERROR_RETURN_ERROR(state->error, 34);\n\n  state->error = checkColorValidity(info->color.colortype, info->color.bitdepth);\n  return state->error;\n}\n\nstatic unsigned unfilterScanline(unsigned char* recon, const unsigned char* scanline, const unsigned char* precon,\n                                 size_t bytewidth, unsigned char filterType, size_t length)\n{\n  /*\n  For PNG filter method 0\n  unfilter a PNG image scanline by scanline. when the pixels are smaller than 1 byte,\n  the filter works byte per byte (bytewidth = 1)\n  precon is the previous unfiltered scanline, recon the result, scanline the current one\n  the incoming scanlines do NOT include the filtertype byte, that one is given in the parameter filterType instead\n  recon and scanline MAY be the same memory address! precon must be disjoint.\n  */\n\n  size_t i;\n  switch(filterType)\n  {\n    case 0:\n      for(i = 0; i != length; ++i) recon[i] = scanline[i];\n      break;\n    case 1:\n      for(i = 0; i != bytewidth; ++i) recon[i] = scanline[i];\n      for(i = bytewidth; i < length; ++i) recon[i] = scanline[i] + recon[i - bytewidth];\n      break;\n    case 2:\n      if(precon)\n      {\n        for(i = 0; i != length; ++i) recon[i] = scanline[i] + precon[i];\n      }\n      else\n      {\n        for(i = 0; i != length; ++i) recon[i] = scanline[i];\n      }\n      break;\n    case 3:\n      if(precon)\n      {\n        for(i = 0; i != bytewidth; ++i) recon[i] = scanline[i] + (precon[i] >> 1);\n        for(i = bytewidth; i < length; ++i) recon[i] = scanline[i] + ((recon[i - bytewidth] + precon[i]) >> 1);\n      }\n      else\n      {\n        for(i = 0; i != bytewidth; ++i) recon[i] = scanline[i];\n        for(i = bytewidth; i < length; ++i) recon[i] = scanline[i] + (recon[i - bytewidth] >> 1);\n      }\n      break;\n    case 4:\n      if(precon)\n      {\n        for(i = 0; i != bytewidth; ++i)\n        {\n          recon[i] = (scanline[i] + precon[i]); /*paethPredictor(0, precon[i], 0) is always precon[i]*/\n        }\n        for(i = bytewidth; i < length; ++i)\n        {\n          recon[i] = (scanline[i] + paethPredictor(recon[i - bytewidth], precon[i], precon[i - bytewidth]));\n        }\n      }\n      else\n      {\n        for(i = 0; i != bytewidth; ++i)\n        {\n          recon[i] = scanline[i];\n        }\n        for(i = bytewidth; i < length; ++i)\n        {\n          /*paethPredictor(recon[i - bytewidth], 0, 0) is always recon[i - bytewidth]*/\n          recon[i] = (scanline[i] + recon[i - bytewidth]);\n        }\n      }\n      break;\n    default: return 36; /*error: unexisting filter type given*/\n  }\n  return 0;\n}\n\nstatic unsigned unfilter(unsigned char* out, const unsigned char* in, unsigned w, unsigned h, unsigned bpp)\n{\n  /*\n  For PNG filter method 0\n  this function unfilters a single image (e.g. without interlacing this is called once, with Adam7 seven times)\n  out must have enough bytes allocated already, in must have the scanlines + 1 filtertype byte per scanline\n  w and h are image dimensions or dimensions of reduced image, bpp is bits per pixel\n  in and out are allowed to be the same memory address (but aren't the same size since in has the extra filter bytes)\n  */\n\n  unsigned y;\n  unsigned char* prevline = 0;\n\n  /*bytewidth is used for filtering, is 1 when bpp < 8, number of bytes per pixel otherwise*/\n  size_t bytewidth = (bpp + 7) / 8;\n  size_t linebytes = (w * bpp + 7) / 8;\n\n  for(y = 0; y < h; ++y)\n  {\n    size_t outindex = linebytes * y;\n    size_t inindex = (1 + linebytes) * y; /*the extra filterbyte added to each row*/\n    unsigned char filterType = in[inindex];\n\n    CERROR_TRY_RETURN(unfilterScanline(&out[outindex], &in[inindex + 1], prevline, bytewidth, filterType, linebytes));\n\n    prevline = &out[outindex];\n  }\n\n  return 0;\n}\n\n/*\nin: Adam7 interlaced image, with no padding bits between scanlines, but between\n reduced images so that each reduced image starts at a byte.\nout: the same pixels, but re-ordered so that they're now a non-interlaced image with size w*h\nbpp: bits per pixel\nout has the following size in bits: w * h * bpp.\nin is possibly bigger due to padding bits between reduced images.\nout must be big enough AND must be 0 everywhere if bpp < 8 in the current implementation\n(because that's likely a little bit faster)\nNOTE: comments about padding bits are only relevant if bpp < 8\n*/\nstatic void Adam7_deinterlace(unsigned char* out, const unsigned char* in, unsigned w, unsigned h, unsigned bpp)\n{\n  unsigned passw[7], passh[7];\n  size_t filter_passstart[8], padded_passstart[8], passstart[8];\n  unsigned i;\n\n  Adam7_getpassvalues(passw, passh, filter_passstart, padded_passstart, passstart, w, h, bpp);\n\n  if(bpp >= 8)\n  {\n    for(i = 0; i != 7; ++i)\n    {\n      unsigned x, y, b;\n      size_t bytewidth = bpp / 8;\n      for(y = 0; y < passh[i]; ++y)\n      for(x = 0; x < passw[i]; ++x)\n      {\n        size_t pixelinstart = passstart[i] + (y * passw[i] + x) * bytewidth;\n        size_t pixeloutstart = ((ADAM7_IY[i] + y * ADAM7_DY[i]) * w + ADAM7_IX[i] + x * ADAM7_DX[i]) * bytewidth;\n        for(b = 0; b < bytewidth; ++b)\n        {\n          out[pixeloutstart + b] = in[pixelinstart + b];\n        }\n      }\n    }\n  }\n  else /*bpp < 8: Adam7 with pixels < 8 bit is a bit trickier: with bit pointers*/\n  {\n    for(i = 0; i != 7; ++i)\n    {\n      unsigned x, y, b;\n      unsigned ilinebits = bpp * passw[i];\n      unsigned olinebits = bpp * w;\n      size_t obp, ibp; /*bit pointers (for out and in buffer)*/\n      for(y = 0; y < passh[i]; ++y)\n      for(x = 0; x < passw[i]; ++x)\n      {\n        ibp = (8 * passstart[i]) + (y * ilinebits + x * bpp);\n        obp = (ADAM7_IY[i] + y * ADAM7_DY[i]) * olinebits + (ADAM7_IX[i] + x * ADAM7_DX[i]) * bpp;\n        for(b = 0; b < bpp; ++b)\n        {\n          unsigned char bit = readBitFromReversedStream(&ibp, in);\n          /*note that this function assumes the out buffer is completely 0, use setBitOfReversedStream otherwise*/\n          setBitOfReversedStream0(&obp, out, bit);\n        }\n      }\n    }\n  }\n}\n\nstatic void removePaddingBits(unsigned char* out, const unsigned char* in,\n                              size_t olinebits, size_t ilinebits, unsigned h)\n{\n  /*\n  After filtering there are still padding bits if scanlines have non multiple of 8 bit amounts. They need\n  to be removed (except at last scanline of (Adam7-reduced) image) before working with pure image buffers\n  for the Adam7 code, the color convert code and the output to the user.\n  in and out are allowed to be the same buffer, in may also be higher but still overlapping; in must\n  have >= ilinebits*h bits, out must have >= olinebits*h bits, olinebits must be <= ilinebits\n  also used to move bits after earlier such operations happened, e.g. in a sequence of reduced images from Adam7\n  only useful if (ilinebits - olinebits) is a value in the range 1..7\n  */\n  unsigned y;\n  size_t diff = ilinebits - olinebits;\n  size_t ibp = 0, obp = 0; /*input and output bit pointers*/\n  for(y = 0; y < h; ++y)\n  {\n    size_t x;\n    for(x = 0; x < olinebits; ++x)\n    {\n      unsigned char bit = readBitFromReversedStream(&ibp, in);\n      setBitOfReversedStream(&obp, out, bit);\n    }\n    ibp += diff;\n  }\n}\n\n/*out must be buffer big enough to contain full image, and in must contain the full decompressed data from\nthe IDAT chunks (with filter index bytes and possible padding bits)\nreturn value is error*/\nstatic unsigned postProcessScanlines(unsigned char* out, unsigned char* in,\n                                     unsigned w, unsigned h, const LodePNGInfo* info_png)\n{\n  /*\n  This function converts the filtered-padded-interlaced data into pure 2D image buffer with the PNG's colortype.\n  Steps:\n  *) if no Adam7: 1) unfilter 2) remove padding bits (= posible extra bits per scanline if bpp < 8)\n  *) if adam7: 1) 7x unfilter 2) 7x remove padding bits 3) Adam7_deinterlace\n  NOTE: the in buffer will be overwritten with intermediate data!\n  */\n  unsigned bpp = lodepng_get_bpp(&info_png->color);\n  if(bpp == 0) return 31; /*error: invalid colortype*/\n\n  if(info_png->interlace_method == 0)\n  {\n    if(bpp < 8 && w * bpp != ((w * bpp + 7) / 8) * 8)\n    {\n      CERROR_TRY_RETURN(unfilter(in, in, w, h, bpp));\n      removePaddingBits(out, in, w * bpp, ((w * bpp + 7) / 8) * 8, h);\n    }\n    /*we can immediately filter into the out buffer, no other steps needed*/\n    else CERROR_TRY_RETURN(unfilter(out, in, w, h, bpp));\n  }\n  else /*interlace_method is 1 (Adam7)*/\n  {\n    unsigned passw[7], passh[7]; size_t filter_passstart[8], padded_passstart[8], passstart[8];\n    unsigned i;\n\n    Adam7_getpassvalues(passw, passh, filter_passstart, padded_passstart, passstart, w, h, bpp);\n\n    for(i = 0; i != 7; ++i)\n    {\n      CERROR_TRY_RETURN(unfilter(&in[padded_passstart[i]], &in[filter_passstart[i]], passw[i], passh[i], bpp));\n      /*TODO: possible efficiency improvement: if in this reduced image the bits fit nicely in 1 scanline,\n      move bytes instead of bits or move not at all*/\n      if(bpp < 8)\n      {\n        /*remove padding bits in scanlines; after this there still may be padding\n        bits between the different reduced images: each reduced image still starts nicely at a byte*/\n        removePaddingBits(&in[passstart[i]], &in[padded_passstart[i]], passw[i] * bpp,\n                          ((passw[i] * bpp + 7) / 8) * 8, passh[i]);\n      }\n    }\n\n    Adam7_deinterlace(out, in, w, h, bpp);\n  }\n\n  return 0;\n}\n\nstatic unsigned readChunk_PLTE(LodePNGColorMode* color, const unsigned char* data, size_t chunkLength)\n{\n  unsigned pos = 0, i;\n  if(color->palette) lodepng_free(color->palette);\n  color->palettesize = chunkLength / 3;\n  color->palette = (unsigned char*)lodepng_malloc(4 * color->palettesize);\n  if(!color->palette && color->palettesize)\n  {\n    color->palettesize = 0;\n    return 83; /*alloc fail*/\n  }\n  if(color->palettesize > 256) return 38; /*error: palette too big*/\n\n  for(i = 0; i != color->palettesize; ++i)\n  {\n    color->palette[4 * i + 0] = data[pos++]; /*R*/\n    color->palette[4 * i + 1] = data[pos++]; /*G*/\n    color->palette[4 * i + 2] = data[pos++]; /*B*/\n    color->palette[4 * i + 3] = 255; /*alpha*/\n  }\n\n  return 0; /* OK */\n}\n\nstatic unsigned readChunk_tRNS(LodePNGColorMode* color, const unsigned char* data, size_t chunkLength)\n{\n  unsigned i;\n  if(color->colortype == LCT_PALETTE)\n  {\n    /*error: more alpha values given than there are palette entries*/\n    if(chunkLength > color->palettesize) return 38;\n\n    for(i = 0; i != chunkLength; ++i) color->palette[4 * i + 3] = data[i];\n  }\n  else if(color->colortype == LCT_GREY)\n  {\n    /*error: this chunk must be 2 bytes for greyscale image*/\n    if(chunkLength != 2) return 30;\n\n    color->key_defined = 1;\n    color->key_r = color->key_g = color->key_b = 256u * data[0] + data[1];\n  }\n  else if(color->colortype == LCT_RGB)\n  {\n    /*error: this chunk must be 6 bytes for RGB image*/\n    if(chunkLength != 6) return 41;\n\n    color->key_defined = 1;\n    color->key_r = 256u * data[0] + data[1];\n    color->key_g = 256u * data[2] + data[3];\n    color->key_b = 256u * data[4] + data[5];\n  }\n  else return 42; /*error: tRNS chunk not allowed for other color models*/\n\n  return 0; /* OK */\n}\n\n\n#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS\n/*background color chunk (bKGD)*/\nstatic unsigned readChunk_bKGD(LodePNGInfo* info, const unsigned char* data, size_t chunkLength)\n{\n  if(info->color.colortype == LCT_PALETTE)\n  {\n    /*error: this chunk must be 1 byte for indexed color image*/\n    if(chunkLength != 1) return 43;\n\n    info->background_defined = 1;\n    info->background_r = info->background_g = info->background_b = data[0];\n  }\n  else if(info->color.colortype == LCT_GREY || info->color.colortype == LCT_GREY_ALPHA)\n  {\n    /*error: this chunk must be 2 bytes for greyscale image*/\n    if(chunkLength != 2) return 44;\n\n    info->background_defined = 1;\n    info->background_r = info->background_g = info->background_b = 256u * data[0] + data[1];\n  }\n  else if(info->color.colortype == LCT_RGB || info->color.colortype == LCT_RGBA)\n  {\n    /*error: this chunk must be 6 bytes for greyscale image*/\n    if(chunkLength != 6) return 45;\n\n    info->background_defined = 1;\n    info->background_r = 256u * data[0] + data[1];\n    info->background_g = 256u * data[2] + data[3];\n    info->background_b = 256u * data[4] + data[5];\n  }\n\n  return 0; /* OK */\n}\n\n/*text chunk (tEXt)*/\nstatic unsigned readChunk_tEXt(LodePNGInfo* info, const unsigned char* data, size_t chunkLength)\n{\n  unsigned error = 0;\n  char *key = 0, *str = 0;\n  unsigned i;\n\n  while(!error) /*not really a while loop, only used to break on error*/\n  {\n    unsigned length, string2_begin;\n\n    length = 0;\n    while(length < chunkLength && data[length] != 0) ++length;\n    /*even though it's not allowed by the standard, no error is thrown if\n    there's no null termination char, if the text is empty*/\n    if(length < 1 || length > 79) CERROR_BREAK(error, 89); /*keyword too short or long*/\n\n    key = (char*)lodepng_malloc(length + 1);\n    if(!key) CERROR_BREAK(error, 83); /*alloc fail*/\n\n    key[length] = 0;\n    for(i = 0; i != length; ++i) key[i] = (char)data[i];\n\n    string2_begin = length + 1; /*skip keyword null terminator*/\n\n    length = chunkLength < string2_begin ? 0 : chunkLength - string2_begin;\n    str = (char*)lodepng_malloc(length + 1);\n    if(!str) CERROR_BREAK(error, 83); /*alloc fail*/\n\n    str[length] = 0;\n    for(i = 0; i != length; ++i) str[i] = (char)data[string2_begin + i];\n\n    error = lodepng_add_text(info, key, str);\n\n    break;\n  }\n\n  lodepng_free(key);\n  lodepng_free(str);\n\n  return error;\n}\n\n/*compressed text chunk (zTXt)*/\nstatic unsigned readChunk_zTXt(LodePNGInfo* info, const LodePNGDecompressSettings* zlibsettings,\n                               const unsigned char* data, size_t chunkLength)\n{\n  unsigned error = 0;\n  unsigned i;\n\n  unsigned length, string2_begin;\n  char *key = 0;\n  ucvector decoded;\n\n  ucvector_init(&decoded);\n\n  while(!error) /*not really a while loop, only used to break on error*/\n  {\n    for(length = 0; length < chunkLength && data[length] != 0; ++length) ;\n    if(length + 2 >= chunkLength) CERROR_BREAK(error, 75); /*no null termination, corrupt?*/\n    if(length < 1 || length > 79) CERROR_BREAK(error, 89); /*keyword too short or long*/\n\n    key = (char*)lodepng_malloc(length + 1);\n    if(!key) CERROR_BREAK(error, 83); /*alloc fail*/\n\n    key[length] = 0;\n    for(i = 0; i != length; ++i) key[i] = (char)data[i];\n\n    if(data[length + 1] != 0) CERROR_BREAK(error, 72); /*the 0 byte indicating compression must be 0*/\n\n    string2_begin = length + 2;\n    if(string2_begin > chunkLength) CERROR_BREAK(error, 75); /*no null termination, corrupt?*/\n\n    length = chunkLength - string2_begin;\n    /*will fail if zlib error, e.g. if length is too small*/\n    error = zlib_decompress(&decoded.data, &decoded.size,\n                            (unsigned char*)(&data[string2_begin]),\n                            length, zlibsettings);\n    if(error) break;\n    ucvector_push_back(&decoded, 0);\n\n    error = lodepng_add_text(info, key, (char*)decoded.data);\n\n    break;\n  }\n\n  lodepng_free(key);\n  ucvector_cleanup(&decoded);\n\n  return error;\n}\n\n/*international text chunk (iTXt)*/\nstatic unsigned readChunk_iTXt(LodePNGInfo* info, const LodePNGDecompressSettings* zlibsettings,\n                               const unsigned char* data, size_t chunkLength)\n{\n  unsigned error = 0;\n  unsigned i;\n\n  unsigned length, begin, compressed;\n  char *key = 0, *langtag = 0, *transkey = 0;\n  ucvector decoded;\n  ucvector_init(&decoded);\n\n  while(!error) /*not really a while loop, only used to break on error*/\n  {\n    /*Quick check if the chunk length isn't too small. Even without check\n    it'd still fail with other error checks below if it's too short. This just gives a different error code.*/\n    if(chunkLength < 5) CERROR_BREAK(error, 30); /*iTXt chunk too short*/\n\n    /*read the key*/\n    for(length = 0; length < chunkLength && data[length] != 0; ++length) ;\n    if(length + 3 >= chunkLength) CERROR_BREAK(error, 75); /*no null termination char, corrupt?*/\n    if(length < 1 || length > 79) CERROR_BREAK(error, 89); /*keyword too short or long*/\n\n    key = (char*)lodepng_malloc(length + 1);\n    if(!key) CERROR_BREAK(error, 83); /*alloc fail*/\n\n    key[length] = 0;\n    for(i = 0; i != length; ++i) key[i] = (char)data[i];\n\n    /*read the compression method*/\n    compressed = data[length + 1];\n    if(data[length + 2] != 0) CERROR_BREAK(error, 72); /*the 0 byte indicating compression must be 0*/\n\n    /*even though it's not allowed by the standard, no error is thrown if\n    there's no null termination char, if the text is empty for the next 3 texts*/\n\n    /*read the langtag*/\n    begin = length + 3;\n    length = 0;\n    for(i = begin; i < chunkLength && data[i] != 0; ++i) ++length;\n\n    langtag = (char*)lodepng_malloc(length + 1);\n    if(!langtag) CERROR_BREAK(error, 83); /*alloc fail*/\n\n    langtag[length] = 0;\n    for(i = 0; i != length; ++i) langtag[i] = (char)data[begin + i];\n\n    /*read the transkey*/\n    begin += length + 1;\n    length = 0;\n    for(i = begin; i < chunkLength && data[i] != 0; ++i) ++length;\n\n    transkey = (char*)lodepng_malloc(length + 1);\n    if(!transkey) CERROR_BREAK(error, 83); /*alloc fail*/\n\n    transkey[length] = 0;\n    for(i = 0; i != length; ++i) transkey[i] = (char)data[begin + i];\n\n    /*read the actual text*/\n    begin += length + 1;\n\n    length = chunkLength < begin ? 0 : chunkLength - begin;\n\n    if(compressed)\n    {\n      /*will fail if zlib error, e.g. if length is too small*/\n      error = zlib_decompress(&decoded.data, &decoded.size,\n                              (unsigned char*)(&data[begin]),\n                              length, zlibsettings);\n      if(error) break;\n      if(decoded.allocsize < decoded.size) decoded.allocsize = decoded.size;\n      ucvector_push_back(&decoded, 0);\n    }\n    else\n    {\n      if(!ucvector_resize(&decoded, length + 1)) CERROR_BREAK(error, 83 /*alloc fail*/);\n\n      decoded.data[length] = 0;\n      for(i = 0; i != length; ++i) decoded.data[i] = data[begin + i];\n    }\n\n    error = lodepng_add_itext(info, key, langtag, transkey, (char*)decoded.data);\n\n    break;\n  }\n\n  lodepng_free(key);\n  lodepng_free(langtag);\n  lodepng_free(transkey);\n  ucvector_cleanup(&decoded);\n\n  return error;\n}\n\nstatic unsigned readChunk_tIME(LodePNGInfo* info, const unsigned char* data, size_t chunkLength)\n{\n  if(chunkLength != 7) return 73; /*invalid tIME chunk size*/\n\n  info->time_defined = 1;\n  info->time.year = 256u * data[0] + data[1];\n  info->time.month = data[2];\n  info->time.day = data[3];\n  info->time.hour = data[4];\n  info->time.minute = data[5];\n  info->time.second = data[6];\n\n  return 0; /* OK */\n}\n\nstatic unsigned readChunk_pHYs(LodePNGInfo* info, const unsigned char* data, size_t chunkLength)\n{\n  if(chunkLength != 9) return 74; /*invalid pHYs chunk size*/\n\n  info->phys_defined = 1;\n  info->phys_x = 16777216u * data[0] + 65536u * data[1] + 256u * data[2] + data[3];\n  info->phys_y = 16777216u * data[4] + 65536u * data[5] + 256u * data[6] + data[7];\n  info->phys_unit = data[8];\n\n  return 0; /* OK */\n}\n#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/\n\n/*read a PNG, the result will be in the same color type as the PNG (hence \"generic\")*/\nstatic void decodeGeneric(unsigned char** out, unsigned* w, unsigned* h,\n                          LodePNGState* state,\n                          const unsigned char* in, size_t insize)\n{\n  unsigned char IEND = 0;\n  const unsigned char* chunk;\n  size_t i;\n  ucvector idat; /*the data from idat chunks*/\n  ucvector scanlines;\n  size_t predict;\n  size_t numpixels;\n  size_t outsize = 0;\n\n  /*for unknown chunk order*/\n  unsigned unknown = 0;\n#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS\n  unsigned critical_pos = 1; /*1 = after IHDR, 2 = after PLTE, 3 = after IDAT*/\n#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/\n\n  /*provide some proper output values if error will happen*/\n  *out = 0;\n\n  state->error = lodepng_inspect(w, h, state, in, insize); /*reads header and resets other parameters in state->info_png*/\n  if(state->error) return;\n\n  numpixels = *w * *h;\n\n  /*multiplication overflow*/\n  if(*h != 0 && numpixels / *h != *w) CERROR_RETURN(state->error, 92);\n  /*multiplication overflow possible further below. Allows up to 2^31-1 pixel\n  bytes with 16-bit RGBA, the rest is room for filter bytes.*/\n  if(numpixels > 268435455) CERROR_RETURN(state->error, 92);\n\n  ucvector_init(&idat);\n  chunk = &in[33]; /*first byte of the first chunk after the header*/\n\n  /*loop through the chunks, ignoring unknown chunks and stopping at IEND chunk.\n  IDAT data is put at the start of the in buffer*/\n  while(!IEND && !state->error)\n  {\n    unsigned chunkLength;\n    const unsigned char* data; /*the data in the chunk*/\n\n    /*error: size of the in buffer too small to contain next chunk*/\n    if((size_t)((chunk - in) + 12) > insize || chunk < in) CERROR_BREAK(state->error, 30);\n\n    /*length of the data of the chunk, excluding the length bytes, chunk type and CRC bytes*/\n    chunkLength = lodepng_chunk_length(chunk);\n    /*error: chunk length larger than the max PNG chunk size*/\n    if(chunkLength > 2147483647) CERROR_BREAK(state->error, 63);\n\n    if((size_t)((chunk - in) + chunkLength + 12) > insize || (chunk + chunkLength + 12) < in)\n    {\n      CERROR_BREAK(state->error, 64); /*error: size of the in buffer too small to contain next chunk*/\n    }\n\n    data = lodepng_chunk_data_const(chunk);\n\n    /*IDAT chunk, containing compressed image data*/\n    if(lodepng_chunk_type_equals(chunk, \"IDAT\"))\n    {\n      size_t oldsize = idat.size;\n      if(!ucvector_resize(&idat, oldsize + chunkLength)) CERROR_BREAK(state->error, 83 /*alloc fail*/);\n      for(i = 0; i != chunkLength; ++i) idat.data[oldsize + i] = data[i];\n#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS\n      critical_pos = 3;\n#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/\n    }\n    /*IEND chunk*/\n    else if(lodepng_chunk_type_equals(chunk, \"IEND\"))\n    {\n      IEND = 1;\n    }\n    /*palette chunk (PLTE)*/\n    else if(lodepng_chunk_type_equals(chunk, \"PLTE\"))\n    {\n      state->error = readChunk_PLTE(&state->info_png.color, data, chunkLength);\n      if(state->error) break;\n#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS\n      critical_pos = 2;\n#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/\n    }\n    /*palette transparency chunk (tRNS)*/\n    else if(lodepng_chunk_type_equals(chunk, \"tRNS\"))\n    {\n      state->error = readChunk_tRNS(&state->info_png.color, data, chunkLength);\n      if(state->error) break;\n    }\n#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS\n    /*background color chunk (bKGD)*/\n    else if(lodepng_chunk_type_equals(chunk, \"bKGD\"))\n    {\n      state->error = readChunk_bKGD(&state->info_png, data, chunkLength);\n      if(state->error) break;\n    }\n    /*text chunk (tEXt)*/\n    else if(lodepng_chunk_type_equals(chunk, \"tEXt\"))\n    {\n      if(state->decoder.read_text_chunks)\n      {\n        state->error = readChunk_tEXt(&state->info_png, data, chunkLength);\n        if(state->error) break;\n      }\n    }\n    /*compressed text chunk (zTXt)*/\n    else if(lodepng_chunk_type_equals(chunk, \"zTXt\"))\n    {\n      if(state->decoder.read_text_chunks)\n      {\n        state->error = readChunk_zTXt(&state->info_png, &state->decoder.zlibsettings, data, chunkLength);\n        if(state->error) break;\n      }\n    }\n    /*international text chunk (iTXt)*/\n    else if(lodepng_chunk_type_equals(chunk, \"iTXt\"))\n    {\n      if(state->decoder.read_text_chunks)\n      {\n        state->error = readChunk_iTXt(&state->info_png, &state->decoder.zlibsettings, data, chunkLength);\n        if(state->error) break;\n      }\n    }\n    else if(lodepng_chunk_type_equals(chunk, \"tIME\"))\n    {\n      state->error = readChunk_tIME(&state->info_png, data, chunkLength);\n      if(state->error) break;\n    }\n    else if(lodepng_chunk_type_equals(chunk, \"pHYs\"))\n    {\n      state->error = readChunk_pHYs(&state->info_png, data, chunkLength);\n      if(state->error) break;\n    }\n#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/\n    else /*it's not an implemented chunk type, so ignore it: skip over the data*/\n    {\n      /*error: unknown critical chunk (5th bit of first byte of chunk type is 0)*/\n      if(!lodepng_chunk_ancillary(chunk)) CERROR_BREAK(state->error, 69);\n\n      unknown = 1;\n#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS\n      if(state->decoder.remember_unknown_chunks)\n      {\n        state->error = lodepng_chunk_append(&state->info_png.unknown_chunks_data[critical_pos - 1],\n                                            &state->info_png.unknown_chunks_size[critical_pos - 1], chunk);\n        if(state->error) break;\n      }\n#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/\n    }\n\n    if(!state->decoder.ignore_crc && !unknown) /*check CRC if wanted, only on known chunk types*/\n    {\n      if(lodepng_chunk_check_crc(chunk)) CERROR_BREAK(state->error, 57); /*invalid CRC*/\n    }\n\n    if(!IEND) chunk = lodepng_chunk_next_const(chunk);\n  }\n\n  ucvector_init(&scanlines);\n  /*predict output size, to allocate exact size for output buffer to avoid more dynamic allocation.\n  If the decompressed size does not match the prediction, the image must be corrupt.*/\n  if(state->info_png.interlace_method == 0)\n  {\n    /*The extra *h is added because this are the filter bytes every scanline starts with*/\n    predict = lodepng_get_raw_size_idat(*w, *h, &state->info_png.color) + *h;\n  }\n  else\n  {\n    /*Adam-7 interlaced: predicted size is the sum of the 7 sub-images sizes*/\n    const LodePNGColorMode* color = &state->info_png.color;\n    predict = 0;\n    predict += lodepng_get_raw_size_idat((*w + 7) >> 3, (*h + 7) >> 3, color) + ((*h + 7) >> 3);\n    if(*w > 4) predict += lodepng_get_raw_size_idat((*w + 3) >> 3, (*h + 7) >> 3, color) + ((*h + 7) >> 3);\n    predict += lodepng_get_raw_size_idat((*w + 3) >> 2, (*h + 3) >> 3, color) + ((*h + 3) >> 3);\n    if(*w > 2) predict += lodepng_get_raw_size_idat((*w + 1) >> 2, (*h + 3) >> 2, color) + ((*h + 3) >> 2);\n    predict += lodepng_get_raw_size_idat((*w + 1) >> 1, (*h + 1) >> 2, color) + ((*h + 1) >> 2);\n    if(*w > 1) predict += lodepng_get_raw_size_idat((*w + 0) >> 1, (*h + 1) >> 1, color) + ((*h + 1) >> 1);\n    predict += lodepng_get_raw_size_idat((*w + 0), (*h + 0) >> 1, color) + ((*h + 0) >> 1);\n  }\n  if(!state->error && !ucvector_reserve(&scanlines, predict)) state->error = 83; /*alloc fail*/\n  if(!state->error)\n  {\n    state->error = zlib_decompress(&scanlines.data, &scanlines.size, idat.data,\n                                   idat.size, &state->decoder.zlibsettings);\n    if(!state->error && scanlines.size != predict) state->error = 91; /*decompressed size doesn't match prediction*/\n  }\n  ucvector_cleanup(&idat);\n\n  if(!state->error)\n  {\n    outsize = lodepng_get_raw_size(*w, *h, &state->info_png.color);\n    *out = (unsigned char*)lodepng_malloc(outsize);\n    if(!*out) state->error = 83; /*alloc fail*/\n  }\n  if(!state->error)\n  {\n    for(i = 0; i < outsize; i++) (*out)[i] = 0;\n    state->error = postProcessScanlines(*out, scanlines.data, *w, *h, &state->info_png);\n  }\n  ucvector_cleanup(&scanlines);\n}\n\nunsigned lodepng_decode(unsigned char** out, unsigned* w, unsigned* h,\n                        LodePNGState* state,\n                        const unsigned char* in, size_t insize)\n{\n  *out = 0;\n  decodeGeneric(out, w, h, state, in, insize);\n  if(state->error) return state->error;\n  if(!state->decoder.color_convert || lodepng_color_mode_equal(&state->info_raw, &state->info_png.color))\n  {\n    /*same color type, no copying or converting of data needed*/\n    /*store the info_png color settings on the info_raw so that the info_raw still reflects what colortype\n    the raw image has to the end user*/\n    if(!state->decoder.color_convert)\n    {\n      state->error = lodepng_color_mode_copy(&state->info_raw, &state->info_png.color);\n      if(state->error) return state->error;\n    }\n  }\n  else\n  {\n    /*color conversion needed; sort of copy of the data*/\n    unsigned char* data = *out;\n    size_t outsize;\n\n    /*TODO: check if this works according to the statement in the documentation: \"The converter can convert\n    from greyscale input color type, to 8-bit greyscale or greyscale with alpha\"*/\n    if(!(state->info_raw.colortype == LCT_RGB || state->info_raw.colortype == LCT_RGBA)\n       && !(state->info_raw.bitdepth == 8))\n    {\n      return 56; /*unsupported color mode conversion*/\n    }\n\n    outsize = lodepng_get_raw_size(*w, *h, &state->info_raw);\n    *out = (unsigned char*)lodepng_malloc(outsize);\n    if(!(*out))\n    {\n      state->error = 83; /*alloc fail*/\n    }\n    else state->error = lodepng_convert(*out, data, &state->info_raw,\n                                        &state->info_png.color, *w, *h);\n    lodepng_free(data);\n  }\n  return state->error;\n}\n\nunsigned lodepng_decode_memory(unsigned char** out, unsigned* w, unsigned* h, const unsigned char* in,\n                               size_t insize, LodePNGColorType colortype, unsigned bitdepth)\n{\n  unsigned error;\n  LodePNGState state;\n  lodepng_state_init(&state);\n  state.info_raw.colortype = colortype;\n  state.info_raw.bitdepth = bitdepth;\n  error = lodepng_decode(out, w, h, &state, in, insize);\n  lodepng_state_cleanup(&state);\n  return error;\n}\n\nunsigned lodepng_decode32(unsigned char** out, unsigned* w, unsigned* h, const unsigned char* in, size_t insize)\n{\n  return lodepng_decode_memory(out, w, h, in, insize, LCT_RGBA, 8);\n}\n\nunsigned lodepng_decode24(unsigned char** out, unsigned* w, unsigned* h, const unsigned char* in, size_t insize)\n{\n  return lodepng_decode_memory(out, w, h, in, insize, LCT_RGB, 8);\n}\n\n#ifdef LODEPNG_COMPILE_DISK\nunsigned lodepng_decode_file(unsigned char** out, unsigned* w, unsigned* h, const char* filename,\n                             LodePNGColorType colortype, unsigned bitdepth)\n{\n  unsigned char* buffer = 0;\n  size_t buffersize;\n  unsigned error;\n  error = lodepng_load_file(&buffer, &buffersize, filename);\n  if(!error) error = lodepng_decode_memory(out, w, h, buffer, buffersize, colortype, bitdepth);\n  lodepng_free(buffer);\n  return error;\n}\n\nunsigned lodepng_decode32_file(unsigned char** out, unsigned* w, unsigned* h, const char* filename)\n{\n  return lodepng_decode_file(out, w, h, filename, LCT_RGBA, 8);\n}\n\nunsigned lodepng_decode24_file(unsigned char** out, unsigned* w, unsigned* h, const char* filename)\n{\n  return lodepng_decode_file(out, w, h, filename, LCT_RGB, 8);\n}\n#endif /*LODEPNG_COMPILE_DISK*/\n\nvoid lodepng_decoder_settings_init(LodePNGDecoderSettings* settings)\n{\n  settings->color_convert = 1;\n#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS\n  settings->read_text_chunks = 1;\n  settings->remember_unknown_chunks = 0;\n#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/\n  settings->ignore_crc = 0;\n  lodepng_decompress_settings_init(&settings->zlibsettings);\n}\n\n#endif /*LODEPNG_COMPILE_DECODER*/\n\n#if defined(LODEPNG_COMPILE_DECODER) || defined(LODEPNG_COMPILE_ENCODER)\n\nvoid lodepng_state_init(LodePNGState* state)\n{\n#ifdef LODEPNG_COMPILE_DECODER\n  lodepng_decoder_settings_init(&state->decoder);\n#endif /*LODEPNG_COMPILE_DECODER*/\n#ifdef LODEPNG_COMPILE_ENCODER\n  lodepng_encoder_settings_init(&state->encoder);\n#endif /*LODEPNG_COMPILE_ENCODER*/\n  lodepng_color_mode_init(&state->info_raw);\n  lodepng_info_init(&state->info_png);\n  state->error = 1;\n}\n\nvoid lodepng_state_cleanup(LodePNGState* state)\n{\n  lodepng_color_mode_cleanup(&state->info_raw);\n  lodepng_info_cleanup(&state->info_png);\n}\n\nvoid lodepng_state_copy(LodePNGState* dest, const LodePNGState* source)\n{\n  lodepng_state_cleanup(dest);\n  *dest = *source;\n  lodepng_color_mode_init(&dest->info_raw);\n  lodepng_info_init(&dest->info_png);\n  dest->error = lodepng_color_mode_copy(&dest->info_raw, &source->info_raw); if(dest->error) return;\n  dest->error = lodepng_info_copy(&dest->info_png, &source->info_png); if(dest->error) return;\n}\n\n#endif /* defined(LODEPNG_COMPILE_DECODER) || defined(LODEPNG_COMPILE_ENCODER) */\n\n#ifdef LODEPNG_COMPILE_ENCODER\n\n/* ////////////////////////////////////////////////////////////////////////// */\n/* / PNG Encoder                                                            / */\n/* ////////////////////////////////////////////////////////////////////////// */\n\n/*chunkName must be string of 4 characters*/\nstatic unsigned addChunk(ucvector* out, const char* chunkName, const unsigned char* data, size_t length)\n{\n  CERROR_TRY_RETURN(lodepng_chunk_create(&out->data, &out->size, (unsigned)length, chunkName, data));\n  out->allocsize = out->size; /*fix the allocsize again*/\n  return 0;\n}\n\nstatic void writeSignature(ucvector* out)\n{\n  /*8 bytes PNG signature, aka the magic bytes*/\n  ucvector_push_back(out, 137);\n  ucvector_push_back(out, 80);\n  ucvector_push_back(out, 78);\n  ucvector_push_back(out, 71);\n  ucvector_push_back(out, 13);\n  ucvector_push_back(out, 10);\n  ucvector_push_back(out, 26);\n  ucvector_push_back(out, 10);\n}\n\nstatic unsigned addChunk_IHDR(ucvector* out, unsigned w, unsigned h,\n                              LodePNGColorType colortype, unsigned bitdepth, unsigned interlace_method)\n{\n  unsigned error = 0;\n  ucvector header;\n  ucvector_init(&header);\n\n  lodepng_add32bitInt(&header, w); /*width*/\n  lodepng_add32bitInt(&header, h); /*height*/\n  ucvector_push_back(&header, (unsigned char)bitdepth); /*bit depth*/\n  ucvector_push_back(&header, (unsigned char)colortype); /*color type*/\n  ucvector_push_back(&header, 0); /*compression method*/\n  ucvector_push_back(&header, 0); /*filter method*/\n  ucvector_push_back(&header, interlace_method); /*interlace method*/\n\n  error = addChunk(out, \"IHDR\", header.data, header.size);\n  ucvector_cleanup(&header);\n\n  return error;\n}\n\nstatic unsigned addChunk_PLTE(ucvector* out, const LodePNGColorMode* info)\n{\n  unsigned error = 0;\n  size_t i;\n  ucvector PLTE;\n  ucvector_init(&PLTE);\n  for(i = 0; i != info->palettesize * 4; ++i)\n  {\n    /*add all channels except alpha channel*/\n    if(i % 4 != 3) ucvector_push_back(&PLTE, info->palette[i]);\n  }\n  error = addChunk(out, \"PLTE\", PLTE.data, PLTE.size);\n  ucvector_cleanup(&PLTE);\n\n  return error;\n}\n\nstatic unsigned addChunk_tRNS(ucvector* out, const LodePNGColorMode* info)\n{\n  unsigned error = 0;\n  size_t i;\n  ucvector tRNS;\n  ucvector_init(&tRNS);\n  if(info->colortype == LCT_PALETTE)\n  {\n    size_t amount = info->palettesize;\n    /*the tail of palette values that all have 255 as alpha, does not have to be encoded*/\n    for(i = info->palettesize; i != 0; --i)\n    {\n      if(info->palette[4 * (i - 1) + 3] == 255) --amount;\n      else break;\n    }\n    /*add only alpha channel*/\n    for(i = 0; i != amount; ++i) ucvector_push_back(&tRNS, info->palette[4 * i + 3]);\n  }\n  else if(info->colortype == LCT_GREY)\n  {\n    if(info->key_defined)\n    {\n      ucvector_push_back(&tRNS, (unsigned char)(info->key_r >> 8));\n      ucvector_push_back(&tRNS, (unsigned char)(info->key_r & 255));\n    }\n  }\n  else if(info->colortype == LCT_RGB)\n  {\n    if(info->key_defined)\n    {\n      ucvector_push_back(&tRNS, (unsigned char)(info->key_r >> 8));\n      ucvector_push_back(&tRNS, (unsigned char)(info->key_r & 255));\n      ucvector_push_back(&tRNS, (unsigned char)(info->key_g >> 8));\n      ucvector_push_back(&tRNS, (unsigned char)(info->key_g & 255));\n      ucvector_push_back(&tRNS, (unsigned char)(info->key_b >> 8));\n      ucvector_push_back(&tRNS, (unsigned char)(info->key_b & 255));\n    }\n  }\n\n  error = addChunk(out, \"tRNS\", tRNS.data, tRNS.size);\n  ucvector_cleanup(&tRNS);\n\n  return error;\n}\n\nstatic unsigned addChunk_IDAT(ucvector* out, const unsigned char* data, size_t datasize,\n                              LodePNGCompressSettings* zlibsettings)\n{\n  ucvector zlibdata;\n  unsigned error = 0;\n\n  /*compress with the Zlib compressor*/\n  ucvector_init(&zlibdata);\n  error = zlib_compress(&zlibdata.data, &zlibdata.size, data, datasize, zlibsettings);\n  if(!error) error = addChunk(out, \"IDAT\", zlibdata.data, zlibdata.size);\n  ucvector_cleanup(&zlibdata);\n\n  return error;\n}\n\nstatic unsigned addChunk_IEND(ucvector* out)\n{\n  unsigned error = 0;\n  error = addChunk(out, \"IEND\", 0, 0);\n  return error;\n}\n\n#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS\n\nstatic unsigned addChunk_tEXt(ucvector* out, const char* keyword, const char* textstring)\n{\n  unsigned error = 0;\n  size_t i;\n  ucvector text;\n  ucvector_init(&text);\n  for(i = 0; keyword[i] != 0; ++i) ucvector_push_back(&text, (unsigned char)keyword[i]);\n  if(i < 1 || i > 79) return 89; /*error: invalid keyword size*/\n  ucvector_push_back(&text, 0); /*0 termination char*/\n  for(i = 0; textstring[i] != 0; ++i) ucvector_push_back(&text, (unsigned char)textstring[i]);\n  error = addChunk(out, \"tEXt\", text.data, text.size);\n  ucvector_cleanup(&text);\n\n  return error;\n}\n\nstatic unsigned addChunk_zTXt(ucvector* out, const char* keyword, const char* textstring,\n                              LodePNGCompressSettings* zlibsettings)\n{\n  unsigned error = 0;\n  ucvector data, compressed;\n  size_t i, textsize = strlen(textstring);\n\n  ucvector_init(&data);\n  ucvector_init(&compressed);\n  for(i = 0; keyword[i] != 0; ++i) ucvector_push_back(&data, (unsigned char)keyword[i]);\n  if(i < 1 || i > 79) return 89; /*error: invalid keyword size*/\n  ucvector_push_back(&data, 0); /*0 termination char*/\n  ucvector_push_back(&data, 0); /*compression method: 0*/\n\n  error = zlib_compress(&compressed.data, &compressed.size,\n                        (unsigned char*)textstring, textsize, zlibsettings);\n  if(!error)\n  {\n    for(i = 0; i != compressed.size; ++i) ucvector_push_back(&data, compressed.data[i]);\n    error = addChunk(out, \"zTXt\", data.data, data.size);\n  }\n\n  ucvector_cleanup(&compressed);\n  ucvector_cleanup(&data);\n  return error;\n}\n\nstatic unsigned addChunk_iTXt(ucvector* out, unsigned compressed, const char* keyword, const char* langtag,\n                              const char* transkey, const char* textstring, LodePNGCompressSettings* zlibsettings)\n{\n  unsigned error = 0;\n  ucvector data;\n  size_t i, textsize = strlen(textstring);\n\n  ucvector_init(&data);\n\n  for(i = 0; keyword[i] != 0; ++i) ucvector_push_back(&data, (unsigned char)keyword[i]);\n  if(i < 1 || i > 79) return 89; /*error: invalid keyword size*/\n  ucvector_push_back(&data, 0); /*null termination char*/\n  ucvector_push_back(&data, compressed ? 1 : 0); /*compression flag*/\n  ucvector_push_back(&data, 0); /*compression method*/\n  for(i = 0; langtag[i] != 0; ++i) ucvector_push_back(&data, (unsigned char)langtag[i]);\n  ucvector_push_back(&data, 0); /*null termination char*/\n  for(i = 0; transkey[i] != 0; ++i) ucvector_push_back(&data, (unsigned char)transkey[i]);\n  ucvector_push_back(&data, 0); /*null termination char*/\n\n  if(compressed)\n  {\n    ucvector compressed_data;\n    ucvector_init(&compressed_data);\n    error = zlib_compress(&compressed_data.data, &compressed_data.size,\n                          (unsigned char*)textstring, textsize, zlibsettings);\n    if(!error)\n    {\n      for(i = 0; i != compressed_data.size; ++i) ucvector_push_back(&data, compressed_data.data[i]);\n    }\n    ucvector_cleanup(&compressed_data);\n  }\n  else /*not compressed*/\n  {\n    for(i = 0; textstring[i] != 0; ++i) ucvector_push_back(&data, (unsigned char)textstring[i]);\n  }\n\n  if(!error) error = addChunk(out, \"iTXt\", data.data, data.size);\n  ucvector_cleanup(&data);\n  return error;\n}\n\nstatic unsigned addChunk_bKGD(ucvector* out, const LodePNGInfo* info)\n{\n  unsigned error = 0;\n  ucvector bKGD;\n  ucvector_init(&bKGD);\n  if(info->color.colortype == LCT_GREY || info->color.colortype == LCT_GREY_ALPHA)\n  {\n    ucvector_push_back(&bKGD, (unsigned char)(info->background_r >> 8));\n    ucvector_push_back(&bKGD, (unsigned char)(info->background_r & 255));\n  }\n  else if(info->color.colortype == LCT_RGB || info->color.colortype == LCT_RGBA)\n  {\n    ucvector_push_back(&bKGD, (unsigned char)(info->background_r >> 8));\n    ucvector_push_back(&bKGD, (unsigned char)(info->background_r & 255));\n    ucvector_push_back(&bKGD, (unsigned char)(info->background_g >> 8));\n    ucvector_push_back(&bKGD, (unsigned char)(info->background_g & 255));\n    ucvector_push_back(&bKGD, (unsigned char)(info->background_b >> 8));\n    ucvector_push_back(&bKGD, (unsigned char)(info->background_b & 255));\n  }\n  else if(info->color.colortype == LCT_PALETTE)\n  {\n    ucvector_push_back(&bKGD, (unsigned char)(info->background_r & 255)); /*palette index*/\n  }\n\n  error = addChunk(out, \"bKGD\", bKGD.data, bKGD.size);\n  ucvector_cleanup(&bKGD);\n\n  return error;\n}\n\nstatic unsigned addChunk_tIME(ucvector* out, const LodePNGTime* time)\n{\n  unsigned error = 0;\n  unsigned char* data = (unsigned char*)lodepng_malloc(7);\n  if(!data) return 83; /*alloc fail*/\n  data[0] = (unsigned char)(time->year >> 8);\n  data[1] = (unsigned char)(time->year & 255);\n  data[2] = (unsigned char)time->month;\n  data[3] = (unsigned char)time->day;\n  data[4] = (unsigned char)time->hour;\n  data[5] = (unsigned char)time->minute;\n  data[6] = (unsigned char)time->second;\n  error = addChunk(out, \"tIME\", data, 7);\n  lodepng_free(data);\n  return error;\n}\n\nstatic unsigned addChunk_pHYs(ucvector* out, const LodePNGInfo* info)\n{\n  unsigned error = 0;\n  ucvector data;\n  ucvector_init(&data);\n\n  lodepng_add32bitInt(&data, info->phys_x);\n  lodepng_add32bitInt(&data, info->phys_y);\n  ucvector_push_back(&data, info->phys_unit);\n\n  error = addChunk(out, \"pHYs\", data.data, data.size);\n  ucvector_cleanup(&data);\n\n  return error;\n}\n\n#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/\n\nstatic void filterScanline(unsigned char* out, const unsigned char* scanline, const unsigned char* prevline,\n                           size_t length, size_t bytewidth, unsigned char filterType)\n{\n  size_t i;\n  switch(filterType)\n  {\n    case 0: /*None*/\n      for(i = 0; i != length; ++i) out[i] = scanline[i];\n      break;\n    case 1: /*Sub*/\n      for(i = 0; i != bytewidth; ++i) out[i] = scanline[i];\n      for(i = bytewidth; i < length; ++i) out[i] = scanline[i] - scanline[i - bytewidth];\n      break;\n    case 2: /*Up*/\n      if(prevline)\n      {\n        for(i = 0; i != length; ++i) out[i] = scanline[i] - prevline[i];\n      }\n      else\n      {\n        for(i = 0; i != length; ++i) out[i] = scanline[i];\n      }\n      break;\n    case 3: /*Average*/\n      if(prevline)\n      {\n        for(i = 0; i != bytewidth; ++i) out[i] = scanline[i] - (prevline[i] >> 1);\n        for(i = bytewidth; i < length; ++i) out[i] = scanline[i] - ((scanline[i - bytewidth] + prevline[i]) >> 1);\n      }\n      else\n      {\n        for(i = 0; i != bytewidth; ++i) out[i] = scanline[i];\n        for(i = bytewidth; i < length; ++i) out[i] = scanline[i] - (scanline[i - bytewidth] >> 1);\n      }\n      break;\n    case 4: /*Paeth*/\n      if(prevline)\n      {\n        /*paethPredictor(0, prevline[i], 0) is always prevline[i]*/\n        for(i = 0; i != bytewidth; ++i) out[i] = (scanline[i] - prevline[i]);\n        for(i = bytewidth; i < length; ++i)\n        {\n          out[i] = (scanline[i] - paethPredictor(scanline[i - bytewidth], prevline[i], prevline[i - bytewidth]));\n        }\n      }\n      else\n      {\n        for(i = 0; i != bytewidth; ++i) out[i] = scanline[i];\n        /*paethPredictor(scanline[i - bytewidth], 0, 0) is always scanline[i - bytewidth]*/\n        for(i = bytewidth; i < length; ++i) out[i] = (scanline[i] - scanline[i - bytewidth]);\n      }\n      break;\n    default: return; /*unexisting filter type given*/\n  }\n}\n\n/* log2 approximation. A slight bit faster than std::log. */\nstatic float flog2(float f)\n{\n  float result = 0;\n  while(f > 32) { result += 4; f /= 16; }\n  while(f > 2) { ++result; f /= 2; }\n  return result + 1.442695f * (f * f * f / 3 - 3 * f * f / 2 + 3 * f - 1.83333f);\n}\n\nstatic unsigned filter(unsigned char* out, const unsigned char* in, unsigned w, unsigned h,\n                       const LodePNGColorMode* info, const LodePNGEncoderSettings* settings)\n{\n  /*\n  For PNG filter method 0\n  out must be a buffer with as size: h + (w * h * bpp + 7) / 8, because there are\n  the scanlines with 1 extra byte per scanline\n  */\n\n  unsigned bpp = lodepng_get_bpp(info);\n  /*the width of a scanline in bytes, not including the filter type*/\n  size_t linebytes = (w * bpp + 7) / 8;\n  /*bytewidth is used for filtering, is 1 when bpp < 8, number of bytes per pixel otherwise*/\n  size_t bytewidth = (bpp + 7) / 8;\n  const unsigned char* prevline = 0;\n  unsigned x, y;\n  unsigned error = 0;\n  LodePNGFilterStrategy strategy = settings->filter_strategy;\n\n  /*\n  There is a heuristic called the minimum sum of absolute differences heuristic, suggested by the PNG standard:\n   *  If the image type is Palette, or the bit depth is smaller than 8, then do not filter the image (i.e.\n      use fixed filtering, with the filter None).\n   * (The other case) If the image type is Grayscale or RGB (with or without Alpha), and the bit depth is\n     not smaller than 8, then use adaptive filtering heuristic as follows: independently for each row, apply\n     all five filters and select the filter that produces the smallest sum of absolute values per row.\n  This heuristic is used if filter strategy is LFS_MINSUM and filter_palette_zero is true.\n\n  If filter_palette_zero is true and filter_strategy is not LFS_MINSUM, the above heuristic is followed,\n  but for \"the other case\", whatever strategy filter_strategy is set to instead of the minimum sum\n  heuristic is used.\n  */\n  if(settings->filter_palette_zero &&\n     (info->colortype == LCT_PALETTE || info->bitdepth < 8)) strategy = LFS_ZERO;\n\n  if(bpp == 0) return 31; /*error: invalid color type*/\n\n  if(strategy == LFS_ZERO)\n  {\n    for(y = 0; y != h; ++y)\n    {\n      size_t outindex = (1 + linebytes) * y; /*the extra filterbyte added to each row*/\n      size_t inindex = linebytes * y;\n      out[outindex] = 0; /*filter type byte*/\n      filterScanline(&out[outindex + 1], &in[inindex], prevline, linebytes, bytewidth, 0);\n      prevline = &in[inindex];\n    }\n  }\n  else if(strategy == LFS_MINSUM)\n  {\n    /*adaptive filtering*/\n    size_t sum[5];\n    unsigned char* attempt[5]; /*five filtering attempts, one for each filter type*/\n    size_t smallest = 0;\n    unsigned char type, bestType = 0;\n\n    for(type = 0; type != 5; ++type)\n    {\n      attempt[type] = (unsigned char*)lodepng_malloc(linebytes);\n      if(!attempt[type]) return 83; /*alloc fail*/\n    }\n\n    if(!error)\n    {\n      for(y = 0; y != h; ++y)\n      {\n        /*try the 5 filter types*/\n        for(type = 0; type != 5; ++type)\n        {\n          filterScanline(attempt[type], &in[y * linebytes], prevline, linebytes, bytewidth, type);\n\n          /*calculate the sum of the result*/\n          sum[type] = 0;\n          if(type == 0)\n          {\n            for(x = 0; x != linebytes; ++x) sum[type] += (unsigned char)(attempt[type][x]);\n          }\n          else\n          {\n            for(x = 0; x != linebytes; ++x)\n            {\n              /*For differences, each byte should be treated as signed, values above 127 are negative\n              (converted to signed char). Filtertype 0 isn't a difference though, so use unsigned there.\n              This means filtertype 0 is almost never chosen, but that is justified.*/\n              unsigned char s = attempt[type][x];\n              sum[type] += s < 128 ? s : (255U - s);\n            }\n          }\n\n          /*check if this is smallest sum (or if type == 0 it's the first case so always store the values)*/\n          if(type == 0 || sum[type] < smallest)\n          {\n            bestType = type;\n            smallest = sum[type];\n          }\n        }\n\n        prevline = &in[y * linebytes];\n\n        /*now fill the out values*/\n        out[y * (linebytes + 1)] = bestType; /*the first byte of a scanline will be the filter type*/\n        for(x = 0; x != linebytes; ++x) out[y * (linebytes + 1) + 1 + x] = attempt[bestType][x];\n      }\n    }\n\n    for(type = 0; type != 5; ++type) lodepng_free(attempt[type]);\n  }\n  else if(strategy == LFS_ENTROPY)\n  {\n    float sum[5];\n    unsigned char* attempt[5]; /*five filtering attempts, one for each filter type*/\n    float smallest = 0;\n    unsigned type, bestType = 0;\n    unsigned count[256];\n\n    for(type = 0; type != 5; ++type)\n    {\n      attempt[type] = (unsigned char*)lodepng_malloc(linebytes);\n      if(!attempt[type]) return 83; /*alloc fail*/\n    }\n\n    for(y = 0; y != h; ++y)\n    {\n      /*try the 5 filter types*/\n      for(type = 0; type != 5; ++type)\n      {\n        filterScanline(attempt[type], &in[y * linebytes], prevline, linebytes, bytewidth, type);\n        for(x = 0; x != 256; ++x) count[x] = 0;\n        for(x = 0; x != linebytes; ++x) ++count[attempt[type][x]];\n        ++count[type]; /*the filter type itself is part of the scanline*/\n        sum[type] = 0;\n        for(x = 0; x != 256; ++x)\n        {\n          float p = count[x] / (float)(linebytes + 1);\n          sum[type] += count[x] == 0 ? 0 : flog2(1 / p) * p;\n        }\n        /*check if this is smallest sum (or if type == 0 it's the first case so always store the values)*/\n        if(type == 0 || sum[type] < smallest)\n        {\n          bestType = type;\n          smallest = sum[type];\n        }\n      }\n\n      prevline = &in[y * linebytes];\n\n      /*now fill the out values*/\n      out[y * (linebytes + 1)] = bestType; /*the first byte of a scanline will be the filter type*/\n      for(x = 0; x != linebytes; ++x) out[y * (linebytes + 1) + 1 + x] = attempt[bestType][x];\n    }\n\n    for(type = 0; type != 5; ++type) lodepng_free(attempt[type]);\n  }\n  else if(strategy == LFS_PREDEFINED)\n  {\n    for(y = 0; y != h; ++y)\n    {\n      size_t outindex = (1 + linebytes) * y; /*the extra filterbyte added to each row*/\n      size_t inindex = linebytes * y;\n      unsigned char type = settings->predefined_filters[y];\n      out[outindex] = type; /*filter type byte*/\n      filterScanline(&out[outindex + 1], &in[inindex], prevline, linebytes, bytewidth, type);\n      prevline = &in[inindex];\n    }\n  }\n  else if(strategy == LFS_BRUTE_FORCE)\n  {\n    /*brute force filter chooser.\n    deflate the scanline after every filter attempt to see which one deflates best.\n    This is very slow and gives only slightly smaller, sometimes even larger, result*/\n    size_t size[5];\n    unsigned char* attempt[5]; /*five filtering attempts, one for each filter type*/\n    size_t smallest = 0;\n    unsigned type = 0, bestType = 0;\n    unsigned char* dummy;\n    LodePNGCompressSettings zlibsettings = settings->zlibsettings;\n    /*use fixed tree on the attempts so that the tree is not adapted to the filtertype on purpose,\n    to simulate the true case where the tree is the same for the whole image. Sometimes it gives\n    better result with dynamic tree anyway. Using the fixed tree sometimes gives worse, but in rare\n    cases better compression. It does make this a bit less slow, so it's worth doing this.*/\n    zlibsettings.btype = 1;\n    /*a custom encoder likely doesn't read the btype setting and is optimized for complete PNG\n    images only, so disable it*/\n    zlibsettings.custom_zlib = 0;\n    zlibsettings.custom_deflate = 0;\n    for(type = 0; type != 5; ++type)\n    {\n      attempt[type] = (unsigned char*)lodepng_malloc(linebytes);\n      if(!attempt[type]) return 83; /*alloc fail*/\n    }\n    for(y = 0; y != h; ++y) /*try the 5 filter types*/\n    {\n      for(type = 0; type != 5; ++type)\n      {\n        unsigned testsize = linebytes;\n        /*if(testsize > 8) testsize /= 8;*/ /*it already works good enough by testing a part of the row*/\n\n        filterScanline(attempt[type], &in[y * linebytes], prevline, linebytes, bytewidth, type);\n        size[type] = 0;\n        dummy = 0;\n        zlib_compress(&dummy, &size[type], attempt[type], testsize, &zlibsettings);\n        lodepng_free(dummy);\n        /*check if this is smallest size (or if type == 0 it's the first case so always store the values)*/\n        if(type == 0 || size[type] < smallest)\n        {\n          bestType = type;\n          smallest = size[type];\n        }\n      }\n      prevline = &in[y * linebytes];\n      out[y * (linebytes + 1)] = bestType; /*the first byte of a scanline will be the filter type*/\n      for(x = 0; x != linebytes; ++x) out[y * (linebytes + 1) + 1 + x] = attempt[bestType][x];\n    }\n    for(type = 0; type != 5; ++type) lodepng_free(attempt[type]);\n  }\n  else return 88; /* unknown filter strategy */\n\n  return error;\n}\n\nstatic void addPaddingBits(unsigned char* out, const unsigned char* in,\n                           size_t olinebits, size_t ilinebits, unsigned h)\n{\n  /*The opposite of the removePaddingBits function\n  olinebits must be >= ilinebits*/\n  unsigned y;\n  size_t diff = olinebits - ilinebits;\n  size_t obp = 0, ibp = 0; /*bit pointers*/\n  for(y = 0; y != h; ++y)\n  {\n    size_t x;\n    for(x = 0; x < ilinebits; ++x)\n    {\n      unsigned char bit = readBitFromReversedStream(&ibp, in);\n      setBitOfReversedStream(&obp, out, bit);\n    }\n    /*obp += diff; --> no, fill in some value in the padding bits too, to avoid\n    \"Use of uninitialised value of size ###\" warning from valgrind*/\n    for(x = 0; x != diff; ++x) setBitOfReversedStream(&obp, out, 0);\n  }\n}\n\n/*\nin: non-interlaced image with size w*h\nout: the same pixels, but re-ordered according to PNG's Adam7 interlacing, with\n no padding bits between scanlines, but between reduced images so that each\n reduced image starts at a byte.\nbpp: bits per pixel\nthere are no padding bits, not between scanlines, not between reduced images\nin has the following size in bits: w * h * bpp.\nout is possibly bigger due to padding bits between reduced images\nNOTE: comments about padding bits are only relevant if bpp < 8\n*/\nstatic void Adam7_interlace(unsigned char* out, const unsigned char* in, unsigned w, unsigned h, unsigned bpp)\n{\n  unsigned passw[7], passh[7];\n  size_t filter_passstart[8], padded_passstart[8], passstart[8];\n  unsigned i;\n\n  Adam7_getpassvalues(passw, passh, filter_passstart, padded_passstart, passstart, w, h, bpp);\n\n  if(bpp >= 8)\n  {\n    for(i = 0; i != 7; ++i)\n    {\n      unsigned x, y, b;\n      size_t bytewidth = bpp / 8;\n      for(y = 0; y < passh[i]; ++y)\n      for(x = 0; x < passw[i]; ++x)\n      {\n        size_t pixelinstart = ((ADAM7_IY[i] + y * ADAM7_DY[i]) * w + ADAM7_IX[i] + x * ADAM7_DX[i]) * bytewidth;\n        size_t pixeloutstart = passstart[i] + (y * passw[i] + x) * bytewidth;\n        for(b = 0; b < bytewidth; ++b)\n        {\n          out[pixeloutstart + b] = in[pixelinstart + b];\n        }\n      }\n    }\n  }\n  else /*bpp < 8: Adam7 with pixels < 8 bit is a bit trickier: with bit pointers*/\n  {\n    for(i = 0; i != 7; ++i)\n    {\n      unsigned x, y, b;\n      unsigned ilinebits = bpp * passw[i];\n      unsigned olinebits = bpp * w;\n      size_t obp, ibp; /*bit pointers (for out and in buffer)*/\n      for(y = 0; y < passh[i]; ++y)\n      for(x = 0; x < passw[i]; ++x)\n      {\n        ibp = (ADAM7_IY[i] + y * ADAM7_DY[i]) * olinebits + (ADAM7_IX[i] + x * ADAM7_DX[i]) * bpp;\n        obp = (8 * passstart[i]) + (y * ilinebits + x * bpp);\n        for(b = 0; b < bpp; ++b)\n        {\n          unsigned char bit = readBitFromReversedStream(&ibp, in);\n          setBitOfReversedStream(&obp, out, bit);\n        }\n      }\n    }\n  }\n}\n\n/*out must be buffer big enough to contain uncompressed IDAT chunk data, and in must contain the full image.\nreturn value is error**/\nstatic unsigned preProcessScanlines(unsigned char** out, size_t* outsize, const unsigned char* in,\n                                    unsigned w, unsigned h,\n                                    const LodePNGInfo* info_png, const LodePNGEncoderSettings* settings)\n{\n  /*\n  This function converts the pure 2D image with the PNG's colortype, into filtered-padded-interlaced data. Steps:\n  *) if no Adam7: 1) add padding bits (= posible extra bits per scanline if bpp < 8) 2) filter\n  *) if adam7: 1) Adam7_interlace 2) 7x add padding bits 3) 7x filter\n  */\n  unsigned bpp = lodepng_get_bpp(&info_png->color);\n  unsigned error = 0;\n\n  if(info_png->interlace_method == 0)\n  {\n    *outsize = h + (h * ((w * bpp + 7) / 8)); /*image size plus an extra byte per scanline + possible padding bits*/\n    *out = (unsigned char*)lodepng_malloc(*outsize);\n    if(!(*out) && (*outsize)) error = 83; /*alloc fail*/\n\n    if(!error)\n    {\n      /*non multiple of 8 bits per scanline, padding bits needed per scanline*/\n      if(bpp < 8 && w * bpp != ((w * bpp + 7) / 8) * 8)\n      {\n        unsigned char* padded = (unsigned char*)lodepng_malloc(h * ((w * bpp + 7) / 8));\n        if(!padded) error = 83; /*alloc fail*/\n        if(!error)\n        {\n          addPaddingBits(padded, in, ((w * bpp + 7) / 8) * 8, w * bpp, h);\n          error = filter(*out, padded, w, h, &info_png->color, settings);\n        }\n        lodepng_free(padded);\n      }\n      else\n      {\n        /*we can immediately filter into the out buffer, no other steps needed*/\n        error = filter(*out, in, w, h, &info_png->color, settings);\n      }\n    }\n  }\n  else /*interlace_method is 1 (Adam7)*/\n  {\n    unsigned passw[7], passh[7];\n    size_t filter_passstart[8], padded_passstart[8], passstart[8];\n    unsigned char* adam7;\n\n    Adam7_getpassvalues(passw, passh, filter_passstart, padded_passstart, passstart, w, h, bpp);\n\n    *outsize = filter_passstart[7]; /*image size plus an extra byte per scanline + possible padding bits*/\n    *out = (unsigned char*)lodepng_malloc(*outsize);\n    if(!(*out)) error = 83; /*alloc fail*/\n\n    adam7 = (unsigned char*)lodepng_malloc(passstart[7]);\n    if(!adam7 && passstart[7]) error = 83; /*alloc fail*/\n\n    if(!error)\n    {\n      unsigned i;\n\n      Adam7_interlace(adam7, in, w, h, bpp);\n      for(i = 0; i != 7; ++i)\n      {\n        if(bpp < 8)\n        {\n          unsigned char* padded = (unsigned char*)lodepng_malloc(padded_passstart[i + 1] - padded_passstart[i]);\n          if(!padded) ERROR_BREAK(83); /*alloc fail*/\n          addPaddingBits(padded, &adam7[passstart[i]],\n                         ((passw[i] * bpp + 7) / 8) * 8, passw[i] * bpp, passh[i]);\n          error = filter(&(*out)[filter_passstart[i]], padded,\n                         passw[i], passh[i], &info_png->color, settings);\n          lodepng_free(padded);\n        }\n        else\n        {\n          error = filter(&(*out)[filter_passstart[i]], &adam7[padded_passstart[i]],\n                         passw[i], passh[i], &info_png->color, settings);\n        }\n\n        if(error) break;\n      }\n    }\n\n    lodepng_free(adam7);\n  }\n\n  return error;\n}\n\n/*\npalette must have 4 * palettesize bytes allocated, and given in format RGBARGBARGBARGBA...\nreturns 0 if the palette is opaque,\nreturns 1 if the palette has a single color with alpha 0 ==> color key\nreturns 2 if the palette is semi-translucent.\n*/\nstatic unsigned getPaletteTranslucency(const unsigned char* palette, size_t palettesize)\n{\n  size_t i;\n  unsigned key = 0;\n  unsigned r = 0, g = 0, b = 0; /*the value of the color with alpha 0, so long as color keying is possible*/\n  for(i = 0; i != palettesize; ++i)\n  {\n    if(!key && palette[4 * i + 3] == 0)\n    {\n      r = palette[4 * i + 0]; g = palette[4 * i + 1]; b = palette[4 * i + 2];\n      key = 1;\n      i = (size_t)(-1); /*restart from beginning, to detect earlier opaque colors with key's value*/\n    }\n    else if(palette[4 * i + 3] != 255) return 2;\n    /*when key, no opaque RGB may have key's RGB*/\n    else if(key && r == palette[i * 4 + 0] && g == palette[i * 4 + 1] && b == palette[i * 4 + 2]) return 2;\n  }\n  return key;\n}\n\n#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS\nstatic unsigned addUnknownChunks(ucvector* out, unsigned char* data, size_t datasize)\n{\n  unsigned char* inchunk = data;\n  while((size_t)(inchunk - data) < datasize)\n  {\n    CERROR_TRY_RETURN(lodepng_chunk_append(&out->data, &out->size, inchunk));\n    out->allocsize = out->size; /*fix the allocsize again*/\n    inchunk = lodepng_chunk_next(inchunk);\n  }\n  return 0;\n}\n#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/\n\nunsigned lodepng_encode(unsigned char** out, size_t* outsize,\n                        const unsigned char* image, unsigned w, unsigned h,\n                        LodePNGState* state)\n{\n  LodePNGInfo info;\n  ucvector outv;\n  unsigned char* data = 0; /*uncompressed version of the IDAT chunk data*/\n  size_t datasize = 0;\n\n  /*provide some proper output values if error will happen*/\n  *out = 0;\n  *outsize = 0;\n  state->error = 0;\n\n  lodepng_info_init(&info);\n  lodepng_info_copy(&info, &state->info_png);\n\n  if((info.color.colortype == LCT_PALETTE || state->encoder.force_palette)\n      && (info.color.palettesize == 0 || info.color.palettesize > 256))\n  {\n    state->error = 68; /*invalid palette size, it is only allowed to be 1-256*/\n    return state->error;\n  }\n\n  if(state->encoder.auto_convert)\n  {\n    state->error = lodepng_auto_choose_color(&info.color, image, w, h, &state->info_raw);\n  }\n  if(state->error) return state->error;\n\n  if(state->encoder.zlibsettings.btype > 2)\n  {\n    CERROR_RETURN_ERROR(state->error, 61); /*error: unexisting btype*/\n  }\n  if(state->info_png.interlace_method > 1)\n  {\n    CERROR_RETURN_ERROR(state->error, 71); /*error: unexisting interlace mode*/\n  }\n\n  state->error = checkColorValidity(info.color.colortype, info.color.bitdepth);\n  if(state->error) return state->error; /*error: unexisting color type given*/\n  state->error = checkColorValidity(state->info_raw.colortype, state->info_raw.bitdepth);\n  if(state->error) return state->error; /*error: unexisting color type given*/\n\n  if(!lodepng_color_mode_equal(&state->info_raw, &info.color))\n  {\n    unsigned char* converted;\n    size_t size = (w * h * (size_t)lodepng_get_bpp(&info.color) + 7) / 8;\n\n    converted = (unsigned char*)lodepng_malloc(size);\n    if(!converted && size) state->error = 83; /*alloc fail*/\n    if(!state->error)\n    {\n      state->error = lodepng_convert(converted, image, &info.color, &state->info_raw, w, h);\n    }\n    if(!state->error) preProcessScanlines(&data, &datasize, converted, w, h, &info, &state->encoder);\n    lodepng_free(converted);\n  }\n  else preProcessScanlines(&data, &datasize, image, w, h, &info, &state->encoder);\n\n  ucvector_init(&outv);\n  while(!state->error) /*while only executed once, to break on error*/\n  {\n#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS\n    size_t i;\n#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/\n    /*write signature and chunks*/\n    writeSignature(&outv);\n    /*IHDR*/\n    addChunk_IHDR(&outv, w, h, info.color.colortype, info.color.bitdepth, info.interlace_method);\n#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS\n    /*unknown chunks between IHDR and PLTE*/\n    if(info.unknown_chunks_data[0])\n    {\n      state->error = addUnknownChunks(&outv, info.unknown_chunks_data[0], info.unknown_chunks_size[0]);\n      if(state->error) break;\n    }\n#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/\n    /*PLTE*/\n    if(info.color.colortype == LCT_PALETTE)\n    {\n      addChunk_PLTE(&outv, &info.color);\n    }\n    if(state->encoder.force_palette && (info.color.colortype == LCT_RGB || info.color.colortype == LCT_RGBA))\n    {\n      addChunk_PLTE(&outv, &info.color);\n    }\n    /*tRNS*/\n    if(info.color.colortype == LCT_PALETTE && getPaletteTranslucency(info.color.palette, info.color.palettesize) != 0)\n    {\n      addChunk_tRNS(&outv, &info.color);\n    }\n    if((info.color.colortype == LCT_GREY || info.color.colortype == LCT_RGB) && info.color.key_defined)\n    {\n      addChunk_tRNS(&outv, &info.color);\n    }\n#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS\n    /*bKGD (must come between PLTE and the IDAt chunks*/\n    if(info.background_defined) addChunk_bKGD(&outv, &info);\n    /*pHYs (must come before the IDAT chunks)*/\n    if(info.phys_defined) addChunk_pHYs(&outv, &info);\n\n    /*unknown chunks between PLTE and IDAT*/\n    if(info.unknown_chunks_data[1])\n    {\n      state->error = addUnknownChunks(&outv, info.unknown_chunks_data[1], info.unknown_chunks_size[1]);\n      if(state->error) break;\n    }\n#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/\n    /*IDAT (multiple IDAT chunks must be consecutive)*/\n    state->error = addChunk_IDAT(&outv, data, datasize, &state->encoder.zlibsettings);\n    if(state->error) break;\n#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS\n    /*tIME*/\n    if(info.time_defined) addChunk_tIME(&outv, &info.time);\n    /*tEXt and/or zTXt*/\n    for(i = 0; i != info.text_num; ++i)\n    {\n      if(strlen(info.text_keys[i]) > 79)\n      {\n        state->error = 66; /*text chunk too large*/\n        break;\n      }\n      if(strlen(info.text_keys[i]) < 1)\n      {\n        state->error = 67; /*text chunk too small*/\n        break;\n      }\n      if(state->encoder.text_compression)\n      {\n        addChunk_zTXt(&outv, info.text_keys[i], info.text_strings[i], &state->encoder.zlibsettings);\n      }\n      else\n      {\n        addChunk_tEXt(&outv, info.text_keys[i], info.text_strings[i]);\n      }\n    }\n    /*LodePNG version id in text chunk*/\n    if(state->encoder.add_id)\n    {\n      unsigned alread_added_id_text = 0;\n      for(i = 0; i != info.text_num; ++i)\n      {\n        if(!strcmp(info.text_keys[i], \"LodePNG\"))\n        {\n          alread_added_id_text = 1;\n          break;\n        }\n      }\n      if(alread_added_id_text == 0)\n      {\n        addChunk_tEXt(&outv, \"LodePNG\", LODEPNG_VERSION_STRING); /*it's shorter as tEXt than as zTXt chunk*/\n      }\n    }\n    /*iTXt*/\n    for(i = 0; i != info.itext_num; ++i)\n    {\n      if(strlen(info.itext_keys[i]) > 79)\n      {\n        state->error = 66; /*text chunk too large*/\n        break;\n      }\n      if(strlen(info.itext_keys[i]) < 1)\n      {\n        state->error = 67; /*text chunk too small*/\n        break;\n      }\n      addChunk_iTXt(&outv, state->encoder.text_compression,\n                    info.itext_keys[i], info.itext_langtags[i], info.itext_transkeys[i], info.itext_strings[i],\n                    &state->encoder.zlibsettings);\n    }\n\n    /*unknown chunks between IDAT and IEND*/\n    if(info.unknown_chunks_data[2])\n    {\n      state->error = addUnknownChunks(&outv, info.unknown_chunks_data[2], info.unknown_chunks_size[2]);\n      if(state->error) break;\n    }\n#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/\n    addChunk_IEND(&outv);\n\n    break; /*this isn't really a while loop; no error happened so break out now!*/\n  }\n\n  lodepng_info_cleanup(&info);\n  lodepng_free(data);\n  /*instead of cleaning the vector up, give it to the output*/\n  *out = outv.data;\n  *outsize = outv.size;\n\n  return state->error;\n}\n\nunsigned lodepng_encode_memory(unsigned char** out, size_t* outsize, const unsigned char* image,\n                               unsigned w, unsigned h, LodePNGColorType colortype, unsigned bitdepth)\n{\n  unsigned error;\n  LodePNGState state;\n  lodepng_state_init(&state);\n  state.info_raw.colortype = colortype;\n  state.info_raw.bitdepth = bitdepth;\n  state.info_png.color.colortype = colortype;\n  state.info_png.color.bitdepth = bitdepth;\n  lodepng_encode(out, outsize, image, w, h, &state);\n  error = state.error;\n  lodepng_state_cleanup(&state);\n  return error;\n}\n\nunsigned lodepng_encode32(unsigned char** out, size_t* outsize, const unsigned char* image, unsigned w, unsigned h)\n{\n  return lodepng_encode_memory(out, outsize, image, w, h, LCT_RGBA, 8);\n}\n\nunsigned lodepng_encode24(unsigned char** out, size_t* outsize, const unsigned char* image, unsigned w, unsigned h)\n{\n  return lodepng_encode_memory(out, outsize, image, w, h, LCT_RGB, 8);\n}\n\n#ifdef LODEPNG_COMPILE_DISK\nunsigned lodepng_encode_file(const char* filename, const unsigned char* image, unsigned w, unsigned h,\n                             LodePNGColorType colortype, unsigned bitdepth)\n{\n  unsigned char* buffer;\n  size_t buffersize;\n  unsigned error = lodepng_encode_memory(&buffer, &buffersize, image, w, h, colortype, bitdepth);\n  if(!error) error = lodepng_save_file(buffer, buffersize, filename);\n  lodepng_free(buffer);\n  return error;\n}\n\nunsigned lodepng_encode32_file(const char* filename, const unsigned char* image, unsigned w, unsigned h)\n{\n  return lodepng_encode_file(filename, image, w, h, LCT_RGBA, 8);\n}\n\nunsigned lodepng_encode24_file(const char* filename, const unsigned char* image, unsigned w, unsigned h)\n{\n  return lodepng_encode_file(filename, image, w, h, LCT_RGB, 8);\n}\n#endif /*LODEPNG_COMPILE_DISK*/\n\nvoid lodepng_encoder_settings_init(LodePNGEncoderSettings* settings)\n{\n  lodepng_compress_settings_init(&settings->zlibsettings);\n  settings->filter_palette_zero = 1;\n  settings->filter_strategy = LFS_MINSUM;\n  settings->auto_convert = 1;\n  settings->force_palette = 0;\n  settings->predefined_filters = 0;\n#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS\n  settings->add_id = 0;\n  settings->text_compression = 1;\n#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/\n}\n\n#endif /*LODEPNG_COMPILE_ENCODER*/\n#endif /*LODEPNG_COMPILE_PNG*/\n\n#ifdef LODEPNG_COMPILE_ERROR_TEXT\n/*\nThis returns the description of a numerical error code in English. This is also\nthe documentation of all the error codes.\n*/\nconst char* lodepng_error_text(unsigned code)\n{\n  switch(code)\n  {\n    case 0: return \"no error, everything went ok\";\n    case 1: return \"nothing done yet\"; /*the Encoder/Decoder has done nothing yet, error checking makes no sense yet*/\n    case 10: return \"end of input memory reached without huffman end code\"; /*while huffman decoding*/\n    case 11: return \"error in code tree made it jump outside of huffman tree\"; /*while huffman decoding*/\n    case 13: return \"problem while processing dynamic deflate block\";\n    case 14: return \"problem while processing dynamic deflate block\";\n    case 15: return \"problem while processing dynamic deflate block\";\n    case 16: return \"unexisting code while processing dynamic deflate block\";\n    case 17: return \"end of out buffer memory reached while inflating\";\n    case 18: return \"invalid distance code while inflating\";\n    case 19: return \"end of out buffer memory reached while inflating\";\n    case 20: return \"invalid deflate block BTYPE encountered while decoding\";\n    case 21: return \"NLEN is not ones complement of LEN in a deflate block\";\n     /*end of out buffer memory reached while inflating:\n     This can happen if the inflated deflate data is longer than the amount of bytes required to fill up\n     all the pixels of the image, given the color depth and image dimensions. Something that doesn't\n     happen in a normal, well encoded, PNG image.*/\n    case 22: return \"end of out buffer memory reached while inflating\";\n    case 23: return \"end of in buffer memory reached while inflating\";\n    case 24: return \"invalid FCHECK in zlib header\";\n    case 25: return \"invalid compression method in zlib header\";\n    case 26: return \"FDICT encountered in zlib header while it's not used for PNG\";\n    case 27: return \"PNG file is smaller than a PNG header\";\n    /*Checks the magic file header, the first 8 bytes of the PNG file*/\n    case 28: return \"incorrect PNG signature, it's no PNG or corrupted\";\n    case 29: return \"first chunk is not the header chunk\";\n    case 30: return \"chunk length too large, chunk broken off at end of file\";\n    case 31: return \"illegal PNG color type or bpp\";\n    case 32: return \"illegal PNG compression method\";\n    case 33: return \"illegal PNG filter method\";\n    case 34: return \"illegal PNG interlace method\";\n    case 35: return \"chunk length of a chunk is too large or the chunk too small\";\n    case 36: return \"illegal PNG filter type encountered\";\n    case 37: return \"illegal bit depth for this color type given\";\n    case 38: return \"the palette is too big\"; /*more than 256 colors*/\n    case 39: return \"more palette alpha values given in tRNS chunk than there are colors in the palette\";\n    case 40: return \"tRNS chunk has wrong size for greyscale image\";\n    case 41: return \"tRNS chunk has wrong size for RGB image\";\n    case 42: return \"tRNS chunk appeared while it was not allowed for this color type\";\n    case 43: return \"bKGD chunk has wrong size for palette image\";\n    case 44: return \"bKGD chunk has wrong size for greyscale image\";\n    case 45: return \"bKGD chunk has wrong size for RGB image\";\n    case 48: return \"empty input buffer given to decoder. Maybe caused by non-existing file?\";\n    case 49: return \"jumped past memory while generating dynamic huffman tree\";\n    case 50: return \"jumped past memory while generating dynamic huffman tree\";\n    case 51: return \"jumped past memory while inflating huffman block\";\n    case 52: return \"jumped past memory while inflating\";\n    case 53: return \"size of zlib data too small\";\n    case 54: return \"repeat symbol in tree while there was no value symbol yet\";\n    /*jumped past tree while generating huffman tree, this could be when the\n    tree will have more leaves than symbols after generating it out of the\n    given lenghts. They call this an oversubscribed dynamic bit lengths tree in zlib.*/\n    case 55: return \"jumped past tree while generating huffman tree\";\n    case 56: return \"given output image colortype or bitdepth not supported for color conversion\";\n    case 57: return \"invalid CRC encountered (checking CRC can be disabled)\";\n    case 58: return \"invalid ADLER32 encountered (checking ADLER32 can be disabled)\";\n    case 59: return \"requested color conversion not supported\";\n    case 60: return \"invalid window size given in the settings of the encoder (must be 0-32768)\";\n    case 61: return \"invalid BTYPE given in the settings of the encoder (only 0, 1 and 2 are allowed)\";\n    /*LodePNG leaves the choice of RGB to greyscale conversion formula to the user.*/\n    case 62: return \"conversion from color to greyscale not supported\";\n    case 63: return \"length of a chunk too long, max allowed for PNG is 2147483647 bytes per chunk\"; /*(2^31-1)*/\n    /*this would result in the inability of a deflated block to ever contain an end code. It must be at least 1.*/\n    case 64: return \"the length of the END symbol 256 in the Huffman tree is 0\";\n    case 66: return \"the length of a text chunk keyword given to the encoder is longer than the maximum of 79 bytes\";\n    case 67: return \"the length of a text chunk keyword given to the encoder is smaller than the minimum of 1 byte\";\n    case 68: return \"tried to encode a PLTE chunk with a palette that has less than 1 or more than 256 colors\";\n    case 69: return \"unknown chunk type with 'critical' flag encountered by the decoder\";\n    case 71: return \"unexisting interlace mode given to encoder (must be 0 or 1)\";\n    case 72: return \"while decoding, unexisting compression method encountering in zTXt or iTXt chunk (it must be 0)\";\n    case 73: return \"invalid tIME chunk size\";\n    case 74: return \"invalid pHYs chunk size\";\n    /*length could be wrong, or data chopped off*/\n    case 75: return \"no null termination char found while decoding text chunk\";\n    case 76: return \"iTXt chunk too short to contain required bytes\";\n    case 77: return \"integer overflow in buffer size\";\n    case 78: return \"failed to open file for reading\"; /*file doesn't exist or couldn't be opened for reading*/\n    case 79: return \"failed to open file for writing\";\n    case 80: return \"tried creating a tree of 0 symbols\";\n    case 81: return \"lazy matching at pos 0 is impossible\";\n    case 82: return \"color conversion to palette requested while a color isn't in palette\";\n    case 83: return \"memory allocation failed\";\n    case 84: return \"given image too small to contain all pixels to be encoded\";\n    case 86: return \"impossible offset in lz77 encoding (internal bug)\";\n    case 87: return \"must provide custom zlib function pointer if LODEPNG_COMPILE_ZLIB is not defined\";\n    case 88: return \"invalid filter strategy given for LodePNGEncoderSettings.filter_strategy\";\n    case 89: return \"text chunk keyword too short or long: must have size 1-79\";\n    /*the windowsize in the LodePNGCompressSettings. Requiring POT(==> & instead of %) makes encoding 12% faster.*/\n    case 90: return \"windowsize must be a power of two\";\n    case 91: return \"invalid decompressed idat size\";\n    case 92: return \"too many pixels, not supported\";\n    case 93: return \"zero width or height is invalid\";\n    case 94: return \"header chunk must have a size of 13 bytes\";\n  }\n  return \"unknown error code\";\n}\n#endif /*LODEPNG_COMPILE_ERROR_TEXT*/\n\n/* ////////////////////////////////////////////////////////////////////////// */\n/* ////////////////////////////////////////////////////////////////////////// */\n/* // C++ Wrapper                                                          // */\n/* ////////////////////////////////////////////////////////////////////////// */\n/* ////////////////////////////////////////////////////////////////////////// */\n\n#ifdef LODEPNG_COMPILE_CPP\nnamespace lodepng\n{\n\n#ifdef LODEPNG_COMPILE_DISK\nunsigned load_file(std::vector<unsigned char>& buffer, const std::string& filename)\n{\n  long size = lodepng_filesize(filename.c_str());\n  if(size < 0) return 78;\n  buffer.resize((size_t)size);\n  return size == 0 ? 0 : lodepng_buffer_file(&buffer[0], (size_t)size, filename.c_str());\n}\n\n/*write given buffer to the file, overwriting the file, it doesn't append to it.*/\nunsigned save_file(const std::vector<unsigned char>& buffer, const std::string& filename)\n{\n  return lodepng_save_file(buffer.empty() ? 0 : &buffer[0], buffer.size(), filename.c_str());\n}\n#endif /* LODEPNG_COMPILE_DISK */\n\n#ifdef LODEPNG_COMPILE_ZLIB\n#ifdef LODEPNG_COMPILE_DECODER\nunsigned decompress(std::vector<unsigned char>& out, const unsigned char* in, size_t insize,\n                    const LodePNGDecompressSettings& settings)\n{\n  unsigned char* buffer = 0;\n  size_t buffersize = 0;\n  unsigned error = zlib_decompress(&buffer, &buffersize, in, insize, &settings);\n  if(buffer)\n  {\n    out.insert(out.end(), &buffer[0], &buffer[buffersize]);\n    lodepng_free(buffer);\n  }\n  return error;\n}\n\nunsigned decompress(std::vector<unsigned char>& out, const std::vector<unsigned char>& in,\n                    const LodePNGDecompressSettings& settings)\n{\n  return decompress(out, in.empty() ? 0 : &in[0], in.size(), settings);\n}\n#endif /* LODEPNG_COMPILE_DECODER */\n\n#ifdef LODEPNG_COMPILE_ENCODER\nunsigned compress(std::vector<unsigned char>& out, const unsigned char* in, size_t insize,\n                  const LodePNGCompressSettings& settings)\n{\n  unsigned char* buffer = 0;\n  size_t buffersize = 0;\n  unsigned error = zlib_compress(&buffer, &buffersize, in, insize, &settings);\n  if(buffer)\n  {\n    out.insert(out.end(), &buffer[0], &buffer[buffersize]);\n    lodepng_free(buffer);\n  }\n  return error;\n}\n\nunsigned compress(std::vector<unsigned char>& out, const std::vector<unsigned char>& in,\n                  const LodePNGCompressSettings& settings)\n{\n  return compress(out, in.empty() ? 0 : &in[0], in.size(), settings);\n}\n#endif /* LODEPNG_COMPILE_ENCODER */\n#endif /* LODEPNG_COMPILE_ZLIB */\n\n\n#ifdef LODEPNG_COMPILE_PNG\n\nState::State()\n{\n  lodepng_state_init(this);\n}\n\nState::State(const State& other)\n{\n  lodepng_state_init(this);\n  lodepng_state_copy(this, &other);\n}\n\nState::~State()\n{\n  lodepng_state_cleanup(this);\n}\n\nState& State::operator=(const State& other)\n{\n  lodepng_state_copy(this, &other);\n  return *this;\n}\n\n#ifdef LODEPNG_COMPILE_DECODER\n\nunsigned decode(std::vector<unsigned char>& out, unsigned& w, unsigned& h, const unsigned char* in,\n                size_t insize, LodePNGColorType colortype, unsigned bitdepth)\n{\n  unsigned char* buffer;\n  unsigned error = lodepng_decode_memory(&buffer, &w, &h, in, insize, colortype, bitdepth);\n  if(buffer && !error)\n  {\n    State state;\n    state.info_raw.colortype = colortype;\n    state.info_raw.bitdepth = bitdepth;\n    size_t buffersize = lodepng_get_raw_size(w, h, &state.info_raw);\n    out.insert(out.end(), &buffer[0], &buffer[buffersize]);\n    lodepng_free(buffer);\n  }\n  return error;\n}\n\nunsigned decode(std::vector<unsigned char>& out, unsigned& w, unsigned& h,\n                const std::vector<unsigned char>& in, LodePNGColorType colortype, unsigned bitdepth)\n{\n  return decode(out, w, h, in.empty() ? 0 : &in[0], (unsigned)in.size(), colortype, bitdepth);\n}\n\nunsigned decode(std::vector<unsigned char>& out, unsigned& w, unsigned& h,\n                State& state,\n                const unsigned char* in, size_t insize)\n{\n  unsigned char* buffer = NULL;\n  unsigned error = lodepng_decode(&buffer, &w, &h, &state, in, insize);\n  if(buffer && !error)\n  {\n    size_t buffersize = lodepng_get_raw_size(w, h, &state.info_raw);\n    out.insert(out.end(), &buffer[0], &buffer[buffersize]);\n  }\n  lodepng_free(buffer);\n  return error;\n}\n\nunsigned decode(std::vector<unsigned char>& out, unsigned& w, unsigned& h,\n                State& state,\n                const std::vector<unsigned char>& in)\n{\n  return decode(out, w, h, state, in.empty() ? 0 : &in[0], in.size());\n}\n\n#ifdef LODEPNG_COMPILE_DISK\nunsigned decode(std::vector<unsigned char>& out, unsigned& w, unsigned& h, const std::string& filename,\n                LodePNGColorType colortype, unsigned bitdepth)\n{\n  std::vector<unsigned char> buffer;\n  unsigned error = load_file(buffer, filename);\n  if(error) return error;\n  return decode(out, w, h, buffer, colortype, bitdepth);\n}\n#endif /* LODEPNG_COMPILE_DECODER */\n#endif /* LODEPNG_COMPILE_DISK */\n\n#ifdef LODEPNG_COMPILE_ENCODER\nunsigned encode(std::vector<unsigned char>& out, const unsigned char* in, unsigned w, unsigned h,\n                LodePNGColorType colortype, unsigned bitdepth)\n{\n  unsigned char* buffer;\n  size_t buffersize;\n  unsigned error = lodepng_encode_memory(&buffer, &buffersize, in, w, h, colortype, bitdepth);\n  if(buffer)\n  {\n    out.insert(out.end(), &buffer[0], &buffer[buffersize]);\n    lodepng_free(buffer);\n  }\n  return error;\n}\n\nunsigned encode(std::vector<unsigned char>& out,\n                const std::vector<unsigned char>& in, unsigned w, unsigned h,\n                LodePNGColorType colortype, unsigned bitdepth)\n{\n  if(lodepng_get_raw_size_lct(w, h, colortype, bitdepth) > in.size()) return 84;\n  return encode(out, in.empty() ? 0 : &in[0], w, h, colortype, bitdepth);\n}\n\nunsigned encode(std::vector<unsigned char>& out,\n                const unsigned char* in, unsigned w, unsigned h,\n                State& state)\n{\n  unsigned char* buffer;\n  size_t buffersize;\n  unsigned error = lodepng_encode(&buffer, &buffersize, in, w, h, &state);\n  if(buffer)\n  {\n    out.insert(out.end(), &buffer[0], &buffer[buffersize]);\n    lodepng_free(buffer);\n  }\n  return error;\n}\n\nunsigned encode(std::vector<unsigned char>& out,\n                const std::vector<unsigned char>& in, unsigned w, unsigned h,\n                State& state)\n{\n  if(lodepng_get_raw_size(w, h, &state.info_raw) > in.size()) return 84;\n  return encode(out, in.empty() ? 0 : &in[0], w, h, state);\n}\n\n#ifdef LODEPNG_COMPILE_DISK\nunsigned encode(const std::string& filename,\n                const unsigned char* in, unsigned w, unsigned h,\n                LodePNGColorType colortype, unsigned bitdepth)\n{\n  std::vector<unsigned char> buffer;\n  unsigned error = encode(buffer, in, w, h, colortype, bitdepth);\n  if(!error) error = save_file(buffer, filename);\n  return error;\n}\n\nunsigned encode(const std::string& filename,\n                const std::vector<unsigned char>& in, unsigned w, unsigned h,\n                LodePNGColorType colortype, unsigned bitdepth)\n{\n  if(lodepng_get_raw_size_lct(w, h, colortype, bitdepth) > in.size()) return 84;\n  return encode(filename, in.empty() ? 0 : &in[0], w, h, colortype, bitdepth);\n}\n#endif /* LODEPNG_COMPILE_DISK */\n#endif /* LODEPNG_COMPILE_ENCODER */\n#endif /* LODEPNG_COMPILE_PNG */\n} /* namespace lodepng */\n#endif /*LODEPNG_COMPILE_CPP*/\n"
  },
  {
    "path": "tools/src/common/lodepng.h",
    "content": "/*\nLodePNG version 20160501\n\nCopyright (c) 2005-2016 Lode Vandevenne\n\nThis software is provided 'as-is', without any express or implied\nwarranty. In no event will the authors be held liable for any damages\narising from the use of this software.\n\nPermission is granted to anyone to use this software for any purpose,\nincluding commercial applications, and to alter it and redistribute it\nfreely, subject to the following restrictions:\n\n    1. The origin of this software must not be misrepresented; you must not\n    claim that you wrote the original software. If you use this software\n    in a product, an acknowledgment in the product documentation would be\n    appreciated but is not required.\n\n    2. Altered source versions must be plainly marked as such, and must not be\n    misrepresented as being the original software.\n\n    3. This notice may not be removed or altered from any source\n    distribution.\n*/\n\n#ifndef LODEPNG_H\n#define LODEPNG_H\n\n#include <string.h> /*for size_t*/\n\nextern const char* LODEPNG_VERSION_STRING;\n\n/*\nThe following #defines are used to create code sections. They can be disabled\nto disable code sections, which can give faster compile time and smaller binary.\nThe \"NO_COMPILE\" defines are designed to be used to pass as defines to the\ncompiler command to disable them without modifying this header, e.g.\n-DLODEPNG_NO_COMPILE_ZLIB for gcc.\nIn addition to those below, you can also define LODEPNG_NO_COMPILE_CRC to\nallow implementing a custom lodepng_crc32.\n*/\n/*deflate & zlib. If disabled, you must specify alternative zlib functions in\nthe custom_zlib field of the compress and decompress settings*/\n#ifndef LODEPNG_NO_COMPILE_ZLIB\n#define LODEPNG_COMPILE_ZLIB\n#endif\n/*png encoder and png decoder*/\n#ifndef LODEPNG_NO_COMPILE_PNG\n#define LODEPNG_COMPILE_PNG\n#endif\n/*deflate&zlib decoder and png decoder*/\n#ifndef LODEPNG_NO_COMPILE_DECODER\n#define LODEPNG_COMPILE_DECODER\n#endif\n/*deflate&zlib encoder and png encoder*/\n#ifndef LODEPNG_NO_COMPILE_ENCODER\n#define LODEPNG_COMPILE_ENCODER\n#endif\n/*the optional built in harddisk file loading and saving functions*/\n#ifndef LODEPNG_NO_COMPILE_DISK\n#define LODEPNG_COMPILE_DISK\n#endif\n/*support for chunks other than IHDR, IDAT, PLTE, tRNS, IEND: ancillary and unknown chunks*/\n#ifndef LODEPNG_NO_COMPILE_ANCILLARY_CHUNKS\n#define LODEPNG_COMPILE_ANCILLARY_CHUNKS\n#endif\n/*ability to convert error numerical codes to English text string*/\n#ifndef LODEPNG_NO_COMPILE_ERROR_TEXT\n#define LODEPNG_COMPILE_ERROR_TEXT\n#endif\n/*Compile the default allocators (C's free, malloc and realloc). If you disable this,\nyou can define the functions lodepng_free, lodepng_malloc and lodepng_realloc in your\nsource files with custom allocators.*/\n#ifndef LODEPNG_NO_COMPILE_ALLOCATORS\n#define LODEPNG_COMPILE_ALLOCATORS\n#endif\n/*compile the C++ version (you can disable the C++ wrapper here even when compiling for C++)*/\n#ifdef __cplusplus\n#ifndef LODEPNG_NO_COMPILE_CPP\n#define LODEPNG_COMPILE_CPP\n#endif\n#endif\n\n#ifdef LODEPNG_COMPILE_CPP\n#include <vector>\n#include <string>\n#endif /*LODEPNG_COMPILE_CPP*/\n\n#ifdef LODEPNG_COMPILE_PNG\n/*The PNG color types (also used for raw).*/\ntypedef enum LodePNGColorType\n{\n  LCT_GREY = 0, /*greyscale: 1,2,4,8,16 bit*/\n  LCT_RGB = 2, /*RGB: 8,16 bit*/\n  LCT_PALETTE = 3, /*palette: 1,2,4,8 bit*/\n  LCT_GREY_ALPHA = 4, /*greyscale with alpha: 8,16 bit*/\n  LCT_RGBA = 6 /*RGB with alpha: 8,16 bit*/\n} LodePNGColorType;\n\n#ifdef LODEPNG_COMPILE_DECODER\n/*\nConverts PNG data in memory to raw pixel data.\nout: Output parameter. Pointer to buffer that will contain the raw pixel data.\n     After decoding, its size is w * h * (bytes per pixel) bytes larger than\n     initially. Bytes per pixel depends on colortype and bitdepth.\n     Must be freed after usage with free(*out).\n     Note: for 16-bit per channel colors, uses big endian format like PNG does.\nw: Output parameter. Pointer to width of pixel data.\nh: Output parameter. Pointer to height of pixel data.\nin: Memory buffer with the PNG file.\ninsize: size of the in buffer.\ncolortype: the desired color type for the raw output image. See explanation on PNG color types.\nbitdepth: the desired bit depth for the raw output image. See explanation on PNG color types.\nReturn value: LodePNG error code (0 means no error).\n*/\nunsigned lodepng_decode_memory(unsigned char** out, unsigned* w, unsigned* h,\n                               const unsigned char* in, size_t insize,\n                               LodePNGColorType colortype, unsigned bitdepth);\n\n/*Same as lodepng_decode_memory, but always decodes to 32-bit RGBA raw image*/\nunsigned lodepng_decode32(unsigned char** out, unsigned* w, unsigned* h,\n                          const unsigned char* in, size_t insize);\n\n/*Same as lodepng_decode_memory, but always decodes to 24-bit RGB raw image*/\nunsigned lodepng_decode24(unsigned char** out, unsigned* w, unsigned* h,\n                          const unsigned char* in, size_t insize);\n\n#ifdef LODEPNG_COMPILE_DISK\n/*\nLoad PNG from disk, from file with given name.\nSame as the other decode functions, but instead takes a filename as input.\n*/\nunsigned lodepng_decode_file(unsigned char** out, unsigned* w, unsigned* h,\n                             const char* filename,\n                             LodePNGColorType colortype, unsigned bitdepth);\n\n/*Same as lodepng_decode_file, but always decodes to 32-bit RGBA raw image.*/\nunsigned lodepng_decode32_file(unsigned char** out, unsigned* w, unsigned* h,\n                               const char* filename);\n\n/*Same as lodepng_decode_file, but always decodes to 24-bit RGB raw image.*/\nunsigned lodepng_decode24_file(unsigned char** out, unsigned* w, unsigned* h,\n                               const char* filename);\n#endif /*LODEPNG_COMPILE_DISK*/\n#endif /*LODEPNG_COMPILE_DECODER*/\n\n\n#ifdef LODEPNG_COMPILE_ENCODER\n/*\nConverts raw pixel data into a PNG image in memory. The colortype and bitdepth\n  of the output PNG image cannot be chosen, they are automatically determined\n  by the colortype, bitdepth and content of the input pixel data.\n  Note: for 16-bit per channel colors, needs big endian format like PNG does.\nout: Output parameter. Pointer to buffer that will contain the PNG image data.\n     Must be freed after usage with free(*out).\noutsize: Output parameter. Pointer to the size in bytes of the out buffer.\nimage: The raw pixel data to encode. The size of this buffer should be\n       w * h * (bytes per pixel), bytes per pixel depends on colortype and bitdepth.\nw: width of the raw pixel data in pixels.\nh: height of the raw pixel data in pixels.\ncolortype: the color type of the raw input image. See explanation on PNG color types.\nbitdepth: the bit depth of the raw input image. See explanation on PNG color types.\nReturn value: LodePNG error code (0 means no error).\n*/\nunsigned lodepng_encode_memory(unsigned char** out, size_t* outsize,\n                               const unsigned char* image, unsigned w, unsigned h,\n                               LodePNGColorType colortype, unsigned bitdepth);\n\n/*Same as lodepng_encode_memory, but always encodes from 32-bit RGBA raw image.*/\nunsigned lodepng_encode32(unsigned char** out, size_t* outsize,\n                          const unsigned char* image, unsigned w, unsigned h);\n\n/*Same as lodepng_encode_memory, but always encodes from 24-bit RGB raw image.*/\nunsigned lodepng_encode24(unsigned char** out, size_t* outsize,\n                          const unsigned char* image, unsigned w, unsigned h);\n\n#ifdef LODEPNG_COMPILE_DISK\n/*\nConverts raw pixel data into a PNG file on disk.\nSame as the other encode functions, but instead takes a filename as output.\nNOTE: This overwrites existing files without warning!\n*/\nunsigned lodepng_encode_file(const char* filename,\n                             const unsigned char* image, unsigned w, unsigned h,\n                             LodePNGColorType colortype, unsigned bitdepth);\n\n/*Same as lodepng_encode_file, but always encodes from 32-bit RGBA raw image.*/\nunsigned lodepng_encode32_file(const char* filename,\n                               const unsigned char* image, unsigned w, unsigned h);\n\n/*Same as lodepng_encode_file, but always encodes from 24-bit RGB raw image.*/\nunsigned lodepng_encode24_file(const char* filename,\n                               const unsigned char* image, unsigned w, unsigned h);\n#endif /*LODEPNG_COMPILE_DISK*/\n#endif /*LODEPNG_COMPILE_ENCODER*/\n\n\n#ifdef LODEPNG_COMPILE_CPP\nnamespace lodepng\n{\n#ifdef LODEPNG_COMPILE_DECODER\n/*Same as lodepng_decode_memory, but decodes to an std::vector. The colortype\nis the format to output the pixels to. Default is RGBA 8-bit per channel.*/\nunsigned decode(std::vector<unsigned char>& out, unsigned& w, unsigned& h,\n                const unsigned char* in, size_t insize,\n                LodePNGColorType colortype = LCT_RGBA, unsigned bitdepth = 8);\nunsigned decode(std::vector<unsigned char>& out, unsigned& w, unsigned& h,\n                const std::vector<unsigned char>& in,\n                LodePNGColorType colortype = LCT_RGBA, unsigned bitdepth = 8);\n#ifdef LODEPNG_COMPILE_DISK\n/*\nConverts PNG file from disk to raw pixel data in memory.\nSame as the other decode functions, but instead takes a filename as input.\n*/\nunsigned decode(std::vector<unsigned char>& out, unsigned& w, unsigned& h,\n                const std::string& filename,\n                LodePNGColorType colortype = LCT_RGBA, unsigned bitdepth = 8);\n#endif /* LODEPNG_COMPILE_DISK */\n#endif /* LODEPNG_COMPILE_DECODER */\n\n#ifdef LODEPNG_COMPILE_ENCODER\n/*Same as lodepng_encode_memory, but encodes to an std::vector. colortype\nis that of the raw input data. The output PNG color type will be auto chosen.*/\nunsigned encode(std::vector<unsigned char>& out,\n                const unsigned char* in, unsigned w, unsigned h,\n                LodePNGColorType colortype = LCT_RGBA, unsigned bitdepth = 8);\nunsigned encode(std::vector<unsigned char>& out,\n                const std::vector<unsigned char>& in, unsigned w, unsigned h,\n                LodePNGColorType colortype = LCT_RGBA, unsigned bitdepth = 8);\n#ifdef LODEPNG_COMPILE_DISK\n/*\nConverts 32-bit RGBA raw pixel data into a PNG file on disk.\nSame as the other encode functions, but instead takes a filename as output.\nNOTE: This overwrites existing files without warning!\n*/\nunsigned encode(const std::string& filename,\n                const unsigned char* in, unsigned w, unsigned h,\n                LodePNGColorType colortype = LCT_RGBA, unsigned bitdepth = 8);\nunsigned encode(const std::string& filename,\n                const std::vector<unsigned char>& in, unsigned w, unsigned h,\n                LodePNGColorType colortype = LCT_RGBA, unsigned bitdepth = 8);\n#endif /* LODEPNG_COMPILE_DISK */\n#endif /* LODEPNG_COMPILE_ENCODER */\n} /* namespace lodepng */\n#endif /*LODEPNG_COMPILE_CPP*/\n#endif /*LODEPNG_COMPILE_PNG*/\n\n#ifdef LODEPNG_COMPILE_ERROR_TEXT\n/*Returns an English description of the numerical error code.*/\nconst char* lodepng_error_text(unsigned code);\n#endif /*LODEPNG_COMPILE_ERROR_TEXT*/\n\n#ifdef LODEPNG_COMPILE_DECODER\n/*Settings for zlib decompression*/\ntypedef struct LodePNGDecompressSettings LodePNGDecompressSettings;\nstruct LodePNGDecompressSettings\n{\n  unsigned ignore_adler32; /*if 1, continue and don't give an error message if the Adler32 checksum is corrupted*/\n\n  /*use custom zlib decoder instead of built in one (default: null)*/\n  unsigned (*custom_zlib)(unsigned char**, size_t*,\n                          const unsigned char*, size_t,\n                          const LodePNGDecompressSettings*);\n  /*use custom deflate decoder instead of built in one (default: null)\n  if custom_zlib is used, custom_deflate is ignored since only the built in\n  zlib function will call custom_deflate*/\n  unsigned (*custom_inflate)(unsigned char**, size_t*,\n                             const unsigned char*, size_t,\n                             const LodePNGDecompressSettings*);\n\n  const void* custom_context; /*optional custom settings for custom functions*/\n};\n\nextern const LodePNGDecompressSettings lodepng_default_decompress_settings;\nvoid lodepng_decompress_settings_init(LodePNGDecompressSettings* settings);\n#endif /*LODEPNG_COMPILE_DECODER*/\n\n#ifdef LODEPNG_COMPILE_ENCODER\n/*\nSettings for zlib compression. Tweaking these settings tweaks the balance\nbetween speed and compression ratio.\n*/\ntypedef struct LodePNGCompressSettings LodePNGCompressSettings;\nstruct LodePNGCompressSettings /*deflate = compress*/\n{\n  /*LZ77 related settings*/\n  unsigned btype; /*the block type for LZ (0, 1, 2 or 3, see zlib standard). Should be 2 for proper compression.*/\n  unsigned use_lz77; /*whether or not to use LZ77. Should be 1 for proper compression.*/\n  unsigned windowsize; /*must be a power of two <= 32768. higher compresses more but is slower. Default value: 2048.*/\n  unsigned minmatch; /*mininum lz77 length. 3 is normally best, 6 can be better for some PNGs. Default: 0*/\n  unsigned nicematch; /*stop searching if >= this length found. Set to 258 for best compression. Default: 128*/\n  unsigned lazymatching; /*use lazy matching: better compression but a bit slower. Default: true*/\n\n  /*use custom zlib encoder instead of built in one (default: null)*/\n  unsigned (*custom_zlib)(unsigned char**, size_t*,\n                          const unsigned char*, size_t,\n                          const LodePNGCompressSettings*);\n  /*use custom deflate encoder instead of built in one (default: null)\n  if custom_zlib is used, custom_deflate is ignored since only the built in\n  zlib function will call custom_deflate*/\n  unsigned (*custom_deflate)(unsigned char**, size_t*,\n                             const unsigned char*, size_t,\n                             const LodePNGCompressSettings*);\n\n  const void* custom_context; /*optional custom settings for custom functions*/\n};\n\nextern const LodePNGCompressSettings lodepng_default_compress_settings;\nvoid lodepng_compress_settings_init(LodePNGCompressSettings* settings);\n#endif /*LODEPNG_COMPILE_ENCODER*/\n\n#ifdef LODEPNG_COMPILE_PNG\n/*\nColor mode of an image. Contains all information required to decode the pixel\nbits to RGBA colors. This information is the same as used in the PNG file\nformat, and is used both for PNG and raw image data in LodePNG.\n*/\ntypedef struct LodePNGColorMode\n{\n  /*header (IHDR)*/\n  LodePNGColorType colortype; /*color type, see PNG standard or documentation further in this header file*/\n  unsigned bitdepth;  /*bits per sample, see PNG standard or documentation further in this header file*/\n\n  /*\n  palette (PLTE and tRNS)\n\n  Dynamically allocated with the colors of the palette, including alpha.\n  When encoding a PNG, to store your colors in the palette of the LodePNGColorMode, first use\n  lodepng_palette_clear, then for each color use lodepng_palette_add.\n  If you encode an image without alpha with palette, don't forget to put value 255 in each A byte of the palette.\n\n  When decoding, by default you can ignore this palette, since LodePNG already\n  fills the palette colors in the pixels of the raw RGBA output.\n\n  The palette is only supported for color type 3.\n  */\n  unsigned char* palette; /*palette in RGBARGBA... order. When allocated, must be either 0, or have size 1024*/\n  size_t palettesize; /*palette size in number of colors (amount of bytes is 4 * palettesize)*/\n\n  /*\n  transparent color key (tRNS)\n\n  This color uses the same bit depth as the bitdepth value in this struct, which can be 1-bit to 16-bit.\n  For greyscale PNGs, r, g and b will all 3 be set to the same.\n\n  When decoding, by default you can ignore this information, since LodePNG sets\n  pixels with this key to transparent already in the raw RGBA output.\n\n  The color key is only supported for color types 0 and 2.\n  */\n  unsigned key_defined; /*is a transparent color key given? 0 = false, 1 = true*/\n  unsigned key_r;       /*red/greyscale component of color key*/\n  unsigned key_g;       /*green component of color key*/\n  unsigned key_b;       /*blue component of color key*/\n} LodePNGColorMode;\n\n/*init, cleanup and copy functions to use with this struct*/\nvoid lodepng_color_mode_init(LodePNGColorMode* info);\nvoid lodepng_color_mode_cleanup(LodePNGColorMode* info);\n/*return value is error code (0 means no error)*/\nunsigned lodepng_color_mode_copy(LodePNGColorMode* dest, const LodePNGColorMode* source);\n\nvoid lodepng_palette_clear(LodePNGColorMode* info);\n/*add 1 color to the palette*/\nunsigned lodepng_palette_add(LodePNGColorMode* info,\n                             unsigned char r, unsigned char g, unsigned char b, unsigned char a);\n\n/*get the total amount of bits per pixel, based on colortype and bitdepth in the struct*/\nunsigned lodepng_get_bpp(const LodePNGColorMode* info);\n/*get the amount of color channels used, based on colortype in the struct.\nIf a palette is used, it counts as 1 channel.*/\nunsigned lodepng_get_channels(const LodePNGColorMode* info);\n/*is it a greyscale type? (only colortype 0 or 4)*/\nunsigned lodepng_is_greyscale_type(const LodePNGColorMode* info);\n/*has it got an alpha channel? (only colortype 2 or 6)*/\nunsigned lodepng_is_alpha_type(const LodePNGColorMode* info);\n/*has it got a palette? (only colortype 3)*/\nunsigned lodepng_is_palette_type(const LodePNGColorMode* info);\n/*only returns true if there is a palette and there is a value in the palette with alpha < 255.\nLoops through the palette to check this.*/\nunsigned lodepng_has_palette_alpha(const LodePNGColorMode* info);\n/*\nCheck if the given color info indicates the possibility of having non-opaque pixels in the PNG image.\nReturns true if the image can have translucent or invisible pixels (it still be opaque if it doesn't use such pixels).\nReturns false if the image can only have opaque pixels.\nIn detail, it returns true only if it's a color type with alpha, or has a palette with non-opaque values,\nor if \"key_defined\" is true.\n*/\nunsigned lodepng_can_have_alpha(const LodePNGColorMode* info);\n/*Returns the byte size of a raw image buffer with given width, height and color mode*/\nsize_t lodepng_get_raw_size(unsigned w, unsigned h, const LodePNGColorMode* color);\n\n#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS\n/*The information of a Time chunk in PNG.*/\ntypedef struct LodePNGTime\n{\n  unsigned year;    /*2 bytes used (0-65535)*/\n  unsigned month;   /*1-12*/\n  unsigned day;     /*1-31*/\n  unsigned hour;    /*0-23*/\n  unsigned minute;  /*0-59*/\n  unsigned second;  /*0-60 (to allow for leap seconds)*/\n} LodePNGTime;\n#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/\n\n/*Information about the PNG image, except pixels, width and height.*/\ntypedef struct LodePNGInfo\n{\n  /*header (IHDR), palette (PLTE) and transparency (tRNS) chunks*/\n  unsigned compression_method;/*compression method of the original file. Always 0.*/\n  unsigned filter_method;     /*filter method of the original file*/\n  unsigned interlace_method;  /*interlace method of the original file*/\n  LodePNGColorMode color;     /*color type and bits, palette and transparency of the PNG file*/\n\n#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS\n  /*\n  suggested background color chunk (bKGD)\n  This color uses the same color mode as the PNG (except alpha channel), which can be 1-bit to 16-bit.\n\n  For greyscale PNGs, r, g and b will all 3 be set to the same. When encoding\n  the encoder writes the red one. For palette PNGs: When decoding, the RGB value\n  will be stored, not a palette index. But when encoding, specify the index of\n  the palette in background_r, the other two are then ignored.\n\n  The decoder does not use this background color to edit the color of pixels.\n  */\n  unsigned background_defined; /*is a suggested background color given?*/\n  unsigned background_r;       /*red component of suggested background color*/\n  unsigned background_g;       /*green component of suggested background color*/\n  unsigned background_b;       /*blue component of suggested background color*/\n\n  /*\n  non-international text chunks (tEXt and zTXt)\n\n  The char** arrays each contain num strings. The actual messages are in\n  text_strings, while text_keys are keywords that give a short description what\n  the actual text represents, e.g. Title, Author, Description, or anything else.\n\n  A keyword is minimum 1 character and maximum 79 characters long. It's\n  discouraged to use a single line length longer than 79 characters for texts.\n\n  Don't allocate these text buffers yourself. Use the init/cleanup functions\n  correctly and use lodepng_add_text and lodepng_clear_text.\n  */\n  size_t text_num; /*the amount of texts in these char** buffers (there may be more texts in itext)*/\n  char** text_keys; /*the keyword of a text chunk (e.g. \"Comment\")*/\n  char** text_strings; /*the actual text*/\n\n  /*\n  international text chunks (iTXt)\n  Similar to the non-international text chunks, but with additional strings\n  \"langtags\" and \"transkeys\".\n  */\n  size_t itext_num; /*the amount of international texts in this PNG*/\n  char** itext_keys; /*the English keyword of the text chunk (e.g. \"Comment\")*/\n  char** itext_langtags; /*language tag for this text's language, ISO/IEC 646 string, e.g. ISO 639 language tag*/\n  char** itext_transkeys; /*keyword translated to the international language - UTF-8 string*/\n  char** itext_strings; /*the actual international text - UTF-8 string*/\n\n  /*time chunk (tIME)*/\n  unsigned time_defined; /*set to 1 to make the encoder generate a tIME chunk*/\n  LodePNGTime time;\n\n  /*phys chunk (pHYs)*/\n  unsigned phys_defined; /*if 0, there is no pHYs chunk and the values below are undefined, if 1 else there is one*/\n  unsigned phys_x; /*pixels per unit in x direction*/\n  unsigned phys_y; /*pixels per unit in y direction*/\n  unsigned phys_unit; /*may be 0 (unknown unit) or 1 (metre)*/\n\n  /*\n  unknown chunks\n  There are 3 buffers, one for each position in the PNG where unknown chunks can appear\n  each buffer contains all unknown chunks for that position consecutively\n  The 3 buffers are the unknown chunks between certain critical chunks:\n  0: IHDR-PLTE, 1: PLTE-IDAT, 2: IDAT-IEND\n  Do not allocate or traverse this data yourself. Use the chunk traversing functions declared\n  later, such as lodepng_chunk_next and lodepng_chunk_append, to read/write this struct.\n  */\n  unsigned char* unknown_chunks_data[3];\n  size_t unknown_chunks_size[3]; /*size in bytes of the unknown chunks, given for protection*/\n#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/\n} LodePNGInfo;\n\n/*init, cleanup and copy functions to use with this struct*/\nvoid lodepng_info_init(LodePNGInfo* info);\nvoid lodepng_info_cleanup(LodePNGInfo* info);\n/*return value is error code (0 means no error)*/\nunsigned lodepng_info_copy(LodePNGInfo* dest, const LodePNGInfo* source);\n\n#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS\nvoid lodepng_clear_text(LodePNGInfo* info); /*use this to clear the texts again after you filled them in*/\nunsigned lodepng_add_text(LodePNGInfo* info, const char* key, const char* str); /*push back both texts at once*/\n\nvoid lodepng_clear_itext(LodePNGInfo* info); /*use this to clear the itexts again after you filled them in*/\nunsigned lodepng_add_itext(LodePNGInfo* info, const char* key, const char* langtag,\n                           const char* transkey, const char* str); /*push back the 4 texts of 1 chunk at once*/\n#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/\n\n/*\nConverts raw buffer from one color type to another color type, based on\nLodePNGColorMode structs to describe the input and output color type.\nSee the reference manual at the end of this header file to see which color conversions are supported.\nreturn value = LodePNG error code (0 if all went ok, an error if the conversion isn't supported)\nThe out buffer must have size (w * h * bpp + 7) / 8, where bpp is the bits per pixel\nof the output color type (lodepng_get_bpp).\nFor < 8 bpp images, there should not be padding bits at the end of scanlines.\nFor 16-bit per channel colors, uses big endian format like PNG does.\nReturn value is LodePNG error code\n*/\nunsigned lodepng_convert(unsigned char* out, const unsigned char* in,\n                         const LodePNGColorMode* mode_out, const LodePNGColorMode* mode_in,\n                         unsigned w, unsigned h);\n\n#ifdef LODEPNG_COMPILE_DECODER\n/*\nSettings for the decoder. This contains settings for the PNG and the Zlib\ndecoder, but not the Info settings from the Info structs.\n*/\ntypedef struct LodePNGDecoderSettings\n{\n  LodePNGDecompressSettings zlibsettings; /*in here is the setting to ignore Adler32 checksums*/\n\n  unsigned ignore_crc; /*ignore CRC checksums*/\n\n  unsigned color_convert; /*whether to convert the PNG to the color type you want. Default: yes*/\n\n#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS\n  unsigned read_text_chunks; /*if false but remember_unknown_chunks is true, they're stored in the unknown chunks*/\n  /*store all bytes from unknown chunks in the LodePNGInfo (off by default, useful for a png editor)*/\n  unsigned remember_unknown_chunks;\n#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/\n} LodePNGDecoderSettings;\n\nvoid lodepng_decoder_settings_init(LodePNGDecoderSettings* settings);\n#endif /*LODEPNG_COMPILE_DECODER*/\n\n#ifdef LODEPNG_COMPILE_ENCODER\n/*automatically use color type with less bits per pixel if losslessly possible. Default: AUTO*/\ntypedef enum LodePNGFilterStrategy\n{\n  /*every filter at zero*/\n  LFS_ZERO,\n  /*Use filter that gives minimum sum, as described in the official PNG filter heuristic.*/\n  LFS_MINSUM,\n  /*Use the filter type that gives smallest Shannon entropy for this scanline. Depending\n  on the image, this is better or worse than minsum.*/\n  LFS_ENTROPY,\n  /*\n  Brute-force-search PNG filters by compressing each filter for each scanline.\n  Experimental, very slow, and only rarely gives better compression than MINSUM.\n  */\n  LFS_BRUTE_FORCE,\n  /*use predefined_filters buffer: you specify the filter type for each scanline*/\n  LFS_PREDEFINED\n} LodePNGFilterStrategy;\n\n/*Gives characteristics about the colors of the image, which helps decide which color model to use for encoding.\nUsed internally by default if \"auto_convert\" is enabled. Public because it's useful for custom algorithms.*/\ntypedef struct LodePNGColorProfile\n{\n  unsigned colored; /*not greyscale*/\n  unsigned key; /*if true, image is not opaque. Only if true and alpha is false, color key is possible.*/\n  unsigned short key_r; /*these values are always in 16-bit bitdepth in the profile*/\n  unsigned short key_g;\n  unsigned short key_b;\n  unsigned alpha; /*alpha channel or alpha palette required*/\n  unsigned numcolors; /*amount of colors, up to 257. Not valid if bits == 16.*/\n  unsigned char palette[1024]; /*Remembers up to the first 256 RGBA colors, in no particular order*/\n  unsigned bits; /*bits per channel (not for palette). 1,2 or 4 for greyscale only. 16 if 16-bit per channel required.*/\n} LodePNGColorProfile;\n\nvoid lodepng_color_profile_init(LodePNGColorProfile* profile);\n\n/*Get a LodePNGColorProfile of the image.*/\nunsigned lodepng_get_color_profile(LodePNGColorProfile* profile,\n                                   const unsigned char* image, unsigned w, unsigned h,\n                                   const LodePNGColorMode* mode_in);\n/*The function LodePNG uses internally to decide the PNG color with auto_convert.\nChooses an optimal color model, e.g. grey if only grey pixels, palette if < 256 colors, ...*/\nunsigned lodepng_auto_choose_color(LodePNGColorMode* mode_out,\n                                   const unsigned char* image, unsigned w, unsigned h,\n                                   const LodePNGColorMode* mode_in);\n\n/*Settings for the encoder.*/\ntypedef struct LodePNGEncoderSettings\n{\n  LodePNGCompressSettings zlibsettings; /*settings for the zlib encoder, such as window size, ...*/\n\n  unsigned auto_convert; /*automatically choose output PNG color type. Default: true*/\n\n  /*If true, follows the official PNG heuristic: if the PNG uses a palette or lower than\n  8 bit depth, set all filters to zero. Otherwise use the filter_strategy. Note that to\n  completely follow the official PNG heuristic, filter_palette_zero must be true and\n  filter_strategy must be LFS_MINSUM*/\n  unsigned filter_palette_zero;\n  /*Which filter strategy to use when not using zeroes due to filter_palette_zero.\n  Set filter_palette_zero to 0 to ensure always using your chosen strategy. Default: LFS_MINSUM*/\n  LodePNGFilterStrategy filter_strategy;\n  /*used if filter_strategy is LFS_PREDEFINED. In that case, this must point to a buffer with\n  the same length as the amount of scanlines in the image, and each value must <= 5. You\n  have to cleanup this buffer, LodePNG will never free it. Don't forget that filter_palette_zero\n  must be set to 0 to ensure this is also used on palette or low bitdepth images.*/\n  const unsigned char* predefined_filters;\n\n  /*force creating a PLTE chunk if colortype is 2 or 6 (= a suggested palette).\n  If colortype is 3, PLTE is _always_ created.*/\n  unsigned force_palette;\n#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS\n  /*add LodePNG identifier and version as a text chunk, for debugging*/\n  unsigned add_id;\n  /*encode text chunks as zTXt chunks instead of tEXt chunks, and use compression in iTXt chunks*/\n  unsigned text_compression;\n#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/\n} LodePNGEncoderSettings;\n\nvoid lodepng_encoder_settings_init(LodePNGEncoderSettings* settings);\n#endif /*LODEPNG_COMPILE_ENCODER*/\n\n\n#if defined(LODEPNG_COMPILE_DECODER) || defined(LODEPNG_COMPILE_ENCODER)\n/*The settings, state and information for extended encoding and decoding.*/\ntypedef struct LodePNGState\n{\n#ifdef LODEPNG_COMPILE_DECODER\n  LodePNGDecoderSettings decoder; /*the decoding settings*/\n#endif /*LODEPNG_COMPILE_DECODER*/\n#ifdef LODEPNG_COMPILE_ENCODER\n  LodePNGEncoderSettings encoder; /*the encoding settings*/\n#endif /*LODEPNG_COMPILE_ENCODER*/\n  LodePNGColorMode info_raw; /*specifies the format in which you would like to get the raw pixel buffer*/\n  LodePNGInfo info_png; /*info of the PNG image obtained after decoding*/\n  unsigned error;\n#ifdef LODEPNG_COMPILE_CPP\n  /* For the lodepng::State subclass. */\n  virtual ~LodePNGState(){}\n#endif\n} LodePNGState;\n\n/*init, cleanup and copy functions to use with this struct*/\nvoid lodepng_state_init(LodePNGState* state);\nvoid lodepng_state_cleanup(LodePNGState* state);\nvoid lodepng_state_copy(LodePNGState* dest, const LodePNGState* source);\n#endif /* defined(LODEPNG_COMPILE_DECODER) || defined(LODEPNG_COMPILE_ENCODER) */\n\n#ifdef LODEPNG_COMPILE_DECODER\n/*\nSame as lodepng_decode_memory, but uses a LodePNGState to allow custom settings and\ngetting much more information about the PNG image and color mode.\n*/\nunsigned lodepng_decode(unsigned char** out, unsigned* w, unsigned* h,\n                        LodePNGState* state,\n                        const unsigned char* in, size_t insize);\n\n/*\nRead the PNG header, but not the actual data. This returns only the information\nthat is in the header chunk of the PNG, such as width, height and color type. The\ninformation is placed in the info_png field of the LodePNGState.\n*/\nunsigned lodepng_inspect(unsigned* w, unsigned* h,\n                         LodePNGState* state,\n                         const unsigned char* in, size_t insize);\n#endif /*LODEPNG_COMPILE_DECODER*/\n\n\n#ifdef LODEPNG_COMPILE_ENCODER\n/*This function allocates the out buffer with standard malloc and stores the size in *outsize.*/\nunsigned lodepng_encode(unsigned char** out, size_t* outsize,\n                        const unsigned char* image, unsigned w, unsigned h,\n                        LodePNGState* state);\n#endif /*LODEPNG_COMPILE_ENCODER*/\n\n/*\nThe lodepng_chunk functions are normally not needed, except to traverse the\nunknown chunks stored in the LodePNGInfo struct, or add new ones to it.\nIt also allows traversing the chunks of an encoded PNG file yourself.\n\nPNG standard chunk naming conventions:\nFirst byte: uppercase = critical, lowercase = ancillary\nSecond byte: uppercase = public, lowercase = private\nThird byte: must be uppercase\nFourth byte: uppercase = unsafe to copy, lowercase = safe to copy\n*/\n\n/*\nGets the length of the data of the chunk. Total chunk length has 12 bytes more.\nThere must be at least 4 bytes to read from. If the result value is too large,\nit may be corrupt data.\n*/\nunsigned lodepng_chunk_length(const unsigned char* chunk);\n\n/*puts the 4-byte type in null terminated string*/\nvoid lodepng_chunk_type(char type[5], const unsigned char* chunk);\n\n/*check if the type is the given type*/\nunsigned char lodepng_chunk_type_equals(const unsigned char* chunk, const char* type);\n\n/*0: it's one of the critical chunk types, 1: it's an ancillary chunk (see PNG standard)*/\nunsigned char lodepng_chunk_ancillary(const unsigned char* chunk);\n\n/*0: public, 1: private (see PNG standard)*/\nunsigned char lodepng_chunk_private(const unsigned char* chunk);\n\n/*0: the chunk is unsafe to copy, 1: the chunk is safe to copy (see PNG standard)*/\nunsigned char lodepng_chunk_safetocopy(const unsigned char* chunk);\n\n/*get pointer to the data of the chunk, where the input points to the header of the chunk*/\nunsigned char* lodepng_chunk_data(unsigned char* chunk);\nconst unsigned char* lodepng_chunk_data_const(const unsigned char* chunk);\n\n/*returns 0 if the crc is correct, 1 if it's incorrect (0 for OK as usual!)*/\nunsigned lodepng_chunk_check_crc(const unsigned char* chunk);\n\n/*generates the correct CRC from the data and puts it in the last 4 bytes of the chunk*/\nvoid lodepng_chunk_generate_crc(unsigned char* chunk);\n\n/*iterate to next chunks. don't use on IEND chunk, as there is no next chunk then*/\nunsigned char* lodepng_chunk_next(unsigned char* chunk);\nconst unsigned char* lodepng_chunk_next_const(const unsigned char* chunk);\n\n/*\nAppends chunk to the data in out. The given chunk should already have its chunk header.\nThe out variable and outlength are updated to reflect the new reallocated buffer.\nReturns error code (0 if it went ok)\n*/\nunsigned lodepng_chunk_append(unsigned char** out, size_t* outlength, const unsigned char* chunk);\n\n/*\nAppends new chunk to out. The chunk to append is given by giving its length, type\nand data separately. The type is a 4-letter string.\nThe out variable and outlength are updated to reflect the new reallocated buffer.\nReturne error code (0 if it went ok)\n*/\nunsigned lodepng_chunk_create(unsigned char** out, size_t* outlength, unsigned length,\n                              const char* type, const unsigned char* data);\n\n\n/*Calculate CRC32 of buffer*/\nunsigned lodepng_crc32(const unsigned char* buf, size_t len);\n#endif /*LODEPNG_COMPILE_PNG*/\n\n\n#ifdef LODEPNG_COMPILE_ZLIB\n/*\nThis zlib part can be used independently to zlib compress and decompress a\nbuffer. It cannot be used to create gzip files however, and it only supports the\npart of zlib that is required for PNG, it does not support dictionaries.\n*/\n\n#ifdef LODEPNG_COMPILE_DECODER\n/*Inflate a buffer. Inflate is the decompression step of deflate. Out buffer must be freed after use.*/\nunsigned lodepng_inflate(unsigned char** out, size_t* outsize,\n                         const unsigned char* in, size_t insize,\n                         const LodePNGDecompressSettings* settings);\n\n/*\nDecompresses Zlib data. Reallocates the out buffer and appends the data. The\ndata must be according to the zlib specification.\nEither, *out must be NULL and *outsize must be 0, or, *out must be a valid\nbuffer and *outsize its size in bytes. out must be freed by user after usage.\n*/\nunsigned lodepng_zlib_decompress(unsigned char** out, size_t* outsize,\n                                 const unsigned char* in, size_t insize,\n                                 const LodePNGDecompressSettings* settings);\n#endif /*LODEPNG_COMPILE_DECODER*/\n\n#ifdef LODEPNG_COMPILE_ENCODER\n/*\nCompresses data with Zlib. Reallocates the out buffer and appends the data.\nZlib adds a small header and trailer around the deflate data.\nThe data is output in the format of the zlib specification.\nEither, *out must be NULL and *outsize must be 0, or, *out must be a valid\nbuffer and *outsize its size in bytes. out must be freed by user after usage.\n*/\nunsigned lodepng_zlib_compress(unsigned char** out, size_t* outsize,\n                               const unsigned char* in, size_t insize,\n                               const LodePNGCompressSettings* settings);\n\n/*\nFind length-limited Huffman code for given frequencies. This function is in the\npublic interface only for tests, it's used internally by lodepng_deflate.\n*/\nunsigned lodepng_huffman_code_lengths(unsigned* lengths, const unsigned* frequencies,\n                                      size_t numcodes, unsigned maxbitlen);\n\n/*Compress a buffer with deflate. See RFC 1951. Out buffer must be freed after use.*/\nunsigned lodepng_deflate(unsigned char** out, size_t* outsize,\n                         const unsigned char* in, size_t insize,\n                         const LodePNGCompressSettings* settings);\n\n#endif /*LODEPNG_COMPILE_ENCODER*/\n#endif /*LODEPNG_COMPILE_ZLIB*/\n\n#ifdef LODEPNG_COMPILE_DISK\n/*\nLoad a file from disk into buffer. The function allocates the out buffer, and\nafter usage you should free it.\nout: output parameter, contains pointer to loaded buffer.\noutsize: output parameter, size of the allocated out buffer\nfilename: the path to the file to load\nreturn value: error code (0 means ok)\n*/\nunsigned lodepng_load_file(unsigned char** out, size_t* outsize, const char* filename);\n\n/*\nSave a file from buffer to disk. Warning, if it exists, this function overwrites\nthe file without warning!\nbuffer: the buffer to write\nbuffersize: size of the buffer to write\nfilename: the path to the file to save to\nreturn value: error code (0 means ok)\n*/\nunsigned lodepng_save_file(const unsigned char* buffer, size_t buffersize, const char* filename);\n#endif /*LODEPNG_COMPILE_DISK*/\n\n#ifdef LODEPNG_COMPILE_CPP\n/* The LodePNG C++ wrapper uses std::vectors instead of manually allocated memory buffers. */\nnamespace lodepng\n{\n#ifdef LODEPNG_COMPILE_PNG\nclass State : public LodePNGState\n{\n  public:\n    State();\n    State(const State& other);\n    virtual ~State();\n    State& operator=(const State& other);\n};\n\n#ifdef LODEPNG_COMPILE_DECODER\n/* Same as other lodepng::decode, but using a State for more settings and information. */\nunsigned decode(std::vector<unsigned char>& out, unsigned& w, unsigned& h,\n                State& state,\n                const unsigned char* in, size_t insize);\nunsigned decode(std::vector<unsigned char>& out, unsigned& w, unsigned& h,\n                State& state,\n                const std::vector<unsigned char>& in);\n#endif /*LODEPNG_COMPILE_DECODER*/\n\n#ifdef LODEPNG_COMPILE_ENCODER\n/* Same as other lodepng::encode, but using a State for more settings and information. */\nunsigned encode(std::vector<unsigned char>& out,\n                const unsigned char* in, unsigned w, unsigned h,\n                State& state);\nunsigned encode(std::vector<unsigned char>& out,\n                const std::vector<unsigned char>& in, unsigned w, unsigned h,\n                State& state);\n#endif /*LODEPNG_COMPILE_ENCODER*/\n\n#ifdef LODEPNG_COMPILE_DISK\n/*\nLoad a file from disk into an std::vector.\nreturn value: error code (0 means ok)\n*/\nunsigned load_file(std::vector<unsigned char>& buffer, const std::string& filename);\n\n/*\nSave the binary data in an std::vector to a file on disk. The file is overwritten\nwithout warning.\n*/\nunsigned save_file(const std::vector<unsigned char>& buffer, const std::string& filename);\n#endif /* LODEPNG_COMPILE_DISK */\n#endif /* LODEPNG_COMPILE_PNG */\n\n#ifdef LODEPNG_COMPILE_ZLIB\n#ifdef LODEPNG_COMPILE_DECODER\n/* Zlib-decompress an unsigned char buffer */\nunsigned decompress(std::vector<unsigned char>& out, const unsigned char* in, size_t insize,\n                    const LodePNGDecompressSettings& settings = lodepng_default_decompress_settings);\n\n/* Zlib-decompress an std::vector */\nunsigned decompress(std::vector<unsigned char>& out, const std::vector<unsigned char>& in,\n                    const LodePNGDecompressSettings& settings = lodepng_default_decompress_settings);\n#endif /* LODEPNG_COMPILE_DECODER */\n\n#ifdef LODEPNG_COMPILE_ENCODER\n/* Zlib-compress an unsigned char buffer */\nunsigned compress(std::vector<unsigned char>& out, const unsigned char* in, size_t insize,\n                  const LodePNGCompressSettings& settings = lodepng_default_compress_settings);\n\n/* Zlib-compress an std::vector */\nunsigned compress(std::vector<unsigned char>& out, const std::vector<unsigned char>& in,\n                  const LodePNGCompressSettings& settings = lodepng_default_compress_settings);\n#endif /* LODEPNG_COMPILE_ENCODER */\n#endif /* LODEPNG_COMPILE_ZLIB */\n} /* namespace lodepng */\n#endif /*LODEPNG_COMPILE_CPP*/\n\n/*\nTODO:\n[.] test if there are no memory leaks or security exploits - done a lot but needs to be checked often\n[.] check compatibility with various compilers  - done but needs to be redone for every newer version\n[X] converting color to 16-bit per channel types\n[ ] read all public PNG chunk types (but never let the color profile and gamma ones touch RGB values)\n[ ] make sure encoder generates no chunks with size > (2^31)-1\n[ ] partial decoding (stream processing)\n[X] let the \"isFullyOpaque\" function check color keys and transparent palettes too\n[X] better name for the variables \"codes\", \"codesD\", \"codelengthcodes\", \"clcl\" and \"lldl\"\n[ ] don't stop decoding on errors like 69, 57, 58 (make warnings)\n[ ] make warnings like: oob palette, checksum fail, data after iend, wrong/unknown crit chunk, no null terminator in text, ...\n[ ] let the C++ wrapper catch exceptions coming from the standard library and return LodePNG error codes\n[ ] allow user to provide custom color conversion functions, e.g. for premultiplied alpha, padding bits or not, ...\n[ ] allow user to give data (void*) to custom allocator\n*/\n\n#endif /*LODEPNG_H inclusion guard*/\n\n/*\nLodePNG Documentation\n---------------------\n\n0. table of contents\n--------------------\n\n  1. about\n   1.1. supported features\n   1.2. features not supported\n  2. C and C++ version\n  3. security\n  4. decoding\n  5. encoding\n  6. color conversions\n    6.1. PNG color types\n    6.2. color conversions\n    6.3. padding bits\n    6.4. A note about 16-bits per channel and endianness\n  7. error values\n  8. chunks and PNG editing\n  9. compiler support\n  10. examples\n   10.1. decoder C++ example\n   10.2. decoder C example\n  11. state settings reference\n  12. changes\n  13. contact information\n\n\n1. about\n--------\n\nPNG is a file format to store raster images losslessly with good compression,\nsupporting different color types and alpha channel.\n\nLodePNG is a PNG codec according to the Portable Network Graphics (PNG)\nSpecification (Second Edition) - W3C Recommendation 10 November 2003.\n\nThe specifications used are:\n\n*) Portable Network Graphics (PNG) Specification (Second Edition):\n     http://www.w3.org/TR/2003/REC-PNG-20031110\n*) RFC 1950 ZLIB Compressed Data Format version 3.3:\n     http://www.gzip.org/zlib/rfc-zlib.html\n*) RFC 1951 DEFLATE Compressed Data Format Specification ver 1.3:\n     http://www.gzip.org/zlib/rfc-deflate.html\n\nThe most recent version of LodePNG can currently be found at\nhttp://lodev.org/lodepng/\n\nLodePNG works both in C (ISO C90) and C++, with a C++ wrapper that adds\nextra functionality.\n\nLodePNG exists out of two files:\n-lodepng.h: the header file for both C and C++\n-lodepng.c(pp): give it the name lodepng.c or lodepng.cpp (or .cc) depending on your usage\n\nIf you want to start using LodePNG right away without reading this doc, get the\nexamples from the LodePNG website to see how to use it in code, or check the\nsmaller examples in chapter 13 here.\n\nLodePNG is simple but only supports the basic requirements. To achieve\nsimplicity, the following design choices were made: There are no dependencies\non any external library. There are functions to decode and encode a PNG with\na single function call, and extended versions of these functions taking a\nLodePNGState struct allowing to specify or get more information. By default\nthe colors of the raw image are always RGB or RGBA, no matter what color type\nthe PNG file uses. To read and write files, there are simple functions to\nconvert the files to/from buffers in memory.\n\nThis all makes LodePNG suitable for loading textures in games, demos and small\nprograms, ... It's less suitable for full fledged image editors, loading PNGs\nover network (it requires all the image data to be available before decoding can\nbegin), life-critical systems, ...\n\n1.1. supported features\n-----------------------\n\nThe following features are supported by the decoder:\n\n*) decoding of PNGs with any color type, bit depth and interlace mode, to a 24- or 32-bit color raw image,\n   or the same color type as the PNG\n*) encoding of PNGs, from any raw image to 24- or 32-bit color, or the same color type as the raw image\n*) Adam7 interlace and deinterlace for any color type\n*) loading the image from harddisk or decoding it from a buffer from other sources than harddisk\n*) support for alpha channels, including RGBA color model, translucent palettes and color keying\n*) zlib decompression (inflate)\n*) zlib compression (deflate)\n*) CRC32 and ADLER32 checksums\n*) handling of unknown chunks, allowing making a PNG editor that stores custom and unknown chunks.\n*) the following chunks are supported (generated/interpreted) by both encoder and decoder:\n    IHDR: header information\n    PLTE: color palette\n    IDAT: pixel data\n    IEND: the final chunk\n    tRNS: transparency for palettized images\n    tEXt: textual information\n    zTXt: compressed textual information\n    iTXt: international textual information\n    bKGD: suggested background color\n    pHYs: physical dimensions\n    tIME: modification time\n\n1.2. features not supported\n---------------------------\n\nThe following features are _not_ supported:\n\n*) some features needed to make a conformant PNG-Editor might be still missing.\n*) partial loading/stream processing. All data must be available and is processed in one call.\n*) The following public chunks are not supported but treated as unknown chunks by LodePNG\n    cHRM, gAMA, iCCP, sRGB, sBIT, hIST, sPLT\n   Some of these are not supported on purpose: LodePNG wants to provide the RGB values\n   stored in the pixels, not values modified by system dependent gamma or color models.\n\n\n2. C and C++ version\n--------------------\n\nThe C version uses buffers allocated with alloc that you need to free()\nyourself. You need to use init and cleanup functions for each struct whenever\nusing a struct from the C version to avoid exploits and memory leaks.\n\nThe C++ version has extra functions with std::vectors in the interface and the\nlodepng::State class which is a LodePNGState with constructor and destructor.\n\nThese files work without modification for both C and C++ compilers because all\nthe additional C++ code is in \"#ifdef __cplusplus\" blocks that make C-compilers\nignore it, and the C code is made to compile both with strict ISO C90 and C++.\n\nTo use the C++ version, you need to rename the source file to lodepng.cpp\n(instead of lodepng.c), and compile it with a C++ compiler.\n\nTo use the C version, you need to rename the source file to lodepng.c (instead\nof lodepng.cpp), and compile it with a C compiler.\n\n\n3. Security\n-----------\n\nEven if carefully designed, it's always possible that LodePNG contains possible\nexploits. If you discover one, please let me know, and it will be fixed.\n\nWhen using LodePNG, care has to be taken with the C version of LodePNG, as well\nas the C-style structs when working with C++. The following conventions are used\nfor all C-style structs:\n\n-if a struct has a corresponding init function, always call the init function when making a new one\n-if a struct has a corresponding cleanup function, call it before the struct disappears to avoid memory leaks\n-if a struct has a corresponding copy function, use the copy function instead of \"=\".\n The destination must also be inited already.\n\n\n4. Decoding\n-----------\n\nDecoding converts a PNG compressed image to a raw pixel buffer.\n\nMost documentation on using the decoder is at its declarations in the header\nabove. For C, simple decoding can be done with functions such as\nlodepng_decode32, and more advanced decoding can be done with the struct\nLodePNGState and lodepng_decode. For C++, all decoding can be done with the\nvarious lodepng::decode functions, and lodepng::State can be used for advanced\nfeatures.\n\nWhen using the LodePNGState, it uses the following fields for decoding:\n*) LodePNGInfo info_png: it stores extra information about the PNG (the input) in here\n*) LodePNGColorMode info_raw: here you can say what color mode of the raw image (the output) you want to get\n*) LodePNGDecoderSettings decoder: you can specify a few extra settings for the decoder to use\n\nLodePNGInfo info_png\n--------------------\n\nAfter decoding, this contains extra information of the PNG image, except the actual\npixels, width and height because these are already gotten directly from the decoder\nfunctions.\n\nIt contains for example the original color type of the PNG image, text comments,\nsuggested background color, etc... More details about the LodePNGInfo struct are\nat its declaration documentation.\n\nLodePNGColorMode info_raw\n-------------------------\n\nWhen decoding, here you can specify which color type you want\nthe resulting raw image to be. If this is different from the colortype of the\nPNG, then the decoder will automatically convert the result. This conversion\nalways works, except if you want it to convert a color PNG to greyscale or to\na palette with missing colors.\n\nBy default, 32-bit color is used for the result.\n\nLodePNGDecoderSettings decoder\n------------------------------\n\nThe settings can be used to ignore the errors created by invalid CRC and Adler32\nchunks, and to disable the decoding of tEXt chunks.\n\nThere's also a setting color_convert, true by default. If false, no conversion\nis done, the resulting data will be as it was in the PNG (after decompression)\nand you'll have to puzzle the colors of the pixels together yourself using the\ncolor type information in the LodePNGInfo.\n\n\n5. Encoding\n-----------\n\nEncoding converts a raw pixel buffer to a PNG compressed image.\n\nMost documentation on using the encoder is at its declarations in the header\nabove. For C, simple encoding can be done with functions such as\nlodepng_encode32, and more advanced decoding can be done with the struct\nLodePNGState and lodepng_encode. For C++, all encoding can be done with the\nvarious lodepng::encode functions, and lodepng::State can be used for advanced\nfeatures.\n\nLike the decoder, the encoder can also give errors. However it gives less errors\nsince the encoder input is trusted, the decoder input (a PNG image that could\nbe forged by anyone) is not trusted.\n\nWhen using the LodePNGState, it uses the following fields for encoding:\n*) LodePNGInfo info_png: here you specify how you want the PNG (the output) to be.\n*) LodePNGColorMode info_raw: here you say what color type of the raw image (the input) has\n*) LodePNGEncoderSettings encoder: you can specify a few settings for the encoder to use\n\nLodePNGInfo info_png\n--------------------\n\nWhen encoding, you use this the opposite way as when decoding: for encoding,\nyou fill in the values you want the PNG to have before encoding. By default it's\nnot needed to specify a color type for the PNG since it's automatically chosen,\nbut it's possible to choose it yourself given the right settings.\n\nThe encoder will not always exactly match the LodePNGInfo struct you give,\nit tries as close as possible. Some things are ignored by the encoder. The\nencoder uses, for example, the following settings from it when applicable:\ncolortype and bitdepth, text chunks, time chunk, the color key, the palette, the\nbackground color, the interlace method, unknown chunks, ...\n\nWhen encoding to a PNG with colortype 3, the encoder will generate a PLTE chunk.\nIf the palette contains any colors for which the alpha channel is not 255 (so\nthere are translucent colors in the palette), it'll add a tRNS chunk.\n\nLodePNGColorMode info_raw\n-------------------------\n\nYou specify the color type of the raw image that you give to the input here,\nincluding a possible transparent color key and palette you happen to be using in\nyour raw image data.\n\nBy default, 32-bit color is assumed, meaning your input has to be in RGBA\nformat with 4 bytes (unsigned chars) per pixel.\n\nLodePNGEncoderSettings encoder\n------------------------------\n\nThe following settings are supported (some are in sub-structs):\n*) auto_convert: when this option is enabled, the encoder will\nautomatically choose the smallest possible color mode (including color key) that\ncan encode the colors of all pixels without information loss.\n*) btype: the block type for LZ77. 0 = uncompressed, 1 = fixed huffman tree,\n   2 = dynamic huffman tree (best compression). Should be 2 for proper\n   compression.\n*) use_lz77: whether or not to use LZ77 for compressed block types. Should be\n   true for proper compression.\n*) windowsize: the window size used by the LZ77 encoder (1 - 32768). Has value\n   2048 by default, but can be set to 32768 for better, but slow, compression.\n*) force_palette: if colortype is 2 or 6, you can make the encoder write a PLTE\n   chunk if force_palette is true. This can used as suggested palette to convert\n   to by viewers that don't support more than 256 colors (if those still exist)\n*) add_id: add text chunk \"Encoder: LodePNG <version>\" to the image.\n*) text_compression: default 1. If 1, it'll store texts as zTXt instead of tEXt chunks.\n  zTXt chunks use zlib compression on the text. This gives a smaller result on\n  large texts but a larger result on small texts (such as a single program name).\n  It's all tEXt or all zTXt though, there's no separate setting per text yet.\n\n\n6. color conversions\n--------------------\n\nAn important thing to note about LodePNG, is that the color type of the PNG, and\nthe color type of the raw image, are completely independent. By default, when\nyou decode a PNG, you get the result as a raw image in the color type you want,\nno matter whether the PNG was encoded with a palette, greyscale or RGBA color.\nAnd if you encode an image, by default LodePNG will automatically choose the PNG\ncolor type that gives good compression based on the values of colors and amount\nof colors in the image. It can be configured to let you control it instead as\nwell, though.\n\nTo be able to do this, LodePNG does conversions from one color mode to another.\nIt can convert from almost any color type to any other color type, except the\nfollowing conversions: RGB to greyscale is not supported, and converting to a\npalette when the palette doesn't have a required color is not supported. This is\nnot supported on purpose: this is information loss which requires a color\nreduction algorithm that is beyong the scope of a PNG encoder (yes, RGB to grey\nis easy, but there are multiple ways if you want to give some channels more\nweight).\n\nBy default, when decoding, you get the raw image in 32-bit RGBA or 24-bit RGB\ncolor, no matter what color type the PNG has. And by default when encoding,\nLodePNG automatically picks the best color model for the output PNG, and expects\nthe input image to be 32-bit RGBA or 24-bit RGB. So, unless you want to control\nthe color format of the images yourself, you can skip this chapter.\n\n6.1. PNG color types\n--------------------\n\nA PNG image can have many color types, ranging from 1-bit color to 64-bit color,\nas well as palettized color modes. After the zlib decompression and unfiltering\nin the PNG image is done, the raw pixel data will have that color type and thus\na certain amount of bits per pixel. If you want the output raw image after\ndecoding to have another color type, a conversion is done by LodePNG.\n\nThe PNG specification gives the following color types:\n\n0: greyscale, bit depths 1, 2, 4, 8, 16\n2: RGB, bit depths 8 and 16\n3: palette, bit depths 1, 2, 4 and 8\n4: greyscale with alpha, bit depths 8 and 16\n6: RGBA, bit depths 8 and 16\n\nBit depth is the amount of bits per pixel per color channel. So the total amount\nof bits per pixel is: amount of channels * bitdepth.\n\n6.2. color conversions\n----------------------\n\nAs explained in the sections about the encoder and decoder, you can specify\ncolor types and bit depths in info_png and info_raw to change the default\nbehaviour.\n\nIf, when decoding, you want the raw image to be something else than the default,\nyou need to set the color type and bit depth you want in the LodePNGColorMode,\nor the parameters colortype and bitdepth of the simple decoding function.\n\nIf, when encoding, you use another color type than the default in the raw input\nimage, you need to specify its color type and bit depth in the LodePNGColorMode\nof the raw image, or use the parameters colortype and bitdepth of the simple\nencoding function.\n\nIf, when encoding, you don't want LodePNG to choose the output PNG color type\nbut control it yourself, you need to set auto_convert in the encoder settings\nto false, and specify the color type you want in the LodePNGInfo of the\nencoder (including palette: it can generate a palette if auto_convert is true,\notherwise not).\n\nIf the input and output color type differ (whether user chosen or auto chosen),\nLodePNG will do a color conversion, which follows the rules below, and may\nsometimes result in an error.\n\nTo avoid some confusion:\n-the decoder converts from PNG to raw image\n-the encoder converts from raw image to PNG\n-the colortype and bitdepth in LodePNGColorMode info_raw, are those of the raw image\n-the colortype and bitdepth in the color field of LodePNGInfo info_png, are those of the PNG\n-when encoding, the color type in LodePNGInfo is ignored if auto_convert\n is enabled, it is automatically generated instead\n-when decoding, the color type in LodePNGInfo is set by the decoder to that of the original\n PNG image, but it can be ignored since the raw image has the color type you requested instead\n-if the color type of the LodePNGColorMode and PNG image aren't the same, a conversion\n between the color types is done if the color types are supported. If it is not\n supported, an error is returned. If the types are the same, no conversion is done.\n-even though some conversions aren't supported, LodePNG supports loading PNGs from any\n colortype and saving PNGs to any colortype, sometimes it just requires preparing\n the raw image correctly before encoding.\n-both encoder and decoder use the same color converter.\n\nNon supported color conversions:\n-color to greyscale: no error is thrown, but the result will look ugly because\nonly the red channel is taken\n-anything to palette when that palette does not have that color in it: in this\ncase an error is thrown\n\nSupported color conversions:\n-anything to 8-bit RGB, 8-bit RGBA, 16-bit RGB, 16-bit RGBA\n-any grey or grey+alpha, to grey or grey+alpha\n-anything to a palette, as long as the palette has the requested colors in it\n-removing alpha channel\n-higher to smaller bitdepth, and vice versa\n\nIf you want no color conversion to be done (e.g. for speed or control):\n-In the encoder, you can make it save a PNG with any color type by giving the\nraw color mode and LodePNGInfo the same color mode, and setting auto_convert to\nfalse.\n-In the decoder, you can make it store the pixel data in the same color type\nas the PNG has, by setting the color_convert setting to false. Settings in\ninfo_raw are then ignored.\n\nThe function lodepng_convert does the color conversion. It is available in the\ninterface but normally isn't needed since the encoder and decoder already call\nit.\n\n6.3. padding bits\n-----------------\n\nIn the PNG file format, if a less than 8-bit per pixel color type is used and the scanlines\nhave a bit amount that isn't a multiple of 8, then padding bits are used so that each\nscanline starts at a fresh byte. But that is NOT true for the LodePNG raw input and output.\nThe raw input image you give to the encoder, and the raw output image you get from the decoder\nwill NOT have these padding bits, e.g. in the case of a 1-bit image with a width\nof 7 pixels, the first pixel of the second scanline will the the 8th bit of the first byte,\nnot the first bit of a new byte.\n\n6.4. A note about 16-bits per channel and endianness\n----------------------------------------------------\n\nLodePNG uses unsigned char arrays for 16-bit per channel colors too, just like\nfor any other color format. The 16-bit values are stored in big endian (most\nsignificant byte first) in these arrays. This is the opposite order of the\nlittle endian used by x86 CPU's.\n\nLodePNG always uses big endian because the PNG file format does so internally.\nConversions to other formats than PNG uses internally are not supported by\nLodePNG on purpose, there are myriads of formats, including endianness of 16-bit\ncolors, the order in which you store R, G, B and A, and so on. Supporting and\nconverting to/from all that is outside the scope of LodePNG.\n\nThis may mean that, depending on your use case, you may want to convert the big\nendian output of LodePNG to little endian with a for loop. This is certainly not\nalways needed, many applications and libraries support big endian 16-bit colors\nanyway, but it means you cannot simply cast the unsigned char* buffer to an\nunsigned short* buffer on x86 CPUs.\n\n\n7. error values\n---------------\n\nAll functions in LodePNG that return an error code, return 0 if everything went\nOK, or a non-zero code if there was an error.\n\nThe meaning of the LodePNG error values can be retrieved with the function\nlodepng_error_text: given the numerical error code, it returns a description\nof the error in English as a string.\n\nCheck the implementation of lodepng_error_text to see the meaning of each code.\n\n\n8. chunks and PNG editing\n-------------------------\n\nIf you want to add extra chunks to a PNG you encode, or use LodePNG for a PNG\neditor that should follow the rules about handling of unknown chunks, or if your\nprogram is able to read other types of chunks than the ones handled by LodePNG,\nthen that's possible with the chunk functions of LodePNG.\n\nA PNG chunk has the following layout:\n\n4 bytes length\n4 bytes type name\nlength bytes data\n4 bytes CRC\n\n8.1. iterating through chunks\n-----------------------------\n\nIf you have a buffer containing the PNG image data, then the first chunk (the\nIHDR chunk) starts at byte number 8 of that buffer. The first 8 bytes are the\nsignature of the PNG and are not part of a chunk. But if you start at byte 8\nthen you have a chunk, and can check the following things of it.\n\nNOTE: none of these functions check for memory buffer boundaries. To avoid\nexploits, always make sure the buffer contains all the data of the chunks.\nWhen using lodepng_chunk_next, make sure the returned value is within the\nallocated memory.\n\nunsigned lodepng_chunk_length(const unsigned char* chunk):\n\nGet the length of the chunk's data. The total chunk length is this length + 12.\n\nvoid lodepng_chunk_type(char type[5], const unsigned char* chunk):\nunsigned char lodepng_chunk_type_equals(const unsigned char* chunk, const char* type):\n\nGet the type of the chunk or compare if it's a certain type\n\nunsigned char lodepng_chunk_critical(const unsigned char* chunk):\nunsigned char lodepng_chunk_private(const unsigned char* chunk):\nunsigned char lodepng_chunk_safetocopy(const unsigned char* chunk):\n\nCheck if the chunk is critical in the PNG standard (only IHDR, PLTE, IDAT and IEND are).\nCheck if the chunk is private (public chunks are part of the standard, private ones not).\nCheck if the chunk is safe to copy. If it's not, then, when modifying data in a critical\nchunk, unsafe to copy chunks of the old image may NOT be saved in the new one if your\nprogram doesn't handle that type of unknown chunk.\n\nunsigned char* lodepng_chunk_data(unsigned char* chunk):\nconst unsigned char* lodepng_chunk_data_const(const unsigned char* chunk):\n\nGet a pointer to the start of the data of the chunk.\n\nunsigned lodepng_chunk_check_crc(const unsigned char* chunk):\nvoid lodepng_chunk_generate_crc(unsigned char* chunk):\n\nCheck if the crc is correct or generate a correct one.\n\nunsigned char* lodepng_chunk_next(unsigned char* chunk):\nconst unsigned char* lodepng_chunk_next_const(const unsigned char* chunk):\n\nIterate to the next chunk. This works if you have a buffer with consecutive chunks. Note that these\nfunctions do no boundary checking of the allocated data whatsoever, so make sure there is enough\ndata available in the buffer to be able to go to the next chunk.\n\nunsigned lodepng_chunk_append(unsigned char** out, size_t* outlength, const unsigned char* chunk):\nunsigned lodepng_chunk_create(unsigned char** out, size_t* outlength, unsigned length,\n                              const char* type, const unsigned char* data):\n\nThese functions are used to create new chunks that are appended to the data in *out that has\nlength *outlength. The append function appends an existing chunk to the new data. The create\nfunction creates a new chunk with the given parameters and appends it. Type is the 4-letter\nname of the chunk.\n\n8.2. chunks in info_png\n-----------------------\n\nThe LodePNGInfo struct contains fields with the unknown chunk in it. It has 3\nbuffers (each with size) to contain 3 types of unknown chunks:\nthe ones that come before the PLTE chunk, the ones that come between the PLTE\nand the IDAT chunks, and the ones that come after the IDAT chunks.\nIt's necessary to make the distionction between these 3 cases because the PNG\nstandard forces to keep the ordering of unknown chunks compared to the critical\nchunks, but does not force any other ordering rules.\n\ninfo_png.unknown_chunks_data[0] is the chunks before PLTE\ninfo_png.unknown_chunks_data[1] is the chunks after PLTE, before IDAT\ninfo_png.unknown_chunks_data[2] is the chunks after IDAT\n\nThe chunks in these 3 buffers can be iterated through and read by using the same\nway described in the previous subchapter.\n\nWhen using the decoder to decode a PNG, you can make it store all unknown chunks\nif you set the option settings.remember_unknown_chunks to 1. By default, this\noption is off (0).\n\nThe encoder will always encode unknown chunks that are stored in the info_png.\nIf you need it to add a particular chunk that isn't known by LodePNG, you can\nuse lodepng_chunk_append or lodepng_chunk_create to the chunk data in\ninfo_png.unknown_chunks_data[x].\n\nChunks that are known by LodePNG should not be added in that way. E.g. to make\nLodePNG add a bKGD chunk, set background_defined to true and add the correct\nparameters there instead.\n\n\n9. compiler support\n-------------------\n\nNo libraries other than the current standard C library are needed to compile\nLodePNG. For the C++ version, only the standard C++ library is needed on top.\nAdd the files lodepng.c(pp) and lodepng.h to your project, include\nlodepng.h where needed, and your program can read/write PNG files.\n\nIt is compatible with C90 and up, and C++03 and up.\n\nIf performance is important, use optimization when compiling! For both the\nencoder and decoder, this makes a large difference.\n\nMake sure that LodePNG is compiled with the same compiler of the same version\nand with the same settings as the rest of the program, or the interfaces with\nstd::vectors and std::strings in C++ can be incompatible.\n\nCHAR_BITS must be 8 or higher, because LodePNG uses unsigned chars for octets.\n\n*) gcc and g++\n\nLodePNG is developed in gcc so this compiler is natively supported. It gives no\nwarnings with compiler options \"-Wall -Wextra -pedantic -ansi\", with gcc and g++\nversion 4.7.1 on Linux, 32-bit and 64-bit.\n\n*) Clang\n\nFully supported and warning-free.\n\n*) Mingw\n\nThe Mingw compiler (a port of gcc for Windows) should be fully supported by\nLodePNG.\n\n*) Visual Studio and Visual C++ Express Edition\n\nLodePNG should be warning-free with warning level W4. Two warnings were disabled\nwith pragmas though: warning 4244 about implicit conversions, and warning 4996\nwhere it wants to use a non-standard function fopen_s instead of the standard C\nfopen.\n\nVisual Studio may want \"stdafx.h\" files to be included in each source file and\ngive an error \"unexpected end of file while looking for precompiled header\".\nThis is not standard C++ and will not be added to the stock LodePNG. You can\ndisable it for lodepng.cpp only by right clicking it, Properties, C/C++,\nPrecompiled Headers, and set it to Not Using Precompiled Headers there.\n\nNOTE: Modern versions of VS should be fully supported, but old versions, e.g.\nVS6, are not guaranteed to work.\n\n*) Compilers on Macintosh\n\nLodePNG has been reported to work both with gcc and LLVM for Macintosh, both for\nC and C++.\n\n*) Other Compilers\n\nIf you encounter problems on any compilers, feel free to let me know and I may\ntry to fix it if the compiler is modern and standards complient.\n\n\n10. examples\n------------\n\nThis decoder example shows the most basic usage of LodePNG. More complex\nexamples can be found on the LodePNG website.\n\n10.1. decoder C++ example\n-------------------------\n\n#include \"lodepng.h\"\n#include <iostream>\n\nint main(int argc, char *argv[])\n{\n  const char* filename = argc > 1 ? argv[1] : \"test.png\";\n\n  //load and decode\n  std::vector<unsigned char> image;\n  unsigned width, height;\n  unsigned error = lodepng::decode(image, width, height, filename);\n\n  //if there's an error, display it\n  if(error) std::cout << \"decoder error \" << error << \": \" << lodepng_error_text(error) << std::endl;\n\n  //the pixels are now in the vector \"image\", 4 bytes per pixel, ordered RGBARGBA..., use it as texture, draw it, ...\n}\n\n10.2. decoder C example\n-----------------------\n\n#include \"lodepng.h\"\n\nint main(int argc, char *argv[])\n{\n  unsigned error;\n  unsigned char* image;\n  size_t width, height;\n  const char* filename = argc > 1 ? argv[1] : \"test.png\";\n\n  error = lodepng_decode32_file(&image, &width, &height, filename);\n\n  if(error) printf(\"decoder error %u: %s\\n\", error, lodepng_error_text(error));\n\n  / * use image here * /\n\n  free(image);\n  return 0;\n}\n\n11. state settings reference\n----------------------------\n\nA quick reference of some settings to set on the LodePNGState\n\nFor decoding:\n\nstate.decoder.zlibsettings.ignore_adler32: ignore ADLER32 checksums\nstate.decoder.zlibsettings.custom_...: use custom inflate function\nstate.decoder.ignore_crc: ignore CRC checksums\nstate.decoder.color_convert: convert internal PNG color to chosen one\nstate.decoder.read_text_chunks: whether to read in text metadata chunks\nstate.decoder.remember_unknown_chunks: whether to read in unknown chunks\nstate.info_raw.colortype: desired color type for decoded image\nstate.info_raw.bitdepth: desired bit depth for decoded image\nstate.info_raw....: more color settings, see struct LodePNGColorMode\nstate.info_png....: no settings for decoder but ouput, see struct LodePNGInfo\n\nFor encoding:\n\nstate.encoder.zlibsettings.btype: disable compression by setting it to 0\nstate.encoder.zlibsettings.use_lz77: use LZ77 in compression\nstate.encoder.zlibsettings.windowsize: tweak LZ77 windowsize\nstate.encoder.zlibsettings.minmatch: tweak min LZ77 length to match\nstate.encoder.zlibsettings.nicematch: tweak LZ77 match where to stop searching\nstate.encoder.zlibsettings.lazymatching: try one more LZ77 matching\nstate.encoder.zlibsettings.custom_...: use custom deflate function\nstate.encoder.auto_convert: choose optimal PNG color type, if 0 uses info_png\nstate.encoder.filter_palette_zero: PNG filter strategy for palette\nstate.encoder.filter_strategy: PNG filter strategy to encode with\nstate.encoder.force_palette: add palette even if not encoding to one\nstate.encoder.add_id: add LodePNG identifier and version as a text chunk\nstate.encoder.text_compression: use compressed text chunks for metadata\nstate.info_raw.colortype: color type of raw input image you provide\nstate.info_raw.bitdepth: bit depth of raw input image you provide\nstate.info_raw: more color settings, see struct LodePNGColorMode\nstate.info_png.color.colortype: desired color type if auto_convert is false\nstate.info_png.color.bitdepth: desired bit depth if auto_convert is false\nstate.info_png.color....: more color settings, see struct LodePNGColorMode\nstate.info_png....: more PNG related settings, see struct LodePNGInfo\n\n\n12. changes\n-----------\n\nThe version number of LodePNG is the date of the change given in the format\nyyyymmdd.\n\nSome changes aren't backwards compatible. Those are indicated with a (!)\nsymbol.\n\n*) 18 apr 2016: Changed qsort to custom stable sort (for platforms w/o qsort).\n*) 09 apr 2016: Fixed colorkey usage detection, and better file loading (within\n   the limits of pure C90).\n*) 08 dec 2015: Made load_file function return error if file can't be opened.\n*) 24 okt 2015: Bugfix with decoding to palette output.\n*) 18 apr 2015: Boundary PM instead of just package-merge for faster encoding.\n*) 23 aug 2014: Reduced needless memory usage of decoder.\n*) 28 jun 2014: Removed fix_png setting, always support palette OOB for\n    simplicity. Made ColorProfile public.\n*) 09 jun 2014: Faster encoder by fixing hash bug and more zeros optimization.\n*) 22 dec 2013: Power of two windowsize required for optimization.\n*) 15 apr 2013: Fixed bug with LAC_ALPHA and color key.\n*) 25 mar 2013: Added an optional feature to ignore some PNG errors (fix_png).\n*) 11 mar 2013 (!): Bugfix with custom free. Changed from \"my\" to \"lodepng_\"\n    prefix for the custom allocators and made it possible with a new #define to\n    use custom ones in your project without needing to change lodepng's code.\n*) 28 jan 2013: Bugfix with color key.\n*) 27 okt 2012: Tweaks in text chunk keyword length error handling.\n*) 8 okt 2012 (!): Added new filter strategy (entropy) and new auto color mode.\n    (no palette). Better deflate tree encoding. New compression tweak settings.\n    Faster color conversions while decoding. Some internal cleanups.\n*) 23 sep 2012: Reduced warnings in Visual Studio a little bit.\n*) 1 sep 2012 (!): Removed #define's for giving custom (de)compression functions\n    and made it work with function pointers instead.\n*) 23 jun 2012: Added more filter strategies. Made it easier to use custom alloc\n    and free functions and toggle #defines from compiler flags. Small fixes.\n*) 6 may 2012 (!): Made plugging in custom zlib/deflate functions more flexible.\n*) 22 apr 2012 (!): Made interface more consistent, renaming a lot. Removed\n    redundant C++ codec classes. Reduced amount of structs. Everything changed,\n    but it is cleaner now imho and functionality remains the same. Also fixed\n    several bugs and shrunk the implementation code. Made new samples.\n*) 6 nov 2011 (!): By default, the encoder now automatically chooses the best\n    PNG color model and bit depth, based on the amount and type of colors of the\n    raw image. For this, autoLeaveOutAlphaChannel replaced by auto_choose_color.\n*) 9 okt 2011: simpler hash chain implementation for the encoder.\n*) 8 sep 2011: lz77 encoder lazy matching instead of greedy matching.\n*) 23 aug 2011: tweaked the zlib compression parameters after benchmarking.\n    A bug with the PNG filtertype heuristic was fixed, so that it chooses much\n    better ones (it's quite significant). A setting to do an experimental, slow,\n    brute force search for PNG filter types is added.\n*) 17 aug 2011 (!): changed some C zlib related function names.\n*) 16 aug 2011: made the code less wide (max 120 characters per line).\n*) 17 apr 2011: code cleanup. Bugfixes. Convert low to 16-bit per sample colors.\n*) 21 feb 2011: fixed compiling for C90. Fixed compiling with sections disabled.\n*) 11 dec 2010: encoding is made faster, based on suggestion by Peter Eastman\n    to optimize long sequences of zeros.\n*) 13 nov 2010: added LodePNG_InfoColor_hasPaletteAlpha and\n    LodePNG_InfoColor_canHaveAlpha functions for convenience.\n*) 7 nov 2010: added LodePNG_error_text function to get error code description.\n*) 30 okt 2010: made decoding slightly faster\n*) 26 okt 2010: (!) changed some C function and struct names (more consistent).\n     Reorganized the documentation and the declaration order in the header.\n*) 08 aug 2010: only changed some comments and external samples.\n*) 05 jul 2010: fixed bug thanks to warnings in the new gcc version.\n*) 14 mar 2010: fixed bug where too much memory was allocated for char buffers.\n*) 02 sep 2008: fixed bug where it could create empty tree that linux apps could\n    read by ignoring the problem but windows apps couldn't.\n*) 06 jun 2008: added more error checks for out of memory cases.\n*) 26 apr 2008: added a few more checks here and there to ensure more safety.\n*) 06 mar 2008: crash with encoding of strings fixed\n*) 02 feb 2008: support for international text chunks added (iTXt)\n*) 23 jan 2008: small cleanups, and #defines to divide code in sections\n*) 20 jan 2008: support for unknown chunks allowing using LodePNG for an editor.\n*) 18 jan 2008: support for tIME and pHYs chunks added to encoder and decoder.\n*) 17 jan 2008: ability to encode and decode compressed zTXt chunks added\n    Also various fixes, such as in the deflate and the padding bits code.\n*) 13 jan 2008: Added ability to encode Adam7-interlaced images. Improved\n    filtering code of encoder.\n*) 07 jan 2008: (!) changed LodePNG to use ISO C90 instead of C++. A\n    C++ wrapper around this provides an interface almost identical to before.\n    Having LodePNG be pure ISO C90 makes it more portable. The C and C++ code\n    are together in these files but it works both for C and C++ compilers.\n*) 29 dec 2007: (!) changed most integer types to unsigned int + other tweaks\n*) 30 aug 2007: bug fixed which makes this Borland C++ compatible\n*) 09 aug 2007: some VS2005 warnings removed again\n*) 21 jul 2007: deflate code placed in new namespace separate from zlib code\n*) 08 jun 2007: fixed bug with 2- and 4-bit color, and small interlaced images\n*) 04 jun 2007: improved support for Visual Studio 2005: crash with accessing\n    invalid std::vector element [0] fixed, and level 3 and 4 warnings removed\n*) 02 jun 2007: made the encoder add a tag with version by default\n*) 27 may 2007: zlib and png code separated (but still in the same file),\n    simple encoder/decoder functions added for more simple usage cases\n*) 19 may 2007: minor fixes, some code cleaning, new error added (error 69),\n    moved some examples from here to lodepng_examples.cpp\n*) 12 may 2007: palette decoding bug fixed\n*) 24 apr 2007: changed the license from BSD to the zlib license\n*) 11 mar 2007: very simple addition: ability to encode bKGD chunks.\n*) 04 mar 2007: (!) tEXt chunk related fixes, and support for encoding\n    palettized PNG images. Plus little interface change with palette and texts.\n*) 03 mar 2007: Made it encode dynamic Huffman shorter with repeat codes.\n    Fixed a bug where the end code of a block had length 0 in the Huffman tree.\n*) 26 feb 2007: Huffman compression with dynamic trees (BTYPE 2) now implemented\n    and supported by the encoder, resulting in smaller PNGs at the output.\n*) 27 jan 2007: Made the Adler-32 test faster so that a timewaste is gone.\n*) 24 jan 2007: gave encoder an error interface. Added color conversion from any\n    greyscale type to 8-bit greyscale with or without alpha.\n*) 21 jan 2007: (!) Totally changed the interface. It allows more color types\n    to convert to and is more uniform. See the manual for how it works now.\n*) 07 jan 2007: Some cleanup & fixes, and a few changes over the last days:\n    encode/decode custom tEXt chunks, separate classes for zlib & deflate, and\n    at last made the decoder give errors for incorrect Adler32 or Crc.\n*) 01 jan 2007: Fixed bug with encoding PNGs with less than 8 bits per channel.\n*) 29 dec 2006: Added support for encoding images without alpha channel, and\n    cleaned out code as well as making certain parts faster.\n*) 28 dec 2006: Added \"Settings\" to the encoder.\n*) 26 dec 2006: The encoder now does LZ77 encoding and produces much smaller files now.\n    Removed some code duplication in the decoder. Fixed little bug in an example.\n*) 09 dec 2006: (!) Placed output parameters of public functions as first parameter.\n    Fixed a bug of the decoder with 16-bit per color.\n*) 15 okt 2006: Changed documentation structure\n*) 09 okt 2006: Encoder class added. It encodes a valid PNG image from the\n    given image buffer, however for now it's not compressed.\n*) 08 sep 2006: (!) Changed to interface with a Decoder class\n*) 30 jul 2006: (!) LodePNG_InfoPng , width and height are now retrieved in different\n    way. Renamed decodePNG to decodePNGGeneric.\n*) 29 jul 2006: (!) Changed the interface: image info is now returned as a\n    struct of type LodePNG::LodePNG_Info, instead of a vector, which was a bit clumsy.\n*) 28 jul 2006: Cleaned the code and added new error checks.\n    Corrected terminology \"deflate\" into \"inflate\".\n*) 23 jun 2006: Added SDL example in the documentation in the header, this\n    example allows easy debugging by displaying the PNG and its transparency.\n*) 22 jun 2006: (!) Changed way to obtain error value. Added\n    loadFile function for convenience. Made decodePNG32 faster.\n*) 21 jun 2006: (!) Changed type of info vector to unsigned.\n    Changed position of palette in info vector. Fixed an important bug that\n    happened on PNGs with an uncompressed block.\n*) 16 jun 2006: Internally changed unsigned into unsigned where\n    needed, and performed some optimizations.\n*) 07 jun 2006: (!) Renamed functions to decodePNG and placed them\n    in LodePNG namespace. Changed the order of the parameters. Rewrote the\n    documentation in the header. Renamed files to lodepng.cpp and lodepng.h\n*) 22 apr 2006: Optimized and improved some code\n*) 07 sep 2005: (!) Changed to std::vector interface\n*) 12 aug 2005: Initial release (C++, decoder only)\n\n\n13. contact information\n-----------------------\n\nFeel free to contact me with suggestions, problems, comments, ... concerning\nLodePNG. If you encounter a PNG image that doesn't work properly with this\ndecoder, feel free to send it and I'll use it to find and fix the problem.\n\nMy email address is (puzzle the account and domain together with an @ symbol):\nDomain: gmail dot com.\nAccount: lode dot vandevenne.\n\n\nCopyright (c) 2005-2016 Lode Vandevenne\n*/\n"
  },
  {
    "path": "tools/src/common/logging.h",
    "content": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at http://mozilla.org/MPL/2.0/. */\n\n#ifndef _ACE_TOOLS_COMMON_LOGGING_H_\n#define _ACE_TOOLS_COMMON_LOGGING_H_\n\n#include <fmt/format.h>\n\nnamespace nLog {\n\ntemplate<typename... t_tArgs>\nvoid error(fmt::format_string<t_tArgs...> szFmt, t_tArgs&&... Args) {\n\tfmt::print(\"ERR: \");\n\tfmt::print(szFmt, std::forward<t_tArgs>(Args)...);\n\tfmt::print(\"\\n\");\n}\n\ntemplate<typename... t_tArgs>\nvoid warn(fmt::format_string<t_tArgs...> szFmt, const t_tArgs&&... Args) {\n\tfmt::print(\"WARN: \");\n\tfmt::print(szFmt, std::forward<t_tArgs>(Args)...);\n\tfmt::print(\"\\n\");\n}\n\n} // namespace nLog\n\n#endif // _ACE_TOOLS_COMMON_LOGGING_H_\n"
  },
  {
    "path": "tools/src/common/math.h",
    "content": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at http://mozilla.org/MPL/2.0/. */\n\n#ifndef _ACE_TOOLS_COMMON_MATH_H_\n#define _ACE_TOOLS_COMMON_MATH_H_\n\n#if defined(_MSC_VER) && _MSC_VER < 1930\nauto ceilToFactor(std::uint64_t Value, std::int64_t Multiple) {\n#else\nauto ceilToFactor(auto Value, auto Multiple) {\n#endif\n\tauto Rounded = ((Value + Multiple - 1) / Multiple) * Multiple;\n\treturn Rounded;\n}\n\n#endif // _ACE_TOOLS_COMMON_MATH_H_\n"
  },
  {
    "path": "tools/src/common/mod.cpp",
    "content": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at http://mozilla.org/MPL/2.0/. */\n\n#include \"mod.h\"\n#include <fstream>\n#include <exception>\n#include <fmt/format.h>\n#include \"endian.h\"\n\n#define SAMPLE_NAME_SIZE 22\n\ntMod::tMod(const std::string &szFileName)\n{\n\tstd::ifstream FileIn;\n\tFileIn.open(szFileName, std::ios::binary);\n\n\tFileIn.seekg(0, std::ios::end);\n\tstd::uint32_t ulFileSize = FileIn.tellg(); // For pattern count calc\n\n\tFileIn.seekg(0, std::ios::beg);\n\n\tchar szSongNameRaw[20];\n\tFileIn.read(szSongNameRaw, sizeof(szSongNameRaw));\n\n\tm_szSongName = szSongNameRaw;\n\n\t// Read sample info\n\tstd::uint32_t ulTotalSampleSize = 0;\n\tfor(std::uint8_t i = 0; i < 31; ++i) {\n\t\tchar szSampleNameRaw[SAMPLE_NAME_SIZE];\n\t\tstd::uint16_t uwSampleLen, uwSampleRepeatOffs, uwSampleRepeatLength;\n\t\tstd::uint8_t ubSampleFineTune, ubSampleLinearVolume;\n\n\t\tFileIn.read(szSampleNameRaw, sizeof(szSampleNameRaw));\n\t\tFileIn.read(\n\t\t\treinterpret_cast<char*>(&uwSampleLen), sizeof(uwSampleLen)\n\t\t); // In words, big endian\n\t\tFileIn.read(\n\t\t\treinterpret_cast<char*>(&ubSampleFineTune), sizeof(ubSampleFineTune)\n\t\t);\n\t\tFileIn.read(\n\t\t\treinterpret_cast<char*>(&ubSampleLinearVolume),\n\t\t\tsizeof(ubSampleLinearVolume)\n\t\t);\n\t\tFileIn.read(\n\t\t\treinterpret_cast<char*>(&uwSampleRepeatOffs), sizeof(uwSampleRepeatOffs)\n\t\t); // In words, big endian\n\t\tFileIn.read(\n\t\t\treinterpret_cast<char*>(&uwSampleRepeatLength), sizeof(uwSampleRepeatLength)\n\t\t); // In words, big endian\n\n\t\t// Convert stuff\n\t\tuwSampleLen = nEndian::fromBig16(uwSampleLen);\n\t\tuwSampleRepeatLength = nEndian::fromBig16(uwSampleRepeatLength);\n\t\tuwSampleRepeatOffs = nEndian::fromBig16(uwSampleRepeatOffs);\n\n\t\t// Data read successfully, fill sample info\n\t\ttSample Sample;\n\t\tfor (std::uint8_t ubCharIndex = 0; ubCharIndex < SAMPLE_NAME_SIZE; ++ubCharIndex){\n\t\t\t// sample name to uppercase, to avoid duplicates\n\t\t\t// will be reworked to: comparison between samples on temporarily uppercased copies\n\t\t\tszSampleNameRaw[ubCharIndex] = std::toupper(szSampleNameRaw[ubCharIndex]);\n\t\t}\n\t\tSample.m_szName = szSampleNameRaw;\n\t\tSample.m_ubFineTune = ubSampleFineTune;\n\t\tSample.m_ubVolume = ubSampleLinearVolume;\n\t\tSample.m_uwRepeatLength = uwSampleRepeatLength;\n\t\tSample.m_uwRepeatOffs = uwSampleRepeatOffs;\n\t\tSample.m_vData.resize(uwSampleLen);\n\t\tm_vSamples.push_back(std::move(Sample));\n\n\t\tulTotalSampleSize += uwSampleLen * 2;\n\t}\n\n\tFileIn.read(reinterpret_cast<char*>(&m_ubArrangementLength), sizeof(m_ubArrangementLength));\n\tFileIn.read(reinterpret_cast<char*>(&m_ubSongEndPos), sizeof(m_ubSongEndPos));\n\n\t// Arrangement - always 128-byte long\n\tm_vArrangement.resize(128);\n\tFileIn.read(reinterpret_cast<char*>(m_vArrangement.data()), 128);\n\n\tchar pTag[5] = {'\\0'};\n\tFileIn.read(pTag, 4);\n\tm_szFileFormatTag = pTag;\n\n\tif(\n\t\tm_szFileFormatTag != \"M.K.\" && m_szFileFormatTag != \"FLT4\" &&\n\t\tm_szFileFormatTag != \"M!K!\" && m_szFileFormatTag != \"4CHN\"\n\t) {\n\t\tfmt::print(\"ERR: unsupported file format tag: {}\", m_szFileFormatTag);\n\t\tthrow std::exception();\n\t}\n\n\t// Determine pattern count\n\tstd::uint32_t ulCurrPos = FileIn.tellg();\n\tstd::uint32_t ulPatternDataSize = (ulFileSize - ulCurrPos - ulTotalSampleSize);\n\tif((ulPatternDataSize / 1024) * 1024 != ulPatternDataSize) {\n\t\tfmt::print(\"ERR: unexpected size of pattern data!\");\n\t\tthrow std::exception();\n\t}\n\tstd::uint8_t ubPatternCount = (ulFileSize - ulCurrPos - ulTotalSampleSize) / 1024;\n\n\t// Read pattern data\n\tm_vPatterns.resize(ubPatternCount);\n\tfor(std::uint8_t ubPattern = 0; ubPattern < ubPatternCount; ++ubPattern) {\n\t\tfor(std::uint8_t ubRow = 0; ubRow < 64; ++ubRow) {\n\t\t\tstd::array<tNote, 4> NotesInRow;\n\t\t\tfor(std::uint8_t i = 0; i < 4; ++i) {\n\t\t\t\tstd::uint32_t ulRawNote; // [instrumentHi:4] [period:12] [instrumentLo:4] [cmdNo:4] [cmdArg:8]\n\t\t\t\tFileIn.read(reinterpret_cast<char*>(&ulRawNote), sizeof(ulRawNote));\n\t\t\t\tulRawNote = nEndian::fromBig32(ulRawNote);\n\t\t\t\ttNote Note = {\n\t\t\t\t\t.ubInstrument = uint8_t(((ulRawNote & 0xF0'00'00'00) >> 24) | ((ulRawNote & 0xF0'00) >> 12)),\n\t\t\t\t\t.uwPeriod =     uint16_t((ulRawNote & 0x0F'FF'00'00) >> 16),\n\t\t\t\t\t.ubCmd =         uint8_t((ulRawNote & 0x00'00'0F'00) >> 8),\n\t\t\t\t\t.ubCmdArg =       uint8_t(ulRawNote & 0x00'00'00'FF),\n\t\t\t\t};\n\t\t\t\tNotesInRow[i] = std::move(Note);\n\t\t\t}\n\t\t\tm_vPatterns[ubPattern].push_back(NotesInRow);\n\t\t}\n\t}\n\n\t// Read sample data\n\tfor(auto &Sample: m_vSamples) {\n\t\t// Read raw sample data\n\t\tFileIn.read(\n\t\t\treinterpret_cast<char*>(Sample.m_vData.data()),\n\t\t\tSample.m_vData.size() * sizeof(Sample.m_vData[0])\n\t\t);\n\t}\n}\n\nvoid tMod::toMod(const std::string &szFileName, bool isSkipSampleData)\n{\n\tstd::ofstream FileOut;\n\tFileOut.open(szFileName, std::ios::binary);\n\n\t// Song name - without garbage after null terminator\n\tchar szSongNameRaw[20] = {'\\0'};\n\tstrcpy(szSongNameRaw, m_szSongName.c_str());\n\tFileOut.write(szSongNameRaw, sizeof(szSongNameRaw));\n\n\t// Samples\n\tfor(const auto &Sample: m_vSamples) {\n\t\tstd::uint16_t uwSampleLen = nEndian::toBig16(Sample.m_vData.size());\n\t\tstd::uint16_t uwSampleRepeatOffs = nEndian::toBig16(Sample.m_uwRepeatOffs);\n\t\tstd::uint16_t uwSampleRepeatLength = nEndian::toBig16(Sample.m_uwRepeatLength);\n\n\t\t// Ensure that garbage after null terminator doesn't get copied\n\t\tchar szSampleNameRaw[22] = {'\\0'};\n\t\tstrcpy(szSampleNameRaw, Sample.m_szName.c_str());\n\n\t\tFileOut.write(szSampleNameRaw, sizeof(szSampleNameRaw));\n\t\tFileOut.write(\n\t\t\treinterpret_cast<char*>(&uwSampleLen), sizeof(uwSampleLen)\n\t\t); // In words, big endian\n\t\tFileOut.write(\n\t\t\treinterpret_cast<const char*>(&Sample.m_ubFineTune), sizeof(Sample.m_ubFineTune)\n\t\t);\n\t\tFileOut.write(\n\t\t\treinterpret_cast<const char*>(&Sample.m_ubVolume), sizeof(Sample.m_ubVolume)\n\t\t);\n\t\tFileOut.write(\n\t\t\treinterpret_cast<char*>(&uwSampleRepeatOffs), sizeof(uwSampleRepeatOffs)\n\t\t); // In words, big endian\n\t\tFileOut.write(\n\t\t\treinterpret_cast<char*>(&uwSampleRepeatLength), sizeof(uwSampleRepeatLength)\n\t\t); // In words, big endian\n\t}\n\n\t// Pattern count, song end jump pos\n\tFileOut.write(reinterpret_cast<char*>(&m_ubArrangementLength), sizeof(m_ubArrangementLength));\n\tFileOut.write(reinterpret_cast<char*>(&m_ubSongEndPos), sizeof(m_ubSongEndPos));\n\n\t// Pattern table\n\tFileOut.write(reinterpret_cast<char*>(m_vArrangement.data()), m_vArrangement.size());\n\n\t// File format tag\n\tFileOut.write(m_szFileFormatTag.data(), 4);\n\n\t// Pattern data\n\tfor(const auto &Pattern: m_vPatterns) {\n\t\tfor(std::uint8_t ubRow = 0; ubRow < 64; ++ubRow) {\n\t\t\tfor(std::uint8_t ubChan = 0; ubChan < 4; ++ubChan) {\n\t\t\t\tconst auto Note = &Pattern[ubRow][ubChan];\n\t\t\t\t// [instrumentHi:4] [period:12] [instrumentLo:4] [cmdNo:4] [cmdArg:8]\n\t\t\t\tstd::uint32_t ulNoteRaw = nEndian::toBig32(\n\t\t\t\t\t((Note->ubInstrument & 0xF0  ) << 24) |\n\t\t\t\t\t((Note->uwPeriod     & 0x0FFF) << 16) |\n\t\t\t\t\t((Note->ubInstrument & 0x0F  ) << 12) |\n\t\t\t\t\t((Note->ubCmd & 0xF) << 8) | (Note->ubCmdArg & 0xFF)\n\t\t\t\t);\n\t\t\t\tFileOut.write(reinterpret_cast<char*>(&ulNoteRaw), sizeof(ulNoteRaw));\n\t\t\t\tFileOut.flush();\n\t\t\t}\n\t\t}\n\t}\n\n\tif(!isSkipSampleData) {\n\t\t// Sample data\n\t\tfor(const auto &Sample: m_vSamples) {\n\t\t\tFileOut.write(\n\t\t\t\treinterpret_cast<const char*>(Sample.m_vData.data()),\n\t\t\t\tSample.m_vData.size() * 2\n\t\t\t);\n\t\t}\n\t}\n}\n\nconst std::vector<tSample> &tMod::getSamples(void) const\n{\n\treturn m_vSamples;\n}\n\nconst std::string &tMod::getSongName(void) const\n{\n\treturn m_szSongName;\n}\n\nvoid tMod::reorderSamples(const std::vector<uint8_t> vNewOrder)\n{\n\t// Generate reordered sample defs - do it on copy because of X->Y & Y->X\n\tstd::vector<tSample> vSamplesNew(m_vSamples.size());\n\tfor(std::uint8_t ubOldIdx = 0; ubOldIdx < vNewOrder.size(); ++ubOldIdx) {\n\t\tif(!m_vSamples[ubOldIdx].m_szName.empty()) {\n\t\t\tstd::uint8_t ubNewIdx = vNewOrder[ubOldIdx];\n\t\t\tvSamplesNew[ubNewIdx] = m_vSamples[ubOldIdx];\n\t\t}\n\t}\n\n\t// Replace all at once\n\tm_vSamples = vSamplesNew;\n\n\t// Replace sample index in patterns\n\tfor(auto &Pattern: m_vPatterns) {\n\t\tfor(auto &Row: Pattern) {\n\t\t\tfor(auto &Channel: Row) {\n\t\t\t\tif(Channel.ubInstrument) {\n\t\t\t\t\t// instruments are starting with 1, zero means \"none\"\n\t\t\t\t\tChannel.ubInstrument = vNewOrder[Channel.ubInstrument - 1] + 1;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\n\nvoid tMod::clearSampleData(void)\n{\n\tfor(auto &Sample: m_vSamples) {\n\t\tSample.m_vData.clear();\n\t}\n}\n\nbool tSample::operator ==(const tSample &Other) const\n{\n\tbool isSame = (\n\t\tm_szName == Other.m_szName &&\n\t\tm_ubFineTune == Other.m_ubFineTune &&\n\t\tm_ubVolume == Other.m_ubVolume &&\n\t\tm_uwRepeatLength == Other.m_uwRepeatLength &&\n\t\tm_uwRepeatOffs == Other.m_uwRepeatOffs &&\n\t\tm_vData == Other.m_vData\n\t);\n\treturn isSame;\n}\n"
  },
  {
    "path": "tools/src/common/mod.h",
    "content": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at http://mozilla.org/MPL/2.0/. */\n\n#ifndef _ACE_TOOLS_COMMON_MOD_H_\n#define _ACE_TOOLS_COMMON_MOD_H_\n\n#include <vector>\n#include <array>\n#include <string>\n#include <cstdint>\n\nstruct tSample {\n\tstd::string m_szName;\n\tstd::uint8_t m_ubFineTune; ///< Finetune. Only lower nibble is used. Values translate to finetune: {0..7, -8..-1}\n\tstd::uint8_t m_ubVolume; ///< Sample volume. 0..64\n\tstd::uint16_t m_uwRepeatOffs; ///< In words.\n\tstd::uint16_t m_uwRepeatLength; ///< In words.\n\n\tstd::vector<uint16_t> m_vData;\n\n\tbool operator ==(const tSample &Other) const;\n\tbool operator !=(const tSample &Other) const\n\t{\n\t\treturn !(*this == Other);\n\t}\n};\n\nstruct tNote {\n\tstd::uint8_t ubInstrument;\n\tstd::uint16_t uwPeriod;\n\tstd::uint8_t ubCmd;\n\tstd::uint8_t ubCmdArg;\n};\n\nclass tMod {\npublic:\n\ttMod(const std::string &szFileName);\n\n\tvoid toMod(const std::string &szFileName, bool isSkipSampleData);\n\n\tconst std::vector<tSample> &getSamples(void) const;\n\n\tconst std::string &getSongName(void) const;\n\n\tvoid setSamples(std::vector<tSample> &vSamplesNew);\n\n\t/**\n\t * @brief Reorder samples in module using the index array.\n\t * Reorder values for empty samples are ignored.\n\t *\n\t * @param vNewOrder Vector index is old sample idx, value is new sample idx.\n\t */\n\tvoid reorderSamples(const std::vector<uint8_t> vNewOrder);\n\n\tvoid clearSampleData(void);\n\nprivate:\n\tstd::string m_szSongName;\n\tstd::uint8_t m_ubArrangementLength; ///< End pattern idx? Jumps are possible.\n\tstd::uint8_t m_ubSongEndPos;\n\tstd::string m_szFileFormatTag;  ///< Should be \"M.K.\" for 31-sample format.\n\n\tstd::vector<tSample> m_vSamples;\n\n\tstd::vector<std::vector<std::array<tNote, 4>>> m_vPatterns;\n\n\t/**\n\t * @brief Song arrangement list (pattern sequence table).\n\t * These list up to 128 pattern numbers and the order they should be played in.\n\t */\n\tstd::vector<uint8_t> m_vArrangement;\n};\n\n#endif // _ACE_TOOLS_COMMON_MOD_H_\n"
  },
  {
    "path": "tools/src/common/palette.cpp",
    "content": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at http://mozilla.org/MPL/2.0/. */\n\n#include \"palette.h\"\n#include <fstream>\n#include <sstream>\n#include <stdexcept>\n#include \"fs.h\"\n#include \"stream.h\"\n#include \"endian.h\"\n#include <fmt/format.h>\n\nnamespace {\n\nconstexpr std::uint8_t PLT_NEW_OCS = 0;\nconstexpr std::uint8_t PLT_NEW_AGA = 1;\n\n} // namespace\n\nstatic bool beginsWith(\n\tconst std::string &szHaystack, const std::string &szNeedle\n) {\n\tif(szHaystack.length() < szNeedle.length()) {\n\t\treturn false;\n\t}\n\treturn szHaystack.substr(0, szNeedle.length()) == szNeedle;\n}\n\ntPalette tPalette::fromGpl(const std::string &szPath) {\n\ttPalette Palette;\n\tstd::ifstream Source(szPath, std::ios::in);\n\tif(!Source.good()) {\n\t\treturn {};\n\t}\n\n\t// Skip header\n\tstd::string szLine;\n\tdo {\n\t\tnStream::getAnyLine(Source, szLine);\n\t} while(!Source.eof() && (\n\t\tbeginsWith(szLine, \"GIMP Palette\") ||\n\t\tbeginsWith(szLine, \"Name:\") ||\n\t\tbeginsWith(szLine, \"Columns:\") ||\n\t\tbeginsWith(szLine, \"#\")\n\t\t));\n\n\t// Read colors\n\tbool isEnd = false;\n\tdo {\n\t\tif(!szLine.empty() && !beginsWith(szLine, \"#\")) {\n\t\t\tstd::stringstream ss(szLine);\n\t\t\tint r, g, b;\n\t\t\tss >> r;\n\t\t\tss >> g;\n\t\t\tss >> b;\n\t\t\ttRgb Color(r, g, b);\n\t\t\tPalette.m_vColors.push_back(Color);\n\t\t}\n\n\t\tif(Source.eof()) {\n\t\t\tisEnd = true;\n\t\t}\n\t\telse {\n\t\t\tnStream::getAnyLine(Source, szLine);\n\t\t}\n\t} while(!isEnd);\n\n\tfmt::print(\"Palette color count: {}\\n\", Palette.m_vColors.size());\n\treturn Palette;\n}\n\ntPalette tPalette::fromPlt(const std::string &szPath) {\n\ttPalette Palette;\n\n\tstd::ifstream Source(szPath, std::ios::in | std::ios::binary);\n\n\tstd::uint8_t ubFirst = 0;\n\tSource.read(reinterpret_cast<char*>(&ubFirst), 1);\n\n\tif(ubFirst <= 1) {\n\t\tstd::uint16_t uwWire = 0;\n\t\tSource.read(reinterpret_cast<char*>(&uwWire), sizeof(uwWire));\n\t\tstd::uint16_t uwNumColors = nEndian::fromBig16(uwWire);\n\n\t\tfmt::print(\"Palette color count (v2): {}\\n\", uwNumColors);\n\n\t\tfor(std::uint16_t i = 0; i < uwNumColors; ++i) {\n\t\t\tif(ubFirst == PLT_NEW_OCS) {\n\t\t\t\tstd::uint8_t ubXR, ubGB;\n\t\t\t\tSource.read(reinterpret_cast<char*>(&ubXR), 1);\n\t\t\t\tSource.read(reinterpret_cast<char*>(&ubGB), 1);\n\n\t\t\t\tPalette.m_vColors.push_back(tRgb(\n\t\t\t\t\tstatic_cast<std::uint8_t>(((ubXR & 0x0F) << 4) | (ubXR & 0x0F)),\n\t\t\t\t\tstatic_cast<std::uint8_t>(((ubGB & 0xF0) >> 4) | (ubGB & 0xF0)),\n\t\t\t\t\tstatic_cast<std::uint8_t>(((ubGB & 0x0F) << 4) | (ubGB & 0x0F))));\n\t\t\t}\n\t\t\telse {\n\t\t\t\tstd::uint8_t ubA, ubR, ubG, ubB;\n\t\t\t\tSource.read(reinterpret_cast<char*>(&ubA), 1);\n\t\t\t\tSource.read(reinterpret_cast<char*>(&ubR), 1);\n\t\t\t\tSource.read(reinterpret_cast<char*>(&ubG), 1);\n\t\t\t\tSource.read(reinterpret_cast<char*>(&ubB), 1);\n\n\t\t\t\tPalette.m_vColors.push_back(tRgb(ubR, ubG, ubB));\n\t\t\t}\n\t\t}\n\t\treturn Palette;\n\t}\n\n\tthrow std::runtime_error(\n\t\t\"Legacy .plt (v1) is not supported; re-export with palette_conv to v2.\"\n\t);\n}\n\ntPalette tPalette::fromPromotionPal(const std::string &szPath) {\n\ttPalette Palette;\n\n\tstd::ifstream Source(szPath, std::ios::in | std::ios::binary);\n\n\tstd::uint16_t uwLastNonZero = 0;\n\tfor(std::uint16_t i = 0; i < 256; ++i) {\n\t\tstd::uint8_t ubR, ubG, ubB;\n\n\t\tSource.read(reinterpret_cast<char*>(&ubR), 1);\n\t\tSource.read(reinterpret_cast<char*>(&ubG), 1);\n\t\tSource.read(reinterpret_cast<char*>(&ubB), 1);\n\t\tPalette.m_vColors.push_back(tRgb(ubR, ubG, ubB));\n\t\tif(ubR || ubG || ubB) {\n\t\t\tuwLastNonZero = i;\n\t\t}\n\t}\n\n\t// Palette is always 256 colors long, so now it's time to trim it\n\tPalette.m_vColors = std::vector<tRgb>(\n\t\tPalette.m_vColors.begin(), Palette.m_vColors.begin() + uwLastNonZero + 1\n\t);\n\n\tfmt::print(\"Palette color count: {}\\n\", Palette.m_vColors.size());\n\treturn Palette;\n}\n\ntPalette tPalette::fromAct(const std::string &szPath) {\n\ttPalette Palette;\n\n\tstd::ifstream Source(szPath, std::ios::in | std::ios::binary);\n\n\tfor(std::uint16_t i = 0; i < 256; ++i) {\n\t\tstd::uint8_t ubR, ubG, ubB;\n\n\t\tSource.read(reinterpret_cast<char*>(&ubR), 1);\n\t\tSource.read(reinterpret_cast<char*>(&ubG), 1);\n\t\tSource.read(reinterpret_cast<char*>(&ubB), 1);\n\t\tPalette.m_vColors.push_back(tRgb(ubR, ubG, ubB));\n\t}\n\n\t// Read color count\n\tstd::uint8_t ubSizeHi, ubSizeLo;\n\tstd::uint16_t uwSize;\n\tSource.read(reinterpret_cast<char*>(&ubSizeHi), 1);\n\tSource.read(reinterpret_cast<char*>(&ubSizeLo), 1);\n\tuwSize = (ubSizeHi << 8) | ubSizeLo;\n\n\t// Trim palette\n\tPalette.m_vColors = std::vector<tRgb>(\n\t\tPalette.m_vColors.begin(), Palette.m_vColors.begin() + uwSize\n\t);\n\tfmt::print(\"Palette color count: {}\\n\", Palette.m_vColors.size());\n\treturn Palette;\n}\n\ntPalette tPalette::fromFile(const std::string &szPath) {\n\tstd::string szExtIn = nFs::getExt(szPath);\n\ttPalette Palette;\n\tif(szExtIn == \"gpl\") {\n\t\tPalette = tPalette::fromGpl(szPath);\n\t}\n\telse if(szExtIn == \"act\") {\n\t\t// Looks like it's same as promotion\n\t\tPalette = tPalette::fromAct(szPath);\n\t}\n\telse if(szExtIn == \"pal\") {\n\t\tPalette = tPalette::fromPromotionPal(szPath);\n\t}\n\telse if(szExtIn == \"plt\") {\n\t\tPalette = tPalette::fromPlt(szPath);\n\t}\n\treturn Palette;\n}\n\nbool tPalette::toPlt(\n\tconst std::string &szPath, bool isUseOcs, bool isClampToOcs\n) {\n\tstd::ofstream Dest(szPath, std::ios::out | std::ios::binary);\n\tif(!Dest.is_open()) {\n\t\treturn false;\n\t}\n\tauto PaletteSize = m_vColors.size();\n\n\tstd::uint8_t ubSentinel = isUseOcs ? PLT_NEW_OCS : PLT_NEW_AGA;\n\n\tDest.write(reinterpret_cast<const char*>(&ubSentinel), 1);\n\t{\n\t\tstd::uint16_t uwWire = nEndian::toBig16(PaletteSize);\n\t\tDest.write(reinterpret_cast<const char*>(&uwWire), sizeof(uwWire));\n\t}\n\n\tfor(std::size_t uwColorIdx = 0; uwColorIdx < PaletteSize; ++uwColorIdx) {\n\t\tconst auto &Color = m_vColors[uwColorIdx];\n\t\tif(isUseOcs) {\n\t\t\ttRgb ColorOcs = Color.to12Bit();\n\t\t\tif(!isClampToOcs && ColorOcs != Color) {\n\t\t\t\tthrow std::runtime_error(fmt::format(\n\t\t\t\t\tFMT_STRING(\n\t\t\t\t\t\t\"Color at index {} ({}) is not suited for OCS. \"\n\t\t\t\t\t\t\"Expected 4-bit channels, e.g. {} (use -cc to auto-truncate)\"\n\t\t\t\t\t),\n\t\t\t\t\tuwColorIdx, Color.toString(), ColorOcs.toString()\n\t\t\t\t));\n\t\t\t}\n\n\t\t\tstd::uint8_t ubXR = ColorOcs.ubR >> 4;\n\t\t\tstd::uint8_t ubGB =\n\t\t\t\t((ColorOcs.ubG >> 4) << 4) | (ColorOcs.ubB >> 4);\n\t\t\tDest.write(reinterpret_cast<char*>(&ubXR), 1);\n\t\t\tDest.write(reinterpret_cast<char*>(&ubGB), 1);\n\t\t}\n\t\telse {\n\t\t\tstd::uint8_t alpha = 0;\n\t\t\tDest.write(reinterpret_cast<const char*>(&alpha), 1);\n\t\t\tDest.write(reinterpret_cast<const char*>(&Color.ubR), 1);\n\t\t\tDest.write(reinterpret_cast<const char*>(&Color.ubG), 1);\n\t\t\tDest.write(reinterpret_cast<const char*>(&Color.ubB), 1);\n\t\t}\n\n\t}\n\treturn true;\n}\n\nbool tPalette::toGpl(const std::string &szPath) {\n\tusing namespace nFs;\n\tstd::ofstream Dest(szPath, std::ios::out);\n\tif(!Dest.is_open()) {\n\t\treturn false;\n\t}\n\n\t// Header\n\tDest << \"GIMP Palette\\n\";\n\tDest << fmt::format(\"Name: {}\\n\", removeExt(getBaseName(szPath)));\n\tDest << \"Columns: 4\\n\";\n\tDest << \"#\\n\";\n\n\t// Colors\n\tfor(auto i = 0; i < m_vColors.size(); ++i) {\n\t\tconst auto &Color = m_vColors.at(i);\n\t\tDest << fmt::format(\n\t\t\t\"{:3d} {:3d} {:3d} Index {}\\n\", Color.ubR, Color.ubG, Color.ubB, i\n\t\t);\n\t}\n\n\treturn true;\n}\n\nbool tPalette::toPromotionPal(const std::string &szPath) {\n\tstd::ofstream Dest(szPath, std::ios::out | std::ios::binary);\n\tif(!Dest.is_open()) {\n\t\treturn false;\n\t}\n\n\tstd::uint32_t i;\n\tfor(i = 0; i < m_vColors.size(); ++i) {\n\t\tconst auto &Color = m_vColors.at(i);\n\t\tDest.write(reinterpret_cast<const char*>(&Color.ubR), 1);\n\t\tDest.write(reinterpret_cast<const char*>(&Color.ubG), 1);\n\t\tDest.write(reinterpret_cast<const char*>(&Color.ubB), 1);\n\t}\n\tconst char pBlank[3] = { 0 };\n\twhile(i < 256) {\n\t\tDest.write(pBlank, 3);\n\t\t++i;\n\t}\n\n\treturn true;\n}\n\nbool tPalette::toAct(const std::string &szPath) {\n\tstd::ofstream Dest(szPath, std::ios::out | std::ios::binary);\n\tif(!Dest.is_open()) {\n\t\treturn false;\n\t}\n\n\tstd::uint32_t i;\n\tfor(i = 0; i < m_vColors.size(); ++i) {\n\t\tconst auto &Color = m_vColors.at(i);\n\t\tDest.write(reinterpret_cast<const char*>(&Color.ubR), 1);\n\t\tDest.write(reinterpret_cast<const char*>(&Color.ubG), 1);\n\t\tDest.write(reinterpret_cast<const char*>(&Color.ubB), 1);\n\t}\n\tconst char pBlank[3] = { 0 };\n\twhile(i < 256) {\n\t\tDest.write(pBlank, 3);\n\t\t++i;\n\t}\n\tstd::uint8_t ubSizeHi = std::uint16_t(m_vColors.size()) >> 8;\n\tstd::uint8_t ubSizeLo = m_vColors.size() & 0xFF;\n\n\tDest.write(reinterpret_cast<char*>(&ubSizeHi), 1);\n\tDest.write(reinterpret_cast<char*>(&ubSizeLo), 1);\n\n\treturn true;\n}\n\n\nint16_t tPalette::getColorIdx(const tRgb &Ref) const {\n\tstd::uint8_t i = 0;\n\tfor(const auto &Color : m_vColors) {\n\t\tif(Color == Ref) {\n\t\t\treturn i;\n\t\t}\n\t\t++i;\n\t}\n\treturn -1;\n}\n\nbool tPalette::isValid(void) const {\n\treturn m_vColors.size() != 0;\n}\n\nstd::uint8_t tPalette::getBpp(void) const {\n\tstd::uint8_t ubBpp = 1;\n\tfor(size_t i = 2; i < m_vColors.size(); i <<= 1) {\n\t\t++ubBpp;\n\t}\n\treturn ubBpp;\n}\n\nbool tPalette::convertToEhb(void) {\n\tif(m_vColors.size() > 32) {\n\t\treturn false;\n\t}\n\n\tm_vColors.resize(64);\n\tfor(std::size_t i = 0; i < 32; ++i) {\n\t\tm_vColors[i + 32] = m_vColors[i].toEhb();\n\t}\n\treturn true;\n}\n"
  },
  {
    "path": "tools/src/common/palette.h",
    "content": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at http://mozilla.org/MPL/2.0/. */\n\n#ifndef _ACE_TOOLS_COMMON_PALETTE_H_\n#define _ACE_TOOLS_COMMON_PALETTE_H_\n\n#include <vector>\n#include <string>\n#include \"../common/rgb.h\"\n\nclass tPalette {\npublic:\n\n\tstatic tPalette fromFile(const std::string &szPath);\n\n\tstatic tPalette fromPlt(const std::string &szPath);\n\n\tstatic tPalette fromGpl(const std::string &szPath);\n\n\tstatic tPalette fromPromotionPal(const std::string &szPath);\n\n\tstatic tPalette fromAct(const std::string &szPath);\n\n\t/**\n\t * @param isUseOcs true = OCS packed 12-bit entries; false = AGA (4 bytes per color).\n\t * @param isClampToOcs if true with OCS, quantize colors with @ref tRgb::to12Bit() instead of erroring.\n\t */\n\tbool toPlt(\n\t\tconst std::string &szPath, bool isUseOcs, bool isClampToOcs = false\n\t);\n\n\tbool toGpl(const std::string &szPath);\n\n\tbool toPromotionPal(const std::string &szPath);\n\n\tbool toAct(const std::string &szPath);\n\n\tbool isValid(void) const;\n\n\tstd::uint8_t getBpp(void) const;\n\n\tbool convertToEhb(void);\n\n\tstd::vector<tRgb> m_vColors;\n\n\ttPalette(void) {}\n\n\ttPalette(const std::vector<tRgb> &vColors) :\n\t\tm_vColors(vColors)\n\t{}\n\n\tstd::int16_t getColorIdx(const tRgb &Ref) const;\n};\n\n#endif // _ACE_TOOLS_COMMON_PALETTE_H_\n"
  },
  {
    "path": "tools/src/common/parse.h",
    "content": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at http://mozilla.org/MPL/2.0/. */\n\n#ifndef _ACE_TOOLS_COMMON_PARSE_H_\n#define _ACE_TOOLS_COMMON_PARSE_H_\n\n#include <string>\n#include \"logging.h\"\n\nnamespace nParse {\n\nstatic inline bool toInt32(\n\tconst std::string &szVal, const std::string &szValName, std::int32_t &lOut\n)\n{\n\ttry {\n\t\tlOut = std::stol(szVal);\n\t}\n\tcatch(std::exception ex) {\n\t\tnLog::error(\"Couldn't parse {}: '{}'\\n\", szValName, szVal);\n\t\treturn false;\n\t}\n\treturn true;\n}\n\ntemplate<typename t_tValue>\nstatic bool hexToRange(const std::string &szVal, t_tValue Min, t_tValue Max, t_tValue &Out) {\n\tauto Value = std::stoll(szVal, nullptr, 16);\n\tif(Value < Min || Max < Value) {\n\t\treturn false;\n\t}\n\n\tOut = static_cast<t_tValue>(Value);\n\treturn true;\n}\n\n} // namespace nParse\n\n\n#endif // _ACE_TOOLS_COMMON_PARSE_H_\n"
  },
  {
    "path": "tools/src/common/rgb.cpp",
    "content": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at http://mozilla.org/MPL/2.0/. */\n\n#include \"rgb.h\"\n#include <fmt/format.h>\n#include <stdexcept>\n#include \"parse.h\"\n\ntRgb::tRgb(const std::string &szCode)\n{\n\tif(szCode[0] == '#') {\n\t\tif(szCode.length() == 3 + 1) {\n\t\t\tnParse::hexToRange<std::uint8_t>(szCode.substr(1, 1), 0, 15, this->ubR);\n\t\t\tnParse::hexToRange<std::uint8_t>(szCode.substr(2, 1), 0, 15, this->ubG);\n\t\t\tnParse::hexToRange<std::uint8_t>(szCode.substr(3, 1), 0, 15, this->ubB);\n\t\t\tthis->ubR *= 17;\n\t\t\tthis->ubG *= 17;\n\t\t\tthis->ubB *= 17;\n\t\t}\n\t\telse if(szCode.length() == 6 + 1) {\n\t\t\tnParse::hexToRange<std::uint8_t>(szCode.substr(1, 2), 0, 255, this->ubR);\n\t\t\tnParse::hexToRange<std::uint8_t>(szCode.substr(3,2), 0, 255, this->ubG);\n\t\t\tnParse::hexToRange<std::uint8_t>(szCode.substr(5, 2), 0, 255, this->ubB);\n\t\t}\n\t\telse {\n\t\t\tthrow std::runtime_error(fmt::format(\"Unknown RGB hex format: {}\", szCode));\n\t\t}\n\t}\n\telse {\n\t\tthrow std::runtime_error(fmt::format(\"Unknown RGB color format: {}\", szCode));\n\t}\n}\n\ntRgb tRgb::to12Bit(void) const\n{\n\tauto R4 = ((this->ubR + 16) / 17);\n\tauto G4 = ((this->ubG + 16) / 17);\n\tauto B4 = ((this->ubB + 16) / 17);\n\tauto Out = tRgb((R4 << 4) | R4, (G4 << 4) | G4, (B4 << 4) | B4);\n\treturn Out;\n}\n\ntRgb tRgb::toEhb(void) const\n{\n\tauto R4 = ((this->ubR + 16) / 17) >> 1;\n\tauto G4 = ((this->ubG + 16) / 17) >> 1;\n\tauto B4 = ((this->ubB + 16) / 17) >> 1;\n\tauto Out = tRgb((R4 << 4) | R4, (G4 << 4) | G4, (B4 << 4) | B4);\n\treturn Out;\n}\n\nstd::string tRgb::toString(void) const\n{\n\treturn fmt::format(\"#{:02X}{:02X}{:02X}\", ubR, ubG, ubB);\n}\n"
  },
  {
    "path": "tools/src/common/rgb.h",
    "content": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at http://mozilla.org/MPL/2.0/. */\n\n#ifndef _ACE_TOOLS_COMMON_RGB_H_\n#define _ACE_TOOLS_COMMON_RGB_H_\n\n#include <cstdint>\n#include <string>\n\nstruct tRgb {\n\tstd::uint8_t ubR, ubG, ubB;\n\n\ttRgb(std::uint8_t ubNewR, std::uint8_t ubNewG, std::uint8_t ubNewB):\n\t\tubR(ubNewR), ubG(ubNewG), ubB(ubNewB) { }\n\n\ttRgb(std::uint8_t ubGrayscale):\n\t\tubR(ubGrayscale), ubG(ubGrayscale), ubB(ubGrayscale) { }\n\n\ttRgb():\n\t\tubR(0), ubG(0), ubB(0) { }\n\n\ttRgb(const std::string &szCode);\n\n\tstd::string toString(void) const;\n\n\ttRgb to12Bit(void) const;\n\n\ttRgb toEhb(void) const;\n\n\tbool operator == (const tRgb &Rhs) const {\n\t\treturn ubB == Rhs.ubB && ubG == Rhs.ubG && ubR == Rhs.ubR;\n\t}\n\n\tbool operator != (const tRgb &Rhs) const {\n\t\treturn !(*this == Rhs);\n\t}\n};\n\n#endif // _ACE_TOOLS_COMMON_RGB_H_\n"
  },
  {
    "path": "tools/src/common/sfx.cpp",
    "content": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at http://mozilla.org/MPL/2.0/. */\n\n#include \"sfx.h\"\n#include <fstream>\n#include <algorithm>\n#include \"logging.h\"\n#include \"endian.h\"\n\ntSfx::tSfx(void):\n\tm_ulFreq(0)\n{\n}\n\ntSfx::tSfx(const tWav &Wav, bool isStrict):\n\ttSfx()\n{\n\tauto vWavData = Wav.getData();\n\tm_ulFreq = Wav.getSampleRate();\n\tauto BitsPerSample = Wav.getBitsPerSample();\n\n\tif(BitsPerSample == 8) {\n\t\t// Convert 8-bit unsigned to signed - https://wiki.multimedia.cx/index.php/PCM#Sign\n\t\tfor(const auto &UnsignedSample: vWavData) {\n\t\t\tstd::int8_t bSample = UnsignedSample - 128;\n\t\t\tm_vData.push_back(bSample);\n\t\t}\n\t}\n\telse if(BitsPerSample == 16) {\n\t\tnLog::warn(\"Got 16bps, expected 8bps. Resample your .wav in proper audio program!\");\n\t\tif(isStrict) {\n\t\t\tnLog::error(\"Strict mode - aborting...\");\n\t\t\treturn;\n\t\t}\n\t\tnLog::warn(\"Resampling data - may result in poor results!\");\n\t\tauto DataSize = vWavData.size();\n\t\tfor(std::uint32_t i = 0; i < DataSize; i += 2) {\n\t\t\tstd::uint16_t uwRawSample = vWavData[i + 0] | (vWavData[i + 1] << 8);\n\t\t\tauto *pAsSigned = reinterpret_cast<std::int16_t *>(&uwRawSample);\n\t\t\tm_vData.push_back(*pAsSigned / 256);\n\t\t}\n\t}\n\n\t// Needs even number of bytes - Amiga reads it as words\n\tif(m_vData.size() & 1) {\n\t\tm_vData.push_back(0);\n\t}\n}\n\nbool tSfx::toSfx(const std::string &szPath, bool isCompress) const {\n\tstd::ofstream FileOut(szPath, std::ios::binary);\n\n\tconst std::uint8_t ubVersion = 2;\n\tconst std::uint16_t uwWordLength = nEndian::toBig16(uint16_t(m_vData.size() / 2));\n\tconst std::uint16_t uwSampleReateHz = nEndian::toBig16(m_ulFreq);\n\n\tFileOut.write(reinterpret_cast<const char*>(&ubVersion), sizeof(ubVersion));\n\tFileOut.write(reinterpret_cast<const char*>(&uwWordLength), sizeof(uwWordLength));\n\tFileOut.write(reinterpret_cast<const char*>(&uwSampleReateHz), sizeof(uwSampleReateHz));\n\n\tif(isCompress) {\n\t\tauto vCompressed = tSfx::compressLosslessDpcm(\n\t\t\tstd::span(m_vData.data(), m_vData.size()\n\t\t));\n\n\t\tstd::uint32_t ulCompressedLength = std::uint16_t(vCompressed.size());\n\t\tstd::uint32_t ulCompressedLengthBe = nEndian::toBig32(ulCompressedLength);\n\t\tFileOut.write(reinterpret_cast<const char*>(&ulCompressedLengthBe), sizeof(ulCompressedLengthBe));\n\t\tFileOut.write(reinterpret_cast<const char*>(vCompressed.data()), vCompressed.size());\n\t\tfmt::print(\n\t\t\tFMT_STRING(\"Compressed: {}/{} ({:.2f}%)\\n\"),\n\t\t\tvCompressed.size(), m_vData.size(), (float(vCompressed.size()) / m_vData.size() * 100)\n\t\t);\n\n\t\t// Verify that compression actually works\n\t\tstd::vector<std::int8_t> vDecompressed = tSfx::decompressLosslessDpcm(vCompressed, std::uint32_t(m_vData.size()));\n\t\tfor(auto i = 0; i < m_vData.size(); ++i) {\n\t\t\tif(vDecompressed[i] != m_vData[i]) {\n\t\t\t\tnLog::error(\"mismatch on byte {}\", i);\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\n\t}\n\telse {\n\t\tstd::uint32_t ulCompressedLength = 0;\n\t\tFileOut.write(reinterpret_cast<const char*>(&ulCompressedLength), sizeof(ulCompressedLength));\n\t\tFileOut.write(reinterpret_cast<const char*>(m_vData.data()), m_vData.size());\n\t}\n\n\treturn true;\n}\n\nbool tSfx::isEmpty(void) const\n{\n\treturn m_vData.empty();\n}\n\nstd::uint32_t tSfx::getLength(void) const\n{\n\treturn std::uint32_t(m_vData.size());\n}\n\nvoid tSfx::normalize(void)\n{\n\t// Get the biggest amplitude - negative or positive\n\tstd::int8_t bMaxAmplitude = 0;\n\tfor(const auto &Sample: m_vData) {\n\t\tauto Amplitude = abs(Sample);\n\t\tif(Amplitude > bMaxAmplitude) {\n\t\t\tbMaxAmplitude = int8_t(Amplitude);\n\t\t}\n\t}\n\n\t// Scale samples\n\tfor(auto &Sample: m_vData) {\n\t\tSample = (Sample * std::numeric_limits<int8_t>::max()) / bMaxAmplitude;\n\t}\n}\n\nvoid tSfx::divideAmplitude(std::uint8_t ubDivisor)\n{\n\tfor(auto &Sample: m_vData) {\n\t\tSample /= ubDivisor;\n\t}\n}\n\nbool tSfx::isFittingMaxAmplitude(std::int8_t bMaxAmplitude) const\n{\n\tfor(auto &Sample: m_vData) {\n\t\tif(Sample > bMaxAmplitude) {\n\t\t\treturn false;\n\t\t}\n\t}\n\treturn true;\n}\n\nbool tSfx::hasEmptyFirstWord(void) const {\n\treturn m_vData[0] == 0 && m_vData[1] == 0;\n}\n\nvoid tSfx::enforceEmptyFirstWord(void) {\n\twhile(!hasEmptyFirstWord()) {\n\t\tm_vData.push_back(0);\n\t\tstd::rotate(m_vData.rbegin(), m_vData.rbegin() + 1, m_vData.rend());\n\t}\n}\n\nvoid tSfx::padContents(std::uint8_t ubAlignment) {\n\t\tstd::uint8_t ubAddCount = m_vData.size() % ubAlignment;\n\t\tfor(std::uint8_t i = ubAddCount; i--;) {\n\t\t\tm_vData.push_back(0);\n\t\t}\n}\n\ntSfx tSfx::splitAfter(std::uint32_t ulSamples) {\n\ttSfx Out;\n\tif(m_vData.size() <= ulSamples) {\n\t\treturn Out;\n\t}\n\n\tfor(std::uint32_t ulPos = ulSamples; ulPos < m_vData.size(); ++ulPos) {\n\t\tOut.m_vData.push_back(m_vData[ulPos]);\n\t}\n\tOut.m_ulFreq = m_ulFreq;\n\tm_vData.resize(ulSamples);\n\treturn Out;\n}\n\nstd::vector<uint8_t> tSfx::compressLosslessDpcm(std::span<const int8_t> Uncompressed)\n{\n\tstatic constexpr auto Sgn = [](std::int8_t bDelta) { return (bDelta > 0) ? 1 : (bDelta < 0) ? -1 : 0;};\n\tstd::int8_t bPrevSample = 0;\n\tstd::uint32_t ulCtl = 0;\n\tstd::vector<uint8_t> vCompressed;\n\tstd::vector<uint8_t> vChunk;\n\tvChunk.reserve(16);\n\tstd::uint8_t ubCtlSize = 0;\n\tfor(auto i = 0; i < Uncompressed.size(); ++i) {\n\t\tauto Delta = Uncompressed[i] - bPrevSample;\n\t\tbool isPacked = false;\n\t\tif(Delta == 0) {\n\t\t\t// Skip sample\n\t\t\tisPacked = true;\n\t\t\t++ubCtlSize;\n\t\t\t// fmt::print(\"skip {}: {}\\n\", i, bPrevSample);\n\t\t}\n\t\telse if(i + 1 < Uncompressed.size() && ubCtlSize <= 14) {\n\t\t\tauto DeltaNext = Uncompressed[i + 1] - Uncompressed[i];\n\t\t\tif(std::abs(Delta) <= 16 && std::abs(DeltaNext) <= 16 && DeltaNext != 0) {\n\t\t\t\tif(Sgn(Delta) > 0) {\n\t\t\t\t\t// fmt::print(\"add delta A {}: {}\\n\", i, abs(Delta));\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\t// fmt::print(\"sub delta A {}: {}\\n\", i, abs(Delta));\n\t\t\t\t}\n\t\t\t\tif(Sgn(DeltaNext) > 0) {\n\t\t\t\t\t// fmt::print(\"add delta B {}: {}\\n\", i, abs(DeltaNext));\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\t// fmt::print(\"sub delta B {}: {}\\n\", i, abs(DeltaNext));\n\t\t\t\t}\n\t\t\t\tulCtl |= ((Sgn(Delta) > 0) ? 0b01 : 0b10) << 30;\n\t\t\t\tulCtl >>= 2;\n\t\t\t\tulCtl |= ((Sgn(DeltaNext) > 0) ? 0b01 : 0b10) << 30;\n\t\t\t\tubCtlSize += 2;\n\t\t\t\tstd::uint8_t ubPacked = ((abs(DeltaNext) - 1) << 4) | (abs(Delta) - 1);\n\t\t\t\tvChunk.push_back(ubPacked);\n\t\t\t\tisPacked = true;\n\t\t\t\tbPrevSample = Uncompressed[i + 1];\n\t\t\t\t++i;\n\t\t\t}\n\t\t}\n\t\tif(!isPacked) {\n\t\t\tvChunk.push_back(Uncompressed[i]);\n\t\t\tbPrevSample = Uncompressed[i];\n\t\t\tulCtl |= 0b11 << 30;\n\t\t\t++ubCtlSize;\n\t\t\t// fmt::print(\"full sample {}: {}\\n\", i, bPrevSample);\n\t\t}\n\t\tif(ubCtlSize == 16) {\n\t\t\tvCompressed.push_back((ulCtl >> 24) & 0xFF);\n\t\t\tvCompressed.push_back((ulCtl >> 16) & 0xFF);\n\t\t\tvCompressed.push_back((ulCtl >> 8) & 0xFF);\n\t\t\tvCompressed.push_back((ulCtl >> 0) & 0xFF);\n\t\t\t// fmt::print(\"write ctl: {:08X}\\n\", ulCtl);\n\t\t\tvCompressed.insert(vCompressed.end(), vChunk.begin(), vChunk.end());\n\t\t\tvChunk.clear();\n\t\t\tubCtlSize = 0;\n\t\t\tulCtl = 0;\n\t\t}\n\t\telse {\n\t\t\tulCtl >>= 2;\n\t\t}\n\t}\n\n\tif(ubCtlSize) {\n\t\t// trailing stuff, incomplete chunk - fill with zeros\n\t\t// at least one shift by 2 was done already, so shift max by 30\n\t\tulCtl >>= (30 - ubCtlSize * 2);\n\t\tvCompressed.push_back((ulCtl >> 24) & 0xFF);\n\t\tvCompressed.push_back((ulCtl >> 16) & 0xFF);\n\t\tvCompressed.push_back((ulCtl >> 8) & 0xFF);\n\t\tvCompressed.push_back((ulCtl >> 0) & 0xFF);\n\t\tvCompressed.insert(vCompressed.end(), vChunk.begin(), vChunk.end());\n\t\t// fmt::print(\"tail ctl: {:08X}, ctl size: {}, tail size: {}\\n\", ulCtl, ubCtlSize, vChunk.size());\n\t}\n\n\treturn vCompressed;\n}\n\nstd::vector<int8_t> tSfx::decompressLosslessDpcm(\n\tconst std::vector<uint8_t> &vCompressed, std::uint32_t ulDecompressedSize\n)\n{\n\tstd::vector<std::int8_t> vDecompressed;\n\tvDecompressed.resize(ulDecompressedSize);\n\tstd::copy(vCompressed.begin(), vCompressed.end(), &vDecompressed[ulDecompressedSize - vCompressed.size()]);\n\tstd::uint32_t ulReadPos = 0;\n\tstd::uint32_t ulCtl;\n\tstd::uint32_t ulWritePos = 0;\n\tstd::int8_t bLastSample = 0;\n\twhile(true) {\n\t\tulCtl = (\n\t\t\t(uint8_t(vCompressed[ulReadPos++]) << 24) |\n\t\t\t(uint8_t(vCompressed[ulReadPos++]) << 16) |\n\t\t\t(uint8_t(vCompressed[ulReadPos++]) << 8) |\n\t\t\tuint8_t(vCompressed[ulReadPos++])\n\t\t);\n\t\t// fmt::print(\"read ctl: {:08X}\\n\", ulCtl);\n\t\tfor(auto i = 0; i < 16; ++i) {\n\t\t\tstd::uint8_t ubCtl = ulCtl & 0b11;\n\t\t\tif(ubCtl == 0) {\n\t\t\t\t// fmt::print(\"skip {}: {}\\n\", ulWritePos, bLastSample);\n\t\t\t\tvDecompressed[ulWritePos++] = bLastSample;\n\t\t\t}\n\t\t\telse if(ubCtl == 0b11) {\n\t\t\t\tbLastSample = vCompressed[ulReadPos++];\n\t\t\t\t// fmt::print(\"full sample {}: {}\\n\", ulWritePos, bLastSample);\n\t\t\t\tvDecompressed[ulWritePos++] = bLastSample;\n\t\t\t}\n\t\t\telse {\n\t\t\t\tstd::uint8_t ubNibbles = vCompressed[ulReadPos++];\n\t\t\t\tif(ubCtl == 0b01) {\n\t\t\t\t\tbLastSample += (ubNibbles & 0xF) + 1;\n\t\t\t\t\t// fmt::print(\"add delta A {}: {}\\n\", ulWritePos, (ubNibbles & 0xF) + 1);\n\t\t\t\t\tvDecompressed[ulWritePos++] = bLastSample;\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tbLastSample -= (ubNibbles & 0xF) + 1;\n\t\t\t\t\t// fmt::print(\"sub delta A {}: {}\\n\", ulWritePos, (ubNibbles & 0xF) + 1);\n\t\t\t\t\tvDecompressed[ulWritePos++] = bLastSample;\n\t\t\t\t}\n\t\t\t\tubNibbles >>= 4;\n\t\t\t\tulCtl >>= 2;\n\t\t\t\t++i;\n\t\t\t\tubCtl = ulCtl & 0b11;\n\t\t\t\tif(ubCtl == 0b01) {\n\t\t\t\t\tbLastSample += ubNibbles + 1;\n\t\t\t\t\t// fmt::print(\"add delta B {}: {}\\n\", ulWritePos, ubNibbles + 1);\n\t\t\t\t\tvDecompressed[ulWritePos++] = bLastSample;\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tbLastSample -= ubNibbles + 1;\n\t\t\t\t\t// fmt::print(\"sub delta B {}: {}\\n\", ulWritePos, ubNibbles + 1);\n\t\t\t\t\tvDecompressed[ulWritePos++] = bLastSample;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tulCtl >>= 2;\n\t\t\tif(ulWritePos >= std::uint32_t(vDecompressed.size())) {\n\t\t\t\treturn vDecompressed;\n\t\t\t}\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "tools/src/common/sfx.h",
    "content": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at http://mozilla.org/MPL/2.0/. */\n\n#ifndef _ACE_TOOLS_COMMON_SFX_H_\n#define _ACE_TOOLS_COMMON_SFX_H_\n\n#include \"wav.h\"\n#include <string>\n#include <span>\n\nclass tSfx {\npublic:\n\ttSfx(void);\n\n\ttSfx(const tWav &Wav, bool isStrict);\n\n\tbool toSfx(const std::string &szPath, bool isCompress) const;\n\n\tbool isEmpty(void) const;\n\n\tstd::uint32_t getLength(void) const;\n\n\tvoid normalize(void);\n\n\tvoid divideAmplitude(std::uint8_t ubDivisor);\n\n\tbool isFittingMaxAmplitude(std::int8_t bMaxAmplitude) const;\n\n\tbool hasEmptyFirstWord(void) const;\n\n\tvoid enforceEmptyFirstWord(void);\n\n\tvoid padContents(std::uint8_t ubAlignment);\n\n\ttSfx splitAfter(std::uint32_t ulSamples);\n\n\tstatic std::vector<uint8_t> compressLosslessDpcm(std::span<const int8_t> Uncompressed);\n\tstatic std::vector<int8_t> decompressLosslessDpcm(const std::vector<uint8_t> &vCompressed, std::uint32_t ulDecompressedSize);\n\nprivate:\n\tstd::uint32_t m_ulFreq;\n\tstd::vector<int8_t> m_vData;\n};\n\n#endif // _ACE_TOOLS_COMMON_SFX_H_\n"
  },
  {
    "path": "tools/src/common/stream.cpp",
    "content": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at http://mozilla.org/MPL/2.0/. */\n\n#include \"stream.h\"\n\nnamespace nStream {\n\nstd::istream &getAnyLine(std::istream &Source, std::string &szLine)\n{\n\tszLine.clear();\n\tchar c;\n\twhile(Source.good()) {\n\t\tSource.read(&c, 1);\n\t\tif(!Source.good()) {\n\t\t\tbreak;\n\t\t}\n\n\t\tif(c == '\\n' || c == '\\r') {\n\t\t\tbreak;\n\t\t}\n\t\tszLine += c;\n\t}\n\n\treturn Source;\n}\n\n}\n"
  },
  {
    "path": "tools/src/common/stream.h",
    "content": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at http://mozilla.org/MPL/2.0/. */\n\n#ifndef _ACE_TOOLS_COMMON_STREAM_H_\n#define _ACE_TOOLS_COMMON_STREAM_H_\n\n#include <istream>\n\nnamespace nStream {\n\nstd::istream &getAnyLine(std::istream &Source, std::string &szLine);\n\n}\n\n#endif _ACE_TOOLS_COMMON_STREAM_H_\n"
  },
  {
    "path": "tools/src/common/utf8.h",
    "content": "// Copyright (c) 2008-2009 Bjoern Hoehrmann <bjoern@hoehrmann.de>\n// See http://bjoern.hoehrmann.de/utf-8/decoder/dfa/ for details.\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n#include <stdint.h>\n\n#define UTF8_ACCEPT 0\n#define UTF8_REJECT 1\n\nstatic const uint8_t utf8d[] = {\n  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 00..1f\n  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 20..3f\n  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 40..5f\n  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 60..7f\n  1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, // 80..9f\n  7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, // a0..bf\n  8,8,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, // c0..df\n  0xa,0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x4,0x3,0x3, // e0..ef\n  0xb,0x6,0x6,0x6,0x5,0x8,0x8,0x8,0x8,0x8,0x8,0x8,0x8,0x8,0x8,0x8, // f0..ff\n  0x0,0x1,0x2,0x3,0x5,0x8,0x7,0x1,0x1,0x1,0x4,0x6,0x1,0x1,0x1,0x1, // s0..s0\n  1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,0,1,0,1,1,1,1,1,1, // s1..s2\n  1,2,1,1,1,1,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1, // s3..s4\n  1,2,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,3,1,3,1,1,1,1,1,1, // s5..s6\n  1,3,1,1,1,1,1,3,1,3,1,1,1,1,1,1,1,3,1,1,1,1,1,1,1,1,1,1,1,1,1,1, // s7..s8\n};\n\nstatic inline uint32_t decode(uint32_t* state, uint32_t* codep, uint32_t byte) {\n  uint32_t type = utf8d[byte];\n\n  *codep = (*state != UTF8_ACCEPT) ?\n    (byte & 0x3fu) | (*codep << 6) :\n    (0xff >> type) & (byte);\n\n  *state = utf8d[256 + *state*16 + type];\n  return *state;\n}\n\n#ifdef __cplusplus\n}\n#endif\n"
  },
  {
    "path": "tools/src/common/wav.cpp",
    "content": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at http://mozilla.org/MPL/2.0/. */\n\n#include \"wav.h\"\n#include <fstream>\n#include <sstream>\n#include <algorithm>\n#include \"logging.h\"\n\nenum class tAudioFormat: std::uint16_t {\n\tPCM = 1\n};\n\nbool tryRead(std::ifstream &Stream, char *Buffer, std::uint32_t ulSize)\n{\n\t// ifstream::read doesn't return meaningful return value\n\t// so here's a helper fn for it\n\tStream.read(Buffer, ulSize);\n\treturn Stream.good();\n}\n\ntWav::tWav(const std::string &szPath)\n{\n\t// Read header - chunk\n\tstd::string szRiffId(4, '\\0');\n\tstd::ifstream StreamFile(szPath.c_str(), std::ios::binary);\n\tif(!StreamFile.is_open()) {\n\t\tnLog::error(\"Couldn't open: '{}'\", szPath);\n\t\treturn;\n\t}\n\ttryRead(StreamFile, szRiffId.data(), szRiffId.length());\n\tif(szRiffId != \"RIFF\") {\n\t\tnLog::error(\"Couldn't find RIFF header, got: '{}'\", szRiffId);\n\t\treturn;\n\t}\n\n\tstd::uint32_t ulChunkSize;\n\ttryRead(StreamFile, reinterpret_cast<char*>(&ulChunkSize), sizeof(ulChunkSize));\n\n\tstd::string szFormat(4, '\\0');\n\ttryRead(StreamFile, szFormat.data(), szFormat.length());\n\n\tif(szFormat != \"WAVE\") {\n\t\tnLog::error(\"Unsupported format: '{}', expected 'WAVE'\", szFormat);\n\t\treturn;\n\t}\n\n\t// Read subchunks\n\tbool isEnd = false;\n\tstd::string szSubchunkId(4, '\\0');\n\twhile(tryRead(StreamFile, szSubchunkId.data(), szSubchunkId.length())) {\n\t\ttSubchunk Subchunk;\n\t\tSubchunk.m_szId = szSubchunkId;\n\t\ttryRead(StreamFile, reinterpret_cast<char*>(&Subchunk.m_ulSize), sizeof(Subchunk.m_ulSize));\n\t\tSubchunk.m_szContents.resize(Subchunk.m_ulSize);\n\t\ttryRead(StreamFile, Subchunk.m_szContents.data(),Subchunk.m_szContents.length());\n\t\tm_vSubchunks.push_back(std::move(Subchunk));\n\t}\n\n\t// Find and read \"fmt\" subchunk\n\tauto *pSubchunkFmt = findSubchunk(\"fmt \");\n\tif(pSubchunkFmt == nullptr) {\n\t\tnLog::error(\"Couldn't find WAV 'fmt' subchunk\");\n\t\treturn;\n\t}\n\tstd::stringstream StreamSubchunk(pSubchunkFmt->m_szContents);\n\ttAudioFormat eAudioFormat;\n\tstd::uint16_t uwNumChannels, uwBlockAlign, uwBitsPerSample;\n\tstd::uint32_t ulSampleRate, ulByteRate;\n\tStreamSubchunk.read(reinterpret_cast<char*>(&eAudioFormat), sizeof(eAudioFormat));\n\tStreamSubchunk.read(reinterpret_cast<char*>(&uwNumChannels), sizeof(uwNumChannels));\n\tStreamSubchunk.read(reinterpret_cast<char*>(&ulSampleRate), sizeof(ulSampleRate));\n\tStreamSubchunk.read(reinterpret_cast<char*>(&ulByteRate), sizeof(ulByteRate));\n\tStreamSubchunk.read(reinterpret_cast<char*>(&uwBlockAlign), sizeof(uwBlockAlign));\n\tStreamSubchunk.read(reinterpret_cast<char*>(&uwBitsPerSample), sizeof(uwBitsPerSample));\n\n\tif(eAudioFormat != tAudioFormat::PCM) {\n\t\tnLog::error(\"Unrecognized WAV audio format: {}\", static_cast<int>(eAudioFormat));\n\t\treturn;\n\t}\n\tif(uwNumChannels != 1) {\n\t\tnLog::error(\"Unsupported WAV channel count: {}\", uwNumChannels);\n\t\treturn;\n\t}\n\tif(uwBitsPerSample != 8 && uwBitsPerSample != 16) {\n\t\tnLog::error(\"Unsupported WAV bps: {}\", uwBitsPerSample);\n\t\treturn;\n\t}\n\n\t// Read \"data\" subchunk\n\tauto *pSubchunkData = findSubchunk(\"data\");\n\tif(pSubchunkData == nullptr) {\n\t\tnLog::error(\"Couldn't find WAV 'data' subchunk\");\n\t\treturn;\n\t}\n\n\tm_ubBitsPerSample = uwBitsPerSample;\n\tm_ulSampleRate = ulSampleRate;\n\tm_vData.resize(pSubchunkData->m_szContents.length());\n\tmemcpy(m_vData.data(), pSubchunkData->m_szContents.data(), pSubchunkData->m_szContents.length());\n}\n\nconst tWav::tSubchunk *tWav::findSubchunk(const std::string &szId) const {\n\tauto Subchunk = std::find_if(\n\t\tm_vSubchunks.cbegin(), m_vSubchunks.cend(), [szId](const tSubchunk &Sc) {\n\t\t\treturn Sc.m_szId == szId;\n\t\t}\n\t);\n\tif(Subchunk == m_vSubchunks.cend()) {\n\t\treturn nullptr;\n\t}\n\treturn &*Subchunk;\n}\n\nconst std::vector<uint8_t> &tWav::getData(void) const\n{\n\treturn m_vData;\n}\n\nstd::uint32_t tWav::getSampleRate(void) const\n{\n\treturn m_ulSampleRate;\n}\n\nstd::uint8_t tWav::getBitsPerSample(void) const\n{\n\treturn m_ubBitsPerSample;\n}\n"
  },
  {
    "path": "tools/src/common/wav.h",
    "content": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at http://mozilla.org/MPL/2.0/. */\n\n#ifndef _ACE_TOOLS_COMMON_WAV_H_\n#define _ACE_TOOLS_COMMON_WAV_H_\n\n#include <string>\n#include <vector>\n#include <cstdint>\n\nclass tWav {\npublic:\n\ttWav(const std::string &szPath);\n\n\tconst std::vector<uint8_t> &getData(void) const;\n\tstd::uint32_t getSampleRate(void) const;\n\tstd::uint8_t getBitsPerSample(void) const;\n\nprivate:\n\tstruct tSubchunk {\n\t\tstd::string m_szId = std::string(4, '\\0');\n\t\tstd::uint32_t m_ulSize;\n\t\tstd::string m_szContents;\n\t};\n\n\tconst tSubchunk *findSubchunk(const std::string &szId) const;\n\n\tstd::vector<tSubchunk> m_vSubchunks;\n\tstd::vector<uint8_t> m_vData;\n\tstd::uint32_t m_ulSampleRate;\n\tstd::uint8_t m_ubBitsPerSample;\n};\n\n#endif // _ACE_TOOLS_COMMON_WAV_H_\n"
  },
  {
    "path": "tools/src/font_conv.cpp",
    "content": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at http://mozilla.org/MPL/2.0/. */\n\n#include <map>\n#include <fstream>\n#include \"common/logging.h\"\n#include \"common/glyph_set.h\"\n#include \"common/fs.h\"\n#include \"common/json.h\"\n#include \"common/utf8.h\"\n\nstatic const std::string s_szDefaultCharset = (\n\t\" ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\"\n);\n\nenum class tFontFormat: std::uint8_t {\n\tINVALID,\n\tTTF,\n\tDIR,\n\tPNG,\n\tFNT,\n\tPMNG,\n};\n\nstd::map<std::string, tFontFormat> s_mOutType = {\n\t{\"ttf\", tFontFormat::TTF},\n\t{\"dir\", tFontFormat::DIR},\n\t{\"png\", tFontFormat::PNG},\n\t{\"fnt\", tFontFormat::FNT},\n\t{\"pmng\", tFontFormat::PMNG},\n};\n\nvoid printUsage(const std::string &szAppName) {\n\tusing fmt::print;\n\tprint(\"Usage:\\n\\t{} inPath outType [extraOpts]\\n\\n\", szAppName);\n\tprint(\"inPath\\t- path to input. Supported types:\\n\");\n\tprint(\"\\tTTF file.\\n\");\n\tprint(\"\\tDirectory with PNG glyphs. All have to be of same height and named with ASCII indices of chars.\\n\");\n\tprint(\"\\tProMotion NG's PNG font.\\n\");\n\tprint(\"outType\\t- one of following:\\n\");\n\tprint(\"\\tdir\\tDirectory with each glyph as separate PNG\\n\");\n\tprint(\"\\tpng\\tSingle PNG file with whole font\\n\");\n\tprint(\"\\tfnt\\tACE font file\\n\");\n\tprint(\"extraOpts:\\n\");\n\t// -chars\n\tprint(\"\\t-chars \\\"AB D\\\"\\t\\tInclude only 'A', 'B', ' ' and 'D' chars in font. Only for TTF input.\\n\");\n\tprint(\"\\t\\t\\t\\tUse backslash (\\\\) to escape quote (\\\") char inside charset specifier\\n\");\n\tprint(\"\\t\\t\\t\\tDefault charset is: \\\"{}\\\"\\n\\n\", s_szDefaultCharset);\n\t// -charFile\n\tprint(\"\\t-charFile \\\"file.txt\\\"\\tInclude chars specified in file.txt.\\n\");\n\tprint(\"\\t\\t\\t\\tNewline chars (\\\\r, \\\\n) and repeats are omitted.\\n\\n\");\n\t// -size\n\tprint(\"\\t-size 8\\t\\t\\tRasterize font using size of 8pt. Default: 20.\\n\\n\");\n\t// -out\n\tprint(\"\\t-out outPath\\tSpecify output path, including file name.\\n\");\n\tprint(\"\\t\\t\\tDefault is same name as input with changed extension\\n\");\n\t// -fc\n\tprint(\"\\t-fc firstchar\\tSpecify first ASCII character idx in ProMotion NG font. Default: 33.\");\n}\n\nstatic std::uint32_t getCharCodeFromTok(const tJson *pJson, std::uint16_t uwTok) {\n\tstd::uint32_t ulVal = 0;\n\tconst auto &Token = pJson->pTokens[uwTok];\n\tif(Token.type == JSMN_STRING) {\n\t\t// read unicode char and return its codepoint\n\t\tstd::uint32_t ulCodepoint, ulState = 0;\n\n\t\tfor(auto i = Token.start; i <= Token.end; ++i) {\n\t\t\tauto CharCode = *reinterpret_cast<const uint8_t*>(&pJson->szData[i]);\n\t\t\tif (\n\t\t\t\tdecode(&ulState, &ulCodepoint, CharCode) != UTF8_ACCEPT ||\n\t\t\t\tulCodepoint == '\\n' || ulCodepoint == '\\r'\n\t\t\t) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tulVal = ulCodepoint;\n\t\t\tbreak;\n\t\t}\n\t}\n\telse {\n\t\t// read number as it is in file and return it\n\t\tulVal = jsonTokToUlong(pJson, uwTok);\n\t}\n\treturn ulVal;\n}\n\nint main(int lArgCount, const char *pArgs[])\n{\n\tconst std::uint8_t ubMandatoryArgCnt = 2;\n\t// Mandatory args\n\tif(lArgCount - 1 < ubMandatoryArgCnt) {\n\t\tnLog::error(\"Too few arguments, expected {}\", ubMandatoryArgCnt);\n\t\tprintUsage(pArgs[0]);\n\t\treturn EXIT_FAILURE;\n\t}\n\n\tstd::string szFontPath = pArgs[1];\n\ttFontFormat eOutType = s_mOutType[pArgs[2]];\n\n\t// Optional args' default values\n\tstd::string szCharset = \"\";\n\tstd::string szOutPath = \"\";\n\tstd::uint8_t ubFirstChar = 33;\n\tstd::string szRemapPath = \"\";\n\tstd::int32_t lSize = -1;\n\n\t// Search for optional args\n\tfor(auto ArgIndex = ubMandatoryArgCnt+1; ArgIndex < lArgCount; ++ArgIndex) {\n\t\tif(pArgs[ArgIndex] == std::string(\"-chars\") && ArgIndex < lArgCount - 1) {\n\t\t\t++ArgIndex;\n\t\t\tszCharset += pArgs[ArgIndex];\n\t\t}\n\t\telse if(pArgs[ArgIndex] == std::string(\"-out\") && ArgIndex < lArgCount - 1) {\n\t\t\t++ArgIndex;\n\t\t\tszOutPath = pArgs[ArgIndex];\n\t\t}\n\t\telse if(pArgs[ArgIndex] == std::string(\"-fc\") && ArgIndex < lArgCount - 1) {\n\t\t\t++ArgIndex;\n\t\t\ttry {\n\t\t\t\tubFirstChar = uint8_t(std::stoul(pArgs[ArgIndex]));\n\t\t\t}\n\t\t\tcatch(std::exception Ex) {\n\t\t\t\tnLog::error(\n\t\t\t\t\t\"Couldn't parse 'first char' param: '{}', expected number\", pArgs[ArgIndex]\n\t\t\t\t);\n\t\t\t\treturn EXIT_FAILURE;\n\t\t\t}\n\t\t}\n\t\telse if(pArgs[ArgIndex] == std::string(\"-charFile\") && ArgIndex < lArgCount - 1) {\n\t\t\t++ArgIndex;\n\t\t\tauto File = std::ifstream(pArgs[ArgIndex], std::ios::binary);\n\t\t\twhile(!File.eof()) {\n\t\t\t\tchar c;\n\t\t\t\tFile.read(&c, 1);\n\t\t\t\tszCharset += c;\n\t\t\t}\n\t\t}\n\t\telse if(pArgs[ArgIndex] == std::string(\"-size\") && ArgIndex < lArgCount - 1) {\n\t\t\t++ArgIndex;\n\t\t\tlSize = std::stol(pArgs[ArgIndex]);\n\t\t}\n\t\telse if(pArgs[ArgIndex] == std::string(\"-remap\") && ArgIndex < lArgCount - 1) {\n\t\t\t++ArgIndex;\n\t\t\tszRemapPath = pArgs[ArgIndex];\n\t\t}\n\t\telse {\n\t\t\tnLog::error(\"Unknown arg or missing value: '{}'\", pArgs[ArgIndex]);\n\t\t\tprintUsage(pArgs[0]);\n\t\t\treturn EXIT_FAILURE;\n\t\t}\n\t}\n\n\tif(szCharset.length() == 0) {\n\t\tszCharset = s_szDefaultCharset;\n\t}\n\tif(lSize < 0) {\n\t\tlSize = 20;\n\t}\n\n\t// Load glyphs from input file\n\ttGlyphSet mGlyphs;\n\ttFontFormat eInType = tFontFormat::INVALID;\n\tif(szFontPath.find(\".ttf\") != std::string::npos) {\n\t\tmGlyphs = tGlyphSet::fromTtf(szFontPath, lSize, szCharset, 128);\n\t\teInType = tFontFormat::TTF;\n\t}\n\telse if(nFs::isDir(szFontPath)) {\n\t\tmGlyphs = tGlyphSet::fromDir(szFontPath);\n\t\tif(!mGlyphs.isOk()) {\n\t\t\tnLog::error(\"Loading glyphs from dir '{}' failed\", szFontPath);\n\t\t\treturn EXIT_FAILURE;\n\t\t}\n\t\teInType = tFontFormat::DIR;\n\t}\n\telse if(szFontPath.find(\".png\") != std::string::npos) {\n\t\t// TODO param for determining whether png is pmng-format or ace format\n\t\tmGlyphs = tGlyphSet::fromPmng(szFontPath, ubFirstChar);\n\t\teInType = tFontFormat::PMNG;\n\t}\n\telse if(szFontPath.find(\".fnt\") != std::string::npos) {\n\t\tmGlyphs = tGlyphSet::fromAceFont(szFontPath);\n\t\teInType = tFontFormat::FNT;\n\t}\n\telse {\n\t\tnLog::error(\"Unsupported font source: '{}'\", pArgs[1]);\n\t\treturn EXIT_FAILURE;\n\t}\n\tif(eInType == tFontFormat::INVALID || !mGlyphs.isOk()) {\n\t\tnLog::error(\"Couldn't read any font glyphs\");\n\t\treturn EXIT_FAILURE;\n\t}\n\n\t// Remap chars accordingly\n\tif(!szRemapPath.empty()) {\n\t\tauto *pJson = jsonCreate(szRemapPath.c_str());\n\t\tif(pJson == nullptr) {\n\t\t\tnLog::error(\"Couldn't open remap file: '{}'\", szRemapPath);\n\t\t\treturn EXIT_FAILURE;\n\t\t}\n\t\tauto TokRemapArray = jsonGetDom(pJson, \"remap\");\n\t\tauto ElementCount = pJson->pTokens[TokRemapArray].size;\n\t\tstd::vector<std::pair<uint32_t, uint32_t>> vFromTo;\n\t\tfor(auto i = ElementCount; i--;) {\n\t\t\tauto TokRemapEntry = jsonGetElementInArray(pJson, TokRemapArray, i);\n\t\t\tauto TokFrom = jsonGetElementInArray(pJson, TokRemapEntry, 0);\n\t\t\tauto TokTo = jsonGetElementInArray(pJson, TokRemapEntry, 1);\n\t\t\tauto From = getCharCodeFromTok(pJson, TokFrom);\n\t\t\tauto To = getCharCodeFromTok(pJson, TokTo);\n\t\t\tfmt::print(\"Remapping {} => {}\\n\", From, To);\n\t\t\tvFromTo.push_back({std::move(From), std::move(To)});\n\t\t}\n\t\tmGlyphs.remapGlyphs(vFromTo);\n\t}\n\n\t// Determine default output path\n\tif(szOutPath == \"\") {\n\t\tszOutPath = szFontPath;\n\t\tauto PosDot = szOutPath.find_last_of(\".\");\n\t\tif(PosDot != std::string::npos) {\n\t\t\tszOutPath = szOutPath.substr(0, PosDot);\n\t\t}\n\t}\n\tif(eInType == eOutType) {\n\t\tnLog::error(\"Output file type can't be same as input\");\n\t\treturn EXIT_FAILURE;\n\t}\n\n\tif(eOutType == tFontFormat::DIR) {\n\t\tif(szOutPath == szFontPath) {\n\t\t\tszOutPath += \".dir\";\n\t\t}\n\t\tmGlyphs.toDir(szOutPath);\n\t}\n\telse {\n\t\tif(eOutType == tFontFormat::PNG) {\n\t\t\ttChunkyBitmap FontChunky = mGlyphs.toPackedBitmap(true);\n\t\t\tif(szOutPath.substr(szOutPath.length() - 4) != \".png\") {\n\t\t\t\tszOutPath += \".png\";\n\t\t\t}\n\t\t\tFontChunky.toPng(szOutPath);\n\t\t}\n\t\telse if(eOutType == tFontFormat::FNT) {\n\t\t\tif(szOutPath.substr(szOutPath.length() - 4) != \".fnt\") {\n\t\t\t\tszOutPath += \".fnt\";\n\t\t\t}\n\t\t\tmGlyphs.toAceFont(szOutPath);\n\t\t}\n\t\telse {\n\t\t\tnLog::error(\"Unsupported output type\");\n\t\t\treturn EXIT_FAILURE;\n\t\t}\n\t}\n\tfmt::print(\"All done!\\n\");\n\treturn EXIT_SUCCESS;\n}\n"
  },
  {
    "path": "tools/src/mod_tool.cpp",
    "content": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at http://mozilla.org/MPL/2.0/. */\n\n#include <cstdlib>\n#include <vector>\n#include <memory>\n#include <algorithm>\n#include <fstream>\n#include <string_view>\n#include <fmt/format.h>\n#include \"common/mod.h\"\n#include \"common/sfx.h\"\n#include \"common/logging.h\"\n#include \"common/endian.h\"\n\nusing namespace std::string_view_literals;\n\nint main(int lArgCount, const char *pArgs[])\n{\n\tif(lArgCount <= 1) {\n\t\tnLog::error(\"no parameters specified\\n\");\n\t\treturn EXIT_FAILURE;\n\t}\n\n\tstd::vector<std::shared_ptr<tMod>> vModsIn;\n\tstd::vector<std::string> vOutNames;\n\tstd::string szSamplePackPath;\n\tbool isStripSamples = true;\n\tbool isCompressed = false;\n\n\tfor(auto ArgIndex = 0; ArgIndex < lArgCount; ++ArgIndex) {\n\t\tif(pArgs[ArgIndex] == \"-i\"sv) {\n\t\t\tvModsIn.push_back(std::make_shared<tMod>(pArgs[++ArgIndex]));\n\t\t}\n\t\telse if(pArgs[ArgIndex] == \"-o\"sv) {\n\t\t\tvOutNames.push_back(pArgs[++ArgIndex]);\n\t\t}\n\t\telse if(pArgs[ArgIndex] == \"-sp\"sv) {\n\t\t\tszSamplePackPath = pArgs[++ArgIndex];\n\t\t}\n\t\telse if(pArgs[ArgIndex] == \"-c\"sv) {\n\t\t\tisCompressed = true;\n\t\t}\n\t}\n\n\tif(vModsIn.size() != vOutNames.size()) {\n\t\tnLog::error(\n\t\t\t\"Output path count ({}) doesn't match input file count ({})\\n\",\n\t\t\tvOutNames.size(), vModsIn.size()\n\t\t);\n\t\treturn EXIT_FAILURE;\n\t}\n\n\tfor(const auto &pMod: vModsIn) {\n\t\tconst auto &ModSamples = pMod->getSamples();\n\t\tconst auto SampleCount = ModSamples.size();\n\t\tfor(auto SampleIndex = 0; SampleIndex < SampleCount; ++SampleIndex) {\n\t\t\tfor(auto OtherIndex = SampleIndex + 1; OtherIndex < SampleCount; ++OtherIndex) {\n\t\t\t\tif(\n\t\t\t\t\t!ModSamples[SampleIndex].m_szName.empty() &&\n\t\t\t\t\tModSamples[SampleIndex].m_szName == ModSamples[OtherIndex].m_szName\n\t\t\t\t) {\n\t\t\t\t\tnLog::error(\n\t\t\t\t\t\t\"Mod '{}' has duplicate sample name: '{}'\\n\",\n\t\t\t\t\t\tpMod->getSongName(), ModSamples[SampleIndex].m_szName\n\t\t\t\t\t);\n\t\t\t\t\treturn EXIT_FAILURE;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// Get the collection of unique samples\n\tstd::vector<tSample> vMergedSamples;\n\tfor(const auto &pMod: vModsIn) {\n\t\tconst auto &ModSamples = pMod->getSamples();\n\t\tfor(const auto &ModSample: ModSamples) {\n\t\t\tif(ModSample.m_vData.empty()) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t// Check if sample is on the list\n\t\t\tauto FoundMergedSample = std::find_if(\n\t\t\t\tvMergedSamples.begin(), vMergedSamples.end(),\n\t\t\t\t[&ModSample](const tSample &RefSample) -> bool {\n\t\t\t\t\tbool isSameName = (RefSample.m_szName == ModSample.m_szName);\n\t\t\t\t\treturn isSameName;\n\t\t\t\t}\n\t\t\t);\n\t\t\tif(FoundMergedSample == vMergedSamples.end()) {\n\t\t\t\t// Sample not on the list - add it\n\t\t\t\tfmt::print(FMT_STRING(\"Adding sample '{}' at index {}\\n\"), ModSample.m_szName, vMergedSamples.size());\n\t\t\t\tvMergedSamples.push_back(ModSample);\n\t\t\t}\n\t\t\telse {\n\t\t\t\t// Verify that Samples are exactly the same\n\t\t\t\tif(ModSample != *FoundMergedSample) {\n\t\t\t\t\tnLog::error(\n\t\t\t\t\t\t\"sample {} '{}' have different contents in mod '{}' than in others\\n\",\n\t\t\t\t\t\t(&ModSample - ModSamples.data()), ModSample.m_szName, pMod->getSongName()\n\t\t\t\t\t);\n\t\t\t\t\treturn EXIT_FAILURE;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// Change the sample indices in modules so that they can be used with the samplepack\n\tfor(const auto &pMod: vModsIn) {\n\t\t// Scan the samples to get the reorder table\n\t\tstd::vector<uint8_t> vReorder; // [idxOld] = idxNew\n\t\tfor(const auto ModSample: pMod->getSamples()) {\n\t\t\tstd::uint8_t ubIdxNew = 0;\n\t\t\tif(!ModSample.m_szName.empty()) {\n\t\t\t\t// Find the sample index in new samplepack\n\t\t\t\tauto SampleNew = std::find_if(\n\t\t\t\t\tvMergedSamples.begin(), vMergedSamples.end(),\n\t\t\t\t\t[&ModSample](const tSample &MergedSample) -> bool {\n\t\t\t\t\t\tbool isSame = MergedSample.m_szName == ModSample.m_szName;\n\t\t\t\t\t\treturn isSame;\n\t\t\t\t\t}\n\t\t\t\t);\n\t\t\t\tubIdxNew = uint8_t(std::distance(vMergedSamples.begin(), SampleNew));\n\t\t\t}\n\t\t\tvReorder.push_back(ubIdxNew);\n\t\t}\n\n\t\t// Reorder samples, replace sample indices in notes\n\t\tpMod->reorderSamples(vReorder);\n\n\t\t// Trim sample data - Don't do it or sample defs will have data length 0\n\t\t// pMod->clearSampleData();\n\t}\n\n\tif(!szSamplePackPath.empty()) {\n\t\tfmt::print(\"Writing sample pack to {}...\\n\", szSamplePackPath);\n\t\tstd::ofstream FileSamplePack;\n\t\tFileSamplePack.open(szSamplePackPath, std::ios::binary);\n\t\tstd::uint8_t ubVersion = 2;\n\t\tstd::uint8_t ubSampleCount = std::uint8_t(vMergedSamples.size());\n\t\tFileSamplePack.write(reinterpret_cast<char*>(&ubVersion), sizeof(ubVersion));\n\t\tFileSamplePack.write(reinterpret_cast<char*>(&ubSampleCount), sizeof(ubSampleCount));\n\n\t\tfor(const auto &Sample: vMergedSamples) {\n\t\t\tstd::uint16_t uwSampleWordLengthBe = nEndian::toBig16(std::uint16_t(Sample.m_vData.size()));\n\t\t\tFileSamplePack.write(reinterpret_cast<char*>(&uwSampleWordLengthBe), sizeof(uwSampleWordLengthBe));\n\t\t\tif(isCompressed) {\n\t\t\t\tstd::uint32_t ulUncompressedSize = std::uint32_t(Sample.m_vData.size() * sizeof(Sample.m_vData[0]));\n\t\t\t\tauto UncompressedBytes = std::span(reinterpret_cast<const int8_t*>(Sample.m_vData.data()), ulUncompressedSize);\n\t\t\t\tauto vCompressed = tSfx::compressLosslessDpcm(UncompressedBytes);\n\t\t\t\tfmt::print(\n\t\t\t\t\tFMT_STRING(\"Compressed: {}/{} ({:.2f}%)\\n\"),\n\t\t\t\t\tvCompressed.size(), ulUncompressedSize,\n\t\t\t\t\t(float(vCompressed.size()) / ulUncompressedSize * 100)\n\t\t\t\t);\n\n\t\t\t\tauto vDecompressed = tSfx::decompressLosslessDpcm(\n\t\t\t\t\tvCompressed, std::uint32_t(Sample.m_vData.size() * sizeof(std::uint16_t))\n\t\t\t\t);\n\t\t\t\tfor(auto i = 0; i < UncompressedBytes.size(); ++i) {\n\t\t\t\t\tif(vDecompressed[i] != UncompressedBytes[i]) {\n\t\t\t\t\t\tnLog::error(\"mismatch on byte {}\", i);\n\t\t\t\t\t\treturn EXIT_FAILURE;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tstd::uint32_t ulCompressedSizeBe = nEndian::toBig32(std::uint32_t(vCompressed.size()));\n\t\t\t\tFileSamplePack.write(reinterpret_cast<char*>(&ulCompressedSizeBe), sizeof(ulCompressedSizeBe));\n\t\t\t\tFileSamplePack.write(\n\t\t\t\t\treinterpret_cast<const char*>(vCompressed.data()),\n\t\t\t\t\tvCompressed.size() * sizeof(vCompressed[0])\n\t\t\t\t);\n\t\t\t}\n\t\t\telse {\n\t\t\t\tstd::uint32_t ulCompressedSizeBe = 0;\n\t\t\t\tFileSamplePack.write(reinterpret_cast<char*>(&ulCompressedSizeBe), sizeof(ulCompressedSizeBe));\n\t\t\t\tFileSamplePack.write(\n\t\t\t\t\treinterpret_cast<const char*>(Sample.m_vData.data()),\n\t\t\t\t\tSample.m_vData.size() * sizeof(Sample.m_vData[0])\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t}\n\n\tstd::uint32_t ulIdx = 0;\n\tfor(const auto &pMod: vModsIn) {\n\t\tfmt::print(\"Writing {} to {}...\\n\", pMod->getSongName(), vOutNames[ulIdx]);\n\t\tpMod->toMod(vOutNames[ulIdx], isStripSamples);\n\t\t++ulIdx;\n\t}\n\n\tfmt::print(\"All done!\\n\");\n\treturn EXIT_SUCCESS;\n}\n"
  },
  {
    "path": "tools/src/pak_tool.cpp",
    "content": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at http://mozilla.org/MPL/2.0/. */\n\n#include <map>\n#include <fstream>\n#include <filesystem>\n#include <vector>\n#include <algorithm>\n#include \"common/logging.h\"\n#include \"common/fs.h\"\n#include \"common/endian.h\"\n#include \"common/compress.hpp\"\n#include \"common/stream.h\"\n\nstruct tPakEntry {\n\tstd::string ShortPath;\n\tstd::string Path;\n\tstd::uint32_t ulChecksum;\n\tstd::uint32_t ulUncompressedSize;\n\tstd::vector<std::uint8_t> vData;\n};\n\nstatic std::uint32_t adler32Buffer(const std::uint8_t *pData, std::uint32_t ulDataSize) {\n\tconstexpr std::uint32_t modulo = 65521;\n\tstd::uint32_t a = 1, b = 0;\n\tfor(std::uint32_t i = 0; i < ulDataSize; ++i) {\n\t\ta += pData[i];\n\t\tif(a >= modulo) {\n\t\t\ta -= modulo;\n\t\t}\n\t\tb += a;\n\t\tif(b >= modulo) {\n\t\t\tb -= modulo;\n\t\t}\n\t}\n\treturn (b << 16) | a;\n}\n\nstatic void printUsage(const std::string &szAppName) {\n\tusing fmt::print;\n\tprint(\"Usage:\\n\\t{} inDir outPak [extraOpts]\\n\\n\", szAppName);\n\tprint(\"Required arguments:\\n\");\n\tprint(\"\\tinDir   Path to input directory.\\n\");\n\tprint(\"\\toutPak  Path to output pak file.\\n\");\n\tprint(\"Extra options:\\n\");\n\tprint(\"\\t-c                Enable compression.\\n\");\n\tprint(\"\\t-r orderfile.txt  Reorder files with list file - one path per line. Omitted files will be appended at the end.\\n\");\n}\n\nint main(int lArgCount, const char *pArgs[])\n{\n\tusing namespace std::string_view_literals;\n\n\tconst std::uint8_t ubMandatoryArgCnt = 2;\n\tif(lArgCount - 1 < ubMandatoryArgCnt) {\n\t\tnLog::error(\"Too few arguments, expected {}\", ubMandatoryArgCnt);\n\t\tprintUsage(pArgs[0]);\n\t\treturn EXIT_FAILURE;\n\t}\n\n\tstd::string InPath(pArgs[1]);\n\tstd::string OutPath(pArgs[2]);\n\tstd::string OrderPath;\n\tbool isCompressed = false;\n\n\tfor(auto ArgIndex = 3; ArgIndex < lArgCount; ++ArgIndex) {\n\t\tstd::string_view Arg = pArgs[ArgIndex];\n\t\tif(Arg == \"-c\"sv) {\n\t\t\tisCompressed = true;\n\t\t}\n\t\telse if(Arg == \"-r\"sv && ArgIndex + 1 < lArgCount) {\n\t\t\tOrderPath = pArgs[++ArgIndex];\n\t\t}\n\t\telse {\n\t\t\tnLog::error(\"Unknown arg or missing value: '{}'\", pArgs[ArgIndex]);\n\t\t\tprintUsage(pArgs[0]);\n\t\t\treturn EXIT_FAILURE;\n\t\t}\n\t}\n\n\tif(!nFs::isDir(InPath)) {\n\t\tnLog::error(\"Path {} isn't a folder\", InPath);\n\t\treturn EXIT_FAILURE;\n\t}\n\n\tstd::ofstream FilePak;\n\tFilePak.open(OutPath, std::ios::binary);\n\tif(FilePak.fail()) {\n\t\tnLog::error(\"Can't open the file for writing\");\n\t\treturn EXIT_FAILURE;\n\t}\n\tstd::vector<tPakEntry> vEntries;\n\n\tauto AbsoluteBasePath = std::filesystem::absolute(InPath);\n\tbool isCollided = false;\n\tstd::vector<std::uint8_t> vFileContents;\n\tstd::vector<std::uint8_t> vPackBuffer;\n\tstd::vector<std::uint8_t> vDecompressed;\n  for (std::filesystem::recursive_directory_iterator i(InPath), end; i != end; ++i) {\n    if (!is_directory(i->path())) {\n\t\t\ttPakEntry Entry;\n\t\t\tEntry.ShortPath = std::filesystem::relative(i->path(), AbsoluteBasePath).generic_string();\n\t\t\tEntry.Path = i->path().generic_string();\n\t\t\tEntry.ulUncompressedSize = std::uint32_t(std::filesystem::file_size(Entry.Path));\n\t\t\tEntry.ulChecksum = adler32Buffer(\n\t\t\t\treinterpret_cast<const std::uint8_t*>(Entry.ShortPath.c_str()),\n\t\t\t\tstd::uint32_t(Entry.ShortPath.size())\n\t\t\t);\n\t\t\tfor(auto OtherIndex = 0; OtherIndex < vEntries.size(); ++OtherIndex) {\n\t\t\t\tif(Entry.ulChecksum == vEntries[OtherIndex].ulChecksum) {\n\t\t\t\t\tnLog::error(\"Entry {} checksum collision with entry {}\", vEntries.size(), OtherIndex);\n\t\t\t\t\tisCollided = true;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tstd::ifstream FileIn;\n\t\t\tFileIn.open(Entry.Path, std::ios::binary);\n\t\t\tif(FileIn.fail()) {\n\t\t\t\tnLog::error(\"Can't open the file\");\n\t\t\t\treturn EXIT_FAILURE;\n\t\t\t}\n\t\t\tvFileContents.resize(Entry.ulUncompressedSize);\n\t\t\tFileIn.read(reinterpret_cast<char*>(vFileContents.data()), Entry.ulUncompressedSize);\n\n\t\t\tif(isCompressed) {\n\t\t\t\tif(vPackBuffer.size() < Entry.ulUncompressedSize * 2) {\n\t\t\t\t\tvPackBuffer.resize(Entry.ulUncompressedSize * 2);\n\t\t\t\t}\n\t\t\t\tauto CompressedSize = (std::uint32_t)compressPack(\n\t\t\t\t\tvFileContents.data(), Entry.ulUncompressedSize, vPackBuffer.data()\n\t\t\t\t);\n\n\t\t\t\tvDecompressed.resize(Entry.ulUncompressedSize);\n\t\t\t\ttCompressUnpacker UnpackState;\n\t\t\t\tcompressUnpackerInit(&UnpackState, vPackBuffer.data(), CompressedSize, Entry.ulUncompressedSize);\n\t\t\t\twhile(true) {\n\t\t\t\t\tstd::uint8_t ubRead;\n\t\t\t\t\ttCompressUnpackResult eResult = compressUnpackerProcess(&UnpackState, &ubRead);\n\t\t\t\t\tif(eResult == COMPRESS_UNPACK_RESULT_DONE) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tif(eResult == COMPRESS_UNPACK_RESULT_BUSY_WROTE_BYTE) {\n\t\t\t\t\t\tvDecompressed[UnpackState.ulWriteOffset - 1] = ubRead;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tfor(std::size_t i = 0; i < Entry.ulUncompressedSize; ++i) {\n\t\t\t\t\tif(vDecompressed[i] != vFileContents[i]) {\n\t\t\t\t\t\tnLog::error(\"mismatch at index {}\", i);\n\t\t\t\t\t\treturn EXIT_FAILURE;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif(CompressedSize < vFileContents.size() - 10) {\n\t\t\t\t\tEntry.vData = std::vector(&vPackBuffer[0], &vPackBuffer[CompressedSize]);\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tEntry.vData = vFileContents;\n\t\t\t\t}\n\t\t\t}\n\t\t\telse {\n\t\t\t\tEntry.vData = vFileContents;\n\t\t\t}\n\n\t\t\tvEntries.push_back(Entry);\n\t\t}\n\t}\n\tfmt::print(\"Discovered {} files\\n\", vEntries.size());\n\tif(isCollided) {\n\t\tnLog::error(\"Aborting due to checksum collisions! Report an issue and/or change your file names a bit.\");\n\t\treturn EXIT_FAILURE;\n\t}\n\n\tif(!OrderPath.empty()) {\n\t\tfmt::println(FMT_STRING(\"Reordering files with {}...\"), OrderPath);\n\t\tstd::vector<tPakEntry> vOrderedEntries;\n\t\tstd::ifstream FileOrder;\n\t\tFileOrder.open(OrderPath);\n\t\tif(FileOrder.fail()) {\n\t\t\tnLog::error(\"Can't open the file\");\n\t\t\treturn EXIT_FAILURE;\n\t\t}\n\t\tstd::string NextPath;\n\t\twhile(nStream::getAnyLine(FileOrder, NextPath)) {\n\t\t\tauto Found = std::find_if(\n\t\t\t\tvEntries.begin(), vEntries.end(),\n\t\t\t\t[&NextPath](tPakEntry &Entry){ return Entry.ShortPath == NextPath;}\n\t\t\t);\n\t\t\tif(Found != vEntries.end()) {\n\t\t\t\tvOrderedEntries.push_back(*Found);\n\t\t\t\tvEntries.erase(Found);\n\t\t\t}\n\t\t\telse {\n\t\t\t\tfmt::println(FMT_STRING(\"WARN: ordered path '{}' not found or duplicate in added files\"), NextPath);\n\t\t\t}\n\t\t}\n\n\t\tfor(const auto &Unordered: vEntries) {\n\t\t\tfmt::println(FMT_STRING(\"WARN: unassigned order for file {}\"), Unordered.ShortPath);\n\t\t}\n\n\t\tvOrderedEntries.insert(vOrderedEntries.end(), vEntries.begin(), vEntries.end());\n\t\tvEntries = vOrderedEntries;\n\t}\n\n\tstd::uint16_t uwFileCount = std::uint16_t(vEntries.size());\n\tstd::uint16_t uwFileCountBe = nEndian::toBig16(uwFileCount);\n\tFilePak.write(reinterpret_cast<char*>(&uwFileCountBe), sizeof(uwFileCountBe));\n\tstd::uint32_t ulNextFileOffs = sizeof(uwFileCount) + (uwFileCount * 4 * sizeof(std::uint32_t));\n\tstd::uint16_t i = 0;\n\tfor(const auto &Entry: vEntries) {\n\t\tfmt::print(\n\t\t\t\"Writing subfile {:4d}: '{}', offset: {}, uncompressed: {}, size: {}, ratio: {:.2f}, checksum: {:08X}...\\n\",\n\t\t\ti++, Entry.ShortPath, ulNextFileOffs, Entry.ulUncompressedSize,\n\t\t\tEntry.vData.size(), float(Entry.vData.size()) / Entry.ulUncompressedSize * 100, Entry.ulChecksum\n\t\t);\n\n\t\tstd::uint32_t ulChecksumBe = nEndian::toBig32(Entry.ulChecksum);\n\t\tstd::uint32_t ulOffsBe = nEndian::toBig32(ulNextFileOffs);\n\t\tstd::uint32_t ulUncompressedSizeBe = nEndian::toBig32(Entry.ulUncompressedSize);\n\t\tstd::uint32_t ulDataSizeBe = nEndian::toBig32(std::uint32_t(Entry.vData.size()));\n\n\t\tFilePak.write(reinterpret_cast<char*>(&ulChecksumBe), sizeof(ulChecksumBe));\n\t\tFilePak.write(reinterpret_cast<char*>(&ulOffsBe), sizeof(ulOffsBe));\n\t\tFilePak.write(reinterpret_cast<const char*>(&ulUncompressedSizeBe), sizeof(ulUncompressedSizeBe));\n\t\tFilePak.write(reinterpret_cast<char*>(&ulDataSizeBe), sizeof(ulDataSizeBe));\n\n\t\tulNextFileOffs += std::uint32_t(Entry.vData.size());\n\t}\n\n\tfor(const auto &Entry: vEntries) {\n\t\tstd::uint32_t UncompressedSizeBe = isCompressed ? nEndian::toBig32(Entry.ulUncompressedSize) : 0;\n\t\tFilePak.write(reinterpret_cast<const char *>(Entry.vData.data()), Entry.vData.size());\n\t}\n\n\tfmt::print(\"All done!\\n\");\n\treturn EXIT_SUCCESS;\n}\n"
  },
  {
    "path": "tools/src/palette_conv.cpp",
    "content": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at http://mozilla.org/MPL/2.0/. */\n\n#include \"common/logging.h\"\n#include \"common/fs.h\"\n#include \"common/palette.h\"\n#include \"common/bitmap.h\"\n#include <cstring>\n#include <exception>\n#include <string>\n#include <vector>\n\nvoid printUsage(const std::string &szAppName) {\n\tusing fmt::print;\n\tfmt::print(\"Usage:\\n\\t{} [options] inPath.ext [outPath.ext]\\n\", szAppName);\n\tprint(\"\\nOptions:\\n\");\n\tprint(\"\\t-ocs\\t\\tWrite .plt v2 with ECS/OCS packed 12-bit entries (default)\\n\");\n\tprint(\"\\t-aga\\t\\tWrite .plt v2 with AGA color entries\\n\");\n\tprint(\"extraOpts:\\n\");\n\tprint(\"\\t-cc\\t\\tConvert colors. Truncate non-OCS colors to OCS precision if necessary\\n\");\n\tprint(\"\\ninPath\\t- path to supported input palette file\\n\");\n\tprint(\"outPath\\t- path to output palette file\\n\");\n\tprint(\"ext\\t- one of the following:\\n\");\n\tprint(\"\\tgpl\\tGIMP Palette\\n\");\n\tprint(\"\\tact\\tAdobe Color Table\\n\");\n\tprint(\"\\tpal\\tProMotion palette\\n\");\n\tprint(\"\\tplt\\tACE palette (default)\\n\");\n\tprint(\"\\tpng\\tPalette preview\\n\");\n}\n\nint main(int lArgCount, const char *pArgs[]) {\n\tbool isUseOcs = true;\n\tbool isClampToOcs = false;\n\n\tstd::vector<const char *> Positionals;\n\n\tfor(int i = 1; i < lArgCount; ++i) {\n\t\tif(std::strcmp(pArgs[i], \"-ocs\") == 0) {\n\t\t\tisUseOcs = true;\n\t\t}\n\t\telse if(std::strcmp(pArgs[i], \"-aga\") == 0) {\n\t\t\tisUseOcs = false;\n\t\t}\n\t\telse if(std::strcmp(pArgs[i], \"-cc\") == 0) {\n\t\t\tisClampToOcs = true;\n\t\t}\n\t\telse if(pArgs[i][0] == '-') {\n\t\t\tnLog::error(\"Unknown option: '{}'\", pArgs[i]);\n\t\t\tprintUsage(pArgs[0]);\n\t\t\treturn EXIT_FAILURE;\n\t\t}\n\t\telse {\n\t\t\tPositionals.push_back(pArgs[i]);\n\t\t}\n\t}\n\n\tif(Positionals.empty()) {\n\t\tnLog::error(\"Too few arguments, expected input path\");\n\t\tprintUsage(pArgs[0]);\n\t\treturn EXIT_FAILURE;\n\t}\n\n\tstd::string szPathIn = Positionals[0];\n\tstd::string szPathOut = nFs::removeExt(szPathIn) + \".gpl\";\n\n\tif(Positionals.size() > 1) {\n\t\tszPathOut = Positionals[1];\n\t}\n\n\t// Load input palette\n\ttPalette Palette;\n\ttry {\n\t\tPalette = tPalette::fromFile(szPathIn);\n\t}\n\tcatch(const std::exception &Exc) {\n\t\tnLog::error(\"{}\", Exc.what());\n\t\treturn EXIT_FAILURE;\n\t}\n\tif(Palette.m_vColors.empty()) {\n\t\tnLog::error(\"Invalid input path or palette is empty: '{}'\", szPathIn);\n\t\treturn 1;\n\t}\n\tfmt::print(\"Loaded palette: '{}'\\n\", szPathIn);\n\n\t// Generate output palette\n\tstd::string szExtOut = nFs::getExt(szPathOut);\n\tbool isOk = false;\n\tif(nFs::getExt(szPathIn) == szExtOut) {\n\t\tnLog::error(\"Input and output extensions are the same\");\n\t\treturn EXIT_FAILURE;\n\t}\n\n\ttry {\n\t\tif(szExtOut == \"gpl\") {\n\t\t\tisOk = Palette.toGpl(szPathOut);\n\t\t}\n\t\telse if(szExtOut == \"act\") {\n\t\t\tisOk = Palette.toAct(szPathOut);\n\t\t}\n\t\telse if(szExtOut == \"pal\") {\n\t\t\tisOk = Palette.toPromotionPal(szPathOut);\n\t\t}\n\t\telse if(szExtOut == \"plt\") {\n\t\t\tisOk = Palette.toPlt(szPathOut, isUseOcs, isClampToOcs);\n\t\t}\n\t\telse if(szExtOut == \"png\") {\n\t\t\tauto ColorCount = Palette.m_vColors.size();\n\t\t\ttChunkyBitmap PltPreview(ColorCount * 32, 16);\n\n\t\t\tfor(std::uint8_t i = 0; i < ColorCount; ++i) {\n\t\t\t\tconst auto &Color = Palette.m_vColors[i];\n\n\t\t\t\tPltPreview.fillRect(i * 32, 0, 32, 16, Color);\n\t\t\t\tisOk = PltPreview.toPng(szPathOut);\n\t\t\t}\n\t\t}\n\t\telse {\n\t\t\tnLog::error(\"unsupported output extension: '{}'\", szExtOut);\n\t\t\tprintUsage(pArgs[0]);\n\t\t\treturn EXIT_FAILURE;\n\t\t}\n\t}\n\tcatch(const std::exception &Exc) {\n\t\tnLog::error(\"Writing palette failed: {}\", Exc.what());\n\t}\n\n\tif(!isOk) {\n\t\tnLog::error(\"Couldn't write to '{}'\", szPathOut);\n\t\treturn EXIT_FAILURE;\n\t}\n\tfmt::print(\"Generated palette: '{}'\\n\", szPathOut);\n\n\treturn EXIT_SUCCESS;\n}\n"
  },
  {
    "path": "tools/src/tileset_conv.cpp",
    "content": "/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at http://mozilla.org/MPL/2.0/. */\n\n#include <optional>\n#include \"common/bitmap.h\"\n#include \"common/logging.h\"\n#include \"common/parse.h\"\n#include \"common/fs.h\"\n#include \"common/math.h\"\n#include \"common/exception.h\"\n\nstruct tConfig {\n\tstd::int32_t m_lTileSize;\n\tstd::int32_t m_lTileHeight;\n\tstd::string m_szInPath;\n\tstd::string m_szOutPath;\n\tstd::string m_szPalettePath;\n\tbool m_isInterleaved;\n\tstd::int32_t m_lColumns;\n\tstd::optional<int32_t> m_lColumnWidth;\n\tbool m_isVaryingHeight;\n\tbool m_isHeightOverride;\n\n\ttConfig(const std::vector<const char*> &vArgs);\n};\n\ntConfig::tConfig(const std::vector<const char*> &vArgs)\n{\n\tauto ArgCount = vArgs.size();\n\tif(ArgCount - 1 < 3) {\n\t\tthrow std::runtime_error(fmt::format(\"Too few arguments, got {}\", ArgCount - 1));\n\t}\n\n\tif(!nParse::toInt32(vArgs[2], \"tileSize\", m_lTileSize) || m_lTileSize < 0) {\n\t\tthrow std::runtime_error(nullptr);\n\t}\n\tm_lTileHeight = m_lTileSize;\n\n\tm_szInPath = vArgs[1];\n\tm_szOutPath = vArgs[3];\n\tm_isInterleaved = false;\n\tm_lColumns = 1;\n\tm_isVaryingHeight = false;\n\tm_isHeightOverride = false;\n\n\tfor(auto ArgIndex = 4; ArgIndex < ArgCount; ++ArgIndex) {\n\t\tif(vArgs[ArgIndex] == std::string(\"-i\")) {\n\t\t\tm_isInterleaved = true;\n\t\t}\n\t\telse if(vArgs[ArgIndex] == std::string(\"-vh\")) {\n\t\t\tm_isVaryingHeight = true;\n\t\t}\n\t\telse if(vArgs[ArgIndex] == std::string(\"-plt\") && ArgIndex < ArgCount - 1) {\n\t\t\t++ArgIndex;\n\t\t\tm_szPalettePath = vArgs[ArgIndex];\n\t\t}\n\t\telse if(vArgs[ArgIndex] == std::string(\"-cols\") && ArgIndex < ArgCount - 1) {\n\t\t\t++ArgIndex;\n\t\t\tif(!nParse::toInt32(vArgs[ArgIndex], \"-cols\", m_lColumns)) {\n\t\t\t\tthrow std::runtime_error(nullptr); // error message inside parsing fn\n\t\t\t}\n\t\t\tif(m_lColumns <= 0) {\n\t\t\t\tthrow std::runtime_error(\"-cols value must be positive\");\n\t\t\t}\n\t\t}\n\t\telse if(vArgs[ArgIndex] == std::string(\"-cw\") && ArgIndex < ArgCount - 1) {\n\t\t\t++ArgIndex;\n\t\t\tstd::int32_t lColumnWidth;\n\t\t\tif(!nParse::toInt32(vArgs[ArgIndex], \"-cw\", lColumnWidth)) {\n\t\t\t\tthrow std::runtime_error(nullptr); // error message inside parsing fn\n\t\t\t}\n\t\t\tif(lColumnWidth <= 0) {\n\t\t\t\tthrow std::runtime_error(\"-cw value must be positive\");\n\t\t\t}\n\t\t\tm_lColumnWidth = lColumnWidth;\n\t\t}\n\t\telse if(vArgs[ArgIndex] == std::string(\"-h\") && ArgIndex < ArgCount - 1) {\n\t\t\t++ArgIndex;\n\t\t\tif(!nParse::toInt32(vArgs[ArgIndex], \"-h\", m_lTileHeight)) {\n\t\t\t\tthrow std::runtime_error(nullptr);\n\t\t\t}\n\t\t\tif(m_lTileHeight <= 0) {\n\t\t\t\tthrow std::runtime_error(\"-h value must be positive\");\n\t\t\t}\n\t\t\tm_isHeightOverride = true;\n\t\t\tfmt::print(\"Override tile height to {}\\n\", m_lTileHeight);\n\t\t}\n\t}\n\n\tif(m_isVaryingHeight && m_isHeightOverride) {\n\t\tthrow std::runtime_error(\"Can't use -vh and -h params together!\");\n\t}\n\n\tif(m_isVaryingHeight && m_lColumns != 1) {\n\t\tthrow std::runtime_error(\"Can't use -vh and -cols params togeter!\");\n\t}\n}\n\nstatic void printUsage(const std::string &szAppName)\n{\n\t// tileset_conv inPath tileSize outPath\n\tusing fmt::print;\n\tprint(\"Usage:\\n\\t{} inPath tileSize outPath\\n\\n\", szAppName);\n\tprint(\"inPath  \\t- path to input file/directory\\n\");\n\tprint(\"tileSize\\t- size of tile's edge, in pixels. For rectangular tiles, controls the tile width.\\n\");\n\tprint(\"outPath \\t- path to output file/directory\\n\");\n\tprint(\"\\nWhen using .bm as output:\\n\");\n\tprint(\"-i              \\t- save as interleaved bitmap\\n\");\n\tprint(\"\\nWhen using .bm as input or output:\\n\");\n\tprint(\"-plt palettePath\\t- use following palette\\n\");\n\tprint(\"\\nAdditional options:\\n\");\n\tprint(\"-cols        \\t- number of columns to use in output (default: 1)\\n\");\n\tprint(\"-cw          \\t- override tile column width, useful for tiles of width not equal to multiple of 16px\\n\");\n\tprint(\"-h tileHeight\\t- override height for rectangular tiles\\n\");\n\tprint(\"-vh          \\t- enable varying height (can't be used with -h and -cols)\\n\");\n}\n\n/**\n * @brief Reads config from source file.\n *\n * @param Config Configuration parameters of read operation.\n * @return Vector of tiles, each stored in separate chunky bitmap.\n *\n * @note Empty tiles are returned as chunky bitmaps with width/height set to zero.\n */\nstatic std::vector<tChunkyBitmap> readTiles(\n\tconst tConfig &Config, const std::optional<tPalette> &Palette\n)\n{\n\tstd::vector<tChunkyBitmap> vTiles;\n\tstd::string szInExt = nFs::getExt(Config.m_szInPath);\n\tif(szInExt == \"png\" || szInExt == \"bm\") {\n\t\ttChunkyBitmap In;\n\t\tauto ColumnWidth = Config.m_lColumnWidth.has_value() ? Config.m_lColumnWidth.value() : Config.m_lTileSize;\n\t\tif(szInExt == \"png\") {\n\t\t\tIn = tChunkyBitmap::fromPng(Config.m_szInPath);\n\t\t}\n\t\telse if(szInExt == \"bm\") {\n\t\t\tif(!Palette.has_value()) {\n\t\t\t\tthrow new std::runtime_error(\"No palette specified to use for .bm file read\");\n\t\t\t}\n\n\t\t\tauto InPlanar = tPlanarBitmap::fromBm(Config.m_szInPath);\n\t\t\tIn = tChunkyBitmap(InPlanar, Palette.value());\n\t\t}\n\n\t\tif(In.m_uwHeight <= 0) {\n\t\t\tthrow std::runtime_error(fmt::format(\"Couldn't load input file: '{}'\", Config.m_szInPath));\n\t\t}\n\n\t\tif(In.m_uwHeight % Config.m_lTileHeight != 0 && !Config.m_isVaryingHeight) {\n\t\t\tthrow std::runtime_error(fmt::format(\"Input bitmap height is not divisible by {}\", Config.m_lTileHeight));\n\t\t}\n\n\t\tif(In.m_uwWidth % Config.m_lTileSize != 0) {\n\t\t\tthrow std::runtime_error(fmt::format(\"Input bitmap width is not divisible by {}\", Config.m_lTileSize));\n\t\t}\n\n\t\tstd::uint16_t TileCountHoriz = In.m_uwWidth / ColumnWidth;\n\t\tstd::uint16_t TileCountVert = In.m_uwHeight / Config.m_lTileHeight;\n\n\t\tvTiles.reserve(TileCountHoriz * TileCountVert);\n\t\tfor(std::uint16_t y = 0; y < TileCountVert; ++y) {\n\t\t\tfor(std::uint16_t x = 0; x < TileCountHoriz; ++x) {\n\t\t\t\ttChunkyBitmap Tile(Config.m_lTileSize, Config.m_lTileHeight);\n\t\t\t\tIn.copyRect(\n\t\t\t\t\tx * ColumnWidth, y * Config.m_lTileHeight, Tile, 0, 0,\n\t\t\t\t\tConfig.m_lTileSize, Config.m_lTileHeight\n\t\t\t\t);\n\t\t\t\tvTiles.push_back(std::move(Tile));\n\t\t\t}\n\t\t}\n\t}\n\telse if(nFs::isDir(Config.m_szInPath)) {\n\t\tuint32_t ulMaxTileIndex = 0;\n\t\tnFs::iterateDirectory(Config.m_szInPath, [&ulMaxTileIndex](const std::string &szFileName) {\n\t\t\tauto BaseName = nFs::removeExt(szFileName);\n\t\t\ttry {\n\t\t\t\t// watch out for `.`,  `..` and any other filename that might mess up stoul\n\t\t\t\tauto TileIndex = std::stoul(BaseName);\n\t\t\t\tif(TileIndex > ulMaxTileIndex) {\n\t\t\t\t\tulMaxTileIndex = TileIndex;\n\t\t\t\t}\n\t\t\t}\n\t\t\tcatch(...) {}\n\t\t});\n\n\t\tstd::int16_t wLastFull = -1;\n\t\tfor(std::uint16_t i = 0; i <= ulMaxTileIndex; ++i) {\n\t\t\tauto Tile = tChunkyBitmap::fromPng(fmt::format(\"{}/{}.png\", Config.m_szInPath, i));\n\t\t\tif(Tile.m_uwHeight != 0) {\n\t\t\t\twLastFull = i;\n\t\t\t\tif(!Config.m_isVaryingHeight && Tile.m_uwHeight != Config.m_lTileHeight) {\n\t\t\t\t\tthrow std::runtime_error(fmt::format(\n\t\t\t\t\t\t\"Tile {} height doesn't match others: got {}, expected {}\",\n\t\t\t\t\t\ti, Tile.m_uwHeight, Config.m_lTileHeight\n\t\t\t\t\t));\n\t\t\t\t}\n\t\t\t}\n\t\t\tvTiles.push_back(std::move(Tile));\n\t\t}\n\t\tvTiles.resize(wLastFull + 1);\n\t}\n\telse {\n\t\tthrow std::runtime_error(fmt::format(\"Unsupported input extension: '{}'\", szInExt));\n\t}\n\treturn vTiles;\n}\n\nstatic void saveTiles(\n\tconst std::vector<tChunkyBitmap> &vTiles, const std::optional<tPalette> &Palette,\n\tconst tConfig &Config\n)\n{\n\tauto TileCount = vTiles.size();\n\tstd::string szOutExt = nFs::getExt(Config.m_szOutPath);\n\tif(szOutExt == \"png\" || szOutExt == \"bm\") {\n\t\ttRgb Bg;\n\t\tif(Palette.has_value() && !Palette.value().m_vColors.empty()) {\n\t\t\tBg = Palette.value().m_vColors.at(0);\n\t\t}\n\t\tfmt::print(\"Using color for bg: #{:02X}{:02X}{:02X}\\n\", Bg.ubR, Bg.ubG, Bg.ubB);\n\n\t\tstd::optional<tChunkyBitmap> Out;\n\t\tauto ColumnWidth = Config.m_lColumnWidth.has_value() ? Config.m_lColumnWidth.value() : Config.m_lTileSize;\n\t\tif(Config.m_lColumns != 1) {\n\t\t\tOut = std::make_optional<tChunkyBitmap>(\n\t\t\t\tuint16_t(ColumnWidth * Config.m_lColumns),\n\t\t\t\tuint16_t(ceilToFactor(TileCount, Config.m_lColumns) * Config.m_lTileHeight),\n\t\t\t\tBg\n\t\t\t);\n\n\t\t\tfor(std::uint16_t i = 0; i < TileCount; ++i) {\n\t\t\t\tauto &Tile = vTiles.at(i);\n\t\t\t\tif(Tile.m_uwHeight != 0) {\n\t\t\t\t\tTile.copyRect(\n\t\t\t\t\t\t0, 0, Out.value(),\n\t\t\t\t\t\t(i % Config.m_lColumns) * ColumnWidth,\n\t\t\t\t\t\tConfig.m_lTileHeight * (i / Config.m_lColumns),\n\t\t\t\t\t\tConfig.m_lTileSize, Config.m_lTileHeight\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\telse {\n\t\t\tstd::uint16_t uwTilesetHeight = 0;\n\t\t\tif(Config.m_isVaryingHeight) {\n\t\t\t\tbool hasEmptyTile = false;\n\t\t\t\tfor(const auto &Tile: vTiles) {\n\t\t\t\t\tif(Tile.m_uwHeight == 0) {\n\t\t\t\t\t\tthrow std::runtime_error(\"Empty tiles not allowed inside varying-height tilesets!\");\n\t\t\t\t\t}\n\t\t\t\t\tuwTilesetHeight += Tile.m_uwHeight;\n\t\t\t\t}\n\t\t\t}\n\t\t\telse {\n\t\t\t\tuwTilesetHeight = uint16_t(Config.m_lTileHeight * TileCount);\n\t\t\t}\n\n\t\t\tOut = std::make_optional<tChunkyBitmap>(\n\t\t\t\tColumnWidth, uwTilesetHeight, Bg\n\t\t\t);\n\n\t\t\tstd::uint16_t uwOffsY = 0;\n\t\t\tfor(const auto &Tile: vTiles) {\n\t\t\t\tTile.copyRect(\n\t\t\t\t\t0, 0, Out.value(), 0, uwOffsY, Tile.m_uwWidth, Tile.m_uwHeight\n\t\t\t\t);\n\t\t\t\tuwOffsY += Config.m_isVaryingHeight ? Tile.m_uwHeight : Config.m_lTileHeight;\n\t\t\t}\n\t\t}\n\n\t\tif(szOutExt == \"png\" && !Out.value().toPng(Config.m_szOutPath)) {\n\t\t\tthrow std::runtime_error(fmt::format(\"Couldn't write output to '{}'\", Config.m_szOutPath));\n\t\t}\n\t\telse if(szOutExt == \"bm\") {\n\t\t\tif(!Palette.has_value() || Palette.value().m_vColors.size() == 0) {\n\t\t\t\tthrow std::runtime_error(\"No valid palette specified\");\n\t\t\t}\n\t\t\ttPlanarBitmap PlanarOut(Out.value(), Palette.value());\n\t\t\tif(PlanarOut.m_uwHeight == 0) {\n\t\t\t\tthrow std::runtime_error(\"Problem with planar conversion\");\n\t\t\t}\n\t\t\tif(!PlanarOut.toBm(Config.m_szOutPath, Config.m_isInterleaved)) {\n\t\t\t\tthrow std::runtime_error(fmt::format(\"Couldn't write to '{}'\", Config.m_szOutPath));\n\t\t\t}\n\t\t}\n\t}\n\telse if(szOutExt == \"\") {\n\t\t// Tile directory\n\t\tnFs::dirCreate(Config.m_szOutPath);\n\t\tfor(std::uint16_t i = 0; i < TileCount; ++i) {\n\t\t\tauto &Tile = vTiles.at(i);\n\t\t\tif(Tile.m_uwHeight != 0) {\n\t\t\t\tstd::string szTilePath = fmt::format(\"{}/{}.png\", Config.m_szOutPath, i);\n\t\t\t\tif(!Tile.toPng(szTilePath)) {\n\t\t\t\t\tthrow std::runtime_error(fmt::format(\"Couldn't write tile to '{}'\", szTilePath));\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\telse {\n\t\tthrow std::runtime_error(fmt::format(\"Unsupported output extension: '{}'\", szOutExt));\n\t}\n}\n\nint main(int lArgCount, const char *pArgs[])\n{\n\tstd::optional<tConfig> Config;\n\ttry {\n\t\tstd::vector<const char*> Args(pArgs, pArgs + lArgCount);\n\t\tConfig = std::make_optional<tConfig>(Args);\n\t}\n\tcatch(std::exception &Ex) {\n\t\texceptionHandle(Ex, \"parsing parameters\");\n\t\tprintUsage(pArgs[0]);\n\t\treturn EXIT_FAILURE;\n\t}\n\n\tstd::optional<tPalette> Palette;\n\tif(!Config->m_szPalettePath.empty()) {\n\t\tPalette = tPalette::fromFile(Config->m_szPalettePath);\n\t\tif(Palette.value().m_vColors.empty()) {\n\t\t\tnLog::error(\"Couldn't read palette: '{}'\", Config->m_szPalettePath);\n\t\t\treturn EXIT_FAILURE;\n\t\t}\n\t\tfmt::print(\n\t\t\t\"Read {} colors from '{}'\\n\",\n\t\t\tPalette.value().m_vColors.size(), Config->m_szPalettePath\n\t\t);\n\t}\n\n\tstd::vector<tChunkyBitmap> vTiles;\n\ttry {\n\t\tvTiles = readTiles(Config.value(), Palette);\n\t\tfmt::print(\"Read {} tiles from '{}'\\n\", vTiles.size(), Config->m_szInPath);\n\t}\n\tcatch(std::exception &Ex) {\n\t\texceptionHandle(Ex, \"reading tiles\");\n\t\treturn EXIT_FAILURE;\n\t}\n\n\ttry {\n\t\tsaveTiles(vTiles, Palette, Config.value());\n\t}\n\tcatch(std::exception &Ex) {\n\t\texceptionHandle(Ex, \"writing tiles\");\n\t}\n\n\treturn EXIT_SUCCESS;\n}\n"
  }
]