├── .gitignore ├── LICENSE ├── app_icon.ico ├── build.bat ├── readme.md ├── source ├── build.cpp ├── game_impl.cpp ├── main.cpp ├── mygame.hpp └── pixie │ ├── app.h │ ├── array.hpp │ ├── assetsys.h │ ├── audiosys.h │ ├── binary_rw.h │ ├── cpp_compat.hpp │ ├── crt_frame.h │ ├── crtemu.h │ ├── dictionary.hpp │ ├── dir.h │ ├── dr_wav.h │ ├── ease.h │ ├── file.h │ ├── file_util.h │ ├── frametimer.h │ ├── funccall.hpp │ ├── gamepad.h │ ├── gamestate.hpp │ ├── graph.hpp │ ├── handles.h │ ├── hashtable.h │ ├── ini.h │ ├── inputmap.h │ ├── jar_mod.h │ ├── jar_xm.h │ ├── log.h │ ├── math_util.hpp │ ├── mempool.hpp │ ├── objrepo.hpp │ ├── paldither.h │ ├── palettize.h │ ├── pixelfont.h │ ├── pixie.hpp │ ├── pixie_build.hpp │ ├── refcount.hpp │ ├── resources.hpp │ ├── rnd.h │ ├── sort.hpp │ ├── stb_image.h │ ├── stb_perlin.h │ ├── stb_vorbis.h │ ├── strpool.h │ ├── strpool.hpp │ ├── strpool_util.hpp │ ├── thread.h │ ├── tween.hpp │ └── vecmath.hpp └── source_data ├── Deltoid-sans.fnt ├── Volter__28Goldfish_29.fnt ├── background.png ├── bitpolka.xm ├── build.ini └── palette.png /.gitignore: -------------------------------------------------------------------------------- 1 | .runtime 2 | .build_temp 3 | .git 4 | .vs 5 | mssccprj.scc 6 | *.ncb 7 | *.sln 8 | *.vcproj 9 | *.vcxproj 10 | *.suo 11 | *.vspscc 12 | *.filters 13 | *.user 14 | source_data 15 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | ------------------------------------------------------------------------------ 2 | 3 | This software is available under 2 licenses - you may choose the one you like. 4 | 5 | ------------------------------------------------------------------------------ 6 | 7 | ALTERNATIVE A - MIT License 8 | 9 | Copyright (c) 2018 Mattias Gustavsson 10 | 11 | Permission is hereby granted, free of charge, to any person obtaining a copy of 12 | this software and associated documentation files (the "Software"), to deal in 13 | the Software without restriction, including without limitation the rights to 14 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 15 | of the Software, and to permit persons to whom the Software is furnished to do 16 | so, subject to the following conditions: 17 | 18 | The above copyright notice and this permission notice shall be included in all 19 | copies or substantial portions of the Software. 20 | 21 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 22 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 23 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 24 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 25 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 26 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 27 | SOFTWARE. 28 | 29 | ------------------------------------------------------------------------------ 30 | 31 | ALTERNATIVE B - Public Domain (www.unlicense.org) 32 | 33 | This is free and unencumbered software released into the public domain. 34 | 35 | Anyone is free to copy, modify, publish, use, compile, sell, or distribute this 36 | software, either in source code form or as a compiled binary, for any purpose, 37 | commercial or non-commercial, and by any means. 38 | 39 | In jurisdictions that recognize copyright laws, the author or authors of this 40 | software dedicate any and all copyright interest in the software to the public 41 | domain. We make this dedication for the benefit of the public at large and to 42 | the detriment of our heirs and successors. We intend this dedication to be an 43 | overt act of relinquishment in perpetuity of all present and future rights to 44 | this software under copyright law. 45 | 46 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 47 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 48 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 49 | AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 50 | ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 51 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 52 | 53 | ------------------------------------------------------------------------------ 54 | -------------------------------------------------------------------------------- /app_icon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mattiasgustavsson/pixie/590856bd400d40ab5b8c5ae013f72e3e59677b5e/app_icon.ico -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | Pixie retro game dev library 2 | ============================ 3 | 4 | Pixie is my own little game engine for C/C++. A basic framework for making small retro styled 2D games. It supports 256 colors, and draws some of its inspiration from old-school BASIC programming languages. 5 | 6 | Currently, the code is very much in pre-beta stage. Expect lots of things not to work. There's no documentation. There are bits missing, and bits which are just plain wrong. I am putting it up here so I have a place to point people to when I ask them to look things over and give me feedback - but it is probably too early to start using it for a real project. 7 | 8 | At this point, I am not accepting any pull requests - but feel free to report issues if you find them. Also, I am happy to answer questions and discuss the code - best way is to message me on twitter, I'm @Mattias_G 9 | -------------------------------------------------------------------------------- /source/build.cpp: -------------------------------------------------------------------------------- 1 | #ifdef BUILD_DATA 2 | 3 | 4 | #define _CRT_NONSTDC_NO_DEPRECATE 5 | #define _CRT_SECURE_NO_WARNINGS 6 | 7 | #pragma warning( push ) 8 | #pragma warning( disable: 4548 ) // expression before comma has no effect; expected expression with side-effect 9 | #include 10 | #pragma warning( pop ) 11 | 12 | #include 13 | #include 14 | #include 15 | 16 | #ifndef NDEBUG 17 | #pragma warning( push ) 18 | #pragma warning( disable: 4619 ) // pragma warning : there is no warning number 'number' 19 | #pragma warning( disable: 4668 ) // 'symbol' is not defined as a preprocessor macro, replacing with '0' for 'directives' 20 | #include 21 | #pragma warning( pop ) 22 | #endif 23 | 24 | #include "pixie/pixie_build.hpp" 25 | 26 | int main( int argc, char** argv ) 27 | { 28 | (void) argc, argv; 29 | #ifndef NDEBUG 30 | int flag = _CrtSetDbgFlag( _CRTDBG_REPORT_FLAG ); // Get current flag 31 | flag ^= _CRTDBG_LEAK_CHECK_DF; // Turn on leak-checking bit 32 | _CrtSetDbgFlag( flag ); // Set flag to the new value 33 | // _CrtSetBreakAlloc( 0 ); 34 | #endif 35 | 36 | // run asset builder on commandline switches -build, -rebuild, clean 37 | pixie_build::build_action build = pixie_build::BUILD_ACTION_UNDEFINED; 38 | for( int i = 1; i < argc; ++i ) 39 | { 40 | if( stricmp( argv[ i ], "-build" ) == 0 ) build = pixie_build::BUILD_ACTION_BUILD; 41 | if( stricmp( argv[ i ], "-rebuild" ) == 0 ) build = pixie_build::BUILD_ACTION_REBUILD; 42 | if( stricmp( argv[ i ], "-clean" ) == 0 ) build = pixie_build::BUILD_ACTION_CLEAN; 43 | } 44 | if( build != pixie_build::BUILD_ACTION_UNDEFINED ) //return pixie_build::build( build, "../source_data", "../.buildtemp/data", "data" ); 45 | { 46 | pixie_build::compiler_list compiler_list[] = 47 | { 48 | { "pixie_copy", pixie_build::compiler_pixie_copy, }, 49 | { "pixie_palette", pixie_build::compiler_pixie_palette, }, 50 | { "pixie_bitmap", pixie_build::compiler_pixie_bitmap, }, 51 | // { "pixie_font", compiler_pixie_font, }, 52 | // { "afterworld_texture", afterworld_build::compiler_afterworld_texture, }, 53 | }; 54 | return pixie_build::build( build, "../source_data", "../.build_temp/data", "data", 55 | compiler_list, sizeof( compiler_list ) / sizeof( *compiler_list ) ); 56 | } 57 | } 58 | 59 | extern "C" int __stdcall WinMain( struct HINSTANCE__*, struct HINSTANCE__*, char*, int ) { return main( __argc, __argv ); } 60 | 61 | #define PIXIE_BUILD_IMPLEMENTATION 62 | #include "pixie/pixie_build.hpp" 63 | 64 | 65 | #endif /*BUILD_DATA*/ 66 | 67 | -------------------------------------------------------------------------------- /source/game_impl.cpp: -------------------------------------------------------------------------------- 1 | #ifndef BUILD_DATA 2 | 3 | // game implementation 4 | #include "mygame.hpp" 5 | 6 | #endif /*BUILD_DATA*/ 7 | -------------------------------------------------------------------------------- /source/main.cpp: -------------------------------------------------------------------------------- 1 | #ifndef BUILD_DATA 2 | 3 | #include "pixie/pixie.hpp" 4 | 5 | int mygame(); // forward declare game main func 6 | 7 | #define _CRT_NONSTDC_NO_DEPRECATE 8 | #define _CRT_SECURE_NO_WARNINGS 9 | #include 10 | #include 11 | #include 12 | 13 | #ifndef NDEBUG 14 | #pragma warning( push ) 15 | #pragma warning( disable: 4619 ) // pragma warning : there is no warning number 'number' 16 | #pragma warning( disable: 4668 ) // 'symbol' is not defined as a preprocessor macro, replacing with '0' for 'directives' 17 | #include 18 | #pragma warning( pop ) 19 | #endif 20 | 21 | int main( int argc, char** argv ) 22 | { 23 | (void) argc, argv; 24 | #ifndef NDEBUG 25 | int flag = _CrtSetDbgFlag( _CRTDBG_REPORT_FLAG ); // Get current flag 26 | flag ^= _CRTDBG_LEAK_CHECK_DF; // Turn on leak-checking bit 27 | _CrtSetDbgFlag( flag ); // Set flag to the new value 28 | // _CrtSetBreakAlloc( 0 ); 29 | #endif 30 | 31 | // run game 32 | return pixie::run( mygame ); 33 | } 34 | 35 | // pass-through so the program will build with either /SUBSYSTEM:WINDOWS or /SUBSYSTEN:CONSOLE 36 | #include // for __argc/__argv 37 | extern "C" int __stdcall WinMain( struct HINSTANCE__*, struct HINSTANCE__*, char*, int ) { return main( __argc, __argv ); } 38 | 39 | 40 | #define PIXIE_IMPLEMENTATION 41 | #include "pixie/pixie.hpp" 42 | 43 | #endif /*BUILD_DATA*/ 44 | 45 | -------------------------------------------------------------------------------- /source/mygame.hpp: -------------------------------------------------------------------------------- 1 | #include "pixie/pixie.hpp" 2 | 3 | using namespace pixie; 4 | 5 | int mygame() 6 | { 7 | title( "My game" ); 8 | screen_size( 320, 200 ); 9 | fullscreen( true ); 10 | crt_mode( true ); // turn on cathode ray tube emulation shader 11 | 12 | load_palette( "data/palette.pal" ); 13 | play_music( "data/bitpolka.xm" ); 14 | 15 | sprite background; 16 | background 17 | .bitmap( "data/background.pix" ) 18 | .position_y( -200 ) 19 | ; 20 | 21 | tween( 1.0f ) 22 | .delay( 2.0f ) 23 | .property( property_position_y( &background ), 0.0f ) 24 | .ease( ease_bounce_out ) 25 | .on_complete( 26 | [&background]() 27 | { 28 | tween( 1.0f ) 29 | .delay( 12.0f ) 30 | .property( property_position_y( &background ), 200.0f ) 31 | .ease( ease_back_in ) 32 | ; 33 | } 34 | ) 35 | ; 36 | 37 | label title; 38 | title 39 | .text( "Pixie retro game dev library" ) 40 | .font( "data/Deltoid-sans.fnt" ) 41 | .position( -160.0f, 10.0f ) 42 | .align( TEXT_ALIGN_CENTER ) 43 | .color( brightest_color() ) 44 | .outline( 17 ) 45 | .bold( true ) 46 | .shadow( 0, 2.0f, 2.0f ) 47 | ; 48 | 49 | tween( 1.0f ) 50 | .delay( 1.0f ) 51 | .property( property_position_x( &title ), 160.0f ) 52 | .ease( ease_quad_out ) 53 | ; 54 | 55 | label intro; 56 | intro 57 | .font( "data/Volter__28Goldfish_29.fnt" ) 58 | .position( 40.0f, 50.0f ) 59 | .wrap( 240 ) 60 | .align( TEXT_ALIGN_CENTER ) 61 | .color( 8 ) 62 | .outline( darkest_color() ) 63 | .shadow( darkest_color() ) 64 | ; 65 | 66 | slowprint( &intro, "This is a small demo for the Pixie library, showing just a few features. The whole library is still very much in an early " 67 | "pre-beta stage - there are bugs, incomplete and untested features and weird behaviour everywhere, and there is no documentation at all. " 68 | "It might be interesting to have a look at, but I wouldn't recommend using it in it's current stage, and I have no idea when there will " 69 | "be a stable release.\n\n /Mattias Gustavsson", 0.015f ).delay( 5 ); 70 | 71 | while( is_running() ) 72 | { 73 | execute_frame(); 74 | clear(); 75 | 76 | u32 seed = (u32) ( clock() / 100 ); 77 | random_seed( seed ); 78 | for( int i = 0; i < 100; ++i ) 79 | { 80 | int x = random( 0, 319 ); 81 | int y = random( 0, 199 ); 82 | int r = random( 1, 40 ); 83 | int c = random( 1, 31 ); 84 | circle_fill( x, y, r, c ); 85 | circle( x, y, r, 0 ); 86 | } 87 | 88 | if( exit_requested() ) end(); // exit immediately if user closes window 89 | if( key_was_pressed( KEY_ESCAPE ) ) end(); // exit with no error 90 | if( key_was_pressed( KEY_SPACE ) ) end(); // exit with no error 91 | if( key_was_pressed( KEY_RETURN ) && key_is_down( KEY_MENU ) ) fullscreen( !fullscreen() ); 92 | if( key_was_pressed( KEY_TAB ) ) crt_mode( !crt_mode() ); 93 | } 94 | 95 | return 0; 96 | } 97 | 98 | -------------------------------------------------------------------------------- /source/pixie/cpp_compat.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | ------------------------------------------------------------------------------ 3 | Licensing information can be found at the end of the file. 4 | ------------------------------------------------------------------------------ 5 | 6 | cpp_compat.hpp - v0.1 - C++ compatibility workarounds for some systems/compilers. 7 | 8 | Ensures we can use final, override and nullptr in all compilers. 9 | Defines a STATIC_ASSERT macro to make static asserts available everywhere. 10 | Makes available the basic integer types from for all compilers. 11 | */ 12 | 13 | #ifndef cpp_compat_hpp 14 | #define cpp_compat_hpp 15 | 16 | #define _CRT_NONSTDC_NO_DEPRECATE 17 | #define _CRT_SECURE_NO_WARNINGS 18 | #include 19 | 20 | // clang-compatible macros 21 | #ifndef __has_builtin 22 | #define __has_builtin( x ) 0 // Compatibility with non-clang compilers. 23 | #endif 24 | 25 | #ifndef __has_feature 26 | #define __has_feature( x ) 0 // Compatibility with non-clang compilers. 27 | #endif 28 | 29 | #ifndef __has_extension 30 | #define __has_extension __has_feature // Compatibility with pre-3.0 compilers. 31 | #endif 32 | 33 | // final 34 | #if ( defined(_MSC_VER) && _MSC_VER < 1700 ) \ 35 | || ( defined( __GNUC__) && !defined( __clang__ ) && !( __GNUC__ >= 4 && __GNUC_MINOR__ >= 7 ) ) \ 36 | || ( defined( __clang__ ) && !( __has_feature( cxx_override_control ) || __has_extension( cxx_override_control ) ) ) 37 | #define final 38 | #endif 39 | 40 | // override 41 | #if ( defined(_MSC_VER) && _MSC_VER < 1400 ) \ 42 | || ( defined( __GNUC__) && !defined( __clang__ ) && !(__GNUC__ >= 4 && __GNUC_MINOR__ >= 7 ) ) \ 43 | || ( defined( __clang__ ) && !( __has_feature( cxx_override_control ) || __has_extension( cxx_override_control ) ) ) 44 | #define override 45 | #endif 46 | 47 | // nullptr 48 | #if ( defined(_MSC_VER) && _MSC_VER < 1600 ) \ 49 | || ( defined( __GNUC__) && !defined( __clang__ ) && !(__GNUC__ >= 4 && __GNUC_MINOR__ >= 6 ) ) \ 50 | || ( defined( __clang__ ) && !( __has_feature( cxx_nullptr ) || __has_extension( cxx_nullptr ) ) ) 51 | 52 | struct nullptr_t 53 | { 54 | template< typename T > 55 | operator T*() const 56 | { 57 | return 0; 58 | } 59 | 60 | template< typename T, typename U > 61 | operator U T::*() const 62 | { 63 | return 0; 64 | } 65 | 66 | private: 67 | void operator&() const; 68 | 69 | }; 70 | 71 | nullptr_t const nullptr = {}; 72 | 73 | #endif 74 | 75 | // static_assert 76 | #if ( defined(_MSC_VER) && _MSC_VER < 1600 ) \ 77 | || ( defined( __GNUC__) && !defined( __clang__ ) && !( __GNUC__ >= 4 && __GNUC_MINOR__ >= 3 ) ) \ 78 | || ( defined( __clang__ ) && !( __has_feature( cxx_static_assert ) || __has_extension( cxx_static_assert ) ) ) 79 | #define CPP_COMPAT_CONCAT_IMPL( x, y ) x##y 80 | #define CPP_COMPAT_CONCAT_MACRO( x, y ) CPP_COMPAT_CONCAT_IMPL( x, y ) 81 | 82 | #define STATIC_ASSERT( expression, message ) \ 83 | struct CPP_COMPAT_CONCAT_MACRO( static_assert_, __COUNTER__ ) \ 84 | { int (message) : !!( (expression) ); } 85 | #else 86 | #define STATIC_ASSERT( expression, message ) \ 87 | static_assert( expression, #message ) 88 | #endif 89 | 90 | // stdint 91 | #if defined(_MSC_VER) && _MSC_VER < 1600 92 | 93 | typedef __int8 int8_t; 94 | typedef unsigned __int8 uint8_t; 95 | typedef __int16 int16_t; 96 | typedef unsigned __int16 uint16_t; 97 | typedef __int32 int32_t; 98 | typedef unsigned __int32 uint32_t; 99 | typedef __int64 int64_t; 100 | typedef unsigned __int64 uint64_t; 101 | #else 102 | #include 103 | #endif 104 | 105 | #if defined(_MSC_VER) && _MSC_VER < 1500 106 | #include 107 | #endif 108 | 109 | 110 | /* 111 | // MSVC version numbers, for reference 112 | MSVC++ 12.0 _MSC_VER == 1800 (Visual Studio 2013) 113 | MSVC++ 11.0 _MSC_VER == 1700 (Visual Studio 2012) 114 | MSVC++ 10.0 _MSC_VER == 1600 (Visual Studio 2010) 115 | MSVC++ 9.0 _MSC_VER == 1500 (Visual Studio 2008) 116 | MSVC++ 8.0 _MSC_VER == 1400 (Visual Studio 2005) 117 | MSVC++ 7.1 _MSC_VER == 1310 (Visual Studio 2003) 118 | MSVC++ 7.0 _MSC_VER == 1300 (Visual Studio 2002) 119 | MSVC++ 6.0 _MSC_VER == 1200 120 | MSVC++ 5.0 _MSC_VER == 1100 121 | */ 122 | 123 | #endif /* cpp_compat_hpp */ 124 | 125 | /* 126 | ------------------------------------------------------------------------------ 127 | 128 | This software is available under 2 licenses - you may choose the one you like. 129 | 130 | ------------------------------------------------------------------------------ 131 | 132 | ALTERNATIVE A - MIT License 133 | 134 | Copyright (c) 2015 Mattias Gustavsson 135 | 136 | Permission is hereby granted, free of charge, to any person obtaining a copy of 137 | this software and associated documentation files (the "Software"), to deal in 138 | the Software without restriction, including without limitation the rights to 139 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 140 | of the Software, and to permit persons to whom the Software is furnished to do 141 | so, subject to the following conditions: 142 | 143 | The above copyright notice and this permission notice shall be included in all 144 | copies or substantial portions of the Software. 145 | 146 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 147 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 148 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 149 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 150 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 151 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 152 | SOFTWARE. 153 | 154 | ------------------------------------------------------------------------------ 155 | 156 | ALTERNATIVE B - Public Domain (www.unlicense.org) 157 | 158 | This is free and unencumbered software released into the public domain. 159 | 160 | Anyone is free to copy, modify, publish, use, compile, sell, or distribute this 161 | software, either in source code form or as a compiled binary, for any purpose, 162 | commercial or non-commercial, and by any means. 163 | 164 | In jurisdictions that recognize copyright laws, the author or authors of this 165 | software dedicate any and all copyright interest in the software to the public 166 | domain. We make this dedication for the benefit of the public at large and to 167 | the detriment of our heirs and successors. We intend this dedication to be an 168 | overt act of relinquishment in perpetuity of all present and future rights to 169 | this software under copyright law. 170 | 171 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 172 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 173 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 174 | AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 175 | ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 176 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 177 | 178 | ------------------------------------------------------------------------------ 179 | */ 180 | -------------------------------------------------------------------------------- /source/pixie/dictionary.hpp: -------------------------------------------------------------------------------- 1 | #ifndef dictionary_hpp 2 | #define dictionary_hpp 3 | 4 | 5 | /* TODO: proper implementation using hash table */ 6 | 7 | #include "array.hpp" 8 | 9 | namespace dictionary_ns { 10 | 11 | template struct entry_t 12 | { 13 | KEY key; 14 | T value; 15 | }; 16 | 17 | #pragma warning( push ) 18 | #pragma warning( disable: 4619 ) // pragma warning : there is no warning number 'number' 19 | #pragma warning( disable: 4217 ) // nonstandard extension used : function declaration from a previous block 20 | 21 | 22 | template< typename KEY, typename T, int CAPACITY = 16 > 23 | struct dictionary : array_ns::array_type< entry_t, CAPACITY, array_ns::NOT_POD > 24 | { 25 | explicit dictionary() : 26 | array_ns::array_type, CAPACITY, array_ns::NOT_POD>( CAPACITY, pixie::internal::memctx() ) 27 | { 28 | } 29 | 30 | 31 | template< typename U > dictionary( U const& other ) : 32 | array_ns::array_type, CAPACITY, array_ns::NOT_POD>( other ) 33 | { 34 | } 35 | 36 | 37 | template< typename U > explicit dictionary( U const* items, int count ) : 38 | array_ns::array_type, CAPACITY, array_ns::NOT_POD>( items, count ) 39 | { 40 | } 41 | 42 | 43 | T const* find( KEY const& key ) const 44 | { 45 | for( int i = 0; i < count(); ++i ) 46 | if( array_ns::array_type, CAPACITY, array_ns::NOT_POD>::operator[]( i ).key == key ) 47 | return &( array_ns::array_type, CAPACITY, array_ns::NOT_POD>::operator[]( i ).value ); 48 | } 49 | 50 | T* find( KEY const& key ) 51 | { 52 | for( int i = 0; i < count(); ++i ) 53 | if( array_ns::array_type, CAPACITY, array_ns::NOT_POD>::operator[](i).key == key ) 54 | return &( array_ns::array_type, CAPACITY, array_ns::NOT_POD>::operator[]( i ).value ); 55 | return 0; 56 | } 57 | 58 | void remove( KEY const& key ) 59 | { 60 | for( int i = 0; i < count(); ++i ) 61 | if( array_ns::array_type, CAPACITY, array_ns::NOT_POD>::operator[]( i ).key == key ) 62 | array_ns::array_type, CAPACITY, array_ns::NOT_POD>::remove( i ); 63 | } 64 | 65 | 66 | KEY const& key( int index ) const 67 | { 68 | return array_ns::array_type, CAPACITY, array_ns::NOT_POD>::operator[]( index ).key; 69 | } 70 | 71 | T& item( int index ) 72 | { 73 | return array_ns::array_type, CAPACITY, array_ns::NOT_POD>::operator[]( index ).value; 74 | } 75 | 76 | T const& item( int index ) const 77 | { 78 | return array_ns::array_type, CAPACITY, array_ns::NOT_POD>::operator[]( index ).value; 79 | } 80 | 81 | T& operator[]( KEY const& key ) 82 | { 83 | for( int i = 0; i < count(); ++i ) 84 | if( array_ns::array_type, CAPACITY, array_ns::NOT_POD>::operator[]( i ).key == key ) 85 | return array_ns::array_type, CAPACITY, array_ns::NOT_POD>::operator[]( i ).value; 86 | 87 | entry_t& entry = add(); 88 | entry.key = key; 89 | entry.value = T(); 90 | return entry.value; 91 | } 92 | 93 | }; 94 | 95 | #pragma warning( pop ) 96 | 97 | } /* namespace dictionary_ns */ 98 | 99 | 100 | #endif // dictionary_hpp 101 | 102 | -------------------------------------------------------------------------------- /source/pixie/dir.h: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | ------------------------------------------------------------------------------ 4 | Licensing information can be found at the end of the dir. 5 | ------------------------------------------------------------------------------ 6 | 7 | dir.h - v0.1 - Directory listing functions for C/C++ 8 | 9 | Do this: 10 | #define DIR_IMPLEMENTATION 11 | before you include this file in *one* C/C++ dir to create the implementation. 12 | */ 13 | 14 | #ifndef dir_h 15 | #define dir_h 16 | 17 | typedef struct dir_t dir_t; 18 | typedef struct dir_entry_t dir_entry_t; 19 | 20 | dir_t* dir_open( char const* path ); 21 | void dir_close( dir_t* dir ); 22 | dir_entry_t* dir_read( dir_t* dir ); 23 | 24 | char const* dir_name( dir_entry_t* entry ); 25 | int dir_is_file( dir_entry_t* entry ); 26 | int dir_is_folder( dir_entry_t* entry ); 27 | 28 | #endif /* dir_h */ 29 | 30 | /* 31 | ---------------------- 32 | IMPLEMENTATION 33 | ---------------------- 34 | */ 35 | 36 | #ifdef DIR_IMPLEMENTATION 37 | #undef DIR_IMPLEMENTATION 38 | 39 | #ifndef DIR_MALLOC 40 | #define _CRT_NONSTDC_NO_DEPRECATE 41 | #define _CRT_SECURE_NO_WARNINGS 42 | #include 43 | #if defined(__cplusplus) 44 | #define DIR_MALLOC( size ) ( ::malloc( size ) ) 45 | #define DIR_FREE( ptr ) ( ::free( ptr ) ) 46 | #else 47 | #define DIR_MALLOC( size ) ( malloc( size ) ) 48 | #define DIR_FREE( ptr ) ( free( ptr ) ) 49 | #endif 50 | #endif 51 | 52 | 53 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 54 | // WINDOWS 55 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 56 | 57 | #if defined( DIR_WINDOWS ) 58 | 59 | #define _CRT_NONSTDC_NO_DEPRECATE 60 | #define _CRT_SECURE_NO_WARNINGS 61 | #if !defined( _WIN32_WINNT ) || _WIN32_WINNT < 0x0501 62 | #undef _WIN32_WINNT 63 | #define _WIN32_WINNT 0x0501 // requires Windows XP minimum 64 | #endif 65 | // 0x0400=Windows NT 4.0, 0x0500=Windows 2000, 0x0501=Windows XP, 0x0502=Windows Server 2003, 0x0600=Windows Vista, 66 | // 0x0601=Windows 7, 0x0602=Windows 8, 0x0603=Windows 8.1, 0x0A00=Windows 10, 67 | #define _WINSOCKAPI_ 68 | #pragma warning( push ) 69 | #pragma warning( disable: 4668 ) // 'symbol' is not defined as a preprocessor macro, replacing with '0' for 'directives' 70 | #pragma warning( disable: 4255 ) // 'function' : no function prototype given: converting '()' to '(void)' 71 | #include 72 | #pragma warning( pop ) 73 | 74 | struct dir_entry_t 75 | { 76 | char name[ MAX_PATH ]; 77 | BOOL is_folder; 78 | }; 79 | 80 | 81 | struct dir_t 82 | { 83 | HANDLE handle; 84 | WIN32_FIND_DATAA data; 85 | dir_entry_t entry; 86 | }; 87 | 88 | 89 | dir_t* dir_open( char const* path ) 90 | { 91 | if( !path ) return 0; 92 | 93 | size_t path_len = strlen( path ); 94 | BOOL trailing_path_separator = path[ path_len - 1 ] == '\\' || path[ path_len - 1 ] == '/'; 95 | const char* string_to_append = "*.*"; 96 | if( path_len + strlen( string_to_append ) + ( trailing_path_separator ? 0 : 1 ) >= MAX_PATH ) return NULL; 97 | char search_pattern[ MAX_PATH ]; 98 | strcpy( search_pattern, path ); 99 | if( !trailing_path_separator ) strcat( search_pattern, "\\" ); 100 | strcat( search_pattern, string_to_append ); 101 | 102 | WIN32_FIND_DATAA data; 103 | HANDLE handle = FindFirstFileA( search_pattern, &data ); 104 | if( handle == INVALID_HANDLE_VALUE ) return NULL; 105 | 106 | dir_t* dir = (dir_t*) DIR_MALLOC( sizeof( dir_t ) ); 107 | dir->handle = handle; 108 | dir->data = data; 109 | 110 | return dir; 111 | } 112 | 113 | 114 | void dir_close( dir_t* dir ) 115 | { 116 | if( !dir ) return; 117 | 118 | if( dir->handle != INVALID_HANDLE_VALUE ) FindClose( dir->handle ); 119 | DIR_FREE( dir ); 120 | } 121 | 122 | 123 | dir_entry_t* dir_read( dir_t* dir ) 124 | { 125 | if( !dir ) return NULL; 126 | if( dir->handle == INVALID_HANDLE_VALUE ) return NULL; 127 | 128 | strcpy( dir->entry.name, dir->data.cFileName ); 129 | dir->entry.is_folder = ( dir->data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ) != 0; 130 | 131 | BOOL result = FindNextFileA( dir->handle, &dir->data ); 132 | if( !result ) 133 | { 134 | FindClose( dir->handle ); 135 | dir->handle = INVALID_HANDLE_VALUE; 136 | } 137 | 138 | return &dir->entry; 139 | } 140 | 141 | 142 | char const* dir_name( dir_entry_t* entry ) 143 | { 144 | if( !entry ) return NULL; 145 | return entry->name; 146 | } 147 | 148 | 149 | int dir_is_file( dir_entry_t* entry ) 150 | { 151 | if( !entry ) return 0; 152 | return entry->is_folder == FALSE; 153 | } 154 | 155 | 156 | int dir_is_folder( dir_entry_t* entry ) 157 | { 158 | if( !entry ) return 0; 159 | return entry->is_folder == TRUE; 160 | } 161 | 162 | 163 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 164 | // POSIX 165 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 166 | #elif defined( DIR_POSIX ) 167 | 168 | #include 169 | 170 | 171 | dir_t* dir_open( char const* path ) 172 | { 173 | DIR* dir = opendir( path ); 174 | return (dir_t*) dir; 175 | } 176 | 177 | 178 | void dir_close( dir_t* dir ) 179 | { 180 | if( !dir ) return; 181 | closedir( (DIR*) dir ); 182 | } 183 | 184 | 185 | dir_entry_t* dir_read( dir_t* dir ) 186 | { 187 | if( !dir ) return NULL; 188 | return (dir_entry_t*)readdir( (DIR*) dir ); 189 | } 190 | 191 | 192 | char const* dir_name( dir_entry_t* entry ) 193 | { 194 | if( !entry ) return NULL; 195 | return ( (struct dirent*)entry )->d_name; 196 | } 197 | 198 | 199 | int dir_is_file( dir_entry_t* entry ) 200 | { 201 | if( !entry ) return 0; 202 | return ( (struct dirent*)entry )->d_type == DT_REG; 203 | } 204 | 205 | 206 | int dir_is_folder( dir_entry_t* entry ) 207 | { 208 | if( !entry ) return 0; 209 | return ( (struct dirent*)entry )->d_type == DT_DIR; 210 | } 211 | 212 | 213 | 214 | 215 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 216 | // PLATFORM ERROR 217 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 218 | #else 219 | 220 | #error Undefined platform. Define DIR_WINDOWS or DIR_POSIX. 221 | 222 | #endif 223 | 224 | 225 | #endif /* DIR_IMPLEMENTATION */ 226 | 227 | /* 228 | ------------------------------------------------------------------------------ 229 | 230 | This software is available under 2 licenses - you may choose the one you like. 231 | 232 | ------------------------------------------------------------------------------ 233 | 234 | ALTERNATIVE A - MIT License 235 | 236 | Copyright (c) 2017 Mattias Gustavsson 237 | 238 | Permission is hereby granted, free of charge, to any person obtaining a copy of 239 | this software and associated documentation files (the "Software"), to deal in 240 | the Software without restriction, including without limitation the rights to 241 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 242 | of the Software, and to permit persons to whom the Software is furnished to do 243 | so, subject to the following conditions: 244 | 245 | The above copyright notice and this permission notice shall be included in all 246 | copies or substantial portions of the Software. 247 | 248 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 249 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 250 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 251 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 252 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 253 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 254 | SOFTWARE. 255 | 256 | ------------------------------------------------------------------------------ 257 | 258 | ALTERNATIVE B - Public Domain (www.unlicense.org) 259 | 260 | This is free and unencumbered software released into the public domain. 261 | 262 | Anyone is free to copy, modify, publish, use, compile, sell, or distribute this 263 | software, either in source code form or as a compiled binary, for any purpose, 264 | commercial or non-commercial, and by any means. 265 | 266 | In jurisdictions that recognize copyright laws, the author or authors of this 267 | software dedicate any and all copyright interest in the software to the public 268 | domain. We make this dedication for the benefit of the public at large and to 269 | the detriment of our heirs and successors. We intend this dedication to be an 270 | overt act of relinquishment in perpetuity of all present and future rights to 271 | this software under copyright law. 272 | 273 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 274 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 275 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 276 | AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 277 | ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 278 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 279 | 280 | ------------------------------------------------------------------------------ 281 | */ 282 | -------------------------------------------------------------------------------- /source/pixie/ease.h: -------------------------------------------------------------------------------- 1 | /* 2 | ------------------------------------------------------------------------------ 3 | Licensing information can be found at the end of the file. 4 | ------------------------------------------------------------------------------ 5 | 6 | ease.h - v0.1 - ease in/out interpolation functions for C/C++. 7 | 8 | Do this: 9 | #define EASE_IMPLEMENTATION 10 | before you include this file in *one* C/C++ file to create the implementation. 11 | 12 | ------------------------------------------------------------------------------ 13 | 14 | Based on http://www.robertpenner.com/easing/penner_chapter7_tweening.pdf 15 | Note that in this code, input and output is in normalized 0.0 to 1.0 range. 16 | 17 | */ 18 | 19 | #ifndef ease_h 20 | #define ease_h 21 | 22 | typedef float (*ease_func_t)( float ); 23 | 24 | float ease_linear( float t ); 25 | 26 | float ease_smoothstep( float t ); 27 | 28 | float ease_smootherstep( float t ); 29 | 30 | float ease_quad_out( float t ); 31 | float ease_quad_in( float t ); 32 | float ease_quad_in_out( float t ); 33 | 34 | float ease_back_out( float t ); 35 | float ease_back_in( float t ); 36 | float ease_back_in_out( float t ); 37 | 38 | float ease_bounce_out( float t ); 39 | float ease_bounce_in( float t ); 40 | float ease_bounce_in_out( float t ); 41 | 42 | float ease_sine_out( float t ); 43 | float ease_sine_in( float t ); 44 | float ease_sine_in_out( float t ); 45 | 46 | float ease_elastic_out( float t ); 47 | float ease_elastic_in( float t ); 48 | float ease_elastic_in_out( float t ); 49 | 50 | float ease_expo_out( float t ); 51 | float ease_expo_in( float t ); 52 | float ease_expo_in_out( float t ); 53 | 54 | float ease_cubic_out( float t ); 55 | float ease_cubic_in( float t ); 56 | float ease_cubic_in_out( float t ); 57 | 58 | float ease_quart_out( float t ); 59 | float ease_quart_in( float t ); 60 | float ease_quart_in_out( float t ); 61 | 62 | float ease_quint_out( float t ); 63 | float ease_quint_in( float t ); 64 | float ease_quint_in_out( float t ); 65 | 66 | float ease_circle_out( float t ); 67 | float ease_circle_in( float t ); 68 | float ease_circle_in_out( float t ); 69 | 70 | #endif /* ease_h */ 71 | 72 | 73 | /* 74 | ---------------------- 75 | IMPLEMENTATION 76 | ---------------------- 77 | */ 78 | 79 | #ifdef EASE_IMPLEMENTATION 80 | #undef EASE_IMPLEMENTATION 81 | 82 | #if !defined( EASE_ACOS ) || !defined( EASE_POW ) || !defined( EASE_SIN ) || !defined( EASE_SQRT ) 83 | #define _CRT_NONSTDC_NO_DEPRECATE 84 | #define _CRT_SECURE_NO_WARNINGS 85 | #pragma warning( push ) 86 | #pragma warning( disable: 4668 ) // 'symbol' is not defined as a preprocessor macro, replacing with '0' for 'directives' 87 | #include 88 | #pragma warning( pop ) 89 | #endif 90 | 91 | #ifndef EASE_ACOS 92 | #define EASE_ACOS( x ) acosf( x ) 93 | #endif 94 | 95 | #ifndef EASE_COS 96 | #define EASE_COS( x ) cosf( x ) 97 | #endif 98 | 99 | #ifndef EASE_POW 100 | #define EASE_POW( x, y ) powf( x, y ) 101 | #endif 102 | 103 | #ifndef EASE_SIN 104 | #define EASE_SIN( x ) sinf( x ) 105 | #endif 106 | 107 | #ifndef EASE_SQRT 108 | #define EASE_SQRT( x ) sqrtf( x ) 109 | #endif 110 | 111 | 112 | float ease_linear( float t ) 113 | { 114 | return t; 115 | } 116 | 117 | 118 | float ease_smoothstep( float t ) 119 | { 120 | return t * t * ( 3.0f - 2.0f * t ); 121 | } 122 | 123 | 124 | float ease_smootherstep( float t ) 125 | { 126 | return t * t * t * ( t * ( t * 6.0f - 15.0f ) + 10.0f ); 127 | } 128 | 129 | 130 | float ease_quad_out( float t ) 131 | { 132 | return -t * ( t - 2.0f ); 133 | } 134 | 135 | 136 | float ease_quad_in( float t ) 137 | { 138 | return t * t; 139 | } 140 | 141 | 142 | float ease_quad_in_out( float t ) 143 | { 144 | return ( ( t *= 2.0f ) < 1.0f ) 145 | ? ( 0.5f * t * t ) 146 | : ( -0.5f * ( ( t - 1.0f ) * ( t - 3.0f ) - 1.0f ) ); 147 | } 148 | 149 | 150 | float ease_back_out( float t ) 151 | { 152 | return ( ( t -= 1.0f ) * t * ( ( 1.70158f + 1.0f ) * t + 1.70158f ) + 1.0f ); 153 | } 154 | 155 | 156 | float ease_back_in( float t ) 157 | { 158 | return t * t * ( ( 1.70158f + 1.0f ) * t - 1.70158f ); 159 | } 160 | 161 | 162 | float ease_back_in_out( float t ) 163 | { 164 | float s = 1.70158f; 165 | 166 | return ( ( t *= 2.0f ) < 1.0f ) 167 | ? 0.5f * ( t * t * ( ( ( s *= 1.525f ) + 1.0f ) * t - s ) ) 168 | : 0.5f * ( ( t -= 2.0f ) * t * ( ( ( s *= 1.525f ) + 1.0f) * t + s ) + 2.0f ); 169 | } 170 | 171 | 172 | float ease_bounce_out( float t ) 173 | { 174 | if( t < ( 1.0f / 2.75f ) ) 175 | return 7.5625f * t * t; 176 | else if( t < ( 2.0f / 2.75f ) ) 177 | return 7.5625f * ( t -= ( 1.50f / 2.75f ) ) * t + 0.75f; 178 | else if( t < ( 2.5f / 2.75f ) ) 179 | return 7.5625f * ( t -= ( 2.25f / 2.75f ) ) * t + 0.9375f; 180 | else 181 | return 7.5625f * ( t -= ( 2.625f / 2.75f ) ) * t + 0.984375f; 182 | } 183 | 184 | 185 | float ease_bounce_in( float t ) 186 | { 187 | return 1.0f - ease_bounce_out( 1.0f - t ); 188 | } 189 | 190 | 191 | float ease_bounce_in_out( float t ) 192 | { 193 | return ( t < 0.5f ) 194 | ? ( ease_bounce_in( t * 2.0f ) * 0.5f ) 195 | : ( ease_bounce_out( t * 2.0f - 1.0f ) * 0.5f + 0.5f ); 196 | } 197 | 198 | 199 | float ease_sine_out( float t ) 200 | { 201 | return EASE_SIN( t * EASE_ACOS( 0.0f ) ); 202 | } 203 | 204 | 205 | float ease_sine_in( float t ) 206 | { 207 | return 1.0f - EASE_COS( t * EASE_ACOS( 0.0f ) ); 208 | } 209 | 210 | 211 | float ease_sine_in_out( float t ) 212 | { 213 | return -( EASE_COS( EASE_ACOS( -1.0f ) * t ) - 1.0f ) / 2.0f; 214 | } 215 | 216 | 217 | float ease_elastic_out( float t ) 218 | { 219 | if( t == 0.0f ) return 0.0f; 220 | if( t == 1.0f ) return 1.0f; 221 | 222 | float p = 0.4f; 223 | float s = p / 4.0f; 224 | return ( EASE_POW( 2.0f, -10.0f * t ) * EASE_SIN( ( t - s ) * ( 2.0f * EASE_ACOS( -1.0f ) ) / p ) + 1.0f ); 225 | } 226 | 227 | 228 | float ease_elastic_in( float t ) 229 | { 230 | if( t == 0.0f ) return 0.0f; 231 | if( t == 1.0f ) return 1.0f; 232 | 233 | float p = 0.4f; 234 | float s = p / 4.0f; 235 | return -( EASE_POW( 2.0f, 10.0f * ( t -= 1.0f ) ) * EASE_SIN( ( t - s ) * ( 2.0f * EASE_ACOS( -1.0f ) ) / p ) ); 236 | } 237 | 238 | 239 | float ease_elastic_in_out( float t ) 240 | { 241 | if( t == 0.0f) return 0.0f; 242 | if( ( t *= 2.0f ) == 2.0f ) return 1.0f; 243 | 244 | float p = 0.3f * 1.5f; 245 | float s = p / 4.0f; 246 | if( t < 1.0f ) 247 | return -0.5f * ( EASE_POW( 2.0f, 10.0f * ( t -= 1.0f ) ) * EASE_SIN( ( t - s ) * ( 2.0f * EASE_ACOS( -1.0f ) ) / p ) ); 248 | else 249 | return EASE_POW( 2.0f, -10.0f * ( t -= 1.0f ) ) * EASE_SIN( ( t - s ) * (2.0f * EASE_ACOS( -1.0f ) ) / p) * 0.5f + 1.0f; 250 | } 251 | 252 | 253 | float ease_expo_out( float t ) 254 | { 255 | return t == 1.0f 256 | ? 1.0f 257 | : ( 1.0f - EASE_POW( 2.0f, -10.0f * t ) ); 258 | } 259 | 260 | 261 | float ease_expo_in( float t ) 262 | { 263 | return t == 0.0f 264 | ? 0.0f 265 | : EASE_POW( 2.0f, 10.0f * ( t - 1.0f ) ); 266 | } 267 | 268 | 269 | float ease_expo_in_out( float t ) 270 | { 271 | if( t == 0.0f ) return 0.0f; 272 | if( t == 1.0f ) return 1.0f; 273 | if( ( t *= 2.0f ) < 1.0f ) 274 | return 0.5f * EASE_POW( 2.0f, 10.0f * ( t - 1.0f ) ); 275 | else 276 | return 0.5f * ( 2.0f - EASE_POW( 2.0f, -10.0f * --t ) ); 277 | } 278 | 279 | 280 | float ease_cubic_out( float t ) 281 | { 282 | return --t * t * t + 1.0f; 283 | } 284 | 285 | 286 | float ease_cubic_in( float t ) 287 | { 288 | return t * t * t; 289 | } 290 | 291 | 292 | float ease_cubic_in_out( float t ) 293 | { 294 | return ( ( t *= 2.0f ) < 1.0f ) 295 | ? 0.5f * t * t * t 296 | : 0.5f * ( ( t -= 2.0f ) * t * t + 2.0f ); 297 | } 298 | 299 | 300 | float ease_quart_out( float t ) 301 | { 302 | return -( --t * t * t * t - 1.0f ); 303 | } 304 | 305 | 306 | float ease_quart_in( float t ) 307 | { 308 | return t * t * t * t; 309 | } 310 | 311 | 312 | float ease_quart_in_out( float t ) 313 | { 314 | return ( ( t *= 2.0f ) < 1.0f ) 315 | ? 0.5f * t * t * t * t 316 | : -0.5f * ( ( t -= 2.0f ) * t * t * t - 2.0f ); 317 | } 318 | 319 | 320 | float ease_quint_out( float t ) 321 | { 322 | return --t * t * t * t * t + 1.0f; 323 | } 324 | 325 | 326 | float ease_quint_in( float t ) 327 | { 328 | return t * t * t * t * t; 329 | } 330 | 331 | 332 | float ease_quint_in_out( float t ) 333 | { 334 | return ( ( t *= 2.0f ) < 1.0f ) 335 | ? 0.5f * t * t * t * t * t 336 | : -0.5f * ( ( t -= 2.0f ) * t * t * t * t - 2.0f ); 337 | } 338 | 339 | 340 | float ease_circle_out( float t ) 341 | { 342 | return EASE_SQRT( 1.0f - ( t -= 1.0f ) * t ); 343 | } 344 | 345 | 346 | float ease_circle_in( float t ) 347 | { 348 | return 1.0f - EASE_SQRT( 1.0f - t * t ); 349 | } 350 | 351 | 352 | float ease_circle_in_out( float t ) 353 | { 354 | return ( ( t *= 2.0f ) < 1.0f ) 355 | ? 0.5f * (1.0f - EASE_SQRT( 1.0f - t * t ) ) 356 | : 0.5f * ( EASE_SQRT( 1.0f - ( t -= 2.0f ) * t ) + 1.0f ); 357 | } 358 | 359 | 360 | #endif /* EASE_IMPLEMENTATION */ 361 | 362 | /* 363 | ------------------------------------------------------------------------------ 364 | 365 | This software is available under 2 licenses - you may choose the one you like. 366 | 367 | ------------------------------------------------------------------------------ 368 | 369 | ALTERNATIVE A - MIT License 370 | 371 | Copyright (c) 2015 Mattias Gustavsson 372 | 373 | Permission is hereby granted, free of charge, to any person obtaining a copy of 374 | this software and associated documentation files (the "Software"), to deal in 375 | the Software without restriction, including without limitation the rights to 376 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 377 | of the Software, and to permit persons to whom the Software is furnished to do 378 | so, subject to the following conditions: 379 | 380 | The above copyright notice and this permission notice shall be included in all 381 | copies or substantial portions of the Software. 382 | 383 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 384 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 385 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 386 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 387 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 388 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 389 | SOFTWARE. 390 | 391 | ------------------------------------------------------------------------------ 392 | 393 | ALTERNATIVE B - Public Domain (www.unlicense.org) 394 | 395 | This is free and unencumbered software released into the public domain. 396 | 397 | Anyone is free to copy, modify, publish, use, compile, sell, or distribute this 398 | software, either in source code form or as a compiled binary, for any purpose, 399 | commercial or non-commercial, and by any means. 400 | 401 | In jurisdictions that recognize copyright laws, the author or authors of this 402 | software dedicate any and all copyright interest in the software to the public 403 | domain. We make this dedication for the benefit of the public at large and to 404 | the detriment of our heirs and successors. We intend this dedication to be an 405 | overt act of relinquishment in perpetuity of all present and future rights to 406 | this software under copyright law. 407 | 408 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 409 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 410 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 411 | AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 412 | ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 413 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 414 | 415 | ------------------------------------------------------------------------------ 416 | */ 417 | -------------------------------------------------------------------------------- /source/pixie/file.h: -------------------------------------------------------------------------------- 1 | /* 2 | ------------------------------------------------------------------------------ 3 | Licensing information can be found at the end of the file. 4 | ------------------------------------------------------------------------------ 5 | 6 | file.h - v1.0 - C/C++ functions to load/save an entire file to/from memory. 7 | 8 | Do this: 9 | #define FILE_IMPLEMENTATION 10 | before you include this file in *one* C/C++ file to create the implementation. 11 | */ 12 | 13 | #ifndef file_h 14 | #define file_h 15 | 16 | #define _CRT_NONSTDC_NO_DEPRECATE 17 | #define _CRT_SECURE_NO_WARNINGS 18 | #include 19 | 20 | struct file_t 21 | { 22 | void* memctx; 23 | size_t size; 24 | char data[ 1 ]; /* "open" array - it is [size] elements long, not [1]. */ 25 | }; 26 | 27 | typedef struct file_t file_t; 28 | 29 | file_t* file_create( size_t size, void* memctx ); 30 | 31 | enum file_mode_t 32 | { 33 | FILE_MODE_BINARY, 34 | FILE_MODE_TEXT, 35 | }; 36 | 37 | file_t* file_load( char const* filename, file_mode_t mode, void* memctx ); 38 | 39 | void file_destroy( file_t* file ); 40 | 41 | void file_save( file_t const* file, char const* filename, file_mode_t mode ); 42 | void file_save_data( void const* data, size_t size, char const* filename, file_mode_t mode ); 43 | 44 | #endif /* file_h */ 45 | 46 | 47 | /* 48 | 49 | Examples: 50 | 51 | ------------------------------------------------------------------------------ 52 | 53 | #define FILE_IMPLEMENTATION 54 | #include "file.h" 55 | 56 | #include 57 | #include 58 | 59 | int main() 60 | { 61 | char const* test = "This is just a test file.\nTest test test."; 62 | file_save_data( test, strlen( test ), "test.txt", FILE_TEXT ); 63 | 64 | file_t* file = file_load( "test.txt", FILE_TEXT ); 65 | if( file && file->size > 0 ) 66 | printf( "%s", file->data ); 67 | 68 | file_save( file, "test_copy.txt", FILE_TEXT ); 69 | file_destroy( file ); 70 | return 0; 71 | } 72 | */ 73 | 74 | 75 | /* 76 | ---------------------- 77 | IMPLEMENTATION 78 | ---------------------- 79 | */ 80 | 81 | #ifdef FILE_IMPLEMENTATION 82 | #undef FILE_IMPLEMENTATION 83 | 84 | #define _CRT_NONSTDC_NO_DEPRECATE 85 | #define _CRT_SECURE_NO_WARNINGS 86 | #include 87 | #include 88 | 89 | #ifndef FILE_MALLOC 90 | #define _CRT_NONSTDC_NO_DEPRECATE 91 | #define _CRT_SECURE_NO_WARNINGS 92 | #include 93 | #if defined(__cplusplus) 94 | #define FILE_MALLOC( ctx, size ) ( ::malloc( size ) ) 95 | #define FILE_FREE( ctx, ptr ) ( ::free( ptr ) ) 96 | #else 97 | #define FILE_MALLOC( ctx, size ) ( malloc( size ) ) 98 | #define FILE_FREE( ctx, ptr ) ( free( ptr ) ) 99 | #endif 100 | #endif 101 | 102 | 103 | file_t* file_create( size_t const size, void* const memctx ) 104 | { 105 | file_t* file = 0; 106 | if( size > 0 ) 107 | { 108 | size_t const size_to_alloc = size + sizeof( file_t ); 109 | file = (file_t*) FILE_MALLOC( memctx, size_to_alloc ); 110 | if( file ) 111 | { 112 | file->memctx = memctx; 113 | file->size = size; 114 | } 115 | } 116 | return file; 117 | } 118 | 119 | 120 | file_t* file_load( char const* const filename, file_mode_t const mode, void* const memctx ) 121 | { 122 | file_t* file = 0; 123 | struct stat s; 124 | if( stat( filename, &s ) == 0 ) 125 | { 126 | FILE* const fp = fopen( filename, mode == FILE_MODE_BINARY ? "rb" : "r" ); 127 | if( fp ) 128 | { 129 | size_t const file_size = (size_t) s.st_size; 130 | if( file_size > 0 ) 131 | { 132 | file = file_create( file_size + ( mode == FILE_MODE_BINARY ? 0 : 1 ), memctx ); 133 | if( file ) 134 | { 135 | size_t const count = fread( file->data, 1, file_size, fp ); 136 | if( mode == FILE_MODE_TEXT ) file->data[ count ] = 0; 137 | file->memctx = memctx; 138 | file->size = count; 139 | } 140 | } 141 | fclose( fp ); 142 | } 143 | } 144 | 145 | return file; 146 | } 147 | 148 | 149 | void file_destroy( file_t* const file ) 150 | { 151 | if( file ) 152 | FILE_FREE( file->memctx, file ); 153 | } 154 | 155 | 156 | void file_save_data( void const* const data, size_t const size, char const* const filename, file_mode_t const mode ) 157 | { 158 | if( data ) 159 | { 160 | FILE* const fp = fopen( filename, mode == FILE_MODE_BINARY ? "wb" : "w" ); 161 | if( fp ) 162 | { 163 | int const skip_last = ( mode == FILE_MODE_BINARY || size <= 0 ) ? 0 : ( (char const*) data )[ size - 1 ] == '\0' ? 1 : 0; 164 | if( ( skip_last == 0 && size > 0 ) || ( skip_last != 0 && size > 1 ) ) 165 | fwrite( data, 1, size - skip_last, fp ); 166 | fclose( fp ); 167 | } 168 | } 169 | } 170 | 171 | 172 | void file_save( file_t const* const file, char const* const filename, file_mode_t const mode ) 173 | { 174 | if( file) 175 | file_save_data( file->data, file->size, filename, mode ); 176 | } 177 | 178 | 179 | #endif /* FILE_IMPLEMENTATION */ 180 | 181 | /* 182 | ------------------------------------------------------------------------------ 183 | 184 | This software is available under 2 licenses - you may choose the one you like. 185 | 186 | ------------------------------------------------------------------------------ 187 | 188 | ALTERNATIVE A - MIT License 189 | 190 | Copyright (c) 2015 Mattias Gustavsson 191 | 192 | Permission is hereby granted, free of charge, to any person obtaining a copy of 193 | this software and associated documentation files (the "Software"), to deal in 194 | the Software without restriction, including without limitation the rights to 195 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 196 | of the Software, and to permit persons to whom the Software is furnished to do 197 | so, subject to the following conditions: 198 | 199 | The above copyright notice and this permission notice shall be included in all 200 | copies or substantial portions of the Software. 201 | 202 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 203 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 204 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 205 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 206 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 207 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 208 | SOFTWARE. 209 | 210 | ------------------------------------------------------------------------------ 211 | 212 | ALTERNATIVE B - Public Domain (www.unlicense.org) 213 | 214 | This is free and unencumbered software released into the public domain. 215 | 216 | Anyone is free to copy, modify, publish, use, compile, sell, or distribute this 217 | software, either in source code form or as a compiled binary, for any purpose, 218 | commercial or non-commercial, and by any means. 219 | 220 | In jurisdictions that recognize copyright laws, the author or authors of this 221 | software dedicate any and all copyright interest in the software to the public 222 | domain. We make this dedication for the benefit of the public at large and to 223 | the detriment of our heirs and successors. We intend this dedication to be an 224 | overt act of relinquishment in perpetuity of all present and future rights to 225 | this software under copyright law. 226 | 227 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 228 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 229 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 230 | AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 231 | ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 232 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 233 | 234 | ------------------------------------------------------------------------------ 235 | */ 236 | -------------------------------------------------------------------------------- /source/pixie/file_util.h: -------------------------------------------------------------------------------- 1 | /* 2 | ------------------------------------------------------------------------------ 3 | Licensing information can be found at the end of the file. 4 | ------------------------------------------------------------------------------ 5 | 6 | file_util.h - v0.1 - Utilities for working with files, folders and paths. 7 | 8 | Do this: 9 | #define FILE_UTIL_IMPLEMENTATION 10 | before you include this file in *one* C/C++ file to create the implementation. 11 | 12 | Dependencies: 13 | dir.h 14 | */ 15 | 16 | #ifndef file_util_h 17 | #define file_util_h 18 | 19 | #include 20 | 21 | char const* basename( char const* path, char const* extension ); 22 | char const* dirname( char const* path ); 23 | char const* extname( char const* path ); 24 | char* basename( char* path, char* extension ); 25 | char* dirname( char* path ); 26 | char* extname( char* path ); 27 | 28 | char const* absolute_path( char const* filename ); 29 | void replace_extension( char* output, char const* path, char const* new_extension ); 30 | 31 | void mkdir( char const* path ); 32 | void rmdir( char const* path ); 33 | int create_path( char const* path ); 34 | void copy_file( char const* source, char const* destination ); 35 | 36 | size_t file_size( char const* filename ); 37 | time_t file_last_changed( char const* filename ); 38 | time_t most_recent_file_modification( char const* path ); 39 | int file_more_recent( char const* source_path, char const* output_path ); 40 | int contains_more_recent_file( char const* source_path, char const* output_path ); 41 | 42 | int folder_count( char const* path ); 43 | int file_count( char const* path ); 44 | int folder_exists( char const* path ); 45 | int file_exists( char const* filename ); 46 | int is_folder( char const* path ); 47 | 48 | #endif /* file_util_h */ 49 | 50 | /* 51 | ---------------------- 52 | IMPLEMENTATION 53 | ---------------------- 54 | */ 55 | 56 | #ifdef FILE_UTIL_IMPLEMENTATION 57 | #undef FILE_UTIL_IMPLEMENTATION 58 | 59 | #define _CRT_NONSTDC_NO_DEPRECATE 60 | #define _CRT_SECURE_NO_WARNINGS 61 | 62 | #ifdef _WIN32 63 | #include 64 | #if !defined( _WIN32_WINNT ) || _WIN32_WINNT < 0x0501 65 | #undef _WIN32_WINNT 66 | #define _WIN32_WINNT 0x0501 // requires Windows XP minimum 67 | #endif 68 | // 0x0400=Windows NT 4.0, 0x0500=Windows 2000, 0x0501=Windows XP, 0x0502=Windows Server 2003, 0x0600=Windows Vista, 69 | // 0x0601=Windows 7, 0x0602=Windows 8, 0x0603=Windows 8.1, 0x0A00=Windows 10, 70 | #define _WINSOCKAPI_ 71 | #pragma warning( push ) 72 | #pragma warning( disable: 4668 ) // 'symbol' is not defined as a preprocessor macro, replacing with '0' for 'directives' 73 | #pragma warning( disable: 4255 ) // 'function' : no function prototype given: converting '()' to '(void)' 74 | #include 75 | #pragma warning( pop ) 76 | 77 | #define mkdir hide_windows_mkdir 78 | #define rmdir hide_windows_rmdir 79 | #include 80 | #undef mkdir 81 | #undef rmdir 82 | #else /* _WIN32 */ 83 | #error unsupported platform 84 | #endif 85 | 86 | #include "dir.h" 87 | 88 | 89 | char const* basename( char const* const path, char const* const extension ) 90 | { 91 | static char result[ MAX_PATH ]; 92 | strcpy( result, "" ); 93 | 94 | if( path ) 95 | { 96 | char const* lastForwardSlash = strrchr( path, '/' ); 97 | char const* lastBackSlash = strrchr( path, '\\' ); 98 | 99 | char const* name = 0; 100 | 101 | if( !lastBackSlash && !lastForwardSlash ) 102 | { 103 | name = path; 104 | } 105 | else if( !lastBackSlash ) 106 | { 107 | name = lastForwardSlash + 1; 108 | } 109 | else if( !lastForwardSlash ) 110 | { 111 | name = lastBackSlash + 1; 112 | } 113 | else if( lastForwardSlash > lastBackSlash ) 114 | { 115 | name = lastForwardSlash + 1; 116 | } 117 | else 118 | { 119 | name = lastBackSlash + 1; 120 | } 121 | 122 | strncpy( result, name, sizeof( result ) ); 123 | 124 | if( extension ) 125 | { 126 | size_t extlen = strlen( extension ); 127 | size_t reslen = strlen( result ); 128 | 129 | if( reslen >= extlen ) 130 | { 131 | if( stricmp( result + (reslen - extlen), extension ) == 0 ) 132 | { 133 | result[ reslen - extlen ] = 0; 134 | } 135 | } 136 | 137 | } 138 | } 139 | 140 | return result; 141 | } 142 | 143 | 144 | char const* dirname( char const* const path ) 145 | { 146 | static char result[ MAX_PATH ]; 147 | strcpy( result, "" ); 148 | 149 | if( path ) 150 | { 151 | char* lastForwardSlash; 152 | char* lastBackSlash; 153 | 154 | strncpy( result, path, sizeof( result ) ); 155 | lastForwardSlash = strrchr( result, '/' ); 156 | lastBackSlash = strrchr( result, '\\' ); 157 | 158 | if( !lastBackSlash && !lastForwardSlash ) 159 | { 160 | result[ 0 ] = 0; 161 | } 162 | else if( !lastBackSlash ) 163 | { 164 | *(lastForwardSlash + 1) = 0; 165 | } 166 | else if( !lastForwardSlash ) 167 | { 168 | *(lastBackSlash +1 ) = 0; 169 | } 170 | else if( lastForwardSlash > lastBackSlash ) 171 | { 172 | *(lastForwardSlash + 1 ) = 0; 173 | } 174 | else 175 | { 176 | *(lastBackSlash + 1) = 0; 177 | } 178 | } 179 | 180 | return result; 181 | } 182 | 183 | 184 | char const* extname( char const* const path ) 185 | { 186 | static char result[ MAX_PATH ]; 187 | strcpy( result, "" ); 188 | 189 | if( path ) 190 | { 191 | char const* lastForwardSlash = strrchr( path, '/' ); 192 | char const* lastBackSlash = strrchr( path, '\\' ); 193 | 194 | char const* name = 0; 195 | char const* ext = 0; 196 | 197 | if( !lastBackSlash && !lastForwardSlash ) 198 | { 199 | name = path; 200 | } 201 | else if( !lastBackSlash ) 202 | { 203 | name = lastForwardSlash + 1; 204 | } 205 | else if( !lastForwardSlash ) 206 | { 207 | name = lastBackSlash + 1; 208 | } 209 | else if( lastForwardSlash > lastBackSlash ) 210 | { 211 | name = lastForwardSlash + 1; 212 | } 213 | else 214 | { 215 | name = lastBackSlash + 1; 216 | } 217 | 218 | ext = strrchr( name, '.' ); 219 | 220 | if( ext && !( ext[ 0 ] == '.' && ext[ 1 ] == 0 ) ) 221 | { 222 | strncpy( result, ext, sizeof( result ) ); 223 | } 224 | } 225 | 226 | return result; 227 | } 228 | 229 | 230 | char* basename( char* path, char* const extension ) { return (char*) basename( (char const*)path, (char const*)extension ); } 231 | char* dirname( char* const path ) { return (char*) dirname( (char const*)path ); } 232 | char* extname( char* const path ) { return (char*) extname( (char const*)path ); } 233 | 234 | 235 | char const* absolute_path( char const* const filename ) 236 | { 237 | if( filename[0] == 0 || filename[1] == ':' ) 238 | { 239 | return filename; 240 | } 241 | 242 | char cwd[ MAX_PATH ]; 243 | #ifdef _WIN32 244 | getcwd( cwd, MAX_PATH ); 245 | #else /* _WIN32 */ 246 | #error unsupported platform 247 | #endif 248 | 249 | static char path[ MAX_PATH ]; 250 | if( filename[0] == '\\' || filename[0] == '/' ) 251 | { 252 | path[ 0 ] = cwd[ 0 ]; 253 | path[ 1 ] = ':'; 254 | path[ 2 ] = 0; 255 | } 256 | else 257 | { 258 | strcat( strcat( strcpy( path, cwd ), "/"), filename ); 259 | } 260 | 261 | char* str = path; 262 | while( *str ) 263 | { 264 | if( *str == '/' ) 265 | { 266 | *str = '\\'; 267 | } 268 | str++; 269 | } 270 | return path; 271 | } 272 | 273 | 274 | void replace_extension( char* const output, char const* const filename, char const* const new_extension ) 275 | { 276 | strcat( strcat( strcpy( output, dirname( filename ) ), basename( filename, extname( filename ) ) ), new_extension ); 277 | } 278 | 279 | 280 | void mkdir( char const* const path ) 281 | { 282 | #ifdef _WIN32 283 | CreateDirectoryA( path, NULL ); 284 | #else /* _WIN32 */ 285 | #error unsupported platform 286 | #endif 287 | } 288 | 289 | 290 | void rmdir( char const* const path ) 291 | { 292 | #ifdef _WIN32 293 | RemoveDirectoryA( path ); 294 | #else /* _WIN32 */ 295 | #error unsupported platform 296 | #endif 297 | } 298 | 299 | 300 | static int recursive_create_path( char* const fullpath, char* const dirname ) 301 | { 302 | if( dirname ) 303 | { 304 | char* next_dir = strtok( 0, "/\\" ); 305 | dir_t* dir = dir_open( fullpath ); 306 | 307 | if( dir ) 308 | { 309 | int dir_found = 0; 310 | size_t len; 311 | 312 | dir_entry_t* ent = dir_read( dir ); 313 | while( ent ) 314 | { 315 | if( stricmp( dir_name( ent ), dirname ) == 0 ) 316 | { 317 | if( dir_is_folder( ent ) ) 318 | { 319 | dir_found = 1; 320 | break; 321 | } 322 | else if( dir_is_file( ent ) ) 323 | { 324 | dir_close( dir ); 325 | return 0; 326 | } 327 | } 328 | ent = dir_read( dir ); 329 | } 330 | 331 | dir_close( dir ); 332 | 333 | len = strlen( fullpath ); 334 | if( len > 0 && fullpath[ len - 1 ] != '\\' && fullpath[ len - 1 ] != '/') 335 | { 336 | strncat( fullpath, "/", MAX_PATH - strlen( fullpath ) ); 337 | } 338 | strncat( fullpath, dirname, MAX_PATH - strlen( fullpath ) ); 339 | 340 | if( !dir_found ) 341 | { 342 | mkdir( fullpath ); 343 | } 344 | 345 | if( next_dir ) 346 | { 347 | return recursive_create_path( fullpath, next_dir ); 348 | } 349 | else 350 | { 351 | return 1; 352 | } 353 | 354 | } 355 | } 356 | 357 | return 0; 358 | } 359 | 360 | 361 | int create_path( char const* const path ) 362 | { 363 | int retval = 0; 364 | 365 | if( path ) 366 | { 367 | char fullpath[ MAX_PATH ] = ""; 368 | char str[ MAX_PATH ]; 369 | strncpy( str, path, MAX_PATH ); 370 | if( str[1] == ':' ) 371 | { 372 | strncpy( fullpath, str, 3); 373 | retval = recursive_create_path( fullpath, strtok( str + 2, "/\\" ) ); 374 | } 375 | else 376 | { 377 | strcpy( fullpath, "./" ); 378 | retval = recursive_create_path( fullpath, strtok( str, "/\\" ) ); 379 | } 380 | } 381 | 382 | return retval; 383 | } 384 | 385 | 386 | void copy_file( char const* const source, char const* const destination ) 387 | { 388 | #ifdef _WIN32 389 | CopyFileA( source, destination, FALSE ); 390 | #else /* _WIN32 */ 391 | #error unsupported platform 392 | #endif 393 | } 394 | 395 | 396 | size_t file_size( char const* const filename ) 397 | { 398 | if( filename ) 399 | { 400 | struct stat result; 401 | int ret; 402 | ret = stat( filename, &result ); 403 | if( ret == 0 ) 404 | { 405 | return (size_t) result.st_size; 406 | } 407 | } 408 | 409 | return 0; 410 | } 411 | 412 | 413 | time_t file_last_changed( char const* const filename ) 414 | { 415 | if( filename ) 416 | { 417 | struct stat result; 418 | int ret; 419 | ret = stat( filename, &result ); 420 | if( ret == 0 ) 421 | { 422 | return result.st_mtime; 423 | } 424 | } 425 | 426 | return 0; 427 | } 428 | 429 | 430 | time_t most_recent_file_modification( char const* const path ) 431 | { 432 | time_t time = 0; 433 | 434 | if( path ) 435 | { 436 | time = file_last_changed( path ); 437 | dir_t* dir = dir_open( path ); 438 | if( dir ) 439 | { 440 | dir_entry_t* ent = dir_read( dir ); 441 | while( ent ) 442 | { 443 | if( dir_is_file( ent ) ) 444 | { 445 | char filename[ MAX_PATH ]; 446 | strcat( strcat ( strcpy( filename, path ), "/" ), dir_name( ent ) ); 447 | time_t file_time = file_last_changed( filename ); 448 | if (file_time > time ) 449 | { 450 | time = file_time; 451 | } 452 | } 453 | 454 | ent = dir_read( dir ); 455 | } 456 | dir_close( dir ); 457 | } 458 | } 459 | 460 | return time; 461 | } 462 | 463 | 464 | int file_more_recent( char const* const source_path, char const* const output_path ) 465 | { 466 | return file_last_changed( source_path ) > file_last_changed( output_path ); 467 | } 468 | 469 | 470 | int contains_more_recent_file( char const* const source_path, char const* const output_path ) 471 | { 472 | time_t source_time = 0; 473 | time_t output_time = 0; 474 | 475 | if( is_folder( source_path ) ) 476 | { 477 | source_time = most_recent_file_modification( source_path ); 478 | } 479 | else 480 | { 481 | source_time = file_last_changed( source_path ); 482 | } 483 | 484 | if( is_folder( output_path ) ) 485 | { 486 | output_time = most_recent_file_modification( output_path ); 487 | } 488 | else 489 | { 490 | output_time = file_last_changed( output_path ); 491 | } 492 | 493 | return source_time > output_time; 494 | } 495 | 496 | 497 | int folder_count( char const* const path ) 498 | { 499 | int count = 0; 500 | 501 | if( path ) 502 | { 503 | dir_t* dir = dir_open( path ); 504 | if( dir ) 505 | { 506 | dir_entry_t* ent = dir_read( dir ); 507 | while( ent ) 508 | { 509 | char const* d_name = dir_name( ent ); 510 | int namlen = (int) strlen( d_name ); 511 | if( dir_is_folder( ent ) && namlen > 0 && strcmp( d_name, "." ) != 0 && strcmp( d_name, ".." ) != 0 ) 512 | { 513 | count++; 514 | } 515 | 516 | ent = dir_read( dir ); 517 | } 518 | dir_close( dir ); 519 | } 520 | } 521 | 522 | return count; 523 | } 524 | 525 | 526 | int file_count( char const* const path ) 527 | { 528 | int count = 0; 529 | 530 | if( path ) 531 | { 532 | dir_t* dir = dir_open( path ); 533 | if( dir ) 534 | { 535 | dir_entry_t* ent = dir_read( dir ); 536 | while( ent ) 537 | { 538 | if( dir_is_file( ent ) == 0 ) 539 | { 540 | count++; 541 | } 542 | 543 | ent = dir_read( dir ); 544 | } 545 | dir_close( dir ); 546 | } 547 | } 548 | 549 | return count; 550 | } 551 | 552 | 553 | int folder_exists( char const* const path ) 554 | { 555 | struct stat result; 556 | int ret; 557 | ret = stat( path, &result ); 558 | if( ret == 0 ) 559 | { 560 | return result.st_mode & S_IFDIR; 561 | } 562 | 563 | return false; 564 | } 565 | 566 | 567 | int file_exists( char const* const filename ) 568 | { 569 | struct stat result; 570 | int ret; 571 | ret = stat( filename, &result ); 572 | if( ret == 0 ) 573 | { 574 | return result.st_mode & S_IFREG; 575 | } 576 | 577 | return false; 578 | } 579 | 580 | 581 | int is_folder( char const* const path ) 582 | { 583 | if( path ) 584 | { 585 | struct stat result; 586 | int ret; 587 | ret = stat( path, &result ); 588 | if( ret == 0 ) 589 | { 590 | return result.st_mode & S_IFDIR; 591 | } 592 | } 593 | 594 | return false; 595 | } 596 | 597 | 598 | #endif /* FILE_UTIL_IMPLEMENTATION */ 599 | 600 | /* 601 | ------------------------------------------------------------------------------ 602 | 603 | This software is available under 2 licenses - you may choose the one you like. 604 | 605 | ------------------------------------------------------------------------------ 606 | 607 | ALTERNATIVE A - MIT License 608 | 609 | Copyright (c) 2015 Mattias Gustavsson 610 | 611 | Permission is hereby granted, free of charge, to any person obtaining a copy of 612 | this software and associated documentation files (the "Software"), to deal in 613 | the Software without restriction, including without limitation the rights to 614 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 615 | of the Software, and to permit persons to whom the Software is furnished to do 616 | so, subject to the following conditions: 617 | 618 | The above copyright notice and this permission notice shall be included in all 619 | copies or substantial portions of the Software. 620 | 621 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 622 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 623 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 624 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 625 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 626 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 627 | SOFTWARE. 628 | 629 | ------------------------------------------------------------------------------ 630 | 631 | ALTERNATIVE B - Public Domain (www.unlicense.org) 632 | 633 | This is free and unencumbered software released into the public domain. 634 | 635 | Anyone is free to copy, modify, publish, use, compile, sell, or distribute this 636 | software, either in source code form or as a compiled binary, for any purpose, 637 | commercial or non-commercial, and by any means. 638 | 639 | In jurisdictions that recognize copyright laws, the author or authors of this 640 | software dedicate any and all copyright interest in the software to the public 641 | domain. We make this dedication for the benefit of the public at large and to 642 | the detriment of our heirs and successors. We intend this dedication to be an 643 | overt act of relinquishment in perpetuity of all present and future rights to 644 | this software under copyright law. 645 | 646 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 647 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 648 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 649 | AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 650 | ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 651 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 652 | 653 | ------------------------------------------------------------------------------ 654 | */ 655 | -------------------------------------------------------------------------------- /source/pixie/frametimer.h: -------------------------------------------------------------------------------- 1 | /* 2 | ------------------------------------------------------------------------------ 3 | Licensing information can be found at the end of the file. 4 | ------------------------------------------------------------------------------ 5 | 6 | frametimer.h - v0.1 - Framerate timer functionality. 7 | 8 | Do this: 9 | #define FRAMETIMER_IMPLEMENTATION 10 | before you include this file in *one* C/C++ file to create the implementation. 11 | */ 12 | 13 | #ifndef frametimer_h 14 | #define frametimer_h 15 | 16 | typedef struct frametimer_t frametimer_t; 17 | 18 | frametimer_t* frametimer_create( void* memxtx ); 19 | 20 | void frametimer_destroy( frametimer_t* frametimer ); 21 | 22 | void frametimer_lock_rate( frametimer_t* frametimer, int fps ); 23 | 24 | float frametimer_update( frametimer_t* frametimer ); 25 | 26 | float frametimer_delta_time( frametimer_t* frametimer ); 27 | 28 | int frametimer_frame_counter( frametimer_t* frametimer ); 29 | 30 | #endif /* frametimer_h */ 31 | 32 | /* 33 | ---------------------- 34 | IMPLEMENTATION 35 | ---------------------- 36 | */ 37 | 38 | #ifdef FRAMETIMER_IMPLEMENTATION 39 | #undef FRAMETIMER_IMPLEMENTATION 40 | 41 | #define _CRT_NONSTDC_NO_DEPRECATE 42 | #define _CRT_SECURE_NO_WARNINGS 43 | 44 | #ifdef _WIN32 45 | #define _CRT_NONSTDC_NO_DEPRECATE 46 | #define _CRT_SECURE_NO_WARNINGS 47 | #if !defined( _WIN32_WINNT ) || _WIN32_WINNT < 0x0501 48 | #undef _WIN32_WINNT 49 | #define _WIN32_WINNT 0x0501 // requires Windows XP minimum 50 | #endif 51 | // 0x0400=Windows NT 4.0, 0x0500=Windows 2000, 0x0501=Windows XP, 0x0502=Windows Server 2003, 0x0600=Windows Vista, 52 | // 0x0601=Windows 7, 0x0602=Windows 8, 0x0603=Windows 8.1, 0x0A00=Windows 10, 53 | #define _WINSOCKAPI_ 54 | #pragma warning( push ) 55 | #pragma warning( disable: 4668 ) // 'symbol' is not defined as a preprocessor macro, replacing with '0' for 'directives' 56 | #pragma warning( disable: 4255 ) // 'function' : no function prototype given: converting '()' to '(void)' 57 | #include 58 | #pragma warning( pop ) 59 | #pragma comment(lib, "winmm.lib") 60 | #endif 61 | 62 | #ifndef FRAMETIMER_MALLOC 63 | #include 64 | #if defined(__cplusplus) 65 | #define FRAMETIMER_MALLOC( ctx, size ) ( ::malloc( size ) ) 66 | #define FRAMETIMER_FREE( ctx, ptr ) ( ::free( ptr ) ) 67 | #else 68 | #define FRAMETIMER_MALLOC( ctx, size ) ( malloc( size ) ) 69 | #define FRAMETIMER_FREE( ctx, ptr ) ( free( ptr ) ) 70 | #endif 71 | #endif 72 | 73 | #ifndef FRAMETIMER_U64 74 | #define FRAMETIMER_U64 unsigned long long 75 | #endif 76 | 77 | 78 | struct frametimer_t 79 | { 80 | FRAMETIMER_U64 clock_freq; 81 | FRAMETIMER_U64 prev_clock; 82 | void* memctx; 83 | float delta_time; 84 | int initialized; 85 | int frame_counter; 86 | int frame_rate_lock; 87 | #ifdef _WIN32 88 | HANDLE waitable_timer; 89 | #endif 90 | }; 91 | 92 | 93 | frametimer_t* frametimer_create( void* memctx ) 94 | { 95 | frametimer_t* frametimer = (frametimer_t*) FRAMETIMER_MALLOC( memctx, sizeof( frametimer_t ) ); 96 | #ifdef _WIN32 97 | TIMECAPS tc; 98 | if( timeGetDevCaps( &tc, sizeof( TIMECAPS ) ) == TIMERR_NOERROR ) 99 | timeBeginPeriod( tc.wPeriodMin ); 100 | frametimer->waitable_timer = CreateWaitableTimer(NULL, TRUE, NULL); 101 | #endif 102 | 103 | frametimer->memctx = memctx; 104 | frametimer->initialized = 0; 105 | 106 | #ifdef _WIN32 107 | LARGE_INTEGER f; 108 | QueryPerformanceFrequency( &f ); 109 | frametimer->clock_freq = (FRAMETIMER_U64) f.QuadPart; 110 | #else 111 | #error unsupported platform 112 | #endif 113 | 114 | frametimer->prev_clock = 0; 115 | frametimer->delta_time = 0.0f; 116 | frametimer->frame_counter = 0; 117 | frametimer->frame_rate_lock = 0; 118 | return frametimer; 119 | } 120 | 121 | 122 | void frametimer_destroy( frametimer_t* frametimer ) 123 | { 124 | #ifdef _WIN32 125 | CloseHandle( frametimer->waitable_timer ); 126 | TIMECAPS tc; 127 | if( timeGetDevCaps( &tc, sizeof( TIMECAPS ) ) == TIMERR_NOERROR ) 128 | timeEndPeriod( tc.wPeriodMin ); 129 | #endif 130 | FRAMETIMER_FREE( frametimer->memctx, frametimer ); 131 | } 132 | 133 | 134 | void frametimer_lock_rate( frametimer_t* frametimer, int fps ) 135 | { 136 | frametimer->frame_rate_lock = ( fps > 0 && fps < 5 ) ? 5 : fps < 0 ? 0 : fps; 137 | } 138 | 139 | 140 | float frametimer_update( frametimer_t* frametimer ) 141 | { 142 | if( !frametimer->initialized ) 143 | { 144 | #ifdef _WIN32 145 | LARGE_INTEGER c; 146 | QueryPerformanceCounter( &c ); 147 | frametimer->prev_clock = (FRAMETIMER_U64) c.QuadPart; 148 | #else 149 | #error unsupported platform 150 | #endif 151 | frametimer->initialized = 1; 152 | } 153 | 154 | ++frametimer->frame_counter; 155 | 156 | 157 | FRAMETIMER_U64 curr_clock = 0ULL; 158 | #ifdef _WIN32 159 | LARGE_INTEGER c; 160 | QueryPerformanceCounter( &c ); 161 | curr_clock = (FRAMETIMER_U64) c.QuadPart; 162 | #else 163 | #error unsupported platform 164 | #endif 165 | 166 | if( frametimer->frame_rate_lock > 0 ) 167 | { 168 | FRAMETIMER_U64 delta = 0ULL; 169 | if( curr_clock > frametimer->prev_clock ) 170 | delta = curr_clock - frametimer->prev_clock - 1ULL; 171 | if( delta < frametimer->clock_freq / frametimer->frame_rate_lock ) 172 | { 173 | FRAMETIMER_U64 wait = ( frametimer->clock_freq / frametimer->frame_rate_lock ) - delta; 174 | #ifdef _WIN32 175 | if( wait > 0 ) 176 | { 177 | LARGE_INTEGER due_time; 178 | due_time.QuadPart = - (LONGLONG) ( ( 10000000ULL * wait ) / frametimer->clock_freq ) ; 179 | 180 | SetWaitableTimer( frametimer->waitable_timer, &due_time, 0, 0, 0, FALSE ); 181 | WaitForSingleObject( frametimer->waitable_timer, 200 ); // wait long enough for timer to trigger ( 200ms == 5fps ) 182 | CancelWaitableTimer( frametimer->waitable_timer ); // in case we timed out 183 | } 184 | #else 185 | #error unsupported platform 186 | #endif 187 | curr_clock += wait; 188 | } 189 | } 190 | 191 | FRAMETIMER_U64 delta_clock = 0ULL; 192 | if( curr_clock > frametimer->prev_clock ) delta_clock = curr_clock - frametimer->prev_clock; 193 | 194 | // Cap delta time if it is too high (running at less than 5 fps ) or things will jump 195 | // like crazy on occasional long stalls. 196 | if( delta_clock > frametimer->clock_freq / 5ULL ) delta_clock = frametimer->clock_freq / 5ULL; // Cap to 5 fps 197 | 198 | float delta_time = (float) ( ( (double) delta_clock ) / ( (double) frametimer->clock_freq ) ); 199 | 200 | frametimer->delta_time = delta_time; 201 | frametimer->prev_clock = curr_clock; 202 | 203 | return delta_time; 204 | } 205 | 206 | 207 | float frametimer_delta_time( frametimer_t* frametimer ) 208 | { 209 | return frametimer->delta_time; 210 | } 211 | 212 | 213 | int frametimer_frame_counter( frametimer_t* frametimer ) 214 | { 215 | return frametimer->frame_counter; 216 | } 217 | 218 | 219 | #endif /* FRAMETIMER_IMPLEMENTATION */ 220 | 221 | 222 | /* 223 | ------------------------------------------------------------------------------ 224 | 225 | This software is available under 2 licenses - you may choose the one you like. 226 | 227 | ------------------------------------------------------------------------------ 228 | 229 | ALTERNATIVE A - MIT License 230 | 231 | Copyright (c) 2015 Mattias Gustavsson 232 | 233 | Permission is hereby granted, free of charge, to any person obtaining a copy of 234 | this software and associated documentation files (the "Software"), to deal in 235 | the Software without restriction, including without limitation the rights to 236 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 237 | of the Software, and to permit persons to whom the Software is furnished to do 238 | so, subject to the following conditions: 239 | 240 | The above copyright notice and this permission notice shall be included in all 241 | copies or substantial portions of the Software. 242 | 243 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 244 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 245 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 246 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 247 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 248 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 249 | SOFTWARE. 250 | 251 | ------------------------------------------------------------------------------ 252 | 253 | ALTERNATIVE B - Public Domain (www.unlicense.org) 254 | 255 | This is free and unencumbered software released into the public domain. 256 | 257 | Anyone is free to copy, modify, publish, use, compile, sell, or distribute this 258 | software, either in source code form or as a compiled binary, for any purpose, 259 | commercial or non-commercial, and by any means. 260 | 261 | In jurisdictions that recognize copyright laws, the author or authors of this 262 | software dedicate any and all copyright interest in the software to the public 263 | domain. We make this dedication for the benefit of the public at large and to 264 | the detriment of our heirs and successors. We intend this dedication to be an 265 | overt act of relinquishment in perpetuity of all present and future rights to 266 | this software under copyright law. 267 | 268 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 269 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 270 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 271 | AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 272 | ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 273 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 274 | 275 | ------------------------------------------------------------------------------ 276 | */ 277 | -------------------------------------------------------------------------------- /source/pixie/gamepad.h: -------------------------------------------------------------------------------- 1 | /* 2 | ------------------------------------------------------------------------------ 3 | Licensing information can be found at the end of the file. 4 | ------------------------------------------------------------------------------ 5 | 6 | gamepad.h - v0.1 - 7 | */ 8 | 9 | #ifndef gamepad_h 10 | #define gamepad_h 11 | 12 | #ifndef GAMEPAD_I16 13 | #define GAMEPAD_I16 short 14 | #endif 15 | #ifndef GAMEPAD_U16 16 | #define GAMEPAD_U16 unsigned short 17 | #endif 18 | #ifndef GAMEPAD_U8 19 | #define GAMEPAD_U8 unsigned char 20 | #endif 21 | 22 | typedef enum gamepad_result_t 23 | { 24 | GAMEPAD_RESULT_NOT_CONNECTED, 25 | GAMEPAD_RESULT_OK, 26 | } gamepad_result_t; 27 | 28 | 29 | typedef struct gamepad_state_t 30 | { 31 | GAMEPAD_U16 buttons; 32 | GAMEPAD_U8 trigger_left; 33 | GAMEPAD_U8 trigger_right; 34 | GAMEPAD_I16 stick_left_x; 35 | GAMEPAD_I16 stick_left_y; 36 | GAMEPAD_I16 stick_right_x; 37 | GAMEPAD_I16 stick_right_y; 38 | } gamepad_state_t; 39 | 40 | 41 | typedef enum gamepad_button_t 42 | { 43 | GAMEPAD_DPAD_UP = 0x0001, 44 | GAMEPAD_DPAD_DOWN = 0x0002, 45 | GAMEPAD_DPAD_LEFT = 0x0004, 46 | GAMEPAD_DPAD_RIGHT = 0x0008, 47 | GAMEPAD_START = 0x0010, 48 | GAMEPAD_BACK = 0x0020, 49 | GAMEPAD_STICK_LEFT = 0x0040, 50 | GAMEPAD_STICK_RIGHT = 0x0080, 51 | GAMEPAD_SHOULDER_LEFT = 0x0100, 52 | GAMEPAD_SHOULDER_RIGHT = 0x0200, 53 | GAMEPAD_A = 0x1000, 54 | GAMEPAD_B = 0x2000, 55 | GAMEPAD_X = 0x4000, 56 | GAMEPAD_Y = 0x8000, 57 | } gamepad_button_t; 58 | 59 | 60 | typedef struct gamepad_t gamepad_t; 61 | 62 | 63 | gamepad_t* gamepad_create( void* memctx ); 64 | 65 | void gamepad_destroy( gamepad_t* gamepad ); 66 | 67 | gamepad_result_t gamepad_read( gamepad_t* gamepad, int index, gamepad_state_t* state ); 68 | 69 | 70 | #endif /* gamepad_h */ 71 | 72 | /* 73 | ---------------------- 74 | IMPLEMENTATION 75 | ---------------------- 76 | */ 77 | 78 | #ifdef GAMEPAD_IMPLEMENTATION 79 | #undef GAMEPAD_IMPLEMENTATION 80 | 81 | 82 | #ifndef GAMEPAD_MALLOC 83 | #define _CRT_NONSTDC_NO_DEPRECATE 84 | #define _CRT_SECURE_NO_WARNINGS 85 | #include 86 | #if defined(__cplusplus) 87 | #define GAMEPAD_MALLOC( ctx, size ) ( ::malloc( size ) ) 88 | #define GAMEPAD_FREE( ctx, ptr ) ( ::free( ptr ) ) 89 | #else 90 | #define GAMEPAD_MALLOC( ctx, size ) ( malloc( size ) ) 91 | #define GAMEPAD_FREE( ctx, ptr ) ( free( ptr ) ) 92 | #endif 93 | #endif 94 | 95 | 96 | typedef struct gamepad_internal_XINPUT_GAMEPAD 97 | { 98 | WORD wButtons; 99 | BYTE bLeftTrigger; 100 | BYTE bRightTrigger; 101 | SHORT sThumbLX; 102 | SHORT sThumbLY; 103 | SHORT sThumbRX; 104 | SHORT sThumbRY; 105 | } gamepad_internal_XINPUT_GAMEPAD; 106 | 107 | 108 | typedef struct gamepad_internal_XINPUT_STATE 109 | { 110 | DWORD dwPacketNumber; 111 | gamepad_internal_XINPUT_GAMEPAD Gamepad; 112 | } gamepad_internal_XINPUT_STATE; 113 | 114 | 115 | typedef DWORD (WINAPI *gamepad_internal_XInputGetState_t)( DWORD, gamepad_internal_XINPUT_STATE* ); 116 | 117 | 118 | typedef struct gamepad_t 119 | { 120 | void* memctx; 121 | HMODULE dll; 122 | gamepad_internal_XInputGetState_t get_state; 123 | } gamepad_t; 124 | 125 | 126 | gamepad_t* gamepad_create( void* memctx ) 127 | { 128 | (void) memctx; 129 | 130 | HMODULE dll = 0; 131 | int version = 4; 132 | char const* dll_name[] = { "xinput1_0.dll", "xinput1_1.dll", "xinput1_2.dll", "xinput1_3.dll", "xinput1_4.dll" }; 133 | char const* dll_name9[] = { "xinput9_1_0.dll", "xinput9_1_1.dll", "xinput9_1_2.dll", "xinput9_1_3.dll", "xinput9_1_4.dll" }; 134 | while( !dll && version >= 0 ) 135 | { 136 | dll = LoadLibraryA( dll_name[ version ] ); 137 | if( !dll ) dll = LoadLibraryA( dll_name9[ version ] ); 138 | --version; 139 | } 140 | 141 | if( !dll ) return 0; 142 | 143 | FARPROC proc = GetProcAddress( dll, "XInputGetState" ); 144 | if( !proc) 145 | { 146 | FreeLibrary( dll ); 147 | return 0; 148 | } 149 | 150 | gamepad_t* gamepad = (gamepad_t*) GAMEPAD_MALLOC( memctx, sizeof( gamepad_t ) ); 151 | gamepad->memctx = memctx; 152 | gamepad->dll = dll; 153 | gamepad->get_state = (gamepad_internal_XInputGetState_t) (uintptr_t) proc; 154 | return gamepad; 155 | } 156 | 157 | 158 | void gamepad_destroy( gamepad_t* gamepad ) 159 | { 160 | FreeLibrary( gamepad->dll ); 161 | GAMEPAD_FREE( gamepad->memctx, gamepad ); 162 | } 163 | 164 | 165 | gamepad_result_t gamepad_read( gamepad_t* gamepad, int index, gamepad_state_t* state ) 166 | { 167 | if( index < 0 || index > 3 ) 168 | { 169 | return GAMEPAD_RESULT_NOT_CONNECTED; 170 | } 171 | else 172 | { 173 | gamepad_internal_XINPUT_STATE xstate; 174 | DWORD result = gamepad->get_state( (DWORD) index, &xstate ); 175 | if( result == ERROR_SUCCESS ) 176 | { 177 | if( state ) 178 | { 179 | state->buttons = xstate.Gamepad.wButtons; 180 | state->trigger_left = xstate.Gamepad.bLeftTrigger; 181 | state->trigger_right = xstate.Gamepad.bRightTrigger; 182 | state->stick_left_x = xstate.Gamepad.sThumbLX; 183 | state->stick_left_y = xstate.Gamepad.sThumbLY; 184 | state->stick_right_x = xstate.Gamepad.sThumbRX; 185 | state->stick_right_y = xstate.Gamepad.sThumbRY; 186 | } 187 | return GAMEPAD_RESULT_OK; 188 | } 189 | else 190 | { 191 | return GAMEPAD_RESULT_NOT_CONNECTED; 192 | } 193 | } 194 | } 195 | 196 | 197 | #endif /* GAMEPAD_IMPLEMENTATION */ 198 | 199 | /* 200 | ------------------------------------------------------------------------------ 201 | 202 | This software is available under 2 licenses - you may choose the one you like. 203 | 204 | ------------------------------------------------------------------------------ 205 | 206 | ALTERNATIVE A - MIT License 207 | 208 | Copyright (c) 2015 Mattias Gustavsson 209 | 210 | Permission is hereby granted, free of charge, to any person obtaining a copy of 211 | this software and associated documentation files (the "Software"), to deal in 212 | the Software without restriction, including without limitation the rights to 213 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 214 | of the Software, and to permit persons to whom the Software is furnished to do 215 | so, subject to the following conditions: 216 | 217 | The above copyright notice and this permission notice shall be included in all 218 | copies or substantial portions of the Software. 219 | 220 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 221 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 222 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 223 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 224 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 225 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 226 | SOFTWARE. 227 | 228 | ------------------------------------------------------------------------------ 229 | 230 | ALTERNATIVE B - Public Domain (www.unlicense.org) 231 | 232 | This is free and unencumbered software released into the public domain. 233 | 234 | Anyone is free to copy, modify, publish, use, compile, sell, or distribute this 235 | software, either in source code form or as a compiled binary, for any purpose, 236 | commercial or non-commercial, and by any means. 237 | 238 | In jurisdictions that recognize copyright laws, the author or authors of this 239 | software dedicate any and all copyright interest in the software to the public 240 | domain. We make this dedication for the benefit of the public at large and to 241 | the detriment of our heirs and successors. We intend this dedication to be an 242 | overt act of relinquishment in perpetuity of all present and future rights to 243 | this software under copyright law. 244 | 245 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 246 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 247 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 248 | AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 249 | ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 250 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 251 | 252 | ------------------------------------------------------------------------------ 253 | */ 254 | -------------------------------------------------------------------------------- /source/pixie/graph.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | ------------------------------------------------------------------------------ 3 | Licensing information can be found at the end of the file. 4 | ------------------------------------------------------------------------------ 5 | 6 | graph.hpp - v0.1 - Util lib for basic graphics drawing, for C++. 7 | 8 | */ 9 | 10 | #ifndef graph_hpp 11 | #define graph_hpp 12 | 13 | namespace graph_ns { 14 | 15 | template< typename SCREEN_TYPE, typename COLOR_TYPE > 16 | struct graph 17 | { 18 | graph(); 19 | graph( SCREEN_TYPE* scr ); 20 | 21 | void pset( int x, int y, COLOR_TYPE color ); 22 | COLOR_TYPE pget( int x, int y ); 23 | 24 | void hline( int x, int y, int len, COLOR_TYPE color ); 25 | void vline( int x, int y, int len, COLOR_TYPE color ); 26 | 27 | void line( int x1, int y1, int x2, int y2, COLOR_TYPE color ); 28 | 29 | void box( int x, int y, int w, int h, COLOR_TYPE color ); 30 | void box_fill( int x, int y, int w, int h, COLOR_TYPE color ); 31 | 32 | void circle( int x, int y, int r, COLOR_TYPE color ); 33 | void circle_fill( int x, int y, int r, COLOR_TYPE color ); 34 | 35 | void ellipse( int x, int y, int rx, int ry, COLOR_TYPE color ); 36 | void ellipse_fill( int x, int y, int rx, int ry, COLOR_TYPE color ); 37 | 38 | void polygon( int* points_xy, int count, COLOR_TYPE color ); 39 | template< int MAX_POLYGON_POINTS > void polygon_fill( int* points_xy, int count, COLOR_TYPE color ); 40 | 41 | SCREEN_TYPE* screen; 42 | }; 43 | 44 | 45 | } /* namespace graph_ns */ 46 | 47 | #endif /* graph_hpp */ 48 | 49 | 50 | /* 51 | ---------------------- 52 | IMPLEMENTATION 53 | ---------------------- 54 | */ 55 | 56 | #ifndef graph_impl 57 | #define graph_impl 58 | 59 | 60 | namespace graph_ns { 61 | 62 | 63 | template< typename SCREEN_TYPE, typename COLOR_TYPE > 64 | graph::graph() : screen(0) 65 | { } 66 | 67 | 68 | template< typename SCREEN_TYPE, typename COLOR_TYPE > 69 | graph::graph( SCREEN_TYPE* scr ) : screen( scr ) 70 | { } 71 | 72 | 73 | template< typename SCREEN_TYPE, typename COLOR_TYPE > 74 | void graph::pset( int x, int y, COLOR_TYPE color ) 75 | { 76 | screen->pset( x, y, color ); 77 | } 78 | 79 | 80 | template< typename SCREEN_TYPE, typename COLOR_TYPE > 81 | COLOR_TYPE graph::pget( int x, int y ) 82 | { 83 | return screen->pget( x, y ); 84 | } 85 | 86 | 87 | template< typename SCREEN_TYPE, typename COLOR_TYPE > 88 | void graph::hline( int x, int y, int len, COLOR_TYPE color ) 89 | { 90 | screen->hline( x, y, len, color ); 91 | } 92 | 93 | 94 | template< typename SCREEN_TYPE, typename COLOR_TYPE > 95 | void graph::vline( int x, int y, int len, COLOR_TYPE color ) 96 | { 97 | for( int i = y; i < y + len; ++i ) 98 | pset( x, i, color ); 99 | } 100 | 101 | 102 | template< typename SCREEN_TYPE, typename COLOR_TYPE > 103 | void graph::line( int x1, int y1, int x2, int y2, COLOR_TYPE color ) 104 | { 105 | int dx = x2 - x1; 106 | dx = dx < 0 ? -dx : dx; 107 | int sx = x1 < x2 ? 1 : -1; 108 | int dy = y2 - y1; 109 | dy = dy < 0 ? -dy : dy; 110 | int sy = y1 < y2 ? 1 : -1; 111 | int err = ( dx > dy ? dx : -dy ) / 2; 112 | 113 | int x = x1; 114 | int y = y1; 115 | while( x != x2 || y != y2 ) 116 | { 117 | pset( x, y, color ); 118 | 119 | int e2 = err; 120 | if( e2 > -dx ) { err -= dy; x += sx; } 121 | if( e2 < dy ) { err += dx; y += sy; } 122 | } 123 | pset( x, y, color ); 124 | } 125 | 126 | 127 | template< typename SCREEN_TYPE, typename COLOR_TYPE > 128 | void graph::box( int x, int y, int w, int h, COLOR_TYPE color ) 129 | { 130 | hline( x, y, w, color ); 131 | hline( x, y + h - 1, w, color ); 132 | vline( x, y, h, color ); 133 | vline( x + w - 1, y, h, color ); 134 | } 135 | 136 | 137 | template< typename SCREEN_TYPE, typename COLOR_TYPE > 138 | void graph::box_fill( int x, int y, int w, int h, COLOR_TYPE color ) 139 | { 140 | for( int i = y; i < y + h; ++i ) 141 | hline( x, i, w, color ); 142 | } 143 | 144 | 145 | template< typename SCREEN_TYPE, typename COLOR_TYPE > 146 | void graph::circle( int x, int y, int r, COLOR_TYPE color ) 147 | { 148 | int f = 1 - r; 149 | int dx = 0; 150 | int dy = -2 * r; 151 | int ix = 0; 152 | int iy = r; 153 | 154 | pset( x, y + r, color ); 155 | pset( x, y - r, color ); 156 | pset( x + r, y, color ); 157 | pset( x - r, y, color ); 158 | 159 | while( ix < iy ) 160 | { 161 | if( f >= 0 ) 162 | { 163 | --iy; 164 | dy += 2; 165 | f += dy; 166 | } 167 | ++ix; 168 | dx += 2; 169 | f += dx + 1; 170 | 171 | pset( x + ix, y + iy, color ); 172 | pset( x - ix, y + iy, color ); 173 | pset( x + ix, y - iy, color ); 174 | pset( x - ix, y - iy, color ); 175 | pset( x + iy, y + ix, color ); 176 | pset( x - iy, y + ix, color ); 177 | pset( x + iy, y - ix, color ); 178 | pset( x - iy, y - ix, color ); 179 | } 180 | } 181 | 182 | 183 | template< typename SCREEN_TYPE, typename COLOR_TYPE > 184 | void graph::circle_fill( int x, int y, int r, COLOR_TYPE color ) 185 | { 186 | int f = 1 - r; 187 | int dx = 0; 188 | int dy = -2 * r; 189 | int ix = 0; 190 | int iy = r; 191 | 192 | while( ix <= iy ) 193 | { 194 | hline( x - iy, y + ix, 2 * iy, color ); 195 | hline( x - iy, y - ix, 2 * iy, color ); 196 | if( f >= 0 ) 197 | { 198 | hline( x - ix, y + iy, 2 * ix, color ); 199 | hline( x - ix, y - iy, 2 * ix, color ); 200 | 201 | --iy; 202 | dy += 2; 203 | f += dy; 204 | } 205 | ++ix; 206 | dx += 2; 207 | f += dx + 1; 208 | } 209 | } 210 | 211 | 212 | template< typename SCREEN_TYPE, typename COLOR_TYPE > 213 | void graph::ellipse( int x, int y, int rx, int ry, COLOR_TYPE color ) 214 | { 215 | int asq = rx * rx; 216 | int bsq = ry * ry; 217 | 218 | pset( x, y + ry, color ); 219 | pset( x, y - ry, color ); 220 | 221 | int wx = 0; 222 | int wy = ry; 223 | int xa = 0; 224 | int ya = asq * 2 * ry; 225 | int thresh = asq / 4 - asq * ry; 226 | 227 | for( ; ; ) 228 | { 229 | thresh += xa + bsq; 230 | 231 | if (thresh >= 0) 232 | { 233 | ya -= asq * 2; 234 | thresh -= ya; 235 | --wy; 236 | } 237 | 238 | xa += bsq * 2; 239 | ++wx; 240 | 241 | if (xa >= ya) break; 242 | 243 | pset( x + wx, y - wy, color ); 244 | pset( x - wx, y - wy, color ); 245 | pset( x + wx, y + wy, color ); 246 | pset( x - wx, y + wy, color ); 247 | } 248 | 249 | pset( x + rx, y, color ); 250 | pset( x - rx, y, color ); 251 | 252 | wx = rx; 253 | wy = 0; 254 | xa = bsq * 2 * rx; 255 | 256 | ya = 0; 257 | thresh = bsq / 4 - bsq * rx; 258 | 259 | for( ; ; ) 260 | { 261 | thresh += ya + asq; 262 | 263 | if (thresh >= 0) 264 | { 265 | xa -= bsq * 2; 266 | thresh = thresh - xa; 267 | --wx; 268 | } 269 | 270 | ya += asq * 2; 271 | ++wy; 272 | 273 | if (ya > xa) break; 274 | 275 | pset( x + wx, y - wy, color ); 276 | pset( x - wx, y - wy, color ); 277 | pset( x + wx, y + wy, color ); 278 | pset( x - wx, y + wy, color ); 279 | } 280 | } 281 | 282 | 283 | template< typename SCREEN_TYPE, typename COLOR_TYPE > 284 | void graph::ellipse_fill( int x, int y, int rx, int ry, COLOR_TYPE color ) 285 | { 286 | int asq = rx * rx; 287 | int bsq = ry * ry; 288 | 289 | int wx = 0; 290 | int wy = ry; 291 | int xa = 0; 292 | int ya = asq * 2 * ry; 293 | int thresh = asq / 4 - asq * ry; 294 | 295 | for( ; ; ) 296 | { 297 | thresh += xa + bsq; 298 | 299 | if (thresh >= 0) 300 | { 301 | ya -= asq * 2; 302 | thresh -= ya; 303 | hline( x - wx, y - wy, wx * 2, color ); 304 | hline( x - wx, y + wy, wx * 2, color ); 305 | --wy; 306 | } 307 | 308 | xa += bsq * 2; 309 | ++wx; 310 | if (xa >= ya) break; 311 | } 312 | 313 | hline( x - rx, y, rx * 2, color ); 314 | 315 | wx = rx; 316 | wy = 0; 317 | xa = bsq * 2 * rx; 318 | 319 | ya = 0; 320 | thresh = bsq / 4 - bsq * rx; 321 | 322 | for( ; ; ) 323 | { 324 | thresh += ya + asq; 325 | 326 | if (thresh >= 0) 327 | { 328 | xa -= bsq * 2; 329 | thresh = thresh - xa; 330 | --wx; 331 | } 332 | 333 | ya += asq * 2; 334 | ++wy; 335 | 336 | if (ya > xa) break; 337 | 338 | hline( x - wx, y - wy, wx * 2, color ); 339 | hline( x - wx, y + wy, wx * 2, color ); 340 | } 341 | } 342 | 343 | 344 | template< typename SCREEN_TYPE, typename COLOR_TYPE > 345 | void graph::polygon( int* points_xy, int count, COLOR_TYPE color ) 346 | { 347 | for( int i = 0; i < count - 1; ++i ) 348 | line( points_xy[ i * 2 + 0 ], points_xy[ i * 2 + 1 ], 349 | points_xy[ ( i + 1 ) * 2 + 0 ], points_xy[ ( i + 1 ) * 2 + 1 ], color ); 350 | } 351 | 352 | 353 | 354 | template< typename SCREEN_TYPE, typename COLOR_TYPE > 355 | template< int MAX_POLYGON_POINTS > 356 | void graph::polygon_fill( int* points_xy, int count, COLOR_TYPE color ) 357 | { 358 | static int node_x[ MAX_POLYGON_POINTS ]; 359 | 360 | if( count <= 0 || count > MAX_POLYGON_POINTS ) return; 361 | 362 | int min_y = points_xy[ 0 + 1 ]; 363 | int max_y = min_y; 364 | 365 | // find extents 366 | for( int i = 1; i < count; ++i ) 367 | { 368 | if( points_xy[ i * 2 + 1 ] < min_y ) min_y = points_xy[ i * 2 + 1 ]; 369 | if( points_xy[ i * 2 + 1 ] > max_y ) max_y = points_xy[ i * 2 + 1 ]; 370 | } 371 | 372 | for( int y = min_y; y < max_y; ++y ) 373 | { 374 | // find intersection points_xy 375 | int nodes = 0; 376 | int j = count - 1; 377 | for( int i = 0; i < count; ++i ) 378 | { 379 | if( ( points_xy[ i * 2 + 1 ] <= y && points_xy[ j * 2 + 1 ] > y ) || 380 | ( points_xy[ j * 2 + 1 ] <= y && points_xy[ i * 2 + 1 ] > y ) ) 381 | { 382 | int dx = points_xy[ j * 2 + 0 ] - points_xy[ i * 2 + 0 ]; 383 | int dy = points_xy[ j * 2 + 1 ] - points_xy[ i * 2 + 1 ]; 384 | node_x[ nodes++ ] = points_xy[ i * 2 + 0 ] + ( ( y - points_xy[ i * 2 + 1 ] ) * dx ) / dy ; 385 | } 386 | j = i; 387 | } 388 | 389 | // sort by x 390 | int xi = 0; 391 | while( xi < nodes - 1 ) 392 | { 393 | if( node_x[ xi ] > node_x[ xi + 1 ] ) 394 | { 395 | int swap = node_x[ xi ]; 396 | node_x[ xi ] = node_x[ xi + 1 ]; 397 | node_x[ xi + 1 ] = swap; 398 | if( xi ) --xi; 399 | } 400 | else 401 | { 402 | ++xi; 403 | } 404 | } 405 | 406 | for( int i = 0; i < nodes; i += 2 ) 407 | hline( node_x[ i ], y, node_x[ i + 1 ] - node_x[ i ], color ); 408 | } 409 | } 410 | 411 | 412 | } /* namespace graph_ns */ 413 | 414 | #endif /* graph_impl */ 415 | 416 | /* 417 | ------------------------------------------------------------------------------ 418 | 419 | This software is available under 2 licenses - you may choose the one you like. 420 | 421 | ------------------------------------------------------------------------------ 422 | 423 | ALTERNATIVE A - MIT License 424 | 425 | Copyright (c) 2015 Mattias Gustavsson 426 | 427 | Permission is hereby granted, free of charge, to any person obtaining a copy of 428 | this software and associated documentation files (the "Software"), to deal in 429 | the Software without restriction, including without limitation the rights to 430 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 431 | of the Software, and to permit persons to whom the Software is furnished to do 432 | so, subject to the following conditions: 433 | 434 | The above copyright notice and this permission notice shall be included in all 435 | copies or substantial portions of the Software. 436 | 437 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 438 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 439 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 440 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 441 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 442 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 443 | SOFTWARE. 444 | 445 | ------------------------------------------------------------------------------ 446 | 447 | ALTERNATIVE B - Public Domain (www.unlicense.org) 448 | 449 | This is free and unencumbered software released into the public domain. 450 | 451 | Anyone is free to copy, modify, publish, use, compile, sell, or distribute this 452 | software, either in source code form or as a compiled binary, for any purpose, 453 | commercial or non-commercial, and by any means. 454 | 455 | In jurisdictions that recognize copyright laws, the author or authors of this 456 | software dedicate any and all copyright interest in the software to the public 457 | domain. We make this dedication for the benefit of the public at large and to 458 | the detriment of our heirs and successors. We intend this dedication to be an 459 | overt act of relinquishment in perpetuity of all present and future rights to 460 | this software under copyright law. 461 | 462 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 463 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 464 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 465 | AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 466 | ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 467 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 468 | 469 | ------------------------------------------------------------------------------ 470 | */ 471 | -------------------------------------------------------------------------------- /source/pixie/handles.h: -------------------------------------------------------------------------------- 1 | /* 2 | ------------------------------------------------------------------------------ 3 | Licensing information can be found at the end of the file. 4 | ------------------------------------------------------------------------------ 5 | 6 | handles.h - v0.1 - Generic handles with validation, for C/C++. 7 | 8 | Do this: 9 | #define HANDLES_IMPLEMENTATION 10 | before you include this file in *one* C/C++ file to create the implementation. 11 | */ 12 | 13 | #ifndef handles_h 14 | #define handles_h 15 | 16 | #ifndef HANDLES_U64 17 | #define HANDLES_U64 unsigned long long 18 | #endif 19 | 20 | typedef struct handles_t handles_t; 21 | 22 | void handles_init( handles_t* handles, int initial_capacity, void* memctx ); 23 | void handles_term( handles_t* handles ); 24 | 25 | int handles_alloc( handles_t* handles, int index ); 26 | void handles_release( handles_t* handles, int handle ); 27 | 28 | int handles_index( handles_t* handles, int handle ); 29 | void handles_update( handles_t* handles, int handle, int index ); 30 | 31 | int handles_validate( handles_t* handles, HANDLES_U64 u ); 32 | HANDLES_U64 handles_to_u64( handles_t* handles, int handle ); 33 | int handles_from_u64( handles_t* handles, HANDLES_U64 u ); 34 | 35 | #endif /* handles_h */ 36 | 37 | 38 | /* 39 | ---------------------- 40 | IMPLEMENTATION 41 | ---------------------- 42 | */ 43 | 44 | #ifndef handles_impl 45 | #define handles_impl 46 | 47 | struct handles_internal_data_t 48 | { 49 | int index; 50 | int counter; 51 | }; 52 | 53 | struct handles_t 54 | { 55 | void* memctx; 56 | struct handles_internal_data_t* data; 57 | int capacity; 58 | int count; 59 | int freelist_head; 60 | int freelist_tail; 61 | }; 62 | 63 | #endif /* handles_impl */ 64 | 65 | 66 | #ifdef HANDLES_IMPLEMENTATION 67 | #undef HANDLES_IMPLEMENTATION 68 | 69 | #ifndef HANDLES_ASSERT 70 | #define _CRT_NONSTDC_NO_DEPRECATE 71 | #define _CRT_SECURE_NO_WARNINGS 72 | #include 73 | #define HANDLES_ASSERT( expression, message ) assert( ( expression ) && ( message ) ) 74 | #endif 75 | 76 | #ifndef HANDLES_MEMCPY 77 | #define _CRT_NONSTDC_NO_DEPRECATE 78 | #define _CRT_SECURE_NO_WARNINGS 79 | #include 80 | #define HANDLES_MEMCPY( dst, src, cnt ) ( memcpy( dst, src, cnt ) ) 81 | #endif 82 | 83 | #ifndef HANDLES_MALLOC 84 | #define _CRT_NONSTDC_NO_DEPRECATE 85 | #define _CRT_SECURE_NO_WARNINGS 86 | #include 87 | #define HANDLES_MALLOC( ctx, size ) ( malloc( size ) ) 88 | #define HANDLES_FREE( ctx, ptr ) ( free( ptr ) ) 89 | #endif 90 | 91 | 92 | void handles_init( handles_t* handles, int initial_capacity, void* memctx ) 93 | { 94 | handles->memctx = memctx; 95 | handles->count = 0; 96 | handles->capacity = initial_capacity <= 0 ? 1 : initial_capacity; 97 | handles->freelist_head = -1; 98 | handles->freelist_tail = -1; 99 | handles->data = (struct handles_internal_data_t*) HANDLES_MALLOC( memctx, handles->capacity * sizeof( *handles->data ) ); 100 | HANDLES_ASSERT( handles->data, "Allocation failed" ); 101 | } 102 | 103 | 104 | void handles_term( handles_t* handles ) 105 | { 106 | HANDLES_FREE( handles->memctx, handles->data ); 107 | } 108 | 109 | 110 | int handles_alloc( handles_t* handles, int index ) 111 | { 112 | int handle; 113 | 114 | if( handles->count < handles->capacity ) 115 | { 116 | handle = handles->count; 117 | handles->data[ handles->count ].counter = 0; 118 | ++handles->count; 119 | } 120 | else if( handles->freelist_head >= 0 ) 121 | { 122 | handle = handles->freelist_head; 123 | if( handles->freelist_tail == handles->freelist_head ) handles->freelist_tail = handles->data[ handles->freelist_head ].index; 124 | handles->freelist_head = handles->data[ handles->freelist_head ].index; 125 | } 126 | else 127 | { 128 | handles->capacity *= 2; 129 | struct handles_internal_data_t* new_data = (struct handles_internal_data_t*) HANDLES_MALLOC( handles->memctx, handles->capacity * sizeof( *handles->data ) ); 130 | HANDLES_ASSERT( new_data, "Allocation failed" ); 131 | HANDLES_MEMCPY( new_data, handles->data, handles->count * sizeof( *handles->data ) ); 132 | HANDLES_FREE( handles->memctx, handles->data ); 133 | handles->data = new_data; 134 | handle = handles->count; 135 | handles->data[ handles->count ].counter = 0; 136 | ++handles->count; 137 | } 138 | 139 | handles->data[ handle ].index = index; 140 | return handle; 141 | } 142 | 143 | 144 | void handles_release( handles_t* handles, int handle ) 145 | { 146 | if( handles->freelist_tail < 0 ) 147 | { 148 | HANDLES_ASSERT( handles->freelist_head < 0, "Freelist invalid" ); 149 | handles->freelist_head = handle; 150 | handles->freelist_tail = handle; 151 | } 152 | else 153 | { 154 | handles->data[ handles->freelist_tail ].index = handle; 155 | handles->freelist_tail = handle; 156 | } 157 | ++handles->data[ handle ].counter; // invalidate handle via counter 158 | handles->data[ handle ].index = -1; 159 | } 160 | 161 | 162 | int handles_index( handles_t* handles, int handle ) 163 | { 164 | if( handle >= 0 && handle < handles->count ) 165 | return handles->data[ handle ].index; 166 | else 167 | return -1; 168 | } 169 | 170 | 171 | void handles_update( handles_t* handles, int handle, int index ) 172 | { 173 | handles->data[ handle ].index = index; 174 | } 175 | 176 | 177 | static HANDLES_U64 to_u64( int handle, int counter ) 178 | { 179 | HANDLES_U64 const i = (HANDLES_U64) ( handle + 1 ); 180 | HANDLES_U64 const c = (HANDLES_U64) counter; 181 | return ( c << 32ull ) | ( i ); 182 | } 183 | 184 | 185 | static int u64_to_counter( HANDLES_U64 u ) 186 | { 187 | return (int) ( u >> 32ull ) ; 188 | } 189 | 190 | 191 | static int u64_to_handle( HANDLES_U64 u ) 192 | { 193 | return ( (int) ( u & 0xffffffffull ) ) - 1; 194 | } 195 | 196 | 197 | HANDLES_U64 handles_to_u64( handles_t* handles, int handle ) 198 | { 199 | return to_u64( handle, handles->data[ handle ].counter ); 200 | } 201 | 202 | 203 | int handles_from_u64( handles_t* handles, HANDLES_U64 u ) 204 | { 205 | int const handle = u64_to_handle( u ); 206 | if( handle >= 0 && handle < handles->count && handles->data[ handle ].counter == u64_to_counter( u ) ) 207 | { 208 | return handle; 209 | } 210 | else 211 | { 212 | return -1; 213 | } 214 | } 215 | 216 | 217 | int handles_validate( handles_t* handles, HANDLES_U64 u ) 218 | { 219 | int const handle = u64_to_handle( u ); 220 | return handle >= 0 && handle < handles->count && handles->data[ handle ].counter == u64_to_counter( u ); 221 | } 222 | 223 | 224 | #endif /* HANDLES_IMPLEMENTATION */ 225 | 226 | /* 227 | ------------------------------------------------------------------------------ 228 | 229 | This software is available under 2 licenses - you may choose the one you like. 230 | 231 | ------------------------------------------------------------------------------ 232 | 233 | ALTERNATIVE A - MIT License 234 | 235 | Copyright (c) 2015 Mattias Gustavsson 236 | 237 | Permission is hereby granted, free of charge, to any person obtaining a copy of 238 | this software and associated documentation files (the "Software"), to deal in 239 | the Software without restriction, including without limitation the rights to 240 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 241 | of the Software, and to permit persons to whom the Software is furnished to do 242 | so, subject to the following conditions: 243 | 244 | The above copyright notice and this permission notice shall be included in all 245 | copies or substantial portions of the Software. 246 | 247 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 248 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 249 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 250 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 251 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 252 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 253 | SOFTWARE. 254 | 255 | ------------------------------------------------------------------------------ 256 | 257 | ALTERNATIVE B - Public Domain (www.unlicense.org) 258 | 259 | This is free and unencumbered software released into the public domain. 260 | 261 | Anyone is free to copy, modify, publish, use, compile, sell, or distribute this 262 | software, either in source code form or as a compiled binary, for any purpose, 263 | commercial or non-commercial, and by any means. 264 | 265 | In jurisdictions that recognize copyright laws, the author or authors of this 266 | software dedicate any and all copyright interest in the software to the public 267 | domain. We make this dedication for the benefit of the public at large and to 268 | the detriment of our heirs and successors. We intend this dedication to be an 269 | overt act of relinquishment in perpetuity of all present and future rights to 270 | this software under copyright law. 271 | 272 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 273 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 274 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 275 | AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 276 | ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 277 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 278 | 279 | ------------------------------------------------------------------------------ 280 | */ 281 | 282 | -------------------------------------------------------------------------------- /source/pixie/jar_mod.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mattiasgustavsson/pixie/590856bd400d40ab5b8c5ae013f72e3e59677b5e/source/pixie/jar_mod.h -------------------------------------------------------------------------------- /source/pixie/jar_xm.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mattiasgustavsson/pixie/590856bd400d40ab5b8c5ae013f72e3e59677b5e/source/pixie/jar_xm.h -------------------------------------------------------------------------------- /source/pixie/log.h: -------------------------------------------------------------------------------- 1 | /* 2 | ------------------------------------------------------------------------------ 3 | Licensing information can be found at the end of the file. 4 | ------------------------------------------------------------------------------ 5 | 6 | log.h - v0.1 - Simple file/console logging helper for C/C++. 7 | 8 | Do this: 9 | #define LOG_IMPLEMENTATION 10 | before you include this file in *one* C/C++ file to create the implementation. 11 | */ 12 | 13 | #ifndef log_h 14 | #define log_h 15 | 16 | typedef struct log_t log_t; 17 | 18 | log_t* log_create( char const* filename, void* memctx ); 19 | void log_destroy( log_t* log ); 20 | void log_print( log_t* log, char const* str, ... ); 21 | void log_print_pending( log_t* log, char const* str, ... ); 22 | void log_discard_pending( log_t* log ); 23 | void log_commit_pending( log_t* log ); 24 | int log_mute( log_t* log ); 25 | int log_unmute( log_t* log ); 26 | 27 | #endif /* log_h */ 28 | 29 | /* 30 | ---------------------- 31 | IMPLEMENTATION 32 | ---------------------- 33 | */ 34 | 35 | #ifdef LOG_IMPLEMENTATION 36 | #undef LOG_IMPLEMENTATION 37 | 38 | #define _CRT_NONSTDC_NO_DEPRECATE 39 | #define _CRT_SECURE_NO_WARNINGS 40 | #include 41 | #include 42 | #include 43 | #include 44 | 45 | #ifndef LOG_MALLOC 46 | #define _CRT_NONSTDC_NO_DEPRECATE 47 | #define _CRT_SECURE_NO_WARNINGS 48 | #include 49 | #define LOG_MALLOC( ctx, size ) ( malloc( size ) ) 50 | #define LOG_FREE( ctx, ptr ) ( free( ptr ) ) 51 | #endif 52 | 53 | struct log_t 54 | { 55 | void* memctx; 56 | char* data; 57 | size_t capacity; 58 | size_t size; 59 | size_t pending_point; 60 | int muted; 61 | FILE* fp; 62 | }; 63 | 64 | 65 | log_t* log_create( char const* const filename, void* memctx ) 66 | { 67 | log_t* log = (log_t*) LOG_MALLOC( memctx, sizeof( log_t ) ); 68 | log->memctx = memctx; 69 | log->data = 0; 70 | log->capacity = 0; 71 | log->size = 0; 72 | log->pending_point = ~(size_t) 0; 73 | log->muted = 0; 74 | if( filename ) 75 | log->fp = fopen( filename, "w" ); 76 | else 77 | log->fp = 0; 78 | 79 | return log; 80 | } 81 | 82 | 83 | void log_destroy( log_t* const log ) 84 | { 85 | log_commit_pending( log ); 86 | if( log->fp ) fclose( log->fp ); 87 | if( log->data ) LOG_FREE( log->memctx, log->data ); 88 | LOG_FREE( log->memctx, log ); 89 | } 90 | 91 | 92 | static void alloc_data( log_t* const log, int const count ) 93 | { 94 | if( log->data ) 95 | { 96 | while( count >= (int) ( log->capacity - log->size ) ) 97 | { 98 | log->capacity *= 2; 99 | } 100 | char* new_data = (char*) LOG_MALLOC( log->memctx, log->capacity ); 101 | memcpy( new_data, log->data, log->size + 1 ); 102 | LOG_FREE( log->memctx, log->data ); 103 | log->data = new_data; 104 | } 105 | else 106 | { 107 | log->capacity = 256; 108 | while( count >= (int) ( log->capacity - log->size ) ) 109 | { 110 | log->capacity *= 2; 111 | } 112 | log->data = (char*) LOG_MALLOC( log->memctx, log->capacity ); 113 | } 114 | } 115 | 116 | 117 | void log_print( log_t* const log, char const* const str, ... ) 118 | { 119 | if( !log ) return; 120 | if( log->muted ) return; 121 | 122 | log->pending_point = ~(size_t) 0; 123 | va_list args; 124 | va_start (args, str); 125 | int count = _vsnprintf( log->data + log->size, log->capacity - log->size, str, args ); 126 | va_end (args); 127 | if( count >= (int) ( log->capacity - log->size ) ) 128 | { 129 | alloc_data( log, count ); 130 | va_start (args, str); 131 | count = _vsnprintf( log->data + log->size, log->capacity - log->size, str, args ); 132 | va_end (args); 133 | } 134 | log->size += count; 135 | log_commit_pending( log ); 136 | } 137 | 138 | 139 | void log_print_pending( log_t* const log, char const* const str, ... ) 140 | { 141 | if( log->muted ) return; 142 | 143 | if( log->pending_point > log->size ) log->pending_point = log->size; 144 | 145 | va_list args; 146 | va_start (args, str); 147 | int count = _vsnprintf( log->data + log->size, log->capacity - log->size, str, args ); 148 | va_end (args); 149 | if( count >= (int) ( log->capacity - log->size ) ) 150 | { 151 | alloc_data( log, count ); 152 | va_start (args, str); 153 | count = _vsnprintf( log->data + log->size, log->capacity - log->size, str, args ); 154 | va_end (args); 155 | } 156 | log->size += count; 157 | } 158 | 159 | 160 | void log_discard_pending( log_t* const log ) 161 | { 162 | if( log->muted ) return; 163 | 164 | if( log->pending_point != ~(size_t) 0 ) 165 | log->size = log->pending_point; 166 | 167 | log->pending_point = ~(size_t) 0; 168 | } 169 | 170 | 171 | void log_commit_pending( log_t* const log ) 172 | { 173 | log->pending_point = ~(size_t) 0; 174 | 175 | if( log->muted ) return; 176 | 177 | if( log->data ) 178 | { 179 | fprintf( stdout, "%s", log->data ); 180 | if( log->fp ) 181 | { 182 | fprintf( log->fp, "%s", log->data ); 183 | } 184 | log->data[ 0 ] = 0; 185 | } 186 | fflush( stdout ); 187 | if( log->fp ) 188 | fflush( log->fp ); 189 | log->size = 0; 190 | } 191 | 192 | 193 | int log_mute( log_t* log ) 194 | { 195 | ++log->muted; 196 | return log->muted; 197 | } 198 | 199 | 200 | int log_unmute( log_t* log ) 201 | { 202 | --log->muted; 203 | return log->muted; 204 | } 205 | 206 | 207 | #endif /* LOG_IMPLEMENTATION */ 208 | 209 | 210 | /* 211 | ------------------------------------------------------------------------------ 212 | 213 | This software is available under 2 licenses - you may choose the one you like. 214 | 215 | ------------------------------------------------------------------------------ 216 | 217 | ALTERNATIVE A - MIT License 218 | 219 | Copyright (c) 2015 Mattias Gustavsson 220 | 221 | Permission is hereby granted, free of charge, to any person obtaining a copy of 222 | this software and associated documentation files (the "Software"), to deal in 223 | the Software without restriction, including without limitation the rights to 224 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 225 | of the Software, and to permit persons to whom the Software is furnished to do 226 | so, subject to the following conditions: 227 | 228 | The above copyright notice and this permission notice shall be included in all 229 | copies or substantial portions of the Software. 230 | 231 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 232 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 233 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 234 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 235 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 236 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 237 | SOFTWARE. 238 | 239 | ------------------------------------------------------------------------------ 240 | 241 | ALTERNATIVE B - Public Domain (www.unlicense.org) 242 | 243 | This is free and unencumbered software released into the public domain. 244 | 245 | Anyone is free to copy, modify, publish, use, compile, sell, or distribute this 246 | software, either in source code form or as a compiled binary, for any purpose, 247 | commercial or non-commercial, and by any means. 248 | 249 | In jurisdictions that recognize copyright laws, the author or authors of this 250 | software dedicate any and all copyright interest in the software to the public 251 | domain. We make this dedication for the benefit of the public at large and to 252 | the detriment of our heirs and successors. We intend this dedication to be an 253 | overt act of relinquishment in perpetuity of all present and future rights to 254 | this software under copyright law. 255 | 256 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 257 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 258 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 259 | AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 260 | ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 261 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 262 | 263 | ------------------------------------------------------------------------------ 264 | */ 265 | -------------------------------------------------------------------------------- /source/pixie/math_util.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | ------------------------------------------------------------------------------ 3 | Licensing information can be found at the end of the file. 4 | ------------------------------------------------------------------------------ 5 | 6 | math_util.hpp - v0.1 - math helper functions for C++. 7 | 8 | Do this: 9 | #define MATH_UTIL_IMPLEMENTATION 10 | before you include this file in *one* C++ file to create the implementation. 11 | */ 12 | 13 | #ifndef math_util_hpp 14 | #define math_util_hpp 15 | 16 | namespace math_util { 17 | 18 | #ifdef max 19 | #undef max 20 | #endif 21 | 22 | #ifdef min 23 | #undef min 24 | #endif 25 | 26 | template< typename T, typename T1, typename T2 > T max( T1 const& a, T2 const& b ); 27 | template< typename T, typename T1, typename T2 > T min( T1 const& a, T2 const& b ); 28 | template< typename T, typename T1, typename T2, typename T3 > T clamp( T1 const& x, T2 const& min, T3 const& max ); 29 | template< typename T > void swap( T& a, T& b ); 30 | 31 | float const PI = 3.1415926535897932384626433832795f; 32 | float const TWO_PI = 6.2831853071795864769252867665590f; 33 | 34 | float to_radians( float degrees ); 35 | float to_degrees( float radians ); 36 | float angle_diff( float a, float b ); 37 | float angle_lerp( float a, float b, float t ); 38 | float lerp( float a, float b, float t ); 39 | 40 | unsigned int pow2_ceil( unsigned int x ); 41 | 42 | int fast_round( float x ); 43 | 44 | short float_to_half( float f ); 45 | float half_to_float( short hf ); 46 | 47 | } /* namespace math_util */ 48 | 49 | 50 | // Unrolled macro version of pow2_ceil, which rounds a constant (at compile time) up to its nearest power-of-two value. 51 | #define POW2_CEIL( x ) ( (((((((x) - 1) | ( ((x) - 1) >> 1 )) | ( (((x) - 1) | ( ((x) - 1) >> 1 )) >> 2 )) \ 52 | | ( ((((x) - 1) | ( ((x) - 1) >> 1 )) | ( (((x) - 1) | ( ((x) - 1) >> 1 )) >> 2 )) >> 4 )) | ( (((((x) - 1) \ 53 | | ( ((x) - 1) >> 1 )) | ( (((x) - 1) | ( ((x) - 1) >> 1 )) >> 2 )) | ( ((((x) - 1) | ( ((x) - 1) >> 1 )) \ 54 | | ( (((x) - 1) | ( ((x) - 1) >> 1 )) >> 2 )) >> 4 )) >> 8 )) | ( ((((((x) - 1) | ( ((x) - 1) >> 1 )) \ 55 | | ( (((x) - 1) | ( ((x) - 1) >> 1 )) >> 2 )) | ( ((((x) - 1) | ( ((x) - 1) >> 1 )) | ( (((x) - 1) \ 56 | | ( ((x) - 1) >> 1 )) >> 2 )) >> 4 )) | ( (((((x) - 1) | ( ((x) - 1) >> 1 )) | ( (((x) - 1) \ 57 | | ( ((x) - 1) >> 1 )) >> 2 )) | ( ((((x) - 1) | ( ((x) - 1) >> 1 )) | ( (((x) - 1) \ 58 | | ( ((x) - 1) >> 1 )) >> 2 )) >> 4 )) >> 8 )) >> 16 )) + 1 ) 59 | 60 | 61 | #endif /* math_util_hpp */ 62 | 63 | 64 | /* 65 | ---------------------- 66 | IMPLEMENTATION 67 | ---------------------- 68 | */ 69 | 70 | #ifndef math_util_impl 71 | #define math_util_impl 72 | 73 | namespace math_util { 74 | 75 | 76 | template< typename T, typename T1, typename T2 > T max( T1 const& a, T2 const& b ) 77 | { 78 | return T( a ) > T( b ) ? T( a ) : T( b ); 79 | } 80 | 81 | 82 | template< typename T, typename T1, typename T2 > T min( T1 const& a, T2 const& b ) 83 | { 84 | return T( a ) < T( b ) ? T( a ) : T( b ); 85 | } 86 | 87 | 88 | template< typename T, typename T1, typename T2, typename T3 > T clamp( T1 const& x, T2 const& min, T3 const& max ) 89 | { 90 | return max( min( x, max ), min ); 91 | } 92 | 93 | 94 | template< typename T > void swap( T& a, T& b ) 95 | { 96 | T t = a; 97 | a = b; 98 | b = t; 99 | } 100 | 101 | 102 | } /* namespace math_util */ 103 | 104 | #endif /* math_util_impl */ 105 | 106 | 107 | #ifdef MATH_UTIL_IMPLEMENTATION 108 | #undef MATH_UTIL_IMPLEMENTATION 109 | 110 | #define _CRT_NONSTDC_NO_DEPRECATE 111 | #define _CRT_SECURE_NO_WARNINGS 112 | #pragma warning( push ) 113 | #pragma warning( disable: 4668 ) // 'symbol' is not defined as a preprocessor macro, replacing with '0' for 'directives' 114 | #include 115 | #pragma warning( pop ) 116 | 117 | #ifndef MATH_UTIL_ASSERT 118 | #undef _CRT_NONSTDC_NO_DEPRECATE 119 | #define _CRT_NONSTDC_NO_DEPRECATE 120 | #undef _CRT_SECURE_NO_WARNINGS 121 | #define _CRT_SECURE_NO_WARNINGS 122 | #include 123 | #define MATH_UTIL_ASSERT( expression, message ) assert( ( expression ) && ( message ) ) 124 | #endif 125 | 126 | #if ( defined( _M_IX86_FP ) && ( _M_IX86_FP > 0 ) ) || defined( _M_X64 ) 127 | #define _CRT_NONSTDC_NO_DEPRECATE 128 | #define _CRT_SECURE_NO_WARNINGS 129 | #pragma warning( push ) 130 | #pragma warning( disable: 4548 ) // expression before comma has no effect; expected expression with side-effect 131 | #include 132 | #pragma warning( pop ) 133 | #endif 134 | 135 | namespace math_util { 136 | 137 | float to_radians( float const degrees ) 138 | { 139 | return ( degrees * PI ) / 180.0f; 140 | } 141 | 142 | 143 | float to_degrees( float const radians ) 144 | { 145 | return ( radians * 180.0f ) / PI; 146 | } 147 | 148 | 149 | float angle_diff( float const a, float const b ) 150 | { 151 | float d = fmodf( b - a, TWO_PI ); 152 | return fmodf( 2.0f * d, TWO_PI ) - d; 153 | } 154 | 155 | 156 | float angle_lerp( float const a, float const b, float const t ) 157 | { 158 | return a + angle_diff( b, a ) * t; 159 | } 160 | 161 | 162 | float lerp( float const a, float const b, float const t ) 163 | { 164 | return a + ( a - b ) * t; 165 | } 166 | 167 | 168 | unsigned int pow2_ceil( unsigned int x ) 169 | { 170 | --x; 171 | x |= x >> 1; 172 | x |= x >> 2; 173 | x |= x >> 4; 174 | x |= x >> 8; 175 | x |= x >> 16; 176 | ++x; 177 | x += ( x == 0 ); 178 | return x; 179 | } 180 | 181 | 182 | int fast_round( float x ) 183 | { 184 | #if ( defined( _M_IX86_FP ) && ( _M_IX86_FP > 0 ) ) || defined( _M_X64 ) 185 | __m128 m; 186 | m.m128_f32[ 0 ] = x; 187 | return _mm_cvtss_si32( m ); 188 | #else 189 | MATH_UTIL_ASSERT( fabs( x )<=0x003fffff, "Only 23 bit values handled" ); 190 | float f = x + ( 3 << 22 ); 191 | int i = *(int*)&f; 192 | return ( i & 0x007fffff ) - 0x00400000; 193 | #endif 194 | } 195 | 196 | 197 | short float_to_half( float f ) 198 | { 199 | typedef unsigned short hfloat; 200 | 201 | // max exponent value in single precision that will be converted 202 | // to Inf or Nan when stored as a half-float 203 | const unsigned int HALF_FLOAT_MAX_BIASED_EXP_AS_SINGLE_FP_EXP = 0x47800000; 204 | const unsigned int HALF_FLOAT_MAX_BIASED_EXP = (0x1F << 10); 205 | 206 | // -15 stored using a single precision bias of 127 207 | const unsigned int HALF_FLOAT_MIN_BIASED_EXP_AS_SINGLE_FP_EXP = 0x38000000; 208 | 209 | // 255 is the max exponent biased value 210 | const unsigned int FLOAT_MAX_BIASED_EXP = (0xFF << 23); 211 | 212 | unsigned int x = *(unsigned int *)(&f); 213 | unsigned int sign = (unsigned short)(x >> 31); 214 | unsigned int mantissa; 215 | unsigned int exp; 216 | hfloat hf; 217 | 218 | // get mantissa 219 | mantissa = x & ((1 << 23) - 1); 220 | // get exponent bits 221 | exp = x & FLOAT_MAX_BIASED_EXP; 222 | if (exp >= HALF_FLOAT_MAX_BIASED_EXP_AS_SINGLE_FP_EXP) 223 | { 224 | // check if the original single precision float number is a NaN 225 | if (mantissa && (exp == FLOAT_MAX_BIASED_EXP)) 226 | { 227 | // we have a single precision NaN 228 | mantissa = (1 << 23) - 1; 229 | } 230 | else 231 | { 232 | // 16-bit half-float representation stores number as Inf 233 | mantissa = 0; 234 | } 235 | hf = (hfloat)( (((hfloat)sign) << 15) | (hfloat)(HALF_FLOAT_MAX_BIASED_EXP) | (hfloat)(mantissa >> 13) ); 236 | } 237 | // check if exponent is <= -15 238 | else if (exp <= HALF_FLOAT_MIN_BIASED_EXP_AS_SINGLE_FP_EXP) 239 | { 240 | 241 | // store a denorm half-float value or zero 242 | exp = (HALF_FLOAT_MIN_BIASED_EXP_AS_SINGLE_FP_EXP - exp) >> 23; 243 | mantissa >>= (14 + exp); 244 | 245 | hf = (hfloat)( (((hfloat)sign) << 15) | (hfloat)(mantissa) ); 246 | } 247 | else 248 | { 249 | hf = (hfloat)( (((hfloat)sign) << 15) | (hfloat)((exp - HALF_FLOAT_MIN_BIASED_EXP_AS_SINGLE_FP_EXP) >> 13) | (hfloat)(mantissa >> 13) ); 250 | } 251 | 252 | return (short) hf; 253 | } 254 | 255 | 256 | float half_to_float( short hf ) 257 | { 258 | typedef unsigned short hfloat; 259 | 260 | // -15 stored using a single precision bias of 127 261 | const unsigned int HALF_FLOAT_MIN_BIASED_EXP_AS_SINGLE_FP_EXP = 0x38000000; 262 | 263 | // 255 is the max exponent biased value 264 | const unsigned int FLOAT_MAX_BIASED_EXP = (0xFF << 23); 265 | 266 | const unsigned int HALF_FLOAT_MAX_BIASED_EXP = (0x1F << 10); 267 | 268 | unsigned int sign = (unsigned int)(((hfloat)hf) >> 15); 269 | unsigned int mantissa = (unsigned int)(((hfloat)hf) & ((1 << 10) - 1)); 270 | unsigned int exp = (unsigned int)(((hfloat)hf) & HALF_FLOAT_MAX_BIASED_EXP); 271 | unsigned int f; 272 | 273 | if (exp == HALF_FLOAT_MAX_BIASED_EXP) 274 | { 275 | // we have a half-float NaN or Inf 276 | // half-float NaNs will be converted to a single precision NaN 277 | // half-float Infs will be converted to a single precision Inf 278 | exp = FLOAT_MAX_BIASED_EXP; 279 | if (mantissa) 280 | mantissa = (1 << 23) - 1; // set all bits to indicate a NaN 281 | } 282 | else if (exp == 0x0) 283 | { 284 | // convert half-float zero/denorm to single precision value 285 | if (mantissa) 286 | { 287 | mantissa <<= 1; 288 | exp = HALF_FLOAT_MIN_BIASED_EXP_AS_SINGLE_FP_EXP; 289 | // check for leading 1 in denorm mantissa 290 | while ((mantissa & (1 << 10)) == 0) 291 | { 292 | // for every leading 0, decrement single precision exponent by 1 293 | // and shift half-float mantissa value to the left 294 | mantissa <<= 1; 295 | exp -= (1 << 23); 296 | } 297 | // clamp the mantissa to 10-bits 298 | mantissa &= ((1 << 10) - 1); 299 | // shift left to generate single-precision mantissa of 23-bits 300 | mantissa <<= 13; 301 | } 302 | } 303 | else 304 | { 305 | // shift left to generate single-precision mantissa of 23-bits 306 | mantissa <<= 13; 307 | // generate single precision biased exponent value 308 | exp = (exp << 13) + HALF_FLOAT_MIN_BIASED_EXP_AS_SINGLE_FP_EXP; 309 | } 310 | 311 | f = (sign << 31) | exp | mantissa; 312 | return *((float *)&f); 313 | } 314 | 315 | } /* namespace math_util */ 316 | 317 | #endif /* MATH_UTIL_IMPLEMENTATION */ 318 | 319 | /* 320 | ------------------------------------------------------------------------------ 321 | 322 | This software is available under 2 licenses - you may choose the one you like. 323 | 324 | ------------------------------------------------------------------------------ 325 | 326 | ALTERNATIVE A - MIT License 327 | 328 | Copyright (c) 2015 Mattias Gustavsson 329 | 330 | Permission is hereby granted, free of charge, to any person obtaining a copy of 331 | this software and associated documentation files (the "Software"), to deal in 332 | the Software without restriction, including without limitation the rights to 333 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 334 | of the Software, and to permit persons to whom the Software is furnished to do 335 | so, subject to the following conditions: 336 | 337 | The above copyright notice and this permission notice shall be included in all 338 | copies or substantial portions of the Software. 339 | 340 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 341 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 342 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 343 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 344 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 345 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 346 | SOFTWARE. 347 | 348 | ------------------------------------------------------------------------------ 349 | 350 | ALTERNATIVE B - Public Domain (www.unlicense.org) 351 | 352 | This is free and unencumbered software released into the public domain. 353 | 354 | Anyone is free to copy, modify, publish, use, compile, sell, or distribute this 355 | software, either in source code form or as a compiled binary, for any purpose, 356 | commercial or non-commercial, and by any means. 357 | 358 | In jurisdictions that recognize copyright laws, the author or authors of this 359 | software dedicate any and all copyright interest in the software to the public 360 | domain. We make this dedication for the benefit of the public at large and to 361 | the detriment of our heirs and successors. We intend this dedication to be an 362 | overt act of relinquishment in perpetuity of all present and future rights to 363 | this software under copyright law. 364 | 365 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 366 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 367 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 368 | AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 369 | ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 370 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 371 | 372 | ------------------------------------------------------------------------------ 373 | */ 374 | -------------------------------------------------------------------------------- /source/pixie/mempool.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | ------------------------------------------------------------------------------ 3 | Licensing information can be found at the end of the file. 4 | ------------------------------------------------------------------------------ 5 | 6 | mempool.hpp - v0.1 - Fixed-size memory blocks allocator for C/C++. 7 | 8 | Do this: 9 | #define MEMPOOL_IMPLEMENTATION 10 | before you include this file in *one* C/C++ file to create the implementation. 11 | */ 12 | 13 | #ifndef mempool_hpp 14 | #define mempool_hpp 15 | 16 | namespace mempool_ns { 17 | 18 | template< typename T > struct mempool final 19 | { 20 | mempool( int initial_capacity = 256, void* memctx = 0 ); 21 | ~mempool(); 22 | 23 | inline T* create(); 24 | template< typename P0 > T* create( P0 p0 ); 25 | template< typename P0, typename P1 > T* create( P0 p0, P1 p1 ); 26 | template< typename P0, typename P1, typename P2 > T* create( P0 p0, P1 p1, P2 p2 ); 27 | template< typename P0, typename P1, typename P2, typename P3 > T* create( P0 p0, P1 p1, P2 p2, P3 p3 ); 28 | template< typename P0, typename P1, typename P2, typename P3, typename P4 > T* create( P0 p0, P1 p1, P2 p2, P3 p3, P4 p4 ); 29 | template< typename P0, typename P1, typename P2, typename P3, typename P4, typename P5 > T* create( P0 p0, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5 ); 30 | template< typename P0, typename P1, typename P2, typename P3, typename P4, typename P5, typename P6 > T* create( P0 p0, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6 ); 31 | template< typename P0, typename P1, typename P2, typename P3, typename P4, typename P5, typename P6, typename P7 > T* create( P0 p0, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7 ); 32 | template< typename P0, typename P1, typename P2, typename P3, typename P4, typename P5, typename P6, typename P7, typename P8 > T* create( P0 p0, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7, P8 p8 ); 33 | template< typename P0, typename P1, typename P2, typename P3, typename P4, typename P5, typename P6, typename P7, typename P8, typename P9 > T* create( P0 p0, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7, P8 p8, P9 p9 ); 34 | void destroy( T* ); 35 | 36 | void clear(); 37 | bool contains( T* item ); 38 | 39 | T* allocate(); 40 | void deallocate( T* ptr ); 41 | 42 | private: 43 | void* memctx_; 44 | int next_capacity_; 45 | struct item_t final 46 | { 47 | T item; 48 | mempool* owner; 49 | }; 50 | struct block_t final 51 | { 52 | item_t* items; 53 | int items_capacity; 54 | int items_count; 55 | int freelist; 56 | }; 57 | block_t* blocks_; 58 | int blocks_capacity_; 59 | int blocks_count_; 60 | }; 61 | 62 | } /* namespace mempool_ns */ 63 | 64 | #endif /* mempool_hpp */ 65 | 66 | 67 | /* 68 | ---------------------- 69 | IMPLEMENTATION 70 | ---------------------- 71 | */ 72 | 73 | #ifndef mempool_impl 74 | #define mempool_impl 75 | 76 | // placement new 77 | #if !defined( PLACEMENT_NEW_OPERATOR_DEFINED ) && !defined( __PLACEMENT_NEW_INLINE ) 78 | #define PLACEMENT_NEW_OPERATOR_DEFINED 79 | #define __PLACEMENT_NEW_INLINE 80 | inline void* operator new( size_t, void* p ) throw() { return p; } inline void operator delete(void*, void*) throw() { } 81 | #endif 82 | 83 | #ifndef MEMPOOL_ASSERT 84 | #define _CRT_NONSTDC_NO_DEPRECATE 85 | #define _CRT_SECURE_NO_WARNINGS 86 | #include 87 | #define MEMPOOL_ASSERT( expression, message ) assert( ( expression ) && ( message ) ) 88 | #endif 89 | 90 | namespace mempool_ns { namespace internal { 91 | 92 | void* mempool_alloc( void* memctx, size_t size ); 93 | void mempool_free( void* memctx, void* p ); 94 | void* mempool_memcpy( void* destination, void const* source, size_t count ); 95 | 96 | } /* namespace internal */ } /* namespace mempool_ns */ 97 | 98 | 99 | template< typename T > mempool_ns::mempool::mempool( int initial_capacity, void* memctx ): 100 | memctx_( memctx ), 101 | next_capacity_( initial_capacity * 2 ), 102 | blocks_count_( 0 ), 103 | blocks_capacity_( 64 ) 104 | { 105 | blocks_ = (block_t*) internal::mempool_alloc( memctx, sizeof( block_t ) * blocks_capacity_ ); 106 | block_t* initial_block = &blocks_[ blocks_count_++ ]; 107 | initial_block->freelist = -1; 108 | initial_block->items_count = 0; 109 | initial_block->items_capacity = initial_capacity; 110 | initial_block->items = (item_t*) internal::mempool_alloc( memctx_, sizeof( item_t ) * initial_block->items_capacity ); 111 | memset( initial_block->items, 0, sizeof( item_t ) * initial_block->items_capacity ); 112 | } 113 | 114 | 115 | template< typename T > 116 | mempool_ns::mempool::~mempool() 117 | { 118 | for( int i = 0; i < blocks_count_; ++i ) 119 | { 120 | block_t* block = &blocks_[ i ]; 121 | for( int j = 0; j < block->items_count; ++j ) 122 | { 123 | if( block->items[ j ].owner ) block->items[ j ].item.~T(); 124 | } 125 | internal::mempool_free( memctx_, block->items ); 126 | } 127 | internal::mempool_free( memctx_, blocks_ ); 128 | } 129 | 130 | 131 | template< typename T > 132 | bool mempool_ns::mempool::contains( T* item ) 133 | { 134 | uintptr_t item_ptr = (uintptr_t) item; 135 | for( int i = 0; i < blocks_count_; ++i ) 136 | { 137 | block_t* block = &blocks_[ i ]; 138 | uintptr_t block_begin = (uintptr_t) block->items; 139 | uintptr_t block_end = block_begin + block->items_capacity * sizeof( item_t ); 140 | if( item_ptr >= block_begin && item_ptr < block_end ) 141 | return true; 142 | } 143 | 144 | return false; 145 | } 146 | 147 | 148 | template< typename T > 149 | T* mempool_ns::mempool::allocate() 150 | { 151 | for( int i = blocks_count_ - 1; i >= 0; --i ) 152 | { 153 | block_t* block = &blocks_[ i ]; 154 | if( block->freelist >= 0 ) 155 | { 156 | int item_index = block->freelist; 157 | block->freelist = *( (int*) &block->items[ item_index ] ); 158 | block->items[ item_index ].owner = this; 159 | return &block->items[ item_index ].item; 160 | } 161 | else if( block->items_count < block->items_capacity ) 162 | { 163 | int item_index = block->items_count++; 164 | block->items[ item_index ].owner = this; 165 | return &block->items[ item_index ].item; 166 | } 167 | } 168 | 169 | if( blocks_count_ >= blocks_capacity_ ) 170 | { 171 | blocks_capacity_ *= 2; 172 | block_t* new_blocks = (block_t*) internal::mempool_alloc( memctx_, sizeof( block_t ) * blocks_capacity_ ); 173 | internal::mempool_memcpy( new_blocks, blocks_, sizeof( block_t ) * blocks_count_ ); 174 | internal::mempool_free( memctx_, blocks_ ); 175 | blocks_ = new_blocks; 176 | } 177 | 178 | block_t* block = &blocks_[ blocks_count_++ ]; 179 | block->freelist = -1; 180 | block->items_count = 1; 181 | block->items_capacity = next_capacity_; 182 | block->items = (item_t*) internal::mempool_alloc( memctx_, sizeof( item_t ) * block->items_capacity ); 183 | memset( block->items, 0, sizeof( item_t ) * block->items_capacity ); 184 | next_capacity_ *= 2; 185 | block->items[ 0 ].owner = this; 186 | return &block->items[ 0 ].item; 187 | } 188 | 189 | 190 | template< typename T > 191 | void mempool_ns::mempool::deallocate( T* item ) 192 | { 193 | uintptr_t item_ptr = (uintptr_t) item; 194 | for( int i = 0; i < blocks_count_; ++i ) 195 | { 196 | block_t* block = &blocks_[ i ]; 197 | uintptr_t block_begin = (uintptr_t) block->items; 198 | uintptr_t block_end = block_begin + block->items_capacity * sizeof( item_t ); 199 | if( item_ptr >= block_begin && item_ptr < block_end ) 200 | { 201 | int item_index = (int)( ( item_ptr - block_begin ) / sizeof( item_t ) ); 202 | MEMPOOL_ASSERT( block->items[ item_index ].owner, "Attempt to destroy an item which is not currently allocated." ); 203 | if( block->items[ item_index ].owner ) 204 | { 205 | block->items[ item_index ].owner = 0; 206 | *( (int*) &block->items[ item_index ] ) = block->freelist; 207 | block->freelist = item_index; 208 | } 209 | return; 210 | } 211 | } 212 | MEMPOOL_ASSERT( false, "Attempt to destroy an item not allocated from this mempool." ); 213 | } 214 | 215 | 216 | template< typename T > 217 | void mempool_ns::mempool::clear() 218 | { 219 | for( int i = 0; i < blocks_count_; ++i ) 220 | { 221 | block_t* block = &blocks_[ i ]; 222 | for( int j = 0; j < block->items_count; ++j ) 223 | { 224 | if( block->items[ j ].owner ) 225 | { 226 | block->items[ j ].item.~T(); 227 | block->items[ j ].owner = 0; 228 | } 229 | } 230 | block->freelist = -1; 231 | block->items_count = 0; 232 | } 233 | } 234 | 235 | 236 | template< typename T > 237 | inline T* mempool_ns::mempool::create() 238 | { 239 | #pragma warning( push ) 240 | #pragma warning( disable: 4619 ) // there is no warning number '4345' 241 | #pragma warning( disable: 4345 ) // behavior change: an object of POD type constructed with an initializer of the form () will be default-initialized 242 | return new ( allocate() ) T(); 243 | #pragma warning( pop ) 244 | } 245 | 246 | 247 | template< typename T > template< typename P0 > 248 | T* mempool_ns::mempool::create( P0 p0 ) 249 | { 250 | return new ( allocate() ) T( p0 ); 251 | } 252 | 253 | 254 | template< typename T > template< typename P0, typename P1 > 255 | T* mempool_ns::mempool::create( P0 p0, P1 p1 ) 256 | { 257 | return new ( allocate() ) T( p0, p1 ); 258 | } 259 | 260 | 261 | template< typename T > template< typename P0, typename P1, typename P2 > 262 | T* mempool_ns::mempool::create( P0 p0, P1 p1, P2 p2 ) 263 | { 264 | return new ( allocate() ) T( p0, p1, p2 ); 265 | } 266 | 267 | 268 | template< typename T > template< typename P0, typename P1, typename P2, typename P3 > 269 | T* mempool_ns::mempool::create( P0 p0, P1 p1, P2 p2, P3 p3 ) 270 | { 271 | return new ( allocate() ) T( p0, p1, p2, p3 ); 272 | } 273 | 274 | 275 | template< typename T > template< typename P0, typename P1, typename P2, typename P3, typename P4 > 276 | T* mempool_ns::mempool::create( P0 p0, P1 p1, P2 p2, P3 p3, P4 p4 ) 277 | { 278 | return new ( allocate() ) T( p0, p1, p2, p3, p4 ); 279 | } 280 | 281 | 282 | template< typename T > template< typename P0, typename P1, typename P2, typename P3, typename P4, typename P5 > 283 | T* mempool_ns::mempool::create( P0 p0, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5 ) 284 | { 285 | return new ( allocate() ) T( p0, p1, p2, p3, p4, p5 ); 286 | } 287 | 288 | 289 | template< typename T > template< typename P0, typename P1, typename P2, typename P3, typename P4, typename P5, typename P6 > 290 | T* mempool_ns::mempool::create( P0 p0, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6 ) 291 | { 292 | return new ( allocate() ) T( p0, p1, p2, p3, p4, p5, p6 ); 293 | } 294 | 295 | 296 | template< typename T > template< typename P0, typename P1, typename P2, typename P3, typename P4, typename P5, typename P6, typename P7 > 297 | T* mempool_ns::mempool::create( P0 p0, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7 ) 298 | { 299 | return new ( allocate() ) T( p0, p1, p2, p3, p4, p5, p6, p7 ); 300 | } 301 | 302 | 303 | template< typename T > template< typename P0, typename P1, typename P2, typename P3, typename P4, typename P5, typename P6, typename P7, typename P8 > 304 | T* mempool_ns::mempool::create( P0 p0, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7, P8 p8 ) 305 | { 306 | return new ( allocate() ) T( p0, p1, p2, p3, p4, p5, p6, p7, p8 ); 307 | } 308 | 309 | 310 | template< typename T > template< typename P0, typename P1, typename P2, typename P3, typename P4, typename P5, typename P6, typename P7, typename P8, typename P9 > 311 | T* mempool_ns::mempool::create( P0 p0, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7, P8 p8, P9 p9 ) 312 | { 313 | return new ( allocate() ) T( p0, p1, p2, p3, p4, p5, p6, p7, p8, p9 ); 314 | } 315 | 316 | 317 | template< typename T > 318 | void mempool_ns::mempool::destroy( T* item ) 319 | { 320 | uintptr_t item_ptr = (uintptr_t) item; 321 | for( int i = 0; i < blocks_count_; ++i ) 322 | { 323 | block_t* block = &blocks_[ i ]; 324 | uintptr_t block_begin = (uintptr_t) block->items; 325 | uintptr_t block_end = block_begin + block->items_capacity * sizeof( item_t ); 326 | if( item_ptr >= block_begin && item_ptr < block_end ) 327 | { 328 | int item_index = (int)( ( item_ptr - block_begin ) / sizeof( item_t ) ); 329 | MEMPOOL_ASSERT( block->items[ item_index ].owner, "Attempt to destroy an item which is not currently allocated." ); 330 | if( block->items[ item_index ].owner ) 331 | { 332 | block->items[ item_index ].item.~T(); 333 | block->items[ item_index ].owner = 0; 334 | *( (int*) &block->items[ item_index ] ) = block->freelist; 335 | block->freelist = item_index; 336 | } 337 | return; 338 | } 339 | } 340 | MEMPOOL_ASSERT( false, "Attempt to destroy an item not allocated from this mempool." ); 341 | } 342 | 343 | #endif /* mempool_impl */ 344 | 345 | #ifdef MEMPOOL_IMPLEMENTATION 346 | #undef MEMPOOL_IMPLEMENTATION 347 | 348 | #ifndef MEMPOOL_MALLOC 349 | #define _CRT_NONSTDC_NO_DEPRECATE 350 | #define _CRT_SECURE_NO_WARNINGS 351 | #include 352 | #define MEMPOOL_MALLOC( ctx, size ) ( malloc( size ) ) 353 | #define MEMPOOL_FREE( ctx, ptr ) ( free( ptr ) ) 354 | #endif 355 | 356 | #ifndef MEMPOOL_MEMCPY 357 | #define _CRT_NONSTDC_NO_DEPRECATE 358 | #define _CRT_SECURE_NO_WARNINGS 359 | #include 360 | #define MEMPOOL_MEMCPY( dst, src, cnt ) ( memcpy( dst, src, cnt ) ) 361 | #endif 362 | 363 | void* mempool_ns::internal::mempool_alloc( void* memctx, size_t size ) 364 | { 365 | return MEMPOOL_MALLOC( memctx, size ); 366 | } 367 | 368 | 369 | void mempool_ns::internal::mempool_free( void* memctx, void* p ) 370 | { 371 | MEMPOOL_FREE( memctx, p ); 372 | } 373 | 374 | 375 | void* mempool_ns::internal::mempool_memcpy( void* destination, void const* source, size_t count ) 376 | { 377 | return MEMPOOL_MEMCPY( destination, source, count ); 378 | } 379 | 380 | #endif /* MEMPOOL_IMPLEMENTATION */ 381 | 382 | /* 383 | ------------------------------------------------------------------------------ 384 | 385 | This software is available under 2 licenses - you may choose the one you like. 386 | 387 | ------------------------------------------------------------------------------ 388 | 389 | ALTERNATIVE A - MIT License 390 | 391 | Copyright (c) 2017 Mattias Gustavsson 392 | 393 | Permission is hereby granted, free of charge, to any person obtaining a copy of 394 | this software and associated documentation files (the "Software"), to deal in 395 | the Software without restriction, including without limitation the rights to 396 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 397 | of the Software, and to permit persons to whom the Software is furnished to do 398 | so, subject to the following conditions: 399 | 400 | The above copyright notice and this permission notice shall be included in all 401 | copies or substantial portions of the Software. 402 | 403 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 404 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 405 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 406 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 407 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 408 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 409 | SOFTWARE. 410 | 411 | ------------------------------------------------------------------------------ 412 | 413 | ALTERNATIVE B - Public Domain (www.unlicense.org) 414 | 415 | This is free and unencumbered software released into the public domain. 416 | 417 | Anyone is free to copy, modify, publish, use, compile, sell, or distribute this 418 | software, either in source code form or as a compiled binary, for any purpose, 419 | commercial or non-commercial, and by any means. 420 | 421 | In jurisdictions that recognize copyright laws, the author or authors of this 422 | software dedicate any and all copyright interest in the software to the public 423 | domain. We make this dedication for the benefit of the public at large and to 424 | the detriment of our heirs and successors. We intend this dedication to be an 425 | overt act of relinquishment in perpetuity of all present and future rights to 426 | this software under copyright law. 427 | 428 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 429 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 430 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 431 | AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 432 | ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 433 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 434 | 435 | ------------------------------------------------------------------------------ 436 | */ 437 | -------------------------------------------------------------------------------- /source/pixie/objrepo.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | ------------------------------------------------------------------------------ 3 | Licensing information can be found at the end of the file. 4 | ------------------------------------------------------------------------------ 5 | 6 | objrepo.hpp - v0.1 - Generic object repositories with type-based lookup for C++. 7 | */ 8 | 9 | #ifndef objrepo_hpp 10 | #define objrepo_hpp 11 | 12 | namespace objrepo { 13 | 14 | namespace internal { struct object_t; struct list_t; } /* namespace internal */ 15 | 16 | struct object_repo 17 | { 18 | object_repo( void* memctx = 0 ); 19 | ~object_repo(); 20 | 21 | template< typename T > void add( T* object ); 22 | template< typename T > void remove( T* object ); 23 | template< typename T > T* get() const; 24 | 25 | private: 26 | void* memctx_; 27 | internal::object_t* objects_; 28 | int capacity_; 29 | int count_; 30 | }; 31 | 32 | 33 | struct object_list_repo 34 | { 35 | object_list_repo( void* memctx = 0 ); 36 | ~object_list_repo(); 37 | 38 | template< typename T > void add( T* object ); 39 | template< typename T > void remove( T* object ); 40 | 41 | template< typename T > struct list 42 | { 43 | T** objects; 44 | int count; 45 | }; 46 | template< typename T > list get() const; 47 | 48 | private: 49 | void* memctx_; 50 | internal::list_t* lists_; 51 | int capacity_; 52 | int count_; 53 | }; 54 | 55 | } /* namespace objrepo */ 56 | 57 | 58 | #endif /* objrepo_hpp */ 59 | 60 | /* 61 | ---------------------- 62 | IMPLEMENTATION 63 | ---------------------- 64 | */ 65 | 66 | #ifndef objrepo_impl 67 | #define objrepo_impl 68 | 69 | namespace objrepo { namespace internal { 70 | 71 | typedef void const* type_id_t; 72 | template< typename T > struct internal_type_id_helper { static int* id() { static int t; return &t; } }; 73 | template< typename T > type_id_t type_id() { return (type_id_t) &internal_type_id_helper::id; } 74 | template< typename T > type_id_t type_id( T const& ) { return (type_id_t) &internal_type_id_helper::id; } 75 | 76 | void objects_add( object_t** objects, int* capacity, int* count, void* object, type_id_t type, void* memctx ); 77 | void objects_remove( object_t** objects, int* count, void* object, type_id_t type ); 78 | void* objects_get( object_t const* objects, int count, type_id_t type ); 79 | 80 | void lists_add( list_t** lists, int* capacity, int* count, void* object, type_id_t type ); 81 | void lists_remove( list_t** lists, int* count, void* object, type_id_t type ); 82 | void** lists_get( int* result_count, list_t const* lists, int count, type_id_t type ); 83 | 84 | } /* namespace internal */ } /* namespace objrepo */ 85 | 86 | 87 | namespace objrepo { 88 | 89 | template< typename T > 90 | void object_repo::add( T* object ) 91 | { 92 | internal::objects_add( &objects_, &capacity_, &count_, object, internal::type_id(), memctx_ ); 93 | } 94 | 95 | 96 | template< typename T > 97 | void object_repo::remove( T* object ) 98 | { 99 | internal::objects_remove( &objects_, &count_, object, internal::type_id() ); 100 | } 101 | 102 | 103 | template< typename T > T* object_repo::get() const 104 | { 105 | return (T*) internal::objects_get( objects_, count_, internal::type_id() ); 106 | } 107 | 108 | 109 | template< typename T > 110 | void object_list_repo::add( T* object ) 111 | { 112 | internal::lists_add( &lists_, &capacity_, &count_, object, internal::type_id() ); 113 | } 114 | 115 | 116 | template< typename T > 117 | void object_list_repo::remove( T* object ) 118 | { 119 | internal::lists_remove( &lists_, &count_, object, internal::type_id() ); 120 | } 121 | 122 | 123 | template< typename T > 124 | object_list_repo::list object_list_repo::get() const 125 | { 126 | list list; 127 | list.objects = (T**) internal::lists_get( &list.count, lists_, count_, internal::type_id() ); 128 | return list; 129 | } 130 | 131 | } /* namespace objrepo */ 132 | 133 | #endif /* objrepo_impl */ 134 | 135 | 136 | #ifdef OBJREPO_IMPLEMENTATION 137 | #undef OBJREPO_IMPLEMENTATION 138 | 139 | #ifndef OBJREPO_MALLOC 140 | #include 141 | #define OBJREPO_MALLOC( ctx, size ) ( ::malloc( size ) ) 142 | #define OBJREPO_FREE( ctx, ptr ) ( ::free( ptr ) ) 143 | #endif 144 | 145 | #ifndef OBJREPO_ASSERT 146 | #undef _CRT_NONSTDC_NO_DEPRECATE 147 | #define _CRT_NONSTDC_NO_DEPRECATE 148 | #undef _CRT_SECURE_NO_WARNINGS 149 | #define _CRT_SECURE_NO_WARNINGS 150 | #include 151 | #define OBJREPO_ASSERT( expression, message ) assert( ( expression ) && ( message ) ) 152 | #endif 153 | 154 | namespace objrepo { namespace internal { 155 | 156 | struct object_t 157 | { 158 | internal::type_id_t type; 159 | void* instance; 160 | }; 161 | 162 | 163 | void objects_add( object_t** objects, int* capacity, int* count, void* object, type_id_t type, void* memctx ) 164 | { 165 | (void) memctx; 166 | OBJREPO_ASSERT( object, "Attempting to add a null-pointer object." ); 167 | OBJREPO_ASSERT( !objects_get( *objects, *count, type ), "An object of this type was already added." ); 168 | if( *count >= *capacity ) 169 | { 170 | *capacity *= 2; 171 | object_t* new_objects = (object_t*) OBJREPO_MALLOC( memctx, *capacity * sizeof( **objects ) ); 172 | memcpy( new_objects, *objects, *count * sizeof( **objects ) ); 173 | OBJREPO_FREE( memctx, *objects ); 174 | *objects = new_objects; 175 | } 176 | object_t* entry = &(*objects)[ (*count)++ ]; 177 | entry->type = type; 178 | entry->instance = object; 179 | } 180 | 181 | 182 | void objects_remove( object_t** objects, int* count, void* object, type_id_t type ) 183 | { 184 | (void) object; 185 | for( int i = 0; i < *count; ++i ) 186 | { 187 | object_t* entry = &(*objects)[ i ]; 188 | if( entry->type == type ) 189 | { 190 | OBJREPO_ASSERT( entry->instance == object, "A matching object type was found, but the instances don not match." ); 191 | (*objects)[ i ] = (*objects)[ --(*count) ]; 192 | return; 193 | } 194 | } 195 | OBJREPO_ASSERT( false, "Object of the specified type could not be found." ); 196 | } 197 | 198 | 199 | void* objects_get( object_t const* objects, int count, type_id_t type ) 200 | { 201 | for( int i = 0; i < count; ++i ) 202 | { 203 | object_t const* entry = &objects[ i ]; 204 | if( entry->type == type ) 205 | return entry->instance; 206 | } 207 | return 0; 208 | } 209 | 210 | 211 | struct list_t 212 | { 213 | internal::type_id_t type; 214 | void** instances; 215 | int capacity; 216 | int count; 217 | }; 218 | 219 | 220 | list_t* find_list( list_t* lists, int count, type_id_t type ) 221 | { 222 | for( int i = 0; i < count; ++i ) 223 | { 224 | list_t* entry = &lists[ i ]; 225 | if( entry->type == type ) 226 | return entry; 227 | } 228 | return 0; 229 | } 230 | 231 | 232 | void lists_add( list_t** lists, int* capacity, int* count, void* object, type_id_t type, void* memctx ) 233 | { 234 | (void) memctx; 235 | list_t* list = find_list( *lists, *count, type ); 236 | if( !list ) 237 | { 238 | if( *count >= *capacity ) 239 | { 240 | *capacity *= 2; 241 | list_t* new_lists = (list_t*) OBJREPO_MALLOC( memctx, *capacity * sizeof( **lists ) ); 242 | memcpy( new_lists, *lists, *count * sizeof( **lists ) ); 243 | OBJREPO_FREE( memctx, *lists ); 244 | *lists = new_lists; 245 | } 246 | list = &(*lists)[ (*count)++ ]; 247 | list->count = 0; 248 | list->capacity = 256; 249 | list->instances = (void**) OBJREPO_MALLOC( memctx, list->capacity * sizeof( *list->instances ) ); 250 | list->type = type; 251 | } 252 | 253 | if( list->count >= list->capacity ) 254 | { 255 | list->capacity *= 2; 256 | void** new_instances = (void**) OBJREPO_MALLOC( memctx, list->capacity * sizeof( *list->instances ) ); 257 | memcpy( new_instances, list->instances, list->count * sizeof( *list->instances ) ); 258 | OBJREPO_FREE( memctx, list->instances ); 259 | list->instances = new_instances; 260 | } 261 | 262 | list->instances[ list->count++ ] = object; 263 | } 264 | 265 | 266 | void lists_remove( list_t** lists, int* count, void* object, type_id_t type ) 267 | { 268 | list_t* list = find_list( *lists, *count, type ); 269 | OBJREPO_ASSERT( list, "No objects of this type has been added." ); 270 | for( int i = 0; i < list->count; ++i ) 271 | { 272 | void** entry = &list->instances[ i ]; 273 | if( entry == object ) 274 | { 275 | list->instances[ i ] = list->instances[ --list->count ]; 276 | return; 277 | } 278 | } 279 | OBJREPO_ASSERT( false, "Object could not be found." ); 280 | } 281 | 282 | 283 | void** lists_get( int* result_count, list_t const* lists, int count, type_id_t type ) 284 | { 285 | list_t* list = find_list( (list_t*) lists, count, type ); 286 | if( list ) 287 | { 288 | *result_count = list->count; 289 | return list->instances; 290 | } 291 | else 292 | { 293 | *result_count = 0; 294 | return 0; 295 | } 296 | } 297 | 298 | } /* namespace internal */ } /* namespace objrepo */ 299 | 300 | 301 | namespace objrepo { 302 | 303 | object_repo::object_repo( void* memctx ): 304 | memctx_( memctx ), 305 | capacity_( 256 ), 306 | count_( 0 ) 307 | { 308 | objects_ = (internal::object_t*) OBJREPO_MALLOC( memctx_, capacity_ * sizeof( *objects_ ) ); 309 | } 310 | 311 | 312 | object_repo::~object_repo() 313 | { 314 | OBJREPO_FREE( memctx_, objects_ ); 315 | } 316 | 317 | 318 | object_list_repo::object_list_repo( void* memctx ): 319 | memctx_( memctx ), 320 | capacity_( 256 ), 321 | count_( 0 ) 322 | { 323 | lists_ = (internal::list_t*) OBJREPO_MALLOC( memctx_, capacity_ * sizeof( *lists_ ) ); 324 | } 325 | 326 | 327 | object_list_repo::~object_list_repo() 328 | { 329 | for( int i = 0; i < count_; ++i ) 330 | OBJREPO_FREE( memctx_, lists_[ i ].instances ); 331 | 332 | OBJREPO_FREE( memctx_, lists_ ); 333 | } 334 | 335 | } /* namespace objrepo */ 336 | 337 | 338 | #endif /* OBJREPO_IMPLEMENTATION */ 339 | 340 | /* 341 | ------------------------------------------------------------------------------ 342 | 343 | This software is available under 2 licenses - you may choose the one you like. 344 | 345 | ------------------------------------------------------------------------------ 346 | 347 | ALTERNATIVE A - MIT License 348 | 349 | Copyright (c) 2015 Mattias Gustavsson 350 | 351 | Permission is hereby granted, free of charge, to any person obtaining a copy of 352 | this software and associated documentation files (the "Software"), to deal in 353 | the Software without restriction, including without limitation the rights to 354 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 355 | of the Software, and to permit persons to whom the Software is furnished to do 356 | so, subject to the following conditions: 357 | 358 | The above copyright notice and this permission notice shall be included in all 359 | copies or substantial portions of the Software. 360 | 361 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 362 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 363 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 364 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 365 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 366 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 367 | SOFTWARE. 368 | 369 | ------------------------------------------------------------------------------ 370 | 371 | ALTERNATIVE B - Public Domain (www.unlicense.org) 372 | 373 | This is free and unencumbered software released into the public domain. 374 | 375 | Anyone is free to copy, modify, publish, use, compile, sell, or distribute this 376 | software, either in source code form or as a compiled binary, for any purpose, 377 | commercial or non-commercial, and by any means. 378 | 379 | In jurisdictions that recognize copyright laws, the author or authors of this 380 | software dedicate any and all copyright interest in the software to the public 381 | domain. We make this dedication for the benefit of the public at large and to 382 | the detriment of our heirs and successors. We intend this dedication to be an 383 | overt act of relinquishment in perpetuity of all present and future rights to 384 | this software under copyright law. 385 | 386 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 387 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 388 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 389 | AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 390 | ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 391 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 392 | 393 | ------------------------------------------------------------------------------ 394 | */ 395 | -------------------------------------------------------------------------------- /source/pixie/pixelfont.h: -------------------------------------------------------------------------------- 1 | /* 2 | ------------------------------------------------------------------------------ 3 | Licensing information can be found at the end of the file. 4 | ------------------------------------------------------------------------------ 5 | 6 | pixelfont.h - v0.1 - 7 | 8 | Do this: 9 | #define PIXELFONT_IMPLEMENTATION 10 | before you include this file in *one* C/C++ file to create the implementation. 11 | */ 12 | 13 | #ifndef pixelfont_h 14 | #define pixelfont_h 15 | 16 | #ifndef PIXELFONT_I8 17 | #define PIXELFONT_I8 signed char 18 | #endif 19 | 20 | #ifndef PIXELFONT_U8 21 | #define PIXELFONT_U8 unsigned char 22 | #endif 23 | 24 | #ifndef PIXELFONT_U16 25 | #define PIXELFONT_U16 unsigned short 26 | #endif 27 | 28 | #ifndef PIXELFONT_U32 29 | #define PIXELFONT_U32 unsigned int 30 | #endif 31 | 32 | typedef struct pixelfont_t 33 | { 34 | PIXELFONT_U32 size_in_bytes; 35 | PIXELFONT_U8 height; 36 | PIXELFONT_U8 line_spacing; 37 | PIXELFONT_U8 baseline; 38 | PIXELFONT_U16 offsets[ 256 ]; 39 | PIXELFONT_U8 glyphs[ 1 ]; // "open" array - ok to access out of bounds (use size_in_bytes to determine the end) 40 | } pixelfont_t; 41 | 42 | 43 | typedef enum pixelfont_align_t 44 | { 45 | PIXELFONT_ALIGN_LEFT, 46 | PIXELFONT_ALIGN_RIGHT, 47 | PIXELFONT_ALIGN_CENTER, 48 | } pixelfont_align_t; 49 | 50 | 51 | typedef enum pixelfont_bold_t 52 | { 53 | PIXELFONT_BOLD_OFF, 54 | PIXELFONT_BOLD_ON, 55 | } pixelfont_bold_t; 56 | 57 | 58 | typedef enum pixelfont_italic_t 59 | { 60 | PIXELFONT_ITALIC_OFF, 61 | PIXELFONT_ITALIC_ON, 62 | } pixelfont_italic_t; 63 | 64 | 65 | typedef enum pixelfont_underline_t 66 | { 67 | PIXELFONT_UNDERLINE_OFF, 68 | PIXELFONT_UNDERLINE_ON, 69 | } pixelfont_underline_t; 70 | 71 | 72 | typedef struct pixelfont_bounds_t 73 | { 74 | int width; 75 | int height; 76 | } pixelfont_bounds_t; 77 | 78 | #endif /* pixelfont_h */ 79 | 80 | 81 | #ifndef PIXELFONT_COLOR 82 | #define PIXELFONT_COLOR PIXELFONT_U8 83 | #endif 84 | 85 | #ifndef PIXELFONT_FUNC_NAME 86 | #define PIXELFONT_FUNC_NAME pixelfont_blit 87 | #endif 88 | 89 | void PIXELFONT_FUNC_NAME( pixelfont_t const* font, int x, int y, char const* text, PIXELFONT_COLOR color, 90 | PIXELFONT_COLOR* target, int width, int height, pixelfont_align_t align, int wrap_width, int hspacing, 91 | int vspacing, int limit, pixelfont_bold_t bold, pixelfont_italic_t italic, pixelfont_underline_t underline, 92 | pixelfont_bounds_t* bounds ); 93 | 94 | 95 | /* 96 | ---------------------- 97 | IMPLEMENTATION 98 | ---------------------- 99 | */ 100 | 101 | #ifdef PIXELFONT_IMPLEMENTATION 102 | #undef PIXELFONT_IMPLEMENTATION 103 | 104 | #ifndef PIXELFONT_PIXEL_FUNC 105 | #define PIXELFONT_PIXEL_FUNC( dst, src ) *(dst) = (src); 106 | #endif 107 | 108 | void PIXELFONT_FUNC_NAME( pixelfont_t const* font, int x, int y, char const* text, PIXELFONT_COLOR color, 109 | PIXELFONT_COLOR* target, int width, int height, pixelfont_align_t align, int wrap_width, int hspacing, 110 | int vspacing, int limit, pixelfont_bold_t bold, pixelfont_italic_t italic, pixelfont_underline_t underline, 111 | pixelfont_bounds_t* bounds ) 112 | { 113 | int xp = x; 114 | int yp = y; 115 | int max_x = x; 116 | int last_x_on_line = xp; 117 | int count = 0; 118 | char const* str = text; 119 | while( *str ) 120 | { 121 | int line_char_count = 0; 122 | int line_width = 0; 123 | int last_space_char_count = 0; 124 | int last_space_width = 0; 125 | char const* tstr = str; 126 | while( *tstr != '\n' && *tstr != '\0' && ( wrap_width <= 0 || line_width <= wrap_width ) ) 127 | { 128 | if( *tstr <= ' ' ) 129 | { 130 | last_space_char_count = line_char_count; 131 | last_space_width = line_width; 132 | } 133 | PIXELFONT_U8 const* g = font->glyphs + font->offsets[ (int) *tstr ]; 134 | line_width += (PIXELFONT_I8) *g++; 135 | int w = *g++; 136 | g += font->height * w; 137 | line_width += (PIXELFONT_I8) *g++; 138 | line_width += hspacing + ( bold ? 1 : 0 ); 139 | ++tstr; 140 | int kern = *g++; 141 | for( int k = 0; k < kern; ++k ) 142 | if( *g++ == *tstr ) { line_width += (PIXELFONT_I8) *g++; break; } else ++g; 143 | ++line_char_count; 144 | } 145 | bool skip_space = false; 146 | if( wrap_width > 0 && line_width > wrap_width ) 147 | { 148 | line_char_count = last_space_char_count; 149 | line_width = last_space_width; 150 | skip_space = true; 151 | } 152 | 153 | if( wrap_width > 0 ) 154 | { 155 | if( align == PIXELFONT_ALIGN_RIGHT ) x += wrap_width - line_width; 156 | if( align == PIXELFONT_ALIGN_CENTER ) x += ( wrap_width - line_width ) / 2; 157 | } 158 | else 159 | { 160 | if( align == PIXELFONT_ALIGN_RIGHT ) x -= line_width; 161 | if( align == PIXELFONT_ALIGN_CENTER ) x -= line_width / 2; 162 | } 163 | 164 | for( int c = 0; c < line_char_count; ++c ) 165 | { 166 | PIXELFONT_U8 const* g = font->glyphs + font->offsets[ (int) *str ]; 167 | x += (PIXELFONT_I8) *g++; 168 | int w = *g++; 169 | int h = font->height; 170 | for( int iy = y; iy < y + h; ++iy ) 171 | { 172 | int xs = x + ( italic ? ( h - ( iy - y ) ) / 2 - 1 : 0 ); 173 | for( int ix = xs; ix < xs + w; ++ix ) 174 | { 175 | if( *g++ && target ) 176 | if( limit < 0 || count < limit ) 177 | if( ix >= 0 && iy >= 0 && ix < width && iy < height ) 178 | { 179 | last_x_on_line = ix >= last_x_on_line ? ix + ( bold ? 1 : 0 ) : last_x_on_line; 180 | PIXELFONT_PIXEL_FUNC( ( &target[ ix + iy * width ] ), color ); 181 | if( bold && ix + 1 < width ) 182 | PIXELFONT_PIXEL_FUNC( ( &target[ ix + 1 + iy * width ] ), color ); 183 | } 184 | } 185 | } 186 | 187 | x += (PIXELFONT_I8) *g++; 188 | x += hspacing + ( bold ? 1 : 0 ); 189 | ++str; 190 | ++count; 191 | 192 | int kern = *g++; 193 | for( int k = 0; k < kern; ++k ) 194 | if( *g++ == *str ) { x += (PIXELFONT_I8) *g++; break; } else ++g; 195 | 196 | } 197 | 198 | if( underline && target && y + font->baseline + 1 >= 0 && y + font->baseline + 1 < height && last_x_on_line > xp ) 199 | for( int ix = xp; ix <= last_x_on_line; ++ix ) 200 | if( ix >= 0 && ix < width ) 201 | PIXELFONT_PIXEL_FUNC( ( &target[ ix + ( y + font->baseline + 1 ) * width ] ), color ); 202 | last_x_on_line = xp; 203 | max_x = x > max_x ? x : max_x; 204 | x = xp; 205 | y += font->line_spacing + vspacing; 206 | if( *str == '\n' ) ++str; 207 | if( *str && skip_space && *str <= ' ' ) ++str; 208 | } 209 | 210 | if( bounds ) 211 | { 212 | bounds->width = wrap_width > 0 ? wrap_width : ( max_x - xp ); 213 | bounds->height = y - yp; 214 | } 215 | } 216 | 217 | #endif /* PIXELFONT_IMPLEMENTATION */ 218 | 219 | 220 | #undef PIXELFONT_COLOR 221 | #undef PIXELFONT_FUNC_NAME 222 | 223 | /* 224 | ------------------------------------------------------------------------------ 225 | 226 | This software is available under 2 licenses - you may choose the one you like. 227 | 228 | ------------------------------------------------------------------------------ 229 | 230 | ALTERNATIVE A - MIT License 231 | 232 | Copyright (c) 2017 Mattias Gustavsson 233 | 234 | Permission is hereby granted, free of charge, to any person obtaining a copy of 235 | this software and associated documentation files (the "Software"), to deal in 236 | the Software without restriction, including without limitation the rights to 237 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 238 | of the Software, and to permit persons to whom the Software is furnished to do 239 | so, subject to the following conditions: 240 | 241 | The above copyright notice and this permission notice shall be included in all 242 | copies or substantial portions of the Software. 243 | 244 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 245 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 246 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 247 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 248 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 249 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 250 | SOFTWARE. 251 | 252 | ------------------------------------------------------------------------------ 253 | 254 | ALTERNATIVE B - Public Domain (www.unlicense.org) 255 | 256 | This is free and unencumbered software released into the public domain. 257 | 258 | Anyone is free to copy, modify, publish, use, compile, sell, or distribute this 259 | software, either in source code form or as a compiled binary, for any purpose, 260 | commercial or non-commercial, and by any means. 261 | 262 | In jurisdictions that recognize copyright laws, the author or authors of this 263 | software dedicate any and all copyright interest in the software to the public 264 | domain. We make this dedication for the benefit of the public at large and to 265 | the detriment of our heirs and successors. We intend this dedication to be an 266 | overt act of relinquishment in perpetuity of all present and future rights to 267 | this software under copyright law. 268 | 269 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 270 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 271 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 272 | AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 273 | ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 274 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 275 | 276 | ------------------------------------------------------------------------------ 277 | */ 278 | -------------------------------------------------------------------------------- /source/pixie/rnd.h: -------------------------------------------------------------------------------- 1 | /* 2 | ------------------------------------------------------------------------------ 3 | Licensing information can be found at the end of the file. 4 | ------------------------------------------------------------------------------ 5 | 6 | rnd.h - v1.0 - Pseudo-random number generators for C/C++. 7 | 8 | Do this: 9 | #define RND_IMPLEMENTATION 10 | before you include this file in *one* C/C++ file to create the implementation. 11 | */ 12 | 13 | #ifndef rnd_h 14 | #define rnd_h 15 | 16 | #ifndef RND_U32 17 | #define RND_U32 unsigned int 18 | #endif 19 | #ifndef RND_U64 20 | #define RND_U64 unsigned long long 21 | #endif 22 | 23 | typedef struct rnd_pcg_t { RND_U64 state[ 2 ]; } rnd_pcg_t; 24 | void rnd_pcg_seed( rnd_pcg_t* pcg, RND_U32 seed ); 25 | RND_U32 rnd_pcg_next( rnd_pcg_t* pcg ); 26 | float rnd_pcg_nextf( rnd_pcg_t* pcg ); 27 | int rnd_pcg_range( rnd_pcg_t* pcg, int min, int max ); 28 | 29 | typedef struct rnd_well_t { RND_U32 state[ 17 ]; } rnd_well_t; 30 | void rnd_well_seed( rnd_well_t* well, RND_U32 seed ); 31 | RND_U32 rnd_well_next( rnd_well_t* well ); 32 | float rnd_well_nextf( rnd_well_t* well ); 33 | int rnd_well_range( rnd_well_t* well, int min, int max ); 34 | 35 | typedef struct rnd_gamerand_t { RND_U32 state[ 2 ]; } rnd_gamerand_t; 36 | void rnd_gamerand_seed( rnd_gamerand_t* gamerand, RND_U32 seed ); 37 | RND_U32 rnd_gamerand_next( rnd_gamerand_t* gamerand ); 38 | float rnd_gamerand_nextf( rnd_gamerand_t* gamerand ); 39 | int rnd_gamerand_range( rnd_gamerand_t* gamerand, int min, int max ); 40 | 41 | typedef struct rnd_xorshift_t { RND_U64 state[ 2 ]; } rnd_xorshift_t; 42 | void rnd_xorshift_seed( rnd_xorshift_t* xorshift, RND_U64 seed ); 43 | RND_U64 rnd_xorshift_next( rnd_xorshift_t* xorshift ); 44 | float rnd_xorshift_nextf( rnd_xorshift_t* xorshift ); 45 | int rnd_xorshift_range( rnd_xorshift_t* xorshift, int min, int max ); 46 | 47 | #endif /* rnd_h */ 48 | 49 | /** 50 | 51 | Example 52 | ======= 53 | 54 | A basic example showing how to use the PCG set of random functions. 55 | 56 | #define RND_IMPLEMENTATION 57 | #include "rnd.h" 58 | 59 | #include // for printf 60 | #include // for time 61 | 62 | int main( int argc, char** argv ) 63 | { 64 | (void) argc, argv; 65 | 66 | rnd_pcg_t pcg; 67 | rnd_pcg_seed( &pcg, 0u ); // initialize generator 68 | 69 | // print a handful of random integers 70 | // these will be the same on every run, as we 71 | // seeded the rng with a fixed value 72 | for( int i = 0; i < 5; ++i ) 73 | { 74 | RND_U32 n = rnd_pcg_next( &pcg ); 75 | printf( "%08x, ", n ); 76 | } 77 | printf( "\n" ); 78 | 79 | // reseed with a value which is different on each run 80 | time_t seconds; 81 | time( &seconds ); 82 | rnd_pcg_seed( &pcg, (RND_U32) seconds ); 83 | 84 | // print another handful of random integers 85 | // these will be different on every run 86 | for( int i = 0; i < 5; ++i ) 87 | { 88 | RND_U32 n = rnd_pcg_next( &pcg ); 89 | printf( "%08x, ", n ); 90 | } 91 | printf( "\n" ); 92 | 93 | 94 | // print a handful of random floats 95 | for( int i = 0; i < 5; ++i ) 96 | { 97 | float f = rnd_pcg_nextf( &pcg ); 98 | printf( "%f, ", f ); 99 | } 100 | printf( "\n" ); 101 | 102 | // print random integers in the range 1 to 6 103 | for( int i = 0; i < 15; ++i ) 104 | { 105 | int r = rnd_pcg_range( &pcg, 1, 6 ); 106 | printf( "%d, ", r ); 107 | } 108 | printf( "\n" ); 109 | 110 | return 0; 111 | } 112 | 113 | 114 | API Documentation 115 | ================= 116 | 117 | rnd.h is a single-header library, and does not need any .lib files or other binaries, or any build scripts. To use it, 118 | you just include rnd.h to get the API declarations. To get the definitions, you must include rnd.h from *one* single C 119 | or C++ file, and #define the symbol `RND_IMPLEMENTATION` before you do. 120 | 121 | The library is meant for general-purpose use, such as games and similar apps. It is not meant to be used for 122 | cryptography and similar use cases. 123 | 124 | 125 | Customization 126 | ------------- 127 | rnd.h allows for specifying the exact type of 32 and 64 bit unsigned integers to be used in its API. By default, these 128 | default to `unsigned int` and `unsigned long long`, but can be redefined by #defining RND_U32 and RND_U64 respectively 129 | before including rnd.h. This is useful if you, for example, use the types from `` in the rest of your program, 130 | and you want rnd.h to use compatible types. In this case, you would include rnd.h using the following code: 131 | 132 | #define RND_U32 uint32_t 133 | #define RND_U64 uint64_t 134 | #include "rnd.h" 135 | 136 | Note that when customizing the data type, you need to use the same definition in every place where you include rnd.h, 137 | as it affect the declarations as well as the definitions. 138 | 139 | 140 | The generators 141 | -------------- 142 | 143 | The library includes four different generators: PCG, WELL, GameRand and XorShift. They all have different 144 | characteristics, and you might want to use them for different things. GameRand is very fast, but does not give a great 145 | distribution or period length. XorShift is the only one returning a 64-bit value. WELL is an improvement of the often 146 | used Mersenne Twister, and has quite a large internal state. PCG is small, fast and has a small state. If you don't 147 | have any specific reason, you may default to using PCG. 148 | 149 | All generators expose their internal state, so it is possible to save this state and later restore it, to resume the 150 | random sequence from the same point. 151 | 152 | 153 | ### PCG - Permuted Congruential Generator 154 | 155 | PCG is a family of simple fast space-efficient statistically good algorithms for random number generation. Unlike many 156 | general-purpose RNGs, they are also hard to predict. 157 | 158 | More information can be found here: http://www.pcg-random.org/ 159 | 160 | 161 | ### WELL - Well Equidistributed Long-period Linear 162 | 163 | Random number generation, using the WELL algorithm by F. Panneton, P. L'Ecuyer and M. Matsumoto. 164 | More information in the original paper: http://www.iro.umontreal.ca/~panneton/WELLRNG.html 165 | 166 | This code is originally based on WELL512 C/C++ code written by Chris Lomont (published in Game Programming Gems 7) 167 | and placed in the public domain. http://lomont.org/Math/Papers/2008/Lomont_PRNG_2008.pdf 168 | 169 | 170 | ### GameRand 171 | 172 | Based on the random number generator by Ian C. Bullard: 173 | http://www.redditmirror.cc/cache/websites/mjolnirstudios.com_7yjlc/mjolnirstudios.com/IanBullard/files/79ffbca75a75720f066d491e9ea935a0-10.html 174 | 175 | GameRand is a random number generator based off an "Image of the Day" posted by Stephan Schaem. More information here: 176 | http://www.flipcode.com/archives/07-15-2002.shtml 177 | 178 | 179 | ### XorShift 180 | 181 | A random number generator of the type LFSR (linear feedback shift registers). This specific implementation uses the 182 | XorShift+ variation, and returns 64-bit random numbers. 183 | 184 | More information can be found here: https://en.wikipedia.org/wiki/Xorshift 185 | 186 | 187 | 188 | rnd_pcg_seed 189 | ------------ 190 | 191 | void rnd_pcg_seed( rnd_pcg_t* pcg, RND_U32 seed ) 192 | 193 | Initialize a PCG generator with the specified seed. The generator is not valid until it's been seeded. 194 | 195 | 196 | rnd_pcg_next 197 | ------------ 198 | 199 | RND_U32 rnd_pcg_next( rnd_pcg_t* pcg ) 200 | 201 | Returns a random number N in the range: 0 <= N <= 0xffffffff, from the specified PCG generator. 202 | 203 | 204 | rnd_pcg_nextf 205 | ------------- 206 | 207 | float rnd_pcg_nextf( rnd_pcg_t* pcg ) 208 | 209 | Returns a random float X in the range: 0.0f <= X < 1.0f, from the specified PCG generator. 210 | 211 | 212 | rnd_pcg_range 213 | ------------- 214 | 215 | int rnd_pcg_range( rnd_pcg_t* pcg, int min, int max ) 216 | 217 | Returns a random integer N in the range: min <= N <= max, from the specified PCG generator. 218 | 219 | 220 | rnd_well_seed 221 | ------------- 222 | 223 | void rnd_well_seed( rnd_well_t* well, RND_U32 seed ) 224 | 225 | Initialize a WELL generator with the specified seed. The generator is not valid until it's been seeded. 226 | 227 | 228 | rnd_well_next 229 | ------------- 230 | 231 | RND_U32 rnd_well_next( rnd_well_t* well ) 232 | 233 | Returns a random number N in the range: 0 <= N <= 0xffffffff, from the specified WELL generator. 234 | 235 | 236 | rnd_well_nextf 237 | -------------- 238 | float rnd_well_nextf( rnd_well_t* well ) 239 | 240 | Returns a random float X in the range: 0.0f <= X < 1.0f, from the specified WELL generator. 241 | 242 | 243 | rnd_well_range 244 | -------------- 245 | 246 | int rnd_well_range( rnd_well_t* well, int min, int max ) 247 | 248 | Returns a random integer N in the range: min <= N <= max, from the specified WELL generator. 249 | 250 | 251 | rnd_gamerand_seed 252 | ----------------- 253 | 254 | void rnd_gamerand_seed( rnd_gamerand_t* gamerand, RND_U32 seed ) 255 | 256 | Initialize a GameRand generator with the specified seed. The generator is not valid until it's been seeded. 257 | 258 | 259 | rnd_gamerand_next 260 | ----------------- 261 | 262 | RND_U32 rnd_gamerand_next( rnd_gamerand_t* gamerand ) 263 | 264 | Returns a random number N in the range: 0 <= N <= 0xffffffff, from the specified GameRand generator. 265 | 266 | 267 | rnd_gamerand_nextf 268 | ------------------ 269 | 270 | float rnd_gamerand_nextf( rnd_gamerand_t* gamerand ) 271 | 272 | Returns a random float X in the range: 0.0f <= X < 1.0f, from the specified GameRand generator. 273 | 274 | 275 | rnd_gamerand_range 276 | ------------------ 277 | 278 | int rnd_gamerand_range( rnd_gamerand_t* gamerand, int min, int max ) 279 | 280 | Returns a random integer N in the range: min <= N <= max, from the specified GameRand generator. 281 | 282 | 283 | rnd_xorshift_seed 284 | ----------------- 285 | 286 | void rnd_xorshift_seed( rnd_xorshift_t* xorshift, RND_U64 seed ) 287 | 288 | Initialize a XorShift generator with the specified seed. The generator is not valid until it's been seeded. 289 | 290 | 291 | rnd_xorshift_next 292 | ----------------- 293 | 294 | RND_U64 rnd_xorshift_next( rnd_xorshift_t* xorshift ) 295 | 296 | Returns a random number N in the range: 0 <= N <= 0xffffffffffffffff, from the specified XorShift generator. 297 | 298 | 299 | rnd_xorshift_nextf 300 | ------------------ 301 | 302 | float rnd_xorshift_nextf( rnd_xorshift_t* xorshift ) 303 | 304 | Returns a random float X in the range: 0.0f <= X < 1.0f, from the specified XorShift generator. 305 | 306 | 307 | rnd_xorshift_range 308 | ------------------ 309 | 310 | int rnd_xorshift_range( rnd_xorshift_t* xorshift, int min, int max ) 311 | 312 | Returns a random integer N in the range: min <= N <= max, from the specified XorShift generator. 313 | 314 | 315 | **/ 316 | 317 | 318 | /* 319 | ---------------------- 320 | IMPLEMENTATION 321 | ---------------------- 322 | */ 323 | 324 | #ifdef RND_IMPLEMENTATION 325 | #undef RND_IMPLEMENTATION 326 | 327 | // Convert a randomized RND_U32 value to a float value x in the range 0.0f <= x < 1.0f. Contributed by Jonatan Hedborg 328 | static float rnd_internal_float_normalized_from_u32( RND_U32 value ) 329 | { 330 | RND_U32 exponent = 127; 331 | RND_U32 mantissa = value >> 9; 332 | RND_U32 result = ( exponent << 23 ) | mantissa; 333 | float fresult = *(float*)( &result ); 334 | return fresult - 1.0f; 335 | } 336 | 337 | 338 | static RND_U32 rnd_internal_murmur3_avalanche32( RND_U32 h ) 339 | { 340 | h ^= h >> 16; 341 | h *= 0x85ebca6b; 342 | h ^= h >> 13; 343 | h *= 0xc2b2ae35; 344 | h ^= h >> 16; 345 | return h; 346 | } 347 | 348 | 349 | static RND_U64 rnd_internal_murmur3_avalanche64( RND_U64 h ) 350 | { 351 | h ^= h >> 33; 352 | h *= 0xff51afd7ed558ccd; 353 | h ^= h >> 33; 354 | h *= 0xc4ceb9fe1a85ec53; 355 | h ^= h >> 33; 356 | return h; 357 | } 358 | 359 | 360 | void rnd_pcg_seed( rnd_pcg_t* pcg, RND_U32 seed ) 361 | { 362 | RND_U64 value = ( ( (RND_U64) seed ) << 1ULL ) | 1ULL; 363 | value = rnd_internal_murmur3_avalanche64( value ); 364 | pcg->state[ 0 ] = 0U; 365 | pcg->state[ 1 ] = ( value << 1ULL ) | 1ULL; 366 | rnd_pcg_next( pcg ); 367 | pcg->state[ 0 ] += rnd_internal_murmur3_avalanche64( value ); 368 | rnd_pcg_next( pcg ); 369 | } 370 | 371 | 372 | RND_U32 rnd_pcg_next( rnd_pcg_t* pcg ) 373 | { 374 | RND_U64 oldstate = pcg->state[ 0 ]; 375 | pcg->state[ 0 ] = oldstate * 0x5851f42d4c957f2dULL + pcg->state[ 1 ]; 376 | RND_U32 xorshifted = (RND_U32)( ( ( oldstate >> 18ULL) ^ oldstate ) >> 27ULL ); 377 | RND_U32 rot = (RND_U32)( oldstate >> 59ULL ); 378 | return ( xorshifted >> rot ) | ( xorshifted << ( ( -(int) rot ) & 31 ) ); 379 | } 380 | 381 | 382 | float rnd_pcg_nextf( rnd_pcg_t* pcg ) 383 | { 384 | return rnd_internal_float_normalized_from_u32( rnd_pcg_next( pcg ) ); 385 | } 386 | 387 | 388 | int rnd_pcg_range( rnd_pcg_t* pcg, int min, int max ) 389 | { 390 | int const range = ( max - min ) + 1; 391 | if( range <= 0 ) return min; 392 | int const value = (int) ( rnd_pcg_nextf( pcg ) * range ); 393 | return min + value; 394 | } 395 | 396 | 397 | void rnd_well_seed( rnd_well_t* well, RND_U32 seed ) 398 | { 399 | RND_U32 value = rnd_internal_murmur3_avalanche32( ( seed << 1U ) | 1U ); 400 | well->state[ 16 ] = 0; 401 | well->state[ 0 ] = value ^ 0xf68a9fc1U; 402 | for( int i = 1; i < 16; ++i ) 403 | well->state[ i ] = ( 0x6c078965U * ( well->state[ i - 1 ] ^ ( well->state[ i - 1 ] >> 30 ) ) + i ); 404 | } 405 | 406 | 407 | RND_U32 rnd_well_next( rnd_well_t* well ) 408 | { 409 | RND_U32 a = well->state[ well->state[ 16 ] ]; 410 | RND_U32 c = well->state[ ( well->state[ 16 ] + 13 ) & 15 ]; 411 | RND_U32 b = a ^ c ^ ( a << 16 ) ^ ( c << 15 ); 412 | c = well->state[ ( well->state[ 16 ] + 9 ) & 15 ]; 413 | c ^= ( c >> 11 ); 414 | a = well->state[ well->state[ 16 ] ] = b ^ c; 415 | RND_U32 d = a ^ ( ( a << 5 ) & 0xda442d24U ); 416 | well->state[ 16 ] = (well->state[ 16 ] + 15 ) & 15; 417 | a = well->state[ well->state[ 16 ] ]; 418 | well->state[ well->state[ 16 ] ] = a ^ b ^ d ^ ( a << 2 ) ^ ( b << 18 ) ^ ( c << 28 ); 419 | return well->state[ well->state[ 16 ] ]; 420 | } 421 | 422 | 423 | float rnd_well_nextf( rnd_well_t* well ) 424 | { 425 | return rnd_internal_float_normalized_from_u32( rnd_well_next( well ) ); 426 | } 427 | 428 | 429 | int rnd_well_range( rnd_well_t* well, int min, int max ) 430 | { 431 | int const range = ( max - min ) + 1; 432 | if( range <= 0 ) return min; 433 | int const value = (int) ( rnd_well_nextf( well ) * range ); 434 | return min + value; 435 | } 436 | 437 | 438 | void rnd_gamerand_seed( rnd_gamerand_t* gamerand, RND_U32 seed ) 439 | { 440 | RND_U32 value = rnd_internal_murmur3_avalanche32( ( seed << 1U ) | 1U ); 441 | gamerand->state[ 0 ] = value; 442 | gamerand->state[ 1 ] = value ^ 0x49616e42U; 443 | } 444 | 445 | 446 | RND_U32 rnd_gamerand_next( rnd_gamerand_t* gamerand ) 447 | { 448 | gamerand->state[ 0 ] = ( gamerand->state[ 0 ] << 16 ) + ( gamerand->state[ 0 ] >> 16 ); 449 | gamerand->state[ 0 ] += gamerand->state[ 1 ]; 450 | gamerand->state[ 1 ] += gamerand->state[ 0 ]; 451 | return gamerand->state[ 0 ]; 452 | } 453 | 454 | 455 | float rnd_gamerand_nextf( rnd_gamerand_t* gamerand ) 456 | { 457 | return rnd_internal_float_normalized_from_u32( rnd_gamerand_next( gamerand ) ); 458 | } 459 | 460 | 461 | int rnd_gamerand_range( rnd_gamerand_t* gamerand, int min, int max ) 462 | { 463 | int const range = ( max - min ) + 1; 464 | if( range <= 0 ) return min; 465 | int const value = (int) ( rnd_gamerand_nextf( gamerand ) * range ); 466 | return min + value; 467 | } 468 | 469 | 470 | void rnd_xorshift_seed( rnd_xorshift_t* xorshift, RND_U64 seed ) 471 | { 472 | RND_U64 value = rnd_internal_murmur3_avalanche64( ( seed << 1ULL ) | 1ULL ); 473 | xorshift->state[ 0 ] = value; 474 | value = rnd_internal_murmur3_avalanche64( value ); 475 | xorshift->state[ 1 ] = value; 476 | } 477 | 478 | 479 | RND_U64 rnd_xorshift_next( rnd_xorshift_t* xorshift ) 480 | { 481 | RND_U64 x = xorshift->state[ 0 ]; 482 | RND_U64 const y = xorshift->state[ 1 ]; 483 | xorshift->state[ 0 ] = y; 484 | x ^= x << 23; 485 | x ^= x >> 17; 486 | x ^= y ^ ( y >> 26 ); 487 | xorshift->state[ 1 ] = x; 488 | return x + y; 489 | } 490 | 491 | 492 | float rnd_xorshift_nextf( rnd_xorshift_t* xorshift ) 493 | { 494 | return rnd_internal_float_normalized_from_u32( (RND_U32)( rnd_xorshift_next( xorshift ) >> 32 ) ); 495 | } 496 | 497 | 498 | int rnd_xorshift_range( rnd_xorshift_t* xorshift, int min, int max ) 499 | { 500 | int const range = ( max - min ) + 1; 501 | if( range <= 0 ) return min; 502 | int const value = (int) ( rnd_xorshift_next( xorshift ) * range ); 503 | return min + value; 504 | } 505 | 506 | 507 | 508 | #endif /* RND_IMPLEMENTATION */ 509 | 510 | /* 511 | 512 | contributors: 513 | Jonatan Hedborg (unsigned int to normalized float conversion) 514 | 515 | revision history: 516 | 1.0 first publicly released version 517 | 518 | */ 519 | 520 | /* 521 | ------------------------------------------------------------------------------ 522 | 523 | This software is available under 2 licenses - you may choose the one you like. 524 | Based on public domain implementation - original licenses can be found next to 525 | the relevant implementation sections of this file. 526 | 527 | ------------------------------------------------------------------------------ 528 | 529 | ALTERNATIVE A - MIT License 530 | 531 | Copyright (c) 2016 Mattias Gustavsson 532 | 533 | Permission is hereby granted, free of charge, to any person obtaining a copy of 534 | this software and associated documentation files (the "Software"), to deal in 535 | the Software without restriction, including without limitation the rights to 536 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 537 | of the Software, and to permit persons to whom the Software is furnished to do 538 | so, subject to the following conditions: 539 | 540 | The above copyright notice and this permission notice shall be included in all 541 | copies or substantial portions of the Software. 542 | 543 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 544 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 545 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 546 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 547 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 548 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 549 | SOFTWARE. 550 | 551 | ------------------------------------------------------------------------------ 552 | 553 | ALTERNATIVE B - Public Domain (www.unlicense.org) 554 | 555 | This is free and unencumbered software released into the public domain. 556 | 557 | Anyone is free to copy, modify, publish, use, compile, sell, or distribute this 558 | software, either in source code form or as a compiled binary, for any purpose, 559 | commercial or non-commercial, and by any means. 560 | 561 | In jurisdictions that recognize copyright laws, the author or authors of this 562 | software dedicate any and all copyright interest in the software to the public 563 | domain. We make this dedication for the benefit of the public at large and to 564 | the detriment of our heirs and successors. We intend this dedication to be an 565 | overt act of relinquishment in perpetuity of all present and future rights to 566 | this software under copyright law. 567 | 568 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 569 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 570 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 571 | AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 572 | ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 573 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 574 | 575 | ------------------------------------------------------------------------------ 576 | */ -------------------------------------------------------------------------------- /source/pixie/sort.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | ------------------------------------------------------------------------------ 3 | Licensing information can be found at the end of the file. 4 | ------------------------------------------------------------------------------ 5 | 6 | sort.hpp - v1.0 - High quality sort function for C++. 7 | 8 | Based on the implementation from the paper "Engineering a Sort Function" by 9 | Jon L Bentley and M Douglas McIlroy (1993). 10 | http://cs.fit.edu/~pkc/classes/writing/samples/bentley93engineering.pdf 11 | 12 | The code has been restructured and made to be partially iterative (with a 13 | manual data stack) instead of fully recursive. When run through a large set 14 | of tests with different initial data organization, it seems to be on about 15 | the same level as MSVC's std::sort. In the case where a custom compare 16 | function is used in place of the comparison operator of the type, this 17 | implementation has significantly better performance, due to inlining of the 18 | compare function. I am not an expert in sorting though, so tests might be 19 | faulty. In any case, it works well for my use cases, with a tiny code 20 | footprint, for those times when STL is not an option. 21 | */ 22 | 23 | #ifndef sort_hpp 24 | #define sort_hpp 25 | 26 | namespace sort_ns { 27 | 28 | 29 | template< typename T > void sort( T* array, int count ); 30 | 31 | template< typename T, int (*COMPARE_FUNC)( T const&, T const& ) > void sort( T* array, int count ); 32 | 33 | 34 | } /* namespace sort_ns */ 35 | 36 | #endif /* sort_hpp */ 37 | 38 | /** 39 | 40 | Example 41 | ======= 42 | 43 | #include "sort.hpp" 44 | using namespace sort_ns; 45 | 46 | int main( int argc, char** argv ) 47 | { 48 | (void) argc, argv; 49 | 50 | int values[ 10 ] = { 7, 6, 3, 9, 5, 4, 8, 2, 0, 1 }; 51 | sort( values, 10 ); 52 | for( int i = 0; i < 10; ++i ) printf( "%d ", values[ i ] ); 53 | return 0; 54 | } 55 | 56 | 57 | 58 | 59 | API Documentation 60 | ================= 61 | 62 | sort 63 | ---- 64 | 65 | template< typename T > void sort( T* array, int count ); 66 | template< typename T, int (*COMPARE_FUNC)( T const&, T const& ) > void sort( T* array, int count ); 67 | 68 | Sorts the given array, containing `count` items. `COMPARE_FUNC` is a custom compare function, used to compare two 69 | elements for sorting. It must return a negative integer value if the first argument is less than the second, 70 | a positive integer value if the first argument is greater than the second and zero if the arguments are equal. 71 | 72 | **/ 73 | 74 | /* 75 | ---------------------- 76 | IMPLEMENTATION 77 | ---------------------- 78 | */ 79 | 80 | #ifndef sort_impl 81 | #define sort_impl 82 | 83 | namespace sort_ns { 84 | 85 | 86 | template< typename T, int (*COMPARE_FUNC)( T const&, T const& ) > 87 | void sort( T* array, int count ) 88 | { 89 | #define SORT_INTERNAL_MED3( a, b, c ) \ 90 | ( COMPARE_FUNC( *(a), *(b) ) < 0 \ 91 | ? ( COMPARE_FUNC( *(b), *(c) ) < 0 ? (b) : COMPARE_FUNC( *(a), *(c) ) < 0 ? (c) : (a) ) \ 92 | : ( COMPARE_FUNC( *(b), *(c) ) > 0 ? (b) : COMPARE_FUNC( *(a), *(c) ) > 0 ? (c) : (a)) ) 93 | 94 | #define SORT_INTERNAL_SWAP( a, b ) \ 95 | { T t = *(a); *(a) = *(b); *(b) = t; } 96 | 97 | #define SORT_INTERNAL_SWAP_RANGE( a, b, n ) \ 98 | { int sn = (n); T* sa = (a); T* sb = (b); while( sn > 0 ) { SORT_INTERNAL_SWAP( sa, sb ); ++sa; ++sb; --sn; } } 99 | 100 | #define SORT_INTERNAL_MIN( a, b ) \ 101 | ( ( (a) < (b) ) ? (a) : (b) ) 102 | 103 | struct { int start; int count; } stack[ 32 ]; 104 | 105 | int top = 0; 106 | stack[ top ].start = 0; 107 | stack[ top ].count = count; 108 | 109 | while ( top >= 0 ) 110 | { 111 | T* a = array + stack[ top ].start; 112 | count = stack[ top-- ].count; 113 | 114 | if( count < 24 ) // Insertion sort on smallest arrays 115 | { 116 | for( T* pm = a + 1; pm < a + count; ++pm ) 117 | for( T* pl = pm; pl > a && COMPARE_FUNC( *( pl - 1 ), *pl ) > 0; --pl ) 118 | SORT_INTERNAL_SWAP( pl, pl - 1 ); 119 | continue; 120 | } 121 | T* pm = a + count / 2; // Small arrays, middle element 122 | if( count > 40 ) // Big arrays, pseudomedian of 9 123 | { 124 | T* pl = a; 125 | T* pn = a + count - 1; 126 | int s = count / 8; 127 | pl = SORT_INTERNAL_MED3( pl, pl + s, pl + 2 * s ); 128 | pm = SORT_INTERNAL_MED3( pm - s, pm, pm + s ); 129 | pn = SORT_INTERNAL_MED3( pn - 2 * s, pn - s, pn ); 130 | pm = SORT_INTERNAL_MED3( pl, pm, pn ); // Mid-size, med of 3 131 | } 132 | T* pv = a; SORT_INTERNAL_SWAP( pv, pm ); // pv points to partition value 133 | T* pa = a; 134 | T* pb = a; 135 | T* pc = a + count - 1; 136 | T* pd = pc; 137 | for( ;; ) 138 | { 139 | int r; 140 | while( pb <= pc && ( r = COMPARE_FUNC( *pb, *pv ) ) <= 0 ) 141 | { 142 | if( r == 0 ) { SORT_INTERNAL_SWAP( pa, pb ); ++pa; } 143 | ++pb; 144 | } 145 | while( pc >= pb && ( r = COMPARE_FUNC( *pc, *pv ) ) >= 0 ) 146 | { 147 | if( r == 0 ) { SORT_INTERNAL_SWAP( pc, pd ); --pd; } 148 | --pc; 149 | } 150 | if( pb > pc ) break; 151 | SORT_INTERNAL_SWAP( pb, pc ); 152 | ++pb; --pc; 153 | } 154 | T* pn = a + count; 155 | int s = (int)SORT_INTERNAL_MIN( pa - a, pb - pa ); SORT_INTERNAL_SWAP_RANGE( a, pb - s, s ); 156 | s = (int)SORT_INTERNAL_MIN( pd - pc, pn - pd - 1 ); SORT_INTERNAL_SWAP_RANGE( pb, pn - s, s ); 157 | if( ( s = (int)( pb - pa ) ) > 1 ) 158 | { 159 | if( ++top >= sizeof( stack) / sizeof( *stack ) ) { --top; sort( a, s ); } 160 | else { stack[ top ].start = (int)( a - array ); stack[ top ].count = s; } 161 | } 162 | if( ( s = (int)( pd - pc ) ) > 1 ) 163 | { 164 | if( ++top >= sizeof( stack) / sizeof( *stack ) ) { --top; sort( pn - s, s ); } 165 | else { stack[ top ].start = (int)( ( pn - s ) - array ); stack[ top ].count = s; } 166 | } 167 | } 168 | 169 | #undef SORT_INTERNAL_MED3 170 | #undef SORT_INTERNAL_SWAP 171 | #undef SORT_INTERNAL_SWAP_RANGE 172 | #undef SORT_INTERNAL_MIN 173 | } 174 | 175 | 176 | template< typename T > 177 | inline int sort_default_cmp( T const& a, T const& b ) 178 | { 179 | return a < b ? -1 : a > b ? 1 : 0; 180 | } 181 | 182 | 183 | template< typename T > 184 | void sort( T* array, int count ) 185 | { 186 | sort< T, &sort_default_cmp >( array, count ); 187 | } 188 | 189 | 190 | } /* namespace sort_ns */ 191 | 192 | 193 | #endif /* sort_impl */ 194 | 195 | /* 196 | ------------------------------------------------------------------------------ 197 | 198 | This software is available under 2 licenses - you may choose the one you like. 199 | 200 | ------------------------------------------------------------------------------ 201 | 202 | ALTERNATIVE A - MIT License 203 | 204 | Copyright (c) 2016 Mattias Gustavsson 205 | 206 | Permission is hereby granted, free of charge, to any person obtaining a copy of 207 | this software and associated documentation files (the "Software"), to deal in 208 | the Software without restriction, including without limitation the rights to 209 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 210 | of the Software, and to permit persons to whom the Software is furnished to do 211 | so, subject to the following conditions: 212 | 213 | The above copyright notice and this permission notice shall be included in all 214 | copies or substantial portions of the Software. 215 | 216 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 217 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 218 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 219 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 220 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 221 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 222 | SOFTWARE. 223 | 224 | ------------------------------------------------------------------------------ 225 | 226 | ALTERNATIVE B - Public Domain (www.unlicense.org) 227 | 228 | This is free and unencumbered software relpalrled into the public domain. 229 | 230 | Anyone is free to copy, modify, publish, use, compile, sell, or distribute this 231 | software, either in source code form or as a compiled binary, for any purpose, 232 | commercial or non-commercial, and by any means. 233 | 234 | In jurisdictions that recognize copyright laws, the author or authors of this 235 | software dedicate any and all copyright interest in the software to the public 236 | domain. We make this dedication for the benefit of the public at large and to 237 | the detriment of our heirs and successors. We intend this dedication to be an 238 | overt act of relinquishment in perpetuity of all present and future rights to 239 | this software under copyright law. 240 | 241 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 242 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 243 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 244 | AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 245 | ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 246 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 247 | 248 | ------------------------------------------------------------------------------ 249 | */ 250 | 251 | -------------------------------------------------------------------------------- /source/pixie/stb_perlin.h: -------------------------------------------------------------------------------- 1 | // stb_perlin.h - v0.3 - perlin noise 2 | // public domain single-file C implementation by Sean Barrett 3 | // 4 | // LICENSE 5 | // 6 | // See end of file. 7 | // 8 | // 9 | // to create the implementation, 10 | // #define STB_PERLIN_IMPLEMENTATION 11 | // in *one* C/CPP file that includes this file. 12 | // 13 | // 14 | // Documentation: 15 | // 16 | // float stb_perlin_noise3( float x, 17 | // float y, 18 | // float z, 19 | // int x_wrap=0, 20 | // int y_wrap=0, 21 | // int z_wrap=0) 22 | // 23 | // This function computes a random value at the coordinate (x,y,z). 24 | // Adjacent random values are continuous but the noise fluctuates 25 | // its randomness with period 1, i.e. takes on wholly unrelated values 26 | // at integer points. Specifically, this implements Ken Perlin's 27 | // revised noise function from 2002. 28 | // 29 | // The "wrap" parameters can be used to create wraparound noise that 30 | // wraps at powers of two. The numbers MUST be powers of two. Specify 31 | // 0 to mean "don't care". (The noise always wraps every 256 due 32 | // details of the implementation, even if you ask for larger or no 33 | // wrapping.) 34 | // 35 | // Fractal Noise: 36 | // 37 | // Three common fractal noise functions are included, which produce 38 | // a wide variety of nice effects depending on the parameters 39 | // provided. Note that each function will call stb_perlin_noise3 40 | // 'octaves' times, so this parameter will affect runtime. 41 | // 42 | // float stb_perlin_ridge_noise3(float x, float y, float z, 43 | // float lacunarity, float gain, float offset, int octaves, 44 | // int x_wrap, int y_wrap, int z_wrap); 45 | // 46 | // float stb_perlin_fbm_noise3(float x, float y, float z, 47 | // float lacunarity, float gain, int octaves, 48 | // int x_wrap, int y_wrap, int z_wrap); 49 | // 50 | // float stb_perlin_turbulence_noise3(float x, float y, float z, 51 | // float lacunarity, float gain,int octaves, 52 | // int x_wrap, int y_wrap, int z_wrap); 53 | // 54 | // Typical values to start playing with: 55 | // octaves = 6 -- number of "octaves" of noise3() to sum 56 | // lacunarity = ~ 2.0 -- spacing between successive octaves (use exactly 2.0 for wrapping output) 57 | // gain = 0.5 -- relative weighting applied to each successive octave 58 | // offset = 1.0? -- used to invert the ridges, may need to be larger, not sure 59 | // 60 | // 61 | // Contributors: 62 | // Jack Mott - additional noise functions 63 | // 64 | 65 | 66 | #ifdef __cplusplus 67 | extern "C" { 68 | #endif 69 | extern float stb_perlin_noise3(float x, float y, float z, int x_wrap, int y_wrap, int z_wrap); 70 | extern float stb_perlin_ridge_noise3(float x, float y, float z,float lacunarity, float gain, float offset, int octaves,int x_wrap, int y_wrap, int z_wrap); 71 | extern float stb_perlin_fbm_noise3(float x, float y, float z,float lacunarity, float gain, int octaves,int x_wrap, int y_wrap, int z_wrap); 72 | extern float stb_perlin_turbulence_noise3(float x, float y, float z, float lacunarity, float gain, int octaves,int x_wrap, int y_wrap, int z_wrap); 73 | #ifdef __cplusplus 74 | } 75 | #endif 76 | 77 | #ifdef STB_PERLIN_IMPLEMENTATION 78 | 79 | // not same permutation table as Perlin's reference to avoid copyright issues; 80 | // Perlin's table can be found at http://mrl.nyu.edu/~perlin/noise/ 81 | // @OPTIMIZE: should this be unsigned char instead of int for cache? 82 | static unsigned char stb__perlin_randtab[512] = 83 | { 84 | 23, 125, 161, 52, 103, 117, 70, 37, 247, 101, 203, 169, 124, 126, 44, 123, 85 | 152, 238, 145, 45, 171, 114, 253, 10, 192, 136, 4, 157, 249, 30, 35, 72, 86 | 175, 63, 77, 90, 181, 16, 96, 111, 133, 104, 75, 162, 93, 56, 66, 240, 87 | 8, 50, 84, 229, 49, 210, 173, 239, 141, 1, 87, 18, 2, 198, 143, 57, 88 | 225, 160, 58, 217, 168, 206, 245, 204, 199, 6, 73, 60, 20, 230, 211, 233, 89 | 94, 200, 88, 9, 74, 155, 33, 15, 219, 130, 226, 202, 83, 236, 42, 172, 90 | 165, 218, 55, 222, 46, 107, 98, 154, 109, 67, 196, 178, 127, 158, 13, 243, 91 | 65, 79, 166, 248, 25, 224, 115, 80, 68, 51, 184, 128, 232, 208, 151, 122, 92 | 26, 212, 105, 43, 179, 213, 235, 148, 146, 89, 14, 195, 28, 78, 112, 76, 93 | 250, 47, 24, 251, 140, 108, 186, 190, 228, 170, 183, 139, 39, 188, 244, 246, 94 | 132, 48, 119, 144, 180, 138, 134, 193, 82, 182, 120, 121, 86, 220, 209, 3, 95 | 91, 241, 149, 85, 205, 150, 113, 216, 31, 100, 41, 164, 177, 214, 153, 231, 96 | 38, 71, 185, 174, 97, 201, 29, 95, 7, 92, 54, 254, 191, 118, 34, 221, 97 | 131, 11, 163, 99, 234, 81, 227, 147, 156, 176, 17, 142, 69, 12, 110, 62, 98 | 27, 255, 0, 194, 59, 116, 242, 252, 19, 21, 187, 53, 207, 129, 64, 135, 99 | 61, 40, 167, 237, 102, 223, 106, 159, 197, 189, 215, 137, 36, 32, 22, 5, 100 | 101 | // and a second copy so we don't need an extra mask or static initializer 102 | 23, 125, 161, 52, 103, 117, 70, 37, 247, 101, 203, 169, 124, 126, 44, 123, 103 | 152, 238, 145, 45, 171, 114, 253, 10, 192, 136, 4, 157, 249, 30, 35, 72, 104 | 175, 63, 77, 90, 181, 16, 96, 111, 133, 104, 75, 162, 93, 56, 66, 240, 105 | 8, 50, 84, 229, 49, 210, 173, 239, 141, 1, 87, 18, 2, 198, 143, 57, 106 | 225, 160, 58, 217, 168, 206, 245, 204, 199, 6, 73, 60, 20, 230, 211, 233, 107 | 94, 200, 88, 9, 74, 155, 33, 15, 219, 130, 226, 202, 83, 236, 42, 172, 108 | 165, 218, 55, 222, 46, 107, 98, 154, 109, 67, 196, 178, 127, 158, 13, 243, 109 | 65, 79, 166, 248, 25, 224, 115, 80, 68, 51, 184, 128, 232, 208, 151, 122, 110 | 26, 212, 105, 43, 179, 213, 235, 148, 146, 89, 14, 195, 28, 78, 112, 76, 111 | 250, 47, 24, 251, 140, 108, 186, 190, 228, 170, 183, 139, 39, 188, 244, 246, 112 | 132, 48, 119, 144, 180, 138, 134, 193, 82, 182, 120, 121, 86, 220, 209, 3, 113 | 91, 241, 149, 85, 205, 150, 113, 216, 31, 100, 41, 164, 177, 214, 153, 231, 114 | 38, 71, 185, 174, 97, 201, 29, 95, 7, 92, 54, 254, 191, 118, 34, 221, 115 | 131, 11, 163, 99, 234, 81, 227, 147, 156, 176, 17, 142, 69, 12, 110, 62, 116 | 27, 255, 0, 194, 59, 116, 242, 252, 19, 21, 187, 53, 207, 129, 64, 135, 117 | 61, 40, 167, 237, 102, 223, 106, 159, 197, 189, 215, 137, 36, 32, 22, 5, 118 | }; 119 | 120 | static float stb__perlin_lerp(float a, float b, float t) 121 | { 122 | return a + (b-a) * t; 123 | } 124 | 125 | static int stb__perlin_fastfloor(float a) 126 | { 127 | int ai = (int) a; 128 | return (a < ai) ? ai-1 : ai; 129 | } 130 | 131 | // different grad function from Perlin's, but easy to modify to match reference 132 | static float stb__perlin_grad(int hash, float x, float y, float z) 133 | { 134 | static float basis[12][4] = 135 | { 136 | { 1, 1, 0 }, 137 | { -1, 1, 0 }, 138 | { 1,-1, 0 }, 139 | { -1,-1, 0 }, 140 | { 1, 0, 1 }, 141 | { -1, 0, 1 }, 142 | { 1, 0,-1 }, 143 | { -1, 0,-1 }, 144 | { 0, 1, 1 }, 145 | { 0,-1, 1 }, 146 | { 0, 1,-1 }, 147 | { 0,-1,-1 }, 148 | }; 149 | 150 | // perlin's gradient has 12 cases so some get used 1/16th of the time 151 | // and some 2/16ths. We reduce bias by changing those fractions 152 | // to 5/64ths and 6/64ths, and the same 4 cases get the extra weight. 153 | static unsigned char indices[64] = 154 | { 155 | 0,1,2,3,4,5,6,7,8,9,10,11, 156 | 0,9,1,11, 157 | 0,1,2,3,4,5,6,7,8,9,10,11, 158 | 0,1,2,3,4,5,6,7,8,9,10,11, 159 | 0,1,2,3,4,5,6,7,8,9,10,11, 160 | 0,1,2,3,4,5,6,7,8,9,10,11, 161 | }; 162 | 163 | // if you use reference permutation table, change 63 below to 15 to match reference 164 | // (this is why the ordering of the table above is funky) 165 | float *grad = basis[indices[hash & 63]]; 166 | return grad[0]*x + grad[1]*y + grad[2]*z; 167 | } 168 | 169 | float stb_perlin_noise3(float x, float y, float z, int x_wrap, int y_wrap, int z_wrap) 170 | { 171 | float u,v,w; 172 | float n000,n001,n010,n011,n100,n101,n110,n111; 173 | float n00,n01,n10,n11; 174 | float n0,n1; 175 | 176 | unsigned int x_mask = (x_wrap-1) & 255; 177 | unsigned int y_mask = (y_wrap-1) & 255; 178 | unsigned int z_mask = (z_wrap-1) & 255; 179 | int px = stb__perlin_fastfloor(x); 180 | int py = stb__perlin_fastfloor(y); 181 | int pz = stb__perlin_fastfloor(z); 182 | int x0 = px & x_mask, x1 = (px+1) & x_mask; 183 | int y0 = py & y_mask, y1 = (py+1) & y_mask; 184 | int z0 = pz & z_mask, z1 = (pz+1) & z_mask; 185 | int r0,r1, r00,r01,r10,r11; 186 | 187 | #define stb__perlin_ease(a) (((a*6-15)*a + 10) * a * a * a) 188 | 189 | x -= px; u = stb__perlin_ease(x); 190 | y -= py; v = stb__perlin_ease(y); 191 | z -= pz; w = stb__perlin_ease(z); 192 | 193 | r0 = stb__perlin_randtab[x0]; 194 | r1 = stb__perlin_randtab[x1]; 195 | 196 | r00 = stb__perlin_randtab[r0+y0]; 197 | r01 = stb__perlin_randtab[r0+y1]; 198 | r10 = stb__perlin_randtab[r1+y0]; 199 | r11 = stb__perlin_randtab[r1+y1]; 200 | 201 | n000 = stb__perlin_grad(stb__perlin_randtab[r00+z0], x , y , z ); 202 | n001 = stb__perlin_grad(stb__perlin_randtab[r00+z1], x , y , z-1 ); 203 | n010 = stb__perlin_grad(stb__perlin_randtab[r01+z0], x , y-1, z ); 204 | n011 = stb__perlin_grad(stb__perlin_randtab[r01+z1], x , y-1, z-1 ); 205 | n100 = stb__perlin_grad(stb__perlin_randtab[r10+z0], x-1, y , z ); 206 | n101 = stb__perlin_grad(stb__perlin_randtab[r10+z1], x-1, y , z-1 ); 207 | n110 = stb__perlin_grad(stb__perlin_randtab[r11+z0], x-1, y-1, z ); 208 | n111 = stb__perlin_grad(stb__perlin_randtab[r11+z1], x-1, y-1, z-1 ); 209 | 210 | n00 = stb__perlin_lerp(n000,n001,w); 211 | n01 = stb__perlin_lerp(n010,n011,w); 212 | n10 = stb__perlin_lerp(n100,n101,w); 213 | n11 = stb__perlin_lerp(n110,n111,w); 214 | 215 | n0 = stb__perlin_lerp(n00,n01,v); 216 | n1 = stb__perlin_lerp(n10,n11,v); 217 | 218 | return stb__perlin_lerp(n0,n1,u); 219 | } 220 | 221 | float stb_perlin_ridge_noise3(float x, float y, float z,float lacunarity, float gain, float offset, int octaves,int x_wrap, int y_wrap, int z_wrap) 222 | { 223 | int i; 224 | float frequency = 1.0f; 225 | float prev = 1.0f; 226 | float amplitude = 0.5f; 227 | float sum = 0.0f; 228 | 229 | for (i = 0; i < octaves; i++) { 230 | float r = (float)(stb_perlin_noise3(x*frequency,y*frequency,z*frequency,x_wrap,y_wrap,z_wrap)); 231 | r = r<0 ? -r : r; // fabs() 232 | r = offset - r; 233 | r = r*r; 234 | sum += r*amplitude*prev; 235 | prev = r; 236 | frequency *= lacunarity; 237 | amplitude *= gain; 238 | } 239 | return sum; 240 | } 241 | 242 | float stb_perlin_fbm_noise3(float x, float y, float z,float lacunarity, float gain, int octaves,int x_wrap, int y_wrap, int z_wrap) 243 | { 244 | int i; 245 | float frequency = 1.0f; 246 | float amplitude = 1.0f; 247 | float sum = 0.0f; 248 | 249 | for (i = 0; i < octaves; i++) { 250 | sum += stb_perlin_noise3(x*frequency,y*frequency,z*frequency,x_wrap,y_wrap,z_wrap)*amplitude; 251 | frequency *= lacunarity; 252 | amplitude *= gain; 253 | } 254 | return sum; 255 | } 256 | 257 | float stb_perlin_turbulence_noise3(float x, float y, float z, float lacunarity, float gain, int octaves,int x_wrap, int y_wrap, int z_wrap) 258 | { 259 | int i; 260 | float frequency = 1.0f; 261 | float amplitude = 1.0f; 262 | float sum = 0.0f; 263 | 264 | for (i = 0; i < octaves; i++) { 265 | float r = stb_perlin_noise3(x*frequency,y*frequency,z*frequency,x_wrap,y_wrap,z_wrap)*amplitude; 266 | r = r<0 ? -r : r; // fabs() 267 | sum += r; 268 | frequency *= lacunarity; 269 | amplitude *= gain; 270 | } 271 | return sum; 272 | } 273 | 274 | #endif // STB_PERLIN_IMPLEMENTATION 275 | 276 | /* 277 | ------------------------------------------------------------------------------ 278 | This software is available under 2 licenses -- choose whichever you prefer. 279 | ------------------------------------------------------------------------------ 280 | ALTERNATIVE A - MIT License 281 | Copyright (c) 2017 Sean Barrett 282 | Permission is hereby granted, free of charge, to any person obtaining a copy of 283 | this software and associated documentation files (the "Software"), to deal in 284 | the Software without restriction, including without limitation the rights to 285 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 286 | of the Software, and to permit persons to whom the Software is furnished to do 287 | so, subject to the following conditions: 288 | The above copyright notice and this permission notice shall be included in all 289 | copies or substantial portions of the Software. 290 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 291 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 292 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 293 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 294 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 295 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 296 | SOFTWARE. 297 | ------------------------------------------------------------------------------ 298 | ALTERNATIVE B - Public Domain (www.unlicense.org) 299 | This is free and unencumbered software released into the public domain. 300 | Anyone is free to copy, modify, publish, use, compile, sell, or distribute this 301 | software, either in source code form or as a compiled binary, for any purpose, 302 | commercial or non-commercial, and by any means. 303 | In jurisdictions that recognize copyright laws, the author or authors of this 304 | software dedicate any and all copyright interest in the software to the public 305 | domain. We make this dedication for the benefit of the public at large and to 306 | the detriment of our heirs and successors. We intend this dedication to be an 307 | overt act of relinquishment in perpetuity of all present and future rights to 308 | this software under copyright law. 309 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 310 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 311 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 312 | AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 313 | ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 314 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 315 | ------------------------------------------------------------------------------ 316 | */ -------------------------------------------------------------------------------- /source/pixie/strpool.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | ------------------------------------------------------------------------------ 3 | Licensing information can be found at the end of the file. 4 | ------------------------------------------------------------------------------ 5 | 6 | strpool.hpp - v0.1 - 7 | 8 | Do this: 9 | #define STRPOOL_HPP_IMPLEMENTATION 10 | before you include this file in *one* C/C++ file to create the implementation. 11 | 12 | Dependencies: 13 | strpool.h 14 | */ 15 | 16 | #ifndef strpool_hpp 17 | #define strpool_hpp 18 | 19 | namespace strpool { 20 | 21 | #ifndef STRPOOL_U64 22 | typedef unsigned long long u64; 23 | #else 24 | typedef STRPOOL_U64 u64; 25 | #endif 26 | 27 | 28 | struct DEFAULT_POOL; 29 | struct STRINGID_POOL; 30 | 31 | template< typename POOL > 32 | struct string_type 33 | { 34 | string_type(); 35 | ~string_type(); 36 | 37 | string_type& operator=( string_type const& other ); 38 | string_type( string_type const& other ); 39 | 40 | template< typename OTHER_POOL > 41 | string_type( string_type const& other ); 42 | 43 | string_type( char* str ); 44 | string_type( char const* str ); 45 | string_type( char const* begin, char const* end ); 46 | 47 | int length() const; 48 | char const* c_str() const; 49 | 50 | bool operator==( string_type const& other ) const; 51 | bool operator!=( string_type const& other ) const; 52 | 53 | template< typename OTHER_POOL> 54 | bool operator==( string_type const& other ) const; 55 | 56 | template< typename OTHER_POOL> 57 | bool operator!=( string_type const& other ) const; 58 | 59 | static void defrag(); 60 | static void nuke(); 61 | 62 | static char* temp_buffer( int len ); 63 | 64 | private: 65 | template< typename POOL > friend struct string_type; 66 | u64 handle_; 67 | 68 | #ifndef NDEBUG 69 | char debug_[ 56 ]; 70 | #endif 71 | }; 72 | 73 | typedef string_type string; 74 | typedef string_type string_id; 75 | 76 | 77 | } /* namespace strpool */ 78 | 79 | #endif /* strpool_h */ 80 | 81 | 82 | /* 83 | ---------------------- 84 | IMPLEMENTATION 85 | ---------------------- 86 | */ 87 | 88 | #ifndef strpool_hpp_impl 89 | #define strpool_hpp_impl 90 | 91 | struct strpool_t; 92 | 93 | // placement new 94 | #if !defined( PLACEMENT_NEW_OPERATOR_DEFINED ) && !defined( __PLACEMENT_NEW_INLINE ) 95 | #define PLACEMENT_NEW_OPERATOR_DEFINED 96 | #define __PLACEMENT_NEW_INLINE 97 | inline void* operator new( size_t, void* p ) throw() { return p; } inline void operator delete(void*, void*) throw() { } 98 | #endif 99 | 100 | namespace strpool { namespace internal { 101 | 102 | int entry_count( strpool_t* pool ); 103 | 104 | struct string_pool 105 | { 106 | string_pool( bool case_sensitive, void* memctx = 0 ); 107 | ~string_pool(); 108 | 109 | void defrag(); 110 | void nuke(); 111 | 112 | u64 get_handle( char const* string_type, int length ); 113 | 114 | void inc_ref_count( u64 handle ); 115 | void dec_ref_count( u64 handle ); 116 | 117 | char const* get_string( u64 handle ); 118 | int get_length( u64 handle ); 119 | 120 | char* temp_buffer( int len ); 121 | 122 | private: 123 | template< typename POOL > 124 | friend internal::string_pool& pool_instance( bool destroy ); 125 | 126 | void* memctx_; 127 | struct strpool_t* pool_; 128 | char* temp_buffer_; 129 | int temp_buffer_size_; 130 | }; 131 | 132 | size_t strlen( char const* str ); 133 | char* strcpy( char* dst, char const* src ); 134 | char* strncpy( char* dest, char const* source, size_t count ); 135 | int memcmp( void const* buf1, void const* buf2, size_t count ); 136 | void* allocate( size_t size ); 137 | void release( void* ptr ); 138 | 139 | template< typename POOL > 140 | internal::string_pool& pool_instance( bool destroy = false ) 141 | { 142 | static string_pool* instance = 0; 143 | if( destroy ) 144 | { 145 | if( instance && entry_count( instance->pool_ ) == 0 ) 146 | { 147 | instance->~string_pool(); 148 | release( instance ); 149 | instance = 0; 150 | } 151 | } 152 | else if( !instance ) 153 | { 154 | instance = (string_pool*) allocate( sizeof( *instance ) ); 155 | new (instance) string_pool( true ); 156 | } 157 | 158 | return *instance; 159 | } 160 | 161 | 162 | template<> 163 | inline internal::string_pool& pool_instance( bool destroy ) 164 | { 165 | static string_pool* instance = 0; 166 | if( destroy ) 167 | { 168 | if( instance && entry_count( instance->pool_ ) == 0 ) 169 | { 170 | instance->~string_pool(); 171 | release( instance ); 172 | instance = 0; 173 | } 174 | } 175 | else if( !instance ) 176 | { 177 | instance = (string_pool*) allocate( sizeof( *instance ) ); 178 | new (instance) string_pool( false ); 179 | } 180 | 181 | return *instance; 182 | } 183 | 184 | 185 | } /* namespace internal */ } /*namespace strpool */ 186 | 187 | namespace strpool { 188 | 189 | template< typename POOL > 190 | string_type::string_type(): 191 | handle_( 0 ) 192 | { 193 | #ifndef NDEBUG 194 | internal::strcpy( debug_, ""); 195 | #endif 196 | } 197 | 198 | template< typename POOL > 199 | string_type::~string_type() 200 | { 201 | if( handle_ ) 202 | { 203 | internal::pool_instance().dec_ref_count( handle_ ); 204 | } 205 | internal::pool_instance( true ); 206 | } 207 | 208 | template< typename POOL > 209 | string_type& string_type::operator=( string_type const& other ) 210 | { 211 | if( handle_ ) internal::pool_instance().dec_ref_count( handle_ ); 212 | handle_ = other.handle_; 213 | if( handle_ ) internal::pool_instance().inc_ref_count( handle_ ); 214 | 215 | #ifndef NDEBUG 216 | internal::strncpy( debug_, c_str(), sizeof( debug_ ) ); 217 | debug_[ sizeof( debug_ ) - 1 ] = '\0'; 218 | #endif 219 | 220 | return *this; 221 | } 222 | 223 | template< typename POOL > 224 | string_type::string_type( string_type const& other ): 225 | handle_( other.handle_ ) 226 | { 227 | if( handle_ ) internal::pool_instance().inc_ref_count( handle_ ); 228 | 229 | #ifndef NDEBUG 230 | internal::strncpy( debug_, c_str(), sizeof( debug_ ) ); 231 | debug_[ sizeof( debug_ ) - 1 ] = '\0'; 232 | #endif 233 | } 234 | 235 | template< typename POOL > template< typename OTHER_POOL > 236 | string_type::string_type( string_type const& other ) 237 | { 238 | handle_ = internal::pool_instance().get_handle( other.c_str(), other.length() ); 239 | if( handle_ ) internal::pool_instance().inc_ref_count( handle_ ); 240 | 241 | #ifndef NDEBUG 242 | internal::strncpy( debug_, c_str(), sizeof( debug_ ) ); 243 | debug_[ sizeof( debug_ ) - 1 ] = '\0'; 244 | #endif 245 | } 246 | 247 | template< typename POOL > 248 | string_type::string_type( char* str ) 249 | { 250 | size_t len = 0; 251 | if( str ) len = internal::strlen( str ); 252 | if( len == 0 ) 253 | { 254 | handle_ = 0; 255 | } 256 | else 257 | { 258 | handle_ = internal::pool_instance().get_handle( str, (int) len ); 259 | if( handle_ ) internal::pool_instance().inc_ref_count( handle_ ); 260 | } 261 | 262 | #ifndef NDEBUG 263 | internal::strncpy( debug_, c_str(), sizeof( debug_ ) ); 264 | debug_[ sizeof( debug_ ) - 1 ] = '\0'; 265 | #endif 266 | } 267 | 268 | template< typename POOL > 269 | string_type::string_type( char const* str ) 270 | { 271 | size_t len = 0; 272 | if( str ) len = internal::strlen( str ); 273 | if( len == 0 ) 274 | { 275 | handle_ = 0; 276 | } 277 | else 278 | { 279 | handle_ = internal::pool_instance().get_handle( str, (int) len ); 280 | if( handle_ ) internal::pool_instance().inc_ref_count( handle_ ); 281 | } 282 | 283 | #ifndef NDEBUG 284 | internal::strncpy( debug_, c_str(), sizeof( debug_ ) ); 285 | debug_[ sizeof( debug_ ) - 1 ] = '\0'; 286 | #endif 287 | } 288 | 289 | template< typename POOL > 290 | string_type::string_type( char const* begin, char const* end ) : 291 | handle_( 0 ) 292 | { 293 | if( !begin ) 294 | { 295 | #ifndef NDEBUG 296 | internal::strcpy( debug_, ""); 297 | #endif 298 | } 299 | size_t len = end ? (size_t)( end - begin ) : internal::strlen( begin ); 300 | if( len == 0 ) 301 | { 302 | handle_ = 0; 303 | } 304 | else 305 | { 306 | handle_ = internal::pool_instance().get_handle( begin, (int) len ); 307 | if( handle_ ) internal::pool_instance().inc_ref_count( handle_ ); 308 | } 309 | 310 | #ifndef NDEBUG 311 | internal::strncpy( debug_, c_str(), sizeof( debug_ ) ); 312 | debug_[ sizeof( debug_ ) - 1 ] = '\0'; 313 | #endif 314 | } 315 | 316 | template< typename POOL > 317 | int string_type::length() const 318 | { 319 | if( handle_ ) 320 | return internal::pool_instance().get_length( handle_ ); 321 | else 322 | return 0; 323 | } 324 | 325 | template< typename POOL > 326 | char const* string_type::c_str() const 327 | { 328 | if( handle_ ) 329 | return internal::pool_instance().get_string( handle_ ); 330 | else 331 | return ""; 332 | } 333 | 334 | template< typename POOL > 335 | bool string_type::operator==( string_type const& other ) const 336 | { 337 | return handle_ == other.handle_; 338 | } 339 | 340 | template< typename POOL > 341 | bool string_type::operator!=( string_type const& other ) const 342 | { 343 | return !( (*this) == other ); 344 | } 345 | 346 | template< typename POOL > template< typename OTHER_POOL> 347 | bool string_type::operator==( string_type const& other ) const 348 | { 349 | if( !handle_ ) return other.handle_ ? false : true; 350 | 351 | int const length = internal::pool_instance().get_length( handle_ ); 352 | int const other_length = internal::pool_instance().get_length( other.handle_ ); 353 | return length == other_length && ( length == 0 || internal::memcmp( c_str(), other.c_str(), (size_t) length ) == 0 ); 354 | } 355 | 356 | template< typename POOL > template< typename OTHER_POOL > 357 | bool string_type::operator!=( string_type const& other ) const 358 | { 359 | return !( (*this) == other ); 360 | } 361 | 362 | 363 | template< typename POOL > 364 | void string_type::defrag() 365 | { 366 | internal::pool_instance().defrag(); 367 | } 368 | 369 | 370 | template< typename POOL > 371 | void string_type::nuke() 372 | { 373 | internal::pool_instance().nuke(); 374 | } 375 | 376 | 377 | template< typename POOL > 378 | char* string_type::temp_buffer( int const len ) 379 | { 380 | return internal::pool_instance().temp_buffer( len ); 381 | } 382 | 383 | } /* namespace strpool */ 384 | 385 | 386 | #endif /* strpool_hpp_impl */ 387 | 388 | 389 | 390 | #ifdef STRPOOL_HPP_IMPLEMENTATION 391 | #undef STRPOOL_HPP_IMPLEMENTATION 392 | 393 | #define _CRT_NONSTDC_NO_DEPRECATE 394 | #define _CRT_SECURE_NO_WARNINGS 395 | #include 396 | #include 397 | 398 | 399 | #ifndef STRPOOL_HPP_MALLOC 400 | #define _CRT_NONSTDC_NO_DEPRECATE 401 | #define _CRT_SECURE_NO_WARNINGS 402 | #include 403 | #define STRPOOL_HPP_MALLOC( ctx, size ) ( malloc( size ) ) 404 | #define STRPOOL_HPP_FREE( ctx, ptr ) ( free( ptr ) ) 405 | #endif 406 | 407 | #include "strpool.h" 408 | 409 | namespace strpool { namespace internal { 410 | 411 | int entry_count( strpool_t* pool ) 412 | { 413 | return pool->entry_count; 414 | } 415 | 416 | 417 | string_pool::string_pool( bool case_sensitive, void* memctx ): 418 | memctx_( memctx ), 419 | temp_buffer_size_( 256 ) 420 | { 421 | strpool_config_t config = strpool_default_config; 422 | config.memctx = memctx; 423 | config.ignore_case = case_sensitive ? 0 : 1; 424 | pool_ = (strpool_t*) STRPOOL_HPP_MALLOC( memctx, sizeof( strpool_t ) ); 425 | strpool_init( pool_, &config ); 426 | temp_buffer_ = (char*) STRPOOL_HPP_MALLOC( memctx, (size_t) temp_buffer_size_ ); 427 | } 428 | 429 | string_pool::~string_pool() 430 | { 431 | strpool_term( pool_ ); 432 | STRPOOL_HPP_FREE( memctx_, pool_ ); 433 | STRPOOL_HPP_FREE( memctx_, temp_buffer_ ); 434 | } 435 | 436 | void string_pool::defrag() 437 | { 438 | strpool_defrag( pool_ ); 439 | } 440 | 441 | void string_pool::nuke() 442 | { 443 | strpool_term( pool_ ); 444 | strpool_init( pool_, &strpool_default_config ); 445 | } 446 | 447 | STRPOOL_U64 string_pool::get_handle( char const* const str, int const length ) 448 | { 449 | return strpool_inject( pool_, str, length ); 450 | } 451 | 452 | void string_pool::inc_ref_count( STRPOOL_U64 const handle ) 453 | { 454 | strpool_incref( pool_, handle ); 455 | } 456 | 457 | void string_pool::dec_ref_count( STRPOOL_U64 const handle ) 458 | { 459 | if( strpool_decref( pool_, handle ) <= 0 ) 460 | { 461 | strpool_discard( pool_, handle ); 462 | } 463 | } 464 | 465 | char const* string_pool::get_string( STRPOOL_U64 const handle ) 466 | { 467 | return strpool_cstr( pool_, handle ); 468 | } 469 | 470 | int string_pool::get_length( STRPOOL_U64 const handle ) 471 | { 472 | return strpool_length( pool_, handle ); 473 | } 474 | 475 | char* string_pool::temp_buffer( int const len ) 476 | { 477 | if( temp_buffer_size_ < len + 1 ) 478 | { 479 | temp_buffer_size_ = len + 1; 480 | STRPOOL_HPP_FREE( memctx_, temp_buffer_ ); 481 | temp_buffer_ = (char*) STRPOOL_HPP_MALLOC( memctx_, (size_t) temp_buffer_size_ ); 482 | } 483 | 484 | return temp_buffer_; 485 | } 486 | 487 | size_t strlen( char const* const str ) { return ::strlen( str ); } 488 | char* strcpy( char* const dst, char const* const src ) { return ::strcpy( dst, src ); } 489 | char* strncpy( char* const dest, char const* const source, size_t const count ) { return ::strncpy( dest, source, count ); } 490 | int memcmp( void const* const buf1, void const* const buf2, size_t const count ) { return ::memcmp( buf1, buf2, count ); } 491 | void* allocate( size_t size ) { return STRPOOL_HPP_MALLOC( 0, size ); } 492 | void release( void* ptr ) { return STRPOOL_HPP_FREE( 0, ptr ); } 493 | 494 | } /* namespace internal */ } /* namespace strpool */ 495 | 496 | #endif /* STRPOOL_HPP_IMPLEMENTATION */ 497 | 498 | 499 | /* 500 | revision history: 501 | 1.0 first released version 502 | */ 503 | 504 | 505 | /* 506 | ------------------------------------------------------------------------------ 507 | 508 | This software is available under 2 licenses - you may choose the one you like. 509 | 510 | ------------------------------------------------------------------------------ 511 | 512 | ALTERNATIVE A - MIT License 513 | 514 | Copyright (c) 2015 Mattias Gustavsson 515 | 516 | Permission is hereby granted, free of charge, to any person obtaining a copy of 517 | this software and associated documentation files (the "Software"), to deal in 518 | the Software without restriction, including without limitation the rights to 519 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 520 | of the Software, and to permit persons to whom the Software is furnished to do 521 | so, subject to the following conditions: 522 | 523 | The above copyright notice and this permission notice shall be included in all 524 | copies or substantial portions of the Software. 525 | 526 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 527 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 528 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 529 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 530 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 531 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 532 | SOFTWARE. 533 | 534 | ------------------------------------------------------------------------------ 535 | 536 | ALTERNATIVE B - Public Domain (www.unlicense.org) 537 | 538 | This is free and unencumbered software released into the public domain. 539 | 540 | Anyone is free to copy, modify, publish, use, compile, sell, or distribute this 541 | software, either in source code form or as a compiled binary, for any purpose, 542 | commercial or non-commercial, and by any means. 543 | 544 | In jurisdictions that recognize copyright laws, the author or authors of this 545 | software dedicate any and all copyright interest in the software to the public 546 | domain. We make this dedication for the benefit of the public at large and to 547 | the detriment of our heirs and successors. We intend this dedication to be an 548 | overt act of relinquishment in perpetuity of all present and future rights to 549 | this software under copyright law. 550 | 551 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 552 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 553 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 554 | AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 555 | ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 556 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 557 | 558 | ------------------------------------------------------------------------------ 559 | */ 560 | -------------------------------------------------------------------------------- /source_data/Deltoid-sans.fnt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mattiasgustavsson/pixie/590856bd400d40ab5b8c5ae013f72e3e59677b5e/source_data/Deltoid-sans.fnt -------------------------------------------------------------------------------- /source_data/Volter__28Goldfish_29.fnt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mattiasgustavsson/pixie/590856bd400d40ab5b8c5ae013f72e3e59677b5e/source_data/Volter__28Goldfish_29.fnt -------------------------------------------------------------------------------- /source_data/background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mattiasgustavsson/pixie/590856bd400d40ab5b8c5ae013f72e3e59677b5e/source_data/background.png -------------------------------------------------------------------------------- /source_data/bitpolka.xm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mattiasgustavsson/pixie/590856bd400d40ab5b8c5ae013f72e3e59677b5e/source_data/bitpolka.xm -------------------------------------------------------------------------------- /source_data/build.ini: -------------------------------------------------------------------------------- 1 | palette.png = pal 2 | .png = bitmap_normal 3 | .fnt = copy 4 | .ttf = font 5 | .xm = copy 6 | 7 | [bitmap_normal] 8 | compiler = pixie_bitmap 9 | format = normal 10 | palette = /palette.png 11 | dither = default 12 | 13 | [pal] 14 | compiler = pixie_palette 15 | 16 | [copy] 17 | compiler = pixie_copy 18 | 19 | -------------------------------------------------------------------------------- /source_data/palette.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mattiasgustavsson/pixie/590856bd400d40ab5b8c5ae013f72e3e59677b5e/source_data/palette.png --------------------------------------------------------------------------------