diff --git a/dchip-8.vcxproj b/dchip-8.vcxproj
index 63e7779..464bf8a 100644
--- a/dchip-8.vcxproj
+++ b/dchip-8.vcxproj
@@ -83,6 +83,7 @@
Windows
+ msimg32.lib;%(AdditionalDependencies)
diff --git a/src/build.bat b/src/build.bat
index 41ceab6..d22a7c2 100644
--- a/src/build.bat
+++ b/src/build.bat
@@ -41,7 +41,7 @@ REM Include directories
set IncludeFlags=
REM Link libraries
-set LinkLibraries=user32.lib gdi32.lib
+set LinkLibraries=user32.lib gdi32.lib msimg32.lib
REM incrmenetal:no, turn incremental builds off
REM opt:ref, try to remove functions from libs that are referenced at all
diff --git a/src/dchip-8.cpp b/src/dchip-8.cpp
index 95406b5..d85ac8d 100644
--- a/src/dchip-8.cpp
+++ b/src/dchip-8.cpp
@@ -9,6 +9,15 @@
#include
#include
+#include
+
+FILE_SCOPE HBITMAP bitmap;
+FILE_SCOPE BITMAPINFO bitmapInfo;
+
+const i32 WIDTH = 64;
+const i32 HEIGHT = 32;
+const i32 RESOLUTION = WIDTH * HEIGHT;
+FILE_SCOPE void *bitmapMemory;
FILE_SCOPE bool globalRunning = false;
@@ -52,13 +61,14 @@ inline FILE_SCOPE LARGE_INTEGER getWallClock()
return result;
}
+#define ErrorBox(text, title) MessageBox(nullptr, text, title, MB_OK);
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nShowCmd)
{
WNDCLASSEX wc =
{
sizeof(WNDCLASSEX),
- CS_HREDRAW | CS_VREDRAW,
+ CS_HREDRAW | CS_VREDRAW | CS_OWNDC,
mainWindowProcCallback,
0, // int cbClsExtra
0, // int cbWndExtra
@@ -72,34 +82,34 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
};
if (!RegisterClassEx(&wc)) {
- // TODO(doyle): Logging, couldn't register class
- ASSERT(INVALID_CODE_PATH);
+ ErrorBox(L"RegisterClassEx() failed.", nullptr);
return -1;
}
+ globalRunning = true;
+
// NOTE: Regarding Window Sizes
// If you specify a window size, e.g. 800x600, Windows regards the 800x600
// region to be inclusive of the toolbars and side borders. So in actuality,
// when you blit to the screen blackness, the area that is being blitted to
// is slightly smaller than 800x600. Windows provides a function to help
// calculate the size you'd need by accounting for the window style.
- RECT r = {};
- r.right = 450;
- r.bottom = 200;
+ RECT rect = {};
+ rect.right = 128;
+ rect.bottom = 64;
- DWORD windowStyle = WS_OVERLAPPEDWINDOW | WS_VISIBLE;
- AdjustWindowRect(&r, windowStyle, FALSE);
+ DWORD windowStyle =
+ WS_OVERLAPPEDWINDOW | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN;
+ AdjustWindowRect(&rect, windowStyle, FALSE);
- globalRunning = true;
HWND mainWindow = CreateWindowEx(
WS_EX_COMPOSITED, wc.lpszClassName, L"dchip-8", windowStyle,
- CW_USEDEFAULT, CW_USEDEFAULT, r.right - r.left, r.bottom - r.top,
- nullptr, nullptr, hInstance, nullptr);
+ CW_USEDEFAULT, CW_USEDEFAULT, rect.right - rect.left,
+ rect.bottom - rect.top, nullptr, nullptr, hInstance, nullptr);
if (!mainWindow)
{
- // TODO(doyle): Logging, couldn't create root window
- ASSERT(INVALID_CODE_PATH);
+ ErrorBox(L"CreateWindowEx() failed.", nullptr);
return -1;
}
@@ -109,6 +119,66 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
f32 targetSecondsPerFrame = 1 / targetFramesPerSecond;
f32 frameTimeInS = 0.0f;
+ {
+ BITMAPINFOHEADER header = {};
+ header.biSize = sizeof(BITMAPINFOHEADER);
+ header.biWidth = WIDTH;
+ header.biHeight = HEIGHT;
+ header.biPlanes = 1;
+ header.biBitCount = 32;
+ header.biCompression = BI_RGB; // uncompressed bitmap
+ header.biSizeImage = 0;
+ header.biXPelsPerMeter = 0;
+ header.biYPelsPerMeter = 0;
+ header.biClrUsed = 0;
+ header.biClrImportant = 0;
+
+ bitmapInfo.bmiHeader = header;
+
+ const i32 numPixels = header.biWidth * header.biHeight;
+ const i32 bytesPerPixel = header.biBitCount / 8;
+#if 0
+ bitmapMemory = calloc(1, numPixels * bytesPerPixel);
+
+ if (!bitmapMemory)
+ {
+ ErrorBox(L"malloc() failed.", nullptr);
+ return -1;
+ }
+
+#else
+ HDC deviceContext = GetDC(mainWindow);
+ bitmap = CreateDIBSection(deviceContext, &bitmapInfo, DIB_RGB_COLORS,
+ &bitmapMemory, NULL, NULL);
+ ReleaseDC(mainWindow, deviceContext);
+
+ if (!bitmapMemory)
+ {
+ ErrorBox(L"CreateDIBSection() failed.", nullptr);
+ return -1;
+ }
+#endif
+
+ u32 *bitmapBuffer = (u32 *)bitmapMemory;
+ for (i32 i = 0; i < numPixels; i++)
+ {
+ // NOTE: Win32 AlphaBlend requires the RGB components to be
+ // premultiplied with alpha.
+ f32 normA = 1.0f;
+ f32 normR = (normA * 0.0f);
+ f32 normG = (normA * 0.0f);
+ f32 normB = (normA * 1.0f);
+
+ u8 r = (u8)(normR * 255.0f);
+ u8 g = (u8)(normG * 255.0f);
+ u8 b = (u8)(normB * 255.0f);
+ u8 a = (u8)(normA * 255.0f);
+
+ u32 color = (a << 24) | (r << 16) | (g << 8) | (b << 0);
+ bitmapBuffer[i] = color;
+ }
+ }
+
MSG msg;
while (globalRunning)
{
@@ -119,10 +189,35 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
DispatchMessage(&msg);
}
+ RECT clientRect = {};
+ GetClientRect(mainWindow, &clientRect);
+
+ LONG clientWidth = clientRect.right - clientRect.left;
+ LONG clientHeight = clientRect.bottom - clientRect.top;
+
+ BLENDFUNCTION blend = {};
+ blend.BlendOp = AC_SRC_OVER;
+ blend.SourceConstantAlpha = 255;
+ blend.AlphaFormat = AC_SRC_ALPHA;
+
+ HDC deviceContext = GetDC(mainWindow);
+ HDC alphaBlendDC = CreateCompatibleDC(deviceContext);
+ SelectObject(alphaBlendDC, bitmap);
+
+ AlphaBlend(deviceContext, 0, 0, WIDTH, HEIGHT, alphaBlendDC, 0, 0,
+ WIDTH, HEIGHT, blend);
+ StretchBlt(deviceContext, 0, 0, clientWidth, clientHeight,
+ deviceContext, 0, 0, WIDTH, HEIGHT, SRCCOPY);
+
+ DeleteDC(alphaBlendDC);
+ ReleaseDC(mainWindow, deviceContext);
+
+ ////////////////////////////////////////////////////////////////////////
+ // Frame Limiting
+ ////////////////////////////////////////////////////////////////////////
LARGE_INTEGER endWorkTime = getWallClock();
f32 workTimeInS =
getTimeFromQueryPerfCounter(startFrameTime, endWorkTime);
-
if (workTimeInS < targetSecondsPerFrame)
{
DWORD remainingTimeInMs =