<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
  xmlns:atom="http://www.w3.org/2005/Atom"
  xmlns:dc="http://purl.org/dc/elements/1.1/"
  xmlns:content="http://purl.org/rss/1.0/modules/content/"
  xmlns:media="http://search.yahoo.com/mrss/"
  xmlns:sy="http://purl.org/rss/1.0/modules/syndication/">
  <channel>
    <title>SOL.VIN Journal - pixel_lang</title>
    <link>https://sol.vin/pixellang/</link>
    <description>An esoteric language entirely in pixels.</description>
    <language>en-us</language>
    <copyright>Copyright (c) 2026 Ian Rash</copyright>
    <managingEditor>Ian Rash</managingEditor>
    <webMaster>Ian Rash</webMaster>
    <pubDate>Sat, 07 Sep 2019 00:00:00 GMT</pubDate>
    <lastBuildDate>Sat, 07 Sep 2019 00:00:00 GMT</lastBuildDate>
    <generator>SOL.VIN Static Site Generator (Crystal)</generator>
    <docs>https://www.rssboard.org/rss-specification</docs>
    <sy:updatePeriod>hourly</sy:updatePeriod>
    <sy:updateFrequency>1</sy:updateFrequency>
    <atom:link href="https://sol.vin/pixellang/rss.xml" rel="self" type="application/rss+xml" />
    <image>
      <url>https://sol.vin/apple-touch-icon.png</url>
      <title>SOL.VIN Journal - pixel_lang</title>
      <link>https://sol.vin/pixellang/</link>
    </image>
    <category domain="chain">pixel_lang</category>
    <category domain="skill">Crystal</category>
    <dc:subject>Crystal</dc:subject>
    <category domain="skill">Esoteric Programming</category>
    <dc:subject>Esoteric Programming</dc:subject>
    <category domain="skill">Generative Art</category>
    <dc:subject>Generative Art</dc:subject>
    <category domain="skill">Raylib</category>
    <dc:subject>Raylib</dc:subject>
    <item>
      <title>Showcase</title>
      <link>https://sol.vin/pixellang/2.html</link>
      <guid isPermaLink="true">https://sol.vin/pixellang/2.html</guid>
      <pubDate>Sat, 07 Sep 2019 00:00:00 GMT</pubDate>
      <dc:date>2019-09-07</dc:date>
      <dc:creator>Ian Rash</dc:creator>
      <author>Ian Rash</author>
      <category domain="chain">pixel_lang</category>
      <category domain="skill">Crystal</category>
      <category domain="skill-slug">crystal</category>
      <category domain="skill-category">Languages</category>
      <dc:subject>Crystal</dc:subject>
      <category domain="skill">Esoteric Programming</category>
      <category domain="skill-slug">esoteric_programming</category>
      <category domain="skill-category">Languages</category>
      <dc:subject>Esoteric Programming</dc:subject>
      <category domain="skill">Generative Art</category>
      <category domain="skill-slug">generative_art</category>
      <category domain="skill-category">Design &amp; Art</category>
      <dc:subject>Generative Art</dc:subject>
      <category domain="skill">Raylib</category>
      <category domain="skill-slug">raylib</category>
      <category domain="skill-category">Libraries &amp; Frameworks</category>
      <dc:subject>Raylib</dc:subject>
      <media:content url="https://sol.vin/images/pixellang/ackermann.gif" medium="image" />
      <media:content url="https://sol.vin/images/pixellang/ackermann-draft.jpg" medium="image" />
      <media:content url="https://sol.vin/images/pixellang/superpainter.gif" medium="image" />
      <media:content url="https://sol.vin/images/pixellang/calc.gif" medium="image" />
      <media:content url="https://sol.vin/images/pixellang/fastprimesieve.gif" medium="image" />
      <media:thumbnail url="https://sol.vin/images/pixellang/ackermann.gif" />
      <description><![CDATA[<p>I&#39;d like to take a little time today to showcase some of the programs I made with pixel_lang. I&#39;m very proud of them, and I&#39;m hoping someone will enjoy watching and dissecting them.</p>
<p>The first one I&#39;d like to show off is my Ackermann function, which uses forking, and it&#39;s own in-memory call stack to orchestrate all the individual pistons to fire when necessary.</p>
<center>
<img src="/images/pixellang/ackermann.gif" style="width: 100%; height: 100%;">
</center>
<p>In the example above, there are three possible decisions made, if M is equal to 0, if N is equal to 0, and the recursive call, with the n-arg. That&#39;s why the fork splits the piston into three, one for the recursive call itself, and one for the n-arg, which is also a recursive call.</p>
<p>Here is the draft version of the function, that I made by hand with comments.</p>
<center>
<img src="/images/pixellang/ackermann-draft.jpg" style="width: 100%; height: 100%;">
</center>
<p>Since each call to ack() waits for the next call to finish, I created a basic lock system, that tests to see if there is a piston still executing the function. When a piston finishes, it either creates new pistons (the recursive n-arg call), or frees up old ones waiting for an answer. The n-arg always goes first, then the other calls, after the n-arg piston has finished.</p>
<p>The locks themselves listen directly to static memory, to make them efficient as possible. A locked piston only needs to run one instruction that way, as well as have a direction instruction that pushes the piston back into the conditional lock.</p>
<p>We know a piston is the last piston alive, because the position in the call stack it&#39;s currently at will always be 0. We check that at the end to see when we need to output the answer.</p>
<p>In this program, MAV is M, and MBV is N. S is the current position of the call stack, and SV is the values on the stack, which are whether or not the piston has solved it&#39;s part of the equation, and what that answer was.</p>
<p>I also want to point out that I could have made this in less cycles using Jumps, but I like watching the flow of the program, so there is only one necessary Jump instruction in the whole program.</p>
<p>The next program is one I developed recently to show off for part 2, but didn&#39;t finish it in time.</p>
<center>
<img src="/images/pixellang/superpainter.gif" style="width: 100%; height: 100%;">
</center>
<p>This program uses the meta-programming instruction IMetaSet, to color the middle square two different colors each rotation. The internals on it I&#39;m pretty proud of.</p>
<p>First of all, this program has an infinite loop with no possibility of memory leakage. In pixel_lang, a piston can potentially crash a program after millions of loops because of things like left-over values in I. Since I is a collection with no bounds, if it gets to full the program either crawls to a halt, or straight crashes.</p>
<p>If you look on the left and right sides, you can see two pistons, each going in a loop. The right side is an incrementer, and the left side is a decrementer. They count either up to 19, or down to 7, which is the exact coordinates of our center square, on two separate SV values. The inner piston changes it&#39;s S to read from either SV depending on what stage of the program it&#39;s at.</p>
<p>The painting bot itself uses a neat effect/tactic. The two colors it&#39;s changing itself between are IMetaSet(:sv, 0, :mav, 0, 2, :ma, 0), IMetaSet(:mav, 0, :sv, 0, 2, :ma, 0). SV and MAV are either X or Y, depending on the direction. MA is the control code register, which is always 0xD (for IMeta). On I we stack the color value, which in this case is either, 0x68480 or 0x49480. Whatever color is currently on the board, it paints the opposite of it.</p>
<p>The timing was really difficult on this program, because fork priority had to be respected at every turn. Since each piston has Read, Execute, and Move phases, the two pistons on the sides only increment/decrement after the painting piston has moved. This gives the effect of painting whats behind it, even though it actually changes the instruction it was on during execute phase, and then moves forward one.</p>
<center>
<img src="/images/pixellang/calc.gif" style="width: 100%; height: 100%;">
</center>
<p>Next is my calculator program, this one takes a non-parenthesized math expression, the runs the operations from left to right (does not respect OoO). This was just a fun artsy project I wanted to do to show art was possible (If you can call it art).</p>
<center>
<img src="/images/pixellang/fastprimesieve.gif" style="width: 100%; height: 100%;">
</center>
<p>Another program I wrote is the Sieve of Eratosthenes, a fun way to filter prime numbers. This program uses Call/Return to move the pistons into an &quot;incremental tar pit&quot;, the higher the number of the current index, the higher the wait for a piston to be released from the tar pit. Basically, a generator forks pistons with the current index (which it increments every cycle), then checks to see if it went over the limit. The forked pistons go through the program. When a prime number is found, it is added to a list of prime numbers which is checked against all other future potential primes.This is list is output at the end of the program, once the last piston is done. This example of the program runs up to 30.</p>
]]></description>
      <content:encoded><![CDATA[<p>I&#39;d like to take a little time today to showcase some of the programs I made with pixel_lang. I&#39;m very proud of them, and I&#39;m hoping someone will enjoy watching and dissecting them.</p>
<p>The first one I&#39;d like to show off is my Ackermann function, which uses forking, and it&#39;s own in-memory call stack to orchestrate all the individual pistons to fire when necessary.</p>
<center>
<img src="/images/pixellang/ackermann.gif" style="width: 100%; height: 100%;">
</center>
<p>In the example above, there are three possible decisions made, if M is equal to 0, if N is equal to 0, and the recursive call, with the n-arg. That&#39;s why the fork splits the piston into three, one for the recursive call itself, and one for the n-arg, which is also a recursive call.</p>
<p>Here is the draft version of the function, that I made by hand with comments.</p>
<center>
<img src="/images/pixellang/ackermann-draft.jpg" style="width: 100%; height: 100%;">
</center>
<p>Since each call to ack() waits for the next call to finish, I created a basic lock system, that tests to see if there is a piston still executing the function. When a piston finishes, it either creates new pistons (the recursive n-arg call), or frees up old ones waiting for an answer. The n-arg always goes first, then the other calls, after the n-arg piston has finished.</p>
<p>The locks themselves listen directly to static memory, to make them efficient as possible. A locked piston only needs to run one instruction that way, as well as have a direction instruction that pushes the piston back into the conditional lock.</p>
<p>We know a piston is the last piston alive, because the position in the call stack it&#39;s currently at will always be 0. We check that at the end to see when we need to output the answer.</p>
<p>In this program, MAV is M, and MBV is N. S is the current position of the call stack, and SV is the values on the stack, which are whether or not the piston has solved it&#39;s part of the equation, and what that answer was.</p>
<p>I also want to point out that I could have made this in less cycles using Jumps, but I like watching the flow of the program, so there is only one necessary Jump instruction in the whole program.</p>
<p>The next program is one I developed recently to show off for part 2, but didn&#39;t finish it in time.</p>
<center>
<img src="/images/pixellang/superpainter.gif" style="width: 100%; height: 100%;">
</center>
<p>This program uses the meta-programming instruction IMetaSet, to color the middle square two different colors each rotation. The internals on it I&#39;m pretty proud of.</p>
<p>First of all, this program has an infinite loop with no possibility of memory leakage. In pixel_lang, a piston can potentially crash a program after millions of loops because of things like left-over values in I. Since I is a collection with no bounds, if it gets to full the program either crawls to a halt, or straight crashes.</p>
<p>If you look on the left and right sides, you can see two pistons, each going in a loop. The right side is an incrementer, and the left side is a decrementer. They count either up to 19, or down to 7, which is the exact coordinates of our center square, on two separate SV values. The inner piston changes it&#39;s S to read from either SV depending on what stage of the program it&#39;s at.</p>
<p>The painting bot itself uses a neat effect/tactic. The two colors it&#39;s changing itself between are IMetaSet(:sv, 0, :mav, 0, 2, :ma, 0), IMetaSet(:mav, 0, :sv, 0, 2, :ma, 0). SV and MAV are either X or Y, depending on the direction. MA is the control code register, which is always 0xD (for IMeta). On I we stack the color value, which in this case is either, 0x68480 or 0x49480. Whatever color is currently on the board, it paints the opposite of it.</p>
<p>The timing was really difficult on this program, because fork priority had to be respected at every turn. Since each piston has Read, Execute, and Move phases, the two pistons on the sides only increment/decrement after the painting piston has moved. This gives the effect of painting whats behind it, even though it actually changes the instruction it was on during execute phase, and then moves forward one.</p>
<center>
<img src="/images/pixellang/calc.gif" style="width: 100%; height: 100%;">
</center>
<p>Next is my calculator program, this one takes a non-parenthesized math expression, the runs the operations from left to right (does not respect OoO). This was just a fun artsy project I wanted to do to show art was possible (If you can call it art).</p>
<center>
<img src="/images/pixellang/fastprimesieve.gif" style="width: 100%; height: 100%;">
</center>
<p>Another program I wrote is the Sieve of Eratosthenes, a fun way to filter prime numbers. This program uses Call/Return to move the pistons into an &quot;incremental tar pit&quot;, the higher the number of the current index, the higher the wait for a piston to be released from the tar pit. Basically, a generator forks pistons with the current index (which it increments every cycle), then checks to see if it went over the limit. The forked pistons go through the program. When a prime number is found, it is added to a list of prime numbers which is checked against all other future potential primes.This is list is output at the end of the program, once the last piston is done. This example of the program runs up to 30.</p>
<hr style="margin-top: 2rem; margin-bottom: 1rem; border: none; border-top: 1px solid #ccc;" />
<div class="rss-entry-metadata" style="font-size: 0.9em; line-height: 1.5; background: #faf6ee; color: #1c1c1e; padding: 0.85rem; border: 1px solid #1c1c1e; border-radius: 4px;">
  <p style="margin: 0.25rem 0;"><strong>Category Chain:</strong> <a href="https://sol.vin/pixellang/">pixel_lang</a></p>
  <p style="margin: 0.25rem 0;"><strong>Date:</strong> 2019-09-07</p>
  <p style="margin: 0.25rem 0;"><strong>Author:</strong> Ian Rash</p>
  <p style="margin: 0.5rem 0 0.25rem 0;"><strong>Skills &amp; Technologies:</strong></p>
  <ul style="margin: 0.25rem 0 0 1.25rem; padding: 0;">
    <li><strong>Crystal</strong> (<em>Languages</em>) &bull; 8 years &mdash; A fast, compiled, statically typed language with Ruby-inspired syntax. [<a href="https://crystal-lang.org">Website</a> | <a href="https://github.com/crystal-lang/crystal">Github</a>]</li>
    <li><strong>Esoteric Programming</strong> (<em>Languages</em>) &bull; 3 years &mdash; Designing non-traditional programming languages to test boundaries of language design and visual computing. [<a href="https://en.wikipedia.org/wiki/Esoteric_programming_language">Wikipedia</a>]</li>
    <li><strong>Generative Art</strong> (<em>Design &amp; Art</em>) &bull; 5 years &mdash; Algorithmic generation of visual artwork, procedural textures, vector SVG patterns, and game graphics. [<a href="https://en.wikipedia.org/wiki/Generative_art">Wikipedia</a>]</li>
    <li><strong>Raylib</strong> (<em>Libraries &amp; Frameworks</em>) &bull; 5 years &mdash; A simple and easy-to-use C library to enjoy videogames programming. [<a href="https://www.raylib.com">Website</a> | <a href="https://github.com/raysan5/raylib">Github</a>]</li>
  </ul>
</div>
]]></content:encoded>
    </item>
    <item>
      <title>More Instructions</title>
      <link>https://sol.vin/pixellang/1.html</link>
      <guid isPermaLink="true">https://sol.vin/pixellang/1.html</guid>
      <pubDate>Fri, 06 Sep 2019 00:00:00 GMT</pubDate>
      <dc:date>2019-09-06</dc:date>
      <dc:creator>Ian Rash</dc:creator>
      <author>Ian Rash</author>
      <category domain="chain">pixel_lang</category>
      <category domain="skill">Crystal</category>
      <category domain="skill-slug">crystal</category>
      <category domain="skill-category">Languages</category>
      <dc:subject>Crystal</dc:subject>
      <category domain="skill">Esoteric Programming</category>
      <category domain="skill-slug">esoteric_programming</category>
      <category domain="skill-category">Languages</category>
      <dc:subject>Esoteric Programming</dc:subject>
      <category domain="skill">Generative Art</category>
      <category domain="skill-slug">generative_art</category>
      <category domain="skill-category">Design &amp; Art</category>
      <dc:subject>Generative Art</dc:subject>
      <category domain="skill">Raylib</category>
      <category domain="skill-slug">raylib</category>
      <category domain="skill-category">Libraries &amp; Frameworks</category>
      <dc:subject>Raylib</dc:subject>
      <media:content url="https://sol.vin/images/pixellang/7.png" medium="image" />
      <media:content url="https://sol.vin/images/pixellang/twistyturny.gif" medium="image" />
      <media:content url="https://sol.vin/images/pixellang/jumpexample.gif" medium="image" />
      <media:content url="https://sol.vin/images/pixellang/moveexample.gif" medium="image" />
      <media:content url="https://sol.vin/images/pixellang/8.png" medium="image" />
      <media:content url="https://sol.vin/images/pixellang/9.png" medium="image" />
      <media:content url="https://sol.vin/images/pixellang/conditionalexample.gif" medium="image" />
      <media:content url="https://sol.vin/images/pixellang/forkexample.gif" medium="image" />
      <media:content url="https://sol.vin/images/pixellang/painter.gif" medium="image" />
      <media:thumbnail url="https://sol.vin/images/pixellang/7.png" />
      <description><![CDATA[<p>We covered Start, End, and Output Char in the last section, next we want to use Direction and Jump. Let&#39;s create a version of Hello World that does some crafty maneuvering to only use a single output char instruction for each character of &quot;Hello World!&quot;. First we need to make the instructions we need to use.</p>
<center>
<img src="/images/pixellang/7.png" style="width: 100%; height: 100%;">
</center>
<p>Then we just need to come up with an interesting layout. I had to specifically be aware of the OutputChar L, because it&#39;s used three times, and I need to go a different route each time.</p>
<center>
<img src="/images/pixellang/twistyturny.gif" style="width: 100%; height: 100%;">
</center>
<p>I often times use Jump to allow a single directional line of code have multiple meanings.</p>
<p>For example, take this program, which only hits the pink spaces one way, and the yellow spaces other. This programs runs indefinitely.</p>
<center>
<img src="/images/pixellang/jumpexample.gif" style="width: 100%; height: 100%;">
</center>
<h3>Insert</h3>
<p>Insert is instruction number 0x8, and it&#39;s 20bit argument is stacked onto the I stack of any Piston that executes it. It&#39;s used to introduce constants into your program.</p>
<h3>Move</h3>
<p>Move is an instruction which takes two register arguments, and moves the value from the source to the destination. When specifying a register, you also need to specify a register option which can change how the register is interacted with.</p>
<p>For example, a MOV(MA(0) -&gt; MB(0)) will move the value in MA into MB, where MOV(MA(1) -&gt; MB(0)) will move a random value where MA is the max of that number, and move it into MB.</p>
<p>Another good example would be MOV(I(0) -&gt; MA(0)) which pops a value off I and puts it into MA, and MOV(I(2) -&gt; MA(0)) which only peeks the value.</p>
<p>Register options can be very useful!</p>
<p>Let&#39;s give Move a try.</p>
<center>
<img src="/images/pixellang/moveexample.gif" style="width: 100%; height: 100%;">
</center>
<p>In the program above, 100, 200, and then 300 are placed on the I stack using Insert, then moved to output using MOV(I(0) -&gt; O(0)), and a space is added between. We can see when the I stack runs out, it always returns 0 if there is no engine input to consume.</p>
<p>MOV can also be used with register options to change register behaviour. For example, if MA is equal to 1234 and MOV(MA(1) -&gt; O(0)) is called, output will be a random number between 0 and 1234. Reading from I(2) doesn&#39;t pull the item off the I stack, while I(0) does.</p>
<p>Move also has two other options, swap and reverse. Swap swaps the values of two registers. The order it does that is very important, since register reads can trigger changes (like I or O for example). When swapping values, the source value is gotten first, then the destination value, then the source is set first, then the destination is set. This is important to understand especially when using the instruction MOV(I(0) -&gt; I(0)), which will swap the top two values on the I stack.</p>
<p>You can also reverse the source and destination, this option isn&#39;t particularly useful, it&#39;s just to allow for more interesting colors to be made.</p>
<h3>Arithmetic</h3>
<p>One of my favorite instructions, Arithmetic allows you to build simple mathematical expressions. Arithmetic takes two source registers, an operation, and a destination register. Here are some examples.</p>
<center>
<img src="/images/pixellang/8.png" style="width: 100%; height: 100%;">
</center>
<p>Here&#39;s a list of all the mathematical operators available.</p>
<pre class="code-block"><code>BOOLEAN_OPERATIONS = [:&amp;lt;, :&amp;gt;, :&amp;lt;=, :&amp;gt;=, :==, :!=]
ARITHMETIC_OPERATIONS = [:+, :-, :*, :/, :**, :&amp;, :|, :^, :%]</code></pre>
<p>Using this instruction we can easily make a program to add 100 to an input number.</p>
<p>The program itself only needs 4 instructions. Start, Insert(100), AR(I(0) + I(0) -&gt; O(0)), and End.</p>
<p>When running the program, you need to include an input number into the Engine before starting or it will always display 100, since I always deafults to 0 when there is no input.</p>
<center>
<img src="/images/pixellang/9.png" style="width: 100%; height: 100%;">
</center>
<h3>Conditional</h3>
<p>Conditional allows pistons to make decisions on where they will go, based on a mathematical expression. You choose two directions, a true direction, and a false direction, and if the mathematical expression evaluates to 0 it goes the false direction, otherwise the true direction.</p>
<p>Boolean operators always produce either a 0 (false), or a 1 (true).</p>
<p>Conditional lets us create decisions and loops that will be the basic building blocks of our programs.</p>
<p>To show off what the Conditional can do, we are going to make a &quot;count to&quot; program which will take a number, and count up to that number.</p>
<center>
<img src="/images/pixellang/conditionalexample.gif" style="width: 100%; height: 100%;">
</center>
<p>In this example, the value of MB is always 1. We use that to increment MA each loop, and use the beige instruction (a Conditional) to determine if we have hit our max number yet. If not, we output the number, output a space, and start over again. Interesting note, Start instructions operate as Direction instructions when executed by a Piston. This allows us to restart programs easily if necessary.</p>
<h2>Call/Return</h2>
<p>These two instructions work in tandem to allow a Piston to return to a previous state, and choose what it takes along with it. Call and Return can be some of the most powerful instructions if used right.</p>
<p>Call takes a couple arguments, the first being an action, which is either :none, :push, :none_run, :push_run. This determines behavior of the Piston after running the Call, if it should push it&#39;s current frame to stack, or not, or if it should step once after the Call. For example, the none option does not push a frame to the call stack, where push does.</p>
<p>Call also takes a signed X and Y argument.</p>
<p>Call moves the Piston X and Y spaces away from the Call instructions. This is all relative spacing, there is no absolute values for Call.</p>
<p>When a Return instruction is read by a Piston, it checks to see if there is a frame on it&#39;s call stack. If there is a frame, the Return instruction chooses what values to copy back to the piston, for example, you can choose to restore the X position but not the Y, the direction, you can choose to keep MA the same, or restore it from the frame, that sort of thing. If there is no frame on the call stack, Return does nothing.</p>
<p>Return has a lot of arguments, a full list from the color_helper dev module:</p>
<pre class="code-block"><code>Return Instruction
Returns a frame from the call stack.
0bCCCC00000000PPABSIIMMXYD
C = Control Code (Instruction) [4 bits]
P = Action bits [:pop, :peek, :pop_push, :peek_push]
A = Copy MA?
B = Copy MB?
S = Copy S?
I = Copy I action? [:keep, :restore, :clear]
M = Copy memory action? [:keep, :restore, :clear]
X = Jump back to X?
Y = Jump back to Y?
D = Change the direction?</code></pre>
<p>First, the action specifies whether or not a frame should peeked, or popped off the call stack and/or if the current frame of the Piston should be added back to the call stack.</p>
<p>Next, should we copy MA, MB, S, X, Y, etc?</p>
<p>Lastly, I and Memory (since they are collections) both have special operations. Whether or not we should keep them, restore the frame&#39;s version, or clear altogether. When using :clear, even if there is nothing on the call stack, that item will still be cleared.</p>
<p>Again Return is super powerful, with it, we can set up all sorts of interesting interactions with the program code.</p>
<h3>Fork</h3>
<p>Fork is used to make exact duplicates of Pistons, facing in different (or the same) directions. One Fork instruction can make up to 4 new pistons. The original piston always follows direction #1, and each piston created afterwards executes after the last one created. Imagine two pistons one the same space that hit a fork instruction. Let&#39;s call them P1 and P2, after their priority numbers. P1 creates a new Piston, sandwiched between it and P2 in the execution order, while P2&#39;s created clone will be below it in the execution order.</p>
<p>Here is an example program I wrote to test the limits of Fork (like how many times can you fork before the program crashes).</p>
<center>
<img src="/images/pixellang/forkexample.gif" style="width: 100%; height: 100%;">
</center>
<p>I also use Fork in my Ackermann implementation, since it&#39;s perfect for the job of expansion!</p>
<h3>InstructionMeta</h3>
<p>InstructionMeta is an instruction that houses four other functions, Get, Set, Resize, and Property.</p>
<p>Get allows a Piston to get the value of a color located at the X and Y values specified by two registers. Puts the control code, then the control value on the I stack.</p>
<p>Set allows a Piston to set the value of a color located at the X and Y values specified by two registers, to the value located on the I Stack. Since the I stack can only hold values up to 0xFFFFF, the I stack is read twice and the values bitshifted and combined to for the color. For example, if 0xBBBBB then 0xA were on the I stack, the color would be 0xABBBBBB.</p>
<p>Resize allows a piston to resize the instructions width and height.</p>
<p>Property allows a Piston to get the width and height of the instruction set.</p>
<p>Using these instructions, we can modify the instructions on the board! Here is an example program, a painter bot.</p>
<center>
<img src="/images/pixellang/painter.gif" style="width: 100%; height: 100%;">
</center>
<p>The program above uses two pistons. One goes in a loop and counts up from 0 to the width of the &quot;drawing canvas&quot;. The other piston reads the IMetaSet instructions, and executes them, changing the current square they are on, then moving to another. This gives the effect of a bot painting the ground behind it.</p>
]]></description>
      <content:encoded><![CDATA[<p>We covered Start, End, and Output Char in the last section, next we want to use Direction and Jump. Let&#39;s create a version of Hello World that does some crafty maneuvering to only use a single output char instruction for each character of &quot;Hello World!&quot;. First we need to make the instructions we need to use.</p>
<center>
<img src="/images/pixellang/7.png" style="width: 100%; height: 100%;">
</center>
<p>Then we just need to come up with an interesting layout. I had to specifically be aware of the OutputChar L, because it&#39;s used three times, and I need to go a different route each time.</p>
<center>
<img src="/images/pixellang/twistyturny.gif" style="width: 100%; height: 100%;">
</center>
<p>I often times use Jump to allow a single directional line of code have multiple meanings.</p>
<p>For example, take this program, which only hits the pink spaces one way, and the yellow spaces other. This programs runs indefinitely.</p>
<center>
<img src="/images/pixellang/jumpexample.gif" style="width: 100%; height: 100%;">
</center>
<h3>Insert</h3>
<p>Insert is instruction number 0x8, and it&#39;s 20bit argument is stacked onto the I stack of any Piston that executes it. It&#39;s used to introduce constants into your program.</p>
<h3>Move</h3>
<p>Move is an instruction which takes two register arguments, and moves the value from the source to the destination. When specifying a register, you also need to specify a register option which can change how the register is interacted with.</p>
<p>For example, a MOV(MA(0) -&gt; MB(0)) will move the value in MA into MB, where MOV(MA(1) -&gt; MB(0)) will move a random value where MA is the max of that number, and move it into MB.</p>
<p>Another good example would be MOV(I(0) -&gt; MA(0)) which pops a value off I and puts it into MA, and MOV(I(2) -&gt; MA(0)) which only peeks the value.</p>
<p>Register options can be very useful!</p>
<p>Let&#39;s give Move a try.</p>
<center>
<img src="/images/pixellang/moveexample.gif" style="width: 100%; height: 100%;">
</center>
<p>In the program above, 100, 200, and then 300 are placed on the I stack using Insert, then moved to output using MOV(I(0) -&gt; O(0)), and a space is added between. We can see when the I stack runs out, it always returns 0 if there is no engine input to consume.</p>
<p>MOV can also be used with register options to change register behaviour. For example, if MA is equal to 1234 and MOV(MA(1) -&gt; O(0)) is called, output will be a random number between 0 and 1234. Reading from I(2) doesn&#39;t pull the item off the I stack, while I(0) does.</p>
<p>Move also has two other options, swap and reverse. Swap swaps the values of two registers. The order it does that is very important, since register reads can trigger changes (like I or O for example). When swapping values, the source value is gotten first, then the destination value, then the source is set first, then the destination is set. This is important to understand especially when using the instruction MOV(I(0) -&gt; I(0)), which will swap the top two values on the I stack.</p>
<p>You can also reverse the source and destination, this option isn&#39;t particularly useful, it&#39;s just to allow for more interesting colors to be made.</p>
<h3>Arithmetic</h3>
<p>One of my favorite instructions, Arithmetic allows you to build simple mathematical expressions. Arithmetic takes two source registers, an operation, and a destination register. Here are some examples.</p>
<center>
<img src="/images/pixellang/8.png" style="width: 100%; height: 100%;">
</center>
<p>Here&#39;s a list of all the mathematical operators available.</p>
<pre class="code-block"><code>BOOLEAN_OPERATIONS = [:&amp;lt;, :&amp;gt;, :&amp;lt;=, :&amp;gt;=, :==, :!=]
ARITHMETIC_OPERATIONS = [:+, :-, :*, :/, :**, :&amp;, :|, :^, :%]</code></pre>
<p>Using this instruction we can easily make a program to add 100 to an input number.</p>
<p>The program itself only needs 4 instructions. Start, Insert(100), AR(I(0) + I(0) -&gt; O(0)), and End.</p>
<p>When running the program, you need to include an input number into the Engine before starting or it will always display 100, since I always deafults to 0 when there is no input.</p>
<center>
<img src="/images/pixellang/9.png" style="width: 100%; height: 100%;">
</center>
<h3>Conditional</h3>
<p>Conditional allows pistons to make decisions on where they will go, based on a mathematical expression. You choose two directions, a true direction, and a false direction, and if the mathematical expression evaluates to 0 it goes the false direction, otherwise the true direction.</p>
<p>Boolean operators always produce either a 0 (false), or a 1 (true).</p>
<p>Conditional lets us create decisions and loops that will be the basic building blocks of our programs.</p>
<p>To show off what the Conditional can do, we are going to make a &quot;count to&quot; program which will take a number, and count up to that number.</p>
<center>
<img src="/images/pixellang/conditionalexample.gif" style="width: 100%; height: 100%;">
</center>
<p>In this example, the value of MB is always 1. We use that to increment MA each loop, and use the beige instruction (a Conditional) to determine if we have hit our max number yet. If not, we output the number, output a space, and start over again. Interesting note, Start instructions operate as Direction instructions when executed by a Piston. This allows us to restart programs easily if necessary.</p>
<h2>Call/Return</h2>
<p>These two instructions work in tandem to allow a Piston to return to a previous state, and choose what it takes along with it. Call and Return can be some of the most powerful instructions if used right.</p>
<p>Call takes a couple arguments, the first being an action, which is either :none, :push, :none_run, :push_run. This determines behavior of the Piston after running the Call, if it should push it&#39;s current frame to stack, or not, or if it should step once after the Call. For example, the none option does not push a frame to the call stack, where push does.</p>
<p>Call also takes a signed X and Y argument.</p>
<p>Call moves the Piston X and Y spaces away from the Call instructions. This is all relative spacing, there is no absolute values for Call.</p>
<p>When a Return instruction is read by a Piston, it checks to see if there is a frame on it&#39;s call stack. If there is a frame, the Return instruction chooses what values to copy back to the piston, for example, you can choose to restore the X position but not the Y, the direction, you can choose to keep MA the same, or restore it from the frame, that sort of thing. If there is no frame on the call stack, Return does nothing.</p>
<p>Return has a lot of arguments, a full list from the color_helper dev module:</p>
<pre class="code-block"><code>Return Instruction
Returns a frame from the call stack.
0bCCCC00000000PPABSIIMMXYD
C = Control Code (Instruction) [4 bits]
P = Action bits [:pop, :peek, :pop_push, :peek_push]
A = Copy MA?
B = Copy MB?
S = Copy S?
I = Copy I action? [:keep, :restore, :clear]
M = Copy memory action? [:keep, :restore, :clear]
X = Jump back to X?
Y = Jump back to Y?
D = Change the direction?</code></pre>
<p>First, the action specifies whether or not a frame should peeked, or popped off the call stack and/or if the current frame of the Piston should be added back to the call stack.</p>
<p>Next, should we copy MA, MB, S, X, Y, etc?</p>
<p>Lastly, I and Memory (since they are collections) both have special operations. Whether or not we should keep them, restore the frame&#39;s version, or clear altogether. When using :clear, even if there is nothing on the call stack, that item will still be cleared.</p>
<p>Again Return is super powerful, with it, we can set up all sorts of interesting interactions with the program code.</p>
<h3>Fork</h3>
<p>Fork is used to make exact duplicates of Pistons, facing in different (or the same) directions. One Fork instruction can make up to 4 new pistons. The original piston always follows direction #1, and each piston created afterwards executes after the last one created. Imagine two pistons one the same space that hit a fork instruction. Let&#39;s call them P1 and P2, after their priority numbers. P1 creates a new Piston, sandwiched between it and P2 in the execution order, while P2&#39;s created clone will be below it in the execution order.</p>
<p>Here is an example program I wrote to test the limits of Fork (like how many times can you fork before the program crashes).</p>
<center>
<img src="/images/pixellang/forkexample.gif" style="width: 100%; height: 100%;">
</center>
<p>I also use Fork in my Ackermann implementation, since it&#39;s perfect for the job of expansion!</p>
<h3>InstructionMeta</h3>
<p>InstructionMeta is an instruction that houses four other functions, Get, Set, Resize, and Property.</p>
<p>Get allows a Piston to get the value of a color located at the X and Y values specified by two registers. Puts the control code, then the control value on the I stack.</p>
<p>Set allows a Piston to set the value of a color located at the X and Y values specified by two registers, to the value located on the I Stack. Since the I stack can only hold values up to 0xFFFFF, the I stack is read twice and the values bitshifted and combined to for the color. For example, if 0xBBBBB then 0xA were on the I stack, the color would be 0xABBBBBB.</p>
<p>Resize allows a piston to resize the instructions width and height.</p>
<p>Property allows a Piston to get the width and height of the instruction set.</p>
<p>Using these instructions, we can modify the instructions on the board! Here is an example program, a painter bot.</p>
<center>
<img src="/images/pixellang/painter.gif" style="width: 100%; height: 100%;">
</center>
<p>The program above uses two pistons. One goes in a loop and counts up from 0 to the width of the &quot;drawing canvas&quot;. The other piston reads the IMetaSet instructions, and executes them, changing the current square they are on, then moving to another. This gives the effect of a bot painting the ground behind it.</p>
<hr style="margin-top: 2rem; margin-bottom: 1rem; border: none; border-top: 1px solid #ccc;" />
<div class="rss-entry-metadata" style="font-size: 0.9em; line-height: 1.5; background: #faf6ee; color: #1c1c1e; padding: 0.85rem; border: 1px solid #1c1c1e; border-radius: 4px;">
  <p style="margin: 0.25rem 0;"><strong>Category Chain:</strong> <a href="https://sol.vin/pixellang/">pixel_lang</a></p>
  <p style="margin: 0.25rem 0;"><strong>Date:</strong> 2019-09-06</p>
  <p style="margin: 0.25rem 0;"><strong>Author:</strong> Ian Rash</p>
  <p style="margin: 0.5rem 0 0.25rem 0;"><strong>Skills &amp; Technologies:</strong></p>
  <ul style="margin: 0.25rem 0 0 1.25rem; padding: 0;">
    <li><strong>Crystal</strong> (<em>Languages</em>) &bull; 8 years &mdash; A fast, compiled, statically typed language with Ruby-inspired syntax. [<a href="https://crystal-lang.org">Website</a> | <a href="https://github.com/crystal-lang/crystal">Github</a>]</li>
    <li><strong>Esoteric Programming</strong> (<em>Languages</em>) &bull; 3 years &mdash; Designing non-traditional programming languages to test boundaries of language design and visual computing. [<a href="https://en.wikipedia.org/wiki/Esoteric_programming_language">Wikipedia</a>]</li>
    <li><strong>Generative Art</strong> (<em>Design &amp; Art</em>) &bull; 5 years &mdash; Algorithmic generation of visual artwork, procedural textures, vector SVG patterns, and game graphics. [<a href="https://en.wikipedia.org/wiki/Generative_art">Wikipedia</a>]</li>
    <li><strong>Raylib</strong> (<em>Libraries &amp; Frameworks</em>) &bull; 5 years &mdash; A simple and easy-to-use C library to enjoy videogames programming. [<a href="https://www.raylib.com">Website</a> | <a href="https://github.com/raysan5/raylib">Github</a>]</li>
  </ul>
</div>
]]></content:encoded>
    </item>
    <item>
      <title>Intro</title>
      <link>https://sol.vin/pixellang/0.html</link>
      <guid isPermaLink="true">https://sol.vin/pixellang/0.html</guid>
      <pubDate>Thu, 05 Sep 2019 00:00:00 GMT</pubDate>
      <dc:date>2019-09-05</dc:date>
      <dc:creator>Ian Rash</dc:creator>
      <author>Ian Rash</author>
      <category domain="chain">pixel_lang</category>
      <category domain="skill">Crystal</category>
      <category domain="skill-slug">crystal</category>
      <category domain="skill-category">Languages</category>
      <dc:subject>Crystal</dc:subject>
      <category domain="skill">Esoteric Programming</category>
      <category domain="skill-slug">esoteric_programming</category>
      <category domain="skill-category">Languages</category>
      <dc:subject>Esoteric Programming</dc:subject>
      <category domain="skill">Generative Art</category>
      <category domain="skill-slug">generative_art</category>
      <category domain="skill-category">Design &amp; Art</category>
      <dc:subject>Generative Art</dc:subject>
      <category domain="skill">Raylib</category>
      <category domain="skill-slug">raylib</category>
      <category domain="skill-category">Libraries &amp; Frameworks</category>
      <dc:subject>Raylib</dc:subject>
      <media:content url="https://sol.vin/images/pixellang/ackermann.gif" medium="image" />
      <media:content url="https://sol.vin/images/pixellang/1.png" medium="image" />
      <media:content url="https://sol.vin/images/pixellang/2.png" medium="image" />
      <media:content url="https://sol.vin/images/pixellang/primesieve.gif" medium="image" />
      <media:content url="https://sol.vin/images/pixellang/3.png" medium="image" />
      <media:content url="https://sol.vin/images/pixellang/5.png" medium="image" />
      <media:content url="https://sol.vin/images/pixellang/6.png" medium="image" />
      <media:content url="https://sol.vin/images/pixellang/7.png" medium="image" />
      <media:thumbnail url="https://sol.vin/images/pixellang/ackermann.gif" />
      <description><![CDATA[<p>Today I&#39;m really excited to start a new series on pixel_lang, a pixel-based 2D esoteric language I wrote myself in Crystal. I&#39;ve always really loved esoteric languages, and they can teach us a lot about programming. I enjoy the aspect of honing one&#39;s programming chops, and esoteric languages are filled with all sorts of interesting challenges. My goal in writing an esoteric language was to make a language with a large instruction set, that could be used to make art, programs, or some combination of the two.</p>
<center>
<img src="/images/pixellang/ackermann.gif" style="width: 100%; height: 100%;">
</center>
<p>You can find all project files located on the <a href="https://github.com/sol-vin/pixel_lang_crystal">GitHub</a>.</p>
<p>The purpose of this article, is to give a basic introduction on how to use the <a href="https://github.com/sol-vin/pixel_lang_crystal">pixel_lang</a> interpreter, as well as the web interface, to load and run programs, as well as a basic explanation of how the system works.</p>
<p>The <a href="https://github.com/sol-vin/pixel_lang_crystal">pixel_lang</a> interpreter takes an input PNG file, and uses that as it&#39;s program code. Each pixel in the PNG is read in, and stored into a 2D array of instructions. Any and all PNG files are valid program code and can be used with the interpreter without error but, may not start without the presence of a Start instruction, or will run infinitely. A program can be given input, either by providing an input string argument, or via the live interactive session (yet to be written). This interpreter is called the <a href="https://github.com/sol-vin/pixel_lang_crystal/blob/master/src/pixel_lang_crystal/engine.cr">Engine</a>.</p>
<p><a href="https://github.com/sol-vin/pixel_lang_crystal/blob/master/src/pixel_lang_crystal/engine.cr">Engines</a> are comprised of a variable number of <a href="https://github.com/sol-vin/pixel_lang_crystal/blob/master/src/pixel_lang_crystal/piston.cr">pistons</a>. These <a href="https://github.com/sol-vin/pixel_lang_crystal/blob/master/src/pixel_lang_crystal/piston.cr">pistons</a> act as separate instruction readers and act mostly independently of each other, save for a few exceptions. The starting number of <a href="https://github.com/sol-vin/pixel_lang_crystal/blob/master/src/pixel_lang_crystal/piston.cr">pistons</a> is determined by a program code&#39;s number of Start instructions. The <a href="https://github.com/sol-vin/pixel_lang_crystal/blob/master/src/pixel_lang_crystal/piston.cr">pistons</a> then each take turns, reading an instruction, executing it, and moving one step forward in the direction it&#39;s facing. When all <a href="https://github.com/sol-vin/pixel_lang_crystal/blob/master/src/pixel_lang_crystal/piston.cr">pistons</a> have run an instruction, that is called a cycle. The instruction type (known as a Control Code or CC) is determined by the upper 4 bits of the color of the pixel, the arguments for the instruction (known as the Control Value or CV) are the bottom 20 bits of the pixel&#39;s color.</p>
<p>The full instruction list is as follows.</p>
<ul>
  <li>0x0 - <a href="https://github.com/sol-vin/pixel_lang_crystal/blob/master/src/pixel_lang_crystal/dev/helpers/color_docs/00_end.cr">End</a></li>
  <li>0x1 - <a href="https://github.com/sol-vin/pixel_lang_crystal/blob/master/src/pixel_lang_crystal/dev/helpers/color_docs/01_start.cr">Start</a></li>
  <li>0x2 - <a href="https://github.com/sol-vin/pixel_lang_crystal/blob/master/src/pixel_lang_crystal/dev/helpers/color_docs/02_pause.cr">Pause</a></li>
  <li>0x3 - <a href="https://github.com/sol-vin/pixel_lang_crystal/blob/master/src/pixel_lang_crystal/dev/helpers/color_docs/03_direction.cr">Direction</a></li>
  <li>0x4 - <a href="https://github.com/sol-vin/pixel_lang_crystal/blob/master/src/pixel_lang_crystal/dev/helpers/color_docs/04_fork.cr">Fork</a></li>
  <li>0x5 - <a href="https://github.com/sol-vin/pixel_lang_crystal/blob/master/src/pixel_lang_crystal/dev/helpers/color_docs/05_jump.cr">Jump</a></li>
  <li>0x6 - <a href="https://github.com/sol-vin/pixel_lang_crystal/blob/master/src/pixel_lang_crystal/dev/helpers/color_docs/06_call.cr">Call</a></li>
  <li>0x7 - <a href="https://github.com/sol-vin/pixel_lang_crystal/blob/master/src/pixel_lang_crystal/dev/helpers/color_docs/07_return.cr">Return</a></li>
  <li>0x8 - <a href="https://github.com/sol-vin/pixel_lang_crystal/blob/master/src/pixel_lang_crystal/dev/helpers/color_docs/08_insert.cr">Insert</a></li>
  <li>0x9 - <a href="https://github.com/sol-vin/pixel_lang_crystal/blob/master/src/pixel_lang_crystal/dev/helpers/color_docs/09_move.cr">Move</a></li>
  <li>0xA - <a href="https://github.com/sol-vin/pixel_lang_crystal/blob/master/src/pixel_lang_crystal/dev/helpers/color_docs/10_arithmetic.cr">Arithmetic</a></li>
  <li>0xB - <a href="https://github.com/sol-vin/pixel_lang_crystal/blob/master/src/pixel_lang_crystal/dev/helpers/color_docs/11_output_char.cr">Output Char</a></li>
  <li>0xC - <a href="https://github.com/sol-vin/pixel_lang_crystal/blob/master/src/pixel_lang_crystal/dev/helpers/color_docs/12_conditional.cr">Conditional</a></li>
  <li>0xD - <a href="https://github.com/sol-vin/pixel_lang_crystal/tree/master/src/pixel_lang_crystal/dev/helpers/color_docs/13_instruction_meta">Instruction Meta</a></li>
  <li>0xE - <a href="https://github.com/sol-vin/pixel_lang_crystal/tree/master/src/pixel_lang_crystal/dev/helpers/color_docs/14_engine_meta">Engine Meta</a></li>
  <li>0xF - Blank</li>
</ul>
<p>Some example instructions 0xA00000 - Arithmetic(MA(0) + MA(0) -&gt; MA(0)) 0x100100 - Start(direction: up, priority: 0x100) 0x200010 - Pause(for 0x10 cycles)</p>
<p>A Piston is deleted when it reads an End instruction, and when an Engine has no more Pistons, it is no longer running.</p>
<p>Each Piston keeps track of a couple of things, it&#39;s current location, the values within it&#39;s own registers and memory, and a call stack (used with Call Return). The Piston has a total of 8 registers, which each hold a 20 bit integer, and each have special properties when read.</p>
<p>The MA register is one of the simpler registers, it takes a value that is written to it, and when read from provides the last value written to it. The default value of this register is always 0x0.</p>
<p>The MAV register is a little different. MAV is controlled by the MA register and when read from, provides the value in the Piston&#39;s memory at the location provided by MA. When written to it changes that memory&#39;s value. An uninitialized memory cell is always 0x0.</p>
<p>For example, if you wrote 0 to the MA register, then read from MAV you&#39;d get 0. If you wrote 1 to the MA register and then read from MAV you&#39;d get 0. If you wrote 333 to the MAV register and read from MAV you&#39;d get 333. If you wrote 0 to the MA register, then read from the MAV register, you&#39;d get 0 again.</p>
<p>The next two registers MB and MBV operate the same as MA and MAV, they even use the same memory pool, so if MA is equal to MB then MAV is always equal to MBV. MA and MB can both be used to reference two different values in the same Piston&#39;s memory. The MB register&#39;s default is 1.</p>
<p>The next two registers are S and SV which work similar to MA and MAV except the memory pool they use is static, meaning all pistons can access this to communicate with each other.</p>
<p>Next we have the I register, which acts like a stack. If written to, it adds a new value to the stack, when read from it pops from the stack. You can choose also to peek this register instead, keeping the value on the top of the stack.</p>
<p>Lastly we have the O register, which is an output register. When read from, it provides the last character that was output from any piston, when set, writes the value to output.</p>
<p>When pistons move off the edge of the program space, it appears on the other side, asteroids style.</p>
<p>That&#39;s really all there is to the internals of the interpreter, the rest is pretty easy.</p>
<p>There are two ways to interact with programs right now, there is the runner, and the web interface. I&#39;d highly recommend using the web interface, it&#39;s not bad to use, runs pretty smoothly, and allows you to watch the programs execute step by step.</p>
<p>To build the runner use <code>shards build runner</code></p>
<p>You can then run any program using <code>./bin/runner program_file &quot;input text!!!!!&quot;</code></p>
<p>You can run the web app by using <code>shards build web_app &amp;&amp; ./bin/web_app</code></p>
<p>We will primarily focus on the web_app, as it is a lot easier to work with than the runner.</p>
<center>
<img src="/images/pixellang/1.png" style="width: 100%; height: 100%;">
</center>
<p>You can create a new Engine with a program loaded using the bottom box on the home page, You must specify a name, and a program. When you open up a program it should look like below.</p>
<center>
<img src="/images/pixellang/2.png" style="width: 100%; height: 100%;">
</center>
<p>Pressing play will start an animation of the execution, showing the pistons moving and doing their work.</p>
<center>
<img src="/images/pixellang/primesieve.gif" style="width: 100%; height: 100%;">
</center>
<p>The above program is the prime sieve of Eratosthenes, which is a special way to filter prime numbers.</p>
<p>My other pride and joy program is the Ackermann function, I highly suggest checking it out.</p>
<p>If you want to write your own programs, any picture editor will do, as long as it supports hex color input (like #AABBCC). Pictures should be saved as PNG. To add them to the web interface, navigate to pixel_lang_crystal/programs and put your files in there, and then restart the web_app. I suggest Aseprite to edit any programs, as it has a useful palette feature to rip all the unique colors out of a picture.</p>
<p>The system also has a special way of helping make colors for you. For this, I would highly recommend opening crystal play in the pixel_lang_crystal directory and using that.</p>
<center>
<img src="/images/pixellang/3.png" style="width: 100%; height: 100%;">
</center>
<h2>Basic Instructions</h2>
<p>In this segment, we will cover some basic instructions, enough to make our own first Hello World program.</p>
<h3>Start</h3>
<p>The Start instruction is used to place pistons when starting the program. Each Start instruction can contain two arguments, what direction the Start is facing (up, down, left, right), and the priority, which describes in what order the pistons all run in. A piston with a priority of 0 runs before a piston with priority 100.</p>
<h3>End</h3>
<p>The End instruction removes a piston from the program space. If all pistons are gone off of the program space, the program has ended. Without an End instruction, a program will run indefinitely. End takes no arguments.</p>
<h3>Direction</h3>
<p>Direction changes the current direction the piston is going to one of 8, stored in it&#39;s arguments.</p>
<ul>
  <li>Up</li>
  <li>Down</li>
  <li>Left</li>
  <li>Right</li>
  <li>Turn Left</li>
  <li>Turn Right</li>
  <li>Reverse</li>
  <li>Straight (No operation)</li>
</ul>
<h3>Jump</h3>
<p>Jump moves a piston in the direction it&#39;s facing, a number of spaces determined by it&#39;s argument. (0x0 - 0xFFFFF).</p>
<p>For example, Jump 0 jumps only one space, Jump 1 jumps 2 spaces, etc etc.</p>
<p>Jumps that jump a piston off the program space wrap the piston back around.</p>
<h3>OutputChar</h3>
<p>Outputs the char defined in the arguments. For example, OutputChar H would be 0xB00048.</p>
<h3>Putting it all together</h3>
<p>Now we have all the instructions we need to try a Hello World program! Let&#39;s put them all together.</p>
<p>The only three instructions we need are Start, End, and OutputChar. We can use crystal play to mix all our colors for us.</p>
<center>
<img src="/images/pixellang/5.png" style="width: 100%; height: 100%;">
</center>
<p>Next we just need to put them all into a PNG, open up your favorite pixel art editor and let&#39;s go!</p>
<center>
<img src="/images/pixellang/6.png" style="width: 100%; height: 100%;">
</center>
<p>If we open up the file and play it in the web app, we can see the output works!</p>
<center>
<img src="/images/pixellang/7.png" style="width: 100%; height: 100%;">
</center>
]]></description>
      <content:encoded><![CDATA[<p>Today I&#39;m really excited to start a new series on pixel_lang, a pixel-based 2D esoteric language I wrote myself in Crystal. I&#39;ve always really loved esoteric languages, and they can teach us a lot about programming. I enjoy the aspect of honing one&#39;s programming chops, and esoteric languages are filled with all sorts of interesting challenges. My goal in writing an esoteric language was to make a language with a large instruction set, that could be used to make art, programs, or some combination of the two.</p>
<center>
<img src="/images/pixellang/ackermann.gif" style="width: 100%; height: 100%;">
</center>
<p>You can find all project files located on the <a href="https://github.com/sol-vin/pixel_lang_crystal">GitHub</a>.</p>
<p>The purpose of this article, is to give a basic introduction on how to use the <a href="https://github.com/sol-vin/pixel_lang_crystal">pixel_lang</a> interpreter, as well as the web interface, to load and run programs, as well as a basic explanation of how the system works.</p>
<p>The <a href="https://github.com/sol-vin/pixel_lang_crystal">pixel_lang</a> interpreter takes an input PNG file, and uses that as it&#39;s program code. Each pixel in the PNG is read in, and stored into a 2D array of instructions. Any and all PNG files are valid program code and can be used with the interpreter without error but, may not start without the presence of a Start instruction, or will run infinitely. A program can be given input, either by providing an input string argument, or via the live interactive session (yet to be written). This interpreter is called the <a href="https://github.com/sol-vin/pixel_lang_crystal/blob/master/src/pixel_lang_crystal/engine.cr">Engine</a>.</p>
<p><a href="https://github.com/sol-vin/pixel_lang_crystal/blob/master/src/pixel_lang_crystal/engine.cr">Engines</a> are comprised of a variable number of <a href="https://github.com/sol-vin/pixel_lang_crystal/blob/master/src/pixel_lang_crystal/piston.cr">pistons</a>. These <a href="https://github.com/sol-vin/pixel_lang_crystal/blob/master/src/pixel_lang_crystal/piston.cr">pistons</a> act as separate instruction readers and act mostly independently of each other, save for a few exceptions. The starting number of <a href="https://github.com/sol-vin/pixel_lang_crystal/blob/master/src/pixel_lang_crystal/piston.cr">pistons</a> is determined by a program code&#39;s number of Start instructions. The <a href="https://github.com/sol-vin/pixel_lang_crystal/blob/master/src/pixel_lang_crystal/piston.cr">pistons</a> then each take turns, reading an instruction, executing it, and moving one step forward in the direction it&#39;s facing. When all <a href="https://github.com/sol-vin/pixel_lang_crystal/blob/master/src/pixel_lang_crystal/piston.cr">pistons</a> have run an instruction, that is called a cycle. The instruction type (known as a Control Code or CC) is determined by the upper 4 bits of the color of the pixel, the arguments for the instruction (known as the Control Value or CV) are the bottom 20 bits of the pixel&#39;s color.</p>
<p>The full instruction list is as follows.</p>
<ul>
  <li>0x0 - <a href="https://github.com/sol-vin/pixel_lang_crystal/blob/master/src/pixel_lang_crystal/dev/helpers/color_docs/00_end.cr">End</a></li>
  <li>0x1 - <a href="https://github.com/sol-vin/pixel_lang_crystal/blob/master/src/pixel_lang_crystal/dev/helpers/color_docs/01_start.cr">Start</a></li>
  <li>0x2 - <a href="https://github.com/sol-vin/pixel_lang_crystal/blob/master/src/pixel_lang_crystal/dev/helpers/color_docs/02_pause.cr">Pause</a></li>
  <li>0x3 - <a href="https://github.com/sol-vin/pixel_lang_crystal/blob/master/src/pixel_lang_crystal/dev/helpers/color_docs/03_direction.cr">Direction</a></li>
  <li>0x4 - <a href="https://github.com/sol-vin/pixel_lang_crystal/blob/master/src/pixel_lang_crystal/dev/helpers/color_docs/04_fork.cr">Fork</a></li>
  <li>0x5 - <a href="https://github.com/sol-vin/pixel_lang_crystal/blob/master/src/pixel_lang_crystal/dev/helpers/color_docs/05_jump.cr">Jump</a></li>
  <li>0x6 - <a href="https://github.com/sol-vin/pixel_lang_crystal/blob/master/src/pixel_lang_crystal/dev/helpers/color_docs/06_call.cr">Call</a></li>
  <li>0x7 - <a href="https://github.com/sol-vin/pixel_lang_crystal/blob/master/src/pixel_lang_crystal/dev/helpers/color_docs/07_return.cr">Return</a></li>
  <li>0x8 - <a href="https://github.com/sol-vin/pixel_lang_crystal/blob/master/src/pixel_lang_crystal/dev/helpers/color_docs/08_insert.cr">Insert</a></li>
  <li>0x9 - <a href="https://github.com/sol-vin/pixel_lang_crystal/blob/master/src/pixel_lang_crystal/dev/helpers/color_docs/09_move.cr">Move</a></li>
  <li>0xA - <a href="https://github.com/sol-vin/pixel_lang_crystal/blob/master/src/pixel_lang_crystal/dev/helpers/color_docs/10_arithmetic.cr">Arithmetic</a></li>
  <li>0xB - <a href="https://github.com/sol-vin/pixel_lang_crystal/blob/master/src/pixel_lang_crystal/dev/helpers/color_docs/11_output_char.cr">Output Char</a></li>
  <li>0xC - <a href="https://github.com/sol-vin/pixel_lang_crystal/blob/master/src/pixel_lang_crystal/dev/helpers/color_docs/12_conditional.cr">Conditional</a></li>
  <li>0xD - <a href="https://github.com/sol-vin/pixel_lang_crystal/tree/master/src/pixel_lang_crystal/dev/helpers/color_docs/13_instruction_meta">Instruction Meta</a></li>
  <li>0xE - <a href="https://github.com/sol-vin/pixel_lang_crystal/tree/master/src/pixel_lang_crystal/dev/helpers/color_docs/14_engine_meta">Engine Meta</a></li>
  <li>0xF - Blank</li>
</ul>
<p>Some example instructions 0xA00000 - Arithmetic(MA(0) + MA(0) -&gt; MA(0)) 0x100100 - Start(direction: up, priority: 0x100) 0x200010 - Pause(for 0x10 cycles)</p>
<p>A Piston is deleted when it reads an End instruction, and when an Engine has no more Pistons, it is no longer running.</p>
<p>Each Piston keeps track of a couple of things, it&#39;s current location, the values within it&#39;s own registers and memory, and a call stack (used with Call Return). The Piston has a total of 8 registers, which each hold a 20 bit integer, and each have special properties when read.</p>
<p>The MA register is one of the simpler registers, it takes a value that is written to it, and when read from provides the last value written to it. The default value of this register is always 0x0.</p>
<p>The MAV register is a little different. MAV is controlled by the MA register and when read from, provides the value in the Piston&#39;s memory at the location provided by MA. When written to it changes that memory&#39;s value. An uninitialized memory cell is always 0x0.</p>
<p>For example, if you wrote 0 to the MA register, then read from MAV you&#39;d get 0. If you wrote 1 to the MA register and then read from MAV you&#39;d get 0. If you wrote 333 to the MAV register and read from MAV you&#39;d get 333. If you wrote 0 to the MA register, then read from the MAV register, you&#39;d get 0 again.</p>
<p>The next two registers MB and MBV operate the same as MA and MAV, they even use the same memory pool, so if MA is equal to MB then MAV is always equal to MBV. MA and MB can both be used to reference two different values in the same Piston&#39;s memory. The MB register&#39;s default is 1.</p>
<p>The next two registers are S and SV which work similar to MA and MAV except the memory pool they use is static, meaning all pistons can access this to communicate with each other.</p>
<p>Next we have the I register, which acts like a stack. If written to, it adds a new value to the stack, when read from it pops from the stack. You can choose also to peek this register instead, keeping the value on the top of the stack.</p>
<p>Lastly we have the O register, which is an output register. When read from, it provides the last character that was output from any piston, when set, writes the value to output.</p>
<p>When pistons move off the edge of the program space, it appears on the other side, asteroids style.</p>
<p>That&#39;s really all there is to the internals of the interpreter, the rest is pretty easy.</p>
<p>There are two ways to interact with programs right now, there is the runner, and the web interface. I&#39;d highly recommend using the web interface, it&#39;s not bad to use, runs pretty smoothly, and allows you to watch the programs execute step by step.</p>
<p>To build the runner use <code>shards build runner</code></p>
<p>You can then run any program using <code>./bin/runner program_file &quot;input text!!!!!&quot;</code></p>
<p>You can run the web app by using <code>shards build web_app &amp;&amp; ./bin/web_app</code></p>
<p>We will primarily focus on the web_app, as it is a lot easier to work with than the runner.</p>
<center>
<img src="/images/pixellang/1.png" style="width: 100%; height: 100%;">
</center>
<p>You can create a new Engine with a program loaded using the bottom box on the home page, You must specify a name, and a program. When you open up a program it should look like below.</p>
<center>
<img src="/images/pixellang/2.png" style="width: 100%; height: 100%;">
</center>
<p>Pressing play will start an animation of the execution, showing the pistons moving and doing their work.</p>
<center>
<img src="/images/pixellang/primesieve.gif" style="width: 100%; height: 100%;">
</center>
<p>The above program is the prime sieve of Eratosthenes, which is a special way to filter prime numbers.</p>
<p>My other pride and joy program is the Ackermann function, I highly suggest checking it out.</p>
<p>If you want to write your own programs, any picture editor will do, as long as it supports hex color input (like #AABBCC). Pictures should be saved as PNG. To add them to the web interface, navigate to pixel_lang_crystal/programs and put your files in there, and then restart the web_app. I suggest Aseprite to edit any programs, as it has a useful palette feature to rip all the unique colors out of a picture.</p>
<p>The system also has a special way of helping make colors for you. For this, I would highly recommend opening crystal play in the pixel_lang_crystal directory and using that.</p>
<center>
<img src="/images/pixellang/3.png" style="width: 100%; height: 100%;">
</center>
<h2>Basic Instructions</h2>
<p>In this segment, we will cover some basic instructions, enough to make our own first Hello World program.</p>
<h3>Start</h3>
<p>The Start instruction is used to place pistons when starting the program. Each Start instruction can contain two arguments, what direction the Start is facing (up, down, left, right), and the priority, which describes in what order the pistons all run in. A piston with a priority of 0 runs before a piston with priority 100.</p>
<h3>End</h3>
<p>The End instruction removes a piston from the program space. If all pistons are gone off of the program space, the program has ended. Without an End instruction, a program will run indefinitely. End takes no arguments.</p>
<h3>Direction</h3>
<p>Direction changes the current direction the piston is going to one of 8, stored in it&#39;s arguments.</p>
<ul>
  <li>Up</li>
  <li>Down</li>
  <li>Left</li>
  <li>Right</li>
  <li>Turn Left</li>
  <li>Turn Right</li>
  <li>Reverse</li>
  <li>Straight (No operation)</li>
</ul>
<h3>Jump</h3>
<p>Jump moves a piston in the direction it&#39;s facing, a number of spaces determined by it&#39;s argument. (0x0 - 0xFFFFF).</p>
<p>For example, Jump 0 jumps only one space, Jump 1 jumps 2 spaces, etc etc.</p>
<p>Jumps that jump a piston off the program space wrap the piston back around.</p>
<h3>OutputChar</h3>
<p>Outputs the char defined in the arguments. For example, OutputChar H would be 0xB00048.</p>
<h3>Putting it all together</h3>
<p>Now we have all the instructions we need to try a Hello World program! Let&#39;s put them all together.</p>
<p>The only three instructions we need are Start, End, and OutputChar. We can use crystal play to mix all our colors for us.</p>
<center>
<img src="/images/pixellang/5.png" style="width: 100%; height: 100%;">
</center>
<p>Next we just need to put them all into a PNG, open up your favorite pixel art editor and let&#39;s go!</p>
<center>
<img src="/images/pixellang/6.png" style="width: 100%; height: 100%;">
</center>
<p>If we open up the file and play it in the web app, we can see the output works!</p>
<center>
<img src="/images/pixellang/7.png" style="width: 100%; height: 100%;">
</center>
<hr style="margin-top: 2rem; margin-bottom: 1rem; border: none; border-top: 1px solid #ccc;" />
<div class="rss-entry-metadata" style="font-size: 0.9em; line-height: 1.5; background: #faf6ee; color: #1c1c1e; padding: 0.85rem; border: 1px solid #1c1c1e; border-radius: 4px;">
  <p style="margin: 0.25rem 0;"><strong>Category Chain:</strong> <a href="https://sol.vin/pixellang/">pixel_lang</a></p>
  <p style="margin: 0.25rem 0;"><strong>Date:</strong> 2019-09-05</p>
  <p style="margin: 0.25rem 0;"><strong>Author:</strong> Ian Rash</p>
  <p style="margin: 0.5rem 0 0.25rem 0;"><strong>Skills &amp; Technologies:</strong></p>
  <ul style="margin: 0.25rem 0 0 1.25rem; padding: 0;">
    <li><strong>Crystal</strong> (<em>Languages</em>) &bull; 8 years &mdash; A fast, compiled, statically typed language with Ruby-inspired syntax. [<a href="https://crystal-lang.org">Website</a> | <a href="https://github.com/crystal-lang/crystal">Github</a>]</li>
    <li><strong>Esoteric Programming</strong> (<em>Languages</em>) &bull; 3 years &mdash; Designing non-traditional programming languages to test boundaries of language design and visual computing. [<a href="https://en.wikipedia.org/wiki/Esoteric_programming_language">Wikipedia</a>]</li>
    <li><strong>Generative Art</strong> (<em>Design &amp; Art</em>) &bull; 5 years &mdash; Algorithmic generation of visual artwork, procedural textures, vector SVG patterns, and game graphics. [<a href="https://en.wikipedia.org/wiki/Generative_art">Wikipedia</a>]</li>
    <li><strong>Raylib</strong> (<em>Libraries &amp; Frameworks</em>) &bull; 5 years &mdash; A simple and easy-to-use C library to enjoy videogames programming. [<a href="https://www.raylib.com">Website</a> | <a href="https://github.com/raysan5/raylib">Github</a>]</li>
  </ul>
</div>
]]></content:encoded>
    </item>
  </channel>
</rss>
