{"action":"created","comment":{"url":"https://api.github.com/repos/citra-emu/citra/pulls/comments/70630881","id":70630881,"diff_hunk":"@@ -2,95 +2,2591 @@\n // Licensed under GPLv2 or any later version\n // Refer to the license.txt file included.\n \n+#include \"common/alignment.h\"\n #include \"common/common_types.h\"\n #include \"common/logging/log.h\"\n+#include \"common/scope_exit.h\"\n+#include \"common/swap.h\"\n \n+#include \"core/arm/arm_interface.h\"\n+#include \"core/hle/kernel/process.h\"\n+#include \"core/hle/kernel/vm_manager.h\"\n #include \"core/hle/service/ldr_ro.h\"\n \n ////////////////////////////////////////////////////////////////////////////////////////////////////\n // Namespace LDR_RO\n \n namespace LDR_RO {\n \n+// GCC versions < 5.0 do not implement std::is_trivially_copyable.\n+// Excluding MSVC because it has weird behaviour for std::is_trivially_copyable.\n+#if (__GNUC__ >= 5) || defined(__clang__)\n+    #define ASSERT_CRO_STRUCT(name, size) \\\n+        static_assert(std::is_standard_layout<name>::value, \"CRO structure \" #name \" doesn't use standard layout\"); \\\n+        static_assert(std::is_trivially_copyable<name>::value, \"CRO structure \" #name \" isn't trivially copyable\"); \\\n+        static_assert(sizeof(name) == (size), \"Unexpected struct size for CRO structure \" #name)\n+#else\n+    #define ASSERT_CRO_STRUCT(name, size) \\\n+        static_assert(std::is_standard_layout<name>::value, \"CRO structure \" #name \" doesn't use standard layout\"); \\\n+        static_assert(sizeof(name) == (size), \"Unexpected struct size for CRO structure \" #name)\n+#endif\n+\n+static constexpr u32 CRO_HEADER_SIZE = 0x138;\n+static constexpr u32 CRO_HASH_SIZE = 0x80;\n+\n+static const ResultCode ERROR_ALREADY_INITIALIZED =   // 0xD9612FF9\n+    ResultCode(ErrorDescription::AlreadyInitialized,         ErrorModule::RO, ErrorSummary::Internal,        ErrorLevel::Permanent);\n+static const ResultCode ERROR_NOT_INITIALIZED =       // 0xD9612FF8\n+    ResultCode(ErrorDescription::NotInitialized,             ErrorModule::RO, ErrorSummary::Internal,        ErrorLevel::Permanent);\n+static const ResultCode ERROR_BUFFER_TOO_SMALL =      // 0xE0E12C1F\n+    ResultCode(static_cast<ErrorDescription>(31),            ErrorModule::RO, ErrorSummary::InvalidArgument, ErrorLevel::Usage);\n+static const ResultCode ERROR_MISALIGNED_ADDRESS =    // 0xD9012FF1\n+    ResultCode(ErrorDescription::MisalignedAddress,          ErrorModule::RO, ErrorSummary::WrongArgument,   ErrorLevel::Permanent);\n+static const ResultCode ERROR_MISALIGNED_SIZE =       // 0xD9012FF2\n+    ResultCode(ErrorDescription::MisalignedSize,             ErrorModule::RO, ErrorSummary::WrongArgument,   ErrorLevel::Permanent);\n+static const ResultCode ERROR_ILLEGAL_ADDRESS =       // 0xE1612C0F\n+    ResultCode(static_cast<ErrorDescription>(15),            ErrorModule::RO, ErrorSummary::Internal,        ErrorLevel::Usage);\n+static const ResultCode ERROR_INVALID_MEMORY_STATE =  // 0xD8A12C08\n+    ResultCode(static_cast<ErrorDescription>(8),             ErrorModule::RO, ErrorSummary::InvalidState,    ErrorLevel::Permanent);\n+static const ResultCode ERROR_NOT_LOADED =            // 0xD8A12C0D\n+    ResultCode(static_cast<ErrorDescription>(13),            ErrorModule::RO, ErrorSummary::InvalidState,    ErrorLevel::Permanent);\n+static const ResultCode ERROR_INVALID_DESCRIPTOR =    // 0xD9001830\n+    ResultCode(ErrorDescription::OS_InvalidBufferDescriptor, ErrorModule::OS, ErrorSummary::WrongArgument,   ErrorLevel::Permanent);\n+\n+static ResultCode CROFormatError(u32 description) {\n+    return ResultCode(static_cast<ErrorDescription>(description), ErrorModule::RO, ErrorSummary::WrongArgument, ErrorLevel::Permanent);\n+}\n+\n+class CROHelper {\n+    const VAddr address; ///< the virtual address of this module\n+\n+    enum HeaderField {\n+        Magic = 0,\n+        NameOffset,\n+        NextCRO,\n+        PreviousCRO,\n+        FileSize,\n+        BssSize,\n+        FixedSize,\n+        UnknownZero,\n+        UnkSegmentTag,\n+        OnLoadSegmentTag,\n+        OnExitSegmentTag,\n+        OnUnresolvedSegmentTag,\n+\n+        CodeOffset,\n+        CodeSize,\n+        DataOffset,\n+        DataSize,\n+        ModuleNameOffset,\n+        ModuleNameSize,\n+        SegmentTableOffset,\n+        SegmentNum,\n+\n+        ExportNamedSymbolTableOffset,\n+        ExportNamedSymbolNum,\n+        ExportIndexedSymbolTableOffset,\n+        ExportIndexedSymbolNum,\n+        ExportStringsOffset,\n+        ExportStringsSize,\n+        ExportTreeTableOffset,\n+        ExportTreeNum,\n+\n+        ImportModuleTableOffset,\n+        ImportModuleNum,\n+        ExternalPatchTableOffset,\n+        ExternalPatchNum,\n+        ImportNamedSymbolTableOffset,\n+        ImportNamedSymbolNum,\n+        ImportIndexedSymbolTableOffset,\n+        ImportIndexedSymbolNum,\n+        ImportAnonymousSymbolTableOffset,\n+        ImportAnonymousSymbolNum,\n+        ImportStringsOffset,\n+        ImportStringsSize,\n+\n+        StaticAnonymousSymbolTableOffset,\n+        StaticAnonymousSymbolNum,\n+        InternalPatchTableOffset,\n+        InternalPatchNum,\n+        StaticPatchTableOffset,\n+        StaticPatchNum,\n+        Fix0Barrier,\n+\n+        Fix3Barrier = ExportNamedSymbolTableOffset,\n+        Fix2Barrier = ImportModuleTableOffset,\n+        Fix1Barrier = StaticAnonymousSymbolTableOffset,\n+    };\n+    static_assert(Fix0Barrier == (CRO_HEADER_SIZE - CRO_HASH_SIZE) / 4, \"CRO Header fields are wrong!\");\n+\n+    enum class SegmentType : u32 {\n+        Code   = 0,\n+        ROData = 1,\n+        Data   = 2,\n+        BSS    = 3,\n+    };\n+\n+    union SegmentTag {\n+        u32_le raw;\n+        BitField<0, 4, u32_le> segment_index;\n+        BitField<4, 28, u32_le> offset_into_segment;\n+        SegmentTag() = default;\n+        SegmentTag(u32 raw_) : raw(raw_) {}\n+    };\n+\n+    struct SegmentEntry {\n+        u32_le offset;\n+        u32_le size;\n+        SegmentType type;\n+        static constexpr HeaderField TABLE_OFFSET_FIELD = SegmentTableOffset;\n+    };\n+    ASSERT_CRO_STRUCT(SegmentEntry, 12);\n+\n+    struct ExportNamedSymbolEntry {\n+        u32_le name_offset;         // pointing to a substring in ExportStrings\n+        SegmentTag symbol_position; // to self's segment\n+        static constexpr HeaderField TABLE_OFFSET_FIELD = ExportNamedSymbolTableOffset;\n+    };\n+    ASSERT_CRO_STRUCT(ExportNamedSymbolEntry, 8);\n+\n+    struct ExportIndexedSymbolEntry {\n+        SegmentTag symbol_position; // to self's segment\n+        static constexpr HeaderField TABLE_OFFSET_FIELD = ExportIndexedSymbolTableOffset;\n+    };\n+    ASSERT_CRO_STRUCT(ExportIndexedSymbolEntry, 4);\n+\n+    struct ExportTreeEntry {\n+        u16_le test_bit; // bit sddress into the name to test\n+        union Child{\n+            u16_le raw;\n+            BitField<0, 15, u16_le> next_index;\n+            BitField<15, 1, u16_le> is_end;\n+        } left, right;\n+        u16_le export_table_index; // index of an ExportNamedSymbolEntry\n+        static constexpr HeaderField TABLE_OFFSET_FIELD = ExportTreeTableOffset;\n+    };\n+    ASSERT_CRO_STRUCT(ExportTreeEntry, 8);\n+\n+    struct ImportNamedSymbolEntry {\n+        u32_le name_offset;        // pointing to a substring in ImportStrings\n+        u32_le patch_batch_offset; // pointing to a patch batch in ExternalPatchTable\n+        static constexpr HeaderField TABLE_OFFSET_FIELD = ImportNamedSymbolTableOffset;\n+    };\n+    ASSERT_CRO_STRUCT(ImportNamedSymbolEntry, 8);\n+\n+    struct ImportIndexedSymbolEntry {\n+        u32_le index;              // index of an opponent's ExportIndexedSymbolEntry\n+        u32_le patch_batch_offset; // pointing to a patch batch in ExternalPatchTable\n+        static constexpr HeaderField TABLE_OFFSET_FIELD = ImportIndexedSymbolTableOffset;\n+    };\n+    ASSERT_CRO_STRUCT(ImportIndexedSymbolEntry, 8);\n+\n+    struct ImportAnonymousSymbolEntry {\n+        SegmentTag symbol_position; // to the opponent's segment\n+        u32_le patch_batch_offset;  // pointing to a patch batch in ExternalPatchTable\n+        static constexpr HeaderField TABLE_OFFSET_FIELD = ImportAnonymousSymbolTableOffset;\n+    };\n+    ASSERT_CRO_STRUCT(ImportAnonymousSymbolEntry, 8);\n+\n+    struct ImportModuleEntry {\n+        u32_le name_offset;                          // pointing to a substring in ImporStrings\n+        u32_le import_indexed_symbol_table_offset;   // pointing to a subtable in ImportIndexedSymbolTable\n+        u32_le import_indexed_symbol_num;\n+        u32_le import_anonymous_symbol_table_offset; // pointing to a subtable in ImportAnonymousSymbolTable\n+        u32_le import_anonymous_symbol_num;\n+        static constexpr HeaderField TABLE_OFFSET_FIELD = ImportModuleTableOffset;\n+\n+        void GetImportIndexedSymbolEntry(u32 index, ImportIndexedSymbolEntry& entry) {\n+            Memory::ReadBlock(import_indexed_symbol_table_offset + index * sizeof(ImportIndexedSymbolEntry),\n+                &entry, sizeof(ImportIndexedSymbolEntry));\n+        }\n+\n+        void GetImportAnonymousSymbolEntry(u32 index, ImportAnonymousSymbolEntry& entry) {\n+            Memory::ReadBlock(import_anonymous_symbol_table_offset + index * sizeof(ImportAnonymousSymbolEntry),\n+                &entry, sizeof(ImportAnonymousSymbolEntry));\n+        }\n+    };\n+    ASSERT_CRO_STRUCT(ImportModuleEntry, 20);\n+\n+    enum class PatchType : u8 {\n+        Nothing                = 0,\n+        AbsoluteAddress        = 2,\n+        RelativeAddress        = 3,\n+        ThumbBranch            = 10,\n+        ArmBranch              = 28,\n+        ModifyArmBranch        = 29,\n+        AbsoluteAddress2       = 38,\n+        AlignedRelativeAddress = 42,\n+    };\n+\n+    struct PatchEntry {\n+        SegmentTag target_position; // to self's segment as an ExternalPatchEntry; to static module segment as a StaticPatchEntry\n+        PatchType type;\n+        u8 is_batch_end;\n+        u8 is_batch_resolved;       // set at a batch beginning if the batch is resolved\n+        INSERT_PADDING_BYTES(1);\n+        u32_le shift;\n+    };\n+\n+    struct ExternalPatchEntry : PatchEntry {\n+        static constexpr HeaderField TABLE_OFFSET_FIELD = ExternalPatchTableOffset;\n+    };\n+    ASSERT_CRO_STRUCT(ExternalPatchEntry, 12);\n+\n+    struct StaticPatchEntry : PatchEntry {\n+        static constexpr HeaderField TABLE_OFFSET_FIELD = StaticPatchTableOffset;\n+    };\n+    ASSERT_CRO_STRUCT(StaticPatchEntry, 12);\n+\n+    struct InternalPatchEntry {\n+        SegmentTag target_position; // to self's segment\n+        PatchType type;\n+        u8 symbol_segment;\n+        INSERT_PADDING_BYTES(2);\n+        u32_le shift;\n+        static constexpr HeaderField TABLE_OFFSET_FIELD = InternalPatchTableOffset;\n+    };\n+    ASSERT_CRO_STRUCT(InternalPatchEntry, 12);\n+\n+    struct StaticAnonymousSymbolEntry {\n+        SegmentTag symbol_position; // to self's segment\n+        u32_le patch_batch_offset;  // pointing to a patch batch in StaticPatchTable\n+        static constexpr HeaderField TABLE_OFFSET_FIELD = StaticAnonymousSymbolTableOffset;\n+    };\n+    ASSERT_CRO_STRUCT(StaticAnonymousSymbolEntry, 8);\n+\n+    static std::array<int, 17> ENTRY_SIZE;\n+    static std::array<HeaderField, 4> FIX_BARRIERS;\n+\n+    static constexpr u32 MAGIC_CRO0 = 0x304F5243;\n+    static constexpr u32 MAGIC_FIXD = 0x44584946;\n+\n+    VAddr Field(HeaderField field) {\n+        return address + CRO_HASH_SIZE + field * 4;\n+    }\n+\n+    u32 GetField(HeaderField field) {\n+        return Memory::Read32(Field(field));\n+    }\n+\n+    void SetField(HeaderField field, u32 value) {\n+        Memory::Write32(Field(field), value);\n+    }\n+\n+    VAddr Next() {\n+        return GetField(NextCRO);\n+    }\n+\n+    VAddr Previous() {\n+        return GetField(PreviousCRO);\n+    }\n+\n+    void SetNext(VAddr next) {\n+        SetField(NextCRO, next);\n+    }\n+\n+    void SetPrevious(VAddr next) {\n+        SetField(PreviousCRO, next);\n+    }\n+\n+    /**\n+     * Iterates over all registered auto-link modules, including the static module.\n+     * @param crs_address the virtual address of the static module\n+     * @param func a function object to operate on a module. It accepts one parameter\n+     *        CROHelper and returns ResultVal<bool>. It should return true to continue the iteration,\n+     *        false to stop the iteration, or an error code (which will also stop the iteration).\n+     * @returns ResultCode indicating the result of the operation, RESULT_SUCCESS if all iteration success,\n+     *         otherwise error code of the last iteration.\n+     */\n+    template <typename T>\n+    static ResultCode ForEachAutoLinkCRO(VAddr crs_address, T func) {\n+        VAddr current = crs_address;\n+        while (current) {\n+            CROHelper cro(current);\n+            CASCADE_RESULT(bool next, func(cro));\n+            if (!next)\n+                break;\n+            current = cro.Next();\n+        }\n+        return RESULT_SUCCESS;\n+    }\n+\n+    /**\n+     * Reads an entry in one of module tables.\n+     * @param index index of the entry\n+     * @param data where to put the read entry\n+     * @note the entry type must have the static member TABLE_OFFSET_FIELD\n+     *       indicating which table the entry is in.\n+     */\n+    template <typename T>\n+    void GetEntry(int index, T& data) {\n+        Memory::ReadBlock(GetField(T::TABLE_OFFSET_FIELD) + index * sizeof(T), &data, sizeof(T));\n+    }\n+\n+    /**\n+     * Writes an entry to one of module tables.\n+     * @param index index of the entry\n+     * @param data the entry data to write\n+     * @note the entry type must have the static member TABLE_OFFSET_FIELD\n+     *       indicating which table the entry is in.\n+     */\n+    template <typename T>\n+    void SetEntry(int index, const T& data) {\n+        Memory::WriteBlock(GetField(T::TABLE_OFFSET_FIELD) + index * sizeof(T), &data, sizeof(T));\n+    }\n+\n+    /// Converts a segment tag to virtual address in this module. Returns 0 if invalid.\n+    VAddr SegmentTagToAddress(SegmentTag segment_tag) {\n+        u32 segment_num = GetField(SegmentNum);\n+\n+        if (segment_tag.segment_index >= segment_num)\n+            return 0;\n+\n+        SegmentEntry entry;\n+        GetEntry(segment_tag.segment_index, entry);\n+\n+        if (segment_tag.offset_into_segment >= entry.size)\n+            return 0;\n+\n+        return entry.offset + segment_tag.offset_into_segment;\n+    }\n+\n+    /**\n+     * Finds a exported named symbol in this module.\n+     * @param name the name of the symbol to find\n+     * @return VAddr the virtual address of the symbol. 0 if not found.\n+     */\n+    VAddr FindExportNamedSymbol(const std::string& name) {\n+        if (!GetField(ExportTreeNum))\n+            return 0;\n+\n+        u32 len = name.size();","path":"src/core/hle/service/ldr_ro.cpp","position":362,"original_position":362,"commit_id":"186f93590bd807f6b97f18011a26d2b117491bd9","original_commit_id":"186f93590bd807f6b97f18011a26d2b117491bd9","user":{"login":"lioncash","id":712067,"avatar_url":"https://avatars.githubusercontent.com/u/712067?v=3","gravatar_id":"","url":"https://api.github.com/users/lioncash","html_url":"https://github.com/lioncash","followers_url":"https://api.github.com/users/lioncash/followers","following_url":"https://api.github.com/users/lioncash/following{/other_user}","gists_url":"https://api.github.com/users/lioncash/gists{/gist_id}","starred_url":"https://api.github.com/users/lioncash/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/lioncash/subscriptions","organizations_url":"https://api.github.com/users/lioncash/orgs","repos_url":"https://api.github.com/users/lioncash/repos","events_url":"https://api.github.com/users/lioncash/events{/privacy}","received_events_url":"https://api.github.com/users/lioncash/received_events","type":"User","site_admin":false},"body":"```cpp\r\nsize_t length = name.size();\r\n```","created_at":"2016-07-13T14:05:05Z","updated_at":"2016-07-13T14:05:05Z","html_url":"https://github.com/citra-emu/citra/pull/1948#discussion_r70630881","pull_request_url":"https://api.github.com/repos/citra-emu/citra/pulls/1948","_links":{"self":{"href":"https://api.github.com/repos/citra-emu/citra/pulls/comments/70630881"},"html":{"href":"https://github.com/citra-emu/citra/pull/1948#discussion_r70630881"},"pull_request":{"href":"https://api.github.com/repos/citra-emu/citra/pulls/1948"}}},"pull_request":{"url":"https://api.github.com/repos/citra-emu/citra/pulls/1948","id":77278075,"html_url":"https://github.com/citra-emu/citra/pull/1948","diff_url":"https://github.com/citra-emu/citra/pull/1948.diff","patch_url":"https://github.com/citra-emu/citra/pull/1948.patch","issue_url":"https://api.github.com/repos/citra-emu/citra/issues/1948","number":1948,"state":"open","locked":false,"title":"Implemented CRO","user":{"login":"wwylele","id":4592895,"avatar_url":"https://avatars.githubusercontent.com/u/4592895?v=3","gravatar_id":"","url":"https://api.github.com/users/wwylele","html_url":"https://github.com/wwylele","followers_url":"https://api.github.com/users/wwylele/followers","following_url":"https://api.github.com/users/wwylele/following{/other_user}","gists_url":"https://api.github.com/users/wwylele/gists{/gist_id}","starred_url":"https://api.github.com/users/wwylele/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/wwylele/subscriptions","organizations_url":"https://api.github.com/users/wwylele/orgs","repos_url":"https://api.github.com/users/wwylele/repos","events_url":"https://api.github.com/users/wwylele/events{/privacy}","received_events_url":"https://api.github.com/users/wwylele/received_events","type":"User","site_admin":false},"body":"_Be prepared. If this is merged, we will begin to get ton of issues from Pokemon fans._\r\n\r\nCredits to @Subv for his original cro branch, which provides me the necessary starting point and guides me a looooot!\r\n\r\nThis PR is here for review, but not for merging soon, for there are two work-around/hack in the code:\r\n - clearing ARM instruction cache. The second commit is a naive implement which just makes it work, but as it in #1946 , we may need a refactor/cleanup for our interpreter.\r\n - memory aliasing, which CRO heavily relies on but is not implemented yet. I made a `MemorySynchronizer` which copies memory back and forth to simulate the aliasing behaviour. \r\n\r\nThese two are beyond the scope of this PR, and I want to leave them to others. Please focus on the CRO implement part when reviewing.\r\n\r\nI wrote a [document](https://gist.github.com/wwylele/325d53ee6a0f1dff6aa3473377335d93) to explain how CRO works, hoping it can help one review.\r\n\r\nNote that I changed many function names which comes from 3dbrew, because I believe they were wrong, according to their behaviour.\r\n\r\nMost code  is \"tested\" by only commercial games but not homebrew test. I have no idea how to write homebrew test for CRO. Since CRO are verified by signature on real 3DS, I think it is impossible to make a homebrew CRO.\r\n\r\n[__Tested games using CRO__](https://gist.github.com/wwylele/abd0c87cf10ace41db231e3c87b95969). Thanks to @HyperGainZ, @Leo626 and many others for helping me test!\r\nNot all games using CRO run well. There are probably mistakes in CRO implement, or they are experiencing other issues. But I think this PR is a good starting point where we can gradually fix them.","created_at":"2016-07-13T12:14:32Z","updated_at":"2016-07-13T14:05:05Z","closed_at":null,"merged_at":null,"merge_commit_sha":"13d0aea6fefc044e4adf47c7fdfbf3079122e076","assignee":null,"assignees":[],"milestone":null,"commits_url":"https://api.github.com/repos/citra-emu/citra/pulls/1948/commits","review_comments_url":"https://api.github.com/repos/citra-emu/citra/pulls/1948/comments","review_comment_url":"https://api.github.com/repos/citra-emu/citra/pulls/comments{/number}","comments_url":"https://api.github.com/repos/citra-emu/citra/issues/1948/comments","statuses_url":"https://api.github.com/repos/citra-emu/citra/statuses/186f93590bd807f6b97f18011a26d2b117491bd9","head":{"label":"wwylele:cro++","ref":"cro++","sha":"186f93590bd807f6b97f18011a26d2b117491bd9","user":{"login":"wwylele","id":4592895,"avatar_url":"https://avatars.githubusercontent.com/u/4592895?v=3","gravatar_id":"","url":"https://api.github.com/users/wwylele","html_url":"https://github.com/wwylele","followers_url":"https://api.github.com/users/wwylele/followers","following_url":"https://api.github.com/users/wwylele/following{/other_user}","gists_url":"https://api.github.com/users/wwylele/gists{/gist_id}","starred_url":"https://api.github.com/users/wwylele/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/wwylele/subscriptions","organizations_url":"https://api.github.com/users/wwylele/orgs","repos_url":"https://api.github.com/users/wwylele/repos","events_url":"https://api.github.com/users/wwylele/events{/privacy}","received_events_url":"https://api.github.com/users/wwylele/received_events","type":"User","site_admin":false},"repo":{"id":53776373,"name":"citra","full_name":"wwylele/citra","owner":{"login":"wwylele","id":4592895,"avatar_url":"https://avatars.githubusercontent.com/u/4592895?v=3","gravatar_id":"","url":"https://api.github.com/users/wwylele","html_url":"https://github.com/wwylele","followers_url":"https://api.github.com/users/wwylele/followers","following_url":"https://api.github.com/users/wwylele/following{/other_user}","gists_url":"https://api.github.com/users/wwylele/gists{/gist_id}","starred_url":"https://api.github.com/users/wwylele/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/wwylele/subscriptions","organizations_url":"https://api.github.com/users/wwylele/orgs","repos_url":"https://api.github.com/users/wwylele/repos","events_url":"https://api.github.com/users/wwylele/events{/privacy}","received_events_url":"https://api.github.com/users/wwylele/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/wwylele/citra","description":"Nintendo 3DS Emulator","fork":true,"url":"https://api.github.com/repos/wwylele/citra","forks_url":"https://api.github.com/repos/wwylele/citra/forks","keys_url":"https://api.github.com/repos/wwylele/citra/keys{/key_id}","collaborators_url":"https://api.github.com/repos/wwylele/citra/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/wwylele/citra/teams","hooks_url":"https://api.github.com/repos/wwylele/citra/hooks","issue_events_url":"https://api.github.com/repos/wwylele/citra/issues/events{/number}","events_url":"https://api.github.com/repos/wwylele/citra/events","assignees_url":"https://api.github.com/repos/wwylele/citra/assignees{/user}","branches_url":"https://api.github.com/repos/wwylele/citra/branches{/branch}","tags_url":"https://api.github.com/repos/wwylele/citra/tags","blobs_url":"https://api.github.com/repos/wwylele/citra/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/wwylele/citra/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/wwylele/citra/git/refs{/sha}","trees_url":"https://api.github.com/repos/wwylele/citra/git/trees{/sha}","statuses_url":"https://api.github.com/repos/wwylele/citra/statuses/{sha}","languages_url":"https://api.github.com/repos/wwylele/citra/languages","stargazers_url":"https://api.github.com/repos/wwylele/citra/stargazers","contributors_url":"https://api.github.com/repos/wwylele/citra/contributors","subscribers_url":"https://api.github.com/repos/wwylele/citra/subscribers","subscription_url":"https://api.github.com/repos/wwylele/citra/subscription","commits_url":"https://api.github.com/repos/wwylele/citra/commits{/sha}","git_commits_url":"https://api.github.com/repos/wwylele/citra/git/commits{/sha}","comments_url":"https://api.github.com/repos/wwylele/citra/comments{/number}","issue_comment_url":"https://api.github.com/repos/wwylele/citra/issues/comments{/number}","contents_url":"https://api.github.com/repos/wwylele/citra/contents/{+path}","compare_url":"https://api.github.com/repos/wwylele/citra/compare/{base}...{head}","merges_url":"https://api.github.com/repos/wwylele/citra/merges","archive_url":"https://api.github.com/repos/wwylele/citra/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/wwylele/citra/downloads","issues_url":"https://api.github.com/repos/wwylele/citra/issues{/number}","pulls_url":"https://api.github.com/repos/wwylele/citra/pulls{/number}","milestones_url":"https://api.github.com/repos/wwylele/citra/milestones{/number}","notifications_url":"https://api.github.com/repos/wwylele/citra/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/wwylele/citra/labels{/name}","releases_url":"https://api.github.com/repos/wwylele/citra/releases{/id}","deployments_url":"https://api.github.com/repos/wwylele/citra/deployments","created_at":"2016-03-13T09:09:07Z","updated_at":"2016-06-30T11:06:41Z","pushed_at":"2016-07-13T12:01:28Z","git_url":"git://github.com/wwylele/citra.git","ssh_url":"git@github.com:wwylele/citra.git","clone_url":"https://github.com/wwylele/citra.git","svn_url":"https://github.com/wwylele/citra","homepage":"https://citra-emu.org","size":13164,"stargazers_count":6,"watchers_count":6,"language":"C++","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":1,"mirror_url":null,"open_issues_count":3,"forks":1,"open_issues":3,"watchers":6,"default_branch":"master"}},"base":{"label":"citra-emu:master","ref":"master","sha":"ffda82eea546830d15284810e91e58c5b6627a0c","user":{"login":"citra-emu","id":7605670,"avatar_url":"https://avatars.githubusercontent.com/u/7605670?v=3","gravatar_id":"","url":"https://api.github.com/users/citra-emu","html_url":"https://github.com/citra-emu","followers_url":"https://api.github.com/users/citra-emu/followers","following_url":"https://api.github.com/users/citra-emu/following{/other_user}","gists_url":"https://api.github.com/users/citra-emu/gists{/gist_id}","starred_url":"https://api.github.com/users/citra-emu/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/citra-emu/subscriptions","organizations_url":"https://api.github.com/users/citra-emu/orgs","repos_url":"https://api.github.com/users/citra-emu/repos","events_url":"https://api.github.com/users/citra-emu/events{/privacy}","received_events_url":"https://api.github.com/users/citra-emu/received_events","type":"Organization","site_admin":false},"repo":{"id":19866730,"name":"citra","full_name":"citra-emu/citra","owner":{"login":"citra-emu","id":7605670,"avatar_url":"https://avatars.githubusercontent.com/u/7605670?v=3","gravatar_id":"","url":"https://api.github.com/users/citra-emu","html_url":"https://github.com/citra-emu","followers_url":"https://api.github.com/users/citra-emu/followers","following_url":"https://api.github.com/users/citra-emu/following{/other_user}","gists_url":"https://api.github.com/users/citra-emu/gists{/gist_id}","starred_url":"https://api.github.com/users/citra-emu/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/citra-emu/subscriptions","organizations_url":"https://api.github.com/users/citra-emu/orgs","repos_url":"https://api.github.com/users/citra-emu/repos","events_url":"https://api.github.com/users/citra-emu/events{/privacy}","received_events_url":"https://api.github.com/users/citra-emu/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/citra-emu/citra","description":"Nintendo 3DS Emulator","fork":false,"url":"https://api.github.com/repos/citra-emu/citra","forks_url":"https://api.github.com/repos/citra-emu/citra/forks","keys_url":"https://api.github.com/repos/citra-emu/citra/keys{/key_id}","collaborators_url":"https://api.github.com/repos/citra-emu/citra/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/citra-emu/citra/teams","hooks_url":"https://api.github.com/repos/citra-emu/citra/hooks","issue_events_url":"https://api.github.com/repos/citra-emu/citra/issues/events{/number}","events_url":"https://api.github.com/repos/citra-emu/citra/events","assignees_url":"https://api.github.com/repos/citra-emu/citra/assignees{/user}","branches_url":"https://api.github.com/repos/citra-emu/citra/branches{/branch}","tags_url":"https://api.github.com/repos/citra-emu/citra/tags","blobs_url":"https://api.github.com/repos/citra-emu/citra/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/citra-emu/citra/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/citra-emu/citra/git/refs{/sha}","trees_url":"https://api.github.com/repos/citra-emu/citra/git/trees{/sha}","statuses_url":"https://api.github.com/repos/citra-emu/citra/statuses/{sha}","languages_url":"https://api.github.com/repos/citra-emu/citra/languages","stargazers_url":"https://api.github.com/repos/citra-emu/citra/stargazers","contributors_url":"https://api.github.com/repos/citra-emu/citra/contributors","subscribers_url":"https://api.github.com/repos/citra-emu/citra/subscribers","subscription_url":"https://api.github.com/repos/citra-emu/citra/subscription","commits_url":"https://api.github.com/repos/citra-emu/citra/commits{/sha}","git_commits_url":"https://api.github.com/repos/citra-emu/citra/git/commits{/sha}","comments_url":"https://api.github.com/repos/citra-emu/citra/comments{/number}","issue_comment_url":"https://api.github.com/repos/citra-emu/citra/issues/comments{/number}","contents_url":"https://api.github.com/repos/citra-emu/citra/contents/{+path}","compare_url":"https://api.github.com/repos/citra-emu/citra/compare/{base}...{head}","merges_url":"https://api.github.com/repos/citra-emu/citra/merges","archive_url":"https://api.github.com/repos/citra-emu/citra/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/citra-emu/citra/downloads","issues_url":"https://api.github.com/repos/citra-emu/citra/issues{/number}","pulls_url":"https://api.github.com/repos/citra-emu/citra/pulls{/number}","milestones_url":"https://api.github.com/repos/citra-emu/citra/milestones{/number}","notifications_url":"https://api.github.com/repos/citra-emu/citra/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/citra-emu/citra/labels{/name}","releases_url":"https://api.github.com/repos/citra-emu/citra/releases{/id}","deployments_url":"https://api.github.com/repos/citra-emu/citra/deployments","created_at":"2014-05-16T18:33:15Z","updated_at":"2016-07-13T13:58:47Z","pushed_at":"2016-07-13T12:14:32Z","git_url":"git://github.com/citra-emu/citra.git","ssh_url":"git@github.com:citra-emu/citra.git","clone_url":"https://github.com/citra-emu/citra.git","svn_url":"https://github.com/citra-emu/citra","homepage":"https://citra-emu.org","size":20836,"stargazers_count":2042,"watchers_count":2042,"language":"C++","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":499,"mirror_url":null,"open_issues_count":193,"forks":499,"open_issues":193,"watchers":2042,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/citra-emu/citra/pulls/1948"},"html":{"href":"https://github.com/citra-emu/citra/pull/1948"},"issue":{"href":"https://api.github.com/repos/citra-emu/citra/issues/1948"},"comments":{"href":"https://api.github.com/repos/citra-emu/citra/issues/1948/comments"},"review_comments":{"href":"https://api.github.com/repos/citra-emu/citra/pulls/1948/comments"},"review_comment":{"href":"https://api.github.com/repos/citra-emu/citra/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/citra-emu/citra/pulls/1948/commits"},"statuses":{"href":"https://api.github.com/repos/citra-emu/citra/statuses/186f93590bd807f6b97f18011a26d2b117491bd9"}}}}
{"actor":{"display_login":"lioncash"}}