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