Initial commit

This commit is contained in:
Doyle Thai 2017-05-03 02:04:12 +10:00
commit 7f62ce23d0
11 changed files with 5282 additions and 0 deletions

4
.gitignore vendored Normal file
View File

@ -0,0 +1,4 @@
bin/
.vs/
ctime.exe
tags

29
drenderer.sln Normal file
View File

@ -0,0 +1,29 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.26403.3
MinimumVisualStudioVersion = 10.0.40219.1
Project("{911E67C6-3D85-4FCE-B560-20A9C3E3FF48}") = "drenderer", "bin\drenderer.exe", "{25476A47-63FF-426D-A4A2-73AB789B9916}"
ProjectSection(DebuggerProjectSystem) = preProject
PortSupplier = 00000000-0000-0000-0000-000000000000
Executable = C:\git\drenderer\bin\drenderer.exe
RemoteMachine = THAI-PC
StartingDirectory = C:\git\drenderer\bin
Environment = Default
LaunchingEngine = 00000000-0000-0000-0000-000000000000
UseLegacyDebugEngines = No
LaunchSQLEngine = No
AttachLaunchAction = No
EndProjectSection
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Release|x64 = Release|x64
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{25476A47-63FF-426D-A4A2-73AB789B9916}.Release|x64.ActiveCfg = Release|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal

46
src/.clang-format Normal file
View File

@ -0,0 +1,46 @@
{
ColumnLimit: 80,
TabWidth: 4,
IndentWidth: 4, # 1 tab
UseTab: ForIndentation,
BreakBeforeBraces: Allman,
PointerBindsToType: false,
###
AlwaysBreakAfterDefinitionReturnType: false,
AlwaysBreakTemplateDeclarations: true,
AlwaysBreakBeforeMultilineStrings: true,
IndentFunctionDeclarationAfterType: false,
#
AccessModifierOffset: -4, # 1 tab
AlignAfterOpenBracket: true,
AlignConsecutiveAssignments: true,
AlignTrailingComments: true,
#
AllowAllParametersOfDeclarationOnNextLine: true,
AllowShortBlocksOnASingleLine: false,
AllowShortIfStatementsOnASingleLine: true,
AllowShortLoopsOnASingleLine: false,
#
BinPackArguments: true,
BinPackParameters: true,
#
BreakConstructorInitializersBeforeComma: true,
ConstructorInitializerIndentWidth: 0,
#
IndentCaseLabels: true,
#
MaxEmptyLinesToKeep: 1,
NamespaceIndentation: None,
#
SpaceBeforeAssignmentOperators: true,
SpaceInEmptyParentheses: false,
SpacesBeforeTrailingComments: 1,
SpacesInAngles: false,
SpacesInCStyleCastParentheses: false,
SpacesInParentheses: false,
SpacesInSquareBrackets: false,
#
Cpp11BracedListStyle: true,
Standard: Cpp11,
#
}

6
src/DRenderer.cpp Normal file
View File

@ -0,0 +1,6 @@
#include "DRendererPlatform.h"
void DR_Update(PlatformRenderBuffer *const renderBuffer,
PlatformInput *const input, PlatformMemory *const memory)
{
}

8
src/DRenderer.h Normal file
View File

@ -0,0 +1,8 @@
#ifndef DRENDERER_H
#define DRENDERER_H
void DR_Update(struct PlatformRenderBuffer *const renderBuffer,
struct PlatformInput *const input,
struct PlatformMemory *const memory);
#endif

97
src/DRendererPlatform.h Normal file
View File

@ -0,0 +1,97 @@
#ifndef DRENDERER_PLATFORM_H
#define DRENDERER_PLATFORM_H
#include "dqn.h"
enum Key
{
key_up,
key_down,
key_left,
key_right,
key_escape,
key_1,
key_2,
key_3,
key_4,
key_q,
key_w,
key_e,
key_r,
key_a,
key_s,
key_d,
key_f,
key_z,
key_x,
key_c,
key_v,
key_count,
};
typedef struct KeyState
{
bool endedDown;
u32 halfTransitionCount;
} KeyState;
typedef struct PlatformInput
{
f32 deltaForFrame;
bool loadNewRom;
wchar_t rom[260];
union {
KeyState key[key_count];
struct
{
KeyState up;
KeyState down;
KeyState left;
KeyState right;
KeyState escape;
KeyState key_1;
KeyState key_2;
KeyState key_3;
KeyState key_4;
KeyState key_q;
KeyState key_w;
KeyState key_e;
KeyState key_r;
KeyState key_a;
KeyState key_s;
KeyState key_d;
KeyState key_f;
KeyState key_z;
KeyState key_x;
KeyState key_c;
KeyState key_v;
};
};
} PlatformInput;
typedef struct PlatformMemory
{
DqnMemBuffer permanentBuffer;
DqnMemBuffer transientBuffer;
} PlatformMemory;
typedef struct PlatformRenderBuffer
{
i32 width;
i32 height;
i32 bytesPerPixel;
void *memory;
} PlatformRenderBuffer;
#endif

View File

@ -0,0 +1,2 @@
#include "..\DRenderer.cpp"
#include "..\Win32DRenderer.cpp"

393
src/Win32DRenderer.cpp Normal file
View File

@ -0,0 +1,393 @@
#include "DRenderer.h"
#include "DRendererPlatform.h"
#define DQN_IMPLEMENTATION
#define DQN_WIN32_IMPLEMENTATION
#include "dqn.h"
#define UNICODE
#define _UNICODE
#include <Windows.h>
typedef struct Win32RenderBitmap
{
BITMAPINFO info;
HBITMAP handle;
i32 width;
i32 height;
i32 bytesPerPixel;
void *memory;
} Win32RenderBitmap;
FILE_SCOPE Win32RenderBitmap globalRenderBitmap;
FILE_SCOPE bool globalRunning;
FILE_SCOPE void Win32DisplayRenderBitmap(Win32RenderBitmap renderBitmap,
HDC deviceContext, LONG width,
LONG height)
{
HDC stretchDC = CreateCompatibleDC(deviceContext);
SelectObject(stretchDC, renderBitmap.handle);
DQN_ASSERT(renderBitmap.width == width);
DQN_ASSERT(renderBitmap.height == height);
StretchBlt(deviceContext, 0, 0, width, height, stretchDC, 0, 0,
renderBitmap.width, renderBitmap.height, SRCCOPY);
// NOTE: Win32 AlphaBlend requires the RGB components to be premultiplied
// with alpha.
#if 0
BLENDFUNCTION blend = {};
blend.BlendOp = AC_SRC_OVER;
blend.SourceConstantAlpha = 255;
blend.AlphaFormat = AC_SRC_ALPHA;
if (!AlphaBlend(deviceContext, 0, 0, width, height, deviceContext, 0, 0,
width, height, blend))
{
OutputDebugString(L"AlphaBlend() failed.");
}
#endif
DeleteDC(stretchDC);
}
enum Win32Menu
{
Win32Menu_FileOpen = 4,
Win32Menu_FileExit,
};
FILE_SCOPE void Win32CreateMenu(HWND window)
{
HMENU menuBar = CreateMenu();
{ // File Menu
HMENU menu = CreatePopupMenu();
AppendMenu(menuBar, MF_STRING | MF_POPUP, (UINT_PTR)menu, "File");
AppendMenu(menu, MF_STRING, Win32Menu_FileOpen, "Open");
AppendMenu(menu, MF_STRING, Win32Menu_FileExit, "Exit");
}
SetMenu(window, menuBar);
}
FILE_SCOPE LRESULT CALLBACK Win32MainProcCallback(HWND window, UINT msg,
WPARAM wParam, LPARAM lParam)
{
LRESULT result = 0;
switch (msg)
{
case WM_CREATE:
{
Win32CreateMenu(window);
}
break;
case WM_CLOSE:
case WM_DESTROY:
{
globalRunning = false;
}
break;
case WM_PAINT:
{
PAINTSTRUCT paint;
HDC deviceContext = BeginPaint(window, &paint);
LONG renderWidth, renderHeight;
DqnWin32_GetClientDim(window, &renderWidth, &renderHeight);
DqnV2 ratio = DqnV2_2i(globalRenderBitmap.width, globalRenderBitmap.height);
DqnV2 newDim = DqnV2_ConstrainToRatio(DqnV2_2i(renderWidth, renderHeight), ratio);
renderWidth = (LONG)newDim.w;
renderHeight = (LONG)newDim.h;
Win32DisplayRenderBitmap(globalRenderBitmap, deviceContext,
renderWidth, renderHeight);
EndPaint(window, &paint);
break;
}
default:
{
result = DefWindowProcW(window, msg, wParam, lParam);
}
break;
}
return result;
}
FILE_SCOPE inline void Win32UpdateKey(KeyState *key, bool isDown)
{
if (key->endedDown != isDown)
{
key->endedDown = isDown;
key->halfTransitionCount++;
}
}
FILE_SCOPE void Win32HandleMenuMessages(HWND window, MSG msg,
PlatformInput *input)
{
switch (LOWORD(msg.wParam))
{
case Win32Menu_FileExit:
{
globalRunning = false;
}
break;
case Win32Menu_FileOpen:
{
#if 0
wchar_t fileBuffer[MAX_PATH] = {};
OPENFILENAME openDialogInfo = {};
openDialogInfo.lStructSize = sizeof(OPENFILENAME);
openDialogInfo.hwndOwner = window;
openDialogInfo.lpstrFile = fileBuffer;
openDialogInfo.nMaxFile = DQN_ARRAY_COUNT(fileBuffer);
openDialogInfo.Flags = OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST;
if (GetOpenFileName(&openDialogInfo) != 0)
{
}
#endif
}
break;
default:
{
DQN_ASSERT(DQN_INVALID_CODE_PATH);
}
break;
}
}
FILE_SCOPE void Win32ProcessMessages(HWND window, PlatformInput *input)
{
MSG msg;
while (PeekMessage(&msg, window, 0, 0, PM_REMOVE))
{
switch (msg.message)
{
case WM_COMMAND:
{
Win32HandleMenuMessages(window, msg, input);
}
break;
case WM_SYSKEYDOWN:
case WM_SYSKEYUP:
case WM_KEYDOWN:
case WM_KEYUP:
{
bool isDown = (msg.message == WM_KEYDOWN);
switch (msg.wParam)
{
case VK_UP: Win32UpdateKey(&input->up, isDown); break;
case VK_DOWN: Win32UpdateKey(&input->down, isDown); break;
case VK_LEFT: Win32UpdateKey(&input->left, isDown); break;
case VK_RIGHT: Win32UpdateKey(&input->right, isDown); break;
case '1': Win32UpdateKey(&input->key_1, isDown); break;
case '2': Win32UpdateKey(&input->key_2, isDown); break;
case '3': Win32UpdateKey(&input->key_3, isDown); break;
case '4': Win32UpdateKey(&input->key_4, isDown); break;
case 'Q': Win32UpdateKey(&input->key_q, isDown); break;
case 'W': Win32UpdateKey(&input->key_w, isDown); break;
case 'E': Win32UpdateKey(&input->key_e, isDown); break;
case 'R': Win32UpdateKey(&input->key_r, isDown); break;
case 'A': Win32UpdateKey(&input->key_a, isDown); break;
case 'S': Win32UpdateKey(&input->key_s, isDown); break;
case 'D': Win32UpdateKey(&input->key_d, isDown); break;
case 'F': Win32UpdateKey(&input->key_f, isDown); break;
case 'Z': Win32UpdateKey(&input->key_z, isDown); break;
case 'X': Win32UpdateKey(&input->key_x, isDown); break;
case 'C': Win32UpdateKey(&input->key_c, isDown); break;
case 'V': Win32UpdateKey(&input->key_v, isDown); break;
case VK_ESCAPE:
{
Win32UpdateKey(&input->escape, isDown);
if (input->escape.endedDown) globalRunning = false;
}
break;
default: break;
}
}
break;
default:
{
TranslateMessage(&msg);
DispatchMessage(&msg);
};
}
}
}
int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPWSTR lpCmdLine, int nShowCmd)
{
////////////////////////////////////////////////////////////////////////////
// Initialise Win32 Window
////////////////////////////////////////////////////////////////////////////
WNDCLASSEXW wc =
{
sizeof(WNDCLASSEX),
CS_HREDRAW | CS_VREDRAW | CS_OWNDC,
Win32MainProcCallback,
0, // int cbClsExtra
0, // int cbWndExtra
hInstance,
LoadIcon(NULL, IDI_APPLICATION),
LoadCursor(NULL, IDC_ARROW),
GetSysColorBrush(COLOR_3DFACE),
L"", // LPCTSTR lpszMenuName
L"DRendererClass",
NULL, // HICON hIconSm
};
if (!RegisterClassExW(&wc))
{
DqnWin32_DisplayLastError("RegisterClassEx() failed.");
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.
const u32 MIN_WIDTH = 800;
const u32 MIN_HEIGHT = 600;
RECT rect = {};
rect.right = MIN_WIDTH;
rect.bottom = MIN_HEIGHT;
DWORD windowStyle =
WS_OVERLAPPEDWINDOW | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN;
AdjustWindowRect(&rect, windowStyle, true);
HWND mainWindow = CreateWindowExW(
WS_EX_COMPOSITED, wc.lpszClassName, L"DRenderer", windowStyle,
CW_USEDEFAULT, CW_USEDEFAULT, rect.right - rect.left,
rect.bottom - rect.top, nullptr, nullptr, hInstance, nullptr);
if (!mainWindow)
{
DqnWin32_DisplayLastError("CreateWindowEx() failed.");
return -1;
}
{ // Initialise the renderbitmap
BITMAPINFOHEADER header = {};
header.biSize = sizeof(BITMAPINFOHEADER);
header.biWidth = MIN_WIDTH;
header.biHeight = MIN_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;
globalRenderBitmap.info.bmiHeader = header;
globalRenderBitmap.width = header.biWidth;
globalRenderBitmap.height = header.biHeight;
globalRenderBitmap.bytesPerPixel = header.biBitCount / 8;
DQN_ASSERT(globalRenderBitmap.bytesPerPixel >= 1);
HDC deviceContext = GetDC(mainWindow);
globalRenderBitmap.handle = CreateDIBSection(
deviceContext, &globalRenderBitmap.info, DIB_RGB_COLORS,
&globalRenderBitmap.memory, NULL, NULL);
ReleaseDC(mainWindow, deviceContext);
}
if (!globalRenderBitmap.memory)
{
DqnWin32_DisplayLastError("CreateDIBSection() failed");
return -1;
}
////////////////////////////////////////////////////////////////////////////
// Update Loop
////////////////////////////////////////////////////////////////////////////
PlatformMemory platformMemory = {};
DQN_ASSERT(DqnMemBuffer_Init(&platformMemory.permanentBuffer, DQN_MEGABYTE(1), true, 4) &&
DqnMemBuffer_Init(&platformMemory.transientBuffer, DQN_MEGABYTE(1), true, 4));
const f32 TARGET_FRAMES_PER_S = 60.0f;
f32 targetSecondsPerFrame = 1 / TARGET_FRAMES_PER_S;
f64 frameTimeInS = 0.0f;
globalRunning = true;
SetWindowTextA(mainWindow, "test");
while (globalRunning)
{
////////////////////////////////////////////////////////////////////////
// Update State
////////////////////////////////////////////////////////////////////////
f64 startFrameTimeInS = DqnTime_NowInS();
{
PlatformInput platformInput = {};
platformInput.deltaForFrame = (f32)frameTimeInS;
Win32ProcessMessages(mainWindow, &platformInput);
PlatformRenderBuffer platformBuffer = {};
platformBuffer.memory = globalRenderBitmap.memory;
platformBuffer.height = globalRenderBitmap.height;
platformBuffer.width = globalRenderBitmap.width;
platformBuffer.bytesPerPixel = globalRenderBitmap.bytesPerPixel;
DR_Update(&platformBuffer, &platformInput, &platformMemory);
}
////////////////////////////////////////////////////////////////////////
// Rendering
////////////////////////////////////////////////////////////////////////
{
LONG renderWidth, renderHeight;
DqnWin32_GetClientDim(mainWindow, &renderWidth, &renderHeight);
DqnV2 ratio = DqnV2_2i(globalRenderBitmap.width, globalRenderBitmap.height);
DqnV2 newDim = DqnV2_ConstrainToRatio(DqnV2_2i(renderWidth, renderHeight), ratio);
renderWidth = (LONG)newDim.w;
renderHeight = (LONG)newDim.h;
HDC deviceContext = GetDC(mainWindow);
Win32DisplayRenderBitmap(globalRenderBitmap, deviceContext,
renderWidth, renderHeight);
ReleaseDC(mainWindow, deviceContext);
}
////////////////////////////////////////////////////////////////////////
// Frame Limiting
////////////////////////////////////////////////////////////////////////
{
f64 workTimeInS = DqnTime_NowInS() - startFrameTimeInS;
if (workTimeInS < targetSecondsPerFrame)
{
DWORD remainingTimeInMs =
(DWORD)((targetSecondsPerFrame - workTimeInS) * 1000);
Sleep(remainingTimeInMs);
}
}
frameTimeInS = DqnTime_NowInS() - startFrameTimeInS;
f32 msPerFrame = 1000.0f * (f32)frameTimeInS;
char windowTitleBuffer[128] = {};
Dqn_sprintf(windowTitleBuffer, "drenderer - dev - %5.2f ms/f",
msPerFrame);
SetWindowTextA(mainWindow, windowTitleBuffer);
#endif
}
return 0;
}

65
src/build.bat Normal file
View File

@ -0,0 +1,65 @@
@echo off
REM Build for Visual Studio compiler. Run your copy of vcvarsall.bat to setup command-line compiler.
REM Check if build tool is on path
REM >nul, 2>nul will remove the output text from the where command
where /q cl.exe
if %errorlevel%==1 (
echo MSVC CL not on path, please add it to path to build by command line.
goto end
)
REM Build tags file
ctags -R
set ProjectName=drenderer
ctime -begin ..\src\%ProjectName%.ctm
IF NOT EXIST ..\bin mkdir ..\bin
pushd ..\bin
REM ////////////////////////////////////////////////////////////////////////////
REM Compile Switches
REM ////////////////////////////////////////////////////////////////////////////
REM EHa- disable exception handling (we don't use)
REM GR- disable c runtime type information (we don't use)
REM MD use dynamic runtime library
REM MT use static runtime library, so build and link it into exe
REM Od disables optimisations
REM Oi enable intrinsics optimisation, let us use CPU intrinsics if there is one
REM instead of generating a call to external library (i.e. CRT).
REM Zi enables debug data, Z7 combines the debug files into one.
REM W4 warning level 4
REM WX treat warnings as errors
REM wd4100 unused argument parameters
REM wd4201 nonstandard extension used: nameless struct/union
REM wd4189 local variable is initialised but not referenced
REM wd4505 unreferenced local function not used will be removed
set CompileFlags=-EHa- -GR- -Oi -MT -Z7 -W4 -wd4100 -wd4201 -wd4189 -wd4505 -Od -FAsc
set Defines=
REM ////////////////////////////////////////////////////////////////////////////
REM Include Directories/Link Libraries
REM ////////////////////////////////////////////////////////////////////////////
set IncludeFiles=
REM Link libraries
set LinkLibraries=user32.lib kernel32.lib gdi32.lib
REM incremental:no, turn incremental builds off
REM opt:ref, try to remove functions from libs that are not referenced at all
set LinkFlags=-incremental:no -opt:ref -subsystem:WINDOWS -machine:x64 -nologo
REM ////////////////////////////////////////////////////////////////////////////
REM Compile
REM ////////////////////////////////////////////////////////////////////////////
cl %CompileFlags% %Defines% ..\src\UnityBuild\UnityBuild.cpp %IncludeFiles% /link %LinkLibraries% %LinkFlags% /out:%ProjectName%.exe
REM cl %CompileFlags% /P %Defines% ..\src\UnityBuild\UnityBuild.cpp %IncludeFiles%
popd
set LastError=%ERRORLEVEL%
ctime -end %ProjectName%.ctm %LastError%
:end
exit /b %LastError%

4632
src/dqn.h Normal file

File diff suppressed because it is too large Load Diff

BIN
src/drenderer.ctm Normal file

Binary file not shown.