├── .gitignore ├── Compressor ├── Compressor.vcxproj ├── Compressor.vcxproj.filters ├── res │ ├── config.xml │ └── metadata.xml └── src │ ├── BufferStream.cpp │ ├── BufferStream.h │ ├── CompressionFormat.h │ ├── Compressor.cpp │ ├── Compressor.h │ ├── Sprite.cpp │ ├── Sprite.h │ └── main.cpp ├── Decompressor.Android ├── AndroidManifest.xml ├── Decompressor.Android.vcxproj ├── Decompressor.Android.vcxproj.filters ├── jni │ ├── com_thecherno_decompressor_Decompressor.cpp │ ├── com_thecherno_decompressor_Decompressor.h │ ├── com_thecherno_decompressor_DisplayActivity_DisplayRenderer.cpp │ └── com_thecherno_decompressor_DisplayActivity_DisplayRenderer.h ├── res │ ├── layout │ │ ├── display_layout.xml │ │ └── main_layout.xml │ └── values │ │ └── strings.xml └── src │ └── com │ └── thecherno │ └── decompressor │ ├── Decompressor.java │ └── DisplayActivity.java ├── Decompressor.Windows ├── Decompressor.Windows.vcxproj ├── Decompressor.Windows.vcxproj.filters └── src │ └── main.cpp ├── Decompressor ├── Decompressor.vcxproj ├── Decompressor.vcxproj.filters └── src │ ├── Common.cpp │ ├── Common.h │ ├── DecompressionTest.cpp │ ├── DecompressionTest.h │ ├── Decompressor.cpp │ └── Decompressor.h ├── Dependencies ├── LZ4 │ ├── LZ4.vcxproj │ ├── LZ4.vcxproj.filters │ ├── ProjectUpgradeBackup_20160825_1847191070 │ │ └── LZ4.vcxproj │ ├── ProjectUpgradeBackup_20160825_1847191160 │ │ └── LZ4.vcxproj.filters │ └── src │ │ ├── lz4.c │ │ └── lz4.h ├── STB │ └── include │ │ └── stb_image.h └── zstd │ ├── src │ ├── common │ │ ├── bitstream.h │ │ ├── entropy_common.c │ │ ├── error_private.h │ │ ├── error_public.h │ │ ├── fse.h │ │ ├── fse_decompress.c │ │ ├── huf.h │ │ ├── mem.h │ │ ├── xxhash.c │ │ ├── xxhash.h │ │ ├── zbuff.h │ │ ├── zstd_common.c │ │ └── zstd_internal.h │ ├── compress │ │ ├── fse_compress.c │ │ ├── huf_compress.c │ │ ├── zbuff_compress.c │ │ ├── zstd_compress.c │ │ └── zstd_opt.h │ ├── decompress │ │ ├── huf_decompress.c │ │ ├── zbuff_decompress.c │ │ └── zstd_decompress.c │ └── zstd.h │ ├── zstd.vcxproj │ └── zstd.vcxproj.filters ├── Flinty ├── Dependencies │ ├── GLEW │ │ ├── GLEW.vcxproj │ │ ├── GLEW.vcxproj.filters │ │ ├── include │ │ │ └── GL │ │ │ │ ├── eglew.h │ │ │ │ ├── glew.h │ │ │ │ ├── glxew.h │ │ │ │ └── wglew.h │ │ └── src │ │ │ ├── glew.c │ │ │ ├── glewinfo.c │ │ │ └── visualinfo.c │ └── GLFW │ │ ├── include │ │ └── GLFW │ │ │ ├── glfw3.h │ │ │ └── glfw3native.h │ │ └── lib │ │ └── x86 │ │ └── glfw3.lib └── Flinty │ ├── Flinty.vcxproj │ ├── Flinty.vcxproj.filters │ └── src │ ├── Flinty.h │ └── fl │ ├── Common.h │ ├── Core.cpp │ ├── Core.h │ ├── String.cpp │ ├── String.h │ ├── Types.h │ ├── gl.h │ ├── graphics │ ├── Renderer.cpp │ ├── Renderer.h │ ├── Window.cpp │ ├── Window.h │ └── shaders │ │ ├── Shader.cpp │ │ ├── Shader.h │ │ ├── ShaderFactory.cpp │ │ ├── ShaderFactory.h │ │ ├── ShaderManager.cpp │ │ ├── ShaderManager.h │ │ ├── ShaderResource.cpp │ │ ├── ShaderResource.h │ │ ├── ShaderUniform.cpp │ │ ├── ShaderUniform.h │ │ └── default │ │ └── Simple.shader │ ├── maths │ ├── AABB.cpp │ ├── AABB.h │ ├── Quaternion.cpp │ ├── Quaternion.h │ ├── Rectangle.cpp │ ├── Rectangle.h │ ├── mat4.cpp │ ├── mat4.h │ ├── maths.h │ ├── maths_func.h │ ├── tvec2.h │ ├── vec2.cpp │ ├── vec2.h │ ├── vec3.cpp │ ├── vec3.h │ ├── vec4.cpp │ └── vec4.h │ ├── platform │ ├── android │ │ ├── AndroidFileSystem.cpp │ │ ├── AndroidRenderer.cpp │ │ ├── AndroidSystem.cpp │ │ └── AndroidSystem.h │ └── windows │ │ ├── WindowsFileSystem.cpp │ │ └── WindowsRenderer.cpp │ ├── system │ ├── FileSystem.cpp │ ├── FileSystem.h │ └── Timer.h │ └── xml │ ├── XMLDocument.cpp │ ├── XMLDocument.h │ └── rapidxml │ ├── license.txt │ ├── manual.html │ ├── rapidxml.hpp │ ├── rapidxml_iterators.hpp │ ├── rapidxml_print.hpp │ └── rapidxml_utils.hpp ├── LICENSE ├── README.md ├── SpriteCompression.sln └── SpriteCompression ├── App.config ├── Properties └── AssemblyInfo.cs ├── SpriteCompression.csproj └── src ├── Compressor.cs ├── Decompressor.cs ├── Program.cs ├── Sprite.cs └── Utils.cs /.gitignore: -------------------------------------------------------------------------------- 1 | bin/ 2 | obj/ 3 | *.db 4 | *.opendb 5 | *.vspx 6 | *.psess 7 | *.suo 8 | *.user 9 | *.png 10 | *.bin -------------------------------------------------------------------------------- /Compressor/Compressor.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | Debug 14 | x64 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | {9c7cf380-1ac0-488b-9034-60c659947ce7} 30 | 31 | 32 | {01947db5-0f7d-47ec-ae58-d445a35764a7} 33 | 34 | 35 | {ceb28ea3-4b44-4c0d-bfd4-948644dc0b78} 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | {C83B9DE2-50D7-4A26-8252-156DDBB1DCF1} 46 | Compressor 47 | 8.1 48 | 49 | 50 | 51 | Application 52 | true 53 | v140 54 | MultiByte 55 | 56 | 57 | Application 58 | false 59 | v140 60 | true 61 | MultiByte 62 | 63 | 64 | Application 65 | true 66 | v140 67 | MultiByte 68 | 69 | 70 | Application 71 | false 72 | v140 73 | true 74 | MultiByte 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | $(SolutionDir)bin\$(Configuration)\$(Platform)\ 96 | $(SolutionDir)bin\$(Configuration)\$(Platform)\Intermediates\$(ProjectName) 97 | 98 | 99 | $(SolutionDir)bin\$(Configuration)\$(Platform)\ 100 | $(SolutionDir)bin\$(Configuration)\$(Platform)\Intermediates\$(ProjectName) 101 | 102 | 103 | 104 | Level3 105 | Disabled 106 | true 107 | $(SolutionDir)Dependencies\zstd\src;$(SolutionDir)Dependencies\LZ4\src;$(SolutionDir)Flinty\Flinty\src;$(SolutionDir)Dependencies\STB\include 108 | _CRT_SECURE_NO_WARNINGS;FL_DEBUG;FL_PLATFORM_WINDOWS;_MBCS;%(PreprocessorDefinitions) 109 | 110 | 111 | 112 | 113 | Level3 114 | Disabled 115 | true 116 | 117 | 118 | 119 | 120 | Level3 121 | MaxSpeed 122 | true 123 | true 124 | true 125 | $(SolutionDir)Dependencies\zstd\src;$(SolutionDir)Dependencies\LZ4\src;$(SolutionDir)Flinty\Flinty\src;$(SolutionDir)Dependencies\STB\include 126 | _CRT_SECURE_NO_WARNINGS;FL_PLATFORM_WINDOWS;_MBCS;%(PreprocessorDefinitions) 127 | 128 | 129 | true 130 | true 131 | 132 | 133 | 134 | 135 | Level3 136 | MaxSpeed 137 | true 138 | true 139 | true 140 | 141 | 142 | true 143 | true 144 | 145 | 146 | 147 | 148 | 149 | -------------------------------------------------------------------------------- /Compressor/Compressor.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | Source Files 20 | 21 | 22 | Source Files 23 | 24 | 25 | Source Files 26 | 27 | 28 | Source Files 29 | 30 | 31 | 32 | 33 | Header Files 34 | 35 | 36 | Header Files 37 | 38 | 39 | Header Files 40 | 41 | 42 | Header Files 43 | 44 | 45 | -------------------------------------------------------------------------------- /Compressor/res/config.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | Compress 4 | 5 | res/Butterfly 6 | output/butterfly512-zstd.bin 7 | 2 8 | 16 9 | 10 | -------------------------------------------------------------------------------- /Compressor/res/metadata.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 20 6 | 24 7 | 8 | 9 | 10 | 11 | 50 12 | 80 13 | 3 14 | 15 | 16 | 4 17 | 18 18 | 1 19 | 20 | 21 | -------------------------------------------------------------------------------- /Compressor/src/BufferStream.cpp: -------------------------------------------------------------------------------- 1 | #include "BufferStream.h" 2 | 3 | BufferStream::BufferStream(uint size) 4 | { 5 | if (size) 6 | m_Buffer = std::vector(size); 7 | } 8 | 9 | BufferStream::~BufferStream() 10 | { 11 | } 12 | 13 | void BufferStream::WriteInternal(const void* buffer, uint size) 14 | { 15 | m_Buffer.insert(m_Buffer.end(), (byte*)buffer, (byte*)buffer + size); 16 | } 17 | 18 | void BufferStream::WriteInternal(const void* buffer, uint size, uint offset) 19 | { 20 | memcpy(&m_Buffer[offset], (byte*)buffer, size); 21 | } 22 | 23 | void BufferStream::WriteBytes(const byte* data, uint size) 24 | { 25 | WriteInternal(data, size); 26 | } 27 | 28 | void BufferStream::WriteBytes(const byte* data, uint size, uint offset) 29 | { 30 | WriteInternal(data, size, offset); 31 | } 32 | 33 | -------------------------------------------------------------------------------- /Compressor/src/BufferStream.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | class BufferStream 6 | { 7 | private: 8 | std::vector m_Buffer; 9 | uint m_Position; 10 | public: 11 | BufferStream(uint size = 0); 12 | ~BufferStream(); 13 | 14 | inline const byte* GetBuffer() const { return &m_Buffer[0]; } 15 | inline uint GetSize() const { return m_Buffer.size(); } 16 | 17 | void WriteBytes(const byte* data, uint size); 18 | void WriteBytes(const byte* data, uint size, uint offset); 19 | 20 | template 21 | void Write(const T* data, uint count = 1) 22 | { 23 | WriteInternal((const void*)data, sizeof(T) * count); 24 | } 25 | 26 | template 27 | void Write(const T* data, uint count, uint offset) 28 | { 29 | WriteInternal((const void*)data, sizeof(T) * count, offset); 30 | } 31 | 32 | private: 33 | void WriteInternal(const void* buffer, uint size); 34 | void WriteInternal(const void* buffer, uint size, uint offset); 35 | }; -------------------------------------------------------------------------------- /Compressor/src/CompressionFormat.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "fl/String.h" 4 | 5 | typedef unsigned char byte; 6 | typedef unsigned short ushort; 7 | typedef unsigned int uint; 8 | 9 | struct Header 10 | { 11 | enum class CompressionType : byte 12 | { 13 | NONE = 0, LZ4 = 1, ZSTD = 2 14 | }; 15 | 16 | enum class Format : byte 17 | { 18 | ARGB = 0 19 | }; 20 | 21 | enum class AnimationMode : byte 22 | { 23 | NONE = 0, NORMAL = 1, LOOP = 2, PINGPONG = 3 24 | }; 25 | 26 | byte h0, h1; // [ 0] 08 08 27 | byte v0, v1; // [ 2] Major/Minor version 28 | byte quality; // [ 4] 0-5 29 | CompressionType compression; // [ 5] 30 | Format format; // [ 6] 31 | byte r0; // [ 7] Reserved 32 | ushort frames; // [ 8] number of frames 33 | ushort width, height; // [10] Size of animation 34 | ushort padding; // [14] 35 | uint decompressionBound; // [16] Size of largest decompression stream 36 | 37 | struct Event 38 | { 39 | ushort eventNameLength; 40 | char* eventName; 41 | ushort startFrame, endFrame; 42 | }; 43 | 44 | ushort eventCount; 45 | Event* events; 46 | 47 | struct Animation 48 | { 49 | ushort animationNameLength; 50 | char* animationName; 51 | uint startFrameOffset; 52 | ushort startFrameIndex; 53 | ushort endFrameIndex; 54 | AnimationMode mode; 55 | }; 56 | 57 | ushort animationCount; 58 | Animation* animations; 59 | }; 60 | 61 | struct Metadata 62 | { 63 | struct Event 64 | { 65 | String name; 66 | ushort startFrame, endFrame; 67 | }; 68 | 69 | struct Animation 70 | { 71 | String name; 72 | ushort startFrame, endFrame; 73 | Header::AnimationMode mode; 74 | }; 75 | 76 | std::vector events; 77 | std::vector animations; 78 | }; -------------------------------------------------------------------------------- /Compressor/src/Compressor.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include "BufferStream.h" 5 | #include "Sprite.h" 6 | 7 | #include "CompressionFormat.h" 8 | 9 | class Compressor 10 | { 11 | private: 12 | int m_Quality; 13 | int m_SimilarityThreshold; 14 | Header::CompressionType m_CompressionMode; 15 | std::vector m_Sprites; 16 | Metadata m_Metadata; 17 | int m_WindowSize; 18 | uint m_DecompressionBound; 19 | std::unordered_map m_AnimationOffsets; 20 | public: 21 | Compressor(const std::vector& sprites, const Metadata& metadata, byte quality, Header::CompressionType compressionType, int windowSize); 22 | ~Compressor(); 23 | 24 | void Compress(const String& toFile); 25 | private: 26 | void WriteHeader(BufferStream& stream); 27 | void WriteKeyframe(BufferStream& stream, const Sprite& sprite, ushort index); 28 | void WriteDeltaFrame(BufferStream& stream, const Sprite& frame, int* previousBuffer); 29 | 30 | int ChannelDiff(int c0, int c1); 31 | 32 | void EmitPacket(BufferStream& stream, int* pixels, int cursor, ushort skipped, ushort copied); 33 | byte* ApplyEntropyCompression(const byte* buffer, uint size, uint* outSize = nullptr); 34 | 35 | bool IsAnimation(ushort index); 36 | }; 37 | -------------------------------------------------------------------------------- /Compressor/src/Sprite.cpp: -------------------------------------------------------------------------------- 1 | #include "Sprite.h" 2 | 3 | #define STB_IMAGE_IMPLEMENTATION 4 | #include 5 | 6 | Sprite::Sprite(const String& path) 7 | { 8 | int c; 9 | int w, h; 10 | pixels = stbi_load(path.c_str(), &w, &h, &c, STBI_rgb_alpha); 11 | width = (uint)w; 12 | height = (uint)h; 13 | } -------------------------------------------------------------------------------- /Compressor/src/Sprite.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | struct Sprite 6 | { 7 | uint width, height; 8 | byte* pixels; 9 | 10 | Sprite(const String& path); 11 | }; 12 | -------------------------------------------------------------------------------- /Compressor/src/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include 6 | #include 7 | 8 | #include "Compressor.h" 9 | 10 | enum class Mode 11 | { 12 | NONE, DECOMPRESS, COMPRESS, CONFIG 13 | }; 14 | 15 | static std::vector GetAllFiles(String path, const String& mask) 16 | { 17 | std::vector results; 18 | HANDLE hFind = INVALID_HANDLE_VALUE; 19 | WIN32_FIND_DATA ffd; 20 | String spec; 21 | std::stack directories; 22 | 23 | directories.push(path); 24 | 25 | while (!directories.empty()) { 26 | path = directories.top(); 27 | spec = path + "/" + mask; 28 | directories.pop(); 29 | 30 | hFind = FindFirstFile(spec.c_str(), &ffd); 31 | if (hFind == INVALID_HANDLE_VALUE) { 32 | return results; 33 | } 34 | 35 | do { 36 | if (strcmp(ffd.cFileName, ".") != 0 && 37 | strcmp(ffd.cFileName, "..") != 0) { 38 | if (ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { 39 | directories.push(path + "/" + ffd.cFileName); 40 | } 41 | else { 42 | results.push_back(path + "/" + ffd.cFileName); 43 | } 44 | } 45 | } while (FindNextFile(hFind, &ffd) != 0); 46 | 47 | if (GetLastError() != ERROR_NO_MORE_FILES) { 48 | FindClose(hFind); 49 | return results; 50 | } 51 | 52 | FindClose(hFind); 53 | hFind = INVALID_HANDLE_VALUE; 54 | } 55 | 56 | return results; 57 | } 58 | 59 | static void PrintUsage() 60 | { 61 | std::cout << "\tUsage: sc mode(compress|decompress) input-path output-path [quality]" << std::endl; 62 | } 63 | 64 | int main(int argc, char** argv) 65 | { 66 | if (argc < 3) 67 | { 68 | PrintUsage(); 69 | return 1; 70 | } 71 | 72 | Mode mode = Mode::NONE; 73 | String m = argv[1]; 74 | if (m == "decompress") 75 | mode = Mode::DECOMPRESS; 76 | else if (m == "compress") 77 | mode = Mode::COMPRESS; 78 | else if (m == "-f") 79 | mode = Mode::CONFIG; 80 | 81 | Metadata metadata; 82 | bool hasMetadata = false; 83 | 84 | FL_ASSERT(mode != Mode::NONE); 85 | // Defaults 86 | String input, output; 87 | byte compression = 0; 88 | byte quality = 0; 89 | int windowSize = 8; 90 | if (mode == Mode::CONFIG) 91 | { 92 | String file = argv[2]; 93 | 94 | fl::XMLDocument document(file); 95 | fl::XMLNode* rootNode = document.FindNode("Config"); 96 | FL_ASSERT(rootNode); 97 | fl::XMLNode* modeNode = rootNode->FindChild("Mode"); 98 | bool compress = false; 99 | if (modeNode) 100 | compress = String(modeNode->value) == "Compress"; 101 | 102 | if (compress) 103 | { 104 | fl::XMLNode* settingsNode = rootNode->FindChild("Compressor"); 105 | if (settingsNode) 106 | { 107 | fl::XMLNode* inputNode = settingsNode->FindChild("Input"); 108 | if (inputNode) 109 | input = inputNode->value; 110 | fl::XMLNode* outputNode = settingsNode->FindChild("Output"); 111 | if (outputNode) 112 | output = outputNode->value; 113 | fl::XMLNode* qualityNode = settingsNode->FindChild("Quality"); 114 | if (qualityNode) 115 | quality = atoi(qualityNode->value.c_str()); 116 | fl::XMLNode* compressionNode = settingsNode->FindChild("Compression"); 117 | if (compressionNode) 118 | compression = atoi(compressionNode->value.c_str()); 119 | fl::XMLNode* windowSizeNode = settingsNode->FindChild("WindowSize"); 120 | if (windowSizeNode) 121 | windowSize = atoi(windowSizeNode->value.c_str()); 122 | } 123 | } 124 | } 125 | else 126 | { 127 | input = String(argv[2]); 128 | if (argc > 3) 129 | output = String(argv[3]); 130 | 131 | if (argc > 4) 132 | quality = (byte)atoi(argv[4]); 133 | 134 | if (argc > 5) 135 | compression = atoi(argv[5]); 136 | 137 | if (argc > 6) 138 | windowSize = atoi(argv[6]); 139 | 140 | if (argc > 7) 141 | { 142 | String metadataFile = argv[7]; 143 | 144 | fl::XMLDocument document(metadataFile); 145 | fl::XMLNode* rootNode = document.FindNode("Metadata"); 146 | FL_ASSERT(rootNode); 147 | 148 | for (fl::XMLNode& e : rootNode->FindChild("Events")->children) 149 | { 150 | Metadata::Event ev; 151 | ev.name = e.FindAttribute("name")->value; 152 | ev.startFrame = atoi(e.FindChild("StartFrame")->value.c_str()); 153 | ev.endFrame = atoi(e.FindChild("EndFrame")->value.c_str()); 154 | metadata.events.push_back(ev); 155 | } 156 | 157 | for (fl::XMLNode& a : rootNode->FindChild("Animations")->children) 158 | { 159 | Metadata::Animation anim; 160 | anim.name = a.FindAttribute("name")->value; 161 | anim.startFrame = atoi(a.FindChild("StartFrame")->value.c_str()); 162 | anim.endFrame = atoi(a.FindChild("EndFrame")->value.c_str()); 163 | anim.mode = (Header::AnimationMode)atoi(a.FindChild("Mode")->value.c_str()); 164 | metadata.animations.push_back(anim); 165 | } 166 | hasMetadata = true; 167 | } 168 | } 169 | 170 | std::vector files = GetAllFiles(input, "*"); 171 | 172 | std::cout << "Reading " << files.size() << " images... "; 173 | std::vector sprites; 174 | for (int i = 0; i < files.size(); i++) 175 | sprites.push_back(Sprite(files[i])); 176 | std::cout << "Done." << std::endl; 177 | 178 | Compressor compressor(sprites, metadata, quality, (Header::CompressionType)compression, windowSize); 179 | compressor.Compress(output); 180 | 181 | return 0; 182 | } -------------------------------------------------------------------------------- /Decompressor.Android/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | 10 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /Decompressor.Android/Decompressor.Android.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 11 5 | 6 | 7 | 8 | Debug 9 | Tegra-Android 10 | 11 | 12 | Release 13 | Tegra-Android 14 | 15 | 16 | Shipping 17 | Tegra-Android 18 | 19 | 20 | 21 | {6C87890C-D661-4E0D-9F59-DB2A935EA075} 22 | Decompressor_Android 23 | 24 | 25 | 26 | android-21 27 | clang-3.6 28 | llvm-libc++_static 29 | GradleBuild 30 | UseTarget 31 | 32 | 33 | android-22 34 | clang-3.6 35 | llvm-libc++_static 36 | GradleBuild 37 | 38 | 39 | android-22 40 | clang-3.6 41 | llvm-libc++_static 42 | GradleBuild 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | $(SolutionDir)bin\$(Configuration)\$(Platform)\ 51 | $(SolutionDir)bin\$(Configuration)\$(Platform)\Intermediates\$(ProjectName) 52 | false 53 | 54 | 55 | $(SolutionDir)bin\$(Configuration)\$(Platform)\ 56 | $(SolutionDir)bin\$(Configuration)\$(Platform)\Intermediates\$(ProjectName) 57 | false 58 | 59 | 60 | $(SolutionDir)bin\$(Configuration)\$(Platform)\ 61 | $(SolutionDir)bin\$(Configuration)\$(Platform)\Intermediates\$(ProjectName) 62 | 63 | 64 | 65 | gnu++11 66 | $(SolutionDir)Flinty\Flinty\src;$(SolutionDir)Decompressor\src;D:\NVPACK\android-ndk-r10e\platforms\android-21\arch-arm\usr\include 67 | FL_PLATFORM_ANDROID;DEBUG; 68 | 69 | 70 | android;GLESv2; 71 | D:\NVPACK\android-ndk-r10e\platforms\android-21\arch-arm\usr\lib; 72 | true 73 | 74 | 75 | assets 76 | False 77 | 78 | 79 | 80 | 81 | gnu++11 82 | $(SolutionDir)Flinty\Flinty\src;$(SolutionDir)Decompressor\src;C:\NVPACK\android-ndk-r10e\platforms\android-21\arch-arm\usr\include; 83 | FL_PLATFORM_ANDROID; 84 | O2 85 | false 86 | 87 | 88 | android;GLESv2; 89 | C:\NVPACK\android-ndk-r10e\platforms\android-21\arch-arm\usr\lib; 90 | 91 | 92 | assets 93 | 94 | 95 | 96 | 97 | gnu++11 98 | $(SolutionDir)Flinty\Flinty\src;$(SolutionDir)Decompressor\src;C:\NVPACK\android-ndk-r10e\platforms\android-21\arch-arm\usr\include; 99 | FL_PLATFORM_ANDROID; 100 | 101 | 102 | android;GLESv2; 103 | C:\NVPACK\android-ndk-r10e\platforms\android-21\arch-arm\usr\lib; 104 | 105 | 106 | assets 107 | 108 | 109 | 110 | 111 | Designer 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | {07e50ef7-c482-4fe6-a9f4-eaf5c9394157} 130 | 131 | 132 | {9c7cf380-1ac0-488b-9034-60c659947ce7} 133 | 134 | 135 | {ceb28ea3-4b44-4c0d-bfd4-948644dc0b78} 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | -------------------------------------------------------------------------------- /Decompressor.Android/Decompressor.Android.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 553221e4-f24e-4650-8b66-9b861c4116c6 6 | 7 | 8 | 63b4c268-7e9f-41b2-be67-902a59499e39 9 | 10 | 11 | a7b17329-621b-4c47-a5b5-117fb6f2feeb 12 | 13 | 14 | b1512e7e-be8c-4f61-a7d8-8de8b092a181 15 | 16 | 17 | 67de3b0f-e3f7-4258-b588-aa7ef70ca6c3 18 | 19 | 20 | 58abff5e-ae86-4c7e-8293-076e014e4292 21 | 22 | 23 | b49f06e3-0b98-48c7-8cfd-c07bab913f66 24 | 25 | 26 | {faaab4a3-95ad-45f1-8e8d-2a700825513c} 27 | 28 | 29 | 30 | 31 | 32 | res\values 33 | 34 | 35 | 36 | 37 | jni 38 | 39 | 40 | 41 | 42 | 43 | jni 44 | 45 | 46 | 47 | 48 | 49 | src\com\thecherno\decompressor 50 | 51 | 52 | src\com\thecherno\decompressor 53 | 54 | 55 | 56 | 57 | res\layout 58 | 59 | 60 | 61 | 62 | res\layout 63 | 64 | 65 | -------------------------------------------------------------------------------- /Decompressor.Android/jni/com_thecherno_decompressor_Decompressor.cpp: -------------------------------------------------------------------------------- 1 | #include "com_thecherno_decompressor_Decompressor.h" 2 | #include "DecompressionTest.h" 3 | 4 | using namespace fl; 5 | 6 | extern void UpdateAnimation(Animation* animation); 7 | extern Renderer* s_Renderer; 8 | 9 | JNIEXPORT jfloatArray JNICALL Java_com_thecherno_decompressor_Decompressor_RunDecompression(JNIEnv* env, jobject obj) 10 | { 11 | Init(env, obj); 12 | s_Renderer = new Renderer(); 13 | 14 | DecompressionTest tester; 15 | std::vector results = tester.RunAllTests(); 16 | 17 | Decompressor d("WS/512/butterfly512-uncompressed-ws16.bin"); 18 | UpdateAnimation(d.Decompress3()); 19 | 20 | uint count = results.size() * 2; 21 | jfloatArray result = env->NewFloatArray(count); 22 | if (!result) 23 | return nullptr; 24 | 25 | jfloat* data = new jfloat[count]; 26 | for (int i = 0; i < results.size(); i++) 27 | { 28 | data[i * 2 + 0] = (float)results[i].size; 29 | data[i * 2 + 1] = results[i].time; 30 | } 31 | 32 | env->SetFloatArrayRegion(result, 0, count, data); 33 | delete[] data; 34 | return result; 35 | } 36 | -------------------------------------------------------------------------------- /Decompressor.Android/jni/com_thecherno_decompressor_Decompressor.h: -------------------------------------------------------------------------------- 1 | /* DO NOT EDIT THIS FILE - it is machine generated */ 2 | #include 3 | 4 | #ifndef _Included_com_thecherno_decompressor_Decompressor 5 | #define _Included_com_thecherno_decompressor_Decompressor 6 | #ifdef __cplusplus 7 | extern "C" { 8 | #endif 9 | 10 | JNIEXPORT jfloatArray JNICALL Java_com_thecherno_decompressor_Decompressor_RunDecompression(JNIEnv *, jobject); 11 | 12 | #ifdef __cplusplus 13 | } 14 | #endif 15 | #endif -------------------------------------------------------------------------------- /Decompressor.Android/jni/com_thecherno_decompressor_DisplayActivity_DisplayRenderer.cpp: -------------------------------------------------------------------------------- 1 | #include "com_thecherno_decompressor_DisplayActivity_DisplayRenderer.h" 2 | 3 | #include "Decompressor.h" 4 | 5 | #include 6 | #include 7 | 8 | using namespace fl; 9 | 10 | static Shader* s_Shader; 11 | static int s_Frame = 0; 12 | static int s_Time = 0; 13 | 14 | static float s_FrameTime = 0.0f; 15 | static float s_UpdateTimer = 0.0f; 16 | static float s_UpdateTick = 1.0f / 60.0f; 17 | static uint s_Frames = 0; 18 | static uint s_Updates = 0; 19 | static Timer s_Timer; 20 | static float s_SecondTimer = 0.0f; 21 | 22 | Renderer* s_Renderer; 23 | 24 | static Animation* s_Animation = nullptr; 25 | static uint s_TextureID = 0; 26 | 27 | static void OnUpdate() 28 | { 29 | s_Time++; 30 | 31 | if (s_Animation && s_Time % 2 == 0) 32 | { 33 | s_Frame = (s_Frame + 1) % s_Animation->frames; 34 | glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, s_Animation->width, s_Animation->height, GL_RGBA, GL_UNSIGNED_BYTE, s_Animation->data[s_Frame]); 35 | } 36 | } 37 | 38 | static void OnRender(Renderer& renderer) 39 | { 40 | glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, NULL); 41 | } 42 | 43 | void UpdateAnimation(Animation* animation) 44 | { 45 | SUBMIT_RENDER_3(Animation*&, m_Animation, s_Animation, 46 | Animation*, m_NewAnimation, animation, 47 | uint&, m_TextureID, s_TextureID, { 48 | if (m_Animation) 49 | delete m_Animation; 50 | 51 | m_Animation = m_NewAnimation; 52 | 53 | if (m_TextureID) 54 | glDeleteTextures(1, &m_TextureID); 55 | 56 | glGenTextures(1, &m_TextureID); 57 | glActiveTexture(GL_TEXTURE0); 58 | glBindTexture(GL_TEXTURE_2D, m_TextureID); 59 | 60 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 61 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 62 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 63 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 64 | glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, m_NewAnimation->width, m_NewAnimation->height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); 65 | }); 66 | } 67 | 68 | JNIEXPORT void JNICALL Java_com_thecherno_decompressor_DisplayActivity_00024DisplayRenderer_OnInit(JNIEnv *, jclass) 69 | { 70 | Renderer::Init(); 71 | 72 | s_Shader = ShaderFactory::SimpleShader(); 73 | ShaderManager::Add(s_Shader); 74 | s_Shader->Bind(); 75 | maths::mat4 proj = maths::mat4::Orthographic(-9.0f, 9.0f, -16.0f, 16.0f, -1.0f, 1.0f); 76 | s_Shader->SetUniform("pr_matrix", (byte*)&proj); 77 | 78 | float vertices[] = { 79 | -8.5f, -8.5f, 0.0f, 0.0f, 1.0f, 80 | -8.5f, 8.5f, 0.0f, 0.0f, 0.0f, 81 | 8.5f, 8.5f, 0.0f, 1.0f, 0.0f, 82 | 8.5f, -8.5f, 0.0f, 1.0f, 1.0f 83 | }; 84 | 85 | int indices[] = { 86 | 0, 1, 2, 2, 3, 0 87 | }; 88 | 89 | 90 | uint buffer; 91 | glGenBuffers(1, &buffer); 92 | glBindBuffer(GL_ARRAY_BUFFER, buffer); 93 | glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); 94 | 95 | uint ibo; 96 | glGenBuffers(1, &ibo); 97 | glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo); 98 | glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW); 99 | 100 | glEnableVertexAttribArray(0); 101 | glEnableVertexAttribArray(1); 102 | glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), 0); 103 | glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (const void*)(3 * sizeof(float))); 104 | } 105 | 106 | JNIEXPORT void JNICALL Java_com_thecherno_decompressor_DisplayActivity_00024DisplayRenderer_OnSurfaceChanged(JNIEnv *, jclass, jint width, jint height) 107 | { 108 | float w = 9.0f; 109 | float h = 16.0f; 110 | if (width > height) 111 | { 112 | w = 16.0f; 113 | h = 9.0f; 114 | } 115 | 116 | maths::mat4 proj = maths::mat4::Orthographic(-w, w, -h, h, -1.0f, 1.0f); 117 | s_Shader->SetUniform("pr_matrix", (byte*)&proj); 118 | } 119 | 120 | JNIEXPORT void JNICALL Java_com_thecherno_decompressor_DisplayActivity_00024DisplayRenderer_OnDraw(JNIEnv *, jclass) 121 | { 122 | if (s_SecondTimer == 0.0f) 123 | s_SecondTimer = s_Timer.Elapsed(); 124 | 125 | float now = s_Timer.ElapsedMillis(); 126 | s_Renderer->Clear(); 127 | 128 | if (now - s_UpdateTimer > s_UpdateTick) 129 | { 130 | OnUpdate(); 131 | s_Updates++; 132 | s_UpdateTimer += s_UpdateTick; 133 | } 134 | 135 | { 136 | Timer frametime; 137 | OnRender(*s_Renderer); 138 | s_Renderer->Flush(); 139 | s_Frames++; 140 | s_FrameTime = frametime.ElapsedMillis(); 141 | } 142 | 143 | if (s_Timer.Elapsed() - s_SecondTimer > 1.0f) 144 | { 145 | s_SecondTimer++; 146 | FL_LOG("Perf: %d ups, %d fps", s_Updates, s_Frames); 147 | s_Updates = 0; 148 | s_Frames = 0; 149 | } 150 | } 151 | -------------------------------------------------------------------------------- /Decompressor.Android/jni/com_thecherno_decompressor_DisplayActivity_DisplayRenderer.h: -------------------------------------------------------------------------------- 1 | /* DO NOT EDIT THIS FILE - it is machine generated */ 2 | #include 3 | /* Header for class com_thecherno_decompressor_DisplayActivity_DisplayRenderer */ 4 | 5 | #ifndef _Included_com_thecherno_decompressor_DisplayActivity_DisplayRenderer 6 | #define _Included_com_thecherno_decompressor_DisplayActivity_DisplayRenderer 7 | #ifdef __cplusplus 8 | extern "C" { 9 | #endif 10 | /* 11 | * Class: com_thecherno_decompressor_DisplayActivity_DisplayRenderer 12 | * Method: OnInit 13 | * Signature: ()V 14 | */ 15 | JNIEXPORT void JNICALL Java_com_thecherno_decompressor_DisplayActivity_00024DisplayRenderer_OnInit 16 | (JNIEnv *, jclass); 17 | 18 | /* 19 | * Class: com_thecherno_decompressor_DisplayActivity_DisplayRenderer 20 | * Method: OnSurfaceChanged 21 | * Signature: (II)V 22 | */ 23 | JNIEXPORT void JNICALL Java_com_thecherno_decompressor_DisplayActivity_00024DisplayRenderer_OnSurfaceChanged 24 | (JNIEnv *, jclass, jint, jint); 25 | 26 | /* 27 | * Class: com_thecherno_decompressor_DisplayActivity_DisplayRenderer 28 | * Method: OnDraw 29 | * Signature: ()V 30 | */ 31 | JNIEXPORT void JNICALL Java_com_thecherno_decompressor_DisplayActivity_00024DisplayRenderer_OnDraw 32 | (JNIEnv *, jclass); 33 | 34 | #ifdef __cplusplus 35 | } 36 | #endif 37 | #endif 38 | -------------------------------------------------------------------------------- /Decompressor.Android/res/layout/display_layout.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 17 | 18 | -------------------------------------------------------------------------------- /Decompressor.Android/res/layout/main_layout.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 16 | 17 | 23 | 24 | 30 | 31 | 37 | 38 | 44 | 45 | 51 | 52 | 56 | 57 |