{"action":"created","comment":{"url":"https://api.github.com/repos/citra-emu/citra/pulls/comments/42082335","id":42082335,"diff_hunk":"@@ -0,0 +1,388 @@\n+// Copyright 2015 Citra Emulator Project\n+// Licensed under GPLv2 or any later version\n+// Refer to the license.txt file included.\n+\n+#include \"video_core/pica.h\"\n+#include \"video_core/renderer_opengl/gl_rasterizer.h\"\n+#include \"video_core/renderer_opengl/gl_shader_gen.h\"\n+\n+using Pica::Regs;\n+using TevStageConfig = Regs::TevStageConfig;\n+\n+namespace GLShader {\n+\n+/// Detects if a TEV stage is configured to be skipped (to avoid generating unnecessary code)\n+static bool IsPassThroughTevStage(const TevStageConfig& stage) {\n+    return (stage.color_op             == TevStageConfig::Operation::Replace &&\n+            stage.alpha_op             == TevStageConfig::Operation::Replace &&\n+            stage.color_source1        == TevStageConfig::Source::Previous &&\n+            stage.alpha_source1        == TevStageConfig::Source::Previous &&\n+            stage.color_modifier1      == TevStageConfig::ColorModifier::SourceColor &&\n+            stage.alpha_modifier1      == TevStageConfig::AlphaModifier::SourceAlpha &&\n+            stage.GetColorMultiplier() == 1 &&\n+            stage.GetAlphaMultiplier() == 1);\n+}\n+\n+/// Writes the specified TEV stage source component(s)\n+static void AppendSource(std::string& out, TevStageConfig::Source source,\n+        const std::string& index_name) {\n+    using Source = TevStageConfig::Source;\n+    switch (source) {\n+    case Source::PrimaryColor:\n+        out += \"attr[2]\";\n+        break;\n+    case Source::PrimaryFragmentColor:\n+        // HACK: Until we implement fragment lighting, use primary_color\n+        out += \"attr[2]\";\n+        break;\n+    case Source::SecondaryFragmentColor:\n+        // HACK: Until we implement fragment lighting, use zero\n+        out += \"vec4(0.0, 0.0, 0.0, 0.0)\";\n+        break;\n+    case Source::Texture0:\n+        out += \"texture(tex[0], attr[3].xy)\";\n+        break;\n+    case Source::Texture1:\n+        out += \"texture(tex[1], attr[3].zw)\";\n+        break;\n+    case Source::Texture2: // TODO: Unverified\n+        out += \"texture(tex[2], attr[5].zw)\";\n+        break;\n+    case Source::PreviousBuffer:\n+        out += \"g_combiner_buffer\";\n+        break;\n+    case Source::Constant:\n+        out += \"const_color[\" + index_name + \"]\";\n+        break;\n+    case Source::Previous:\n+        out += \"g_last_tex_env_out\";\n+        break;\n+    default:\n+        out += \"vec4(0.0)\";\n+        LOG_CRITICAL(Render_OpenGL, \"Unknown source op %u\", source);\n+        break;\n+    }\n+}\n+\n+/// Writes the color components to use for the specified TEV stage color modifier\n+static void AppendColorModifier(std::string& out, TevStageConfig::ColorModifier modifier,\n+        TevStageConfig::Source source, const std::string& index_name) {\n+    using ColorModifier = TevStageConfig::ColorModifier;\n+    switch (modifier) {\n+    case ColorModifier::SourceColor:\n+        AppendSource(out, source, index_name);\n+        out += \".rgb\";\n+        break;\n+    case ColorModifier::OneMinusSourceColor:\n+        out += \"vec3(1.0) - \";\n+        AppendSource(out, source, index_name);\n+        out += \".rgb\";\n+        break;\n+    case ColorModifier::SourceAlpha:\n+        AppendSource(out, source, index_name);\n+        out += \".aaa\";\n+        break;\n+    case ColorModifier::OneMinusSourceAlpha:\n+        out += \"vec3(1.0) - \";\n+        AppendSource(out, source, index_name);\n+        out += \".aaa\";\n+        break;\n+    case ColorModifier::SourceRed:\n+        AppendSource(out, source, index_name);\n+        out += \".rrr\";\n+        break;\n+    case ColorModifier::OneMinusSourceRed:\n+        out += \"vec3(1.0) - \";\n+        AppendSource(out, source, index_name);\n+        out += \".rrr\";\n+        break;\n+    case ColorModifier::SourceGreen:\n+        AppendSource(out, source, index_name);\n+        out += \".ggg\";\n+        break;\n+    case ColorModifier::OneMinusSourceGreen:\n+        out += \"vec3(1.0) - \";\n+        AppendSource(out, source, index_name);\n+        out += \".ggg\";\n+        break;\n+    case ColorModifier::SourceBlue:\n+        AppendSource(out, source, index_name);\n+        out += \".bbb\";\n+        break;\n+    case ColorModifier::OneMinusSourceBlue:\n+        out += \"vec3(1.0) - \";\n+        AppendSource(out, source, index_name);\n+        out += \".bbb\";\n+        break;\n+    default:\n+        out += \"vec3(0.0)\";\n+        LOG_CRITICAL(Render_OpenGL, \"Unknown color modifier op %u\", modifier);\n+        break;\n+    }\n+}\n+\n+/// Writes the alpha component to use for the specified TEV stage alpha modifier\n+static void AppendAlphaModifier(std::string& out, TevStageConfig::AlphaModifier modifier,\n+        TevStageConfig::Source source, const std::string& index_name) {\n+    using AlphaModifier = TevStageConfig::AlphaModifier;\n+    switch (modifier) {\n+    case AlphaModifier::SourceAlpha:\n+        AppendSource(out, source, index_name);\n+        out += \".a\";\n+        break;\n+    case AlphaModifier::OneMinusSourceAlpha:\n+        out += \"1.0 - \";\n+        AppendSource(out, source, index_name);\n+        out += \".a\";\n+        break;\n+    case AlphaModifier::SourceRed:\n+        AppendSource(out, source, index_name);\n+        out += \".r\";\n+        break;\n+    case AlphaModifier::OneMinusSourceRed:\n+        out += \"1.0 - \";\n+        AppendSource(out, source, index_name);\n+        out += \".r\";\n+        break;\n+    case AlphaModifier::SourceGreen:\n+        AppendSource(out, source, index_name);\n+        out += \".g\";\n+        break;\n+    case AlphaModifier::OneMinusSourceGreen:\n+        out += \"1.0 - \";\n+        AppendSource(out, source, index_name);\n+        out += \".g\";\n+        break;\n+    case AlphaModifier::SourceBlue:\n+        AppendSource(out, source, index_name);\n+        out += \".b\";\n+        break;\n+    case AlphaModifier::OneMinusSourceBlue:\n+        out += \"1.0 - \";\n+        AppendSource(out, source, index_name);\n+        out += \".b\";\n+        break;\n+    default:\n+        out += \"0.0\";\n+        LOG_CRITICAL(Render_OpenGL, \"Unknown alpha modifier op %u\", modifier);\n+        break;\n+    }\n+}\n+\n+/// Writes the combiner function for the color components for the specified TEV stage operation\n+static void AppendColorCombiner(std::string& out, TevStageConfig::Operation operation,\n+        const std::string& variable_name) {\n+    using Operation = TevStageConfig::Operation;\n+\n+    switch (operation) {\n+    case Operation::Replace:\n+        out += variable_name + \"[0]\";\n+        break;\n+    case Operation::Modulate:\n+        out += variable_name + \"[0] * \" + variable_name + \"[1]\";\n+        break;\n+    case Operation::Add:\n+        out += \"min(\" + variable_name + \"[0] + \" + variable_name + \"[1], vec3(1.0))\";\n+        break;\n+    case Operation::AddSigned:\n+        out += \"clamp(\" + variable_name + \"[0] + \" + variable_name + \"[1] - vec3(0.5), vec3(0.0), vec3(1.0))\";\n+        break;\n+    case Operation::Lerp:\n+        out += variable_name + \"[0] * \" + variable_name + \"[2] + \" + variable_name + \"[1] * (vec3(1.0) - \" + variable_name + \"[2])\";\n+        break;\n+    case Operation::Subtract:\n+        out += \"max(\" + variable_name + \"[0] - \" + variable_name + \"[1], vec3(0.0))\";\n+        break;\n+    case Operation::MultiplyThenAdd:\n+        out += \"min(\" + variable_name + \"[0] * \" + variable_name + \"[1] + \" + variable_name + \"[2], vec3(1.0))\";\n+        break;\n+    case Operation::AddThenMultiply:\n+        out += \"min(\" + variable_name + \"[0] + \" + variable_name + \"[1], vec3(1.0)) * \" + variable_name + \"[2]\";\n+        break;\n+    default:\n+        out += \"vec3(0.0)\";\n+        LOG_CRITICAL(Render_OpenGL, \"Unknown color combiner operation: %u\", operation);\n+        break;\n+    }\n+}\n+\n+/// Writes the combiner function for the alpha component for the specified TEV stage operation\n+static void AppendAlphaCombiner(std::string& out, TevStageConfig::Operation operation,\n+        const std::string& variable_name) {\n+    using Operation = TevStageConfig::Operation;\n+    switch (operation) {\n+    case Operation::Replace:\n+        out += variable_name + \"[0]\";\n+        break;\n+    case Operation::Modulate:\n+        out += variable_name + \"[0] * \" + variable_name + \"[1]\";\n+        break;\n+    case Operation::Add:\n+        out += \"min(\" + variable_name + \"[0] + \" + variable_name + \"[1], 1.0)\";\n+        break;\n+    case Operation::AddSigned:\n+        out += \"clamp(\" + variable_name + \"[0] + \" + variable_name + \"[1] - 0.5, 0.0, 1.0)\";\n+        break;\n+    case Operation::Lerp:\n+        out += variable_name + \"[0] * \" + variable_name + \"[2] + \" + variable_name + \"[1] * (1.0 - \" + variable_name + \"[2])\";\n+        break;\n+    case Operation::Subtract:\n+        out += \"max(\" + variable_name + \"[0] - \" + variable_name + \"[1], 0.0)\";\n+        break;\n+    case Operation::MultiplyThenAdd:\n+        out += \"min(\" + variable_name + \"[0] * \" + variable_name + \"[1] + \" + variable_name + \"[2], 1.0)\";\n+        break;\n+    case Operation::AddThenMultiply:\n+        out += \"min(\" + variable_name + \"[0] + \" + variable_name + \"[1], 1.0) * \" + variable_name + \"[2]\";\n+        break;\n+    default:\n+        out += \"0.0\";\n+        LOG_CRITICAL(Render_OpenGL, \"Unknown alpha combiner operation: %u\", operation);\n+        break;\n+    }\n+}\n+\n+/// Writes the if-statement condition used to evaluate alpha testing\n+static void AppendAlphaTestCondition(std::string& out, Regs::CompareFunc func) {\n+    using CompareFunc = Regs::CompareFunc;\n+    switch (func) {\n+    case CompareFunc::Never:\n+        out += \"true\";\n+        break;\n+    case CompareFunc::Always:\n+        out += \"false\";\n+        break;\n+    case CompareFunc::Equal:\n+        out += \"int(g_last_tex_env_out.a * 255.0f) != alphatest_ref\";\n+        break;\n+    case CompareFunc::NotEqual:\n+        out += \"int(g_last_tex_env_out.a * 255.0f) == alphatest_ref\";\n+        break;\n+    case CompareFunc::LessThan:\n+        out += \"int(g_last_tex_env_out.a * 255.0f) >= alphatest_ref\";\n+        break;\n+    case CompareFunc::LessThanOrEqual:\n+        out += \"int(g_last_tex_env_out.a * 255.0f) > alphatest_ref\";\n+        break;\n+    case CompareFunc::GreaterThan:\n+        out += \"int(g_last_tex_env_out.a * 255.0f) <= alphatest_ref\";\n+        break;\n+    case CompareFunc::GreaterThanOrEqual:\n+        out += \"int(g_last_tex_env_out.a * 255.0f) < alphatest_ref\";\n+        break;\n+    default:\n+        out += \"false\";\n+        LOG_CRITICAL(Render_OpenGL, \"Unknown alpha test condition %u\", func);\n+        break;\n+    }\n+}\n+\n+/// Writes the code to emulate the specified TEV stage\n+static void WriteTevStage(std::string& out, const PicaShaderConfig& config, unsigned index) {\n+    auto& stage = config.tev_stages[index];\n+    if (!IsPassThroughTevStage(stage)) {\n+        std::string index_name = std::to_string(index);\n+\n+        out += \"vec3 color_results_\" + index_name + \"[3] = vec3[3](\";\n+        AppendColorModifier(out, stage.color_modifier1, stage.color_source1, index_name);\n+        out += \", \";\n+        AppendColorModifier(out, stage.color_modifier2, stage.color_source2, index_name);\n+        out += \", \";\n+        AppendColorModifier(out, stage.color_modifier3, stage.color_source3, index_name);\n+        out += \");\\n\";\n+\n+        out += \"vec3 color_output_\" + index_name + \" = \";\n+        AppendColorCombiner(out, stage.color_op, \"color_results_\" + index_name);\n+        out += \";\\n\";\n+\n+        out += \"float alpha_results_\" + index_name + \"[3] = float[3](\";\n+        AppendAlphaModifier(out, stage.alpha_modifier1, stage.alpha_source1, index_name);\n+        out += \", \";\n+        AppendAlphaModifier(out, stage.alpha_modifier2, stage.alpha_source2, index_name);\n+        out += \", \";\n+        AppendAlphaModifier(out, stage.alpha_modifier3, stage.alpha_source3, index_name);\n+        out += \");\\n\";\n+\n+        out += \"float alpha_output_\" + index_name + \" = \";\n+        AppendAlphaCombiner(out, stage.alpha_op, \"alpha_results_\" + index_name);\n+        out += \";\\n\";\n+\n+        out += \"g_last_tex_env_out = vec4(\"\n+            \"clamp(color_output_\" + index_name + \" * \" + std::to_string(stage.GetColorMultiplier()) + \".0, 0.0, 1.0),\"\n+            \"clamp(alpha_output_\" + index_name + \" * \" + std::to_string(stage.GetAlphaMultiplier()) + \".0, 0.0, 1.0));\\n\";\n+    }\n+\n+    if (config.TevStageUpdatesCombinerBufferColor(index))\n+        out += \"g_combiner_buffer.rgb = g_last_tex_env_out.rgb;\\n\";\n+\n+    if (config.TevStageUpdatesCombinerBufferAlpha(index))\n+        out += \"g_combiner_buffer.a = g_last_tex_env_out.a;\\n\";\n+}\n+\n+std::string GenerateFragmentShader(const PicaShaderConfig& config) {\n+    std::string out = R\"(\n+#version 330\n+#extension GL_ARB_explicit_uniform_location : require","path":"src/video_core/renderer_opengl/gl_shader_gen.cpp","position":329,"original_position":325,"commit_id":"e23dba792ecb94cf6358ff423e177ecb5f44137e","original_commit_id":"66ba44df351da695b672cb5c2bd86ea56465cd12","user":{"login":"Zaneo","id":295949,"avatar_url":"https://avatars.githubusercontent.com/u/295949?v=3","gravatar_id":"","url":"https://api.github.com/users/Zaneo","html_url":"https://github.com/Zaneo","followers_url":"https://api.github.com/users/Zaneo/followers","following_url":"https://api.github.com/users/Zaneo/following{/other_user}","gists_url":"https://api.github.com/users/Zaneo/gists{/gist_id}","starred_url":"https://api.github.com/users/Zaneo/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Zaneo/subscriptions","organizations_url":"https://api.github.com/users/Zaneo/orgs","repos_url":"https://api.github.com/users/Zaneo/repos","events_url":"https://api.github.com/users/Zaneo/events{/privacy}","received_events_url":"https://api.github.com/users/Zaneo/received_events","type":"User","site_admin":false},"body":"@yuriks \r\n\r\nFrom wildfire Games, If I am reading this correctly:\r\n\r\n 53% (s) GL_ARB_explicit_uniform_location\r\n\r\nhttp://feedback.wildfiregames.com/report/opengl/\r\nhttp://feedback.wildfiregames.com/report/opengl/feature/GL_ARB_explicit_uniform_location\r\n\r\n","created_at":"2015-10-15T04:25:53Z","updated_at":"2015-10-15T04:25:53Z","html_url":"https://github.com/citra-emu/citra/pull/1187#discussion_r42082335","pull_request_url":"https://api.github.com/repos/citra-emu/citra/pulls/1187","_links":{"self":{"href":"https://api.github.com/repos/citra-emu/citra/pulls/comments/42082335"},"html":{"href":"https://github.com/citra-emu/citra/pull/1187#discussion_r42082335"},"pull_request":{"href":"https://api.github.com/repos/citra-emu/citra/pulls/1187"}}},"pull_request":{"url":"https://api.github.com/repos/citra-emu/citra/pulls/1187","id":46968241,"html_url":"https://github.com/citra-emu/citra/pull/1187","diff_url":"https://github.com/citra-emu/citra/pull/1187.diff","patch_url":"https://github.com/citra-emu/citra/pull/1187.patch","issue_url":"https://api.github.com/repos/citra-emu/citra/issues/1187","number":1187,"state":"open","locked":false,"title":"GLSL Fragment Shader Generation","user":{"login":"bunnei","id":6956688,"avatar_url":"https://avatars.githubusercontent.com/u/6956688?v=3","gravatar_id":"","url":"https://api.github.com/users/bunnei","html_url":"https://github.com/bunnei","followers_url":"https://api.github.com/users/bunnei/followers","following_url":"https://api.github.com/users/bunnei/following{/other_user}","gists_url":"https://api.github.com/users/bunnei/gists{/gist_id}","starred_url":"https://api.github.com/users/bunnei/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/bunnei/subscriptions","organizations_url":"https://api.github.com/users/bunnei/orgs","repos_url":"https://api.github.com/users/bunnei/repos","events_url":"https://api.github.com/users/bunnei/events{/privacy}","received_events_url":"https://api.github.com/users/bunnei/received_events","type":"User","site_admin":false},"body":"This PR adds an initial implementation of GLSL fragment shader generation for the OpenGL HW renderer. It is based off of an initial implementation from @Subv, and some improvements and fixes made by @yuriks. I fixed the remaining (known) bugs and cleaned it up a lot. There are two motivating factors for this PR:\r\n* We previously used a single GLSL shader to emulate TEV/fragment operations, and it was quite gnarly. If you run Citra on an IGP, this may have been a performance bottleneck for you. Instead, these changes now generate fragment shaders (and cache them) as-needed for various Pica configurations, greatly reducing the size of most shader programs and basically removing all branches from the shader code (which are slow). This should improve speed pretty significantly on low-end GPUs, and less significantly (but still noticeable) on discrete GPUs.\r\n* More advanced Pica features (e.g. per-fragment lighting, bump mapping, fog, etc.) are sufficiently complex that it would simply be impractical to keep the \"one shader fits all\" approach. As I've been dabbling with implementing some of these features in parallel, it was important to me to get this groundwork in place.\r\n\r\nEDIT: I recommend reviewing this PR as one large diff, not commit-by-commit. There are several large cleanups/refactors from the initial implementation.","created_at":"2015-10-06T22:48:59Z","updated_at":"2015-10-15T04:25:53Z","closed_at":null,"merged_at":null,"merge_commit_sha":"b00da935c8b85fa1cd5d55e579022aa6007afb79","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/citra-emu/citra/pulls/1187/commits","review_comments_url":"https://api.github.com/repos/citra-emu/citra/pulls/1187/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/1187/comments","statuses_url":"https://api.github.com/repos/citra-emu/citra/statuses/e23dba792ecb94cf6358ff423e177ecb5f44137e","head":{"label":"bunnei:shader-gen","ref":"shader-gen","sha":"e23dba792ecb94cf6358ff423e177ecb5f44137e","user":{"login":"bunnei","id":6956688,"avatar_url":"https://avatars.githubusercontent.com/u/6956688?v=3","gravatar_id":"","url":"https://api.github.com/users/bunnei","html_url":"https://github.com/bunnei","followers_url":"https://api.github.com/users/bunnei/followers","following_url":"https://api.github.com/users/bunnei/following{/other_user}","gists_url":"https://api.github.com/users/bunnei/gists{/gist_id}","starred_url":"https://api.github.com/users/bunnei/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/bunnei/subscriptions","organizations_url":"https://api.github.com/users/bunnei/orgs","repos_url":"https://api.github.com/users/bunnei/repos","events_url":"https://api.github.com/users/bunnei/events{/privacy}","received_events_url":"https://api.github.com/users/bunnei/received_events","type":"User","site_admin":false},"repo":{"id":19964905,"name":"citra","full_name":"bunnei/citra","owner":{"login":"bunnei","id":6956688,"avatar_url":"https://avatars.githubusercontent.com/u/6956688?v=3","gravatar_id":"","url":"https://api.github.com/users/bunnei","html_url":"https://github.com/bunnei","followers_url":"https://api.github.com/users/bunnei/followers","following_url":"https://api.github.com/users/bunnei/following{/other_user}","gists_url":"https://api.github.com/users/bunnei/gists{/gist_id}","starred_url":"https://api.github.com/users/bunnei/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/bunnei/subscriptions","organizations_url":"https://api.github.com/users/bunnei/orgs","repos_url":"https://api.github.com/users/bunnei/repos","events_url":"https://api.github.com/users/bunnei/events{/privacy}","received_events_url":"https://api.github.com/users/bunnei/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/bunnei/citra","description":"Nintendo 3DS emulator/debugger","fork":true,"url":"https://api.github.com/repos/bunnei/citra","forks_url":"https://api.github.com/repos/bunnei/citra/forks","keys_url":"https://api.github.com/repos/bunnei/citra/keys{/key_id}","collaborators_url":"https://api.github.com/repos/bunnei/citra/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/bunnei/citra/teams","hooks_url":"https://api.github.com/repos/bunnei/citra/hooks","issue_events_url":"https://api.github.com/repos/bunnei/citra/issues/events{/number}","events_url":"https://api.github.com/repos/bunnei/citra/events","assignees_url":"https://api.github.com/repos/bunnei/citra/assignees{/user}","branches_url":"https://api.github.com/repos/bunnei/citra/branches{/branch}","tags_url":"https://api.github.com/repos/bunnei/citra/tags","blobs_url":"https://api.github.com/repos/bunnei/citra/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/bunnei/citra/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/bunnei/citra/git/refs{/sha}","trees_url":"https://api.github.com/repos/bunnei/citra/git/trees{/sha}","statuses_url":"https://api.github.com/repos/bunnei/citra/statuses/{sha}","languages_url":"https://api.github.com/repos/bunnei/citra/languages","stargazers_url":"https://api.github.com/repos/bunnei/citra/stargazers","contributors_url":"https://api.github.com/repos/bunnei/citra/contributors","subscribers_url":"https://api.github.com/repos/bunnei/citra/subscribers","subscription_url":"https://api.github.com/repos/bunnei/citra/subscription","commits_url":"https://api.github.com/repos/bunnei/citra/commits{/sha}","git_commits_url":"https://api.github.com/repos/bunnei/citra/git/commits{/sha}","comments_url":"https://api.github.com/repos/bunnei/citra/comments{/number}","issue_comment_url":"https://api.github.com/repos/bunnei/citra/issues/comments{/number}","contents_url":"https://api.github.com/repos/bunnei/citra/contents/{+path}","compare_url":"https://api.github.com/repos/bunnei/citra/compare/{base}...{head}","merges_url":"https://api.github.com/repos/bunnei/citra/merges","archive_url":"https://api.github.com/repos/bunnei/citra/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/bunnei/citra/downloads","issues_url":"https://api.github.com/repos/bunnei/citra/issues{/number}","pulls_url":"https://api.github.com/repos/bunnei/citra/pulls{/number}","milestones_url":"https://api.github.com/repos/bunnei/citra/milestones{/number}","notifications_url":"https://api.github.com/repos/bunnei/citra/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/bunnei/citra/labels{/name}","releases_url":"https://api.github.com/repos/bunnei/citra/releases{/id}","created_at":"2014-05-20T02:28:14Z","updated_at":"2015-06-08T02:39:50Z","pushed_at":"2015-10-13T03:08:29Z","git_url":"git://github.com/bunnei/citra.git","ssh_url":"git@github.com:bunnei/citra.git","clone_url":"https://github.com/bunnei/citra.git","svn_url":"https://github.com/bunnei/citra","homepage":null,"size":12192,"stargazers_count":52,"watchers_count":52,"language":"C++","has_issues":false,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":14,"mirror_url":null,"open_issues_count":0,"forks":14,"open_issues":0,"watchers":52,"default_branch":"master"}},"base":{"label":"citra-emu:master","ref":"master","sha":"addef06081c368928f1e76d929a8f176a6209eb2","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/debugger","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}","created_at":"2014-05-16T18:33:15Z","updated_at":"2015-10-15T04:10:11Z","pushed_at":"2015-10-14T13:10:21Z","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":null,"size":24644,"stargazers_count":1202,"watchers_count":1202,"language":"C++","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":293,"mirror_url":null,"open_issues_count":110,"forks":293,"open_issues":110,"watchers":1202,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/citra-emu/citra/pulls/1187"},"html":{"href":"https://github.com/citra-emu/citra/pull/1187"},"issue":{"href":"https://api.github.com/repos/citra-emu/citra/issues/1187"},"comments":{"href":"https://api.github.com/repos/citra-emu/citra/issues/1187/comments"},"review_comments":{"href":"https://api.github.com/repos/citra-emu/citra/pulls/1187/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/1187/commits"},"statuses":{"href":"https://api.github.com/repos/citra-emu/citra/statuses/e23dba792ecb94cf6358ff423e177ecb5f44137e"}}}}