<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>Zorg&#39;s Space</title>
    <link>https://zgcoder.net/</link>
    <description>Recent content on Zorg&#39;s Space</description>
    <generator>Hugo -- gohugo.io</generator>
    <language>en-us</language>
    <lastBuildDate>Sat, 10 Feb 2024 00:15:51 +0000</lastBuildDate>
    
	<atom:link href="https://zgcoder.net/feed.xml" rel="self" type="application/rss+xml" />
    
    
    <item>
      <title>Dodge Danger</title>
      <link>https://zgcoder.net/ramblings/dodge-danger/</link>
      <pubDate>Sat, 10 Feb 2024 00:15:51 +0000</pubDate>
      
      <guid>https://zgcoder.net/ramblings/dodge-danger/</guid>
      <description>&lt;!-- https://github.com/zorgiepoo/dodgedanger --&gt;
&lt;p&gt;I created a small cross-platform 3D obstacle dodging game under 500 KB.&lt;/p&gt;</description>
      <content:encoded>&lt;!-- https://github.com/zorgiepoo/dodgedanger --&gt;
&lt;p&gt;I created a small cross-platform 3D obstacle dodging game under 500 KB.&lt;/p&gt;
&lt;h2 id=&#34;a-small-new-game&#34;&gt;A small new game&lt;/h2&gt;
&lt;p&gt;I spent around a week creating a small game called Dodge Danger. I also open sourced the game. Check it out on &lt;a href=&#34;https://github.com/zorgiepoo/dodgedanger&#34;&gt;GitHub&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;In this game the player must dodge the obstacles which are 3D rendered cubes.&lt;/p&gt;
&lt;figure&gt;
    &lt;img src=&#34;https://zgcoder.net/zfw/dodge-danger-playing.png&#34; alt=&#34;Gameplay for Dodge Danger&#34; width=&#34;600&#34;/&gt;
&lt;/figure&gt;
&lt;p&gt;Dodge Danger is under 500 KB both on macOS and Windows. On Windows the game is a standalone executable. I even built an arm64 version for Windows but I have not tested it yet. No audio is used in this game, but the game does support using game controllers.&lt;/p&gt;
&lt;p&gt;The game has minimal dependencies and mostly uses system libraries. The texture loading, font loading, window handling, and game controller support use the system libraries and the rendering uses Metal and Direct3D 11. I copied and pasted a large amount of the engine code from &lt;a href=&#34;https://zgcoder.net/#sky-checkers&#34;&gt;Sky Checkers&lt;/a&gt; so the game-specific code is just around 1,000 lines of code.&lt;/p&gt;
&lt;p&gt;My goal was not to make a &amp;ldquo;game engine.&amp;rdquo; My goal was to create another game, but I achieved this by re-using a lot of the code from my previous game. I believe this is the &lt;em&gt;right way&lt;/em&gt; to go about creating a &amp;ldquo;game engine.&amp;rdquo;&lt;/p&gt;
&lt;p&gt;I also made some improvements when making the second game. For example, I found out I can embed the HLSL shaders as header files at compile time instead of manually loading their byte contents from a file at runtime. I also fixed assumptions about HiDPI my previous game didn&amp;rsquo;t handle. Still, Dodge Danger has some future improvements I could make. For one, the font rendering is very inefficient and uses more memory than necessary. This was not a big issue in Sky Checkers.&lt;/p&gt;
&lt;p&gt;I am also going to use this game as a tutorial for &lt;a href=&#34;https://github.com/zorgiepoo/Bit-Slicer/wiki/Pointers&#34;&gt;searching for pointers using Bit Slicer&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;If you have a chance of trying out Dodge Danger, let me know what you think!&lt;/p&gt;</content:encoded>
    </item>
    
    <item>
      <title>Create Modern Mac Disk Images</title>
      <link>https://zgcoder.net/ramblings/modern-dmgs/</link>
      <pubDate>Sat, 30 Sep 2023 00:07:48 +0000</pubDate>
      
      <guid>https://zgcoder.net/ramblings/modern-dmgs/</guid>
      <description>&lt;p&gt;Mac applications outside the App Store are often delivered using disk images (dmg files), but many apps are not delivered using a modern or efficient disk image format. Below I provide my recommendations for creating more optimal disk image files.&lt;/p&gt;</description>
      <content:encoded>&lt;p&gt;Mac applications outside the App Store are often delivered using disk images (dmg files), but many apps are not delivered using a modern or efficient disk image format. Below I provide my recommendations for creating more optimal disk image files.&lt;/p&gt;
&lt;h2 id=&#34;filesystem&#34;&gt;Filesystem&lt;/h2&gt;
&lt;p&gt;If you target macOS 10.13 or later, you should prefer APFS over HFS+ for the disk image filesystem.&lt;/p&gt;
&lt;p&gt;APFS supercedes HFS+. HFS+ is generally worse than APFS for extraction speed, especially for larger workloads under heavy compression in my testing.&lt;/p&gt;
&lt;p&gt;Given that Xcode no longer supports deploying to macOS versions older than 10.13 anymore, HFS+ should not be used much. If you mount an existing disk image, you can check its filesystem by examining the output from &lt;code&gt;diskutil list&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&#34;compression-format&#34;&gt;Compression Format&lt;/h2&gt;
&lt;p&gt;You should default to using lzfse as your compression format for disk images.&lt;/p&gt;
&lt;p&gt;If you want to create disk images optimized for smaller file sizes (at the expense of slower extraction), you may consider using lzma if your users are running macOS 10.15 or later. However if you still support older OS versions, you may need to consider using bzip2 instead for creating smaller disk images.&lt;/p&gt;
&lt;p&gt;lzfse (macOS 10.11+) supercedes zlib and lzma (macOS 10.15+) supercedes bzip2 (which &lt;code&gt;hdiutil&lt;/code&gt; deprecated). The successors are better both by file size and extraction speed.&lt;/p&gt;
&lt;p&gt;You can check the compression format of an existing disk image by running the &lt;code&gt;file&lt;/code&gt; command on it.&lt;/p&gt;
&lt;h2 id=&#34;software-license-agreements&#34;&gt;Software License Agreements&lt;/h2&gt;
&lt;p&gt;Avoid attaching software license agreements to disk images. Software license agreements rely on a deprecated tool (&lt;code&gt;hdiutil udifrez&lt;/code&gt;) which results in the generated disk images taking significantly longer to mount in Finder (last verified on macOS Sonoma).&lt;/p&gt;
&lt;h2 id=&#34;tooling&#34;&gt;Tooling&lt;/h2&gt;
&lt;p&gt;As a Mac developer, you may be using another developer&amp;rsquo;s tool for creating disk images and may be concerned about its support for creating modern dmg files. Indeed, a year ago I observed that many tools lacked support for creating APFS or lzfse/lzma disk images. But I have some good news!&lt;/p&gt;
&lt;p&gt;Earlier this year I contributed patches to several projects to adopt the more modern options (in no particular order):&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/create-dmg/create-dmg&#34;&gt;create-dmg/create-dmg&lt;/a&gt; (&lt;a href=&#34;https://github.com/create-dmg/create-dmg/pull/145&#34;&gt;#145&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/sindresorhus/create-dmg&#34;&gt;sindresorhus/create-dmg&lt;/a&gt; (&lt;a href=&#34;https://github.com/sindresorhus/create-dmg/pull/81&#34;&gt;#81&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/LinusU/node-appdmg&#34;&gt;node-appdmg&lt;/a&gt; (&lt;a href=&#34;https://github.com/LinusU/node-appdmg/pull/220&#34;&gt;#220&lt;/a&gt;, &lt;a href=&#34;https://github.com/LinusU/node-appdmg/pull/221&#34;&gt;#221&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/dmgbuild/dmgbuild&#34;&gt;dmgbuild&lt;/a&gt; (&lt;a href=&#34;https://github.com/dmgbuild/dmgbuild/pull/53&#34;&gt;#53&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I also nudged the authors for enhancing the following software:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://www.araelium.com/dmgcanvas&#34;&gt;DMG Canvas 4&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://c-command.com/dropdmg/&#34;&gt;DropDMG&lt;/a&gt; (supports APFS disk images via an esoteric preference)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Below is a screenshot showing DMG Canvas, which defaults to LZFSE and APFS but allows choosing other compression options like LZMA.&lt;/p&gt;
&lt;picture&gt;
    &lt;source srcset=&#34;https://zgcoder.net/zfw/dmgcanvas-default-dark.png&#34; media=&#34;(prefers-color-scheme: dark)&#34;&gt;
    &lt;img src=&#34;https://zgcoder.net/zfw/dmgcanvas-default-light.png&#34; alt=&#34;Image of DMG Canvas defaulting to LZFSE and APFS but allows choosing other compression options like LZMA&#34; width=&#34;600&#34;&gt;
&lt;/picture&gt;
&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;When creating a new disk image for your Mac application, prefer using APFS and lzfse. If you want to optimize for a smaller file size, prefer to use lzma but consider bzip2 for supporting older macOS versions.&lt;/p&gt;
&lt;p&gt;If you use another developer&amp;rsquo;s tool for creating disk images (rather than using &lt;code&gt;hdiutil&lt;/code&gt; directly), chances are it has been updated to support these options. Otherwise check &lt;code&gt;man hdiutil&lt;/code&gt; for how do adopt them.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;July 4, 2024&lt;/strong&gt;: Added section for avoiding software license agreements.&lt;/p&gt;</content:encoded>
    </item>
    
    <item>
      <title>Code Injection</title>
      <link>https://zgcoder.net/ramblings/code-injection/</link>
      <pubDate>Sun, 04 Dec 2022 14:39:00 +0000</pubDate>
      
      <guid>https://zgcoder.net/ramblings/code-injection/</guid>
      <description>&lt;p&gt;I recently released an update to &lt;a href=&#34;https://zgcoder.net/#bit-slicer&#34;&gt;Bit Slicer&lt;/a&gt; that adds Code Injection support for arm64 or native Apple Silicon processes. Code injection allows injecting new code and logic into a running program. I will discuss how this functionality works in a debugger like Bit Slicer and what changes were made to enable this functionality for Apple Silicon.&lt;/p&gt;</description>
      <content:encoded>&lt;p&gt;I recently released an update to &lt;a href=&#34;https://zgcoder.net/#bit-slicer&#34;&gt;Bit Slicer&lt;/a&gt; that adds Code Injection support for arm64 or native Apple Silicon processes. Code injection allows injecting new code and logic into a running program. I will discuss how this functionality works in a debugger like Bit Slicer and what changes were made to enable this functionality for Apple Silicon.&lt;/p&gt;
&lt;h2 id=&#34;how-code-injection-works&#34;&gt;How Code Injection Works&lt;/h2&gt;
&lt;p&gt;Bit Slicer has provided assembly-level Code Injection support for many years now for Intel or x86 processes.&lt;/p&gt;
&lt;p&gt;First the user needs to find an unused region of memory or (more commonly for Bit Slicer) allocate a new region of memory to inject new code into. This is often called a &amp;ldquo;code cave&amp;rdquo; by game hackers.&lt;/p&gt;
&lt;p&gt;Then the user finds an area of known used instructions and has Bit Slicer replace however many instructions are needed with a branch instruction that jumps to the new code cave. The user also inserts their custom code into this code cave, optionally copying the original instructions that were sacrificed for the jump.&lt;/p&gt;
&lt;p&gt;The last instruction written in this code cave finally jumps back to the original code, following after the instruction that jumps to the code cave. An illustration of these steps is below:&lt;/p&gt;
&lt;figure&gt;
	&lt;img src=&#34;https://zgcoder.net/zfw/code-injection.png&#34; alt=&#34;Illustration of Code Injection&#34; width=&#34;600&#34;/&gt;
&lt;/figure&gt;
&lt;p&gt;The result is that new code and logic can be added at runtime without overriding large essential portions of existing code.&lt;/p&gt;
&lt;h2 id=&#34;code-injection-using-branches&#34;&gt;Code Injection Using Branches&lt;/h2&gt;
&lt;p&gt;For Intel, Bit Slicer prefers to use a &lt;code&gt;jmp&lt;/code&gt; instruction which occupies 5 bytes and 4 of those bytes are used for the relative offset to jump to which starts from the end of the &lt;code&gt;jmp&lt;/code&gt; instruction.&lt;/p&gt;
&lt;p&gt;For example, if the original instruction a user wants to overwrite is at &lt;code&gt;0x1000&lt;/code&gt; and the new code cave is at &lt;code&gt;0x4000&lt;/code&gt;, then the original instruction can be overwritten as &lt;code&gt;jmp 0x4000&lt;/code&gt; and the offset at that location will be encoded as &lt;code&gt;(0x4000 - (0x1000 + 0x5))&lt;/code&gt; or simply &lt;code&gt;0x2FFB&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Note instructions vary in size on Intel, so Bit Slicer may end up overwriting multiple instructions depending on the chosen insertion point. Any remaining unused bytes from replaced instructions are overwritten with 1-byte NOP, or no-operation, instructions.&lt;/p&gt;
&lt;p&gt;In x86_64 or 64-bit Intel processes a relative &lt;code&gt;jmp&lt;/code&gt; will not suffice if the code cave is too far away and the signed offset cannot be represented using 32 bits. In this case, Bit Slicer falls back to executing an indirect jump which will need to use 3 instructions and overwrite 11 bytes of existing code instead of 5 from a relative &lt;code&gt;jmp&lt;/code&gt;:&lt;/p&gt;
&lt;figure&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-nasm&#34; data-lang=&#34;nasm&#34;&gt;&lt;span class=&#34;nl&#34;&gt;ORIGINAL_CODE:&lt;/span&gt;

&lt;span class=&#34;c1&#34;&gt;; Branch to the code cave&lt;/span&gt;
&lt;span class=&#34;c1&#34;&gt;; The original instruction(s) that were here were replaced by these in order to jump to the code cave&lt;/span&gt;
&lt;span class=&#34;nf&#34;&gt;push&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;rax&lt;/span&gt;
&lt;span class=&#34;nf&#34;&gt;mov&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;rax&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;NEW_CODE&lt;/span&gt;
&lt;span class=&#34;nf&#34;&gt;jmp&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;rax&lt;/span&gt;

&lt;span class=&#34;nl&#34;&gt;BACK_TO_ORIGINAL_CODE:&lt;/span&gt;

&lt;span class=&#34;nf&#34;&gt;pop&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;rax&lt;/span&gt;
&lt;span class=&#34;c1&#34;&gt;; ..rest of original code is here..&lt;/span&gt;

&lt;span class=&#34;c1&#34;&gt;; ----------&lt;/span&gt;

&lt;span class=&#34;nl&#34;&gt;NEW_CODE:&lt;/span&gt;

&lt;span class=&#34;nf&#34;&gt;pop&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;rax&lt;/span&gt;
&lt;span class=&#34;c1&#34;&gt;; ..insert new code here..&lt;/span&gt;

&lt;span class=&#34;c1&#34;&gt;; Now branch back to the original code&lt;/span&gt;
&lt;span class=&#34;nf&#34;&gt;push&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;rax&lt;/span&gt;
&lt;span class=&#34;nf&#34;&gt;mov&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;rax&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;BACK_TO_ORIGINAL_CODE&lt;/span&gt;
&lt;span class=&#34;nf&#34;&gt;jmp&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;rax&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/figure&gt;
&lt;p&gt;Overwriting more instructions, modifying the stack, and preserving registers that are spilled like this is less ideal than using a 5-byte relative &lt;code&gt;jmp&lt;/code&gt; instruction. Overwriting more space requires more caution on choosing an adequate insertion point, especially if any of the instructions that are being overwritten encode relative offsets themselves.&lt;/p&gt;
&lt;h2 id=&#34;code-injection-using-breakpoints&#34;&gt;Code Injection Using Breakpoints&lt;/h2&gt;
&lt;p&gt;On arm64, code injection using a relative branch instruction (&lt;code&gt;b&lt;/code&gt;) can be done similarly with one important caveat: the relative offset can only hold up to 2&lt;sup&gt;28&lt;/sup&gt; values rather than 2&lt;sup&gt;32&lt;/sup&gt; values for Intel. This is a big difference. For Intel, I was contempt with 32 bits because this was often large enough in my experiments and often did not require falling back to an indirect jump. Also instructions are variable size on Intel, so finding an insertion point that does not overwrite too many instructions can be feasible.&lt;/p&gt;
&lt;p&gt;On arm64, however, 28 bits is often insufficient for jumping to a newly allocated block of code due to it being too far away. Performing an indirect jump using a 64-bit address while saving register state can occupy many more bytes and instructions than on Intel (around 6 instructions or 24 bytes by my calculations). Instructions on arm64 are always 4 bytes long which also makes finding a good insertion point more difficult.&lt;/p&gt;
&lt;p&gt;Rather than implementing an approach again that would overwrite several instructions and spill several registers, I decided to go a different route. Bit Slicer now uses breakpoints and handles moving the instruction pointer to and from the code cave.&lt;/p&gt;
&lt;p&gt;The way this approach works is as following: Bit Slicer overwrites an original instruction with a breakpoint instruction. When that instruction is executed, an exception for hitting a breakpoint is raised and Bit Slicer catches it. Bit Slicer then updates the instruction pointer register of the suspended thread to point to the code cave and resumes execution. Similarly, a breakpoint instruction is inserted at the end of the code cave so Bit Slicer can move execution back to the original code.&lt;/p&gt;
&lt;p&gt;The advantages of this approach is that only one instruction needs to be overwritten and no registers need to be spilled to jump to a far away location. The disadvantages are that this requires debugger support and the program will incur a small performance penalty by having the debugger catch and handle the exception (however the debugger tries to be fast!). Bit Slicer shows a fake &amp;ldquo;emulated&amp;rdquo; branch instruction to the user when they look at the live disassembly of the app (similiar to how debuggers show the original instructions when they are overwritten with breakpoints).&lt;/p&gt;
&lt;h2 id=&#34;code-injection-example&#34;&gt;Code Injection Example&lt;/h2&gt;
&lt;p&gt;At last, here is a simple example of using code injection in &lt;a href=&#34;https://zgcoder.net/#sky-checkers&#34;&gt;my game&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;When players are knocked off the checkerboard stage, they normally move downwards on the z axis. The code in the game that handles this decreases the player’s z position variable repeatably at a frequent interval.&lt;/p&gt;
&lt;p&gt;With code injection, I can add additional code here that also alters the player’s x location so that the player is falling in a more slanted manner.&lt;/p&gt;
&lt;p&gt;Here is an example of the changes:&lt;/p&gt;
&lt;figure&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-asm&#34; data-lang=&#34;asm&#34;&gt;&lt;span class=&#34;nl&#34;&gt;ORIGINAL_CODE:&lt;/span&gt;
&lt;span class=&#34;nf&#34;&gt;fsub&lt;/span&gt; &lt;span class=&#34;no&#34;&gt;s0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;no&#34;&gt;s0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;no&#34;&gt;s1&lt;/span&gt;

&lt;span class=&#34;c&#34;&gt;; Branch to the code cave
&lt;/span&gt;&lt;span class=&#34;c&#34;&gt;; Note this might actually be a breakpoint underneath and be emulated
&lt;/span&gt;&lt;span class=&#34;c&#34;&gt;; This instruction was replaced and previously: str s0, [x8, 0x8]
&lt;/span&gt;&lt;span class=&#34;c&#34;&gt;&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;b&lt;/span&gt; &lt;span class=&#34;no&#34;&gt;NEW_CODE&lt;/span&gt;

&lt;span class=&#34;nl&#34;&gt;BACK_TO_ORIGINAL_CODE:&lt;/span&gt;
&lt;span class=&#34;c&#34;&gt;; This is an original instruction that remains untouched
&lt;/span&gt;&lt;span class=&#34;c&#34;&gt;&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;ldur&lt;/span&gt; &lt;span class=&#34;no&#34;&gt;x8&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;no&#34;&gt;x29&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;0x20&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;

&lt;span class=&#34;c&#34;&gt;; ------------
&lt;/span&gt;&lt;span class=&#34;c&#34;&gt;&lt;/span&gt;
&lt;span class=&#34;nl&#34;&gt;NEW_CODE:&lt;/span&gt;
&lt;span class=&#34;c&#34;&gt;; Copy over and execute the original instruction making the player’s z position decrease
&lt;/span&gt;&lt;span class=&#34;c&#34;&gt;&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;str&lt;/span&gt; &lt;span class=&#34;no&#34;&gt;s0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;no&#34;&gt;x8&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0x8&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;

&lt;span class=&#34;c&#34;&gt;; Preserve registers for s0 and s1 on the stack which will be used later
&lt;/span&gt;&lt;span class=&#34;c&#34;&gt;; Note the stack must be 16-byte aligned on Apple platforms
&lt;/span&gt;&lt;span class=&#34;c&#34;&gt;&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;stp&lt;/span&gt; &lt;span class=&#34;no&#34;&gt;s0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;no&#34;&gt;s1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;no&#34;&gt;sp&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;0x10&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]!&lt;/span&gt;

&lt;span class=&#34;c&#34;&gt;; Subtract the player’s x position by 0.25 too
&lt;/span&gt;&lt;span class=&#34;c&#34;&gt;; (Note if the player&amp;#39;s z position is a float at offset 8, then it&amp;#39;s very likely the y position is at offset 4 and x offset is at offset 0)
&lt;/span&gt;&lt;span class=&#34;c&#34;&gt;&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;ldr&lt;/span&gt; &lt;span class=&#34;no&#34;&gt;s0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;no&#34;&gt;x8&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;
&lt;span class=&#34;nf&#34;&gt;fmov&lt;/span&gt; &lt;span class=&#34;no&#34;&gt;s1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;no&#34;&gt;.25&lt;/span&gt;
&lt;span class=&#34;nf&#34;&gt;fsub&lt;/span&gt; &lt;span class=&#34;no&#34;&gt;s0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;no&#34;&gt;s0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;no&#34;&gt;s1&lt;/span&gt;
&lt;span class=&#34;nf&#34;&gt;str&lt;/span&gt; &lt;span class=&#34;no&#34;&gt;s0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;no&#34;&gt;x8&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;

&lt;span class=&#34;c&#34;&gt;; Restore registers for s0 and s1
&lt;/span&gt;&lt;span class=&#34;c&#34;&gt;&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;ldp&lt;/span&gt; &lt;span class=&#34;no&#34;&gt;s0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;no&#34;&gt;s1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;no&#34;&gt;sp&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0x10&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]!&lt;/span&gt;

&lt;span class=&#34;c&#34;&gt;; Branch back to the original code
&lt;/span&gt;&lt;span class=&#34;c&#34;&gt;; Note this might actually be a breakpoint underneath and be emulated
&lt;/span&gt;&lt;span class=&#34;c&#34;&gt;&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;b&lt;/span&gt; &lt;span class=&#34;no&#34;&gt;BACK_TO_ORIGINAL_CODE&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/figure&gt;
&lt;p&gt;This is just a simple example, but the possibilities are endless.&lt;/p&gt;
&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;I went over how Bit Slicer provides assembly-level code injection and how I adapted the debugger to handle injecting code in arm64 more feasibly.&lt;/p&gt;
&lt;p&gt;As a final note, this is not the only method to inject code. Some other ways not discussed here may be:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Injecting a compiled dylib when spawning the process using the &lt;code&gt;DYLD_INSERT_LIBRARIES&lt;/code&gt; environment variable. This might include an initializer that runs when the library is loaded.&lt;/li&gt;
&lt;li&gt;Creating and injecting a new thread that executes new code the user crafts.&lt;/li&gt;
&lt;li&gt;Exploiting a bug in the targetted software.&lt;/li&gt;
&lt;/ul&gt;</content:encoded>
    </item>
    
    <item>
      <title>10 Years of Bit Slicer 🎉</title>
      <link>https://zgcoder.net/ramblings/decade-of-bit-slicer/</link>
      <pubDate>Sun, 19 Jul 2020 19:21:25 -0700</pubDate>
      
      <guid>https://zgcoder.net/ramblings/decade-of-bit-slicer/</guid>
      <description>&lt;p&gt;Back to my late teenage years I began developing an app to modify, enhance, and cheat Mac games. After struggling to come up with a good name, my friend Dylan named it Bit Slicer (nobody liked my &amp;ldquo;XZCheat&amp;rdquo; prototype name 😅). Fast forward 10 years to now, &lt;a href=&#34;https://github.com/zorgiepoo/Bit-Slicer&#34;&gt;Bit Slicer&lt;/a&gt; has become one of my most beloved applications that I have poured a lot of my soul into. To celebrate its decade long anniversary, let me start with how it began.&lt;/p&gt;</description>
      <content:encoded>&lt;p&gt;Back to my late teenage years I began developing an app to modify, enhance, and cheat Mac games. After struggling to come up with a good name, my friend Dylan named it Bit Slicer (nobody liked my &amp;ldquo;XZCheat&amp;rdquo; prototype name 😅). Fast forward 10 years to now, &lt;a href=&#34;https://github.com/zorgiepoo/Bit-Slicer&#34;&gt;Bit Slicer&lt;/a&gt; has become one of my most beloved applications that I have poured a lot of my soul into. To celebrate its decade long anniversary, let me start with how it began.&lt;/p&gt;
&lt;h2 id=&#34;the-cheat&#34;&gt;The Cheat&lt;/h2&gt;
&lt;p&gt;Back in the Mac OS X Leopard era (2008) when many of us were still on PowerPC machines, several of us spent an obsessive amount of time modifying and adding content to a video game. We had a thriving community of tinkerers and programmers alike. We made great achievements by altering game data files on disk, but some of us also desired the possibilities of modifying the game while it was running.&lt;/p&gt;
&lt;p&gt;A small number of us at the time experimented with using the &amp;ldquo;Legendary Game Trainer for Mac OS X&amp;rdquo; &amp;ndash; &lt;a href=&#34;https://github.com/chazmcgarvey/thecheat&#34;&gt;The Cheat&lt;/a&gt;:&lt;/p&gt;
&lt;img src=&#34;https://zgcoder.net/zfw/thecheat.jpeg&#34; alt=&#34;Image of The Cheat&#34; width=&#34;500&#34;/&gt;
&lt;p&gt;Inspired by &lt;a href=&#34;https://imgur.com/t/videogames/ly56JqH&#34;&gt;Pandora&amp;rsquo;s Box&lt;/a&gt; for Mac OS (1996), The Cheat enables searching and narrowing down variables that can later be altered. A basic scenario of how this works: if a player has 1378 coins in a side-scrolling game and searches for this value in the game&amp;rsquo;s memory, they may get 1,000 potential results. When the player gains two more coins and narrows down which of the previous results are now 1380, they reduce or narrow down the set of potential results. By repeating this process, they may find the single variable address that represents their coins and then alter the value to give themselves 9999 coins.&lt;/p&gt;
&lt;p&gt;We loved using this utility. We discovered and applied new hacks that were not possible via other methods. It was sophisticated by providing a variety of data types and operators. It enabled us to save and share modifications to others. It also behaved like a native Mac application.&lt;/p&gt;
&lt;p&gt;Unfortunately main development on The Cheat halted and newer issues crept up in newer released operating systems. I dug into the codebase and made patches to resolve the issues I encountered for a while, but eventually ran into feature limitations that warranted me to ditch the beloved utility and present alternatives like iHaxGamez.&lt;/p&gt;
&lt;h2 id=&#34;bit-slicer&#34;&gt;Bit Slicer&lt;/h2&gt;
&lt;p&gt;In a couple weeks, I developed a prototype which lead to an eventual shipping version of Bit Slicer. It had a user interface that on the surface looked similar to The Cheat above and covered most of its functionality.&lt;/p&gt;
&lt;p&gt;In its initial release, Bit Slicer also allowed users to add variables at specified memory addresses manually without first searching for them, and allowed searches to be preserved across different or re-spawned processes. Without going into elaborate detail, these two enhancements assisted me in enabling a hidden option in a trial version of a game.&lt;/p&gt;
&lt;p&gt;Bit Slicer was thus produced to fulfill my desire of enhancing games in new ways with a long journey ahead of it.&lt;/p&gt;
&lt;h2 id=&#34;community&#34;&gt;Community&lt;/h2&gt;
&lt;p&gt;A few months after Bit Slicer&amp;rsquo;s initial release in September 2010, a new user began the following email exchange with me:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;loco: Hey there, I saw your bit slicer project today, finally someone is making an effort in making a better memory editor for mac. I saw your sources and binaries are only for 10.6. Is there any way for me to compile it so it runs on my 10.5&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;Zorg: Hey. Sorry, but Bit Slicer will not run or compile on a OS lower than 10.6 because it uses features and API&amp;rsquo;s that became available in 10.6&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;loco: That&amp;rsquo;s too bad&amp;hellip; Thanks for the speedy reply anyway! Great work on the release though! I have a suggestion if you haven&amp;rsquo;t included it yet. Allow it to start a search for an unknown variable, and then look for changes as you normally would. There is no program for mac by the looks of it that lets you do this.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;A couple months later, I added a feature to search and compare values based on a previously taken snapshot of a process, and loco upgraded to macOS 10.6. Loco tried out the application to his delight and then invited me to have a dedicated section on PortingTeam (a Mac porting focussed gaming forum). I gained more feedback from users, shared my progress, and released beta versions there. I made some great connections and friends including loco. This was the start of Bit Slicer&amp;rsquo;s life-cycle.&lt;/p&gt;
&lt;h2 id=&#34;debuggers&#34;&gt;Debuggers&lt;/h2&gt;
&lt;p&gt;I took a tangential break after adding features such as pointer references, byte arrays, and a memory viewer. I became obsessed with playing a short side-scrolling game called Doukutsu Monogatari, or better known as Cave Story (it&amp;rsquo;s a really good game by the way). Shortly later, I was introduced to assembly languages in one of my courses. Some peers thought the material wasn&amp;rsquo;t very practical, but it intrigued my unawareness of how code is executed on a lower level.&lt;/p&gt;
&lt;p&gt;Out of curiosity, I used a tool bundled as part of Xcode to disassemble Cave Story. Lucky for me, all the debug symbols were available. So I found a procedure with a corresponding symbol named like &amp;ldquo;DamageMe&amp;rdquo; and peeked at the assembly instructions that were decrementing a value and writing its result to an address in memory. I thought, what if I can make these instructions do nothing instead? With a hex editor, I went to the location of where these instructions resided in the binary and overwrote these instruction bytes with 0x90&amp;rsquo;s (a no-operation opcode on x86).&lt;/p&gt;
&lt;p&gt;To my amazement, my experiment of changing the code worked and my player could no longer be hurt. I also found a more practical way to find the instruction without using symbols (which are not always available). After searching for the player&amp;rsquo;s health using Bit Slicer, I set a watchpoint using gdb on the memory address to find what instruction was writing to the value when it had changed.&lt;/p&gt;
&lt;p&gt;I soon began to debug other games like this by setting watchpoints and breakpoints, but gdb wasn&amp;rsquo;t very fun to use and lldb wasn&amp;rsquo;t very mature at the time (late 2012). These debuggers are also not very approachable to many game tinkerers. So I went on a long journey of adding debugging capabilities to Bit Slicer.&lt;/p&gt;
&lt;p&gt;I spent a few weeks researching how to achieve this. I found a x86 disassembler library to disassemble instructions I read in from a process&amp;rsquo; virtual memory. I scrambled throughout the internet finding scarce references on implementing an exception handler that attaches to another process. I found private system APIs to set and get register states from a specified thread. I made sure to understand how to manipulate &lt;a href=&#34;https://en.wikipedia.org/wiki/X86_debug_register&#34;&gt;debug registers&lt;/a&gt; for setting watchpoints and breakpoints. I read how to implement backtraces and instruction breakpoints from the web and through gdb and lldb&amp;rsquo;s source code. I learned about debugger edge cases such as stepping out from a recursive function and heuristics such as deciding where to start disassembling instructions efficiently. I learned how to identify code and data segments, identify which variables are static across runs, and how to relativize variables based on address space layout randomization.&lt;/p&gt;
&lt;p&gt;After a long amount of dedication, I ended up writing debugger level features as part of Bit Slicer version 1.6 and later enhanced by 1.7. Users could now find the instructions that accessed a variable, overwrite existing instructions, view the disassembled code around them, or set breakpoints to debug their games. Version 1.7 also later enabled injecting new assembly code into a process and writing scripts to automate searching and debugging tasks.&lt;/p&gt;
&lt;p&gt;To reflect on my dedication involved, I estimate these two major versions combined took around &lt;a href=&#34;https://portingteam.com/topic/7976-16-alphas/&#34;&gt;12&lt;/a&gt; &lt;a href=&#34;https://portingteam.com/topic/9588-17-alphas/&#34;&gt;months&lt;/a&gt; of hard work to reach their point zero releases. Some weeks I was working for many hours daily even when I held a full time position. I recall having two distinct 40-60 day coding streaks on GitHub. This wasn&amp;rsquo;t always a daily endeavor, but I may have lost a little sleep for some of the time 😅.&lt;/p&gt;
&lt;h2 id=&#34;user-interfaces&#34;&gt;User Interfaces&lt;/h2&gt;
&lt;p&gt;User interfaces are very crucial but often neglected. Many applications act the way they do because its developers are influenced by prior experiences. Imagining new ways that simplify interfaces and maintain power is no simple task. If the majority of users are asked what they think of an existing application&amp;rsquo;s user interface, they may exclaim it&amp;rsquo;s great. But the same users will also change their minds once they experience a simpler and more powerful design. And after a new design comes out, it becomes ingrained again and suddenly becomes the &lt;em&gt;obvious&lt;/em&gt; way such applications should function.&lt;/p&gt;
&lt;p&gt;I am not immune to this problem. Initial versions of Bit Slicer looked and behaved similarly to The Cheat, which was influenced from an application before it. Other game cheating software on other platforms have similar influences from a long tail of software before it. From Bit Slicer&amp;rsquo;s initial release, however, I made one significant design decision contrary to popular trends.&lt;/p&gt;
&lt;p&gt;For a little background, The Cheat and other popular alternatives actually have two tables or views that users use. One table populates the memory addresses and values when memory scans are performed. The other table is purposed for variables that the user chooses to apply cheats to. So with The Cheat for example, users search for their desired variable in one table and then add that variable to another table where they can alter it.&lt;/p&gt;
&lt;p&gt;The biggest distinction I made from the beginning was choosing &lt;em&gt;not&lt;/em&gt; to have two different tables. Bit Slicer is the first to unify searching and altering values while still providing a great amount of flexibility. Users can search for variables and then edit variables at any stage in the search. They can add and remove variables at any point. They can change a variable&amp;rsquo;s data type. They can mark variables to be preserved and excluded from newly performed searches. Two tables were simplified and purposed into one while retaining the power a user may expect:&lt;/p&gt;
&lt;img src=&#34;https://zgcoder.net/software/bitslicer/images/old/bitslicer_1.png&#34; alt=&#34;Image of Bit Slicer 1.6&#34; width=&#34;600&#34;/&gt;
&lt;p&gt;While developing version 1.7, I gained inspiration from an experienced Mac developer to re-invent the user interface. The user interface in version 1.6 above had a number of issues that went long ignored. Controls did not extend well when the window grew big or became fullscreen. Some spots in the window had awkward dead space. The window was becoming cluttered with controls and adding any additional options would complicate it further. The searching progress bar was always visible taking up space and looked unnatural. After considering all of these issues, I have thus ended up with the following interface:&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://zgcoder.net/software/bitslicer/images/bitslicer_ss_new2.png&#34; alt=&#34;Image of Bit Slicer 1.7&#34;&gt;&lt;/p&gt;
&lt;p&gt;The table became the primary focus and changed to stretch the entire window. All the primary options became placed in the very top toolbar along with a natural behaving search field. Search and cancel/clear buttons are no longer separate and are now part of the search field. Additional but rarely used options are accessible from the advanced gears option in the bottom left instead of cluttering the search window. The search status including the numbers of variables displayed is now updated in the center bottom status bar. Descriptions became auto-populated with &lt;a href=&#34;https://github.com/zorgiepoo/Bit-Slicer/wiki/Search-Windows#description-annotations&#34;&gt;useful metadata&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The searching progress became de-emphasized. Instead of a big progress bar, a small circular progress indicator now appears in the bottom right of the status bar while a search is occurring. Because searching became more efficient in 1.7, the progress indicator also does not usually appear for a very long amount of time and otherwise stays out of the way. Furthermore, the progress of searching feels more responsive and pleasing because 1.7 shows variable results as the search is progressing instead of only when the search has completed.&lt;/p&gt;
&lt;p&gt;The new user interface was a breath of fresh air. While Bit Slicer still has questionable design concerns, nobody desired to go back to the way older versions acted.&lt;/p&gt;
&lt;h2 id=&#34;reflections&#34;&gt;Reflections&lt;/h2&gt;
&lt;p&gt;While Bit Slicer has an uncertain future due to various reasons including my time spent to maintain it, I am thrilled it has been serving users well for a decade.&lt;/p&gt;
&lt;p&gt;As a side project, I gained better expertise in reverse engineering and producing user end applications, which has helped me immensely. Similarly, the project has aided many others, including friends of mine, into learning how to debug software on a lower level.&lt;/p&gt;
&lt;p&gt;Bit Slicer has been referenced in YouTube &lt;a href=&#34;https://github.com/zorgiepoo/Bit-Slicer/wiki/Video-Tutorials&#34;&gt;videos&lt;/a&gt;, blog posts, and security talks. It has been used heavily by a younger audience to just apply their favorite cheat mods, and by a more technical audience for analyzing a program&amp;rsquo;s memory structure in depth. Its source code has been used to help others understand how it functions; its code has helped others make their own programs, even including commercial ones.&lt;/p&gt;
&lt;p&gt;To this day, curious tinkerers still utilize the application and ask questions regarding it use.&lt;/p&gt;
&lt;p&gt;A developer once asked me how I motivated myself into spending a couple thousand commits worth on developing this application.&lt;/p&gt;
&lt;p&gt;I do not know the all encompassing way to respond to that question. But I do know I had fun modifying video games and I wanted to make that task more feasible.&lt;/p&gt;</content:encoded>
    </item>
    
    <item>
      <title>Distributing Binaries on Linux</title>
      <link>https://zgcoder.net/ramblings/distributing-linux-binaries/</link>
      <pubDate>Sat, 16 May 2020 18:34:46 -0700</pubDate>
      
      <guid>https://zgcoder.net/ramblings/distributing-linux-binaries/</guid>
      <description>&lt;p&gt;When I ported Sky Checkers to Linux a decade ago, distributing binaries to users on the platform was a painful experience. Now, the situation has improved a little. Last week I released Sky Checkers binaries for Linux on the &lt;a href=&#34;https://snapcraft.io/skycheckers&#34;&gt;Snap Store&lt;/a&gt; and &lt;a href=&#34;https://flathub.org/apps/details/net.zgcoder.skycheckers&#34;&gt;Flathub&lt;/a&gt;. I will discuss what distribution approaches I looked at and why I ultimately decided to distribute my software through these channels.&lt;/p&gt;</description>
      <content:encoded>&lt;p&gt;When I ported Sky Checkers to Linux a decade ago, distributing binaries to users on the platform was a painful experience. Now, the situation has improved a little. Last week I released Sky Checkers binaries for Linux on the &lt;a href=&#34;https://snapcraft.io/skycheckers&#34;&gt;Snap Store&lt;/a&gt; and &lt;a href=&#34;https://flathub.org/apps/details/net.zgcoder.skycheckers&#34;&gt;Flathub&lt;/a&gt;. I will discuss what distribution approaches I looked at and why I ultimately decided to distribute my software through these channels.&lt;/p&gt;
&lt;h2 id=&#34;dependency-bundling&#34;&gt;Dependency Bundling&lt;/h2&gt;
&lt;p&gt;The first approach for distributing my software I looked into is static linking. Initially I wanted to only statically link 3rd party dependencies but distinguishing which of my linked dependencies on my system are 3rd party is not straightforward. This lead me to statically link all libraries including glibc, which should be statically linked anyway for compatibility sake. However, static linking does not integrate with the system correctly for functions in glibc &lt;a href=&#34;https://stackoverflow.com/questions/15165306/compile-a-static-binary-which-code-there-a-function-gethostbyname&#34;&gt;such as gethostbyname()&lt;/a&gt; or anything from OpenGL. Furthermore, the Linux ecosystem has resistance towards static linking, making it more painful when I have to chase down static versions of libraries not readily available.&lt;/p&gt;
&lt;p&gt;I also explored bundling dynamic libraries and creating a wrapper shell script that set the dynamic loader path, but this approach has the same drawbacks with additional complexity. I also did not want to create or run a shell script.&lt;/p&gt;
&lt;p&gt;These approaches may also require a developer to be compiling on the oldest version of a distribution they intend to support, which I want to avoid out of principle.&lt;/p&gt;
&lt;p&gt;Thus distributing precompiled binaries, whether as a .deb, .rpm, or from a tgz archive, is not great.&lt;/p&gt;
&lt;h2 id=&#34;traditional-package-management&#34;&gt;Traditional Package Management&lt;/h2&gt;
&lt;p&gt;I briefly looked at traditional package management options such as distributing my software through Debian and RPM. I was turned off by the lack of simple documentation and processes involved as well as political concerns; for example, I wanted to distribute non-free data assets and that had implications on what channels my software can be distributed through. The process on the surface also appeared to be slow. Furthermore, a developer can&amp;rsquo;t ensure that a user can install the most recent version of a library required for the best user experience. I am not the only one that finds this experience painful. Listen to Linus&amp;rsquo;s &lt;a href=&#34;https://youtu.be/5PmHRSeA2c8?t=340&#34;&gt;rant&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Additionally, software that becomes delivered through these channels may not be easy to install. If installing software requires command line usage on popular user friendly distributions, then that&amp;rsquo;s not acceptable.&lt;/p&gt;
&lt;p&gt;Some free software I&amp;rsquo;ve seen also passes responsibility of maintaining packages to volunteers of a Linux distribution. This is also not ideal. The developer should be responsible for maintaining packages for all distributions and maintenance should not be a burden. Updates to software should be in sync with all supported distributions.&lt;/p&gt;
&lt;h2 id=&#34;appimage&#34;&gt;AppImage&lt;/h2&gt;
&lt;p&gt;&lt;a href=&#34;http://appimage.org&#34;&gt;AppImage&lt;/a&gt; allows a developer to create a binary with bundled dependencies that can run anywhere without additional setup.&lt;/p&gt;
&lt;p&gt;This technology looks nice but has a few drawbacks for production. The first drawback is the lack of desktop integration out of the box on popular distributions. The second one is making users set the executable bit of an AppImage they download online. The last one is producing an AppImage requires the developer to be on an &lt;a href=&#34;https://github.com/AppImage/AppImageKit/wiki/Creating-AppImages/cc2441518975caca23e9ce2dba6f08a22c678d1e#creating-appimages-that-are-compatible-with-many-systems&#34;&gt;old enough system&lt;/a&gt; with older versions of system libraries installed, which I want to avoid.&lt;/p&gt;
&lt;h2 id=&#34;snap--flatpak&#34;&gt;Snap &amp;amp; Flatpak&lt;/h2&gt;
&lt;p&gt;&lt;a href=&#34;https://snapcraft.io&#34;&gt;Snap&lt;/a&gt; and &lt;a href=&#34;https://flatpak.org&#34;&gt;Flatpak&lt;/a&gt; are finally what I ended up on in this day and age. They allow the developer to specify what dependencies to bundle and allow specifying a base runtime of libraries to use, which makes compatibility more deterministic. They also have software centers that are embraced by popular distributions which makes installation friendly there. Lastly, they make shipping closed source software more of a possibility.&lt;/p&gt;
&lt;p&gt;Unfortunately, two of these competing technologies exist. Maybe some day Canonical will give up on Snap and migrate onto Flatpak, although I do like snaps in some ways better.&lt;/p&gt;
&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;Ultimately, none of the approaches except for distributing through the Snap Store and Flathub worked well for me. This is due to lack of control, ease of use, binary stability, politics, etc.&lt;/p&gt;
&lt;p&gt;Unfortunately, Snap and Flatpak have issues on their own such as bloating software sizes, slowing down application launches, having a much to be desired sandboxing model, and perhaps UI integration issues. They also receive a bad reputation from users that may be unaware or do not sympathize about the painful state of distributing software on Linux.&lt;/p&gt;
&lt;p&gt;Some users may also believe these packages are bad from a security point of view for not allowing distributions to update vulnerabilities in dependencies. My take is that developers should be managing vulnerabilities in their application code and in their dependencies. I do not trust library authors for maintaining compatibility despite their best efforts nor want to look out for defects or missing features in old libraries users may install. Software distribution on macOS and Windows &lt;a href=&#34;https://en.wikipedia.org/wiki/AppImage#cite_note-16&#34;&gt;gets this right&lt;/a&gt;; apps bundle 3rd party dependencies and they are maintained by the developer. Snap and Flatpak packages may also provide limited degree of sandboxing which makes assessing security not so black and white.&lt;/p&gt;
&lt;p&gt;Overall, although Snap and Flatpak have significant issues, the other alternatives for distributing applications tend to be worse off from my perspective. Hopefully distributing software on Linux will further improve in the next decade.&lt;/p&gt;</content:encoded>
    </item>
    
    <item>
      <title>Sky Checkers for iOS</title>
      <link>https://zgcoder.net/ramblings/skycheckers-ios/</link>
      <pubDate>Fri, 10 Apr 2020 22:50:00 +0000</pubDate>
      
      <guid>https://zgcoder.net/ramblings/skycheckers-ios.html</guid>
      <description>&lt;p&gt;Last year I rambled about making a &lt;a href=&#34;https://zgcoder.net/ramblings/skycheckers-update/&#34;&gt;major update to the rendering and netcode&lt;/a&gt; in Sky Checkers. This week I uploaded an even newer update that supports playing on Apple&amp;rsquo;s mobile platforms! Big architectural changes were made along this journey to iOS, but I will focus on just one interesting challenge I encountered for creating this port.&lt;/p&gt;</description>
      <content:encoded>&lt;p&gt;Last year I rambled about making a &lt;a href=&#34;https://zgcoder.net/ramblings/skycheckers-update/&#34;&gt;major update to the rendering and netcode&lt;/a&gt; in Sky Checkers. This week I uploaded an even newer update that supports playing on Apple&amp;rsquo;s mobile platforms! Big architectural changes were made along this journey to iOS, but I will focus on just one interesting challenge I encountered for creating this port.&lt;/p&gt;
&lt;h2 id=&#34;touch-controls&#34;&gt;Touch Controls&lt;/h2&gt;
&lt;p&gt;The challenge in making the mobile port play well is all in the controls. The desktop version of Sky Checkers uses the arrow keys and space bar for the primary player by default so I needed a way to map that experience to iOS. I thought of two possible approaches:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Stick a fixed virtual 4-directional d-pad that responds to touch input on the left side of the screen and a fire button on the right side of the screen.&lt;/li&gt;
&lt;li&gt;Move by holding down a horizontal or vertical swipe and fire by tapping anywhere.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The first approach seemed obvious due to being seen commonly in arcade ports and emulators. However, I really liked the second approach because I didn&amp;rsquo;t want fixed virtual controls on the screen and I wanted the flexibility of using the controls anywhere.&lt;/p&gt;
&lt;p&gt;So I implemented the swipe and tap gesture controls. The controls worked out much better than I had anticipated; they even felt competitive to the desktop experience. I was relieved and hopeful. For testing, I handed the game over to a couple friends to try.&lt;/p&gt;
&lt;p&gt;They couldn&amp;rsquo;t move 🙁.&lt;/p&gt;
&lt;p&gt;They tried moving by touching and dragging the character along a direction. In this case, the character would soon stop moving as they released the touch. They didn&amp;rsquo;t realize characters are not touch interactive in this game and that the touch gesture had to be held down for continuous movement. I realized quickly I needed to make a tutorial.&lt;/p&gt;
&lt;p&gt;I set out to create the tutorial with several stages. First a player learns how to move, then the player learns how to move efficiently without halting, and lastly the player learns how to knock off enemies. I displayed written instructions to swipe a direction to begin movement and release to stop movement.&lt;/p&gt;
&lt;p&gt;My testers still couldn&amp;rsquo;t move.&lt;/p&gt;
&lt;p&gt;In another attempt, I added visuals showing the potential changes in movement a player could make. These visuals changed position on screen dynamically based on the current touch input.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://zgcoder.net/software/skycheckers/images/ios-ramble/first-arrow-attempt.png?1&#34; alt=&#34;First Attempt&#34;&gt;&lt;/p&gt;
&lt;p&gt;This confused players instead of aiding them. They were also still trying to drag the character.&lt;/p&gt;
&lt;p&gt;So despite not wanting to convey a fixed d-pad, I gave up and added one to the left side of the screen that lit up the active direction:&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://zgcoder.net/software/skycheckers/images/ios-ramble/tutorial-arrows.png?1&#34; alt=&#34;Tutorial Arrows&#34;&gt;&lt;/p&gt;
&lt;p&gt;This helped quite a bit. But players still tried to drag the character by touch even despite the written instructions. So I added a boundary by disabling touch recognition in the middle of the board for the beginning tutorial stages. This eventually guided a confused player to try touching on the side of the screen because the game was no longer responding in any way to dragging a character from the center.&lt;/p&gt;
&lt;p&gt;After adding this, my friends were able to learn the controls and the success rate became higher. I did not want to convey the controls only functioned on a fixed part of the screen, however, that approach became easier to illustrate visually.&lt;/p&gt;
&lt;p&gt;One last major problem: some players were still learning inefficiently because they were not reading the instructions. They were too concentrated on the scene and touch interactivity to read the text. I finally addressed this by adding a black cover to direct the eyes towards the instructions at the beginning of each tutorial stage:&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://zgcoder.net/software/skycheckers/images/ios-ramble/black-tutorial-cover.png?1&#34; alt=&#34;Black Cover&#34;&gt;&lt;/p&gt;
&lt;h2 id=&#34;port-complete&#34;&gt;Port Complete&lt;/h2&gt;
&lt;p&gt;Overall I explored two potential approaches to controls. One is using swipe gestures and the other is using a fixed control pad. Sky Checkers uses swipe gestures and flexible touch controls, but after much experimenting, a fixed control pad became valuable for instructing. Additionally, touch input boundaries and guides on where to focus attention were added.&lt;/p&gt;
&lt;p&gt;With incorporating all these details, my new friends gave me good feedback on learning how to play. Or they just didn&amp;rsquo;t want to make me feel bad 😉. Over the past few months, other changes were made in this update as well such as adding a pause menu and overhauling the controller support.&lt;/p&gt;
&lt;p&gt;If you have an up to date iPhone or iPad, give my game a test run on the &lt;a href=&#34;https://apps.apple.com/us/app/sky-checkers/id1506448773?ls=1&#34;&gt;App Store&lt;/a&gt;. Otherwise, check out my game for &lt;a href=&#34;https://zgcoder.net#sky-checkers&#34;&gt;other platforms&lt;/a&gt;. This may even be a great time to play online with friends during the lockdown.&lt;/p&gt;
&lt;p&gt;I will welcome any feedback 🙂.&lt;/p&gt;</content:encoded>
    </item>
    
    <item>
      <title>Sky Checkers</title>
      <link>https://zgcoder.net/ramblings/skycheckers-update/</link>
      <pubDate>Sun, 28 Apr 2019 01:42:00 +0000</pubDate>
      
      <guid>https://zgcoder.net/ramblings/skycheckers-update.html</guid>
      <description>&lt;p&gt;Over 10 years ago I dreamt of creating a fun 3-D multiplayer action packed game and started developing Sky Checkers. Last week, I released an update including major refinements developed in the past few months. Let me introduce the game and mention some of the highlights!&lt;/p&gt;</description>
      <content:encoded>&lt;p&gt;Over 10 years ago I dreamt of creating a fun 3-D multiplayer action packed game and started developing Sky Checkers. Last week, I released an update including major refinements developed in the past few months. Let me introduce the game and mention some of the highlights!&lt;/p&gt;
&lt;h2 id=&#34;gameplay&#34;&gt;Gameplay&lt;/h2&gt;
&lt;p&gt;&lt;img src=&#34;https://zgcoder.net/software/skycheckers/images/playing-thumb_v1_1.png&#34; alt=&#34;Gameplay&#34;&gt;&lt;/p&gt;
&lt;p&gt;Sky Checkers is a 1-4 player game where players knock other players off a checkerboard stage using their tile-crushing weapon. The last one standing wins! This game is most fun when battling several friends next to each other or online, but the game has AI (bots) to accompany missing humans.&lt;/p&gt;
&lt;p&gt;Not much has actually changed recently in terms of gameplay, but I want to highlight the improved AIs and how they function generally.&lt;/p&gt;
&lt;p&gt;For movement, every one or two seconds the AIs make a change in direction. They also change directions when they collide with another player or reach an end of the board. Previously, the AIs often stayed in one direction and didn&amp;rsquo;t change often. Now, they are a little smarter in making more changes, enabling them to be in the middle of the stage more often rather than the outer edges.&lt;/p&gt;
&lt;p&gt;For firing, AIs make a new decision every 0.25 seconds (&lt;a href=&#34;https://backyardbrains.com/experiments/reactiontime&#34;&gt;the average human reaction time&lt;/a&gt;). They may decide to do nothing which occurs more often for easy mode AIs than hard mode ones, or they will fire if they think they can knock another player out. Previously, the AIs would fire only if they were on the same row or column as another player. Now, the AIs also fire if their row or column is neighboring another player&amp;rsquo;s row or column. This enables AIs to fire based on predicting where players will move, which often imitates what humans do!&lt;/p&gt;
&lt;p&gt;While play testing with my friends and having other people provide feedback, I observed skills amongst them can vary widely. Easy mode AIs (the default mode) are tuned to be challenging for beginners. More experienced players can play against the medium or hard mode AIs which react more often.&lt;/p&gt;
&lt;h2 id=&#34;renderers&#34;&gt;Renderers&lt;/h2&gt;
&lt;p&gt;The rendering code used to draw the 3-D graphics on screen has changed significantly behind the scenes.&lt;/p&gt;
&lt;p&gt;Previously, Sky Checkers was using immediate mode OpenGL (eg: &lt;code&gt;glBegin&lt;/code&gt;, &lt;code&gt;glEnd&lt;/code&gt;) and GLUT for drawing some spherical objects and text.&lt;/p&gt;
&lt;p&gt;To support modern versions of OpenGL, I removed using GLUT utility functions and plotted coordinates for specific objects myself, replaced &lt;code&gt;glTranslate&lt;/code&gt;/&lt;code&gt;glRotate&lt;/code&gt;/&lt;code&gt;glScale&lt;/code&gt; by managing matrix multiplications myself, and created buffer objects from vertices, texture coordinates, or colors that are passed to shader programs to produce a final output.&lt;/p&gt;
&lt;p&gt;Once I supported modern OpenGL, I added a Metal renderer for macOS and a Direct3D 11 renderer for Windows, which are now the preferred backends for those respective platforms. In this process of adding more renderers, I needed to fix the draw order by rendering opaque objects first followed by translucent objects (from z-far to z-near).&lt;/p&gt;
&lt;p&gt;As for the rationale behind Metal and Direct3D: Metal is justified because OpenGL is deprecated on macOS and Metal provides better performance even for single threaded code. I also found both Metal and Direct3D to have a better explicit API and better platform support. I noticed OpenGL programs failed to run via remote desktop on Windows as one particular example where OpenGL didn&amp;rsquo;t shine.&lt;/p&gt;
&lt;p&gt;Moreover, learning to use other graphics APIs is fun and a worthwhile investment 😉. One day I may consider adding renderers for Direct3D 12 and then Vulkan if Linux support becomes better. I didn&amp;rsquo;t start with Vulkan because Metal seems easier and I didn&amp;rsquo;t want to rely on a 3rd party library that creates an impedance mismatch between the APIs (eg: MoltenVK).&lt;/p&gt;
&lt;h2 id=&#34;netcode&#34;&gt;Netcode&lt;/h2&gt;
&lt;p&gt;The netcode used to play with people online has improved the most in this update. Previously, online play was only usable in LAN environments or if players lived very close to each other. Now, this game can be played comfortably with friends on the opposite side of the country. Watch a &lt;a href=&#34;https://zgcoder.net/zfw/skycheckers_play_no_audio.mov&#34;&gt;video clip (no audio)&lt;/a&gt; of me being crushed by such friends!&lt;/p&gt;
&lt;p&gt;Message reliability has improved to achieve better latency. Messages are transferred using UDP which doesn&amp;rsquo;t guarantee that packets will arrive onto the other end or arrive in the correct order. To tackle the out of order problem, each packet is tagged with an increasing number to ensure they are processed in correct order. To ensure messages are not lost, packets for important messages are resent continously until the other side acknowledges that a message has been received. Important messages includes change in direction or firing, but not messages like position updates where the previous state doesn&amp;rsquo;t need to be processed. Individual messages are now also bit-packed and aggregated minimizing the number of bytes and how often packets are transferred.&lt;/p&gt;
&lt;p&gt;Interpolation has also been added to achieve smoother animation. When a client receives position updates from the server, instead of setting the position naively, the client now renders a few updates before the latest positional update allowing the client to smoothly interpolate to a target position. This also allows the client to have a position to update to in case one or two updates don&amp;rsquo;t arrive due to UDP unreliability. When positions of players become out of sync, the client tries to correct the position gradually over multiple frames.&lt;/p&gt;
&lt;p&gt;Prediction has lastly been added to achieve better responsiveness. When a client makes a decision such as firing or changing directions, the client immediately renders or predicts those changes before sending them and waiting for the server to tell the client what actions to perform. If a client makes a decision incorrectly, it can correct its prediction once the actions are received from the server. Without prediction, input on the clients side would feel lagged. Note to prevent cheating, servers are authorative and clients can only make decisions such as changing direction and firing, but not where to fire or where to be positioned on the stage.&lt;/p&gt;
&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;Sky Checkers is perceived as my first significant programming project. It has now been updated to support modern rendering APIs and smoother online play! Minor improvements have also been made recently in the AIs, animation, audio, and keyboard &amp;amp; gamepad input. The game also has been updated to using SDL 2 recently. Sky Checkers still has ways to go regarding polish and gameplay experience, but the recent behind the scenes improvements are satisfying.&lt;/p&gt;
&lt;p&gt;Please be sure to &lt;a href=&#34;https://github.com/zorgiepoo/Sky-Checkers&#34;&gt;check out the game&lt;/a&gt; and let me know what you think!&lt;/p&gt;</content:encoded>
    </item>
    
    <item>
      <title>My Website Design</title>
      <link>https://zgcoder.net/ramblings/my-website-design/</link>
      <pubDate>Sat, 30 Mar 2019 21:29:00 +0000</pubDate>
      
      <guid>https://zgcoder.net/ramblings/my-website-design.html</guid>
      <description>&lt;p&gt;Fifteen years ago I hosted a HTTP server to send files to my friends and created my personal website using a HTML template I scavenged from the web. For a decent 10 years, I used &lt;a href=&#34;http://www.openwebdesign.org/design/4056/Simplicity_two_point_oh/&#34;&gt;a theme&lt;/a&gt; which had served me quite well during the Web 2.0 era up until entering the mobile landscape. A few years ago, I designed my own website style that you see today.&lt;/p&gt;</description>
      <content:encoded>&lt;p&gt;Fifteen years ago I hosted a HTTP server to send files to my friends and created my personal website using a HTML template I scavenged from the web. For a decent 10 years, I used &lt;a href=&#34;http://www.openwebdesign.org/design/4056/Simplicity_two_point_oh/&#34;&gt;a theme&lt;/a&gt; which had served me quite well during the Web 2.0 era up until entering the mobile landscape. A few years ago, I designed my own website style that you see today.&lt;/p&gt;
&lt;h2 id=&#34;motivation&#34;&gt;Motivation&lt;/h2&gt;
&lt;p&gt;Knowing my website began to look dated and not be mobile friendly, I had no choice but to seek alternatives. In the end, I decided to write my next website iteration from scratch because I wanted:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Minimal dependencies (no frameworks)&lt;/li&gt;
&lt;li&gt;No flashiness, banners, background pictures, cookie requesting pop-ups, &lt;a href=&#34;https://mattgemmell.com/comments-off/&#34;&gt;commenting&lt;/a&gt;, dynamic behavior, etc&lt;/li&gt;
&lt;li&gt;No JavaScript code (better for screen readers, search engines, NoScript users)&lt;/li&gt;
&lt;li&gt;Markdown generated content&lt;/li&gt;
&lt;li&gt;Scaling to mobile devices without differing in appearance or function&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://html5.validator.nu&#34;&gt;Valid&lt;/a&gt; HTML&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Above all else, I wanted &lt;strong&gt;focus&lt;/strong&gt;. I removed tabbed navigation that linked to pages with weak content and focussed on a single-column based page to showcase my software.&lt;/p&gt;
&lt;p&gt;I also wanted a simple flatter layout with more style than a text document from the 90s 😊.&lt;/p&gt;
&lt;h2 id=&#34;owning-the-stack&#34;&gt;Owning the Stack&lt;/h2&gt;
&lt;p&gt;I write content in &lt;a href=&#34;https://www.markdownguide.org/getting-started/&#34;&gt;Markdown&lt;/a&gt; and use &lt;a href=&#34;https://jekyllrb.com&#34;&gt;Jekyll&lt;/a&gt; to statically generate my HTML and blog posts.&lt;/p&gt;
&lt;p&gt;I created the CSS myself, which I did by looking up documentation and seeing how a couple other websites functioned. I ended up with a CSS style for the &lt;a href=&#34;../../css/main.css&#34;&gt;homepage&lt;/a&gt; and the &lt;a href=&#34;../../css/ramblings.css&#34;&gt;blog&lt;/a&gt; that are both very short.&lt;/p&gt;
&lt;p&gt;Owning the stack means that I understand what goes into the generated website content, or at least that it would not be difficult to understand if I were to forget specific details. As always, less code is easier to maintain and I wanted to avoid validating and updating large dependencies (which often break compatibility).&lt;/p&gt;
&lt;p&gt;I can also adopt features or customize my website when I see fit. For example, if you have been visiting my website recently under Dark mode in Safari, you may have noticed the &lt;a href=&#34;https://zgcoder.net/zfw/images/b6ffcf6866.png&#34;&gt;lights turned off&lt;/a&gt;. More systems and web browsers will support this mode in a matter of time.&lt;/p&gt;
&lt;h2 id=&#34;moving-forward&#34;&gt;Moving Forward&lt;/h2&gt;
&lt;p&gt;Overall, I&amp;rsquo;m quite pleased with how my latest website iteration turned out. While I admit this style may be tailored to a personal sort of feel, I hope this style serves me well for the next decade. When it becomes dated, I should not have a difficult time updating it due to having minimal dependence.&lt;/p&gt;
&lt;p&gt;In spirit of this post, I have posted this theme on &lt;a href=&#34;https://github.com/zorgiepoo/website-mini&#34;&gt;GitHub&lt;/a&gt; hoping that it may encourage others that designing a website isn&amp;rsquo;t so daunting and can be very rewarding!&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;April 12, 2020&lt;/strong&gt;: I no longer have my theme hosted on GitHub and do not use Jekyll anymore. I switched to using &lt;a href=&#34;https://gohugo.io&#34;&gt;Hugo&lt;/a&gt;, which is quite similar but fits my needs better.&lt;/p&gt;</content:encoded>
    </item>
    
    <item>
      <title>Komet</title>
      <link>https://zgcoder.net/ramblings/komet/</link>
      <pubDate>Sat, 23 Mar 2019 16:36:00 +0000</pubDate>
      
      <guid>https://zgcoder.net/ramblings/komet.html</guid>
      <description>&lt;p&gt;Today I released an update for &lt;a href=&#34;https://github.com/zorgiepoo/Komet&#34;&gt;Komet&lt;/a&gt;: a utility for writing commit messages on macOS. The latest bug fixes aren&amp;rsquo;t too interesting, so I will instead discuss how this project came to be!&lt;/p&gt;</description>
      <content:encoded>&lt;p&gt;Today I released an update for &lt;a href=&#34;https://github.com/zorgiepoo/Komet&#34;&gt;Komet&lt;/a&gt;: a utility for writing commit messages on macOS. The latest bug fixes aren&amp;rsquo;t too interesting, so I will instead discuss how this project came to be!&lt;/p&gt;
&lt;h2 id=&#34;why-i-wrote-komet&#34;&gt;Why I wrote Komet&lt;/h2&gt;
&lt;p&gt;&lt;img src=&#34;https://zgcoder.net/software/komet/images/comet128.png&#34; alt=&#34;Komet Icon&#34;&gt;&lt;/p&gt;
&lt;p&gt;One day, a couple years ago, I was complaining in an IRC channel about how I loathed using vim for writing commit messages.&lt;/p&gt;
&lt;p&gt;I disliked using vim, which I was only using regularly for commit messages, because I frequently invoked &amp;ldquo;simple&amp;rdquo; sequences that ought to be in muscle memory like &lt;code&gt;&amp;lt;escape&amp;gt;&amp;lt;shift-down&amp;gt;;&amp;lt;shift-up&amp;gt;wq&amp;lt;return&amp;gt;&lt;/code&gt; wrong. As one example, if I even typed &lt;code&gt;Wq&lt;/code&gt; instead of &lt;code&gt;wq&lt;/code&gt; (note shift was held down an extra character), vim would fail. In other scenarios, I accidentally entered an unfamiliar editing mode.&lt;/p&gt;
&lt;p&gt;I also disliked that quitting without saving changes &lt;a href=&#34;https://stackoverflow.com/questions/4323440/how-do-i-stop-a-git-commit-when-vi-is-on-the-screen-waiting-for-a-commit-message/4323790&#34;&gt;doesn&amp;rsquo;t necessarily abort a commit&lt;/a&gt; (people still don&amp;rsquo;t believe me when I tell them this).&lt;/p&gt;
&lt;p&gt;While the majority in the IRC channel I was ranting in were happy with their editors of choice including vim, a couple sympathized with me. Knowing I wasn&amp;rsquo;t alone was enough to motivate me to seek alternatives and create my own if necessary.&lt;/p&gt;
&lt;p&gt;My core requirements were to not discourage poor short commit messages (eg: &lt;code&gt;git -m&lt;/code&gt;), compliment command line usage (no VCS GUI or IDEs), use easy native &lt;code&gt;command&lt;/code&gt; shortcuts (no &lt;code&gt;escape&lt;/code&gt;), be non-obstructive (not bring up other documents), and not be stuck in the mental model to close &lt;em&gt;and&lt;/em&gt; save a file.&lt;/p&gt;
&lt;p&gt;That eliminated everything available to me so I set out to make my own commit editor including &lt;a href=&#34;https://github.com/zorgiepoo/Komet&#34;&gt;additional features&lt;/a&gt; like spell check and highlight warnings to improve ease of use and write better quality commit messages.&lt;/p&gt;
&lt;h2 id=&#34;development&#34;&gt;Development&lt;/h2&gt;
&lt;p&gt;&lt;img src=&#34;https://zgcoder.net/zfw/komet-dark.png&#34; alt=&#34;Dark theme of Komet&#34;&gt;&lt;/p&gt;
&lt;p&gt;I received help in the IRC room for designing the user interface. Believe it or not, having UI elements in the title bar section was not obvious to me. Neither were choices regarding colors, fonts, and highlighting. Feedback received from prototyping and beta testing was very helpful.&lt;/p&gt;
&lt;p&gt;After I pushed out an initial release, I showed it off as a &lt;a href=&#34;https://news.ycombinator.com/show&#34;&gt;Show HN&lt;/a&gt; which retrieved traction. Shortly afterwards, Trevor Fountain coded support for &lt;a href=&#34;https://github.com/zorgiepoo/Komet/pull/4&#34;&gt;stylistic themes&lt;/a&gt; and designed the current application icon making Komet appeal to a wider audience. Indeed, I now use the dark theme myself, shown above.&lt;/p&gt;
&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;Thus that is how Komet came to be. I identified a frustrating problem for an important task I encountered daily, and sought out to optimize writing commits for mine and others needs.&lt;/p&gt;
&lt;p&gt;Don&amp;rsquo;t just take my word for it. Feel free to read &lt;a href=&#34;http://texasexpat.net/2017/07/write-beautiful-commit-logs&#34;&gt;others thoughts&lt;/a&gt; on Komet or check out an &lt;a href=&#34;https://ar.al/2018/08/15/introducing-gnomit-a-simple-git-commit-message-editor-for-gnome/&#34;&gt;inspired alternative&lt;/a&gt; for Gnome.&lt;/p&gt;
&lt;p&gt;Regardless of your religious text editing preferences, continue to commit or komet away!&lt;/p&gt;</content:encoded>
    </item>
    
    <item>
      <title>Grammar Errors in Software</title>
      <link>https://zgcoder.net/ramblings/grammar-errors-software/</link>
      <pubDate>Thu, 14 Mar 2019 04:29:00 +0000</pubDate>
      
      <guid>https://zgcoder.net/ramblings/grammar-errors-software.html</guid>
      <description>&lt;p&gt;We dream that software is crafted in art form, that its creators have done everything possible to make their software friendly and professional. Unfortunately, software&amp;rsquo;s creators are just humans subject to making common grammar mistakes I nitpick below.&lt;/p&gt;</description>
      <content:encoded>&lt;p&gt;We dream that software is crafted in art form, that its creators have done everything possible to make their software friendly and professional. Unfortunately, software&amp;rsquo;s creators are just humans subject to making common grammar mistakes I nitpick below.&lt;/p&gt;
&lt;h2 id=&#34;incorrect-pluralization&#34;&gt;Incorrect Pluralization&lt;/h2&gt;
&lt;p&gt;Are you guilty of writing code like this?&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span class=&#34;n&#34;&gt;printf&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;You have %d new messages!&lt;/span&gt;&lt;span class=&#34;se&#34;&gt;\n&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;messages&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This only produces a correct sentence when the number of messages isn&amp;rsquo;t &lt;code&gt;1&lt;/code&gt;. A way to make this code more correct:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span class=&#34;n&#34;&gt;printf&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;You have %d new message%s!&lt;/span&gt;&lt;span class=&#34;se&#34;&gt;\n&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;messages&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;messages&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;!=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;?&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;s&amp;#34;&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;));&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;I won&amp;rsquo;t call out any names but I saw this error in a popular iOS app I use daily.&lt;/p&gt;
&lt;p&gt;Note localized software tends to exercise more care due to different languages having &lt;a href=&#34;https://unicode.org/cldr/charts/latest/supplemental/language_plural_rules.html&#34;&gt;different number of pluralization forms&lt;/a&gt;. I believe that software that isn&amp;rsquo;t localized (many aren&amp;rsquo;t) should still care, which even includes the likes of command line utilties.&lt;/p&gt;
&lt;h2 id=&#34;using-nouns-as-verbs&#34;&gt;Using Nouns as Verbs&lt;/h2&gt;
&lt;p&gt;Ever see a website tellling you to &amp;ldquo;please login&amp;rdquo; or a mobile app informing you to &amp;ldquo;setup your account&amp;rdquo;?&lt;/p&gt;
&lt;p&gt;Words like login or setup have no verb form. Alternatives here are &amp;ldquo;log in&amp;rdquo; and &amp;ldquo;set up.&amp;rdquo;&lt;/p&gt;
&lt;h2 id=&#34;arent-you-fetching&#34;&gt;Aren&amp;rsquo;t you Fetching?&lt;/h2&gt;
&lt;p&gt;The way I know someone has been programming computers long enough is if &amp;ldquo;fetching&amp;rdquo; is in their vocabulary to mean retrieving. This actually confuses users because this form doesn&amp;rsquo;t exist &lt;a href=&#34;https://www.merriam-webster.com/dictionary/fetching&#34;&gt;in the dictionary&lt;/a&gt; the way programmers desire.&lt;/p&gt;
&lt;p&gt;Fetching aside, this point applies to any too technical or made up term. I like poking fun at this word though.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;edit: Actually, I stand corrected, and the definition of &amp;ldquo;fetching&amp;rdquo; does exist in the way programmers think. But I still recommend using a better term such as receiving.&lt;/em&gt;&lt;/p&gt;
&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;Clearly, these are not all the grammar errors programmers make. I have not even touched upon user interface design.&lt;/p&gt;
&lt;p&gt;I just wanted to point out common grammar errors that I see regularly which are pet peeves of mine. I exercise great care to avoid making these mistakes, so maybe you will too!&lt;/p&gt;</content:encoded>
    </item>
    
  </channel>
</rss>
