From 8283f85e248f5d214d754f2681b7dd37b53e4543 Mon Sep 17 00:00:00 2001 From: Gleb Mazovetskiy Date: Sat, 2 Jan 2021 12:34:31 +0000 Subject: [PATCH] Engine: Functions to render to any buffer Refactor the rendering functions to allow rendering to any output buffer. New functions that accept a buffer have the `To` suffix. The functions that render to the global buffer now always accept coordinates. --- Source/control.cpp | 44 ++--- Source/engine.cpp | 419 ++++++++++++-------------------------------- Source/engine.h | 320 +++++++++++++++++++++++++++++++-- Source/inv.cpp | 9 +- Source/minitext.cpp | 15 +- Source/scrollrt.cpp | 4 +- 6 files changed, 445 insertions(+), 366 deletions(-) diff --git a/Source/control.cpp b/Source/control.cpp index 4c25bad25..a3758ce79 100644 --- a/Source/control.cpp +++ b/Source/control.cpp @@ -5,6 +5,8 @@ */ #include "all.h" +#include + DEVILUTION_BEGIN_NAMESPACE BYTE sgbNextTalkSave; @@ -775,22 +777,20 @@ void UpdateManaFlask() DrawSpell(); } +static CelOutputBuffer AllocCelOutputBuffer(BYTE **raw, size_t width, size_t height) { + const std::size_t size = width * height; + *raw = DiabloAllocPtr(size); + memset(*raw, 0, size); + return CelOutputBuffer{*raw, *raw + size, static_cast(width)}; +} + void InitControlPan() { int i; - BYTE *tBuff; + const CelOutputBuffer btm_buf = AllocCelOutputBuffer(&pBtmBuff, PANEL_WIDTH, (PANEL_HEIGHT + 16) * (gbIsMultiplayer ? 2 : 1)); + const CelOutputBuffer mana_buf = AllocCelOutputBuffer(&pManaBuff, 88, 88); + const CelOutputBuffer life_buf = AllocCelOutputBuffer(&pLifeBuff, 88, 88); - if (!gbIsMultiplayer) { - pBtmBuff = DiabloAllocPtr((PANEL_HEIGHT + 16) * PANEL_WIDTH); - memset(pBtmBuff, 0, (PANEL_HEIGHT + 16) * PANEL_WIDTH); - } else { - pBtmBuff = DiabloAllocPtr((PANEL_HEIGHT + 16) * 2 * PANEL_WIDTH); - memset(pBtmBuff, 0, (PANEL_HEIGHT + 16) * 2 * PANEL_WIDTH); - } - pManaBuff = DiabloAllocPtr(88 * 88); - memset(pManaBuff, 0, 88 * 88); - pLifeBuff = DiabloAllocPtr(88 * 88); - memset(pLifeBuff, 0, 88 * 88); pPanelText = LoadFileInMem("CtrlPan\\SmalText.CEL", NULL); pChrPanel = LoadFileInMem("Data\\Char.CEL", NULL); if (!gbIsHellfire) @@ -798,18 +798,18 @@ void InitControlPan() else pSpellCels = LoadFileInMem("Data\\SpelIcon.CEL", NULL); SetSpellTrans(RSPLTYPE_SKILL); - tBuff = LoadFileInMem("CtrlPan\\Panel8.CEL", NULL); - CelBlitWidth(pBtmBuff, 0, (PANEL_HEIGHT + 16) - 1, PANEL_WIDTH, tBuff, 1, PANEL_WIDTH); - MemFreeDbg(tBuff); - tBuff = LoadFileInMem("CtrlPan\\P8Bulbs.CEL", NULL); - CelBlitWidth(pLifeBuff, 0, 87, 88, tBuff, 1, 88); - CelBlitWidth(pManaBuff, 0, 87, 88, tBuff, 2, 88); - MemFreeDbg(tBuff); + BYTE *pStatusPanel = LoadFileInMem("CtrlPan\\Panel8.CEL", NULL); + CelDrawUnsafeTo(btm_buf, 0, (PANEL_HEIGHT + 16) - 1, pStatusPanel, 1, PANEL_WIDTH); + MemFreeDbg(pStatusPanel); + pStatusPanel = LoadFileInMem("CtrlPan\\P8Bulbs.CEL", NULL); + CelDrawUnsafeTo(life_buf, 0, 87, pStatusPanel, 1, 88); + CelDrawUnsafeTo(mana_buf, 0, 87, pStatusPanel, 2, 88); + MemFreeDbg(pStatusPanel); talkflag = FALSE; if (gbIsMultiplayer) { - tBuff = LoadFileInMem("CtrlPan\\TalkPanl.CEL", NULL); - CelBlitWidth(pBtmBuff, 0, (PANEL_HEIGHT + 16) * 2 - 1, PANEL_WIDTH, tBuff, 1, PANEL_WIDTH); - MemFreeDbg(tBuff); + BYTE * pTalkPanel = LoadFileInMem("CtrlPan\\TalkPanl.CEL", NULL); + CelDrawUnsafeTo(btm_buf, 0, (PANEL_HEIGHT + 16) * 2 - 1, pTalkPanel, 1, PANEL_WIDTH); + MemFreeDbg(pTalkPanel); pMultiBtns = LoadFileInMem("CtrlPan\\P8But2.CEL", NULL); pTalkBtns = LoadFileInMem("CtrlPan\\TalkButt.CEL", NULL); sgbPlrTalkTbl = 0; diff --git a/Source/engine.cpp b/Source/engine.cpp index 157d86ea6..4ec62b5cf 100644 --- a/Source/engine.cpp +++ b/Source/engine.cpp @@ -31,132 +31,73 @@ const int RndInc = 1; */ const int RndMult = 0x015A4E35; -/** - * @brief Blit CEL sprite to the back buffer at the given coordinates - * @param sx Back buffer coordinate - * @param sy Back buffer coordinate - * @param pCelBuff Cel data - * @param nCel CEL frame number - * @param nWidth Width of sprite - */ -void CelDraw(int sx, int sy, BYTE *pCelBuff, int nCel, int nWidth) -{ - CelBlitFrame(&gpBuffer[sx + BUFFER_WIDTH * sy], pCelBuff, nCel, nWidth); -} - -/** - * @brief Blit a given CEL frame to the given buffer - * @param pBuff Target buffer - * @param pCelBuff Cel data - * @param nCel CEL frame number - * @param nWidth Width of sprite - */ -void CelBlitFrame(BYTE *pBuff, BYTE *pCelBuff, int nCel, int nWidth) +void CelDrawTo(CelOutputBuffer out, int sx, int sy, BYTE *pCelBuff, int nCel, int nWidth) { int nDataSize; BYTE *pRLEBytes; assert(pCelBuff != NULL); - assert(pBuff != NULL); + assert(out.begin != NULL); pRLEBytes = CelGetFrame(pCelBuff, nCel, &nDataSize); - CelBlitSafe(pBuff, pRLEBytes, nDataSize, nWidth); + CelBlitSafeTo(out, sx, sy, pRLEBytes, nDataSize, nWidth); } -/** - * @brief Same as CelDraw but with the option to skip parts of the top and bottom of the sprite - * @param sx Back buffer coordinate - * @param sy Back buffer coordinate - * @param pCelBuff Cel data - * @param nCel CEL frame number - * @param nWidth Width of sprite - */ -void CelClippedDraw(int sx, int sy, BYTE *pCelBuff, int nCel, int nWidth) +void CelClippedDrawTo(CelOutputBuffer out, int sx, int sy, BYTE *pCelBuff, int nCel, int nWidth) { BYTE *pRLEBytes; int nDataSize; - assert(gpBuffer); + assert(out.begin != NULL); assert(pCelBuff != NULL); pRLEBytes = CelGetFrameClipped(pCelBuff, nCel, &nDataSize); - CelBlitSafe( - &gpBuffer[sx + BUFFER_WIDTH * sy], - pRLEBytes, - nDataSize, - nWidth); + CelBlitSafeTo(out, sx, sy, pRLEBytes, nDataSize, nWidth); } -/** - * @brief Blit CEL sprite, and apply lighting, to the back buffer at the given coordinates - * @param sx Back buffer coordinate - * @param sy Back buffer coordinate - * @param pCelBuff Cel data - * @param nCel CEL frame number - * @param nWidth Width of sprite - */ -void CelDrawLight(int sx, int sy, BYTE *pCelBuff, int nCel, int nWidth, BYTE *tbl) +void CelDrawLightTo(CelOutputBuffer out, int sx, int sy, BYTE *pCelBuff, int nCel, int nWidth, BYTE *tbl) { int nDataSize; - BYTE *pDecodeTo, *pRLEBytes; + BYTE *pRLEBytes; - assert(gpBuffer); + assert(out.begin != NULL); assert(pCelBuff != NULL); pRLEBytes = CelGetFrame(pCelBuff, nCel, &nDataSize); - pDecodeTo = &gpBuffer[sx + BUFFER_WIDTH * sy]; if (light_table_index || tbl) - CelBlitLightSafe(pDecodeTo, pRLEBytes, nDataSize, nWidth, tbl); + CelBlitLightSafeTo(out, sx, sy, pRLEBytes, nDataSize, nWidth, tbl); else - CelBlitSafe(pDecodeTo, pRLEBytes, nDataSize, nWidth); + CelBlitSafeTo(out, sx, sy, pRLEBytes, nDataSize, nWidth); } -/** - * @brief Same as CelDrawLight but with the option to skip parts of the top and bottom of the sprite - * @param sx Back buffer coordinate - * @param sy Back buffer coordinate - * @param pCelBuff Cel data - * @param nCel CEL frame number - * @param nWidth Width of sprite - */ -void CelClippedDrawLight(int sx, int sy, BYTE *pCelBuff, int nCel, int nWidth) +void CelClippedDrawLightTo(CelOutputBuffer out, int sx, int sy, BYTE *pCelBuff, int nCel, int nWidth) { int nDataSize; - BYTE *pRLEBytes, *pDecodeTo; + BYTE *pRLEBytes; - assert(gpBuffer); + assert(out.begin != NULL); assert(pCelBuff != NULL); pRLEBytes = CelGetFrameClipped(pCelBuff, nCel, &nDataSize); - pDecodeTo = &gpBuffer[sx + BUFFER_WIDTH * sy]; if (light_table_index) - CelBlitLightSafe(pDecodeTo, pRLEBytes, nDataSize, nWidth, NULL); + CelBlitLightSafeTo(out, sx, sy, pRLEBytes, nDataSize, nWidth, NULL); else - CelBlitSafe(pDecodeTo, pRLEBytes, nDataSize, nWidth); + CelBlitSafeTo(out, sx, sy, pRLEBytes, nDataSize, nWidth); } -/** - * @brief Blit CEL sprite, and apply lighting, to the back buffer at the given coordinates, translated to a red hue - * @param sx Back buffer coordinate - * @param sy Back buffer coordinate - * @param pCelBuff Cel data - * @param nCel CEL frame number - * @param nWidth Width of sprite - * @param light Light shade to use - */ -void CelDrawLightRed(int sx, int sy, BYTE *pCelBuff, int nCel, int nWidth, char light) +void CelDrawLightRedTo(CelOutputBuffer out, int sx, int sy, BYTE *pCelBuff, int nCel, int nWidth, char light) { int nDataSize, w, idx; BYTE *pRLEBytes, *dst, *tbl; - assert(gpBuffer); + assert(out.begin != NULL); assert(pCelBuff != NULL); pRLEBytes = CelGetFrameClipped(pCelBuff, nCel, &nDataSize); - dst = &gpBuffer[sx + BUFFER_WIDTH * sy]; + dst = out.at(sx, sy); idx = light4flag ? 1024 : 4096; if (light == 2) @@ -170,7 +111,7 @@ void CelDrawLightRed(int sx, int sy, BYTE *pCelBuff, int nCel, int nWidth, char tbl = &pLightTbl[idx]; end = &pRLEBytes[nDataSize]; - for (; pRLEBytes != end; dst -= BUFFER_WIDTH + nWidth) { + for (; pRLEBytes != end; dst -= out.line_width + nWidth) { for (w = nWidth; w;) { width = *pRLEBytes++; if (!(width & 0x80)) { @@ -190,33 +131,25 @@ void CelDrawLightRed(int sx, int sy, BYTE *pCelBuff, int nCel, int nWidth, char } } -/** - * @brief Blit CEL sprite to the given buffer, checks for drawing outside the buffer - * @param pDecodeTo The output buffer - * @param pRLEBytes CEL pixel stream (run-length encoded) - * @param nDataSize Size of CEL in bytes - * @param nWidth Width of sprite - */ -void CelBlitSafe(BYTE *pDecodeTo, BYTE *pRLEBytes, int nDataSize, int nWidth) +void CelBlitSafeTo(CelOutputBuffer out, int sx, int sy, BYTE *pRLEBytes, int nDataSize, int nWidth) { int i, w; BYTE width; BYTE *src, *dst; - assert(pDecodeTo != NULL); + assert(out.begin != NULL); assert(pRLEBytes != NULL); - assert(gpBuffer); src = pRLEBytes; - dst = pDecodeTo; + dst = out.at(sx, sy); w = nWidth; - for (; src != &pRLEBytes[nDataSize]; dst -= BUFFER_WIDTH + w) { + for (; src != &pRLEBytes[nDataSize]; dst -= out.line_width + w) { for (i = w; i;) { width = *src++; if (!(width & 0x80)) { i -= width; - if (dst < gpBufEnd && dst > gpBufStart) { + if (dst < out.end && dst > out.begin) { memcpy(dst, src, width); } src += width; @@ -230,61 +163,39 @@ void CelBlitSafe(BYTE *pDecodeTo, BYTE *pRLEBytes, int nDataSize, int nWidth) } } -/** - * @brief Same as CelClippedDraw but checks for drawing outside the buffer - * @param sx Back buffer coordinate - * @param sy Back buffer coordinate - * @param pCelBuff Cel data - * @param nCel CEL frame number - * @param nWidth Width of sprite - */ -void CelClippedDrawSafe(int sx, int sy, BYTE *pCelBuff, int nCel, int nWidth) +void CelClippedDrawSafeTo(CelOutputBuffer out, int sx, int sy, BYTE *pCelBuff, int nCel, int nWidth) { BYTE *pRLEBytes; int nDataSize; - assert(gpBuffer); + assert(out.begin != NULL); assert(pCelBuff != NULL); pRLEBytes = CelGetFrameClipped(pCelBuff, nCel, &nDataSize); - - CelBlitSafe( - &gpBuffer[sx + BUFFER_WIDTH * sy], - pRLEBytes, - nDataSize, - nWidth); + CelBlitSafeTo(out, sx, sy, pRLEBytes, nDataSize, nWidth); } -/** - * @brief Blit CEL sprite, and apply lighting, to the given buffer, checks for drawing outside the buffer - * @param pDecodeTo The output buffer - * @param pRLEBytes CEL pixel stream (run-length encoded) - * @param nDataSize Size of CEL in bytes - * @param nWidth Width of sprite - * @param tbl Palette translation table - */ -void CelBlitLightSafe(BYTE *pDecodeTo, BYTE *pRLEBytes, int nDataSize, int nWidth, BYTE *tbl) +void CelBlitLightSafeTo(CelOutputBuffer out, int sx, int sy, BYTE *pRLEBytes, int nDataSize, int nWidth, BYTE *tbl) { int i, w; BYTE width; BYTE *src, *dst; - assert(pDecodeTo != NULL); + assert(out.begin != NULL); assert(pRLEBytes != NULL); - assert(gpBuffer); src = pRLEBytes; - dst = pDecodeTo; + dst = out.at(sx, sy); if (tbl == NULL) tbl = &pLightTbl[light_table_index * 256]; w = nWidth; - for (; src != &pRLEBytes[nDataSize]; dst -= BUFFER_WIDTH + w) { + for (; src != &pRLEBytes[nDataSize]; dst -= out.line_width + w) { for (i = w; i;) { width = *src++; if (!(width & 0x80)) { i -= width; - if (dst < gpBufEnd && dst > gpBufStart) { + if (dst < out.end && dst > out.begin) { if (width & 1) { dst[0] = tbl[src[0]]; src++; @@ -319,39 +230,31 @@ void CelBlitLightSafe(BYTE *pDecodeTo, BYTE *pRLEBytes, int nDataSize, int nWidt } } -/** - * @brief Same as CelBlitLightSafe, with stippled transparancy applied - * @param pDecodeTo The output buffer - * @param pRLEBytes CEL pixel stream (run-length encoded) - * @param nDataSize Size of CEL in bytes - * @param nWidth Width of sprite - */ -static void CelBlitLightTransSafe(BYTE *pDecodeTo, BYTE *pRLEBytes, int nDataSize, int nWidth) +void CelBlitLightTransSafeTo(CelOutputBuffer out, int sx, int sy, BYTE *pRLEBytes, int nDataSize, int nWidth) { int w; BOOL shift; BYTE *tbl; - assert(pDecodeTo != NULL); assert(pRLEBytes != NULL); - assert(gpBuffer); + assert(out.begin != NULL); int i; BYTE width; BYTE *src, *dst; src = pRLEBytes; - dst = pDecodeTo; + dst = out.at(sx, sy); tbl = &pLightTbl[light_table_index * 256]; w = nWidth; shift = (BYTE)(size_t)dst & 1; - for (; src != &pRLEBytes[nDataSize]; dst -= BUFFER_WIDTH + w, shift = (shift + 1) & 1) { + for (; src != &pRLEBytes[nDataSize]; dst -= out.line_width + w, shift = (shift + 1) & 1) { for (i = w; i;) { width = *src++; if (!(width & 0x80)) { i -= width; - if (dst < gpBufEnd && dst > gpBufStart) { + if (dst < out.end && dst > out.begin) { if (((BYTE)(size_t)dst & 1) == shift) { if (!(width & 1)) { goto L_ODD; @@ -417,18 +320,17 @@ static void CelBlitLightTransSafe(BYTE *pDecodeTo, BYTE *pRLEBytes, int nDataSiz * @param nWidth Width of sprite * @param tbl Palette translation table */ -static void CelBlitLightBlendedSafe(BYTE *pDecodeTo, BYTE *pRLEBytes, int nDataSize, int nWidth, BYTE *tbl) +static void CelBlitLightBlendedSafeTo(CelOutputBuffer out, int sx, int sy, BYTE *pRLEBytes, int nDataSize, int nWidth, BYTE *tbl) { int i, w; BYTE width; BYTE *src, *dst; - assert(pDecodeTo != NULL); + assert(out.begin != NULL); assert(pRLEBytes != NULL); - assert(gpBuffer); src = pRLEBytes; - dst = pDecodeTo; + dst = out.at(sx, sy); if (tbl == NULL) tbl = &pLightTbl[light_table_index * 256]; w = nWidth; @@ -473,14 +375,7 @@ static void CelBlitLightBlendedSafe(BYTE *pDecodeTo, BYTE *pRLEBytes, int nDataS } } -/** - * @brief Same as CelBlitLightSafe, with stippled transparancy applied - * @param pBuff Target buffer - * @param pCelBuff Cel data - * @param nCel CEL frame number - * @param nWidth Width of sprite - */ -void CelClippedBlitLightTrans(BYTE *pBuff, BYTE *pCelBuff, int nCel, int nWidth) +void CelClippedBlitLightTransTo(CelOutputBuffer out, int sx, int sy, BYTE *pCelBuff, int nCel, int nWidth) { int nDataSize; BYTE *pRLEBytes; @@ -491,34 +386,25 @@ void CelClippedBlitLightTrans(BYTE *pBuff, BYTE *pCelBuff, int nCel, int nWidth) if (cel_transparency_active) { if (sgOptions.blendedTransparancy) - CelBlitLightBlendedSafe(pBuff, pRLEBytes, nDataSize, nWidth, NULL); + CelBlitLightBlendedSafeTo(out, sx, sy, pRLEBytes, nDataSize, nWidth, NULL); else - CelBlitLightTransSafe(pBuff, pRLEBytes, nDataSize, nWidth); + CelBlitLightTransSafeTo(out, sx, sy, pRLEBytes, nDataSize, nWidth); } else if (light_table_index) - CelBlitLightSafe(pBuff, pRLEBytes, nDataSize, nWidth, NULL); + CelBlitLightSafeTo(out, sx, sy, pRLEBytes, nDataSize, nWidth, NULL); else - CelBlitSafe(pBuff, pRLEBytes, nDataSize, nWidth); + CelBlitSafeTo(out, sx, sy, pRLEBytes, nDataSize, nWidth); } -/** - * @brief Same as CelDrawLightRed but checks for drawing outside the buffer - * @param sx Back buffer coordinate - * @param sy Back buffer coordinate - * @param pCelBuff Cel data - * @param nCel CEL frame number - * @param nWidth Width of cel - * @param light Light shade to use - */ -void CelDrawLightRedSafe(int sx, int sy, BYTE *pCelBuff, int nCel, int nWidth, char light) +void CelDrawLightRedSafeTo(CelOutputBuffer out, int sx, int sy, BYTE *pCelBuff, int nCel, int nWidth, char light) { int nDataSize, w, idx; BYTE *pRLEBytes, *dst, *tbl; - assert(gpBuffer); + assert(out.begin != NULL); assert(pCelBuff != NULL); pRLEBytes = CelGetFrameClipped(pCelBuff, nCel, &nDataSize); - dst = &gpBuffer[sx + BUFFER_WIDTH * sy]; + dst = out.at(sx, sy); idx = light4flag ? 1024 : 4096; if (light == 2) @@ -533,12 +419,12 @@ void CelDrawLightRedSafe(int sx, int sy, BYTE *pCelBuff, int nCel, int nWidth, c end = &pRLEBytes[nDataSize]; - for (; pRLEBytes != end; dst -= BUFFER_WIDTH + nWidth) { + for (; pRLEBytes != end; dst -= out.line_width + nWidth) { for (w = nWidth; w;) { width = *pRLEBytes++; if (!(width & 0x80)) { w -= width; - if (dst < gpBufEnd && dst > gpBufStart) { + if (dst < out.end && dst > out.begin) { while (width) { *dst = tbl[*pRLEBytes]; pRLEBytes++; @@ -558,31 +444,21 @@ void CelDrawLightRedSafe(int sx, int sy, BYTE *pCelBuff, int nCel, int nWidth, c } } -/** - * @brief Blit to a buffer at given coordinates - * @param pBuff Target buffer - * @param x Cordinate in pBuff buffer - * @param y Cordinate in pBuff buffer - * @param wdt Width of pBuff - * @param pCelBuff Cel data - * @param nCel CEL frame number - * @param nWidth Width of cel - */ -void CelBlitWidth(BYTE *pBuff, int x, int y, int wdt, BYTE *pCelBuff, int nCel, int nWidth) +void CelDrawUnsafeTo(CelOutputBuffer out, int x, int y, BYTE *pCelBuff, int nCel, int nWidth) { BYTE *pRLEBytes, *dst, *end; assert(pCelBuff != NULL); - assert(pBuff != NULL); + assert(out.begin != NULL); int i, nDataSize; BYTE width; pRLEBytes = CelGetFrame(pCelBuff, nCel, &nDataSize); end = &pRLEBytes[nDataSize]; - dst = &pBuff[y * wdt + x]; + dst = out.at(x, y); - for (; pRLEBytes != end; dst -= wdt + nWidth) { + for (; pRLEBytes != end; dst -= out.line_width + nWidth) { for (i = nWidth; i;) { width = *pRLEBytes++; if (!(width & 0x80)) { @@ -599,38 +475,29 @@ void CelBlitWidth(BYTE *pBuff, int x, int y, int wdt, BYTE *pCelBuff, int nCel, } } -/** - * @brief Blit a solid colder shape one pixel larger then the given sprite shape, to the back buffer at the given coordianates - * @param col Color index from current palette - * @param sx Back buffer coordinate - * @param sy Back buffer coordinate - * @param pCelBuff CEL buffer - * @param nCel CEL frame number - * @param nWidth Width of sprite - */ -void CelBlitOutline(BYTE col, int sx, int sy, BYTE *pCelBuff, int nCel, int nWidth) +void CelBlitOutlineTo(CelOutputBuffer out, BYTE col, int sx, int sy, BYTE *pCelBuff, int nCel, int nWidth) { int nDataSize, w; BYTE *src, *dst, *end; BYTE width; assert(pCelBuff != NULL); - assert(gpBuffer); + assert(out.begin != NULL); src = CelGetFrameClipped(pCelBuff, nCel, &nDataSize); end = &src[nDataSize]; - dst = &gpBuffer[sx + BUFFER_WIDTH * sy]; + dst = out.at(sx, sy); - for (; src != end; dst -= BUFFER_WIDTH + nWidth) { + for (; src != end; dst -= out.line_width + nWidth) { for (w = nWidth; w;) { width = *src++; if (!(width & 0x80)) { w -= width; - if (dst < gpBufEnd && dst > gpBufStart) { - if (dst >= gpBufEnd - BUFFER_WIDTH) { + if (dst < out.end && dst > out.begin) { + if (dst >= out.end - out.line_width) { while (width) { if (*src++) { - dst[-BUFFER_WIDTH] = col; + dst[-out.line_width] = col; dst[-1] = col; dst[1] = col; } @@ -640,10 +507,10 @@ void CelBlitOutline(BYTE col, int sx, int sy, BYTE *pCelBuff, int nCel, int nWid } else { while (width) { if (*src++) { - dst[-BUFFER_WIDTH] = col; + dst[-out.line_width] = col; dst[-1] = col; dst[1] = col; - dst[BUFFER_WIDTH] = col; + dst[out.line_width] = col; } dst++; width--; @@ -662,35 +529,14 @@ void CelBlitOutline(BYTE col, int sx, int sy, BYTE *pCelBuff, int nCel, int nWid } } -/** - * @brief Set the value of a single pixel in the back buffer, checks bounds - * @param sx Back buffer coordinate - * @param sy Back buffer coordinate - * @param col Color index from current palette - */ -void ENG_set_pixel(int sx, int sy, BYTE col) +void SetPixel(CelOutputBuffer out, int sx, int sy, BYTE col) { - BYTE *dst; - - assert(gpBuffer); - - if (sy < 0 || sy >= SCREEN_HEIGHT + SCREEN_Y || sx < SCREEN_X || sx >= SCREEN_WIDTH + SCREEN_X) + assert(out.begin != NULL); + if (!out.in_bounds(sx, sy)) return; - - dst = &gpBuffer[sx + BUFFER_WIDTH * sy]; - - if (dst < gpBufEnd && dst > gpBufStart) - *dst = col; + *out.at(sx, sy) = col; } -/** - * @brief Draw a line on the back buffer - * @param x0 Back buffer coordinate - * @param y0 Back buffer coordinate - * @param x1 Back buffer coordinate - * @param y1 Back buffer coordinate - * @param col Color index from current palette - */ void DrawLine(int x0, int y0, int x1, int y1, BYTE col) { int i, dx, dy, steps; @@ -709,14 +555,6 @@ void DrawLine(int x0, int y0, int x1, int y1, BYTE col) } } -/** - * @brief Calculate the best fit direction between two points - * @param x1 Tile coordinate - * @param y1 Tile coordinate - * @param x2 Tile coordinate - * @param y2 Tile coordinate - * @return A value from the direction enum - */ int GetDirection(int x1, int y1, int x2, int y2) { int mx, my; @@ -938,12 +776,14 @@ void Cl2ApplyTrans(BYTE *p, BYTE *ttbl, int nCel) /** * @brief Blit CL2 sprite to the given buffer - * @param pDecodeTo The output 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(BYTE *pDecodeTo, BYTE *pRLEBytes, int nDataSize, int nWidth) +static void Cl2BlitSafe(CelOutputBuffer out, int sx, int sy, BYTE *pRLEBytes, int nDataSize, int nWidth) { int w; char width; @@ -951,7 +791,7 @@ static void Cl2BlitSafe(BYTE *pDecodeTo, BYTE *pRLEBytes, int nDataSize, int nWi BYTE *src, *dst; src = pRLEBytes; - dst = pDecodeTo; + dst = out.at(sx, sy); w = nWidth; while (nDataSize) { @@ -963,7 +803,7 @@ static void Cl2BlitSafe(BYTE *pDecodeTo, BYTE *pRLEBytes, int nDataSize, int nWi width -= 65; nDataSize--; fill = *src++; - if (dst < gpBufEnd && dst > gpBufStart) { + if (dst < out.end && dst > out.begin) { w -= width; while (width) { *dst = fill; @@ -972,13 +812,13 @@ static void Cl2BlitSafe(BYTE *pDecodeTo, BYTE *pRLEBytes, int nDataSize, int nWi } if (!w) { w = nWidth; - dst -= BUFFER_WIDTH + w; + dst -= out.line_width + w; } continue; } } else { nDataSize -= width; - if (dst < gpBufEnd && dst > gpBufStart) { + if (dst < out.end && dst > out.begin) { w -= width; while (width) { *dst = *src; @@ -988,7 +828,7 @@ static void Cl2BlitSafe(BYTE *pDecodeTo, BYTE *pRLEBytes, int nDataSize, int nWi } if (!w) { w = nWidth; - dst -= BUFFER_WIDTH + w; + dst -= out.line_width + w; } continue; } else { @@ -1008,7 +848,7 @@ static void Cl2BlitSafe(BYTE *pDecodeTo, BYTE *pRLEBytes, int nDataSize, int nWi } if (!w) { w = nWidth; - dst -= BUFFER_WIDTH + w; + dst -= out.line_width + w; } } } @@ -1016,20 +856,22 @@ static void Cl2BlitSafe(BYTE *pDecodeTo, BYTE *pRLEBytes, int nDataSize, int nWi /** * @brief Blit a solid colder shape one pixel larger then the given sprite shape, to the given buffer - * @param pDecodeTo The output 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(BYTE *pDecodeTo, BYTE *pRLEBytes, int nDataSize, int nWidth, BYTE col) +static void Cl2BlitOutlineSafe(CelOutputBuffer out, int sx, int sy, BYTE *pRLEBytes, int nDataSize, int nWidth, BYTE col) { int w; char width; BYTE *src, *dst; src = pRLEBytes; - dst = pDecodeTo; + dst = out.at(sx, sy); w = nWidth; while (nDataSize) { @@ -1040,40 +882,40 @@ static void Cl2BlitOutlineSafe(BYTE *pDecodeTo, BYTE *pRLEBytes, int nDataSize, if (width > 65) { width -= 65; nDataSize--; - if (*src++ && dst < gpBufEnd && dst > gpBufStart) { + if (*src++ && dst < out.end && dst > out.begin) { w -= width; dst[-1] = col; dst[width] = col; while (width) { - dst[-BUFFER_WIDTH] = col; - dst[BUFFER_WIDTH] = col; + dst[-out.line_width] = col; + dst[out.line_width] = col; dst++; width--; } if (!w) { w = nWidth; - dst -= BUFFER_WIDTH + w; + dst -= out.line_width + w; } continue; } } else { nDataSize -= width; - if (dst < gpBufEnd && dst > gpBufStart) { + if (dst < out.end && dst > out.begin) { w -= width; while (width) { if (*src++) { dst[-1] = col; dst[1] = col; - dst[-BUFFER_WIDTH] = col; + dst[-out.line_width] = col; // BUGFIX: only set `if (dst+BUFFER_WIDTH < gpBufEnd)` - dst[BUFFER_WIDTH] = col; + dst[out.line_width] = col; } dst++; width--; } if (!w) { w = nWidth; - dst -= BUFFER_WIDTH + w; + dst -= out.line_width + w; } continue; } else { @@ -1093,7 +935,7 @@ static void Cl2BlitOutlineSafe(BYTE *pDecodeTo, BYTE *pRLEBytes, int nDataSize, } if (!w) { w = nWidth; - dst -= BUFFER_WIDTH + w; + dst -= out.line_width + w; } } } @@ -1101,13 +943,15 @@ static void Cl2BlitOutlineSafe(BYTE *pDecodeTo, BYTE *pRLEBytes, int nDataSize, /** * @brief Blit CL2 sprite, and apply lighting, to the given buffer - * @param pDecodeTo The output 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(BYTE *pDecodeTo, BYTE *pRLEBytes, int nDataSize, int nWidth, BYTE *pTable) +static void Cl2BlitLightSafe(CelOutputBuffer out, int sx, int sy, BYTE *pRLEBytes, int nDataSize, int nWidth, BYTE *pTable) { int w, spriteWidth; char width; @@ -1115,7 +959,7 @@ static void Cl2BlitLightSafe(BYTE *pDecodeTo, BYTE *pRLEBytes, int nDataSize, in BYTE *src, *dst; src = pRLEBytes; - dst = pDecodeTo; + dst = out.at(sx, sy); w = nWidth; spriteWidth = nWidth; @@ -1128,7 +972,7 @@ static void Cl2BlitLightSafe(BYTE *pDecodeTo, BYTE *pRLEBytes, int nDataSize, in width -= 65; nDataSize--; fill = pTable[*src++]; - if (dst < gpBufEnd && dst > gpBufStart) { + if (dst < out.end && dst > out.begin) { w -= width; while (width) { *dst = fill; @@ -1137,13 +981,13 @@ static void Cl2BlitLightSafe(BYTE *pDecodeTo, BYTE *pRLEBytes, int nDataSize, in } if (w == 0) { w = spriteWidth; - dst -= BUFFER_WIDTH + w; + dst -= out.line_width + w; } continue; } } else { nDataSize -= width; - if (dst < gpBufEnd && dst > gpBufStart) { + if (dst < out.end && dst > out.begin) { w -= width; while (width) { *dst = pTable[*src]; @@ -1153,7 +997,7 @@ static void Cl2BlitLightSafe(BYTE *pDecodeTo, BYTE *pRLEBytes, int nDataSize, in } if (w == 0) { w = spriteWidth; - dst -= BUFFER_WIDTH + w; + dst -= out.line_width + w; } continue; } else { @@ -1173,20 +1017,12 @@ static void Cl2BlitLightSafe(BYTE *pDecodeTo, BYTE *pRLEBytes, int nDataSize, in } if (w == 0) { w = spriteWidth; - dst -= BUFFER_WIDTH + w; + dst -= out.line_width + w; } } } } -/** - * @brief Blit CL2 sprite, to the back buffer at the given coordianates - * @param sx Back buffer coordinate - * @param sy Back buffer coordinate - * @param pCelBuff CL2 buffer - * @param nCel CL2 frame number - * @param nWidth Width of sprite - */ void Cl2Draw(int sx, int sy, BYTE *pCelBuff, int nCel, int nWidth) { BYTE *pRLEBytes; @@ -1198,11 +1034,7 @@ void Cl2Draw(int sx, int sy, BYTE *pCelBuff, int nCel, int nWidth) pRLEBytes = CelGetFrameClipped(pCelBuff, nCel, &nDataSize); - Cl2BlitSafe( - &gpBuffer[sx + BUFFER_WIDTH * sy], - pRLEBytes, - nDataSize, - nWidth); + Cl2BlitSafe(GlobalBackBuffer(), sx, sy, pRLEBytes, nDataSize, nWidth); } /** * @brief Blit a solid colder shape one pixel larger then the given sprite shape, to the back buffer at the given coordianates @@ -1224,36 +1056,21 @@ void Cl2DrawOutline(BYTE col, int sx, int sy, BYTE *pCelBuff, int nCel, int nWid pRLEBytes = CelGetFrameClipped(pCelBuff, nCel, &nDataSize); - gpBufEnd -= BUFFER_WIDTH; - Cl2BlitOutlineSafe( - &gpBuffer[sx + BUFFER_WIDTH * sy], - pRLEBytes, - nDataSize, - nWidth, - col); - gpBufEnd += BUFFER_WIDTH; + CelOutputBuffer out = GlobalBackBuffer(); + out.end -= out.line_width; + Cl2BlitOutlineSafe(out, sx, sy, pRLEBytes, nDataSize, nWidth, col); } -/** - * @brief Blit CL2 sprite, and apply a given lighting, to the back buffer at the given coordianates - * @param sx Back buffer coordinate - * @param sy Back buffer coordinate - * @param pCelBuff CL2 buffer - * @param nCel CL2 frame number - * @param nWidth Width of sprite - * @param light Light shade to use - */ void Cl2DrawLightTbl(int sx, int sy, BYTE *pCelBuff, int nCel, int nWidth, char light) { int nDataSize, idx; - BYTE *pRLEBytes, *pDecodeTo; + BYTE *pRLEBytes; assert(gpBuffer != NULL); assert(pCelBuff != NULL); assert(nCel > 0); pRLEBytes = CelGetFrameClipped(pCelBuff, nCel, &nDataSize); - pDecodeTo = &gpBuffer[sx + BUFFER_WIDTH * sy]; idx = light4flag ? 1024 : 4096; if (light == 2) @@ -1261,38 +1078,24 @@ void Cl2DrawLightTbl(int sx, int sy, BYTE *pCelBuff, int nCel, int nWidth, char if (light >= 4) idx += (light - 1) << 8; - Cl2BlitLightSafe( - pDecodeTo, - pRLEBytes, - nDataSize, - nWidth, - &pLightTbl[idx]); + Cl2BlitLightSafe(GlobalBackBuffer(), sx, sy, pRLEBytes, nDataSize, nWidth, &pLightTbl[idx]); } -/** - * @brief Blit CL2 sprite, and apply lighting, to the back buffer at the given coordinates - * @param sx Back buffer coordinate - * @param sy Back buffer coordinate - * @param pCelBuff CL2 buffer - * @param nCel CL2 frame number - * @param nWidth Width of sprite - */ void Cl2DrawLight(int sx, int sy, BYTE *pCelBuff, int nCel, int nWidth) { int nDataSize; - BYTE *pRLEBytes, *pDecodeTo; + BYTE *pRLEBytes; assert(gpBuffer != NULL); assert(pCelBuff != NULL); assert(nCel > 0); pRLEBytes = CelGetFrameClipped(pCelBuff, nCel, &nDataSize); - pDecodeTo = &gpBuffer[sx + BUFFER_WIDTH * sy]; if (light_table_index) - Cl2BlitLightSafe(pDecodeTo, pRLEBytes, nDataSize, nWidth, &pLightTbl[light_table_index * 256]); + Cl2BlitLightSafe(GlobalBackBuffer(), sx, sy, pRLEBytes, nDataSize, nWidth, &pLightTbl[light_table_index * 256]); else - Cl2BlitSafe(pDecodeTo, pRLEBytes, nDataSize, nWidth); + Cl2BlitSafe(GlobalBackBuffer(), sx, sy, pRLEBytes, nDataSize, nWidth); } /** diff --git a/Source/engine.h b/Source/engine.h index 1c8e2df71..05b70dcaf 100644 --- a/Source/engine.h +++ b/Source/engine.h @@ -13,6 +13,10 @@ #ifndef __ENGINE_H__ #define __ENGINE_H__ +#ifdef __cplusplus +#include +#endif + DEVILUTION_BEGIN_NAMESPACE #ifdef __cplusplus @@ -49,22 +53,306 @@ inline BYTE *CelGetFrameClipped(BYTE *pCelBuff, int nCel, int *nDataSize) return pRLEBytes + nDataStart; } -void CelDraw(int sx, int sy, BYTE *pCelBuff, int nCel, int nWidth); -void CelBlitFrame(BYTE *pBuff, BYTE *pCelBuff, int nCel, int nWidth); -void CelClippedDraw(int sx, int sy, BYTE *pCelBuff, int nCel, int nWidth); -void CelDrawLight(int sx, int sy, BYTE *pCelBuff, int nCel, int nWidth, BYTE *tbl); -void CelClippedDrawLight(int sx, int sy, BYTE *pCelBuff, int nCel, int nWidth); -void CelClippedBlitLightTrans(BYTE *pBuff, BYTE *pCelBuff, int nCel, int nWidth); -void CelDrawLightRed(int sx, int sy, BYTE *pCelBuff, int nCel, int nWidth, char light); -void CelBlitSafe(BYTE *pDecodeTo, BYTE *pRLEBytes, int nDataSize, int nWidth); -void CelClippedDrawSafe(int sx, int sy, BYTE *pCelBuff, int nCel, int nWidth); -void CelBlitLightSafe(BYTE *pDecodeTo, BYTE *pRLEBytes, int nDataSize, int nWidth, BYTE *tbl); -void CelDrawLightRedSafe(int sx, int sy, BYTE *pCelBuff, int nCel, int nWidth, char light); -void CelBlitWidth(BYTE *pBuff, int x, int y, int wdt, BYTE *pCelBuff, int nCel, int nWidth); -void CelBlitOutline(BYTE col, int sx, int sy, BYTE *pCelBuff, int nCel, int nWidth); -void ENG_set_pixel(int sx, int sy, BYTE col); +struct CelOutputBuffer { + BYTE *begin; + BYTE *end; + int line_width; + +#ifdef __cplusplus + BYTE *at(int x, int y) const + { + return &begin[x + line_width * y]; + } + + bool in_bounds(int x, int y) const + { + return x >= 0 && y >= 0 && begin + x + line_width * y < end; + } + + CelOutputBuffer subregion(int x0, int y0, int x1, int y1) const + { + return CelOutputBuffer { at(x0, y0), std::min(at(x1, y1), end), line_width }; + } +#endif +}; + +inline CelOutputBuffer GlobalBackBuffer() +{ + extern BYTE *gpBuffer; + extern BYTE *gpBufEnd; + return CelOutputBuffer { gpBuffer, gpBufEnd, BUFFER_WIDTH }; +} + +/** + * @brief Blit CEL sprite to the back buffer at the given coordinates + * @param out Target buffer + * @param sx Target buffer coordinate + * @param sy Target buffer coordinate + * @param pCelBuff Cel data + * @param nCel CEL frame number + * @param nWidth Width of sprite + */ +void CelDrawTo(CelOutputBuffer out, int sx, int sy, BYTE *pCelBuff, int nCel, int nWidth); +inline void CelDraw(int sx, int sy, BYTE *pCelBuff, int nCel, int nWidth) +{ + CelDrawTo(GlobalBackBuffer(), sx, sy, pCelBuff, nCel, nWidth); +} + +/** + * @briefBlit CEL sprite to the given buffer, does not perform bounds-checking. + * @param out Target buffer + * @param x Cordinate in the target buffer + * @param y Cordinate in the target buffer + * @param pCelBuff Cel data + * @param nCel CEL frame number + * @param nWidth Width of cel + */ +void CelDrawUnsafeTo(CelOutputBuffer out, int x, int y, BYTE *pCelBuff, int nCel, int nWidth); + +/** + * @brief Same as CelDrawTo but with the option to skip parts of the top and bottom of the sprite + * @param out Target buffer + * @param sx Target buffer coordinate + * @param sy Target buffer coordinate + * @param pCelBuff Cel data + * @param nCel CEL frame number + * @param nWidth Width of sprite + */ +void CelClippedDrawTo(CelOutputBuffer out, int sx, int sy, BYTE *pCelBuff, int nCel, int nWidth); +inline void CelClippedDraw(int sx, int sy, BYTE *pCelBuff, int nCel, int nWidth) +{ + CelClippedDrawTo(GlobalBackBuffer(), sx, sy, pCelBuff, nCel, nWidth); +} + +/** + * @brief Blit CEL sprite, and apply lighting, to the back buffer at the given coordinates + * @param out Target buffer + * @param sx Target buffer coordinate + * @param sy Target buffer coordinate + * @param pCelBuff Cel data + * @param nCel CEL frame number + * @param nWidth Width of sprite + */ +void CelDrawLightTo(CelOutputBuffer out, int sx, int sy, BYTE *pCelBuff, int nCel, int nWidth, BYTE *tbl); +inline void CelDrawLight(int sx, int sy, BYTE *pCelBuff, int nCel, int nWidth, BYTE *tbl) +{ + CelDrawLightTo(GlobalBackBuffer(), sx, sy, pCelBuff, nCel, nWidth, tbl); +} + +/** + * @brief Same as CelDrawLightTo but with the option to skip parts of the top and bottom of the sprite + * @param out Target buffer + * @param sx Target buffer coordinate + * @param sy Target buffer coordinate + * @param pCelBuff Cel data + * @param nCel CEL frame number + * @param nWidth Width of sprite + */ +void CelClippedDrawLightTo(CelOutputBuffer out, int sx, int sy, BYTE *pCelBuff, int nCel, int nWidth); +inline void CelClippedDrawLight(int sx, int sy, BYTE *pCelBuff, int nCel, int nWidth) +{ + return CelClippedDrawLightTo(GlobalBackBuffer(), sx, sy, pCelBuff, nCel, nWidth); +} + +/** + * @brief Same as CelBlitLightTransSafeTo + * @param out Target buffer + * @param sx Target buffer coordinate + * @param sy Target buffer coordinate + * @param pCelBuff Cel data + * @param nCel CEL frame number + * @param nWidth Width of sprite + */ +void CelClippedBlitLightTransTo(CelOutputBuffer out, int sx, int sy, BYTE *pCelBuff, int nCel, int nWidth); +inline void CelClippedBlitLightTrans(int sx, int sy, BYTE *pCelBuff, int nCel, int nWidth) +{ + return CelClippedBlitLightTransTo(GlobalBackBuffer(), sx, sy, pCelBuff, nCel, nWidth); +} + +/** + * @brief Blit CEL sprite, and apply lighting, to the back buffer at the given coordinates, translated to a red hue + * @param out Target buffer + * @param sx Target buffer coordinate + * @param sy Target buffer coordinate + * @param pCelBuff Cel data + * @param nCel CEL frame number + * @param nWidth Width of sprite + * @param light Light shade to use + */ +void CelDrawLightRedTo(CelOutputBuffer out, int sx, int sy, BYTE *pCelBuff, int nCel, int nWidth, char light); +inline void CelDrawLightRed(int sx, int sy, BYTE *pCelBuff, int nCel, int nWidth, char light) +{ + return CelDrawLightRedTo(GlobalBackBuffer(), sx, sy, pCelBuff, nCel, nWidth, light); +} + +/** + * @brief Blit CEL sprite to the given buffer, checks for drawing outside the buffer. + * @param out Target buffer + * @param sx Target buffer coordinate + * @param sy Target buffer coordinate + * @param pRLEBytes CEL pixel stream (run-length encoded) + * @param nDataSize Size of CEL in bytes + * @param nWidth Width of sprite + */ +void CelBlitSafeTo(CelOutputBuffer out, int sx, int sy, BYTE *pRLEBytes, int nDataSize, int nWidth); +inline void CelBlitSafe(int sx, int sy, BYTE *pRLEBytes, int nDataSize, int nWidth) +{ + return CelBlitSafeTo(GlobalBackBuffer(), sx, sy, pRLEBytes, nDataSize, nWidth); +} + +/** + * @brief Same as CelClippedDrawTo but checks for drawing outside the buffer + * @param out Target buffer + * @param sx Target buffer coordinate + * @param sy Target buffer coordinate + * @param pCelBuff Cel data + * @param nCel CEL frame number + * @param nWidth Width of sprite + */ +void CelClippedDrawSafeTo(CelOutputBuffer out, int sx, int sy, BYTE *pCelBuff, int nCel, int nWidth); +inline void CelClippedDrawSafe(int sx, int sy, BYTE *pCelBuff, int nCel, int nWidth) +{ + return CelClippedDrawSafeTo(GlobalBackBuffer(), sx, sy, pCelBuff, nCel, nWidth); +} + +/** + * @brief Blit CEL sprite, and apply lighting, to the given buffer, checks for drawing outside the buffer + * @param out Target buffer + * @param sx Target buffer coordinate + * @param sy Target buffer coordinate + * @param pRLEBytes CEL pixel stream (run-length encoded) + * @param nDataSize Size of CEL in bytes + * @param nWidth Width of sprite + * @param tbl Palette translation table + */ +void CelBlitLightSafeTo(CelOutputBuffer out, int sx, int sy, BYTE *pRLEBytes, int nDataSize, int nWidth, BYTE *tbl); +inline void CelBlitLightSafe(int sx, int sy, BYTE *pRLEBytes, int nDataSize, int nWidth, BYTE *tbl) +{ + return CelBlitLightSafeTo(GlobalBackBuffer(), sx, sy, pRLEBytes, nDataSize, nWidth, tbl); +} + +/** + * @brief Same as CelBlitLightSafeTo but with stippled transparancy applied + * @param out Target buffer + * @param sx Target buffer coordinate + * @param sy Target buffer coordinate + * @param pRLEBytes CEL pixel stream (run-length encoded) + * @param nDataSize Size of CEL in bytes + * @param nWidth Width of sprite + */ +void CelBlitLightTransSafeTo(CelOutputBuffer out, int sx, int sy, BYTE *pRLEBytes, int nDataSize, int nWidth); +inline void CelBlitLightTransSafe(int sx, int sy, BYTE *pRLEBytes, int nDataSize, int nWidth) +{ + return CelBlitLightTransSafeTo(GlobalBackBuffer(), sx, sy, pRLEBytes, nDataSize, nWidth); +} + +/** + * @brief Same as CelDrawLightRedTo but checks for drawing outside the buffer + * @param out Target buffer + * @param sx Target buffer coordinate + * @param sy Target buffer coordinate + * @param pCelBuff Cel data + * @param nCel CEL frame number + * @param nWidth Width of cel + * @param light Light shade to use + */ +void CelDrawLightRedSafeTo(CelOutputBuffer out, int sx, int sy, BYTE *pCelBuff, int nCel, int nWidth, char light); +inline void CelDrawLightRedSafe(int sx, int sy, BYTE *pCelBuff, int nCel, int nWidth, char light) +{ + return CelDrawLightRedSafeTo(GlobalBackBuffer(), sx, sy, pCelBuff, nCel, nWidth, light); +} + +/** + * @brief Blit a solid colder shape one pixel larger then the given sprite shape, to the target buffer at the given coordianates + * @param out Target buffer + * @param col Color index from current palette + * @param sx Target buffer coordinate + * @param sy Target buffer coordinate + * @param pCelBuff CEL buffer + * @param nCel CEL frame number + * @param nWidth Width of sprite + */ +void CelBlitOutlineTo(CelOutputBuffer out, BYTE col, int sx, int sy, BYTE *pCelBuff, int nCel, int nWidth); +inline void CelBlitOutline(BYTE col, int sx, int sy, BYTE *pCelBuff, int nCel, int nWidth) +{ + return CelBlitOutlineTo(GlobalBackBuffer(), col, sx, sy, pCelBuff, nCel, nWidth); +} + +/** + * @brief Set the value of a single pixel in the back buffer, checks bounds + * @param out Target buffer + * @param sx Target buffer coordinate + * @param sy Target buffer coordinate + * @param col Color index from current palette + */ +void SetPixel(CelOutputBuffer out, int sx, int sy, BYTE col); +inline void ENG_set_pixel(int sx, int sy, BYTE col) +{ + return SetPixel(GlobalBackBuffer(), sx, sy, col); +} + +/** + * @brief Blit CL2 sprite, to the back buffer at the given coordianates + * @param sx Back buffer coordinate + * @param sy Back buffer coordinate + * @param pCelBuff CL2 buffer + * @param nCel CL2 frame number + * @param nWidth Width of sprite + */ +void Cl2Draw(int sx, int sy, BYTE *pCelBuff, int nCel, int nWidth); + +/** + * @brief Blit a solid colder shape one pixel larger then the given sprite shape, to the back buffer at the given coordianates + * @param col Color index from current palette + * @param sx Back buffer coordinate + * @param sy Back buffer coordinate + * @param pCelBuff CL2 buffer + * @param nCel CL2 frame number + * @param nWidth Width of sprite + */ +void Cl2DrawOutline(BYTE col, int sx, int sy, BYTE *pCelBuff, int nCel, int nWidth); + +/** + * @brief Blit CL2 sprite, and apply a given lighting, to the back buffer at the given coordianates + * @param sx Back buffer coordinate + * @param sy Back buffer coordinate + * @param pCelBuff CL2 buffer + * @param nCel CL2 frame number + * @param nWidth Width of sprite + * @param light Light shade to use + */ +void Cl2DrawLightTbl(int sx, int sy, BYTE *pCelBuff, int nCel, int nWidth, char light); + +/** + * @brief Blit CL2 sprite, and apply lighting, to the back buffer at the given coordinates + * @param sx Back buffer coordinate + * @param sy Back buffer coordinate + * @param pCelBuff CL2 buffer + * @param nCel CL2 frame number + * @param nWidth Width of sprite + */ +void Cl2DrawLight(int sx, int sy, BYTE *pCelBuff, int nCel, int nWidth); + +/** + * @brief Draw a line on the back buffer + * @param x0 Back buffer coordinate + * @param y0 Back buffer coordinate + * @param x1 Back buffer coordinate + * @param y1 Back buffer coordinate + * @param col Color index from current palette + */ void DrawLine(int x0, int y0, int x1, int y1, BYTE col); + +/** + * @brief Calculate the best fit direction between two points + * @param x1 Tile coordinate + * @param y1 Tile coordinate + * @param x2 Tile coordinate + * @param y2 Tile coordinate + * @return A value from the direction enum + */ int GetDirection(int x1, int y1, int x2, int y2); + void SetRndSeed(int s); int AdvanceRndSeed(); int GetRndSeed(); @@ -74,10 +362,6 @@ void mem_free_dbg(void *p); BYTE *LoadFileInMem(const char *pszName, DWORD *pdwFileLen); DWORD LoadFileWithMem(const char *pszName, BYTE *p); void Cl2ApplyTrans(BYTE *p, BYTE *ttbl, int nCel); -void Cl2Draw(int sx, int sy, BYTE *pCelBuff, int nCel, int nWidth); -void Cl2DrawOutline(BYTE col, int sx, int sy, BYTE *pCelBuff, int nCel, int nWidth); -void Cl2DrawLightTbl(int sx, int sy, BYTE *pCelBuff, int nCel, int nWidth, char light); -void Cl2DrawLight(int sx, int sy, BYTE *pCelBuff, int nCel, int nWidth); void PlayInGameMovie(const char *pszMovie); #ifdef __cplusplus diff --git a/Source/inv.cpp b/Source/inv.cpp index d43f78a18..8b82f8590 100644 --- a/Source/inv.cpp +++ b/Source/inv.cpp @@ -365,13 +365,12 @@ void DrawInv() light_table_index = 0; cel_transparency_active = TRUE; - pBuff = frame_width == INV_SLOT_SIZE_PX - ? &gpBuffer[SCREENXY(RIGHT_PANEL_X + 197, SCREEN_Y)] - : &gpBuffer[SCREENXY(RIGHT_PANEL_X + 183, SCREEN_Y)]; + const int dst_x = SCREEN_X + RIGHT_PANEL_X + (frame_width == INV_SLOT_SIZE_PX ? 197 : 183); + const int dst_y = SCREEN_Y; if (frame <= 179) { - CelClippedBlitLightTrans(pBuff, pCursCels, frame, frame_width); + CelClippedBlitLightTrans(dst_x, dst_y, pCursCels, frame, frame_width); } else { - CelClippedBlitLightTrans(pBuff, pCursCels2, frame - 179, frame_width); + CelClippedBlitLightTrans(dst_x, dst_y, pCursCels2, frame - 179, frame_width); } cel_transparency_active = FALSE; diff --git a/Source/minitext.cpp b/Source/minitext.cpp index 558e4c63e..979f241a3 100644 --- a/Source/minitext.cpp +++ b/Source/minitext.cpp @@ -144,17 +144,10 @@ int CalcTextSpeed(int nSFX) */ void PrintQTextChr(int sx, int sy, Uint8 *pCelBuff, int nCel) { - Uint8 *pStart, *pEnd; - - assert(gpBuffer); - pStart = gpBufStart; - gpBufStart = &gpBuffer[BUFFER_WIDTH * (49 + SCREEN_Y + UI_OFFSET_Y)]; - pEnd = gpBufEnd; - gpBufEnd = &gpBuffer[BUFFER_WIDTH * (309 + SCREEN_Y + UI_OFFSET_Y)]; - CelDraw(sx, sy, pCelBuff, nCel, 22); - - gpBufStart = pStart; - gpBufEnd = pEnd; + CelOutputBuffer buf = GlobalBackBuffer(); + const int start_y = 49 + SCREEN_Y + UI_OFFSET_Y; + buf = buf.subregion(0, start_y, buf.line_width, 309 + SCREEN_Y + UI_OFFSET_Y); + CelDrawTo(buf, sx, sy - start_y, pCelBuff, nCel, 22); } /** diff --git a/Source/scrollrt.cpp b/Source/scrollrt.cpp index 5657a6bad..5ce9712ee 100644 --- a/Source/scrollrt.cpp +++ b/Source/scrollrt.cpp @@ -815,7 +815,7 @@ static void scrollrt_draw_dungeon(int sx, int sy, int dx, int dy) cel_transparency_active = 0; // Turn transparency off here for debugging } #endif - CelClippedBlitLightTrans(&gpBuffer[dx + BUFFER_WIDTH * dy], pSpecialCels, bArch, 64); + CelClippedBlitLightTrans(dx, dy, pSpecialCels, bArch, 64); #ifdef _DEBUG if (GetAsyncKeyState(DVL_VK_MENU) & 0x8000) { cel_transparency_active = TransList[bMap]; // Turn transparency back to its normal state @@ -829,7 +829,7 @@ static void scrollrt_draw_dungeon(int sx, int sy, int dx, int dy) if (sx > 0 && sy > 0 && dy > TILE_HEIGHT + SCREEN_Y) { bArch = dSpecial[sx - 1][sy - 1]; if (bArch != 0) { - CelBlitFrame(&gpBuffer[dx + BUFFER_WIDTH * (dy - TILE_HEIGHT)], pSpecialCels, bArch, 64); + CelDraw(dx, dy - TILE_HEIGHT, pSpecialCels, bArch, 64); } } }