Separate dchip update from rendering
This commit is contained in:
		
							parent
							
								
									1c4c6d3dca
								
							
						
					
					
						commit
						de4365126d
					
				| @ -18,6 +18,9 @@ | ||||
|       <Platform>x64</Platform> | ||||
|     </ProjectConfiguration> | ||||
|   </ItemGroup> | ||||
|   <ItemGroup> | ||||
|     <ClCompile Include="src\unity_build.cpp" /> | ||||
|   </ItemGroup> | ||||
|   <PropertyGroup Label="Globals"> | ||||
|     <ProjectGuid>{01B5A474-4BA5-48A3-B645-7116ADF5585D}</ProjectGuid> | ||||
|     <RootNamespace>dchip8</RootNamespace> | ||||
| @ -119,9 +122,6 @@ | ||||
|       <OptimizeReferences>true</OptimizeReferences> | ||||
|     </Link> | ||||
|   </ItemDefinitionGroup> | ||||
|   <ItemGroup> | ||||
|     <ClCompile Include="src\dchip-8.cpp" /> | ||||
|   </ItemGroup> | ||||
|   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> | ||||
|   <ImportGroup Label="ExtensionTargets"> | ||||
|   </ImportGroup> | ||||
|  | ||||
| @ -15,7 +15,7 @@ | ||||
|     </Filter> | ||||
|   </ItemGroup> | ||||
|   <ItemGroup> | ||||
|     <ClCompile Include="src\dchip-8.cpp"> | ||||
|     <ClCompile Include="src\unity_build.cpp"> | ||||
|       <Filter>Source Files</Filter> | ||||
|     </ClCompile> | ||||
|   </ItemGroup> | ||||
|  | ||||
| @ -4,7 +4,6 @@ | ||||
| #include "stdint.h" | ||||
| 
 | ||||
| #define LOCAL_PERSIST static | ||||
| #define GLOBAL_VAR    static | ||||
| #define FILE_SCOPE    static | ||||
| 
 | ||||
| typedef uint32_t u32; | ||||
|  | ||||
| @ -2,7 +2,8 @@ | ||||
| @REM vcvarsall.bat to setup command-line compiler. | ||||
| 
 | ||||
| @echo OFF | ||||
| set ProjectName=dchip-8 | ||||
| set ProjectName=dchip8 | ||||
| set CompileEntryPoint=..\src\unity_build.cpp | ||||
| 
 | ||||
| ctime -begin %ProjectName%.ctm | ||||
| 
 | ||||
| @ -47,7 +48,7 @@ REM incrmenetal:no, turn incremental builds off | ||||
| REM opt:ref, try to remove functions from libs that are referenced at all | ||||
| set LinkFlags=-incremental:no -opt:ref | ||||
| 
 | ||||
| cl %CompileFlags% ..\src\%ProjectName%.cpp %IncludeFlags% /link -subsystem:WINDOWS,5.1 %LinkLibraries% %LinkFlags% /nologo /OUT:"%ProjectName%.exe" | ||||
| cl %CompileFlags% %CompileEntryPoint% %IncludeFlags% /link -subsystem:WINDOWS,5.1 %LinkLibraries% %LinkFlags% /nologo /OUT:"%ProjectName%.exe" | ||||
| 
 | ||||
| popd | ||||
| ctime -end %ProjectName%.ctm | ||||
|  | ||||
							
								
								
									
										241
									
								
								src/dchip-8.cpp
									
									
									
									
									
								
							
							
						
						
									
										241
									
								
								src/dchip-8.cpp
									
									
									
									
									
								
							| @ -1,241 +0,0 @@ | ||||
| #define UNICODE | ||||
| #define _UNICODE | ||||
| 
 | ||||
| #ifndef WIN32_LEAN_AND_MEAN | ||||
|   #define WIN32_LEAN_AND_MEAN | ||||
| #endif | ||||
| 
 | ||||
| #include "Common.h" | ||||
| 
 | ||||
| #include <Windows.h> | ||||
| #include <stdio.h> | ||||
| #include <stdlib.h> | ||||
| 
 | ||||
| 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; | ||||
| 
 | ||||
| FILE_SCOPE LRESULT CALLBACK mainWindowProcCallback(HWND window, UINT msg, | ||||
|                                                    WPARAM wParam, LPARAM lParam) | ||||
| { | ||||
| 	LRESULT result = 0; | ||||
| 	switch (msg) | ||||
| 	{ | ||||
| 		case WM_CLOSE: | ||||
| 		case WM_DESTROY: | ||||
| 		{ | ||||
| 			globalRunning = false; | ||||
| 		} | ||||
| 		break; | ||||
| 
 | ||||
| 		default: | ||||
| 		{ | ||||
| 			result = DefWindowProc(window, msg, wParam, lParam); | ||||
| 		} | ||||
| 		break; | ||||
| 	} | ||||
| 
 | ||||
| 	return result; | ||||
| } | ||||
| 
 | ||||
| GLOBAL_VAR LARGE_INTEGER globalQueryPerformanceFrequency; | ||||
| inline FILE_SCOPE f32 getTimeFromQueryPerfCounter(LARGE_INTEGER start, | ||||
|                                                   LARGE_INTEGER end) | ||||
| { | ||||
| 	f32 result = (f32)(end.QuadPart - start.QuadPart) / | ||||
| 	             globalQueryPerformanceFrequency.QuadPart; | ||||
| 	return result; | ||||
| } | ||||
| 
 | ||||
| inline FILE_SCOPE LARGE_INTEGER getWallClock() | ||||
| { | ||||
| 	LARGE_INTEGER result; | ||||
| 	QueryPerformanceCounter(&result); | ||||
| 
 | ||||
| 	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_OWNDC, | ||||
| 		mainWindowProcCallback, | ||||
| 		0, // int cbClsExtra
 | ||||
| 		0, // int cbWndExtra
 | ||||
| 		hInstance, | ||||
| 		LoadIcon(NULL, IDI_APPLICATION), | ||||
| 		LoadCursor(NULL, IDC_ARROW), | ||||
| 		GetSysColorBrush(COLOR_3DFACE), | ||||
| 		L"", // LPCTSTR lpszMenuName
 | ||||
| 		L"dchip-8Class", | ||||
| 		NULL, // HICON hIconSm
 | ||||
| 	}; | ||||
| 
 | ||||
| 	if (!RegisterClassEx(&wc)) { | ||||
| 		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 rect   = {}; | ||||
| 	rect.right  = 128; | ||||
| 	rect.bottom = 64; | ||||
| 
 | ||||
| 	DWORD windowStyle = | ||||
| 	    WS_OVERLAPPEDWINDOW | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN; | ||||
| 	AdjustWindowRect(&rect, windowStyle, FALSE); | ||||
| 
 | ||||
| 	HWND mainWindow = CreateWindowEx( | ||||
| 	    WS_EX_COMPOSITED, wc.lpszClassName, L"dchip-8", windowStyle, | ||||
| 	    CW_USEDEFAULT, CW_USEDEFAULT, rect.right - rect.left, | ||||
| 	    rect.bottom - rect.top, nullptr, nullptr, hInstance, nullptr); | ||||
| 
 | ||||
| 	if (!mainWindow) | ||||
| 	{ | ||||
| 		ErrorBox(L"CreateWindowEx() failed.", nullptr); | ||||
| 		return -1; | ||||
| 	} | ||||
| 
 | ||||
| 	QueryPerformanceFrequency(&globalQueryPerformanceFrequency); | ||||
| 	LARGE_INTEGER startFrameTime; | ||||
| 	const f32 targetFramesPerSecond = 16.0f; | ||||
| 	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) | ||||
| 	{ | ||||
| 		startFrameTime = getWallClock(); | ||||
| 		while (PeekMessage(&msg, mainWindow, 0, 0, PM_REMOVE)) | ||||
| 		{ | ||||
| 			TranslateMessage(&msg); | ||||
| 			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 = | ||||
| 			    (DWORD)((targetSecondsPerFrame - workTimeInS) * 1000); | ||||
| 			Sleep(remainingTimeInMs); | ||||
| 		} | ||||
| 
 | ||||
| 		LARGE_INTEGER endFrameTime = getWallClock(); | ||||
| 		frameTimeInS = | ||||
| 		    getTimeFromQueryPerfCounter(startFrameTime, endFrameTime); | ||||
| 		f32 msPerFrame = 1000.0f * frameTimeInS; | ||||
| 
 | ||||
| 		wchar_t windowTitleBuffer[128] = {}; | ||||
| 		_snwprintf_s(windowTitleBuffer, ARRAY_COUNT(windowTitleBuffer), | ||||
| 		             ARRAY_COUNT(windowTitleBuffer), L"dchip-8 | %5.2f ms/f", | ||||
| 		             msPerFrame); | ||||
| 		SetWindowText(mainWindow, windowTitleBuffer); | ||||
| 	} | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
							
								
								
									
										27
									
								
								src/dchip8.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								src/dchip8.cpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,27 @@ | ||||
| #include "common.h" | ||||
| #include "dchip8_platform.h" | ||||
| 
 | ||||
| void dchip8_update(PlatformRenderBuffer *renderBuffer) | ||||
| { | ||||
| 	ASSERT(renderBuffer.bytesPerPixel == 4); | ||||
| 
 | ||||
| 	const i32 numPixels = renderBuffer->width * renderBuffer->height; | ||||
| 	u32 *bitmapBuffer   = (u32 *)renderBuffer->memory; | ||||
| 	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; | ||||
| 	} | ||||
| } | ||||
							
								
								
									
										8
									
								
								src/dchip8.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								src/dchip8.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,8 @@ | ||||
| #ifndef DCHIP8_H | ||||
| #define DCHIP8_H | ||||
| 
 | ||||
| #include "dchip8_platform.h" | ||||
| 
 | ||||
| void dchip8_update(PlatformRenderBuffer *renderBuffer); | ||||
| 
 | ||||
| #endif | ||||
							
								
								
									
										14
									
								
								src/dchip8_platform.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								src/dchip8_platform.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,14 @@ | ||||
| #ifndef DCHIP_8_PLATFORM | ||||
| #define DCHIP_8_PLATFORM | ||||
| 
 | ||||
| #include "Common.h" | ||||
| 
 | ||||
| typedef struct PlatformRenderBuffer | ||||
| { | ||||
| 	i32   width; | ||||
| 	i32   height; | ||||
| 	i32   bytesPerPixel; | ||||
| 	void *memory; | ||||
| } PlatformRenderBuffer; | ||||
| 
 | ||||
| #endif | ||||
							
								
								
									
										3
									
								
								src/unity_build.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								src/unity_build.cpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,3 @@ | ||||
| #include "win32_dchip8.cpp" | ||||
| 
 | ||||
| #include "dchip8.cpp" | ||||
							
								
								
									
										233
									
								
								src/win32_dchip8.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										233
									
								
								src/win32_dchip8.cpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,233 @@ | ||||
| #define UNICODE | ||||
| #define _UNICODE | ||||
| 
 | ||||
| #ifndef WIN32_LEAN_AND_MEAN | ||||
|   #define WIN32_LEAN_AND_MEAN | ||||
| #endif | ||||
| 
 | ||||
| #include <Windows.h> | ||||
| #include <stdio.h> | ||||
| #include <stdlib.h> | ||||
| 
 | ||||
| #include "common.h" | ||||
| #include "dchip8.h" | ||||
| #include "dchip8_platform.h" | ||||
| 
 | ||||
| FILE_SCOPE bool globalRunning = false; | ||||
| FILE_SCOPE LARGE_INTEGER globalQueryPerformanceFrequency; | ||||
| #define win32_error_box(text, title) MessageBox(nullptr, text, title, MB_OK); | ||||
| 
 | ||||
| FILE_SCOPE LRESULT CALLBACK win32_main_proc_callback(HWND window, UINT msg, | ||||
|                                                      WPARAM wParam, | ||||
|                                                      LPARAM lParam) | ||||
| { | ||||
| 	LRESULT result = 0; | ||||
| 	switch (msg) | ||||
| 	{ | ||||
| 		case WM_CLOSE: | ||||
| 		case WM_DESTROY: | ||||
| 		{ | ||||
| 			globalRunning = false; | ||||
| 		} | ||||
| 		break; | ||||
| 
 | ||||
| 		default: | ||||
| 		{ | ||||
| 			result = DefWindowProc(window, msg, wParam, lParam); | ||||
| 		} | ||||
| 		break; | ||||
| 	} | ||||
| 
 | ||||
| 	return result; | ||||
| } | ||||
| 
 | ||||
| inline FILE_SCOPE f32 win32_query_perf_counter_get_time(LARGE_INTEGER start, | ||||
|                                                         LARGE_INTEGER end) | ||||
| { | ||||
| 	f32 result = (f32)(end.QuadPart - start.QuadPart) / | ||||
| 	             globalQueryPerformanceFrequency.QuadPart; | ||||
| 	return result; | ||||
| } | ||||
| 
 | ||||
| inline FILE_SCOPE LARGE_INTEGER win32_query_perf_counter_time() | ||||
| { | ||||
| 	LARGE_INTEGER result; | ||||
| 	QueryPerformanceCounter(&result); | ||||
| 
 | ||||
| 	return result; | ||||
| } | ||||
| 
 | ||||
| typedef struct Win32RenderBitmap | ||||
| { | ||||
| 	BITMAPINFO  info; | ||||
| 	HBITMAP     handle; | ||||
| 	i32         width; | ||||
| 	i32         height; | ||||
| 	i32         bytesPerPixel; | ||||
| 	void       *memory; | ||||
| } Win32RenderBitmap; | ||||
| 
 | ||||
| FILE_SCOPE void win32_display_render_bitmap(Win32RenderBitmap renderBitmap, | ||||
|                                             HDC deviceContext, LONG width, | ||||
|                                             LONG height) | ||||
| { | ||||
| 	BLENDFUNCTION blend       = {}; | ||||
| 	blend.BlendOp             = AC_SRC_OVER; | ||||
| 	blend.SourceConstantAlpha = 255; | ||||
| 	blend.AlphaFormat         = AC_SRC_ALPHA; | ||||
| 
 | ||||
| 	HDC alphaBlendDC  = CreateCompatibleDC(deviceContext); | ||||
| 	SelectObject(alphaBlendDC, renderBitmap.handle); | ||||
| 
 | ||||
| 	AlphaBlend(deviceContext, 0, 0, width, height, alphaBlendDC, 0, 0, | ||||
| 	           renderBitmap.width, renderBitmap.height, blend); | ||||
| 	StretchBlt(deviceContext, 0, 0, width, height, deviceContext, 0, 0, | ||||
| 	           renderBitmap.width, renderBitmap.height, SRCCOPY); | ||||
| 
 | ||||
| 	DeleteDC(alphaBlendDC); | ||||
| } | ||||
| 
 | ||||
| int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, | ||||
|                    LPSTR lpCmdLine, int nShowCmd) | ||||
| { | ||||
| 	WNDCLASSEX wc = | ||||
| 	{ | ||||
| 		sizeof(WNDCLASSEX), | ||||
| 		CS_HREDRAW | CS_VREDRAW | CS_OWNDC, | ||||
| 		win32_main_proc_callback, | ||||
| 		0, // int cbClsExtra
 | ||||
| 		0, // int cbWndExtra
 | ||||
| 		hInstance, | ||||
| 		LoadIcon(NULL, IDI_APPLICATION), | ||||
| 		LoadCursor(NULL, IDC_ARROW), | ||||
| 		NULL, // GetSysColorBrush(COLOR_3DFACE),
 | ||||
| 		L"", // LPCTSTR lpszMenuName
 | ||||
| 		L"dchip-8Class", | ||||
| 		NULL, // HICON hIconSm
 | ||||
| 	}; | ||||
| 
 | ||||
| 	if (!RegisterClassEx(&wc)) { | ||||
| 		win32_error_box(L"RegisterClassEx() failed.", nullptr); | ||||
| 		return -1; | ||||
| 	} | ||||
| 
 | ||||
| 	// 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 rect   = {}; | ||||
| 	rect.right  = 128; | ||||
| 	rect.bottom = 64; | ||||
| 
 | ||||
| 	DWORD windowStyle = | ||||
| 	    WS_OVERLAPPEDWINDOW | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN; | ||||
| 	AdjustWindowRect(&rect, windowStyle, FALSE); | ||||
| 
 | ||||
| 	HWND mainWindow = CreateWindowEx( | ||||
| 	    WS_EX_COMPOSITED, wc.lpszClassName, L"dchip-8", windowStyle, | ||||
| 	    CW_USEDEFAULT, CW_USEDEFAULT, rect.right - rect.left, | ||||
| 	    rect.bottom - rect.top, nullptr, nullptr, hInstance, nullptr); | ||||
| 
 | ||||
| 	if (!mainWindow) | ||||
| 	{ | ||||
| 		win32_error_box(L"CreateWindowEx() failed.", nullptr); | ||||
| 		return -1; | ||||
| 	} | ||||
| 
 | ||||
| 	Win32RenderBitmap renderBitmap = {}; | ||||
| 	{ // Initialise the renderbitmap
 | ||||
| 		BITMAPINFOHEADER header = {}; | ||||
| 		header.biSize           = sizeof(BITMAPINFOHEADER); | ||||
| 		header.biWidth          = 64; | ||||
| 		header.biHeight         = 32; | ||||
| 		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; | ||||
| 
 | ||||
| 		renderBitmap.info.bmiHeader = header; | ||||
| 		renderBitmap.width          = header.biWidth; | ||||
| 		renderBitmap.height         = header.biHeight; | ||||
| 		renderBitmap.bytesPerPixel  = header.biBitCount / 8; | ||||
| 		ASSERT(renderBitmap.bytesPerPixel >= 1); | ||||
| 
 | ||||
| 		HDC deviceContext = GetDC(mainWindow); | ||||
| 		renderBitmap.handle = | ||||
| 		    CreateDIBSection(deviceContext, &renderBitmap.info, DIB_RGB_COLORS, | ||||
| 		                     &renderBitmap.memory, NULL, NULL); | ||||
| 		ReleaseDC(mainWindow, deviceContext); | ||||
| 	} | ||||
| 
 | ||||
| 	if (!renderBitmap.memory) | ||||
| 	{ | ||||
| 		win32_error_box(L"CreateDIBSection() failed.", nullptr); | ||||
| 		return -1; | ||||
| 	} | ||||
| 
 | ||||
| 	////////////////////////////////////////////////////////////////////////////
 | ||||
| 	// Update Loop
 | ||||
| 	////////////////////////////////////////////////////////////////////////////
 | ||||
| 	QueryPerformanceFrequency(&globalQueryPerformanceFrequency); | ||||
| 	const f32 TARGET_FRAMES_PER_S = 60.0f; | ||||
| 	f32 targetSecondsPerFrame     = 1 / TARGET_FRAMES_PER_S; | ||||
| 	f32 frameTimeInS              = 0.0f; | ||||
| 	globalRunning                 = true; | ||||
| 
 | ||||
| 	while (globalRunning) | ||||
| 	{ | ||||
| 		LARGE_INTEGER startFrameTime = win32_query_perf_counter_time(); | ||||
| 
 | ||||
| 		MSG msg; | ||||
| 		while (PeekMessage(&msg, mainWindow, 0, 0, PM_REMOVE)) | ||||
| 		{ | ||||
| 			TranslateMessage(&msg); | ||||
| 			DispatchMessage(&msg); | ||||
| 		} | ||||
| 
 | ||||
| 		////////////////////////////////////////////////////////////////////////
 | ||||
| 		// Rendering
 | ||||
| 		////////////////////////////////////////////////////////////////////////
 | ||||
| 		PlatformRenderBuffer renderBuffer = {}; | ||||
| 		renderBuffer.memory               = renderBitmap.memory; | ||||
| 		renderBuffer.height               = renderBitmap.height; | ||||
| 		renderBuffer.width                = renderBitmap.width; | ||||
| 		dchip8_update(&renderBuffer); | ||||
| 
 | ||||
| 		HDC deviceContext = GetDC(mainWindow); | ||||
| 		win32_display_render_bitmap(renderBitmap, deviceContext, clientWidth, | ||||
| 		                            clientHeight); | ||||
| 		ReleaseDC(mainWindow, deviceContext); | ||||
| 
 | ||||
| 		////////////////////////////////////////////////////////////////////////
 | ||||
| 		// Frame Limiting
 | ||||
| 		////////////////////////////////////////////////////////////////////////
 | ||||
| 		LARGE_INTEGER endWorkTime = win32_query_perf_counter_time(); | ||||
| 		f32 workTimeInS = | ||||
| 		    win32_query_perf_counter_get_time(startFrameTime, endWorkTime); | ||||
| 		if (workTimeInS < targetSecondsPerFrame) | ||||
| 		{ | ||||
| 			DWORD remainingTimeInMs = | ||||
| 			    (DWORD)((targetSecondsPerFrame - workTimeInS) * 1000); | ||||
| 			Sleep(remainingTimeInMs); | ||||
| 		} | ||||
| 
 | ||||
| 		LARGE_INTEGER endFrameTime = win32_query_perf_counter_time(); | ||||
| 		frameTimeInS = | ||||
| 		    win32_query_perf_counter_get_time(startFrameTime, endFrameTime); | ||||
| 		f32 msPerFrame = 1000.0f * frameTimeInS; | ||||
| 
 | ||||
| 		wchar_t windowTitleBuffer[128] = {}; | ||||
| 		_snwprintf_s(windowTitleBuffer, ARRAY_COUNT(windowTitleBuffer), | ||||
| 		             ARRAY_COUNT(windowTitleBuffer), L"dchip-8 | %5.2f ms/f", | ||||
| 		             msPerFrame); | ||||
| 		SetWindowText(mainWindow, windowTitleBuffer); | ||||
| 	} | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user