c++11 refactor

This commit is contained in:
2024-04-13 14:36:42 +10:00
parent 54d6226e4a
commit 6532465324

View File

@@ -4,82 +4,70 @@
#else #else
# include <SDL2_image/SDL_image.h> # include <SDL2_image/SDL_image.h>
#endif #endif
#include <cstdio>
#include <cmath> #include <cmath>
#include <memory.h> #include <cstdint>
#include <cstdlib>
#include <cstdio>
#include <array>
#include <utility>
#define CHARWIDTH 8
#define CHARHEIGHT 16 constexpr int cellWidth = 8, cellHeight = 16;
enum class EColour : unsigned char enum class EColour : unsigned char
{ {
BLACK, BLACK, BLUE, GREEN, CYAN, RED, MEGENTA, BROWN, LTGREY,
BLUE, DKGREY, LTBLUE, LTGREEN, LTCYAN, LTRED, LTMEGENTA, YELLOW, WHITE
GREEN,
CYAN,
RED,
MEGENTA,
BROWN,
LTGREY,
DKGREY,
LTBLUE,
LTGREEN,
LTCYAN,
LTRED,
LTMEGENTA,
YELLOW,
WHITE
}; };
SDL_Colour g_aColourTable[] = static constexpr std::array<SDL_Colour, 16> colourTable =
{ {
{ 0x00, 0x00, 0x00, 0xFF }, // BLACK /* EColour::BLACK */ SDL_Colour{ 0x00, 0x00, 0x00, 0xFF },
{ 0x00, 0x00, 0xAA, 0xFF }, // BLUE /* EColour::BLUE */ SDL_Colour{ 0x00, 0x00, 0xAA, 0xFF },
{ 0x00, 0xAA, 0x00, 0xFF }, // GREEN /* EColour::GREEN */ SDL_Colour{ 0x00, 0xAA, 0x00, 0xFF },
{ 0x00, 0xAA, 0xAA, 0xFF }, // CYAN /* EColour::CYAN */ SDL_Colour{ 0x00, 0xAA, 0xAA, 0xFF },
{ 0xAA, 0x00, 0x00, 0xFF }, // RED /* EColour::RED */ SDL_Colour{ 0xAA, 0x00, 0x00, 0xFF },
{ 0xAA, 0x00, 0xAA, 0xFF }, // MEGENTA /* EColour::MEGENTA */ SDL_Colour{ 0xAA, 0x00, 0xAA, 0xFF },
{ 0xAA, 0x55, 0x00, 0xFF }, // BROWN /* EColour::BROWN */ SDL_Colour{ 0xAA, 0x55, 0x00, 0xFF },
{ 0xAA, 0xAA, 0xAA, 0xFF }, // LTGREY /* EColour::LTGREY */ SDL_Colour{ 0xAA, 0xAA, 0xAA, 0xFF },
{ 0x55, 0x55, 0x55, 0xFF }, // DKGREY /* EColour::DKGREY */ SDL_Colour{ 0x55, 0x55, 0x55, 0xFF },
{ 0x55, 0x55, 0xFF, 0xFF }, // BLUE /* EColour::LTBLUE */ SDL_Colour{ 0x55, 0x55, 0xFF, 0xFF },
{ 0x55, 0xFF, 0x55, 0xFF }, // GREEN /* EColour::LTGREEN */ SDL_Colour{ 0x55, 0xFF, 0x55, 0xFF },
{ 0x55, 0xFF, 0xFF, 0xFF }, // CYAN /* EColour::LTCYAN */ SDL_Colour{ 0x55, 0xFF, 0xFF, 0xFF },
{ 0xFF, 0x55, 0x55, 0xFF }, // RED /* EColour::LTRED */ SDL_Colour{ 0xFF, 0x55, 0x55, 0xFF },
{ 0xFF, 0x55, 0xFF, 0xFF }, // MEGENTA /* EColour::LTMEGENTA */ SDL_Colour{ 0xFF, 0x55, 0xFF, 0xFF },
{ 0xFF, 0xFF, 0x55, 0xFF }, // YELLOW /* EColour::YELLOW */ SDL_Colour{ 0xFF, 0xFF, 0x55, 0xFF },
{ 0xFF, 0xFF, 0xFF, 0xFF } // WHITE /* EColour::WHITE */ SDL_Colour{ 0xFF, 0xFF, 0xFF, 0xFF }
}; };
struct SChar struct Cell
{ {
unsigned char character; unsigned char character;
EColour bgColour; EColour bgColour, fgColour;
EColour fgColour;
bool blinking; bool blinking;
}; };
inline int clampi(int a_iVal, int a_iMin, int a_iMax) template <typename T> constexpr T clamp(T x, T min, T max)
{ {
return (a_iVal < a_iMin) ? a_iMin : (a_iVal > a_iMax) ? a_iMax : a_iVal; return x < min ? min : (x > max ? max : x);
} }
static Uint32 TimerCallback(Uint32 a_uiInterval, void* a_pParam) static Uint32 timerCallback(Uint32 interval, void* param)
{ {
SDL_Event event; SDL_Event event =
SDL_UserEvent userEvent; {
.type = SDL_USEREVENT,
userEvent.type = SDL_USEREVENT; .user =
userEvent.code = 0; {
userEvent.data1 = nullptr; .type = SDL_USEREVENT,
userEvent.data2 = nullptr; .timestamp = SDL_GetTicks(),
.code = 0,
event.type = SDL_USEREVENT; .data1 = nullptr,
event.user = userEvent; .data2 = nullptr
}
};
SDL_PushEvent(&event); SDL_PushEvent(&event);
return interval;
return a_uiInterval;
} }
int main(int argc, char** argv) int main(int argc, char** argv)
@@ -95,83 +83,86 @@ int main(int argc, char** argv)
return -1; return -1;
} }
SDL_Window* pWindow = nullptr; SDL_Window* window = nullptr;
SDL_Renderer* pRenderer = nullptr; SDL_Renderer* renderer = nullptr;
if (SDL_CreateWindowAndRenderer(640, 400, 0, &pWindow, &pRenderer) < 0) if (SDL_CreateWindowAndRenderer(640, 400, 0, &window, &renderer) < 0)
{ {
IMG_Quit(); IMG_Quit();
SDL_Quit(); SDL_Quit();
return -1; return -1;
} }
SDL_SetWindowTitle(pWindow, "EnDOOMed"); SDL_SetWindowTitle(window, "EnDOOMed");
SDL_Texture* pCodepage = IMG_LoadTexture(pRenderer, "codepage.png"); SDL_Texture* codepage = IMG_LoadTexture(renderer, "codepage.png");
if (pCodepage == nullptr) if (codepage == nullptr)
{ {
SDL_DestroyRenderer(pRenderer); SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(pWindow); SDL_DestroyWindow(window);
IMG_Quit(); IMG_Quit();
SDL_Quit(); SDL_Quit();
return -1; return -1;
} }
SChar aDisplay[2000]; std::array<Cell, 2000> display;
memset(aDisplay, 0, sizeof(aDisplay)); std::memset(display.data(), 0, sizeof(Cell) * display.size());
FILE* pFile = fopen("ENDOOM.bin", "rb"); FILE* file = fopen("ENDOOM.bin", "rb");
if (pFile == nullptr) if (file == nullptr)
{ {
SDL_DestroyTexture(pCodepage); SDL_DestroyTexture(codepage);
SDL_DestroyRenderer(pRenderer); SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(pWindow); SDL_DestroyWindow(window);
IMG_Quit(); IMG_Quit();
SDL_Quit(); SDL_Quit();
return -1; return -1;
} }
for (int i = 0; i < 2000; ++i) for (Cell& currentCharacter : display)
{ {
SChar& currentCharacter = aDisplay[i]; unsigned char character[2];
fread(character, sizeof(unsigned char), 2, file);
unsigned char ucSpecial; currentCharacter =
fread(&currentCharacter.character, sizeof(unsigned char), 1, pFile); {
fread(&ucSpecial, sizeof(unsigned char), 1, pFile); .character = character[0],
.bgColour = EColour((character[1] & 0x70) >> 4),
currentCharacter.bgColour = EColour((ucSpecial & 112) >> 4); .fgColour = EColour( character[1] & 0x0F),
currentCharacter.fgColour = EColour(ucSpecial & 15); .blinking = (character[1] & (0x80 > 1)) ? true : false
currentCharacter.blinking = (ucSpecial & 128 > 0) ? true : false; };
} }
SDL_AddTimer(400, TimerCallback, nullptr); SDL_AddTimer(400, timerCallback, nullptr);
SChar leftBrush; Cell leftBrush =
leftBrush.character = 219;
leftBrush.bgColour = EColour::BLACK;
leftBrush.fgColour = EColour::LTGREY;
leftBrush.blinking = false;
SChar rightBrush;
rightBrush.character = ' ';
rightBrush.bgColour = EColour::BLACK;
rightBrush.fgColour = EColour::LTGREY;
rightBrush.blinking = false;
bool bMouseLeft = false, bMouseRight = false;
int iMousePrevX = 0, iMousePrevY = 0;
int iMouseX = 0, iMouseY = 0;
bool bMouseInWindow = false;
bool bValidRender = false;
bool bBlinkState = true;
bool bRunning = true;
SDL_Event event;
while (bRunning)
{ {
iMousePrevX = iMouseX; .character = 219,
iMousePrevY = iMouseY; .bgColour = EColour::BLACK,
.fgColour = EColour::LTGREY,
.blinking = false
};
Cell rightBrush =
{
.character = ' ',
.bgColour = EColour::BLACK,
.fgColour = EColour::LTGREY,
.blinking = false
};
SDL_PumpEvents(); bool mouseLeft = false, mouseRight = false;
int mousePrevX = 0, mousePrevY = 0;
int mouseX = 0, mouseY = 0;
bool mouseInWindow = false;
bool running = true, damage = true;
bool blinkState = true;
do
{
mousePrevX = mouseX;
mousePrevY = mouseY;
SDL_Event event;
if (SDL_WaitEvent(&event)) if (SDL_WaitEvent(&event))
{ {
do do
@@ -179,44 +170,46 @@ int main(int argc, char** argv)
switch (event.type) switch (event.type)
{ {
case SDL_QUIT: case SDL_QUIT:
bRunning = false; running = false;
break; break;
case SDL_USEREVENT: case SDL_USEREVENT:
bBlinkState = !bBlinkState; blinkState = !blinkState;
bValidRender = false; damage = true;
break; break;
case SDL_MOUSEBUTTONDOWN: case SDL_MOUSEBUTTONDOWN:
if (event.button.button == SDL_BUTTON_LEFT) switch (event.button.button)
{ {
bMouseLeft = true; case SDL_BUTTON_LEFT:
} mouseLeft = true;
else if (event.button.button == SDL_BUTTON_RIGHT) break;
{ case SDL_BUTTON_RIGHT:
bMouseRight = true; mouseRight = true;
break;
} }
break; break;
case SDL_MOUSEBUTTONUP: case SDL_MOUSEBUTTONUP:
if (event.button.button == SDL_BUTTON_LEFT) switch (event.button.button)
{ {
bMouseLeft = false; case SDL_BUTTON_LEFT:
} mouseLeft = false;
else if (event.button.button == SDL_BUTTON_RIGHT) break;
{ case SDL_BUTTON_RIGHT:
bMouseRight = false; mouseRight = false;
break;
} }
break; break;
case SDL_MOUSEMOTION: case SDL_MOUSEMOTION:
iMouseX = event.motion.x; mouseX = event.motion.x;
iMouseY = event.motion.y; mouseY = event.motion.y;
break; break;
case SDL_WINDOWEVENT: case SDL_WINDOWEVENT:
switch (event.window.event) switch (event.window.event)
{ {
case SDL_WINDOWEVENT_LEAVE: case SDL_WINDOWEVENT_LEAVE:
bMouseInWindow = false; mouseInWindow = false;
break; break;
case SDL_WINDOWEVENT_ENTER: case SDL_WINDOWEVENT_ENTER:
bMouseInWindow = true; mouseInWindow = true;
break; break;
}; };
break; break;
@@ -225,142 +218,105 @@ int main(int argc, char** argv)
while (SDL_PollEvent(&event) > 0); while (SDL_PollEvent(&event) > 0);
} }
if (bMouseInWindow && (bMouseLeft || bMouseRight)) if (mouseInWindow && (mouseLeft || mouseRight))
{ {
int iFromX = clampi(iMouseX / CHARWIDTH, 0, 79); int fromX = clamp(mouseX / cellWidth, 0, 79);
int iFromY = clampi(iMouseY / CHARHEIGHT, 0, 24); int fromY = clamp(mouseY / cellHeight, 0, 24);
int iToX = clampi(iMousePrevX / CHARWIDTH, 0, 79); int toX = clamp(mousePrevX / cellWidth, 0, 79);
int iToY = clampi(iMousePrevY / CHARHEIGHT, 0, 24); int toY = clamp(mousePrevY / cellHeight, 0, 24);
SChar* srcChar = nullptr; auto srcChar = mouseLeft ? leftBrush : rightBrush;
if (bMouseLeft) if (toX == fromX && toY == fromY)
{ {
srcChar = &leftBrush; display[toX + toY * 80] = srcChar;
}
else if (bMouseRight)
{
srcChar = &rightBrush;
}
if (iToX == iFromX && iToY == iFromY)
{
SChar& dstChar = aDisplay[iToX + iToY * 80];
dstChar.blinking = srcChar->blinking;
dstChar.bgColour = srcChar->bgColour;
dstChar.fgColour = srcChar->fgColour;
dstChar.character = srcChar->character;
} }
else else
{ {
int iTemp; bool steep = std::abs(toY - fromY) > std::abs(toX - fromX);
bool bSteep = labs(iToY - iFromY) > labs(iToX - iFromX); if (steep)
if (bSteep)
{ {
iTemp = iFromY; std::swap(fromY, fromX);
iFromY = iFromX; std::swap(toY, toX);
iFromX = iTemp;
iTemp = iToY;
iToY = iToX;
iToX = iTemp;
} }
if (iFromX > iToX) if (fromX > toX)
{ {
iTemp = iToX; std::swap(toX, fromX);
iToX = iFromX; std::swap(toY, fromY);
iFromX = iTemp;
iTemp = iToY;
iToY = iFromY;
iFromY = iTemp;
} }
int iDeltaX = iToX - iFromX; int deltaX = toX - fromX;
int iDeltaY = labs(iToY - iFromY); int deltaY = std::abs(toY - fromY);
int iError = iDeltaX / 2; int error = deltaX / 2;
int iY = iFromY; int y = fromY;
int iYStep = (iFromY < iToY) ? 1 : -1; int yStep = (fromY < toY) ? 1 : -1;
for (int iX = iFromX; iX <= iToX; ++iX) for (int x = fromX; x <= toX; ++x)
{ {
if (bSteep) int idx = steep
{ ? y + x * 80
SChar& dstChar = aDisplay[iY + iX * 80]; : x + y * 80;
dstChar.blinking = srcChar->blinking; display[idx] = srcChar;
dstChar.bgColour = srcChar->bgColour;
dstChar.fgColour = srcChar->fgColour;
dstChar.character = srcChar->character;
}
else
{
SChar& dstChar = aDisplay[iX + iY * 80];
dstChar.blinking = srcChar->blinking;
dstChar.bgColour = srcChar->bgColour;
dstChar.fgColour = srcChar->fgColour;
dstChar.character = srcChar->character;
}
iError -= iDeltaY; error -= deltaY;
if (iError < 0) if (error < 0)
{ {
iY += iYStep; y += yStep;
iError += iDeltaX; error += deltaX;
} }
} }
} }
bValidRender = false; damage = true;
} }
if (!bValidRender) if (damage)
{ {
SDL_SetRenderDrawColor(pRenderer, 48, 48, 48, 255); SDL_SetRenderDrawColor(renderer, 48, 48, 48, 255);
SDL_RenderClear(pRenderer); SDL_RenderClear(renderer);
SDL_Rect src, dst; SDL_Rect src, dst;
src.w = cellWidth;
src.h = cellHeight;
dst.w = cellWidth;
dst.h = cellHeight;
src.w = CHARWIDTH; int x = 0, y = 0;
src.h = CHARHEIGHT; for (const auto& currentCharacter : display)
dst.w = CHARWIDTH;
dst.h = CHARHEIGHT;
int iX = 0, iY = 0;
for (int i = 0; i < 2000; ++i)
{ {
SChar& currentCharacter = aDisplay[i]; auto currentBgColour = colourTable[static_cast<unsigned char>(currentCharacter.bgColour)];
SDL_Colour& currentBgColour = g_aColourTable[(unsigned char)aDisplay[i].bgColour]; auto currentFgColour = colourTable[static_cast<unsigned char>(currentCharacter.fgColour)];
SDL_Colour& currentFgColour = g_aColourTable[(unsigned char)aDisplay[i].fgColour];
src.x = (currentCharacter.character % 32) * CHARWIDTH; src.x = (currentCharacter.character % 32) * cellWidth;
src.y = (currentCharacter.character / 32) * CHARHEIGHT; src.y = (currentCharacter.character / 32) * cellHeight;
dst.x = iX * CHARWIDTH; dst.x = x * cellWidth;
dst.y = iY * CHARHEIGHT; dst.y = y * cellHeight;
SDL_SetRenderDrawColor(pRenderer, currentBgColour.r, currentBgColour.g, currentBgColour.b, currentBgColour.a); SDL_SetRenderDrawColor(renderer, currentBgColour.r, currentBgColour.g, currentBgColour.b, currentBgColour.a);
SDL_RenderFillRect(pRenderer, &dst); SDL_RenderFillRect(renderer, &dst);
SDL_SetRenderDrawColor(pRenderer, 0, 0, 0, currentFgColour.a); SDL_SetRenderDrawColor(renderer, 0, 0, 0, currentFgColour.a);
if (bBlinkState || !currentCharacter.blinking) if (blinkState || !currentCharacter.blinking)
{ {
SDL_SetTextureColorMod(pCodepage, currentFgColour.r, currentFgColour.g, currentFgColour.b); SDL_SetTextureColorMod(codepage, currentFgColour.r, currentFgColour.g, currentFgColour.b);
SDL_RenderCopy(pRenderer, pCodepage, &src, &dst); SDL_RenderCopy(renderer, codepage, &src, &dst);
} }
if (++iX >= 80) if (++x >= 80)
{ {
iX = 0; x = 0;
++iY; ++y;
} }
} }
SDL_RenderPresent(pRenderer); SDL_RenderPresent(renderer);
bValidRender = true; damage = false;
} }
} }
while (running);
fclose(pFile); fclose(file);
SDL_DestroyTexture(pCodepage); SDL_DestroyTexture(codepage);
SDL_DestroyRenderer(pRenderer); SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(pWindow); SDL_DestroyWindow(window);
IMG_Quit(); IMG_Quit();
SDL_Quit(); SDL_Quit();
return 0; return 0;