Add dll reloading
This commit is contained in:
parent
7f62ce23d0
commit
e6d198b232
@ -1,29 +0,0 @@
|
|||||||
|
|
||||||
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
|
|
@ -1,6 +1,22 @@
|
|||||||
|
#include "DRenderer.h"
|
||||||
|
|
||||||
#include "DRendererPlatform.h"
|
#include "DRendererPlatform.h"
|
||||||
|
|
||||||
void DR_Update(PlatformRenderBuffer *const renderBuffer,
|
extern "C" void DR_Update(PlatformRenderBuffer *const renderBuffer,
|
||||||
PlatformInput *const input, PlatformMemory *const memory)
|
PlatformInput *const input,
|
||||||
|
PlatformMemory *const memory)
|
||||||
{
|
{
|
||||||
|
u32 *bitmapPtr = (u32 *)renderBuffer->memory;
|
||||||
|
for (i32 y = 0; y < renderBuffer->height; y++)
|
||||||
|
{
|
||||||
|
for (i32 x = 0; x < renderBuffer->width; x++)
|
||||||
|
{
|
||||||
|
u8 red = 255;
|
||||||
|
u8 green = 0;
|
||||||
|
u8 blue = 0;
|
||||||
|
|
||||||
|
u32 color = (red << 16) | (green << 8) | (blue << 0);
|
||||||
|
bitmapPtr[x + (y * renderBuffer->width)] = color;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,7 @@
|
|||||||
#ifndef DRENDERER_H
|
#ifndef DRENDERER_H
|
||||||
#define DRENDERER_H
|
#define DRENDERER_H
|
||||||
|
|
||||||
void DR_Update(struct PlatformRenderBuffer *const renderBuffer,
|
typedef void DR_UpdateFunction(struct PlatformRenderBuffer *const renderBuffer,
|
||||||
struct PlatformInput *const input,
|
struct PlatformInput *const input,
|
||||||
struct PlatformMemory *const memory);
|
struct PlatformMemory *const memory);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -44,9 +44,6 @@ typedef struct PlatformInput
|
|||||||
{
|
{
|
||||||
f32 deltaForFrame;
|
f32 deltaForFrame;
|
||||||
|
|
||||||
bool loadNewRom;
|
|
||||||
wchar_t rom[260];
|
|
||||||
|
|
||||||
union {
|
union {
|
||||||
KeyState key[key_count];
|
KeyState key[key_count];
|
||||||
struct
|
struct
|
||||||
@ -91,6 +88,8 @@ typedef struct PlatformRenderBuffer
|
|||||||
i32 width;
|
i32 width;
|
||||||
i32 height;
|
i32 height;
|
||||||
i32 bytesPerPixel;
|
i32 bytesPerPixel;
|
||||||
|
|
||||||
|
// Pixel Format: XX RR GG BB
|
||||||
void *memory;
|
void *memory;
|
||||||
} PlatformRenderBuffer;
|
} PlatformRenderBuffer;
|
||||||
|
|
||||||
|
@ -1,2 +1 @@
|
|||||||
#include "..\DRenderer.cpp"
|
#include "..\DRenderer.cpp"
|
||||||
#include "..\Win32DRenderer.cpp"
|
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
#define UNICODE
|
#define UNICODE
|
||||||
#define _UNICODE
|
#define _UNICODE
|
||||||
|
|
||||||
|
#include <Pathcch.h>
|
||||||
#include <Windows.h>
|
#include <Windows.h>
|
||||||
typedef struct Win32RenderBitmap
|
typedef struct Win32RenderBitmap
|
||||||
{
|
{
|
||||||
@ -22,33 +23,13 @@ typedef struct Win32RenderBitmap
|
|||||||
FILE_SCOPE Win32RenderBitmap globalRenderBitmap;
|
FILE_SCOPE Win32RenderBitmap globalRenderBitmap;
|
||||||
FILE_SCOPE bool globalRunning;
|
FILE_SCOPE bool globalRunning;
|
||||||
|
|
||||||
FILE_SCOPE void Win32DisplayRenderBitmap(Win32RenderBitmap renderBitmap,
|
typedef struct Win32ExternalCode
|
||||||
HDC deviceContext, LONG width,
|
|
||||||
LONG height)
|
|
||||||
{
|
{
|
||||||
HDC stretchDC = CreateCompatibleDC(deviceContext);
|
HMODULE dll;
|
||||||
SelectObject(stretchDC, renderBitmap.handle);
|
FILETIME lastWriteTime;
|
||||||
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
|
DR_UpdateFunction *DR_Update;
|
||||||
// with alpha.
|
} Win32ExternalCode;
|
||||||
#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
|
enum Win32Menu
|
||||||
{
|
{
|
||||||
@ -56,6 +37,62 @@ enum Win32Menu
|
|||||||
Win32Menu_FileExit,
|
Win32Menu_FileExit,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
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);
|
||||||
|
DeleteDC(stretchDC);
|
||||||
|
}
|
||||||
|
|
||||||
|
FILETIME Win32GetLastWriteTime(const char *const srcName)
|
||||||
|
{
|
||||||
|
WIN32_FIND_DATA findData = {};
|
||||||
|
FILETIME lastWriteTime = {};
|
||||||
|
HANDLE findHandle = FindFirstFileA(srcName, &findData);
|
||||||
|
if (findHandle != INVALID_HANDLE_VALUE)
|
||||||
|
{
|
||||||
|
lastWriteTime = findData.ftLastWriteTime;
|
||||||
|
FindClose(findHandle);
|
||||||
|
}
|
||||||
|
|
||||||
|
return lastWriteTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
FILE_SCOPE Win32ExternalCode Win32LoadExternalDLL(const char *const srcPath,
|
||||||
|
const char *const tmpPath,
|
||||||
|
const FILETIME lastWriteTime)
|
||||||
|
{
|
||||||
|
Win32ExternalCode result = {};
|
||||||
|
result.lastWriteTime = lastWriteTime;
|
||||||
|
CopyFile(srcPath, tmpPath, false);
|
||||||
|
|
||||||
|
DR_UpdateFunction *updateFunction = NULL;
|
||||||
|
result.dll = LoadLibraryA(tmpPath);
|
||||||
|
if (result.dll)
|
||||||
|
{
|
||||||
|
updateFunction =
|
||||||
|
(DR_UpdateFunction *)GetProcAddress(result.dll, "DR_Update");
|
||||||
|
if (updateFunction) result.DR_Update = updateFunction;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
FILE_SCOPE void Win32UnloadExternalDLL(Win32ExternalCode *externalCode)
|
||||||
|
{
|
||||||
|
|
||||||
|
if (externalCode->dll) FreeLibrary(externalCode->dll);
|
||||||
|
externalCode->dll = NULL;
|
||||||
|
externalCode->DR_Update = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
FILE_SCOPE void Win32CreateMenu(HWND window)
|
FILE_SCOPE void Win32CreateMenu(HWND window)
|
||||||
{
|
{
|
||||||
HMENU menuBar = CreateMenu();
|
HMENU menuBar = CreateMenu();
|
||||||
@ -229,6 +266,35 @@ FILE_SCOPE void Win32ProcessMessages(HWND window, PlatformInput *input)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Return the index of the last slash
|
||||||
|
i32 Win32GetModuleDirectory(char *const buf, const u32 bufLen)
|
||||||
|
{
|
||||||
|
if (!buf || bufLen == 0) return 0;
|
||||||
|
u32 copiedLen = GetModuleFileName(NULL, buf, bufLen);
|
||||||
|
if (copiedLen == bufLen)
|
||||||
|
{
|
||||||
|
DQN_WIN32_ERROR_BOX(
|
||||||
|
"GetModuleFileName() buffer maxed: Len of copied text is len "
|
||||||
|
"of supplied buffer.",
|
||||||
|
NULL);
|
||||||
|
DQN_ASSERT(DQN_INVALID_CODE_PATH);
|
||||||
|
}
|
||||||
|
|
||||||
|
// NOTE: Should always work if GetModuleFileName works and we're running an
|
||||||
|
// executable.
|
||||||
|
i32 lastSlashIndex = 0;
|
||||||
|
for (i32 i = copiedLen; i > 0; i--)
|
||||||
|
{
|
||||||
|
if (buf[i] == '\\')
|
||||||
|
{
|
||||||
|
lastSlashIndex = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return lastSlashIndex;
|
||||||
|
}
|
||||||
|
|
||||||
int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
|
int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
|
||||||
LPWSTR lpCmdLine, int nShowCmd)
|
LPWSTR lpCmdLine, int nShowCmd)
|
||||||
{
|
{
|
||||||
@ -268,14 +334,13 @@ int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
|
|||||||
RECT rect = {};
|
RECT rect = {};
|
||||||
rect.right = MIN_WIDTH;
|
rect.right = MIN_WIDTH;
|
||||||
rect.bottom = MIN_HEIGHT;
|
rect.bottom = MIN_HEIGHT;
|
||||||
DWORD windowStyle =
|
DWORD windowStyle = WS_OVERLAPPEDWINDOW | WS_VISIBLE;
|
||||||
WS_OVERLAPPEDWINDOW | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN;
|
|
||||||
AdjustWindowRect(&rect, windowStyle, true);
|
AdjustWindowRect(&rect, windowStyle, true);
|
||||||
|
|
||||||
HWND mainWindow = CreateWindowExW(
|
HWND mainWindow = CreateWindowExW(
|
||||||
WS_EX_COMPOSITED, wc.lpszClassName, L"DRenderer", windowStyle,
|
0, wc.lpszClassName, L"DRenderer", windowStyle, CW_USEDEFAULT,
|
||||||
CW_USEDEFAULT, CW_USEDEFAULT, rect.right - rect.left,
|
CW_USEDEFAULT, rect.right - rect.left, rect.bottom - rect.top, nullptr,
|
||||||
rect.bottom - rect.top, nullptr, nullptr, hInstance, nullptr);
|
nullptr, hInstance, nullptr);
|
||||||
|
|
||||||
if (!mainWindow)
|
if (!mainWindow)
|
||||||
{
|
{
|
||||||
@ -291,11 +356,6 @@ int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
|
|||||||
header.biPlanes = 1;
|
header.biPlanes = 1;
|
||||||
header.biBitCount = 32;
|
header.biBitCount = 32;
|
||||||
header.biCompression = BI_RGB; // uncompressed bitmap
|
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.info.bmiHeader = header;
|
||||||
globalRenderBitmap.width = header.biWidth;
|
globalRenderBitmap.width = header.biWidth;
|
||||||
@ -315,6 +375,26 @@ int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
|
|||||||
DqnWin32_DisplayLastError("CreateDIBSection() failed");
|
DqnWin32_DisplayLastError("CreateDIBSection() failed");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Make DLL Path
|
||||||
|
////////////////////////////////////////////////////////////////////////////
|
||||||
|
Win32ExternalCode dllCode = {};
|
||||||
|
char dllPath[MAX_PATH] = {};
|
||||||
|
char dllTmpPath[MAX_PATH] = {};
|
||||||
|
{
|
||||||
|
char exeDir[MAX_PATH] = {};
|
||||||
|
i32 lastSlashIndex =
|
||||||
|
Win32GetModuleDirectory(exeDir, DQN_ARRAY_COUNT(exeDir));
|
||||||
|
DQN_ASSERT(lastSlashIndex + 1 < DQN_ARRAY_COUNT(exeDir));
|
||||||
|
|
||||||
|
exeDir[lastSlashIndex + 1] = 0;
|
||||||
|
u32 numCopied = Dqn_sprintf(dllPath, "%s%s", exeDir, "drenderer.dll");
|
||||||
|
DQN_ASSERT(numCopied < DQN_ARRAY_COUNT(dllPath));
|
||||||
|
|
||||||
|
numCopied =
|
||||||
|
Dqn_sprintf(dllTmpPath, "%s%s", exeDir, "drenderer_temp.dll");
|
||||||
|
DQN_ASSERT(numCopied < DQN_ARRAY_COUNT(dllPath));
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////
|
||||||
// Update Loop
|
// Update Loop
|
||||||
@ -328,13 +408,20 @@ int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
|
|||||||
f64 frameTimeInS = 0.0f;
|
f64 frameTimeInS = 0.0f;
|
||||||
globalRunning = true;
|
globalRunning = true;
|
||||||
|
|
||||||
SetWindowTextA(mainWindow, "test");
|
|
||||||
while (globalRunning)
|
while (globalRunning)
|
||||||
{
|
{
|
||||||
////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////
|
||||||
// Update State
|
// Update State
|
||||||
////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////
|
||||||
f64 startFrameTimeInS = DqnTime_NowInS();
|
f64 startFrameTimeInS = DqnTime_NowInS();
|
||||||
|
|
||||||
|
FILETIME lastWriteTime = Win32GetLastWriteTime(dllPath);
|
||||||
|
if (CompareFileTime(&lastWriteTime, &dllCode.lastWriteTime) != 0)
|
||||||
|
{
|
||||||
|
Win32UnloadExternalDLL(&dllCode);
|
||||||
|
dllCode = Win32LoadExternalDLL(dllPath, dllTmpPath, lastWriteTime);
|
||||||
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
PlatformInput platformInput = {};
|
PlatformInput platformInput = {};
|
||||||
platformInput.deltaForFrame = (f32)frameTimeInS;
|
platformInput.deltaForFrame = (f32)frameTimeInS;
|
||||||
@ -345,7 +432,12 @@ int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
|
|||||||
platformBuffer.height = globalRenderBitmap.height;
|
platformBuffer.height = globalRenderBitmap.height;
|
||||||
platformBuffer.width = globalRenderBitmap.width;
|
platformBuffer.width = globalRenderBitmap.width;
|
||||||
platformBuffer.bytesPerPixel = globalRenderBitmap.bytesPerPixel;
|
platformBuffer.bytesPerPixel = globalRenderBitmap.bytesPerPixel;
|
||||||
DR_Update(&platformBuffer, &platformInput, &platformMemory);
|
|
||||||
|
if (dllCode.DR_Update)
|
||||||
|
{
|
||||||
|
dllCode.DR_Update(&platformBuffer, &platformInput,
|
||||||
|
&platformMemory);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////
|
||||||
@ -386,7 +478,6 @@ int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
|
|||||||
Dqn_sprintf(windowTitleBuffer, "drenderer - dev - %5.2f ms/f",
|
Dqn_sprintf(windowTitleBuffer, "drenderer - dev - %5.2f ms/f",
|
||||||
msPerFrame);
|
msPerFrame);
|
||||||
SetWindowTextA(mainWindow, windowTitleBuffer);
|
SetWindowTextA(mainWindow, windowTitleBuffer);
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -37,12 +37,9 @@ REM wd4201 nonstandard extension used: nameless struct/union
|
|||||||
REM wd4189 local variable is initialised but not referenced
|
REM wd4189 local variable is initialised but not referenced
|
||||||
REM wd4505 unreferenced local function not used will be removed
|
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 CompileFlags=-EHa- -GR- -Oi -MT -Z7 -W4 -wd4100 -wd4201 -wd4189 -wd4505 -Od -FAsc
|
||||||
set Defines=
|
set DLLFlags=/Fm%ProjectName% /Fo%ProjectName% /Fa%ProjectName% /Fe%ProjectName%
|
||||||
|
set Win32Flags=/FmWin32DRenderer /FeWin32DRenderer
|
||||||
REM ////////////////////////////////////////////////////////////////////////////
|
set TimeStamp=%date:~10,4%%date:~7,2%%date:~4,2%_%time:~0,2%%time:~3,2%%time:~6,2%
|
||||||
REM Include Directories/Link Libraries
|
|
||||||
REM ////////////////////////////////////////////////////////////////////////////
|
|
||||||
set IncludeFiles=
|
|
||||||
|
|
||||||
REM Link libraries
|
REM Link libraries
|
||||||
set LinkLibraries=user32.lib kernel32.lib gdi32.lib
|
set LinkLibraries=user32.lib kernel32.lib gdi32.lib
|
||||||
@ -54,9 +51,9 @@ set LinkFlags=-incremental:no -opt:ref -subsystem:WINDOWS -machine:x64 -nologo
|
|||||||
REM ////////////////////////////////////////////////////////////////////////////
|
REM ////////////////////////////////////////////////////////////////////////////
|
||||||
REM Compile
|
REM Compile
|
||||||
REM ////////////////////////////////////////////////////////////////////////////
|
REM ////////////////////////////////////////////////////////////////////////////
|
||||||
cl %CompileFlags% %Defines% ..\src\UnityBuild\UnityBuild.cpp %IncludeFiles% /link %LinkLibraries% %LinkFlags% /out:%ProjectName%.exe
|
del *.pdb >NUL 2>NUL
|
||||||
REM cl %CompileFlags% /P %Defines% ..\src\UnityBuild\UnityBuild.cpp %IncludeFiles%
|
cl %CompileFlags% %Win32Flags% ..\src\Win32DRenderer.cpp /link %LinkLibraries% %LinkFlags%
|
||||||
|
cl %CompileFlags% %DLLFlags% ..\src\UnityBuild\UnityBuild.cpp /LD /link /PDB:%ProjectName%_%TimeStamp%.pdb /export:DR_Update %LinkFlags%
|
||||||
popd
|
popd
|
||||||
set LastError=%ERRORLEVEL%
|
set LastError=%ERRORLEVEL%
|
||||||
ctime -end %ProjectName%.ctm %LastError%
|
ctime -end %ProjectName%.ctm %LastError%
|
||||||
|
Loading…
Reference in New Issue
Block a user