
<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>kometbomb</title>
	<atom:link href="http://kometbomb.net/feed/" rel="self" type="application/rss+xml" />
	<link>http://kometbomb.net</link>
	<description>Programming and stuff.</description>
	<lastBuildDate>Mon, 15 May 2017 13:54:23 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.2.9</generator>
	<item>
		<title>Maps in MICRO MURDER (but it&#8217;s PICO-8 so it&#8217;s hard)</title>
		<link>http://kometbomb.net/2017/04/20/maps-in-micro-murder-but-its-pico-8-so-its-hard/</link>
					<comments>http://kometbomb.net/2017/04/20/maps-in-micro-murder-but-its-pico-8-so-its-hard/#comments</comments>
		
		<dc:creator><![CDATA[kometbomb]]></dc:creator>
		<pubDate>Thu, 20 Apr 2017 17:41:53 +0000</pubDate>
				<category><![CDATA[Games]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[pico-8]]></category>
		<guid isPermaLink="false">http://kometbomb.net/?p=1110</guid>

					<description><![CDATA[MICRO MURDER: But It&#8217;s Robots So It&#8217;s OK has a deformable map (that is, you can dig holes in it) that spans multiple screens and all the collisions seem to be per pixel &#8211; the holes on the map are not limited to tile boundaries and can be of any radius (and theoretically any shape). [&#8230;]]]></description>
										<content:encoded><![CDATA[<p><center><iframe loading="lazy" frameborder="0" src="https://itch.io/embed/130935" width="552" height="167"></iframe></center></p>
<p><strong><a href="http://kometbomb.net/games/micro-murder-but-its-robots-so-its-ok/">MICRO MURDER: But It&#8217;s Robots So It&#8217;s OK</a></strong> has a deformable map (that is, you can dig holes in it) that spans multiple screens and all the collisions seem to be per pixel &#8211; the holes on the map are not limited to tile boundaries and can be of any radius (and theoretically any shape). On a modern platform (or, even a platfrom from past, as in the original <em>Worms</em> was an Amiga game) it would be a very simple task: store the whole map in memory as a huge bitmap and read and write from it as you please.</p>
<p>On a PICO-8 this is a bit more complicated task: the machine doesn&#8217;t have enough memory for having much more than a single screen&#8217;s (128&#215;128) worth of pixels in an array and even if it did, it would be very slow to draw pixel by pixel from the array to the screen memory. </p>
<p>Instead, we need to combine a few things, old and new, and apply a liberal amount of smoke and mirrors.</p>
<h3>Checking for pixels</h3>
<p>We start the collision checking by simply using the map. Using mget() to check for tiles is of course pretty much PICO-8 101 stuff and we can add a single step to also check pixel inside the tile:</p>
<pre class="brush: cpp; title: ; notranslate">function checkpixel(x, y)
 -- transform screen coordinates to tile
 -- coordinates (8x8 tiles)
 x = x / 8
 y = y / 8

 local tile = mget(x, y)

 if tile == 0 then
  -- the tile is not set so we know
  -- there will be no pixels
  return false
 end

 -- manually check if the pixel
 -- inside the map tile is non-zero

 -- 1. find out the pixel coordinate inside 
 -- the tile. it's what's after the decimal dot
 -- scaled to tile size (8x8 pixels)

 local sx = (x - flr(x)) * 8
 local sy = (y - flr(y)) * 8

 -- 2. find out the top-left corner of the tile
 -- inside sprite memory

 local tx = tile % 16 * 8
 local ty = flr(tile / 16) * 8

 if sget(sx + tx, sy + ty) == 0 then
   -- the pixel was zero
   return false
 end

 -- there were no empty pixels
 -- so it was a hit!

 return true
end
</pre>
<p>We can now easily check every pixel inside the map. But, how do we edit the map pixel per pixel? It&#8217;s quite simple:<br />
we just store all the holes (circles) made by projectiles and separately check if the coordinate is inside the hole.</p>
<pre class="brush: cpp; title: ; notranslate">function checkhole(x, y)
 for hole in all(holes) do
  local dx = x - hole.x
  local dy = y - hole.y
  if dx * dx + dy * dy &lt;= hole.r * hole.r then
   return true
  end
 end
 return false
end
</pre>
<p>If we found a pixel that isn&#8217;t inside a hole, the projectile explodes and we simply add a new hole at the coordinates (with a variable radius).</p>
<p>So, here&#8217;s the whole thing in short:</p>
<ol>
<li>Check for if there&#8217;s a tile at the coordinate</li>
<li>Check if the coordinate is inside a hole</li>
<li>Check if the tile has a pixel at the &#8220;sub-tile coordinate&#8221;</li>
</ol>
<div id="attachment_1122" style="width: 266px" class="wp-caption aligncenter"><img aria-describedby="caption-attachment-1122" decoding="async" loading="lazy" src="http://kometbomb.net/wp-content/uploads/2017/04/PICO-8_123.gif" alt="" width="256" height="256" class="size-full wp-image-1122" /><p id="caption-attachment-1122" class="wp-caption-text">Holes are drawn as white circle outlines instead of filled black circles</p></div>
<p>Note that in the above screenshot also tiles that are fully inside holes are set to empty for speed (we don&#8217;t need to check for the individual pixels because we know the whole tile is destroyed).</p>
<pre class="brush: cpp; title: ; notranslate">if checkpixel(projectile.x, projectile.y) and 
 not checkhole(projectile.x, projectile.y) then
 -- BOOM!
 add(holes, {x=projectile.x, y=projectile.y, radius=10})
end
</pre>
<p>For speed, you might want to experiment by changing the order of the checks, depending on exact circumstances. Also, you will want to use a more efficient way to store the holes if you have thousands of them.</p>
<h3>Bouncy bombs</h3>
<p>In <strong>MM:BIRSIO</strong>, there are projectiles that collide with the map and seem to bounce quite accurately according to the slope at the collision point. How to find out the angle from the map pixels? </p>
<p>This is easy: you can get a normal vector by scanning the pixels surrounding the collision point and building a vector that is the sum of the vector pointing from the collision point to the scanned pixel: </p>
<pre class="brush: cpp; title: ; notranslate">-- dx,dy = normal vector at collision point
local dy=0
local dx=0

-- scan the surrounding area, 2 pixels to any direction
for sy=-2,2 do
 for sx=-2,2 do
  if not checkpixel(collision_point.x + sx,collision_point.y + sy) then
   -- found an empty pixel, add vector sx,sy to dx,dy
   dx += sx
   dy += sy
  end
 end
end

-- normalize dx,dy
local d = sqrt(dx * dx + dy * dy)
dx /= d
dy /= d

-- proceed with the usual reflection vector 
-- calculations etc.
-- ...
</pre>
<p>This is of course just an approximation but it works perfectly fine for our purposes. And, in case of collisions, the ground probably is uneven and has tiny rocks and so on so the bounce would not be mathematically perfect.</p>
<h3>Drawing the map</h3>
<p>You have probably realized that we have a tiny problem if we draw the map on screen like this (assuming a black background):</p>
<pre class="brush: cpp; title: ; notranslate">cls()

-- draw the untouched, original tiles
map()

-- draw the holes over the tiles
for hole in all(holes) do
 circfill(hole.x, hole.y, hole.radius, 0)
end
</pre>
<p>The above code will draw the map and holes correctly but you are now limited to a plain black background. If you draw a background before drawing the map over it, as you usually would, the holes would clearly be just black circles stamped against the background. This would ruin the illusion of having a huge, per pixel map.</p>
<p>In <strong>MM:BIRSIO</strong>, we simply add more smoke: instead of having some magic to make the holes somehow invisible, the starfield is drawn after the map &#8211; we manually check the pixel color and decide if the star would be behind the map or visible. This trick would probably be too slow for a full background (drawn pixel by pixel) but for a handful of pixels it&#8217;s perfectly fine.</p>

<div class="wp_rp_wrap  wp_rp_plain" id="wp_rp_first"><div class="wp_rp_content"><h3 class="related_post_title">You might also like...</h3><ul class="related_post wp_rp"><li data-position="0" data-poid="in-1074" data-post-type="empty" ><a href="http://kometbomb.net/2017/03/10/how-levels-are-generated-in-spaceman-8/" class="wp_rp_title">How levels are generated in Spaceman 8</a></li><li data-position="1" data-poid="in-933" data-post-type="empty" ><a href="http://kometbomb.net/2016/04/03/how-does-pico-racer-work/" class="wp_rp_title">How does Pico Racer work?</a></li><li data-position="2" data-poid="in-226" data-post-type="empty" ><a href="http://kometbomb.net/2008/03/19/ideas-for-blogs/" class="wp_rp_title">Ideas for Blogs</a></li><li data-position="3" data-poid="in-135" data-post-type="empty" ><a href="http://kometbomb.net/2007/11/17/viewer2-build-3782/" class="wp_rp_title">Viewer2 Build 3782</a></li><li data-position="4" data-poid="in-205" data-post-type="empty" ><a href="http://kometbomb.net/2008/02/29/travis-bickle-superhero/" class="wp_rp_title">Travis Bickle, Superhero</a></li></ul></div></div>
]]></content:encoded>
					
					<wfw:commentRss>http://kometbomb.net/2017/04/20/maps-in-micro-murder-but-its-pico-8-so-its-hard/feed/</wfw:commentRss>
			<slash:comments>2</slash:comments>
		
		
			</item>
		<item>
		<title>How levels are generated in Spaceman 8</title>
		<link>http://kometbomb.net/2017/03/10/how-levels-are-generated-in-spaceman-8/</link>
		
		<dc:creator><![CDATA[kometbomb]]></dc:creator>
		<pubDate>Fri, 10 Mar 2017 21:01:56 +0000</pubDate>
				<category><![CDATA[Games]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[pico-8]]></category>
		<category><![CDATA[Procedural generation]]></category>
		<guid isPermaLink="false">http://kometbomb.net/?p=1074</guid>

					<description><![CDATA[All levels in Spaceman 8 are procedurally generated and get larger and more complicated as the game progresses. PICO-8 has technical limitations so the map generator has to be relatively simple. The level generator works in two steps: first by generating the general structure of the level and then adding superficial details on the map [&#8230;]]]></description>
										<content:encoded><![CDATA[<p>All levels in <a href="https://tictactoad.itch.io/spaceman8">Spaceman 8</a> are procedurally generated and get larger and more complicated as the game progresses. PICO-8 has technical limitations so the map generator has to be relatively simple. The level generator works in two steps: first by generating the general structure of the level and then adding superficial details on the map that is eventually drawn on the screen. The map contains randomly placed objects that are often found in the ends of the map corridors.</p>
<h3>The seed map</h3>
<p>The seed map has two types of cells: &#8220;open&#8221; and &#8220;closed&#8221; cells. Map is initialized with closed cells.<br />
All level objects (the collectables and the exits) are treated similarly.</p>
<ol>
<li>Start with single open cell in the center of the map</li>
<li>
Position all objects in the starting cell</li>
<li>Pick a random cell on the map using these rules:
<ul>
<li> The cell has to be closed</li>
<li>Zero to one diagonal (NW, NE, SE, SW) neighbors have to be open</li>
<li>1 or 2 cardinal (N, E, S, W) neighbors have to be open</li>
</ul>
</li>
<li>
Change the cell type open and move an object from any of the neighboring cells or a randomly picked object in the new open cell</li>
<li>Repeat from step 3 until map is large enough</li>
</ol>
<p><img decoding="async" loading="lazy" src="http://kometbomb.net/wp-content/uploads/2017/03/PICO-8_77.gif" alt="" width="256" height="256" class="aligncenter size-full wp-image-1082" /></p>
<p><center><span class="ffs-bs"><a href="http://www.lexaloffle.com/bbs/?tid=28947" class="btn btn-large " style="color:#fff;" ><span class="ffs-icon-container left"><i class="fa fa-play"></i></span>Demo cart and code</a></span></center></p>
<p>You now have a branching, mazelike map that has all open cells connected at least from one direction. The objects should be positioned (mostly) in the ends of the corridors, further from the starting position (this of course depends on luck and you should fiddle with it if you want to make sure the object locations are always challenging).</p>
<h3>Making it pretty</h3>
<p>The map is upscaled so that each cell now takes twice the cells vertically and horizontally. There is a random change that a cell flips its state if the neighboring cell is of the opposite type. The resizing is done again and again so that the level corridors are suitably wide (at first they are only one tile wide, then two, four etc.). The randomness from the resizing steps carries over and adds first large and then (relatively) smaller random variation to the edges.</p>
<p>The visible map is built from the data using a tileset that has tiles for different edge/side combinations. </p>
<p>The seed map is scanned cell-by-cell and if the current tile is closed, a bitmask is built from the four neighboring seed tiles in the cardinal directions (see the linked cart for working code). The bitmask tells us the tile we want on the visible map. E.g. if all neighboring seed tiles are closed, the bitmask will be binary) 1111b = 15, we know we want to use tile 15 which is a fully filled tile. If one of the sides is open, let&#8217;s say to the east, the mask will be 1101b = 13 and we will use tile 13. </p>
<p>If the current seed tile is empty, the visible map will simply have an empty cell. All of this is very easy to implement when just following instructions (basically just make sure the tile order is the same and it will work) but here is <a href="https://gamedevelopment.tutsplus.com/tutorials/how-to-use-tile-bitmasking-to-auto-tile-your-level-layouts--cms-25673">a good article about the technique</a> in case you want more details.</p>
<p><img decoding="async" loading="lazy" src="http://kometbomb.net/wp-content/uploads/2017/03/PICO-8_79.gif" alt="" width="256" height="256" class="aligncenter size-full wp-image-1085" /></p>
<p><center><span class="ffs-bs"><a href="http://www.lexaloffle.com/bbs/?tid=28948" class="btn btn-large " style="color:#fff;" ><span class="ffs-icon-container left"><i class="fa fa-play"></i></span>Demo cart and code</a></span></center></p>
<p>Finally, the visible map has some random variations added on it: empty cells have a random change to have a non-black background tile and the fully filled tiles have a random change to have a pebble tile and so on. This randomness doesn&#8217;t change the level geometry.</p>

<div class="wp_rp_wrap  wp_rp_plain" ><div class="wp_rp_content"><h3 class="related_post_title">You might also like...</h3><ul class="related_post wp_rp"><li data-position="0" data-poid="ex-in_933" data-post-type="own_sourcefeed" ><a href="http://kometbomb.net/2016/04/03/how-does-pico-racer-work/" class="wp_rp_title">How does Pico Racer work?</a></li><li data-position="1" data-poid="ex-in_190" data-post-type="own_sourcefeed" ><a href="http://kometbomb.net/2008/02/22/generating-game-content/" class="wp_rp_title">Generating game content</a></li><li data-position="2" data-poid="ex-in_223" data-post-type="own_sourcefeed" ><a href="http://kometbomb.net/2008/03/18/more-generated-game-content/" class="wp_rp_title">More generated game content</a></li><li data-position="3" data-poid="in-1110" data-post-type="empty" ><a href="http://kometbomb.net/2017/04/20/maps-in-micro-murder-but-its-pico-8-so-its-hard/" class="wp_rp_title">Maps in MICRO MURDER (but it&#8217;s PICO-8 so it&#8217;s hard)</a></li><li data-position="4" data-poid="in-234" data-post-type="empty" ><a href="http://kometbomb.net/2008/03/25/some-cool-demoscene-stuff/" class="wp_rp_title">Some Cool Demoscene Stuff</a></li></ul></div></div>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Let&#8217;s add the same CSS class to all cookie warning popups</title>
		<link>http://kometbomb.net/2016/08/26/lets-add-the-same-css-class-to-all-cookie-warning-popups/</link>
		
		<dc:creator><![CDATA[kometbomb]]></dc:creator>
		<pubDate>Fri, 26 Aug 2016 16:47:17 +0000</pubDate>
				<category><![CDATA[Nonsense]]></category>
		<guid isPermaLink="false">http://kometbomb.net/?p=1035</guid>

					<description><![CDATA[A proposal: let&#8217;s all just decide to use a specific CSS class on all cookie warning popups from this point onwards. Something like .eu-cookie-warning-popup. What are cookie warning popups? In the EU, it is mandatory to point the fact that a website might use cookies to track the users of the website. When visiting a [&#8230;]]]></description>
										<content:encoded><![CDATA[<p>A proposal: let&#8217;s all just decide to use a specific CSS class on all cookie warning popups from this point onwards. </p>
<p>Something like <em><strong>.eu-cookie-warning-popup</strong></em>.</p>
<p><span id="more-1035"></span></p>
<h4>What are cookie warning popups?</h4>
<p>In the EU, <a href="http://ec.europa.eu/ipg/basics/legal/cookies/index_en.htm">it is mandatory to point the fact that a website might use cookies to track the users of the website</a>. When visiting a website, you will usually always get a hovering popup that mentions this fact. Like this:</p>
<p><img decoding="async" src="http://ec.europa.eu/ipg/images/cookie-consent_en.jpg" /></p>
<p>The HTML for the popup might be something like this:</p>
<p><code>&lt;div class="eu-cookie-warning-popup"&gt;<br />
  &lt;p&gt;This site uses cookies ...&lt;/p&gt;<br />
  &lt;button&gt;Close popup&lt;/button&gt;<br />
&lt;/div&gt;</code></p>
<p>Usually, the popups will cover the page elements or just use precious screen space. The sites often show this popup on every visit, which might be several times a day. Which gets quite annoying.</p>
<h4>Why add a CSS class?</h4>
<p>If all popups have a class with the same name, e.g. <kbd>.eu-cookie-warning-popup</kbd>, people can then use whatever tool they want (user styles, Greasemonkey etc.) to automatically stop the popups showing. This class should be added to the main popup element so that when you apply this style&#8230;</p>
<p><code>.eu-cookie-warning-popup {<br />
  display: none !important;<br />
}</code></p>
<p>&#8230; the user will never know the page wanted to display the popup. You essentially <em>enhance the site usability with minimal effort</em> for any site.</p>
<h4>Isn&#8217;t the warning there for a reason?</h4>
<p>Anyone who knows how to hide page elements by using user styles or scripts pretty much knows what you can do with cookies (that is, nothing dangerous that you couldn&#8217;t also do without using cookies) and would close the popup without even reading the contents.</p>

<div class="wp_rp_wrap  wp_rp_plain" ><div class="wp_rp_content"><h3 class="related_post_title">You might also like...</h3><ul class="related_post wp_rp"><li data-position="0" data-poid="in-725" data-post-type="none" ><a href="http://kometbomb.net/2010/03/11/ahx-import-in-klystrack-1-4-0/" class="wp_rp_title">AHX Import in klystrack 1.4</a></li><li data-position="1" data-poid="in-767" data-post-type="none" ><a href="http://kometbomb.net/2011/01/02/lossless-audio-compression/" class="wp_rp_title">Lossless Audio Compression</a></li><li data-position="2" data-poid="in-31" data-post-type="none" ><a href="http://kometbomb.net/2007/05/07/viewer2-build-1089/" class="wp_rp_title">Viewer2 Build 1089</a></li><li data-position="3" data-poid="in-317" data-post-type="none" ><a href="http://kometbomb.net/2008/07/23/collision-detection-with-occlusion-queries-redux/" class="wp_rp_title">Collision Detection with Occlusion Queries Redux</a></li><li data-position="4" data-poid="in-102" data-post-type="none" ><a href="http://kometbomb.net/2007/09/12/conscience-cleared/" class="wp_rp_title">Conscience Cleared?</a></li></ul></div></div>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>How does Pico Racer work?</title>
		<link>http://kometbomb.net/2016/04/03/how-does-pico-racer-work/</link>
		
		<dc:creator><![CDATA[kometbomb]]></dc:creator>
		<pubDate>Sun, 03 Apr 2016 10:04:39 +0000</pubDate>
				<category><![CDATA[Games]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[gamedev]]></category>
		<category><![CDATA[pico-8]]></category>
		<guid isPermaLink="false">http://kometbomb.net/?p=933</guid>

					<description><![CDATA[After I released Pico Racer, lots of people have thought it looks nice and is an achievement. I don&#8217;t think it does anything special or pushes the limits of the Pico-8. Here I try to explain the small tricks I used in the game. If you want a general tutorial about pseudo 3D racers in [&#8230;]]]></description>
										<content:encoded><![CDATA[<p>After I released <a href="https://kometbomb.itch.io/pico-racer">Pico Racer</a>, lots of people have thought it looks nice and is an achievement. I don&#8217;t think it does anything special or pushes the limits of the Pico-8. Here I try to explain the small tricks I used in the game. If you want a general tutorial about pseudo 3D racers in general then please check out <a href="http://www.extentofthejam.com/pseudo/">Louis Gorenfeld&#8217;s excellent page about the subject</a>, I try to focus on Pico-8 specific stuff.</p>
<p><ol class="toc-generator"><li class="heading-2 selected"><a href="#toc-road-rendering" title="Jump to Road rendering">Road rendering</a></li><li class="heading-2"><a href="#toc-sprite-rendering" title="Jump to Sprite rendering">Sprite rendering</a></li><li class="heading-3"><a href="#toc-car-rendering-and-sprite-perspective" title="Jump to Car rendering and sprite perspective">Car rendering and sprite perspective</a></li><li class="heading-2"><a href="#toc-night-levels-and-color-fades" title="Jump to Night levels and color fades">Night levels and color fades</a></li><li class="heading-2"><a href="#toc-pico-8-performance" title="Jump to Pico-8 performance">Pico-8 performance</a></li></ol></p>
<h2 id="toc-road-rendering">Road rendering</h2>
<p>Usually, with pseudo 3D racers, the road is drawn using a simple trick: there is a full screen graphic of a straight road with perspective and every horizontal line gets shifted left or right, more the further down the road the current horizontal line is. This makes the road look like it&#8217;s curving. Palette tricks are used to create the familiar stripes that give an illusion of motion. </p>
<p>With Pico-8, there is no space for a precalculated road asset but we can draw scaled sprites instead. The road in Pico Racer is simply a series of one pixel high sprites scaled by distance, one for both track edges and two used to draw the road surface. The road is a true textured plane instead of a distorted image. Curves works similarly to the above classic method.</p>
<p>Additionally, when rendering the road (from bottom of the screen to the middle of the screen) we iterate along the track data. This is very approximate because we just take the screen Y, calculate the Z and figure out which part of the track the horizontal line belongs to. A more accurate way would be to iterate Z instead of the screen space Y and when Z projected to the screen gives a different screen Y coordinate, we would draw the horizontal line. But going along Y gives a good enough effect, the player will get a good enough hint what is coming towards him. </p>
<p>The road X position on screen is stored for each Y coordinate which we will use later to render the sprites correctly along the road. Note: this gives a slightly crude motion to sprites when they are far away because the X offset are stored per each screen Y coordinate instead of Z. As long as the action is fast, the player will not notice anything.</p>
<p>The road texture graphic used per line is selected so that the further away the line is, the lighter the colors in the texture. Dithering is used to mask the exact position where the texture changes. </p>
<div id="attachment_956" style="width: 590px" class="wp-caption aligncenter"><img aria-describedby="caption-attachment-956" decoding="async" loading="lazy" src="http://kometbomb.net/wp-content/uploads/2016/04/PICO-8_2.png" alt="One texture" width="580" height="540" class="size-full wp-image-956" srcset="http://kometbomb.net/wp-content/uploads/2016/04/PICO-8_2.png 580w, http://kometbomb.net/wp-content/uploads/2016/04/PICO-8_2-250x233.png 250w, http://kometbomb.net/wp-content/uploads/2016/04/PICO-8_2-430x400.png 430w" sizes="(max-width: 580px) 100vw, 580px" /><p id="caption-attachment-956" class="wp-caption-text">One texture</p></div>
<div id="attachment_955" style="width: 590px" class="wp-caption aligncenter"><img aria-describedby="caption-attachment-955" decoding="async" loading="lazy" src="http://kometbomb.net/wp-content/uploads/2016/04/PICO-8_1.png" alt="Multiple textures" width="580" height="540" class="size-full wp-image-955" srcset="http://kometbomb.net/wp-content/uploads/2016/04/PICO-8_1.png 580w, http://kometbomb.net/wp-content/uploads/2016/04/PICO-8_1-250x233.png 250w, http://kometbomb.net/wp-content/uploads/2016/04/PICO-8_1-430x400.png 430w" sizes="(max-width: 580px) 100vw, 580px" /><p id="caption-attachment-955" class="wp-caption-text">Multiple textures</p></div>
<div id="attachment_954" style="width: 590px" class="wp-caption aligncenter"><img aria-describedby="caption-attachment-954" decoding="async" loading="lazy" src="http://kometbomb.net/wp-content/uploads/2016/04/PICO-8_0.png" alt="Dithered textures" width="580" height="540" class="size-full wp-image-954" srcset="http://kometbomb.net/wp-content/uploads/2016/04/PICO-8_0.png 580w, http://kometbomb.net/wp-content/uploads/2016/04/PICO-8_0-250x233.png 250w, http://kometbomb.net/wp-content/uploads/2016/04/PICO-8_0-430x400.png 430w" sizes="(max-width: 580px) 100vw, 580px" /><p id="caption-attachment-954" class="wp-caption-text">Dithered textures</p></div>
<p>This is done because of two reasons: in nature, colors get lighter the further away something is (actually, tint to sky blue beacuse there is air between you and the faraway object) and also so that the road sides and lane markings won&#8217;t strobe as much.</p>
<div id="attachment_949" style="width: 266px" class="wp-caption aligncenter"><img aria-describedby="caption-attachment-949" decoding="async" loading="lazy" src="http://kometbomb.net/wp-content/uploads/2016/04/PICO-8_5.gif" alt="PICO-8_5" width="256" height="256" class="aligncenter size-full wp-image-949" /><p id="caption-attachment-949" class="wp-caption-text">Lots of flicker</p></div>
<div id="attachment_950" style="width: 266px" class="wp-caption aligncenter"><img aria-describedby="caption-attachment-950" decoding="async" loading="lazy" src="http://kometbomb.net/wp-content/uploads/2016/04/PICO-8_6.gif" alt="Less flicker" width="256" height="256" class="size-full wp-image-950" /><p id="caption-attachment-950" class="wp-caption-text">Less flicker</p></div>
<h2 id="toc-sprite-rendering">Sprite rendering</h2>
<p>Sprites are rendered basically using the same idea as for the horizontal road lines. First, Z is used to determine the zoom factor. Secondly, sprite X position (on screen) is divided by Z and the road offset for the sprite screen Y coordinate is used to offset the sprites so that they are arranged along the road.</p>
<h3 id="toc-car-rendering-and-sprite-perspective">Car rendering and sprite perspective</h3>
<p>There is one very important and unavoidable problem with sprites and 3D: the sprites always face the camera. This is not a problem with orthogonal 2D projection, since there is only one way the camera looks at. Everything is on one flat plane. But with a perspective projection the sprites start to look like they are always rotated to face the camera unless you take the time and draw multiple versions of the sprite from different angles. This is how Origin&#8217;s <em>Wing Commander</em> and Lucasarts&#8217; <em>Their Finest Hour</em> work. But this takes a lot of effort and more importantly: it needs a lot of space for the sprites.</p>
<p>In Pico Racer, sprite perspective is handled so that most sprites (trees, warning signs) have no perspective. This works reasonably well due to two facts: the objects are two-dimensional (warning signs) AND they are always located to the sides so that the angle to them would be pretty much the same at all times. Only the player car and the opponent cars have visible perspective, since that&#8217;s what you look at the most. Also, the cars (especially the player car) have a lot of sideways motion which would immediately make the cars&#8217; perspective look odd. </p>
<p><div id="attachment_941" style="width: 266px" class="wp-caption aligncenter"><img aria-describedby="caption-attachment-941" decoding="async" loading="lazy" src="http://kometbomb.net/wp-content/uploads/2016/04/PICO-8_4.gif" alt="No perspective" width="256" height="256" class="alignleft size-full wp-image-939" /><p id="caption-attachment-941" class="wp-caption-text">No perspective</p></div><div id="attachment_941" style="width: 266px" class="wp-caption aligncenter"><img aria-describedby="caption-attachment-941" decoding="async" loading="lazy" src="http://kometbomb.net/wp-content/uploads/2016/04/PICO-8_3.gif" alt="Sprite perspective" width="256" height="256" class="aligncenter size-full wp-image-940" /><p id="caption-attachment-941" class="wp-caption-text">Sprite perspective</p></div><div id="attachment_941" style="width: 266px" class="wp-caption aligncenter"><img aria-describedby="caption-attachment-941" decoding="async" loading="lazy" src="http://kometbomb.net/wp-content/uploads/2016/04/PICO-8_2.gif" alt="Full perspective" width="256" height="256" class="aligncenter size-full wp-image-941" /><p id="caption-attachment-941" class="wp-caption-text">Full perspective</p></div></p>
<p>The cars use two tricks to fake a convincing perspective: firstly, they have multiple versions of the sprites. Secondly, the cars are built of a number of separate sprites located at slightly different distances. I borrowed this idea from Lankhor&#8217;s <em>Vroom</em> and it works well with cars that have no flat sides and instead have clear &#8220;sections&#8221; &#8211; just like F1 cars have. The cars have the rear sprite, the front sprite and a middle section. When the car moves sideways, in addition to showing the sprite from an angle, the rear wheels have some sideways motion against with respect to the front wheels. And, while not a perspective thing, the front section is moved sideways when the player turns left or right, when the road has a curve or when the car bounces giving the illusion the car is yawing and pitching.</p>
<div id="attachment_971" style="width: 227px" class="wp-caption aligncenter"><img aria-describedby="caption-attachment-971" decoding="async" loading="lazy" src="http://kometbomb.net/wp-content/uploads/2016/04/carparts.png" alt="Parts of the car" width="217" height="150" class="size-full wp-image-971" /><p id="caption-attachment-971" class="wp-caption-text">Parts of the car</p></div>
<h2 id="toc-night-levels-and-color-fades">Night levels and color fades</h2>
<p>The color fades in Pico Racer are done using the palette mapping feature in Pico-8 and a few lookup tables. Basically, the tables tell which color to use for each of the 16 colors at a set brightness. Hand picking the colors gives the possibility (actually, with the fixed palette the fade will be tinted) to tint the fades so that they mimic sunset and so on. The road, sky and the sprites use a different lookup table each so that e.g. the road has markings visible even at pitch black and the sky and the horizon have a slightly different fade curve (because nature works like that).</p>
<div id="attachment_961" style="width: 590px" class="wp-caption aligncenter"><img aria-describedby="caption-attachment-961" decoding="async" loading="lazy" src="http://kometbomb.net/wp-content/uploads/2016/04/PICO-8_5.png" alt="Palette lookup table" width="580" height="540" class="size-full wp-image-961" srcset="http://kometbomb.net/wp-content/uploads/2016/04/PICO-8_5.png 580w, http://kometbomb.net/wp-content/uploads/2016/04/PICO-8_5-250x233.png 250w, http://kometbomb.net/wp-content/uploads/2016/04/PICO-8_5-430x400.png 430w" sizes="(max-width: 580px) 100vw, 580px" /><p id="caption-attachment-961" class="wp-caption-text">Palette lookup table</p></div>
<p>It all works something like this:</p>
<pre class="brush: cpp; title: ; notranslate">PALETTE={
 {1,1,1,1,2,2,2,0},
 ...
}

FUNCTION SETFADE(LEVEL)
 FOR C=1,15 DO
  -- ALL COLORS WITH VALUE C ARE NOW DRAWN 
  -- WITH THE FADED COLOR
  PAL(C, PALETTE[C][LEVEL])
 END
END</pre>
<p>On night levels, the cars are have rear lights drawn after it is dark enough. They are simply two extra sprites drawn without using the fade lookup palette.</p>
<h2 id="toc-pico-8-performance">Pico-8 performance</h2>
<p>The Pico-8 is more than enough to do all the math and rendering in one frame (30 FPS). In fact, only the sprites rendering seems to be a bottleneck. Mainly, when sprites are zoomed, their area grows exponentially and the area is used to calculate how long Pico-8 takes to draw the sprite. Sometimes even large but fully clipped (i.e. outside the screen or the clip rectangle) sprites slow everything down. I found the combined area of the sprites is more important than the number of sprites.</p>
<p>In Pico Racer, I capped sprites so that they never zoom larger than 100 %. This has minimal effect on visuals, although you will easily notice it if you know it&#8217;s happening. Since e.g. the cars suddenly stop growing as they get closer to the camera, your brain thinks the cars in fact start shrinking. Likewise, since there is a short range where all the cars are drawn equally large, a car a bit further away looks larger than a car closer to the camera, everything because your brain expects things further down the road to be a bit smaller.  </p>
<p>As for performance, limiting sprite size gives a big performance boost since as the sprites come very close to the camera and they get larger and larger, they very quickly get zoomed 200 %, 300 %, 600 % and so on. Further away they are just a dozen of pixels for a very long distance.</p>
<p>Since the area of sprites is the main contributing factor, this makes rendering the road quite efficient because every horizontal line is just one pixel high even though there are four sprites per horizontal line and 64 lines total.</p>

<div class="wp_rp_wrap  wp_rp_plain" ><div class="wp_rp_content"><h3 class="related_post_title">You might also like...</h3><ul class="related_post wp_rp"><li data-position="0" data-poid="in-1110" data-post-type="none" ><a href="http://kometbomb.net/2017/04/20/maps-in-micro-murder-but-its-pico-8-so-its-hard/" class="wp_rp_title">Maps in MICRO MURDER (but it&#8217;s PICO-8 so it&#8217;s hard)</a></li><li data-position="1" data-poid="in-1074" data-post-type="none" ><a href="http://kometbomb.net/2017/03/10/how-levels-are-generated-in-spaceman-8/" class="wp_rp_title">How levels are generated in Spaceman 8</a></li><li data-position="2" data-poid="in-847" data-post-type="none" ><a href="http://kometbomb.net/2011/10/20/prince-of-persia-on-the-c64/" class="wp_rp_title">Prince of Persia on the C64</a></li><li data-position="3" data-poid="in-804" data-post-type="none" ><a href="http://kometbomb.net/2011/07/25/android-ndk-and-sdl_rwops/" class="wp_rp_title">Android NDK and SDL_RWops</a></li><li data-position="4" data-poid="in-767" data-post-type="none" ><a href="http://kometbomb.net/2011/01/02/lossless-audio-compression/" class="wp_rp_title">Lossless Audio Compression</a></li></ul></div></div>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Prince of Persia on the C64</title>
		<link>http://kometbomb.net/2011/10/20/prince-of-persia-on-the-c64/</link>
		
		<dc:creator><![CDATA[kometbomb]]></dc:creator>
		<pubDate>Thu, 20 Oct 2011 21:33:28 +0000</pubDate>
				<category><![CDATA[Games]]></category>
		<category><![CDATA[Webfinds]]></category>
		<category><![CDATA[Amiga]]></category>
		<category><![CDATA[C64]]></category>
		<category><![CDATA[Retro gaming]]></category>
		<category><![CDATA[Video games]]></category>
		<guid isPermaLink="false">http://kometbomb.net/?p=847</guid>

					<description><![CDATA[This is so awesome. ]]></description>
										<content:encoded><![CDATA[<p><iframe loading="lazy" width="960" height="720" src="https://www.youtube.com/embed/tBs5-WOtIpc?feature=oembed" frameborder="0" allowfullscreen></iframe></p>
<p>This is so awesome. </p>
<p>It is almost in sync with the Amiga version (they use the same joystick input to play the game on an Amiga emulator and on a C64 emulator):</p>
<p><iframe loading="lazy" width="960" height="540" src="https://www.youtube.com/embed/2xkGBak5Glo?feature=oembed" frameborder="0" allowfullscreen></iframe></p>
<p>Wow. You can <a href="http://noname.c64.org/csdb/release/?id=102248">get it here</a> and read the <a href="http://popc64.blogspot.com/">author&#8217;s dev blog here</a>. Read <a href="http://www.rgcd.co.uk/2011/10/prince-of-persia-c64.html">a better article at RGCD</a> (this was just a heads-up).</p>

<div class="wp_rp_wrap  wp_rp_plain" ><div class="wp_rp_content"><h3 class="related_post_title">You might also like...</h3><ul class="related_post wp_rp"><li data-position="0" data-poid="in-268" data-post-type="none" ><a href="http://kometbomb.net/2008/06/18/thrustlikes/" class="wp_rp_title">Thrustlikes</a></li><li data-position="1" data-poid="in-219" data-post-type="none" ><a href="http://kometbomb.net/2008/03/09/dev-stories-from-the-past/" class="wp_rp_title">Dev Stories from the Past</a></li><li data-position="2" data-poid="in-760" data-post-type="none" ><a href="http://kometbomb.net/2010/12/27/review-ninja-senki/" class="wp_rp_title">Review: Ninja Senki</a></li><li data-position="3" data-poid="in-611" data-post-type="none" ><a href="http://kometbomb.net/2009/09/22/introducing-my-latest-projects/" class="wp_rp_title">Introducing My Latest Projects</a></li><li data-position="4" data-poid="in-249" data-post-type="none" ><a href="http://kometbomb.net/2008/04/10/rom-check-fail/" class="wp_rp_title">ROM CHECK FAIL</a></li></ul></div></div>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Chiptune Drums</title>
		<link>http://kometbomb.net/2011/10/11/chiptune-drums/</link>
		
		<dc:creator><![CDATA[kometbomb]]></dc:creator>
		<pubDate>Tue, 11 Oct 2011 22:51:07 +0000</pubDate>
				<category><![CDATA[Nonsense]]></category>
		<category><![CDATA[chiptune]]></category>
		<category><![CDATA[klystrack]]></category>
		<category><![CDATA[music]]></category>
		<category><![CDATA[Tutorial]]></category>
		<guid isPermaLink="false">http://kometbomb.net/?p=844</guid>

					<description><![CDATA[Here's how to emulate kick and snare drums when all you have got is one oscillator and a handful of waveform shapes.]]></description>
										<content:encoded><![CDATA[<p><a href="http://ilkke.blogspot.com/">Ilkke</a> asked me how to create a nice chiptune snare. This question escalated into a challenge to write a little tutorial about how to make less boring chiptune drums. I used <a href="http://code.google.com/p/klystrack/">Klystrack</a> to experiment but the basic theory holds for most programs and sound chips. You can hear the results below.</p>
<h3>Hi-hat</h3>
<p>We&#8217;ll start with the easiest drum. Generally, just a stable noise waveform with a sharpish attack and a longer decay is enough. If a filter is available, filtering out the low frequencies with a high or band-pass filter helps to make the other rhythm sounds stand out &#8211; you don&#8217;t want the hi-hat to drown out the snare. For a shaker type sound, make the attack phase longer.</p>
<h3>Kick drum</h3>
<p>Kick drum is a quite simple drum as well, if you need a basic techno kick or a longer 808-style sine wave oomph. The theory behind a basic kick goes like this: start high, finish low. Make the amplitude and the frequency drop sharply. If you hear a sharp decay in the frequency, you will perceive it like something punching through the other sounds. See an example below, it&#8217;s a generic 909 bass drum.</p>
<p><a href="http://kometbomb.net/wp-content/uploads/2011/10/kick.png"><img decoding="async" loading="lazy" src="http://kometbomb.net/wp-content/uploads/2011/10/kick.png" alt="" title="kick" width="800" height="130" class="alignright size-full wp-image-853" srcset="http://kometbomb.net/wp-content/uploads/2011/10/kick.png 800w, http://kometbomb.net/wp-content/uploads/2011/10/kick-250x40.png 250w, http://kometbomb.net/wp-content/uploads/2011/10/kick-550x89.png 550w" sizes="(max-width: 800px) 100vw, 800px" /></a></p>
<p>However, if we look at a more interesting (and louder) kick sound, we will notice it&#8217;s not just a sine wave. There are higher frequencies there even though they are not that pronounced. A good thing to do is to combine the soft sine wave (triangle wave is a nice approximation) with something sharper and louder in the first moments of the kick. Try having a few milliseconds worth of square wave and/or noise in the beginning of the drum. Then continue as usual with a low-frequency tail.</p>
<p>To simulate a distorted drum, use the square waveform. As in the example below, you can see a hard-limited sine wave looks like square wave:</p>
<p><a href="http://kometbomb.net/wp-content/uploads/2011/10/distkick.png"><img decoding="async" loading="lazy" src="http://kometbomb.net/wp-content/uploads/2011/10/distkick.png" alt="" title="distkick" width="768" height="139" class="aligncenter size-full wp-image-854" srcset="http://kometbomb.net/wp-content/uploads/2011/10/distkick.png 768w, http://kometbomb.net/wp-content/uploads/2011/10/distkick-250x45.png 250w, http://kometbomb.net/wp-content/uploads/2011/10/distkick-550x99.png 550w" sizes="(max-width: 768px) 100vw, 768px" /></a></p>
<p>An analysis of the <a href="http://www.ucapps.de/howto_sid_wavetables_1.html">kick drum sound used in <em>Auf Wiedersehen Monty</em></a> confirms the ideas discussed above:</p>
<blockquote><p><img decoding="async" loading="lazy" src="http://kometbomb.net/wp-content/uploads/2011/10/montysnare.png" alt="" title="montysnare" width="573" height="108" class="aligncenter size-full wp-image-875" srcset="http://kometbomb.net/wp-content/uploads/2011/10/montysnare.png 573w, http://kometbomb.net/wp-content/uploads/2011/10/montysnare-250x47.png 250w, http://kometbomb.net/wp-content/uploads/2011/10/montysnare-550x103.png 550w" sizes="(max-width: 573px) 100vw, 573px" /><br />
[&#8230;]</p>
<ol>
<li>
<p>it begins with a triangle wave, which is active for 20 mS [one program tick]</p>
</li>
<li>
<p>thereafter there is a short noise part for 20 mS</p>
</li>
<li>
<p>it ends with a pulse wave, the frequency and amplitude gets lower</p>
</li>
</ol>
</blockquote>
<h3>Snare drum</h3>
<p>Creating a convincing snare drum starts to get a bit complicated. It helps if we once again look at what is actually happening in a good snare sound.</p>
<p><a href="http://kometbomb.net/wp-content/uploads/2011/10/snare.png"><img decoding="async" loading="lazy" src="http://kometbomb.net/wp-content/uploads/2011/10/snare.png" alt="" title="snare" width="800" height="119" class="alignright size-full wp-image-857" /></a></p>
<p>As you can see, the snare sound consists of noise and a lower sine wave sound, the low frequency hum is the drum membrane vibrating. Also, the beginning of the hit the low sine wave is louder than the noisy rattle which adds a nice punch. We can emulate this by having a short pure triangle wave tone (use square wave to make it louder) in the beginning and change it to noise a moment later. As you can see, the waveform now looks a bit more like the original and has a beefy attack. </p>
<p>Another method to make an interesting snare often used by e.g. Rob Hubbard (I think) is to vary the noise frequency with a multi-octave arpeggio. If you need a real world analogue, you could think the cycling noise frequency (low-hi-low-hi-etc.) as reverberation.</p>
<h3>Closing thoughts and examples</h3>
<p>So, what did we learn? Nature is interesting because it has tons of variation and is never static or perfect. For chiptune drums, this means: never use a single waveform or frequency.</p>

<ol>
<li>
<p>Kick: Triangle wave only</p>
</li>
<li>
<p>Kick: Square wave</p>
</li>
<li>
<p>Kick: Square wave attack, triangle wave delay</p>
</li>
<li>
<p>Snare: Noise mixed with square and triangle, pure noise decay</p>
</li>
<li>
<p>Snare: Arpeggiated noise</p>
</li>
</ol>
<ul>
<li><a href='http://kometbomb.net/wp-content/uploads/2011/10/drums2.zip'>The above example as a Klystrack .kt file</a></li>
</ul>

<div class="wp_rp_wrap  wp_rp_plain" ><div class="wp_rp_content"><h3 class="related_post_title">You might also like...</h3><ul class="related_post wp_rp"><li data-position="0" data-poid="in-755" data-post-type="none" ><a href="http://kometbomb.net/2010/12/10/klystrack-1-5-demo/" class="wp_rp_title">klystrack 1.5 Demo</a></li><li data-position="1" data-poid="in-767" data-post-type="none" ><a href="http://kometbomb.net/2011/01/02/lossless-audio-compression/" class="wp_rp_title">Lossless Audio Compression</a></li><li data-position="2" data-poid="in-740" data-post-type="none" ><a href="http://kometbomb.net/2010/11/29/klystrack-1-5-is-approaching/" class="wp_rp_title">klystrack 1.5 Is Approaching Fast!</a></li><li data-position="3" data-poid="in-730" data-post-type="none" ><a href="http://kometbomb.net/2010/06/16/amegas/" class="wp_rp_title">Amegas</a></li><li data-position="4" data-poid="in-725" data-post-type="none" ><a href="http://kometbomb.net/2010/03/11/ahx-import-in-klystrack-1-4-0/" class="wp_rp_title">AHX Import in klystrack 1.4</a></li></ul></div></div>
]]></content:encoded>
					
		
		<enclosure url="http://kometbomb.net/wp-content/uploads/2011/10/drums.mp3" length="123714" type="audio/mpeg" />

			</item>
		<item>
		<title>What to do when Catalyst Control Center won&#8217;t load?</title>
		<link>http://kometbomb.net/2011/09/03/what-to-do-when-catalyst-control-center-wont-load/</link>
		
		<dc:creator><![CDATA[kometbomb]]></dc:creator>
		<pubDate>Sat, 03 Sep 2011 10:09:44 +0000</pubDate>
				<category><![CDATA[Nonsense]]></category>
		<category><![CDATA[Software]]></category>
		<category><![CDATA[Webfinds]]></category>
		<category><![CDATA[Annoyances]]></category>
		<category><![CDATA[ati]]></category>
		<category><![CDATA[bugs]]></category>
		<category><![CDATA[catalyst control center]]></category>
		<category><![CDATA[ccc]]></category>
		<category><![CDATA[Rants]]></category>
		<category><![CDATA[video adapters]]></category>
		<category><![CDATA[world of tanks]]></category>
		<guid isPermaLink="false">http://kometbomb.net/?p=811</guid>

					<description><![CDATA[Short answer: replace CCC with <a href="http://www.guru3d.com/article/ati-tray-tools-/">ATI Tray Tools</a>. ]]></description>
										<content:encoded><![CDATA[<p>Short answer: replace CCC with <a href="http://www.guru3d.com/article/ati-tray-tools-/">ATI Tray Tools</a>. The software has the most common stuff like setting anti-alias options and resolution and lots more for tweaking. And it&#8217;s very light-weight in comparison.</p>
<p><!--adsense_inside_post--></p>
<p>In my case, I wanted to disable forced anti-aliasing so that the enemy outlines in <a href="http://www.worldoftanks.com/" title="The Best Game Ever 2011(tm)">World of Tanks</a> were visible. A well-known <a href="http://forum.worldoftanks.com/index.php?/topic/17905-tank-outlines/">bug in the game with a working solution</a>, but an another well-known &#8220;feature&#8221; in the video software made working around it impossible as I couldn&#8217;t access the video settings.</p>
<p>The most dorky thing with CCC is that while there&#8217;s a ton of trouble with it, it seems the install procedure is the real reason for it not working. In my case, it was probably because of missing libraries and so the software refused to start (the only hint was an error message in Event Viewer: <kbd>Could not find Type [ATI.ACE.CLI.Component.Dashboard.Dashboard] from [CLI.Component.Dashboard]</kbd>).</p>
<p>Many tutorials on how to fix this is to reinstall CCC and the drivers but I found this won&#8217;t work and is very annoying even if it did work. So, I recommend skipping that and use this little tool instead. Thank you Ray Adams, no thanks ATI/AMD.</p>

<div class="wp_rp_wrap  wp_rp_plain" ><div class="wp_rp_content"><h3 class="related_post_title">You might also like...</h3><ul class="related_post wp_rp"><li data-position="0" data-poid="in-45" data-post-type="none" ><a href="http://kometbomb.net/2007/05/29/webdesign-stuff-that-annoys-me/" class="wp_rp_title">Webdesign stuff that annoys me</a></li><li data-position="1" data-poid="in-275" data-post-type="none" ><a href="http://kometbomb.net/2008/06/27/proposal-one-sentence-news/" class="wp_rp_title">Proposal: One-sentence News</a></li><li data-position="2" data-poid="in-241" data-post-type="none" ><a href="http://kometbomb.net/2008/04/01/get-your-act-together-mozilla/" class="wp_rp_title">Get your act together, Mozilla</a></li><li data-position="3" data-poid="in-152" data-post-type="none" ><a href="http://kometbomb.net/2007/12/10/look-smart-on-the-internet-in-three-easy-steps/" class="wp_rp_title">Look smart on the Internet in three easy steps</a></li><li data-position="4" data-poid="in-113" data-post-type="none" ><a href="http://kometbomb.net/2007/10/07/viewer-build-3350/" class="wp_rp_title">Viewer2 Build 3350</a></li></ul></div></div>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Android NDK and SDL_RWops</title>
		<link>http://kometbomb.net/2011/07/25/android-ndk-and-sdl_rwops/</link>
		
		<dc:creator><![CDATA[kometbomb]]></dc:creator>
		<pubDate>Mon, 25 Jul 2011 17:48:53 +0000</pubDate>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Android]]></category>
		<category><![CDATA[Android NDK]]></category>
		<category><![CDATA[C]]></category>
		<category><![CDATA[Native]]></category>
		<category><![CDATA[SDL]]></category>
		<category><![CDATA[Source code]]></category>
		<guid isPermaLink="false">http://kometbomb.net/?p=804</guid>

					<description><![CDATA[Note: There&#8217;s now a patch for SDL that makes the same possible on older Androids as well. The Android NDK makes it possible to use SDL to code Android apps. The aliens.c example bundled with the Android SDL port is fine and dandy except it reads data from /sdcard/data and it has to be pushed [&#8230;]]]></description>
										<content:encoded><![CDATA[<p><b>Note:</b> There&#8217;s now <a href="http://bugzilla.libsdl.org/show_bug.cgi?id=1261">a patch for SDL</a> that makes the same possible on older Androids as well.</p>
<p>The Android NDK makes it possible to use SDL to code Android apps. The aliens.c example bundled with the Android SDL port is fine and dandy except it reads data from /sdcard/data and it has to be pushed manually on the device. A nicer approach is to use the standard SDL way to load data from weird sources: with the SDL_RWops struct. We can use the Android AssetManager object to read data from the APK file (the assets directory in the project), Android 2.3 comes with <kbd>&lt;android/asset_manager.h&gt;</kbd> that has the needed helper NDK stuff.</p>
<p>Now, the SDL example is for Android 1.5 (or 1.6, I forget) which means it doesn&#8217;t use NativeActivity but instead rolls its own Java wrapper. That means we don&#8217;t have simple access to the asset manager &#8212; NativeActivity makes this easy because it calls the native code with all the useful stuff ready in a <kbd>struct android_app</kbd> &#8212; so we have to look it up ourselves. </p>
<p>In short:</p>
<ol>
<li>
<p>Get access to AAssetManager</p>
<ol>
<li>
<p>Using NativeActivity, it&#8217;s in struct android_app passed to android_main()</p>
</li>
<li>
<p>If struct android_app is not available (as in the SDL example), store JNI environment in a global variable in the SDL startup code and use it in your code to get AssetManager</p>
</li>
</ol>
</li>
<li>
<p>Use AAsset_RWFromAsset() defined below to get an SDL_RWops to a file inside the assets directory</p>
</li>
</ol>
<p>We have to modify the SDL startup method defined in the library source code:</p>
<h3>SDL_android_main.cpp (line 19-ish)</h3>
<pre><code>JNIEnv *g_env;

extern "C" void Java_org_libsdl_app_SDLActivity_nativeInit(JNIEnv* env, jclass cls, jobject obj)
{
    // Store the environment for later use.
    g_env = env;

    /* This interface could expand with ABI negotiation, calbacks, etc. */
    SDL_Android_Init(env, cls);

    /* Run the application code! */
    int status;
    char *argv[2];
    argv[0] = strdup("SDL_app");
    argv[1] = NULL;
    status = SDL_main(1, argv);

    /* We exit here for consistency with other platforms. */
    exit(status);
}</code></pre>
<h3>main.c</h3>
<p>Note: <kbd>fatal()</kbd> is a macro that invokes the Android logging interfaces, much like the LOGE() macro.</p>
<pre><code>#include "android_rwops.h"
#include &lt;android/asset_manager_jni.h&gt;
#include &lt;jni.h&gt;

// g_env is set in SDL_android_main.cpp
extern JNIEnv *g_env;

// This function retrieves a static member of SDLActivity called mAssetMgr
// which is initialized in the onCreate() method like so:
// ...
//   mAssetMgr = getAssets();
// ...
// You can also call the getAssets() method from the native code.

AAssetManager * get_asset_manager()
{
	jclass sdlClass = (*g_env)-&gt;FindClass(g_env, "org/libsdl/app/SDLActivity");

	if (sdlClass == 0)
	{
		fatal("org/libsdl/app/SDLActivity not found.");
		return NULL;
	}

	jfieldID assman = (*g_env)-&gt;GetStaticFieldID(g_env, sdlClass, 
                          "mAssetMgr", "Landroid/content/res/AssetManager;");

	if (assman == 0)
	{
		fatal("Could not find mAssetMgr.");
		return NULL;
	}

	jobject assets = (*g_env)-&gt;GetStaticObjectField(g_env, sdlClass, assman);

	if (assets == 0)
	{
		fatal("Could not get mAssetMgr.");
		return NULL;
	}

	return AAssetManager_fromJava(g_env, assets);
}

int main(int argc, char **argv)
{
  AAssetManager *assets = get_asset_manager();

  // You should check the return value, here we assume logo.png is found
  SDL_RWops *rw = AAsset_RWFromAsset(assets, "image.bmp");

  // Do whatever you want with the rwops
  GfxSurface *i = SDL_LoadBMP_RW(rw, 1);

  ...
}
</code></pre>
<h3>android_rwops.h</h3>
<pre><code>#pragma once

#ifdef _cplusplus
extern "C" {
#endif

#include "SDL_rwops.h"
#include &lt;android/asset_manager.h&gt;

SDL_RWops * AAsset_RWFromAsset(AAssetManager *mgr, const char *filename);

#ifdef _cplusplus
}
#endif</code></pre>
<h3>android_rwops.c</h3>
<pre><code>#include "android_rwops.h"

static SDLCALL long aa_rw_seek(struct SDL_RWops * ops, long offset, int whence)
{
	return AAsset_seek((AAsset*)ops-&gt;hidden.unknown.data1, offset, whence);
}


static SDLCALL size_t aa_rw_read(struct SDL_RWops * ops, void *ptr, size_t size, size_t maxnum)
{
	return AAsset_read((AAsset*)ops-&gt;hidden.unknown.data1, ptr, maxnum * size) / size;
}


static SDLCALL int aa_rw_close(struct SDL_RWops * ops)
{
	AAsset_close((AAsset*)ops-&gt;hidden.unknown.data1);
	SDL_FreeRW(ops);

	return 0;
}


SDL_RWops * AAsset_RWFromAsset(AAssetManager *mgr, const char *filename)
{
	AAsset *asset = AAssetManager_open(mgr, filename, AASSET_MODE_RANDOM);

	if (!asset)
		return NULL;
	
	SDL_RWops *ops = SDL_AllocRW();
	
	if (!ops)
	{
		AAsset_close(asset);
		return NULL;
	}
	
	ops-&gt;hidden.unknown.data1 = asset;
	ops-&gt;read = aa_rw_read;
	ops-&gt;write = NULL;
	ops-&gt;seek = aa_rw_seek;
	ops-&gt;close = aa_rw_close;
	
	return ops;
}</code></pre>

<div class="wp_rp_wrap  wp_rp_plain" ><div class="wp_rp_content"><h3 class="related_post_title">You might also like...</h3><ul class="related_post wp_rp"><li data-position="0" data-poid="in-767" data-post-type="none" ><a href="http://kometbomb.net/2011/01/02/lossless-audio-compression/" class="wp_rp_title">Lossless Audio Compression</a></li><li data-position="1" data-poid="in-611" data-post-type="none" ><a href="http://kometbomb.net/2009/09/22/introducing-my-latest-projects/" class="wp_rp_title">Introducing My Latest Projects</a></li><li data-position="2" data-poid="in-701" data-post-type="none" ><a href="http://kometbomb.net/2010/02/28/libconfig/" class="wp_rp_title">An Alternative to XML</a></li><li data-position="3" data-poid="in-695" data-post-type="none" ><a href="http://kometbomb.net/2009/12/31/creating-a-simple-gui-from-scratch/" class="wp_rp_title">Creating a Simple GUI from Scratch</a></li><li data-position="4" data-poid="in-227" data-post-type="none" ><a href="http://kometbomb.net/2008/03/21/a-tiny-xml-parser/" class="wp_rp_title">A Tiny XML Parser</a></li></ul></div></div>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Lossless Audio Compression</title>
		<link>http://kometbomb.net/2011/01/02/lossless-audio-compression/</link>
					<comments>http://kometbomb.net/2011/01/02/lossless-audio-compression/#comments</comments>
		
		<dc:creator><![CDATA[kometbomb]]></dc:creator>
		<pubDate>Sun, 02 Jan 2011 23:38:17 +0000</pubDate>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Algorithms]]></category>
		<category><![CDATA[audio compression]]></category>
		<category><![CDATA[C]]></category>
		<category><![CDATA[klystrack]]></category>
		<category><![CDATA[Source code]]></category>
		<category><![CDATA[Tutorial]]></category>
		<guid isPermaLink="false">http://kometbomb.net/?p=767</guid>

					<description><![CDATA[Here's an audio compression scheme I came up for <a href="http://code.google.com/p/klystrack/">my tracker project</a>. ]]></description>
										<content:encoded><![CDATA[<h2 id="toc-introduction">Introduction</h2>
<p>Here&#8217;s an audio compression scheme I came up for <a href="http://code.google.com/p/klystrack/">my tracker project</a>. Generally, I wanted an algorithm that meets these three conditions:</p>
<ul>
<li>Has to compress mono audio losslessly</li>
<li>Has to be simple, should be just one source code file or 500 lines of C code at most</li>
<li>Should compress 8-bit audio that&#8217;s upscaled to 16-bits to near 8 bits per sample</li>
</ul>
<p><ol class="toc-generator"><li class="heading-2 selected"><a href="#toc-road-rendering" title="Jump to Road rendering">Road rendering</a></li><li class="heading-2"><a href="#toc-sprite-rendering" title="Jump to Sprite rendering">Sprite rendering</a></li><li class="heading-3"><a href="#toc-car-rendering-and-sprite-perspective" title="Jump to Car rendering and sprite perspective">Car rendering and sprite perspective</a></li><li class="heading-2"><a href="#toc-night-levels-and-color-fades" title="Jump to Night levels and color fades">Night levels and color fades</a></li><li class="heading-2"><a href="#toc-pico-8-performance" title="Jump to Pico-8 performance">Pico-8 performance</a></li><li class="heading-2"><a href="#toc-introduction" title="Jump to Introduction">Introduction</a></li><li class="heading-2"><a href="#toc-the-algorithm" title="Jump to The algorithm">The algorithm</a></li><li class="heading-3"><a href="#toc-delta-encoding" title="Jump to Delta encoding">Delta encoding</a></li><li class="heading-3"><a href="#toc-gray-encoding" title="Jump to Gray encoding">Gray encoding</a></li><li class="heading-3"><a href="#toc-reordering-data-in-bit-planes" title="Jump to Reordering data in bit planes">Reordering data in bit planes</a></li><li class="heading-3"><a href="#toc-run-length-encoding" title="Jump to Run-length encoding">Run-length encoding</a></li><li class="heading-2"><a href="#toc-improvements" title="Jump to Improvements">Improvements</a></li><li class="heading-2"><a href="#toc-compression-results" title="Jump to Compression results">Compression results</a></li><li class="heading-2"><a href="#toc-source-code" title="Jump to Source code">Source code</a></li></ol></p>
<p>The lossless requirement is obvious and the simplicity gives the benefit of not having to rely on external libraries (e.g. when using something like RAR compression) and not being overkill. The audio data is not huge in any case so the compression ratio doesn&#8217;t have to be exceptional. The last requirement is the most important: in klystrack, it is possible to load raw 8-bit audio files, usually originally from the Amiga computer. The native audio format in klystrack is 16-bit, however, so when saving the audio data there always are 8 redundant bits and the file will generally be twice as large as the original file. Also, since the software deals with low-fidelity aesthetics (chiptunes), the audio data might be even lower quality than 8-bit.</p>
<p>While there&#8217;s the option of detecting the bit fidelity and only saving the most significant bits, I thought it should be quite simple to devise an algorithm that automatically detects and leaves the redundant bits out while still doing some compression for even 16-bit audio data.</p>
<p><!--adsense_inside_post--></p>
<h2 id="toc-the-algorithm">The algorithm</h2>
<p>In short, the algorithm does this:</p>
<ol>
<li>
<p><a href="http://en.wikipedia.org/wiki/Delta_encoding">Delta code</a> input data</p>
</li>
<li>
<p><a href="http://en.wikipedia.org/wiki/Gray_code">Gray code</a> the data from above</p>
</li>
<li>
<p>Reorder the data from above in <a href="http://en.wikipedia.org/wiki/Bit_plane">bit planes</a>. I.e. first output the least significant bit of all samples, then the next bit for all samples and so forth</p>
</li>
<li>
<p><a href="http://en.wikipedia.org/wiki/Run-length_encoding">Run-length encode</a> the above data exploiting the fact you only need to store the distance between bit flips</p>
</li>
</ol>
<h3 id="toc-delta-encoding">Delta encoding</h3>
<p>By delta encoding the audio data, we can exploit the fact audio data very often changes just a little between samples and so the generated delta values (the amount of change) need fewer bits to be expressed. However, you can&#8217;t store 16-bit data with e.g. 8-bit delta values since it is not assured the change is always small enough to be stored in 8 bits, requiring the use of 16-bit delta values in the worst case. </p>
<h3 id="toc-gray-encoding">Gray encoding</h3>
<p>Using gray codes we can minimize the amount of bit flipping that happens (e.g. when a value changes between 7 and 8, where the bits change from <kbd>0111</kbd> to <kbd>1000</kbd> &#8212; three bits flip even if the value changes by one) to one bit flip between any two neighboring values. In practice, this doesn&#8217;t always result in better compression and sometimes it even can hurt the compression ratio.</p>
<h3 id="toc-reordering-data-in-bit-planes">Reordering data in bit planes</h3>
<p>This step is the key to good compression in our case. Between two neighboring delta values, it&#8217;s common that most of the bits are the same and it&#8217;s common for one bit to stay completely static for the whole data. So, we take the bits from all samples and sort them so that all significant bits come before the lesser bits. The result is long runs of bits, usually in the most significant bits.</p>
<p><!--adsense_inside_post--></p>
<h3 id="toc-run-length-encoding">Run-length encoding</h3>
<p>Finally, we take the encoded and reordered data and store the bits using RLE. While RLE usually stores the repeated data and the number of repetitions, we can exploit the fact the data is always zero or one, always changing between runs &#8212; only the starting state of the bit needs to be stored. <a href="http://en.wikipedia.org/wiki/Elias_gamma_coding">Elias gamma coding</a> is used to store the run-lengths since in most cases the run length is in the range of a few bits (for completely empty bit planes we can use special flags that tell they&#8217;re all zero or one) and tend to fall in 1-4 bits. With gamma coding it&#8217;s possible to store the number 1 by using one bit, the number two takes three bits. </p>
<p>Also, for some bit planes a raw dump of bits with no compression should be used if compression would result in much longer data than the original. There are also two special codes for the bit planes, in cases where all bits are zero or one (common if the audio data is quiet, i.e. uses only a subrange of the 16-bit resolution) or if the data is offset by a constant.</p>
<p>Depending on implementation the total overhead is around two bits per bit plane (i.e. 32 bits or two bytes for 16-bit audio data), not including the header data describing the compressed data (data length, uncompressed length). Since there&#8217;s the possibility of a raw dump of bits, in the worst case (none of the bit planes compress at all), the data size grows only by two bytes. A completely quiet (all zero bits) data will take only two bytes for any length. </p>
<h2 id="toc-improvements">Improvements</h2>
<p>My implementation only compresses the whole audio data as one big chunk but this can be easily improved to compress in chunks. This should improve the compression when there are parts where the audio is quiet and most of the bits will be zero.</p>
<p>Stereo audio can be compressed by compressing two chunks of data, one for both channels. The other channel should be delta coded compared to the other channel since in stereo audio the two channels often heavily correlate.</p>
<p>Since the Gray coding may even hurt compression, there should be the option to disable the coding for chunks. This can be simply by brute force, comparing which combination of options produces the shortest compressed data.</p>
<h2 id="toc-compression-results">Compression results</h2>
<p>The following contains example compression results. The Option column tells different configurations where the input data is delta coded and/or Gray coded.  This shows how different preprocessing steps work better for different kinds of input data.</p>
<p><em>Legend: 0 = no coding before compression, 1 = delta coding, 2 = Gray coding, 3 = delta and Gray coding.</em></p>
<style type="text/css">tr.best { background-color: #cfc; } table.maintable table td {text-align:right;}  table.maintable table tr.heading { background-color: #ddd; } table.maintable > tr > td { padding-right: 40px; }</style>
<table class="maintable">
<tr>
<td>
<table>
<tr class="heading">
<th>Options</th>
<th>Ratio</th>
</tr>
<tr>
<th colspan="2">Sine wave (loud)</th>
</tr>
<tr>
<td>0</td>
<td>73.1 %</td>
</tr>
<tr>
<td>1</td>
<td>29.6 %</td>
</tr>
<tr>
<td>2</td>
<td>67.9 %</td>
</tr>
<tr class="best">
<td>3</td>
<td>22.6 %</td>
</tr>
<tr>
<th colspan="2">White noise (loud)</th>
</tr>
<tr>
<td>0</td>
<td>100.0 %</td>
</tr>
<tr>
<td>1</td>
<td>100.0 %</td>
</tr>
<tr class="best">
<td>2</td>
<td>99.8 %</td>
</tr>
<tr>
<td>3</td>
<td>100.0 %</td>
</tr>
<tr>
<th colspan="2">Complex wave</th>
</tr>
<tr>
<td>0</td>
<td>75.3 %</td>
</tr>
<tr>
<td>1</td>
<td>38.2 %</td>
</tr>
<tr>
<td>2</td>
<td>69.6 %</td>
</tr>
<tr class="best">
<td>3</td>
<td>30.0 %</td>
</tr>
</table>
</td>
<td>
<table>
<tr class="heading">
<th>Options</th>
<th>Ratio</th>
</tr>
<tr>
<th colspan="2">Sine wave and noise</th>
</tr>
<tr>
<td>0</td>
<td>84.7 %</td>
</tr>
<tr>
<td>1</td>
<td>100.0 %</td>
</tr>
<tr class="best">
<td>2</td>
<td>80.9 %</td>
</tr>
<tr class="best">
<td>3</td>
<td>80.9 %</td>
</tr>
<tr>
<th colspan="2">White noise (quiet)</th>
</tr>
<tr class="best">
<td>0</td>
<td>50.0 %</td>
</tr>
<tr>
<td>1</td>
<td>100.0 %</td>
</tr>
<tr class="best">
<td>2</td>
<td>50.0 %</td>
</tr>
<tr>
<td>3</td>
<td>55.9 %</td>
</tr>
<tr>
<th colspan="2">Complex wave (saturated)</th>
</tr>
<tr>
<td>0</td>
<td>38.9 %</td>
</tr>
<tr>
<td>1</td>
<td>21.9 %</td>
</tr>
<tr>
<td>2</td>
<td>37.2 %</td>
</tr>
<tr class="best">
<td>3</td>
<td>17.7 %</td>
</tr>
</table>
</td>
</tr>
</table>
<h2 id="toc-source-code">Source code</h2>
<pre class="brush: cpp; title: ; notranslate">#include &lt;stdio.h&gt;
#include &lt;stdlib.h&gt;
#include &lt;string.h&gt;
#include &lt;math.h&gt;

typedef unsigned char Uint8;
typedef short int Sint16;
typedef unsigned short int Uint16;
typedef int Sint32;
typedef unsigned int Uint32;


/* bitpack() bit plane codes */
enum
{
	BITPACK_STATIC0,
	BITPACK_STATIC1,
	BITPACK_LITERAL,
	BITPACK_RLE
};


/* bitstream writer helpers*/
typedef struct
{
	Uint8 *buffer;
	Uint32 byte, size_byte; 	// Read/write position counters (byte component)
	Uint8 bit, size_bit;		// Read/write position counters (bit component)
} BitPtr;

#define BIT_BLOCK_SIZE 1024 // Bitstream buffer allocation increment size

void bit_init(BitPtr *p, Uint8 *buffer, Uint32 size_bytes, Uint8 size_bits)
{
	memset(p, 0, sizeof(*p));
	p-&gt;buffer = buffer;
	p-&gt;size_byte = size_bytes;
	p-&gt;size_bit = size_bits;
}


void bit_deinit(BitPtr *p)
{
	free(p-&gt;buffer);
	memset(p, 0, sizeof(*p));
}


void bit_rewind(BitPtr *p)
{
	p-&gt;bit = p-&gt;byte = 0;
}


void bit_seek(BitPtr *p, Uint32 byte, Uint8 bit)
{
	p-&gt;byte = byte;
	p-&gt;bit = bit;
}


void bit_w(BitPtr *p, int bit)
{
	if (p-&gt;bit == 0 &amp;&amp; !(p-&gt;byte &amp; (BIT_BLOCK_SIZE - 1)))
	{
		// If write position modulo BIT_BLOCK_SIZE is zero, allocate a larger buffer
		p-&gt;buffer = realloc(p-&gt;buffer, p-&gt;byte + BIT_BLOCK_SIZE);
	}

	if (bit)
		p-&gt;buffer[p-&gt;byte] |= 1 &lt;&lt; p-&gt;bit;
	else
		p-&gt;buffer[p-&gt;byte] &amp;= ~(1 &lt;&lt; p-&gt;bit);

	++p-&gt;bit;
	
	if (p-&gt;bit == 8)
	{
		p-&gt;bit = 0;
		++p-&gt;byte;
	}
	
	p-&gt;size_byte = p-&gt;byte;
	p-&gt;size_bit = p-&gt;bit;
}


int bit_r(BitPtr *p)
{
	if (p-&gt;size_byte &lt;= p-&gt;byte &amp;&amp; p-&gt;size_bit &lt;= p-&gt;bit)
		return -1;

	int bit = (p-&gt;buffer[p-&gt;byte] &amp; (1 &lt;&lt; p-&gt;bit)) != 0;
	
	++p-&gt;bit;
	
	if (p-&gt;bit == 8)
	{
		p-&gt;bit = 0;
		++p-&gt;byte;
	}
	
	return bit;
}


/* Write Elias gamma coded value (has to be nonzero) */
void bit_wgamma(BitPtr *p, Uint32 value)
{
	int l = log2(value);
	
	for (int a=0; a &lt; l; a++)
		bit_w(p, 0); //put 0s to indicate how many bits will follow
		
	bit_w(p, 1);      //mark the end of the 0s
	
	for (int a=l-1; a &gt;= 0; a--) //Write the bits as plain binary
	{
		bit_w(p, value &amp; 1 &lt;&lt; a);
	}
	
}


/* Read Elias gamma coded value, zero return value signals read error */
Uint32 bit_rgamma(BitPtr *p)
{
	int numberBits = 0;
	int bit;
	while (!(bit = bit_r(p)))
		numberBits++; //keep on reading until we fetch a one...
	
	if (bit &lt; 0) return 0;
		
	Uint32 current = 0;
	for (int a=numberBits-1; a &gt;= 0; a--) //Read numberBits bits
	{
		if ((bit = bit_r(p)))
			current |= 1 &lt;&lt; a;
			
		if (bit &lt; 0) return 0;
	}
	current |= 1 &lt;&lt; numberBits; //last bit isn't encoded!
	
	return current;
}


/* Read bits bits */
Sint32 bit_rbits(BitPtr *p, Uint8 bits)
{
	Sint32 rval = 0;

	for (int i = 0 ; i &lt; bits ; ++i)
	{
		int bit = bit_r(p);
		
		if (bit &lt; 0) return -1;
		
		rval |= bit &lt;&lt; i;
	}
	
	return rval;
}


/* Write bits bits of v */
void bit_wbits(BitPtr *p, Uint32 v, Uint8 bits)
{
	for (int i = 0 ; i &lt; bits ; ++i)
	{
		bit_w(p, v &amp; (1 &lt;&lt; i));
	}
}


/* Gray and delta encoding helpers */
static inline Uint16 gray(Uint16 v)
{
	return v ^ (v &gt;&gt; 1);
}


static inline Uint16 degray(Uint16 v)
{
	v ^= (v&gt;&gt;8);
    v ^= (v&gt;&gt;4);
	v ^= (v&gt;&gt;2);
	v ^= (v&gt;&gt;1);
	return v;
}


static void delta_encode(Sint16 *buffer, const int n)
{
	Sint32 delta = 0;
	Sint32 original;
	for (int i = 0; i &lt; n; ++i)
	{
		original = buffer[i];
		Sint32 x = original - delta;
		buffer[i] = gray(x + 32768); // Gray code can not be negative
		delta = original;
	}
}


static void delta_decode(Sint16 *buffer, const int n)
{
	Sint32 delta = 0;
	for (int i = 0; i &lt; n; ++i)
	{
		Sint32 v = degray(buffer[i]);
		buffer[i] = (v - 32768) + delta;
		delta = buffer[i];
	}
}


/* Compress 16-bit signed data into bitstream, return compressed data size in packed_size (in bits) */
Uint8 * bitpack(const Sint16 *_buffer, const int n, Uint32 *packed_size)
{
	BitPtr bp;
	bit_init(&amp;bp, NULL, 0, 0);
	
	Sint16 *buffer = malloc(sizeof(Sint16) * n);
	memcpy(buffer, _buffer, sizeof(Sint16) * n);
	
	delta_encode(buffer, n);
	
	for (int plane = 0 ; plane &lt; sizeof(*buffer) * 8 ; ++plane)
	{
		const Sint16 mask = 1 &lt;&lt; plane;
		int bit = mask &amp; *buffer;
		
		int type = BITPACK_STATIC0 | (bit != 0);
		
		for (int i = 0 ; i &lt; n ; ++i)
			if ((buffer[i] &amp; mask) != bit)
			{
				// Was not all zeros or all ones, needs to compress
				type = BITPACK_RLE;
				break;
			}
			
		Uint32 p_byte = bp.byte;
		Uint32 p_bit = bp.bit;
		
again:
		
		bit_wbits(&amp;bp, type, 2);
			
		switch (type)
		{
			case BITPACK_LITERAL:
				for (int i = 0 ; i &lt; n ; ++i)
					bit_w(&amp;bp, buffer[i] &amp; mask);
				break;
			
			case BITPACK_STATIC0:			
			case BITPACK_STATIC1:
				// No data needed, bit plane is all zeros or all ones
				break;
				
			case BITPACK_RLE:
			{
				// Write starting bit state
				bit_w(&amp;bp, bit);
				
				Uint32 ctr = 0;
				
				for (int i = 0 ; i &lt; n ; ++i)
				{
					if (((buffer[i] &amp; mask) == bit))
						++ctr;
						
					if ((buffer[i] &amp; mask) != bit)
					{
						bit_wgamma(&amp;bp, ctr);

						ctr = 1;
						
						// Flip the bit (no neighboring bits are the same state)
						bit ^= mask;
					}
				}
				
				if (ctr != 0) bit_wgamma(&amp;bp, ctr);
				
				if ((bp.byte * 8 + bp.bit) - (p_byte * 8 + p_bit) &gt; n + 2)
				{
					// RLE gave longer data than the original, dump data instead
					bit_seek(&amp;bp, p_byte, p_bit);
					type = BITPACK_LITERAL;
					goto again;
				}
				
			}	
			break;
		}
		
	}
	
	free(buffer);
	
	*packed_size = bp.byte * 8 + bp.bit;
	
	return bp.buffer;
}


/* Decompress compressed bitstream into 16-bit signed data, decompress at most packed_size bits
	unpacked_size tells the function the data length (important)
 */
Sint16 * bitunpack(const Uint8 *packed_data, const Uint32 packed_size, Uint32 unpacked_size)
{
	BitPtr bp;
	bit_init(&amp;bp, (Uint8*)packed_data, packed_size / 8, packed_size &amp; 7);
	
	Sint16 *buffer = calloc(unpacked_size, sizeof(Sint16));
	
	for (int plane = 0 ; plane &lt; sizeof(*buffer) * 8 ; ++plane)
	{
		const Sint16 mask = 1 &lt;&lt; plane;
		
		Sint32 type = bit_rbits(&amp;bp, 2);
		
		if (type &lt; 0) goto read_error;
			
		switch (type)
		{
			case BITPACK_LITERAL:
				for (int i = 0 ; i &lt; unpacked_size ; ++i)
				{
					int bit = bit_r(&amp;bp);
					if (bit &lt; 0) goto read_error;
					if (bit) buffer[i] |= mask;
				}
				break;
				
			case BITPACK_STATIC0:
				// Data bits are zero by default, no action needed
				break;
				
			case BITPACK_STATIC1:
				// Fill bit plane with set/unset bit
				for (int i = 0 ; i &lt; unpacked_size ; ++i)
					buffer[i] |= mask;
				break;
				
			case BITPACK_RLE:
			{
				// Read the starting bit status
				int bit = bit_r(&amp;bp);
				
				if (bit &lt; 0) goto read_error;
				
				if (bit) bit = mask; else bit = 0;
				
				buffer[0] |= bit;
				
				for (int i = 0 ; i &lt; unpacked_size ; )
				{
					Uint32 ctr = bit_rgamma(&amp;bp);
					
					if (ctr == 0) goto read_error;
					
					for (; i &lt; unpacked_size &amp;&amp; ctr ; ++i, --ctr)
						buffer[i] |= bit;
					
					if (ctr) goto read_error;
					
					// Flip the bit (neighboring bits are always different)
					bit ^= mask;
				}
			}		
			break;
		}
	}
	
	delta_decode(buffer, unpacked_size);
	
	if (0)
	{
read_error:
		free(buffer);
		return NULL;
	}
	
	return buffer;
}


/* Generate test data, 0 is a sine wave and 1 generates noise */
void getdata(Sint16 *buffer, const int n, int t)
{
	switch (t)
	{
		case 0:
			for (int i = 0 ; i &lt; n ; ++i)
			{
				buffer[i] = (((int)(sin((float)i / 1000 * 3.141 * 2) * 20000)));
			}
			
			break;
			
		case 1:
			for (int i = 0 ; i &lt; n ; ++i)
				buffer[i] = (rand() * 4);
			
			break;
	}
}


int main(int argc, char **argv)
{
	const int n = 100000;

	Sint16 *b = malloc(sizeof(Sint16) * n);
	Uint32 packed_size;
	
	getdata(b, n, 0);
	
	Uint8 * data = bitpack(b, n, &amp;packed_size);
	Sint16 * udata = bitunpack(data, packed_size, n);
	
	if (udata == NULL || memcmp(b, udata, sizeof(Sint16) * n) != 0)
	{
		printf(&quot;Upack failed\n&quot;);
	}
	else
	{
		printf(&quot;Compression ratio %.1f %%\n&quot;, (float)100 * packed_size / (n * sizeof(Sint16) * 8));
		
	}
		
	free(data);
	free(udata);
	free(b);
	
	return 0;
}
</pre>

<div class="wp_rp_wrap  wp_rp_plain" ><div class="wp_rp_content"><h3 class="related_post_title">You might also like...</h3><ul class="related_post wp_rp"><li data-position="0" data-poid="in-804" data-post-type="none" ><a href="http://kometbomb.net/2011/07/25/android-ndk-and-sdl_rwops/" class="wp_rp_title">Android NDK and SDL_RWops</a></li><li data-position="1" data-poid="in-128" data-post-type="none" ><a href="http://kometbomb.net/2009/11/09/plenty-of-room-part-ii/" class="wp_rp_title">Plenty of Room, Part II</a></li><li data-position="2" data-poid="in-844" data-post-type="none" ><a href="http://kometbomb.net/2011/10/11/chiptune-drums/" class="wp_rp_title">Chiptune Drums</a></li><li data-position="3" data-poid="in-701" data-post-type="none" ><a href="http://kometbomb.net/2010/02/28/libconfig/" class="wp_rp_title">An Alternative to XML</a></li><li data-position="4" data-poid="in-611" data-post-type="none" ><a href="http://kometbomb.net/2009/09/22/introducing-my-latest-projects/" class="wp_rp_title">Introducing My Latest Projects</a></li></ul></div></div>
]]></content:encoded>
					
					<wfw:commentRss>http://kometbomb.net/2011/01/02/lossless-audio-compression/feed/</wfw:commentRss>
			<slash:comments>5</slash:comments>
		
		
			</item>
		<item>
		<title>Review: Ninja Senki</title>
		<link>http://kometbomb.net/2010/12/27/review-ninja-senki/</link>
		
		<dc:creator><![CDATA[kometbomb]]></dc:creator>
		<pubDate>Mon, 27 Dec 2010 01:35:57 +0000</pubDate>
				<category><![CDATA[Games]]></category>
		<category><![CDATA[Retro gaming]]></category>
		<category><![CDATA[Reviews]]></category>
		<category><![CDATA[Video]]></category>
		<category><![CDATA[Video games]]></category>
		<guid isPermaLink="false">http://kometbomb.net/?p=760</guid>

					<description><![CDATA[A few days ago the indie game <a href="http://www.ninjasenki.com/">Ninja Senki</a> was released after a year of development. In short, it's a Ninja Gaiden inspired (a lot of pages say Mega Man but I don't agree with that) retro platformer that looks <i>very</i> late 1980s and also has that late 1980s difficulty.]]></description>
										<content:encoded><![CDATA[<p>A few days ago the indie game <a href="http://www.ninjasenki.com/">Ninja Senki</a> was released after a year of development. In short, it&#8217;s a Ninja Gaiden inspired (a lot of pages say Mega Man but I don&#8217;t agree with that) retro platformer that looks <i>very</i> late 1980s and also has that late 1980s difficulty.</p>
<p>The game is <i>hard</i>. This is why it reminds me more of Ninja Gaiden (besides the theme) than Mega Man. The gameplay is very simple, in that you can only run, jump and throw shuriken. You can also double jump once while airborne and that skill is available and required from the beginning. Which is perfectly fine. The game chooses a gameplay style and sticks to it with no afterthoughts. The gameplay feels perfect and the high difficulty doesn&#8217;t feel unfair as it would with controls that were less than perfect. The game also supports <a href="http://www.retrousb.com/index.php?cPath=21">gamepads</a>.</p>
<p><a href="http://kometbomb.net/wp-content/uploads/2010/12/ns_screenshot211.png"><img decoding="async" loading="lazy" src="http://kometbomb.net/wp-content/uploads/2010/12/ns_screenshot211.png" alt="Ninja Senki screenshot" title="Ninja Senki screenshot from a later level" width="320" height="288" class="alignright size-full wp-image-795" srcset="http://kometbomb.net/wp-content/uploads/2010/12/ns_screenshot211.png 320w, http://kometbomb.net/wp-content/uploads/2010/12/ns_screenshot211-250x225.png 250w" sizes="(max-width: 320px) 100vw, 320px" /></a> I really liked the music and sound effects, they&#8217;re pretty much 100-percent authentic (<a href="http://famitracker.shoodot.net/">FamiTracker</a> was used to create the sound effects which pretty much makes it sound exactly like a NES game with the chiptune background music). The graphics are simple, obviously, since they imitate the Gameboy resolution (160&#215;144) and the NES palette limitations. In my opinion, some of the graphics could have benefited from some variation. Especially, the few first levels look very monotone and boring compared to the later levels with more colorful backgrounds. It still looks fine, though. But as far as first impressions go, I saw more interesting stuff in the trailer than in the first few minutes of the game.</p>
<p>There are multiple endings depending on how well you play which is great considering how hard the game is. It feels like the game knows it&#8217;s way too difficult for 2010  so it has some slack (as long as you play your eyes open, you&#8217;ll probably be able to buy a continue or two with your score) but still would like you to play a perfect game. There are no save games which I think is not too bad considering it adds to the feeling (you have to play from beginning to end in one sitting just like you did as a kid) but since people who love retro games are not children anymore and actually have stuff to do, the game should have at least some way to continue the game.</p>
<p>The game is free (I was a bit surprised of this) and feels great so anyone interested in challenging platformers should check it out.</p>
<p class="aligncenter"><span style="text-align: center; display: block;"><iframe loading="lazy" src="http://player.vimeo.com/video/17794020?title=0&amp;byline=0&amp;portrait=0" width="400" height="360" frameborder="0"></iframe></span></p>

<div class="wp_rp_wrap  wp_rp_plain" ><div class="wp_rp_content"><h3 class="related_post_title">You might also like...</h3><ul class="related_post wp_rp"><li data-position="0" data-poid="in-268" data-post-type="none" ><a href="http://kometbomb.net/2008/06/18/thrustlikes/" class="wp_rp_title">Thrustlikes</a></li><li data-position="1" data-poid="in-249" data-post-type="none" ><a href="http://kometbomb.net/2008/04/10/rom-check-fail/" class="wp_rp_title">ROM CHECK FAIL</a></li><li data-position="2" data-poid="in-611" data-post-type="none" ><a href="http://kometbomb.net/2009/09/22/introducing-my-latest-projects/" class="wp_rp_title">Introducing My Latest Projects</a></li><li data-position="3" data-poid="in-219" data-post-type="none" ><a href="http://kometbomb.net/2008/03/09/dev-stories-from-the-past/" class="wp_rp_title">Dev Stories from the Past</a></li><li data-position="4" data-poid="in-180" data-post-type="none" ><a href="http://kometbomb.net/2008/02/21/awesome-games-that-are-also-free/" class="wp_rp_title">Awesome games that are also free</a></li></ul></div></div>
]]></content:encoded>
					
		
		
			</item>
	</channel>
</rss>
