Handmade Hero»Episode Guide
Platform-independent Debug File I/O
?
?

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)
01:26Overview of the two classes of game file I/O
01:26Overview of the two classes of game file I/O
01:26Overview of the two classes of game file I/O
05:30Today's goals (building a minimal set of I/O functions)
05:30Today's goals (building a minimal set of I/O functions)
05:30Today's goals (building a minimal set of I/O functions)
06:48A brief lesson on the sad history of file I/O
06:48A brief lesson on the sad history of file I/O
06:48A brief lesson on the sad history of file I/O
12:40The modern and better way of handling files
12:40The modern and better way of handling files
12:40The modern and better way of handling files
14:54A first pass at the usage code
14:54A first pass at the usage code
14:54A first pass at the usage code
18:56Locking our janky code out of the release build
18:56Locking our janky code out of the release build
18:56Locking our janky code out of the release build
22:01Implementing the I/O functions in the platform layer
22:01Implementing the I/O functions in the platform layer
22:01Implementing the I/O functions in the platform layer
23:46File handles and CreateFile() breakdown
23:46File handles and CreateFile() breakdown
23:46File handles and CreateFile() breakdown
29:07GetFileSize() and GetFileSizeEx()
29:07GetFileSize() and GetFileSizeEx()
29:07GetFileSize() and GetFileSizeEx()
35:03A janky situation with ReadFile()
35:03A janky situation with ReadFile()
35:03A janky situation with ReadFile()
37:07An inline function, SafeTruncateUInt64()
37:07An inline function, SafeTruncateUInt64()
37:07An inline function, SafeTruncateUInt64()
43:15Step-through of our read function
43:15Step-through of our read function
43:15Step-through of our read function
47:01Making a write based on the read function
47:01Making a write based on the read function
47:01Making a write based on the read function
50:19Using the write function
50:19Using the write function
50:19Using the write function
53:29Step-through of the write function
53:29Step-through of the write function
53:29Step-through of the write function
56:40Editing the .emacs file
56:40Editing the .emacs file
56:40Editing the .emacs file
58:27Breaking the .emacs file
58:27Breaking the .emacs file
58:27Breaking the .emacs file
1:00:19An IMPORTANT note on the safety of file I/O code
1:00:19An IMPORTANT note on the safety of file I/O code
1:00:19An IMPORTANT note on the safety of file I/O code
1:02:15Q&A
🗩
1:02:15Q&A
🗩
1:02:15Q&A
🗩
1:02:54Will the game be able to carry on in spite of some big time failure, like a graphics device reset. And does software rendering make that easier to deal with?
1:02:54Will the game be able to carry on in spite of some big time failure, like a graphics device reset. And does software rendering make that easier to deal with?
1:02:54Will the game be able to carry on in spite of some big time failure, like a graphics device reset. And does software rendering make that easier to deal with?
1:04:28Would it make sense to call normal GetFileSize() and then assert that the high 32-bit value is zero?
1:04:28Would it make sense to call normal GetFileSize() and then assert that the high 32-bit value is zero?
1:04:28Would it make sense to call normal GetFileSize() and then assert that the high 32-bit value is zero?
1:06:00Would it be useful for us to write our own allocation function that specifically allocates sections of our already-reserved temporary memory? I am having trouble understanding why we are doing separate allocations.
1:06:00Would it be useful for us to write our own allocation function that specifically allocates sections of our already-reserved temporary memory? I am having trouble understanding why we are doing separate allocations.
1:06:00Would it be useful for us to write our own allocation function that specifically allocates sections of our already-reserved temporary memory? I am having trouble understanding why we are doing separate allocations.
1:07:54Will we implement some kind of cloud storage for the writes?
1:07:54Will we implement some kind of cloud storage for the writes?
1:07:54Will we implement some kind of cloud storage for the writes?
1:08:55I know you removed it for now, but wouldn't a reserve memory method with an arbitrary size still introduce a failure point since it could fail like VirtualAlloc() and we have simply moved the burden onto ourselves?
1:08:55I know you removed it for now, but wouldn't a reserve memory method with an arbitrary size still introduce a failure point since it could fail like VirtualAlloc() and we have simply moved the burden onto ourselves?
1:08:55I know you removed it for now, but wouldn't a reserve memory method with an arbitrary size still introduce a failure point since it could fail like VirtualAlloc() and we have simply moved the burden onto ourselves?
1:09:59You can reload your emacs settings without blowing everything up each time with evalbuffer.
1:09:59You can reload your emacs settings without blowing everything up each time with evalbuffer.
1:09:59You can reload your emacs settings without blowing everything up each time with evalbuffer.
1:10:55Are there any other benefits to doing one massive allocation, aside from having one failure point. Also does the order of properties in your structs matter when it comes to performance efficiency?
1:10:55Are there any other benefits to doing one massive allocation, aside from having one failure point. Also does the order of properties in your structs matter when it comes to performance efficiency?
1:10:55Are there any other benefits to doing one massive allocation, aside from having one failure point. Also does the order of properties in your structs matter when it comes to performance efficiency?
1:16:00Do games really usually write to a second file rather than using some soft of safe write function that won't overwrite it if it somehow fails?
1:16:00Do games really usually write to a second file rather than using some soft of safe write function that won't overwrite it if it somehow fails?
1:16:00Do games really usually write to a second file rather than using some soft of safe write function that won't overwrite it if it somehow fails?
1:17:31Do you miss multiple return values in C?
1:17:31Do you miss multiple return values in C?
1:17:31Do you miss multiple return values in C?
1:18:30Why don't we just map the file into memory?
1:18:30Why don't we just map the file into memory?
1:18:30Why don't we just map the file into memory?
1:19:19Will allocating a single amount of memory up front make it more difficult to selectively enable/disable certain features of the game, since there could be many combinations, each requiring different amounts of memory?
1:19:19Will allocating a single amount of memory up front make it more difficult to selectively enable/disable certain features of the game, since there could be many combinations, each requiring different amounts of memory?
1:19:19Will allocating a single amount of memory up front make it more difficult to selectively enable/disable certain features of the game, since there could be many combinations, each requiring different amounts of memory?
1:20:32Why does the order of fake_struct_a and b matter?
1:20:32Why does the order of fake_struct_a and b matter?
1:20:32Why does the order of fake_struct_a and b matter?
1:21:10Why did you do the byte macros, but hesitate on the swap? Is there some hidden complexity on pointer swaps?
1:21:10Why did you do the byte macros, but hesitate on the swap? Is there some hidden complexity on pointer swaps?
1:21:10Why did you do the byte macros, but hesitate on the swap? Is there some hidden complexity on pointer swaps?
1:24:35So structs with unions in them have bad performance issues?
1:24:35So structs with unions in them have bad performance issues?
1:24:35So structs with unions in them have bad performance issues?
1:25:11You mentioned IOCP (I/O Completion Ports) for async file I/O. Are you planning to use multiple worker threads? I've been doing some multithreaded epoll code on Linux, and it's a very janky API unless you're using one worker thread. There are even a few articles on LWN.net only about how to safely remove a file descriptor with epoll.
1:25:11You mentioned IOCP (I/O Completion Ports) for async file I/O. Are you planning to use multiple worker threads? I've been doing some multithreaded epoll code on Linux, and it's a very janky API unless you're using one worker thread. There are even a few articles on LWN.net only about how to safely remove a file descriptor with epoll.
1:25:11You mentioned IOCP (I/O Completion Ports) for async file I/O. Are you planning to use multiple worker threads? I've been doing some multithreaded epoll code on Linux, and it's a very janky API unless you're using one worker thread. There are even a few articles on LWN.net only about how to safely remove a file descriptor with epoll.
1:26:27On the swap, why does it have to be a macro. Wouldn't a function do the job and cover the janky complexity with types in the macro?
1:26:27On the swap, why does it have to be a macro. Wouldn't a function do the job and cover the janky complexity with types in the macro?
1:26:27On the swap, why does it have to be a macro. Wouldn't a function do the job and cover the janky complexity with types in the macro?
1:27:06Why don't you define the swap macro to be #define swap(a,b){ type_of(a) temp...?
1:27:06Why don't you define the swap macro to be #define swap(a,b){ type_of(a) temp...?
1:27:06Why don't you define the swap macro to be #define swap(a,b){ type_of(a) temp...?
1:27:33Does ArrayCount macro work with strings?
1:27:33Does ArrayCount macro work with strings?
1:27:33Does ArrayCount macro work with strings?
1:27:46Won Chun: Async file I/O in Linux is nutty.
1:27:46Won Chun: Async file I/O in Linux is nutty.
1:27:46Won Chun: Async file I/O in Linux is nutty.
1:28:13(Key Switches)Brown or blue?
1:28:13(Key Switches)Brown or blue?
1:28:13(Key Switches)Brown or blue?
1:28:53It (ArrayCount) actually works with string literals.
1:28:53It (ArrayCount) actually works with string literals.
1:28:53It (ArrayCount) actually works with string literals.