From b34b6a735fb765a396d968d3c8e16faa65fca625 Mon Sep 17 00:00:00 2001
From: Phillip Stephens <antidote.crk@gmail.com>
Date: Thu, 18 Feb 2016 00:56:11 -0800
Subject: [PATCH 01/22] Initial ModelViewer view

---
 Editor/ModelViewer.cpp | 25 +++++++++++++++++++++++++
 Editor/ModelViewer.hpp | 12 ++++++++++--
 2 files changed, 35 insertions(+), 2 deletions(-)

diff --git a/Editor/ModelViewer.cpp b/Editor/ModelViewer.cpp
index e69de29bb..2b19d1b4f 100644
--- a/Editor/ModelViewer.cpp
+++ b/Editor/ModelViewer.cpp
@@ -0,0 +1,25 @@
+#include "ModelViewer.hpp"
+
+namespace URDE
+{
+
+void ModelViewer::View::resized(const boo::SWindowRect& root, const boo::SWindowRect& sub)
+{
+    Specter::View::resized(root, sub);
+    m_scissorRect = sub;
+}
+
+void ModelViewer::View::draw(boo::IGraphicsCommandQueue* gfxQ)
+{
+    gfxQ->setScissor(m_scissorRect);
+    m_mv.m_lineRenderer->Reset();
+    m_mv.m_lineRenderer->AddVertex({-0.5f, 0.f, -0.5f}, Zeus::CColor::skBlue, 1.f);
+    m_mv.m_lineRenderer->AddVertex({-0.5f, 0.f, 0.5f}, Zeus::CColor::skBlue, 1.f);
+    m_mv.m_lineRenderer->AddVertex({0.5f, 10.f, 0.5f}, Zeus::CColor::skRed, 3.f);
+    m_mv.m_lineRenderer->AddVertex({0.5f, 0.f, -0.5f}, Zeus::CColor::skBlue, 1.f);
+    m_mv.m_lineRenderer->Render();
+    gfxQ->setScissor({});
+}
+
+
+}
diff --git a/Editor/ModelViewer.hpp b/Editor/ModelViewer.hpp
index 33f035e5d..c35b3dc02 100644
--- a/Editor/ModelViewer.hpp
+++ b/Editor/ModelViewer.hpp
@@ -26,13 +26,20 @@ class ModelViewer : public ViewerSpace
     } m_state;
 
     const Space::State& spaceState() const { return m_state; }
-
+    std::unique_ptr<pshag::CLineRenderer> m_lineRenderer;
     struct View : Specter::View
     {
         ModelViewer& m_mv;
+        boo::SWindowRect m_scissorRect;
+
         View(ModelViewer& mv, Specter::ViewResources& res)
             : Specter::View(res, mv.m_vm.rootView()), m_mv(mv)
-        {}
+        {
+            commitResources(res);
+        }
+
+        void resized(const boo::SWindowRect& root, const boo::SWindowRect& sub);
+        void draw(boo::IGraphicsCommandQueue *gfxQ);
     };
 
     Camera m_camera;
@@ -43,6 +50,7 @@ public:
         : ViewerSpace(vm, Class::ModelViewer, parent)
     {
         reloadState();
+        m_lineRenderer.reset(new pshag::CLineRenderer(pshag::CLineRenderer::EPrimitiveMode::LineStrip, 4, nullptr, true));
     }
 
     ModelViewer(ViewManager& vm, Space* parent, const ModelViewer& other)

From 7d07eb5058fd92f4a4c062098366080923c02829 Mon Sep 17 00:00:00 2001
From: Jack Andersen <jackoalan@gmail.com>
Date: Wed, 17 Feb 2016 21:56:14 -1000
Subject: [PATCH 02/22] Fix member visibility derp

---
 Runtime/Graphics/CLineRenderer.hpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Runtime/Graphics/CLineRenderer.hpp b/Runtime/Graphics/CLineRenderer.hpp
index 25cece156..9d23945b6 100644
--- a/Runtime/Graphics/CLineRenderer.hpp
+++ b/Runtime/Graphics/CLineRenderer.hpp
@@ -19,7 +19,7 @@ public:
         LineLoop
     };
 
-public:
+private:
     EPrimitiveMode m_mode;
     u32 m_maxVerts;
     u32 m_nextVert = 0;

From 3045bfae24e228e940b4806c1743b724b59e8fa4 Mon Sep 17 00:00:00 2001
From: Phillip Stephens <antidote.crk@gmail.com>
Date: Thu, 18 Feb 2016 05:06:12 -0800
Subject: [PATCH 03/22] Update hecl

---
 hecl | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/hecl b/hecl
index 92604d9ce..de8d872bf 160000
--- a/hecl
+++ b/hecl
@@ -1 +1 @@
-Subproject commit 92604d9ce5c32aa9a7c58603683b43f2064850b5
+Subproject commit de8d872bfa1f07850389bcbfcec1f1aa957efd69

From 5d3cf64a6bc94bd1696c8b0ff5eaa2b4bd80e2c2 Mon Sep 17 00:00:00 2001
From: Phillip Stephens <antidote.crk@gmail.com>
Date: Thu, 18 Feb 2016 08:14:57 -0800
Subject: [PATCH 04/22] Add missing assignment

---
 Runtime/CTimeProvider.cpp | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/Runtime/CTimeProvider.cpp b/Runtime/CTimeProvider.cpp
index 7642c91b8..4054a9bde 100644
--- a/Runtime/CTimeProvider.cpp
+++ b/Runtime/CTimeProvider.cpp
@@ -12,6 +12,8 @@ CTimeProvider::CTimeProvider(const float& time)
     if (x8_lastProvider != nullptr)
         x8_lastProvider->x4_first = false;
 
+    g_currentTimeProvider = this;
+
 #if 0
     CGraphics::SetExternalTimeProvider(this);
 #endif

From bd0a72a4cb2b347b4585407aedffce95a164e114 Mon Sep 17 00:00:00 2001
From: Jack Andersen <jackoalan@gmail.com>
Date: Thu, 18 Feb 2016 10:53:17 -1000
Subject: [PATCH 05/22] CLineRenderer HLSL shaders

---
 Editor/ViewManager.cpp                        |   2 +-
 Runtime/Graphics/CLineRenderer.cpp            |   5 +-
 Runtime/Graphics/CLineRendererShadersHLSL.cpp | 147 ++++++++++++++++++
 hecl                                          |   2 +-
 4 files changed, 152 insertions(+), 4 deletions(-)

diff --git a/Editor/ViewManager.cpp b/Editor/ViewManager.cpp
index 5581774d9..9439b6791 100644
--- a/Editor/ViewManager.cpp
+++ b/Editor/ViewManager.cpp
@@ -20,7 +20,7 @@ namespace URDE
 
 void ViewManager::BuildTestPART(pshag::IObjectStore& objStore)
 {
-    m_partGenDesc = objStore.GetObj({HECL::FOURCC('PART'), 0x1E348530});
+    m_partGenDesc = objStore.GetObj({HECL::FOURCC('PART'), 0x972A5CD2});
     m_partGen.reset(new pshag::CElementGen(m_partGenDesc,
                                            pshag::CElementGen::EModelOrientationType::Normal,
                                            pshag::CElementGen::EOptionalSystemFlags::None));
diff --git a/Runtime/Graphics/CLineRenderer.cpp b/Runtime/Graphics/CLineRenderer.cpp
index d89e79461..47dc8300a 100644
--- a/Runtime/Graphics/CLineRenderer.cpp
+++ b/Runtime/Graphics/CLineRenderer.cpp
@@ -154,7 +154,7 @@ void CLineRenderer::Reset()
 void CLineRenderer::AddVertex(const Zeus::CVector3f& position, const Zeus::CColor& color, float width,
                               const Zeus::CVector2f& uv)
 {
-    if (!m_shaderBind || m_nextVert >= m_maxVerts)
+    if (m_final || !m_shaderBind || m_nextVert >= m_maxVerts)
         return;
 
     float adjWidth = width / 480.f;
@@ -385,15 +385,16 @@ void CLineRenderer::Render(const Zeus::CColor& moduColor)
 
     SDrawUniform uniformData = {moduColor};
     m_uniformBuf->load(&uniformData, sizeof(SDrawUniform));
-    CGraphics::SetShaderDataBinding(m_shaderBind);
     if (m_textured)
     {
         m_vertBuf->load(g_StaticLineVertsTex.data(), sizeof(SDrawVertTex) * g_StaticLineVertsTex.size());
+        CGraphics::SetShaderDataBinding(m_shaderBind);
         CGraphics::DrawArray(boo::Primitive::TriStrips, 0, g_StaticLineVertsTex.size());
     }
     else
     {
         m_vertBuf->load(g_StaticLineVertsNoTex.data(), sizeof(SDrawVertNoTex) * g_StaticLineVertsNoTex.size());
+        CGraphics::SetShaderDataBinding(m_shaderBind);
         CGraphics::DrawArray(boo::Primitive::TriStrips, 0, g_StaticLineVertsNoTex.size());
     }
 }
diff --git a/Runtime/Graphics/CLineRendererShadersHLSL.cpp b/Runtime/Graphics/CLineRendererShadersHLSL.cpp
index e69de29bb..909d38f03 100644
--- a/Runtime/Graphics/CLineRendererShadersHLSL.cpp
+++ b/Runtime/Graphics/CLineRendererShadersHLSL.cpp
@@ -0,0 +1,147 @@
+#include "CLineRendererShaders.hpp"
+#include "CLineRenderer.hpp"
+
+namespace pshag
+{
+
+static const char* VS_HLSL_TEX =
+"struct VertData\n"
+"{\n"
+"    float4 posIn : POSITION;\n"
+"    float4 colorIn : COLOR;\n"
+"    float4 uvIn : UV;\n"
+"};\n"
+"\n"
+"cbuffer LineUniform : register(b0)\n"
+"{\n"
+"    float4 moduColor;\n"
+"};\n"
+"\n"
+"struct VertToFrag\n"
+"{\n"
+"    float4 position : SV_Position;\n"
+"    float4 color : COLOR;\n"
+"    float2 uv : UV;\n"
+"};\n"
+"\n"
+"VertToFrag main(in VertData v)\n"
+"{\n"
+"    VertToFrag vtf;\n"
+"    vtf.color = v.colorIn * moduColor;\n"
+"    vtf.uv = v.uvIn.xy;\n"
+"    vtf.position = v.posIn;\n"
+"    return vtf;\n"
+"}\n";
+
+static const char* FS_HLSL_TEX =
+"SamplerState samp : register(s0);\n"
+"Texture2D tex0 : register(t0);\n"
+"struct VertToFrag\n"
+"{\n"
+"    float4 position : SV_Position;\n"
+"    float4 color : COLOR;\n"
+"    float2 uv : UV;\n"
+"};\n"
+"\n"
+"float4 main(in VertToFrag vtf) : SV_Target0\n"
+"{\n"
+"    return vtf.color * tex0.Sample(samp, vtf.uv);\n"
+"}\n";
+
+static const char* VS_HLSL_NOTEX =
+"struct VertData\n"
+"{\n"
+"    float4 posIn : POSITION;\n"
+"    float4 colorIn : COLOR;\n"
+"};\n"
+"\n"
+"cbuffer LineUniform : register(b0)\n"
+"{\n"
+"    float4 moduColor;\n"
+"};\n"
+"\n"
+"struct VertToFrag\n"
+"{\n"
+"    float4 position : SV_Position;\n"
+"    float4 color : COLOR;\n"
+"};\n"
+"\n"
+"VertToFrag main(in VertData v)\n"
+"{\n"
+"    VertToFrag vtf;\n"
+"    vtf.color = v.colorIn * moduColor;\n"
+"    vtf.position = v.posIn;\n"
+"    return vtf;\n"
+"}\n";
+
+static const char* FS_HLSL_NOTEX =
+"struct VertToFrag\n"
+"{\n"
+"    float4 position : SV_Position;\n"
+"    float4 color : COLOR;\n"
+"};\n"
+"\n"
+"float4 main(in VertToFrag vtf) : SV_Target0\n"
+"{\n"
+"    return vtf.color;\n"
+"}\n";
+
+struct HLSLLineDataBindingFactory : CLineRendererShaders::IDataBindingFactory
+{
+    void BuildShaderDataBinding(CLineRenderer& renderer, boo::IShaderPipeline* pipeline, boo::ITexture* texture)
+    {
+        int texCount = 0;
+        boo::ITexture* textures[1];
+
+        if (texture)
+        {
+            textures[0] = texture;
+            texCount = 1;
+        }
+
+        boo::IGraphicsBuffer* uniforms[] = {renderer.m_uniformBuf};
+
+        renderer.m_shaderBind = CGraphics::g_BooFactory->newShaderDataBinding(pipeline, nullptr, renderer.m_vertBuf,
+                                                                              nullptr, nullptr, 1, uniforms,
+                                                                              texCount, textures);
+    }
+};
+
+CLineRendererShaders::IDataBindingFactory* CLineRendererShaders::Initialize(boo::ID3DDataFactory& factory)
+{
+    static const boo::VertexElementDescriptor VtxFmtTex[] =
+    {
+        {nullptr, nullptr, boo::VertexSemantic::Position4},
+        {nullptr, nullptr, boo::VertexSemantic::Color},
+        {nullptr, nullptr, boo::VertexSemantic::UV4}
+    };
+    m_texVtxFmt = factory.newVertexFormat(3, VtxFmtTex);
+
+    static const boo::VertexElementDescriptor VtxFmtNoTex[] =
+    {
+        {nullptr, nullptr, boo::VertexSemantic::Position4},
+        {nullptr, nullptr, boo::VertexSemantic::Color}
+    };
+    m_noTexVtxFmt = factory.newVertexFormat(2, VtxFmtNoTex);
+
+    m_texAlpha = factory.newShaderPipeline(VS_HLSL_TEX, FS_HLSL_TEX, ComPtr<ID3DBlob>(), ComPtr<ID3DBlob>(),
+                                           ComPtr<ID3DBlob>(), m_texVtxFmt,
+                                           boo::BlendFactor::SrcAlpha, boo::BlendFactor::InvSrcAlpha,
+                                           false, true, false);
+    m_texAdditive = factory.newShaderPipeline(VS_HLSL_TEX, FS_HLSL_TEX, ComPtr<ID3DBlob>(), ComPtr<ID3DBlob>(),
+                                              ComPtr<ID3DBlob>(), m_texVtxFmt,
+                                              boo::BlendFactor::SrcAlpha, boo::BlendFactor::One,
+                                              false, false, false);
+    m_noTexAlpha = factory.newShaderPipeline(VS_HLSL_NOTEX, FS_HLSL_NOTEX, ComPtr<ID3DBlob>(), ComPtr<ID3DBlob>(),
+                                             ComPtr<ID3DBlob>(), m_noTexVtxFmt,
+                                             boo::BlendFactor::SrcAlpha, boo::BlendFactor::InvSrcAlpha,
+                                             false, true, false);
+    m_noTexAdditive = factory.newShaderPipeline(VS_HLSL_NOTEX, FS_HLSL_NOTEX, ComPtr<ID3DBlob>(), ComPtr<ID3DBlob>(),
+                                                ComPtr<ID3DBlob>(), m_noTexVtxFmt,
+                                                boo::BlendFactor::SrcAlpha, boo::BlendFactor::One,
+                                                false, false, false);
+
+    return new struct HLSLLineDataBindingFactory;
+}
+
+}
diff --git a/hecl b/hecl
index de8d872bf..e8ab7ce9b 160000
--- a/hecl
+++ b/hecl
@@ -1 +1 @@
-Subproject commit de8d872bfa1f07850389bcbfcec1f1aa957efd69
+Subproject commit e8ab7ce9b252f02674c88b39a8cdf0a32cc3ba6e

From 4bfe4026f21f59a4345aa28ad04b9600e78327eb Mon Sep 17 00:00:00 2001
From: Phillip Stephens <antidote.crk@gmail.com>
Date: Fri, 19 Feb 2016 21:49:47 -0800
Subject: [PATCH 06/22] Fix crash on exit

---
 Editor/main.cpp      | 15 +++++++++------
 Runtime/MP1/main.cpp |  3 ++-
 2 files changed, 11 insertions(+), 7 deletions(-)

diff --git a/Editor/main.cpp b/Editor/main.cpp
index 4255ba21a..a3c5c157b 100644
--- a/Editor/main.cpp
+++ b/Editor/main.cpp
@@ -15,26 +15,29 @@ struct Application : boo::IApplicationCallback
 {
     HECL::Runtime::FileStoreManager m_fileMgr;
     HECL::CVarManager m_cvarManager;
-    ViewManager m_viewManager;
+    std::unique_ptr<ViewManager> m_viewManager;
 
     bool m_running = true;
 
     Application() :
         m_fileMgr(_S("urde")),
-        m_cvarManager(m_fileMgr),
-        m_viewManager(m_fileMgr, m_cvarManager) {}
+        m_cvarManager(m_fileMgr)
+    {
+        m_viewManager.reset(new ViewManager(m_fileMgr, m_cvarManager));
+    }
 
     int appMain(boo::IApplication* app)
     {
         initialize(app);
-        m_viewManager.init(app);
+        m_viewManager->init(app);
         while (m_running)
         {
-            if (!m_viewManager.proc())
+            if (!m_viewManager->proc())
                 break;
         }
-        m_viewManager.stop();
+        m_viewManager->stop();
         m_cvarManager.serialize();
+        m_viewManager.reset();
         return 0;
     }
     void appQuitting(boo::IApplication*)
diff --git a/Runtime/MP1/main.cpp b/Runtime/MP1/main.cpp
index 37ecaf0a2..9aa043d9f 100644
--- a/Runtime/MP1/main.cpp
+++ b/Runtime/MP1/main.cpp
@@ -179,7 +179,7 @@ int CMain::appMain(boo::IApplication* app)
     TOneStatic<CGameArchitectureSupport> archSupport;
 
     boo::IGraphicsCommandQueue* gfxQ = mainWindow->getCommandQueue();
-    float rgba[4] = { 0.5f, 0.5f, 0.5f, 1.0f};
+    float rgba[4] = { 0.2f, 0.2f, 0.2f, 1.0f};
     gfxQ->setClearColor(rgba);
 
     float time = 0.0f;
@@ -192,6 +192,7 @@ int CMain::appMain(boo::IApplication* app)
         xe8_b24_finished = archSupport->Update();
         gfxQ->clearTarget();
 
+        gfxQ->resolveDisplay(nullptr);
         gfxQ->execute();
 
         time = (frame++) / 60.f;

From 5229f95fb779e834c5cd4c7aa0021ae16b9e2fc8 Mon Sep 17 00:00:00 2001
From: Phillip Stephens <antidote.crk@gmail.com>
Date: Fri, 19 Feb 2016 22:45:36 -0800
Subject: [PATCH 07/22] Restructure event handling

---
 Runtime/CArchitectureMessage.hpp  |  11 ++-
 Runtime/Input/CInputGenerator.cpp |   2 +-
 Runtime/Input/CInputGenerator.hpp | 117 +++++++++++++++---------------
 Runtime/MP1/main.cpp              |  45 +++++++++++-
 4 files changed, 112 insertions(+), 63 deletions(-)

diff --git a/Runtime/CArchitectureMessage.hpp b/Runtime/CArchitectureMessage.hpp
index 5c23f8047..ad3735290 100644
--- a/Runtime/CArchitectureMessage.hpp
+++ b/Runtime/CArchitectureMessage.hpp
@@ -12,7 +12,9 @@ class CIOWin;
 enum class EArchMsgTarget
 {
     IOWinManager = 0,
-    Game = 1
+    Game = 1,
+    /* PathShagged targets, we start at 255 */
+    ArchitectureSupport = 255,
 };
 
 enum class EArchMsgType
@@ -28,6 +30,8 @@ enum class EArchMsgType
     QuitGameplay = 8,
     UpdateBegin = 10,
     FrameBegin = 11,
+    /* PathShagged messages, we start at 255 */
+    ApplicationExit = 255,
 };
 
 struct IArchMsgParm
@@ -143,6 +147,11 @@ public:
     {
         return *msg.GetParm<CArchMsgParmVoidPtr>();
     }
+    /* PathShagged Messages */
+    static CArchitectureMessage CreateApplicationExit(EArchMsgTarget target)
+    {
+        return CArchitectureMessage(target, EArchMsgType::ApplicationExit, new CArchMsgParmNull());
+    }
 };
 
 }
diff --git a/Runtime/Input/CInputGenerator.cpp b/Runtime/Input/CInputGenerator.cpp
index cd1abd8c7..3c620cb76 100644
--- a/Runtime/Input/CInputGenerator.cpp
+++ b/Runtime/Input/CInputGenerator.cpp
@@ -8,7 +8,7 @@ namespace pshag
 void CInputGenerator::Update(float dt, CArchitectureQueue& queue)
 {
     /* Keyboard/Mouse first */
-    CFinalInput kbInput = m_windowCb.getFinalInput(0, dt);
+    CFinalInput kbInput = getFinalInput(0, dt);
     bool kbUsed = false;
 
     /* Dolphin controllers next */
diff --git a/Runtime/Input/CInputGenerator.hpp b/Runtime/Input/CInputGenerator.hpp
index 3dc3bdeb4..3d8f8ac7c 100644
--- a/Runtime/Input/CInputGenerator.hpp
+++ b/Runtime/Input/CInputGenerator.hpp
@@ -24,6 +24,7 @@ class CInputGenerator : public boo::DeviceFinder
      * the logical state */
     float m_leftDiv;
     float m_rightDiv;
+    CKeyboardMouseControllerData m_data;
 public:
     CInputGenerator(float leftDiv, float rightDiv)
     : boo::DeviceFinder({typeid(boo::DolphinSmashAdapter)}),
@@ -35,70 +36,66 @@ public:
      * for buffering events in its own way, then boo flushes the buffer
      * at the start of each frame, invoking these methods. No atomic locking
      * is necessary, only absolute state tracking. */
-    struct WindowCallback : boo::IWindowCallback
+
+    void mouseDown(const boo::SWindowCoord&, boo::EMouseButton button, boo::EModifierKey)
     {
-        CKeyboardMouseControllerData m_data;
+        m_data.m_mouseButtons[int(button)] = true;
+    }
+    void mouseUp(const boo::SWindowCoord&, boo::EMouseButton button, boo::EModifierKey)
+    {
+        m_data.m_mouseButtons[int(button)] = false;
+    }
+    void mouseMove(const boo::SWindowCoord& coord)
+    {
+        m_data.m_mouseCoord = coord;
+    }
+    void scroll(const boo::SWindowCoord&, const boo::SScrollDelta& scroll)
+    {
+        m_data.m_accumScroll += scroll;
+    }
 
-        void mouseDown(const boo::SWindowCoord&, boo::EMouseButton button, boo::EModifierKey)
-        {
-            m_data.m_mouseButtons[int(button)] = true;
-        }
-        void mouseUp(const boo::SWindowCoord&, boo::EMouseButton button, boo::EModifierKey)
-        {
-            m_data.m_mouseButtons[int(button)] = false;
-        }
-        void mouseMove(const boo::SWindowCoord& coord)
-        {
-            m_data.m_mouseCoord = coord;
-        }
-        void scroll(const boo::SWindowCoord&, const boo::SScrollDelta& scroll)
-        {
-            m_data.m_accumScroll += scroll;
-        }
+    void charKeyDown(unsigned long charCode, boo::EModifierKey, bool)
+    {
+        charCode = tolower(charCode);
+        if (charCode > 255)
+            return;
+        m_data.m_charKeys[charCode] = true;
+    }
+    void charKeyUp(unsigned long charCode, boo::EModifierKey mods)
+    {
+        charCode = tolower(charCode);
+        if (charCode > 255)
+            return;
+        m_data.m_charKeys[charCode] = false;
+    }
+    void specialKeyDown(boo::ESpecialKey key, boo::EModifierKey, bool)
+    {
+        m_data.m_specialKeys[int(key)] = true;
+    }
+    void specialKeyUp(boo::ESpecialKey key, boo::EModifierKey)
+    {
+        m_data.m_specialKeys[int(key)] = false;
+    }
+    void modKeyDown(boo::EModifierKey mod, bool)
+    {
+        m_data.m_modMask = m_data.m_modMask | mod;
+    }
+    void modKeyUp(boo::EModifierKey mod)
+    {
+        m_data.m_modMask = m_data.m_modMask & ~mod;
+    }
 
-        void charKeyDown(unsigned long charCode, boo::EModifierKey, bool)
-        {
-            charCode = tolower(charCode);
-            if (charCode > 255)
-                return;
-            m_data.m_charKeys[charCode] = true;
-        }
-        void charKeyUp(unsigned long charCode, boo::EModifierKey mods)
-        {
-            charCode = tolower(charCode);
-            if (charCode > 255)
-                return;
-            m_data.m_charKeys[charCode] = false;
-        }
-        void specialKeyDown(boo::ESpecialKey key, boo::EModifierKey, bool)
-        {
-            m_data.m_specialKeys[int(key)] = true;
-        }
-        void specialKeyUp(boo::ESpecialKey key, boo::EModifierKey)
-        {
-            m_data.m_specialKeys[int(key)] = false;
-        }
-        void modKeyDown(boo::EModifierKey mod, bool)
-        {
-            m_data.m_modMask = m_data.m_modMask | mod;
-        }
-        void modKeyUp(boo::EModifierKey mod)
-        {
-            m_data.m_modMask = m_data.m_modMask & ~mod;
-        }
+    void reset()
+    {
+        m_data.m_accumScroll.zeroOut();
+    }
 
-        void reset()
-        {
-            m_data.m_accumScroll.zeroOut();
-        }
-
-        CFinalInput m_lastUpdate;
-        const CFinalInput& getFinalInput(unsigned idx, float dt)
-        {
-            m_lastUpdate = CFinalInput(idx, dt, m_data, m_lastUpdate);
-            return m_lastUpdate;
-        }
-    } m_windowCb;
+    CFinalInput m_lastUpdate;
+    const CFinalInput& getFinalInput(unsigned idx, float dt)
+    {
+        m_lastUpdate = CFinalInput(idx, dt, m_data, m_lastUpdate);
+        return m_lastUpdate;
+    }
 
     /* Input via the smash adapter is received asynchronously on a USB
      * report thread. This class atomically exchanges that data to the
diff --git a/Runtime/MP1/main.cpp b/Runtime/MP1/main.cpp
index 9aa043d9f..c2801c0b2 100644
--- a/Runtime/MP1/main.cpp
+++ b/Runtime/MP1/main.cpp
@@ -98,7 +98,7 @@ public:
     }
 };
 
-class CGameArchitectureSupport
+class CGameArchitectureSupport : public boo::IWindowCallback
 {
     CArchitectureQueue m_archQueue;
     CAudioSys m_audioSys;
@@ -109,6 +109,30 @@ class CGameArchitectureSupport
     CMainFlow m_mainFlow;
     CConsoleOutputWindow m_consoleWindow;
     CAudioStateWin m_audioStateWin;
+
+    void mouseDown(const boo::SWindowCoord &coord, boo::EMouseButton button, boo::EModifierKey mods)
+    { m_inputGenerator.mouseDown(coord, button, mods); }
+    void mouseUp(const boo::SWindowCoord &coord, boo::EMouseButton button, boo::EModifierKey mods)
+    { m_inputGenerator.mouseUp(coord, button, mods); }
+    void mouseMove(const boo::SWindowCoord &coord)
+    { m_inputGenerator.mouseMove(coord); }
+    void scroll(const boo::SWindowCoord &coord, const boo::SScrollDelta &scroll)
+    { m_inputGenerator.scroll(coord, scroll); }
+    void charKeyDown(unsigned long charCode, boo::EModifierKey mods, bool isRepeat)
+    { m_inputGenerator.charKeyDown(charCode, mods, isRepeat); }
+    void charKeyUp(unsigned long charCode, boo::EModifierKey mods)
+    { m_inputGenerator.charKeyUp(charCode, mods); }
+    void specialKeyDown(boo::ESpecialKey key, boo::EModifierKey mods, bool isRepeat)
+    { m_inputGenerator.specialKeyDown(key, mods, isRepeat); }
+    void specialKeyUp(boo::ESpecialKey key, boo::EModifierKey mods)
+    { m_inputGenerator.specialKeyUp(key, mods); }
+    void modKeyDown(boo::EModifierKey mod, bool isRepeat)
+    { m_inputGenerator.modKeyDown(mod, isRepeat);}
+    void modKeyUp(boo::EModifierKey mod)
+    { m_inputGenerator.modKeyUp(mod); }
+
+    void destroyed() { m_archQueue.Push(std::move(MakeMsg::CreateApplicationExit(EArchMsgTarget::ArchitectureSupport))); }
+
 public:
     CGameArchitectureSupport()
         : m_audioSys(0,0,0,0,0),
@@ -120,6 +144,24 @@ public:
     bool Update()
     {
         bool finished = false;
+        m_inputGenerator.Update(1.0 / 60.0, m_archQueue);
+
+        while(m_archQueue)
+        {
+            CArchitectureMessage msg = m_archQueue.Pop();
+            if (msg.GetTarget() == EArchMsgTarget::ArchitectureSupport)
+            {
+                if (msg.GetType() == EArchMsgType::ApplicationExit)
+                    finished = true;
+            }
+
+            if (msg.GetTarget() == EArchMsgTarget::Game && msg.GetType() == EArchMsgType::UserInput)
+            {
+                const CArchMsgParmUserInput* input = msg.GetParm<CArchMsgParmUserInput>();
+                if (input->x4_parm.DStart())
+                    m_archQueue.Push(std::move(MakeMsg::CreateApplicationExit(EArchMsgTarget::ArchitectureSupport)));
+            }
+        }
         return finished;
     }
 };
@@ -177,6 +219,7 @@ int CMain::appMain(boo::IApplication* app)
     g_TweakManager->ReadFromMemoryCard("AudioTweaks");
     FillInAssetIDs();
     TOneStatic<CGameArchitectureSupport> archSupport;
+    mainWindow->setCallback(archSupport.GetAllocSpace());
 
     boo::IGraphicsCommandQueue* gfxQ = mainWindow->getCommandQueue();
     float rgba[4] = { 0.2f, 0.2f, 0.2f, 1.0f};

From 8af98fb2f390a7a9db809c834f49716cd64dde65 Mon Sep 17 00:00:00 2001
From: Phillip Stephens <antidote.crk@gmail.com>
Date: Sat, 20 Feb 2016 00:31:11 -0800
Subject: [PATCH 08/22] Code cleanup and add NamedResourceCatalog

---
 DataSpec/DNACommon/CMakeLists.txt           |   1 +
 DataSpec/DNACommon/NamedResourceCatalog.hpp | 132 ++++++++++++++++++++
 DataSpec/DNACommon/PAK.hpp                  |  14 +++
 Runtime/Input/CInputGenerator.hpp           |  14 +--
 Runtime/MP1/main.cpp                        |   7 --
 5 files changed, 154 insertions(+), 14 deletions(-)
 create mode 100644 DataSpec/DNACommon/NamedResourceCatalog.hpp

diff --git a/DataSpec/DNACommon/CMakeLists.txt b/DataSpec/DNACommon/CMakeLists.txt
index 6ca52ff02..e805d53e6 100644
--- a/DataSpec/DNACommon/CMakeLists.txt
+++ b/DataSpec/DNACommon/CMakeLists.txt
@@ -21,6 +21,7 @@ add_library(DNACommon
             ParticleCommon.cpp
             DeafBabe.hpp
             BabeDead.hpp
+            NamedResourceCatalog.hpp
             Tweaks/ITweakGame.hpp
             Tweaks/ITweakParticle.hpp
             Tweaks/ITweakPlayer.hpp
diff --git a/DataSpec/DNACommon/NamedResourceCatalog.hpp b/DataSpec/DNACommon/NamedResourceCatalog.hpp
new file mode 100644
index 000000000..3d848ede7
--- /dev/null
+++ b/DataSpec/DNACommon/NamedResourceCatalog.hpp
@@ -0,0 +1,132 @@
+#ifndef __DNACOMMON_NAMEDRESOURCECATALOG_HPP__
+#define __DNACOMMON_NAMEDRESOURCECATALOG_HPP__
+
+#include "DNACommon.hpp"
+namespace DataSpec
+{
+template <class IDType>
+struct NamedResourceCatalog : BigYAML
+{
+    Delete _d;
+    Value<atUint32> namedResCount;
+    struct NamedResource : BigYAML
+    {
+        Delete _d;
+        DNAFourCC type;
+        String<-1> name;
+        IDType uid;
+
+        void read(Athena::io::IStreamReader& __dna_reader)
+        {
+            /* type */
+            type.read(__dna_reader);
+            /* name */
+            name = __dna_reader.readString(-1);
+            /* uid */
+            uid.read(__dna_reader);
+        }
+
+        void write(Athena::io::IStreamWriter& __dna_writer) const
+        {
+            /* type */
+            type.write(__dna_writer);
+            /* name */
+            __dna_writer.writeString(name, -1);
+            /* uid */
+            uid.write(__dna_writer);
+        }
+
+        void read(Athena::io::YAMLDocReader& __dna_docin)
+        {
+            /* type */
+            __dna_docin.enumerate("type", type);
+            /* name */
+            name = __dna_docin.readString("name");
+            /* uid */
+            __dna_docin.enumerate("uid", uid);
+        }
+
+        void write(Athena::io::YAMLDocWriter& __dna_docout) const
+        {
+            /* type */
+            __dna_docout.enumerate("type", type);
+            /* name */
+            __dna_docout.writeString("name", name);
+            /* uid */
+            __dna_docout.enumerate("uid", uid);
+        }
+
+        static const char* DNAType() { return "DataSpec::DNACommon::NameResourceCatalog::NamedResource"; }
+
+        size_t binarySize(size_t __isz) const
+        {
+            __isz = type.binarySize(__isz);
+            __isz += name.size() + 1;
+            __isz = uid.binarySize(__isz);
+            return __isz;
+        }
+    };
+    Vector<NamedResource, DNA_COUNT(namedResCount)> namedResources;
+
+    void read(Athena::io::IStreamReader& __dna_reader)
+    {
+        /* namedResCount */
+        namedResCount = __dna_reader.readUint32Big();
+        /* namedResources */
+        __dna_reader.enumerate(namedResources, namedResCount);
+    }
+
+    void write(Athena::io::IStreamWriter& __dna_writer) const
+    {
+        /* namedResCount */
+        __dna_writer.writeUint32Big(namedResCount);
+        /* namedResources */
+        __dna_writer.enumerate(namedResources);
+    }
+
+    void read(Athena::io::YAMLDocReader& __dna_docin)
+    {
+        /* namedResCount */
+        namedResCount = __dna_docin.readUint32("namedResCount");
+        /* namedResources */
+        __dna_docin.enumerate("namedResources", namedResources, namedResCount);
+    }
+
+    void write(Athena::io::YAMLDocWriter& __dna_docout) const
+    {
+        /* namedResCount */
+        __dna_docout.writeUint32("namedResCount", namedResCount);
+        /* namedResources */
+        __dna_docout.enumerate("namedResources", namedResources);
+    }
+
+    static const char* DNAType()
+    {
+        return "DataSpec::DNACommon::NameResourceCatalog";
+    }
+
+    size_t binarySize(size_t __isz) const
+    {
+        __isz = __EnumerateSize(__isz, namedResources);
+        return __isz + 4;
+    }
+
+    void addNamedResource(const std::string& name, const IDType& id, const DNAFourCC& type)
+    {
+        NamedResource res;
+        res.type = type;
+        res.name = name;
+        res.uid = id;
+        auto it = std::find_if(namedResources.begin(), namedResources.end(), [res](const NamedResource& a)->bool
+        { return (a.name == res.name && a.type == res.type && a.uid == res.uid); });
+
+        if (it != namedResources.end())
+            return;
+
+        namedResources.push_back(std::move(res));
+        namedResCount++;
+    }
+};
+}
+
+#endif // NAMEDRESOURCECATALOG_HPP
diff --git a/DataSpec/DNACommon/PAK.hpp b/DataSpec/DNACommon/PAK.hpp
index 6a4303ac9..dd14fe754 100644
--- a/DataSpec/DNACommon/PAK.hpp
+++ b/DataSpec/DNACommon/PAK.hpp
@@ -2,6 +2,7 @@
 #define __DNACOMMON_PAK_HPP__
 
 #include "DNACommon.hpp"
+#include "NamedResourceCatalog.hpp"
 
 namespace DataSpec
 {
@@ -240,6 +241,7 @@ public:
     using EntryType = typename PAKType::Entry;
     using RigPair = std::pair<IDType, IDType>;
 private:
+    NamedResourceCatalog<IDType> m_catalog;
     const SpecBase& m_dataSpec;
     const std::vector<BRIDGETYPE>* m_bridges = nullptr;
     std::vector<std::pair<HECL::ProjectPath,HECL::ProjectPath>> m_bridgePaths;
@@ -309,9 +311,21 @@ public:
             /* Add RigPairs to global map */
             bridge.addCMDLRigPairs(*this, m_cmdlRigs);
 
+            /* Add named resources to catalog */
+            for (const auto& namedEntry : pak.m_nameEntries)
+                m_catalog.addNamedResource(namedEntry.name, namedEntry.id, namedEntry.type);
+
             progress(++count / bridgesSz);
             ++bridgeIdx;
         }
+
+        HECL::SystemString catalogPath = m_gameCooked.getAbsolutePath() + _S("/catalog.yaml");
+        FILE* catalog = HECL::Fopen(catalogPath.c_str(), _S("wb"));
+        if (catalog)
+        {
+            m_catalog.toYAMLFile(catalog);
+            fclose(catalog);
+        }
     }
 
     void enterPAKBridge(const BRIDGETYPE& pakBridge)
diff --git a/Runtime/Input/CInputGenerator.hpp b/Runtime/Input/CInputGenerator.hpp
index 3d8f8ac7c..6d3b4dfec 100644
--- a/Runtime/Input/CInputGenerator.hpp
+++ b/Runtime/Input/CInputGenerator.hpp
@@ -25,6 +25,13 @@ class CInputGenerator : public boo::DeviceFinder
     float m_leftDiv;
     float m_rightDiv;
     CKeyboardMouseControllerData m_data;
+
+    CFinalInput m_lastUpdate;
+    const CFinalInput& getFinalInput(unsigned idx, float dt)
+    {
+        m_lastUpdate = CFinalInput(idx, dt, m_data, m_lastUpdate);
+        return m_lastUpdate;
+    }
 public:
     CInputGenerator(float leftDiv, float rightDiv)
     : boo::DeviceFinder({typeid(boo::DolphinSmashAdapter)}),
@@ -90,13 +97,6 @@ public:
         m_data.m_accumScroll.zeroOut();
     }
 
-    CFinalInput m_lastUpdate;
-    const CFinalInput& getFinalInput(unsigned idx, float dt)
-    {
-        m_lastUpdate = CFinalInput(idx, dt, m_data, m_lastUpdate);
-        return m_lastUpdate;
-    }
-
     /* Input via the smash adapter is received asynchronously on a USB
      * report thread. This class atomically exchanges that data to the
      * game thread as needed */
diff --git a/Runtime/MP1/main.cpp b/Runtime/MP1/main.cpp
index c2801c0b2..e1d0c3036 100644
--- a/Runtime/MP1/main.cpp
+++ b/Runtime/MP1/main.cpp
@@ -225,10 +225,6 @@ int CMain::appMain(boo::IApplication* app)
     float rgba[4] = { 0.2f, 0.2f, 0.2f, 1.0f};
     gfxQ->setClearColor(rgba);
 
-    float time = 0.0f;
-    int frame = 0;
-    CTimeProvider test(time);
-
     while (!xe8_b24_finished)
     {
         mainWindow->waitForRetrace();
@@ -237,9 +233,6 @@ int CMain::appMain(boo::IApplication* app)
 
         gfxQ->resolveDisplay(nullptr);
         gfxQ->execute();
-
-        time = (frame++) / 60.f;
-        //fprintf(stderr, "%f\n", test.x0_currentTime);
     }
     return 0;
 }

From 19e7dc6b63436faf96f47ac44dc16e4dbf197dae Mon Sep 17 00:00:00 2001
From: Phillip Stephens <antidote.crk@gmail.com>
Date: Sat, 20 Feb 2016 00:35:00 -0800
Subject: [PATCH 09/22] Fix API usage

---
 DataSpec/DNACommon/PAK.hpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/DataSpec/DNACommon/PAK.hpp b/DataSpec/DNACommon/PAK.hpp
index dd14fe754..93b643efa 100644
--- a/DataSpec/DNACommon/PAK.hpp
+++ b/DataSpec/DNACommon/PAK.hpp
@@ -319,7 +319,7 @@ public:
             ++bridgeIdx;
         }
 
-        HECL::SystemString catalogPath = m_gameCooked.getAbsolutePath() + _S("/catalog.yaml");
+        HECL::SystemString catalogPath = HECL::ProjectPath(m_gameCooked, "catalog.yaml").getAbsolutePath();
         FILE* catalog = HECL::Fopen(catalogPath.c_str(), _S("wb"));
         if (catalog)
         {

From ff200677e191ab1d21551c69604e76d2aced5995 Mon Sep 17 00:00:00 2001
From: Phillip Stephens <antidote.crk@gmail.com>
Date: Sat, 20 Feb 2016 00:53:06 -0800
Subject: [PATCH 10/22] More error messages

---
 DataSpec/SpecBase.cpp | 9 ++++++---
 1 file changed, 6 insertions(+), 3 deletions(-)

diff --git a/DataSpec/SpecBase.cpp b/DataSpec/SpecBase.cpp
index 75ac313cf..a98f7ccef 100644
--- a/DataSpec/SpecBase.cpp
+++ b/DataSpec/SpecBase.cpp
@@ -25,9 +25,12 @@ static const HECL::SystemChar* MomErr[] =
     _S("Contradictive narratives unsupported"),
     _S("Wiimote profile \"NES + Zapper\" not recognized"),
     _S("Unable to find Waldo"),
-    _S("Expected Ridley, found furby")
+    _S("Expected Ridley, found furby"),
+    _S("Adam has not authorized this, please do not bug the developers"),
+    _S("Error: Lady returned objection")
 };
 
+constexpr uint32_t MomErrCount = 11;
 SpecBase::SpecBase(HECL::Database::Project& project)
 : m_project(project),
   m_masterShader(project.getProjectWorkingPath(), ".hecl/RetroMasterShader.blend") {}
@@ -44,9 +47,9 @@ bool SpecBase::canExtract(const ExtractPassInfo& info, std::vector<ExtractReport
         unsigned int t = time(nullptr);
 #if _WIN32
         rand_s(&t);
-        int r = t % 9;
+        int r = t % MomErrCount;
 #else
-        int r = rand_r(&t) % 9;
+        int r = rand_r(&t) % MomErrCount;
 #endif
         Log.report(LogVisor::FatalError, MomErr[r]);
     }

From cf6c5bf55acb6612a54eaf4a903ea0e978b52155 Mon Sep 17 00:00:00 2001
From: Phillip Stephens <antidote.crk@gmail.com>
Date: Sat, 20 Feb 2016 01:52:16 -0800
Subject: [PATCH 11/22] Add virtual destructors to Architecture Message
 Parameters Fix function signature

---
 Runtime/CArchitectureMessage.hpp  | 8 ++++++++
 Runtime/Input/CInputGenerator.hpp | 2 +-
 2 files changed, 9 insertions(+), 1 deletion(-)

diff --git a/Runtime/CArchitectureMessage.hpp b/Runtime/CArchitectureMessage.hpp
index ad3735290..e2668e295 100644
--- a/Runtime/CArchitectureMessage.hpp
+++ b/Runtime/CArchitectureMessage.hpp
@@ -43,6 +43,7 @@ struct CArchMsgParmInt32 : IArchMsgParm
 {
     u32 x4_parm;
     CArchMsgParmInt32(u32 parm) : x4_parm(parm) {}
+    virtual ~CArchMsgParmInt32() {}
 };
 
 struct CArchMsgParmVoidPtr : IArchMsgParm
@@ -50,6 +51,7 @@ struct CArchMsgParmVoidPtr : IArchMsgParm
     void* x4_parm1;
     CArchMsgParmVoidPtr(void* parm1)
     : x4_parm1(parm1) {}
+    virtual ~CArchMsgParmVoidPtr() {}
 };
 
 struct CArchMsgParmInt32Int32VoidPtr : IArchMsgParm
@@ -59,22 +61,26 @@ struct CArchMsgParmInt32Int32VoidPtr : IArchMsgParm
     void* xc_parm3;
     CArchMsgParmInt32Int32VoidPtr(u32 parm1, u32 parm2, void* parm3)
     : x4_parm1(parm1), x8_parm2(parm2), xc_parm3(parm3) {}
+    virtual ~CArchMsgParmInt32Int32VoidPtr() {}
 };
 
 struct CArchMsgParmNull : IArchMsgParm
 {
+    virtual ~CArchMsgParmNull() {}
 };
 
 struct CArchMsgParmReal32 : IArchMsgParm
 {
     float x4_parm;
     CArchMsgParmReal32(float parm) : x4_parm(parm) {}
+    virtual ~CArchMsgParmReal32() {}
 };
 
 struct CArchMsgParmUserInput : IArchMsgParm
 {
     CFinalInput x4_parm;
     CArchMsgParmUserInput(const CFinalInput& parm) : x4_parm(parm) {}
+    virtual ~CArchMsgParmUserInput() {}
 };
 
 struct CArchMsgParmControllerStatus : IArchMsgParm
@@ -83,6 +89,8 @@ struct CArchMsgParmControllerStatus : IArchMsgParm
     bool x6_parm2;
     CArchMsgParmControllerStatus(u16 a, bool b)
     : x4_parm1(a), x6_parm2(b) {}
+
+    virtual ~CArchMsgParmControllerStatus() {}
 };
 
 class CArchitectureMessage
diff --git a/Runtime/Input/CInputGenerator.hpp b/Runtime/Input/CInputGenerator.hpp
index 6d3b4dfec..8fe435c04 100644
--- a/Runtime/Input/CInputGenerator.hpp
+++ b/Runtime/Input/CInputGenerator.hpp
@@ -111,7 +111,7 @@ public:
             /* Controller thread */
             m_statusChanges[idx].store(EStatusChange::Connected);
         }
-        void controllerDisconnected(unsigned idx, boo::EDolphinControllerType)
+        void controllerDisconnected(unsigned idx)
         {
             /* Controller thread */
             std::unique_lock<std::mutex> lk(m_stateLock);

From a37f536ae9b18e5cece7cfa5afbf84b550a64429 Mon Sep 17 00:00:00 2001
From: Phillip Stephens <antidote.crk@gmail.com>
Date: Sat, 20 Feb 2016 02:26:43 -0800
Subject: [PATCH 12/22] Use rendertarget

---
 Runtime/MP1/main.cpp | 30 ++++++++++++++++++++++++++++--
 1 file changed, 28 insertions(+), 2 deletions(-)

diff --git a/Runtime/MP1/main.cpp b/Runtime/MP1/main.cpp
index e1d0c3036..883b91f56 100644
--- a/Runtime/MP1/main.cpp
+++ b/Runtime/MP1/main.cpp
@@ -109,6 +109,8 @@ class CGameArchitectureSupport : public boo::IWindowCallback
     CMainFlow m_mainFlow;
     CConsoleOutputWindow m_consoleWindow;
     CAudioStateWin m_audioStateWin;
+    boo::SWindowRect m_windowRect;
+    bool m_rectIsDirty;
 
     void mouseDown(const boo::SWindowCoord &coord, boo::EMouseButton button, boo::EModifierKey mods)
     { m_inputGenerator.mouseDown(coord, button, mods); }
@@ -133,6 +135,12 @@ class CGameArchitectureSupport : public boo::IWindowCallback
 
     void destroyed() { m_archQueue.Push(std::move(MakeMsg::CreateApplicationExit(EArchMsgTarget::ArchitectureSupport))); }
 
+    void resized(const boo::SWindowRect &rect)
+    {
+        m_windowRect = rect;
+        m_rectIsDirty = true;
+    }
+
 public:
     CGameArchitectureSupport()
         : m_audioSys(0,0,0,0,0),
@@ -164,6 +172,13 @@ public:
         }
         return finished;
     }
+
+    bool isRectDirty() { return m_rectIsDirty; }
+    const boo::SWindowRect& getWindowRect()
+    {
+        m_rectIsDirty = false;
+        return m_windowRect;
+    }
 };
 
 CMain::CMain()
@@ -222,6 +237,8 @@ int CMain::appMain(boo::IApplication* app)
     mainWindow->setCallback(archSupport.GetAllocSpace());
 
     boo::IGraphicsCommandQueue* gfxQ = mainWindow->getCommandQueue();
+    boo::SWindowRect windowRect = mainWindow->getWindowFrame();
+    boo::ITextureR* renderTex = mainWindow->getMainContextDataFactory()->newRenderTexture(windowRect.size[0], windowRect.size[1], 1);
     float rgba[4] = { 0.2f, 0.2f, 0.2f, 1.0f};
     gfxQ->setClearColor(rgba);
 
@@ -229,9 +246,18 @@ int CMain::appMain(boo::IApplication* app)
     {
         mainWindow->waitForRetrace();
         xe8_b24_finished = archSupport->Update();
-        gfxQ->clearTarget();
 
-        gfxQ->resolveDisplay(nullptr);
+        if (archSupport->isRectDirty())
+        {
+            const boo::SWindowRect& windowRect = archSupport->getWindowRect();
+            gfxQ->resizeRenderTexture(renderTex,
+                                      windowRect.size[0],
+                                      windowRect.size[1]);
+        }
+
+        gfxQ->setRenderTarget(renderTex);
+        gfxQ->clearTarget();
+        gfxQ->resolveDisplay(renderTex);
         gfxQ->execute();
     }
     return 0;

From 764d75f38e99a2f0ae2fd2b4bbef8418f091ba0c Mon Sep 17 00:00:00 2001
From: Phillip Stephens <antidote.crk@gmail.com>
Date: Sat, 20 Feb 2016 04:40:58 -0800
Subject: [PATCH 13/22] Add ability to reference resources by name

---
 Editor/ProjectResourceFactory.cpp | 48 ++++++++++++++--------------
 Editor/ProjectResourceFactory.hpp | 52 ++++++++++++++++++++++++++++++-
 Editor/ViewManager.cpp            |  3 +-
 Runtime/MP1/main.cpp              |  2 +-
 Runtime/RetroTypes.hpp            |  2 +-
 5 files changed, 78 insertions(+), 29 deletions(-)

diff --git a/Editor/ProjectResourceFactory.cpp b/Editor/ProjectResourceFactory.cpp
index b530ff563..6c540b3ce 100644
--- a/Editor/ProjectResourceFactory.cpp
+++ b/Editor/ProjectResourceFactory.cpp
@@ -17,31 +17,26 @@ ProjectResourceFactory::ProjectResourceFactory()
     m_factoryMgr.AddFactory(HECL::FOURCC('PART'), pshag::FParticleFactory);
 }
 
-void ProjectResourceFactory::RecursiveAddDirObjects(const HECL::ProjectPath& path)
-{
-    HECL::DirectoryEnumerator de = path.enumerateDir();
-    for (const HECL::DirectoryEnumerator::Entry& ent : de)
-    {
-        if (ent.m_isDir)
-            RecursiveAddDirObjects(HECL::ProjectPath(path, ent.m_name));
-        if (ent.m_name.size() == 13 && ent.m_name[4] == _S('_'))
-        {
-            HECL::SystemUTF8View entu8(ent.m_name);
-            u32 id = strtoul(entu8.c_str() + 5, nullptr, 16);
-            if (id)
-            {
-                pshag::SObjectTag objTag = {HECL::FourCC(entu8.c_str()), id};
-                if (m_resPaths.find(objTag) == m_resPaths.end())
-                    m_resPaths[objTag] = HECL::ProjectPath(path, ent.m_name);
-            }
-        }
-    }
-}
-
-void ProjectResourceFactory::BuildObjectMap(const HECL::Database::Project::ProjectDataSpec& spec)
+void ProjectResourceFactory::BuildObjectMap(const HECL::Database::Project::ProjectDataSpec &spec)
 {
     m_resPaths.clear();
-    RecursiveAddDirObjects(spec.cookedPath);
+    m_namedResources.clear();
+    HECL::SystemString catalogPath = HECL::ProjectPath(spec.cookedPath, std::string(spec.spec.m_name) + "/catalog.yaml").getAbsolutePath();
+    FILE* catalogFile = HECL::Fopen(catalogPath.c_str(), _S("r"));
+    if (!HECL::StrCmp(spec.spec.m_name, "MP3"))
+    {
+        DataSpec::NamedResourceCatalog<DataSpec::UniqueID64> catalog;
+        if (catalogFile)
+            catalog.fromYAMLFile(catalogFile);
+        RecursiveAddDirObjects(spec.cookedPath, catalog);
+    }
+    else
+    {
+        DataSpec::NamedResourceCatalog<DataSpec::UniqueID32> catalog;
+        if (catalogFile)
+            catalog.fromYAMLFile(catalogFile);
+        RecursiveAddDirObjects(spec.cookedPath, catalog);
+    }
 }
 
 std::unique_ptr<pshag::IObj> ProjectResourceFactory::Build(const pshag::SObjectTag& tag,
@@ -83,9 +78,12 @@ bool ProjectResourceFactory::CanBuild(const pshag::SObjectTag& tag)
     return true;
 }
 
-const pshag::SObjectTag* ProjectResourceFactory::GetResourceIdByName(const char*) const
+const pshag::SObjectTag* ProjectResourceFactory::GetResourceIdByName(const char* name) const
 {
-    return nullptr;
+    if (m_namedResources.find(name) == m_namedResources.end())
+        return nullptr;
+    const pshag::SObjectTag& tag = m_namedResources.at(name);
+    return &tag;
 }
 
 }
diff --git a/Editor/ProjectResourceFactory.hpp b/Editor/ProjectResourceFactory.hpp
index 595815003..7d40fe2c4 100644
--- a/Editor/ProjectResourceFactory.hpp
+++ b/Editor/ProjectResourceFactory.hpp
@@ -3,6 +3,7 @@
 
 #include "Runtime/IFactory.hpp"
 #include "Runtime/CFactoryMgr.hpp"
+#include "DataSpec/DNACommon/NamedResourceCatalog.hpp"
 
 namespace URDE
 {
@@ -10,8 +11,57 @@ namespace URDE
 class ProjectResourceFactory : public pshag::IFactory
 {
     std::unordered_map<pshag::SObjectTag, HECL::ProjectPath> m_resPaths;
+    std::unordered_map<std::string, pshag::SObjectTag> m_namedResources;
     pshag::CFactoryMgr m_factoryMgr;
-    void RecursiveAddDirObjects(const HECL::ProjectPath& path);
+    template <class IDType>
+    void RecursiveAddDirObjects(const HECL::ProjectPath& path, const DataSpec::NamedResourceCatalog<IDType>& catalog)
+    {
+        HECL::DirectoryEnumerator de = path.enumerateDir();
+        const int idLen = 5 + (IDType::BinarySize() * 2);
+        for (const HECL::DirectoryEnumerator::Entry& ent : de)
+        {
+            if (ent.m_isDir)
+                RecursiveAddDirObjects(HECL::ProjectPath(path, ent.m_name), catalog);
+            if (ent.m_name.size() == idLen && ent.m_name[4] == _S('_'))
+            {
+                HECL::SystemUTF8View entu8(ent.m_name);
+                u64 id = strtouq(entu8.c_str() + 5, nullptr, 16);
+
+                if (id)
+                {
+                    pshag::SObjectTag objTag = {HECL::FourCC(entu8.c_str()), id};
+                    if (m_resPaths.find(objTag) == m_resPaths.end())
+                        m_resPaths[objTag] = HECL::ProjectPath(path, ent.m_name);
+                }
+            }
+            else
+            {
+                HECL::SystemUTF8View nameView(ent.m_name);
+                auto it = std::find_if(catalog.namedResources.begin(), catalog.namedResources.end(),
+                                       [&nameView](const typename DataSpec::NamedResourceCatalog<IDType>::NamedResource& res) -> bool
+                { return res.name == nameView.str(); });
+                if (it == catalog.namedResources.end())
+                    continue;
+
+                const typename DataSpec::NamedResourceCatalog<IDType>::NamedResource& nr = *it;
+                pshag::SObjectTag objTag = GetTag<IDType>(nr);
+
+                m_namedResources[nr.name.c_str()] = objTag;
+                m_resPaths[objTag] = HECL::ProjectPath(path, ent.m_name);
+            }
+        }
+    }
+
+    template <class IDType>
+    pshag::SObjectTag GetTag(const DataSpec::NamedResourceCatalog<DataSpec::UniqueID32>::NamedResource &nr,
+                typename std::enable_if<std::is_same<IDType, DataSpec::UniqueID32>::value>::type* = 0)
+    { return { nr.type, nr.uid.toUint32() }; }
+
+    template <class IDType>
+    pshag::SObjectTag GetTag(const typename DataSpec::NamedResourceCatalog<IDType>::NamedResource& nr,
+                typename std::enable_if<std::is_same<IDType, DataSpec::UniqueID64>::value>::type* = 0)
+    { return { nr.type, nr.uid.toUint64() }; }
+
 public:
     ProjectResourceFactory();
     void BuildObjectMap(const HECL::Database::Project::ProjectDataSpec& spec);
diff --git a/Editor/ViewManager.cpp b/Editor/ViewManager.cpp
index 9439b6791..2370db4fb 100644
--- a/Editor/ViewManager.cpp
+++ b/Editor/ViewManager.cpp
@@ -20,7 +20,8 @@ namespace URDE
 
 void ViewManager::BuildTestPART(pshag::IObjectStore& objStore)
 {
-    m_partGenDesc = objStore.GetObj({HECL::FOURCC('PART'), 0x972A5CD2});
+    //m_partGenDesc = objStore.GetObj({HECL::FOURCC('PART'), 0x972A5CD2});
+    m_partGenDesc = objStore.GetObj("WallSpark");
     m_partGen.reset(new pshag::CElementGen(m_partGenDesc,
                                            pshag::CElementGen::EModelOrientationType::Normal,
                                            pshag::CElementGen::EOptionalSystemFlags::None));
diff --git a/Runtime/MP1/main.cpp b/Runtime/MP1/main.cpp
index 883b91f56..d78243268 100644
--- a/Runtime/MP1/main.cpp
+++ b/Runtime/MP1/main.cpp
@@ -244,7 +244,6 @@ int CMain::appMain(boo::IApplication* app)
 
     while (!xe8_b24_finished)
     {
-        mainWindow->waitForRetrace();
         xe8_b24_finished = archSupport->Update();
 
         if (archSupport->isRectDirty())
@@ -259,6 +258,7 @@ int CMain::appMain(boo::IApplication* app)
         gfxQ->clearTarget();
         gfxQ->resolveDisplay(renderTex);
         gfxQ->execute();
+        mainWindow->waitForRetrace();
     }
     return 0;
 }
diff --git a/Runtime/RetroTypes.hpp b/Runtime/RetroTypes.hpp
index 3e4b16683..18a1c8e6b 100644
--- a/Runtime/RetroTypes.hpp
+++ b/Runtime/RetroTypes.hpp
@@ -12,7 +12,7 @@ namespace pshag
 {
 
 using FourCC = HECL::FourCC;
-using TResId = u32;
+using TResId = u64;
 
 struct SObjectTag
 {

From 7ec23b50baeab834fab1a8ea33f5788c8025a0ba Mon Sep 17 00:00:00 2001
From: Phillip Stephens <antidote.crk@gmail.com>
Date: Sat, 20 Feb 2016 22:34:42 -0800
Subject: [PATCH 14/22] First round Rumble stubs

---
 Runtime/Input/CFinalInput.hpp      |  2 +
 Runtime/Input/CInputGenerator.cpp  |  6 +++
 Runtime/Input/CInputGenerator.hpp  |  2 +
 Runtime/Input/CMakeLists.txt       |  5 +-
 Runtime/Input/CRumbleGenerator.cpp |  8 ++++
 Runtime/Input/CRumbleGenerator.hpp | 17 +++++++
 Runtime/Input/CRumbleManager.cpp   |  8 ++++
 Runtime/Input/CRumbleManager.hpp   | 21 +++++++++
 Runtime/Input/CRumbleVoice.cpp     |  5 ++
 Runtime/Input/CRumbleVoice.hpp     | 76 ++++++++++++++++++++++++++++++
 10 files changed, 149 insertions(+), 1 deletion(-)
 create mode 100644 Runtime/Input/CRumbleGenerator.cpp
 create mode 100644 Runtime/Input/CRumbleGenerator.hpp
 create mode 100644 Runtime/Input/CRumbleManager.cpp
 create mode 100644 Runtime/Input/CRumbleManager.hpp
 create mode 100644 Runtime/Input/CRumbleVoice.cpp
 create mode 100644 Runtime/Input/CRumbleVoice.hpp

diff --git a/Runtime/Input/CFinalInput.hpp b/Runtime/Input/CFinalInput.hpp
index ca882fa7c..b8ee75992 100644
--- a/Runtime/Input/CFinalInput.hpp
+++ b/Runtime/Input/CFinalInput.hpp
@@ -72,6 +72,8 @@ public:
                 const CKeyboardMouseControllerData& data,
                 const CFinalInput& prevInput);
     CFinalInput& operator|=(const CFinalInput& other);
+    bool operator==(const CFinalInput& other)
+    { return memcmp(this, &other, sizeof(CFinalInput)) == 0; }
 
     bool PStart() const {return x2e_b31_PStart;}
     bool PR() const {return x2e_b26_PR;}
diff --git a/Runtime/Input/CInputGenerator.cpp b/Runtime/Input/CInputGenerator.cpp
index 3c620cb76..6f4abf82a 100644
--- a/Runtime/Input/CInputGenerator.cpp
+++ b/Runtime/Input/CInputGenerator.cpp
@@ -7,6 +7,12 @@ namespace pshag
 
 void CInputGenerator::Update(float dt, CArchitectureQueue& queue)
 {
+    if (m_firstFrame)
+    {
+        m_firstFrame = false;
+        return;
+    }
+
     /* Keyboard/Mouse first */
     CFinalInput kbInput = getFinalInput(0, dt);
     bool kbUsed = false;
diff --git a/Runtime/Input/CInputGenerator.hpp b/Runtime/Input/CInputGenerator.hpp
index 8fe435c04..160366378 100644
--- a/Runtime/Input/CInputGenerator.hpp
+++ b/Runtime/Input/CInputGenerator.hpp
@@ -32,6 +32,8 @@ class CInputGenerator : public boo::DeviceFinder
         m_lastUpdate = CFinalInput(idx, dt, m_data, m_lastUpdate);
         return m_lastUpdate;
     }
+
+    bool m_firstFrame = true;
 public:
     CInputGenerator(float leftDiv, float rightDiv)
     : boo::DeviceFinder({typeid(boo::DolphinSmashAdapter)}),
diff --git a/Runtime/Input/CMakeLists.txt b/Runtime/Input/CMakeLists.txt
index a09f2b6e2..4e3926808 100644
--- a/Runtime/Input/CMakeLists.txt
+++ b/Runtime/Input/CMakeLists.txt
@@ -3,4 +3,7 @@ add_library(RuntimeCommonInput
             CKeyboardMouseController.hpp
             ControlMapper.hpp ControlMapper.cpp
             CInputGenerator.hpp CInputGenerator.cpp
-            CFinalInput.hpp CFinalInput.cpp)
+            CFinalInput.hpp CFinalInput.cpp
+            CRumbleManager.hpp CRumbleManager.cpp
+            CRumbleGenerator.hpp CRumbleGenerator.cpp
+            CRumbleVoice.hpp CRumbleVoice.cpp)
diff --git a/Runtime/Input/CRumbleGenerator.cpp b/Runtime/Input/CRumbleGenerator.cpp
new file mode 100644
index 000000000..24c7861df
--- /dev/null
+++ b/Runtime/Input/CRumbleGenerator.cpp
@@ -0,0 +1,8 @@
+#include "CRumbleGenerator.hpp"
+
+namespace pshag
+{
+CRumbleGenerator::CRumbleGenerator()
+{
+}
+}
diff --git a/Runtime/Input/CRumbleGenerator.hpp b/Runtime/Input/CRumbleGenerator.hpp
new file mode 100644
index 000000000..e9c2ca247
--- /dev/null
+++ b/Runtime/Input/CRumbleGenerator.hpp
@@ -0,0 +1,17 @@
+#ifndef CRUMBLEGENERATOR_HPP
+#define CRUMBLEGENERATOR_HPP
+
+#include "CRumbleVoice.hpp"
+
+namespace pshag
+{
+class CRumbleGenerator
+{
+public:
+    CRumbleGenerator();
+    void Update(float);
+    void HardStopAll();
+};
+}
+
+#endif // CRUMBLEGENERATOR_HPP
diff --git a/Runtime/Input/CRumbleManager.cpp b/Runtime/Input/CRumbleManager.cpp
new file mode 100644
index 000000000..f5a0c7618
--- /dev/null
+++ b/Runtime/Input/CRumbleManager.cpp
@@ -0,0 +1,8 @@
+#include "CRumbleManager.hpp"
+
+namespace pshag
+{
+
+void CRumbleManager::Update(float dt) { x0_rumbleGenerator.Update(dt); }
+
+}
diff --git a/Runtime/Input/CRumbleManager.hpp b/Runtime/Input/CRumbleManager.hpp
new file mode 100644
index 000000000..cb19adf68
--- /dev/null
+++ b/Runtime/Input/CRumbleManager.hpp
@@ -0,0 +1,21 @@
+#ifndef __PSHAG_CRUMBLEMANAGER_HPP__
+#define __PSHAG_CRUMBLEMANAGER_HPP__
+
+#include "CRumbleGenerator.hpp"
+
+namespace pshag
+{
+class CStateManager;
+class CRumbleManager
+{
+    CRumbleGenerator x0_rumbleGenerator;
+public:
+    CRumbleManager() = default;
+    void Update(float);
+    void StopRumble(u16) {}
+    void Rumble(ERumbleFxId, CStateManager&, ERumblePriority priority);
+    void Rumble(ERumbleFxId, float, CStateManager&, ERumblePriority priority);
+};
+}
+
+#endif // __PSHAG_CRUMBLEMANAGER_HPP__
diff --git a/Runtime/Input/CRumbleVoice.cpp b/Runtime/Input/CRumbleVoice.cpp
new file mode 100644
index 000000000..77ed2dfb1
--- /dev/null
+++ b/Runtime/Input/CRumbleVoice.cpp
@@ -0,0 +1,5 @@
+#include "CRumbleVoice.hpp"
+
+namespace pshag
+{
+}
diff --git a/Runtime/Input/CRumbleVoice.hpp b/Runtime/Input/CRumbleVoice.hpp
new file mode 100644
index 000000000..1f61917c3
--- /dev/null
+++ b/Runtime/Input/CRumbleVoice.hpp
@@ -0,0 +1,76 @@
+#ifndef CRUMBLEVOICE_HPP
+#define CRUMBLEVOICE_HPP
+
+#include "RetroTypes.hpp"
+
+namespace pshag
+{
+enum class ERumbleFxId
+{
+
+};
+enum class ERumblePriority
+{
+    None
+};
+
+struct SAdsrData;
+class CRumbleVoice
+{
+public:
+    CRumbleVoice() {}
+    CRumbleVoice(const SAdsrData& data);
+};
+
+struct SAdsrData
+{
+    float x0 = 0.f;
+    float x4 = 0.f;
+    float x8 = 0.f;
+    float xc = 0.f;
+    float x10 = 0.f;
+    float x14 = 0.f;
+    union
+    {
+        struct { bool x18_24 : 1; bool x18_25 : 1; };
+        u8 dummy = 0;
+    };
+
+    SAdsrData() = default;
+    SAdsrData(float a, float b, float c, float d, float e, float f, bool g, bool h)
+        : x0(a), x4(b), x8(c), xc(d), x10(e), x14(f)
+    {
+        x18_24 = g;
+        x18_25 = h;
+    }
+};
+
+struct SAdsrDelta
+{
+    enum class EPhase
+    {
+        Stop,
+        Start,
+    };
+
+    float x0 = 0.f;
+    float x4 = 0.f;
+    float x8 = 0.f;
+    float xc = 0.f;
+    float x10 = 0.f;
+    ERumblePriority x1c_priority;
+    EPhase          x20_phase;
+
+    SAdsrDelta(EPhase phase, ERumblePriority priority)
+        : x1c_priority(priority), x20_phase(phase)
+    {}
+    SAdsrDelta(EPhase phase)
+        : x1c_priority(ERumblePriority::None), x20_phase(phase)
+    {}
+
+    static SAdsrDelta Stopped() { return SAdsrDelta(EPhase::Stop); }
+    static SAdsrDelta Start(ERumblePriority priority) { return SAdsrDelta(EPhase::Start, priority); }
+};
+}
+
+#endif // CRUMBLEVOICE_HPP

From 513465e9f2ec8705cdb8ab0e7ca9c9a9084f54ec Mon Sep 17 00:00:00 2001
From: Phillip Stephens <antidote.crk@gmail.com>
Date: Sun, 21 Feb 2016 14:05:11 -0800
Subject: [PATCH 15/22] Add PTLA DNA

---
 DataSpec/DNAMP2/CMakeLists.txt |  1 +
 DataSpec/DNAMP2/PTLA.hpp       | 72 ++++++++++++++++++++++++++++++++++
 2 files changed, 73 insertions(+)
 create mode 100644 DataSpec/DNAMP2/PTLA.hpp

diff --git a/DataSpec/DNAMP2/CMakeLists.txt b/DataSpec/DNAMP2/CMakeLists.txt
index 0bd09ef53..7c1e4b45c 100644
--- a/DataSpec/DNAMP2/CMakeLists.txt
+++ b/DataSpec/DNAMP2/CMakeLists.txt
@@ -6,6 +6,7 @@ make_dnalist(liblist
              CINF
              CSKR
              MREA
+             PTLA
              DeafBabe)
 add_library(DNAMP2
             DNAMP2.hpp DNAMP2.cpp
diff --git a/DataSpec/DNAMP2/PTLA.hpp b/DataSpec/DNAMP2/PTLA.hpp
new file mode 100644
index 000000000..2e59e74c8
--- /dev/null
+++ b/DataSpec/DNAMP2/PTLA.hpp
@@ -0,0 +1,72 @@
+#ifndef PTLA_HPP
+#define PTLA_HPP
+
+#include "../DNACommon/DNACommon.hpp"
+
+namespace DataSpec
+{
+namespace DNAMP2
+{
+struct PTLA : BigDNA
+{
+    DECL_DNA
+    Value<atUint32> magic;
+    Value<atUint32> version;
+    struct UnknownStruct1 : BigDNA
+    {
+        DECL_DNA
+        Value<atUint32> count;
+        struct Entry : BigDNA
+        {
+            DECL_DNA
+            Value<float> unknown1;
+            Value<float> unknown2;
+            Value<float> unknown3;
+            Value<float> unknown4;
+            Value<atUint16> unknown5;
+            Value<atUint16> unknown6;
+        };
+        Vector<Entry, DNA_COUNT(count)> entries;
+        Value<atVec3f> unknown[2];
+    };
+    Value<atUint32> count1;
+    Vector<UnknownStruct1, DNA_COUNT(count1)> entries1;
+
+    struct UnknownStruct2 : BigDNA
+    {
+        DECL_DNA
+        Value<atUint32> count;
+        struct Entry : BigDNA
+        {
+            DECL_DNA
+            Value<float> unknown1;
+            Value<float> unknown2;
+            Value<float> unknown3;
+            Value<float> unknown4;
+        };
+        Vector<Entry, DNA_COUNT(count)> entries;
+        Value<atUint16> unknown;
+    };
+    Value<atUint32> count2;
+    Vector<UnknownStruct2, DNA_COUNT(count2)> entries2;
+
+    Value<atUint32> shortCount1;
+    Vector<atUint16, DNA_COUNT(shortCount1)> shorts1;
+
+    Value<atUint32> shortCount2;
+    Vector<atUint16, DNA_COUNT(shortCount2)> shorts2;
+
+    struct UnknownStruct3 : BigDNA
+    {
+        DECL_DNA
+        Value<atVec3f> unknown1[2];
+        Value<atUint16> unknown2;
+        Value<atUint16> unknown3;
+        Value<atUint16> unknown4;
+    };
+    Value<atUint32> count3;
+    Vector<UnknownStruct3, DNA_COUNT(count3)> entries3;
+};
+}
+}
+#endif // PTLA_HPP

From f09019246d609abd42f41265de4fe955138de3ef Mon Sep 17 00:00:00 2001
From: Phillip Stephens <antidote.crk@gmail.com>
Date: Mon, 22 Feb 2016 18:08:13 -0800
Subject: [PATCH 16/22] Factory fixes

---
 Runtime/Particle/CDecalDataFactory.cpp            | 8 +++++++-
 Runtime/Particle/CDecalDataFactory.hpp            | 2 +-
 Runtime/Particle/CParticleElectricDataFactory.cpp | 2 +-
 Runtime/Particle/CProjectileWeaponDataFactory.cpp | 3 +++
 4 files changed, 12 insertions(+), 3 deletions(-)

diff --git a/Runtime/Particle/CDecalDataFactory.cpp b/Runtime/Particle/CDecalDataFactory.cpp
index 33d01bb1f..8427e1e9b 100644
--- a/Runtime/Particle/CDecalDataFactory.cpp
+++ b/Runtime/Particle/CDecalDataFactory.cpp
@@ -4,9 +4,15 @@
 
 namespace pshag
 {
-std::unique_ptr<IObj> FDealDataFactory(const SObjectTag &tag, CInputStream &in, const CVParamTransfer &vparms)
+CDecalDescription* CDecalDataFactory::GetGeneratorDesc(CInputStream& in, CSimplePool* resPool)
+{
+    return nullptr;
+}
+
+std::unique_ptr<IObj> FDecalDataFactory(const SObjectTag &tag, CInputStream &in, const CVParamTransfer &vparms)
 {
     CSimplePool* sp = static_cast<CSimplePool*>(static_cast<TObjOwnerParam<IObjectStore*>*>(vparms.GetObj())->GetParam());
     return TToken<CDecalDescription>::GetIObjObjectFor(std::unique_ptr<CDecalDescription>(CDecalDataFactory::GetGeneratorDesc(in, sp)));
 }
+
 }
diff --git a/Runtime/Particle/CDecalDataFactory.hpp b/Runtime/Particle/CDecalDataFactory.hpp
index 7d3426f2f..55bb7d22e 100644
--- a/Runtime/Particle/CDecalDataFactory.hpp
+++ b/Runtime/Particle/CDecalDataFactory.hpp
@@ -20,6 +20,6 @@ public:
     static bool CreateDPSM(CDecalDescription* desc,CInputStream& in,CSimplePool* resPool);
 };
 
-std::unique_ptr<IObj> FDealDataFactory(const SObjectTag& tag, CInputStream& in, const CVParamTransfer& vparms);
+std::unique_ptr<IObj> FDecalDataFactory(const SObjectTag& tag, CInputStream& in, const CVParamTransfer& vparms);
 }
 #endif // __PSHAG_CDECALDATAFACTORY_HPP__
diff --git a/Runtime/Particle/CParticleElectricDataFactory.cpp b/Runtime/Particle/CParticleElectricDataFactory.cpp
index a5c847c4c..47e548736 100644
--- a/Runtime/Particle/CParticleElectricDataFactory.cpp
+++ b/Runtime/Particle/CParticleElectricDataFactory.cpp
@@ -132,7 +132,7 @@ void CParticleElectricDataFactory::LoadELSMTokens(CElectricDescription* desc)
         desc->x60_EPSM.m_gen = desc->x60_EPSM.m_token.GetObj();
 }
 
-std::unique_ptr<pshag::IObj> FParticleElecrticFactory(const pshag::SObjectTag &tag, pshag::CInputStream &in, const pshag::CVParamTransfer &vparms)
+std::unique_ptr<IObj> FParticleElectricDataFactory(const SObjectTag &tag, CInputStream &in, const CVParamTransfer &vparms)
 {
     CSimplePool* sp = static_cast<CSimplePool*>(static_cast<TObjOwnerParam<IObjectStore*>*>(vparms.GetObj())->GetParam());
     return TToken<CElectricDescription>::GetIObjObjectFor(std::unique_ptr<CElectricDescription>(CParticleElectricDataFactory::GetGeneratorDesc(in, sp)));
diff --git a/Runtime/Particle/CProjectileWeaponDataFactory.cpp b/Runtime/Particle/CProjectileWeaponDataFactory.cpp
index fa47bc7cb..d32a03a45 100644
--- a/Runtime/Particle/CProjectileWeaponDataFactory.cpp
+++ b/Runtime/Particle/CProjectileWeaponDataFactory.cpp
@@ -78,6 +78,9 @@ bool CProjectileWeaponDataFactory::CreateWPSM(CWeaponDescription* desc, CInputSt
             desc->x2a_AP11 = CPF::GetBool(in);
         break;
         case SBIG('AP21'):
+            desc->x2b_AP21 = CPF::GetBool(in);
+        break;
+        case SBIG('AS11'):
             desc->x2c_AS11 = CPF::GetBool(in);
         break;
         case SBIG('AS12'):

From 7e7f789c28e86f3bf6ed9717aa3f1aa0ad71c034 Mon Sep 17 00:00:00 2001
From: Jack Andersen <jackoalan@gmail.com>
Date: Mon, 22 Feb 2016 16:34:16 -1000
Subject: [PATCH 17/22] Vulkan updates

---
 CMakeLists.txt                                |   1 +
 Runtime/CGraphics.hpp                         |   6 +-
 Runtime/CTextureBoo.cpp                       |  50 +++---
 Runtime/Graphics/CLineRenderer.cpp            |  12 +-
 Runtime/Graphics/CLineRendererShaders.hpp     |   7 +-
 Runtime/Graphics/CLineRendererShadersGLSL.cpp |  60 ++++++-
 Runtime/Particle/CElementGen.cpp              |  16 +-
 Runtime/Particle/CElementGenShaders.hpp       |   7 +-
 Runtime/Particle/CElementGenShadersGLSL.cpp   | 158 +++++++++++++++++-
 hecl                                          |   2 +-
 libSpecter                                    |   2 +-
 11 files changed, 281 insertions(+), 40 deletions(-)

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 6682e6622..04fd7b20b 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -77,6 +77,7 @@ set(HECL_DATASPEC_PUSHES
     HECL::Database::DATA_SPEC_REGISTRY.push_back(&DataSpec::SpecEntMP2);
     HECL::Database::DATA_SPEC_REGISTRY.push_back(&DataSpec::SpecEntMP3);")
 add_subdirectory(hecl)
+add_definitions(${BOO_SYS_DEFINES})
 add_subdirectory(libSpecter)
 set(SPECTER_INCLUDE_DIR libSpecter/include libSpecter/freetype2/include)
 add_subdirectory(NODLib)
diff --git a/Runtime/CGraphics.hpp b/Runtime/CGraphics.hpp
index ca84f1e39..0b5eab90f 100644
--- a/Runtime/CGraphics.hpp
+++ b/Runtime/CGraphics.hpp
@@ -206,14 +206,12 @@ public:
     {
         g_BooMainCommandQueue->setShaderDataBinding(binding);
     }
-    static void DrawInstances(boo::Primitive prim, size_t start, size_t count, size_t instCount)
+    static void DrawInstances(size_t start, size_t count, size_t instCount)
     {
-        g_BooMainCommandQueue->setDrawPrimitive(prim);
         g_BooMainCommandQueue->drawInstances(start, count, instCount);
     }
-    static void DrawArray(boo::Primitive prim, size_t start, size_t count)
+    static void DrawArray(size_t start, size_t count)
     {
-        g_BooMainCommandQueue->setDrawPrimitive(prim);
         g_BooMainCommandQueue->draw(start, count);
     }
 };
diff --git a/Runtime/CTextureBoo.cpp b/Runtime/CTextureBoo.cpp
index 72e11ce66..4f1d59cb4 100644
--- a/Runtime/CTextureBoo.cpp
+++ b/Runtime/CTextureBoo.cpp
@@ -111,10 +111,11 @@ void CTexture::BuildI4FromGCN(CInputStream& in)
             h /= 2;
     }
 
+    boo::ITextureS* tmp;
     m_booToken = CGraphics::g_BooFactory->newStaticTextureNoContext(x4_w, x6_h, x8_mips,
                                                                     boo::TextureFormat::RGBA8,
-                                                                    buf.get(), texelCount * 4,
-                                                                    reinterpret_cast<boo::ITextureS**>(&m_booTex));
+                                                                    buf.get(), texelCount * 4, tmp);
+    m_booTex = tmp;
 }
 
 void CTexture::BuildI8FromGCN(CInputStream& in)
@@ -157,10 +158,11 @@ void CTexture::BuildI8FromGCN(CInputStream& in)
             h /= 2;
     }
 
+    boo::ITextureS* tmp;
     m_booToken = CGraphics::g_BooFactory->newStaticTextureNoContext(x4_w, x6_h, x8_mips,
                                                                     boo::TextureFormat::RGBA8,
-                                                                    buf.get(), texelCount * 4,
-                                                                    reinterpret_cast<boo::ITextureS**>(&m_booTex));
+                                                                    buf.get(), texelCount * 4, tmp);
+    m_booTex = tmp;
 }
 
 void CTexture::BuildIA4FromGCN(CInputStream& in)
@@ -204,10 +206,11 @@ void CTexture::BuildIA4FromGCN(CInputStream& in)
             h /= 2;
     }
 
+    boo::ITextureS* tmp;
     m_booToken = CGraphics::g_BooFactory->newStaticTextureNoContext(x4_w, x6_h, x8_mips,
                                                                     boo::TextureFormat::RGBA8,
-                                                                    buf.get(), texelCount * 4,
-                                                                    reinterpret_cast<boo::ITextureS**>(&m_booTex));
+                                                                    buf.get(), texelCount * 4, tmp);
+    m_booTex = tmp;
 }
 
 void CTexture::BuildIA8FromGCN(CInputStream& in)
@@ -251,10 +254,11 @@ void CTexture::BuildIA8FromGCN(CInputStream& in)
             h /= 2;
     }
 
+    boo::ITextureS* tmp;
     m_booToken = CGraphics::g_BooFactory->newStaticTextureNoContext(x4_w, x6_h, x8_mips,
                                                                     boo::TextureFormat::RGBA8,
-                                                                    buf.get(), texelCount * 4,
-                                                                    reinterpret_cast<boo::ITextureS**>(&m_booTex));
+                                                                    buf.get(), texelCount * 4, tmp);
+    m_booTex = tmp;
 }
 
 static std::vector<RGBA8> DecodePalette(int numEntries, CInputStream& in)
@@ -357,10 +361,11 @@ void CTexture::BuildC4FromGCN(CInputStream& in)
             h /= 2;
     }
 
+    boo::ITextureS* tmp;
     m_booToken = CGraphics::g_BooFactory->newStaticTextureNoContext(x4_w, x6_h, x8_mips,
                                                                     boo::TextureFormat::RGBA8,
-                                                                    buf.get(), texelCount * 4,
-                                                                    reinterpret_cast<boo::ITextureS**>(&m_booTex));
+                                                                    buf.get(), texelCount * 4, tmp);
+    m_booTex = tmp;
 }
 
 void CTexture::BuildC8FromGCN(CInputStream& in)
@@ -399,10 +404,11 @@ void CTexture::BuildC8FromGCN(CInputStream& in)
             h /= 2;
     }
 
+    boo::ITextureS* tmp;
     m_booToken = CGraphics::g_BooFactory->newStaticTextureNoContext(x4_w, x6_h, x8_mips,
                                                                     boo::TextureFormat::RGBA8,
-                                                                    buf.get(), texelCount * 4,
-                                                                    reinterpret_cast<boo::ITextureS**>(&m_booTex));
+                                                                    buf.get(), texelCount * 4, tmp);
+    m_booTex = tmp;
 }
 
 void CTexture::BuildC14X2FromGCN(CInputStream& in)
@@ -449,10 +455,11 @@ void CTexture::BuildRGB565FromGCN(CInputStream& in)
             h /= 2;
     }
 
+    boo::ITextureS* tmp;
     m_booToken = CGraphics::g_BooFactory->newStaticTextureNoContext(x4_w, x6_h, x8_mips,
                                                                     boo::TextureFormat::RGBA8,
-                                                                    buf.get(), texelCount * 4,
-                                                                    reinterpret_cast<boo::ITextureS**>(&m_booTex));
+                                                                    buf.get(), texelCount * 4, tmp);
+    m_booTex = tmp;
 }
 
 void CTexture::BuildRGB5A3FromGCN(CInputStream& in)
@@ -504,10 +511,11 @@ void CTexture::BuildRGB5A3FromGCN(CInputStream& in)
             h /= 2;
     }
 
+    boo::ITextureS* tmp;
     m_booToken = CGraphics::g_BooFactory->newStaticTextureNoContext(x4_w, x6_h, x8_mips,
                                                                     boo::TextureFormat::RGBA8,
-                                                                    buf.get(), texelCount * 4,
-                                                                    reinterpret_cast<boo::ITextureS**>(&m_booTex));
+                                                                    buf.get(), texelCount * 4, tmp);
+    m_booTex = tmp;
 }
 
 void CTexture::BuildRGBA8FromGCN(CInputStream& in)
@@ -559,10 +567,11 @@ void CTexture::BuildRGBA8FromGCN(CInputStream& in)
             h /= 2;
     }
 
+    boo::ITextureS* tmp;
     m_booToken = CGraphics::g_BooFactory->newStaticTextureNoContext(x4_w, x6_h, x8_mips,
                                                                     boo::TextureFormat::RGBA8,
-                                                                    buf.get(), texelCount * 4,
-                                                                    reinterpret_cast<boo::ITextureS**>(&m_booTex));
+                                                                    buf.get(), texelCount * 4, tmp);
+    m_booTex = tmp;
 }
 
 struct DXT1Block
@@ -621,10 +630,11 @@ void CTexture::BuildDXT1FromGCN(CInputStream& in)
             h /= 2;
     }
 
+    boo::ITextureS* tmp;
     m_booToken = CGraphics::g_BooFactory->newStaticTextureNoContext(x4_w, x6_h, x8_mips,
                                                                     boo::TextureFormat::DXT1,
-                                                                    buf.get(), blockCount * 8,
-                                                                    reinterpret_cast<boo::ITextureS**>(&m_booTex));
+                                                                    buf.get(), blockCount * 8, tmp);
+    m_booTex = tmp;
 }
 
 CTexture::CTexture(CInputStream& in)
diff --git a/Runtime/Graphics/CLineRenderer.cpp b/Runtime/Graphics/CLineRenderer.cpp
index 47dc8300a..8effbe535 100644
--- a/Runtime/Graphics/CLineRenderer.cpp
+++ b/Runtime/Graphics/CLineRenderer.cpp
@@ -31,10 +31,16 @@ void CLineRendererShaders::Initialize()
     case boo::IGraphicsDataFactory::Platform::D3D12:
         m_bindFactory.reset(Initialize(*static_cast<boo::ID3DDataFactory*>(CGraphics::g_BooFactory)));
         break;
-#elif BOO_HAS_METAL
+#endif
+#if BOO_HAS_METAL
     case boo::IGraphicsDataFactory::Platform::Metal:
         m_bindFactory.reset(Initialize(*static_cast<boo::MetalDataFactory*>(CGraphics::g_BooFactory)));
         break;
+#endif
+#if BOO_HAS_VULKAN
+    case boo::IGraphicsDataFactory::Platform::Vulkan:
+        m_bindFactory.reset(Initialize(*static_cast<boo::VulkanDataFactory*>(CGraphics::g_BooFactory)));
+        break;
 #endif
     default: break;
     }
@@ -389,13 +395,13 @@ void CLineRenderer::Render(const Zeus::CColor& moduColor)
     {
         m_vertBuf->load(g_StaticLineVertsTex.data(), sizeof(SDrawVertTex) * g_StaticLineVertsTex.size());
         CGraphics::SetShaderDataBinding(m_shaderBind);
-        CGraphics::DrawArray(boo::Primitive::TriStrips, 0, g_StaticLineVertsTex.size());
+        CGraphics::DrawArray(0, g_StaticLineVertsTex.size());
     }
     else
     {
         m_vertBuf->load(g_StaticLineVertsNoTex.data(), sizeof(SDrawVertNoTex) * g_StaticLineVertsNoTex.size());
         CGraphics::SetShaderDataBinding(m_shaderBind);
-        CGraphics::DrawArray(boo::Primitive::TriStrips, 0, g_StaticLineVertsNoTex.size());
+        CGraphics::DrawArray(0, g_StaticLineVertsNoTex.size());
     }
 }
 
diff --git a/Runtime/Graphics/CLineRendererShaders.hpp b/Runtime/Graphics/CLineRendererShaders.hpp
index bd26608b4..4d810e6d7 100644
--- a/Runtime/Graphics/CLineRendererShaders.hpp
+++ b/Runtime/Graphics/CLineRendererShaders.hpp
@@ -5,6 +5,7 @@
 #include "boo/graphicsdev/GL.hpp"
 #include "boo/graphicsdev/D3D.hpp"
 #include "boo/graphicsdev/Metal.hpp"
+#include "boo/graphicsdev/Vulkan.hpp"
 
 namespace pshag
 {
@@ -36,9 +37,13 @@ public:
     static IDataBindingFactory* Initialize(boo::GLDataFactory& factory);
 #if _WIN32
     static IDataBindingFactory* Initialize(boo::ID3DDataFactory& factory);
-#elif BOO_HAS_METAL
+#endif
+#if BOO_HAS_METAL
     static IDataBindingFactory* Initialize(boo::MetalDataFactory& factory);
 #endif
+#if BOO_HAS_VULKAN
+    static IDataBindingFactory* Initialize(boo::VulkanDataFactory& factory);
+#endif
 
     static void Initialize();
     static void Shutdown();
diff --git a/Runtime/Graphics/CLineRendererShadersGLSL.cpp b/Runtime/Graphics/CLineRendererShadersGLSL.cpp
index caf19c08a..28d1d05e2 100644
--- a/Runtime/Graphics/CLineRendererShadersGLSL.cpp
+++ b/Runtime/Graphics/CLineRendererShadersGLSL.cpp
@@ -81,7 +81,7 @@ static const char* FS_GLSL_NOTEX =
 "    colorOut = vtf.color;\n"
 "}\n";
 
-struct GLSLLineDataBindingFactory : CLineRendererShaders::IDataBindingFactory
+struct OGLLineDataBindingFactory : CLineRendererShaders::IDataBindingFactory
 {
     void BuildShaderDataBinding(CLineRenderer& renderer, boo::IShaderPipeline* pipeline, boo::ITexture* texture)
     {
@@ -136,7 +136,63 @@ CLineRendererShaders::IDataBindingFactory* CLineRendererShaders::Initialize(boo:
                                                 boo::BlendFactor::SrcAlpha, boo::BlendFactor::One,
                                                 false, false, false);
 
-    return new struct GLSLLineDataBindingFactory;
+    return new struct OGLLineDataBindingFactory;
 }
 
+#if BOO_HAS_VULKAN
+struct VulkanLineDataBindingFactory : CLineRendererShaders::IDataBindingFactory
+{
+    void BuildShaderDataBinding(CLineRenderer& renderer, boo::IShaderPipeline* pipeline, boo::ITexture* texture)
+    {
+        int texCount = 0;
+        boo::ITexture* textures[1];
+
+        if (texture)
+        {
+            textures[0] = texture;
+            texCount = 1;
+        }
+
+        boo::IGraphicsBuffer* uniforms[] = {renderer.m_uniformBuf};
+
+        renderer.m_shaderBind = CGraphics::g_BooFactory->newShaderDataBinding(pipeline, nullptr, renderer.m_vertBuf,
+                                                                              nullptr, nullptr, 1, uniforms,
+                                                                              texCount, textures);
+    }
+};
+
+CLineRendererShaders::IDataBindingFactory* CLineRendererShaders::Initialize(boo::VulkanDataFactory& factory)
+{
+    static const boo::VertexElementDescriptor VtxFmtTex[] =
+    {
+        {nullptr, nullptr, boo::VertexSemantic::Position4},
+        {nullptr, nullptr, boo::VertexSemantic::Color},
+        {nullptr, nullptr, boo::VertexSemantic::UV4}
+    };
+    m_texVtxFmt = factory.newVertexFormat(3, VtxFmtTex);
+
+    static const boo::VertexElementDescriptor VtxFmtNoTex[] =
+    {
+        {nullptr, nullptr, boo::VertexSemantic::Position4},
+        {nullptr, nullptr, boo::VertexSemantic::Color}
+    };
+    m_noTexVtxFmt = factory.newVertexFormat(2, VtxFmtNoTex);
+
+    m_texAlpha = factory.newShaderPipeline(VS_GLSL_TEX, FS_GLSL_TEX, m_texVtxFmt,
+                                           boo::BlendFactor::SrcAlpha, boo::BlendFactor::InvSrcAlpha,
+                                           false, true, false);
+    m_texAdditive = factory.newShaderPipeline(VS_GLSL_TEX, FS_GLSL_TEX, m_texVtxFmt,
+                                              boo::BlendFactor::SrcAlpha, boo::BlendFactor::One,
+                                              false, false, false);
+    m_noTexAlpha = factory.newShaderPipeline(VS_GLSL_NOTEX, FS_GLSL_NOTEX, m_noTexVtxFmt,
+                                             boo::BlendFactor::SrcAlpha, boo::BlendFactor::InvSrcAlpha,
+                                             false, true, false);
+    m_noTexAdditive = factory.newShaderPipeline(VS_GLSL_NOTEX, FS_GLSL_NOTEX, m_noTexVtxFmt,
+                                                boo::BlendFactor::SrcAlpha, boo::BlendFactor::One,
+                                                false, false, false);
+
+    return new struct VulkanLineDataBindingFactory;
+}
+#endif
+
 }
diff --git a/Runtime/Particle/CElementGen.cpp b/Runtime/Particle/CElementGen.cpp
index f50ad12c7..5f7cdd5fb 100644
--- a/Runtime/Particle/CElementGen.cpp
+++ b/Runtime/Particle/CElementGen.cpp
@@ -185,10 +185,16 @@ void CElementGenShaders::Initialize()
     case boo::IGraphicsDataFactory::Platform::D3D12:
         m_bindFactory.reset(Initialize(*static_cast<boo::ID3DDataFactory*>(CGraphics::g_BooFactory)));
         break;
-#elif BOO_HAS_METAL
+#endif
+#if BOO_HAS_METAL
     case boo::IGraphicsDataFactory::Platform::Metal:
         m_bindFactory.reset(Initialize(*static_cast<boo::MetalDataFactory*>(CGraphics::g_BooFactory)));
         break;
+#endif
+#if BOO_HAS_VULKAN
+    case boo::IGraphicsDataFactory::Platform::Vulkan:
+        m_bindFactory.reset(Initialize(*static_cast<boo::VulkanDataFactory*>(CGraphics::g_BooFactory)));
+        break;
 #endif
     default: break;
     }
@@ -1706,11 +1712,11 @@ void CElementGen::RenderParticles()
         {
         case CElementGenShaders::EShaderClass::Tex:
             m_instBuf->load(g_instTexData.data(), g_instTexData.size() * sizeof(SParticleInstanceTex));
-            CGraphics::DrawInstances(boo::Primitive::TriStrips, 0, 4, g_instTexData.size());
+            CGraphics::DrawInstances(0, 4, g_instTexData.size());
             break;
         case CElementGenShaders::EShaderClass::NoTex:
             m_instBuf->load(g_instNoTexData.data(), g_instNoTexData.size() * sizeof(SParticleInstanceNoTex));
-            CGraphics::DrawInstances(boo::Primitive::TriStrips, 0, 4, g_instNoTexData.size());
+            CGraphics::DrawInstances(0, 4, g_instNoTexData.size());
             break;
         default: break;
         }
@@ -1845,11 +1851,11 @@ void CElementGen::RenderParticles()
         {
         case CElementGenShaders::EShaderClass::Tex:
             m_instBuf->load(g_instTexData.data(), g_instTexData.size() * sizeof(SParticleInstanceTex));
-            CGraphics::DrawInstances(boo::Primitive::TriStrips, 0, 4, g_instTexData.size());
+            CGraphics::DrawInstances(0, 4, g_instTexData.size());
             break;
         case CElementGenShaders::EShaderClass::NoTex:
             m_instBuf->load(g_instNoTexData.data(), g_instNoTexData.size() * sizeof(SParticleInstanceNoTex));
-            CGraphics::DrawInstances(boo::Primitive::TriStrips, 0, 4, g_instNoTexData.size());
+            CGraphics::DrawInstances(0, 4, g_instNoTexData.size());
             break;
         default: break;
         }
diff --git a/Runtime/Particle/CElementGenShaders.hpp b/Runtime/Particle/CElementGenShaders.hpp
index 3c7977fd0..f2eab5303 100644
--- a/Runtime/Particle/CElementGenShaders.hpp
+++ b/Runtime/Particle/CElementGenShaders.hpp
@@ -5,6 +5,7 @@
 #include "boo/graphicsdev/GL.hpp"
 #include "boo/graphicsdev/D3D.hpp"
 #include "boo/graphicsdev/Metal.hpp"
+#include "boo/graphicsdev/Vulkan.hpp"
 
 namespace pshag
 {
@@ -63,9 +64,13 @@ public:
     static IDataBindingFactory* Initialize(boo::GLDataFactory& factory);
 #if _WIN32
     static IDataBindingFactory* Initialize(boo::ID3DDataFactory& factory);
-#elif BOO_HAS_METAL
+#endif
+#if BOO_HAS_METAL
     static IDataBindingFactory* Initialize(boo::MetalDataFactory& factory);
 #endif
+#if BOO_HAS_VULKAN
+    static IDataBindingFactory* Initialize(boo::VulkanDataFactory& factory);
+#endif
 
     static void Initialize();
     static void Shutdown();
diff --git a/Runtime/Particle/CElementGenShadersGLSL.cpp b/Runtime/Particle/CElementGenShadersGLSL.cpp
index e387204e5..73c392d93 100644
--- a/Runtime/Particle/CElementGenShadersGLSL.cpp
+++ b/Runtime/Particle/CElementGenShadersGLSL.cpp
@@ -177,7 +177,7 @@ static const char* FS_GLSL_NOTEX =
 "    colorOut = vtf.color;\n"
 "}\n";
 
-struct GLSLElementDataBindingFactory : CElementGenShaders::IDataBindingFactory
+struct OGLElementDataBindingFactory : CElementGenShaders::IDataBindingFactory
 {
     void BuildShaderDataBinding(CElementGen& gen,
                                 boo::IShaderPipeline* regPipeline,
@@ -333,7 +333,161 @@ CElementGenShaders::IDataBindingFactory* CElementGenShaders::Initialize(boo::GLD
                                                        boo::BlendFactor::SrcAlpha, boo::BlendFactor::One,
                                                        false, false, false);
 
-    return new struct GLSLElementDataBindingFactory;
+    return new struct OGLElementDataBindingFactory;
 }
 
+#if BOO_HAS_VULKAN
+struct VulkanElementDataBindingFactory : CElementGenShaders::IDataBindingFactory
+{
+    void BuildShaderDataBinding(CElementGen& gen,
+                                boo::IShaderPipeline* regPipeline,
+                                boo::IShaderPipeline* redToAlphaPipeline)
+    {
+        CGenDescription* desc = gen.GetDesc();
+
+        CUVElement* texr = desc->x54_TEXR.get();
+        CUVElement* tind = desc->x58_TIND.get();
+        int texCount = 0;
+        boo::ITexture* textures[3];
+
+        if (texr)
+        {
+            textures[0] = texr->GetValueTexture(0).GetObj()->GetBooTexture();
+            texCount = 1;
+            if (tind)
+            {
+                textures[1] = CGraphics::g_SpareTexture;
+                textures[2] = tind->GetValueTexture(0).GetObj()->GetBooTexture();
+                texCount = 3;
+            }
+        }
+
+        boo::IGraphicsBuffer* uniforms[] = {gen.m_uniformBuf};
+
+        if (regPipeline)
+            gen.m_normalDataBind = CGraphics::g_BooFactory->newShaderDataBinding(regPipeline, nullptr, nullptr,
+                                                                                 gen.m_instBuf, nullptr, 1, uniforms,
+                                                                                 texCount, textures);
+        if (redToAlphaPipeline)
+            gen.m_redToAlphaDataBind = CGraphics::g_BooFactory->newShaderDataBinding(redToAlphaPipeline, nullptr, nullptr,
+                                                                                     gen.m_instBuf, nullptr, 1, uniforms,
+                                                                                     texCount, textures);
+    }
+};
+
+CElementGenShaders::IDataBindingFactory* CElementGenShaders::Initialize(boo::VulkanDataFactory& factory)
+{
+    static const boo::VertexElementDescriptor TexFmtTex[] =
+    {
+        {nullptr, nullptr, boo::VertexSemantic::Position4 | boo::VertexSemantic::Instanced, 0},
+        {nullptr, nullptr, boo::VertexSemantic::Position4 | boo::VertexSemantic::Instanced, 1},
+        {nullptr, nullptr, boo::VertexSemantic::Position4 | boo::VertexSemantic::Instanced, 2},
+        {nullptr, nullptr, boo::VertexSemantic::Position4 | boo::VertexSemantic::Instanced, 3},
+        {nullptr, nullptr, boo::VertexSemantic::Color | boo::VertexSemantic::Instanced},
+        {nullptr, nullptr, boo::VertexSemantic::UV4 | boo::VertexSemantic::Instanced, 0},
+        {nullptr, nullptr, boo::VertexSemantic::UV4 | boo::VertexSemantic::Instanced, 1},
+        {nullptr, nullptr, boo::VertexSemantic::UV4 | boo::VertexSemantic::Instanced, 2},
+        {nullptr, nullptr, boo::VertexSemantic::UV4 | boo::VertexSemantic::Instanced, 3}
+    };
+    m_vtxFormatTex = factory.newVertexFormat(9, TexFmtTex);
+
+    static const boo::VertexElementDescriptor TexFmtIndTex[] =
+    {
+        {nullptr, nullptr, boo::VertexSemantic::Position4 | boo::VertexSemantic::Instanced, 0},
+        {nullptr, nullptr, boo::VertexSemantic::Position4 | boo::VertexSemantic::Instanced, 1},
+        {nullptr, nullptr, boo::VertexSemantic::Position4 | boo::VertexSemantic::Instanced, 2},
+        {nullptr, nullptr, boo::VertexSemantic::Position4 | boo::VertexSemantic::Instanced, 3},
+        {nullptr, nullptr, boo::VertexSemantic::Color | boo::VertexSemantic::Instanced},
+        {nullptr, nullptr, boo::VertexSemantic::UV4 | boo::VertexSemantic::Instanced, 0},
+        {nullptr, nullptr, boo::VertexSemantic::UV4 | boo::VertexSemantic::Instanced, 1},
+        {nullptr, nullptr, boo::VertexSemantic::UV4 | boo::VertexSemantic::Instanced, 2},
+        {nullptr, nullptr, boo::VertexSemantic::UV4 | boo::VertexSemantic::Instanced, 3},
+        {nullptr, nullptr, boo::VertexSemantic::UV4 | boo::VertexSemantic::Instanced, 4},
+        {nullptr, nullptr, boo::VertexSemantic::UV4 | boo::VertexSemantic::Instanced, 5},
+        {nullptr, nullptr, boo::VertexSemantic::UV4 | boo::VertexSemantic::Instanced, 6},
+        {nullptr, nullptr, boo::VertexSemantic::UV4 | boo::VertexSemantic::Instanced, 7}
+    };
+    m_vtxFormatIndTex = CGraphics::g_BooFactory->newVertexFormat(13, TexFmtIndTex);
+
+    static const boo::VertexElementDescriptor TexFmtNoTex[] =
+    {
+        {nullptr, nullptr, boo::VertexSemantic::Position4 | boo::VertexSemantic::Instanced, 0},
+        {nullptr, nullptr, boo::VertexSemantic::Position4 | boo::VertexSemantic::Instanced, 1},
+        {nullptr, nullptr, boo::VertexSemantic::Position4 | boo::VertexSemantic::Instanced, 2},
+        {nullptr, nullptr, boo::VertexSemantic::Position4 | boo::VertexSemantic::Instanced, 3},
+        {nullptr, nullptr, boo::VertexSemantic::Color | boo::VertexSemantic::Instanced}
+    };
+    m_vtxFormatNoTex = CGraphics::g_BooFactory->newVertexFormat(5, TexFmtNoTex);
+
+    m_texZTestZWrite = factory.newShaderPipeline(VS_GLSL_TEX, FS_GLSL_TEX, m_vtxFormatTex,
+                                                 boo::BlendFactor::SrcAlpha, boo::BlendFactor::InvSrcAlpha,
+                                                 true, true, false);
+    m_texNoZTestZWrite = factory.newShaderPipeline(VS_GLSL_TEX, FS_GLSL_TEX, m_vtxFormatTex,
+                                                   boo::BlendFactor::SrcAlpha, boo::BlendFactor::InvSrcAlpha,
+                                                   false, true, false);
+    m_texZTestNoZWrite = factory.newShaderPipeline(VS_GLSL_TEX, FS_GLSL_TEX, m_vtxFormatTex,
+                                                   boo::BlendFactor::SrcAlpha, boo::BlendFactor::InvSrcAlpha,
+                                                   true, false, false);
+    m_texNoZTestNoZWrite = factory.newShaderPipeline(VS_GLSL_TEX, FS_GLSL_TEX, m_vtxFormatTex,
+                                                     boo::BlendFactor::SrcAlpha, boo::BlendFactor::InvSrcAlpha,
+                                                     false, false, false);
+
+    m_texAdditiveZTest = factory.newShaderPipeline(VS_GLSL_TEX, FS_GLSL_TEX, m_vtxFormatTex,
+                                                   boo::BlendFactor::SrcAlpha, boo::BlendFactor::One,
+                                                   true, false, false);
+    m_texAdditiveNoZTest = factory.newShaderPipeline(VS_GLSL_TEX, FS_GLSL_TEX, m_vtxFormatTex,
+                                                     boo::BlendFactor::SrcAlpha, boo::BlendFactor::One,
+                                                     false, false, false);
+
+    m_texRedToAlphaZTest = factory.newShaderPipeline(VS_GLSL_TEX, FS_GLSL_TEX_REDTOALPHA, m_vtxFormatTex,
+                                                     boo::BlendFactor::SrcAlpha, boo::BlendFactor::InvSrcAlpha,
+                                                     true, false, false);
+    m_texRedToAlphaNoZTest = factory.newShaderPipeline(VS_GLSL_TEX, FS_GLSL_TEX_REDTOALPHA, m_vtxFormatTex,
+                                                       boo::BlendFactor::SrcAlpha, boo::BlendFactor::InvSrcAlpha,
+                                                       false, false, false);
+
+    m_indTexZWrite = factory.newShaderPipeline(VS_GLSL_INDTEX, FS_GLSL_INDTEX, m_vtxFormatIndTex,
+                                               boo::BlendFactor::SrcAlpha, boo::BlendFactor::InvSrcAlpha,
+                                               true, true, false);
+    m_indTexNoZWrite = factory.newShaderPipeline(VS_GLSL_INDTEX, FS_GLSL_INDTEX, m_vtxFormatIndTex,
+                                                 boo::BlendFactor::SrcAlpha, boo::BlendFactor::InvSrcAlpha,
+                                                 true, false, false);
+    m_indTexAdditive = factory.newShaderPipeline(VS_GLSL_INDTEX, FS_GLSL_INDTEX, m_vtxFormatIndTex,
+                                                 boo::BlendFactor::SrcAlpha, boo::BlendFactor::One,
+                                                 true, true, false);
+
+    m_cindTexZWrite = factory.newShaderPipeline(VS_GLSL_INDTEX, FS_GLSL_CINDTEX, m_vtxFormatIndTex,
+                                                boo::BlendFactor::SrcAlpha, boo::BlendFactor::InvSrcAlpha,
+                                                true, true, false);
+    m_cindTexNoZWrite = factory.newShaderPipeline(VS_GLSL_INDTEX, FS_GLSL_CINDTEX, m_vtxFormatIndTex,
+                                                  boo::BlendFactor::SrcAlpha, boo::BlendFactor::InvSrcAlpha,
+                                                  true, false, false);
+    m_cindTexAdditive = factory.newShaderPipeline(VS_GLSL_INDTEX, FS_GLSL_CINDTEX, m_vtxFormatIndTex,
+                                                  boo::BlendFactor::SrcAlpha, boo::BlendFactor::One,
+                                                  true, true, false);
+
+    m_noTexZTestZWrite = factory.newShaderPipeline(VS_GLSL_NOTEX, FS_GLSL_NOTEX, m_vtxFormatNoTex,
+                                                   boo::BlendFactor::SrcAlpha, boo::BlendFactor::InvSrcAlpha,
+                                                   true, true, false);
+    m_noTexNoZTestZWrite = factory.newShaderPipeline(VS_GLSL_NOTEX, FS_GLSL_NOTEX, m_vtxFormatNoTex,
+                                                     boo::BlendFactor::SrcAlpha, boo::BlendFactor::InvSrcAlpha,
+                                                     false, true, false);
+    m_noTexZTestNoZWrite = factory.newShaderPipeline(VS_GLSL_NOTEX, FS_GLSL_NOTEX, m_vtxFormatNoTex,
+                                                     boo::BlendFactor::SrcAlpha, boo::BlendFactor::InvSrcAlpha,
+                                                     true, false, false);
+    m_noTexNoZTestNoZWrite = factory.newShaderPipeline(VS_GLSL_NOTEX, FS_GLSL_NOTEX, m_vtxFormatNoTex,
+                                                       boo::BlendFactor::SrcAlpha, boo::BlendFactor::InvSrcAlpha,
+                                                       false, false, false);
+
+    m_noTexAdditiveZTest = factory.newShaderPipeline(VS_GLSL_NOTEX, FS_GLSL_NOTEX, m_vtxFormatNoTex,
+                                                     boo::BlendFactor::SrcAlpha, boo::BlendFactor::One,
+                                                     true, false, false);
+    m_noTexAdditiveNoZTest = factory.newShaderPipeline(VS_GLSL_NOTEX, FS_GLSL_NOTEX, m_vtxFormatNoTex,
+                                                       boo::BlendFactor::SrcAlpha, boo::BlendFactor::One,
+                                                       false, false, false);
+
+    return new struct VulkanElementDataBindingFactory;
+}
+#endif
+
 }
diff --git a/hecl b/hecl
index e8ab7ce9b..2ff161839 160000
--- a/hecl
+++ b/hecl
@@ -1 +1 @@
-Subproject commit e8ab7ce9b252f02674c88b39a8cdf0a32cc3ba6e
+Subproject commit 2ff161839491dd42362a680221f5ef4bc95f32cc
diff --git a/libSpecter b/libSpecter
index 38b3396e0..c83c1f0b9 160000
--- a/libSpecter
+++ b/libSpecter
@@ -1 +1 @@
-Subproject commit 38b3396e0853e9bf446859a9d8b042044d9fd78e
+Subproject commit c83c1f0b939115497f4a15cfbc2669445e07bdb7

From 0c5a28f03c44503019f3f8a500b88e84bbc8e3c0 Mon Sep 17 00:00:00 2001
From: Phillip Stephens <antidote.crk@gmail.com>
Date: Tue, 23 Feb 2016 01:16:40 -0800
Subject: [PATCH 18/22] Update hecl

---
 hecl | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/hecl b/hecl
index 2ff161839..2b65259a7 160000
--- a/hecl
+++ b/hecl
@@ -1 +1 @@
-Subproject commit 2ff161839491dd42362a680221f5ef4bc95f32cc
+Subproject commit 2b65259a7e6b8b274e8135a8023fd74bbf3c77f2

From 88cbb2b6598887a2e7169cabb5ad522363be7995 Mon Sep 17 00:00:00 2001
From: Phillip Stephens <antidote.crk@gmail.com>
Date: Tue, 23 Feb 2016 02:34:19 -0800
Subject: [PATCH 19/22] Add DSPC factory

---
 Runtime/Particle/CDecalDataFactory.cpp        | 124 ++++++++++++++++++
 Runtime/Particle/CDecalDataFactory.hpp        |   6 +-
 Runtime/Particle/CDecalDescription.hpp        |  32 +++++
 .../Particle/CParticleSwooshDataFactory.cpp   |   6 +-
 4 files changed, 164 insertions(+), 4 deletions(-)

diff --git a/Runtime/Particle/CDecalDataFactory.cpp b/Runtime/Particle/CDecalDataFactory.cpp
index 8427e1e9b..b6264daae 100644
--- a/Runtime/Particle/CDecalDataFactory.cpp
+++ b/Runtime/Particle/CDecalDataFactory.cpp
@@ -1,14 +1,138 @@
 #include "CDecalDataFactory.hpp"
 #include "CDecalDescription.hpp"
+#include "CParticleDataFactory.hpp"
 #include "CSimplePool.hpp"
+#include "CRandom16.hpp"
 
 namespace pshag
 {
+static LogVisor::LogModule Log("pshag::CDecalDataFactory");
+
+using CPF = CParticleDataFactory;
 CDecalDescription* CDecalDataFactory::GetGeneratorDesc(CInputStream& in, CSimplePool* resPool)
 {
+    return CreateGeneratorDescription(in, resPool);
+}
+
+CDecalDescription* CDecalDataFactory::CreateGeneratorDescription(CInputStream& in, CSimplePool* resPool)
+{
+    FourCC clsId = CPF::GetClassID(in);
+    if (clsId == FOURCC('DPSM'))
+    {
+        CDecalDescription* desc = new CDecalDescription;
+        if (CreateDPSM(desc, in, resPool))
+            return desc;
+        else
+            delete desc;
+    }
     return nullptr;
 }
 
+
+bool CDecalDataFactory::CreateDPSM(CDecalDescription* desc, CInputStream& in, CSimplePool* resPool)
+{
+    CRandom16 rand{99};
+    CGlobalRandom gr{rand};
+    FourCC clsId = CPF::GetClassID(in);
+
+    while(clsId != SBIG('_END'))
+    {
+        bool loadFirstDesc = false;
+        switch(clsId)
+        {
+        case SBIG('1SZE'):
+        case SBIG('1LFT'):
+        case SBIG('1ROT'):
+        case SBIG('1OFF'):
+        case SBIG('1CLR'):
+        case SBIG('1TEX'):
+        case SBIG('1ADD'):
+            loadFirstDesc = true;
+        case SBIG('2LFT'):
+        case SBIG('2SZE'):
+        case SBIG('2ROT'):
+        case SBIG('2OFF'):
+        case SBIG('2CLR'):
+        case SBIG('2TEX'):
+        case SBIG('2ADD'):
+            if (loadFirstDesc)
+                GetQuadDecalInfo(in, resPool, clsId, desc->x0_Quad);
+            else
+                GetQuadDecalInfo(in, resPool, clsId, desc->x1c_Quad);
+        break;
+
+        case SBIG('DMDL'):
+            desc->x38_DMDL = CPF::GetModel(in, resPool);
+        break;
+        case SBIG('DFLT'):
+            desc->x48_DFLT.reset(CPF::GetIntElement(in));
+        break;
+        case SBIG('DMOP'):
+            desc->x4c_DMOP.reset(CPF::GetVectorElement(in));
+        break;
+        case SBIG('DMRT'):
+            desc->x50_DMRT.reset(CPF::GetVectorElement(in));
+        break;
+        case SBIG('DMSC'):
+            desc->x54_DMSC.reset(CPF::GetVectorElement(in));
+        break;
+        case SBIG('DMCL'):
+            desc->x58_DMCL.reset(CPF::GetColorElement(in));
+        break;
+        case SBIG('DMAB'):
+            desc->x5c_24_DMAB = CPF::GetBool(in);
+        break;
+        case SBIG('DMOO'):
+            desc->x5c_25_DMOO = CPF::GetBool(in);
+        break;
+        default:
+        {
+            uint32_t clsName = clsId.toUint32();
+            Log.report(LogVisor::FatalError, "Unknown DPSC class %.4s @%" PRIi64, &clsName, in.position());
+            return false;
+        }
+        }
+
+        clsId = CPF::GetClassID(in);
+    }
+    return true;
+}
+
+void CDecalDataFactory::GetQuadDecalInfo(CInputStream& in, CSimplePool* resPool, FourCC clsId, SQuadDescr& quad)
+{
+    switch(clsId)
+    {
+    case SBIG('1LFT'):
+    case SBIG('2LFT'):
+        quad.x0_LFT.reset(CPF::GetIntElement(in));
+    break;
+    case SBIG('1SZE'):
+    case SBIG('2SZE'):
+        quad.x4_SZE.reset(CPF::GetRealElement(in));
+    break;
+    case SBIG('1ROT'):
+    case SBIG('2ROT'):
+        quad.x8_ROT.reset(CPF::GetRealElement(in));
+    break;
+    case SBIG('1OFF'):
+    case SBIG('2OFF'):
+        quad.xc_OFF.reset(CPF::GetVectorElement(in));
+    break;
+    case SBIG('1CLR'):
+    case SBIG('2CLR'):
+        quad.x10_CLR.reset(CPF::GetColorElement(in));
+    break;
+    case SBIG('1TEX'):
+    case SBIG('2TEX'):
+        quad.x14_TEX.reset(CPF::GetTextureElement(in, resPool));
+    break;
+    case SBIG('1ADD'):
+    case SBIG('2ADD'):
+        quad.x18_ADD = CPF::GetBool(in);
+    break;
+    }
+}
+
 std::unique_ptr<IObj> FDecalDataFactory(const SObjectTag &tag, CInputStream &in, const CVParamTransfer &vparms)
 {
     CSimplePool* sp = static_cast<CSimplePool*>(static_cast<TObjOwnerParam<IObjectStore*>*>(vparms.GetObj())->GetParam());
diff --git a/Runtime/Particle/CDecalDataFactory.hpp b/Runtime/Particle/CDecalDataFactory.hpp
index 55bb7d22e..586399c23 100644
--- a/Runtime/Particle/CDecalDataFactory.hpp
+++ b/Runtime/Particle/CDecalDataFactory.hpp
@@ -9,15 +9,17 @@
 
 namespace pshag
 {
+struct SQuadDescr;
 class CDecalDescription;
 class CSimplePool;
 
 class CDecalDataFactory
 {
+    static bool CreateDPSM(CDecalDescription* desc,CInputStream& in,CSimplePool* resPool);
+    static CDecalDescription* CreateGeneratorDescription(CInputStream& in, CSimplePool* resPool);
+    static void GetQuadDecalInfo(CInputStream& in, CSimplePool* resPool, FourCC clsId, SQuadDescr& quad);
 public:
     static CDecalDescription* GetGeneratorDesc(CInputStream& in,CSimplePool* resPool);
-    static CDecalDescription* CreateGeneratorDescription(CInputStream& in, CSimplePool* resPool);
-    static bool CreateDPSM(CDecalDescription* desc,CInputStream& in,CSimplePool* resPool);
 };
 
 std::unique_ptr<IObj> FDecalDataFactory(const SObjectTag& tag, CInputStream& in, const CVParamTransfer& vparms);
diff --git a/Runtime/Particle/CDecalDescription.hpp b/Runtime/Particle/CDecalDescription.hpp
index 8c0fc81ca..75bb0aa83 100644
--- a/Runtime/Particle/CDecalDescription.hpp
+++ b/Runtime/Particle/CDecalDescription.hpp
@@ -1,10 +1,42 @@
 #ifndef __PSHAG_CDECALDESCRIPTION_HPP__
 #define __PSHAG_CDECALDESCRIPTION_HPP__
 
+#include "CRealElement.hpp"
+#include "CIntElement.hpp"
+#include "CVectorElement.hpp"
+#include "CColorElement.hpp"
+#include "CUVElement.hpp"
+#include "CParticleDataFactory.hpp"
+
 namespace pshag
 {
+struct SQuadDescr
+{
+    std::unique_ptr<CIntElement> x0_LFT;
+    std::unique_ptr<CRealElement> x4_SZE;
+    std::unique_ptr<CRealElement> x8_ROT;
+    std::unique_ptr<CVectorElement> xc_OFF;
+    std::unique_ptr<CColorElement> x10_CLR;
+    std::unique_ptr<CUVElement> x14_TEX;
+    bool x18_ADD = false;
+};
+
 class CDecalDescription
 {
+public:
+    SQuadDescr x0_Quad;
+    SQuadDescr x1c_Quad;
+    SParticleModel x38_DMDL;
+    std::unique_ptr<CIntElement> x48_DFLT;
+    std::unique_ptr<CVectorElement> x4c_DMOP;
+    std::unique_ptr<CVectorElement> x50_DMRT;
+    std::unique_ptr<CVectorElement> x54_DMSC;
+    std::unique_ptr<CColorElement>  x58_DMCL;
+    union
+    {
+        struct { bool x5c_24_DMAB : 1; bool x5c_25_DMOO : 1;};
+        u8 dummy = 0;
+    };
 };
 
 }
diff --git a/Runtime/Particle/CParticleSwooshDataFactory.cpp b/Runtime/Particle/CParticleSwooshDataFactory.cpp
index c8b3431f0..f4cc0759c 100644
--- a/Runtime/Particle/CParticleSwooshDataFactory.cpp
+++ b/Runtime/Particle/CParticleSwooshDataFactory.cpp
@@ -23,8 +23,10 @@ CSwooshDescription*CParticleSwooshDataFactory::CreateGeneratorDescription(CInput
     if (clsId == FOURCC('SWSH'))
     {
         CSwooshDescription* desc = new CSwooshDescription;
-        CreateWPSM(desc, in, resPool);
-        return desc;
+        if (CreateWPSM(desc, in, resPool))
+            return desc;
+        else
+            delete desc;
     }
     return nullptr;
 }

From 488de1bdb9848217c20f7f6445fcdac655821fbd Mon Sep 17 00:00:00 2001
From: Jack Andersen <jackoalan@gmail.com>
Date: Tue, 23 Feb 2016 17:20:07 -1000
Subject: [PATCH 20/22] GLSL macros

---
 Editor/ViewManager.cpp                        |  2 +-
 Runtime/Graphics/CLineRendererShadersGLSL.cpp |  9 +++++---
 Runtime/MP1/main.cpp                          |  4 ++--
 Runtime/Particle/CElementGenShadersGLSL.cpp   | 21 ++++++++++++-------
 hecl                                          |  2 +-
 libSpecter                                    |  2 +-
 6 files changed, 25 insertions(+), 15 deletions(-)

diff --git a/Editor/ViewManager.cpp b/Editor/ViewManager.cpp
index 2370db4fb..68d90fede 100644
--- a/Editor/ViewManager.cpp
+++ b/Editor/ViewManager.cpp
@@ -201,7 +201,7 @@ void ViewManager::pushRecentFile(const HECL::SystemString& path)
 
 void ViewManager::init(boo::IApplication* app)
 {
-    m_mainWindow = std::unique_ptr<boo::IWindow>(app->newWindow(_S("URDE")));
+    m_mainWindow = std::unique_ptr<boo::IWindow>(app->newWindow(_S("URDE"), 1));
     m_mainWindow->showWindow();
     m_mainWindow->setWaitCursor(true);
 
diff --git a/Runtime/Graphics/CLineRendererShadersGLSL.cpp b/Runtime/Graphics/CLineRendererShadersGLSL.cpp
index 28d1d05e2..57d3d7b28 100644
--- a/Runtime/Graphics/CLineRendererShadersGLSL.cpp
+++ b/Runtime/Graphics/CLineRendererShadersGLSL.cpp
@@ -6,11 +6,12 @@ namespace pshag
 
 static const char* VS_GLSL_TEX =
 "#version 330\n"
+BOO_GLSL_BINDING_HEAD
 "layout(location=0) in vec4 posIn;\n"
 "layout(location=1) in vec4 colorIn;\n"
 "layout(location=2) in vec4 uvIn;\n"
 "\n"
-"uniform LineUniform\n"
+"UBINDING0 uniform LineUniform\n"
 "{\n"
 "    vec4 moduColor;\n"
 "};\n"
@@ -31,6 +32,7 @@ static const char* VS_GLSL_TEX =
 
 static const char* FS_GLSL_TEX =
 "#version 330\n"
+BOO_GLSL_BINDING_HEAD
 "struct VertToFrag\n"
 "{\n"
 "    vec4 color;\n"
@@ -39,7 +41,7 @@ static const char* FS_GLSL_TEX =
 "\n"
 "in VertToFrag vtf;\n"
 "layout(location=0) out vec4 colorOut;\n"
-"uniform sampler2D texs[1];\n"
+"TBINDING0 uniform sampler2D texs[1];\n"
 "void main()\n"
 "{\n"
 "    colorOut = vtf.color * texture(texs[0], vtf.uv);\n"
@@ -47,10 +49,11 @@ static const char* FS_GLSL_TEX =
 
 static const char* VS_GLSL_NOTEX =
 "#version 330\n"
+BOO_GLSL_BINDING_HEAD
 "layout(location=0) in vec4 posIn;\n"
 "layout(location=1) in vec4 colorIn;\n"
 "\n"
-"uniform LineUniform\n"
+"UBINDING0 uniform LineUniform\n"
 "{\n"
 "    vec4 moduColor;\n"
 "};\n"
diff --git a/Runtime/MP1/main.cpp b/Runtime/MP1/main.cpp
index d78243268..9df03844a 100644
--- a/Runtime/MP1/main.cpp
+++ b/Runtime/MP1/main.cpp
@@ -224,7 +224,7 @@ void CMain::LoadAudio()
 int CMain::appMain(boo::IApplication* app)
 {
     Zeus::detectCPU();
-    mainWindow = app->newWindow(_S("Metroid Prime 1 Reimplementation vZygote"));
+    mainWindow = app->newWindow(_S("Metroid Prime 1 Reimplementation vZygote"), 1);
     mainWindow->showWindow();
     TOneStatic<CGameGlobalObjects> globalObjs;
     InitializeSubsystems();
@@ -238,7 +238,7 @@ int CMain::appMain(boo::IApplication* app)
 
     boo::IGraphicsCommandQueue* gfxQ = mainWindow->getCommandQueue();
     boo::SWindowRect windowRect = mainWindow->getWindowFrame();
-    boo::ITextureR* renderTex = mainWindow->getMainContextDataFactory()->newRenderTexture(windowRect.size[0], windowRect.size[1], 1);
+    boo::ITextureR* renderTex = mainWindow->getMainContextDataFactory()->newRenderTexture(windowRect.size[0], windowRect.size[1]);
     float rgba[4] = { 0.2f, 0.2f, 0.2f, 1.0f};
     gfxQ->setClearColor(rgba);
 
diff --git a/Runtime/Particle/CElementGenShadersGLSL.cpp b/Runtime/Particle/CElementGenShadersGLSL.cpp
index 73c392d93..dad9140b6 100644
--- a/Runtime/Particle/CElementGenShadersGLSL.cpp
+++ b/Runtime/Particle/CElementGenShadersGLSL.cpp
@@ -10,11 +10,12 @@ namespace pshag
 
 static const char* VS_GLSL_TEX =
 "#version 330\n"
+BOO_GLSL_BINDING_HEAD
 "layout(location=0) in vec4 posIn[4];\n"
 "layout(location=4) in vec4 colorIn;\n"
 "layout(location=5) in vec4 uvsIn[4];\n"
 "\n"
-"uniform ParticleUniform\n"
+"UBINDING0 uniform ParticleUniform\n"
 "{\n"
 "    mat4 mvp;\n"
 "    vec4 moduColor;\n"
@@ -36,6 +37,7 @@ static const char* VS_GLSL_TEX =
 
 static const char* FS_GLSL_TEX =
 "#version 330\n"
+BOO_GLSL_BINDING_HEAD
 "struct VertToFrag\n"
 "{\n"
 "    vec4 color;\n"
@@ -44,7 +46,7 @@ static const char* FS_GLSL_TEX =
 "\n"
 "in VertToFrag vtf;\n"
 "layout(location=0) out vec4 colorOut;\n"
-"uniform sampler2D texs[1];\n"
+"TBINDING0 uniform sampler2D texs[1];\n"
 "void main()\n"
 "{\n"
 "    colorOut = vtf.color * texture(texs[0], vtf.uv);\n"
@@ -52,6 +54,7 @@ static const char* FS_GLSL_TEX =
 
 static const char* FS_GLSL_TEX_REDTOALPHA =
 "#version 330\n"
+BOO_GLSL_BINDING_HEAD
 "struct VertToFrag\n"
 "{\n"
 "    vec4 color;\n"
@@ -60,7 +63,7 @@ static const char* FS_GLSL_TEX_REDTOALPHA =
 "\n"
 "in VertToFrag vtf;\n"
 "layout(location=0) out vec4 colorOut;\n"
-"uniform sampler2D texs[1];\n"
+"TBINDING0 uniform sampler2D texs[1];\n"
 "void main()\n"
 "{\n"
 "    colorOut = vtf.color * texture(texs[0], vtf.uv);\n"
@@ -69,12 +72,13 @@ static const char* FS_GLSL_TEX_REDTOALPHA =
 
 static const char* VS_GLSL_INDTEX =
 "#version 330\n"
+BOO_GLSL_BINDING_HEAD
 "layout(location=0) in vec4 posIn[4];\n"
 "layout(location=4) in vec4 colorIn;\n"
 "layout(location=5) in vec4 uvsInTexrTind[4];\n"
 "layout(location=9) in vec2 uvsInScene[4];\n"
 "\n"
-"uniform ParticleUniform\n"
+"UBINDING0 uniform ParticleUniform\n"
 "{\n"
 "    mat4 mvp;\n"
 "    vec4 moduColor;\n"
@@ -100,6 +104,7 @@ static const char* VS_GLSL_INDTEX =
 
 static const char* FS_GLSL_INDTEX =
 "#version 330\n"
+BOO_GLSL_BINDING_HEAD
 "struct VertToFrag\n"
 "{\n"
 "    vec4 color;\n"
@@ -110,7 +115,7 @@ static const char* FS_GLSL_INDTEX =
 "\n"
 "in VertToFrag vtf;\n"
 "layout(location=0) out vec4 colorOut;\n"
-"uniform sampler2D texs[3];\n"
+"TBINDING0 uniform sampler2D texs[3];\n"
 "void main()\n"
 "{\n"
 "    vec2 tindTexel = texture(texs[2], vtf.uvTind).ba;\n"
@@ -122,6 +127,7 @@ static const char* FS_GLSL_INDTEX =
 
 static const char* FS_GLSL_CINDTEX =
 "#version 330\n"
+BOO_GLSL_BINDING_HEAD
 "struct VertToFrag\n"
 "{\n"
 "    vec4 color;\n"
@@ -132,7 +138,7 @@ static const char* FS_GLSL_CINDTEX =
 "\n"
 "in VertToFrag vtf;\n"
 "layout(location=0) out vec4 colorOut;\n"
-"uniform sampler2D texs[3];\n"
+"TBINDING0 uniform sampler2D texs[3];\n"
 "void main()\n"
 "{\n"
 "    vec2 tindTexel = texture(texs[2], vtf.uvTind).ba;\n"
@@ -142,10 +148,11 @@ static const char* FS_GLSL_CINDTEX =
 
 static const char* VS_GLSL_NOTEX =
 "#version 330\n"
+BOO_GLSL_BINDING_HEAD
 "layout(location=0) in vec4 posIn[4];\n"
 "layout(location=4) in vec4 colorIn;\n"
 "\n"
-"uniform ParticleUniform\n"
+"UBINDING0 uniform ParticleUniform\n"
 "{\n"
 "    mat4 mvp;\n"
 "    vec4 moduColor;\n"
diff --git a/hecl b/hecl
index 2ff161839..5fa984eba 160000
--- a/hecl
+++ b/hecl
@@ -1 +1 @@
-Subproject commit 2ff161839491dd42362a680221f5ef4bc95f32cc
+Subproject commit 5fa984eba8c87a974fba3c5f621747f2cd6982fc
diff --git a/libSpecter b/libSpecter
index c83c1f0b9..019cb96a2 160000
--- a/libSpecter
+++ b/libSpecter
@@ -1 +1 @@
-Subproject commit c83c1f0b939115497f4a15cfbc2669445e07bdb7
+Subproject commit 019cb96a24828ddd2304c3a05ab6cd124a94c4b7

From e9996034c957ca320fbe343ad08231f6df49aa7f Mon Sep 17 00:00:00 2001
From: Phillip Stephens <antidote.crk@gmail.com>
Date: Tue, 23 Feb 2016 20:52:45 -0800
Subject: [PATCH 21/22] Update Specter

---
 libSpecter | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/libSpecter b/libSpecter
index 019cb96a2..0deeec94c 160000
--- a/libSpecter
+++ b/libSpecter
@@ -1 +1 @@
-Subproject commit 019cb96a24828ddd2304c3a05ab6cd124a94c4b7
+Subproject commit 0deeec94cc838c5e3a4f094fee0ca9fd1d524de3

From eb3679dd889c1333fa95c92a075845ad322c77fe Mon Sep 17 00:00:00 2001
From: Jack Andersen <jackoalan@gmail.com>
Date: Wed, 24 Feb 2016 10:53:26 -1000
Subject: [PATCH 22/22] Windows fixes

---
 DataSpec/DNACommon/NamedResourceCatalog.hpp |  2 +-
 Editor/ProjectResourceFactory.cpp           |  4 ++--
 Editor/ProjectResourceFactory.hpp           |  4 ++++
 Runtime/Particle/CDecalDataFactory.cpp      | 10 +++++++---
 hecl                                        |  2 +-
 libSpecter                                  |  2 +-
 6 files changed, 16 insertions(+), 8 deletions(-)

diff --git a/DataSpec/DNACommon/NamedResourceCatalog.hpp b/DataSpec/DNACommon/NamedResourceCatalog.hpp
index 3d848ede7..4ce7cda8a 100644
--- a/DataSpec/DNACommon/NamedResourceCatalog.hpp
+++ b/DataSpec/DNACommon/NamedResourceCatalog.hpp
@@ -8,7 +8,7 @@ template <class IDType>
 struct NamedResourceCatalog : BigYAML
 {
     Delete _d;
-    Value<atUint32> namedResCount;
+    Value<atUint32> namedResCount = 0;
     struct NamedResource : BigYAML
     {
         Delete _d;
diff --git a/Editor/ProjectResourceFactory.cpp b/Editor/ProjectResourceFactory.cpp
index 6c540b3ce..eb70c4513 100644
--- a/Editor/ProjectResourceFactory.cpp
+++ b/Editor/ProjectResourceFactory.cpp
@@ -21,9 +21,9 @@ void ProjectResourceFactory::BuildObjectMap(const HECL::Database::Project::Proje
 {
     m_resPaths.clear();
     m_namedResources.clear();
-    HECL::SystemString catalogPath = HECL::ProjectPath(spec.cookedPath, std::string(spec.spec.m_name) + "/catalog.yaml").getAbsolutePath();
+    HECL::SystemString catalogPath = HECL::ProjectPath(spec.cookedPath, HECL::SystemString(spec.spec.m_name) + _S("/catalog.yaml")).getAbsolutePath();
     FILE* catalogFile = HECL::Fopen(catalogPath.c_str(), _S("r"));
-    if (!HECL::StrCmp(spec.spec.m_name, "MP3"))
+    if (!HECL::StrCmp(spec.spec.m_name, _S("MP3")))
     {
         DataSpec::NamedResourceCatalog<DataSpec::UniqueID64> catalog;
         if (catalogFile)
diff --git a/Editor/ProjectResourceFactory.hpp b/Editor/ProjectResourceFactory.hpp
index 7d40fe2c4..22cfa974a 100644
--- a/Editor/ProjectResourceFactory.hpp
+++ b/Editor/ProjectResourceFactory.hpp
@@ -25,7 +25,11 @@ class ProjectResourceFactory : public pshag::IFactory
             if (ent.m_name.size() == idLen && ent.m_name[4] == _S('_'))
             {
                 HECL::SystemUTF8View entu8(ent.m_name);
+#if _WIN32
+                u64 id = _strtoui64(entu8.c_str() + 5, nullptr, 16);
+#else
                 u64 id = strtouq(entu8.c_str() + 5, nullptr, 16);
+#endif
 
                 if (id)
                 {
diff --git a/Runtime/Particle/CDecalDataFactory.cpp b/Runtime/Particle/CDecalDataFactory.cpp
index b6264daae..a35fdd1ce 100644
--- a/Runtime/Particle/CDecalDataFactory.cpp
+++ b/Runtime/Particle/CDecalDataFactory.cpp
@@ -1,6 +1,10 @@
 #include "CDecalDataFactory.hpp"
 #include "CDecalDescription.hpp"
+#include "CGenDescription.hpp"
+#include "CSwooshDescription.hpp"
+#include "CElectricDescription.hpp"
 #include "CParticleDataFactory.hpp"
+#include "CModel.hpp"
 #include "CSimplePool.hpp"
 #include "CRandom16.hpp"
 
@@ -35,10 +39,10 @@ bool CDecalDataFactory::CreateDPSM(CDecalDescription* desc, CInputStream& in, CS
     CGlobalRandom gr{rand};
     FourCC clsId = CPF::GetClassID(in);
 
-    while(clsId != SBIG('_END'))
+    while (clsId != SBIG('_END'))
     {
         bool loadFirstDesc = false;
-        switch(clsId)
+        switch (clsId)
         {
         case SBIG('1SZE'):
         case SBIG('1LFT'):
@@ -100,7 +104,7 @@ bool CDecalDataFactory::CreateDPSM(CDecalDescription* desc, CInputStream& in, CS
 
 void CDecalDataFactory::GetQuadDecalInfo(CInputStream& in, CSimplePool* resPool, FourCC clsId, SQuadDescr& quad)
 {
-    switch(clsId)
+    switch (clsId)
     {
     case SBIG('1LFT'):
     case SBIG('2LFT'):
diff --git a/hecl b/hecl
index 5fa984eba..47e723844 160000
--- a/hecl
+++ b/hecl
@@ -1 +1 @@
-Subproject commit 5fa984eba8c87a974fba3c5f621747f2cd6982fc
+Subproject commit 47e72384415a5062cc0358512a272fc939aa1514
diff --git a/libSpecter b/libSpecter
index 0deeec94c..bb78a2055 160000
--- a/libSpecter
+++ b/libSpecter
@@ -1 +1 @@
-Subproject commit 0deeec94cc838c5e3a4f094fee0ca9fd1d524de3
+Subproject commit bb78a20553ea665c0ec301404dce0c6753b8eb09