diff --git a/Source/Render/DX9/TextureDX9.cpp b/Source/Render/DX9/TextureDX9.cpp index a92cc39..df847ac 100644 --- a/Source/Render/DX9/TextureDX9.cpp +++ b/Source/Render/DX9/TextureDX9.cpp @@ -8,15 +8,25 @@ #include namespace { + // OFFSET: 0x00573170 + std::uint16_t Color4444(std::uint32_t color) { + return ((color >> 16) & 0xF000) | ((color >> 12) & 0xF00) | ((color >> 8) & 0xF0) | ((color >> 4) & 0xF); + } + + // OFFSET: 0x005731B0 + std::uint16_t Color565(std::uint32_t color) { + return ((color >> 8) & 0xF800) | ((color >> 5) & 0x7E0) | ((color >> 3) & 0x1F); + } + // INLINED std::uint16_t Convert16(std::uint32_t color, D3DFORMAT format) { switch (format) { case D3DFMT_R5G6B5: - return ((color & 255) >> 3) | ((color >> 5) & 0x7E0) | ((color >> 8) & 0xF800); + return Color565(color); case D3DFMT_A1R5G5B5: return ((color >> 16) & 0x8000) | ((color & 255) >> 3) | ((color >> 6) & 0x3E0) | ((color >> 9) & 0x7C00); case D3DFMT_A4R4G4B4: - return ((color & 255) >> 4) | ((color >> 8) & 0xF0) | ((color >> 12) & 0xF00) | ((color >> 16) & 0xF000); + return Color4444(color); default: return 0; } diff --git a/Source/Render/Primitives/RenderVertexPool.cpp b/Source/Render/Primitives/RenderVertexPool.cpp index 5b8f293..86499e8 100644 --- a/Source/Render/Primitives/RenderVertexPool.cpp +++ b/Source/Render/Primitives/RenderVertexPool.cpp @@ -64,6 +64,22 @@ RenderVertex* RenderVertexPool::Acquire(unsigned count) { return block.data(); } +// OFFSET: 0x00AB77A0 +RenderVertex* RenderVertexPool::Block::Append(unsigned count) { + const unsigned first = static_cast(this->size()); + if (first + count > this->capacity()) { + return nullptr; + } + + this->resize(first + count); + + for (unsigned index = first; index < this->size(); ++index) { + (*this)[index].specular = 0xFF000000u; + } + + return this->data() + (this->size() - count); +} + // INLINED void RenderVertexPool::Rewind() { for (auto& block : this->m_active) { diff --git a/Source/Render/Primitives/RenderVertexPool.h b/Source/Render/Primitives/RenderVertexPool.h index 490af0d..4064d81 100644 --- a/Source/Render/Primitives/RenderVertexPool.h +++ b/Source/Render/Primitives/RenderVertexPool.h @@ -14,7 +14,10 @@ public: void Rewind(); private: - using Block = std::vector; + struct Block : std::vector { + RenderVertex* Append(unsigned count); + }; + /* 00B0 */ unsigned m_minimum; /* 00B4 */ unsigned m_used; /* 00B8 */ std::forward_list> m_active; diff --git a/Source/Render/Primitives/UIRPData.h b/Source/Render/Primitives/UIRPData.h index fbe3ea2..e4c60d6 100644 --- a/Source/Render/Primitives/UIRPData.h +++ b/Source/Render/Primitives/UIRPData.h @@ -4,15 +4,20 @@ #include "Render/Primitives/RenderPrimitive.h" #include +#include class CTexture; class RenderPrimitivePool; +class TextureCache; class UIRPData { public: UIRPData(); virtual ~UIRPData(); void Draw(RenderPrimitivePool& pool, int x, int y, CTexture* texture, std::uint32_t color, int width, int height, bool stretched); + void DrawStretched(RenderPrimitivePool& pool, int x, int y, CTexture* texture, std::uint32_t color, int width, int height); + void DrawNamed(RenderPrimitivePool& pool, TextureCache& textures, int x, int y, std::string name, std::uint32_t color, int width, int height); + void SetSolid(RenderPrimitivePool& pool, int width, int height, std::uint32_t color); protected: /* 0004 */ std::list m_primitives; diff --git a/Source/Render/RendererDX7.cpp b/Source/Render/RendererDX7.cpp new file mode 100644 index 0000000..06be680 --- /dev/null +++ b/Source/Render/RendererDX7.cpp @@ -0,0 +1,16 @@ +#include "Render/RendererDX7.h" + +// OFFSET: 0x0055EC00 +void CRendererDX7::SetClearColor(unsigned color) { + this->clearColor = color; +} + +// OFFSET: 0x0055ED40 +// FUNCTION: fn_02115 +void CRendererDX7::SetCamera(const float* eye, const float* target, const float* up) { +} + +// OFFSET: 0x0055F690 +void CRendererDX7::SetTextureFormat(unsigned format) { + this->unknown_024C = format; +} diff --git a/Source/Render/RendererDX7.h b/Source/Render/RendererDX7.h new file mode 100644 index 0000000..6a6f23d --- /dev/null +++ b/Source/Render/RendererDX7.h @@ -0,0 +1,23 @@ +#ifndef RAGNAROK_SOURCE_RENDER_RENDERERDX7_H +#define RAGNAROK_SOURCE_RENDER_RENDERERDX7_H + +#include "Render/Renderer.h" + +class CRendererDX7 : public CRenderer { +public: + /* 025C */ unsigned char unknown_025C[0x14]; + /* 0270 */ unsigned clearColor; + /* 0274 */ unsigned char unknown_0274[0x10]; + + void SetCamera(const float* eye, const float* target, const float* up) override; + void SetClearColor(unsigned color) override; + + void SetTextureFormat(unsigned format); +}; + +#if defined(_WIN32) && !defined(_WIN64) +static_assert(sizeof(CRendererDX7) == 0x284); +static_assert(offsetof(CRendererDX7, clearColor) == 0x0270); +#endif + +#endif diff --git a/Source/Render/ScreenGeometry.cpp b/Source/Render/ScreenGeometry.cpp new file mode 100644 index 0000000..fec6fdb --- /dev/null +++ b/Source/Render/ScreenGeometry.cpp @@ -0,0 +1,74 @@ +#include "Render/ScreenGeometry.h" +#include "Render/Primitives/RenderPrimitivePool.h" +#include "Render/Primitives/RenderQueues.h" +#include "Utility/Math/AffineMatrix.h" + +#include + +// OFFSET: 0x0054E2B0 +void DrawScreenLine( + RenderPrimitivePool& primitives, RenderQueues& queues, float startX, float startY, float endX, float endY, int thickness, CTexture* texture, + std::uint32_t color, bool depthAlpha, float depthStart, float depthEnd +) { + if (SquareRoot((endY - startY) * (endY - startY) + (endX - startX) * (endX - startX)) == 0.0f) { + return; + } + + const float deltaX = endX - startX; + const float deltaY = endY - startY; + const float inverseLength = 1.0f / SquareRoot(deltaY * deltaY + deltaX * deltaX); + float angle = static_cast(std::acos(static_cast(inverseLength * deltaX))); + if (inverseLength * deltaY < 0.0f) { + angle = 6.283184f - angle; + } + + angle += 1.570796f; + const float width = static_cast(thickness); + const float offsetY = std::sin(angle) * width; + const float offsetX = std::cos(angle) * width; + DrawScreenQuad( + primitives, queues, startX - offsetX, startY - offsetY, startX + offsetX, startY + offsetY, endX - offsetX, endY - offsetY, endX + offsetX, + endY + offsetY, texture, color, depthAlpha, depthStart, depthEnd + ); +} + +// OFFSET: 0x0054DB40 +void DrawScreenQuad( + RenderPrimitivePool& primitives, RenderQueues& queues, float x0, float y0, float x1, float y1, float x2, float y2, float x3, float y3, CTexture* texture, + std::uint32_t color, bool depthAlpha, float depthStart, float depthEnd +) { + RenderPrimitive* primitive = primitives.Acquire(); + RenderVertex* vertices = primitive->vertices; + vertices[0].x = x0; + vertices[0].y = y0; + vertices[0].z = 0.8f; + vertices[0].rhw = 1.0f; + vertices[0].diffuse = color; + vertices[0].u = 0.0f; + vertices[0].v = 0.0f; + vertices[1].x = x1; + vertices[1].y = y1; + vertices[1].z = 0.8f; + vertices[1].rhw = 1.0f; + vertices[1].diffuse = color; + vertices[1].u = 1.0f; + vertices[1].v = 0.0f; + vertices[2].x = x2; + vertices[2].y = y2; + vertices[2].z = 0.8f; + vertices[2].rhw = 1.0f; + vertices[2].diffuse = color; + vertices[2].u = 0.0f; + vertices[2].v = 1.0f; + vertices[3].x = x3; + vertices[3].y = y3; + vertices[3].z = 0.8f; + vertices[3].rhw = 1.0f; + vertices[3].diffuse = color; + vertices[3].u = 1.0f; + vertices[3].v = 1.0f; + primitive->texture = texture; + primitive->unknown_0018 = 2; + primitive->unknown_001C = 4; + queues.Submit(primitive, 513, depthAlpha, depthStart, depthEnd); +} diff --git a/Source/Render/ScreenGeometry.h b/Source/Render/ScreenGeometry.h new file mode 100644 index 0000000..b359b75 --- /dev/null +++ b/Source/Render/ScreenGeometry.h @@ -0,0 +1,19 @@ +#ifndef RAGNAROK_SOURCE_RENDER_SCREENGEOMETRY_H +#define RAGNAROK_SOURCE_RENDER_SCREENGEOMETRY_H + +#include + +class CTexture; +class RenderPrimitivePool; +struct RenderQueues; + +void DrawScreenQuad( + RenderPrimitivePool& primitives, RenderQueues& queues, float x0, float y0, float x1, float y1, float x2, float y2, float x3, float y3, CTexture* texture, + std::uint32_t color, bool depthAlpha, float depthStart, float depthEnd +); +void DrawScreenLine( + RenderPrimitivePool& primitives, RenderQueues& queues, float startX, float startY, float endX, float endY, int thickness, CTexture* texture, + std::uint32_t color, bool depthAlpha, float depthStart, float depthEnd +); + +#endif diff --git a/Source/Render/ScreenRectangle.cpp b/Source/Render/ScreenRectangle.cpp new file mode 100644 index 0000000..6b64cc7 --- /dev/null +++ b/Source/Render/ScreenRectangle.cpp @@ -0,0 +1,114 @@ +#include "Render/ScreenRectangle.h" +#include "Render/Primitives/RenderPrimitivePool.h" +#include "Render/Primitives/RenderQueues.h" +#include "Render/Textures/Texture.h" +#include "Render/Textures/TextureCache.h" + +// OFFSET: 0x0054E590 +void DrawBlendedRectangle( + RenderPrimitivePool& primitives, TextureCache& textures, RenderQueues& queues, int x, int y, int width, int height, std::uint32_t color, bool depthAlpha, + float depthStart, float depthEnd +) { + if ((color & 0xFF000000u) == 0) { + return; + } + + RenderPrimitive* primitive = primitives.Acquire(); + primitive->texture = textures.Default(); + const float left = static_cast(x); + const float top = static_cast(y); + const float right = static_cast(x + width); + const float bottom = static_cast(y + height); + primitive->quad[0].x = left; + primitive->quad[0].y = top; + primitive->quad[1].x = right; + primitive->quad[1].y = top; + primitive->quad[2].x = left; + primitive->quad[2].y = bottom; + primitive->quad[3].x = right; + primitive->quad[3].y = bottom; + for (RenderVertex& vertex : primitive->quad) { + vertex.z = 0.000001f; + vertex.rhw = 0.000001f; + vertex.diffuse = color; + vertex.u = 0.0f; + vertex.v = 0.0f; + } + primitive->unknown_0018 = 5; + primitive->unknown_001C = 6; + queues.Submit(primitive, 517, depthAlpha, depthStart, depthEnd); +} + +// OFFSET: 0x0054ED40 +void DrawTexturedRectangle( + RenderPrimitivePool& primitives, TextureCache& textures, RenderQueues& queues, int x, int y, int width, int height, std::uint32_t color, CTexture* texture, + bool depthAlpha, float depthStart, float depthEnd +) { + if ((color & 0xFF000000u) == 0) { + return; + } + + RenderPrimitive* primitive = primitives.Acquire(); + primitive->texture = texture ? texture : textures.Default(); + const float left = static_cast(x); + const float top = static_cast(y); + const float right = static_cast(x + width); + const float bottom = static_cast(y + height); + primitive->quad[0].x = left; + primitive->quad[0].y = top; + primitive->quad[0].u = 0.0f; + primitive->quad[0].v = 0.0f; + primitive->quad[1].x = right; + primitive->quad[1].y = top; + primitive->quad[1].u = 1.0f; + primitive->quad[1].v = 0.0f; + primitive->quad[2].x = left; + primitive->quad[2].y = bottom; + primitive->quad[2].u = 0.0f; + primitive->quad[2].v = 1.0f; + primitive->quad[3].x = right; + primitive->quad[3].y = bottom; + primitive->quad[3].u = 1.0f; + primitive->quad[3].v = 1.0f; + for (RenderVertex& vertex : primitive->quad) { + vertex.z = 0.000001f; + vertex.rhw = 0.999999f; + vertex.diffuse = color; + } + queues.Submit(primitive, 513, depthAlpha, depthStart, depthEnd); +} + +// OFFSET: 0x0054EFD0 +void DrawTextureRegion( + RenderPrimitivePool& primitives, TextureCache& textures, RenderQueues& queues, float x, float y, float width, float height, std::uint32_t color, + CTexture* texture, bool depthAlpha, float depthStart, float depthEnd +) { + if ((color & 0xFF000000u) == 0) { + return; + } + + RenderPrimitive* primitive = primitives.Acquire(); + primitive->texture = texture ? texture : textures.Default(); + primitive->quad[0].x = x; + primitive->quad[0].y = y; + primitive->quad[0].u = g_textureOffsetX / static_cast(texture->TextureWidth()); + primitive->quad[0].v = g_textureOffsetY / static_cast(texture->TextureHeight()); + primitive->quad[1].x = x + width; + primitive->quad[1].y = y; + primitive->quad[1].u = (static_cast(texture->Width()) + g_textureOffsetX) / static_cast(texture->TextureWidth()); + primitive->quad[1].v = g_textureOffsetY / static_cast(texture->TextureHeight()); + primitive->quad[2].x = x; + primitive->quad[2].y = y + height; + primitive->quad[2].u = g_textureOffsetX / static_cast(texture->TextureWidth()); + primitive->quad[2].v = (static_cast(texture->Height()) + g_textureOffsetY) / static_cast(texture->TextureHeight()); + primitive->quad[3].x = x + width; + primitive->quad[3].y = y + height; + primitive->quad[3].u = (static_cast(texture->Width()) + g_textureOffsetX) / static_cast(texture->TextureWidth()); + primitive->quad[3].v = (static_cast(texture->Height()) + g_textureOffsetY) / static_cast(texture->TextureHeight()); + for (RenderVertex& vertex : primitive->quad) { + vertex.z = 0.000001f; + vertex.rhw = 0.999999f; + vertex.diffuse = color; + } + queues.Submit(primitive, 513, depthAlpha, depthStart, depthEnd); +} diff --git a/Source/Render/ScreenRectangle.h b/Source/Render/ScreenRectangle.h new file mode 100644 index 0000000..22ce45d --- /dev/null +++ b/Source/Render/ScreenRectangle.h @@ -0,0 +1,24 @@ +#ifndef RAGNAROK_SOURCE_RENDER_SCREENRECTANGLE_H +#define RAGNAROK_SOURCE_RENDER_SCREENRECTANGLE_H + +#include + +class CTexture; +class RenderPrimitivePool; +class TextureCache; +struct RenderQueues; + +void DrawBlendedRectangle( + RenderPrimitivePool& primitives, TextureCache& textures, RenderQueues& queues, int x, int y, int width, int height, std::uint32_t color, bool depthAlpha, + float depthStart, float depthEnd +); +void DrawTexturedRectangle( + RenderPrimitivePool& primitives, TextureCache& textures, RenderQueues& queues, int x, int y, int width, int height, std::uint32_t color, CTexture* texture, + bool depthAlpha, float depthStart, float depthEnd +); +void DrawTextureRegion( + RenderPrimitivePool& primitives, TextureCache& textures, RenderQueues& queues, float x, float y, float width, float height, std::uint32_t color, + CTexture* texture, bool depthAlpha, float depthStart, float depthEnd +); + +#endif diff --git a/Source/Render/TextureQuad.cpp b/Source/Render/TextureQuad.cpp new file mode 100644 index 0000000..1f7a623 --- /dev/null +++ b/Source/Render/TextureQuad.cpp @@ -0,0 +1,6 @@ +#include "Render/TextureQuad.h" + +// OFFSET: 0x0055D310 +float RhwToDepth(float rhw) { + return ((1.0f / rhw - 10.0f) * 1.0067114f) * rhw; +} diff --git a/Source/Render/TextureQuad.h b/Source/Render/TextureQuad.h new file mode 100644 index 0000000..735915e --- /dev/null +++ b/Source/Render/TextureQuad.h @@ -0,0 +1,6 @@ +#ifndef RAGNAROK_SOURCE_RENDER_TEXTUREQUAD_H +#define RAGNAROK_SOURCE_RENDER_TEXTUREQUAD_H + +float RhwToDepth(float rhw); + +#endif diff --git a/Source/Render/UIRPDataDrawing.cpp b/Source/Render/UIRPDataDrawing.cpp new file mode 100644 index 0000000..efdaf49 --- /dev/null +++ b/Source/Render/UIRPDataDrawing.cpp @@ -0,0 +1,120 @@ +#include "Render/Primitives/RenderPrimitivePool.h" +#include "Render/Primitives/UIRPData.h" +#include "Render/Textures/Texture.h" +#include "Render/Textures/TextureCache.h" + +// OFFSET: 0x008130A0 +void UIRPData::DrawStretched(RenderPrimitivePool& pool, int x, int y, CTexture* texture, std::uint32_t color, int width, int height) { + if (!texture) { + return; + } + + RenderPrimitive* primitive = pool.Acquire(); + primitive->texture = texture; + const int right = x + width; + const int bottom = y + height; + primitive->quad[0].x = static_cast(x); + primitive->quad[0].y = static_cast(y); + primitive->quad[0].u = g_textureOffsetX / static_cast(texture->TextureWidth()); + primitive->quad[0].v = g_textureOffsetY / static_cast(texture->TextureHeight()); + primitive->quad[1].x = static_cast(right); + primitive->quad[1].y = static_cast(y); + primitive->quad[1].u = (static_cast(texture->Width()) + g_textureOffsetX) / static_cast(texture->TextureWidth()); + primitive->quad[1].v = g_textureOffsetY / static_cast(texture->TextureHeight()); + primitive->quad[2].x = static_cast(x); + primitive->quad[2].y = static_cast(bottom); + primitive->quad[2].u = g_textureOffsetX / static_cast(texture->TextureWidth()); + primitive->quad[2].v = (static_cast(texture->Height()) + g_textureOffsetX) / static_cast(texture->TextureHeight()); + primitive->quad[3].x = static_cast(right); + primitive->quad[3].y = static_cast(bottom); + primitive->quad[3].u = (static_cast(texture->Width()) + g_textureOffsetX) / static_cast(texture->TextureWidth()); + primitive->quad[3].v = (static_cast(texture->Height()) + g_textureOffsetX) / static_cast(texture->TextureHeight()); + for (RenderVertex& vertex : primitive->quad) { + vertex.diffuse = color; + } + + for (RenderVertex& vertex : primitive->quad) { + vertex.z = 0.000001f; + vertex.rhw = 0.999999f; + } + + this->m_primitives.push_back(primitive); +} + +// OFFSET: 0x008134B0 +void UIRPData::DrawNamed(RenderPrimitivePool& pool, TextureCache& textures, int x, int y, std::string name, std::uint32_t color, int width, int height) { + CTexture* texture = textures.Load(name.c_str(), 0, true, true, false); + if (!texture) { + return; + } + + RenderPrimitive* primitive = pool.Acquire(); + primitive->texture = texture; + const int imageWidth = texture->Width(); + const int imageHeight = texture->Height(); + if (!width) { + width = texture->Width(); + } + + if (!height) { + height = texture->Height(); + } + + const float textureWidth = static_cast(texture->TextureWidth()); + const float textureHeight = static_cast(texture->TextureHeight()); + const int right = x + width; + const float bottom = static_cast(y + height); + primitive->quad[0].x = static_cast(x); + primitive->quad[0].y = static_cast(y); + primitive->quad[0].u = g_textureOffsetX / textureWidth; + primitive->quad[0].v = g_textureOffsetY / textureHeight; + primitive->quad[1].x = static_cast(right); + primitive->quad[1].y = static_cast(y); + primitive->quad[1].u = (static_cast(width <= imageWidth ? width : imageWidth) + g_textureOffsetX) / textureWidth; + primitive->quad[1].v = g_textureOffsetY / textureHeight; + primitive->quad[2].x = static_cast(x); + primitive->quad[2].y = bottom; + primitive->quad[2].u = g_textureOffsetX / textureWidth; + primitive->quad[2].v = + (height <= imageHeight ? static_cast(height) + g_textureOffsetX : static_cast(imageHeight) + g_textureOffsetY) / textureHeight; + primitive->quad[3].x = static_cast(right); + primitive->quad[3].y = bottom; + primitive->quad[3].u = (static_cast(width <= imageWidth ? width : imageWidth) + g_textureOffsetX) / textureWidth; + primitive->quad[3].v = + (height <= imageHeight ? static_cast(height) + g_textureOffsetX : static_cast(imageHeight) + g_textureOffsetY) / textureHeight; + for (RenderVertex& vertex : primitive->quad) { + vertex.diffuse = color; + } + + for (RenderVertex& vertex : primitive->quad) { + vertex.z = 0.000001f; + vertex.rhw = 0.999999f; + } + + this->m_primitives.push_back(primitive); +} + +// OFFSET: 0x00813A00 +void UIRPData::SetSolid(RenderPrimitivePool& pool, int width, int height, std::uint32_t color) { + this->m_primitives.clear(); + + RenderPrimitive* primitive = pool.Acquire(); + primitive->texture = nullptr; + primitive->quad[0].x = 0.0f; + primitive->quad[0].y = 0.0f; + primitive->quad[1].x = static_cast(width); + primitive->quad[1].y = 0.0f; + primitive->quad[2].x = 0.0f; + primitive->quad[2].y = static_cast(height); + primitive->quad[3].x = static_cast(width); + primitive->quad[3].y = static_cast(height); + for (RenderVertex& vertex : primitive->quad) { + vertex.u = 0.0f; + vertex.v = 0.0f; + vertex.z = 0.000001f; + vertex.rhw = 0.999999f; + vertex.diffuse = color; + } + + this->m_primitives.push_back(primitive); +} diff --git a/data/compile.json b/data/compile.json index 968e47f..3010ed3 100644 --- a/data/compile.json +++ b/data/compile.json @@ -500,14 +500,19 @@ "Source/Render/RenderAdapter.cpp": 0, "Source/Render/RenderBackends.cpp": 0, "Source/Render/Renderer.cpp": 0, + "Source/Render/RendererDX7.cpp": 0, + "Source/Render/ScreenGeometry.cpp": 0, + "Source/Render/ScreenRectangle.cpp": 0, "Source/Render/Text/FontCache.cpp": 0, "Source/Render/Text/TextContext.cpp": 0, + "Source/Render/TextureQuad.cpp": 0, "Source/Render/Textures/BitmapPixels.cpp": 0, "Source/Render/Textures/BitmapTextureCache.cpp": 0, "Source/Render/Textures/SpriteAtlas.cpp": 0, "Source/Render/Textures/Surface.cpp": 0, "Source/Render/Textures/Texture.cpp": 0, "Source/Render/Textures/TextureCache.cpp": 3, + "Source/Render/UIRPDataDrawing.cpp": 0, "Source/Render/ViewportProjection.cpp": 0, "Source/Resource/Audio/WaveResource.cpp": 3, "Source/Resource/Bitmap/BitmapImage.cpp": 3,