<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
  <generator uri="http://jekyllrb.com" version="4.4.1">Jekyll</generator>
  
  
  <link href="https://mon.im/feed.xml" rel="self" type="application/atom+xml" />
  <link href="https://mon.im/" rel="alternate" type="text/html" hreflang="en" />
  <updated>2025-10-12T08:32:34+00:00</updated>
  <id>https://mon.im/</id>

  
    <title type="html">mon.im</title>
  

  
    <subtitle>Music and code</subtitle>
  

  
    <author>
        <name>mon</name>
      
      
    </author>
  

  
  
    <entry>
      
      <title type="html">Using the Tatacon to USB converter with a PS4</title>
      
      
      <link href="https://mon.im/2018/12/tatacon-usb-ps4.html" rel="alternate" type="text/html" title="Using the Tatacon to USB converter with a PS4" />
      
      <published>2018-12-13T22:30:00+00:00</published>
      <updated>2018-12-13T22:30:00+00:00</updated>
      <id>https://mon.im/2018/12/tatacon-usb-ps4</id>
      <content type="html" xml:base="https://mon.im/2018/12/tatacon-usb-ps4.html">&lt;p&gt;&lt;strong&gt;This post has been contributed by Blackkat101, with my thanks.&lt;/strong&gt;&lt;br /&gt;
&lt;strong&gt;I do not own any of these devices but this information is invaluable to those who have them&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;As it so happens, the Tatacon to USB converter works with these commercial USB controller adapters:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://cronusmax.com/&quot;&gt;ChronusMax+&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.consoletuner.com/products/titan-one/&quot;&gt;TitanOne&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.consoletuner.com/products/titan-two/&quot;&gt;TitanTwo&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These adapters can convert standard USB gamepads and keyboards to work with PS4, Switch and the XBox.
&lt;em&gt;Please note, native Switch firmware is coming to the Tatacon to USB adapter. If you are patient, it could save you some money&lt;/em&gt;.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;ChronusMax is the original and has the most scripts out there to use (as it’s normally used for using one controller on another system, or creating macros/hotkeys/rapidfire/more).  The TitanOne is a clone of the ChronusMax in literally everything, from the looks to the software (seriously, they just copy pasted everything….).  The TitanOne hasn’t been around as long, thus there are not as many scrips in it’s library, so if you have one, you’ll be mainly making your own, or copying and (slight) converting them to work on the TitanOne from the ChronusMax library.&lt;/p&gt;

&lt;p&gt;The software for the ChronusMax+ (and transversely, the TitanOne) is suuuper easy to use.  Allowing you to code in normal programing language to a super simple idiot proof tile mode that is drag and drop and one with no programming knowledge whatsoever can use it to make their controllers do whatever they want.
The TitanTwo is the newest device, having only been out for a year or so.   For some reason it uses new scripts, so you need to convert TitanOne scrips if you want to use those.  For some reason, they removed the idiot proof tile programming ability too…&lt;/p&gt;

&lt;p&gt;NOW onto how it works with the Taiko USB mon made.&lt;/p&gt;

&lt;p&gt;For the ChronusMax+ (and TitanOne), you need to plug this device into both a computer and your console.  Thus something like a laptop (or a tablet that can run Windows/Mac standard software) next to your system and then the drum (treated as a keyboard) would then be plugged into the PC device.&lt;/p&gt;

&lt;p&gt;The TitanTwo (much to my sadness) wins out because (while being a larger device, looking like a large plastic box while the ChronusMax+/TitanOne is a small USB device) it does not need a computer to go through when doing the keyboard.   Do note that any other type of controller does not need a computer pass through for controllers.  Just that the ChronusMax+/TitanOne need it for Keyboard and Mouse while the TitanTwo does not.&lt;/p&gt;

&lt;p&gt;The Titan Two does cost more money though, so keep that in mind.  It is also a partial device that has lots of expensive upgrades to get the most out of it.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;ChronusMax+ costs normally $60 (when not near a holiday, for some reason when I checked right now, people want $100 for it on Amazon…. ouch…..)
TitanOne costs usually $55-60 (so about the same, often times it is a little cheaper than the ChronusMax+ because of it being considered a cheap knockoff.  It is the only one I don’t own personally though…)&lt;/p&gt;

&lt;p&gt;TitanTwo costs around $90 for the base unit.  If you want the Bluetooth adapter, you need to spend another $40, but at least it is an option for wireless play that the previous two don’t have.  You will also want to buy an AC adapter if buying the Bluetooth adapter or using cables that are longer than 3-4ft or you will get lag from a lack of power.  The AC adapter is a generic one (make sure you get the right specs) and will cost you around $15-25 for that.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;I tried multiple other devices with mon’s USB Taiko adapter and it did not work with things like from 8bitdo or the Magic-NS from Mayflash.
It does again however work with the previous mentioned 3 devices.  I did buy all those and personally tested them all out.
I am currently using the TitanTwo (even though I love my ChronusMax+) because I do not need to have my laptop next to the system.
It did take a bit to get the controls right and then tweaking the in game settings for timing.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;I personally set it up as so:  (This is the Switch set up, but it’s pretty much the same on the PS4)&lt;/p&gt;

&lt;p&gt;Left Kan = Z (default) = ZR (on switch pro controller)&lt;br /&gt;
Left Don = X (default) = Down D-Pad (on switch pro controller)&lt;br /&gt;
Right Don = C (default) = A Button (on switch pro controller)&lt;br /&gt;
Right Kan = V (default) = ZL (on switch pro controller)&lt;/p&gt;

&lt;p&gt;As you can see, I didn’t change the default 4 keyboard buttons that were set as it didn’t really matter what they were.
I used the ZR and ZL (those are the triggers) instead of the R and L (those are the bumpers) as the ZR and ZL allow you to scroll through the song lists and difficulty, like hitting up and down on the d-pad.&lt;br /&gt;
Right Don set to A for selecting enter (obviously needed).&lt;br /&gt;
The left Don, I really wanted set to the B button and it would still register as a Don hit, but it would register in game as hitting the right side of the drum, which felt odd….  So even though I don’t have a way to go back with the drum, I set it to the down arrow on the d-pad (any arrow would have worked), so that it registers right when playing.&lt;/p&gt;

&lt;p&gt;I have the in game controls set to register as Pro Controller setting 2.&lt;/p&gt;

&lt;p&gt;I have a Switch Pro Controller also plugged into the TitanTwo (need a USB hub if using a ChronusMax+ or TitanOne) for controller authentication.  This controller is then set next to the drum.  Turn the rumble off so the controller doesn’t vibrate on the table the drum is on.  Since you’re not holding the controller, that rumble on a hard surface is loud.  This controller can still be used like normal, so this allows for Pausing and a B button to go back (but since I generally never need to do either of those things, I then rarely have to touch that and can go through the song list, pick my difficulty and play with just the drum.&lt;/p&gt;

&lt;p&gt;I found that (so far) setting the timing of the on TV settings for the first bar to be -10 and the second bar to be -5 (the third bar left alone).  Not near my Switch so cannot check what the names of the exact settings are but that’s what they’re set at.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;So now you know that though doing all that you can use your Wii Taiko Drums on the PS4, Switch or any other system.&lt;/p&gt;</content>

      
      
      
      
      

      
        <author>
            <name>Blackkat101</name>
          
          
        </author>
      

      

      

      
        <summary type="html">This post has been contributed by Blackkat101, with my thanks. I do not own any of these devices but this information is invaluable to those who have them</summary>
      

      
      
    </entry>
  
  
  
    <entry>
      
      <title type="html">Pocket Voltex production update</title>
      
      
      <link href="https://mon.im/2018/08/pocket-voltex-update.html" rel="alternate" type="text/html" title="Pocket Voltex production update" />
      
      <published>2018-08-10T10:17:00+00:00</published>
      <updated>2018-08-10T10:17:00+00:00</updated>
      <id>https://mon.im/2018/08/pocket-voltex-update</id>
      <content type="html" xml:base="https://mon.im/2018/08/pocket-voltex-update.html">&lt;p&gt;Here’s the latest and greatest progress update - if you’re signed up to the mailing list, you should have got this in email form too!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;TL;DR: I have to fix some design aspects and produce advertising materials and we’re good to go.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Here’s a picture of a pre-production unit
&lt;a target=&quot;_blank&quot; href=&quot;https://mon.im/img/large/sdvx/new_pre_prod.jpg&quot;&gt;
&lt;img src=&quot;https://mon.im/img/medium/sdvx/new_pre_prod.jpg&quot; /&gt;
&lt;/a&gt;&lt;/p&gt;

&lt;h2 id=&quot;whats-new&quot;&gt;What’s new?&lt;/h2&gt;
&lt;ul&gt;
  &lt;li&gt;Hotswappable switches&lt;/li&gt;
  &lt;li&gt;USB C&lt;/li&gt;
  &lt;li&gt;30% bigger FX buttons&lt;/li&gt;
  &lt;li&gt;Straight FX buttons&lt;/li&gt;
  &lt;li&gt;Stabilisers for FX (no more “hit the edge, it’s mushy”)&lt;/li&gt;
  &lt;li&gt;Wider knob design (closer to real muscle memory)&lt;/li&gt;
  &lt;li&gt;Artwork is now a paper cutout - make your own waifu art!&lt;/li&gt;
  &lt;li&gt;PCB is now designed using KiCad, making the Pocket Voltex even more open!&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;whats-blocking-the-next-batch&quot;&gt;What’s blocking the next batch&lt;/h2&gt;
&lt;ul&gt;
  &lt;li&gt;The paper cutout was the wrong size&lt;/li&gt;
  &lt;li&gt;The paper cutout lets through way too much light and the LEDs are far too obvious&lt;/li&gt;
  &lt;li&gt;Still waiting on new box designs&lt;/li&gt;
  &lt;li&gt;No single supplier has enough encoders (for knobs) for a production run. I hope I don’t exhaust the global supply…&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;what-are-you-doing-to-fix-it&quot;&gt;What are you doing to fix it?&lt;/h2&gt;
&lt;ul&gt;
  &lt;li&gt;Have contacted my manufacturer to rectify the cutouts&lt;/li&gt;
  &lt;li&gt;Have ordered both white and mirrored acrylic to explore more reflective layers&lt;/li&gt;
  &lt;li&gt;Once these are confirmed it’s a moment’s decision to move to the new material&lt;/li&gt;
  &lt;li&gt;Boxes should be here in a week&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;when-can-i-give-you-money&quot;&gt;When can I give you money?&lt;/h2&gt;
&lt;ul&gt;
  &lt;li&gt;Best estimate? 3 weeks. You’ll receive an email if you signed up!&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;will-i-get-one&quot;&gt;Will I get one?&lt;/h2&gt;
&lt;p&gt;There’s currently 3x more people signed up for updates than I plan to produce boards for. It’s quite possible you might miss out. What the hell, mon!?  Produce more boards! If there are unforseen issues with this batch, I will bankrupt myself. If you happen to miss this batch, please await the next - once ~30% of orders from this batch are delivered and I confirm they work fine, I’ll order a lot more to fulfil demand.&lt;/p&gt;

&lt;p&gt;It might be a while, but I don’t have any plans to stop producing these until they stop selling. Thank you everyone for your continued patience while I work out how to mass manufacture my designs ❤.&lt;/p&gt;</content>

      
      
      
      
      

      
        <author>
            <name>mon</name>
          
          
        </author>
      

      

      

      
        <summary type="html">Here’s the latest and greatest progress update - if you’re signed up to the mailing list, you should have got this in email form too!</summary>
      

      
      
    </entry>
  
  
  
    <entry>
      
      <title type="html">Unravelling Konami’s Arcade DRM</title>
      
      
      <link href="https://mon.im/2017/12/konami-arcade-drm.html" rel="alternate" type="text/html" title="Unravelling Konami&apos;s Arcade DRM" />
      
      <published>2017-12-03T00:00:00+00:00</published>
      <updated>2017-12-03T00:00:00+00:00</updated>
      <id>https://mon.im/2017/12/konami-arcade-drm</id>
      <content type="html" xml:base="https://mon.im/2017/12/konami-arcade-drm.html">&lt;p&gt;It’s well known that Konami doesn’t have complex protection on its arcade systems. &lt;a href=&quot;https://andynumbers.wordpress.com/2015/03/09/the-end-of-an-era-programmed-world-post-op/&quot;&gt;Programmed World&lt;/a&gt; was a fan-made network replacement and update service for Konami arcade games with no support outside of Japan. Nothing of its scale and quality had been seen before, and nothing has been seen since, despite other franchises on other systems having similarly impressive userbases. It existed for so many years, pushing day-1 data updates where no other system came close. Surely that means the crypto is simple? Well, it’s certainly not a walk in the park, but I’ve managed to completely reverse the system.&lt;/p&gt;

&lt;p&gt;Background: I consider myself a proficient low-level programmer, but my reverse engineering skills leave a lot to be desired. However, I’m persistent! Despite my techniques being inefficient, it took me about 1.5 months to reverse Konami’s crypto, working in my spare time.&lt;/p&gt;

&lt;p&gt;I’ll be focusing on two things for this adventure - my process in reversing the encryption, because by sharing my methods I may help others. Secondly, high level details of Konami’s dongle-based encryption, because it’s rare to find proper information on actual, in-the-wild implementations of USB dongle based security.&lt;/p&gt;

&lt;p&gt;Oh, and before you get your hopes up - I couldn’t find any obvious flaws. As far as I can see, there is no way to decrypt data without the private keys stored in the dongle.&lt;/p&gt;

&lt;p&gt;Let’s dive in!&lt;/p&gt;

&lt;h2 id=&quot;obtaining-the-hardware&quot;&gt;Obtaining the hardware&lt;/h2&gt;
&lt;p&gt;First of all, how’d I get my system? For me, it’s not really a “system”… If you hang around Yahoo! Auctions and rhythm game communities, you’ll eventually see people selling game HDDs along with security dongles (a good start is searching YAJ for ドングル, Japanese for dongle). I waited a while and PM’d some people, and managed to score a Reflec Beat HDD+Dongle combo from 2011, and it only cost me $50!&lt;br /&gt;
&lt;img src=&quot;https://mon.im/img/drm/RB_Arcade.jpg&quot; alt=&quot;&quot; /&gt;&lt;br /&gt;
Without the arcade machine attached, it might not boot far enough to decrypt the game. For $50 I was willing to take the risk.&lt;/p&gt;

&lt;p&gt;Eventually they arrived:&lt;br /&gt;
&lt;img src=&quot;https://mon.im/img/drm/dongle.jpg&quot; alt=&quot;&quot; /&gt;&lt;br /&gt;
The dongle looked far too big for what it is, so I took a guess and pried open the outer shell:&lt;br /&gt;
&lt;img src=&quot;https://mon.im/img/drm/dongle_internals.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Much easier to fit in my hub. An amusing note - the large shell says “Made in Japan”, the actual dongle is “Made in China”.&lt;/p&gt;

&lt;p&gt;After making a HDD backup, what’s on it? Zanneth does a far better job explaining it &lt;a href=&quot;http://www.zanneth.com/projects/konami_data/notes.html&quot;&gt;here&lt;/a&gt;. Replace LDJ with KBR (Reflec Beat’s game code) and that’s essentially what’s on the drive.&lt;/p&gt;

&lt;h2 id=&quot;firing-it-up&quot;&gt;Firing it up&lt;/h2&gt;
&lt;p&gt;Next, can I boot the game through a VM? Through a surprisingly laborious process of GParted and SATA-&amp;gt;USB adapters, I got the game into a VMWare image. It boots!&lt;br /&gt;
&lt;img src=&quot;https://mon.im/img/drm/bootscreen.PNG&quot; alt=&quot;&quot; /&gt;&lt;br /&gt;
And gets to a hardware error screen:&lt;br /&gt;
&lt;img src=&quot;https://mon.im/img/drm/itboots.PNG&quot; alt=&quot;&quot; /&gt;&lt;br /&gt;
Presumably this is my lack of game IO. I couldn’t find anything remotely like this error in the unencrypted files, so I guessed it’s getting far enough to decrypt. A good fallback!&lt;/p&gt;

&lt;h3 id=&quot;running-natively&quot;&gt;Running natively&lt;/h3&gt;
&lt;p&gt;However, I loathe Windows XP Embedded, even with remote debugging tools - running a VM seems so wasteful. Time to see if I can get it running on Windows 10!&lt;/p&gt;

&lt;p&gt;By investigating the various startup .bats in the system, the magic happens inside bootstrap.exe, inside the game directory’s modules folder. It contains a few dlls, along with 9 (!) encrypted DLLs. Most of them all start with 0x00, then appear entirely random. Two have a different system - kdm.dll and kws.dll both have plaintext ‘test’ along with some structured data, but quickly turn random as well.&lt;br /&gt;
&lt;img src=&quot;https://mon.im/img/drm/kdm_hex.PNG&quot; alt=&quot;&quot; /&gt;&lt;br /&gt;
Decoding these headers is what we’re here for!&lt;/p&gt;

&lt;p&gt;Bootstrap is given some file arguments - trustcerts.p7s and trustfiles.p7s. These are &lt;a href=&quot;https://en.wikipedia.org/wiki/Abstract_Syntax_Notation_One&quot;&gt;ASN.1 encoded certificates&lt;/a&gt;, with some extra encrypted binary data - a list of trusted system files and their MD5 hashes, to prevent tampering. It also gets a configuration xml (encrypted) and a configuration to run.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;reflec&amp;gt; bootstrap.exe ..\prop\bootstrap.xml env_drm ..\prop\trustcerts.p7s ..\prop\trustfiles.p7s
M:boot: bootstrap 1.2.5  build at 2010-09-16 10:43:37+9
F:boot: Unable to initialize the ikey service.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Clearly this isn’t booting as far as Windows XP did. Time to fire up IDA, and holy debugging messages:&lt;br /&gt;
&lt;img src=&quot;https://mon.im/img/drm/bootstrap_main.PNG&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Throughout this project, my work was simplified by the thorough, plaintext debugging messages sprinkled judiciously through Konami’s code. I still had to reverse all the low-level details, but high level functionality was very easy to discern thanks to these error messages.&lt;/p&gt;

&lt;p&gt;So, bypassing the ikey error… Going into the function, it appears to be restarting services related to the dongle, presumably to get a clean slate. I didn’t have dongle drivers yet, so I made the function return success.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;M:boot: bootstrap 1.2.5  build at 2010-09-16 10:43:37+9
F:boot: Unable to initialize the pki world.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This error is thrown by a function called before the ikey initialiser, so what’s up? Seems like some sort of security check - I did just tamper with the exe, after all. On a whim, I used a combination of CreateProcess and WriteProcessMemory to patch the code in memory. I put in a pause to give me time to attach a debugger, and off we go~&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Applied 1 patch
Press enter to continue...
M:boot: bootstrap 1.2.5  build at 2010-09-16 10:43:37+9
F:boot: Unable to initialize security process.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;We got further, looking good! In the end I made 3 more patches - one to enable verbose logging (why this was left in is beyond me), and two to bypass signature checks the game loaded from trustfiles.p7s. They were easy to implement, since the game prints helpful messages when files fail validation.&lt;/p&gt;

&lt;p&gt;A small debugging hiccup came in the form of kbd.exe (I think it’s short for Konami Bootstrap Debugger) - this file attaches a debugger to bootstrap.exe, which fails if I’m already debugging it. If kbd quits, so does bootstrap. As an experiment, I made the most basic replacement for it:&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;cp&quot;&gt;#include&lt;/span&gt; &lt;span class=&quot;cpf&quot;&gt;&amp;lt;stdio.h&amp;gt;&lt;/span&gt;&lt;span class=&quot;cp&quot;&gt;
#include&lt;/span&gt; &lt;span class=&quot;cpf&quot;&gt;&amp;lt;windows.h&amp;gt;&lt;/span&gt;&lt;span class=&quot;cp&quot;&gt;
&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;printf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;I:adb proxy launched&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;while&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;Sleep&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;10000&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This actually worked :D So, where do these patches get us?&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;E:boot: Unable to load bootstrap.dll: 0x00000003
F:boot: Unable to run bootstrap.dll.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;a-brick-wall-of-missing-files&quot;&gt;A brick wall of missing files&lt;/h3&gt;
&lt;p&gt;0x03 is the Windows error code for ERROR_PATH_NOT_FOUND, so it’s time to fire up one of my favourite tools - Process Monitor. If you’ve never heard of it, it logs filesystem, registry, thread and some network activity. It captures a stackdump for every event, which is super useful in finding where files are loaded.&lt;/p&gt;

&lt;p&gt;With Procmon, I can see bootstrap loading several encrypted DLLs along with (presumably) their system DLL dependencies. However, just before exiting, bootstrap fruitlessly checks my entire PATH for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;api-ms-win-core-processenvironment-l1-1-0.dll&lt;/code&gt;. It turns out this is a part of &lt;a href=&quot;https://msdn.microsoft.com/en-us/library/windows/desktop/dn933214(v=vs.85).aspx&quot;&gt;Microsoft’s new “API Sets” feature&lt;/a&gt; introduced in Windows 8. These are “virtual” DLLs, in that they don’t really exist on the filesystem, but LoadLibrary sorts them right out. For their DRM, Konami appears to have overwritten LoadLibrary with their own version, which breaks this system. This makes sense, as calling LoadLibrary on an encrypted DLL doesn’t return an error - it pops up a MessageBox, which is very programmer unfriendly.&lt;/p&gt;

&lt;p&gt;This path filter needs patching, but it was beyond me at the time. Bootstrap already loads several encrypted DLLs, such as kbt, ltsme, and libavs-win32. We can ignore the path issues for the moment and get these DLLs decrypted. I took the CloseFile event for kbt.dll (the first DLL loaded), put a breakpoint in the function that calls it, and began my slow reversing process.&lt;/p&gt;

&lt;h2 id=&quot;first-stage-decryption&quot;&gt;First stage decryption&lt;/h2&gt;
&lt;p&gt;So what do I know? I know the file has just been loaded. I know that all DLLs start with the magic characters “MZ”. So, I fired up Cheat Engine and searched for “MZ”. There were some libraries loaded, so I got 4 results. I then began stepping through the code after the CloseFile call. I then repeated the search. When another MZ appears in the list, I know the function I just stepped over performs decryption. I can then break on this function, restart the program, and repeat the process until I get to the meat of the algorithm.&lt;/p&gt;

&lt;p&gt;This isn’t very efficient! To keep track of things, I also named functions as I drilled down. This results in quite a soup of names as I go deeper and deeper.&lt;br /&gt;
&lt;img src=&quot;https://mon.im/img/drm/poor_naming.PNG&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;However, in the end I managed to work out this “stage 1” crypto. First, I found the function creating the first block of decrypted data. Cryptographic algorithms are very obvious in disassembly, because they’re full of bitshifts, XORs and other bitwise ops.&lt;br /&gt;
&lt;img src=&quot;https://mon.im/img/drm/bitwise.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;By looking at the constant arrays referenced in this code, I found AES constants. Alright, so we’re using AES! Moving back up the functions, I found the AES key and what appeared to be an IV. I could also see the first decrypted block inside the encrypted file, and it wasn’t at offset 0. Now I knew how long the header was. I made a quick Python script using PyCrypto, and attempted to decrypt kbt.dll. And it worked… almost. The first block was decrypted, but the rest was garbage. Moving back up, the IV was being modified in a very confusing way - it was split into 4 ints, then the last one was being mangled:&lt;br /&gt;
&lt;img src=&quot;https://mon.im/img/drm/ctr.PNG&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;After 15 minutes spent trying to decipher this, I simply translated the code into Python and iterated infinitely. Turns out, this is how you perform big-endian addition without actually converting the number to little-endian. An odd way of doing it, but perhaps a compiler optimisation. It turns out they’re actually using AES_CTR, but instead of incrementing the entire counter IV, they’re only using the last 4 bytes. A little strange, but if your encrypted file is 2&lt;sup&gt;32&lt;/sup&gt; * 16 bytes long, you have other problems to worry about.&lt;/p&gt;

&lt;p&gt;The final step was to find how the encryption key was generated. For this, I repeated my “Cheat Engine binary search”(TM) method, waiting until keys popped into memory. This time I found even more RORs and ROLs along with XORs, and again some data tables - googling some constants, this was SHA1! So far, so good.&lt;/p&gt;

&lt;p&gt;It turns out the encryption key comes from hashing parts of the file header, but I was missing something critical. The internal state in the SHA1 structure wasn’t matching the standard initialisation values (0x012345678 etc) plus the buffer was half-filled with a great deal of “PADDINGXXPADDING”, which is inserted into binaries by compilers. I could check what I knew so far, by finding a pure-Python SHA1 library and meddling with its internal state. I set it to the state I found, hashed the stuff I did know… and it gave me the right key! So it’s half solved, but where did this state come from?&lt;/p&gt;

&lt;p&gt;Again I repeated the Cheat Engine technique, until I found this state in memory. I’ve probably restarted the game a few hundred times by now, it’s really not a fast way of doing things! This brought me to a very long function full of loops and conditionals making lots of calls to the hash function I encountered before. By inspecting the locations and sizes being passed in, I eventually realised the code was parsing the &lt;a href=&quot;https://en.wikibooks.org/wiki/X86_Disassembly/Windows_Executable_Files&quot;&gt;PE header&lt;/a&gt; of bootstrap.exe, and hashing individual sections! The “PADDINGXXPADDING” lives at the end of bootstrap.exe, which explains why it was left in the SHA1 buffer..&lt;/p&gt;

&lt;p&gt;This is a very clever way to prevent tampering - if bootstrap.exe is modified, it can’t decrypt anything as the keys will be wrong! By reading up about the PE header, and thanks to the lovely pefile library, I finally got myself a standalone decryptor for “stage 1”. This includes kbt, kdu, kmp, libavs-win32 and ltsme, as well as the configuration files bootstrap.xml and avs-config.xml. It also worked on the binary blobs inside trustfiles/trustcerts, but the decrypted contents are an unknown binary format - all I could glean was the names of the trustfiles checked.&lt;/p&gt;

&lt;h2 id=&quot;second-stage-decryption&quot;&gt;Second stage decryption&lt;/h2&gt;
&lt;p&gt;This left kdm and kws to reverse, and the game files of course. But before we start, time to look at our newly decrypted DLLs. Inspecting them, kbt is what the game refers to as bootstrap.dll, and actually executes the game. kdu probably stands for “Konami Dongle Utils” and communicates with the dongle drivers. kmp seems to be some sort of memory pool. libavs-win32 is a general purpose library containing a ton of filesystem, logging, memory management and utility functions.&lt;/p&gt;

&lt;p&gt;ltsme.dll is a little more interesting - it’s structured far differently from all the k__ DLLs, and contains many strings referring to different crypto algorithms, as well as source file references for throwing errors. Googling these source files reveals it’s probably the RSA BSAFE library - certified implementations of many common cryptographic algorithms. This makes sense, as every Konami game I’ve seen has a splash screen proclaiming:&lt;br /&gt;
&lt;img src=&quot;https://mon.im/img/drm/rsa.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;All of the k__ DLLs have their function exports obfuscated, of the pattern &amp;lt;dll_name&amp;gt;_&amp;lt;n&amp;gt; where n is the ordinal of the export (kdu_1, kdu_2 etc). Thanks again to Konami’s gratuitous debugging, a lot of these functions can have their names reversed anyway. libavs thankfully lacks this obfuscation, which makes it easy to see it’s a utility library:&lt;br /&gt;
&lt;img src=&quot;https://mon.im/img/drm/libavs.PNG&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;the-pesky-path-filter&quot;&gt;The pesky path filter&lt;/h3&gt;
&lt;p&gt;Before we can load the remaining DLLs, it’s time to look back at the DLL loader’s conflicts with API sets. Thanks again to Process Monitor, I know the function that’s making the search:&lt;br /&gt;
&lt;img src=&quot;https://mon.im/img/drm/searchpath.PNG&quot; alt=&quot;&quot; /&gt; 
At first, I tried ignoring the conditonals and always returning success. However, the LoadLibrary replacement is recursive, and loads dependencies from the DLL it finds. By stubbing the function, I simply get null pointer dereferences. Naive! By moving only 2 functions up the call stack, I found my saviour, which in hindsight was very obvious.&lt;br /&gt;
&lt;img src=&quot;https://mon.im/img/drm/getmodulehandle.PNG&quot; alt=&quot;&quot; /&gt;&lt;br /&gt;
To avoid infinite recursion from circular dependencies, bootstrap checks to see if the module is loaded using GetModuleHandle. If I just force Windows DLLs to load using the real LoadLibrary, I’ll avoid the API set debacle. Time to test out some new skills and write a DLL injection library! There’s tons of literature on the web to teach this, and it didn’t take me very long to implement. Before running bootstrap, I save the real LoadLibrary before it’s tampered with, and hook GetModuleHandle to include my extra checks.&lt;/p&gt;
&lt;div class=&quot;language-c highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;WINAPI&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;my_GetModuleHandleW&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;LPCWSTR&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;lpModuleName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;auto&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ret&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;orig_GetModuleHandleW&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;lpModuleName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ret&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
		&lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ret&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;printf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Loading module %ls&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;lpModuleName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;wcsstr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;lpModuleName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;L&quot;api-&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
		&lt;span class=&quot;n&quot;&gt;printf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Windows library, preloading&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
		&lt;span class=&quot;n&quot;&gt;orig_LoadLibraryW&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;lpModuleName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
	&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// return newly loaded module&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;orig_GetModuleHandleW&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;lpModuleName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Hacky, but it worked! Now where are we up to?&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;W:boot: Dongle is not connected.
I:boot: Entry loadlibrary (p7e)
I:boot: DRM module is about to be loading.
W:boot: ERROR:don_manager_slot_license
W:boot: unable to load &apos;kdm.dll&apos;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;ding-dongle&quot;&gt;Ding dong(le)&lt;/h3&gt;
&lt;p&gt;Time to use the security dongle! First up, our prime suspect for analysis - kbt.dll. It initialises a lot of our newly decrypted libraries. Importantly, it has references to dongle driver DLLs (through kdu), so we install &lt;a href=&quot;https://support.globalsign.com/customer/portal/articles/1698654-safenet-drivers&quot;&gt;those drivers&lt;/a&gt;. The dongle is a Safenet iKey 2032, and can be treated as an encryption black box containing a secret key. The dongle library thankfully follows a &lt;a href=&quot;https://www.cryptsoft.com/pkcs11doc/v220/&quot;&gt;well documented standard called PKCS11&lt;/a&gt;, which greatly simplifies login, decryption, and session management.&lt;/p&gt;

&lt;p&gt;kbt calls kdu functions in so many places, and kdu calls dongle functions in so many places, that manually stepping through and finding calls is going to be a huge pain. I’ve just learnt how to inject DLLs and hook functions, so why not put this to good use? I looked at the imports of kdu, hooked all of the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;C_&lt;/code&gt; functions that sounded interesting, and fired up bootstrap once again.&lt;/p&gt;

&lt;p&gt;Thanks to my hooks, I could now print the return address every time a dongle function is called. I can also print the arguments and return values, which is incredibly useful. Hooking &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;C_Login&lt;/code&gt; led me to the algorithm that generates the dongle PIN. By hooking &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;C_Decrypt&lt;/code&gt;, I can print out the data that’s going to the dongle - this makes it super easy to cross-reference with what’s in the encrypted files. Hooks are great!&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;DONGLE: C_FindObjectsInit(session: 0x09850004, count: 3)
DONGLE: C_FindObjectsInit(session: 0x09850004, count: 3)
M:boot: watcher enabled
I:boot: don_manager_start_lib is running.
DONGLE: C_Login(session: 0x0E150006, u_type: 1, pin: 0xBFA7911976079F6B757A32D69BAA4671, pin_len: 16)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;I know I could have used breakpoints with IDC/IDAPython to print information, but I really wanted to learn DLL injection and hooking. kbt.dll also switches from bootstrap.exe’s logging to functions provided by libavs-win32.dll. There is a debug flag to enable here too, so it’s easier to just inject.&lt;/p&gt;

&lt;p&gt;When attempting dongle login, if you enter the incorrect password 10 times, the dongle will permanently lock you out. Luckily I didn’t find this by accident: the dongle drivers let you know how many attempts remain. One advantage of dynamic analysis meant that I could test my PIN generation algorithm, fail a few times, and run bootstrap.exe again to let the game perform a correct login. This is a useful safety net when failure results in a brick!&lt;/p&gt;

&lt;p&gt;The dongle PIN turned out to be reasonably simple - a salt appended to some identifying info from the dongle, hashed with SHA1. To avoid errant null terminators from the hash, each successive \0 becomes \1, \2 etc etc… However, in newer versions of the dongle drivers these PINs aren’t always valid. The spec says they have to be UTF-8 encoded, and a SHA1 hash sure doesn’t guarantee this. I changed my dongle’s PIN to “helloworld” to perform some tests, but attempting to change it back resulted in an invalid length error. I had to boot up the old XP VM to change the PIN back, as it doesn’t care about bad characters.&lt;/p&gt;

&lt;p&gt;Ok, time to inspect kdm. Why kdm and not kws? Well…
&lt;img src=&quot;https://mon.im/img/drm/drm_module_loading.PNG&quot; alt=&quot;&quot; /&gt;&lt;br /&gt;
&lt;img src=&quot;https://mon.im/img/drm/great_obfuscation.PNG&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Great function name obfuscation guys, really effective.&lt;/p&gt;

&lt;p&gt;The hex dump of kdm.dll reminded me of the trustcerts file. Could it be ASN.1?
&lt;img src=&quot;https://mon.im/img/drm/kdm_asn.PNG&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Brilliant! By hooking more &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;C_*&lt;/code&gt; functions related to encryption, and cross referencing data with the ASN.1 dump, “stage 2” became 100% obvious. I never had to look at disassembly for this stage, because the dongle calls told the entire story.
&lt;img src=&quot;https://mon.im/img/drm/stage2_decrypt.PNG&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Both key and IV were extracted directly from the ASN.1 blob. The key was decrypted by the dongle and its private key (using RSA PKCS), then the pair were used with the dongle’s AES mechanism to decrypt the DLL. Oddly, the dongle’s AES is identical to standard AES, and I was able to perform the decryption on the PC side. Limited by USB 2.0, the dongle ends up slower, so I wonder why Konami chose to perform this decryption on the dongle. I guessed they will move to a more performant encryption for the real game, since those files are significantly larger. Read on to see if I was right :)&lt;/p&gt;

&lt;h2 id=&quot;final-stage-decryption&quot;&gt;Final stage decryption&lt;/h2&gt;
&lt;p&gt;With kdm and kws decrypted, it’s time for the final frontier! Decryption of the actual game, not just the bootstrapping DLLs.&lt;/p&gt;

&lt;p&gt;Konami’s extensive debug string usage was once again a huge help here - before I even started reversing specific functions I knew exactly what they should do. Wouldn’t every reverse engineer wish for something so nice?
&lt;img src=&quot;https://mon.im/img/drm/lovely.PNG&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;path-obfuscation&quot;&gt;Path obfuscation&lt;/h3&gt;
&lt;p&gt;The hardest part (for me) didn’t turn out to be the decryption, but the path obfuscation. The actual game files aren’t as conveniently named as the dlls in the modules folder.&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;KBR/contents$ tree
.
├── 0
│   ├── 1
│   │   ├── 1
│   │   │   ├── 5a7ddaa7bcaca08f81911ad290be72f9e14c1
│   │   │   └── 77c12c396141778ba39762dcda195807dc76b
│   │   └── f
│   │       └── be3ff2c203d690006af3a243f5e78f35d965a
│   ├── 2
│   │   ├── 1
│   │   │   └── d44f8e863315302ddb81868fa4338f16dcc0d
│   │   ├── 5
│   │   │   └── 07c708612ae712921e83cb2db48dcf0b709b0
│   │   └── 6
│   │       └── 814976b86d6913c97d615691cdf2db41545dd
│   ├── 4
│   │   ├── 5
│   │   │   └── 26445d335bcb0da2c2d72accdd3b119a46a30
│   │   └── b
│   │       └── db5f902601454b4c4863bab941647f994af7d
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This continues for all 600 files in the game. The first file accessed (thanks again to Process Monitor) is eventually traced back to its “real” name: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;keyfile.dat&lt;/code&gt;. Sounds exciting! Through the slow Cheat Engine process, I found the function generating these paths:
&lt;img src=&quot;https://mon.im/img/drm/cry_mac.PNG&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;I googled this and discovered it was a &lt;a href=&quot;https://en.wikipedia.org/wiki/Message_authentication_code&quot;&gt;MAC&lt;/a&gt; algorithm. The input was the real filepath, the key/hash/code was more dongle data and a salt. I then wasted many days trying to reverse exactly what this function was doing. I didn’t know anything about MAC, so I couldn’t reliably differentiate RSA’s boilerplate from the real deal. The entire library is dynamic functions and vtables, so static analysis is useless for me.&lt;/p&gt;

&lt;p&gt;After much crying and gnashing of teeth I had a good night’s rest and looked back at the main function again. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cry_mac.c&lt;/code&gt;. One &lt;em&gt;proper&lt;/em&gt; search later, some more Python poking, and I realise that mac is short for &lt;a href=&quot;https://en.wikipedia.org/wiki/Hash-based_message_authentication_code&quot;&gt;_H_MAC&lt;/a&gt;. Boom - instant success. Lesson: You can step through code all you want, but do try and understand the basics.&lt;/p&gt;

&lt;h3 id=&quot;keys-to-the-kingdom&quot;&gt;Keys to the kingdom&lt;/h3&gt;
&lt;p&gt;With path obfuscation solved, the very final step is probably the simplest work in this entire saga. The decryption functions are well commented with error messages, easy to follow, and consistent. The keyring was loaded into memory, so offsets into it are simple to understand. The reversing of this algorithm was quite basic compared to the rest, so I won’t go into detail. Instead, for (in my opinion) the most interesting information of all. How are the files encrypted?&lt;/p&gt;

&lt;p&gt;The biggest surprise - to decrypt all the files &lt;em&gt;in the entire game&lt;/em&gt;, only one call is made to the dongle. I guess at this point, decrypting files (or even multiple file keys) with the dongle would just slow the game down.&lt;br /&gt;
So, here’s the process:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;The keyfile contains the keys for the game. Every file has a different key.&lt;/li&gt;
  &lt;li&gt;The “master key” is decrypted using the dongle.
    &lt;ul&gt;
      &lt;li&gt;This master key changes with every single game update (I had some leftover update files on my HDD)&lt;/li&gt;
      &lt;li&gt;This is why you always need a dongle!&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;When a file is loaded, a key for that file is decrypted using the master key&lt;/li&gt;
  &lt;li&gt;&lt;em&gt;That&lt;/em&gt; key is then used to decrypt a &lt;em&gt;second key&lt;/em&gt;&lt;/li&gt;
  &lt;li&gt;&lt;em&gt;&lt;strong&gt;THAT&lt;/strong&gt;&lt;/em&gt; key is then used to decrypt the real file.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Phew! Crypto layers on crypto layers on crypto layers! The final question - how does the game know which file belongs to which key? The very first file decrypted, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;file.xml&lt;/code&gt;, contains a list of every file in the game, along with their key offsets:&lt;/p&gt;
&lt;div class=&quot;language-xml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;cp&quot;&gt;&amp;lt;?xml version=&apos;1.0&apos; encoding=&apos;UTF-8&apos;?&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;fileinfo&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;contents_code=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;KBR-001&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;dir&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;data&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;dir&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;graphics&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
      &lt;span class=&quot;nt&quot;&gt;&amp;lt;dir&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;cardentry&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;&amp;lt;file&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;card.bin&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
          &lt;span class=&quot;nt&quot;&gt;&amp;lt;key_idx&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;__type=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;u32&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;1&lt;span class=&quot;nt&quot;&gt;&amp;lt;/key_idx&amp;gt;&lt;/span&gt;
          &lt;span class=&quot;nt&quot;&gt;&amp;lt;orig_size&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;__type=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;u32&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;6982428&lt;span class=&quot;nt&quot;&gt;&amp;lt;/orig_size&amp;gt;&lt;/span&gt;
          &lt;span class=&quot;nt&quot;&gt;&amp;lt;dst_path&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;__type=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;bin&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;__size=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;20&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;d2b50a2ae7d3392205ead278d70506d85ae9bee0&lt;span class=&quot;nt&quot;&gt;&amp;lt;/dst_path&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;&amp;lt;/file&amp;gt;&lt;/span&gt;
      &lt;span class=&quot;nt&quot;&gt;&amp;lt;/dir&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Combining everything into a (now quite large) Python program, I can decrypt my game HDD for the 7 year old ReflecBeat.&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&amp;gt; python .\decrypt_all.py &apos;D:\reflec\game\KBR\contents&apos;
Successful dongle login
Keys loaded
File list loaded
data/graphics/cardentry/card.bin
data/graphics/cardentry/card_2.bin
data/graphics/caution/caution.bin
data/graphics/common/cmn.bin
data/graphics/common/loca_info.bin
data/graphics/common/paseli.bin
data/graphics/font/f0000.bin
data/graphics/gameover/gameover.bin
data/graphics/gameover/info.bin
...
...
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;whats-next&quot;&gt;What’s next?&lt;/h2&gt;
&lt;p&gt;With what I’ve learned, I’m confident in purchasing a real arcade cabinet. No arcades in my city have these games, and frequent trips to Japan become expensive ;). New games can’t run offline by default, so maybe I can write my own personal network server and buy a Sound Voltex cab to fawn over. Of course, this would be useless if Konami has changed their system in the last 7 years (very likely!). If I buy a cab and it’s got a new system, I guess you’ll see another blog post :)&lt;/p&gt;

&lt;p&gt;I could also start writing emulation tools for ReflecBeat’s IO system and bypass the hardware error to get it playable on a touchscreen laptop. At this point, I don’t have the time. Perhaps a later date!&lt;/p&gt;

&lt;p&gt;I hope you’ve enjoyed reading this as much as I enjoyed writing it! It’s been a fun ride.&lt;/p&gt;</content>

      
      
      
      
      

      
        <author>
            <name>mon</name>
          
          
        </author>
      

      

      

      
        <summary type="html">It’s well known that Konami doesn’t have complex protection on its arcade systems. Programmed World was a fan-made network replacement and update service for Konami arcade games with no support outside of Japan. Nothing of its scale and quality had been seen before, and nothing has been seen since, despite other franchises on other systems having similarly impressive userbases. It existed for so many years, pushing day-1 data updates where no other system came close. Surely that means the crypto is simple? Well, it’s certainly not a walk in the park, but I’ve managed to completely reverse the system.</summary>
      

      
      
    </entry>
  
  
  
    <entry>
      
      <title type="html">$70 SDVX Controller</title>
      
      
      <link href="https://mon.im/2016/07/70-sdvx-controller.html" rel="alternate" type="text/html" title="$70 SDVX Controller" />
      
      <published>2016-07-22T10:17:00+00:00</published>
      <updated>2016-07-22T10:17:00+00:00</updated>
      <id>https://mon.im/2016/07/70-sdvx-controller</id>
      <content type="html" xml:base="https://mon.im/2016/07/70-sdvx-controller.html">&lt;p&gt;In my neverending quest to play more rhythm games, I discovered SDVX/kshootmania. Unfortunately there really is no good way to play these without a controller. An expensive investment, you’re looking at over $200AUD shipped. Not something I want to spend for a game I may not even like!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;This is a work in progress. If you find this on Google and it helps you, leave a comment to inspire me to polish it and post pictures when I complete my setup.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Working off &lt;a href=&quot;http://sdvxii.pancakeapps.com/LEONARDO&quot;&gt;this guide&lt;/a&gt;, I’ve made several changes…&lt;/p&gt;

&lt;p&gt;All prices in AUD, so if you work in USD, prepare for a happy discount :)&lt;/p&gt;

&lt;h2 id=&quot;parts-list&quot;&gt;Parts list&lt;/h2&gt;
&lt;ul&gt;
  &lt;li&gt;Leonardo Pro Micro, $6. Search on eBay for a seller. Should look like this:&lt;br /&gt;
&lt;img src=&quot;https://mon.im/img/sdvx_ghetto/leo.jpg&quot; alt=&quot;&quot; /&gt;&lt;/li&gt;
  &lt;li&gt;Sheet of MDF. Cost me $6 at Bunnings. I wouldn’t go under 6.5mm thick otherwise it flexes too much. Also acceptable is plywood and possibly acrylic.&lt;/li&gt;
  &lt;li&gt;The switches themselves. “9x Beatmania IIDX Video Game DIY Parts LED Illuminated Rectangular Push Button”. $37 from eBay.&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://www.ebay.com.au/itm/1PCS-30mmDIAx22-Aluminum-STEREO-VOLUME-CONTROL-KNOB-/380905947186&quot;&gt;Aluminium knobs&lt;/a&gt;: $17.50. These are completely overkill but they feel wonderful in my hands. You can probably find much cheaper ones on aliexpress.&lt;/li&gt;
  &lt;li&gt;Encoders. The ones listed in the pancake guide are wrong! The don’t have threads so can’t easily be attached to the board. &lt;a href=&quot;https://au.rs-online.com/web/p/mechanical-rotary-encoders/7899517/&quot;&gt;I got these instead&lt;/a&gt;. $5.20. After using them for a while, these really aren’t amazing encoders. The next step up are 600ppr ones, which are somewhat insane. See the “upgrades” section.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Total: $70-ish (AUD)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I had these parts lying around, but you may need to buy them:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Female header pins (2.54mm)&lt;/li&gt;
  &lt;li&gt;Male to female jumper cables (listed as “breadboard jumpers” on ebay usually)&lt;/li&gt;
  &lt;li&gt;150 ohm resistors&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;make-a-box&quot;&gt;Make a box&lt;/h2&gt;
&lt;p&gt;The arcade templates on Pancake were far too big for my liking - I want this as compact as possible whilst maintaining decent arcade styling. I shortened everything.&lt;br /&gt;
&lt;img src=&quot;https://mon.im/img/sdvx_ghetto/ghetto_cutouts.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;The VOL squares are not centered, you will have to mark these with a pencil when you make the cut.&lt;/p&gt;

&lt;p&gt;I printed this out on A4, glued the parts together, then used it for my hole drilling.&lt;/p&gt;

&lt;p&gt;Here also is the &lt;a href=&quot;https://mon.im/img/sdvx_ghetto/SDVXIIDXmode.svg&quot;&gt;svg file&lt;/a&gt; and &lt;a href=&quot;https://mon.im/img/sdvx_ghetto/SDVXIIDXmode.png&quot;&gt;high res png&lt;/a&gt;. I also have &lt;a href=&quot;https://mon.im/img/sdvx_ghetto/SDVXIIDXmode.pdf&quot;&gt;a pdf&lt;/a&gt; - if you print with Acrobat reader there’s options to tile it onto 2 sheets of A4.&lt;/p&gt;

&lt;h2 id=&quot;12v-to-5v-led-conversion&quot;&gt;12v to 5v LED conversion&lt;/h2&gt;
&lt;p&gt;If you can find switches with 5V LEDs already inside, buy them, this will save you some effort. Take out all the LEDs from their holders, desolder the existing resistors, and solder in your 150 ohm resistors. This means we can drive the LEDs directly from the MCU with no extra hardware! Very convenient.&lt;/p&gt;

&lt;h2 id=&quot;firmware&quot;&gt;Firmware&lt;/h2&gt;
&lt;p&gt;Sorry, Pancake man, but your code was bad. I’ve reworked it to run better and be more configurable. &lt;a href=&quot;https://gist.github.com/mon/45420cf5caaa82e5a82333419354c501&quot;&gt;Get it here&lt;/a&gt;. For best encoder performance, make sure the encoder pins are 0, 1, 2, 3. Any order is fine, just as long as you use those pins. All other pins you’re free to use whatever you want!&lt;/p&gt;

&lt;h2 id=&quot;wiring&quot;&gt;Wiring&lt;/h2&gt;
&lt;p&gt;Common ground across everything, then switch + LED connectors for each button, and A/B for each encoder.&lt;/p&gt;

&lt;h2 id=&quot;future-upgrades&quot;&gt;Future upgrades&lt;/h2&gt;
&lt;p&gt;The switches are insanely heavy. I’ve bought some &lt;a href=&quot;http://global.rakuten.com/en/store/sanwadenshi/item/ilumb_223/&quot;&gt;50g omrons&lt;/a&gt;. Expensive, however! Cost me $37 shipped to Australia.
You could probably get big square switches.&lt;/p&gt;

&lt;p&gt;The encoders are kinda crap. I found some arcade quality 600PPR ones, 2 cost me $27. &lt;a href=&quot;http://www.ebay.com.au/itm/600P/281730272439&quot;&gt;Here’s a link&lt;/a&gt;, but I highly recommend just searching ebay for “encoder 600 6mm”. I saved $10 by searching and finding the cheapest for my location.&lt;/p&gt;</content>

      
      
      
      
      

      
        <author>
            <name>mon</name>
          
          
        </author>
      

      

      

      
        <summary type="html">In my neverending quest to play more rhythm games, I discovered SDVX/kshootmania. Unfortunately there really is no good way to play these without a controller. An expensive investment, you’re looking at over $200AUD shipped. Not something I want to spend for a game I may not even like!</summary>
      

      
      
    </entry>
  
  
  
    <entry>
      
      <title type="html">TEVO Tarantula BLTouch Setup</title>
      
      
      <link href="https://mon.im/2016/06/tevo-tarantula-bltouch-setup.html" rel="alternate" type="text/html" title="TEVO Tarantula BLTouch Setup" />
      
      <published>2016-06-19T05:52:00+00:00</published>
      <updated>2016-06-19T05:52:00+00:00</updated>
      <id>https://mon.im/2016/06/tevo-tarantula-bltouch-setup</id>
      <content type="html" xml:base="https://mon.im/2016/06/tevo-tarantula-bltouch-setup.html">&lt;p&gt;The logical next step to improving your 3D printer experience is an automatically levelled bed. I won’t go into specifics, but the BLTouch is awesome - accurate, simple, and works on any surface. No fuss!&lt;/p&gt;

&lt;p&gt;This is a setup guide specifically for the Tevo Tarantula 3D printer. It uses an MKS Base board and runs best with Marlin firmware. Let’s get started!&lt;/p&gt;

&lt;h2 id=&quot;what-youll-need&quot;&gt;What you’ll need&lt;/h2&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://plus.google.com/113792662927481823969/posts/cobJgVYWgD8&quot;&gt;The BLTouch itself&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://www.aliexpress.com/item/Free-shipping-300mm-10pcs-lot-servo-extension-Lead-wire-cable-for-Futaba-JR-male-and-female/1541423824.html&quot;&gt;Servo extension leads&lt;/a&gt; (select 60cm male to female)&lt;/li&gt;
  &lt;li&gt;A way to mount it
    &lt;ul&gt;
      &lt;li&gt;I use &lt;a href=&quot;https://arcaded.discussion.community/post/lpa-fanduct-version-4-8139028?pid=1292518715&quot;&gt;the excellent LPA fan duct&lt;/a&gt; - there’s versions for stock and E3D hotends.&lt;/li&gt;
      &lt;li&gt;If you have the control board mounted on the printer, I advise mirroring the print so it doesn’t collide with the PCB&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Marlin firmware
    &lt;ul&gt;
      &lt;li&gt;Go to the “Files” section on &lt;a href=&quot;https://www.facebook.com/groups/TEVO.3dprinter.owners/&quot;&gt;the Facebook group&lt;/a&gt;, scroll down until you find a Marlin zip. I use this version:&lt;/li&gt;
      &lt;li&gt;&lt;img src=&quot;https://mon.im/img/tevo/marlin.png&quot; alt=&quot;&quot; /&gt;&lt;/li&gt;
      &lt;li&gt;If you are using &lt;strong&gt;RC6&lt;/strong&gt;, this guide supports that too!&lt;/li&gt;
      &lt;li&gt;Copy the Configuration.h from &lt;strong&gt;ABL_YES&lt;/strong&gt; into the Marlin folder&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;wiring&quot;&gt;Wiring&lt;/h2&gt;
&lt;p&gt;&lt;span style=&quot;color: red;&quot;&gt;&lt;strong&gt;IMPORTANT IMPORTANT IMPORTANT&lt;/strong&gt;&lt;/span&gt;&lt;br /&gt;
Some TEVO Tarantula boards (MKS Base) have &lt;strong&gt;SWAPPED POWER AND GROUND PINS. YOU MUST SWAP THE BLTOUCH CONNECTOR OR YOU WILL FRY YOUR BLTOUCH&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The BLTouch connector has 2 connectors:&lt;br /&gt;
The main connector is &lt;span style=&quot;color: orange;&quot;&gt;Signal&lt;/span&gt;, &lt;span style=&quot;color: red;&quot;&gt;Power&lt;/span&gt;, &lt;span style=&quot;color: brown;&quot;&gt;Ground&lt;/span&gt; (orange, red, brown)&lt;br /&gt;
Using a pair of tweezers or a toothpick, carefully bend the plastic keeping the Power and Ground pins in place, pull them out, and swap them.&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;new order&lt;/strong&gt; should be &lt;span style=&quot;color: orange;&quot;&gt;Signal&lt;/span&gt;, &lt;span style=&quot;color: brown;&quot;&gt;Ground&lt;/span&gt;, &lt;span style=&quot;color: red;&quot;&gt;Power&lt;/span&gt; (orange, brown, red)&lt;br /&gt;
Note how they match up to the MKS Board:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://mon.im/img/tevo/pins.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;One this is done, attach your 60cm servo extension leads to both cables of the BLTouch. Be sure to line up signal with signal. For the 2 pin plug, just plug it into signal and “power” (which we know is ground).&lt;/p&gt;

&lt;p&gt;Plug the &lt;strong&gt;3 wire cable&lt;/strong&gt; into the bare pins on the right - you want the one marked &lt;strong&gt;D11&lt;/strong&gt;. The signal wire will be right next to the label, and brown (actually power since we swapped) on the back.&lt;/p&gt;

&lt;p&gt;Plug the &lt;strong&gt;2 wire cable&lt;/strong&gt; into the &lt;strong&gt;Z-&lt;/strong&gt; plug. The fit won’t be 100% secure but this is fine. Ensure that if you trace the wires, the pin marked “&lt;strong&gt;-&lt;/strong&gt;” goes to the black wire and the pin marked &lt;strong&gt;S&lt;/strong&gt; goes to the white wire.&lt;/p&gt;

&lt;h2 id=&quot;sanity-check&quot;&gt;Sanity check&lt;/h2&gt;
&lt;p&gt;Make sure the BLTouch, when retracted, is higher than your hotend. You don’t want it crashing before the hotend does!&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://mon.im/img/tevo/alignment.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;If this is the case, loosen the grub screws holding the heat break into the heatsink. Drop it a mm or 2 and the BLTouch should now clear.&lt;/p&gt;

&lt;h2 id=&quot;firmware&quot;&gt;Firmware&lt;/h2&gt;
&lt;p&gt;Marlin is best. No question.
You’ll want to edit Configuration.h to setup the BLTouch.&lt;/p&gt;

&lt;h3 id=&quot;find-and-modify-these-variables&quot;&gt;Find and modify these variables:&lt;/h3&gt;
&lt;div class=&quot;language-c highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;bool&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Z_MIN_ENDSTOP_INVERTING&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Comment out this line by adding “//” to the start:&lt;/p&gt;
&lt;div class=&quot;language-c highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;//#define FIX_MOUNTED_PROBE&lt;/span&gt;

&lt;span class=&quot;cp&quot;&gt;#define NUM_SERVOS 1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;if-you-are-on-rc6&quot;&gt;If you are on RC6:&lt;/h3&gt;
&lt;div class=&quot;language-c highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;
&lt;span class=&quot;cp&quot;&gt;#define Z_ENDSTOP_SERVO_NR 0
#define SERVO_ENDSTOP_ANGLES {{10,90}}
&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;if-you-are-on-rc7&quot;&gt;If you are on RC7:&lt;/h3&gt;
&lt;div class=&quot;language-c highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;cp&quot;&gt;#define BLTOUCH
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;You will need to set your probe offsets. Luckily, the &lt;a href=&quot;https://arcaded.discussion.community/post/lpa-fanduct-version-4-8139028?pid=1292518715&quot;&gt;LPA fan duct documentation&lt;/a&gt; has a handy table for us. Here are mine:&lt;/p&gt;
&lt;div class=&quot;language-c highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;cp&quot;&gt;#define X_PROBE_OFFSET_FROM_EXTRUDER 38
#define Y_PROBE_OFFSET_FROM_EXTRUDER -4
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Don’t worry about Z offset yet, we’ll get that perfect later.&lt;/p&gt;

&lt;p&gt;You may want to slightly increase the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Z_RAISE&lt;/code&gt; (&lt;strong&gt;RC6&lt;/strong&gt;) settings. I increased them by 1 or 2mm each. If you are on &lt;strong&gt;RC7&lt;/strong&gt;, these are called &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Z_PROBE_DEPLOY_HEIGHT&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Z_PROBE_TRAVEL_HEIGHT&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;RC6 only&lt;/strong&gt;: For some reason, Marlin doesn’t like pulling the probe pin up after the last probe. This is easily fixed:&lt;/p&gt;
&lt;div class=&quot;language-c highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;cp&quot;&gt;#define Z_PROBE_END_SCRIPT &quot;M280 P0 S90&quot;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Personally, I don’t like EEPROM, so I disable it. This is entirely up to you.&lt;/p&gt;
&lt;div class=&quot;language-c highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;//#define EEPROM_SETTINGS&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;If the code won’t compile and warns you about unreachable probe points, you will need to modify them. For example, I had to change &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;LEFT_PROBE_BED_POSITION&lt;/code&gt; from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;30&lt;/code&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;38&lt;/code&gt;.&lt;/p&gt;

&lt;h2 id=&quot;calibration&quot;&gt;Calibration&lt;/h2&gt;
&lt;p&gt;&lt;span style=&quot;color: red;&quot;&gt;&lt;strong&gt;BRING YOUR Z VERY HIGH FOR TESTING&lt;/strong&gt;&lt;/span&gt;&lt;br /&gt;
You &lt;strong&gt;must&lt;/strong&gt; give yourself time to abort a test if you set things up incorrectly.&lt;/p&gt;

&lt;p&gt;Connect your printer to your computer and start executing some GCode:&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;G28 X0 Y0; Setup X and Y
G28 Z0
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This will begin endstop testing with your BLTouch. Using your hand, &lt;strong&gt;manually stop it&lt;/strong&gt; far above the bed to ensure it works. If it does, then you can proceed:&lt;/p&gt;

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

&lt;p&gt;Keep a very close eye on the first autolevel - if your offsets are wrong, there is a chance you will run off the bed into air, and crash into the bed.&lt;/p&gt;

&lt;p&gt;If this succeeds, great! Now time to calibrate the Z offset.
Using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;G1 Z{distance}&lt;/code&gt; and a piece of paper, move down until you get a decent amount of friction on the paper. Same as manual levelling!&lt;/p&gt;

&lt;p&gt;For example, I ran &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;G1 Z0&lt;/code&gt;. This far far too high, so I went &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;G1 Z-1&lt;/code&gt;. Getting closer, I started going down in increments of 0.1, so &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;G1 Z-1.1&lt;/code&gt; then &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;G1 Z-1.2&lt;/code&gt; etc etc until I found the perfect number.&lt;/p&gt;

&lt;p&gt;Once you have this number, enter it as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Z_PROBE_OFFSET_FROM_EXTRUDER&lt;/code&gt; in the Configuration.h&lt;/p&gt;

&lt;p&gt;You’re almost done!&lt;/p&gt;

&lt;h2 id=&quot;gcode&quot;&gt;GCode&lt;/h2&gt;
&lt;p&gt;Finally, you’ll need to modify your GCode to perform an Autolevel sequence (G29) before each print.&lt;/p&gt;

&lt;p&gt;Simply find where you have &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;G28 Z0&lt;/code&gt; and put &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;G29&lt;/code&gt; after it.&lt;/p&gt;</content>

      
      
      
      
      

      
        <author>
            <name>mon</name>
          
          
        </author>
      

      

      

      
        <summary type="html">The logical next step to improving your 3D printer experience is an automatically levelled bed. I won’t go into specifics, but the BLTouch is awesome - accurate, simple, and works on any surface. No fuss!</summary>
      

      
      
    </entry>
  
  
  
    <entry>
      
      <title type="html">Evoluent VerticalMouse C Review, teardown, comparison</title>
      
      
      <link href="https://mon.im/2016/03/evoluent-verticalmouse-c-review.html" rel="alternate" type="text/html" title="Evoluent VerticalMouse C Review, teardown, comparison" />
      
      <published>2016-03-17T11:55:00+00:00</published>
      <updated>2016-03-17T11:55:00+00:00</updated>
      <id>https://mon.im/2016/03/evoluent-verticalmouse-c-review</id>
      <content type="html" xml:base="https://mon.im/2016/03/evoluent-verticalmouse-c-review.html">&lt;p&gt;Computer mice haven’t really changed since they were invented. It’s still a block you move about with your hand in a flat position. However, this twisting of the forearm is unnatural, and frequent mouse users will find they develop wrist pain.&lt;br /&gt;
The solution is a vertically oriented mouse. It lets the hand rest in a natural state and in my experience is super comfortable. These are readily available for under $30 on eBay, Amazon and Aliexpress, but are often &lt;a href=&quot;http://www.amazon.com/dp/B00LAZ2BN8&quot;&gt;childsize&lt;/a&gt; or simply &lt;a href=&quot;http://www.amazon.com/dp/B00TJ4ZD28&quot;&gt;not comfortable enough&lt;/a&gt;. After trying about 4 mice I’ve realised who the reigning champion is: &lt;a href=&quot;https://evoluent.com/&quot;&gt;Evoluent&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I’ve been a happy owner of their &lt;a href=&quot;https://evoluent.com/products/vm4r/&quot;&gt;VerticalMouse 4&lt;/a&gt; (VM4) for almost a year now. It’s comfortable but a little awkward, and &lt;a href=&quot;/2015/09/evoluent-vertical-mouse-4-sensor.html&quot;&gt;required some modding to really make it good&lt;/a&gt;. I’ve been using it interchangeably with my &lt;a href=&quot;http://www.razerzone.com/gaming-mice/razer-deathadder-chroma&quot;&gt;Razer DeathAdder&lt;/a&gt;, but definitely use the DeathAdder more.&lt;/p&gt;

&lt;p&gt;Released in February 2016, the Evoluent VerticalMouse C (VMC) is the company’s next iteration of their flagship product. It comes in wired and wireless versions, and is right handed only for now. If it’s anything like the VM4, a left handed version will follow.&lt;/p&gt;

&lt;p&gt;I purchased the VMC Right Wired for $150 AUD shipped &lt;a href=&quot;http://www.bhphotovideo.com/c/product/1219798-REG/evoluent_vmcr_verticalmouse_c_right.html&quot;&gt;from B&amp;amp;H&lt;/a&gt; to Australia.&lt;/p&gt;

&lt;p&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://mon.im/img/large/vmc/1.jpg&quot;&gt;
&lt;img src=&quot;https://mon.im/img/thumbs/vmc/1.jpg&quot; /&gt;
&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;But how does it stack up against the previous VM4? Is it good enough for gaming? Read on to find out…&lt;/p&gt;

&lt;h2 id=&quot;look&quot;&gt;Look&lt;/h2&gt;
&lt;p&gt;Evoluent has really leapt into this decade with the design of the VMC. The curves are beautiful and complement the ergonomic shape. It practically looks like a spacecraft now, and that’s a good thing!&lt;/p&gt;

&lt;p&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://mon.im/img/large/vmc/2.jpg&quot;&gt;
&lt;img src=&quot;https://mon.im/img/thumbs/vmc/2.jpg&quot; /&gt;
&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Compared to the VM4, it’s a huge upgrade.&lt;/p&gt;

&lt;p&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://mon.im/img/large/vmc/3.jpg&quot;&gt;
&lt;img src=&quot;https://mon.im/img/thumbs/vmc/3.jpg&quot; /&gt;
&lt;/a&gt;  &lt;br /&gt;
&lt;a target=&quot;_blank&quot; href=&quot;https://mon.im/img/large/vmc/4.jpg&quot;&gt;
&lt;img src=&quot;https://mon.im/img/thumbs/vmc/4.jpg&quot; /&gt;
&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Compared to my DeathAdder, it’s quite a difference.&lt;/p&gt;

&lt;p&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://mon.im/img/large/vmc/5.jpg&quot;&gt;
&lt;img src=&quot;https://mon.im/img/thumbs/vmc/5.jpg&quot; /&gt;
&lt;/a&gt;  &lt;br /&gt;
&lt;a target=&quot;_blank&quot; href=&quot;https://mon.im/img/large/vmc/6.jpg&quot;&gt;
&lt;img src=&quot;https://mon.im/img/thumbs/vmc/6.jpg&quot; /&gt;
&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The bottom of the mouse is similarly simple, with only the sensor hole, signature, and feet.&lt;/p&gt;

&lt;p&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://mon.im/img/large/vmc/7.jpg&quot;&gt;
&lt;img src=&quot;https://mon.im/img/thumbs/vmc/7.jpg&quot; /&gt;
&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can also find promotional shots of the mouse on &lt;a href=&quot;https://evoluent.com/products/vmcr/&quot;&gt;Evoluent’s page&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;feel&quot;&gt;Feel&lt;/h2&gt;
&lt;p&gt;The VMC has again come into the modern age by replacing the silver plastic with a lovely matte finish. It’s that slightly rougher plastic that you see on mice like the DeathAdder, and it’s very sweat resistant. My VM4 is covered in dried sweat (yuck!) but I don’t see this being a problem with the VMC. The thumb area is the same material, a welcome change from the gloss finish on the previous versions. The silver gloss is now reserved for the side of the mouse you don’t touch, and it looks great.&lt;/p&gt;

&lt;p&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://mon.im/img/large/vmc/8.jpg&quot;&gt;
&lt;img src=&quot;https://mon.im/img/thumbs/vmc/8.jpg&quot; /&gt;
&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The cable isn’t braided, but it’s not standard either - it has a rubbery finish, almost feels like RC silicone wire. Its very pliable but it also gets in the way as it catches on my mouse pad. I will probably replace this with a donor braided cable.&lt;/p&gt;

&lt;p&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://mon.im/img/large/vmc/9.jpg&quot;&gt;
&lt;img src=&quot;https://mon.im/img/thumbs/vmc/9.jpg&quot; /&gt;
&lt;/a&gt;&lt;/p&gt;

&lt;h2 id=&quot;ergonomics&quot;&gt;Ergonomics&lt;/h2&gt;
&lt;p&gt;If you’ve never used a vertical mouse before, the VMC would make an excellent introduction. I gave myself fairly serious hand pain from playing far too much Osu and TF2. I eventually realised that sore hands every breakfast was not at all normal.&lt;/p&gt;

&lt;p&gt;I didn’t think it was possible, but Evoluent has bested the VM4 in almost every aspect. The pinky rest lip is bigger than before and a joy to rest my hand on. The entire mouse feels more fluid, and it’s much more natural to hold.
However, the grip is slightly smaller than the VM4. I have large hands, and if I fully grasp the mouse my fingers now extend past the edge of the face. It’s not uncomfortably small - the mouse is still much nicer than the VM4 - but it could be just a little bit bigger.&lt;/p&gt;

&lt;h2 id=&quot;mousing&quot;&gt;Mousing&lt;/h2&gt;

&lt;h3 id=&quot;buttons&quot;&gt;Buttons&lt;/h3&gt;
&lt;p&gt;I have to start off with this - &lt;strong&gt;the VMC has no scroll wheel click&lt;/strong&gt;. It is instead replaced by the third face button. The extra face button is certainly comfortable, but why remove the scroll click? I imagine it’s harder to press a scroll wheel and it was removed for ergo purposes, but two buttons is better than one.&lt;/p&gt;

&lt;p&gt;Otherwise, the VMC has a fairly standard button configuration. There’s 2 thumb buttons, scroll wheel, DPI changer and the 3 face buttons. The extra face button is quite comfortable to press with my ring and pinky fingers combined, and it doesn’t feel as awkward as it looks. The thumb buttons are easy to click easy to avoid when you don’t want to click them. The DPI switcher button is conveniently placed, and the LEDs to indicate your current sensitivity are subtle and quickly glanceable. The scroll wheel feels like “upper class office” style - that weird combination of mushy (the good kind) and clicky. Personal preference, but I quite like it.
My only real gripe is that Mouse1 requires about half the force to actuate than the other mouse buttons, which resulted in heaps of miss-clicks as I was adjusting to the mouse. Lighter switches are ergonomically superior, but it’s confusing why only 1 of the buttons get this treatment.&lt;/p&gt;

&lt;p&gt;Lots of buttons are useless without configuration, and Evoluent’s software comes through in spades. Each button can be set to any standard mouse or keyboard button or a pre-recorded macro. Bindings can also be customised on a per-application basis, which is excellent to see. Also included is a break timer to remind you to get off your arse, and “Click lock” and “Auto click” features to reduce strain from clicking things.&lt;/p&gt;

&lt;p&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://mon.im/img/large/vmc/ui1.png&quot;&gt;
&lt;img src=&quot;https://mon.im/img/thumbs/vmc/ui1.png&quot; /&gt;
&lt;/a&gt;  &lt;br /&gt;
&lt;a target=&quot;_blank&quot; href=&quot;https://mon.im/img/large/vmc/ui2.png&quot;&gt;
&lt;img src=&quot;https://mon.im/img/thumbs/vmc/ui2.png&quot; /&gt;
&lt;/a&gt;  &lt;br /&gt;
&lt;a target=&quot;_blank&quot; href=&quot;https://mon.im/img/large/vmc/ui3.png&quot;&gt;
&lt;img src=&quot;https://mon.im/img/thumbs/vmc/ui3.png&quot; /&gt;
&lt;/a&gt;  &lt;br /&gt;
&lt;a target=&quot;_blank&quot; href=&quot;https://mon.im/img/large/vmc/ui4.png&quot;&gt;
&lt;img src=&quot;https://mon.im/img/thumbs/vmc/ui4.png&quot; /&gt;
&lt;/a&gt;&lt;/p&gt;

&lt;h2 id=&quot;tracking&quot;&gt;Tracking&lt;/h2&gt;
&lt;p&gt;Initially I used the VMC on my Goliathus ‘Speed’ edition mouspad. It’s a cloth pad with a smooth surface, and I enjoy it with my DeathAdder. With the VMC it’s unusable. Incredibly slippery. For those who enjoy cloth pads, it’s like switching to a super smooth hard pad - I felt I was tracking on ice.
Luckily I bought a Goliathus ‘Control’ by accident some time ago. It’s also cloth but quite rough. It made a huge difference to the feel of the mouse, and tracking now feels good. I’m starting to regain muscle memory with this configuration - headshots and airshots are become more common, and I’m not overshooting on-screen buttons like I was on the Speed.
The feet are as smooth, if not smoother than the ones on my DeathAdder. Combined with the vertical stance putting more weight on the mouse, this would explain the slipperiness.&lt;/p&gt;

&lt;p&gt;I don’t actually know what DPI Evoluent is using for the VMC. There are 2 ways to adjust sensitivity. The first is using the built in Windows sensitivity settings - the Evoluent software doesn’t add any precise control. Additionally, the mouse itself has a DPI button that changes between 4 different sensitivity settings. These are not configurable. This is pretty annoying, because my DeathAdder was set up perfectly. By forcing me to adjust using the Windows DPI settings, I now have to correct the DeathAdder’s sensitivity to compensate, which is a pain. Adding a DPI slider would be a great improvement to the Evoluent software.&lt;/p&gt;

&lt;p&gt;Unlike standard mice where you actually lift the entire mouse, the most natural way to “lift off” using the VMC is to tilt the mouse to the side and slide with one end still on the mat. The manual even recommends this method, and it’s definitely the most comfortable. However, the liftoff distance of the sensor is quite high, and not configurable. I found myself not lifting far enough and sliding back. After a few days (and swapping mouse pads) it’s getting better, but it’s another pain point to consider when adapting to the new mouse - even if you already own a vertical mouse.&lt;/p&gt;

&lt;p&gt;Lastly, the mouse updates at 125Hz, but this isn’t a deal breaker for me. Worth mentioning for the 1KHz diehards. I’m just a schmuck on the internet, but I think Evoluent would do well to try and capture the gaming market with a dedicated product. There’s a lot of gamers abusing their hands that probably don’t realise such comfort exists.&lt;/p&gt;

&lt;h2 id=&quot;teardown&quot;&gt;Teardown&lt;/h2&gt;
&lt;p&gt;Basic disassembly is quite simple. By removing 2 of the mouse feet and 4 screws, the bottom simply falls out, revealing the PCB and ribbon cables to the button assemblies. Having to remove the feet is annoying as ever, as it’s never quite the same when you replace them after disassembly. Replacements aren’t offered yet, but I reached out to Evoluent and they said they’ll sell them soon.&lt;/p&gt;

&lt;p&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://mon.im/img/large/vmc/10.jpg&quot;&gt;
&lt;img src=&quot;https://mon.im/img/thumbs/vmc/10.jpg&quot; /&gt;
&lt;/a&gt;&lt;br /&gt;
&lt;a target=&quot;_blank&quot; href=&quot;https://mon.im/img/large/vmc/11.jpg&quot;&gt;
&lt;img src=&quot;https://mon.im/img/thumbs/vmc/11.jpg&quot; /&gt;
&lt;/a&gt;&lt;br /&gt;
&lt;a target=&quot;_blank&quot; href=&quot;https://mon.im/img/large/vmc/12.jpg&quot;&gt;
&lt;img src=&quot;https://mon.im/img/thumbs/vmc/12.jpg&quot; /&gt;
&lt;/a&gt;&lt;br /&gt;
&lt;a target=&quot;_blank&quot; href=&quot;https://mon.im/img/large/vmc/13.jpg&quot;&gt;
&lt;img src=&quot;https://mon.im/img/thumbs/vmc/13.jpg&quot; /&gt;
&lt;/a&gt;&lt;/p&gt;

&lt;h3 id=&quot;sensor&quot;&gt;Sensor&lt;/h3&gt;
&lt;p&gt;My VM4 was an early model and had an rubbish laser sensor. The VMC (and the VM4 if bought new today) have a huge upgrade - the Avago ADNS-3000. It’s not gaming class, but it’s optical and made by Avago. It uses a Kingsis lens and should be good for up to 2000dpi. I don’t know much about lenses but from what I’ve read the Kingsis seems pretty standard.
The date code on the sensor indicates it was manufactured in April 2015.&lt;/p&gt;

&lt;h3 id=&quot;processor&quot;&gt;Processor&lt;/h3&gt;
&lt;p&gt;The processor is a Cyprus CY7C64215. Nothing particularly special here, it does what it needs to do.&lt;/p&gt;

&lt;h2 id=&quot;wrap-up&quot;&gt;Wrap-up&lt;/h2&gt;
&lt;p&gt;The Evoluent VerticalMouse C is a welcome upgrade over the VerticalMouse 4, and may well be the best ergonomic mouse on the market today. For office use its purchase should be a no-brainer. For gaming it certainly holds its own, and I would definitely consider a purchase if hand pain is a problem for you. However, limited DPI customisation, 125Hz update rate and missing scroll click mean the VMC won’t be ideal for hardcore or competitive gamers.&lt;/p&gt;

&lt;p&gt;Is it worth $100 USD? It’s a tough purchase, but the answer is simple for me - $100 now or permanent hand pain as I grow old. That it happens to be a great mouse is just a bonus.&lt;/p&gt;</content>

      
      
      
      
      

      
        <author>
            <name>mon</name>
          
          
        </author>
      

      

      

      
        <summary type="html">Computer mice haven’t really changed since they were invented. It’s still a block you move about with your hand in a flat position. However, this twisting of the forearm is unnatural, and frequent mouse users will find they develop wrist pain. The solution is a vertically oriented mouse. It lets the hand rest in a natural state and in my experience is super comfortable. These are readily available for under $30 on eBay, Amazon and Aliexpress, but are often childsize or simply not comfortable enough. After trying about 4 mice I’ve realised who the reigning champion is: Evoluent.</summary>
      

      
      
    </entry>
  
  
  
    <entry>
      
      <title type="html">cthelper - fix “Failed to allocate pseudoterminal”</title>
      
      
      <link href="https://mon.im/2016/01/cthelper-fix-failed-to-allocate.html" rel="alternate" type="text/html" title="cthelper - fix &quot;Failed to allocate pseudoterminal&quot;" />
      
      <published>2016-01-17T06:46:00+00:00</published>
      <updated>2016-01-17T06:46:00+00:00</updated>
      <id>https://mon.im/2016/01/cthelper-fix-failed-to-allocate</id>
      <content type="html" xml:base="https://mon.im/2016/01/cthelper-fix-failed-to-allocate.html">&lt;p&gt;Kitty/PuttyCyg, Windows 10, cthelper, Cygwin64.
This blog post is brief, but my mosh stopped working and I felt I should
document the solution.&lt;/p&gt;

&lt;p&gt;Open your cygwin installer (just download it again if you don’t have it) and
update packages - don’t select anything, just go through until it installs. Boom, fixed!&lt;/p&gt;</content>

      
      
      
      
      

      
        <author>
            <name>mon</name>
          
          
        </author>
      

      

      

      
        <summary type="html">Kitty/PuttyCyg, Windows 10, cthelper, Cygwin64. This blog post is brief, but my mosh stopped working and I felt I should document the solution.</summary>
      

      
      
    </entry>
  
  
  
    <entry>
      
      <title type="html">Evoluent Vertical Mouse 4 Sensor Transplant</title>
      
      
      <link href="https://mon.im/2015/09/evoluent-vertical-mouse-4-sensor.html" rel="alternate" type="text/html" title="Evoluent Vertical Mouse 4 Sensor Transplant" />
      
      <published>2015-09-14T14:58:00+00:00</published>
      <updated>2015-09-14T14:58:00+00:00</updated>
      <id>https://mon.im/2015/09/evoluent-vertical-mouse-4-sensor</id>
      <content type="html" xml:base="https://mon.im/2015/09/evoluent-vertical-mouse-4-sensor.html">&lt;p&gt;Maybe I just play games badly, but for many months I was getting serious wrist pain using my Deathadder. I tried a couple of “ergo” mice, including a Logitech ball mouse (the &lt;a href=&quot;http://www.logitech.com/en-au/product/wireless-trackball-m570&quot;&gt;M570&lt;/a&gt;) and a no name eBay vertical mouse, but they didn’t really help, and were damn hard to play games with. At the suggestion of a physio friend, I finally bought the “real deal”, the &lt;a href=&quot;https://evoluent.com/products/vm4r/&quot;&gt;Evoluent VM4&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;It’s weird to start off, but by 2 weeks I was playing (almost) as well as I did with the DA, and my wrist pain had practically disappeared. There was only 1 problem. &lt;strong&gt;The sensor is garbage!&lt;/strong&gt; It has a weird jitter I can’t really place. Is it angle snapping? 125Hz update rate? Or simply laser sensors being horrible as always? Either way, it could never replace the DA for “real” play, so I set off on an adventure to fix it.&lt;/p&gt;

&lt;h2 id=&quot;the-donor-mouse&quot;&gt;The donor mouse&lt;/h2&gt;
&lt;p&gt;Thanks to &lt;a href=&quot;http://accel.drok-radnik.com/&quot;&gt;pvh&lt;/a&gt; I found a suitable donor, the &lt;a href=&quot;http://www.amazon.com/dp/B00SV735GU&quot;&gt;EVGA TORQ X5&lt;/a&gt;. It has enough buttons to match the 8 on the Evoluent, and a great sensor, the Pixart 3988. On top of this, I grabbed one for $20 used off Amazon. Now came the fun part - shoving it in its new case, and connecting all the switches and lights from the vertical mouse.&lt;/p&gt;

&lt;p&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://mon.im/img/large/evo_conversion/1.jpg&quot;&gt;
&lt;img src=&quot;https://mon.im/img/thumbs/evo_conversion/1.jpg&quot; /&gt;
&lt;/a&gt;   &lt;br /&gt;
&lt;a target=&quot;_blank&quot; href=&quot;https://mon.im/img/large/evo_conversion/2.jpg&quot;&gt;
&lt;img src=&quot;https://mon.im/img/thumbs/evo_conversion/2.jpg&quot; /&gt;
&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Quite the difference.&lt;/p&gt;

&lt;h2 id=&quot;disassembly&quot;&gt;Disassembly&lt;/h2&gt;
&lt;h3 id=&quot;evoluent-disassembly&quot;&gt;Evoluent Disassembly&lt;/h3&gt;

&lt;p&gt;I haven’t found anyone online do a complete disassembly of this mouse, so I’m going to be a little verbose. Feel free to skip past this section.&lt;/p&gt;

&lt;p&gt;The VM4 comes apart with 4 screws in the bottom:&lt;/p&gt;

&lt;p&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://mon.im/img/large/evo_conversion/3.jpg&quot;&gt;
&lt;img src=&quot;https://mon.im/img/thumbs/evo_conversion/3.jpg&quot; /&gt;
&lt;/a&gt;   &lt;br /&gt;
&lt;a target=&quot;_blank&quot; href=&quot;https://mon.im/img/large/evo_conversion/4.jpg&quot;&gt;
&lt;img src=&quot;https://mon.im/img/thumbs/evo_conversion/4.jpg&quot; /&gt;
&lt;/a&gt;   &lt;br /&gt;
&lt;a target=&quot;_blank&quot; href=&quot;https://mon.im/img/large/evo_conversion/5.jpg&quot;&gt;
&lt;img src=&quot;https://mon.im/img/thumbs/evo_conversion/5.jpg&quot; /&gt;
&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Simple PCB, and the crappy sensor:&lt;/p&gt;

&lt;p&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://mon.im/img/large/evo_conversion/6.jpg&quot;&gt;
&lt;img src=&quot;https://mon.im/img/thumbs/evo_conversion/6.jpg&quot; /&gt;
&lt;/a&gt;   &lt;br /&gt;
&lt;a target=&quot;_blank&quot; href=&quot;https://mon.im/img/large/evo_conversion/7.jpg&quot;&gt;
&lt;img src=&quot;https://mon.im/img/thumbs/evo_conversion/7.jpg&quot; /&gt;
&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Next you undo all the screws you can see, then fiddle with a large flathead screwdriver until the side pops off. Then you can take the entire shell apart.&lt;/p&gt;

&lt;p&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://mon.im/img/large/evo_conversion/8.jpg&quot;&gt;
&lt;img src=&quot;https://mon.im/img/thumbs/evo_conversion/8.jpg&quot; /&gt;
&lt;/a&gt;   &lt;br /&gt;
&lt;a target=&quot;_blank&quot; href=&quot;https://mon.im/img/large/evo_conversion/9.jpg&quot;&gt;
&lt;img src=&quot;https://mon.im/img/thumbs/evo_conversion/9.jpg&quot; /&gt;
&lt;/a&gt;   &lt;br /&gt;
&lt;a target=&quot;_blank&quot; href=&quot;https://mon.im/img/large/evo_conversion/10.jpg&quot;&gt;
&lt;img src=&quot;https://mon.im/img/thumbs/evo_conversion/10.jpg&quot; /&gt;
&lt;/a&gt;   &lt;br /&gt;
&lt;a target=&quot;_blank&quot; href=&quot;https://mon.im/img/large/evo_conversion/11.jpg&quot;&gt;
&lt;img src=&quot;https://mon.im/img/thumbs/evo_conversion/11.jpg&quot; /&gt;
&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Couple more screws and the scrollwheel assembly comes out:&lt;/p&gt;

&lt;p&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://mon.im/img/large/evo_conversion/12.jpg&quot;&gt;
&lt;img src=&quot;https://mon.im/img/thumbs/evo_conversion/12.jpg&quot; /&gt;
&lt;/a&gt;   &lt;br /&gt;
&lt;a target=&quot;_blank&quot; href=&quot;https://mon.im/img/large/evo_conversion/13.jpg&quot;&gt;
&lt;img src=&quot;https://mon.im/img/thumbs/evo_conversion/13.jpg&quot; /&gt;
&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And that’s it!&lt;/p&gt;

&lt;h3 id=&quot;torq-x5-disassembly&quot;&gt;TORQ X5 Disassembly&lt;/h3&gt;
&lt;p&gt;This one’s really easy. 4 screws hidden under the skids, and the whole body comes apart. Nothing much else to say!&lt;/p&gt;

&lt;p&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://mon.im/img/large/evo_conversion/14.jpg&quot;&gt;
&lt;img src=&quot;https://mon.im/img/thumbs/evo_conversion/14.jpg&quot; /&gt;
&lt;/a&gt;   &lt;br /&gt;
&lt;a target=&quot;_blank&quot; href=&quot;https://mon.im/img/large/evo_conversion/15.jpg&quot;&gt;
&lt;img src=&quot;https://mon.im/img/thumbs/evo_conversion/15.jpg&quot; /&gt;
&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Mmmm, that lovely Pixart.&lt;/p&gt;

&lt;p&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://mon.im/img/large/evo_conversion/16.jpg&quot;&gt;
&lt;img src=&quot;https://mon.im/img/thumbs/evo_conversion/16.jpg&quot; /&gt;
&lt;/a&gt;&lt;/p&gt;

&lt;h2 id=&quot;first-attempts&quot;&gt;First attempts&lt;/h2&gt;
&lt;p&gt;It was clear that the X5 wouldn’t fit inside the body of the VM without cutting off the front.&lt;/p&gt;

&lt;p&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://mon.im/img/large/evo_conversion/17.jpg&quot;&gt;
&lt;img src=&quot;https://mon.im/img/thumbs/evo_conversion/17.jpg&quot; /&gt;
&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;First mistake: I figured putting the X5 scrollwheel inside the VM4 would be a brilliant idea. WRONG. The 2 wheel assemblies are completely different, and to get it to fit I ruined the middle click actuation of the mouse. Learn from my mistakes. I then purchased my second VM4, with a horrible exterior but working interior parts to salvage.&lt;/p&gt;

&lt;p&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://mon.im/img/large/evo_conversion/18.jpg&quot;&gt;
&lt;img src=&quot;https://mon.im/img/thumbs/evo_conversion/18.jpg&quot; /&gt;
&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The new bashed up donor:&lt;/p&gt;

&lt;p&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://mon.im/img/large/evo_conversion/19.jpg&quot;&gt;
&lt;img src=&quot;https://mon.im/img/thumbs/evo_conversion/19.jpg&quot; /&gt;
&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Was this left out in the sun? Weird wear.&lt;/p&gt;

&lt;p&gt;So, to the next failure. I have to cut the front off the X5 to make it fit. The buttons live on the front. Thus, I have to wire jumpers on the microcontroller. Individually. With several right next to each other. I wasted hours on this. I even used a hot air gun to take the entire MCU off the board, bend certain pins up, and resolder it. In doing so I busted the mouse3 pin, which meant I had to map two buttons to the same pin. What a disaster!&lt;/p&gt;

&lt;p&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://mon.im/img/large/evo_conversion/20.jpg&quot;&gt;
&lt;img src=&quot;https://mon.im/img/thumbs/evo_conversion/20.jpg&quot; /&gt;
&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;PCB surgery: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;soldering_skills++; sanity--&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://mon.im/img/large/evo_conversion/21.jpg&quot;&gt;
&lt;img src=&quot;https://mon.im/img/thumbs/evo_conversion/21.jpg&quot; /&gt;
&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Not pictured here is the soldered ribbon cable adapter, after I painstakingly mapped all the VM4 pins to their functions.
After all this, I plugged it in… And it worked! …Except for the scroll wheel. Turns out, mechanical scroll wheels (X5) don’t put out the same signals as IR scroll wheel (VM4). I practically gave up at this point, and the project was dead for several weeks, until my hand got sore enough to look back into it.&lt;/p&gt;

&lt;h2 id=&quot;final-success&quot;&gt;Final Success&lt;/h2&gt;
&lt;p&gt;After failing to shove VM4 bits into the X5, I had a stroke of genius - why not use the X5 board just as a sensor, the VM4 board just for buttons, and put a USB hub in there? $2 and 2 weeks later, my 4 port eBay hub arrived. I forgot to take a before when it had all 4 ports, but the extra 2 snapped off with no problems:&lt;/p&gt;

&lt;p&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://mon.im/img/large/evo_conversion/22.jpg&quot;&gt;
&lt;img src=&quot;https://mon.im/img/thumbs/evo_conversion/22.jpg&quot; /&gt;
&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;From there it was a simple matter of desoldering the USB ports and hardwiring all the relevant mice connectors to the board:&lt;/p&gt;

&lt;p&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://mon.im/img/large/evo_conversion/23.jpg&quot;&gt;
&lt;img src=&quot;https://mon.im/img/thumbs/evo_conversion/23.jpg&quot; /&gt;
&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;With a solution finally in place, I went ahead and cut the front off the X5 PCB, scribed its outline, dremeled a hole for the lens, and dremeled a bunch of plastic off the VM4 case so the PCB would lay flat. Add a bit of hot glue to the lens and you’re set:&lt;/p&gt;

&lt;p&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://mon.im/img/large/evo_conversion/24.jpg&quot;&gt;
&lt;img src=&quot;https://mon.im/img/thumbs/evo_conversion/24.jpg&quot; /&gt;
&lt;/a&gt;   &lt;br /&gt;
&lt;a target=&quot;_blank&quot; href=&quot;https://mon.im/img/large/evo_conversion/25.jpg&quot;&gt;
&lt;img src=&quot;https://mon.im/img/thumbs/evo_conversion/25.jpg&quot; /&gt;
&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Because the sensor fits to the lens quite solidly, no extra glue is required.
I had to reposition the PCB once, as it initially collided with the top half of the shell. After the move it’s a tight fit:&lt;/p&gt;

&lt;p&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://mon.im/img/large/evo_conversion/26.jpg&quot;&gt;
&lt;img src=&quot;https://mon.im/img/thumbs/evo_conversion/26.jpg&quot; /&gt;
&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now comes the easy part, putting it back together. I added some kapton tape to the scroll wheel PCB just to be sure there weren’t going to be any shorts. I probably should have covered the original laser aperture, but with no lens it hasn’t given me any problems yet.&lt;/p&gt;

&lt;p&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://mon.im/img/large/evo_conversion/27.jpg&quot;&gt;
&lt;img src=&quot;https://mon.im/img/thumbs/evo_conversion/27.jpg&quot; /&gt;
&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Looks messy, works beautifully. Amazingly, the $2 hub was actually USB 2.0! MouseView was showing 1000Hz from the X5, which is just lovely.&lt;/p&gt;

&lt;p&gt;The RGB LEDs on the X5 even show through the Evoluent logo, which is a great bonus:&lt;/p&gt;

&lt;p&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://mon.im/img/large/evo_conversion/28.jpg&quot;&gt;
&lt;img src=&quot;https://mon.im/img/thumbs/evo_conversion/28.jpg&quot; /&gt;
&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Compared to all the failed attempts, this mod is now wonderfully easy, assuming you’re capable of desoldering USB connectors. However, since there’s no longer a need for any buttons on the donor, I’d recommend getting a smaller mouse to shove inside this one to save hacking away at PCBs.&lt;/p&gt;

&lt;p&gt;Again, if you get wrist pain from gaming, I’d highly recommend a vertical mouse. Don’t get a Chinese copy, they’re simply too small to be useful. I got mine for $70AUD used, they seem to go for about $40USD if you’re in the states. See if you can deal with the bad sensor, and if you can’t, upgrade it!&lt;/p&gt;</content>

      
      
      
      
      

      
        <author>
            <name>mon</name>
          
          
        </author>
      

      

      

      
        <summary type="html">Maybe I just play games badly, but for many months I was getting serious wrist pain using my Deathadder. I tried a couple of “ergo” mice, including a Logitech ball mouse (the M570) and a no name eBay vertical mouse, but they didn’t really help, and were damn hard to play games with. At the suggestion of a physio friend, I finally bought the “real deal”, the Evoluent VM4.</summary>
      

      
      
    </entry>
  
  
  
    <entry>
      
      <title type="html">Modifying AVR PROGMEM at runtime</title>
      
      
      <link href="https://mon.im/2014/11/modifying-avr-progmem-at-runtime.html" rel="alternate" type="text/html" title="Modifying AVR PROGMEM at runtime" />
      
      <published>2014-11-06T12:07:00+00:00</published>
      <updated>2014-11-06T12:07:00+00:00</updated>
      <id>https://mon.im/2014/11/modifying-avr-progmem-at-runtime</id>
      <content type="html" xml:base="https://mon.im/2014/11/modifying-avr-progmem-at-runtime.html">&lt;p&gt;As part of a project this year, I needed about 11.5KiB of data which would be maintained on power off, could be modified on the fly, could be read blazingly fast, and didn’t use the Arduino bootloader. Storing stuff in flash using PROGMEM sounds great, but you can’t modify that, right? Wrong!&lt;/p&gt;

&lt;p&gt;First up: Don’t do this unless you have a very good reason to. The flash memory on most AVR microcontrollers has an endurance of only 10,000 writes. Make sure that you’re not going to hit this limit in your application, or bad things could happen! The data is also lost on every program flash (unlike EEPROM, which can be preserved), so keep that in mind if you rapidly iterate.&lt;/p&gt;

&lt;p&gt;Here’s some example code to make it all work:&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;cp&quot;&gt;#include&lt;/span&gt; &lt;span class=&quot;cpf&quot;&gt;&amp;lt;avr/io.h&amp;gt;&lt;/span&gt;&lt;span class=&quot;cp&quot;&gt;
#include&lt;/span&gt; &lt;span class=&quot;cpf&quot;&gt;&amp;lt;avr/boot.h&amp;gt;&lt;/span&gt;&lt;span class=&quot;cp&quot;&gt;
#include&lt;/span&gt; &lt;span class=&quot;cpf&quot;&gt;&amp;lt;avr/interrupt.h&amp;gt;&lt;/span&gt;&lt;span class=&quot;cp&quot;&gt;
#include&lt;/span&gt; &lt;span class=&quot;cpf&quot;&gt;&amp;lt;avr/pgmspace.h&amp;gt;&lt;/span&gt;&lt;span class=&quot;cp&quot;&gt;
&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;rewrite_data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;BOOTLOADER_SECTION&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;boot_program_page&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;uint32_t&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;page&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;uint8_t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;buf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;uint8_t&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;flash_data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;11520&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;__attribute__&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;aligned&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;SPM_PAGESIZE&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PROGMEM&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{};&lt;/span&gt;

&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;rewrite_data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
 &lt;span class=&quot;kt&quot;&gt;uint8_t&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;SPM_PAGESIZE&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;
 &lt;span class=&quot;c1&quot;&gt;// Break data into pages&lt;/span&gt;
 &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;11520&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;SPM_PAGESIZE&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;// Load data&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;j&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;j&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;SPM_PAGESIZE&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;j&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
   &lt;span class=&quot;c1&quot;&gt;// For my project this came from serial, don&apos;t just use 42!&lt;/span&gt;
   &lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;42&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;boot_program_page&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;uint32_t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;flash_data&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
 &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// avr/boot.h documentation example&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;BOOTLOADER_SECTION&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;boot_program_page&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;uint32_t&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;page&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;uint8_t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;buf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
 &lt;span class=&quot;kt&quot;&gt;uint16_t&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
 &lt;span class=&quot;kt&quot;&gt;uint8_t&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sreg&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
 &lt;span class=&quot;c1&quot;&gt;// Disable interrupts.&lt;/span&gt;
 &lt;span class=&quot;n&quot;&gt;sreg&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;SREG&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
 &lt;span class=&quot;n&quot;&gt;cli&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
 &lt;span class=&quot;n&quot;&gt;eeprom_busy_wait&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
 &lt;span class=&quot;n&quot;&gt;boot_page_erase&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;page&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
 &lt;span class=&quot;n&quot;&gt;boot_spm_busy_wait&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;();&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// Wait until the memory is erased.&lt;/span&gt;
 &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;SPM_PAGESIZE&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
 &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;// Set up little-endian word.&lt;/span&gt;
  &lt;span class=&quot;kt&quot;&gt;uint16_t&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;w&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;buf&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;w&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;buf&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;boot_page_fill&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;page&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;w&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
 &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
 &lt;span class=&quot;n&quot;&gt;boot_page_write&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;page&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// Store buffer in flash page.&lt;/span&gt;
 &lt;span class=&quot;n&quot;&gt;boot_spm_busy_wait&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// Wait until the memory is written.&lt;/span&gt;
 &lt;span class=&quot;c1&quot;&gt;// Reenable RWW-section again. We need this if we want to jump back&lt;/span&gt;
 &lt;span class=&quot;c1&quot;&gt;// to the application after bootloading.&lt;/span&gt;
 &lt;span class=&quot;n&quot;&gt;boot_rww_enable&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
 &lt;span class=&quot;n&quot;&gt;sei&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
 &lt;span class=&quot;c1&quot;&gt;// Re-enable interrupts (if they were ever enabled).&lt;/span&gt;
 &lt;span class=&quot;n&quot;&gt;SREG&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sreg&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;To explain some tricky sections:&lt;/p&gt;
&lt;div class=&quot;language-c highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;uint8_t&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;flash_data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;11520&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;__attribute__&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;aligned&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;SPM_PAGESIZE&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PROGMEM&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This defines your data - in my case, a 11520 byte array of unsigned 8 bit integers. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PROGMEM&lt;/code&gt; is the AVR directive to put this variable inside flash memory instead of SRAM. The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;___attribute__((aligned(SPM_PAGESIZE))&lt;/code&gt;  is so that the data gets put into its own page. AVR flash memory is per page, and there is no way around that. You &lt;em&gt;could&lt;/em&gt; read in the previous page data before yours, add your data, then write it back, but this is unnecessary effort. Aligning the data to a page boundary means you can write data directly to that page without worrying about other things in that memory space.&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;BOOTLOADER_SECTION&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;boot_program_page&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;uint32_t&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;page&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;uint8_t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;buf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This puts this function (only this function) inside the bootloader section of the flash memory. If you try to execute flash memory modifications outside this area, nothing happens.&lt;/p&gt;

&lt;p&gt;Now, if you were to compile this, you’d get a linker error. Whilst you’ve said that your special programmer function should exist in the bootloader, it doesn’t actually know where that is. How do we find out where it should go? The datasheet! I was using the Atmega328P, so I’ll use this for an example.&lt;/p&gt;

&lt;p&gt;The bootloader section can be several different sizes depending on which fuses you’ve set. For the 328 we go to section 26.8.16, page 291.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://mon.im/img/progmem/datasheet.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;In this case, the page programming code happily fits inside 256 words, so we set our
BOOTSZ[1:0] bits to 3. We can also see that the bootloader will then start at 0x3F00. So how do we tell the linker this?&lt;/p&gt;

&lt;p&gt;In Atmel Studio you can set this up under the project settings:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://mon.im/img/progmem/compiler.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Using commandline tools, just add &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--section-start=.bootloader=0x3F00&lt;/code&gt; to your linker flags. Double check your address is actually in bootloader space! Otherwise the code will run happily but not modify anything.&lt;/p&gt;

&lt;p&gt;That’s it! Enjoy your newfound “kind of EEPROM but not really” space!&lt;/p&gt;</content>

      
      
      
      
      

      
        <author>
            <name>mon</name>
          
          
        </author>
      

      

      

      
        <summary type="html">As part of a project this year, I needed about 11.5KiB of data which would be maintained on power off, could be modified on the fly, could be read blazingly fast, and didn’t use the Arduino bootloader. Storing stuff in flash using PROGMEM sounds great, but you can’t modify that, right? Wrong!</summary>
      

      
      
    </entry>
  
  
</feed>
