Handmade Hero»Episode Guide
Finishing HHT-Based Font Importing
?
?

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:02Recap and set the stage for the day
🗩
0:02Recap and set the stage for the day
🗩
0:02Recap and set the stage for the day
🗩
1:32Check out our NotImplemented routines
📖
1:32Check out our NotImplemented routines
📖
1:32Check out our NotImplemented routines
📖
2:34Implement the overloaded GetOrCreateAssetSourceFile() that takes a string, making the char * version call it
2:34Implement the overloaded GetOrCreateAssetSourceFile() that takes a string, making the char * version call it
2:34Implement the overloaded GetOrCreateAssetSourceFile() that takes a string, making the char * version call it
4:27Set up to implement ImportGlyph(), reacquainting ourselves with ParseTopLevelBlock() with a view to compressing it
📖
4:27Set up to implement ImportGlyph(), reacquainting ourselves with ParseTopLevelBlock() with a view to compressing it
📖
4:27Set up to implement ImportGlyph(), reacquainting ourselves with ParseTopLevelBlock() with a view to compressing it
📖
8:30Enable ImportGlyph() to open source PNG file based on code copied from ParseTopLevelBlock()
8:30Enable ImportGlyph() to open source PNG file based on code copied from ParseTopLevelBlock()
8:30Enable ImportGlyph() to open source PNG file based on code copied from ParseTopLevelBlock()
12:03Compress out the asset data updating code from ParseTopLevelBlock() into UpdateAssetDataFromFile()
12:03Compress out the asset data updating code from ParseTopLevelBlock() into UpdateAssetDataFromFile()
12:03Compress out the asset data updating code from ParseTopLevelBlock() into UpdateAssetDataFromFile()
23:04Remove ImportGlyph() in favour of making ParseFontBlock() perform that work itself
23:04Remove ImportGlyph() in favour of making ParseFontBlock() perform that work itself
23:04Remove ImportGlyph() in favour of making ParseFontBlock() perform that work itself
25:05Merge ProcesPlateImport() into ProcessSingleTileImport(), making the latter take a MaximumDim value
25:05Merge ProcesPlateImport() into ProcessSingleTileImport(), making the latter take a MaximumDim value
25:05Merge ProcesPlateImport() into ProcessSingleTileImport(), making the latter take a MaximumDim value
27:34Continue to implement ParseFontBlock(), calling UpdateAssetDataFromFile() and setting the BitmapID for each glyph
27:34Continue to implement ParseFontBlock(), calling UpdateAssetDataFromFile() and setting the BitmapID for each glyph
27:34Continue to implement ParseFontBlock(), calling UpdateAssetDataFromFile() and setting the BitmapID for each glyph
34:12Compress out the file matching code from ParseFontBlock() into FindMatchingFileFor(), for ParseTopLevelBlock() also to call
34:12Compress out the file matching code from ParseFontBlock() into FindMatchingFileFor(), for ParseTopLevelBlock() also to call
34:12Compress out the file matching code from ParseFontBlock() into FindMatchingFileFor(), for ParseTopLevelBlock() also to call
49:41Reflect on the state of our asset system with a view to testing the font importing
🗩
49:41Reflect on the state of our asset system with a view to testing the font importing
🗩
49:41Reflect on the state of our asset system with a view to testing the font importing
🗩
51:08Move the base_game.* and intro_cutscene.* files out of the way, and trigger a non-font asset rebuild
🏃
51:08Move the base_game.* and intro_cutscene.* files out of the way, and trigger a non-font asset rebuild
🏃
51:08Move the base_game.* and intro_cutscene.* files out of the way, and trigger a non-font asset rebuild
🏃
55:37clownoffire handmade_hero Are you having any issues with the debugger or is it okay even if it's an early version?
🗪
55:37clownoffire handmade_hero Are you having any issues with the debugger or is it okay even if it's an early version?
🗪
55:37clownoffire handmade_hero Are you having any issues with the debugger or is it okay even if it's an early version?
🗪
58:04Find that everything imported correctly
🏃
58:04Find that everything imported correctly
🏃
58:04Find that everything imported correctly
🏃
58:38Run in release mode to find that the sound is fine, with the determination to finish up dynamic loading of fonts
🏃
58:38Run in release mode to find that the sound is fine, with the determination to finish up dynamic loading of fonts
🏃
58:38Run in release mode to find that the sound is fine, with the determination to finish up dynamic loading of fonts
🏃
59:59Make ExtractFont() write out all our glyph information and set their alignment points
59:59Make ExtractFont() write out all our glyph information and set their alignment points
59:59Make ExtractFont() write out all our glyph information and set their alignment points
1:08:50Consider getting updated alignment points to flow to ParseFontBlock()
🗩
1:08:50Consider getting updated alignment points to flow to ParseFontBlock()
🗩
1:08:50Consider getting updated alignment points to flow to ParseFontBlock()
🗩
1:12:18Enable UpdateAssetDataFromFile() to update alignment points
1:12:18Enable UpdateAssetDataFromFile() to update alignment points
1:12:18Enable UpdateAssetDataFromFile() to update alignment points
1:14:22Understanding C's rightward-then-leftward parsing behaviour, and our ability to control it using parentheses
🗩
1:14:22Understanding C's rightward-then-leftward parsing behaviour, and our ability to control it using parentheses
🗩
1:14:22Understanding C's rightward-then-leftward parsing behaviour, and our ability to control it using parentheses
🗩
1:17:41Make ParseFontBlock() pass an hha_align_point array to UpdateAssetDataFromFile()
1:17:41Make ParseFontBlock() pass an hha_align_point array to UpdateAssetDataFromFile()
1:17:41Make ParseFontBlock() pass an hha_align_point array to UpdateAssetDataFromFile()
1:22:00Trigger a full .hha rebuild
🏃
1:22:00Trigger a full .hha rebuild
🏃
1:22:00Trigger a full .hha rebuild
🏃
1:23:13Find that the full rebuild succeeded
🏃
1:23:13Find that the full rebuild succeeded
🏃
1:23:13Find that the full rebuild succeeded
🏃
1:23:24Move testfonts_v2.* out of the way, trigger a font asset rebuild, and hit a remedybg crash
🏃
1:23:24Move testfonts_v2.* out of the way, trigger a font asset rebuild, and hit a remedybg crash
🏃
1:23:24Move testfonts_v2.* out of the way, trigger a font asset rebuild, and hit a remedybg crash
🏃
1:24:02Set up WinDBG as our just-in-time debugger1,2,3
🗹
1:24:02Set up WinDBG as our just-in-time debugger1,2,3
🗹
1:24:02Set up WinDBG as our just-in-time debugger1,2,3
🗹
1:33:02Click "Debug" and hit a "Visual Studio Just-In-Time Debugger" error
🗹
1:33:02Click "Debug" and hit a "Visual Studio Just-In-Time Debugger" error
🗹
1:33:02Click "Debug" and hit a "Visual Studio Just-In-Time Debugger" error
🗹
1:33:45Fix the path of WinDBG so that the root user can find it
🗹
1:33:45Fix the path of WinDBG so that the root user can find it
🗹
1:33:45Fix the path of WinDBG so that the root user can find it
🗹
1:34:43Trigger a font asset rebuild, reliably crash remedybg and save our mini-dump to send to George4
🗹
1:34:43Trigger a font asset rebuild, reliably crash remedybg and save our mini-dump to send to George4
🗹
1:34:43Trigger a font asset rebuild, reliably crash remedybg and save our mini-dump to send to George4
🗹
1:39:14Run win32_handmade in remedybg okay
🏃
1:39:14Run win32_handmade in remedybg okay
🏃
1:39:14Run win32_handmade in remedybg okay
🏃
1:39:56Step through SynchronizeAssetFileChanges() to see files being erroneously marked as modified
🏃
1:39:56Step through SynchronizeAssetFileChanges() to see files being erroneously marked as modified
🏃
1:39:56Step through SynchronizeAssetFileChanges() to see files being erroneously marked as modified
🏃
1:40:58Regenerate our glyph PNGs using hhafont and organise them into our directory structure
🗹
1:40:58Regenerate our glyph PNGs using hhafont and organise them into our directory structure
🗹
1:40:58Regenerate our glyph PNGs using hhafont and organise them into our directory structure
🗹
1:45:04#include LiberationMono.hht in base_game.hht
🗹
1:45:04#include LiberationMono.hht in base_game.hht
🗹
1:45:04#include LiberationMono.hht in base_game.hht
🗹
1:46:54Step through ParseHHT() on the included LiberationMono.hht
🏃
1:46:54Step through ParseHHT() on the included LiberationMono.hht
🏃
1:46:54Step through ParseHHT() on the included LiberationMono.hht
🏃
1:48:24Add a ParseFontBlock() call to ParseHHT()
1:48:24Add a ParseFontBlock() call to ParseHHT()
1:48:24Add a ParseFontBlock() call to ParseHHT()
1:48:53Step through ParseFontBlock(), to find that we encounter a parsing error
🏃
1:48:53Step through ParseFontBlock(), to find that we encounter a parsing error
🏃
1:48:53Step through ParseFontBlock(), to find that we encounter a parsing error
🏃
1:50:02Fix ParseFontBlock() to treat the FontName syntactically as a string
1:50:02Fix ParseFontBlock() to treat the FontName syntactically as a string
1:50:02Fix ParseFontBlock() to treat the FontName syntactically as a string
1:52:28Continue to step through ParseFontBlock() to find that the Glyph syntax is parsed incorrectly
🏃
1:52:28Continue to step through ParseFontBlock() to find that the Glyph syntax is parsed incorrectly
🏃
1:52:28Continue to step through ParseFontBlock() to find that the Glyph syntax is parsed incorrectly
🏃
1:55:30Enable ParseFontBlock() to handle more correctly our desired Glyph syntax
1:55:30Enable ParseFontBlock() to handle more correctly our desired Glyph syntax
1:55:30Enable ParseFontBlock() to handle more correctly our desired Glyph syntax
1:56:20Continue to step through ParseFontBlock() to find that the Glyph syntax parsing is a little incorrect
🏃
1:56:20Continue to step through ParseFontBlock() to find that the Glyph syntax parsing is a little incorrect
🏃
1:56:20Continue to step through ParseFontBlock() to find that the Glyph syntax parsing is a little incorrect
🏃
1:57:01Fix ParseFontBlock() to fully handle our desired Glyph syntax
1:57:01Fix ParseFontBlock() to fully handle our desired Glyph syntax
1:57:01Fix ParseFontBlock() to fully handle our desired Glyph syntax
1:58:06Continue to step through ParseFontBlock() to ParsePNG(), to find that the latter fails due to the PNG being zero-sized
🏃
1:58:06Continue to step through ParseFontBlock() to ParsePNG(), to find that the latter fails due to the PNG being zero-sized
🏃
1:58:06Continue to step through ParseFontBlock() to ParsePNG(), to find that the latter fails due to the PNG being zero-sized
🏃
2:01:10Force WritePNG() to enter the chunk writing loop
2:01:10Force WritePNG() to enter the chunk writing loop
2:01:10Force WritePNG() to enter the chunk writing loop
2:02:25Regenerate our glyph PNGs using hhafont
🗹
2:02:25Regenerate our glyph PNGs using hhafont
🗹
2:02:25Regenerate our glyph PNGs using hhafont
🗹
2:03:24Step through ParseFontBlock() and past a zero-sized ParsePNG() call, until finally failing in GetFontInfo()
🏃
2:03:24Step through ParseFontBlock() and past a zero-sized ParsePNG() call, until finally failing in GetFontInfo()
🏃
2:03:24Step through ParseFontBlock() and past a zero-sized ParsePNG() call, until finally failing in GetFontInfo()
🏃
2:06:00Reacquaint ourselves with the Asset->HHA.Type setting code
📖
2:06:00Reacquaint ourselves with the Asset->HHA.Type setting code
📖
2:06:00Reacquaint ourselves with the Asset->HHA.Type setting code
📖
2:09:30Make ParseFontBlock() set the Asset->HHA.Type
2:09:30Make ParseFontBlock() set the Asset->HHA.Type
2:09:30Make ParseFontBlock() set the Asset->HHA.Type
2:10:04Again hit our assertion in GetFontInfo()
🏃
2:10:04Again hit our assertion in GetFontInfo()
🏃
2:10:04Again hit our assertion in GetFontInfo()
🏃
2:10:30Tag the liberation_mono font with Tag_FontType(10)
🗹
2:10:30Tag the liberation_mono font with Tag_FontType(10)
🗹
2:10:30Tag the liberation_mono font with Tag_FontType(10)
🗹
2:11:32Crash in StringLength(), and investigate why
🏃
2:11:32Crash in StringLength(), and investigate why
🏃
2:11:32Crash in StringLength(), and investigate why
🏃
2:14:12Try to watch the Format variable of OutfArgList() and crash remedybg
🏃
2:14:12Try to watch the Format variable of OutfArgList() and crash remedybg
🏃
2:14:12Try to watch the Format variable of OutfArgList() and crash remedybg
🏃
2:15:10Continue to investigate our crash in StringLength()
🏃
2:15:10Continue to investigate our crash in StringLength()
🏃
2:15:10Continue to investigate our crash in StringLength()
🏃
2:18:33Rename to ErrorArgList() the overloaded version of Error() that takes a va_list, to work around the treatment of va_list as a char *
2:18:33Rename to ErrorArgList() the overloaded version of Error() that takes a va_list, to work around the treatment of va_list as a char *
2:18:33Rename to ErrorArgList() the overloaded version of Error() that takes a va_list, to work around the treatment of va_list as a char *
2:19:25Find that the StringLength() crash is fixed, and that we are back to addressing the assertion in GetFontInfo()
🏃
2:19:25Find that the StringLength() crash is fixed, and that we are back to addressing the assertion in GetFontInfo()
🏃
2:19:25Find that the StringLength() crash is fixed, and that we are back to addressing the assertion in GetFontInfo()
🏃
2:19:40Set the GlyphCount before the Tags in LiberationMono.hht
🗹
2:19:40Set the GlyphCount before the Tags in LiberationMono.hht
🗹
2:19:40Set the GlyphCount before the Tags in LiberationMono.hht
🗹
2:19:46Find that we still hit that assertion in GetFontInfo()
🏃
2:19:46Find that we still hit that assertion in GetFontInfo()
🏃
2:19:46Find that we still hit that assertion in GetFontInfo()
🏃
2:20:34Make ParseFontBlock() set the font's basic category
2:20:34Make ParseFontBlock() set the font's basic category
2:20:34Make ParseFontBlock() set the font's basic category
2:24:36Find that GetBestMatchAssetFrom() still fails to find our font
🏃
2:24:36Find that GetBestMatchAssetFrom() still fails to find our font
🏃
2:24:36Find that GetBestMatchAssetFrom() still fails to find our font
🏃
2:24:47Change ParseFontBlock() to set the font's basic category in the ExtraTags
2:24:47Change ParseFontBlock() to set the font's basic category in the ExtraTags
2:24:47Change ParseFontBlock() to set the font's basic category in the ExtraTags
2:25:34Find that GetBestMatchAssetFrom() still fails to find our font
🏃
2:25:34Find that GetBestMatchAssetFrom() still fails to find our font
🏃
2:25:34Find that GetBestMatchAssetFrom() still fails to find our font
🏃
2:25:54Step through ParseFontBlock(), to find that we have a parsing error
🏃
2:25:54Step through ParseFontBlock(), to find that we have a parsing error
🏃
2:25:54Step through ParseFontBlock(), to find that we have a parsing error
🏃
2:27:15Fix the FontType tag in LiberationMono.hht
🗹
2:27:15Fix the FontType tag in LiberationMono.hht
🗹
2:27:15Fix the FontType tag in LiberationMono.hht
🗹
2:27:21Step through ParseFontBlock() to completion, but sadly not success
🏃
2:27:21Step through ParseFontBlock() to completion, but sadly not success
🏃
2:27:21Step through ParseFontBlock() to completion, but sadly not success
🏃
2:28:34Fix ParseFontBlock() to set the glyph's BitmapID whether or not the font was updated
2:28:34Fix ParseFontBlock() to set the glyph's BitmapID whether or not the font was updated
2:28:34Fix ParseFontBlock() to set the glyph's BitmapID whether or not the font was updated
2:30:29Step through ParseFontBlock() to find that our glyphs' BitmapID values do not align as expected
🏃
2:30:29Step through ParseFontBlock() to find that our glyphs' BitmapID values do not align as expected
🏃
2:30:29Step through ParseFontBlock() to find that our glyphs' BitmapID values do not align as expected
🏃
2:37:01Using one integer to refer to an asset, by offsetting indices by those of other assets, as opposed to pre-allocating all the indices (as in The Witness)
🗩
2:37:01Using one integer to refer to an asset, by offsetting indices by those of other assets, as opposed to pre-allocating all the indices (as in The Witness)
🗩
2:37:01Using one integer to refer to an asset, by offsetting indices by those of other assets, as opposed to pre-allocating all the indices (as in The Witness)
🗩
2:38:27Fix ParseFontBlock() to offset the glyph BitmapID values by the AssetBase of their containing .hha file
2:38:27Fix ParseFontBlock() to offset the glyph BitmapID values by the AssetBase of their containing .hha file
2:38:27Fix ParseFontBlock() to offset the glyph BitmapID values by the AssetBase of their containing .hha file
2:41:28Find that our font importing works, but that the spacing may be a little off
🏃
2:41:28Find that our font importing works, but that the spacing may be a little off
🏃
2:41:28Find that our font importing works, but that the spacing may be a little off
🏃
2:42:23Run in release mode to see no obvious font bugs
🏃
2:42:23Run in release mode to see no obvious font bugs
🏃
2:42:23Run in release mode to see no obvious font bugs
🏃
2:43:18Q&A
🗩
2:43:18Q&A
🗩
2:43:18Q&A
🗩
2:44:05macielda Q: If you had to support ligatures (for instance "ffi" can optionally become a single glyph when using some fonts), how would you store that information in an asset file? (I think Arabic works in a similar way...?) What about substitutions, like in some fonts the uppercase 'Q' can have a longer tail when in front of 'u' like in 'Quest'?5
🗪
2:44:05macielda Q: If you had to support ligatures (for instance "ffi" can optionally become a single glyph when using some fonts), how would you store that information in an asset file? (I think Arabic works in a similar way...?) What about substitutions, like in some fonts the uppercase 'Q' can have a longer tail when in front of 'u' like in 'Quest'?5
🗪
2:44:05macielda Q: If you had to support ligatures (for instance "ffi" can optionally become a single glyph when using some fonts), how would you store that information in an asset file? (I think Arabic works in a similar way...?) What about substitutions, like in some fonts the uppercase 'Q' can have a longer tail when in front of 'u' like in 'Quest'?5
🗪
2:45:51Make CameraEditor() append "\\5c0f" to the "SAVE STARTUP LOCATION" button
2:45:51Make CameraEditor() append "\\5c0f" to the "SAVE STARTUP LOCATION" button
2:45:51Make CameraEditor() append "\\5c0f" to the "SAVE STARTUP LOCATION" button
2:46:32Find that the "\\5c0f" codepoint did not get parsed as expected
🏃
2:46:32Find that the "\\5c0f" codepoint did not get parsed as expected
🏃
2:46:32Find that the "\\5c0f" codepoint did not get parsed as expected
🏃
2:47:29Change IsHex() to be case-insensitive
2:47:29Change IsHex() to be case-insensitive
2:47:29Change IsHex() to be case-insensitive
2:47:58Find that the "\\5c0f" codepoint did not display as expected
🏃
2:47:58Find that the "\\5c0f" codepoint did not display as expected
🏃
2:47:58Find that the "\\5c0f" codepoint did not display as expected
🏃
2:48:10Change GetHex() to be case-insensitive
2:48:10Change GetHex() to be case-insensitive
2:48:10Change GetHex() to be case-insensitive
2:48:28Find our glyph displaying in the button
🏃
2:48:28Find our glyph displaying in the button
🏃
2:48:28Find our glyph displaying in the button
🏃
2:48:32Add the U+FB00 to U+FB05 ligatures to the Test charset in hhafont6
2:48:32Add the U+FB00 to U+FB05 ligatures to the Test charset in hhafont6
2:48:32Add the U+FB00 to U+FB05 ligatures to the Test charset in hhafont6
2:52:06Make CameraEditor() use the "\\FB03" codepoint in our button
2:52:06Make CameraEditor() use the "\\FB03" codepoint in our button
2:52:06Make CameraEditor() use the "\\FB03" codepoint in our button
2:52:47Find that our font must lack the U+FB03 (ffi) ligature
🏃
2:52:47Find that our font must lack the U+FB03 (ffi) ligature
🏃
2:52:47Find that our font must lack the U+FB03 (ffi) ligature
🏃
2:53:28Try to determine the existence of "ffi" in Liberation Mono using LibreOffice Writer
🗹
2:53:28Try to determine the existence of "ffi" in Liberation Mono using LibreOffice Writer
🗹
2:53:28Try to determine the existence of "ffi" in Liberation Mono using LibreOffice Writer
🗹
2:56:46Temporarily change our font to Segoe UI Regular
🗹
2:56:46Temporarily change our font to Segoe UI Regular
🗹
2:56:46Temporarily change our font to Segoe UI Regular
🗹
2:59:47Regenerate our assets, triggering a remedybg crash
🏃
2:59:47Regenerate our assets, triggering a remedybg crash
🏃
2:59:47Regenerate our assets, triggering a remedybg crash
🏃
3:02:52Check out the exported ligatures of Segoe UI Regular and Liberation Mono
🗹
3:02:52Check out the exported ligatures of Segoe UI Regular and Liberation Mono
🗹
3:02:52Check out the exported ligatures of Segoe UI Regular and Liberation Mono
🗹
3:05:03tshugako This wasn't the kanji for owl...
🗪
3:05:03tshugako This wasn't the kanji for owl...
🗪
3:05:03tshugako This wasn't the kanji for owl...
🗪
3:07:27letambourinroyal handmade_hero 小 is not owl, it means small
🗪
3:07:27letambourinroyal handmade_hero 小 is not owl, it means small
🗪
3:07:27letambourinroyal handmade_hero 小 is not owl, it means small
🗪
3:08:43xxthebigfoxx Q: I was going through the platform code and noticed that you declare the platform struct with all the function pointers as extern in handmade_platform.h. How does the linker resolve that? Isn't the platform in a different executable?
🗪
3:08:43xxthebigfoxx Q: I was going through the platform code and noticed that you declare the platform struct with all the function pointers as extern in handmade_platform.h. How does the linker resolve that? Isn't the platform in a different executable?
🗪
3:08:43xxthebigfoxx Q: I was going through the platform code and noticed that you declare the platform struct with all the function pointers as extern in handmade_platform.h. How does the linker resolve that? Isn't the platform in a different executable?
🗪
3:09:35letambourinroyal Q: How do we render text and do you have any thoughts on dealing with a large number of glyphs such as in Chinese
🗪
3:09:35letambourinroyal Q: How do we render text and do you have any thoughts on dealing with a large number of glyphs such as in Chinese
🗪
3:09:35letambourinroyal Q: How do we render text and do you have any thoughts on dealing with a large number of glyphs such as in Chinese
🗪
3:10:35diffserv Q: Casey, do you think most of the optimizations you use are domain specific, i.e. game development related? And if so, do you think it's possible to decouple optimizations and algorithms in the context of games? And if so, to what extent?
🗪
3:10:35diffserv Q: Casey, do you think most of the optimizations you use are domain specific, i.e. game development related? And if so, do you think it's possible to decouple optimizations and algorithms in the context of games? And if so, to what extent?
🗪
3:10:35diffserv Q: Casey, do you think most of the optimizations you use are domain specific, i.e. game development related? And if so, do you think it's possible to decouple optimizations and algorithms in the context of games? And if so, to what extent?
🗪
3:11:47centhusiast Q: How was your experience of CygnusEd text editor on Amiga? How do you compare it to emacs?
🗪
3:11:47centhusiast Q: How was your experience of CygnusEd text editor on Amiga? How do you compare it to emacs?
🗪
3:11:47centhusiast Q: How was your experience of CygnusEd text editor on Amiga? How do you compare it to emacs?
🗪
3:12:57miblo Okay, the selection happened right here7
🗪
3:12:57miblo Okay, the selection happened right here7
🗪
3:12:57miblo Okay, the selection happened right here7
🗪
3:14:08Kanji owl research8
📖
3:14:08Kanji owl research8
📖
3:14:08Kanji owl research8
📖
3:16:40miblo Q: Sadly the site you found it on seems be deceased (or at least changed). But yeah, "short eared owl" is indeed what the site said!
🗪
3:16:40miblo Q: Sadly the site you found it on seems be deceased (or at least changed). But yeah, "short eared owl" is indeed what the site said!
🗪
3:16:40miblo Q: Sadly the site you found it on seems be deceased (or at least changed). But yeah, "short eared owl" is indeed what the site said!
🗪
3:16:58Wrap it up
🗩
3:16:58Wrap it up
🗩
3:16:58Wrap it up
🗩