Browse Source

🚚 Move CL2 rendering to engine/render/cl2_render.cpp

pull/1888/head
Gleb Mazovetskiy 5 years ago committed by Anders Jenbo
parent
commit
9a9941efdd
  1. 1
      CMakeLists.txt
  2. 317
      Source/engine.cpp
  3. 43
      Source/engine.h
  4. 321
      Source/engine/render/cl2_render.cpp
  5. 65
      Source/engine/render/cl2_render.hpp
  6. 8
      Source/monster.cpp
  7. 1
      Source/scrollrt.cpp

1
CMakeLists.txt

@ -352,6 +352,7 @@ set(devilutionx_SRCS
Source/engine/animationinfo.cpp
Source/engine/render/automap_render.cpp
Source/engine/render/cel_render.cpp
Source/engine/render/cl2_render.cpp
Source/engine/render/dun_render.cpp
Source/qol/autopickup.cpp
Source/qol/common.cpp

317
Source/engine.cpp

@ -36,10 +36,6 @@ const uint32_t RndInc = 1;
*/
const uint32_t RndMult = 0x015A4E35;
namespace {
constexpr std::uint8_t MaxCl2Width = 65;
} // namespace
CelSprite LoadCel(const char *pszName, int width)
{
return CelSprite(LoadFileInMem(pszName), width);
@ -251,319 +247,6 @@ void LoadFileData(const char *pszName, byte *buffer, size_t fileLen)
SFileCloseFile(file);
}
/**
* @brief Apply the color swaps to a CL2 sprite
* @param p CL2 buffer
* @param ttbl Palette translation table
* @param nCel Frame number in CL2 file
*/
void Cl2ApplyTrans(byte *p, const std::array<uint8_t, 256> &ttbl, int nCel)
{
assert(p != nullptr);
for (int i = 1; i <= nCel; i++) {
int nDataSize;
byte *dst = CelGetFrame(p, i, &nDataSize) + 10;
nDataSize -= 10;
while (nDataSize > 0) {
auto width = static_cast<std::int8_t>(*dst++);
nDataSize--;
assert(nDataSize >= 0);
if (width < 0) {
width = -width;
if (width > MaxCl2Width) {
nDataSize--;
assert(nDataSize >= 0);
*dst = static_cast<byte>(ttbl[static_cast<std::uint8_t>(*dst)]);
dst++;
} else {
nDataSize -= width;
assert(nDataSize >= 0);
for (; width > 0; width--) {
*dst = static_cast<byte>(ttbl[static_cast<std::uint8_t>(*dst)]);
dst++;
}
}
}
}
}
}
/**
* @brief Blit CL2 sprite to the given buffer
* @param out Target buffer
* @param sx Target buffer coordinate
* @param sy Target buffer coordinate
* @param pRLEBytes CL2 pixel stream (run-length encoded)
* @param nDataSize Size of CL2 in bytes
* @param nWidth Width of sprite
*/
static void Cl2BlitSafe(const CelOutputBuffer &out, int sx, int sy, const byte *pRLEBytes, int nDataSize, int nWidth)
{
const byte *src = pRLEBytes;
BYTE *dst = out.at(sx, sy);
int w = nWidth;
while (nDataSize > 0) {
auto width = static_cast<std::int8_t>(*src++);
nDataSize--;
if (width < 0) {
width = -width;
if (width > MaxCl2Width) {
width -= MaxCl2Width;
nDataSize--;
const auto fill = static_cast<std::uint8_t>(*src++);
if (dst < out.end() && dst > out.begin()) {
w -= width;
while (width > 0) {
*dst = fill;
dst++;
width--;
}
if (w == 0) {
w = nWidth;
dst -= out.pitch() + w;
}
continue;
}
} else {
nDataSize -= width;
if (dst < out.end() && dst > out.begin()) {
w -= width;
while (width > 0) {
*dst = static_cast<std::uint8_t>(*src);
src++;
dst++;
width--;
}
if (w == 0) {
w = nWidth;
dst -= out.pitch() + w;
}
continue;
}
src += width;
}
}
while (width > 0) {
if (width > w) {
dst += w;
width -= w;
w = 0;
} else {
dst += width;
w -= width;
width = 0;
}
if (w == 0) {
w = nWidth;
dst -= out.pitch() + w;
}
}
}
}
/**
* @brief Blit a solid colder shape one pixel larger then the given sprite shape, to the given buffer
* @param out Target buffer
* @param sx Target buffer coordinate
* @param sy Target buffer coordinate
* @param pRLEBytes CL2 pixel stream (run-length encoded)
* @param nDataSize Size of CL2 in bytes
* @param nWidth Width of sprite
* @param col Color index from current palette
*/
static void Cl2BlitOutlineSafe(const CelOutputBuffer &out, int sx, int sy, const byte *pRLEBytes, int nDataSize, int nWidth, uint8_t col)
{
const byte *src = pRLEBytes;
BYTE *dst = out.at(sx, sy);
int w = nWidth;
while (nDataSize > 0) {
auto width = static_cast<std::int8_t>(*src++);
nDataSize--;
if (width < 0) {
width = -width;
if (width > MaxCl2Width) {
width -= MaxCl2Width;
nDataSize--;
if (static_cast<std::uint8_t>(*src++) != 0 && dst < out.end() && dst > out.begin()) {
w -= width;
dst[-1] = col;
dst[width] = col;
while (width > 0) {
dst[-out.pitch()] = col;
dst[out.pitch()] = col;
dst++;
width--;
}
if (w == 0) {
w = nWidth;
dst -= out.pitch() + w;
}
continue;
}
} else {
nDataSize -= width;
if (dst < out.end() && dst > out.begin()) {
w -= width;
while (width > 0) {
if (static_cast<std::uint8_t>(*src) != 0) {
dst[-1] = col;
dst[1] = col;
dst[-out.pitch()] = col;
// BUGFIX: only set `if (dst+out.pitch() < out.end())`
dst[out.pitch()] = col;
}
src++;
dst++;
width--;
}
if (w == 0) {
w = nWidth;
dst -= out.pitch() + w;
}
continue;
}
src += width;
}
}
while (width > 0) {
if (width > w) {
dst += w;
width -= w;
w = 0;
} else {
dst += width;
w -= width;
width = 0;
}
if (w == 0) {
w = nWidth;
dst -= out.pitch() + w;
}
}
}
}
/**
* @brief Blit CL2 sprite, and apply lighting, to the given buffer
* @param out Target buffer
* @param sx Target buffer coordinate
* @param sy Target buffer coordinate
* @param pRLEBytes CL2 pixel stream (run-length encoded)
* @param nDataSize Size of CL2 in bytes
* @param nWidth With of CL2 sprite
* @param pTable Light color table
*/
static void Cl2BlitLightSafe(const CelOutputBuffer &out, int sx, int sy, const byte *pRLEBytes, int nDataSize, int nWidth, uint8_t *pTable)
{
const byte *src = pRLEBytes;
BYTE *dst = out.at(sx, sy);
int w = nWidth;
while (nDataSize > 0) {
auto width = static_cast<std::int8_t>(*src++);
nDataSize--;
if (width < 0) {
width = -width;
if (width > MaxCl2Width) {
width -= MaxCl2Width;
nDataSize--;
const uint8_t fill = pTable[static_cast<std::uint8_t>(*src++)];
if (dst < out.end() && dst > out.begin()) {
w -= width;
while (width > 0) {
*dst = fill;
dst++;
width--;
}
if (w == 0) {
w = nWidth;
dst -= out.pitch() + w;
}
continue;
}
} else {
nDataSize -= width;
if (dst < out.end() && dst > out.begin()) {
w -= width;
while (width > 0) {
*dst = pTable[static_cast<std::uint8_t>(*src)];
src++;
dst++;
width--;
}
if (w == 0) {
w = nWidth;
dst -= out.pitch() + w;
}
continue;
}
src += width;
}
}
while (width > 0) {
if (width > w) {
dst += w;
width -= w;
w = 0;
} else {
dst += width;
w -= width;
width = 0;
}
if (w == 0) {
w = nWidth;
dst -= out.pitch() + w;
}
}
}
}
void Cl2Draw(const CelOutputBuffer &out, int sx, int sy, const CelSprite &cel, int frame)
{
assert(frame > 0);
int nDataSize;
const byte *pRLEBytes = CelGetFrameClipped(cel.Data(), frame, &nDataSize);
Cl2BlitSafe(out, sx, sy, pRLEBytes, nDataSize, cel.Width(frame));
}
void Cl2DrawOutline(const CelOutputBuffer &out, uint8_t col, int sx, int sy, const CelSprite &cel, int frame)
{
assert(frame > 0);
int nDataSize;
const byte *pRLEBytes = CelGetFrameClipped(cel.Data(), frame, &nDataSize);
const CelOutputBuffer &sub = out.subregionY(0, out.h() - 1);
Cl2BlitOutlineSafe(sub, sx, sy, pRLEBytes, nDataSize, cel.Width(frame), col);
}
void Cl2DrawLightTbl(const CelOutputBuffer &out, int sx, int sy, const CelSprite &cel, int frame, char light)
{
assert(frame > 0);
int nDataSize;
const byte *pRLEBytes = CelGetFrameClipped(cel.Data(), frame, &nDataSize);
Cl2BlitLightSafe(out, sx, sy, pRLEBytes, nDataSize, cel.Width(frame), GetLightTable(light));
}
void Cl2DrawLight(const CelOutputBuffer &out, int sx, int sy, const CelSprite &cel, int frame)
{
assert(frame > 0);
int nDataSize;
const byte *pRLEBytes = CelGetFrameClipped(cel.Data(), frame, &nDataSize);
if (light_table_index != 0)
Cl2BlitLightSafe(out, sx, sy, pRLEBytes, nDataSize, cel.Width(frame), &pLightTbl[light_table_index * 256]);
else
Cl2BlitSafe(out, sx, sy, pRLEBytes, nDataSize, cel.Width(frame));
}
/**
* @brief Fade to black and play a video
* @param pszMovie file path of movie

43
Source/engine.h

@ -408,48 +408,6 @@ inline void SetPixel(const CelOutputBuffer &out, Point position, std::uint8_t co
out[position] = col;
}
/**
* @brief Blit CL2 sprite, to the back buffer at the given coordianates
* @param out Output buffer
* @param sx Output buffer coordinate
* @param sy Output buffer coordinate
* @param pCelBuff CL2 buffer
* @param nCel CL2 frame number
*/
void Cl2Draw(const CelOutputBuffer &out, int sx, int sy, const CelSprite &cel, int frame);
/**
* @brief Blit a solid colder shape one pixel larger then the given sprite shape, to the given buffer at the given coordianates
* @param col Color index from current palette
* @param out Output buffer
* @param sx Output buffer coordinate
* @param sy Output buffer coordinate
* @param pCelBuff CL2 buffer
* @param nCel CL2 frame number
*/
void Cl2DrawOutline(const CelOutputBuffer &out, uint8_t col, int sx, int sy, const CelSprite &cel, int frame);
/**
* @brief Blit CL2 sprite, and apply a given lighting, to the given buffer at the given coordianates
* @param out Output buffer
* @param sx Output buffer coordinate
* @param sy Output buffer coordinate
* @param pCelBuff CL2 buffer
* @param nCel CL2 frame number
* @param light Light shade to use
*/
void Cl2DrawLightTbl(const CelOutputBuffer &out, int sx, int sy, const CelSprite &cel, int frame, char light);
/**
* @brief Blit CL2 sprite, and apply lighting, to the given buffer at the given coordinates
* @param out Output buffer
* @param sx Output buffer coordinate
* @param sy Output buffer coordinate
* @param pCelBuff CL2 buffer
* @param nCel CL2 frame number
*/
void Cl2DrawLight(const CelOutputBuffer &out, int sx, int sy, const CelSprite &cel, int frame);
/**
* @brief Draw a horizontal line segment in the target buffer (left to right)
* @param out Target buffer
@ -549,7 +507,6 @@ std::unique_ptr<T[]> LoadFileInMem(const char *path, size_t *elements = nullptr)
return buf;
}
void Cl2ApplyTrans(byte *p, const std::array<uint8_t, 256> &ttbl, int nCel);
void PlayInGameMovie(const char *pszMovie);
} // namespace devilution

321
Source/engine/render/cl2_render.cpp

@ -0,0 +1,321 @@
#include "cl2_render.hpp"
#include "engine/render/common_impl.h"
#include "scrollrt.h"
namespace devilution {
namespace {
constexpr std::uint8_t MaxCl2Width = 65;
/**
* @brief Blit CL2 sprite to the given buffer
* @param out Target buffer
* @param sx Target buffer coordinate
* @param sy Target buffer coordinate
* @param pRLEBytes CL2 pixel stream (run-length encoded)
* @param nDataSize Size of CL2 in bytes
* @param nWidth Width of sprite
*/
void Cl2BlitSafe(const CelOutputBuffer &out, int sx, int sy, const byte *pRLEBytes, int nDataSize, int nWidth)
{
const byte *src = pRLEBytes;
BYTE *dst = out.at(sx, sy);
int w = nWidth;
while (nDataSize > 0) {
auto width = static_cast<std::int8_t>(*src++);
nDataSize--;
if (width < 0) {
width = -width;
if (width > MaxCl2Width) {
width -= MaxCl2Width;
nDataSize--;
const auto fill = static_cast<std::uint8_t>(*src++);
if (dst < out.end() && dst > out.begin()) {
w -= width;
while (width > 0) {
*dst = fill;
dst++;
width--;
}
if (w == 0) {
w = nWidth;
dst -= out.pitch() + w;
}
continue;
}
} else {
nDataSize -= width;
if (dst < out.end() && dst > out.begin()) {
w -= width;
while (width > 0) {
*dst = static_cast<std::uint8_t>(*src);
src++;
dst++;
width--;
}
if (w == 0) {
w = nWidth;
dst -= out.pitch() + w;
}
continue;
}
src += width;
}
}
while (width > 0) {
if (width > w) {
dst += w;
width -= w;
w = 0;
} else {
dst += width;
w -= width;
width = 0;
}
if (w == 0) {
w = nWidth;
dst -= out.pitch() + w;
}
}
}
}
/**
* @brief Blit a solid colder shape one pixel larger then the given sprite shape, to the given buffer
* @param out Target buffer
* @param sx Target buffer coordinate
* @param sy Target buffer coordinate
* @param pRLEBytes CL2 pixel stream (run-length encoded)
* @param nDataSize Size of CL2 in bytes
* @param nWidth Width of sprite
* @param col Color index from current palette
*/
void Cl2BlitOutlineSafe(const CelOutputBuffer &out, int sx, int sy, const byte *pRLEBytes, int nDataSize, int nWidth, uint8_t col)
{
const byte *src = pRLEBytes;
BYTE *dst = out.at(sx, sy);
int w = nWidth;
while (nDataSize > 0) {
auto width = static_cast<std::int8_t>(*src++);
nDataSize--;
if (width < 0) {
width = -width;
if (width > MaxCl2Width) {
width -= MaxCl2Width;
nDataSize--;
if (static_cast<std::uint8_t>(*src++) != 0 && dst < out.end() && dst > out.begin()) {
w -= width;
dst[-1] = col;
dst[width] = col;
while (width > 0) {
dst[-out.pitch()] = col;
dst[out.pitch()] = col;
dst++;
width--;
}
if (w == 0) {
w = nWidth;
dst -= out.pitch() + w;
}
continue;
}
} else {
nDataSize -= width;
if (dst < out.end() && dst > out.begin()) {
w -= width;
while (width > 0) {
if (static_cast<std::uint8_t>(*src) != 0) {
dst[-1] = col;
dst[1] = col;
dst[-out.pitch()] = col;
// BUGFIX: only set `if (dst+out.pitch() < out.end())`
dst[out.pitch()] = col;
}
src++;
dst++;
width--;
}
if (w == 0) {
w = nWidth;
dst -= out.pitch() + w;
}
continue;
}
src += width;
}
}
while (width > 0) {
if (width > w) {
dst += w;
width -= w;
w = 0;
} else {
dst += width;
w -= width;
width = 0;
}
if (w == 0) {
w = nWidth;
dst -= out.pitch() + w;
}
}
}
}
/**
* @brief Blit CL2 sprite, and apply lighting, to the given buffer
* @param out Target buffer
* @param sx Target buffer coordinate
* @param sy Target buffer coordinate
* @param pRLEBytes CL2 pixel stream (run-length encoded)
* @param nDataSize Size of CL2 in bytes
* @param nWidth With of CL2 sprite
* @param pTable Light color table
*/
void Cl2BlitLightSafe(const CelOutputBuffer &out, int sx, int sy, const byte *pRLEBytes, int nDataSize, int nWidth, uint8_t *pTable)
{
const byte *src = pRLEBytes;
BYTE *dst = out.at(sx, sy);
int w = nWidth;
while (nDataSize > 0) {
auto width = static_cast<std::int8_t>(*src++);
nDataSize--;
if (width < 0) {
width = -width;
if (width > MaxCl2Width) {
width -= MaxCl2Width;
nDataSize--;
const uint8_t fill = pTable[static_cast<std::uint8_t>(*src++)];
if (dst < out.end() && dst > out.begin()) {
w -= width;
while (width > 0) {
*dst = fill;
dst++;
width--;
}
if (w == 0) {
w = nWidth;
dst -= out.pitch() + w;
}
continue;
}
} else {
nDataSize -= width;
if (dst < out.end() && dst > out.begin()) {
w -= width;
while (width > 0) {
*dst = pTable[static_cast<std::uint8_t>(*src)];
src++;
dst++;
width--;
}
if (w == 0) {
w = nWidth;
dst -= out.pitch() + w;
}
continue;
}
src += width;
}
}
while (width > 0) {
if (width > w) {
dst += w;
width -= w;
w = 0;
} else {
dst += width;
w -= width;
width = 0;
}
if (w == 0) {
w = nWidth;
dst -= out.pitch() + w;
}
}
}
}
} // namespace
void Cl2ApplyTrans(byte *p, const std::array<uint8_t, 256> &ttbl, int nCel)
{
assert(p != nullptr);
for (int i = 1; i <= nCel; i++) {
int nDataSize;
byte *dst = CelGetFrame(p, i, &nDataSize) + 10;
nDataSize -= 10;
while (nDataSize > 0) {
auto width = static_cast<std::int8_t>(*dst++);
nDataSize--;
assert(nDataSize >= 0);
if (width < 0) {
width = -width;
if (width > MaxCl2Width) {
nDataSize--;
assert(nDataSize >= 0);
*dst = static_cast<byte>(ttbl[static_cast<std::uint8_t>(*dst)]);
dst++;
} else {
nDataSize -= width;
assert(nDataSize >= 0);
for (; width > 0; width--) {
*dst = static_cast<byte>(ttbl[static_cast<std::uint8_t>(*dst)]);
dst++;
}
}
}
}
}
}
void Cl2Draw(const CelOutputBuffer &out, int sx, int sy, const CelSprite &cel, int frame)
{
assert(frame > 0);
int nDataSize;
const byte *pRLEBytes = CelGetFrameClipped(cel.Data(), frame, &nDataSize);
Cl2BlitSafe(out, sx, sy, pRLEBytes, nDataSize, cel.Width(frame));
}
void Cl2DrawOutline(const CelOutputBuffer &out, uint8_t col, int sx, int sy, const CelSprite &cel, int frame)
{
assert(frame > 0);
int nDataSize;
const byte *pRLEBytes = CelGetFrameClipped(cel.Data(), frame, &nDataSize);
const CelOutputBuffer &sub = out.subregionY(0, out.h() - 1);
Cl2BlitOutlineSafe(sub, sx, sy, pRLEBytes, nDataSize, cel.Width(frame), col);
}
void Cl2DrawLightTbl(const CelOutputBuffer &out, int sx, int sy, const CelSprite &cel, int frame, char light)
{
assert(frame > 0);
int nDataSize;
const byte *pRLEBytes = CelGetFrameClipped(cel.Data(), frame, &nDataSize);
Cl2BlitLightSafe(out, sx, sy, pRLEBytes, nDataSize, cel.Width(frame), GetLightTable(light));
}
void Cl2DrawLight(const CelOutputBuffer &out, int sx, int sy, const CelSprite &cel, int frame)
{
assert(frame > 0);
int nDataSize;
const byte *pRLEBytes = CelGetFrameClipped(cel.Data(), frame, &nDataSize);
if (light_table_index != 0)
Cl2BlitLightSafe(out, sx, sy, pRLEBytes, nDataSize, cel.Width(frame), &pLightTbl[light_table_index * 256]);
else
Cl2BlitSafe(out, sx, sy, pRLEBytes, nDataSize, cel.Width(frame));
}
} // namespace devilution

65
Source/engine/render/cl2_render.hpp

@ -0,0 +1,65 @@
/**
* @file cl2_render.hpp
*
* CL2 rendering.
*/
#pragma once
#include <array>
#include <cstdint>
#include "engine.h"
namespace devilution {
/**
* @brief Apply the color swaps to a CL2 sprite
* @param p CL2 buffer
* @param ttbl Palette translation table
* @param nCel Frame number in CL2 file
*/
void Cl2ApplyTrans(byte *p, const std::array<uint8_t, 256> &ttbl, int nCel);
/**
* @brief Blit CL2 sprite, to the back buffer at the given coordianates
* @param out Output buffer
* @param sx Output buffer coordinate
* @param sy Output buffer coordinate
* @param pCelBuff CL2 buffer
* @param nCel CL2 frame number
*/
void Cl2Draw(const CelOutputBuffer &out, int sx, int sy, const CelSprite &cel, int frame);
/**
* @brief Blit a solid colder shape one pixel larger then the given sprite shape, to the given buffer at the given coordianates
* @param col Color index from current palette
* @param out Output buffer
* @param sx Output buffer coordinate
* @param sy Output buffer coordinate
* @param pCelBuff CL2 buffer
* @param nCel CL2 frame number
*/
void Cl2DrawOutline(const CelOutputBuffer &out, uint8_t col, int sx, int sy, const CelSprite &cel, int frame);
/**
* @brief Blit CL2 sprite, and apply a given lighting, to the given buffer at the given coordianates
* @param out Output buffer
* @param sx Output buffer coordinate
* @param sy Output buffer coordinate
* @param pCelBuff CL2 buffer
* @param nCel CL2 frame number
* @param light Light shade to use
*/
void Cl2DrawLightTbl(const CelOutputBuffer &out, int sx, int sy, const CelSprite &cel, int frame, char light);
/**
* @brief Blit CL2 sprite, and apply lighting, to the given buffer at the given coordinates
* @param out Output buffer
* @param sx Output buffer coordinate
* @param sy Output buffer coordinate
* @param pCelBuff CL2 buffer
* @param nCel CL2 frame number
*/
void Cl2DrawLight(const CelOutputBuffer &out, int sx, int sy, const CelSprite &cel, int frame);
} // namespace devilution

8
Source/monster.cpp

@ -12,11 +12,9 @@
#include "control.h"
#include "cursor.h"
#include "dead.h"
#ifdef _DEBUG
#include "debug.h"
#endif
#include "drlg_l1.h"
#include "drlg_l4.h"
#include "engine/render/cl2_render.hpp"
#include "init.h"
#include "lighting.h"
#include "minitext.h"
@ -29,6 +27,10 @@
#include "trigs.h"
#include "utils/language.h"
#ifdef _DEBUG
#include "debug.h"
#endif
namespace devilution {
#define NIGHTMARE_TO_HIT_BONUS 85

1
Source/scrollrt.cpp

@ -11,6 +11,7 @@
#include "doom.h"
#include "dx.h"
#include "engine/render/cel_render.hpp"
#include "engine/render/cl2_render.hpp"
#include "engine/render/dun_render.hpp"
#include "error.h"
#include "gmenu.h"

Loading…
Cancel
Save