Handmade Hero»Episode Guide
Removing the CRT from the Win32 Loader
?
?

Keyboard Navigation

Global Keys

[, < / ], > Jump to previous / next episode
W, K, P / S, J, N Jump to previous / next marker
t / T Toggle theatre / SUPERtheatre mode
V Revert filter to original state Y Select link (requires manual Ctrl-c)

Menu toggling

q Quotes r References f Filter y Link c Credits

In-Menu Movement

a
w
s
d
h j k l


Quotes and References Menus

Enter Jump to timecode

Quotes, References and Credits Menus

o Open URL (in new tab)

Filter Menu

x, Space Toggle category and focus next
X, ShiftSpace Toggle category and focus previous
v Invert topics / media as per focus

Filter and Link Menus

z Toggle filter / linking mode

Credits Menu

Enter Open URL (in new tab)
0:06Recap and set the stage for the day removing the C Runtime Library
🗩
0:06Recap and set the stage for the day removing the C Runtime Library
🗩
0:06Recap and set the stage for the day removing the C Runtime Library
🗩
0:52Read our linker flags in build.bat
📖
0:52Read our linker flags in build.bat
📖
0:52Read our linker flags in build.bat
📖
3:02Inspect our executable in depends1 to see what we're linking with
🗹
3:02Inspect our executable in depends1 to see what we're linking with
🗹
3:02Inspect our executable in depends1 to see what we're linking with
🗹
7:54Replace the -MTd switch with -MD in our CommonCompilerFlags2
7:54Replace the -MTd switch with -MD in our CommonCompilerFlags2
7:54Replace the -MTd switch with -MD in our CommonCompilerFlags2
10:54Inspect this executable in depends to see VCRUNTIME140.DLL in there
🗹
10:54Inspect this executable in depends to see VCRUNTIME140.DLL in there
🗹
10:54Inspect this executable in depends to see VCRUNTIME140.DLL in there
🗹
14:00NODEFAULTLIB3
📖
14:00NODEFAULTLIB3
📖
14:00NODEFAULTLIB3
📖
15:12Add /NODEFAULTLIB to our 64-bit win32_handmade.cpp compilation line and move -MTd down to there
15:12Add /NODEFAULTLIB to our 64-bit win32_handmade.cpp compilation line and move -MTd down to there
15:12Add /NODEFAULTLIB to our 64-bit win32_handmade.cpp compilation line and move -MTd down to there
17:28On the trend of compilers to essentially try and force the use of the CRT, and how to get around this
💢
🗩
17:28On the trend of compilers to essentially try and force the use of the CRT, and how to get around this
💢
🗩
17:28On the trend of compilers to essentially try and force the use of the CRT, and how to get around this
💢
🗩
19:20Determine which functions from the CRT we need to replace
📖
19:20Determine which functions from the CRT we need to replace
📖
19:20Determine which functions from the CRT we need to replace
📖
21:56Read 'How to avoid C/C++ runtime on Windows' by mmozeiko4 on allocating large arrays / structures on stack (>4KB)
📖
21:56Read 'How to avoid C/C++ runtime on Windows' by mmozeiko4 on allocating large arrays / structures on stack (>4KB)
📖
21:56Read 'How to avoid C/C++ runtime on Windows' by mmozeiko4 on allocating large arrays / structures on stack (>4KB)
📖
31:04Add -STACK:0x100000,0x100000, -GS- and -Gs9999999 to our CommonCompilerFlags5,6
31:04Add -STACK:0x100000,0x100000, -GS- and -Gs9999999 to our CommonCompilerFlags5,6
31:04Add -STACK:0x100000,0x100000, -GS- and -Gs9999999 to our CommonCompilerFlags5,6
35:55Grab the function signature of memset() from vcruntime_string.h, and write our own implementation in a new file using #pragma intrinsic7
35:55Grab the function signature of memset() from vcruntime_string.h, and write our own implementation in a new file using #pragma intrinsic7
35:55Grab the function signature of memset() from vcruntime_string.h, and write our own implementation in a new file using #pragma intrinsic7
46:36Change our memset() to use #pragma function8
46:36Change our memset() to use #pragma function8
46:36Change our memset() to use #pragma function8
48:15Hunt for _fltused in the CRT
📖
48:15Hunt for _fltused in the CRT
📖
48:15Hunt for _fltused in the CRT
📖
50:57Grab the int _fltused from fltused.cpp
50:57Grab the int _fltused from fltused.cpp
50:57Grab the int _fltused from fltused.cpp
52:14Find WinMainCRTStartup
📖
52:14Find WinMainCRTStartup
📖
52:14Find WinMainCRTStartup
📖
58:52Pull in the declaration of WinMainCRTStartup
58:52Pull in the declaration of WinMainCRTStartup
58:52Pull in the declaration of WinMainCRTStartup
1:02:02Read about the /ENTRY9 and /SUBSYSTEM10 flags
📖
1:02:02Read about the /ENTRY9 and /SUBSYSTEM10 flags
📖
1:02:02Read about the /ENTRY9 and /SUBSYSTEM10 flags
📖
1:04:31Add /SUBSYSTEM:windows to our win32_handmade.cpp compilation line
1:04:31Add /SUBSYSTEM:windows to our win32_handmade.cpp compilation line
1:04:31Add /SUBSYSTEM:windows to our win32_handmade.cpp compilation line
1:07:55Run the game to see that we're running just fine without the CRT
🏃
1:07:55Run the game to see that we're running just fine without the CRT
🏃
1:07:55Run the game to see that we're running just fine without the CRT
🏃
1:08:25Add /NODEFAULTLIB to our handmade.cpp compilation line and compile to see that we are only missing the transcendental mathematics functions, sinf(), cosf() and atan2f()
1:08:25Add /NODEFAULTLIB to our handmade.cpp compilation line and compile to see that we are only missing the transcendental mathematics functions, sinf(), cosf() and atan2f()
1:08:25Add /NODEFAULTLIB to our handmade.cpp compilation line and compile to see that we are only missing the transcendental mathematics functions, sinf(), cosf() and atan2f()
1:13:37Inspect the asm of cosf() with the determination to write our own
📖
1:13:37Inspect the asm of cosf() with the determination to write our own
📖
1:13:37Inspect the asm of cosf() with the determination to write our own
📖
1:15:54Why we did all of this: for sampling the hemisphere
1:15:54Why we did all of this: for sampling the hemisphere
1:15:54Why we did all of this: for sampling the hemisphere
1:16:53Remove /NODEFAULTLIB from our handmade.cpp compilation line for now
1:16:53Remove /NODEFAULTLIB from our handmade.cpp compilation line for now
1:16:53Remove /NODEFAULTLIB from our handmade.cpp compilation line for now
1:17:24Read through our hemisphere sampling code in ComputeLightPropagation()
📖
1:17:24Read through our hemisphere sampling code in ComputeLightPropagation()
📖
1:17:24Read through our hemisphere sampling code in ComputeLightPropagation()
📖
1:18:28Run the game to show our sampling debug visualisation
🏃
1:18:28Run the game to show our sampling debug visualisation
🏃
1:18:28Run the game to show our sampling debug visualisation
🏃
1:18:53Remove cruft – including EntropyCounter from lighting_solution – from the lighting code
1:18:53Remove cruft – including EntropyCounter from lighting_solution – from the lighting code
1:18:53Remove cruft – including EntropyCounter from lighting_solution – from the lighting code
1:20:56Run the game, hit Alt-F4 and note that the game is still running
🏃
1:20:56Run the game, hit Alt-F4 and note that the game is still running
🏃
1:20:56Run the game, hit Alt-F4 and note that the game is still running
🏃
1:21:46Make WinMainCRTStartup() call ExitProcess()
1:21:46Make WinMainCRTStartup() call ExitProcess()
1:21:46Make WinMainCRTStartup() call ExitProcess()
1:22:29Run the game, hit Alt-F4 and successfully exit out
🏃
1:22:29Run the game, hit Alt-F4 and successfully exit out
🏃
1:22:29Run the game, hit Alt-F4 and successfully exit out
🏃
1:22:45Investigate ceilf() and floorf() from our debug build
📖
1:22:45Investigate ceilf() and floorf() from our debug build
📖
1:22:45Investigate ceilf() and floorf() from our debug build
📖
1:26:13Crash in ComputeLightPropagation() and consult the asm to try and determine why
🏃
1:26:13Crash in ComputeLightPropagation() and consult the asm to try and determine why
🏃
1:26:13Crash in ComputeLightPropagation() and consult the asm to try and determine why
🏃
1:31:50Realise that threads initialised by us, subsequent to the first one initialised by Windows, were overflowing the stack11
🗩
1:31:50Realise that threads initialised by us, subsequent to the first one initialised by Windows, were overflowing the stack11
🗩
1:31:50Realise that threads initialised by us, subsequent to the first one initialised by Windows, were overflowing the stack11
🗩
1:36:18Make Win32MakeQueue() pass 1 megabyte as dwStackSize to CreateThread()
1:36:18Make Win32MakeQueue() pass 1 megabyte as dwStackSize to CreateThread()
1:36:18Make Win32MakeQueue() pass 1 megabyte as dwStackSize to CreateThread()
1:36:43Run the game and try to determine how much stack space ComputeLightPropagation() could need
🏃
1:36:43Run the game and try to determine how much stack space ComputeLightPropagation() could need
🏃
1:36:43Run the game and try to determine how much stack space ComputeLightPropagation() could need
🏃
1:47:08Note that our HitPointIndex is out of bounds, and investigate how
🏃
1:47:08Note that our HitPointIndex is out of bounds, and investigate how
🏃
1:47:08Note that our HitPointIndex is out of bounds, and investigate how
🏃
1:50:28Run the game until we crash in ComputeLightPropagation() and try to recover the HitBox and BoxSurfaceIndex information with help from the asm
🏃
1:50:28Run the game until we crash in ComputeLightPropagation() and try to recover the HitBox and BoxSurfaceIndex information with help from the asm
🏃
1:50:28Run the game until we crash in ComputeLightPropagation() and try to recover the HitBox and BoxSurfaceIndex information with help from the asm
🏃
1:57:32Investigate how BoxSurfaceIndex could get set to 6
📖
1:57:32Investigate how BoxSurfaceIndex could get set to 6
📖
1:57:32Investigate how BoxSurfaceIndex could get set to 6
📖
2:00:29Assert (unfortunately in the #if 0 code) in RayCast() that Positive == 1 or 0, and that BoxSurfaceIndex is less than 6
2:00:29Assert (unfortunately in the #if 0 code) in RayCast() that Positive == 1 or 0, and that BoxSurfaceIndex is less than 6
2:00:29Assert (unfortunately in the #if 0 code) in RayCast() that Positive == 1 or 0, and that BoxSurfaceIndex is less than 6
2:01:10Run the game until we crash
🏃
2:01:10Run the game until we crash
🏃
2:01:10Run the game until we crash
🏃
2:02:43Assert in the correct part of RayCast() that BoxSurfaceIndex is less that 6
2:02:43Assert in the correct part of RayCast() that BoxSurfaceIndex is less that 6
2:02:43Assert in the correct part of RayCast() that BoxSurfaceIndex is less that 6
2:05:46Run the game, hit the assertion on our third lane, and note that a BoxSurfaceIndex > 5 could be produced if a box has no size
🏃
2:05:46Run the game, hit the assertion on our third lane, and note that a BoxSurfaceIndex > 5 could be produced if a box has no size
🏃
2:05:46Run the game, hit the assertion on our third lane, and note that a BoxSurfaceIndex > 5 could be produced if a box has no size
🏃
2:16:10Make RayCast() keep a running total of box surface hits in a RunningMask in order to correctly determine the BoxSurfaceIndex()12
2:16:10Make RayCast() keep a running total of box surface hits in a RunningMask in order to correctly determine the BoxSurfaceIndex()12
2:16:10Make RayCast() keep a running total of box surface hits in a RunningMask in order to correctly determine the BoxSurfaceIndex()12
2:30:13Run the game and try unsuccessfully to trigger our BoxSurfaceIndex assertions
🏃
2:30:13Run the game and try unsuccessfully to trigger our BoxSurfaceIndex assertions
🏃
2:30:13Run the game and try unsuccessfully to trigger our BoxSurfaceIndex assertions
🏃
2:32:32Q&A
🗩
2:32:32Q&A
🗩
2:32:32Q&A
🗩
2:33:17desuused Q: Can we use six separate bits to represent hits with each box wall, then take the highest bit to determine which individual box hit we'll use? (see: _mm_lzcnt_epi3213)
🗪
2:33:17desuused Q: Can we use six separate bits to represent hits with each box wall, then take the highest bit to determine which individual box hit we'll use? (see: _mm_lzcnt_epi3213)
🗪
2:33:17desuused Q: Can we use six separate bits to represent hits with each box wall, then take the highest bit to determine which individual box hit we'll use? (see: _mm_lzcnt_epi3213)
🗪
2:37:00ginger_bill cmuratori, RETURN THE ORIGINAL DESTINATION!!!!!
🗪
2:37:00ginger_bill cmuratori, RETURN THE ORIGINAL DESTINATION!!!!!
🗪
2:37:00ginger_bill cmuratori, RETURN THE ORIGINAL DESTINATION!!!!!
🗪
2:37:22Make memset() return _Dst
2:37:22Make memset() return _Dst
2:37:22Make memset() return _Dst
2:38:21yurasniper Q: Would it be better to make hemisphere sampling visualization as an actual hemisphere with dots rendered on it?
🗪
2:38:21yurasniper Q: Would it be better to make hemisphere sampling visualization as an actual hemisphere with dots rendered on it?
🗪
2:38:21yurasniper Q: Would it be better to make hemisphere sampling visualization as an actual hemisphere with dots rendered on it?
🗪
2:38:46Reduce the length of the debug lines in LightingTest()
2:38:46Reduce the length of the debug lines in LightingTest()
2:38:46Reduce the length of the debug lines in LightingTest()
2:39:26Run the game to see this debug visualisation
🏃
2:39:26Run the game to see this debug visualisation
🏃
2:39:26Run the game to see this debug visualisation
🏃
2:40:01Make LightingTest() use PushCube() instead
2:40:01Make LightingTest() use PushCube() instead
2:40:01Make LightingTest() use PushCube() instead
2:42:06Run the game to see the cubes
🏃
2:42:06Run the game to see the cubes
🏃
2:42:06Run the game to see the cubes
🏃
2:42:31Enable LightingTest() to display a stationary sampling pattern
2:42:31Enable LightingTest() to display a stationary sampling pattern
2:42:31Enable LightingTest() to display a stationary sampling pattern
2:43:09Run the game to see the static debug visualisation
🏃
2:43:09Run the game to see the static debug visualisation
🏃
2:43:09Run the game to see the static debug visualisation
🏃
2:44:06mmozeiko Q: Why do you do *(unsigned char*)&_Val instead of (unsigned char)_Val in memset?
🗪
2:44:06mmozeiko Q: Why do you do *(unsigned char*)&_Val instead of (unsigned char)_Val in memset?
🗪
2:44:06mmozeiko Q: Why do you do *(unsigned char*)&_Val instead of (unsigned char)_Val in memset?
🗪
2:46:11areriff Q: Off-topic: What harm do you think could happen if you click on that yellow flag to upgrade MSVC? No breaking change has been introduce since this new machine, just lots of compiler upgrades
🗪
2:46:11areriff Q: Off-topic: What harm do you think could happen if you click on that yellow flag to upgrade MSVC? No breaking change has been introduce since this new machine, just lots of compiler upgrades
🗪
2:46:11areriff Q: Off-topic: What harm do you think could happen if you click on that yellow flag to upgrade MSVC? No breaking change has been introduce since this new machine, just lots of compiler upgrades
🗪
2:47:55filiadelski Q: Is the stack size set on the command line for the entire stack or for each stack frame?
🗪
2:47:55filiadelski Q: Is the stack size set on the command line for the entire stack or for each stack frame?
🗪
2:47:55filiadelski Q: Is the stack size set on the command line for the entire stack or for each stack frame?
🗪
2:48:35mmozeiko Q: Another thing to mention when using /stack to get 1MB stack vs 4kb probing, is that all threads also will have this stack size by default. It could be an issue if somebody is creating and keeping hundreds of threads live
🗪
2:48:35mmozeiko Q: Another thing to mention when using /stack to get 1MB stack vs 4kb probing, is that all threads also will have this stack size by default. It could be an issue if somebody is creating and keeping hundreds of threads live
🗪
2:48:35mmozeiko Q: Another thing to mention when using /stack to get 1MB stack vs 4kb probing, is that all threads also will have this stack size by default. It could be an issue if somebody is creating and keeping hundreds of threads live
🗪
2:48:59alexkelbo Q: Also you once said that in your projects you don't include windows.h and other windows-related h-files. How would we go about doing that?
🗪
2:48:59alexkelbo Q: Also you once said that in your projects you don't include windows.h and other windows-related h-files. How would we go about doing that?
🗪
2:48:59alexkelbo Q: Also you once said that in your projects you don't include windows.h and other windows-related h-files. How would we go about doing that?
🗪
2:49:49mextrox Q: I hope this is not too far off-topic. Recently I have thought about a hook-based execution / memory management system. Where when you allocate memory you can tell in the next line when it should be freed. There would be as many hooks as you like, for example: afterFrameHook or levelLoadHook or stuff like this. The hooks internally would be a collection of lambdas so they can capture the address that
🗪
2:49:49mextrox Q: I hope this is not too far off-topic. Recently I have thought about a hook-based execution / memory management system. Where when you allocate memory you can tell in the next line when it should be freed. There would be as many hooks as you like, for example: afterFrameHook or levelLoadHook or stuff like this. The hooks internally would be a collection of lambdas so they can capture the address that
🗪
2:49:49mextrox Q: I hope this is not too far off-topic. Recently I have thought about a hook-based execution / memory management system. Where when you allocate memory you can tell in the next line when it should be freed. There would be as many hooks as you like, for example: afterFrameHook or levelLoadHook or stuff like this. The hooks internally would be a collection of lambdas so they can capture the address that
🗪
2:51:30conspicoussquirrel Q: What are your thoughts on using macro's in C to make writing certain repeated patterns shorter? For example, encapsulating extremely common patterns like: #define DO(f,n) = for(int i = 0;i<n;i++)f;
🗪
2:51:30conspicoussquirrel Q: What are your thoughts on using macro's in C to make writing certain repeated patterns shorter? For example, encapsulating extremely common patterns like: #define DO(f,n) = for(int i = 0;i<n;i++)f;
🗪
2:51:30conspicoussquirrel Q: What are your thoughts on using macro's in C to make writing certain repeated patterns shorter? For example, encapsulating extremely common patterns like: #define DO(f,n) = for(int i = 0;i<n;i++)f;
🗪
2:52:24klemensbaum Q: Sorry off-topic, but since you worked at Microsoft, would you recommend working at Microsoft nowadays, for a new grad?
🗪
2:52:24klemensbaum Q: Sorry off-topic, but since you worked at Microsoft, would you recommend working at Microsoft nowadays, for a new grad?
🗪
2:52:24klemensbaum Q: Sorry off-topic, but since you worked at Microsoft, would you recommend working at Microsoft nowadays, for a new grad?
🗪
3:02:58wolverinegator Q: Do we still need a separate translation unit for the MSVC stuff? In my projects I had no problems having it in one unit
🗪
3:02:58wolverinegator Q: Do we still need a separate translation unit for the MSVC stuff? In my projects I had no problems having it in one unit
🗪
3:02:58wolverinegator Q: Do we still need a separate translation unit for the MSVC stuff? In my projects I had no problems having it in one unit
🗪
3:03:52nxsy So, if you’re joining FB, ask me. If google, ask quartertron. I’m sure there are more people in the community for the others
🗪
3:03:52nxsy So, if you’re joining FB, ask me. If google, ask quartertron. I’m sure there are more people in the community for the others
🗪
3:03:52nxsy So, if you’re joining FB, ask me. If google, ask quartertron. I’m sure there are more people in the community for the others
🗪
3:05:08naysayer88 cmuratori You are so jealous that I get to go to GDC next week and see all the great talks
🗪
3:05:08naysayer88 cmuratori You are so jealous that I get to go to GDC next week and see all the great talks
🗪
3:05:08naysayer88 cmuratori You are so jealous that I get to go to GDC next week and see all the great talks
🗪
3:06:40Close down with a reminder of mmozeiko's guide 'How to avoid C/C++ runtime on Windows'14
🗩
3:06:40Close down with a reminder of mmozeiko's guide 'How to avoid C/C++ runtime on Windows'14
🗩
3:06:40Close down with a reminder of mmozeiko's guide 'How to avoid C/C++ runtime on Windows'14
🗩