<?xml version="1.0" encoding="UTF-8"?>
<!--Generated by Site-Server v6.0.0-9489d352f302c13358503a431019cc1446f74583-1 (http://www.squarespace.com) on Mon, 26 Aug 2024 20:33:39 GMT
--><rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:media="http://www.rssboard.org/media-rss" version="2.0"><channel><title>Tutorials Articles - Dustlayer</title><link>https://dustlayer.com/c64-coding-tutorials/</link><lastBuildDate>Sat, 28 Nov 2015 21:43:53 +0000</lastBuildDate><language>en-US</language><generator>Site-Server v6.0.0-9489d352f302c13358503a431019cc1446f74583-1 (http://www.squarespace.com)</generator><description><![CDATA[]]></description><item><title>Episode 3-9: Greetings, Acknowledgments and Links</title><dc:creator>actraiser</dc:creator><pubDate>Thu, 23 May 2013 20:33:57 +0000</pubDate><link>https://dustlayer.com/c64-coding-tutorials/2013/5/24/episode-3-9-greetings-acknowledgments-and-links</link><guid isPermaLink="false">511651d6e4b0a31c035e30aa:5117493de4b085e20f7f2f40:51961f16e4b0cc86d60c917f</guid><description><![CDATA[<p><strong>Synopsis:</strong> The Greetings and Acknowledgments for Spritro. Without the help and resources it would have taken much longer to publish this Episode. </p>

<p><strong>Download via <a href="https://dustlayer.com/c64-coding-tutorials/2013/5/24/episode-3-1-spritro-an-intro-with-a-sprite">dust</a>:</strong> $ dust tutorials (select 'spritro') <br />
<strong>Github Repository:</strong> <a href="https://github.com/actraiser/dust-tutorial-c64-spritro" target="_new">Spritro Source Code on Github</a>  </p>

<ul>
<li><a href="https://dustlayer.com/c64-coding-tutorials/2013/5/24/episode-3-1-spritro-an-intro-with-a-sprite">Episode 3-1: Spritro - An Intro with a Sprite</a></li>
<li><a href="https://dustlayer.com/c64-coding-tutorials/2013/5/24/episode-3-2-creating-the-shapes-hello-spritepad">Episode 3-2: Creating the Shapes - Hello SpritePad</a></li>
<li><a href="https://dustlayer.com/c64-coding-tutorials/2013/5/24/episode-3-3-loading-shapes-and-grasping-symbols">Episode 3-3: Loading Shapes and grasping Symbols</a></li>
<li><a href="https://dustlayer.com/c64-coding-tutorials/2013/5/24/episode-3-4-flying-the-space-ship-off-course">Episode 3-4: Flying the Space Ship off Course</a></li>
<li><a href="https://dustlayer.com/c64-coding-tutorials/2013/5/24/episode-3-5-taking-command-of-the-ship-controls">Episode 3-5: Taking Command of the Ship Controls</a></li>
<li><a href="https://dustlayer.com/c64-coding-tutorials/2013/5/24/episode-3-6-custom-character-sets-hello-charpad">Episode 3-6: Custom Character Sets - Hello CharPad</a></li>
<li><a href="https://dustlayer.com/c64-coding-tutorials/2013/5/24/episode-3-7-creating-pseudo-timers-for-color-cycle">Episode 3-7: Creating Pseudo Timers for Color Cycle</a>d</li>
<li><a href="https://dustlayer.com/c64-coding-tutorials/2013/5/24/episode-3-8-if-the-sid-doesnt-fit-use-a-bigger-hammer">Episode 3-8: If the SID doesn't fit, use a bigger Hammer</a></li>
<li><strong>Episode 3-9: Greetings, Acknowledgments and Links</strong></li>
</ul>

<hr />



  <p>​Writing this Episode would have not been possible without lots of information spread all over the net. Here are some acknowledgments.</p><h3>Assets</h3><p><strong>Spritro Font:</strong> Rambo - First Blood Part II (Ocean Software)​<br><strong>Spritro Music</strong>: Empty (512 Bytes) by 4-Mat<br><strong>Spritro Sprite:</strong> Uridium (Hewson)</p><h3>External Resources</h3><p><strong></strong><span><strong>Episode 3-2: Creating the Shapes - Hello SpritePad</strong></span><br><span></span></p><p>SpritePad 1.8.1 is a program by ​SubChrist Software <a href="http://csdb.dk/release/?id=100657" target="_blank">[Download]</a><br>WineBottler is a program by Mike Kronenberg <a href="http://winebottler.kronenberg.org/" target="_blank">[Download]</a></p><p><strong>Episode 3-4: Flying the Space Ship off Course</strong><br></p><p>Top/Bottom Border Routine by HCL/Booze Design <a href="http://codebase64.org/doku.php?id=base:removing_the_top_bottom_border" target="_blank">[Link]</a><br>Explanation inspired by Forums Post by Ferris<a href="http://www.dbfinteractive.com/forum/index.php?topic=4477.0" target="_blank"> [Link]​</a></p><p></p><p><strong>Episode 3-5: Taking Command of the Ship Controls</strong></p><p>Keyboard Matrix based on an ASCII Table by TWW <a href="http://codebase64.org/doku.php?id=base:reading_the_keyboard#dc00_dc01_reference_for_english_keyboards" target="_blank">[Link]</a>​</p><p><strong>Episode 3-6: Custom Character Sets - Hello CharPad</strong></p><p><strong></strong>CharPad 1.8.3 is a program by SubChrist Software <a href="http://csdb.dk/release/?id=101863" target="_blank">[Download]</a>​</p><p><span></span><strong><span>Episode 3-8: If the SID doesn't fit, use a bigger Hammer</span></strong><br></p><p><strong></strong>SidReloc is an utility coded by ​Linus Akesson <a href="http://www.linusakesson.net/software/sidreloc/" target="_blank">[Download]</a></p><h3>​Greetings</h3><p>Greetings go out to the 90+ Likers of the <a href="http://www.facebook.com/dustlayer.c64.coding" target="_blank">Dustlayer Facebook Page</a>​, the guys idling in #c-64 who always have great input when I have questions and likewise to the people sending me very encouraging emails and do comments on the blog postings. Special shout out to Diamenta Princessa who runs <a href="http://www.commocore.com/" target="_blank">Commocore</a>!&nbsp;</p><p>Thank you all!&nbsp;</p><p>-act</p><p></p><p></p><p></p><p></p><p></p><p></p><p></p><p>​</p>]]></description><media:content type="image/png" url="https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1369341633784-887FC40QWLV7CWXQTHI0/518cf3ffe4b05a048098403e+%281%29.png?format=1500w" medium="image" isDefault="true" width="300" height="74"><media:title type="plain">Episode 3-9: Greetings, Acknowledgments and Links</media:title></media:content></item><item><title>Episode 3-8: If the SID doesn't fit, use a bigger Hammer</title><dc:creator>actraiser</dc:creator><pubDate>Thu, 23 May 2013 20:33:08 +0000</pubDate><link>https://dustlayer.com/c64-coding-tutorials/2013/5/24/episode-3-8-if-the-sid-doesnt-fit-use-a-bigger-hammer</link><guid isPermaLink="false">511651d6e4b0a31c035e30aa:5117493de4b085e20f7f2f40:518cf3ffe4b05a048098403e</guid><description><![CDATA[<p><strong>Synopsis:</strong> Sometimes you want to use a SID file which is set up for a special memory address which is not aligned with you own memory strategy. I introduce a great tool to fix this. </p>

<p><strong>Download via <a href="https://dustlayer.com/c64-coding-tutorials/2013/5/24/episode-3-1-spritro-an-intro-with-a-sprite">dust</a>:</strong> $ dust tutorials (select 'spritro') <br />
<strong>Github Repository:</strong> <a href="https://github.com/actraiser/dust-tutorial-c64-spritro" target="_new">Spritro Source Code on Github</a>  </p>

<ul>
<li><a href="https://dustlayer.com/c64-coding-tutorials/2013/5/24/episode-3-1-spritro-an-intro-with-a-sprite">Episode 3-1: Spritro - An Intro with a Sprite</a></li>
<li><a href="https://dustlayer.com/c64-coding-tutorials/2013/5/24/episode-3-2-creating-the-shapes-hello-spritepad">Episode 3-2: Creating the Shapes - Hello SpritePad</a></li>
<li><a href="https://dustlayer.com/c64-coding-tutorials/2013/5/24/episode-3-3-loading-shapes-and-grasping-symbols">Episode 3-3: Loading Shapes and grasping Symbols</a></li>
<li><a href="https://dustlayer.com/c64-coding-tutorials/2013/5/24/episode-3-4-flying-the-space-ship-off-course">Episode 3-4: Flying the Space Ship off Course</a></li>
<li><a href="https://dustlayer.com/c64-coding-tutorials/2013/5/24/episode-3-5-taking-command-of-the-ship-controls">Episode 3-5: Taking Command of the Ship Controls</a></li>
<li><a href="https://dustlayer.com/c64-coding-tutorials/2013/5/24/episode-3-6-custom-character-sets-hello-charpad">Episode 3-6: Custom Character Sets - Hello CharPad</a></li>
<li><a href="https://dustlayer.com/c64-coding-tutorials/2013/5/24/episode-3-7-creating-pseudo-timers-for-color-cycle">Episode 3-7: Creating Pseudo Timers for Color Cycle</a></li>
<li><strong>Episode 3-8: If the SID doesn't fit, use a bigger Hammer</strong></li>
<li><a href="https://dustlayer.com/c64-coding-tutorials/2013/5/24/episode-3-9-greetings-acknowledgments-and-links">Episode 3-9: Greetings, Acknowledgments and Links</a></li>
</ul>

<hr />



  <h3>The nature of playing back a SID file</h3><p>A SID file is more than just some music data. A SID comes with everything you need to play back the music too. So there is Replay Routine, the actual Music Information and some SID header. ​No matter which Replay Routine is used, whether it be custom or something standardized due some popular Music Editor the procedure to play a SID file is always the same after loaded into memory:</p><ol><li>Initialize the Playback routine once by jumping to the SIDs init address</li><li>​Trigger the Play Routine Address with every screen refresh</li></ol><p>​When there are subtunes you also may want to actually select beforehand which tune to play back. The common convention is to set the X-Register to the desired subtune number before initializing the SID.</p><p>It also turned out to be pretty standard to store the SID file starting at memory location $1000 and program the replay routines accordingly. The main reason is that $1000 - $1fff are overshadowed with the Character Generator ROM so this place is not really usable to the VIC-II which can not access for example graphics you store in the RAM under ROM in that area. It is important to understand that the SID actually defines itself where it wants to be located. If you put a SID file that is&nbsp;intended&nbsp;to be put at $1000 into a different memory location it just might now work anymore.&nbsp;</p><p>There are SIDs which require other locations than $1000 though and when you want to use those in your "standard" intro you may run into problems. ​The good news is that this can usually be very easily fixed with a tool released in 2013 actually - SidReloc. &nbsp;SidReloc is actually installed when you use DUST. If you use your own environment you have to download the&nbsp;<a href="http://www.linusakesson.net/software/sidreloc/" target="_blank">SidReloc</a>&nbsp;source code and compile it yourself.</p><p>Let's look for a SID tune which is not using the standard location to demonstrate SidReloc magic. </p><h3>Selecting a guinea pig</h3>

































































 

  
  
    

      

      
        <figure class="
              sqs-block-image-figure
              intrinsic
            "
        >
          
        
        

        
          
            
          
            
                
                
                
                
                
                
                
                <img data-stretch="false" data-image="https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1368192072072-SLH92I5T5N54JM746S5G/Screen+Shot+2013-05-10+at+3.20.57+PM.png" data-image-dimensions="406x287" data-image-focal-point="0.5,0.5" alt="" data-load="false" elementtiming="system-image-block" src="https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1368192072072-SLH92I5T5N54JM746S5G/Screen+Shot+2013-05-10+at+3.20.57+PM.png?format=1000w" width="406" height="287" sizes="(max-width: 640px) 100vw, (max-width: 767px) 100vw, 100vw" onload="this.classList.add(&quot;loaded&quot;)" srcset="https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1368192072072-SLH92I5T5N54JM746S5G/Screen+Shot+2013-05-10+at+3.20.57+PM.png?format=100w 100w, https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1368192072072-SLH92I5T5N54JM746S5G/Screen+Shot+2013-05-10+at+3.20.57+PM.png?format=300w 300w, https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1368192072072-SLH92I5T5N54JM746S5G/Screen+Shot+2013-05-10+at+3.20.57+PM.png?format=500w 500w, https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1368192072072-SLH92I5T5N54JM746S5G/Screen+Shot+2013-05-10+at+3.20.57+PM.png?format=750w 750w, https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1368192072072-SLH92I5T5N54JM746S5G/Screen+Shot+2013-05-10+at+3.20.57+PM.png?format=1000w 1000w, https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1368192072072-SLH92I5T5N54JM746S5G/Screen+Shot+2013-05-10+at+3.20.57+PM.png?format=1500w 1500w, https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1368192072072-SLH92I5T5N54JM746S5G/Screen+Shot+2013-05-10+at+3.20.57+PM.png?format=2500w 2500w" loading="lazy" decoding="async" data-loader="sqs">

            
          
        
          
        

        
      
        </figure>
      

    
  






  <p>​Empty (512 Bytes) by 4-Mat is a brillant SID - short yet powerful. I can listen to it like forever. It also sets a good mood for the Spritro. To find out it's init and play address on Mac we can open it in <a href="http://www.sidmusic.org/sidplay/mac/" target="_blank">SidPlay</a>&nbsp;and check the Info Window. Let's look at the original SID file!</p><p>Load Address is $0801 which is actually the start of BASIC in the C64 memory, than Init Address is $09ed and last but not least, the Play Routine resides at $0804.​</p><p>This does not go along well with our requirements to have it start somewhere at $1000. ​</p><p></p><p>​</p>


























  <p>Let's open the terminal and run SidReloc against that SID file. By default it will try to relocate the SID to $1000 but you can also specify any other location as long as it is the beginning of a page in memory. For clarification, a page is an expression for 256 Bytes of Memory. The Commodore C64 therefor has 256 Pages as 256 Bytes times 256 equals 65536 Bytes. Even easier is to remember that the ZeroPage ranges from $0000 to $00FF, Page 1 from $0100 to $01FF and so forth. Since we want to use the area starting at address $1000, we don't need to specify anything but for the sake of&nbsp;completeness&nbsp;I put down the full command in the terminal screenshot below:&nbsp;</p><p><strong>sidreloc --page 10 empty_512.bytes.sid empty_1000.sid</strong></p>

































































 

  
  
    

      

      
        <figure class="
              sqs-block-image-figure
              intrinsic
            "
        >
          
        
        

        
          
            
          
            
                
                
                
                
                
                
                
                <img data-stretch="false" data-image="https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1368192035580-PK7OCEFI4FUS6IOZQD0Y/Screen+Shot+2013-05-10+at+3.18.36+PM.png" data-image-dimensions="631x178" data-image-focal-point="0.5,0.5" alt="" data-load="false" elementtiming="system-image-block" src="https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1368192035580-PK7OCEFI4FUS6IOZQD0Y/Screen+Shot+2013-05-10+at+3.18.36+PM.png?format=1000w" width="631" height="178" sizes="(max-width: 640px) 100vw, (max-width: 767px) 100vw, 100vw" onload="this.classList.add(&quot;loaded&quot;)" srcset="https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1368192035580-PK7OCEFI4FUS6IOZQD0Y/Screen+Shot+2013-05-10+at+3.18.36+PM.png?format=100w 100w, https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1368192035580-PK7OCEFI4FUS6IOZQD0Y/Screen+Shot+2013-05-10+at+3.18.36+PM.png?format=300w 300w, https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1368192035580-PK7OCEFI4FUS6IOZQD0Y/Screen+Shot+2013-05-10+at+3.18.36+PM.png?format=500w 500w, https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1368192035580-PK7OCEFI4FUS6IOZQD0Y/Screen+Shot+2013-05-10+at+3.18.36+PM.png?format=750w 750w, https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1368192035580-PK7OCEFI4FUS6IOZQD0Y/Screen+Shot+2013-05-10+at+3.18.36+PM.png?format=1000w 1000w, https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1368192035580-PK7OCEFI4FUS6IOZQD0Y/Screen+Shot+2013-05-10+at+3.18.36+PM.png?format=1500w 1500w, https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1368192035580-PK7OCEFI4FUS6IOZQD0Y/Screen+Shot+2013-05-10+at+3.18.36+PM.png?format=2500w 2500w" loading="lazy" decoding="async" data-loader="sqs">

            
          
        
          
        

        
      
        </figure>
      

    
  






  <p>Looks good so far! SidReloc analyzed the SID and created a new output file empty_1000.sid. &nbsp;Let's load that new file in Sidplay and check again the Info Window. &nbsp;​</p>

































































 

  
  
    

      

      
        <figure class="
              sqs-block-image-figure
              intrinsic
            "
        >
          
        
        

        
          
            
          
            
                
                
                
                
                
                
                
                <img data-stretch="false" data-image="https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1368192048329-51DB0DVH1JJAY9H6VQHX/Screen+Shot+2013-05-10+at+3.19.20+PM.png" data-image-dimensions="410x287" data-image-focal-point="0.5,0.5" alt="" data-load="false" elementtiming="system-image-block" src="https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1368192048329-51DB0DVH1JJAY9H6VQHX/Screen+Shot+2013-05-10+at+3.19.20+PM.png?format=1000w" width="410" height="287" sizes="(max-width: 640px) 100vw, (max-width: 767px) 50vw, 50vw" onload="this.classList.add(&quot;loaded&quot;)" srcset="https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1368192048329-51DB0DVH1JJAY9H6VQHX/Screen+Shot+2013-05-10+at+3.19.20+PM.png?format=100w 100w, https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1368192048329-51DB0DVH1JJAY9H6VQHX/Screen+Shot+2013-05-10+at+3.19.20+PM.png?format=300w 300w, https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1368192048329-51DB0DVH1JJAY9H6VQHX/Screen+Shot+2013-05-10+at+3.19.20+PM.png?format=500w 500w, https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1368192048329-51DB0DVH1JJAY9H6VQHX/Screen+Shot+2013-05-10+at+3.19.20+PM.png?format=750w 750w, https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1368192048329-51DB0DVH1JJAY9H6VQHX/Screen+Shot+2013-05-10+at+3.19.20+PM.png?format=1000w 1000w, https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1368192048329-51DB0DVH1JJAY9H6VQHX/Screen+Shot+2013-05-10+at+3.19.20+PM.png?format=1500w 1500w, https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1368192048329-51DB0DVH1JJAY9H6VQHX/Screen+Shot+2013-05-10+at+3.19.20+PM.png?format=2500w 2500w" loading="lazy" decoding="async" data-loader="sqs">

            
          
        
          
        

        
      
        </figure>
      

    
  






  <p>Et Voila - the SID file has been relocated!</p><p> The Load Address is not exactly at $1000 since it must consider the relative Load, Init and Play Address of the original file but it's good enough to utilize the otherwise useless area around our desired memory location. ​</p><p>​</p><p>​</p>


























  <p>We finally load the SID file in&nbsp;<strong>config_resources.asm</strong>&nbsp;and setup the two symbols&nbsp;<strong>init_sid</strong>&nbsp;and&nbsp;<strong>play_sid</strong>&nbsp;in in&nbsp;<strong>config_symbols.asm</strong>&nbsp;so we don't have to remember the addresses. &nbsp;In our Interrupt Setup routine in&nbsp;<strong>main.asm</strong>&nbsp;we initialize the SID with<strong>&nbsp;jsr init_sid</strong>&nbsp;and from there we just call&nbsp;<strong>jsr&nbsp;</strong><strong>play_sid</strong>&nbsp;within our custom interrupt 50 times a second. Everything works just fine!&nbsp;</p><p>SidReloc is a really a nice little utility.&nbsp;</p><p>-act</p><p>​</p>]]></description></item><item><title>Epsiode 3-7 - Creating Pseudo Timers for Color Cycle</title><dc:creator>actraiser</dc:creator><pubDate>Thu, 23 May 2013 17:22:41 +0000</pubDate><link>https://dustlayer.com/c64-coding-tutorials/2013/5/24/episode-3-7-creating-pseudo-timers-for-color-cycle</link><guid isPermaLink="false">511651d6e4b0a31c035e30aa:5117493de4b085e20f7f2f40:51938b95e4b09d4594e6e533</guid><description><![CDATA[<p><strong>Synopsis:</strong> For our two color cycle effects we experiment with different ideas where to source timing information from.</p>

<p><strong>Download via <a href="https://dustlayer.com/c64-coding-tutorials/2013/5/24/episode-3-1-spritro-an-intro-with-a-sprite">dust</a>:</strong> $ dust tutorials (select 'spritro') <br />
<strong>Github Repository:</strong> <a href="https://github.com/actraiser/dust-tutorial-c64-spritro" target="_new">Spritro Source Code on Github</a>  </p>

<ul>
<li><a href="https://dustlayer.com/c64-coding-tutorials/2013/5/24/episode-3-1-spritro-an-intro-with-a-sprite">Episode 3-1: Spritro - An Intro with a Sprite</a></li>
<li><a href="https://dustlayer.com/c64-coding-tutorials/2013/5/24/episode-3-2-creating-the-shapes-hello-spritepad">Episode 3-2: Creating the Shapes - Hello SpritePad</a></li>
<li><a href="https://dustlayer.com/c64-coding-tutorials/2013/5/24/episode-3-3-loading-shapes-and-grasping-symbols">Episode 3-3: Loading Shapes and grasping Symbols</a></li>
<li><a href="https://dustlayer.com/c64-coding-tutorials/2013/5/24/episode-3-4-flying-the-space-ship-off-course">Episode 3-4: Flying the Space Ship off Course</a></li>
<li><a href="https://dustlayer.com/c64-coding-tutorials/2013/5/24/episode-3-5-taking-command-of-the-ship-controls">Episode 3-5: Taking Command of the Ship Controls</a></li>
<li><a href="https://dustlayer.com/c64-coding-tutorials/2013/5/24/episode-3-6-custom-character-sets-hello-charpad">Episode 3-6: Custom Character Sets - Hello CharPad</a></li>
<li><strong>Episode 3-7: Creating Pseudo Timers for Color Cycle</strong></li>
<li><a href="https://dustlayer.com/c64-coding-tutorials/2013/5/24/episode-3-8-if-the-sid-doesnt-fit-use-a-bigger-hammer">Episode 3-8: If the SID doesn't fit, use a bigger Hammer</a></li>
<li><a href="https://dustlayer.com/c64-coding-tutorials/2013/5/24/episode-3-9-greetings-acknowledgments-and-links">Episode 3-9: Greetings, Acknowledgments and Links</a></li>
</ul>

<hr />



  <h3>A different Color Cycle Effect</h3><p>In the first tutorial we used a table with values to generate a nice color washing effect. This time we will use a different source to cycle through color information across all our characters. ​Along the way we will also flip colors in the side borders.&nbsp;<span>​</span></p>

































































 

  
  
    

      

      
        <figure class="
              sqs-block-image-figure
              intrinsic
            "
        >
          
        
        

        
          
            
              
              
          
            
                
                
                
                
                
                
                
                <img data-stretch="true" data-image="https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1369228209020-8TSJV74SW9FLOXY7MP97/dustlayer.com-color-cycle-spritro-c64.png" data-image-dimensions="353x88" data-image-focal-point="0.5,0.5" alt="" data-load="false" elementtiming="system-image-block" src="https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1369228209020-8TSJV74SW9FLOXY7MP97/dustlayer.com-color-cycle-spritro-c64.png?format=1000w" width="353" height="88" sizes="(max-width: 640px) 100vw, (max-width: 767px) 100vw, 100vw" onload="this.classList.add(&quot;loaded&quot;)" srcset="https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1369228209020-8TSJV74SW9FLOXY7MP97/dustlayer.com-color-cycle-spritro-c64.png?format=100w 100w, https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1369228209020-8TSJV74SW9FLOXY7MP97/dustlayer.com-color-cycle-spritro-c64.png?format=300w 300w, https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1369228209020-8TSJV74SW9FLOXY7MP97/dustlayer.com-color-cycle-spritro-c64.png?format=500w 500w, https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1369228209020-8TSJV74SW9FLOXY7MP97/dustlayer.com-color-cycle-spritro-c64.png?format=750w 750w, https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1369228209020-8TSJV74SW9FLOXY7MP97/dustlayer.com-color-cycle-spritro-c64.png?format=1000w 1000w, https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1369228209020-8TSJV74SW9FLOXY7MP97/dustlayer.com-color-cycle-spritro-c64.png?format=1500w 1500w, https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1369228209020-8TSJV74SW9FLOXY7MP97/dustlayer.com-color-cycle-spritro-c64.png?format=2500w 2500w" loading="lazy" decoding="async" data-loader="sqs">

            
          
        
            
          
        

        
          
          <figcaption class="image-caption-wrapper">
            <p>​another color cycle effect for text and side borders</p>
          </figcaption>
        
      
        </figure>
      

    
  






  <h3>Two ways of Timing the uncommon Way</h3><p>Programming the C64 is really about trying things - sometimes not the standard way, sometimes not even the smart way. The approach I took is probably even stupid but it fulfilled its purpose. Coding the C64 is really not about the greatest algorithm but quite the contrary you sometimes need to be sloppy to save cycles or achieve a certain effect in the given number of CPU cycles.</p><p>For the color cycle effect on the letters in Spritro I wanted to cycle 16 colors from right to left, actually 15 because I want to skip a black foreground color. To have a good looking cycle speed the cycle&nbsp;should&nbsp;proceed every second screen refresh at most. &nbsp;Instead of wasting another memory location to keep progress of the colors I thought why not use the ship animation pointer. It has 16 Frames after all and is updated every two screen refreshes already - that seemed to fit nicely with the 16 color values I want to cycle through.&nbsp;</p><p>In the same subroutine I also let the side borders flip between to color states - dark blue and light blue. This again should be executed significantly slower. I thought with a bit of trial and error I could sync it to the lead instrument of the SID tune. ​We know how to flip some state already with a simple EOR instruction on some reserved Byte. But we also need to delay the switching.</p><p>Let's check the code in <strong>sub_color_cycle.asm</strong> on how I approached this. This sub routine is executed in the custom interrupt routine 50 times per second on a PAL machine so I need to take delay actions within the sub routine.</p>


























  <p>​We start by initializing the X-Register with #$00. The X-Register's purpose is to check our column position when writing to the screen. Then we load the<strong> sprite_ship_current_frame</strong> symbol which holds the current shape number displayed within the space ship animation. We cmp against #$0f, the last of the 16 color codes of the C64. If the value is indeed #$0f we skip the next instruction which is incrementing that value. &nbsp;<span>​</span></p><p>We store the current value into Color RAM locations for the three rows of text and then subtract 1 from it. So if the value was for example #$06, it became #$05. We compare if the value is #$00 yet because if this is the case we want to skip the next step - we are not interested in using a Black foreground color. If it is not we increase our X register to step forward in our text. Then we check if we reached the end of the row already by comparing X against #$28 (= Column 40). As long as we have not reached the end of the row we will keep branching back to the <strong>color_inc </strong>label. It will colorize the next character with the current value in the Accumulator and so forth. With this, every character in all three lines of texts are changing color every two screen&nbsp;refreshes.&nbsp;</p><p><span>​Now how did we sync the border flipping color with the SID (kinda...). As already mentioned it is simple trial and error. For the switching logic I used a free memory location and attached the symbol </span><strong>delay_counter</strong><span>&nbsp;to it.&nbsp;Every time&nbsp;we completed to colorize all three lines of text I load the delay pointer into the accumulator and compare it against #$34. If this comparison turns out true I flip the border color by simply loading the current color from $d021 and EOR'ing it against the value #$08. This wil flip dark blue for light blue and vice-versa every time this is executed. If you put in another EOR value it will flip against another color. After that the </span><strong>delay_counter</strong><span> is reseted to #$00.&nbsp;</span><br></p><p>If we have not reached #$34 yet in the<strong> delay_counter</strong>, it is simply incremented and we return from the subroutine. ​This approach will delay the flipping to about ever three seconds which is at least for the first few chords in sync with the music.&nbsp;​It is far from perfect though after a few chords the music and color flipping will be out of sync. It's fine for a first impression though.</p><h3>​ConclusionI</h3><p>​Again this was actually not really smart nor anything near timing perfect. But It just shows that you can do what you want in that machine. If you see an opportunity to create something no matter how strange it might feel - don't hesitate. You don't have always to copy and paste stuff you find on the net. &nbsp;The Commodore C64 gave you an All Access Pass to do whatever you want to do.</p><p>-act</p><p>​</p>]]></description></item><item><title>Episode 3-6: Custom Character Sets - Hello CharPad</title><dc:creator>actraiser</dc:creator><pubDate>Thu, 23 May 2013 16:03:21 +0000</pubDate><link>https://dustlayer.com/c64-coding-tutorials/2013/5/24/episode-3-6-custom-character-sets-hello-charpad</link><guid isPermaLink="false">511651d6e4b0a31c035e30aa:5117493de4b085e20f7f2f40:51938b74e4b09d4594e6e521</guid><description><![CDATA[<p><strong>Synopsis:</strong> Using the Standard C64 Character Set is not really cool, so we will acquire a modfied set taken a C64 game and edit it in another Windows tool which can also run on Mac. </p>

<p><strong>Download via <a href="https://dustlayer.com/c64-coding-tutorials/2013/5/24/episode-3-1-spritro-an-intro-with-a-sprite">dust</a>:</strong> $ dust tutorials (select 'spritro') <br />
<strong>Github Repository:</strong> <a href="https://github.com/actraiser/dust-tutorial-c64-spritro" target="_new">Spritro Source Code on Github</a>  </p>

<ul>
<li><a href="https://dustlayer.com/c64-coding-tutorials/2013/5/24/episode-3-1-spritro-an-intro-with-a-sprite">Episode 3-1: Spritro - An Intro with a Sprite</a></li>
<li><a href="https://dustlayer.com/c64-coding-tutorials/2013/5/24/episode-3-2-creating-the-shapes-hello-spritepad">Episode 3-2: Creating the Shapes - Hello SpritePad</a></li>
<li><a href="https://dustlayer.com/c64-coding-tutorials/2013/5/24/episode-3-3-loading-shapes-and-grasping-symbols">Episode 3-3: Loading Shapes and grasping Symbols</a></li>
<li><a href="https://dustlayer.com/c64-coding-tutorials/2013/5/24/episode-3-4-flying-the-space-ship-off-course">Episode 3-4: Flying the Space Ship off Course</a></li>
<li><a href="https://dustlayer.com/c64-coding-tutorials/2013/5/24/episode-3-5-taking-command-of-the-ship-controls">Episode 3-5: Taking Command of the Ship Controls</a></li>
<li><strong>Episode 3-6: Custom Character Sets - Hello CharPad</strong></li>
<li><a href="https://dustlayer.com/c64-coding-tutorials/2013/5/24/episode-3-7-creating-pseudo-timers-for-color-cycle">Episode 3-7: Creating Pseudo Timers for Color Cycle</a></li>
<li><a href="https://dustlayer.com/c64-coding-tutorials/2013/5/24/episode-3-8-if-the-sid-doesnt-fit-use-a-bigger-hammer">Episode 3-8: If the SID doesn't fit, use a bigger Hammer</a></li>
<li><a href="https://dustlayer.com/c64-coding-tutorials/2013/5/24/episode-3-9-greetings-acknowledgments-and-links">Episode 3-9: Greetings, Acknowledgments and Links</a></li>
</ul>

<hr />



  <h3>Characters the nice way</h3><p>We used the Standard Commodore Character Set to display some text in our first tutorial but this is kinda lame and you rather want to use custom characters for your on-screen text and scrollers.​</p><p>Again Mac Users are stuck as there are no good tools to work with Characters for the C64 on this platform. Again we are lucky that the Windows Program CharPad will just run fine using Wine. For this chapter we use <a href="http://csdb.dk/release/?id=101863" target="_blank">CharPad 1.8.3</a>&nbsp;which was the latest version at the time of writing. &nbsp;If you have not installed WineBottler yet, you should do it now to run the program.</p><h3>​A brief look on CharPad</h3><p>​CharPad was coded by the same author who did SpritePad so the overall look and feel is similar yet CharPad is the much more complex program as Characters are not only used to build some Letters but in fact for entire tiled-based background graphics. For this intro we will just modify an existing 1x1 Character Set and will look into the many other options within CharPad at another appropriate time. You can check the example directory which has some great Character Sets including lots of tiled-based graphics.</p><p></p><p>Start up CharPad and load the rambo_font.ctm which came with the source code of Spritro. ​Since I already prepared that Character Set there is not really anything to do for the actual Spritro, however, feel free to change letters to your liking and work a bit with the program. At a later point you want to create your own characters.</p>

































































 

  
  
    

      

      
        <figure class="
              sqs-block-image-figure
              intrinsic
            "
        >
          
        
        

        
          
            
              
              
          
            
                
                
                
                
                
                
                
                <img data-stretch="true" data-image="https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1369224528925-Y24W0NVP9SJ8PICDQQKO/dustlayer.com-charpad.png" data-image-dimensions="887x674" data-image-focal-point="0.5,0.5" alt="" data-load="false" elementtiming="system-image-block" src="https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1369224528925-Y24W0NVP9SJ8PICDQQKO/dustlayer.com-charpad.png?format=1000w" width="887" height="674" sizes="(max-width: 640px) 100vw, (max-width: 767px) 100vw, 100vw" onload="this.classList.add(&quot;loaded&quot;)" srcset="https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1369224528925-Y24W0NVP9SJ8PICDQQKO/dustlayer.com-charpad.png?format=100w 100w, https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1369224528925-Y24W0NVP9SJ8PICDQQKO/dustlayer.com-charpad.png?format=300w 300w, https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1369224528925-Y24W0NVP9SJ8PICDQQKO/dustlayer.com-charpad.png?format=500w 500w, https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1369224528925-Y24W0NVP9SJ8PICDQQKO/dustlayer.com-charpad.png?format=750w 750w, https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1369224528925-Y24W0NVP9SJ8PICDQQKO/dustlayer.com-charpad.png?format=1000w 1000w, https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1369224528925-Y24W0NVP9SJ8PICDQQKO/dustlayer.com-charpad.png?format=1500w 1500w, https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1369224528925-Y24W0NVP9SJ8PICDQQKO/dustlayer.com-charpad.png?format=2500w 2500w" loading="lazy" decoding="async" data-loader="sqs">

            
          
        
            
          
        

        
          
          <figcaption class="image-caption-wrapper">
            <p>CharPad after loading the Rambo Font</p>
          </figcaption>
        
      
        </figure>
      

    
  






  <h3>Loading Characters and setting Pointers</h3><p>The Commodore Character Set has a Standard Size of 2 Kbyte which can hold 256 different items. We don't need that many items as we only work with the letters A-Z and some punctuation letters as well as a Heart Symbol which I put at the position of the "]"-letter. It is of course important that the order of the letters match the standard order of the C64 Character Sets so that the screen codes resulting from our text in the sources is adequately converted to the C64 screen.</p><p>In <strong>data_text.asm </strong>​you will find the three lines of text that are displayed on the screen. Notice how I use the "]" character which will be later shown as a heart character.&nbsp;</p><p>Before we load our Character Set into the project we we need to identify some acceptable space in memory and as with the Sprite Data &nbsp;make sure that the VIC-II can actually see the data its selected Bank. In Standard Bank 3 of the VIC-II there are not too many options and we decide to load our small set starting at $3800.&nbsp;</p><p>This is done in <strong>config_resources.asm </strong>and again we need to consider that CharPad exports files with a header with lots of information. Since we only use the raw data without the need to consider anything special we skip all the header information spanning over 24 Bytes and just load the 384 Bytes of the following Character Data into memory. That translates to 48 single Characters each having a size of 8 Bytes or 8x8 Pixels. Lots of them are empty though because I did not bother to clean the Charset up thoughtfully.&nbsp; &nbsp;​</p><p>Once the Character Set is loaded into memory we need to tell the VIC-II where it needs to fetch the data from because it is still pointing to the standard Character Generator ROM and we need to bend that pointer in question to our location at $3800. ​ We do this in the routine we execute only once to write all characters to the screen located in the file <strong>sub_write_text.asm</strong><span>.</span></p><p>​The register we need to store our Character Location at is $d018. As the Standard Character Set is 2Kb large, we have in theory 8 possible location in a 16Kb Bank.&nbsp;<span>So s</span><span>imilar as with the Sprite Pointers we need to make sure that the Character Set is put into a location that can be divided by 2048.&nbsp;</span><span>Unfortunately the options in Bank 3 are limited as a few areas are overshadowed with ROM and the VIC-II can not read RAM information underneath. Location $3800 works for us though.&nbsp;</span></p><p>Now t<span>o store 8 different values of possible Character Set locations we actually only need 3 Bits that can represent the values 0-7. &nbsp;This job is done by <strong>Bit#1 to Bit#3 of $d018</strong>. S</span><span>etting the Bits to $00 will configure the Character Pointer to $0000, using #$02 will point to $0800 &nbsp;and ongoing until the last possible spot which requires the value #$0e to finally point to $3800. This is the last spot because $3800 + $800 (=2048 Bytes) marks the end of the 16Kb of Bank 3 and the VIC-II expects 2Kb of Data for a Character Set..&nbsp;</span></p><p><strong>Here is the code to set the character pointer and draw text to the screen:</strong></p><p></p><p></p><p></p><p></p><p></p><p></p><p></p><p></p><p></p><p>​</p>


























  <p>The output to the screen is the same as in the first tutorial, it's a simple loop over each of the characters in the <strong>data_text.asm</strong>​. We don't set color information at this point as the color cycling effect is being taken care of in <strong>sub_color_cycle.asm</strong>.</p><p></p><p>-act</p>]]></description></item><item><title>Episode 3-5: Taking Command of the Ship Controls</title><dc:creator>actraiser</dc:creator><pubDate>Thu, 23 May 2013 15:52:52 +0000</pubDate><link>https://dustlayer.com/c64-coding-tutorials/2013/5/24/episode-3-5-taking-command-of-the-ship-controls</link><guid isPermaLink="false">511651d6e4b0a31c035e30aa:5117493de4b085e20f7f2f40:512295e3e4b0dce195c895fe</guid><description><![CDATA[<p><strong>Synopsis:</strong> We implement some basic steering controls for our Space Ship using the C64 keyboard.  </p>

<p><strong>Download via <a href="https://dustlayer.com/c64-coding-tutorials/2013/5/24/episode-3-1-spritro-an-intro-with-a-sprite">dust</a>:</strong> $ dust tutorials (select 'spritro') <br />
<strong>Github Repository:</strong> <a href="https://github.com/actraiser/dust-tutorial-c64-spritro" target="_new">Spritro Source Code on Github</a>  </p>

<ul>
<li><a href="https://dustlayer.com/c64-coding-tutorials/2013/5/24/episode-3-1-spritro-an-intro-with-a-sprite">Episode 3-1: Spritro - An Intro with a Sprite</a></li>
<li><a href="https://dustlayer.com/c64-coding-tutorials/2013/5/24/episode-3-2-creating-the-shapes-hello-spritepad">Episode 3-2: Creating the Shapes - Hello SpritePad</a></li>
<li><a href="https://dustlayer.com/c64-coding-tutorials/2013/5/24/episode-3-3-loading-shapes-and-grasping-symbols">Episode 3-3: Loading Shapes and grasping Symbols</a></li>
<li><a href="https://dustlayer.com/c64-coding-tutorials/2013/5/24/episode-3-4-flying-the-space-ship-off-course">Episode 3-4: Flying the Space Ship off Course</a></li>
<li><strong>Episode 3-5: Taking Command of the Ship Controls</strong></li>
<li><a href="https://dustlayer.com/c64-coding-tutorials/2013/5/24/episode-3-6-custom-character-sets-hello-charpad">Episode 3-6: Custom Character Sets - Hello CharPad</a></li>
<li><a href="https://dustlayer.com/c64-coding-tutorials/2013/5/24/episode-3-7-creating-pseudo-timers-for-color-cycle">Episode 3-7: Creating Pseudo Timers for Color Cycle</a></li>
<li><a href="https://dustlayer.com/c64-coding-tutorials/2013/5/24/episode-3-8-if-the-sid-doesnt-fit-use-a-bigger-hammer">Episode 3-8: If the SID doesn't fit, use a bigger Hammer</a></li>
<li><a href="https://dustlayer.com/c64-coding-tutorials/2013/5/24/episode-3-9-greetings-acknowledgments-and-links">Episode 3-9: Greetings, Acknowledgments and Links</a></li>
</ul>

<hr />



  <h3>Steering the Ship</h3><p>The Intro comes with some basic keyboard controls. You can hit the key D to steer the ship downwards to the bottom border area or U to fly upwards to the top. If we would use Kernel routines this would be a no-brainer as all you need to know about what key is currently pressed is stored by the Kernel in a specific memory locations. However, as usual, this is slow compared to accessing the hardware directly. ​</p><p></p><p>​Once you understand how the different Keys are stored in memory and addressed using the CIAs the resulting routine is actually very small.&nbsp;</p><p><strong>Querying the Keyboard Matrix</strong>​</p><p>Your C64 has 66 Keys where SHIFT-LOCK and RESTORE being not part of the internal Keyboard Matrix. RESTORE is connected to the NMI, thus it triggers an non-maskable interrupt when pressed. SHIFT-LOCK is actually a switch and not a key per se so it is like-wise not detectable within the Keyboard Matrix.</p><p>All other 64 keys can be easily addressed and checked using the SCNKEY Kernal routine. However, as already pointed out we want to work without the Kernal, so we need &nbsp;to go one layer deeper into the hardware.</p><p> The Keyboard Matrix System can be imagined as 8x8 Grid where Rows and Columns can be individually accessed by the CIA-1 which is one of two Complex Interface Adapters (CIA 6526) in the Commodore C64. ​</p><p>The ​approach to check for an individual pressed key is actually not very hard. You first need to set up two so-called Data Direction Registers. Then you look at the Keyboard Matrix below and identify the row with your &nbsp;key in question. The value of that Row from that Table needs to be put into the Port Register A at $dc00. When this is done we just need to load the Port Register B $dc01 and test it against a Bit pattern to check if the appropriate key was pressed.</p><p>What needs to be considered is that the Bits in $dc00 and $dc01 are low-active, so if a key is pressed, a Bit is 0, if it is not pressed the Bit is set high.</p><p><strong>Let's do an example!​&nbsp;</strong></p><p></p><p>Below is the matrix as organized between the two Port Register A and Port Register B. ​Next to each key the Screen Code is shown for the sake of completeness but it is not required for the following scan. The testing for keys without supplied Screen Code need some additional checking in other registers which we will not discuss at this point.</p><p><span>So let's check if the "x" key is currently pressed because we may want to exit a program in that case. &nbsp;If we follow the approach outlined above we need to set the Data Direction Registers first so reading is actually possible. Then we write the Bit Pattern of the third row into Port Register A and can afterwards query if Bit#7 of Port Register B to check if it is NOT set. When this is the case the 'x' key is pressed down.</span></p>

































































 

  
  
    

      

      
        <figure class="
              sqs-block-image-figure
              intrinsic
            "
        >
          
        
        

        
          
            
              
              
          
            
                
                
                
                
                
                
                
                <img data-stretch="true" data-image="https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1369219614957-CZ7FU715PJH28C0S3UXN/dustlayer.com-keyboard-matrix-c64.png" data-image-dimensions="880x611" data-image-focal-point="0.5,0.5" alt="" data-load="false" elementtiming="system-image-block" src="https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1369219614957-CZ7FU715PJH28C0S3UXN/dustlayer.com-keyboard-matrix-c64.png?format=1000w" width="880" height="611" sizes="(max-width: 640px) 100vw, (max-width: 767px) 100vw, 100vw" onload="this.classList.add(&quot;loaded&quot;)" srcset="https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1369219614957-CZ7FU715PJH28C0S3UXN/dustlayer.com-keyboard-matrix-c64.png?format=100w 100w, https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1369219614957-CZ7FU715PJH28C0S3UXN/dustlayer.com-keyboard-matrix-c64.png?format=300w 300w, https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1369219614957-CZ7FU715PJH28C0S3UXN/dustlayer.com-keyboard-matrix-c64.png?format=500w 500w, https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1369219614957-CZ7FU715PJH28C0S3UXN/dustlayer.com-keyboard-matrix-c64.png?format=750w 750w, https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1369219614957-CZ7FU715PJH28C0S3UXN/dustlayer.com-keyboard-matrix-c64.png?format=1000w 1000w, https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1369219614957-CZ7FU715PJH28C0S3UXN/dustlayer.com-keyboard-matrix-c64.png?format=1500w 1500w, https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1369219614957-CZ7FU715PJH28C0S3UXN/dustlayer.com-keyboard-matrix-c64.png?format=2500w 2500w" loading="lazy" decoding="async" data-loader="sqs">

            
          
        
            
          
        

        
          
          <figcaption class="image-caption-wrapper">
            <p>​It's easy to check for a pressed key with the CIA-1</p>
          </figcaption>
        
      
        </figure>
      

    
  






  <p><strong>Now for the code:​</strong></p>


























  <p>When you have the table - it is really not hard to follow.&nbsp;</p><p>With this knowledge we can easily test for three different keys, the 'u'-key, the 'd'-key and the 'Space'-key and act accordingly, that is move the ship one Y-Coordinate up or down or exit the program. Additionally we want to add a boundary in the top and bottom of the screen so the ship can not vanish.​</p><p></p>


























  <p>As you can see, it is not very hard to check for a specific key press and take actions accordingly.​ We check for three keys&nbsp;consecutively before we either return with rts or if we identified one of the keys take some action before returning.&nbsp;</p><p>-act</p>]]></description></item><item><title>Episode 3-4: Flying the Space Ship off Course</title><dc:creator>actraiser</dc:creator><pubDate>Thu, 23 May 2013 14:12:01 +0000</pubDate><link>https://dustlayer.com/c64-coding-tutorials/2013/5/24/episode-3-4-flying-the-space-ship-off-course</link><guid isPermaLink="false">511651d6e4b0a31c035e30aa:5117493de4b085e20f7f2f40:51980202e4b00822eb8625a7</guid><description><![CDATA[<p><strong>Synopsis:</strong> Moving an animated Sprite is cool, but moving it across borders of the C64 results in +1 in Street Credibility.  </p>

<p><strong>Download via <a href="https://dustlayer.com/c64-coding-tutorials/2013/5/24/episode-3-1-spritro-an-intro-with-a-sprite">dust</a>:</strong> $ dust tutorials (select 'spritro') <br />
<strong>Github Repository:</strong> <a href="https://github.com/actraiser/dust-tutorial-c64-spritro" target="_new">Spritro Source Code on Github</a>  </p>

<ul>
<li><a href="https://dustlayer.com/c64-coding-tutorials/2013/5/24/episode-3-1-spritro-an-intro-with-a-sprite">Episode 3-1: Spritro - An Intro with a Sprite</a></li>
<li><a href="https://dustlayer.com/c64-coding-tutorials/2013/5/24/episode-3-2-creating-the-shapes-hello-spritepad">Episode 3-2: Creating the Shapes - Hello SpritePad</a></li>
<li><a href="https://dustlayer.com/c64-coding-tutorials/2013/5/24/episode-3-3-loading-shapes-and-grasping-symbols">Episode 3-3: Loading Shapes and grasping Symbols</a></li>
<li><strong>Episode 3-4: Flying the Space Ship off Course</strong></li>
<li><a href="https://dustlayer.com/c64-coding-tutorials/2013/5/24/episode-3-5-taking-command-of-the-ship-controls">Episode 3-5: Taking Command of the Ship Controls</a></li>
<li><a href="https://dustlayer.com/c64-coding-tutorials/2013/5/24/episode-3-6-custom-character-sets-hello-charpad">Episode 3-6: Custom Character Sets - Hello CharPad</a></li>
<li><a href="https://dustlayer.com/c64-coding-tutorials/2013/5/24/epsiode-3-7-creating-pseudo-timers-for-color-cycle">Episode 3-7: Creating Pseudo Timers for Color Cycle</a></li>
<li><a href="https://dustlayer.com/c64-coding-tutorials/2013/5/24/episode-3-8-if-the-sid-doesnt-fit-use-a-bigger-hammer">Episode 3-8: If the SID doesn't fit, use a bigger Hammer</a></li>
<li><a href="https://dustlayer.com/c64-coding-tutorials/2013/5/24/episode-3-9-greetings-acknowledgments-and-links">Episode 3-9: Greetings, Acknowledgments and Links</a></li>
</ul>

<hr />



  <h3>Setting Sail to unknown Territories</h3><p>It's about time to ​to move the Sprite and update it's animations so we have a nice rotating Space Ship flying from right to left. This challenge will actually turn out to be easily achievable. All we need to do is to update the X-Coordinate with every screen refresh and accordingly set our Sprite Pointer to the next shape in the timeline of&nbsp;consecutive&nbsp;Sprite Shapes.&nbsp;</p><p>But first we want to check<strong> main.asm</strong> because this is where we call our subroutines for the move and animate action plus we open the top and bottom borders!​<span>​</span></p>


























  <p>I have removed some of the Custom Interrupt Setup Code as it is identical with the one from the <a href="http://dustlayer.com/c64-coding-tutorials/2013/4/8/episode-2-3-did-i-interrupt-you">"First Intro" Tutorial</a>. ​</p><p>Not surprisingly our main routine has only two responsibilities</p><ol><li>​run any subroutine which needs to be executed once at the beginning of the intro</li><li>install a custom interrupt and run any routines which needs to be executed&nbsp;repeatedly&nbsp;on each screen refresh</li></ol><p>What is different compared to the last tutorial is that the custom interrupt also executes some code after it processed our &nbsp;subroutines. That extra code exploits a VIC-II bug that opens the top and bottom border of the Commodore C64. &nbsp;I will explain this easy but very cool exploit before we continue with the actual trivial Sprite animations and movement. ​</p><p></p><h3>How to trick the VIC-II in not drawing the border</h3><p>Before we go through the code let's examine what the VIC-II actually does during a screen refresh in respect to borders. We look only at the top and bottom border at this point though the side boarders can be opened in a similar fashion but that requires some additional considerations which are out of the scope for this episode. ​</p><p>The C64 can switch between two different screen heights and screen widths. You can select the standard height of 25 visible rows or shrink to 24 rows.&nbsp;Horizontally&nbsp;you are allowed to choose between the default 40 visible columns versus a smaller area with only 38 columns. </p><p>To shrink the rows horizontally one needs to set Bit#3 in the control register $d011 low. By default this Bit is set high so 25 rows are visible which together with the 40 default columns corresponds to the standard 1000 screen locations in a 25 x 40 grid each cell being 8x8 Bits in size. </p><p><strong>Why are there modes which shrink the screen in the first place you may ask?</strong> </p><p>You know that 8x8 Bit Characters can be put on any of the 1000 locations via Screen RAM. This also applies when we use either of the alternative modes for screen height and width. This makes it possible to draw something below not visible area - imagine for example the beginning of &nbsp;a text which soft scrolls from right to left. Without hiding the first scrolling character of your text behind some invisible area the character would just suddenly appear on the screen - which does not look great. By limiting horizontal width by one column to the left and to the right you can not only smoothly scroll in a text from below the extended border into the users focus, you can also equally get them off screen on the opposite side of the screen.&nbsp;</p><p>Vertically for whatever reason only one row which in fact is split can be added to the screen so effectively you have four lines extending the top and and 4 lines extending the bottom border area. I did not find a satisfying answer why you can shrink by two full columns horizontally but only by one row vertically yet . Different theories came up in #c-64, e.g. that the designers might have though that limiting the already small height of 24 rows even further would not be acceptable while shrinking 40 to 38 columns is barely notable. Or that they simply wanted to avoid more costs by saving a few transistors in the chip design It seems to still be mystery after 30 years. &nbsp;</p><p>Whether you scroll something from right to left or from bottom to top it does not really matter. Even four pixels vertically on each side of the screen is fine to gently let something appear into the screen.​</p><p><span>Anyways, we can exploit this mode switching feature to actually make the borders disappear completely. It will come with some constraints like that you can still not put characters in the area where the borders were originally located - you are still restricted to the 1000 Bytes in Screen RAM after all - but Sprites for instance can be freely in that then visible area. ​</span><br></p><p><strong>So how does the trick work? ​</strong></p><p>The VIC-II internally holds an ON and OFF state for both, the top/bottom and the side borders. When it starts drawing the top border for instance the state for top/bottom is set to ON. After it finished drawing - which&nbsp;happens&nbsp;at Raster Line 50 in default 25 rows mode - it will switch the state to OFF to continue with rendering the visible area of the the screen. After the VIC-II has finished drawing the last possible character to that visible area - that is the 1000th location in the 25x40 grid - it &nbsp;will turn the Border State to ON again to draw the bottom border. That happens at Raster Line 250. </p><p>In 24 Row Mode the state&nbsp;switching Border Drawing ON and OFF happens in Raster Line 54 and in Raster Line 246 accordingly. &nbsp;Understood the procedure? <strong>Good, because here comes the actual exploit!</strong>&nbsp;​</p><p>Let's assume we are in 25 rows mode. We start drawing the first Lines of the Top border, that is the Border State is set to ON. The VIC-II turns OFF border at Raster Line 50 as expected. We know that the next time the VIC-II will turn border state ON is at line 250. What we do is to let the VIC-II draw the screen until it reaches Raster Line 249 that is the 25th Row, hence the last visible row on the screen. We wait until it finished drawing that last line in this final row <strong>AND THEN </strong>we clear the Bit#3 of $d011 to instantly switch to 24 rows mode.&nbsp;<strong>There we fooled the VIC-II!&nbsp;</strong></p><p><strong></strong>​What, you ask? What did we do? We switched to 24 Rows Mode <strong>while we already passed the 24th Row</strong>, in fact we are at Row 25. But in 24 Row Mode the VIC-II is supposed to turns Border State ON in Raster Line 246 - a line we already passed. And since &nbsp;we already passed this Raster Line, the VIC-II does not turn ON the border state - it will remain OFF, no Border is drawn. &nbsp;</p><p></p><p></p><p><span>To make this exploit work properly we have to set Bit#3 of $d011 high again before the next screen refresh. We do this on the last line of the screen.</span><br></p>

































































 

  
  
    

      

      
        <figure class="
              sqs-block-image-figure
              intrinsic
            "
        >
          
        
        

        
          
            
              
              
          
            
                
                
                
                
                
                
                
                <img data-stretch="false" data-image="https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1369149714829-YBDVFSAYUGSM6TV52AWC/dustlayer.com-opening-top-bottom-borders-c64.png" data-image-dimensions="837x298" data-image-focal-point="0.5,0.5" alt="" data-load="false" elementtiming="system-image-block" src="https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1369149714829-YBDVFSAYUGSM6TV52AWC/dustlayer.com-opening-top-bottom-borders-c64.png?format=1000w" width="837" height="298" sizes="(max-width: 640px) 100vw, (max-width: 767px) 100vw, 100vw" onload="this.classList.add(&quot;loaded&quot;)" srcset="https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1369149714829-YBDVFSAYUGSM6TV52AWC/dustlayer.com-opening-top-bottom-borders-c64.png?format=100w 100w, https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1369149714829-YBDVFSAYUGSM6TV52AWC/dustlayer.com-opening-top-bottom-borders-c64.png?format=300w 300w, https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1369149714829-YBDVFSAYUGSM6TV52AWC/dustlayer.com-opening-top-bottom-borders-c64.png?format=500w 500w, https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1369149714829-YBDVFSAYUGSM6TV52AWC/dustlayer.com-opening-top-bottom-borders-c64.png?format=750w 750w, https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1369149714829-YBDVFSAYUGSM6TV52AWC/dustlayer.com-opening-top-bottom-borders-c64.png?format=1000w 1000w, https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1369149714829-YBDVFSAYUGSM6TV52AWC/dustlayer.com-opening-top-bottom-borders-c64.png?format=1500w 1500w, https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1369149714829-YBDVFSAYUGSM6TV52AWC/dustlayer.com-opening-top-bottom-borders-c64.png?format=2500w 2500w" loading="lazy" decoding="async" data-loader="sqs">

            
          
        
            
          
        

        
          
          <figcaption class="image-caption-wrapper">
            <p>​We opened the Top/Bottom borders</p>
          </figcaption>
        
      
        </figure>
      

    
  






  <p>The exploit comes with a constraint. Since there is no Screen RAM available behind the borders - remember we still work in a&nbsp;<span>25x40 grid for Characters no matter what - you are not able to write text using standard character into the new visible areas. ​Sprites are fine though as they can move freely across the screen so coders for example started to build Character Sets from Sprite Data and used that in the opened border areas.&nbsp;</span></p><p>We also confused the VIC-II a bit along the way. Since it does not draw any border it just draws SOMETHING into the new uncharted territory. It simply uses whatever is written in the last Byte of the selected Bank. For the default Bank 3 that would be the content of $3fff.&nbsp;<span>&nbsp;We want to to clear that Byte to not have any potential garbage on our screen.&nbsp;</span></p><p><span>The actual exploit is really short and straight forward, let's quickly check the portion of code that achieves this result. ​It is part of our custom interrupt routine which is executed with every screen refresh.&nbsp;</span><br></p>


























  <p>​As just pointed out we clear $3fff to not see any garbage in the border area. &nbsp;Then we wait until Raster Line 249 is reached. This is done by just checking $d012 and loop with <strong>bne *-3</strong> which means to branch back three bytes as long as we have not reached the Raster Line in question. &nbsp;Then we set Bit#3 in $d011 to low to achieve 24 Rows Mode and wait until we reached the end of the screen to set Bit#3 of $d011 high again - that is, switch back to 25 rows mode. This last step is required to make the trick work - in fact the border will not show up anymore.&nbsp;</p>


























  <h3>Moving and Animating the Space Ship</h3><p>Now that we have opened the borders we want to move the ship from right to left in all its glory. For that we want to execute the&nbsp;<strong>update_ship</strong>&nbsp;subroutine 50 times a second. ​Let's look into the code residing in <strong>sub_</strong><strong>update_ship.asm</strong>. </p><p>Since both Moving the Ship and Cycling through the different Shapes is done in this routine we need to delay the latter within the subroutine because otherwise the playback of the animation is simply too fast.&nbsp;</p>


























  <p>Coming from our Custom Interrupt Routine in <strong>main.as</strong>​<strong>m&nbsp;</strong>&nbsp;we jump to the label <strong>update_ship </strong>in<strong> sub_update_ship.asm</strong>.</p><p>We decrease the X-Coordinate register for Sprite#0 at $d000 and check if it it has become #$00 yet. When this happens we need to branch to the label&nbsp;<strong>ship_x_high</strong> and flip the 9th Bit for Sprite#0 accordingly and start over. &nbsp;This will make sure that our Sprite will not reappear in the middle of the screen when reaching the left side of the screen but in fact is set back to the outer right below the side border.&nbsp;</p><p></p><p></p><p></p><p>The next thing we check is the&nbsp;<strong>delay_animation_pointer&nbsp;</strong>​- we did set up this Byte in <strong>config_sprites.asm</strong> before to flip between two states. This is achieved with <strong>eor #$01</strong> which will flip the corresponding Bit#0 between high and low. Whenever the Bit is low we want to delay the animation and just take a short cut and return from the subroutine to wait for the next refresh.&nbsp;</p>

































































 

  
  
    

      

      
        <figure class="
              sqs-block-image-figure
              intrinsic
            "
        >
          
        
        

        
          
            
              
              
          
            
                
                
                
                
                
                
                
                <img data-stretch="false" data-image="https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1369199082589-MVRP9OJJWYEWR3JK2T00/dustlayer.com-formula-memory-address-sprite-pointer-c64.png" data-image-dimensions="256x155" data-image-focal-point="0.5,0.5" alt="" data-load="false" elementtiming="system-image-block" src="https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1369199082589-MVRP9OJJWYEWR3JK2T00/dustlayer.com-formula-memory-address-sprite-pointer-c64.png?format=1000w" width="256" height="155" sizes="(max-width: 640px) 100vw, (max-width: 767px) 100vw, 100vw" onload="this.classList.add(&quot;loaded&quot;)" srcset="https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1369199082589-MVRP9OJJWYEWR3JK2T00/dustlayer.com-formula-memory-address-sprite-pointer-c64.png?format=100w 100w, https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1369199082589-MVRP9OJJWYEWR3JK2T00/dustlayer.com-formula-memory-address-sprite-pointer-c64.png?format=300w 300w, https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1369199082589-MVRP9OJJWYEWR3JK2T00/dustlayer.com-formula-memory-address-sprite-pointer-c64.png?format=500w 500w, https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1369199082589-MVRP9OJJWYEWR3JK2T00/dustlayer.com-formula-memory-address-sprite-pointer-c64.png?format=750w 750w, https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1369199082589-MVRP9OJJWYEWR3JK2T00/dustlayer.com-formula-memory-address-sprite-pointer-c64.png?format=1000w 1000w, https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1369199082589-MVRP9OJJWYEWR3JK2T00/dustlayer.com-formula-memory-address-sprite-pointer-c64.png?format=1500w 1500w, https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1369199082589-MVRP9OJJWYEWR3JK2T00/dustlayer.com-formula-memory-address-sprite-pointer-c64.png?format=2500w 2500w" loading="lazy" decoding="async" data-loader="sqs">

            
          
        
            
          
        

        
          
          <figcaption class="image-caption-wrapper">
            <p>Retrieving the Sprite Pointer Value is simple math.</p>
          </figcaption>
        
      
        </figure>
      

    
  






  <p>If Bit#0 in the&nbsp;<strong>delay_animation_pointer</strong> is set high on the other hand, we want to go forward one step in our animation - that is exchange the current Sprite Shape with the next one. We branch to the <strong>dec_ship_frame </strong>label where increase ​t<span>he Sprite Pointer for Sprite#0 by 1. If there was the value #$80 written in the Sprite Pointer register it now becomes #$81, and in fact, this works fine because #$81 determines the next Sprite Shape location which is residing at $2040. So #$81 &nbsp;is pointing to the next block of 64 Bytes after the first Sprite Shape. </span></p><p>​<span>With this pattern we can just go forward step by step in our 16 shapes by manipulating the Sprite Pointer at the end of Screen RAM by counting up the value.</span></p>

































































 

  
  
    

      

      
        <figure class="
              sqs-block-image-figure
              intrinsic
            "
        >
          
        
        

        
          
            
              
              
          
            
                
                
                
                
                
                
                
                <img data-stretch="false" data-image="https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1369200786051-68H4GBVKPVA35MZ9V4RE/dustlayer.com-sprite-pointer-memory-addresses.png" data-image-dimensions="446x314" data-image-focal-point="0.5,0.5" alt="" data-load="false" elementtiming="system-image-block" src="https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1369200786051-68H4GBVKPVA35MZ9V4RE/dustlayer.com-sprite-pointer-memory-addresses.png?format=1000w" width="446" height="314" sizes="(max-width: 640px) 100vw, (max-width: 767px) 100vw, 100vw" onload="this.classList.add(&quot;loaded&quot;)" srcset="https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1369200786051-68H4GBVKPVA35MZ9V4RE/dustlayer.com-sprite-pointer-memory-addresses.png?format=100w 100w, https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1369200786051-68H4GBVKPVA35MZ9V4RE/dustlayer.com-sprite-pointer-memory-addresses.png?format=300w 300w, https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1369200786051-68H4GBVKPVA35MZ9V4RE/dustlayer.com-sprite-pointer-memory-addresses.png?format=500w 500w, https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1369200786051-68H4GBVKPVA35MZ9V4RE/dustlayer.com-sprite-pointer-memory-addresses.png?format=750w 750w, https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1369200786051-68H4GBVKPVA35MZ9V4RE/dustlayer.com-sprite-pointer-memory-addresses.png?format=1000w 1000w, https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1369200786051-68H4GBVKPVA35MZ9V4RE/dustlayer.com-sprite-pointer-memory-addresses.png?format=1500w 1500w, https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1369200786051-68H4GBVKPVA35MZ9V4RE/dustlayer.com-sprite-pointer-memory-addresses.png?format=2500w 2500w" loading="lazy" decoding="async" data-loader="sqs">

            
          
        
            
          
        

        
          
          <figcaption class="image-caption-wrapper">
            <p>​The location of each Sprite Shape maps perfectly fine to valid Sprite Pointer when the location is&nbsp;divisible&nbsp;by 64 or $40</p>
          </figcaption>
        
      
        </figure>
      

    
  






  <p><span>We additionally need to decrease the current frame counter in the process as we need to keep track somewhere whether we have played back all 16 Shapes yet.&nbsp;</span><span>​</span></p><p>Once this is the case we will reset all pointers back to the beginning. We branch to the label<strong> reset_ship_frames</strong>​ and&nbsp;<span>simply load the&nbsp;</span><strong>sprite_ship_current_frame&nbsp;<span>w</span></strong><strong>i<span>th the total numbers of frames, that is 16. That is how we initialized it in the first place in&nbsp;</span></strong><strong>config_sprites.asm</strong>.&nbsp;<span>Then we load the original value for the Sprite#0 pointer into the respective Pointer Register at $07f7 and everything is ready for restart.&nbsp;</span><span>​</span></p><p>That's it - not much magic here, the most challenging part is to keep track of Bit#9 for the X-Coord. ​</p><p>-act</p>]]></description></item><item><title>Episode 3-3: Loading Shapes and grasping Symbols</title><dc:creator>actraiser</dc:creator><pubDate>Thu, 23 May 2013 13:52:52 +0000</pubDate><link>https://dustlayer.com/c64-coding-tutorials/2013/5/24/episode-3-3-loading-shapes-and-grasping-symbols</link><guid isPermaLink="false">511651d6e4b0a31c035e30aa:5117493de4b085e20f7f2f40:516fb31ee4b0e33555993d99</guid><description><![CDATA[<p><strong>Synopsis:</strong> We will finally load our Sprite into memory and discuss the usage of Symbols along the way.</p>

<p><strong>Download via <a href="https://dustlayer.com/c64-coding-tutorials/2013/5/24/episode-3-1-spritro-an-intro-with-a-sprite">dust</a>:</strong> $ dust tutorials (select 'spritro') <br />
<strong>Github Repository:</strong> <a href="https://github.com/actraiser/dust-tutorial-c64-spritro" target="_new">Spritro Source Code on Github</a>  </p>

<ul>
<li><a href="https://dustlayer.com/c64-coding-tutorials/2013/5/24/episode-3-1-spritro-an-intro-with-a-sprite">Episode 3-1: Spritro - An Intro with a Sprite</a></li>
<li><a href="https://dustlayer.com/c64-coding-tutorials/2013/5/24/episode-3-2-creating-the-shapes-hello-spritepad">Episode 3-2: Creating the Shapes - Hello SpritePad</a></li>
<li><strong>Episode 3-3: Loading Shapes and grasping Symbols</strong></li>
<li><a href="https://dustlayer.com/c64-coding-tutorials/2013/5/24/episode-3-4-flying-the-space-ship-off-course">Episode 3-4: Flying the Space Ship off Course</a></li>
<li><a href="https://dustlayer.com/c64-coding-tutorials/2013/5/24/episode-3-5-taking-command-of-the-ship-controls">Episode 3-5: Taking Command of the Ship Controls</a></li>
<li><a href="https://dustlayer.com/c64-coding-tutorials/2013/5/24/episode-3-6-custom-character-sets-hello-charpad">Episode 3-6: Custom Character Sets - Hello CharPad</a></li>
<li><a href="https://dustlayer.com/c64-coding-tutorials/2013/5/24/episode-3-7-creating-pseudo-timers-for-color-cycle">Episode 3-7: Creating Pseudo Timers for Color Cycle</a></li>
<li><a href="https://dustlayer.com/c64-coding-tutorials/2013/5/24/episode-3-8-if-the-sid-doesnt-fit-use-a-bigger-hammer">Episode 3-8: If the SID doesn't fit, use a bigger Hammer</a></li>
<li><a href="https://dustlayer.com/c64-coding-tutorials/2013/5/24/episode-3-9-greetings-acknowledgments-and-links">Episode 3-9: Greetings, Acknowledgments and Links</a></li>
</ul>

<hr />



  <h3>There is the Sprite - now what?</h3><p>We have stored our 16 Sprite Shapes that make up the Space Ship Animation into a file in SpritePad-format. We have to load it into C64 memory then we want to setup the appropriate VIC-II registers to actually display the Sprite and last but not least we want to run the animation and move the space ship over the screen - smoothly. ​As a bonus, we want to open the top and bottom borders by exploiting a VIC-II bug and let the Space Ship fly freely in that area.&nbsp;</p><p>The source codes in the Spritro project are split up so responsibilities in each file are more or less clear by looking at the file name. Working with the Sprite spans over four different files, each having a very specific set of tasks.&nbsp;</p><ul><li><strong>config_resources.asm&nbsp;</strong>​loads the spritesheet file exported from SpritePad into memory</li><li><strong>config_sprites.asm&nbsp;</strong>​does all sort of setups to display the Sprite on the screen</li><li><strong>main.asm&nbsp;</strong>​sets up our custom interrupt which calls the the subroutine to move and animate the ship. It also uses a trick to open the top and bottom borders.</li><li><strong>update_ship.asm&nbsp;</strong>​includes the subroutines that take care of the animation and movement of the space ship</li></ul><p>Looks like a lot at first glance but actually we are talking about less than 100 lines of code all together for everything Sprite related.&nbsp;<span>​</span></p><p></p><h3>Choosing appropriate Space in Memory</h3><p>Our Sprite has 16 individual frames or Shapes, each 64 Bytes long as they consist of 12 double-wide horizontal pixels * 21 vertical pixels plus an extra byte to pad them to the convenient number 64. This last Byte is used by SpritePad to store whether the Sprite Shape is in MultiColor or Standard Mode plus it holds the individual Sprite Color. Each of the 8 Hardware Sprites can have one of 16 individual colors that it does not share with other Sprites as opposed to the Background Color, MultiColor 1 and MultiColor 2 in the appropriate Mode. &nbsp;</p><p>The 16*64 Bytes or 1 Kbyte of Sprite Data needs to be stored in an area the VIC-II is able to see. As we don't change the Bank the VIC-II looks at on C64 boot time the range we can theoretically use are the 16 Kbytes from $0000 to $3FFF. Before we decide on the location there is one more thing to take into account. The address where the Sprite is stored must be dividable by 64. That is important for the Sprite Pointers I will elaborate about in a bit. I will use $2000 for no special reason. I don't have anything lying around $2000 so this location seems fine. All of our shapes take up 1 Kbyte all together so we are going to occupy the C64 memory from $2000 to $23FF.&nbsp;</p><h3>Loading Data in Order</h3><p>Sometimes it can be tricky to get the order right when loading multiple files into C64 memory. The Index file which is also the file you later compile with your&nbsp;favorite&nbsp;cross assembler or using DUST ​is already structured in a way that should always work fine.&nbsp;</p><p>That&nbsp;<strong>index.asm </strong>​has three responsibilities it takes care in a specific order:&nbsp;</p><ol><li>load external resources (graphics, music, charsets)​ by including <strong>config_resources.asm</strong> at the top.&nbsp;</li><li>set up BASIC loader so we do not have to write SYS 41952 to run the Intro after loading the compiled .prg on the C64</li><li>include all remaining source files with the actual 6502 code starting at a dedicated memory address ​</li></ol><p>We define the memory starting locations for external binary files using some meaningful symbols within the <strong>config_resources.asm </strong>file and then load each resource by defining the starting zone with <strong>* = &lt;our_defined_symbol&gt;&nbsp;</strong>​along with the ACME pseudo operator <strong>!bin&nbsp;</strong>​to actually read the data from disk into the specified location.&nbsp;</p>


























  <p><span>Regarding the Spritesheet we know that the first three bytes of SpritePad 1.8.1-formated files contain a header with color Information for all shared colors but we actually do not really need that information as we can remember the three colors and just skip an extra step of parsing them from the actual file. The !bin command is modified to load 1024 bytes but skipping the first three bytes of the file before loading the data starting at memory address $2000. Similar procedure applies to the SID and Character Set import which will be discussed later. Then inclusion flow is returned to the next statements in <strong>index.asm&nbsp;</strong>​where the BASIC Loader is set up starting at $0801 before all the actual 6502 code is written into memory starting from $c000.&nbsp;</span></p>

































































 

  
  
    

      

      
        <figure class="
              sqs-block-image-figure
              intrinsic
            "
        >
          
        
        

        
          
            
              
              
          
            
                
                
                
                
                
                
                
                <img data-stretch="false" data-image="https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1369319985481-BHQBB38A0IOHCYRAYINZ/dustlayer.com-inclusion-flow.png" data-image-dimensions="594x489" data-image-focal-point="0.5,0.5" alt="" data-load="false" elementtiming="system-image-block" src="https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1369319985481-BHQBB38A0IOHCYRAYINZ/dustlayer.com-inclusion-flow.png?format=1000w" width="594" height="489" sizes="(max-width: 640px) 100vw, (max-width: 767px) 100vw, 100vw" onload="this.classList.add(&quot;loaded&quot;)" srcset="https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1369319985481-BHQBB38A0IOHCYRAYINZ/dustlayer.com-inclusion-flow.png?format=100w 100w, https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1369319985481-BHQBB38A0IOHCYRAYINZ/dustlayer.com-inclusion-flow.png?format=300w 300w, https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1369319985481-BHQBB38A0IOHCYRAYINZ/dustlayer.com-inclusion-flow.png?format=500w 500w, https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1369319985481-BHQBB38A0IOHCYRAYINZ/dustlayer.com-inclusion-flow.png?format=750w 750w, https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1369319985481-BHQBB38A0IOHCYRAYINZ/dustlayer.com-inclusion-flow.png?format=1000w 1000w, https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1369319985481-BHQBB38A0IOHCYRAYINZ/dustlayer.com-inclusion-flow.png?format=1500w 1500w, https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1369319985481-BHQBB38A0IOHCYRAYINZ/dustlayer.com-inclusion-flow.png?format=2500w 2500w" loading="lazy" decoding="async" data-loader="sqs">

            
          
        
            
          
        

        
          
          <figcaption class="image-caption-wrapper">
            <p>​index.asm first loads all external binaries and puts them in defined memory locations, then sets up a basic loader and includes all other code starting at $c000</p>
          </figcaption>
        
      
        </figure>
      

    
  






  <h3>A brief Detour about Symbols and Labels</h3><p><span>When I started getting into 6502 coding the thing which was a source of regular confusion at start was the whole issue with using addressing modes in conjunction with symbols. When I define a symbol, Is it a value, a vector or is it a memory address I refer to? ​During my first steps into 6502 coding It seemed to be totally random when later used with keywords like LDA or STA. But then my eyes opened one day - </span><strong>it is what you would like it to be! &nbsp;Just understand the 6502 addressing modes!</strong><span>​</span><br></p>

































































 

  
  
    

      

      
        <figure class="
              sqs-block-image-figure
              intrinsic
            "
        >
          
        
        

        
          
            
              
              
          
            
                
                
                
                
                
                
                
                <img data-stretch="false" data-image="https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1369130384477-H9E0M2KTUPWUOQW7UBOC/whatever-you-like.jpg" data-image-dimensions="705x416" data-image-focal-point="0.5,0.5" alt="" data-load="false" elementtiming="system-image-block" src="https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1369130384477-H9E0M2KTUPWUOQW7UBOC/whatever-you-like.jpg?format=1000w" width="705" height="416" sizes="(max-width: 640px) 100vw, (max-width: 767px) 100vw, 100vw" onload="this.classList.add(&quot;loaded&quot;)" srcset="https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1369130384477-H9E0M2KTUPWUOQW7UBOC/whatever-you-like.jpg?format=100w 100w, https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1369130384477-H9E0M2KTUPWUOQW7UBOC/whatever-you-like.jpg?format=300w 300w, https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1369130384477-H9E0M2KTUPWUOQW7UBOC/whatever-you-like.jpg?format=500w 500w, https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1369130384477-H9E0M2KTUPWUOQW7UBOC/whatever-you-like.jpg?format=750w 750w, https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1369130384477-H9E0M2KTUPWUOQW7UBOC/whatever-you-like.jpg?format=1000w 1000w, https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1369130384477-H9E0M2KTUPWUOQW7UBOC/whatever-you-like.jpg?format=1500w 1500w, https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1369130384477-H9E0M2KTUPWUOQW7UBOC/whatever-you-like.jpg?format=2500w 2500w" loading="lazy" decoding="async" data-loader="sqs">

            
          
        
            
          
        

        
          
          <figcaption class="image-caption-wrapper">
            <p>​A reference to "Coming to America"&nbsp;</p>
          </figcaption>
        
      
        </figure>
      

    
  






  <p>If you are unfamiliar and confused, just read the <a href="https://dustlayer.com/cpu-6510-articles/2013/5/24/whatever-you-like-coming-to-addressing-modes">knowledge base article on 6510 Addressing Modes</a>&nbsp;to get clarity.</p><p>Let's quickly talk about Symbols as such. <strong>S<span>ymbols</span></strong><span> are not really the same as variables you know from other programming languages. <strong>Labels</strong>&nbsp;are not variables either but mark a starting point within the program code. During assembling those labels and all instructions pointing to the label will point to the corresponding memory address instead - or rather the offset when using branch commands. It is good to know what actually happens during assembling.&nbsp;</span></p><p><span>An assembler passes over a source file and needs to collect the symbols and also labels for resolving future references and doing the actual assembly. T</span><span>he difficult part is to resolve future label references and assemble all code in only one assembler pass. That's why most assemblers are doing<em> two passes</em>. In the first pass the assembler looks for all label and symbol definitions and puts them in an internal table. In the second pass, after the table is set up, it does the actual assembly by translating the operations and replaces labels with the calculated memory locations and also replace all values originating from using Symbols.</span></p><p>For example, in our custom interrupt routine in <strong>main.asm</strong> we jump to the subroutine <strong>color_cycle</strong> which is actually label in the file <strong>sub_color_cycle.asm</strong> . After the first pass the assembler knows the actual memory location of where the subroutine starts. In the second pass it replaces the <strong>jsr color_cycle&nbsp;</strong>instruction with <strong>jsr<span>&nbsp;$c17e</span></strong><span></span><span>&nbsp;. If we look into memory after starting the intro we can see that $c17e is in fact the place where our color_cycle subroutine starts.</span></p><p></p><p></p><h3>Enlightening the VIC-II</h3><p><span>​We know that our sprites are loaded at $2000 but the VIC-II does not yet. The VIC-II actually knows nothing about our intentions to use Sprites in the first place so let's address this in</span><span>&nbsp;</span><strong>code/config_sprites.asm.&nbsp;</strong>​</p>


























  <p>The <strong>config_sprites.asm</strong> file is basically split in three parts. We define some memory locations and values using symbols we need for later use. We then start initializing the locations and some VIC-II sprite registers to get the word out to the street that we want to show our space ship. ​</p><p>​First of all I have &nbsp;to pick two memory locations I know are not occupied by something important in the C64 while the intro is running. I will use $fb and $fc.&nbsp;</p><ul><li><span>$fb will be used to store the currently shown sprite shape within our 16 frames animation. </span></li><li><span>$fc will be used as a flipping Byte which we use to change between two colors in the side borders.&nbsp;</span><br></li></ul><p>The next symbol is a placeholder for the Integer 16 which represents the overall number of used frames/sprite shapes in our animation.&nbsp;</p><p>The <strong>sprinter_pointer_ship </strong>symbol may at first look awkward. We divide what we defined in the symbol <strong>address_sprites</strong> in the <strong>config_resources.asm</strong> by the value $40. That would be $2000 / $40 or 8192 / 64 which translates to $80 respectively 128. ​ $80 is the value that we need to put into the Sprite Pointer for Sprite#0 which is stored at the end of Screen RAM. &nbsp;</p><p><strong>What is a Sprite Pointer?</strong> Each of the last 8 Bytes of Screen RAM define the location of our Sprite Shape currently appointed to the respective Hardware Sprite, hence the name Sprite Pointer. As explained in the <a href="https://dustlayer.com/vic-ii/2013/4/28/vic-ii-for-beginners-part-5-bringing-sprites-in-shape">VIC-II knowledge base article on Sprites</a>&nbsp;one Byte is all we need to address any possible Sprite location in the part of the C64 memory the VIC-II looks at. The reason is that the VIC-II can only see data within a portion of 16 Kbyte of Ram and<strong> 16340 Bytes / 255 possible Byte Values</strong> <strong>translates to 64 Bytes</strong> - the size of a single Shape actually. So in theory a Sprite Shape can be put anywhere in the active VIC-II Bank area by putting the Sprites memory location divided by 64 into the appropriate Sprite Pointer Register. $80 is therefor pointing to our first Sprite Shape out of 16 as $80 (128) * $40 (64) results in $2000, the address we loaded our Spritesheet into. </p><p><strong>What about animation?</strong> We will get to this topic in a later chapter.</p><p>​Next we assign a few values to symbols reflecting the shared colors for theoretically all hardware sprites but we just use Sprite#0. The color information is taken from the SpritePad program - it's not so hard to remember three colors after all so we did not parse the header of the<em> sprites.spr</em> file for this. Likewise the individual ship color is also stored in a symbol.</p><p>​Now we have our symbols set up and can use them to initialize our registers and as a side effect have a much better readability in the process by using all those symbols.&nbsp;<span>&nbsp;​</span></p><p>I already pointed out that a symbol just references to a value whose purpose is then determined by the way you use it in your code, in plain terms, it all comes down what addressing mode you use. ​ The following LDA/STA pairs do simply load some value from a memory location or take an absolute value and store them in a specific register. Again the symbols help us to keep readability but in your mindset you can just replace them for the referenced value and consider any addressing mode syntax in the process.&nbsp;</p><p></p><p></p><p></p><p></p><p>Let's look at the place where we store the location of the Sprite Shape for Sprite#0 into the Sprite Pointer.&nbsp;<span>As already elaborated &nbsp;the location to store the value is the very first of 8 Bytes at the end of Screen RAM. I have defined a symbol called <em>screen_ram</em> in <strong>config_symbols.asm</strong> &nbsp;so using <strong>sta screen ram + $3f8</strong> will indeed store the previous calculated value $80 into the first Sprite Pointer Byte since $0400 which is start of Screen RAM plus $03f8 results in $07f8 - the first of the last 8 Bytes. Why use this complex construct and not just <strong>sta $07f8</strong> instead? If you move Screen RAM for any reason, e.g. you may want to use a different VIC-II bank, you would not need to recalculate the locations of the Sprite Pointer Registers. ​</span></p>

































































 

  
  
    

      

      
        <figure class="
              sqs-block-image-figure
              intrinsic
            "
        >
          
        
        

        
          
            
              
              
          
            
                
                
                
                
                
                
                
                <img data-stretch="false" data-image="https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1369135111667-Z7N1AV722ZWB5GFWK3LB/dustlayer.com-sprite-position-start.png" data-image-dimensions="490x373" data-image-focal-point="0.5,0.5" alt="" data-load="false" elementtiming="system-image-block" src="https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1369135111667-Z7N1AV722ZWB5GFWK3LB/dustlayer.com-sprite-position-start.png?format=1000w" width="490" height="373" sizes="(max-width: 640px) 100vw, (max-width: 767px) 100vw, 100vw" onload="this.classList.add(&quot;loaded&quot;)" srcset="https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1369135111667-Z7N1AV722ZWB5GFWK3LB/dustlayer.com-sprite-position-start.png?format=100w 100w, https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1369135111667-Z7N1AV722ZWB5GFWK3LB/dustlayer.com-sprite-position-start.png?format=300w 300w, https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1369135111667-Z7N1AV722ZWB5GFWK3LB/dustlayer.com-sprite-position-start.png?format=500w 500w, https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1369135111667-Z7N1AV722ZWB5GFWK3LB/dustlayer.com-sprite-position-start.png?format=750w 750w, https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1369135111667-Z7N1AV722ZWB5GFWK3LB/dustlayer.com-sprite-position-start.png?format=1000w 1000w, https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1369135111667-Z7N1AV722ZWB5GFWK3LB/dustlayer.com-sprite-position-start.png?format=1500w 1500w, https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1369135111667-Z7N1AV722ZWB5GFWK3LB/dustlayer.com-sprite-position-start.png?format=2500w 2500w" loading="lazy" decoding="async" data-loader="sqs">

            
          
        
            
          
        

        
          
          <figcaption class="image-caption-wrapper">
            <p>​Our Ship starts in the lower left corner of the screen - invisible at Start.</p>
          </figcaption>
        
      
        </figure>
      

    
  






  <p><span>At the very end we define the starting X/Y coordinates for Sprite#0. Since we set Bit#0 in $d010 high you can basically consider it to be a set 9th Bit for the X-Coordinate or in other words add 256 to whatever is written to $d000. In our case we put $a0 into $d000 so this translates to Decimal 160 plus the 9th Bit which values to 256 and that results in X-Coordinate 416. That is a location outside the visible area which is of course desired so the ship can fly into the&nbsp;scenery. ​</span></p><p><span>For the Y-Coord we chose a value which is &nbsp;actually hidden by the bottom border of the Commodore C64 but since we remove this border later, our Sprite will happily fly along that part of the screen and be visible.&nbsp;</span><br></p><p>Speaking of flying - at the moment the Sprite does not go anywhere - we don't even see it because it's hidden below the right bottom corner. The next chapter will deal with the Ship Animation and Movement.​</p><p>​-act</p><p></p><p></p><p></p><p></p><p>​</p>]]></description></item><item><title>Episode 3-2: Creating the Shapes - Hello SpritePad</title><dc:creator>actraiser</dc:creator><pubDate>Thu, 23 May 2013 12:52:52 +0000</pubDate><link>https://dustlayer.com/c64-coding-tutorials/2013/5/24/episode-3-2-creating-the-shapes-hello-spritepad</link><guid isPermaLink="false">511651d6e4b0a31c035e30aa:5117493de4b085e20f7f2f40:51229511e4b06840010e3573</guid><description><![CDATA[<p><strong>Synopsis:</strong> Creating C64 Sprites - especially on Mac - is not trivial. Here is an easy way to circumvent the problem with non-existing C64 Tools on Mac - we will simply run a Windows tool! </p>

<p><strong>Download via <a href="https://dustlayer.com/c64-coding-tutorials/2013/5/24/episode-3-1-spritro-an-intro-with-a-sprite">dust</a>:</strong> $ dust tutorials (select 'spritro') <br />
<strong>Github Repository:</strong> <a href="https://github.com/actraiser/dust-tutorial-c64-spritro" target="_new">Spritro Source Code on Github</a>  </p>

<ul>
<li><a href="https://dustlayer.com/c64-coding-tutorials/2013/5/24/episode-3-1-spritro-an-intro-with-a-sprite">Episode 3-1: Spritro - An Intro with a Sprite</a></li>
<li><strong>Episode 3-2: Creating the Shapes - Hello SpritePad</strong></li>
<li><a href="https://dustlayer.com/c64-coding-tutorials/2013/5/24/episode-3-3-loading-shapes-and-grasping-symbols">Episode 3-3: Loading Shapes and grasping Symbols</a></li>
<li><a href="https://dustlayer.com/c64-coding-tutorials/2013/5/24/episode-3-4-flying-the-space-ship-off-course">Episode 3-4: Flying the Space Ship off Course</a></li>
<li><a href="https://dustlayer.com/c64-coding-tutorials/2013/5/24/episode-3-5-taking-command-of-the-ship-controls">Episode 3-5: Taking Command of the Ship Controls</a></li>
<li><a href="https://dustlayer.com/c64-coding-tutorials/2013/5/24/episode-3-6-custom-character-sets-hello-charpad">Episode 3-6: Custom Character Sets - Hello CharPad</a></li>
<li><a href="https://dustlayer.com/c64-coding-tutorials/2013/5/24/episode-3-7-creating-pseudo-timers-for-color-cycle">Episode 3-7: Creating Pseudo Timers for Color Cycle</a></li>
<li><a href="https://dustlayer.com/c64-coding-tutorials/2013/5/24/episode-3-8-if-the-sid-doesnt-fit-use-a-bigger-hammer">Episode 3-8: If the SID doesn't fit, use a bigger Hammer</a></li>
<li><a href="https://dustlayer.com/c64-coding-tutorials/2013/5/24/episode-3-9-greetings-acknowledgments-and-links">Episode 3-9: Greetings, Acknowledgments and Links</a></li>
</ul>

<hr />



  <h3>Creating Sprite Shapes on Mac OSX using a Windows Program</h3><p>For moving Sprites over the screen we need Sprite Shapes which is the common term for one single frame of an animated Sprite. For this we want to use some good software - unfortunately such software does not exist on Mac OSX! However, we can use Wine - the Windows Emulator - to run SpritePad on Mac. SpritePad is a free Windows program which comes with everything we need to create Sprite Shapes for our intro.&nbsp;</p><h3>​Getting Windows programs on Mac the easy way</h3><p>​We need to install Wine, however, as with many large open source projects, this can be very painful. Fortunately there are already solutions which install and configure everything you need to run Windows-Programs on a Mac using One-Click installers. The easiest I found is WineBottler. Just <a href="http://winebottler.kronenberg.org/" target="_blank">download it on the official site</a>. &nbsp;Open the .dmg and drag the Wine and the WineBottler application to the <em>/Application</em>-Folder. Then run WineBottler for the first time - it will set up some directories and with that you are good to go.&nbsp;</p><h3>Running SpritePad on Mac</h3><p><a href="http://csdb.dk/release/?id=100657" target="_blank">Download SpritePad</a>&nbsp;and unzip it to a folder of your choice. The clean way would be to put it under&nbsp;<em>~/Wine Files/drive_c/Program Files&nbsp;</em>​which is the directory set up by WineBottler when it was run for the first time but really every other directory works as well. Double-Click on <em>SpritePad.exe</em> and after a short time you should see the User Interface - let's start!<span>​&nbsp;</span></p><p></p><h3>What do we want to achieve?</h3><p>For our little intro we need to animate and move a Sprite from right to left. I went for the traditional space ship but as a matter of fact I am no way skilled to draw and animate a good-looking sprite myself. &nbsp;</p><p>Luckily, SpritePad comes with some pre-bundled examples which&nbsp;include&nbsp;a number of Shapes - in modern environments you would probably call those files&nbsp;spritesheets. We will use one as basis and modify it to our liking. Let's load the <a href="http://www.lemon64.com/?game_id=2766" target="_blank">Uridium</a> spritesheet which is located in the<em> /examples</em> directory of the unzipped SpritePad project. The good thing about using this particular sheet is that it already comes with a great Sprite - the famous Manta Class Space Ship from the game Uridium.</p><p>Our ship is supposed to fly into the screen from the right - go all the way to the left to disappear behind the side border before it shows up again on the opposite side.​</p><p><span>Let's prepare our Spritesheet using SpritePad now.​ Click on </span><em>File-&gt;Open </em><span>then select the </span><em>Examples</em><span> folder and load the Uridium Spritesheet named </span><em>Uridium.spd</em><span>. If you don't want to do the work, just load the Sprites.spr which came with the Spritro Sources.</span><br></p>

































































 

  
  
    

      

      
        <figure class="
              sqs-block-image-figure
              intrinsic
            "
        >
          
        
        

        
          
            
              
              
          
            
                
                
                
                
                
                
                
                <img data-stretch="false" data-image="https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1367931521912-69PSI05DPYU3CBRJGE9F/dustlayer.com-c64-coding-spritepad-start.png" data-image-dimensions="937x683" data-image-focal-point="0.5,0.5" alt="" data-load="false" elementtiming="system-image-block" src="https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1367931521912-69PSI05DPYU3CBRJGE9F/dustlayer.com-c64-coding-spritepad-start.png?format=1000w" width="937" height="683" sizes="(max-width: 640px) 100vw, (max-width: 767px) 100vw, 100vw" onload="this.classList.add(&quot;loaded&quot;)" srcset="https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1367931521912-69PSI05DPYU3CBRJGE9F/dustlayer.com-c64-coding-spritepad-start.png?format=100w 100w, https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1367931521912-69PSI05DPYU3CBRJGE9F/dustlayer.com-c64-coding-spritepad-start.png?format=300w 300w, https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1367931521912-69PSI05DPYU3CBRJGE9F/dustlayer.com-c64-coding-spritepad-start.png?format=500w 500w, https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1367931521912-69PSI05DPYU3CBRJGE9F/dustlayer.com-c64-coding-spritepad-start.png?format=750w 750w, https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1367931521912-69PSI05DPYU3CBRJGE9F/dustlayer.com-c64-coding-spritepad-start.png?format=1000w 1000w, https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1367931521912-69PSI05DPYU3CBRJGE9F/dustlayer.com-c64-coding-spritepad-start.png?format=1500w 1500w, https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1367931521912-69PSI05DPYU3CBRJGE9F/dustlayer.com-c64-coding-spritepad-start.png?format=2500w 2500w" loading="lazy" decoding="async" data-loader="sqs">

            
          
        
            
          
        

        
          
          <figcaption class="image-caption-wrapper">
            <p>​Empty Project when starting spritepad</p>
          </figcaption>
        
      
        </figure>
      

    
  






  <ul>This Uridium-Spritesheet contains 128 different Shapes. When you scroll a bit down using the right side scrollbar you will find the Manta Space Ship and all of its animations. ​</ul>

































































 

  
  
    

      

      
        <figure class="
              sqs-block-image-figure
              intrinsic
            "
        >
          
        
        

        
          
            
              
              
          
            
                
                
                
                
                
                
                
                <img data-stretch="false" data-image="https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1367931534503-SU254LAMPVYP5CPH5RK3/dustlayer.com-c64-coding-uridium-spritesheet.png" data-image-dimensions="706x494" data-image-focal-point="0.5,0.5" alt="" data-load="false" elementtiming="system-image-block" src="https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1367931534503-SU254LAMPVYP5CPH5RK3/dustlayer.com-c64-coding-uridium-spritesheet.png?format=1000w" width="706" height="494" sizes="(max-width: 640px) 100vw, (max-width: 767px) 50vw, 50vw" onload="this.classList.add(&quot;loaded&quot;)" srcset="https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1367931534503-SU254LAMPVYP5CPH5RK3/dustlayer.com-c64-coding-uridium-spritesheet.png?format=100w 100w, https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1367931534503-SU254LAMPVYP5CPH5RK3/dustlayer.com-c64-coding-uridium-spritesheet.png?format=300w 300w, https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1367931534503-SU254LAMPVYP5CPH5RK3/dustlayer.com-c64-coding-uridium-spritesheet.png?format=500w 500w, https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1367931534503-SU254LAMPVYP5CPH5RK3/dustlayer.com-c64-coding-uridium-spritesheet.png?format=750w 750w, https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1367931534503-SU254LAMPVYP5CPH5RK3/dustlayer.com-c64-coding-uridium-spritesheet.png?format=1000w 1000w, https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1367931534503-SU254LAMPVYP5CPH5RK3/dustlayer.com-c64-coding-uridium-spritesheet.png?format=1500w 1500w, https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1367931534503-SU254LAMPVYP5CPH5RK3/dustlayer.com-c64-coding-uridium-spritesheet.png?format=2500w 2500w" loading="lazy" decoding="async" data-loader="sqs">

            
          
        
            
          
        

        
          
          <figcaption class="image-caption-wrapper">
            <p>​This is the Uridium spritesheet</p>
          </figcaption>
        
      
        </figure>
      

    
  













































 

  
  
    

      

      
        <figure class="
              sqs-block-image-figure
              intrinsic
            "
        >
          
        
        

        
          
            
              
              
          
            
                
                
                
                
                
                
                
                <img data-stretch="false" data-image="https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1367931546727-67F2KTXV0MZQQP46GTA6/dustlayer.com-c64-coding-uridium-manta.png" data-image-dimensions="706x492" data-image-focal-point="0.5,0.5" alt="" data-load="false" elementtiming="system-image-block" src="https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1367931546727-67F2KTXV0MZQQP46GTA6/dustlayer.com-c64-coding-uridium-manta.png?format=1000w" width="706" height="492" sizes="(max-width: 640px) 100vw, (max-width: 767px) 50vw, 50vw" onload="this.classList.add(&quot;loaded&quot;)" srcset="https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1367931546727-67F2KTXV0MZQQP46GTA6/dustlayer.com-c64-coding-uridium-manta.png?format=100w 100w, https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1367931546727-67F2KTXV0MZQQP46GTA6/dustlayer.com-c64-coding-uridium-manta.png?format=300w 300w, https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1367931546727-67F2KTXV0MZQQP46GTA6/dustlayer.com-c64-coding-uridium-manta.png?format=500w 500w, https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1367931546727-67F2KTXV0MZQQP46GTA6/dustlayer.com-c64-coding-uridium-manta.png?format=750w 750w, https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1367931546727-67F2KTXV0MZQQP46GTA6/dustlayer.com-c64-coding-uridium-manta.png?format=1000w 1000w, https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1367931546727-67F2KTXV0MZQQP46GTA6/dustlayer.com-c64-coding-uridium-manta.png?format=1500w 1500w, https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1367931546727-67F2KTXV0MZQQP46GTA6/dustlayer.com-c64-coding-uridium-manta.png?format=2500w 2500w" loading="lazy" decoding="async" data-loader="sqs">

            
          
        
            
          
        

        
          
          <figcaption class="image-caption-wrapper">
            <p>​The Manta Ship of Uridium</p>
          </figcaption>
        
      
        </figure>
      

    
  






  <h3>SpritePad 101</h3><p>Let's quickly run through some of the buttons and boxes on SpritePad. Lots of the stuff should make sense to you when you read all other articles on Dustlayer.com. In the top left you have the 12x21 grid with double wide Pixels which is typical for a Multicolor Sprite.​ If you turn off Multicolor by using the checkbox below you will see that the grid changes to the standard 24x21 Layout but it also affects instantly the colors of course. As you remember Standard Sprites only have one common Background color stored in $D021 and one individual Foreground Color while in Multicolor mode we gain two extra colors and lose half of the horizontal resolution.&nbsp;</p><p>SpritePad will automatically adapt the options palette in the GUI. In Multicolor Mode a Sprite is displayed in the 12x21 Grid and we have four colors to choose from. When clearing the Multicolor checkbox, we have only two color options available. The Background Color and the individual Sprite Color stays as it is the same in both color modes but the two Multicolors disappeared and the Sprite in all editing and preview window changes accordingly - that is very convenient.<span>​</span></p>

































































 

  
  
    

      

      
        <figure class="
              sqs-block-image-figure
              intrinsic
            "
        >
          
        
        

        
          
            
              
              
          
            
                
                
                
                
                
                
                
                <img data-stretch="false" data-image="https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1367932126597-1WQCLJ3AO03PH3SYU6CS/dustlayer.com-c64-coding-multicolor-sprite.png" data-image-dimensions="281x325" data-image-focal-point="0.5,0.5" alt="" data-load="false" elementtiming="system-image-block" src="https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1367932126597-1WQCLJ3AO03PH3SYU6CS/dustlayer.com-c64-coding-multicolor-sprite.png?format=1000w" width="281" height="325" sizes="(max-width: 640px) 100vw, (max-width: 767px) 50vw, 50vw" onload="this.classList.add(&quot;loaded&quot;)" srcset="https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1367932126597-1WQCLJ3AO03PH3SYU6CS/dustlayer.com-c64-coding-multicolor-sprite.png?format=100w 100w, https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1367932126597-1WQCLJ3AO03PH3SYU6CS/dustlayer.com-c64-coding-multicolor-sprite.png?format=300w 300w, https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1367932126597-1WQCLJ3AO03PH3SYU6CS/dustlayer.com-c64-coding-multicolor-sprite.png?format=500w 500w, https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1367932126597-1WQCLJ3AO03PH3SYU6CS/dustlayer.com-c64-coding-multicolor-sprite.png?format=750w 750w, https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1367932126597-1WQCLJ3AO03PH3SYU6CS/dustlayer.com-c64-coding-multicolor-sprite.png?format=1000w 1000w, https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1367932126597-1WQCLJ3AO03PH3SYU6CS/dustlayer.com-c64-coding-multicolor-sprite.png?format=1500w 1500w, https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1367932126597-1WQCLJ3AO03PH3SYU6CS/dustlayer.com-c64-coding-multicolor-sprite.png?format=2500w 2500w" loading="lazy" decoding="async" data-loader="sqs">

            
          
        
            
          
        

        
          
          <figcaption class="image-caption-wrapper">
            <p>A Multicolor Sprite</p>
          </figcaption>
        
      
        </figure>
      

    
  













































 

  
  
    

      

      
        <figure class="
              sqs-block-image-figure
              intrinsic
            "
        >
          
        
        

        
          
            
              
              
          
            
                
                
                
                
                
                
                
                <img data-stretch="false" data-image="https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1367932136706-4SQZTYSPBPZTAYMFMPE7/dustlayer.com-c64-coding-standard-sprite.png" data-image-dimensions="279x330" data-image-focal-point="0.5,0.5" alt="" data-load="false" elementtiming="system-image-block" src="https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1367932136706-4SQZTYSPBPZTAYMFMPE7/dustlayer.com-c64-coding-standard-sprite.png?format=1000w" width="279" height="330" sizes="(max-width: 640px) 100vw, (max-width: 767px) 50vw, 50vw" onload="this.classList.add(&quot;loaded&quot;)" srcset="https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1367932136706-4SQZTYSPBPZTAYMFMPE7/dustlayer.com-c64-coding-standard-sprite.png?format=100w 100w, https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1367932136706-4SQZTYSPBPZTAYMFMPE7/dustlayer.com-c64-coding-standard-sprite.png?format=300w 300w, https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1367932136706-4SQZTYSPBPZTAYMFMPE7/dustlayer.com-c64-coding-standard-sprite.png?format=500w 500w, https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1367932136706-4SQZTYSPBPZTAYMFMPE7/dustlayer.com-c64-coding-standard-sprite.png?format=750w 750w, https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1367932136706-4SQZTYSPBPZTAYMFMPE7/dustlayer.com-c64-coding-standard-sprite.png?format=1000w 1000w, https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1367932136706-4SQZTYSPBPZTAYMFMPE7/dustlayer.com-c64-coding-standard-sprite.png?format=1500w 1500w, https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1367932136706-4SQZTYSPBPZTAYMFMPE7/dustlayer.com-c64-coding-standard-sprite.png?format=2500w 2500w" loading="lazy" decoding="async" data-loader="sqs">

            
          
        
            
          
        

        
          
          <figcaption class="image-caption-wrapper">
            <p>​Result when switching off Multicolor mode</p>
          </figcaption>
        
      
        </figure>
      

    
  






  <p>SpritePad comes with a simple Animator Tool to check whether our different Shapes will make a fluent animation when the&nbsp;they are played back&nbsp;continuously. ​To test this, just select the a number of sprite shapes with your mouse, then select the <em>Animator...</em>-Option unter Tools or hit the Short-Cut Button at the very right in the tool bar.</p><p>For example, select all Shapes from Frame 72 to Frame 87 - the Frame Number is displayed below the the small preview window between the Grid and the Spritesheet Window. ​ After you open the Animator you simply click on the <em>Play</em> Icon, that is the one facing to the right. The animation plays backs. </p><p>​</p>

































































 

  
  
    

      

      
        <figure class="
              sqs-block-image-figure
              intrinsic
            "
        >
          
        
        

        
          
            
              
              
          
            
                
                
                
                
                
                
                
                <img data-stretch="false" data-image="https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1367932569318-CW0EMNUSKCNMPMUZX4VL/dustlayer.com-c64-coding-animator-spritepad.png" data-image-dimensions="913x494" data-image-focal-point="0.5,0.5" alt="" data-load="false" elementtiming="system-image-block" src="https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1367932569318-CW0EMNUSKCNMPMUZX4VL/dustlayer.com-c64-coding-animator-spritepad.png?format=1000w" width="913" height="494" sizes="(max-width: 640px) 100vw, (max-width: 767px) 100vw, 100vw" onload="this.classList.add(&quot;loaded&quot;)" srcset="https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1367932569318-CW0EMNUSKCNMPMUZX4VL/dustlayer.com-c64-coding-animator-spritepad.png?format=100w 100w, https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1367932569318-CW0EMNUSKCNMPMUZX4VL/dustlayer.com-c64-coding-animator-spritepad.png?format=300w 300w, https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1367932569318-CW0EMNUSKCNMPMUZX4VL/dustlayer.com-c64-coding-animator-spritepad.png?format=500w 500w, https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1367932569318-CW0EMNUSKCNMPMUZX4VL/dustlayer.com-c64-coding-animator-spritepad.png?format=750w 750w, https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1367932569318-CW0EMNUSKCNMPMUZX4VL/dustlayer.com-c64-coding-animator-spritepad.png?format=1000w 1000w, https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1367932569318-CW0EMNUSKCNMPMUZX4VL/dustlayer.com-c64-coding-animator-spritepad.png?format=1500w 1500w, https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1367932569318-CW0EMNUSKCNMPMUZX4VL/dustlayer.com-c64-coding-animator-spritepad.png?format=2500w 2500w" loading="lazy" decoding="async" data-loader="sqs">

            
          
        
            
          
        

        
          
          <figcaption class="image-caption-wrapper">
            <p>​Spritepads Animator feature to play back animations</p>
          </figcaption>
        
      
        </figure>
      

    
  






  <p><strong>Looks great, doesn't it?&nbsp;</strong>​You can change Animation Speed and whether the Animation will repeat or go back and forth. This&nbsp;behavior&nbsp;of course is not exported with your Sprite Data but must be programmed ourselves later.&nbsp;<span>To get back to the SpriteEditor you must first close the Animator-Tool by the way.</span><span>​</span></p><h3>Building our Sprite Shapes</h3><p></p><p>​Sprite Pad has a few more interesting options but for our intro we will only use existing frames without really modifying them.</p>


























  <p>The Space Ship is already there and you played back the animation a minute ago. We will Simply use the 16 already completed frames from 72 to 87. Since our Ship will just fly from right to left, that is all we need - case closed.​ Let's delete the rows below that animation by selecting everything and then hitting DEL on the keyboard.</p>

































































 

  
  
    

      

      
        <figure class="
              sqs-block-image-figure
              intrinsic
            "
        >
          
        
        

        
          
            
              
              
          
            
                
                
                
                
                
                
                
                <img data-stretch="false" data-image="https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1367933494424-VOTEQZBAIKLTCB7GJRBD/dustlayer.com-c64-coding-isolated-uridium-sprite.png" data-image-dimensions="427x177" data-image-focal-point="0.5,0.5" alt="" data-load="false" elementtiming="system-image-block" src="https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1367933494424-VOTEQZBAIKLTCB7GJRBD/dustlayer.com-c64-coding-isolated-uridium-sprite.png?format=1000w" width="427" height="177" sizes="(max-width: 640px) 100vw, (max-width: 767px) 50vw, 50vw" onload="this.classList.add(&quot;loaded&quot;)" srcset="https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1367933494424-VOTEQZBAIKLTCB7GJRBD/dustlayer.com-c64-coding-isolated-uridium-sprite.png?format=100w 100w, https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1367933494424-VOTEQZBAIKLTCB7GJRBD/dustlayer.com-c64-coding-isolated-uridium-sprite.png?format=300w 300w, https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1367933494424-VOTEQZBAIKLTCB7GJRBD/dustlayer.com-c64-coding-isolated-uridium-sprite.png?format=500w 500w, https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1367933494424-VOTEQZBAIKLTCB7GJRBD/dustlayer.com-c64-coding-isolated-uridium-sprite.png?format=750w 750w, https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1367933494424-VOTEQZBAIKLTCB7GJRBD/dustlayer.com-c64-coding-isolated-uridium-sprite.png?format=1000w 1000w, https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1367933494424-VOTEQZBAIKLTCB7GJRBD/dustlayer.com-c64-coding-isolated-uridium-sprite.png?format=1500w 1500w, https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1367933494424-VOTEQZBAIKLTCB7GJRBD/dustlayer.com-c64-coding-isolated-uridium-sprite.png?format=2500w 2500w" loading="lazy" decoding="async" data-loader="sqs">

            
          
        
            
          
        

        
          
          <figcaption class="image-caption-wrapper">
            <p>​Our isolated Uridium Sprite</p>
          </figcaption>
        
      
        </figure>
      

    
  






  <p>Finally we want to delete all the Frames from 0 to 71 in the Spritesheet. Then we cut and paste the remaining 16 Ship Frames to the top of the spritesheet matrix. O<span>nce this is copied we can safely change the number of Frames from 128 to 16. This makes sure that only &nbsp;the shapes for the ship animation are saved into the output file.&nbsp;</span></p><p><strong>Our work is done!&nbsp;</strong>&nbsp;We would save the spritesheet as sprites.spr and put it in our resources folder of the Spritro project but of course it is already there when you downloaded the sources from Github or using DUST. Play a bit with the Sprite Editor though and change individual frames to get a feel for SpritePad. It's a great tool!</p>


























  <h3>The SpritePad Format</h3><p>To further work with our Sprites in the actual C64 code we need to know how the Spritepad format is organized. It is in fact not hard to grasp but changed over the last couple of versions. The release I use is 1.8.1 downloaded at <a href="http://csdb.dk/release/?id=100657" target="_blank">CSDB</a>. The files have the extension .SPR, in the <em>/example</em> folder of SpritePad they actually have the extension .SPD which seems to be for historic reasons.&nbsp;</p><p>Anyways, the .SPR file starts with a header of three Bytes that determine the three shared colors. It does not matter if you only use Standard Mode sprites by the way, there will always be three bytes at the beginning of a .spr file reserved to store three bytes of information, thus in Standard Mode two of those Bytes are Zero.</p><p>After that header all the sprite shapes are following one by one. They consist of 63 Bytes of the actual Sprite Data plus 1 Byte which holds the the Information whether a Sprite is MultiColor or in Standard Mode plus the color code of the individual Sprite Color.</p>

































































 

  
  
    

      

      
        <figure class="
              sqs-block-image-figure
              intrinsic
            "
        >
          
        
        

        
          
            
              
              
          
            
                
                
                
                
                
                
                
                <img data-stretch="false" data-image="https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1368189375511-MY1AORAUJO0GMSL9C28X/dustlayer.com-c64-coding-manta.png" data-image-dimensions="200x182" data-image-focal-point="0.5,0.5" alt="" data-load="false" elementtiming="system-image-block" src="https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1368189375511-MY1AORAUJO0GMSL9C28X/dustlayer.com-c64-coding-manta.png?format=1000w" width="200" height="182" sizes="(max-width: 640px) 100vw, (max-width: 767px) 100vw, 100vw" onload="this.classList.add(&quot;loaded&quot;)" srcset="https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1368189375511-MY1AORAUJO0GMSL9C28X/dustlayer.com-c64-coding-manta.png?format=100w 100w, https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1368189375511-MY1AORAUJO0GMSL9C28X/dustlayer.com-c64-coding-manta.png?format=300w 300w, https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1368189375511-MY1AORAUJO0GMSL9C28X/dustlayer.com-c64-coding-manta.png?format=500w 500w, https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1368189375511-MY1AORAUJO0GMSL9C28X/dustlayer.com-c64-coding-manta.png?format=750w 750w, https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1368189375511-MY1AORAUJO0GMSL9C28X/dustlayer.com-c64-coding-manta.png?format=1000w 1000w, https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1368189375511-MY1AORAUJO0GMSL9C28X/dustlayer.com-c64-coding-manta.png?format=1500w 1500w, https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1368189375511-MY1AORAUJO0GMSL9C28X/dustlayer.com-c64-coding-manta.png?format=2500w 2500w" loading="lazy" decoding="async" data-loader="sqs">

            
          
        
            
          
        

        
          
          <figcaption class="image-caption-wrapper">
            <p>​The Manta Class Space Ship.</p>
          </figcaption>
        
      
        </figure>
      

    
  






  <p>To get a better feeling for the data we look at the first 67 Bytes of our sprites.spr supplied with the Spritro sources. After the three initial Bytes for the shared colors we can basically see the first frame of the Manta Space Ship in the binary code - well with good imagination that is or by using some coloring like I used below in the picture. ​</p><p>The first three Bytes are $00, $0B and $01 which correspond to ​Background Color, MultiColor 1 and MultiColor 2. We defined those colors in the SpritePad application. Since it is a MultiColor Sprite the next 252 Bit-Pairs define the source for the color information for each individual pair of pixels. In Standard Mode you would only work with $00 and $FF values of course but in Multicolor we have four different states, hence sources for color information. Read corresponding articles in the knowledge base if you need to recap on this.&nbsp;</p><p></p><p><span><span>Finally we reach Byte 64. The low Nibble stores the individual color Black in this particular case -&nbsp;</span>therefore<span>&nbsp;it is $00 - and the high Nibble of that Byte indicates by the most significant Bit set that this Sprite uses Multicolor Mode. For Standard Mode, Bit#7 of Byte 64 would have been set to low by SpritePad.</span></span><br></p><p><strong>Here is a drawing for a quick overview of the just explained properties of the format.&nbsp;</strong><span>​</span></p>

































































 

  
  
    

      

      
        <figure class="
              sqs-block-image-figure
              intrinsic
            "
        >
          
        
        

        
          
            
              
              
          
            
                
                
                
                
                
                
                
                <img data-stretch="false" data-image="https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1368189527560-2DD2ER235O0M1S5E4TCM/dustlayer.com-spritepad-181-format.png" data-image-dimensions="992x749" data-image-focal-point="0.5,0.5" alt="" data-load="false" elementtiming="system-image-block" src="https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1368189527560-2DD2ER235O0M1S5E4TCM/dustlayer.com-spritepad-181-format.png?format=1000w" width="992" height="749" sizes="(max-width: 640px) 100vw, (max-width: 767px) 100vw, 100vw" onload="this.classList.add(&quot;loaded&quot;)" srcset="https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1368189527560-2DD2ER235O0M1S5E4TCM/dustlayer.com-spritepad-181-format.png?format=100w 100w, https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1368189527560-2DD2ER235O0M1S5E4TCM/dustlayer.com-spritepad-181-format.png?format=300w 300w, https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1368189527560-2DD2ER235O0M1S5E4TCM/dustlayer.com-spritepad-181-format.png?format=500w 500w, https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1368189527560-2DD2ER235O0M1S5E4TCM/dustlayer.com-spritepad-181-format.png?format=750w 750w, https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1368189527560-2DD2ER235O0M1S5E4TCM/dustlayer.com-spritepad-181-format.png?format=1000w 1000w, https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1368189527560-2DD2ER235O0M1S5E4TCM/dustlayer.com-spritepad-181-format.png?format=1500w 1500w, https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1368189527560-2DD2ER235O0M1S5E4TCM/dustlayer.com-spritepad-181-format.png?format=2500w 2500w" loading="lazy" decoding="async" data-loader="sqs">

            
          
        
            
          
        

        
          
          <figcaption class="image-caption-wrapper">
            <p>​SpritePad 1.8.2 Format - The three first bytes carry all shared colors. Then 504 Bits define the Shape and a last Fillbyte determines if this shape is in Standard or Multicolor and the individual Sprite Color.</p>
          </figcaption>
        
      
        </figure>
      

    
  






  <p>When we load the Spritesheet into our program we must consider that the first three bytes are color information and that all the shapes follow afterwards. When loading the data into our program we can either parse the first three bytes or just skip them and put the color information manually into the appropriate registers. The latter is actually what I did.</p><p>​-act</p>]]></description></item><item><title>Episode 3-1: Spritro - an Intro with a Sprite</title><dc:creator>actraiser</dc:creator><pubDate>Thu, 23 May 2013 11:52:52 +0000</pubDate><link>https://dustlayer.com/c64-coding-tutorials/2013/5/24/episode-3-1-spritro-an-intro-with-a-sprite</link><guid isPermaLink="false">511651d6e4b0a31c035e30aa:5117493de4b085e20f7f2f40:5188e5c2e4b0851a91a17dac</guid><description><![CDATA[<p><strong>Synopsis:</strong> In this huge Episode we will analyze an intro with an animated Sprite controlled via Keyboard. To spice up the action we add a new color cycle effect and open the top and bottom borders where our sprite can freely move into. Finally we fix a SID file which is not locating it's data at our desired memory location. </p>

<p><strong>Download via <a href="https://dustlayer.com/c64-coding-tutorials/2013/5/24/episode-3-1-spritro-an-intro-with-a-sprite">dust</a>:</strong> $ dust tutorials (select 'spritro') <br />
<strong>Github Repository:</strong> <a href="https://github.com/actraiser/dust-tutorial-c64-spritro" target="_new">Spritro Source Code on Github</a>  </p>

<ul>
<li><strong>Episode 3-1: Spritro - An Intro with a Sprite</strong></li>
<li><a href="https://dustlayer.com/c64-coding-tutorials/2013/5/24/episode-3-2-creating-the-shapes-hello-spritepad">Episode 3-2: Creating the Shapes - Hello SpritePad</a></li>
<li><a href="https://dustlayer.com/c64-coding-tutorials/2013/5/24/episode-3-3-loading-shapes-and-grasping-symbols">Episode 3-3: Loading Shapes and grasping Symbols</a></li>
<li><a href="https://dustlayer.com/c64-coding-tutorials/2013/5/24/episode-3-4-flying-the-space-ship-off-course">Episode 3-4: Flying the Space Ship off Course</a></li>
<li><a href="https://dustlayer.com/c64-coding-tutorials/2013/5/24/episode-3-5-taking-command-of-the-ship-controls">Episode 3-5: Taking Command of the Ship Controls</a></li>
<li><a href="https://dustlayer.com/c64-coding-tutorials/2013/5/24/episode-3-6-custom-character-sets-hello-charpad">Episode 3-6: Custom Character Sets - Hello CharPad</a></li>
<li><a href="https://dustlayer.com/c64-coding-tutorials/2013/5/24/episode-3-7-creating-pseudo-timers-for-color-cycle">Episode 3-7: Creating Pseudo Timers for Color Cycle</a></li>
<li><a href="https://dustlayer.com/c64-coding-tutorials/2013/5/24/episode-3-8-if-the-sid-doesnt-fit-use-a-bigger-hammer">Episode 3-8: If the SID doesn't fit, use a bigger Hammer</a></li>
<li><a href="https://dustlayer.com/c64-coding-tutorials/2013/5/24/episode-3-9-greetings-acknowledgments-and-links">Episode 3-9: Greetings, Acknowledgments and Links</a></li>
</ul>

<hr />



  <h3>​Spritro - a simple intro with a Sprite</h3><p>Welcome to a new multi-part tutorial on C64 programming on dustlayer.com! It's been a month since the last coding tutorial but I did not waste a lot of time in-between but &nbsp;filled the site with a few in-depth knowledge base articles.&nbsp;</p><p><span>If you have not read the Knowledge Base Series&nbsp;</span><a href="https://dustlayer.squarespace.com/vic-ii/2013/4/22/when-visibility-matters">VIC-II for Beginners</a><span>,&nbsp;</span><a href="https://dustlayer.squarespace.com/cpu-6510-articles/2013/4/18/math-basics-number-systems">Math Basics</a><span>&nbsp;and&nbsp;</span><a href="https://dustlayer.squarespace.com/c64-architecture/2013/5/7/hardware-basics-part-1-tick-tock-know-your-clock">Hardware Basics</a><span>&nbsp;yet - I encourage to do so.​&nbsp;</span></p><p>I &nbsp;improved a bit on my coding style and changed things around in how I structure new projects. This first chapter is an overview of the actual outcome of this tutorial and how everything is organized.&nbsp;</p><p><strong>But first </strong>- download the Spritro via DUST or clone it from the Github repository linked above, then build it. If you are too lazy to do this now, you can also watch the following video.​</p><p></p>























<iframe data-image-dimensions="640x480" allowfullscreen="" src="http://www.youtube.com/embed/P2k6zOcmIq4?feature=oembed&amp;wmode=opaque&amp;enablejsapi=1" width="640" data-embed="true" frameborder="0" height="480"></iframe><p>This is the output of the Spritro Tutorial. The actual tutorial spans over several chapters over at http://dustlayer.com</p>


  <h3>Some obvious and not so obvious features</h3><p>This little intro comes with an <strong>animated Sprite </strong>- of course you know it's the famous <a href="http://www.lemon64.com/?game_id=2766" target="_blank">Manta Class Ship from Uridium</a>. It <strong>moves smoothly</strong> from right to left - but did you notice something?! Is this ship not a bit low on the screen? Shouldn't there be a border?! ​</p><p>It should! But by exploiting a VIC-II bug the<strong> top and bottem borders have been removed </strong>and the Sprite can freely move across 312 PAL Rasterlines on the screen. You also have some <strong>control by hitting the U or D key</strong> to move the ship up and down. ​</p><p>Additionally as opposed to the <a href="https://dustlayer.com/c64-coding-tutorials/2013/2/17/a-simple-c64-intro">First Intro Tutorial</a>&nbsp;we use a <strong>custom font</strong> to display some text on the screen - actually it is a very popular character set from the game <a href="http://www.lemon64.com/?game_id=2084" target="_blank">Rambo First Blood Part II</a>&nbsp;- used in dozens of other games and intros before.&nbsp;</p><p>The different&nbsp;<strong>color cycle effect</strong> on the text is this time not based on a table of values but kinda syncs with the 16 frames of the Ship animation. If you don't understand at this moment - don't worry, I will explain it along the way. There is also a periodic switching of colors in the side borders to <strong>demo how to delay timing</strong> of effects while on the interrupt. &nbsp; ​</p><p>Last but not least an <strong>awesome SID tune</strong>&nbsp;is playing - this time <em>"Empty (512 Bytes)"</em> by 4-Mat. The original SID file places it's play routine and data in a memory location not suitable for our intro so we<strong> learn how to relocate SIDs</strong> in memory. This is a task &nbsp;which was rather tedious to do not so long ago but with a recently released tool it has become incredibly easy. ​</p><p>That's it! We have a lot of ground to cover but first, I want to explain what you find where in the project.</p>


























  <h3>Project Structure</h3><p>As with the last tutorial we stick to three directories and an index files.&nbsp;</p><p>The<strong> index.asm</strong> file is basically something like a header file which includes all the other source code files from the project plus it sets up a BASIC loader so we do not have to type <em>SYS 49152</em> ourselves after loading the .prg.​ It is the file you compile against to build your .prg output file.</p>

































































 

  
  
    

      

      
        <figure class="
              sqs-block-image-figure
              intrinsic
            "
        >
          
        
        

        
          
            
          
            
                
                
                
                
                
                
                
                <img data-stretch="true" data-image="https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1368735238144-ICYQXG53WUTCY7G0OKHU/Bildschirmfoto+2013-05-16+um+22.11.37.png" data-image-dimensions="205x463" data-image-focal-point="0.5,0.5" alt="" data-load="false" elementtiming="system-image-block" src="https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1368735238144-ICYQXG53WUTCY7G0OKHU/Bildschirmfoto+2013-05-16+um+22.11.37.png?format=1000w" width="205" height="463" sizes="(max-width: 640px) 100vw, (max-width: 767px) 100vw, 100vw" onload="this.classList.add(&quot;loaded&quot;)" srcset="https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1368735238144-ICYQXG53WUTCY7G0OKHU/Bildschirmfoto+2013-05-16+um+22.11.37.png?format=100w 100w, https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1368735238144-ICYQXG53WUTCY7G0OKHU/Bildschirmfoto+2013-05-16+um+22.11.37.png?format=300w 300w, https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1368735238144-ICYQXG53WUTCY7G0OKHU/Bildschirmfoto+2013-05-16+um+22.11.37.png?format=500w 500w, https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1368735238144-ICYQXG53WUTCY7G0OKHU/Bildschirmfoto+2013-05-16+um+22.11.37.png?format=750w 750w, https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1368735238144-ICYQXG53WUTCY7G0OKHU/Bildschirmfoto+2013-05-16+um+22.11.37.png?format=1000w 1000w, https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1368735238144-ICYQXG53WUTCY7G0OKHU/Bildschirmfoto+2013-05-16+um+22.11.37.png?format=1500w 1500w, https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1368735238144-ICYQXG53WUTCY7G0OKHU/Bildschirmfoto+2013-05-16+um+22.11.37.png?format=2500w 2500w" loading="lazy" decoding="async" data-loader="sqs">

            
          
        
          
        

        
          
          <figcaption class="image-caption-wrapper">
            <p>​Spritro Directory Structure</p>
          </figcaption>
        
      
        </figure>
      

    
  






  <p>If the&nbsp;<strong>/<em>build-directory</em></strong><em></em>&nbsp;does not exist, it is created automatically when you compile the intro for the first time. It contains the finished&nbsp;<em>executable .prg file</em>&nbsp;and - if you use DUST - &nbsp;a list of&nbsp;<em>labels and their memory addresses&nbsp;</em>are dumped here into a file and on the screen as well. If the labels are not generated you need to update DUST with the command 'dust setup' and select option 1 ("install all").&nbsp;</p><p><strong></strong><strong>​</strong>The<em> <strong>/resources-directory</strong></em> includes &nbsp;all our binaries we like to load into the intro, namely a SID file, our custom character set and of course the Sprite Data. ​</p><p>Finally the <em><strong>/code-directory</strong>&nbsp;</em>​includes all the routines and other code. The prefixes on each file indicate their role. </p><p><em><strong>config-files</strong> </em>set up something, e.g. place a loaded sprite at the desired memory location, initialize registers at start, setup symbols, define how to actually load a binary.&nbsp;</p><p><em><strong>data-files</strong></em> are strings or tables with information to iterate over. For Spritro it's just three lines of static text. ​</p><p><em><strong>sub-files</strong></em> are subroutines. I use one file per subroutine usually and the name of the file minus the prefix corresponds to the label in the code you would jump to.&nbsp;</p><p>Finally, the <em><strong>main.asm</strong></em> file is the basis of our custom interrupt routine and executes all the other subroutines either one-time or periodically during the interrupt.</p>


























  <h3>Ready, Set, Go!</h3><p>Now go to the next chapter which will deal with the Sprite creation process. Enjoy this new Episode and don't hesitate to send comments or like my <a href="http://www.facebook.com/dustlayer.c64.coding" target="_blank">Facebook page</a> or follow me on <a href="https://twitter.com/actraiser" target="_blank">Twitter</a>.</p><p>-act</p>]]></description></item><item><title>Episode 2-5: Understanding and including music</title><dc:creator>actraiser</dc:creator><pubDate>Sat, 06 Apr 2013 19:15:00 +0000</pubDate><link>https://dustlayer.com/c64-coding-tutorials/2013/4/8/episode-2-5-understanding-and-including-music</link><guid isPermaLink="false">511651d6e4b0a31c035e30aa:5117493de4b085e20f7f2f40:516285c8e4b058e82d8a8c5c</guid><description><![CDATA[<p><strong>Topics:</strong> The last chapter of this introduction episode to C64 coding will be about including SID music into the intro. <br />
<strong>Download via <a href="http://dustlayer.com/c64-coding-tutorials/2013/2/10/dust-c64-command-line-tool">dust</a>:</strong> $ dust tutorials (select 'first intro') 
<strong>Github Repository:</strong> <a href="https://github.com/actraiser/dust-tutorial-c64-first-intro" target="_new">First Intro on Github</a>  </p>

<ul>
<li><a href="http://dustlayer.com/c64-coding-tutorials/2013/2/17/a-simple-c64-intro">Episode 2-1: Let's compile and run C64 code</a></li>
<li><a href="http://dustlayer.com/c64-coding-tutorials/2013/4/8/episode-2-2-writing-to-the-c64-screen">Episode 2-2: Writing to the C64 Screen</a></li>
<li><a href="http://dustlayer.com/c64-coding-tutorials/2013/4/8/episode-2-3-getting-into-interrupts">Episode 2-3: Getting into interrupts</a></li>
<li><a href="http://dustlayer.com/c64-coding-tutorials/2013/4/8/episode-2-4-reading-from-a-data-table">Episode 2-4: Effects using a table of data</a></li>
<li><strong>Episode 2-5: Understanding and including music</strong></li>
</ul>

<hr />



  <h3>Music is essential to a great C64 experience</h3><p>If you are a C64 enthusiast - and why would you read this blog if this is not the case - you of course love the music generated by the SID-Chip. To me music is equally important to a game or demo as are great looking effects. ​</p><p>Our intro would not be half as cool if I had not included a catchy tune so let's take a look how this music got into the finished intro.​</p><h3>Loading resources</h3><p><strong>Let's have a look at code/load_resource.asm</strong>​</p>


























  <p>We need to get our music into the intro. For this we need to specify a loading address, that is where is the SID stored in memory. I already set up a symbol earlier in <em>init_symbols.asm</em> which assigns $1000 to the symbol <em>address_music . &nbsp;</em>​With<em> * = address_music</em> we therefor tell ACME that the next instruction should be put in memory at $1000.&nbsp;<strong>​</strong>​</p><p>​This instruction is once again a very handy pseudo opcode by ACME. !bin loads a file from your harddisk into your C64 code. It also allows for a few parameters we need to work with SID files as provided on the net, e.g. from the HVSC database. &nbsp;Those SIDs come with a special header with some extra information for various cross platform music players which we need to remove when importing the file into our codebase. Luckily the !bin command lets us remove that extra information.</p><p>Once we loaded the resource, how do we playback the SID? This is a two-step process. First we need to initialize the music replay routine and then we need to trigger the actual music player routine with every screen refresh. ​ Do do either, we need to know the start address of the initialization routine and the start address of the replay routine. That information is encoded within the SID. &nbsp;A very common init address for SIDs is $1000 and for the playback routine $1003. The command line tool <em>sidreloc</em> which is installed by <em>DUST&nbsp;</em>​​can be used to move the SID so init address and play routine address can be adjusted to what makes sense for your demo. I will write a an article on <em>sidreloc</em> at some other time.&nbsp;</p><p>With this information the whole music playing is actually dead simple. We jump once to the sub routine at $1000 - this is done in code/main.asm - and from that point on we execute the actual replay subroutine with every screen refresh in our custom interrupt. ​And if you wonder where the actual code for the playback resides - it is always supplied with the SID file itself so all we need to know is where to jump to within the memory we put the SID into.&nbsp;</p><p><strong>That's it! Incredibly easy, is it not? ​</strong></p><p>​This closes the first tutorial episode on coding the Commodore 64. It was meant to get you a bit excited about coding and we will go deeper in many areas which have only been mentioned briefly in later tutorials. &nbsp;If you have comments please feel free to send fedback either below the chapters or on <a href="http://www.facebook.com/dustlayer.c64.coding" target="_blank">Facebook</a>.</p><p>-act</p>]]></description><media:content type="image/png" url="https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1365411362602-SJLDPGFFAZOVA6PHUF1H/asm_tiled.png?format=1500w" medium="image" isDefault="true" width="632" height="111"><media:title type="plain">Episode 2-5: Understanding and including music</media:title></media:content></item><item><title>Episode 2-4: Effects using a table of data</title><dc:creator>actraiser</dc:creator><pubDate>Fri, 05 Apr 2013 19:01:00 +0000</pubDate><link>https://dustlayer.com/c64-coding-tutorials/2013/4/8/episode-2-4-reading-from-a-data-table</link><guid isPermaLink="false">511651d6e4b0a31c035e30aa:5117493de4b085e20f7f2f40:516285bbe4b0715db6223175</guid><description><![CDATA[<p><strong>Topics:</strong> We will understand the first demo effect which is cycling a color pattern on some text. To achieve this we must know how to iterate over table data.  </p>

<p><strong>Download via <a href="http://dustlayer.com/c64-coding-tutorials/2013/2/10/dust-c64-command-line-tool">dust</a>:</strong> $ dust tutorials (select 'first intro') <br />
<strong>Github Repository:</strong> <a href="https://github.com/actraiser/dust-tutorial-c64-first-intro" target="_new">First Intro on Github</a>  </p>

<ul>
<li><a href="http://dustlayer.com/c64-coding-tutorials/2013/2/17/a-simple-c64-intro">Episode 2-1: Let's compile and run C64 code</a></li>
<li><a href="http://dustlayer.com/c64-coding-tutorials/2013/4/8/episode-2-2-writing-to-the-c64-screen">Episode 2-2: Writing to the C64 Screen</a></li>
<li><a href="http://dustlayer.com/c64-coding-tutorials/2013/4/8/episode-2-3-getting-into-interrupts">Episode 2-3: Getting into interrupts</a></li>
<li><strong>Episode 2-4: Effects using a table of data</strong></li>
<li><a href="http://dustlayer.com/c64-coding-tutorials/2013/4/8/episode-2-5-understanding-and-including-music">Episode 2-5: Understanding and including music</a> </li>
</ul>

<hr />



  <h3>The Color Washer effect</h3><p>We have put some text on the screen and now we want a nice effect to happen. A good starter is an effect which is sometimes referred as color cycle or color wash effect. In our intro it's about changing the foreground text color for each letter in a pattern so it does look like the color <em>washes</em> from one end to the other.&nbsp;</p><p><strong>There are two extra challenges:​</strong></p><ul></ul><ol><li>We need to change the foreground colors of all letters with every screen refresh.</li><li>We want that the color moves from right to left in the upper line of text and r<em>eturn&nbsp;</em>​from left to right in the second line of text. With this we achieve a little optical illusion of a rotating color cycle across both lines.</li></ol><p></p><p>We need to define what colors we want to use for the effect and put it in a table we can iterate over. The tricky part is to write down a pattern auf color codes that actually look good in our pseudo motion. You can experiment by changing color information in the data tables. ​</p><p><strong>Open code/sub_colorwash.asm</strong>​<br></p>


























  <p>There is the first mystery - &nbsp;we want to load some information from somewhere labeled <em>color+$00 </em>ut there is no such label in that file. I actually like to organize code in as many chunks as possible and that is why you find the table data with the color information in a different file. So additionally &nbsp;open<strong> code/data_colorwash.asm.&nbsp;</strong></p>


























  <p>Now we have everything we need to understand the code. &nbsp;First of all, &nbsp;why would we use two tables? or simplicity actually - with some more thoughts put into a good routine one table is probably sufficient. But this is something you do on C64 all the time - looking for optimizations. &nbsp;In this example we use two tables so it's easier to follow what is going on.</p><p>The two tables in <em>data_colorwash.asm</em>&nbsp;are labeled with <em>color</em> and <em>color2</em>. ACMEs pseudo opcode !byte wrote al the values consecutively into memory. A subroutine can now retrieve the data by referencing to the labels <em>color</em> and <em>color2 </em>- this is what we do in <em>sub_colorwash.asm</em><strong></strong><strong></strong>. &nbsp; The way the tables are formatted is not of importance, I used an 8x5 matrix because it looked fine for 40 values. &nbsp;We use 40 values because we are manipulating 40 positions per row. &nbsp;The values are numbers ranging form 1 to 15 ($00 - $0F) as there are 16 colors available on the Commodore C64 to work with. &nbsp;</p><p>If you would stop the effect while running the intro you get a visualization of the color pattern. You need to experiment a bit with different colors to generate for example some kind of shining effect like this one.</p>

































































 

  
  
    

      

      
        <figure class="
              sqs-block-image-figure
              intrinsic
            "
        >
          
        
        

        
          
            
              
              
          
            
                
                
                
                
                
                
                
                <img data-stretch="false" data-image="https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1365965368735-LT6P1DWLLZH8FNV1UBYG/dustlayer.com+-+color+wash+halted.png" data-image-dimensions="326x69" data-image-focal-point="0.5,0.5" alt="" data-load="false" elementtiming="system-image-block" src="https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1365965368735-LT6P1DWLLZH8FNV1UBYG/dustlayer.com+-+color+wash+halted.png?format=1000w" width="326" height="69" sizes="(max-width: 640px) 100vw, (max-width: 767px) 100vw, 100vw" onload="this.classList.add(&quot;loaded&quot;)" srcset="https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1365965368735-LT6P1DWLLZH8FNV1UBYG/dustlayer.com+-+color+wash+halted.png?format=100w 100w, https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1365965368735-LT6P1DWLLZH8FNV1UBYG/dustlayer.com+-+color+wash+halted.png?format=300w 300w, https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1365965368735-LT6P1DWLLZH8FNV1UBYG/dustlayer.com+-+color+wash+halted.png?format=500w 500w, https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1365965368735-LT6P1DWLLZH8FNV1UBYG/dustlayer.com+-+color+wash+halted.png?format=750w 750w, https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1365965368735-LT6P1DWLLZH8FNV1UBYG/dustlayer.com+-+color+wash+halted.png?format=1000w 1000w, https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1365965368735-LT6P1DWLLZH8FNV1UBYG/dustlayer.com+-+color+wash+halted.png?format=1500w 1500w, https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1365965368735-LT6P1DWLLZH8FNV1UBYG/dustlayer.com+-+color+wash+halted.png?format=2500w 2500w" loading="lazy" decoding="async" data-loader="sqs">

            
          
        
            
          
        

        
          
          <figcaption class="image-caption-wrapper">
            <p>​frozen color wash animation</p>
          </figcaption>
        
      
        </figure>
      

    
  






  <p>Let's look at the actual sub routine in <em>sub_colorwash.asm</em>&nbsp;which manipulates the first line of text. Every time we execute the routine &nbsp;- which is on every screen refresh - we change the foreground color of all characters in both rows starting at $0590 for the first row and $05E0 for the second row on the screen. In the places where no text is printed we won't see any side effect as there is no character where a foreground color would change anything. So if there is a space character, it will remain black to the viewer's eye though we actually do change the memory location in the process.&nbsp; &nbsp;</p><h3>The principle of the effect</h3><p>At first glance the code might confuse because we seem to work on the color table itself and not on the characters in Screen Ram - <em>but</em>&nbsp;this is in fact what we do.</p><p>Take a moment to grasp the principle:&nbsp;The foreground color of each of the two rows of text can be manipulated in Color RAM. There is no need to care about the Screen RAM as the actual character codes will not change.&nbsp;To achieve a color cycle effect we need to change foreground color of all our characters in Color RAM with every screen refresh. And for that we basically rotate the values in the color tables and write the updated color information into Color Ram.</p><p><strong>Still confused? Let's go through the code.</strong></p><p>As you can see, there are two main blocks of code. <em>colwash</em> and <em>cycle1</em> for manipulating the first row of text where we want the colors to "wash" from right to left and then there is <em>colwash2</em> and <em>cylce2</em> with the reverse effect for the second line of text.&nbsp;</p><p>There is one not obvious complexity in the code that is due to how I designed the data table for the colors.&nbsp;&nbsp;The two tables are adjacent, that is there are 40 bytes in the first table named <em>color</em> and right after another 40 bytes in the table named color2. The problem with this was pointed out in the blog comments below for an earlier version of this subroutine where I accidentally operated one byte outside the tables.&nbsp;</p><p>You may want to read through the blog comments to get the whole picture but the important thing is that we need a temporary location to store one color value while iterating in the process. You will understand in a bit.&nbsp;</p><p><strong>Let's focus again and continue to step through the code with the just said in mind.&nbsp;</strong></p><p>I will dissect exactly what happens in the first iteration of the loop. &nbsp;We start by initializing the x-register with the number of iterations we need to do. Then, for our first line of text, we load the last color of the first color table,&nbsp;&nbsp;that is the 40th byte -&nbsp;that is position $27/#39 when you count from zero. &nbsp;</p><p>Now the actual loop starts. We grab the next color from the end of the color table which is at this point at position #38 and temporarily store it into the y-register. The table location we read that color from is then overwritten with the color that is still stored in our accumulator from the initialization process at start. That would be the color formerly known as color number #40. It is written into Color Ram for the character in column position $27/#39 of the row that starts at Color Ram location $d990. That memory address $d990 maps exactly the color information for our characters in the Screen Ram location starting at $0590.&nbsp;&nbsp;If you <em>check init_static_text.asm</em>, you see that this is exactly the row we use for our first line of text.&nbsp;</p><p>So what we did here in the first iteration is to move the color from the formerly 40th position of the color table to the 39th position <strong>and</strong>&nbsp;<strong>before that </strong>kept a note of the color that was previously stored at position 39 for later use. That information is now restored using the implicit <em>tya</em>&nbsp;operator which transfers the content of y to accumulator. &nbsp;We can now decrement x and check if we already did 39 iterations. If we did, we only need to write our final 40th color to beginning of our &nbsp;Color Ram of the first line of text at $d990. Thanks to the y-register that final value has been remembered and moved to the accumulator in the last iteration.&nbsp;</p><p>That was a bit of heavy stuff, mainly because of the temporary storage strategy. Maybe it clicks when we do the reverse approach for the second line of text. This time we wash our colors from left to right to achieve those sort of rotor-effect in the intro. This requires some minor changes but the principle remains exactly the same.&nbsp;</p><p>We don't start at the end but in the beginning of the table, so x-register is initialized with #$00.&nbsp;Accumulator is again initialized wit the last color,&nbsp;&nbsp;this time from the <em>color2</em> table.. &nbsp;Again we grab the next color and store it temporary in y plus write it into the color2 table overwriting the memory address we just remembered the previous value of. This in turn is again transferred to the accumulator and written into Color Ram, this time two rows lower as our second line of text is located in Screen ram row starting at position $05e0 which has it's Color Ram position starting at $d9e0. &nbsp;In our 39th iteration (starting at 0 that would be $26/#38), we put our final color into the last position in Color Ram. Again this is only possible because we remembered it in the y-register before and moved it to the accumulator in the last iteration step.&nbsp;</p><p><strong>We now did the whole round trip for both lines of text!</strong></p><p>As a beginner you will need to read the code over and over again probably because it's a bit hard to grasp at first but it will eventually make sense after some time looking at the code and the output.</p><h3>perfect color cycle example</h3><p>Using color cycling is a very interesting technique. You can do very simple effects like the one in our intro but also create astonishing visualizations. For some inspiration, please check this awesome color cycle effect implemented by Joseph Huckaby. &nbsp;There are more incredible screens available on <a target="_blank" href="http://www.effectgames.com/demos/canvascycle/">this page</a> at Effect Games.</p>

































































 

  
  
    

      

      
        <figure class="
              sqs-block-image-figure
              intrinsic
            "
        >
          
        
        

        
          
            
              
              
          
            
                
                
                
                
                
                
                
                <img data-stretch="false" data-image="https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1365951106205-V29UA8TMDJ050QGGU25V/color_cycle_example_joseph.gif" data-image-dimensions="640x480" data-image-focal-point="0.5,0.5" alt="" data-load="false" elementtiming="system-image-block" src="https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1365951106205-V29UA8TMDJ050QGGU25V/color_cycle_example_joseph.gif?format=1000w" width="640" height="480" sizes="(max-width: 640px) 100vw, (max-width: 767px) 100vw, 100vw" onload="this.classList.add(&quot;loaded&quot;)" srcset="https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1365951106205-V29UA8TMDJ050QGGU25V/color_cycle_example_joseph.gif?format=100w 100w, https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1365951106205-V29UA8TMDJ050QGGU25V/color_cycle_example_joseph.gif?format=300w 300w, https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1365951106205-V29UA8TMDJ050QGGU25V/color_cycle_example_joseph.gif?format=500w 500w, https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1365951106205-V29UA8TMDJ050QGGU25V/color_cycle_example_joseph.gif?format=750w 750w, https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1365951106205-V29UA8TMDJ050QGGU25V/color_cycle_example_joseph.gif?format=1000w 1000w, https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1365951106205-V29UA8TMDJ050QGGU25V/color_cycle_example_joseph.gif?format=1500w 1500w, https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1365951106205-V29UA8TMDJ050QGGU25V/color_cycle_example_joseph.gif?format=2500w 2500w" loading="lazy" decoding="async" data-loader="sqs">

            
          
        
            
          
        

        
          
          <figcaption class="image-caption-wrapper">
            <p>​This is a wonderful example of a Color Cycle Effect. &nbsp;Artwork by Mark Ferrari and implementation by Joseph Huckaby.&nbsp;</p>
          </figcaption>
        
      
        </figure>
      

    
  






  <p>In the last episode of this tutorial I briefly talk about including external resources, namely music. ​</p><p>-act</p>]]></description></item><item><title>Episode 2-3: Did I interrupt you?</title><dc:creator>actraiser</dc:creator><pubDate>Fri, 05 Apr 2013 18:09:00 +0000</pubDate><link>https://dustlayer.com/c64-coding-tutorials/2013/4/8/episode-2-3-did-i-interrupt-you</link><guid isPermaLink="false">511651d6e4b0a31c035e30aa:5117493de4b085e20f7f2f40:516285ade4b0f29c9266c987</guid><description><![CDATA[<p><strong>Topics:</strong> Many C64 programmers did avoid dealing with interrupts yet it is only thing that lets us create really cool things on the C64. There are various types of interrupts, we start with a very simple one.  </p>

<p><strong>Download via <a href="http://dustlayer.com/c64-coding-tutorials/2013/2/10/dust-c64-command-line-tool">dust</a>:</strong> $ dust tutorials (select 'first intro') <br />
<strong>Github Repository:</strong> <a href="https://github.com/actraiser/dust-tutorial-c64-first-intro" target="_new">First Intro on Github</a>  </p>

<ul>
<li><a href="http://dustlayer.com/c64-coding-tutorials/2013/2/17/a-simple-c64-intro">Episode 2-1: Let's compile and run C64 code</a></li>
<li><a href="http://dustlayer.com/c64-coding-tutorials/2013/4/8/episode-2-2-writing-to-the-c64-screen">Episode 2-2: Writing to the C64 Screen</a></li>
<li><strong>Episode 2-3: Did I interrupt you?</strong></li>
<li><a href="http://dustlayer.com/c64-coding-tutorials/2013/4/8/episode-2-4-reading-from-a-data-table">Episode 2-4: Effects using a table of data</a></li>
<li><a href="http://dustlayer.com/c64-coding-tutorials/2013/4/8/episode-2-5-understanding-and-including-music">Episode 2-5: Understanding and including music</a></li>
</ul>

<hr />



  <h3>The problem we want to solve</h3><p>Our intro must print two lines of text to the screen, do a color wash effect on top of it and play music. While we can print our text once at the start and leave as is the color washer and the music on the other hand must be triggered&nbsp;continuously during execution. &nbsp;How would we manage this? This obviously requires some sort of timing capability - we need to find a clock or any other predictable event in the system to help us to execute our subroutines for music or color effects at a specific time while the intro runs.&nbsp;</p><p></p><p></p><p>It turns out that the C64 is a very organized computer following a specific procedure which involves triggering a so-called system interrupt routine about every 1/60 of a second on NTSC Machines and a about 1/50 of a second on PAL systems. What does this mean? Continuously the C64 freezes the current program to rather run some other code. After this code has been worked off, it will continue at the point it stopped before. From a perspective of the original frozen program nothing has changed. It does not know it was interrupted. You can read more about <a href="https://dustlayer.com/c64-architecture/2013/5/7/hardware-basics-part-1-tick-tock-know-your-clock">Clock Rates on NTSC and Pal machines in a dedicated article</a>.</p><p>This interruption of the system is happening so fast that as a user you do not realize either. For example the blinking cursor is actually a routine which is executed within the system interruption routine. &nbsp;Let's look at that &nbsp;routine a bit closer.</p><p></p><p>The system routine starts at memory address $EA31. It checks for example if the RUN-STOP key has been pressed which is instrumental when you want to stop a BASIC program. It also takes care that your cursor blinks three times per second by decrementing a counter from 20 once per interrupt. When zero is reached, it will reverse the cursor and the counting down restarts. Since the interrupt is triggered 60 times per second on NTSC respectively 50 times per second on PAL machines the cursor will&nbsp;therefor&nbsp;blink about three times in that period.&nbsp;</p><p>We now know two things - we have a system wide interruption that automatically occurs a number of times per second and there is a pattern for the C64 to make sure that things happening during that interrupt can be fine-controlled, in it's simplest form by using a countdown to skip execution of a subroutine within the interruption . With this we have the reliable recurring event we were looking for. We want to hop on that interval and execute our own code. ​</p><p></p><h3>Hijacking the System Interrupt</h3><p>​So since there is already something happening on a repeating basis, why not just use this to our advantage - let's hijack the system interrupt and execute our own subroutines in addition to the general interrupt routines. Before we do anything though we should understand how the interrupt is executed and where we can actually hook up.&nbsp;</p><h3>The Commodore Jump Table</h3><p>There are two important vectors which point to some part of the triggered system routine. A vector is simply a memory location stored in two bytes. Using a special jump instruction the C64 will use the address it finds in that vector to hop to that specific location. </p><p>Why not jump directly to the routine but use a vector instead you may ask? This is a design pattern by Commodore to help developers across their machines to rely on specific entry points for executing various main system routines available on all computers. For that they added a so-called jump table into the ROM which holds all the different vectors with addresses to those general system routines. That basically means that the actual system routine jumped to may be located at different memory locations depending on the machine but the entry vector to get to this location would be the same across systems. For example jumping to the vector at $FFF0/$FFF1&nbsp;is used to set the cursor position on all those &nbsp;machines back then though the actual memory location of PLOT varies from system to system.</p><p></p><h3>Time for boarding</h3><p>So the system interrupts first action every 1/60 of a second is to jump to the vector $FFFE/$FFFF. This vector is residing in ROM, so we can not change it to point to our own routines. What it does is to save the current status registers and index registers before pointing to $0314/$0315 - which is another vector pointing to our actual system interrupt routine. Why does it save all registers? Because during that interrupt registers will change for various reasons but the system wants to continue the frozen program in the same state it was interrupted before. After the system routine has done it's work, all saves registers are restored.&nbsp;</p><p></p><p>Now the second vector $0314/$0315 as opposed to $FFFE/$FFFF is located in RAM. We can just change the address in those two bytes to point to our own custom routine. Once our routine has finished execution we continue normal &nbsp;operation by pointing to the real system service routine at $EA31 which was the original target stored in $0314/$0315.​​&nbsp;</p>

































































 

  
  
    

      

      
        <figure class="
              sqs-block-image-figure
              intrinsic
            "
        >
          
        
        

        
          
            
              
              
          
            
                
                
                
                
                
                
                
                <img data-stretch="false" data-image="https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1365946865480-84N42DB4BNVFZE8BVCAF/highjacking_interrupt_3.png" data-image-dimensions="682x395" data-image-focal-point="0.5,0.5" alt="" data-load="false" elementtiming="system-image-block" src="https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1365946865480-84N42DB4BNVFZE8BVCAF/highjacking_interrupt_3.png?format=1000w" width="682" height="395" sizes="(max-width: 640px) 100vw, (max-width: 767px) 100vw, 100vw" onload="this.classList.add(&quot;loaded&quot;)" srcset="https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1365946865480-84N42DB4BNVFZE8BVCAF/highjacking_interrupt_3.png?format=100w 100w, https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1365946865480-84N42DB4BNVFZE8BVCAF/highjacking_interrupt_3.png?format=300w 300w, https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1365946865480-84N42DB4BNVFZE8BVCAF/highjacking_interrupt_3.png?format=500w 500w, https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1365946865480-84N42DB4BNVFZE8BVCAF/highjacking_interrupt_3.png?format=750w 750w, https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1365946865480-84N42DB4BNVFZE8BVCAF/highjacking_interrupt_3.png?format=1000w 1000w, https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1365946865480-84N42DB4BNVFZE8BVCAF/highjacking_interrupt_3.png?format=1500w 1500w, https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1365946865480-84N42DB4BNVFZE8BVCAF/highjacking_interrupt_3.png?format=2500w 2500w" loading="lazy" decoding="async" data-loader="sqs">

            
          
        
            
          
        

        
          
          <figcaption class="image-caption-wrapper">
            <p>The C64 executes the system interrupt routine 60 times per second. We can integrate our custom interrupt routine into that process.​</p>
          </figcaption>
        
      
        </figure>
      

    
  






  <h3>Slowing down</h3><p>Our custom routine is now executed 60 times per second - which is way too fast. We need to control this. We could use a counter like the interrupt service routine does for the cursor blinking but this does not give us the degree of accuracy we require plus it is not really convenient. Our music and color effect routine need to be executed exactly once per screen refresh - how do we sync to that refresh rate?</p><p></p><p>Luckily there is not only the automatic system interrupt but lots of other sources in the C64 which can be asked to trigger an interruption of the system when a certain event &nbsp;takes place. One of those sources is the VIC-II, our Video Controller Chip. It has a few special registers which lets us request a notification when for example two sprites collide on the screen - because in a game you may want to update scores exactly when this happens. Another possibility is to request notification when the raster beam which is generating the screen output continuously has reached a specific line on the monitor. In fact this option is a popular method to sync custom routines to whatever happens on the screen.&nbsp;</p><p><strong>Let's clarify what we need to do:​</strong></p><ol><li>​change a vector within the regular system interrupt process to point to some custom code every time the system interrupt &nbsp;is triggered</li><li>​we want to execute subroutines when reaching a defined moment in time, in our case when the raster beam has reached a certain line on the screen. We have to do this because executing our subroutines 60 times per second respectively&nbsp;50 times per second is usually too fast.</li><li>when the subroutines have completed execution we point back to the regular system interrupt routine which is $EA31 - <strong>we have come full circle</strong>! &nbsp;</li></ol><p>To meet this behaviour we need to do only two things. Setup the hijacking of the system interrupt and within that ask the VIC-II controller to let us know when the raster beam has reached a certain position. Let's check the example code.</p><p><strong>Open code/main.asm!​</strong></p><p></p><p>​</p>


























  <p>We start with the first part of the code in the main routine.&nbsp;</p><p>In the setup code we first need to tell the C64 to stop triggering interrupts for a brief moment. Why is this of importance? Think about that we change the vector at $314/$315 to point to our own routine. For that we consecutively change the byte in $314 and then in $315. But what happens when an interrupt just occurs after we wrote to $314? The vector will point to the wrong address and the system will probably crash. To avoid this there is the machine language command SEI. It sets the <em>Interrupt Disable Flag</em> in the status register to 1 and from that point on no interrupt is triggered until the flag has been cleared again using the complementary command <em>CLI </em>which clears that <strong>disabling</strong>&nbsp;flag again. hile we turn off the system interrupt there will be no cursor &nbsp;blinking and RUN-STOP key will not function either. Of course since we only disable the interrupt for a fraction of a second, we will not notice this as a user.&nbsp;</p><p>Before we finally redirect the system interrupt vector we also take the opportunity and do some one time initializations like clearing the screen, then writing the two lines of text for our intro and we also initialize the SID music routine. Those are the parts of our intro that only need to be executed once so we don't want that to be included in the routines happening 60 times per second.</p><p>After this there follows a block which disables other sources of interrupts and does some clean up work so there are no interferences to be expected. I will go into the various sources of interrupts in a dedicated Interrupt article at some point.</p><p>The important part of the setup code as far as the hijacking idea plan goes is where we finally load the accumulator and the X-Index-Register with the memory location the label <em>irq is pointing to and &nbsp;store it into $314/$315. </em></p><p><strong>There we have hijacked the system interrupt routine!</strong></p><h3>Syncing to the raster beam</h3><p>We need to make sure that our routine is only executed once per screen refresh otherwise the music would be way too fast and the color wash effect would look like a strobe light. You can in fact test how this would look. Just remove the dec $d019 command, but do not delete the label <em>irq</em>. Then build and run index.asm &nbsp;and watch the intro being played back in Warp9 speed. This also means that $d019 is somewhat important to make sure that the notification request for the raster beam is refreshed - I will explain in a bit.</p><p>To get the optimal speed for our intro we want to run our subroutines once per screen refresh. But how do we determine this? e will register a request with the VIC-II chip. We need to tell the Video Controller what type of interrupt we want to be informed of and of course at what point the notification should happen. In the address $D01A we set Bit 0 to let the VIC-II know that we want to request a notification from a raster beam event. $D012 is the place where we define at what line number the interrupt should be triggered - for our intro that would be line zero. We could have used any other line number as we are only concerned to get a notification once per screen refresh no matter where it occurs.</p><p>Last but not least we need to consider that the C64 has a mechanism to check if the raster beam has passed line 255. As you know one Byte can hold only up to 256 values - so we can very easily check if the raster beam is somewhere between line 0 and line 255 - <strong>but the C64 has more horizontal lines</strong>. &nbsp;How would the C64 know that we are on line 300 for instance?</p><p>We actually need 9 Bits to really check all available raster lines. And that is exactly what the C64 is asking for. It borrows Bit#7 of the register $d011 to use it as extra Bit. When the raster beam has passed the 256 possible values in $d012 it will set Bit#0 on $d011 &nbsp;and restarts counting in $d012 until it reached the end of the screen. Then it clears Bit#0 in $d011 again. As we know that our text is written somewhere in the middle of the screen we want to make sure that Bit#0 in $d011 is not set by accident when we start our intro. This could be the case when for example certain Fastloader cartridges are inserted.&nbsp;</p><p> </p><p>Our setup code is complete - whenever the raster beam reaches line zero, our custom routine at label <em>irq </em>is executed.</p><p> </p><h3>The custom IRQ routine</h3><p>Our custom IRQ routine is actually very simple. All it does is acknowledging the IRQ and reset the register then it runs two sub routines. One is for the color wash effect and the other is for playing back the music. Once both subroutines have returned we jump to $EA31, the original system interrupt routine.</p><p>The acknowledging command <strong>dec $d019 </strong>might actually be confusing and needs clarification.</p><p>What we &nbsp;need to do every time our custom IRQ routine is executed is to tell via register $d019 that everything is fine and that we want another notification with the next screen refresh, that is the next time the raster beam reaches line zero on the screen. To make this happen the process is to read the content of $d019 and write it back to the same register. This will reset $d019 and our interrupt triggered from the VIC-II chip will be executed again as configured in $d012 before. The Read/Write pattern to do the reset is a special behavior of that $d019 register.</p><p>Now as coders are looking for optimization all the time somebody found out that the decrement command <em>dec</em> can be used to do both operations with just one single command. This works because dec is a so-called Read-Modify-Write command that writes back the original value during the modify cycle.</p><p>Using <em>dec $d019</em> instead of &nbsp;executing the two consecutive commands <em>lda $d019</em> and<em> sta $d019</em> will save us some time in typing and system cycles.<span>&nbsp;</span></p><p>This is all you need to know about the interrupt for this first example intro. In the next two chapters we will look at the two subroutines we execute on our raster beam interrupt.</p><p>-act</p>]]></description></item><item><title>Episode 2-2: Writing to the C64 Screen</title><dc:creator>actraiser</dc:creator><pubDate>Fri, 05 Apr 2013 17:41:00 +0000</pubDate><link>https://dustlayer.com/c64-coding-tutorials/2013/4/8/episode-2-2-writing-to-the-c64-screen</link><guid isPermaLink="false">511651d6e4b0a31c035e30aa:5117493de4b085e20f7f2f40:51628551e4b05c30816907ec</guid><description><![CDATA[<p><strong>Topics:</strong> Now that we saw the working intro, we want to understand how it works. Let's start with the text written to the C64 screen.  </p>

<p><strong>Download via <a href="http://dustlayer.com/c64-coding-tutorials/2013/2/10/dust-c64-command-line-tool">dust</a>:</strong> $ dust tutorials (select 'first intro') <br />
<strong>Github Repository:</strong> <a href="https://github.com/actraiser/dust-tutorial-c64-first-intro" target="_new">First Intro on Github</a>  </p>

<ul>
<li><a href="http://dustlayer.com/c64-coding-tutorials/2013/2/17/a-simple-c64-intro">Episode 2-1: Let's compile and run C64 code</a></li>
<li><strong>Episode 2-2: Writing to the C64 Screen</strong></li>
<li><a href="http://dustlayer.com/c64-coding-tutorials/2013/4/8/episode-2-3-did-i-interrupt-you">Episode 2-3: Did I interrupt you?</a></li>
<li><a href="http://dustlayer.com/c64-coding-tutorials/2013/4/8/episode-2-4-reading-from-a-data-table">Episode 2-4: Effects using a table of data</a></li>
<li><a href="http://dustlayer.com/c64-coding-tutorials/2013/4/8/episode-2-5-understanding-and-including-music">Episode 2-5: Understanding and including music</a> </li>
</ul>

<hr />



  <h3>The Memory Map</h3><p>Before we write to the C64 screen we need to cover some basics about how memory is organized in the C64. If you are not fluent in this topic just take a look at the &nbsp;<a href="https://dustlayer.com/c64-architecture/2013/4/13/ram-under-rom">RAM under ROM</a>&nbsp;article in the knowledge base.&nbsp;</p><p></p><h3>Let's put text on the screen</h3><p>So everything in the C64 is addressable using memory locations. The 40 columns x 25 rows of screen you see when turning on the C64 is simply a 1000 Bytes (40x25) large area of the memory called Screen RAM located at address 1024-2023 ($0400-$07F7). Whatever you write into any of those 1000 locations, it will show up in some way on the screen. To put something there which makes sense you have to look up Screen Codes which are associated which each of the C64 characters available when you turn on the computer. Luckily you don't have to bother with Screen Code tables as ACME already provides features to make this easy - I will explain below.</p><p>Anyways, for example the Screen Code 1 put into location 1024 ($0400) will print the letter "A" on the top left corner of the screen.&nbsp;</p><p>n addition to Screen RAM, there is Color RAM from 55296-56295 ($D800-$DBE7). It also spans over 1000 Bytes and maps the Screen RAM locations 1:1. The lower 4 Bits of the Color RAM are used to set foreground color for the appropriate Screen RAM location. &nbsp;You only need the 4 Bits - also called a Nibble which means "one half of a byte" - as there are only 16 colors available on the C64, so 4 Bits are sufficient to store any of the 16 combinations. &nbsp;If you put a zero into memory location 55296, the previously printed A turns black.&nbsp;</p><p><strong>Type in the BASIC POKE commands on your emulator or real hardware to verify:</strong></p><p><em><em>POKE 1024,1</em></em><br /><em>POKE 55296,0</em></p>


































































  

    
  
    

      

      
        <figure class="
              sqs-block-image-figure
              intrinsic
            "
        >
          
        
        

        
          
            
              
              
          
            
                
                
                
                
                
                
                
                <img data-stretch="false" data-image="https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1365881071008-9YO8VEOAFB7PZF5890MO/Bildschirmfoto+2013-04-13+um+21.22.30.png" data-image-dimensions="357x270" data-image-focal-point="0.5,0.5" alt="" data-load="false" elementtiming="system-image-block" src="https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1365881071008-9YO8VEOAFB7PZF5890MO/Bildschirmfoto+2013-04-13+um+21.22.30.png?format=1000w" width="357" height="270" sizes="(max-width: 640px) 100vw, (max-width: 767px) 100vw, 100vw" onload="this.classList.add(&quot;loaded&quot;)" srcset="https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1365881071008-9YO8VEOAFB7PZF5890MO/Bildschirmfoto+2013-04-13+um+21.22.30.png?format=100w 100w, https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1365881071008-9YO8VEOAFB7PZF5890MO/Bildschirmfoto+2013-04-13+um+21.22.30.png?format=300w 300w, https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1365881071008-9YO8VEOAFB7PZF5890MO/Bildschirmfoto+2013-04-13+um+21.22.30.png?format=500w 500w, https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1365881071008-9YO8VEOAFB7PZF5890MO/Bildschirmfoto+2013-04-13+um+21.22.30.png?format=750w 750w, https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1365881071008-9YO8VEOAFB7PZF5890MO/Bildschirmfoto+2013-04-13+um+21.22.30.png?format=1000w 1000w, https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1365881071008-9YO8VEOAFB7PZF5890MO/Bildschirmfoto+2013-04-13+um+21.22.30.png?format=1500w 1500w, https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1365881071008-9YO8VEOAFB7PZF5890MO/Bildschirmfoto+2013-04-13+um+21.22.30.png?format=2500w 2500w" loading="lazy" decoding="async" data-loader="sqs">

            
          
        
            
          
        

        
          
          <figcaption class="image-caption-wrapper">
            <p>writing to Screen RAM and Color RAM using BASIC Poke command</p>
          </figcaption>
        
      
        </figure>
      

    
  


  





  <p>So how does this work with machine language? Let's look at the intro code.</p><h3>​Black out</h3><p>Our Intro can not start with the standard blue background and C64 welcome text, let's put out the lights. There in fact is a single system routine we could execute but &nbsp;we want to do it the hard but faster way. ​</p><p><strong>Open code/init_clear_screen.asm</strong></p>


























  <p>The first thing we want to do is to set the border and background color to black. There are two memory locations we just need to set to $00 to achieve this $d020 and $d021.&nbsp;</p><p>Then we learned that the actual screen is just an area in memory spanning over 1000 bytes. If we put a space bar in each of those locations and turn the foreground color to black we should achieve a completely black screen without any text. &nbsp;And that is what we will do!</p><p>We load the Accumulator with the screen code for the &lt;blank&gt; character which is $20 (decimal 32). Since 1000 locations need to be filled but only 256 iterations can be done with a single byte counter we just start at four positions on the screen at once with the filling. With this method we will be able to turn the entire screen black with just 256 iterations. That's why all we need to do is to check if our X-Index-Register has turned to Zero with the <em>bne</em> branch command. Unless this is the case we increment X and hop back to the <em>clear</em> label. &nbsp;</p><p>Of course we also need to set the color to black in Color Ram for each of the locations. We do this along the way by loading the Accumulator with $00 and store it in the appropriate memory location starting at $d800.</p><p>By the way - with this information you should now be able to do the "inc $d020" effect I ranted about in Episode 2-1. All you need is an infinite loop and increment the memory location of the border color. </p><h3>Writing Text to the middle of the screen</h3><p><strong>Open the file code/data_static_text.asm</strong></p>


























  <p>Now meet one of many&nbsp;conveniences using a cross-development environment. As we use the assembler syntax of the ACME cross assembler we have some very helpful pseudo opcodes which ACME will process for us during compilation. All ACME pseudo opcodes are prefixed with an&nbsp;exclamation&nbsp;mark.&nbsp;</p><p>What "!scr" does is to translate the following string to individual C64 screen codes and puts each in the next processed memory location. Which location that might be is not of a big concern to us for this first simple example. &nbsp;By prefixing each of the rows with a label (<em>line1, line2</em>) we can easily reference the memory location later, e.g. when we need to loop over this data to actually display the text. Again, we do not need to know where in memory the text is stored which is very convenient.&nbsp;</p><p>So here comes the next challenge. Now that we have some text defined, how do we print it to the screen using 6502 machine language?</p><p><strong>Open code/init_static_text.asm</strong></p>


























  <p>What we want to do is to put the two strings stored in data_static_text.asm into the middle of the C64 screen. We know that the screen ram starts in memory at $0400 so we estimate the middle of the screen near $0590 for the first line of text and $05E0 for the second line. </p><p>We now need to loop over the previously defined string data byte by byte and copy what we read into the memory locations of the Screen Ram. As pointed out above, we do not need to know where the text is located in memory but just use the label specified before.</p><p>e add another label for the code to loop over the text (init_text), then we initialize our X-Index-Register with zero and start with loading the first byte stored at label line1 into the accumulator. The content of the accumulator is then stored at the location near the middle of the screen plus the content of the X-Index-Register which is 0 at the beginning.&nbsp;</p><p>The content of <em>line1,x </em>s the first byte in the first string, actually the Screen Code for a space character. We store the code from the accumulator to the appropriate position in Screen RAM at $0590 plus the value of the X-Index-Register which is still zero.&nbsp;</p><p>We repeat the process with line2 but this time we start storing the screen code at $05E0 which is two lines below the previous Screen RAM we wrote to earlier. </p><p> </p><p>The first byte of each line of text has been written to Screen RAM - excellent! Now we want to do the same with the second character of the string. For that all we need to do is to increment the X-Index-Register and continue looping.&nbsp;</p><p><em>inx </em>oes exactly that - it increments the content of the X-Index-Register. The next thing before we continue the loop is to check whether we already finished iterating over the complete line. As one row of the C64 screen can not hold more than 40 characters we simply compare the X-Index-Register using the <em>cmp</em> command to the number 40 which is $28 in hex. the branch command <em>bne</em>&nbsp;will jump back to our label <em>loop_text</em> if the comparison is not true. With this we can work through 40 bytes of data for each line. Once the comparison to $28 is true the next command after <em>bne executed. </em>&nbsp;This is an <em>rts </em>hich means <em>return from subroutine</em>.</p><p><strong>And that's it!&nbsp;</strong>on't worry that we skipped some details yet but you should have been able to get what we did to write some text to the C64 screen. We will soon do another iteration example when it comes to the color washer effect but before that, we talk about interrupts.</p><p>-act</p>]]></description></item><item><title>Episode 2-1:  Let's compile and run C64 code</title><dc:creator>actraiser</dc:creator><pubDate>Thu, 04 Apr 2013 08:00:00 +0000</pubDate><link>https://dustlayer.com/c64-coding-tutorials/2013/2/17/a-simple-c64-intro</link><guid isPermaLink="false">511651d6e4b0a31c035e30aa:5117493de4b085e20f7f2f40:5121383fe4b06840010a7377</guid><description><![CDATA[<p><strong>Topics:</strong> In this first tutorial I want to cover some basics like loading code, writing text to screen, adding effects and include music. No indepth explanations yet, let's get an initial feeling for C64 coding.  </p>
<p><strong>Download via <a href="http://dustlayer.com/c64-coding-tutorials/2013/2/10/dust-c64-command-line-tool">dust</a>:</strong> $ dust tutorials (select 'first intro')<br><strong>Github Repository:</strong> <a data-preserve-html-node="true" href="https://github.com/actraiser/dust-tutorial-c64-first-intro" target="_new">First Intro on Github</a>  </p>
<ul>
<li><strong>Episode 2-1: Let's compile and run C64 code</strong></li>
<li><a href="http://dustlayer.com/c64-coding-tutorials/2013/4/8/episode-2-2-writing-to-the-c64-screen">Episode 2-2: Writing to the C64 Screen</a></li>
<li><a href="http://dustlayer.com/c64-coding-tutorials/2013/4/8/episode-2-3-did-i-interrupt-you">Episode 2-3: Did I interrupt you?</a></li>
<li><a href="http://dustlayer.com/c64-coding-tutorials/2013/4/8/episode-2-4-reading-from-a-data-table">Episode 2-4: Effects using a table of data</a></li>
<li><a href="http://dustlayer.com/c64-coding-tutorials/2013/4/8/episode-2-5-understanding-and-including-music">Episode 2-5: Understanding and including music</a></li>
</ul>
<hr>




  <h3>We start simple but not too simple</h3><p><strong>Is there something more boring then the "inc $d020" tutorials seen on most C64 beginner tutorials?</strong> I think people who start coding the C64 want to do the cool stuff they did not understand in the past. And new people to C64 coding must get an immediate understanding with how little effort you can achieve cool stuff. I think if you want to get people excited about C64 development one must provide a breath of retro demo coding. On the other hand I understand that a lot of simplification is required to not frustrate people on their first steps. Anyways, if you wonder what that standard introduction into C64 coding looks like, here is a screenshot.</p>


































































  

    
  
    

      

      
        <figure class="
              sqs-block-image-figure
              intrinsic
            "
        >
          
        
        

        
          
            
              
              
          
            
                
                
                
                
                
                
                
                <img data-stretch="false" data-image="https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1365169478511-1O2SJ8125PVYZ8AG7KUR/inc-d020.png" data-image-dimensions="320x242" data-image-focal-point="0.5,0.5" alt="" data-load="false" elementtiming="system-image-block" src="https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1365169478511-1O2SJ8125PVYZ8AG7KUR/inc-d020.png?format=1000w" width="320" height="242" sizes="(max-width: 640px) 100vw, (max-width: 767px) 100vw, 100vw" onload="this.classList.add(&quot;loaded&quot;)" srcset="https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1365169478511-1O2SJ8125PVYZ8AG7KUR/inc-d020.png?format=100w 100w, https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1365169478511-1O2SJ8125PVYZ8AG7KUR/inc-d020.png?format=300w 300w, https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1365169478511-1O2SJ8125PVYZ8AG7KUR/inc-d020.png?format=500w 500w, https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1365169478511-1O2SJ8125PVYZ8AG7KUR/inc-d020.png?format=750w 750w, https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1365169478511-1O2SJ8125PVYZ8AG7KUR/inc-d020.png?format=1000w 1000w, https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1365169478511-1O2SJ8125PVYZ8AG7KUR/inc-d020.png?format=1500w 1500w, https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1365169478511-1O2SJ8125PVYZ8AG7KUR/inc-d020.png?format=2500w 2500w" loading="lazy" decoding="async" data-loader="sqs">

            
          
        
            
          
        

        
          
          <figcaption class="image-caption-wrapper">
            <p>If you look for first steps into C64 assembler programming, chances are high you will be offered with this super simple effect. Boring...​</p>
          </figcaption>
        
      
        </figure>
      

    
  


  





  <h3>A real C64 intro explained</h3><p>As opposed to the boring screenshot above the little intro that we will inspect during this tutorial is simple but as a kid in the 80s I would have thought it is &nbsp;looking cool. Basically something I wanted to achieve myself one day after I understand how to code C64 - I &nbsp;just did not expect to wait for over 25 years. The intro is not much more complex than let's say <a target="_blank" href="http://www.youtube.com/watch?v=nLaVqPULd7I">the famous Dynamic Duo intro</a> and how much did I admire those guys and felt good whenever I saw the intro.</p><p> </p><p>All our little intro does is to display two lines of text with a rotor-like colorcycle effect and it plays some background music.&nbsp;</p>























dust users can download the code via the command line
<p>When the code has been downloaded, just change into the directory and run "dust compile". Vice should open and the compiled intro will be loaded in the emulator. If you don't use DUST there is some advice in the <a href="http://dustlayer.com/c64-coding-tutorials/2013/4/8/working-without-dust-environment">second chapter</a> of this tutorial.</p>

<p><strong>Here is a video of the actual program.</strong></p>
<iframe data-image-dimensions="854x480" allowfullscreen="" src="http://www.youtube.com/embed/iUVFHxnvabM?feature=oembed&amp;wmode=opaque&amp;enablejsapi=1" width="854" data-embed="true" frameborder="0" height="480"></iframe><p>This is the output of the Beginner's Tutorial on C64 coding. The tutorial is located at https://dustlayer.com/c64-coding-tutorials/2013/2/17/a-simple-c64-intro</p>


  <p>Wow! So simple but it somewhat catches the beginner with the nice sid music and the color cycling, does it not?&nbsp;</p><p>So what we do here is putting two lines of text using the standard C64 font in the middle of the screen, do twice the color cycle effect in two different directions for each line and last but not least make sure the music is played while all this crazy stuff happens. &nbsp;</p><h3>The basics you will get introduced to</h3><p>In the next chapters I will describe in details everything that is required to understand what is going on in the intro. We will touch programming of the interrupt, you will also soon understand how memory,&nbsp;and in particular the screen,&nbsp;is organized on the C64. I will explain how to iterate over tables of data, e.g. to change color information or to display a line of text. Finally we will include the music into the intro and look how initialization and playback work.</p><h3><span>-act</span></h3>]]></description></item><item><title>Episode 1-2: Working without DUST environment</title><dc:creator>actraiser</dc:creator><pubDate>Tue, 02 Apr 2013 20:14:00 +0000</pubDate><link>https://dustlayer.com/c64-coding-tutorials/2013/4/8/working-without-dust-environment</link><guid isPermaLink="false">511651d6e4b0a31c035e30aa:5117493de4b085e20f7f2f40:51628718e4b01df404d6fea9</guid><description><![CDATA[<p><strong>Topics:</strong> Maybe you are on Windows or Linux or the DUST setup for some reason did not work out. Here is some information how to work with the tutorial code provided on dustlayer.com.</p>

<ul>
<li><a href="http://dustlayer.com/c64-coding-tutorials/2013/2/10/dust-c64-command-line-tool">Episode 1-1: Introduction to DUST - the Mac tool for C64 development</a></li>
<li><strong>Episode 1-2: working without DUST environment</strong></li>
</ul>

<hr />



  <h3>The point of using DUST</h3><p>DUST is a problem solver for Mac OSX users. It takes care of setting up various tools to ease C64 cross-development. It follows a setup which is compliant with what I use to learn Machine Language and it is also the setup which will run code from dustlayer.com.</p><p>If you want to work with the tutorials on dustlayer.com but have a system environment not compatible to install DUST you can of course set up everything required yourself.</p><h3>Mandatory Tools</h3><p><strong>ACME Cross Assembler &nbsp;</strong><br />You will need the ACME cross assembler. There are of course other cross assemblers but I use this one. I have not tried others so I don't know if they are better but then again I am too lazy to evaluate assemblers when ACME works just fine.<br /><a target="_blank" href="https://sourceforge.net/projects/acme-crossass/">Download ACME</a></p><p><strong>A C64 Emulator &nbsp;</strong><br />Probably any C64 Emulator will do but I use Vice which is available on many systems.&nbsp;<br /><a target="_blank" href="http://sourceforge.net/projects/vice-emu/">Download Vice</a></p><p><strong>Git</strong><br />Git is a command line client to download projects from a git repository. It's basically a version control system. I host all tutorials on <a target="_blank" href="http://github.com/actraiser">github.com</a> which is great way to distribute source code. You need git to download tutorials code, every tutorial on dustlayer.com will have the download information on top of each article. You don't need to sign up on github.com if all you want is to download the code for the tutorials.<br /><a target="_blank" href="http://git-scm.com/downloads">Download Git</a></p><p>That's all what is mandatory - everything else provided by DUST is sugar on top like pre-configured IDEs, build scripts, additional command line tools etc.</p><h3>Running dustlayer tutorial code</h3><p>Here is an example workflow which should work out of the box when all tools above are set up by you.</p>


























  <p>The <em>open</em> command does not exist on Windows - run the hello_world.prg by double clicking it in the Explorer. It should be associated with the C64 emulator of your choice.</p><p>-act</p>]]></description><media:content type="image/png" url="https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1365411681146-6K3NP7JLIWDI4CYASAJJ/dust_tiled.png?format=1500w" medium="image" isDefault="true" width="546" height="177"><media:title type="plain">Episode 1-2: Working without DUST environment</media:title></media:content></item><item><title>Episode 1-1: Introduction to DUST - the Mac tool for C64 development</title><dc:creator>actraiser</dc:creator><pubDate>Tue, 02 Apr 2013 12:58:00 +0000</pubDate><link>https://dustlayer.com/c64-coding-tutorials/2013/2/10/dust-c64-command-line-tool</link><guid isPermaLink="false">511651d6e4b0a31c035e30aa:5117493de4b085e20f7f2f40:51174953e4b085e20f7f2f5f</guid><description><![CDATA[<p><strong>Topics:</strong> Introduction into the DUST Command Line Utility for Mac OSX. Get a complete C64 cross development environment in three minutes with all the bells and whistles.</p>

<ul>
<li><strong>Episode 1-1: Introduction to DUST - the Mac tool for C64 development</strong></li>
<li><a href="http://dustlayer.com/c64-coding-tutorials/2013/4/8/working-without-dust-environment">Episode 1-2: working without DUST environment</a></li>
</ul>

<hr />



  <h2>The joy of cross-development</h2><p>While coding the Commodore C64 is fun, coding ON the C64 is not so much by todays standards. You probably don't want to hack and comment code in a 40x25 screen, you also don't want to miss helpful tools and functions in todays editors, source code versioning, quick testing, etc. &nbsp;Of course please feel encouraged to use real hardware to see your work in a true retro environment - this is something cross development will never provide. &nbsp;</p><p>Since the times are no more when one put notes and register information on a piece of paper or draw sprites on&nbsp;<span>quad-ruled&nbsp;</span>paper first we should ask what development environment&nbsp;we want. . To have fun by todays coding standards I wanted the following covered on a Mac OSX system:</p><ul><li>efficient and fun workflow - develop, compile, crunch and run code triggered within the editor on a key press or from the command line</li><li>IDE with 6502 and eventually BASIC syntax highlighting</li><li>no Installation hell - ideally a package manager-like solution</li></ul><p>&nbsp;</p><p>&nbsp;</p><p>So when I started to learn coding 6502 assembler last year I built my setup from scratch without real pointers what the right approach might be on a Mac. There are two to me known all-in-one editors for Windows, &nbsp;<a target="_blank" href="http://www.georg-rottensteiner.de/en/index.html">C64Studio</a> and <a target="_blank" href="http://popelganda.de/relaunch64.html">Relaunch64</a>. The latter is also now available in a Beta-Version based on Java that somewhat works on a Mac but I rather wanted to use a rock-solid Mac-based IDE instead which is Sublime Text 2.&nbsp;</p><p>&nbsp;</p><p>&nbsp;</p><p>&nbsp;</p><p>I wanted to write tutorials for beginners like me and provide the code in a easy to use way. nd for what it's worth - the whole setup on the Mac must be ready within minutes and all installed software should be upgradable without hassle with a one step command.</p><p>&nbsp;</p><p>&nbsp;</p><p>&nbsp;</p><p>&nbsp;</p><p>&nbsp;</p><p><strong>What needs to be set up by you:</strong></p><ul><li>If your OSX Version is lower than 10.7.4 you need to Install Apples XCode. With OSX Versions 10.7.4 or higher you can just download the much smaller CLI Package also provided by Apple on their <a target="_blank" href="https://developer.apple.com/downloads/index.action">download page</a> (one time registration required).</li><li>Two small tools need to be installed, git and node.js - both are available as one click installers.</li></ul><p>&nbsp;</p><p><span><strong>Wh</strong></span><strong>at DUST will set up for you:</strong></p><p>&nbsp;</p><ul><li>Of course the 'dust' command line suite</li><li>ACME Cross Compiler (6502 compiler which compiles your source code to a executable .prg file</li><li>exobasic (optimizer for Basic 2.0 and many of its extensions like Simons Basic).</li><li>Sublime Text 2 plus a few extensions and scripts</li><li>pucrunch (a cruncher which will pack the output file created by ACME)</li><li>Vice64 (the C64 Emulator which runs your code)</li><li>Sidreloc (helpful utility to relocate sid files in C64 memory)</li></ul><p>&nbsp;</p><p>Sublime will be configured to provide syntax highlighting for 6502 assembler and BASIC. Build Systems are setup so you can compile and run code with one short cut.</p><h3>The feature history of DUST</h3><p>DUST started out as a simple shell script I executed from an text editor to compile C64 Machine Language code to run it in VICE - rather than to do this in the shell each time I wanted to check something.&nbsp;</p><p>Over Time features were consecutively added:</p><ul><li> automatic installation process to install various tools for the command line and the OSX desktop including emulation of some popular Win32 tools</li><li>Configuration of the tools like addition of Syntax Highlighting for Machine Language and BASIC code n Sublime Text 2.&nbsp;</li><li>Commands to create a basic project layout for Machine Language and BASIC</li><li>Download of code for tutorials published on dustlayer.com</li><li>Support for automatic setup routines and configuration for additional systems is included but I have not added any other system in addition to the C64 yet.&nbsp;</li></ul><p>Also the tool was moved from being a shell script to a node.js driven solution as it allowed for more&nbsp;flexibility&nbsp;and easy installation and distribution via NPM. </p><p>&nbsp;</p><h3>Let's start with the &nbsp;three steps of installation work!</h3><p>&nbsp;</p><h3>1. Download and install XCode or the Command Line Tools</h3><p><strong>Command Line tools (OSX 10.7.3+)</strong><br>If you don't have XCode installed in the past and your OSX Version is higher than 10.7.3, than you can just download the Command Line Tools by Apple which will install all the utilities needed to do day by day development . Download a version which matches your system at the <a target="_blank" href="https://developer.apple.com/downloads/index.action">Apple Developer Portal</a>.</p><p><strong>XCode (OSX &gt;10.7.3 or for people who already have XCode installed)</strong><br>If your OSX Version is below 10.7.3, just need to download XCode at the same place mentioned above. The difference is that XCode includes lots of things we will not need but makes the download much bigger plus there is an extra setup to enable the command line tools:</p><p>When XCode is installed you need to post-install the XCode Command Line Tools. The install button is well hidden in the <strong>XCode Preferences</strong> under the <strong>Downloads</strong> tab:&nbsp;</p>

































































 

  
  
    

      

      
        <figure class="
              sqs-block-image-figure
              intrinsic
            "
        >
          
        
        

        
          
            
              
              
          
            
                
                
                
                
                
                
                
                <img data-stretch="false" data-image="https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1361345317328-W8OBK8I9ATXCYYBFNVC6/cmd+tools.png" data-image-dimensions="750x528" data-image-focal-point="0.5,0.5" alt="" data-load="false" elementtiming="system-image-block" src="https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1361345317328-W8OBK8I9ATXCYYBFNVC6/cmd+tools.png?format=1000w" width="750" height="528" sizes="(max-width: 640px) 100vw, (max-width: 767px) 100vw, 100vw" onload="this.classList.add(&quot;loaded&quot;)" srcset="https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1361345317328-W8OBK8I9ATXCYYBFNVC6/cmd+tools.png?format=100w 100w, https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1361345317328-W8OBK8I9ATXCYYBFNVC6/cmd+tools.png?format=300w 300w, https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1361345317328-W8OBK8I9ATXCYYBFNVC6/cmd+tools.png?format=500w 500w, https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1361345317328-W8OBK8I9ATXCYYBFNVC6/cmd+tools.png?format=750w 750w, https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1361345317328-W8OBK8I9ATXCYYBFNVC6/cmd+tools.png?format=1000w 1000w, https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1361345317328-W8OBK8I9ATXCYYBFNVC6/cmd+tools.png?format=1500w 1500w, https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1361345317328-W8OBK8I9ATXCYYBFNVC6/cmd+tools.png?format=2500w 2500w" loading="lazy" decoding="async" data-loader="sqs">

            
          
        
            
          
        

        
      
        </figure>
      

    
  






  <h3>2. Install git and node.js</h3><p>Bot Git and Node.JS are available as One-Click installers.&nbsp;</p><p><a target="_blank" href="http://git-scm.com/downloads">Git Download Page</a><br><a target="_blank" href="http://nodejs.org/">Node.js Download Page</a></p>


























  <h3>3. Install DUST</h3><p>Installing DUST&nbsp;is very easy. Just go into your terminal and type the following command. There actually already was a project named 'dust' &nbsp;so I had to choose the name dustlayer for the package - well, first come first serve.</p>


























  <p>After a short while DUST is installed at your system. The installation output should look like this. After the installation, invoke the DUST command and check if it works.&nbsp;</p>


























  <h3>4. Setup environment</h3><p>Now it's a matter of setting up your environment using the DUST utility. Just type <strong>dust setup&nbsp;</strong>and everything will be installed and configured to get going. You typically want to use the 'Install all'-option unless you want to use an editor other than Sublime 2.</p><p>After Setup is completed, y<span>ou should download a project with the command 'dust tutorials', e.g. for the </span><a href="https://dustlayer.com/c64-coding-tutorials/2013/2/17/a-simple-c64-intro">Episode 2 tutorial</a><span> to test your setup. &nbsp;You also need to select &nbsp;the build system in Sublime which must be done in the Tools/Build System menu only once.</span></p>

































































 

  
  
    

      

      
        <figure class="
              sqs-block-image-figure
              intrinsic
            "
        >
          
        
        

        
          
            
          
            
                
                
                
                
                
                
                
                <img data-stretch="false" data-image="https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1361358943194-VF8U2838ACAPG72LG3X0/Screen+Shot+2013-02-20+at+12.15.20+PM.png" data-image-dimensions="603x429" data-image-focal-point="0.5,0.5" alt="" data-load="false" elementtiming="system-image-block" src="https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1361358943194-VF8U2838ACAPG72LG3X0/Screen+Shot+2013-02-20+at+12.15.20+PM.png?format=1000w" width="603" height="429" sizes="(max-width: 640px) 100vw, (max-width: 767px) 100vw, 100vw" onload="this.classList.add(&quot;loaded&quot;)" srcset="https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1361358943194-VF8U2838ACAPG72LG3X0/Screen+Shot+2013-02-20+at+12.15.20+PM.png?format=100w 100w, https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1361358943194-VF8U2838ACAPG72LG3X0/Screen+Shot+2013-02-20+at+12.15.20+PM.png?format=300w 300w, https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1361358943194-VF8U2838ACAPG72LG3X0/Screen+Shot+2013-02-20+at+12.15.20+PM.png?format=500w 500w, https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1361358943194-VF8U2838ACAPG72LG3X0/Screen+Shot+2013-02-20+at+12.15.20+PM.png?format=750w 750w, https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1361358943194-VF8U2838ACAPG72LG3X0/Screen+Shot+2013-02-20+at+12.15.20+PM.png?format=1000w 1000w, https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1361358943194-VF8U2838ACAPG72LG3X0/Screen+Shot+2013-02-20+at+12.15.20+PM.png?format=1500w 1500w, https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1361358943194-VF8U2838ACAPG72LG3X0/Screen+Shot+2013-02-20+at+12.15.20+PM.png?format=2500w 2500w" loading="lazy" decoding="async" data-loader="sqs">

            
          
        
          
        

        
      
        </figure>
      

    
  






  <p>Select "<strong>c64</strong>" for assembling 6502 code. Make sure the file <strong>index.asm&nbsp;</strong>is still the focused file in the editor and then hit <strong>⌘ + B</strong> to compile and execute. Vice will open and run the example.&nbsp;</p>

































































 

  
  
    

      

      
        <figure class="
              sqs-block-image-figure
              intrinsic
            "
        >
          
        
        

        
          
            
          
            
                
                
                
                
                
                
                
                <img data-stretch="false" data-image="https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1361184412803-4K641L9NS3FDHC05YCUP/helloworld_dustlayer.png" data-image-dimensions="364x295" data-image-focal-point="0.5,0.5" alt="" data-load="false" elementtiming="system-image-block" src="https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1361184412803-4K641L9NS3FDHC05YCUP/helloworld_dustlayer.png?format=1000w" width="364" height="295" sizes="(max-width: 640px) 100vw, (max-width: 767px) 100vw, 100vw" onload="this.classList.add(&quot;loaded&quot;)" srcset="https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1361184412803-4K641L9NS3FDHC05YCUP/helloworld_dustlayer.png?format=100w 100w, https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1361184412803-4K641L9NS3FDHC05YCUP/helloworld_dustlayer.png?format=300w 300w, https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1361184412803-4K641L9NS3FDHC05YCUP/helloworld_dustlayer.png?format=500w 500w, https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1361184412803-4K641L9NS3FDHC05YCUP/helloworld_dustlayer.png?format=750w 750w, https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1361184412803-4K641L9NS3FDHC05YCUP/helloworld_dustlayer.png?format=1000w 1000w, https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1361184412803-4K641L9NS3FDHC05YCUP/helloworld_dustlayer.png?format=1500w 1500w, https://images.squarespace-cdn.com/content/v1/511651d6e4b0a31c035e30aa/1361184412803-4K641L9NS3FDHC05YCUP/helloworld_dustlayer.png?format=2500w 2500w" loading="lazy" decoding="async" data-loader="sqs">

            
          
        
          
        

        
      
        </figure>
      

    
  






  <p>By the way, if you do modifcations to the code, you can just hit <strong>⌘ + B </strong>again without closing Vice before-hand. The assemble script will take care that eventual open Vice Sessions are closed. If you want to test the basic project you need to change the build system to 'c64 basic'. Dustlayer focuses on 6502 coding though but I wanted to include support for BASIC editing and executing nevertheless.</p><p>&nbsp;</p><p>The setup will eventually improve over time, update individual components or add new features. Updating will be very simply using a single npm command. I hope this tool lifts a lot of work from anyone who want to kickstart on C64 development on Mac OSX.</p><p>&nbsp;</p><p>-act</p>]]></description></item></channel></rss>