<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title></title>
    <description></description>
    <link>https://glouw.com</link>
    <atom:link href="https://glouw.com/feed.xml" rel="self" type="application/rss+xml" />
    
      <item>
        <title>Ensim4</title>
        <description>&lt;p&gt;&lt;a href=&quot;https://github.com/glouw/ensim4&quot;&gt;Github Source&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Engine Simulator 4, or ensim4, is a rewrite of ensim3 with emphasis on cache locality,
and now includes SIMD based branchless 1D-CFD (Computational Fluid Dynamics) LF (Lax–Friedrichs)
for audio generation.&lt;/p&gt;

&lt;p&gt;Seen here, an inline 8 engine with modeled fuel injection, combustion, isentropic mass flow,
and two exhaust plenums, each output displacement vs. amplitude in their &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;wave_0_pa&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;wave_1_pa&lt;/code&gt;
widgets to the right:&lt;/p&gt;

&lt;iframe width=&quot;720&quot; height=&quot;405&quot; src=&quot;https://www.youtube.com/embed/fq1WPNeVXrI&quot; frameborder=&quot;0&quot; allow=&quot;autoplay; encrypted-media&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;

&lt;p&gt;Having explored both HLLC and HLLE Riemann solvers (which promised better audio fidelity due to their
better contact surface restoration characteristics) I found that the audio fidelity of a branchless Riemann-like
Lax–Friedrichs solver is almost imperceptible from the Riemann powerhouses, especially for straight pipes where
flow is almost guaranteed to be subsonic.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;static struct wave_flux_s
calc_solver_flux(struct wave_prim_s ql, struct wave_prim_s qr)
{
    struct wave_cons_s ul = prim_to_cons(ql);
    struct wave_cons_s ur = prim_to_cons(qr);
    double cl = sqrt(g_wave_gamma * ql.p / ql.r);
    double cr = sqrt(g_wave_gamma * qr.p / qr.r);
    struct wave_flux_s fl = { .r = ul.m, .m = ul.m * ql.u + ql.p, .e = (ul.e + ql.p) * ql.u };
    struct wave_flux_s fr = { .r = ur.m, .m = ur.m * qr.u + qr.p, .e = (ur.e + qr.p) * qr.u };
    double a = fmax(fabs(ql.u) + cl, fabs(qr.u) + cr);
    /*
     *       1               1
     * FC = --- (FL + FR) - --- a * (UR - UL)
     *       2               2
     */
    return (struct wave_flux_s) {
        .r = 0.5 * (fl.r + fr.r) - 0.5 * a * (ur.r - ul.r),
        .m = 0.5 * (fl.m + fr.m) - 0.5 * a * (ur.m - ul.m),
        .e = 0.5 * (fl.e + fr.e) - 0.5 * a * (ur.e - ul.e),
    };
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The branchless nature is SIMD friendly and readily auto-vectorizes, at least with clang.&lt;/p&gt;

&lt;p&gt;For reference, consider the inline 8 from ensim2 which did not model exhaust pipe CFD, where simply the
exhaust plenum’s chamber pressure was sampled:&lt;/p&gt;

&lt;iframe width=&quot;720&quot; height=&quot;405&quot; src=&quot;https://www.youtube.com/embed/fSB2aZC542A&quot; frameborder=&quot;0&quot; allow=&quot;autoplay; encrypted-media&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;
</description>
        <pubDate>Sun, 12 Oct 2025 00:00:00 +0000</pubDate>
        <link>https://glouw.com//2025/10/12/Ensim4.html</link>
        <guid isPermaLink="true">https://glouw.com//2025/10/12/Ensim4.html</guid>
      </item>
    
      <item>
        <title>Ensim3</title>
        <description>&lt;p&gt;&lt;a href=&quot;https://github.com/glouw/ensim3&quot;&gt;GitHub Source&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Engine Simulator 3, or ensim3, is my third attempt at modelling an open source
internal combustion engine simulator. Built on graph theory fundamentals (Directed Cyclic Graphs and such),
ensim3 executes node pairs connected by edge breadth-first as an isentropic flow transaction.
Audio is sampled in the engine collector and convoluted with an impulse reverb.&lt;/p&gt;

&lt;iframe width=&quot;720&quot; height=&quot;405&quot; src=&quot;https://www.youtube.com/embed/ALh3dlBqQvo&quot; frameborder=&quot;0&quot; allow=&quot;autoplay; encrypted-media&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;

&lt;p&gt;This video showcases some of an inline 3’s intrinsic gas properties - air fuel mixture,
when unburned during an engine overrun, pumps a gas mixture of greater molar mass into the collector,
causing a pressure fluctuation phenomena known as overrun burble. Modifying exhaust runner length
changes pulse arrival time, which changes the sound of the burble.&lt;/p&gt;

&lt;p&gt;To accurately capture burble, and avoid unequal flow transactions, Directed Cyclic Graphs (DCG) traverse breadth first. Seen below,
an inline 8 engine &lt;em&gt;hypothetical&lt;/em&gt; execution with plenum intake left, and four exhaust system, ejecting to the atmosphere right, with a turbo
charger making use of latent heat and pressure of each exhaust system:&lt;/p&gt;

&lt;iframe width=&quot;720&quot; height=&quot;405&quot; src=&quot;https://www.youtube.com/embed/jX-kl0I_fHk&quot; frameborder=&quot;0&quot; allow=&quot;autoplay; encrypted-media&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;

&lt;p&gt;While ensim3 does not support feedback mechanisms like turbo chargers yet, the video above exemplifies that a DCG framework can.&lt;/p&gt;

&lt;p&gt;The workings for this discussion rely on shared pointers, though clever use of unique pointers can offer a nice 30% performance boost.
With a widget base class, each node is connected together by user input. Shared or weak pointers are automatically deduced,
and each node can at runtime be swapped for static volume (plenum, runner, exhaust, etc), and/or dynamic volume (a piston).
The conventional flow math, directed by isentropic choked flow, moves gas mass left to right, from widget to widget.&lt;/p&gt;

&lt;p&gt;A node (as a parent) holds shared or weak children (next):&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;template &amp;lt;typename T&amp;gt;
using non_unique_ptr = variant&amp;lt;shared_ptr&amp;lt;T&amp;gt;, weak_ptr&amp;lt;T&amp;gt;&amp;gt;;

struct node_t : enable_shared_from_this&amp;lt;node_t&amp;gt;
{
    unique_ptr&amp;lt;widget_t&amp;gt; widget = {};
    list&amp;lt;non_unique_ptr&amp;lt;node_t&amp;gt;&amp;gt; next = {};
}
...
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;BFS iteration as a public member function serves to operate on the parent (finding a node, rendering a node, etc), and serves
to operate on parent to child (rendering lines between nodes, flowing from node to node, etc):&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;...
using handle_node = function&amp;lt;shared_ptr&amp;lt;node_t&amp;gt;(const shared_ptr&amp;lt;node_t&amp;gt;&amp;amp;)&amp;gt;;
using handle_edge = function&amp;lt;shared_ptr&amp;lt;node_t&amp;gt;(const shared_ptr&amp;lt;node_t&amp;gt;&amp;amp;, const shared_ptr&amp;lt;node_t&amp;gt;&amp;amp;)&amp;gt;;

shared_ptr&amp;lt;node_t&amp;gt; node_t::iterate(const handle_node&amp;amp; handle_node, const handle_edge&amp;amp; handle_edge)
{
    queue&amp;lt;shared_ptr&amp;lt;node_t&amp;gt;&amp;gt; q;
    q.push(shared_from_this());
    while(!q.empty())
    {
        shared_ptr&amp;lt;node_t&amp;gt; parent = q.front();
        q.pop();
        if(handle_node(parent))
        {
            return parent;
        }
        for(const non_unique_ptr&amp;lt;node_t&amp;gt;&amp;amp; node : parent-&amp;gt;nodes)
        {
            if(holds_alternative&amp;lt;shared_ptr&amp;lt;node_t&amp;gt;&amp;gt;(node))
            {
                shared_ptr&amp;lt;node_t&amp;gt; child = get&amp;lt;shared_ptr&amp;lt;node_t&amp;gt;&amp;gt;(node);
                q.push(child);
                handle_edge(parent, child);
            }
            else
            if(shared_ptr&amp;lt;node_t&amp;gt; child = get&amp;lt;weak_ptr&amp;lt;node_t&amp;gt;&amp;gt;(node).lock())
            {
                handle_edge(parent, child);
            }
        }
    }
    return nullptr;
}
...
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Where utilization might be defined as:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;...
graph-&amp;gt;iterate(
    [](const shared_ptr&amp;lt;node_t&amp;gt;&amp;amp; parent)
    {
        parent-&amp;gt;widget-&amp;gt;do_work();
        return nullptr;
    },
    [](const shared_ptr&amp;lt;node_t&amp;gt;&amp;amp; parent, const shared_ptr&amp;lt;node_t&amp;gt;&amp;amp; child)
    {
        parent-&amp;gt;widget-&amp;gt;flow(child-&amp;gt;widget);
        return nullptr;
    }
);
...
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;do_work() performs mechanical and electrical work on a widget (adiabatic compression,
spark plug ignition), and flow() performs the transfer of moles, via isentropic flow,
from one node to the next.&lt;/p&gt;

&lt;p&gt;Ensim3’s procedural audio improves upon Ensim2’s procedural audio, effectively capturing nuances like engine burble. Ensim3
currently relies on impulse convolutions to capture exhaust reverb. Impulse reverbs capture room temperature acoustics, and
do not account for the fluid dynamics present in collector exhaust pipes, especially that of reflected pressure waves and
the varying speed of sound impacted by gas density and gas temperature. Nevertheless, one dimensional computational
fluid dynamics (1DCFD) solves such a problem, and a fourth attempt, aptly named ensim4 in the future, will solve this problem.
&lt;a href=&quot;https://github.com/glouw/ensim3&quot;&gt;Though, ensim3 is still very much worth the read for anyone curious on dependency free inline engine modeling.&lt;/a&gt;&lt;/p&gt;
</description>
        <pubDate>Mon, 20 Jan 2025 00:00:00 +0000</pubDate>
        <link>https://glouw.com//2025/01/20/Ensim3.html</link>
        <guid isPermaLink="true">https://glouw.com//2025/01/20/Ensim3.html</guid>
      </item>
    
      <item>
        <title>Ensim2</title>
        <description>&lt;p&gt;In this post I outline one way to simulate a four stroke Inline Internal Combustion Engine (IICE) with
realistic and performant procedural audio. The engine core utilizes fundamentals of thermodynamics,
fluid mechanics, classical dynamics, and (should you deviate from the above), high school chemistry.&lt;/p&gt;

&lt;p&gt;Applications include, but are not limited to, game development vehicular audio and physics:&lt;/p&gt;

&lt;iframe width=&quot;720&quot; height=&quot;405&quot; src=&quot;https://www.youtube.com/embed/fSB2aZC542A&quot; frameborder=&quot;0&quot; allow=&quot;autoplay; encrypted-media&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;

&lt;h3 id=&quot;defining-piston-kinematics&quot;&gt;Defining Piston Kinematics&lt;/h3&gt;

&lt;p&gt;An inline piston’s movement is constrained by its vertical axis. Updating a piston’s theta (in radians)
updates the piston pin’s y position (in meters) and its bearing &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;x&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;y&lt;/code&gt; position (in meters).
The conrod (connecting rod) length (in meters) and crank throw (in meters) are effectively constants.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;struct piston
{
    double pin_x_m;
    double pin_y_m;
    double bearing_x_m;
    double bearing_y_m;
    double theta_r;
    double conrod_m;
    double conrod_crank_throw_m;
};
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The piston updates with an applied angular velocity (in radians per second). The delta radians
applied to the piston’s theta is determined by the time step which is effectively the inverse of
a common audio sampling rate of 44100 Hz.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;#define DT_S (1.0 / 44100.0)

void
update_position(struct piston* self, const double angular_velocity_r_per_s)
{
    self-&amp;gt;theta_r += angular_velocity_r_per_s * DT_S;
    self-&amp;gt;bearing_x_m = self-&amp;gt;conrod_crank_throw_m * sin(self-&amp;gt;theta_r);
    self-&amp;gt;bearing_y_m = self-&amp;gt;conrod_crank_throw_m * cos(self-&amp;gt;theta_r);
    self-&amp;gt;pin_x_m = 0.0;
    self-&amp;gt;pin_y_m = sqrt(pow(self-&amp;gt;conrod_m, 2.0) - pow(self-&amp;gt;conrod_crank_throw_m * sin(self-&amp;gt;theta_r), 2.0)) + self-&amp;gt;conrod_crank_throw_m * cos(self-&amp;gt;theta_r);
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;defining-the-otto-cycle&quot;&gt;Defining the Otto Cycle&lt;/h3&gt;

&lt;p&gt;The piston provides engine torque by igniting a compressed air fuel mixture. This process
is known as the Otto cycle:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;A: Piston inlet opens.
B: Piston chamber expands. Cool atmospheric air draws in.
C: Piston inlet closes.
D: Piston chamber compresses. Air temperature and pressure raises due to compression.
E: Fuel is injected. Air to Fuel ratio is then roughly 14.7 parts air to 1 part fuel.
F: Air Fuel Mixture is combusted, creating a downwards force on the piston head.
G: Downwards force creates torque, causing the piston chamber to expand, cooling the piston gas and lowering pressure.
H: Piston outlet opens. Hot piston air expels to the atmosphere.
I: Piston outlet closes.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The cycle repeats. The four strokes of an IICE are then defined as:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;A + B: Intake stroke (0 * M_PI to 1 * M_PI)
C + D: Compression stroke (1 * M_PI to 2 * M_PI)
E + F + G: Expansion Power stroke (2 * M_PI to 3 * M_PI)
H + I: Exhaust stroke (3 * M_PI to 4 * M_PI)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The input of the Otto cycle relies on its output. That is to say, chamber expansion and compression in
step B and D require the mechanical force provided by the torque created in step G.
Since no system is truly perpetual, a secondary &lt;em&gt;starter&lt;/em&gt; motor with a large gear ratio
provides the initial compression and decompression torque. The starter motor then disconnects.&lt;/p&gt;

&lt;p&gt;Piston inlet and outlet openness (lift) ratio is a 4-5-6-7 polynomial function of piston theta,
where &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;engage_r&lt;/code&gt; (in radians) determines at which point valve opening begins, and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ramp_r&lt;/code&gt; the ramp length:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;double
calc_lift_ratio(double theta_r, double engage_r, double ramp_r)
{
    double theta_mod_four_stroke_r = calc_theta_mod_four_stroke_r(theta_r);
    if(theta_mod_four_stroke_r &amp;gt; engage_r)
    {
        double open_r = theta_mod_four_stroke_r - engage_r;
        double term1 = 35.0 * pow(open_r / ramp_r, 4.0);
        double term2 = 84.0 * pow(open_r / ramp_r, 5.0);
        double term3 = 70.0 * pow(open_r / ramp_r, 6.0);
        double term4 = 20.0 * pow(open_r / ramp_r, 7.0);
        return term1 - term2 + term3 - term4;
    }
    return 0.0;
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Where four stroke modulation is calculated as:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;#define FOUR_STROKE_R (4.0 * M_PI)

double
calc_theta_mod_four_stroke_r(double theta_r)
{
    return fmod(theta_r, FOUR_STROKE_R);
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;While our model &lt;em&gt;can&lt;/em&gt; be a piston connected to an atmospheric source and sink, engine sound and performance is greatly
improved upon by adding intake and exhaust chambers. The intake chamber is a lump sum of the throttle chamber, plenum,
and intake runner. Similarly, the exhaust chamber is a lump sum of the exhaust runner, collector,
tailpipe, muffler. The lump sum can be further broken down into individual chamber components to achieve more accurate
engine sounds and performance.&lt;/p&gt;

&lt;h3 id=&quot;defining-the-chamber&quot;&gt;Defining the Chamber&lt;/h3&gt;

&lt;p&gt;Chambers are comprised of a volume (in cubic meters) and a gas:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;struct chamber
{
    double volume_m3;
    struct gas gas;
};
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;A gas at rest is comprised of some mole count (in moles) and static temperature (in kelvins).
The mole count specifies the amount of substance (think gas molecules) physically present in a chamber.
The static temperature represents the average kinetic energy of the substance (think gas molecules)
moving in any random direction while also being at rest in bulk to the observer.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;struct gas
{
    double static_temperature_k;
    double moles;
};
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The static pressure of the gas is derived from the ideal gas law:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;#define R_J_PER_MOL_K 8.314

double
calc_static_pressure_pa(struct chamber* self)
{
    return (self-&amp;gt;gas.moles * R_J_PER_MOL_K * self-&amp;gt;gas.static_temperature_k) / self-&amp;gt;volume_m3;
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;A chamber’s static pressure represents the average force of molecules against the inner
walls of a chamber. Like with the static temperature definition, the velocity (in meters per second)
of each gas molecules is random, and so the net &lt;em&gt;bulk velocity&lt;/em&gt; of the gas is zero; the gas does not
move in any particular direction like a cool breeze on a warm summer’s day. IICE’s are
concerned with the movement of gas from intake to exhaust, and so a secondary one dimensional description
of the moving gas in terms of bulk momentum (in kilogram meters per second) is needed to describe the corollary
to static pressure and static temperature - total pressure and total temperature.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;struct gas
{
    double static_temperature_k;
    double moles;
+   double bulk_momentum_kg_m_per_s;
};
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Although to calculate total pressure and total temperature, the bulk velocity of the gas is to be derived from the
bulk momentum of the gas. The mass of the gas requires that we know the molar mass (in kilogram per mol) of the gas.
From the Otto cycle, the gasses present within any chamber are lumped into either air, fuel, or combusted.
Their specific molar masses are defined as:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;#define MOLAR_MASS_COMBUSTED_KG_PER_MOL 0.02885
#define MOLAR_MASS_AIR_KG_PER_MOL 0.0289647
#define MOLAR_MASS_FUEL_KG_PER_MOL 0.11423
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Updating the gas definition:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;struct gas
{
    double static_temperature_k;
    double moles;
    double bulk_momentum_kg_m_per_s;
+   double combusted_ratio;
+   double air_ratio;
+   double fuel_ratio;
};
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The molar mass of the chamber is then calculated as the sum of three:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;double
calc_molar_mass_kg_per_mol(struct chamber* self)
{
    return self-&amp;gt;gas.combusted_ratio * MOLAR_MASS_COMBUSTED_KG_PER_MOL
         + self-&amp;gt;gas.air_ratio * MOLAR_MASS_AIR_KG_PER_MOL
         + self-&amp;gt;gas.fuel_ratio * MOLAR_MASS_FUEL_KG_PER_MOL;
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;From the molar mass we can derive gas mass (in kilograms):&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;double
calc_mass_kg(struct chamber* self)
{
    return self-&amp;gt;gas.moles * calc_molar_mass_kg_per_mol(self);
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;And gas density (in kilogram per meter cubed):&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;double
calc_density_kg_per_m3(struct chamber* self)
{
    return calc_mass_kg(self) / self-&amp;gt;volume_m3;
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;And gas bulk velocity (in meters per second):&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;double
calc_bulk_velocity_m_per_s(struct chamber* self)
{
    return self-&amp;gt;gas.bulk_momentum_kg_m_per_s / calc_mass_kg(self);
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The dynamic pressure of the gas (in kelvin) is then defined as:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;double
calc_dynamic_pressure_pa(struct chamber* self)
{
    return calc_density_kg_per_m3(self) * pow(calc_bulk_velocity_m_per_s(self), 2.0) / 2.0;
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The total pressure of the gas the sum of dynamic and static pressure:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;double
calc_total_pressure_pa(struct chamber* self)
{
    return calc_static_pressure_pa(self) + calc_dynamic_pressure_pa(self);
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;And the total temperature of the gas, while knowing the gamma of the gas, is derived as:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;double
calc_total_temperature_k(struct chamber* self, double mach_number)
{
    return self-&amp;gt;gas.static_temperature_k * (1.0 + (calc_gamma(self) - 1.0) / 2.0 * pow(mach_number, 2.0));
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The gas gamma value (no dimensions) characterizes how a gas behaves during compression.
A higher gamma gas generally compresses more easily than a lower gamma gas,
and raises the temperature greater than that of a lower gamma gas, under the same compression scenario.
The gamma calculation is similar to that of the molar mass calculation:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;#define GAMMA_COMBUSTED 1.3
#define GAMMA_FUEL 1.15
#define GAMMA_AIR 1.4

double
calc_gamma(struct chamber* self)
{
    return self-&amp;gt;gas.combusted_ratio * GAMMA_COMBUSTED
         + self-&amp;gt;gas.air_ratio * GAMMA_AIR
         + self-&amp;gt;gas.fuel_ratio * GAMMA_FUEL;
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Compressing, or decompressing, the chamber to some new volume will respectively increase, or decrease,
the static temperature of the gas:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;void
compress_adiabatically(struct chamber* self, double new_volume_m3)
{
    self-&amp;gt;gas.static_temperature_k *= pow(self-&amp;gt;volume_m3 / new_volume_m3, calc_gamma(self) - 1.0);
    self-&amp;gt;volume_m3 = new_volume_m3;
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;defining-mach-number-and-mass-flow-rates&quot;&gt;Defining Mach Number and Mass Flow Rates&lt;/h3&gt;

&lt;p&gt;Flow from chamber to chamber is dictated by the mach number, as introduced as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mach_number&lt;/code&gt; in the
total temperature function. A mach number less than 1.0 indicates subsonic flow,
and a mach number equal to 1.0 indicates choked flow, or sonic flow. For purposes of IICE
design, mach numbers greater than 1.0 indicated supersonic flow and will not be used. A clamp
between 0.0 and 1.0 can be applied to the mach number calculation:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;double
calc_mach_number(double total_pressure_upstream_pa, double total_pressure_downstream_pa, double gamma_downstream)
{
    double compression_ratio = total_pressure_upstream_pa / total_pressure_downstream_pa;
    return sqrt((pow(compression_ratio, gamma_downstream / (gamma_downstream - 1.0)) - 1.0) * (2.0 / (gamma_downstream - 1.0)));
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Flow always occurs from the higher total pressure chamber to the lower total pressure chamber. An increase in cross sectional area
between two chambers will linearly increase mass flow rate under steady state conditions:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;double
calc_mass_flow_rate_kg_per_s(struct chamber* upstream, double mach_number, double cross_sectional_flow_area_m2)
{
    double term1 = cross_sectional_flow_area_m2 * calc_total_pressure_pa(upstream) / sqrt(calc_total_temperature_k(upstream, mach_number));
    double term2 = sqrt(calc_gamma(upstream) / calc_specific_gas_constant_j_per_kg_k(upstream)) * mach_number;
    double term3 = pow(1.0 + (calc_gamma(upstream) - 1.0) / 2.0 * pow(mach_number, 2.0), - (calc_gamma(upstream) + 1.0) / (2.0 * (calc_gamma(upstream) - 1.0)));
    return term1 * term2 * term3;
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Where the gas constant of a chamber (in joules per kilogram kelvin) is defined as:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;double
calc_specific_gas_constant_j_per_kg_k(struct chamber* self)
{
    return R_J_PER_MOL_K / calc_molar_mass_kg_per_mol(self);
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;defining-mass-transfer-between-chambers&quot;&gt;Defining Mass Transfer Between Chambers&lt;/h3&gt;

&lt;p&gt;The mass flowed from chamber to chamber is then:&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;double mass_flowed_kg = mass_flow_rate_kg_per_s * DT_S;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;And the bulk momentum flowed from chamber to chamber is then:&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;double bulk_momentum_flowed_kg_m_per_s = mass_flowed_kg * nozzle_velocity_m_per_s;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Given a flow function, where flow always occurs from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;x&lt;/code&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;y&lt;/code&gt;, where &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;x&lt;/code&gt; is the chamber with higher total pressure:&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;void
flow(struct chamber* x, struct chamber* y, double cross_sectional_flow_area_m2);
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The bulk moles transferred from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;x&lt;/code&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;y&lt;/code&gt; is defined as:&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;double moles_flowed = mass_flowed_kg / calc_molar_mass_kg_per_mol(x);
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;And the moles of the two chambers are updated:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;add_moles(x, -moles_flowed);
add_moles(y, +moles_flowed);
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Where:&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;void
add_moles(struct chamber* self, const double delta_moles)
{
    double new_moles = self-&amp;gt;gas.moles + delta_moles;
    double new_static_temperature_k = self-&amp;gt;gas.static_temperature_k * pow(new_moles / self-&amp;gt;gas.moles, (calc_gamma(self) - 1.0) / calc_gamma(self));
    self-&amp;gt;gas.static_temperature_k = new_static_temperature_k;
    self-&amp;gt;gas.moles = new_moles;
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Adding moles to a chamber increases the chamber’s static temperature, which in turn increases the static pressure.&lt;/p&gt;

&lt;p&gt;Momentum between chambers is then conserved by:&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;x-&amp;gt;gas.bulk_momentum_kg_m_per_s -= bulk_momentum_flowed_kg_m_per_s;
y-&amp;gt;gas.bulk_momentum_kg_m_per_s += bulk_momentum_flowed_kg_m_per_s;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Where extra consideration is taken to ensure the chamber’s gas momentum does not exceed the medium’s speed of sound.&lt;/p&gt;

&lt;p&gt;The downstream chamber, assuming flow always occurs from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;x&lt;/code&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;y&lt;/code&gt;, has its air, fuel, and combusted ratios mixed with the inflowing gas:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;y-&amp;gt;gas.air_ratio = calc_weighted_average(y-&amp;gt;gas.air_ratio, y-&amp;gt;gas.moles, x-&amp;gt;gas.air_ratio, moles_flowed);
y-&amp;gt;gas.fuel_ratio = calc_weighted_average(y-&amp;gt;gas.fuel_ratio, y-&amp;gt;gas.moles, x-&amp;gt;gas.fuel_ratio, moles_flowed);
y-&amp;gt;gas.combusted_ratio = calc_weighted_average(y-&amp;gt;gas.combusted_ratio, y-&amp;gt;gas.moles, x-&amp;gt;gas.combusted_ratio, moles_flowed);
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The upstream chamber is not mixed. Thermal cooling (or heating) of the downstream gas also occurs:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;y-&amp;gt;gas.static_temperature_k = calc_weighted_average(y-&amp;gt;gas.static_temperature_k, y-&amp;gt;gas.moles, x-&amp;gt;gas.static_temperature_k, moles_flowed);
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Where the weighted average function is defined as:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;double
calc_weighted_average(const double value1, const double weight1, const double value2, const double weight2)
{
    return (value1 * weight1 + value2 * weight2) / (weight1 + weight2);
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;defining-direct-fuel-injection-and-chamber-combustion&quot;&gt;Defining Direct Fuel Injection and Chamber Combustion&lt;/h3&gt;

&lt;p&gt;Direct fuel injection can be simplified to a lump addition model of fuel gas moles. The fuel
is added instantaneously, at a balanced 14.7 parts air to 1 parts fuel, and the air, fuel,
and combusted ratios are updated:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;void
inject_directly(struct chamber* self)
{
    double air_fuel_ratio = 14.7;
    double current_air_moles = self-&amp;gt;gas.moles * self-&amp;gt;gas.air_ratio;
    double current_fuel_moles = self-&amp;gt;gas.moles * self-&amp;gt;gas.fuel_ratio;
    double current_combusted_moles = self-&amp;gt;gas.moles * self-&amp;gt;gas.combusted_ratio;
    double delta_fuel_moles = current_air_moles / air_fuel_ratio - current_fuel_moles;
    double new_air_moles = current_air_moles;
    double new_fuel_moles = current_fuel_moles + delta_fuel_moles;
    double new_combusted_moles = current_combusted_moles;
    add_moles(self, delta_fuel_moles);
    self-&amp;gt;gas.air_ratio = new_air_moles / self-&amp;gt;gas.moles;
    self-&amp;gt;gas.fuel_ratio = new_fuel_moles / self-&amp;gt;gas.moles;
    self-&amp;gt;gas.combusted_ratio = new_combusted_moles / self-&amp;gt;gas.moles;
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;With a chamber primed with injected fuel, and the chamber ignited from the top,
the rate at which the combustion flame burns in the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;x&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;y&lt;/code&gt; direction (in meters per second)
is defined as:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;#define STP_PRESSURE_PA 101325.0
#define STP_TEMPERATURE_K 273.15

double
calc_flame_speed_m_per_s(struct chamber* self)
{
    double pressure_exponent = 1.7;
    double temperature_exponent = 1.2;
    double laminar_flame_speed_m_per_s = 0.4;
    return laminar_flame_speed_m_per_s
        * pow(calc_static_pressure_pa(self) / STP_PRESSURE_PA, pressure_exponent)
        * pow(self-&amp;gt;gas.static_temperature_k / STP_TEMPERATURE_K, temperature_exponent);
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Knowing the volume of the gas chamber burned for time step &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;DT_S&lt;/code&gt;, the burned ratio is defined as:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;double burned_ratio = volume_burned_m3 / chamber-&amp;gt;volume_m3;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;And the delta change in static temperature is defined as:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;#define GASOLINE_LOWER_HEATING_VALUE_J_PER_KG 44e6

double
calc_delta_static_temperature_from_burned_afr_k(struct chamber* self, double burned_ratio)
{
    double burned_fuel_moles = self-&amp;gt;gas.fuel_ratio * self-&amp;gt;gas.moles * burned_ratio;
    double burned_fuel_mass_kg = burned_fuel_moles * calc_molar_mass_kg_per_mol(self);
    double energy_released_j = burned_fuel_mass_kg * GASOLINE_LOWER_HEATING_VALUE_J_PER_KG;
    return energy_released_j / (calc_mass_kg(self) * calc_specific_heat_capacity_at_constant_pressure_j_per_kg_k(self));
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Where:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;double
calc_specific_heat_capacity_at_constant_volume_j_per_kg_k(struct chamber* self)
{
    return calc_specific_gas_constant_j_per_kg_k(self) / (calc_gamma(self) - 1.0);
}

double
calc_specific_heat_capacity_at_constant_pressure_j_per_kg_k(struct chamber* self)
{
    return calc_gamma(self) * calc_specific_heat_capacity_at_constant_volume_j_per_kg_k(self);
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The maximum allowable flame temperature is determined by the adiabatic flame temperature. Delta static temperature
changes to a chamber’s static temperature may not exceed the adiabatic flame temperature.
For model simplification, the standard atmospheric temperature is used as an approximation for initial temperature:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;double
calc_adiabatic_flame_static_temperature_k(struct chamber* self)
{
    double air_fuel_ratio = self-&amp;gt;gas.air_ratio / self-&amp;gt;gas.fuel_ratio;
    double energy_density_j_per_kg = GASOLINE_LOWER_HEATING_VALUE_J_PER_KG / (1.0 + air_fuel_ratio);
    return STP_TEMPERATURE_K + energy_density_j_per_kg / calc_specific_heat_capacity_at_constant_pressure_j_per_kg_k(self);
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;defining-piston-torque-generation&quot;&gt;Defining Piston Torque Generation&lt;/h3&gt;

&lt;p&gt;The added static temperature change from combustion directly raises the static pressure of the piston chamber. This
change in pressure drives the piston head down, creating a torque that drives the camshaft, and thus, the engine.&lt;/p&gt;

&lt;p&gt;Modifying the piston to support a combustion chamber:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;struct piston
{
    double pin_x_m;
    double pin_y_m;
    double bearing_x_m;
    double bearing_y_m;
    double theta_r;
    double conrod_m;
    double conrod_crank_throw_m;
+   struct chamber chamber;
+   double head_radius_m;
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The chamber volume and gas states are tracked internally to match the head radius, and updated per cycle.
The torque produced by the gas within the piston (in newton meters) is defined as:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;double
calc_gas_torque_nm(struct piston* self)
{
    double area_m2 = calc_circle_area_m2(self-&amp;gt;head_radius_m);
    double term1 = calc_static_gauge_pressure_pa(&amp;amp;self-&amp;gt;chamber) * area_m2 * self-&amp;gt;conrod_crank_throw_m * sin(self-&amp;gt;theta_r);
    double term2 = 1.0 + (self-&amp;gt;conrod_crank_throw_m / self-&amp;gt;conrod_m) * cos(self-&amp;gt;theta_r);
    return term1 * term2;
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Where:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;double
calc_circle_area_m2(double radius_m)
{
    return M_PI * pow(radius_m, 2.0);
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;double
calc_static_gauge_pressure_pa(struct chamber* self)
{
    return calc_static_pressure_pa(self) - STP_PRESSURE_PA;
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Note that while a huge positive spike in torque is created during combustion, a negative torque is created during compression.
A weak starter motor, for instance, may struggle to provide enough torque to counter the initial gas torque created during the compression stroke.&lt;/p&gt;

&lt;p&gt;A piston moving at a high speed, especially a piston head with decent mass, creates inertia torque (in newton meters).
Modifying the piston to support inertia torque:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;struct piston
{
    double pin_x_m;
    double pin_y_m;
    double bearing_x_m;
    double bearing_y_m;
    double theta_r;
    double conrod_m;
    double conrod_crank_throw_m;
    struct chamber chamber;
    double head_radius_m;
+   double conrod_mass_kg;
+   double head_mass_kg;
};
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The moment of inertia (in kilograms per meters squared) can be simplified as that of a
reciprocating mass:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;double
calc_moment_of_inertia_kg_per_m2(struct piston* self)
{
    double mass_reciprocating_kg = self-&amp;gt;head_mass_kg + 0.5 * self-&amp;gt;conrod_mass_kg;
    double term1 = 1.0;
    double term2 = self-&amp;gt;conrod_crank_throw_m / (4.0 * self-&amp;gt;conrod_m);
    double term3 = pow(self-&amp;gt;conrod_crank_throw_m, 2.0) / (8.0 * pow(self-&amp;gt;conrod_m, 2.0));
    return mass_reciprocating_kg * pow(self-&amp;gt;conrod_crank_throw_m, 2.0) * (term1 + term2 + term3);
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;And the inertia torque:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;double
calc_inertia_torque_nm(struct piston* self, double angular_velocity_r_per_s)
{
    double term1 = 0.25 * sin(1.0 * self-&amp;gt;theta_r) * self-&amp;gt;conrod_crank_throw_m / self-&amp;gt;conrod_m;
    double term2 = 0.50 * sin(2.0 * self-&amp;gt;theta_r);
    double term3 = 0.75 * sin(3.0 * self-&amp;gt;theta_r) * self-&amp;gt;conrod_crank_throw_m / self-&amp;gt;conrod_m;
    return calc_moment_of_inertia_kg_per_m2(self) * pow(angular_velocity_r_per_s, 2.0) * (term1 - term2 - term3);
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The total torque produced by the piston is then:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;double total_torque_nm = calc_moment_of_inertia_kg_per_m2(piston) + calc_inertia_torque_nm(piston, angular_velocity_r_per_s);
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;defining-engine-angular-velocity&quot;&gt;Defining Engine Angular Velocity&lt;/h3&gt;

&lt;p&gt;The angular acceleration (in radians per second squared) supplied to the engine is:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;double angular_acceleration_r_per_s2 = total_torque_nm / total_engine_moment_of_inertia_kg_per_m2;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Where the total engine moment of inertia accounts for the flywheel and piston. The flywheel
moment of inertia is defined as:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;double flywheel_moment_of_inertia_kg_per_m2 = 0.5 * mass_flywheel_kg * pow(radius_flywheel_m, 2.0);
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Angular velocity is then updated by angular acceleration multiplied by the time step:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;angular_velocity_r_per_s += angular_acceleration_r_per_s2 * DT_S;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;For an IICE with more than one piston, the torques and moment of inertias for each piston are simply added together.&lt;/p&gt;

&lt;h3 id=&quot;defining-sound&quot;&gt;Defining Sound&lt;/h3&gt;

&lt;p&gt;Total pressure in the exhaust chamber can be sampled and outputted to the sound card at 44100Hz in 512 byte
samples. The audio buffer size can vary, but 512 bytes at 44100Hz is roughly 90Hz, which allows for
engine interaction and readings to occur almost 50% faster than your average 60fps game loop.&lt;/p&gt;

&lt;h3 id=&quot;source&quot;&gt;Source&lt;/h3&gt;

&lt;p&gt;Unavailable! But check back for future updates on engine modelling, particullary a (hopeful) attempt at a V-config.&lt;/p&gt;
</description>
        <pubDate>Sat, 21 Sep 2024 00:00:00 +0000</pubDate>
        <link>https://glouw.com//2024/09/21/Ensim2.html</link>
        <guid isPermaLink="true">https://glouw.com//2024/09/21/Ensim2.html</guid>
      </item>
    
      <item>
        <title>Switch</title>
        <description>&lt;p&gt;&lt;a href=&quot;https://github.com/glouw/switch&quot;&gt;GitHub Source&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let us use ANSI-C (C90) to compile (or transpile, for the pedantic) a target language to an intermediate ANSI-C file.&lt;/p&gt;

&lt;h1 id=&quot;the-target-language&quot;&gt;The Target Language&lt;/h1&gt;

&lt;p&gt;Our target language, dubbed &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;switch&lt;/code&gt;, will be reminiscent of the B Programming Language, supporting
a single type &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;int&lt;/code&gt;, pointers thereto, operators doubly thereof, basic control flow and looping,
and recursion, but of course, barring function pointers - more on this later. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;switch&lt;/code&gt; files use the
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.sw&lt;/code&gt; file type, require an entry point &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;main&lt;/code&gt;, and cannot import other &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;switch&lt;/code&gt; files.&lt;/p&gt;

&lt;p&gt;For the purpose of this post, a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;switch&lt;/code&gt; program can wholistically be exemplified with:&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;main.sw&lt;/code&gt;&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;int fun()
{
    ret 3;
}

int main()
{
    int x = 1 + fun();
    while(x != 1)
    {
        x = x - 1;
    }
    if(x == 1)
    {
        ret 0;
    }
    ret 1;
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;This example provides basic operators, a function call with a return, variables,
loops, and conditional branching. Sparing the complexities of recursive descent parsing,
lexing, and BNF, this post aims to share the workings of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;switch&lt;/code&gt;’s transpiled if-statements,
while loops, and function calls / returns.&lt;/p&gt;

&lt;h1 id=&quot;the-if-statement&quot;&gt;The If Statement&lt;/h1&gt;

&lt;p&gt;Our standard if-statement:&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;if.sw&lt;/code&gt;&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;int main()
{
    if(1)
    {
        2;
    }
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;This can be realized in transpiled ANSI-C as:&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;if.c&lt;/code&gt;&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;#define INT(var) vs[sp++] = var
#define BRZ(label) if(vs[--sp] == 0) goto label
#define BRA(label) goto label
#define POP() --sp
int main(void)
{
    int vs[128] = { 0 };
    register int sp = 0;
    goto main;
main:
    INT(1);
    BRZ(L0);
    INT(2);
    POP();
    BRA(L1);
L0:
L1:
    return 0;
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Our transpiled ANSI-C enters &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;main&lt;/code&gt; and sets up a variable stack &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vs&lt;/code&gt; and
a stack pointer &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sp&lt;/code&gt; to track variable pushes and pops to the variable stack.
The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;register&lt;/code&gt; keyword prepended to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sp&lt;/code&gt; serves no purpose but to document the
modeling of the stack machine. A &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;goto main&lt;/code&gt; statement acts as a reset vector, placing
execution at the goto label &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;main&lt;/code&gt;. An integer of 1 is loaded, and branches to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;L0&lt;/code&gt;
should the integer be zero, otherwise, the next instruction executes, eventually branching to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;L1&lt;/code&gt;, which
signifies the end of the program. Integer 1 is popped by the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;BRZ&lt;/code&gt; instruction.&lt;/p&gt;

&lt;p&gt;Within the body of the if-statement lies an expression without assignment, which loads integer 2,
but subsequently pops the integer from the stack. It serves only to have &lt;em&gt;some form of
expression&lt;/em&gt; within the block of the if-statement to pretty print the transpile.
Empty blocks are permitted.&lt;/p&gt;

&lt;h1 id=&quot;the-while-loop&quot;&gt;The While Loop&lt;/h1&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;while.c&lt;/code&gt;&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;int main()
{
    while(1)
    {
        2;
    }
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Our while loop uses the same inner workings as the if statement.
Integer 1 is pushed to the stack, and branches to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;L1&lt;/code&gt; (the end
of the program) if it is zero. The loop pushes and pops integer 2
for the exemplary, and a branch to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;L0&lt;/code&gt; repeats the loop. In all instances,
integer 1 is popped form the stack with the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;BRZ&lt;/code&gt; instruction.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;while.c&lt;/code&gt;&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;#define INT(var) vs[sp++] = var
#define BRZ(label) if(vs[--sp] == 0) goto label
#define BRA(label) goto label
#define POP() --sp
int main(void)
{
    int vs[128] = { 0 };
    register int sp = 0;
    goto main;
main:
L0:
    INT(1);
    BRZ(L1);
    INT(2);
    POP();
    BRA(L0);
L1:
    return 0;
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h1 id=&quot;the-function-call&quot;&gt;The Function Call&lt;/h1&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;func.sw&lt;/code&gt;&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;int func()
{
    ret 9;
}

int main()
{
    func();
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The function call introduces stacks &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;fs&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bs&lt;/code&gt; which track the function
and base pointer stacks, respectively. Additionally, registers &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;fp&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;fa&lt;/code&gt;, and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rr&lt;/code&gt;,
are introduced, where &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;fp&lt;/code&gt; tracks pushes and pops to the function and base pointer
stacks, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;fa&lt;/code&gt; that stores the pop of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;fs&lt;/code&gt; to temporarily obtain a return function address,
and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rr&lt;/code&gt; to temporarily store the return value of a function. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;switch&lt;/code&gt; functions do
not support void returns. New instructions, separate to our &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;if&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;while&lt;/code&gt; examples, are &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SET&lt;/code&gt;,
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CAL&lt;/code&gt;, and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;RET&lt;/code&gt;. A keen eye notices the intermingling of a switch statement with gotos within &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;func.c&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SET&lt;/code&gt; pushes the current stack frame’s stack pointer value &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sp&lt;/code&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bs&lt;/code&gt; at &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;fp&lt;/code&gt;.
A base pointer allows called functions to accurately reference local variables according
to their zero offset at compile time. This post will not cover the parsing techniques
for managing local variables, their stack pointer values, lvalues, and rvalues,
so &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bs&lt;/code&gt; can effectively be ignored.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CAL&lt;/code&gt; stores the return address in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;fs[fp]&lt;/code&gt;, which is the current source line number,
and goes to the call goto label after incrementing &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;fp&lt;/code&gt;. The return address is a case statement
with the same line number.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;RET&lt;/code&gt; stores the top of the variable stack in the return register &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rr&lt;/code&gt;, decrements the
function pointer &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;fp&lt;/code&gt;, reloads the previous &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sp&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;fa&lt;/code&gt; register values from their respective
stacks, and places the return register &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rr&lt;/code&gt; on top of the variable stack &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vs&lt;/code&gt;. The return function
address, now residing in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;fa&lt;/code&gt;, is jumped to by the switch statement after jumping to the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;begin&lt;/code&gt; label.&lt;/p&gt;

&lt;p&gt;As the program concludes, a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;POP()&lt;/code&gt; instruction after the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CAL()&lt;/code&gt; instruction ensures the stack is cleaned up
of integer 9.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;func.c&lt;/code&gt;&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;#define POP() --sp
#define INT(var) vs[sp++] = var

#define SET()          \
    bs[fp] = sp

#define CAL(name)      \
    fs[fp] = __LINE__; \
    fp++;              \
    goto name;         \
    case __LINE__:

#define RET()          \
    rr = vs[sp - 1];   \
    --fp;              \
    sp = bs[fp];       \
    fa = fs[fp];       \
    vs[sp] = rr;       \
    sp++;              \
    goto begin

int main(void) {
    int fs[32] = { 0 };
    int bs[32] = { 0 };
    int vs[128] = { 0 };
    register int fp = 1;
    register int fa = 0;
    register int sp = 0;
    register int rr = 0;
    goto main;
begin:
    switch(fa)
    {
func:
    INT(9);
    RET();
main:
    SET();
    CAL(func);
    POP();
    }
    return 0;
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h1 id=&quot;outro&quot;&gt;Outro&lt;/h1&gt;
&lt;p&gt;Combine the if-statement, the while loop, and the function call syntaxing, and we have a working language (barring
pointers, operators, and everything else that makes a language expressive, of course). Furthermore,
ANSI-C proves to serve as a highly portable stack machine (with a bit of creativity),
which makes a perfect target for compilation (or transpilation if we are being pedantic).
I have a fully functional &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;switch&lt;/code&gt; compiler / transpiler that you can find on my
&lt;a href=&quot;https://github.com/glouw/switch&quot;&gt;GitHub page&lt;/a&gt;. There are more &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;switch&lt;/code&gt; examples there to be found,
including string usage, and integer printing (I regulated myself to &lt;em&gt;only&lt;/em&gt; having access to libc’s
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;putchar&lt;/code&gt;, which is accessed through the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$&lt;/code&gt; operator).&lt;/p&gt;

&lt;p&gt;And alas, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;switch&lt;/code&gt; does not support function pointers without a GNU extension that allows the address of labels
to be taken as values, for example:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;label:
    0;
    ...
    void* ptr = &amp;amp;&amp;amp;label;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Other than that, I leave you with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;qsort.sw&lt;/code&gt;, which is fully transpilable with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;switch&lt;/code&gt;, and I leave you
with the post processed intermediate ANSI C file (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gcc -E qsort.c&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;qsort.sw&lt;/code&gt;&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;int swap(int* a, int x, int y)
{
    int temp = *(a + x);
    *(a + x) = *(a + y);
    *(a + y) = temp;
}

int qsort(int* a, int l, int r)
{
    int i = 0;
    int last = 0;
    if(l &amp;gt;= r)
    {
        ret 0;
    }
    swap(a, l, (l + r) / 2);
    last = l;
    i = l + 1;
    while(i &amp;lt;= r)
    {
        if(*(a + i) &amp;lt; *(a + l))
        {
            last = last + 1;
            swap(a, last, i);
        }
        i = i + 1;
    }
    swap(a, l, last);
    qsort(a, l, last - 1);
    qsort(a, last + 1, r);
}

int main()
{
    int a[] = { 9, 43, 1, 5, 32 };
    qsort(a, 0, @a - 1); # The `@` operator returns the size of the array.
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;May you all have a good day.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gcc -E qsort.c&lt;/code&gt;&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;int main(void) {
 int fs[4096] = { 0 };
 int bs[4096] = { 0 };
 int vs[65536] = { 0 };
 register int fp = 1;
 register int fa = 0;
 register int sp = 0;
 register int rr = 0;
 goto main;
begin:
 if(fp == 0)
  return vs[sp - 1];
 switch(fa)
 {
swap:
 vs[sp++] = 0 + bs[fp - 1];
 vs[sp - 1] = vs[vs[sp - 1]];
 vs[sp++] = 1 + bs[fp - 1];
 vs[sp - 1] = vs[vs[sp - 1]];
 vs[sp - 2] += vs[sp - 1]; --sp;
 vs[sp - 1] = vs[vs[sp - 1]];
 vs[sp++] = 0 + bs[fp - 1];
 vs[sp - 1] = vs[vs[sp - 1]];
 vs[sp++] = 1 + bs[fp - 1];
 vs[sp - 1] = vs[vs[sp - 1]];
 vs[sp - 2] += vs[sp - 1]; --sp;
 vs[sp++] = 0 + bs[fp - 1];
 vs[sp - 1] = vs[vs[sp - 1]];
 vs[sp++] = 2 + bs[fp - 1];
 vs[sp - 1] = vs[vs[sp - 1]];
 vs[sp - 2] += vs[sp - 1]; --sp;
 vs[sp - 1] = vs[vs[sp - 1]];
 vs[vs[sp - 2]] = vs[sp - 1];;
 vs[sp - 2] = vs[sp - 1]; --sp;;
 --sp;
 vs[sp++] = 0 + bs[fp - 1];
 vs[sp - 1] = vs[vs[sp - 1]];
 vs[sp++] = 2 + bs[fp - 1];
 vs[sp - 1] = vs[vs[sp - 1]];
 vs[sp - 2] += vs[sp - 1]; --sp;
 vs[sp++] = 3 + bs[fp - 1];
 vs[sp - 1] = vs[vs[sp - 1]];
 vs[vs[sp - 2]] = vs[sp - 1];;
 vs[sp - 2] = vs[sp - 1]; --sp;;
 --sp;
 --sp;
 --sp;
 --sp;
 --sp;
 vs[sp++] = 0;
 rr = vs[sp - 1];--fp;sp = bs[fp];fa = fs[fp];vs[sp] = rr;sp++;goto begin;
qsort:
 vs[sp++] = 0;
 vs[sp++] = 0;
 vs[sp++] = 1 + bs[fp - 1];
 vs[sp - 1] = vs[vs[sp - 1]];
 vs[sp++] = 2 + bs[fp - 1];
 vs[sp - 1] = vs[vs[sp - 1]];
 vs[sp - 2] = vs[sp - 2] &amp;gt;= vs[sp - 1]; --sp;
 if(vs[--sp] == 0) goto L0;
 vs[sp++] = 0;
 rr = vs[sp - 1];--fp;sp = bs[fp];fa = fs[fp];vs[sp] = rr;sp++;goto begin;
 goto L1;
L0:
L1:
 bs[fp] = sp;
 vs[sp++] = 0 + bs[fp - 1];
 vs[sp - 1] = vs[vs[sp - 1]];
 vs[sp++] = 1 + bs[fp - 1];
 vs[sp - 1] = vs[vs[sp - 1]];
 vs[sp++] = 1 + bs[fp - 1];
 vs[sp - 1] = vs[vs[sp - 1]];
 vs[sp++] = 2 + bs[fp - 1];
 vs[sp - 1] = vs[vs[sp - 1]];
 vs[sp - 2] += vs[sp - 1]; --sp;
 vs[sp++] = 2;
 vs[sp - 2] /= vs[sp - 1]; --sp;
 fs[fp] = 110;fp++;goto swap;case 110:;
 --sp;
 vs[sp++] = 4 + bs[fp - 1];
 vs[sp++] = 1 + bs[fp - 1];
 vs[sp - 1] = vs[vs[sp - 1]];
 vs[vs[sp - 2]] = vs[sp - 1];;
 vs[sp - 2] = vs[sp - 1]; --sp;;
 --sp;
 vs[sp++] = 3 + bs[fp - 1];
 vs[sp++] = 1 + bs[fp - 1];
 vs[sp - 1] = vs[vs[sp - 1]];
 vs[sp++] = 1;
 vs[sp - 2] += vs[sp - 1]; --sp;
 vs[vs[sp - 2]] = vs[sp - 1];;
 vs[sp - 2] = vs[sp - 1]; --sp;;
 --sp;
L2:
 vs[sp++] = 3 + bs[fp - 1];
 vs[sp - 1] = vs[vs[sp - 1]];
 vs[sp++] = 2 + bs[fp - 1];
 vs[sp - 1] = vs[vs[sp - 1]];
 vs[sp - 2] = vs[sp - 2] &amp;lt;= vs[sp - 1]; --sp;
 if(vs[--sp] == 0) goto L3;
 vs[sp++] = 0 + bs[fp - 1];
 vs[sp - 1] = vs[vs[sp - 1]];
 vs[sp++] = 3 + bs[fp - 1];
 vs[sp - 1] = vs[vs[sp - 1]];
 vs[sp - 2] += vs[sp - 1]; --sp;
 vs[sp - 1] = vs[vs[sp - 1]];
 vs[sp++] = 0 + bs[fp - 1];
 vs[sp - 1] = vs[vs[sp - 1]];
 vs[sp++] = 1 + bs[fp - 1];
 vs[sp - 1] = vs[vs[sp - 1]];
 vs[sp - 2] += vs[sp - 1]; --sp;
 vs[sp - 1] = vs[vs[sp - 1]];
 vs[sp - 2] = vs[sp - 2] &amp;lt; vs[sp - 1]; --sp;
 if(vs[--sp] == 0) goto L4;
 vs[sp++] = 4 + bs[fp - 1];
 vs[sp++] = 4 + bs[fp - 1];
 vs[sp - 1] = vs[vs[sp - 1]];
 vs[sp++] = 1;
 vs[sp - 2] += vs[sp - 1]; --sp;
 vs[vs[sp - 2]] = vs[sp - 1];;
 vs[sp - 2] = vs[sp - 1]; --sp;;
 --sp;
 bs[fp] = sp;
 vs[sp++] = 0 + bs[fp - 1];
 vs[sp - 1] = vs[vs[sp - 1]];
 vs[sp++] = 4 + bs[fp - 1];
 vs[sp - 1] = vs[vs[sp - 1]];
 vs[sp++] = 3 + bs[fp - 1];
 vs[sp - 1] = vs[vs[sp - 1]];
 fs[fp] = 162;fp++;goto swap;case 162:;
 --sp;
 goto L5;
L4:
L5:
 vs[sp++] = 3 + bs[fp - 1];
 vs[sp++] = 3 + bs[fp - 1];
 vs[sp - 1] = vs[vs[sp - 1]];
 vs[sp++] = 1;
 vs[sp - 2] += vs[sp - 1]; --sp;
 vs[vs[sp - 2]] = vs[sp - 1];;
 vs[sp - 2] = vs[sp - 1]; --sp;;
 --sp;
 goto L2;
L3:
 bs[fp] = sp;
 vs[sp++] = 0 + bs[fp - 1];
 vs[sp - 1] = vs[vs[sp - 1]];
 vs[sp++] = 1 + bs[fp - 1];
 vs[sp - 1] = vs[vs[sp - 1]];
 vs[sp++] = 4 + bs[fp - 1];
 vs[sp - 1] = vs[vs[sp - 1]];
 fs[fp] = 184;fp++;goto swap;case 184:;
 --sp;
 bs[fp] = sp;
 vs[sp++] = 0 + bs[fp - 1];
 vs[sp - 1] = vs[vs[sp - 1]];
 vs[sp++] = 1 + bs[fp - 1];
 vs[sp - 1] = vs[vs[sp - 1]];
 vs[sp++] = 4 + bs[fp - 1];
 vs[sp - 1] = vs[vs[sp - 1]];
 vs[sp++] = 1;
 vs[sp - 2] -= vs[sp - 1]; --sp;
 fs[fp] = 195;fp++;goto qsort;case 195:;
 --sp;
 bs[fp] = sp;
 vs[sp++] = 0 + bs[fp - 1];
 vs[sp - 1] = vs[vs[sp - 1]];
 vs[sp++] = 4 + bs[fp - 1];
 vs[sp - 1] = vs[vs[sp - 1]];
 vs[sp++] = 1;
 vs[sp - 2] += vs[sp - 1]; --sp;
 vs[sp++] = 2 + bs[fp - 1];
 vs[sp - 1] = vs[vs[sp - 1]];
 fs[fp] = 206;fp++;goto qsort;case 206:;
 --sp;
 --sp;
 --sp;
 --sp;
 --sp;
 --sp;
 vs[sp++] = 0;
 rr = vs[sp - 1];--fp;sp = bs[fp];fa = fs[fp];vs[sp] = rr;sp++;goto begin;
main:
 vs[sp++] = 9;
 vs[sp++] = 43;
 vs[sp++] = 1;
 vs[sp++] = 5;
 vs[sp++] = 32;
 bs[fp] = sp;
 vs[sp++] = 0 + bs[fp - 1];
 vs[sp++] = 0;
 vs[sp++] = 0 + bs[fp - 1];
 --sp;
 vs[sp++] = 5;
 vs[sp++] = 1;
 vs[sp - 2] -= vs[sp - 1]; --sp;
 fs[fp] = 229;fp++;goto qsort;case 229:;
 --sp;
 --sp;
 vs[sp++] = 0;
 rr = vs[sp - 1];--fp;sp = bs[fp];fa = fs[fp];vs[sp] = rr;sp++;goto begin;
 }
 return 0;
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
</description>
        <pubDate>Tue, 07 Nov 2023 00:00:00 +0000</pubDate>
        <link>https://glouw.com//2023/11/07/Switch.html</link>
        <guid isPermaLink="true">https://glouw.com//2023/11/07/Switch.html</guid>
      </item>
    
      <item>
        <title>Roman2</title>
        <description>&lt;p&gt;&lt;a href=&quot;https://github.com/glouw/rr&quot;&gt;GitHub Source&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Roman2 - otherwise known as Python with pointers and curly braces -
is my first attempt at creating a dependency free programming
language. Roman2 is comprised of a recursive descent parser, an
assembler, virtual machine, and runtime garbage collector. The
syntax is primitive, borrowing the feel of C and the expression
of Python from the early 21st century. Included are lists, dicts,
strings, booleans, and numeric double types. Roman2 has no real
benefit over popular mainline programming languages, save for
it’s small runtime source and final executable size.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Fib(n)
{
    if(n == 0)
    {
        ret 0;
    }
    elif((n == 1) || (n == 2))
    {
        ret 1;
    }
    else
    {
        ret Fib(n - 1) + Fib(n - 2);
    }
}

Main()
{
    Print(Fib(25));
    ret 0;
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Roman2 is not a functional programming language, but it is
functional as a programming language. The README &lt;a href=&quot;https://github.com/glouw/rr&quot;&gt;on GitHub&lt;/a&gt;
goes a little more in depth.&lt;/p&gt;
</description>
        <pubDate>Fri, 06 May 2022 00:00:00 +0000</pubDate>
        <link>https://glouw.com//2022/05/06/Roman2.html</link>
        <guid isPermaLink="true">https://glouw.com//2022/05/06/Roman2.html</guid>
      </item>
    
      <item>
        <title>Minimidi</title>
        <description>&lt;p&gt;&lt;a href=&quot;https://github.com/glouw/minimidi&quot;&gt;GitHub Source&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I recently took a detour exploring FM synthesis and MIDI parsers. FM waves, similar to
that of generic DOS sound-card OPL waveforms, make for quite the neat little orchestra
when fed directly to the sound-card through SDL2. The waveforms, mocking up various instruments
like the piano, guitar, brass, and winds, are emulated by FM synthesizing either a triangle, sine,
square, half triangle, or quarter sine waveform with another. Here I play Howard Shore’s Concerning Hobbits:&lt;/p&gt;

&lt;iframe width=&quot;640&quot; height=&quot;480&quot; src=&quot;https://www.youtube.com/embed/0W_rKMd_tzo&quot; frameborder=&quot;0&quot; allow=&quot;autoplay; encrypted-media&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;

&lt;p&gt;Instrument wise, an organ may be synthesized as a half triangle modulated by that of a sine wave:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;static int16_t
(Wave_Organ)
(Wave* wave, Note* note, float fm)
{
    (void) fm;
    return Wave_FM(wave, note, Wave_TRH, Wave_SIN, 0.8f);
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;A small library of waveforms generators can be built and mapped to that of the
General MIDI specification:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;static int16_t
(*WAVE_WAVEFORMS[])(Wave* wave, Note* note, float fm) = {
    [  0 ] = Wave_Piano,
    [  1 ] = Wave_ChromaticPercussion,
    [  2 ] = Wave_Organ,
    [  3 ] = Wave_Guitar,
    [  4 ] = Wave_Bass,
    [  5 ] = Wave_Strings1,
    [  6 ] = Wave_Strings2,
    [  7 ] = Wave_Brass,
    [  8 ] = Wave_Reed,
    [  9 ] = Wave_Pipe,
    [ 10 ] = Wave_SynthLead,
    [ 11 ] = Wave_SynthPad,
    [ 12 ] = Wave_SynthEffects,
    [ 13 ] = Wave_Ethnic,
    [ 14 ] = Wave_Percussive,
    [ 15 ] = Wave_SoundEffects,
};
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Once a couple threads are initialized, one to parse a MIDI file and “turn on and off” instruments,
and another thread to generate the appropriate waveforms for the sound card, an orchestra is emulated
purely from that of programming text and some fundamental mathematics.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://github.com/glouw/minimidi&quot;&gt;Try giving giving the source a read&lt;/a&gt;. The source resides in a single file,
with a single consumer thread, a producer thread, and a small video driver to draw the waveforms
on screen with zero phase offset.&lt;/p&gt;
</description>
        <pubDate>Tue, 18 May 2021 00:00:00 +0000</pubDate>
        <link>https://glouw.com//2021/05/18/Minimidi.html</link>
        <guid isPermaLink="true">https://glouw.com//2021/05/18/Minimidi.html</guid>
      </item>
    
      <item>
        <title>C Template Library</title>
        <description>&lt;p&gt;&lt;a href=&quot;https://github.com/glouw/ctl&quot;&gt;GitHub Source&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A recent round of small projects left me rewriting the same set of linked lists and
resizable arrays for a myriad of types. While enjoyable to most C programmers, rewriting the
same data structure is definitely a time sink, and the conventional approach
of &lt;a href=&quot;https://glouw.com/2020/07/13/Generic-Hash-Tables.html&quot;&gt;encapsulating void pointers&lt;/a&gt;
is slow and prone to type errors.&lt;/p&gt;

&lt;p&gt;The gist to effective compile time polymorphism lies within the preprocessor:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;#define T int

T sum(T* array, size_t size)
{
    T total = 0;
    for(size_t i = 0; i &amp;lt; size; i++)
        total += array[i];
    return total;
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The caveat being, names require a type signature, expanding the above to
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;int int_sum(int* array, size_t size)&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;#define CAT(a, b) a##b
#define PASTE(a, b) CAT(a, b)
#define JOIN(prefix, name) PASTE(prefix, PASTE(_, name))

#define T int

T JOIN(T, sum)(T* array, size_t size)
{
    T total = 0;
    for(size_t i = 0; i &amp;lt; size; i++)
        total += array[i];
    return total;
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Wrapping the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sum&lt;/code&gt; function as a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;static inline&lt;/code&gt; into a single header named
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sum.h&lt;/code&gt; yields an infinite number of expansion possibilities
(granted, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;T&lt;/code&gt; is undefined within &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sum.h&lt;/code&gt;):&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;#define CAT(a, b) a##b
#define PASTE(a, b) CAT(a, b)
#define JOIN(prefix, name) PASTE(prefix, PASTE(_, name))

#define T int
#include &quot;sum.h&quot;

#define T float
#include &quot;sum.h&quot;

#define T double
#include &quot;sum.h&quot;

#define T char
#include &quot;sum.h&quot;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;I pushed this concept to the extreme, and backported the core of the C++11 STL
to ISO C99/C11. As per a measure of safety, each push to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;master&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;staging&lt;/code&gt; kicks
off a 3 hour test suite which randomly runs each container function against the STL
and checks for inconsistencies. As of writing, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;unordered_set&lt;/code&gt; is not implemented -
the holidays has effectively put me in vacation mode, &lt;a href=&quot;https://github.com/glouw/ctl&quot;&gt;but have yourself a look&lt;/a&gt;.&lt;/p&gt;
</description>
        <pubDate>Sat, 02 Jan 2021 00:00:00 +0000</pubDate>
        <link>https://glouw.com//2021/01/02/C-Template-Library.html</link>
        <guid isPermaLink="true">https://glouw.com//2021/01/02/C-Template-Library.html</guid>
      </item>
    
      <item>
        <title>Obfuscating Assets</title>
        <description>&lt;p&gt;Often times one needs to obfuscate game assets. If a game relies on BMP files, SDL2,
and vim, the first step to obfuscating the assets without the need of cryptography is already done.&lt;/p&gt;

&lt;p&gt;SDL2 has out of the box support for Windows BMP files. The macro to load BMP files is declared in
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SDL_Surface.h&lt;/code&gt; and takes a file path string as an argument:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;#define SDL_LoadBMP(file) SDL_LoadBMP_RW(SDL_RWFromFile(file, &quot;rb&quot;), 1)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;By dissecting the contents of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SDL_LoadBMP&lt;/code&gt; we learn &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SDL_RWFromFile&lt;/code&gt; returns an &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SDL_RWops&lt;/code&gt; pointer.
Fortunately, an alternative declaration in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SDL_rwops.h&lt;/code&gt; exists, and it allows for a generic read from raw memory:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;extern DECLSPEC SDL_RWops *SDLCALL SDL_RWFromMem(void *mem, int size);
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Combining this call with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SDL_LoadBMP_RW&lt;/code&gt; forms a new definition, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SDL_LoadBMPFromMem&lt;/code&gt;, and it provides
a facility for loading BMP files from memory:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;#define SDL_LoadBMPFromMem(mem, size) SDL_LoadBMP_RW(SDL_RWFromMem(mem, size), 0)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Thankfully, a hex dumper named &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;xxd&lt;/code&gt; comes pre-installed with vim and it includes a huge time saving flag
named &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-include&lt;/code&gt; for transforming a file (in this case, a BMP file) into a C style array with a size constant:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;xxd -include Image.bmp
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The output prints directly to stdout, printing both the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;unsigned char&lt;/code&gt; array &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Image.bmp&lt;/code&gt; and the length
of the array:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;unsigned char Image_bmp[] = {
...
    0xeb, 0x01, 0x40, 0x33, 0x33, 0x13, 0x80, 0x66, 0x66, 0x26, 0x40, 0x66,
    0x66, 0x06, 0xa0, 0x99, 0x99, 0x09, 0x3c, 0x0a, 0xd7, 0x03, 0x24, 0x5c,
    0x8f, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
...
};
unsigned int Image_bmp_len = 373;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Loading the BMP image is just a matter of using the newly crafted &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SDL_LoadBMPFromMem&lt;/code&gt; macro:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;SDL_Surface* arrow = SDL_LoadBMPFromMem(Image_bmp, Image_bmp_len)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;With &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;xxd&lt;/code&gt; able to reverse BMP images, and SDL2 being able to natively load BMP images
without the need of external dependencies like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SDL_image&lt;/code&gt;, this solution is the first step
to obfuscating important art assets in a lightweight fashion that would otherwise spoil a game’s plot.
Yes, the game binary will bloat, and the BMP can still be reversed with an &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;objdump&lt;/code&gt; of the binary,
but by hiding the BMP in the binary the secret asset will be hidden to most of the players.&lt;/p&gt;

&lt;p&gt;Of course, if the game becomes really popular, chances are it will be disassembled, and the Streisand Effect
may otherwise further publicize the assets that were once obfuscated!&lt;/p&gt;
</description>
        <pubDate>Wed, 12 Aug 2020 00:00:00 +0000</pubDate>
        <link>https://glouw.com//2020/08/12/Obfuscating-Assets.html</link>
        <guid isPermaLink="true">https://glouw.com//2020/08/12/Obfuscating-Assets.html</guid>
      </item>
    
      <item>
        <title>Paperview</title>
        <description>&lt;p&gt;&lt;a href=&quot;https://github.com/glouw/paperview&quot;&gt;Github Source&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I recently stumbled upon a small bash script that calls &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;feh --bg-fill&lt;/code&gt; in a loop over an array of
PNG files to animate the desktop background.
The performance was fairly poor. Cumulative CPU usage was close to 40% on my X230.&lt;/p&gt;

&lt;p&gt;As an alternative, I discovered SDL2 can provide a generic interface to create a window from a pixel array,
including the base root X11 window used by desktop wallpaper setter (the high CPU usage in the video is attributed
to the screen recorder):&lt;/p&gt;

&lt;iframe width=&quot;720&quot; height=&quot;405&quot; src=&quot;https://www.youtube.com/embed/6ZTiA885bWM&quot; frameborder=&quot;0&quot; allow=&quot;autoplay; encrypted-media&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;

&lt;p&gt;X11 windows can be coerced into a void pointer and passed to SDL2 and directly accessed via an SDL renderer:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Display* x11d = XOpenDisplay(NULL);
Window x11w = RootWindow(x11d, DefaultScreen(x11d));
SDL_Window* window = SDL_CreateWindowFrom((void*) x11w);
SDL_Renderer* renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;From here:&lt;/p&gt;

&lt;p&gt;1) Bitmaps are loaded into RAM with SDL2:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;SDL_Surface* surface = SDL_LoadBMP(&quot;frame.bmp&quot;);
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;2) The bitmaps are moved from RAM to the GPU:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;SDL_Texture* texture = SDL_CreateTextureFromSurface(renderer, surface);
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;3) The bitmaps, now residing in GPU memory, are copied to the desktop wallpaper:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;SDL_RenderCopy(renderer, texture, NULL, NULL);
SDL_RenderPresent(renderer);
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The two NULL arguments signal the renderer to stretch fill the background wallpaper.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://github.com/glouw/paperview&quot;&gt;Also, try giving the source a read&lt;/a&gt;. A single file (main.c) in less than 150 lines
yields a high performance animated desktop wallpaper at 60 frames per second. The name paperview stems
from pre-Netflix era video services dubbed Pay-Per-View and the idea of &lt;em&gt;viewing wallpapers&lt;/em&gt; in an animated fashion.
My X230 uses an integrated Intel video chipset, and fortunately Arch provides a nice GPU metric tool;
running the following at 1920x1080 (via the VGA port to an external monitor at 60 Hz):&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;intel_gpu_time ./paperview scenes/castle 5
user: 1.904135s, sys: 0.357277s, elapsed: 100.458648s, CPU: 2.3%, GPU: 11.7%G
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
</description>
        <pubDate>Sun, 02 Aug 2020 00:00:00 +0000</pubDate>
        <link>https://glouw.com//2020/08/02/Paperview.html</link>
        <guid isPermaLink="true">https://glouw.com//2020/08/02/Paperview.html</guid>
      </item>
    
      <item>
        <title>Generic Hash Tables</title>
        <description>&lt;p&gt;Generic C99 hash tables (or dicts for the python programmers) can be readily built upon pre-existing generic list data structures.&lt;/p&gt;

&lt;p&gt;The gist is that a generic portion of memory is hashed, and the hash retrieves a list from an array of lists (also known as buckets).
In the case of an insertion, the data is pushed to the back of this hashed list. In the case of a get, a node pointer is returned from this hashed list:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;typedef struct
{
    List** list;
    Iterate iterate;
    size_t buckets;
}
Dict;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Initializing the dictionary requires an &lt;em&gt;iterate&lt;/em&gt; pointer be stored for matching the actual contents of the key with one of the items in the list.
The number of buckets is best suited by a prime number, roughly half the size of the maximum number of expected elements to be stored
such that hash collisions only need 2-3 list iterations for quick retrieval:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Dict* Dict_Init(size_t buckets, Iterate iterate, Destruct destruct)
{
    Dict* self = malloc(sizeof(*self));
    self-&amp;gt;list = malloc(sizeof(*self-&amp;gt;list) * buckets);
    for(size_t i = 0; i &amp;lt; buckets; i++)
        self-&amp;gt;list[i] = List_Init(destruct);
    self-&amp;gt;iterate = iterate;
    self-&amp;gt;buckets = buckets;
    return self;
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The hashing is arbitrary - a key, of any data, with length is specified, and looped over, constructing a number that is
ultimately modulated by the number of buckets such that the look up index does not go out of bounds:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;unsigned Dict_Hash(Dict* self, void* key, size_t len)
{
    char* byte = key;
    unsigned value = 0x0;
    for(size_t i = 0; i &amp;lt; len; i++)
    {
        value = (value &amp;lt;&amp;lt; 4) + byte[i];
        unsigned temp = value &amp;amp; 0xF0000000;
        if(temp)
        {
            value = value ^ (temp &amp;gt;&amp;gt; 24);
            value = value ^ temp;
        }
    }
    return value % self-&amp;gt;buckets;
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Retrieving a list, with a hash, is just an index:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;List* Dict_Index(Dict* self, void* key, size_t size)
{
    size_t hash = Dict_Hash(self, key, size);
    return self-&amp;gt;list[hash];
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Getting workable data from a dictionary just uses the index, and uses the &lt;em&gt;iterate&lt;/em&gt; callback to match
with the item in the indexed list:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Node* Dict_Get(Dict* self, void* key, size_t size)
{
    List* list = Dict_Index(self, key, size);
    return List_For(list, self-&amp;gt;iterate, key);
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Inserting does a get to see if the data exists. If not, it inserts the data into the list.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;bool Dict_Insert(Dict* self, void* key, size_t size, void* data)
{
    Node* found = Dict_Get(self, key, size);
    if(found)
        return false;
    else
    {
        List* list = Dict_Index(self, key, size);
        List_Push(list, data, TAIL);
        return true;
    }
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Unfortunately the call to Dict_index occurs twice in Dict_Insert, but is kept so for readability,
and is hopefully optimized away by the compiler.&lt;/p&gt;

&lt;p&gt;Finally, freeing the dictionary is defined as:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;void Dict_Free(Dict** dict)
{
    Dict* self = *dict;
    for(size_t i = 0; i &amp;lt; self-&amp;gt;buckets; i++)
        List_Free(self-&amp;gt;list[i]);
    free(self-&amp;gt;list);
    free(self);
    *dict = NULL;
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Using a Person object, for example, hashes the persons name for its insert and get operations, and in
doing so, uses a function Person_MatchName for its &lt;em&gt;iteration&lt;/em&gt; callback which matches people by name:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;typedef struct
{
    char* const name; // USED AS A KEY, SO REMAINS CONST.
    double age;
    double weight;
    double height;
}
Person;

Person* Person_Init(char* name, double age, double weight, double height)
{
    Person* self = malloc(sizeof(*self));
    *(char**) &amp;amp;self-&amp;gt;name = name;
    self-&amp;gt;age = age;
    self-&amp;gt;weight = weight;
    self-&amp;gt;height = height;
    return self;
}

void Person_Free(void* p)
{
    Person* self = p;
    free(self);
}

Action Person_Print(void* data, void* args)
{
    Person* self = data;
    char* prefix = args;
    if(prefix)
        printf(&quot;%s: &quot;, prefix);
    printf(&quot;%s : %.2f %.2f %.2f\n&quot;, self-&amp;gt;name, self-&amp;gt;age, self-&amp;gt;weight, self-&amp;gt;height);
    return CONTINUE;
}

Action Person_MatchName(void* data, void* args)
{
    Person* person = data;
    return strcmp(person-&amp;gt;name, args) == 0 ? STOP : CONTINUE;
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Alas, a bucket size, being the prime number 1699, is used only as an example:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;int main(void)
{
    Dict* dict = Dict_Init(1699, Person_MatchName, Person_Free);

    /* INSERT */;
    Person* person = Person_Init(&quot;Gustav Louw&quot;, 123, 456, 789);
    if(!Dict_Insert(dict, person-&amp;gt;name, strlen(person-&amp;gt;name), person))
        Person_Free(person);

    /* GET */
    char* name = &quot;Gustav Louw&quot;;
    Node* found = Dict_Get(dict, name, strlen(name));
    if(found)
        Person_Print(found-&amp;gt;data, &quot;FOUND PERSON&quot;);

    Dict_Free(&amp;amp;dict);
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Any piece of data can be hashed, but the data must remain constant, else the hash will invalidate itself.&lt;/p&gt;
</description>
        <pubDate>Mon, 13 Jul 2020 00:00:00 +0000</pubDate>
        <link>https://glouw.com//2020/07/13/Generic-Hash-Tables.html</link>
        <guid isPermaLink="true">https://glouw.com//2020/07/13/Generic-Hash-Tables.html</guid>
      </item>
    
      <item>
        <title>Generic Lists, Queues, And Stacks</title>
        <description>&lt;p&gt;This post will outline a generic solution to lists, queues, and stacks in C99.&lt;/p&gt;

&lt;h2 id=&quot;doubly-linked-lists&quot;&gt;Doubly Linked Lists&lt;/h2&gt;

&lt;p&gt;The eternal memory allocator, malloc, being declared as:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;void* malloc(size_t size);
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;yields a plugin to a generic node datatype:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;typedef struct Node
{
    void* data;
    struct Node* a;
    struct Node* b;
}
Node;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;A node points to data allocated by malloc, and is doubly linked to data allocated by
malloc with both next (b) and previous (a) pointers.
(The naming is generic, as the Node data type will be reused for left and right
for trees in a later post).&lt;/p&gt;

&lt;p&gt;Building a node reserves space for itself, and initializes data given by malloc:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Node* Node_Init(void* data)
{
    Node* node = malloc(sizeof(*node));
    node-&amp;gt;data = data;
    node-&amp;gt;b = NULL;
    node-&amp;gt;a = NULL;
    return node;
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The doubly linked list points to the head and tail of the list. A destructor will define
the cleanup method for each node. This destructor callback is only used when the list is freed.
The size variable indicates the number of nodes in the list.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;typedef void (*Destruct)(void* data);

typedef struct
{
    Node* head;
    Node* tail;
    Destruct destruct;
    size_t size;
}
List;

List* List_Init(Destruct destruct)
{
    List* self = malloc(sizeof(*self));
    self-&amp;gt;head = NULL;
    self-&amp;gt;tail = NULL;
    self-&amp;gt;size = 0;
    self-&amp;gt;destruct = destruct;
    return self;
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Inserting a new node into the list can be done at the head or tail of the list. The End enum is superfluous,
as it may simply be replaced with a boolean, but its intent will make the later definitions of queues and
stacks a little more readable.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;typedef enum
{
    HEAD, TAIL
}
End;

void List_Push(List* self, void* data, End end)
{
    Node* node = Node_Init(data);
    if(self-&amp;gt;size == 0)
    {
        self-&amp;gt;head = node;
        self-&amp;gt;tail = node;
    }
    else
    {
        if(end == HEAD)
        {
            node-&amp;gt;b = self-&amp;gt;head;
            node-&amp;gt;b-&amp;gt;a = node;
            self-&amp;gt;head = node;
        }
        if(end == TAIL)
        {
            node-&amp;gt;a = self-&amp;gt;tail;
            node-&amp;gt;a-&amp;gt;b = node;
            self-&amp;gt;tail = node;
        }
    }
    self-&amp;gt;size += 1;
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Popping an element from the list is done on a per node basis. This gives us the flexibility to
loop through and delete all nodes within in the list, or simply look up the head and tail nodes
and pop those. A destroy callback internally cleans up node data.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;void* List_Pop(List* self, Node* node, bool destroy)
{
    Node* a = node-&amp;gt;a;
    Node* b = node-&amp;gt;b;
    void* data = node-&amp;gt;data;
    if(node == self-&amp;gt;head) self-&amp;gt;head = b;
    if(node == self-&amp;gt;tail) self-&amp;gt;tail = a;
    if(a) a-&amp;gt;b = b;
    if(b) b-&amp;gt;a = a;
    if(destroy)
    {
        self-&amp;gt;destruct(data);
        data = NULL;
    }
    free(node);
    self-&amp;gt;size -= 1;
    return data;
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;All operations on lists are done with loops. A single loop function with a &lt;em&gt;programmable&lt;/em&gt; callback
defines actions to be done on nodes. That is, the list iteration callback can stop or continue at some node,
or entirely delete the contents of some node.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;typedef enum
{
    CONTINUE, STOP, DELETE
}
Action;

typedef Action (*Iterate)(void* data, void* args);
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The optional &lt;em&gt;args&lt;/em&gt; void pointer is used for further extending the functionality of the iteration callback:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Node* List_For(List* self, Iterate iterate, void* args)
{
    Node* node = self-&amp;gt;head;
    while(node)
    {
        Node* b = node-&amp;gt;b;
        switch(iterate(node-&amp;gt;data, args))
        {
            case DELETE:
                List_Pop(self, node, true);
            case CONTINUE:
                break;
            case STOP:
                return node;
        }
        node = b;
    }
    return NULL;
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Clearing the list pops the head until the size of the list is 0:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;void List_Clear(List* self)
{
    while(self-&amp;gt;size &amp;gt; 0)
        List_Pop(self, self-&amp;gt;head, true);
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Freeing the list calls free, but ensures the list is cleared prior:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;void List_Free(List* self)
{
    List_Clear(self);
    free(self);
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;examples&quot;&gt;Examples&lt;/h2&gt;

&lt;p&gt;The doubly linked list excelt in generic settings, given &lt;em&gt;data&lt;/em&gt; is always
allocated by malloc (note free is passed as the destructor for free as no internal cleanup is required):&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;List* list = List_Init(free);
for(int i = 0; i &amp;lt; 42; i++)
{
    int* temp = malloc(sizeof(*temp));
    *temp = i;
    List_Push(list, temp, TAIL);
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;A printing function to print integers is defined as (note that CONTINUE is returned such that all elements are printed):&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Action Print(void* data, void* args)
{
    (void) args;
    int* integer = data;
    printf(&quot;%d\n&quot;, *integer);
    return CONTINUE;
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;And used as:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;List_For(list, Print, NULL);
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Use of args is pretty much universal, but an example to sum the contents of a list is defined as:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Action Sum(void* data, void* args)
{
    int* integer = data;
    int* total = args;
    *total += *integer;
    return CONTINUE;
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;And used as:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;int total = 0;
List_For(list, Sum, &amp;amp;total);
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Searching the list for elements that may exist is done similarly - STOP may be used to return the
first node found:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Action Find(void* data, void* args)
{
    int* integer = data;
    int* key = args;
    if(*integer == *key)
        return STOP;
    else
        return CONTINUE;
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Used as:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;int key = 42;
Node* data = List_For(list, Find, &amp;amp;key);
if(data != NULL)
{
    // FOUND.
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;And of course, deleting all elements matching a key can be done with the above, but simply swap out&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;return STOP;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;for the alternate:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;return DELETE;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The above doubly linked list example used integers, but any object allocated by malloc can be used.
An employee, for instance, marked by name, salary, and an Orewellian ID can just be easily inserted
into a new list, searched for by name, deleted, printed, and so on:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;typedef struct
{
    char* name;
    int salary;
    int id;
}
Person;

Person* Person_Init(char* name, int salary, int id)
{
    Person* person = malloc(sizeof(*person));
    person-&amp;gt;name = name;
    person-&amp;gt;salary = salary;
    person-&amp;gt;id = id;
    return person;
}

Action Find(void* data, void* args)
{
    Person* person = data;
    if(strcmp(person-&amp;gt;name, args) == 0)
        return STOP;
    else
        return CONTINUE;
}

...

List* list = List_Init(free);
List_Push(list, Person_Init(&quot;Paul Desmond&quot;, INT32_MAX, rand()), TAIL);

...

Node* found = List_For(list, Find, &quot;John Coltrane&quot;);

...
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;queues&quot;&gt;Queues&lt;/h2&gt;

&lt;p&gt;The doubly linked list, being as flexible as it is, just needs a couple renames to build a queue.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;#define Queue_Init(destruct) List_Init(destruct)
#define Queue_Free(self) List_Free(self)
#define Queue_Enqueue(self, data) List_Push(self, data, TAIL)
#define Queue_Dequeue(self) List_Pop(self, self-&amp;gt;head, false)
#define Queue_Peek(self) (self-&amp;gt;head-&amp;gt;data);
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;stacks&quot;&gt;Stacks&lt;/h2&gt;

&lt;p&gt;And of course, a stack is that of a queue, but popping (dequeues) are done from the same end as the pushing (enqueues):&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;#define Stack_Init(destruct) List_Init(destruct)
#define Stack_Free(self) List_Free(self)
#define Stack_Push(self, data) List_Push(self, data, TAIL)
#define Stack_Pop(self) List_Pop(self, self-&amp;gt;tail, false)
#define Stack_Peek(self) (self-&amp;gt;tail-&amp;gt;data)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
</description>
        <pubDate>Sun, 12 Jul 2020 00:00:00 +0000</pubDate>
        <link>https://glouw.com//2020/07/12/Generic-Lists,-Queues,-And-Stacks.html</link>
        <guid isPermaLink="true">https://glouw.com//2020/07/12/Generic-Lists,-Queues,-And-Stacks.html</guid>
      </item>
    
      <item>
        <title>Cpu Shaders</title>
        <description>&lt;p&gt;&lt;a href=&quot;https://github.com/glouw/softshader&quot;&gt;GitHub Source&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I ported a couple popular Shadertoy shaders to run on the CPU:&lt;/p&gt;

&lt;p&gt;Sea Scape, by Alex Alekseev (shadertoy.com/user/TDM)&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/ss/seascape.png&quot; alt=&quot;seascape&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Creation, by Danilo Guanabara (shadertoy.com/user/Danguafer)&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/ss/creation.png&quot; alt=&quot;creation&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Tunnel, by Inigo Quilez (shadertoy.com/user/iq)&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/ss/tunnel.png&quot; alt=&quot;tunnel&quot; /&gt;&lt;/p&gt;

&lt;p&gt;The shaders request a single &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;uint32_t&lt;/code&gt; pointer from SDL2 and then proceeds to divide
the screen into as many horizontal rows as there are logical cores on your CPU. Each
render row is rendered in tandem with the others.&lt;/p&gt;

&lt;p&gt;The performance is strong for the creation and tunnel shaders, averaging
60 FPS with vertical sync, but the seascape shader runs at a steady 0.5 FPS, even without
antialiasing. &lt;a href=&quot;https://github.com/glouw/softshader&quot;&gt;The full source is here&lt;/a&gt;.
The creation and tunnel shaders are worth the study:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;#include &quot;softshader.hh&quot;

static uint32_t shade(const ss::V2 coord)
{
    const auto per = coord / ss::res;
    auto c = ss::V3 {};
    auto l = 0.f;
    auto z = ss::uptime();
    for(int i = 0; i &amp;lt; 3; i++)
    {
        const auto p = (per - 0.5f) * ss::V2 { ss::res.x / ss::res.y, 1.f };
        l = ss::length(p);
        z += 0.07f;
        const auto uv = per + p / l * (ss::sin(z) + 1.f) * ss::abs(ss::sin(l * 9.f - z * 2.f));
        const auto cc = ss::length(ss::abs(ss::mod(uv, 1.f) - 0.5f));
        c[i] = (cc == 0.f) ? 1.f : (0.01f / cc);
    }
    const auto v = c / l;
    return v.color(ss::uptime());
}

int main()
{
    ss::run(shade);
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
</description>
        <pubDate>Sat, 30 May 2020 00:00:00 +0000</pubDate>
        <link>https://glouw.com//2020/05/30/CPU-Shaders.html</link>
        <guid isPermaLink="true">https://glouw.com//2020/05/30/CPU-Shaders.html</guid>
      </item>
    
      <item>
        <title>Open Empire Part 1</title>
        <description>&lt;p&gt;This multi-part series is a walk-through on implementing an 8 player Real Time Strategy (RTS) lockstep engine using the assets
from Trial version of Age of Empires II. Certain simplifications, like omitting terrain elevations and civilizations,
will be made to reduce overall complexity of the source.&lt;/p&gt;

&lt;p&gt;This tool-set in this series will be using a standard ISO C99 compiler, a Makefile, and your standard address and thread sanitizers.
The entirety of the engine, including the networking control system, multithreaded renderer, sound and input system, asset database,
and the pathfinder, will be built from the ground up. Universe and apple pies apart, SDL2 and friends (SDL2_net, SDL2_mixer) will
provide the foundation for cross platform play.&lt;/p&gt;

&lt;p&gt;For legal reasons, the art data files will not be supplied with the source rewrite, but can be attained
by downloading and installing (with Wine if on Linux) the &lt;a href=&quot;https://archive.org/download/AgeofEmpiresIITheAgeofKings_1020/AoE2demo.zip&quot;&gt;Age of Empires 2 - The Age of Kings Trial&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Below is a quick screen grab of the latest development progress (as of April 9, 2020).&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/openempires/img1.png&quot; alt=&quot;Men at Arms vs Men at Arms&quot; /&gt;&lt;/p&gt;
</description>
        <pubDate>Thu, 09 Apr 2020 00:00:00 +0000</pubDate>
        <link>https://glouw.com//2020/04/09/Open-Empire-Part-1.html</link>
        <guid isPermaLink="true">https://glouw.com//2020/04/09/Open-Empire-Part-1.html</guid>
      </item>
    
      <item>
        <title>Vim Tabs</title>
        <description>&lt;p&gt;Vim tabs, like chrome or firefox tabs, allow for a quicker streamlined work flow.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;vim -p Theme.c Timer.c World.c
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;img src=&quot;/images/vim/2019-02-02-041150_681x248_scrot.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;To switch between tabs use:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;gT
gt
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Or, for the inclined, add the following to your .vimrc:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;set tabpagemax=128
map &amp;lt;C-h&amp;gt; gT
map &amp;lt;C-l&amp;gt; gt
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;And now you can switch between 128 open tabs with Ctrl + H and Ctrl + L.&lt;/p&gt;

&lt;p&gt;Some vim pundits argue this to be a misuse of vim’s tab system. Certainly,
long directory names do get in the way, even after vim shortens the tab names.
An alternative is to horizontally stack files with windows instead of tabs.
Simply add:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;set winminwidth=0
map &amp;lt;c-j&amp;gt; &amp;lt;c-w&amp;gt;j&amp;lt;c-w&amp;gt;_
map &amp;lt;c-k&amp;gt; &amp;lt;c-w&amp;gt;k&amp;lt;c-w&amp;gt;_
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;And vim will fold windows into a single line, giving a nice horizontal
stacking effect that can be traversed up and down with CTRL + J and CTRL + K.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/vim/2020-07-08-225637_668x522_scrot.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Take it one step further and have CTAGS, with CTRL + N, open a new window via
symbol lookup for you:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;noremap &amp;lt;c-n&amp;gt; &amp;lt;c-w&amp;gt;g&amp;lt;c-]&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
</description>
        <pubDate>Fri, 01 Feb 2019 00:00:00 +0000</pubDate>
        <link>https://glouw.com//2019/02/01/Vim-Tabs.html</link>
        <guid isPermaLink="true">https://glouw.com//2019/02/01/Vim-Tabs.html</guid>
      </item>
    
      <item>
        <title>Cheaderless</title>
        <description>&lt;p&gt;Headerless C99. It can be done given a basic template:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;#ifndef __CLASS__
#define __CLASS__

#undef defines
#ifdef CLASS
    #define defines(...);
#else
    #define defines(...){__VA_ARGS__}
#endif

#endif
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Let us model a wristwatch as WATCH.c:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;#ifndef __WATCH__
#define __WATCH__

#include &amp;lt;stdio.h&amp;gt;

#undef defines
#ifdef WATCH
    #define defines(...);
#else
    #define defines(...){__VA_ARGS__}
#endif

typedef struct
{
    int hour;
    int minutes;
    int seconds;
}
Watch;

Watch wnew(void) defines
(
    Watch w;
    w.hour = 4;
    w.minutes = 20;
    w.seconds = 0;
    return w;
)

void wtell(const Watch w) defines
(
    printf(&quot;%d\n&quot;, w.hour);
    printf(&quot;%d\n&quot;, w.minutes);
    printf(&quot;%d\n&quot;, w.seconds);
)

#endif
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Our wristwatch object can be compiled into an object file with:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;gcc WATCH.c -c
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;And its inclusion into another file can be done with:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;#define WATCH
#include &quot;WATCH.c&quot;

int main()
{
    Watch watch = wnew();
    wtell(watch);
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The lines:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;#define WATCH
#include &quot;WATCH.c&quot;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;serve as an import statement.&lt;/p&gt;

&lt;p&gt;Our final binary may be compiled as:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;gcc -c main.c WATCH.o
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;As the system model grows, a Makefile can track .c file dependency inclusions with the
-MMD -MP -MT -MF flags and recompile changed .c files and dependencies thereof. For such an
advanced build using more than one object for a system, see &lt;a href=&quot;https://github.com/glouw/cheaderless&quot;&gt;Cheaderless&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The makefile it uses is described here: &lt;a href=&quot;http://glouw.com/2018/04/14/Good-Makefiles.html&quot;&gt;Good Makefiles&lt;/a&gt;.
Touching main.c, for instance (as it is dependency free), will recompile main.c and leave the PERSON and WATCH
.c files alone and relink their object files.&lt;/p&gt;

&lt;p&gt;Now, if only there were a way to have the import statement:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;#define WATCH
#include &quot;WATCH.c&quot;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;defined as:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;#import WATCH
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;then this would be a fun system to maintain!&lt;/p&gt;

&lt;p&gt;Alas, there is no way to run the preprocessor twice, and the addition of a secondary custom preprocessor
is fringing upon new language territory.&lt;/p&gt;
</description>
        <pubDate>Mon, 06 Aug 2018 00:00:00 +0000</pubDate>
        <link>https://glouw.com//2018/08/06/Cheaderless.html</link>
        <guid isPermaLink="true">https://glouw.com//2018/08/06/Cheaderless.html</guid>
      </item>
    
      <item>
        <title>Good Makefiles</title>
        <description>&lt;p&gt;GNU Makefiles and C. One just needs a good template:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;BIN = a.out

SRCS = main.c foo.c bar.c

OBJS = $(SRCS:.c=.o)
DEPS = $(SRCS:.c=.d)

CC = gcc

CFLAGS = -Wshadow -Wall -pedantic -Wextra -g -O3 -flto -march=native

LDLIBS = -lm

LDFLAGS =

$(BIN): $(OBJS) $(DEPS)
	$(CC) $(OBJS) $(LDFLAGS) $(LDLIBS) -o $(BIN)

%.o : %.c %.d Makefile
	$(CC) $(CFLAGS) -MMD -MP -MT $@ -MF $*.d -c $&amp;lt;

-include *.d

%.d : ;

.PHONY: clean
clean:
	rm -f $(BIN) $(OBJS) $(DEPS)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Dependency files are generated during compilation. If a source file is updated it is solely recompiled and linked.
If any header is updated then the dependency file is referenced and all source files which included the header are recompiled
and then linked. If a dependency file is accidentally deleted then it is regenerated. If the Makefile is updated then all source
files are recompiled and linked. Simply add your new source files to SRCS, compiler flags to CFLAGS, libraries to LDLIBS, and linker flags to LDFLAGS.&lt;/p&gt;

&lt;p&gt;As for C++ compatibility, change CC to CXX, gcc to g++, CFLAGS to CXXFLAGS, and all .c files to .cpp files.&lt;/p&gt;

&lt;p&gt;Check out the &lt;a href=&quot;https://github.com/glouw/andvaranaut/blob/master/src/Makefile&quot;&gt;Makefile for Andvaranaut.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It uses this Makefile template, but the C source is written in the intersection of c99 and c++98, making it compilable with
C and C++ compilers using both gcc and clang (and as such, CC and CXX are removed en lieu of the COMPILER variable).&lt;/p&gt;
</description>
        <pubDate>Sat, 14 Apr 2018 00:00:00 +0000</pubDate>
        <link>https://glouw.com//2018/04/14/Good-Makefiles.html</link>
        <guid isPermaLink="true">https://glouw.com//2018/04/14/Good-Makefiles.html</guid>
      </item>
    
      <item>
        <title>Littlewolf</title>
        <description>&lt;p&gt;&lt;a href=&quot;https://github.com/glouw/littlewolf&quot;&gt;GitHub Source&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Raycasting howto blogs are a dime a dozen, though little about ceiling or floor casting is ever mentioned.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/lw/peekgif.gif&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;h1 id=&quot;wall-height&quot;&gt;Wall Height&lt;/h1&gt;

&lt;p&gt;The height of the wall is calculated by taking the normal ray to the wall (in this case, the x direction), and multiplying the
focal length of the field of view. The normal is clamped to a small value in case the player gets too close to the screen.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;const float normal = ray.x &amp;lt; 1e-2f ? 1e-2f : ray.x;
const float size = 0.5f * focal * xres / normal;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The ray is defined as the difference of the vectors of the wall hit and the player:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;const Ray ray = sub(wall.hit.where, hero.where);
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The top and bottom of the wall can be found by subtracting half the size of the wall from the middle of the screen’s y-resolution.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;const int top = (yres + size) / 2.0f;
const int bot = (yres - size) / 2.0f;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;When the player is parallel to a wall the following scene is rendered:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/lw/9.PNG&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;h1 id=&quot;ceiling-and-floor-casting&quot;&gt;Ceiling and Floor casting&lt;/h1&gt;

&lt;p&gt;Ceiling and floor casting require a percentage of the floor in relation to the wall height:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/lw/12.PNG&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;An expression for y:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;y = yres / 2 - h / 2
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Where h is the size of the wall calculated earlier. With a bit of reordering a percentage (p) expression for y is simply:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;p = -h / (2 * y - yres)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;As both (h) and (yres) are constant, (y) will vary and change the percentage (p). This percentage is then used to lerp the along the casted ray:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/lw/11.PNG&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://github.com/glouw/littlewolf&quot;&gt;The full source is here.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;See pcast(). This handles the floor and ceiling casting.&lt;/p&gt;
</description>
        <pubDate>Sun, 11 Mar 2018 00:00:00 +0000</pubDate>
        <link>https://glouw.com//2018/03/11/littlewolf.html</link>
        <guid isPermaLink="true">https://glouw.com//2018/03/11/littlewolf.html</guid>
      </item>
    
      <item>
        <title>C8c</title>
        <description>&lt;p&gt;&lt;a href=&quot;https://github.com/glouw/c8c&quot;&gt;GitHub Source&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Chip8 is a rather obscure virtual machine written for the long forgotten COSMAC VIP.
The virtual machine has 35 opcodes making it an ideal first emulation project.&lt;/p&gt;

&lt;p&gt;High level assemblers exist for the chip8, but not high level programming languages mainly due to limited stack space.&lt;/p&gt;

&lt;p&gt;Fortunately, with a bit of craftsmanship, a B-Like programming language is fully feasible, barring
pointers, of course.&lt;/p&gt;

&lt;p&gt;Take the following addition function:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;add(a, b)
{
    return a + b;
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Here it is called with a bit of stack noise.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;main()
{
    auto a = 7;
    auto b = 8;
    auto c = add(1, 2);
    auto d = 9;
    while(1)
    {
        // Never leave main
    }
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Chip8 reserves address space 0x000 - 0x1FF for the interpreter on the COSMAC VIP system. The first 80 bytes of
this address range is reserved for 16 sprite fonts (0-F, including F), allowing the following set of opcodes to store
general purpose registers V0-VE (including VE) right after the sprite fonts:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;LD  VE, 0x10 ; (6XKK)
LD   F,   VE ; (FX29) Works with multiples of five (0x10 * 5 == 80)
LD [I],   VE ; (FX55)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;VF is not included as it doubles as a scratchpad and V0-VE is fifteen bytes - a multiple of three.&lt;/p&gt;

&lt;p&gt;To store the next stack, change the address pointer I by 15 bytes (multiple of five three times) and push.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;LD  VF, 0x03 ; (6XKK)
ADD VE,   VF ; (8XY4)
LD   F,   VE ; (FX29)
LD [I],   VE ; (FX55)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Popping a previously stored stack works the same but in reverse:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;LD  VF, 0x03 ; (6XKK)
SUB VE,   VF ; (8XY5)
LD   F,   VE ; (FX29)
LD  VE,  [I] ; (FX65)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Optionally, before popping a previously stored stack, a value can be saved in VF.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;LD  VF, 0x03 ; (6XKK)
SUB VE,   VF ; (8XY5)
LD  VF,   V2 ; (8XY0) Saving V2 in VF
LD   F,   VE ; (FX29)
LD  VE,  [I] ; (FX65)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Stringing these ideas together, functions can be built with a bit of register management. Looking at main():&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;main()
{
    auto a = 7;
    auto b = 8;
    auto c = add(1, 2);
    auto d = 9;
    while(1)
    {
        // Never leave main
    }
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;When compiled without any sort of optimization, this may become:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;main:
    LD VE,0x10 ; Initial setup for call stacks - lets I point to location after sprite fonts
    LD V0,0x07 ; auto a = 7
    LD V1,0x08 ; auto b = 8
    LD V2,0x01 ; 1st argument to add()
    LD V3,0x02 ; 2nd argument to add()
    LD F,VE    ; Stack push
    LD [I],VE
    LD VF,0x03
    ADD VE,VF
    LD V0,V2   ; Transfer by value arguments for function call
    LD V1,V3
    CALL add   ; Call the add function
    LD V2,VF   ; Copy return value stored in VF to V2
    LD V3,0x09 ; auto d = 9
WHILE7:
    LD V4,0x01   ; while(1)
    SNE V4,0x00  ; {
    JP END7      ;     // Never leave main
    JP WHILE7    ; }
END7:
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Returning to the add function, this:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;add(a, b)
{
    return a + b;
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;May compile into:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;add:
    LD V2,V0   ; Scratchpad copy
    LD V3,V1   ; Scratchpad copy
    ADD V2,V3  ; Do the addition
    LD VF,0x03 ; Prepare stack pop
    SUB VE,VF
    LD VF,V2   ; Save to VF for return
    LD F,VE    ; Stack pop
    LD VE,[I]
    RET
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;A beasty yet plausible solution to function calls on the chip8’s extremely limited platform.
Unfortunately this does not work for all data types other that word size of chip8 (one byte) which
makes a full fitting B-Implementation (not including pointers) feasible. Have you an actual COSMAC
running the chip8 virtual machine with this code beware that the stack frames may clobber the virtual
machine itself.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://github.com/glouw/c8c&quot;&gt;Nevertheless, check out c8c - a single portable single source compiler for the chip8 platform&lt;/a&gt;.
Included is a virtual machine mock-up and assembler to test it out.&lt;/p&gt;

&lt;p&gt;The code it generates is dorm room hobby quality serving as a proof of concept. Don’t expect small binaries.&lt;/p&gt;
</description>
        <pubDate>Mon, 05 Mar 2018 00:00:00 +0000</pubDate>
        <link>https://glouw.com//2018/03/05/C8C.html</link>
        <guid isPermaLink="true">https://glouw.com//2018/03/05/C8C.html</guid>
      </item>
    
      <item>
        <title>Dungen</title>
        <description>&lt;p&gt;&lt;a href=&quot;https://github.com/glouw/dungen&quot;&gt;GitHub Source&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There are many dungeon generation algorithms out there, but my favorite by
far is what Phi Dinh of Tiny Keep was able to do with &lt;a href=&quot;https://www.reddit.com/r/gamedev/comments/1dlwc4/procedural_dungeon_generation_algorithm_explained/&quot;&gt;Delaunay Triangulation
and minimum spanning trees&lt;/a&gt;.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;#############################################################
###########         #         #         #         ###########
##       ##         #         #         #         ###########
##       ##         #         #         #         #         #
##       ##         #         #         #         #         #
##                                                          #
##       ##         #         #         #         #         #
##       ##         #         #         #         #         #
##       ##         #         #         #         ##### #####
###########         #         #         #         ##### #####
############### ################### ################### #####
############### ###############         #         ##       ##
#############     #############         #         ##       ##
###########         ###########         #         #         #
###########         ###########         #         #         #
###########         ###########                             #
###########         ###########         #         #         #
###########         ###########         #         #         #
#############     #############         #         ##       ##
############### ###############         #         ##       ##
############### ############################# ######### #####
###     #####     ########################       ####     ###
###     #####     ####       #############       ###       ##
###     ###         ##       #############       ##         #
###     ###         ##       #############       ##         #
###                          #############                  #
###     ###         ##       #############       ##         #
###     ###         ##       #############       ##         #
###     #####     ####       #############       ###       ##
###     #####     ####### ################       ####     ###
##### ######### ######### ############################# #####
#         #         ##### ######       ###       ####     ###
#         #         ##       ###       ###       ####     ###
#         #         ##       ###       ###       ####     ###
#         #         ##       ###       ###       ####     ###
#                   ##                                    ###
#         #         ##       ###       ###       ####     ###
#         #         ##       ###       ###       ####     ###
#         #         ##       ###       ###       ####     ###
#         #         ############       ###       ####     ###
##### #######################################################
##### ######       ###       ################################
##       ###       ###       ################################
##       ###       ###       ################################
##       ###       ###       ################################
##                           ################################
##       ###       ###       ################################
##       ###       ###       ################################
##       ###       ###       ################################
############       ###       ################################
############### ######### ###################################
############       ###       ##############     #############
############       ###       ##############     #####     ###
############       ###       ##############     ####       ##
############       ###       ##############     ####       ##
############       ###       ##############                ##
############       ###       ##############     ####       ##
############       ###       ##############     ####       ##
############       ###       ##############     #####     ###
############       ###       ##############     ####### #####
############### ######### ################### ######### #####
#         ###     ####       ##############     ####### #####
#         ##       ##         #         ###     ####       ##
#         ##       ##         #         ##       ###       ##
#         ##       ##         #         ##       ###       ##
#                                       ##       ###       ##
#         ##       ##         #         ##       ###       ##
#         ##       ##         #         ##       ###       ##
#         ##       ##         #         ###     ####       ##
#         ###     ####       ###### #######     ####### #####
##### ############################# ######### ######### #####
#         ######################### ######### #####         #
#         #######################     #####     ###         #
#         #######################     ####       ##         #
#         #######################     ####       ##         #
#         #######################                           #
#         #######################     ####       ##         #
#         #######################     ####       ##         #
#         #######################     #####     ###         #
#         #########################################         #
##### ################################################# #####
##### #####         ###     #####     #############         #
#         #         ##       ####     #############         #
#         #         ##       ####     #############         #
#         #         ##       ####     #############         #
#                                     #############         #
#         #         ##       ####     #############         #
#         #         ##       ####     #############         #
#         #         ##       ####     #############         #
###########         ###     #####     #############         #
############### ######### ######### ################### #####
###########         ##### #####         #         ##### #####
###########         ##       ##         #         ##       ##
###########         ##       ##         #         ##       ##
###########         ##       ##         #         ##       ##
###########         ##       ##                            ##
###########         ##       ##         #         ##       ##
###########         ##       ##         #         ##       ##
###########         ##       ##         #         ##       ##
###########         ###########         #         ###########
#############################################################
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This implementation uses Kruskal’s Reverse Delete algorithm, only that each edge
has a reversed duplicate edge, and the algorithm is applied on a sorted-by-length list
of edges. Reverse edge cousins may not be perfectly grouped in pairs of two after the sort,
creating chances for circularly connected edges.&lt;/p&gt;

&lt;p&gt;Once the spanning tree is generated, a room is placed at the points of each edge,
and the edge length is used as a step vector for placing the corridors.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://github.com/glouw/dungen&quot;&gt;See my implementation here.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It’s MIT - Phi’s brain child before all.&lt;/p&gt;

&lt;p&gt;If you are further interested, check out &lt;a href=&quot;https://github.com/glouw/Andvaranaut&quot;&gt;Andvaranaut&lt;/a&gt; on github.
It uses this to generate 32 large connected rooms, and renders them so in a 2.5D Doom like first person fashion.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/and/andvaranaut.png&quot; alt=&quot;Andvaranaut&quot; /&gt;&lt;/p&gt;
</description>
        <pubDate>Sat, 17 Feb 2018 00:00:00 +0000</pubDate>
        <link>https://glouw.com//2018/02/17/dungen.html</link>
        <guid isPermaLink="true">https://glouw.com//2018/02/17/dungen.html</guid>
      </item>
    
      <item>
        <title>Weaver</title>
        <description>&lt;p&gt;&lt;a href=&quot;https://github.com/glouw/weaver&quot;&gt;GitHub Source&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Weaver generates a spider tapestry with a two fold algorithm. The initial phase
processes the image: The image is blurred with a Gaussian convolution blur,
grey scaled, and then sobel filtered. A threshold is then applied to identify
edges with a binary true or false. These points are pushed into list.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/wv/geralt.png&quot; alt=&quot;The White Wolf&quot; /&gt;&lt;/p&gt;

&lt;p&gt;The latter phase makes use of Delaunay Triangulation:
A point from the list may freely be placed in a triangle mesh given that all triangles
do not contain the point within in their circumcenters. Fortunately this will
never be the case as the window is engulfed with a super-triangle.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/wv/1tri.png&quot; alt=&quot;One triangle engulfs the entire window on the outside&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Given that the point does lie in a triangle’s circumcenter, the triangle is
removed and its edges torn to form three new triangles with the point.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/wv/3tri.png&quot; alt=&quot;Three Triangles&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Given the point is placed in the circumcenter of two or more triangles, the
triangles are removed and overlapping aligning edges of the triangles are also removed.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/wv/2tri.png&quot; alt=&quot;Two Triangles&quot; /&gt;&lt;/p&gt;

&lt;p&gt;The remaining edges are unique and are used to construct new triangles with the point.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/wv/4tri.png&quot; alt=&quot;Four Triangles&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Triangle edges are painted with the pixel color value at the center of the triangle.&lt;/p&gt;

&lt;p&gt;The iteration continues until all points have been added to the mesh.&lt;/p&gt;

&lt;p&gt;Check out the &lt;a href=&quot;https://github.com/glouw/weaver&quot;&gt;code available here.&lt;/a&gt;&lt;/p&gt;
</description>
        <pubDate>Thu, 01 Feb 2018 00:00:00 +0000</pubDate>
        <link>https://glouw.com//2018/02/01/weaver.html</link>
        <guid isPermaLink="true">https://glouw.com//2018/02/01/weaver.html</guid>
      </item>
    
      <item>
        <title>Gel</title>
        <description>&lt;p&gt;&lt;a href=&quot;https://github.com/glouw/gel&quot;&gt;GitHub Source&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;An N64 like pipeline is obviously not as complicated as any modern day graphical pipeline,
but the combination of z-buffering, Gouraud shading, and texture mapping yields some pretty nice results:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/gel/salesman.gif&quot; alt=&quot;Salesman&quot; /&gt;&lt;/p&gt;

&lt;p&gt;This can be done in about 500 lines of pure C code without any graphic libraries.
One just needs a 32 bit pointer to video memory, a strong understanding of linear algebra, and plenty of patience.&lt;/p&gt;

&lt;h1 id=&quot;software-renderering-like-it-is-1996&quot;&gt;Software renderering like it is 1996&lt;/h1&gt;

&lt;p&gt;3D models are stored in wavefront object files. These object files contain a list of vertices, faces,
vertex normals, and texture vertices for each face.&lt;/p&gt;

&lt;p&gt;Faces from the object file are centered around (0, 0, 0). To be of use the faces must be
translated to fit the screen. Faces need color and are filled by wrapping a 2D rectangle
around a trigon. For every pixel of the rectangle the barycentric coordinate of the trigon is calculated.
If the x, y, and z coordinates of the barycenter coordinate are all greater than zero then the x and y
coordinates of the rectangle are within the trigon.&lt;/p&gt;

&lt;p&gt;The amount of light reflected from a trigon is calculated using the dot product of the sum of the trigon vertex
normals with the direction of light from the camera.&lt;/p&gt;

&lt;p&gt;Trigons in the foreground may not overlap trigons in the background. A z-buffer keeps track of pixel
distance from the viewport. When a new pixel is added the z-buffer is referenced for an already drawn foreground pixel.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/gel/a.png&quot; alt=&quot;Flat shading - Isometric&quot; /&gt;&lt;/p&gt;

&lt;p&gt;A perspective view of the image is established by dividing the x and y coordinate of each vertex with the
corresponding z value using (1.0 - z).&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/gel/b.png&quot; alt=&quot;Flat shading - Perspective&quot; /&gt;&lt;/p&gt;

&lt;p&gt;By reusing the previously calculated barycenter, a varying vertex of the trigon can be calculated
with dot products of the normal vertices with the direction of light from the camera. This technique is
known as Gouraud shading.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/gel/c.png&quot; alt=&quot;Gouraud shading&quot; /&gt;&lt;/p&gt;

&lt;p&gt;By once again reusing the barycenter, an x and y coordinate can be calculated
by multiplying the x, y, and z coordinates of the barycenter with the x, y, and z coordinates of the texture
vertices of the trigon. This x and y coordinate will return the pixel color of the object file’s associating texture
bitmap file.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/gel/d.png&quot; alt=&quot;Gouraud shading&quot; /&gt;&lt;/p&gt;

&lt;p&gt;And thats all there is to it. I must admit that it is easier said than done. Have a look at
the &lt;a href=&quot;https://github.com/glouw/gel&quot;&gt;implementation.&lt;/a&gt;&lt;/p&gt;
</description>
        <pubDate>Sun, 12 Nov 2017 00:00:00 +0000</pubDate>
        <link>https://glouw.com//2017/11/12/gel.html</link>
        <guid isPermaLink="true">https://glouw.com//2017/11/12/gel.html</guid>
      </item>
    
  </channel>
</rss>
