<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
    <title>Gekkio&#x27;s Technical Blog</title>
    <subtitle>Technical blog by Joonas Javanainen</subtitle>
    <link rel="self" type="application/atom+xml" href="https://gekkio.fi/atom.xml"/>
    <link rel="alternate" type="text/html" href="https://gekkio.fi"/>
    <generator uri="https://www.getzola.org/">Zola</generator>
    <updated>2026-02-07T00:00:00+00:00</updated>
    <id>https://gekkio.fi/atom.xml</id>
    <entry xml:lang="en">
        <title>Game Boy Advance d-pad capacitor measurements</title>
        <published>2026-02-07T00:00:00+00:00</published>
        <updated>2026-02-07T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Joonas Javanainen
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://gekkio.fi/blog/2026/game-boy-advance-d-pad-capacitor-measurements/"/>
        <id>https://gekkio.fi/blog/2026/game-boy-advance-d-pad-capacitor-measurements/</id>
        
        <content type="html" xml:base="https://gekkio.fi/blog/2026/game-boy-advance-d-pad-capacitor-measurements/">&lt;p&gt;Game Boy Advance boards have a &lt;strong&gt;10 nF capacitor C62&lt;&#x2F;strong&gt; between the d-pad up input and ground, but other d-pad buttons have no capacitor. This raises the question: why is it needed for one input but not for the others?&lt;&#x2F;p&gt;
&lt;figure&gt;
&lt;img src=&quot;schematic.png&quot; alt=&quot;Schematic&quot;&gt;
&lt;figcaption&gt;Schematic screenshot from &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;Redherring32&#x2F;OpenTendo-AGB&quot;&gt;OpenTendo Game Boy Advance&lt;&#x2F;a&gt;, which is a recreation of the original board&lt;&#x2F;figcaption&gt;
&lt;&#x2F;figure&gt;
&lt;h2 id=&quot;theory-dc-dc-conversion-noise&quot;&gt;Theory: DC&#x2F;DC conversion noise&lt;&#x2F;h2&gt;
&lt;p&gt;I think the capacitor is needed, because the d-pad is very close to the noisy DC&#x2F;DC conversion circuitry. Without the capacitor you could get spurious up button presses in some scenarios, which isn&#x27;t something we want while playing a difficult game on the console. Let&#x27;s look at the placement of the d-pad:&lt;&#x2F;p&gt;
&lt;figure&gt;
&lt;img src=&quot;agb_front.jpg&quot; alt=&quot;AGB console front photo with up button pads highlighted&quot;&gt;
&lt;figcaption&gt;AGB console front photo with up button pads highlighted&lt;&#x2F;figcaption&gt;
&lt;&#x2F;figure&gt;
&lt;p&gt;The d-pad is on the left side of the board. On this side you can see some components of the DC&#x2F;DC conversion circuitry, such as transformer T1 on the bottom.&lt;&#x2F;p&gt;
&lt;figure&gt;
&lt;img src=&quot;agb_back.jpg&quot; alt=&quot;AGB console back photo with the PMIC highlighted&quot;&gt;
&lt;figcaption&gt;AGB console back photo with the PMIC highlighted&lt;&#x2F;figcaption&gt;
&lt;&#x2F;figure&gt;
&lt;p&gt;If we flip the PCB to look at the other side, we see a Power Management IC (PMIC) directly behind the up button pads. There are also other DC&#x2F;DC conversion components, such as capacitors and a boost inductor, around the right side of the PCB. The PMIC is not necessarily the noisiest part of the conversion circuit, but the PCB has no inner layers to shield the two opposing sides from each other, so component locations matter.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;real-world-measurements&quot;&gt;Real-world measurements&lt;&#x2F;h2&gt;
&lt;p&gt;The effect of the capacitor can be seen in real-world measurements. Here&#x27;s the measurement setup:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;a GBA with an AGB-CPU-01 mainboard (&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;gbhwdb.gekkio.fi&#x2F;consoles&#x2F;agb&#x2F;AH10045235.html&quot;&gt;AH10045235&lt;&#x2F;a&gt;)&lt;&#x2F;li&gt;
&lt;li&gt;a programmable DC power supply outputting a stable +3V, connected to the GBA battery connectors&lt;&#x2F;li&gt;
&lt;li&gt;no game is inserted, and the measurements were started only after the boot animation finished&lt;&#x2F;li&gt;
&lt;li&gt;Rigol DHO924S oscilloscope using a 10x probe, AC coupling, peak detection mode, 20 MHz bandwidth limit enabled&lt;&#x2F;li&gt;
&lt;li&gt;oscilloscope probe with ground spring, measuring two pads of a d-pad input (ground spring goes to GND, probe pin goes to the other pad)&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;First, let&#x27;s look at a reference measurement from the &lt;strong&gt;left d-pad&lt;&#x2F;strong&gt;:&lt;&#x2F;p&gt;
&lt;figure&gt;
&lt;img src=&quot;dpad_left.png&quot; alt=&quot;Left d-pad measurement&quot;&gt;
&lt;figcaption&gt;Left d-pad measurement&lt;&#x2F;figcaption&gt;
&lt;&#x2F;figure&gt;
&lt;p&gt;In the screenshot we can see the raw AC-coupled signal on the left side, and a Fast Fourier Transform (FFT) on the right side, showing the frequency spectrum up to 1 MHz. The total peak-to-peak noise is around 40 mV, which is not a lot and the scope&#x27;s own noise is also probably affecting it. In the FFT we can see a peak at ~95 kHz, which is in this case the DC&#x2F;DC conversion switching frequency. We can also see harmonics of this switching frequency at integer multiples (190 kHz, 285 kHz, etc...).&lt;&#x2F;p&gt;
&lt;p&gt;Let&#x27;s also look at the up d-pad:&lt;&#x2F;p&gt;
&lt;figure&gt;
&lt;img src=&quot;dpad_up.png&quot; alt=&quot;Up d-pad measurement (unmodified console)&quot;&gt;
&lt;figcaption&gt;Up d-pad measurement (unmodified console)&lt;&#x2F;figcaption&gt;
&lt;&#x2F;figure&gt;
&lt;p&gt;The up input is a lot less noisy, which is not surprising since capacitor C62 reduces the noise.&lt;&#x2F;p&gt;
&lt;p&gt;However, here&#x27;s what happens if we &lt;strong&gt;desolder C62&lt;&#x2F;strong&gt;:&lt;&#x2F;p&gt;
&lt;figure&gt;
&lt;img src=&quot;dpad_up_nocap.png&quot; alt=&quot;Up d-pad measurement (C62 desoldered)&quot;&gt;
&lt;figcaption&gt;Up d-pad measurement (C62 desoldered)&lt;&#x2F;figcaption&gt;
&lt;&#x2F;figure&gt;
&lt;p&gt;When there&#x27;s no C62 capacitor, the up input is &lt;em&gt;more noisy&lt;&#x2F;em&gt; than the left input. The total noise is around 60 mV in this case, and the FFT shows even more clearly the switching frequency and its harmonics.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;conclusions&quot;&gt;Conclusions&lt;&#x2F;h2&gt;
&lt;p&gt;The measurements clearly show that the up input is more noisy than the left input when C62 is not present. 40 mV vs 60 mV peak-to-peak might not sound like much, but the measurements were done in very &quot;nice&quot; conditions at room temperature, using stable +3V input, and with no game inserted. In real-world use there are many factors that affect the noise, so a good design leaves plenty of safety margin. In this case, Nintendo probably calculated that adding an extra capacitor was worth it, compared to the risk of users having issues with the up button input.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;tl-dr&quot;&gt;TL;DR&lt;&#x2F;h3&gt;
&lt;p&gt;Due to its location on the board, the up input gets more DC&#x2F;DC conversion noise than other d-pad inputs. C62 is probably there to reduce noise so there&#x27;s less risk of spurious up button presses.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>8 years of Game Boy tweets</title>
        <published>2022-12-26T00:00:00+00:00</published>
        <updated>2022-12-26T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Joonas Javanainen
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://gekkio.fi/blog/2022/8-years-of-game-boy-tweets/"/>
        <id>https://gekkio.fi/blog/2022/8-years-of-game-boy-tweets/</id>
        
        <content type="html" xml:base="https://gekkio.fi/blog/2022/8-years-of-game-boy-tweets/">&lt;p&gt;Thanks to the &quot;great&quot; effort of Elon Musk, Twitter is in flames and I&#x27;ve suddenly realized all my data there is potentially at risk. During the last 8 years, I&#x27;ve occasionally tweeted about my Game Boy research and projects, so here&#x27;s an archive of my Game Boy tweets with some extra commentary.&lt;&#x2F;p&gt;
&lt;p&gt;Quick links to each year:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;#2015&quot;&gt;2015: Research begins&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;#2016&quot;&gt;2016: First custom hardware to support research&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;#2017&quot;&gt;2017: Hardware tests using GB-BENCH-G1, more discoveries, birth of gb-ctr&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;#2018&quot;&gt;2018: Reverse engineering expanded to decap photo tracing, more custom hardware work&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;#2019&quot;&gt;2019: Discovery that GB uses &quot;SM83 CPU core&quot;, being busy with too many GB projects&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;#2020&quot;&gt;2020: SM83 CPU decap photo tracing, various GB schematics, work on better decapping microscope&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;#2021&quot;&gt;2021: SM83 CPU work burnout, focus on better microscope and random GB projects&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;#2022&quot;&gt;2022: More schematics, SM83 CPU core fully reverse engineered&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;style&gt;
  .tweet {
    display: flex;
  }
  .tweet &gt; * {
    flex: 0 1 auto;
    width: 50%;
    overflow-x: scroll;
  }
  @media only screen and (max-width: 600px) {
    .tweet {
      flex-direction: column;
    }
    .tweet &gt; * {
      width: auto;
    }
  }
&lt;&#x2F;style&gt;
&lt;h2 id=&quot;2015&quot;&gt;2015: Research begins&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;2015-01-13&quot;&gt;2015-01-13&lt;&#x2F;h3&gt;
&lt;div class=&quot;tweet&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;gekkio&#x2F;status&#x2F;555049610872647680&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;2015-01-13.png&quot; alt=&quot;Screenshot of the original tweet&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Mooneye GB: A Gameboy emulator written in Rust &lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2015&#x2F;mooneye-gb-a-gameboy-emulator-written-in-rust&#x2F;&quot;&gt;link&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;This tweet is the one that started it all: In late 2014 I had started my emulator assuming there was plenty of accurate documentation about the Game Boy. After all, it was a 25 year old game console, so why wouldn&#x27;t we fully understand it at that point? I quickly realized how wrong I was, and started to research the hardware myself without much knowledge about digital electronics. After a couple of months, the first public commit of Mooneye GB appeared on Github.&lt;&#x2F;p&gt;
&lt;p&gt;Looks like I also didn&#x27;t know the correct spelling&#x2F;capitalization of Game Boy at this time. 😅&lt;&#x2F;p&gt;
&lt;h3 id=&quot;2015-02-14&quot;&gt;2015-02-14&lt;&#x2F;h3&gt;
&lt;div class=&quot;tweet&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;gekkio&#x2F;status&#x2F;566611487780003840&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;2015-02-14.png&quot; alt=&quot;Screenshot of the original tweet&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Mooneye GB: Gameboy cartridge types &lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2015&#x2F;mooneye-gb-gameboy-cartridge-types&#x2F;&quot;&gt;link&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;&#x2F;div&gt;
&lt;h3 id=&quot;2015-05-01&quot;&gt;2015-05-01&lt;&#x2F;h3&gt;
&lt;div class=&quot;tweet&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;gekkio&#x2F;status&#x2F;571798737988788225&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;2015-05-01.png&quot; alt=&quot;Screenshot of the original tweet&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Mooneye GB: Cartridge analysis - Tetris (no MBC) &lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2015&#x2F;mooneye-gb-cartridge-analysis-tetris&#x2F;&quot;&gt;link&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;&#x2F;div&gt;
&lt;h3 id=&quot;2015-05-17&quot;&gt;2015-05-17&lt;&#x2F;h3&gt;
&lt;div class=&quot;tweet&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;gekkio&#x2F;status&#x2F;599961326539145217&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;2015-05-17.png&quot; alt=&quot;Screenshot of the original tweet&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Mooneye GB: Cartridge analysis - Wizards &amp;amp; Warriors X: Fortress of Fear (MBC1) &lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2015&#x2F;mooneye-gb-cartridge-analysis-fortress-of-fear&#x2F;&quot;&gt;link&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;&#x2F;div&gt;
&lt;h3 id=&quot;2015-05-18&quot;&gt;2015-05-18&lt;&#x2F;h3&gt;
&lt;div class=&quot;tweet&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;gekkio&#x2F;status&#x2F;600382619809878017&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;2015-05-18.png&quot; alt=&quot;Screenshot of the original tweet&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Mooneye GB: Cartridge analysis - three games with DMG-BEAN-02 boards &lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2015&#x2F;mooneye-gb-cartridge-analysis-dmg-bean-02&#x2F;&quot;&gt;link&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;&#x2F;div&gt;
&lt;h3 id=&quot;2015-09-13&quot;&gt;2015-09-13&lt;&#x2F;h3&gt;
&lt;div class=&quot;tweet&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;gekkio&#x2F;status&#x2F;643077561082347520&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;2015-09-13.png&quot; alt=&quot;Screenshot of the original tweet&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Dumping the Super Game Boy 2 boot ROM &lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2015&#x2F;dumping-the-super-game-boy-2-boot-rom&#x2F;&quot;&gt;link&lt;&#x2F;a&gt;&lt;br&gt;
&lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;643077561082347520-COyrojhUYAA-Xmq.jpg&quot;&gt;Attached photo&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;This boot ROM dump was pretty exciting for me, because it proved I could perform the dump with fairly primitive tools...at this point I didn&#x27;t know dumping would be even easier on non-SGB devices using a simpler method.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;2015-09-27&quot;&gt;2015-09-27&lt;&#x2F;h3&gt;
&lt;div class=&quot;tweet&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;gekkio&#x2F;status&#x2F;648117181251764224&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;2015-09-27.png&quot; alt=&quot;Screenshot of the original tweet&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Mooneye GB 0.1.0 released &lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2015&#x2F;mooneye-gb-0-1-0-released&#x2F;&quot;&gt;link&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;Initial (and at the time of writing, the only) release of Mooneye GB 😅 . I was of course planning to release more versions, but at this point I didn&#x27;t realize research would take all my time and my focus would shift away from actual emulator development.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;2016&quot;&gt;2016: First custom hardware to support research&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;2016-03-19&quot;&gt;2016-03-19&lt;&#x2F;h3&gt;
&lt;div class=&quot;tweet&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;gekkio&#x2F;status&#x2F;711150351190196224&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;2016-03-19.png&quot; alt=&quot;Screenshot of the original tweet&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Game Boy cartridge PCB photos &lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2016&#x2F;game-boy-cartridge-pcb-photos&#x2F;&quot;&gt;link&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;&#x2F;div&gt;
&lt;h3 id=&quot;2016-08-05&quot;&gt;2016-08-05&lt;&#x2F;h3&gt;
&lt;div class=&quot;tweet&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;gekkio&#x2F;status&#x2F;761667041317314560&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;2016-08-05.png&quot; alt=&quot;Screenshot of the original tweet&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;My rapid Game Boy development cartridge works! &amp;lt;1 s save-compile-flash-reboot-observe cycle on real hardware&lt;br&gt;
&lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;761667041317314560-CpH71AOWIAAIvqG.jpg&quot;&gt;Attached photo 1&lt;&#x2F;a&gt;&lt;br&gt;
&lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;761667041317314560-CpH71AQWAAA7TFj.jpg&quot;&gt;Attached photo 2&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;GB-LIVE32 v1.0 was very exciting for me! The initial design had some issues but the approach of using a small static RAM chip as the &quot;cartridge ROM&quot; worked, and it made it very quick to update the &quot;ROM&quot; contents leading to quick feedback from real hardware.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;2016-08-06&quot;&gt;2016-08-06&lt;&#x2F;h3&gt;
&lt;div class=&quot;tweet&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;gekkio&#x2F;status&#x2F;761927876266582016&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;2016-08-06.png&quot; alt=&quot;Screenshot of the original tweet&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Here&#x27;s a (low-quality gif) video of the rapid development cart &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;gfycat.com&#x2F;EquatorialCavernousFish&quot;&gt;https:&#x2F;&#x2F;gfycat.com&#x2F;EquatorialCavernousFish&lt;&#x2F;a&gt; No touching of cables or power switches&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;&#x2F;div&gt;
&lt;h3 id=&quot;2016-10-11&quot;&gt;2016-10-11&lt;&#x2F;h3&gt;
&lt;div class=&quot;tweet&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;gekkio&#x2F;status&#x2F;785594988323188736&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;2016-10-11.png&quot; alt=&quot;Screenshot of the original tweet&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Game Boy test ROM do&#x27;s and don&#x27;ts &lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2016&#x2F;game-boy-test-rom-dos-and-donts&#x2F;&quot;&gt;link&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;&#x2F;div&gt;
&lt;h3 id=&quot;2016-10-17&quot;&gt;2016-10-17&lt;&#x2F;h3&gt;
&lt;div class=&quot;tweet&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;gekkio&#x2F;status&#x2F;788100518166032384&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;2016-10-17.png&quot; alt=&quot;Screenshot of the original tweet&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Finally found a Game Boy with the elusive DMG-CPU C. Just one more CGB CPU version and I have all the GB CPUs for research and testing&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;&lt;em&gt;Narrator&#x27;s voice&lt;&#x2F;em&gt;: Unfortunately he didn&#x27;t realize he&#x27;d discover even more GB CPU versions later...&lt;&#x2F;p&gt;
&lt;h3 id=&quot;2016-10-19&quot;&gt;2016-10-19&lt;&#x2F;h3&gt;
&lt;div class=&quot;tweet&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;gekkio&#x2F;status&#x2F;788767892745715712&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;2016-10-19.png&quot; alt=&quot;Screenshot of the original tweet&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Got the CPU CGB A as well, so I now have a full set of 18 Game Boy CPUs (I don&#x27;t care about OXY so CPU AGB E is not included)&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;&#x2F;div&gt;
&lt;h3 id=&quot;2016-12-06&quot;&gt;2016-12-06&lt;&#x2F;h3&gt;
&lt;div class=&quot;tweet&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;gekkio&#x2F;status&#x2F;806218871749414912&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;2016-12-06.png&quot; alt=&quot;Screenshot of the original tweet&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Current status: finally working Game Boy hw tools: hw breakpoints, clock edge counts, full signal traces. A treasure trove for research!&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;This was another research breakthrough...GB-BENCH made it possible to gather full signal traces of almost all the SoC chip pins, and do much lower level hardware testing than what was previously possible.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;2016-12-08&quot;&gt;2016-12-08&lt;&#x2F;h3&gt;
&lt;div class=&quot;tweet&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;gekkio&#x2F;status&#x2F;806980625374806016&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;2016-12-08.png&quot; alt=&quot;Screenshot of the original tweet&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Signal trace of running Game Boy Tetris for two seconds...16 million samples, 300 MB Value Change Dump. This is the &quot;light&quot; version :)&lt;br&gt;
&lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;806980625374806016-CzL3r5GWEAAvpxS.jpg&quot;&gt;Attached screenshot&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;&#x2F;div&gt;
&lt;h3 id=&quot;2016-12-09&quot;&gt;2016-12-09&lt;&#x2F;h3&gt;
&lt;div class=&quot;tweet&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;gekkio&#x2F;status&#x2F;806989678041825280&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;2016-12-09.png&quot; alt=&quot;Screenshot of the original tweet&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Let&#x27;s zoom in until we can see the single byte read from $0040 when the CPU reads the first instruction of the vblank routine&lt;br&gt;
&lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;806989678041825280-CzMAhU_WEAELTc5.mp4&quot;&gt;Attached video&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;&#x2F;div&gt;
&lt;h2 id=&quot;2017&quot;&gt;2017: Hardware tests using GB-BENCH, more discoveries, birth of gb-ctr&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;2017-06-10&quot;&gt;2017-06-10&lt;&#x2F;h3&gt;
&lt;div class=&quot;tweet&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;gekkio&#x2F;status&#x2F;873554988945076226&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;2017-06-10.png&quot; alt=&quot;Screenshot of the original tweet&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Current status: my new hardware setup can trace all 73 digital signals of Game Boy CPU chips. Full tracing@30 kHz, run+trigger@3 MHz&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;&#x2F;div&gt;
&lt;h3 id=&quot;2017-06-18&quot;&gt;2017-06-18&lt;&#x2F;h3&gt;
&lt;div class=&quot;tweet&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;gekkio&#x2F;status&#x2F;876445350357282816&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;2017-06-18.png&quot; alt=&quot;Screenshot of the original tweet&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Brace yourselves...more GB test ROMs are coming. VRAM&#x2F;OAM accessibility timing for read and write can differ! And it makes sense from hw POV&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;tweet&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;gekkio&#x2F;status&#x2F;876479425717698561&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;2017-06-18-2.png&quot; alt=&quot;Screenshot of the original tweet&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Like taking candy from a baby&lt;br&gt;
&lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;876479425717698561-DCnhDR-WsAARHSj.jpg&quot;&gt;Attached screenshot&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;In retrospect I was sometimes a bit too proud of finding problems with existing emulators...at some point I realized this and stopped announcing these kind of things and instead just released test ROMs, or preferably released documentation first and tests later.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;2017-06-30&quot;&gt;2017-06-30&lt;&#x2F;h3&gt;
&lt;div class=&quot;tweet&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;gekkio&#x2F;status&#x2F;880696333375610881&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;2017-06-30.png&quot; alt=&quot;Screenshot of the original tweet&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;HW is blocking my research progress ATM...Who knew a system with ~200 loose wires and 5 boards could have noise issues? :P ;) Time for KiCad&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;&#x2F;div&gt;
&lt;h3 id=&quot;2017-07-06&quot;&gt;2017-07-06&lt;&#x2F;h3&gt;
&lt;div class=&quot;tweet&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;gekkio&#x2F;status&#x2F;883032145249406976&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;2017-07-06.png&quot; alt=&quot;Screenshot of the original tweet&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Hmm...using a slow slew rate for the GB clock has fixed my HW issues. I hate magic like this but I&#x27;ll use this as long as things work :P&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;&#x2F;div&gt;
&lt;h3 id=&quot;2017-07-12&quot;&gt;2017-07-12&lt;&#x2F;h3&gt;
&lt;div class=&quot;tweet&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;gekkio&#x2F;status&#x2F;884881227261640704&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;2017-07-12.png&quot; alt=&quot;Screenshot of the original tweet&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Joined the Rigol DS1000Z owner club. Here&#x27;s the clock signal from my CPLD to the Game Boy CPU (divided to 1MHz because of noise issues)&lt;br&gt;
&lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;884881227261640704-DEe06diXgAEjphy.jpg&quot;&gt;Attached picture&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;&#x2F;div&gt;
&lt;h3 id=&quot;2017-07-19&quot;&gt;2017-07-19&lt;&#x2F;h3&gt;
&lt;div class=&quot;tweet&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;gekkio&#x2F;status&#x2F;887777372124196868&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;2017-07-19.png&quot; alt=&quot;Screenshot of the original tweet&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Time to start doing preliminary routing of this monster&lt;br&gt;
&lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;887777372124196868-DFIEhHdXcAEpcLJ.jpg&quot;&gt;Attached screenshot&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;This monster would turn out to be GB-BENCH-G1, the first fully integrated GB-BENCH where everything was on a single board. The previous version (not released as open source) consisted of multiple PCBs and a lot of wiring was required. It worked, but was quite unreliable at times.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;2017-08-21&quot;&gt;2017-08-21&lt;&#x2F;h3&gt;
&lt;div class=&quot;tweet&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;gekkio&#x2F;status&#x2F;899567037923696640&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;2017-08-21.png&quot; alt=&quot;Screenshot of the original tweet&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Very happy with my first 4-layer board :) (manufactured by Elecrow) Soldering took almost 4 hours (hot air + drag soldering)&lt;br&gt;
&lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;899567037923696640-DHvkubLXoAE5y4c.jpg&quot;&gt;Attached photo&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;&#x2F;div&gt;
&lt;h3 id=&quot;2017-08-28&quot;&gt;2017-08-28&lt;&#x2F;h3&gt;
&lt;div class=&quot;tweet&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;gekkio&#x2F;status&#x2F;902262192631939073&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;2017-08-28.png&quot; alt=&quot;Screenshot of the original tweet&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Added Lisp scripting to my GB testbench :) I don&#x27;t even like lisps but it works quite nicely here. Dialect is Ketos: &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;murarth&#x2F;ketos&quot;&gt;https:&#x2F;&#x2F;github.com&#x2F;murarth&#x2F;ketos&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;&#x2F;div&gt;
&lt;h3 id=&quot;2017-09-03&quot;&gt;2017-09-03&lt;&#x2F;h3&gt;
&lt;div class=&quot;tweet&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;gekkio&#x2F;status&#x2F;904428788565594112&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;2017-09-03.png&quot; alt=&quot;Screenshot of the original tweet&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Published sources for my GB breakout board v3.0. This version was designed with KiCad &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;Gekkio&#x2F;gb-hardware&quot;&gt;https:&#x2F;&#x2F;github.com&#x2F;Gekkio&#x2F;gb-hardware&lt;&#x2F;a&gt;&lt;br&gt;
&lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;904428788565594112-DI0s9klXUAQxNww.jpg&quot;&gt;Attached photo&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;&#x2F;div&gt;
&lt;h3 id=&quot;2017-09-10&quot;&gt;2017-09-10&lt;&#x2F;h3&gt;
&lt;div class=&quot;tweet&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;gekkio&#x2F;status&#x2F;906930836804702208&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;2017-09-10.png&quot; alt=&quot;Screenshot of the original tweet&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Problem? My problem is that I still don&#x27;t have all the Game Boys I need ;)&lt;br&gt;
&lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;906930836804702208-DJYQLVZXcAAIqUk.jpg&quot;&gt;Attached photo&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;&#x2F;div&gt;
&lt;h3 id=&quot;2017-09-19&quot;&gt;2017-09-19&lt;&#x2F;h3&gt;
&lt;div class=&quot;tweet&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;gekkio&#x2F;status&#x2F;910225035763306502&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;2017-09-19.png&quot; alt=&quot;Screenshot of the original tweet&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Oh dear, I&#x27;ve done it again...another test that passes on real hardware but fails on emulators 😈&lt;br&gt;
&lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;910225035763306502-DKHEWF7XUAg7IZ9.jpg&quot;&gt;Attached screenshot&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;&#x2F;div&gt;
&lt;h3 id=&quot;2017-12-03&quot;&gt;2017-12-03&lt;&#x2F;h3&gt;
&lt;div class=&quot;tweet&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;gekkio&#x2F;status&#x2F;937260146006339585&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;2017-12-03.png&quot; alt=&quot;Screenshot of the original tweet&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;New GB hardware test: ei_sequence &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;Gekkio&#x2F;mooneye-gb&#x2F;commit&#x2F;b61f9c6e8b3d809957846cd932760aa0398e0a3b&quot;&gt;https:&#x2F;&#x2F;github.com&#x2F;Gekkio&#x2F;mooneye-gb&#x2F;commit&#x2F;b61f9c6e8b3d809957846cd932760aa0398e0a3b&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;tweet&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;gekkio&#x2F;status&#x2F;937318109052010497&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;2017-12-03_2.png&quot; alt=&quot;Screenshot of the original tweet&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Another new GB hardware test: mbc1&#x2F;bits_ram_en &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;Gekkio&#x2F;mooneye-gb&#x2F;commit&#x2F;7e34ea3bde5b1192ee2d6d51b2704764785d60dc&quot;&gt;https:&#x2F;&#x2F;github.com&#x2F;Gekkio&#x2F;mooneye-gb&#x2F;commit&#x2F;7e34ea3bde5b1192ee2d6d51b2704764785d60dc&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;&#x2F;div&gt;
&lt;h3 id=&quot;2017-12-04&quot;&gt;2017-12-04&lt;&#x2F;h3&gt;
&lt;div class=&quot;tweet&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;gekkio&#x2F;status&#x2F;937652553222782976&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;2017-12-04.png&quot; alt=&quot;Screenshot of the original tweet&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;It&#x27;s been on Github for quite some time already, but I think it&#x27;s time to start actively telling people about the existence of my WIP reference documentation of all GB things: &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;Gekkio&#x2F;gb-ctr&quot;&gt;https:&#x2F;&#x2F;github.com&#x2F;Gekkio&#x2F;gb-ctr&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;tweet&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;gekkio&#x2F;status&#x2F;937654134613962752&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;2017-12-04_2.png&quot; alt=&quot;Screenshot of the original tweet&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Instead of being copy-paste of existing GB docs, my focus is on accurate and deep technical documentation, especially stuff that can&#x27;t be found elsewhere. For example, &lt;em&gt;complete&lt;&#x2F;em&gt; documentation of MBC1 that covers edge cases as well.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;At this point I was naively hoping more people would read gb-ctr...lack of readers and lack of feedback are the main reasons why I ended up updating gb-ctr rarely.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;2017-12-05&quot;&gt;2017-12-05&lt;&#x2F;h3&gt;
&lt;div class=&quot;tweet&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;gekkio&#x2F;status&#x2F;938103486113304576&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;2017-12-05.png&quot; alt=&quot;Screenshot of the original tweet&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Looks like either A) GB uses simple pipelining or B) my M-cycle boundaries are wrong. An M-cycle is 4 T-cycles, but I have evidence that opcode decoding happens 3.5 T-cycles after PC is put on the address bus. That would leave only one T-clock edge for the actual instruction&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;&lt;em&gt;Narrator&#x27;s voice&lt;&#x2F;em&gt;: Option A would later turn out to be true!&lt;&#x2F;p&gt;
&lt;h3 id=&quot;2017-12-06&quot;&gt;2017-12-06&lt;&#x2F;h3&gt;
&lt;div class=&quot;tweet&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;gekkio&#x2F;status&#x2F;938412089554718720&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;2017-12-06.png&quot; alt=&quot;Screenshot of the original tweet&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Published sources for my 2015 Game Boy bus conflict test ROM called &quot;naughtyemu.gb&quot;: &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;Gekkio&#x2F;naughtyemu&quot;&gt;https:&#x2F;&#x2F;github.com&#x2F;Gekkio&#x2F;naughtyemu&lt;&#x2F;a&gt;. Basic explanation is in this forum post: &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;forums.nesdev.org&#x2F;viewtopic.php?f=20&amp;amp;t=16796&amp;amp;p=209596#p209596&quot;&gt;https:&#x2F;&#x2F;forums.nesdev.org&#x2F;viewtopic.php?f=20&amp;amp;t=16796&amp;amp;p=209596#p209596&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;&#x2F;div&gt;
&lt;h3 id=&quot;2017-12-11&quot;&gt;2017-12-11&lt;&#x2F;h3&gt;
&lt;div class=&quot;tweet&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;gekkio&#x2F;status&#x2F;940235979117547521&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;2017-12-11.png&quot; alt=&quot;Screenshot of the original tweet&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Going to talk at @Disobey_fi about Game Boy reverse engineering. The original GB launched in 1989 (almost 30 years ago) and a lot of RE work has been done, but we still keep finding behaviour and edge cases not covered by existing docs or emulators. &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;disobey.fi&quot;&gt;disobey.fi&#x2F;#program&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;This was going to be a big public talk in front of a fairly large audience...very intimidating to an introvert like me, but I couldn&#x27;t pass the opportunity, even as an inexperienced public speaker!&lt;&#x2F;p&gt;
&lt;h2 id=&quot;2018&quot;&gt;2018: Reverse engineering expanded to decap photo tracing, more custom hardware work&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;2018-01-05&quot;&gt;2018-01-05&lt;&#x2F;h3&gt;
&lt;div class=&quot;tweet&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;gekkio&#x2F;status&#x2F;949236843933036544&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;2018-01-05.png&quot; alt=&quot;Screenshot of the original tweet&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Finished tracing all the signal pins in this DMG-CPU B decap photo.
Yes, there will eventually be an interactive viewer with toggling&#x2F;coloring of signals ;)&lt;&#x2F;p&gt;
&lt;p&gt;(Decap photo CC BY 4.0 digshadow &#x2F; &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;siliconpr0n.org&quot;&gt;https:&#x2F;&#x2F;siliconpr0n.org&lt;&#x2F;a&gt;)&lt;br&gt;
&lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;949236843933036544-DSxdKR0WAAAFix5.jpg&quot;&gt;Attached picture 1&lt;&#x2F;a&gt;&lt;br&gt;
&lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;949236843933036544-DSxdLAUWsAUBcxf.jpg&quot;&gt;Attached picture 2&lt;&#x2F;a&gt;&lt;br&gt;
&lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;949236843933036544-DSxdMEYW4AAfjNt.jpg&quot;&gt;Attached picture 3&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;&lt;em&gt;Narrator&#x27;s voice&lt;&#x2F;em&gt;: Sadly an interactive viewer was never created...&lt;&#x2F;p&gt;
&lt;div class=&quot;tweet&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;gekkio&#x2F;status&#x2F;949372419327881219&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;2018-01-05_2.png&quot; alt=&quot;Screenshot of the original tweet&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Here&#x27;s a version of the earlier picture with pin labels added&lt;br&gt;
&lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;949372419327881219-DSzYoeoX0AAAhGP.jpg&quot;&gt;Attached picture&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;&#x2F;div&gt;
&lt;h3 id=&quot;2018-01-08&quot;&gt;2018-01-08&lt;&#x2F;h3&gt;
&lt;div class=&quot;tweet&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;gekkio&#x2F;status&#x2F;950444423242043393&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;2018-01-08.png&quot; alt=&quot;Screenshot of the original tweet&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Looks like info about &quot;corrupted STOP&quot; on GB is nonsense. The next byte is simply skipped instead of some values being &quot;corrupted&quot;. Yes, it still makes sense to put a NOP there, but the justification in current docs for this seems wrong&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;tweet&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;gekkio&#x2F;status&#x2F;950478077871652864&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;2018-01-08_2.png&quot; alt=&quot;Screenshot of the original tweet&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;&quot;A wild STOPHALT bug appeared!&quot;...so it turns out that executing STOP &lt;em&gt;while already pressing a button&lt;&#x2F;em&gt; doesn&#x27;t do STOP but a different version of HALT. And yes, the HALT bugs are also present here but in a weird way&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;&#x2F;div&gt;
&lt;h3 id=&quot;2018-01-30&quot;&gt;2018-01-30&lt;&#x2F;h3&gt;
&lt;div class=&quot;tweet&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;gekkio&#x2F;status&#x2F;958397607839260675&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;2018-01-30.png&quot; alt=&quot;Screenshot of the original tweet&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Ugh... GB bench v1 has 3 separate power rails and it wasn&#x27;t easy to design the board and route it. In v2 I&#x27;ve got 6 power rails so far in the design from just following datasheet recommendations :O challenge accepted :)&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;&#x2F;div&gt;
&lt;h3 id=&quot;2018-02-04&quot;&gt;2018-02-04&lt;&#x2F;h3&gt;
&lt;div class=&quot;tweet&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;gekkio&#x2F;status&#x2F;960103260781727744&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;2018-02-04.png&quot; alt=&quot;Screenshot of the original tweet&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Here&#x27;s my GB talk from Disobey :D the fine details section has some errors, but I&#x27;ll write an errata blog post soon to point out the errors&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;tweet&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;gekkio&#x2F;status&#x2F;960235856849227777&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;2018-02-04_2.png&quot; alt=&quot;Screenshot of the original tweet&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;The full video of my GB talk from Disobey 2018 is now available :) the last 10 minutes were missing in the earlier upload. Remember that the &quot;fine details&quot; part has some errors, so wait for my errata blog post before fixing your emulator ;) https:&#x2F;&#x2F;twitter.com&#x2F;Disobey_fi&#x2F;status&#x2F;960221371619045377&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;Despite being nervous at first, the talk went well and I&#x27;m very happy about the whole thing!&lt;&#x2F;p&gt;
&lt;h3 id=&quot;2018-02-06&quot;&gt;2018-02-06&lt;&#x2F;h3&gt;
&lt;div class=&quot;tweet&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;gekkio&#x2F;status&#x2F;960635715041275904&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;2018-02-06.png&quot; alt=&quot;Screenshot of the original tweet&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Errata blog post for my GB talk is now available. The last section (=&quot;fine details&quot;) had some wrong clock edges, although the main points are still valid and remain the same &lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2018&#x2F;errata-for-reverse-engineering-fine-details-of-game-boy-hardware&#x2F;&quot;&gt;link&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;&#x2F;div&gt;
&lt;h3 id=&quot;2018-02-27&quot;&gt;2018-02-27&lt;&#x2F;h3&gt;
&lt;div class=&quot;tweet&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;gekkio&#x2F;status&#x2F;968543728100093952&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;2018-02-27.png&quot; alt=&quot;Screenshot of the original tweet&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;THE TIME FOR HIDE AND SEEK IS OVER, MR CHIP. I FOUND YOU!&lt;&#x2F;p&gt;
&lt;p&gt;Soooo, once again I can say that I&#x27;ve got all the known GB CPU versions :)&lt;br&gt;
&lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;968543728100093952-DXD0yyTX4AMJ3J-.jpg&quot;&gt;Attached photo&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;&#x2F;div&gt;
&lt;h3 id=&quot;2018-03-15&quot;&gt;2018-03-15&lt;&#x2F;h3&gt;
&lt;div class=&quot;tweet&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;gekkio&#x2F;status&#x2F;974183960845672449&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;2018-03-15.png&quot; alt=&quot;Screenshot of the original tweet&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Discovered a new hw technique yesterday: I can now read&#x2F;write GB hw registers freely in my test bench, so I can read stuff like PPU registers at &lt;em&gt;one clock edge accuracy&lt;&#x2F;em&gt;. This is &lt;em&gt;huge&lt;&#x2F;em&gt;!!&lt;&#x2F;p&gt;
&lt;p&gt;Screenshot 1: scanline LY + modes&lt;br&gt;
Screenshot 2: mode 1 &#x2F; line 144&lt;br&gt;
&lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;974183960845672449-DYT9f6VXUAAK5Lm.jpg&quot;&gt;Attached screenshot 1&lt;&#x2F;a&gt;&lt;br&gt;
&lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;974183960845672449-DYT9obaXcAAxmbh.jpg&quot;&gt;Attached screenshot 2&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;&#x2F;div&gt;
&lt;h3 id=&quot;2018-03-18&quot;&gt;2018-03-18&lt;&#x2F;h3&gt;
&lt;div class=&quot;tweet&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;gekkio&#x2F;status&#x2F;975409992688861184&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;2018-03-18.png&quot; alt=&quot;Screenshot of the original tweet&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;New GB test ROM: acceptance&#x2F;ppu&#x2F;stat_lyc_onoff&lt;&#x2F;p&gt;
&lt;p&gt;You know the drill...it passes on all real hardware versions and fails in every emulator I tested (including mine) :)&lt;br&gt;
&lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;975409992688861184-DYlS9QGW4AA2qLQ.jpg&quot;&gt;Attached screenshot&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;&#x2F;div&gt;
&lt;h3 id=&quot;2018-03-24&quot;&gt;2018-03-24&lt;&#x2F;h3&gt;
&lt;div class=&quot;tweet&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;gekkio&#x2F;status&#x2F;977530749934063621&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;2018-03-24.png&quot; alt=&quot;Screenshot of the original tweet&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;GB research is on hold for this weekend because I&#x27;m looking for secret lost GB hardware documents in the Alps. Haven&#x27;t found any yet but I&#x27;ll keep looking! 😜 next week: PPU interrupt and OAM DMA conflict tests + docs in gbctr&lt;br&gt;
&lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;977530749934063621-DZDjA73WkAAQyMp.jpg&quot;&gt;Attached photo&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;&#x2F;div&gt;
&lt;h3 id=&quot;2018-03-27&quot;&gt;2018-03-27&lt;&#x2F;h3&gt;
&lt;div class=&quot;tweet&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;gekkio&#x2F;status&#x2F;978585482786492417&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;2018-03-27.png&quot; alt=&quot;Screenshot of the original tweet&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;I&#x27;ll be doing an updated version of my recent talk about GB reverse engineering at the next Reaktor Meetup.&lt;&#x2F;p&gt;
&lt;p&gt;There&#x27;s still a couple of spots left, so enroll now if you are in Helsinki next Tuesday and are interested in three hardware-focused talks:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.meetup.com&#x2F;reaktor-events-helsinki&#x2F;events&#x2F;248991039&quot;&gt;https:&#x2F;&#x2F;www.meetup.com&#x2F;reaktor-events-helsinki&#x2F;events&#x2F;248991039&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;&#x2F;div&gt;
&lt;h3 id=&quot;2018-04-01&quot;&gt;2018-04-01&lt;&#x2F;h3&gt;
&lt;div class=&quot;tweet&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;gekkio&#x2F;status&#x2F;980442995110678528&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;2018-04-01.png&quot; alt=&quot;Screenshot of the original tweet&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Now I&#x27;m pretty sure the glop top DMG CPU is the B version.&lt;&#x2F;p&gt;
&lt;p&gt;Left: DMG-CPU B (© Digshadow&#x2F;siliconpr0n.org)&lt;br&gt;
Right: glop top decap by me&lt;&#x2F;p&gt;
&lt;p&gt;The die took a lot of damage, but the &quot;L20A&quot; part of &quot;CESL20A&quot; is IMHO clearly visible.&lt;br&gt;
&lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;980442995110678528-DZs6IUFXUAAKy3C.jpg&quot;&gt;Attached photo&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;This was an important discovery: the glop top chips were not inherently unique, but were simply repackaged B and C revisions. The revision is even indicated on the board, which is obvious in hindsight 😄&lt;&#x2F;p&gt;
&lt;h3 id=&quot;2018-04-26&quot;&gt;2018-04-26&lt;&#x2F;h3&gt;
&lt;div class=&quot;tweet&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;gekkio&#x2F;status&#x2F;989590390473977863&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;2018-04-26.png&quot; alt=&quot;Screenshot of the original tweet&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;I&#x27;ll be speaking about Game Boy reverse engineering at @ReaktorBP on May 24th. My talk includes live hw demos and some newly discovered hw details :D&lt;&#x2F;p&gt;
&lt;p&gt;There&#x27;s a lot of exciting talks at the event, so check out the program and get your tickets here: &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;reaktorbreakpoint.com&quot;&gt;reaktorbreakpoint.com&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;&#x2F;div&gt;
&lt;h3 id=&quot;2018-05-03&quot;&gt;2018-05-03&lt;&#x2F;h3&gt;
&lt;div class=&quot;tweet&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;gekkio&#x2F;status&#x2F;992096966925467648&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;2018-05-03.png&quot; alt=&quot;Screenshot of the original tweet&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Finally received my shipment of 50 Game Boy link ports. Gonna use several for, uh, a project ;) Now I just need to create a couple of new KiCad symbols+footprints, design a PCB and write some VHDL...&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;&lt;em&gt;Narrator&#x27;s voice&lt;&#x2F;em&gt;: Unfortunately these link ports would remain in storage, because he ended up focusing on too many other projects...&lt;&#x2F;p&gt;
&lt;h3 id=&quot;2018-05-05&quot;&gt;2018-05-05&lt;&#x2F;h3&gt;
&lt;div class=&quot;tweet&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;gekkio&#x2F;status&#x2F;992706504800264192&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;2018-05-05.png&quot; alt=&quot;Screenshot of the original tweet&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Another day, another board :) This is just an update to my old GB-LIVE32 board, but it&#x27;s an important stepping stone to something bigger...&lt;br&gt;
&lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;992706504800264192-DcbMDJ0X4AEV8qI.jpg&quot;&gt;Attached screenshot&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;&#x2F;div&gt;
&lt;h3 id=&quot;2018-05-11&quot;&gt;2018-05-11&lt;&#x2F;h3&gt;
&lt;div class=&quot;tweet&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;gekkio&#x2F;status&#x2F;994892528049643520&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;2018-05-11.png&quot; alt=&quot;Screenshot of the original tweet&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Finally found hard evidence that the GB CPU has a 2-stage pipeline (or &quot;prefetch&quot;). An important find for understanding true timing of hardware traces and some behaviours. I&#x27;ll present some details and consequences in my Reaktor Breakpoint presentation in two weeks :)&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;&#x2F;div&gt;
&lt;h3 id=&quot;2018-05-14&quot;&gt;2018-05-14&lt;&#x2F;h3&gt;
&lt;div class=&quot;tweet&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;gekkio&#x2F;status&#x2F;996102947233828864&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;2018-05-14.png&quot; alt=&quot;Screenshot of the original tweet&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;It&#x27;s going to require a lot of effort to have Game Boy Pocket and Game Boy Color CPU support in my test bench system, but this is how it starts: desoldering CPU chips for upcoming test bench boards. (also in picture: various support chips)&lt;br&gt;
&lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;996102947233828864-DdLdXBeW0AECQca.jpg&quot;&gt;Attached photo&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;&#x2F;div&gt;
&lt;h3 id=&quot;2018-05-27&quot;&gt;2018-05-27&lt;&#x2F;h3&gt;
&lt;div class=&quot;tweet&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;gekkio&#x2F;status&#x2F;1000836098371842049&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;2018-05-27.png&quot; alt=&quot;Screenshot of the original tweet&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Spent a lot of time today desoldering and measuring all components from this poor corroded Game Boy Pocket board. Loose 0603s are a pain to probe, but I only managed to lose one component. Goodbye C35, you will be missed.&lt;&#x2F;p&gt;
&lt;p&gt;Same unit before desoldering: &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;gbhwdb.gekkio.fi&#x2F;consoles&#x2F;mgb&#x2F;MH12129596.html&quot;&gt;https:&#x2F;&#x2F;gbhwdb.gekkio.fi&#x2F;consoles&#x2F;mgb&#x2F;MH12129596.html&lt;&#x2F;a&gt;&lt;br&gt;
&lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;1000836098371842049-DeOtTuBX0AIK7fE.jpg&quot;&gt;Attached photo&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;&#x2F;div&gt;
&lt;h3 id=&quot;2018-06-06&quot;&gt;2018-06-06&lt;&#x2F;h3&gt;
&lt;div class=&quot;tweet&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;gekkio&#x2F;status&#x2F;1004453394508079104&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;2018-06-06.png&quot; alt=&quot;Screenshot of the original tweet&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;10+ hours of USB debugging has finally paid off: my GB-LIVE32 rapid development cart v2.0 is now much more reliable than its predecessor. This time I&#x27;ve polished things a lot, so everything will be open sourced (KiCad design, PIC18F firmware, Rust lib+CLI app).&lt;br&gt;
&lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;1004453394508079104-DfCH-9sX0AEVhnR.jpg&quot;&gt;Attached photo&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;GB-LIVE32 v2.0 would turn out to be a true workhorse for hardware testing! I even gave some to other people so they could run tests much easier and faster.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;2018-07-08&quot;&gt;2018-07-08&lt;&#x2F;h3&gt;
&lt;div class=&quot;tweet&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;gekkio&#x2F;status&#x2F;1015721966483988481&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;2018-07-08.png&quot; alt=&quot;Screenshot of the original tweet&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Getting ready to start routing this little guy...if this works out, it means I can create a working MAX 10 FPGA design with some high speed IO included. And that is the road to GB-BENCH v2 with new stuff like audio capture and Game Boy Color CPU support&lt;br&gt;
&lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;1015721966483988481-DhiEtMhWAAEUB0j.jpg&quot;&gt;Attached photo&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;This turned out to be too ambitious...in 2022 GB-BENCH v2 still hasn&#x27;t been completed, and I&#x27;ve iterated various different designs without actually building anything.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;2018-07-11&quot;&gt;2018-07-11&lt;&#x2F;h3&gt;
&lt;div class=&quot;tweet&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;gekkio&#x2F;status&#x2F;1017149896674234368&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;2018-07-11.png&quot; alt=&quot;Screenshot of the original tweet&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Here&#x27;s a (very) rough demo video of my GB-LIVE32 v2.0 rapid development cartridge:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=GCIcgmga9Mo&quot;&gt;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=GCIcgmga9Mo&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Now fully open source!&lt;&#x2F;p&gt;
&lt;p&gt;KiCad&#x2F;gerbers: &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;gekkio&#x2F;gb-hardware&quot;&gt;https:&#x2F;&#x2F;github.com&#x2F;gekkio&#x2F;gb-hardware&lt;&#x2F;a&gt;&lt;br&gt;
Firmware&#x2F;software: &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;gekkio&#x2F;gb-live32&quot;&gt;https:&#x2F;&#x2F;github.com&#x2F;gekkio&#x2F;gb-live32&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;&#x2F;div&gt;
&lt;h3 id=&quot;2018-08-27&quot;&gt;2018-08-27&lt;&#x2F;h3&gt;
&lt;div class=&quot;tweet&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;gekkio&#x2F;status&#x2F;1034157871372484608&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;2018-08-27.png&quot; alt=&quot;Screenshot of the original tweet&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;I&#x27;ve got two valid excuses for doing slightly less GB things recently:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;The parcel with new GB-BENCH control PCBs still hasn&#x27;t arrived and tracking says it&#x27;s been stuck at the Helsinki airport for two weeks now 😢&lt;br&gt;&lt;&#x2F;li&gt;
&lt;li&gt;I started playing Danganronpa and am completely hooked 😇&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;&#x2F;blockquote&gt;
&lt;&#x2F;div&gt;
&lt;h3 id=&quot;2018-09-11&quot;&gt;2018-09-11&lt;&#x2F;h3&gt;
&lt;div class=&quot;tweet&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;gekkio&#x2F;status&#x2F;1039588344706093057&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;2018-09-11.png&quot; alt=&quot;Screenshot of the original tweet&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Ok looks like I&#x27;ve managed to confirm my first finding of temperature-dependent behaviour on Game Boy hardware :D now emulators just need to add support for temperature sensors and&#x2F;or a temperature slider in the UI.......&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;&#x2F;div&gt;
&lt;h3 id=&quot;2018-11-04&quot;&gt;2018-11-04&lt;&#x2F;h3&gt;
&lt;div class=&quot;tweet&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;gekkio&#x2F;status&#x2F;1058851052475334656&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;2018-11-04.png&quot; alt=&quot;Screenshot of the original tweet&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;TIL:
a Game Boy and 2 games in hand luggage is normal.&lt;br&gt;
3 Game Boys and 6 games in hand luggage gets you &quot;Sir, you&#x27;ve got a lot of electronics in your bag&quot; and a bag search at the airport security :D&lt;&#x2F;p&gt;
&lt;p&gt;(not complaining...I&#x27;m sure it looks a bit unusual :P)&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;&#x2F;div&gt;
&lt;h3 id=&quot;2018-11-13&quot;&gt;2018-11-13&lt;&#x2F;h3&gt;
&lt;div class=&quot;tweet&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;gekkio&#x2F;status&#x2F;1062412348349136897&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;2018-11-13.png&quot; alt=&quot;Screenshot of the original tweet&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Current status: experimenting with different approaches to writing a parser that can identify chips on GB cartridge boards based on the chip labels&lt;br&gt;
&lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;1062412348349136897-Dr5xmWsW4AExhpl.mp4&quot;&gt;Attached video&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;Spoiler: regex won 😄. My GB hardware database site would eventually switch to regexes to parse chip information from labels.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;2019&quot;&gt;2019: Discovery that GB uses &quot;SM83 CPU core&quot;, being busy with too many GB projects&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;2019-01-06&quot;&gt;2019-01-06&lt;&#x2F;h3&gt;
&lt;div class=&quot;tweet&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;gekkio&#x2F;status&#x2F;1081706992882847745&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;2019-01-06.png&quot; alt=&quot;Screenshot of the original tweet&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;I&#x27;m entirely convinced that the original GB CPU chip uses a Sharp SM83 CPU core. And there are public datasheets of some chips that use the same core....😍&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;This was a huge discovery and perhaps even a historical moment in GB research...I think I was searching some datasheet archive for Sharp, STOP, and HALT, and randomly stumbled upon some SM83xx SoC datasheet. After staring at it for a while, I realized the instruction set looked suspiciously familiar, and started to investigate more. Eventually I realized it was a perfect match for the GB CPU core.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;2019-01-13&quot;&gt;2019-01-13&lt;&#x2F;h3&gt;
&lt;div class=&quot;tweet&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;gekkio&#x2F;status&#x2F;1084391449087655936&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;2019-01-13.png&quot; alt=&quot;Screenshot of the original tweet&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;One more thing about SM83 CPU core: it&#x27;s possible GB is not exactly SM83 but just &lt;em&gt;SM83-compatible&lt;&#x2F;em&gt;...there might be an older ancestor (a bit like 6502 vs 65C02). In 1986 data book there&#x27;s SM-812&#x2F;SM-813 with the same reported instruction count as SM8311&#x2F;SM8320...but no details&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;I can&#x27;t emphasize this enough...SM83 is still the best guess, but personally I still suspect GB SoCs might have the unnamed predecessor.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;2019-01-14&quot;&gt;2019-01-14&lt;&#x2F;h3&gt;
&lt;div class=&quot;tweet&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;gekkio&#x2F;status&#x2F;1084572996868677632&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;2019-01-14.png&quot; alt=&quot;Screenshot of the original tweet&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Not looking forward to soldering this beast 😓 the schematic isn&#x27;t even ready yet, so there will be more capacitors&lt;br&gt;
&lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;1084572996868677632-Dw0sZazXQAAePgm.jpg&quot;&gt;Attached screenshot&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;Yet another GB-BENCH v2 attempt that would turn out to be a waste of time...&lt;&#x2F;p&gt;
&lt;h3 id=&quot;2019-06-01&quot;&gt;2019-06-01&lt;&#x2F;h3&gt;
&lt;div class=&quot;tweet&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;gekkio&#x2F;status&#x2F;1134568927210684416&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;2019-06-01.png&quot; alt=&quot;Screenshot of the original tweet&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Internal primary 8-bit data bus of the Game Boy DMG-CPU B chip visualized&lt;br&gt;
&lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;1134568927210684416-D77L5qqXYAIntX-.jpg&quot;&gt;Attached screenshot&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;&#x2F;div&gt;
&lt;h3 id=&quot;2019-06-07&quot;&gt;2019-06-07&lt;&#x2F;h3&gt;
&lt;div class=&quot;tweet&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;gekkio&#x2F;status&#x2F;1137068368983396353&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;2019-06-07.png&quot; alt=&quot;Screenshot of the original tweet&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Time to write some VHDL for this monster :D&lt;br&gt;
&lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;1137068368983396353-D8etpe6WkAEM0tH.jpg&quot;&gt;Attached photo&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;I still use GB-CARTPP Pro (known as just GB-CARTPP at the time), because it&#x27;s crazy fast and reliable. I&#x27;m very happy about this little device, even though v1.0 had some design issues that needed some ugly bodges.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;2019-06-19&quot;&gt;2019-06-19&lt;&#x2F;h3&gt;
&lt;div class=&quot;tweet&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;gekkio&#x2F;status&#x2F;1141447103740284930&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;2019-06-19.png&quot; alt=&quot;Screenshot of the original tweet&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Experimenting with Ghidra and Game Boy ROM reverse engineering...there&#x27;s no official support for GB but my custom language support files work already surprisingly well&lt;br&gt;
&lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;1141447103740284930-D9c69Y8WwAc3cYf.jpg&quot;&gt;Attached screenshot&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;This would become GhidraBoy a bit later, and would become my primary tool for GB ROM reverse engineering.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;2019-06-23&quot;&gt;2019-06-23&lt;&#x2F;h3&gt;
&lt;div class=&quot;tweet&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;gekkio&#x2F;status&#x2F;1142792866814746624&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;2019-06-23.png&quot; alt=&quot;Screenshot of the original tweet&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;I shall call this &quot;art piece&quot; The Twins&lt;&#x2F;p&gt;
&lt;p&gt;Got some soldering to do during the holidays 😁&lt;br&gt;
&lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;1142792866814746624-D9wC8pDWsAYWyqh.jpg&quot;&gt;Attached screenshot&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;Sadly both twins didn&#x27;t survive very long...I got the PCBs and soldered everything, but both designs had too many issues and I ended up scrapping them.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;2019-07-15&quot;&gt;2019-07-15&lt;&#x2F;h3&gt;
&lt;div class=&quot;tweet&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;gekkio&#x2F;status&#x2F;1150803080314798080&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;2019-07-15.png&quot; alt=&quot;Screenshot of the original tweet&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;My FPGA-based GB cartridge dumper can now dump a Tetris cart ROM in ~40 ms. It&#x27;s overkill, but I&#x27;m practicing using FT232H USB chip&#x27;s FT245 sync mode (~40 MB&#x2F;s half-duplex, but limited here to ~15 MB&#x2F;s at the moment, because pipelining in my VHDL code isn&#x27;t yet perfect)&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;&#x2F;div&gt;
&lt;h3 id=&quot;2019-07-17&quot;&gt;2019-07-17&lt;&#x2F;h3&gt;
&lt;div class=&quot;tweet&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;gekkio&#x2F;status&#x2F;1151475649359601664&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;2019-07-17.png&quot; alt=&quot;Screenshot of the original tweet&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Time required to dump Densha De Go 2 ROM (largest Game Boy game, 8MB ROM):&lt;&#x2F;p&gt;
&lt;p&gt;GB01 (a polished-looking cartridge reader you can buy): 5 min 30 s&lt;br&gt;
GB-CARTPP (my not-so-beautiful device): 10 s&lt;&#x2F;p&gt;
&lt;p&gt;And I still have two performance tricks left that I can do with the FPGA 😊 target is &amp;lt;5 s&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;&#x2F;div&gt;
&lt;h3 id=&quot;2019-07-18&quot;&gt;2019-07-18&lt;&#x2F;h3&gt;
&lt;div class=&quot;tweet&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;gekkio&#x2F;status&#x2F;1151883272496013314&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;2019-07-18.png&quot; alt=&quot;Screenshot of the original tweet&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Improved the hardware timings, so now I can dump Densha De Go 2 in &lt;strong&gt;2.1s&lt;&#x2F;strong&gt;. However, this is with &quot;overdriven&quot; timings so it&#x27;s not a good idea in normal use. Perfectly compatible timings give 5.1s, which is still a good result&lt;br&gt;
&lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;1151883272496013314-D_xNxBHXsAAhKdN.jpg&quot;&gt;Attached screenshot&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;&#x2F;div&gt;
&lt;h3 id=&quot;2019-07-26&quot;&gt;2019-07-26&lt;&#x2F;h3&gt;
&lt;div class=&quot;tweet&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;gekkio&#x2F;status&#x2F;1154832167836553216&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;2019-07-26.png&quot; alt=&quot;Screenshot of the original tweet&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Published my Game Boy extension for the Ghidra reverse engineering framework:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;Gekkio&#x2F;GhidraBoy&quot;&gt;https:&#x2F;&#x2F;github.com&#x2F;Gekkio&#x2F;GhidraBoy&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;It can be used for both cartridge ROM and boot ROM disassembly &#x2F; reverse engineering&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;&#x2F;div&gt;
&lt;h3 id=&quot;2019-08-03&quot;&gt;2019-08-03&lt;&#x2F;h3&gt;
&lt;div class=&quot;tweet&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;gekkio&#x2F;status&#x2F;1157408978382610438&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;2019-08-03.png&quot; alt=&quot;Screenshot of the original tweet&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Prebuilt GhidraBoy release zips are now available for both Ghidra 9.0.4 and 9.1-DEV (latest Ghidra git master) &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;Gekkio&#x2F;GhidraBoy&quot;&gt;https:&#x2F;&#x2F;github.com&#x2F;Gekkio&#x2F;GhidraBoy&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;&#x2F;div&gt;
&lt;h3 id=&quot;2019-10-21&quot;&gt;2019-10-21&lt;&#x2F;h3&gt;
&lt;div class=&quot;tweet&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;gekkio&#x2F;status&#x2F;1186380074280468480&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;2019-10-21.png&quot; alt=&quot;Screenshot of the original tweet&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;I&#x27;ve been working tirelessly to go through and fully understand the recently released amazing Game Boy schematics by @Furrtek. Still got plenty of work, but here&#x27;s simulation results of some bus accesses that match real hardware. Automatic VHDL generation from KiCad helps 😀&lt;br&gt;
&lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;1186380074280468480-EHbeY3JWkAEEs4G.png&quot;&gt;Attached screenshot&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;Furrtek&#x27;s release was groundbreaking! I was slightly annoyed about how much time I had personally spent on DMG-CPU B SoC tracing that was now unnecessary, but having full schematics meant a chance to make great progress with improving low-level understanding of the SoC. The only problem was that Furrtek&#x27;s schematics didn&#x27;t include the CPU core, and there were quite a lot of mistakes. I couldn&#x27;t get even the first page to simulate correctly, so I ended up redoing a lot of the work and making my own schematics.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;2019-11-04&quot;&gt;2019-11-04&lt;&#x2F;h3&gt;
&lt;div class=&quot;tweet&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;gekkio&#x2F;status&#x2F;1191416558972817409&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;2019-11-04.png&quot; alt=&quot;Screenshot of the original tweet&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;I&#x27;ve released GhidraBoy 20191104, which has been tested to work with the recently released Ghidra 9.1 release&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;Gekkio&#x2F;GhidraBoy&#x2F;releases&#x2F;tag&#x2F;20191104_ghidra_9.1&quot;&gt;https:&#x2F;&#x2F;github.com&#x2F;Gekkio&#x2F;GhidraBoy&#x2F;releases&#x2F;tag&#x2F;20191104_ghidra_9.1&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;&#x2F;div&gt;
&lt;h3 id=&quot;2019-11-21&quot;&gt;2019-11-21&lt;&#x2F;h3&gt;
&lt;div class=&quot;tweet&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;gekkio&#x2F;status&#x2F;1197273506423197697&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;2019-11-21.png&quot; alt=&quot;Screenshot of the original tweet&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;It&#x27;s just Tetris, right?&lt;&#x2F;p&gt;
&lt;p&gt;...this image was generated by a low-level 11kloc VHDL simulation model consisting of 1200+ DMG-CPU B standard cells almost entirely generated from KiCad schematics.&lt;&#x2F;p&gt;
&lt;p&gt;Simulating ~20ms took ~40s of real time and generated a 250MB signal dump file.&lt;br&gt;
&lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;1197273506423197697-EJ2R5_-W4AAYyqQ.png&quot;&gt;Attached screenshot&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;Just one month later after acknowledging Furrtek&#x27;s amazing work, I had my own WIP schematics simulating Tetris correctly. Unfortunately my approach was getting more and more complicated and error-prone, and this would end up being the best I could do for a while.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;2020&quot;&gt;2020: SM83 CPU decap photo tracing, various GB schematics, work on better decapping microscope&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;2020-02-07&quot;&gt;2020-02-07&lt;&#x2F;h3&gt;
&lt;div class=&quot;tweet&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;gekkio&#x2F;status&#x2F;1225901940904808449&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;2020-02-07.png&quot; alt=&quot;Screenshot of the original tweet&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;SM83 CPU core tracing progress...unfortunately currently available decap photos are not good enough for much more. But I&#x27;m surprised how much one can learn from just looking at how things are connected. For example, the register file has more buses than one might expect.&lt;br&gt;
&lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;1225901940904808449-EQNC7iNX0AAbkAh.jpg&quot;&gt;Attached screenshot&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;After getting frustrated with the inability to run test ROMs on the DMG-CPU B HDL model, I decided to try to reverse engineer the CPU core.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;2020-02-19&quot;&gt;2020-02-19&lt;&#x2F;h3&gt;
&lt;div class=&quot;tweet&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;gekkio&#x2F;status&#x2F;1230202377229209601&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;2020-02-19.png&quot; alt=&quot;Screenshot of the original tweet&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;GhidraBoy has been updated and the latest release is compatible with Ghidra 9.1.2 🎉&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;Gekkio&#x2F;GhidraBoy&#x2F;releases&#x2F;tag&#x2F;20200219_ghidra_9.1.2&quot;&gt;https:&#x2F;&#x2F;github.com&#x2F;Gekkio&#x2F;GhidraBoy&#x2F;releases&#x2F;tag&#x2F;20200219_ghidra_9.1.2&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;&#x2F;div&gt;
&lt;h3 id=&quot;2020-03-15&quot;&gt;2020-03-15&lt;&#x2F;h3&gt;
&lt;div class=&quot;tweet&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;gekkio&#x2F;status&#x2F;1239214486424301570&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;2020-03-15.png&quot; alt=&quot;Screenshot of the original tweet&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Here&#x27;s DMG-AMP IR3R40 (manufactured by Sharp), the amplifier chip from the original Game Boy&lt;br&gt;
&lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;1239214486424301570-ETKSxeBWkAISzFo.jpg&quot;&gt;Attached photo&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;tweet&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;gekkio&#x2F;status&#x2F;1239280360124567554&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;2020-03-15_2.png&quot; alt=&quot;Screenshot of the original tweet&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Here&#x27;s DMG-AMP and F411A under higher magnification. I don&#x27;t have a motorized XY stage so everything was done manually. Luckily Microsoft ICE worked much better than I expected and managed to stitch the photos fairly well.&lt;br&gt;
&lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;1239280360124567554-ETLLJ_SXkAAYh0h.jpg&quot;&gt;Attached photo&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Max resolution photos are here:&lt;br&gt;
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;files&#x2F;decapped-chips&#x2F;AM4515ZT4&#x2F;&quot;&gt;https:&#x2F;&#x2F;gekkio.fi&#x2F;files&#x2F;decapped-chips&#x2F;AM4515ZT4&#x2F;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;&#x2F;div&gt;
&lt;h3 id=&quot;2020-03-28&quot;&gt;2020-03-28&lt;&#x2F;h3&gt;
&lt;div class=&quot;tweet&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;gekkio&#x2F;status&#x2F;1243887873683869696&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;2020-03-28.png&quot; alt=&quot;Screenshot of the original tweet&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Better tools -&amp;gt; better chip decap photos.&lt;br&gt;
This is the same magnified part of the DMG-AMP chip die taken with my old tools and new tools for comparison.&lt;br&gt;
&lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;1243887873683869696-EUMsrQhXkAAgXsH.jpg&quot;&gt;Attached photo 1&lt;&#x2F;a&gt;&lt;br&gt;
&lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;1243887873683869696-EUMsrQoX0AIbXJm.jpg&quot;&gt;Attached photo 2&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;I finally had decent tooling for decapping, although without a motorized stage I was limited to small chips or small areas of large chips...certainly usable for the SM83 CPU core!&lt;&#x2F;p&gt;
&lt;h3 id=&quot;2020-05-07&quot;&gt;2020-05-07&lt;&#x2F;h3&gt;
&lt;div class=&quot;tweet&quot; id=&quot;tweet-1258483113023373318&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;gekkio&#x2F;status&#x2F;1258483113023373318&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;2020-05-07.png&quot; alt=&quot;Screenshot of the original tweet&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;This cell is my reverse engineering mystery of today...behaviour suggests it could be AND gate. But note how In2 only goes to a gnd-side NMOS, so the input side looks almost like Pseudo-NMOS NAND with 2x NMOS in series. But In1 also has the complementary PMOS near vdd-side (?!)&lt;br&gt;
&lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;1258483113023373318-EXcGBd0X0AQ4RIO.png&quot;&gt;Attached photo&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;tweet&quot; id=&quot;tweet-1258498108297752581&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;gekkio&#x2F;status&#x2F;1258498108297752581&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;2020-05-07_2.png&quot; alt=&quot;Screenshot of the original tweet&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Here&#x27;s how I see it at the moment...black rectangles are the transistors. Seems like an AND gate but In2 PMOS is missing. The yellow signal also has one unexplained via that seems to be connected to diffusion area going up towards gnd, but obscured by the green signal metal&lt;br&gt;
&lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;1258498108297752581-EXcUeb4WsAAE_oE.png&quot;&gt;Attached photo&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;&#x2F;div&gt;
&lt;h3 id=&quot;2020-05-09&quot;&gt;2020-05-09&lt;&#x2F;h3&gt;
&lt;div class=&quot;tweet&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;gekkio&#x2F;status&#x2F;1259135507214327808&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;2020-05-09.png&quot; alt=&quot;Screenshot of the original tweet&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Abstract art, or fully traced Game Boy SM83 CPU core instruction decoding 1st stage? You decide...&lt;&#x2F;p&gt;
&lt;p&gt;In: 8-bit instruction register + 3-bit seq counter + &quot;in CB mode&quot; flag + &quot;in interrupt dispatch&quot; flag&lt;br&gt;
Out: 107 control signals, 3 seem to be always low&lt;br&gt;
Uses dynamic domino logic &lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;1259135507214327808-EXlWaWdXgAInMny.jpg&quot;&gt;Attached photo&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;&#x2F;div&gt;
&lt;h3 id=&quot;2020-05-27&quot;&gt;2020-05-27&lt;&#x2F;h3&gt;
&lt;div class=&quot;tweet&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;gekkio&#x2F;status&#x2F;1265706867352797185&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;2020-05-27.png&quot; alt=&quot;Screenshot of the original tweet&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;This is what a fully traced Game Boy Pocket mainboard looks like :D&lt;br&gt;
...&lt;br&gt;
...&lt;br&gt;
...&lt;br&gt;
And here are the schematics!&lt;br&gt;
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;gekkio&#x2F;gb-schematics&quot;&gt;https:&#x2F;&#x2F;github.com&#x2F;gekkio&#x2F;gb-schematics&lt;&#x2F;a&gt;&lt;br&gt;
&lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;1265706867352797185-EZCw3tNXkAcUUgZ.jpg&quot;&gt;Attached photo&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;My first GB schematics release! A lot of work, but I really enjoyed it and ended up reverse engineering much more GB hardware and releasing more schematics.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;2020-06-14&quot;&gt;2020-06-14&lt;&#x2F;h3&gt;
&lt;div class=&quot;tweet&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;gekkio&#x2F;status&#x2F;1272167835876446210&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;2020-06-14.png&quot; alt=&quot;Screenshot of the original tweet&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;GB SM83 CPU core I&#x2F;O cell reverse engineered. One surprise about the CPU core is how much dynamic logic and precharging it uses. Even the main SoC data bus (EXT_DATA) has precharge circuitry and the CPU core only uses a low-side driver (but SoC peripherals are proper push&#x2F;pull)&lt;br&gt;
&lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;1272167835876446210-EaejU6wXQAIIC9m.jpg&quot;&gt;Attached screenshot&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;tweet&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;gekkio&#x2F;status&#x2F;1272215638883393538&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;2020-06-14_2.png&quot; alt=&quot;Screenshot of the original tweet&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Some more info and the Inkscape SVG is now here: &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;Gekkio&#x2F;sm83-research&quot;&gt;https:&#x2F;&#x2F;github.com&#x2F;Gekkio&#x2F;sm83-research&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;I&#x27;ve got a lot more details about SM83 coming soon™, including new info about the register file and the various (and plentiful) 8-bit buses internal to the CPU core.&lt;br&gt;
Also: simulation-tested HDL code&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;Much later in 2022 when finishing my full RE work on the SM83 CPU core, I was very surprised that I got all the important details right at this point! The locations of individual transistors were sometimes guesses and were not perfectly correct, but I didn&#x27;t miss any transistors or misunderstand the behaviour.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;2020-06-19&quot;&gt;2020-06-19&lt;&#x2F;h3&gt;
&lt;div class=&quot;tweet&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;gekkio&#x2F;status&#x2F;1273971586937360384&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;2020-06-19.png&quot; alt=&quot;Screenshot of the original tweet&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Ummm...yeah sure, Microsoft Image Composite Editor, that&#x27;s exactly what the chip die looks like. Good job! Well stitched!&lt;br&gt;
&lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;1273971586937360384-Ea4NdXIXsAIbjio.jpg&quot;&gt;Attached screenshot&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;tweet&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;gekkio&#x2F;status&#x2F;1273972804216664064&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;2020-06-19_2.png&quot; alt=&quot;Screenshot of the original tweet&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;It managed to stitch this 10x objective photo correctly, but at 40x there seems to be too much repetition and not enough information for it to infer the layout correctly :(&lt;br&gt;
&lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;1273972804216664064-Ea4O94lX0AECQfy.jpg&quot;&gt;Attached screenshot&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;&#x2F;div&gt;
&lt;h3 id=&quot;2020-06-20&quot;&gt;2020-06-20&lt;&#x2F;h3&gt;
&lt;div class=&quot;tweet&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;gekkio&#x2F;status&#x2F;1274427461225402368&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;2020-06-20.png&quot; alt=&quot;Screenshot of the original tweet&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Here&#x27;s a &quot;handy&quot; guide to some Game Boy MBC3B memory bank controller chip standard cells&lt;br&gt;
&lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;1274427461225402368-Ea-s3ijWAActLgL.jpg&quot;&gt;Attached screenshot&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;tweet&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;gekkio&#x2F;status&#x2F;1274428892548300804&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;2020-06-20_2.png&quot; alt=&quot;Screenshot of the original tweet&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;And no, there&#x27;s no ARM microcontroller on the chip&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;Sadly I don&#x27;t think many people understood this pun... 😭&lt;&#x2F;p&gt;
&lt;h3 id=&quot;2020-06-29&quot;&gt;2020-06-29&lt;&#x2F;h3&gt;
&lt;div class=&quot;tweet&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;gekkio&#x2F;status&#x2F;1277675285069148160&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;2020-06-29.png&quot; alt=&quot;Screenshot of the original tweet&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;What exactly are you implying, FJWC?? 🤨🧐&lt;br&gt;
...&lt;br&gt;
FJWC=(NOT nSHDN) OR (nWR)&lt;br&gt;
In other words, FJWC=nWR when nSHDN=1, and FJWC=1 when nSHDN=0. Turns out nSHDN isolates pins (like Lattice Power Guard &#x2F; Xilinx DataGATE), so this extra gating is needed to keep nWR safely deasserted&lt;br&gt;
&lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;1277675285069148160-Ebszbo1WkAMGRnB.jpg&quot;&gt;Attached screenshot&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;&#x2F;div&gt;
&lt;h3 id=&quot;2020-07-22&quot;&gt;2020-07-22&lt;&#x2F;h3&gt;
&lt;div class=&quot;tweet&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;gekkio&#x2F;status&#x2F;1285952815362383873&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;2020-07-22.png&quot; alt=&quot;Screenshot of the original tweet&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Aaaaand nope, I don&#x27;t think I&#x27;ll capture a full set of photos of a decapped CPU CGB B chip die, since stitching is a nightmare as usual and I&#x27;ll go mad before getting it to work with a chip this large. People with motorized XY(Z) stages don&#x27;t know how lucky they are&lt;br&gt;
&lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;1285952815362383873-EdiekklWsAETEJ4.jpg&quot;&gt;Attached screenshot 1&lt;&#x2F;a&gt;&lt;br&gt;
&lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;1285952815362383873-EdielU_WsAA15B9.jpg&quot;&gt;Attached screenshot 2&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;&#x2F;div&gt;
&lt;h3 id=&quot;2020-08-06&quot;&gt;2020-08-06&lt;&#x2F;h3&gt;
&lt;div class=&quot;tweet&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;gekkio&#x2F;status&#x2F;1291426842038153216&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;2020-08-06.png&quot; alt=&quot;Screenshot of the original tweet&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Decapped an SGB-CPU 01 chip to capture some Game Boy SM83 CPU core photos with 40x magnification + EDF. Can &lt;em&gt;you&lt;&#x2F;em&gt; tell the difference between left (from &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;siliconpr0n.org&quot;&gt;siliconpr0n.org&lt;&#x2F;a&gt;, 20x I think?) and right (mine, 40x + EDF)? 😎&lt;br&gt;
&lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;1291426842038153216-EewRFf-WoAAeAx-.png&quot;&gt;Attached screenshot&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;tweet&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;gekkio&#x2F;status&#x2F;1291429988323950597&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;2020-08-06_2.png&quot; alt=&quot;Screenshot of the original tweet&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;The previous photos were of an IO cell. Here&#x27;s a piece of the ALU&lt;br&gt;
&lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;1291429988323950597-EewUi5xXoAAs4Nf.png&quot;&gt;Attached screenshot&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;&#x2F;div&gt;
&lt;h3 id=&quot;2020-08-09&quot;&gt;2020-08-09&lt;&#x2F;h3&gt;
&lt;div class=&quot;tweet&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;gekkio&#x2F;status&#x2F;1292206670710480896&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;2020-08-09.png&quot; alt=&quot;Screenshot of the original tweet&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Finally figured out this mystery cell used in the Game Boy SM83 CPU core &lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;#tweet-1258483113023373318&quot;&gt;link to tweet&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;It&#x27;s just an SR latch (with reset signal prioritized) but unusual because S and R have opposite polarities.&lt;&#x2F;p&gt;
&lt;p&gt;Truth table:&lt;br&gt;
nR  S   Q&lt;br&gt;
0    0   0&lt;br&gt;
0    1   0&lt;br&gt;
1    0   held&lt;br&gt;
1    1   1&lt;br&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;tweet&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;gekkio&#x2F;status&#x2F;1292211341000876032&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;2020-08-09_2.png&quot; alt=&quot;Screenshot of the original tweet&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;I almost had it figured out here: &lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;#tweet-1258498108297752581&quot;&gt;link to tweet&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Yellow is inverted and output to green, but the previously missing part is another inverter (2 transistors)! Green is also inverted and output to yellow, creating a cross-coupled inverter loop that makes the cell a latch&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;tweet&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;gekkio&#x2F;status&#x2F;1292212531340214280&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;2020-08-09_3.png&quot; alt=&quot;Screenshot of the original tweet&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Here&#x27;s a higher resolution photo of the damn thing...&lt;&#x2F;p&gt;
&lt;p&gt;&quot;bastard_gate.jpg&quot;&lt;br&gt;
&lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;1292212531340214280-Ee7b9nIXkAcIxDi.jpg&quot;&gt;Attached photo&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;&#x2F;div&gt;
&lt;h3 id=&quot;2020-08-22&quot;&gt;2020-08-22&lt;&#x2F;h3&gt;
&lt;div class=&quot;tweet&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;gekkio&#x2F;status&#x2F;1297197932429619200&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;2020-08-22.png&quot; alt=&quot;Screenshot of the original tweet&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Here&#x27;s something I started writing 4 years ago...I wrote it because most reviews of Game Boy mods&#x2F;parts focus on ease of installation and not on the technical side&lt;&#x2F;p&gt;
&lt;p&gt;&quot;HHL Bivert Module V2 - technical review&quot; a.k.a &quot;how hard can it be to invert two signals&quot;&lt;br&gt;
&lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2020&#x2F;hhl-bivert-v2-technical-review&#x2F;&quot;&gt;link&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;&#x2F;div&gt;
&lt;h3 id=&quot;2020-10-16&quot;&gt;2020-10-16&lt;&#x2F;h3&gt;
&lt;div class=&quot;tweet&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;gekkio&#x2F;status&#x2F;1317205752608624641&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;2020-10-16.png&quot; alt=&quot;Screenshot of the original tweet&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;After another evening of lovely reverse engineering work, I proudly present the first publicly available schematics of Game Boy Advance SP console.&lt;&#x2F;p&gt;
&lt;p&gt;(this is for AGS-001 mainboard revision AGS-CPU-11...other versions have some differences)&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;Gekkio&#x2F;gb-schematics#game-boy-advance-sp-ags-001-mainboard-ags-cpu-11&quot;&gt;https:&#x2F;&#x2F;github.com&#x2F;Gekkio&#x2F;gb-schematics#game-boy-advance-sp-ags-001-mainboard-ags-cpu-11&lt;&#x2F;a&gt;&lt;br&gt;
&lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;1317205752608624641-EkencqXXIAEDrM_.jpg&quot;&gt;Attached screenshot&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;&#x2F;div&gt;
&lt;h3 id=&quot;2020-11-13&quot;&gt;2020-11-13&lt;&#x2F;h3&gt;
&lt;div class=&quot;tweet&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;gekkio&#x2F;status&#x2F;1327011528084774912&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;2020-11-13.png&quot; alt=&quot;Screenshot of the original tweet&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Earlier this year I reverse-engineered stage 1 of the Game Boy SM83 CPU core decoding logic. I think it&#x27;s time to start working on stage 2 😎&lt;br&gt;
Not really looking forward to stage 3, which is the largest one.&lt;br&gt;
&lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;1327011528084774912-Emp7CqDXEAI3ust.jpg&quot;&gt;Attached screenshot&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;tweet&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;gekkio&#x2F;status&#x2F;1327012903858434048&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;2020-11-13_2.png&quot; alt=&quot;Screenshot of the original tweet&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;The goal is to generate a lot of control signals depending on the opcode in the IR register and a couple of system state signals.&lt;br&gt;
Instead of simple and clean grid-like structure, all stages use pass transistors and surprisingly complicated diffusion layer to do both AND&#x2F;OR logic.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;tweet&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;gekkio&#x2F;status&#x2F;1327014498725748738&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;2020-11-13_3.png&quot; alt=&quot;Screenshot of the original tweet&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;For example, this blue column is a stage 1 output I call OP_NOP_STOP_S0XX. Purple &quot;taps&quot; are pass transistor gate inputs, horizontal lines are the inputs. If all pass transistors conduct, an electrical path is formed between top and bottom ends of the column (ground and output).&lt;br&gt;
&lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;1327014498725748738-Emp_YkmXcAAk-lA.jpg&quot;&gt;Attached screenshot&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;tweet&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;gekkio&#x2F;status&#x2F;1327015222532517888&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;2020-11-13_4.png&quot; alt=&quot;Screenshot of the original tweet&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Dynamic logic is used, so in one clock phase, the ground in the top end is always disconnected and the output is precharged to 1. In the other clock phase, the ground is available and the column may pull its output low.&lt;&#x2F;p&gt;
&lt;p&gt;Here&#x27;s a VHDL implementation of this column.&lt;br&gt;
&lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;1327015222532517888-EmqAwUyWEAEvVlg.jpg&quot;&gt;Attached screenshot&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;tweet&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;gekkio&#x2F;status&#x2F;1327016906382045187&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;2020-11-13_5.png&quot; alt=&quot;Screenshot of the original tweet&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Doesn&#x27;t look that bad, right? Well, that was a simple case 😏&lt;br&gt;
The blue &quot;column&quot; can be much more complex, and multiple outputs share some parts.&lt;&#x2F;p&gt;
&lt;p&gt;Here&#x27;s 3 outputs based on a complicated shared diffusion layer structure with branching:&lt;br&gt;
OP_LD_X_N&lt;br&gt;
OP_LD_X_N_SX00&lt;br&gt;
OP_LD_R_N_SX01&lt;br&gt;
&lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;1327016906382045187-EmqCFxOXcAEY71m.png&quot;&gt;Attached screenshot&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;tweet&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;gekkio&#x2F;status&#x2F;1327018976937906176&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;2020-11-13_6.png&quot; alt=&quot;Screenshot of the original tweet&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Remember, all that matters is creating a path to ground! So the three parallel mini columns basically form a NOR3.&lt;br&gt;
Here&#x27;s the VHDL 😅&lt;br&gt;
Note that this code intentionally matches the original structure, and the same logic could be written in a simpler way without branching&#x2F;sharing. &lt;br&gt;
&lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;1327018976937906176-EmqDWL0XcAYX4E8.jpg&quot;&gt;Attached screenshot&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;tweet&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;gekkio&#x2F;status&#x2F;1327356800669261824&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;2020-11-13_7.png&quot; alt=&quot;Screenshot of the original tweet&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Ghidra 9.2 has finally been released and I&#x27;ve also released a new version of GhidraBoy freshly built for Ghidra 9.2 🎉&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;Gekkio&#x2F;GhidraBoy&#x2F;releases&#x2F;tag&#x2F;20201113_ghidra_9.2&quot;&gt;https:&#x2F;&#x2F;github.com&#x2F;Gekkio&#x2F;GhidraBoy&#x2F;releases&#x2F;tag&#x2F;20201113_ghidra_9.2&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;&#x2F;div&gt;
&lt;h3 id=&quot;2020-11-17&quot;&gt;2020-11-17&lt;&#x2F;h3&gt;
&lt;div class=&quot;tweet&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;gekkio&#x2F;status&#x2F;1328787565143592966&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;2020-11-17.png&quot; alt=&quot;Screenshot of the original tweet&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Took me more than 30 minutes to spot one error in the traced blue areas in Game Boy SM83 CPU core stage 1 decoder. Can &lt;em&gt;you&lt;&#x2F;em&gt; spot the mistake?😏&lt;&#x2F;p&gt;
&lt;p&gt;One challenge with stage 2 RE is that even small mistakes in stage 1 propagate and lead to great chaos and confusion in stage 2&lt;br&gt;
&lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;1328787565143592966-EnDKXZNUwAATnNe.jpg&quot;&gt;Attached screenshot&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;&#x2F;div&gt;
&lt;h3 id=&quot;2020-11-19&quot;&gt;2020-11-19&lt;&#x2F;h3&gt;
&lt;div class=&quot;tweet&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;gekkio&#x2F;status&#x2F;1329188003483430913&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;2020-11-19.png&quot; alt=&quot;Screenshot of the original tweet&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;All done with Game Boy SM83 CPU core decoder stage 2! Simple simulation gave sensible control signals, although there&#x27;s definitely some mistakes left here (and in stage 1 too!). More CPU core areas are needed for thorough testing...&lt;&#x2F;p&gt;
&lt;p&gt;Photo shows stage 2 before vs after tracing&lt;br&gt;
&lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;1329188003483430913-EnI4XsbXEAUSR1Q.jpg&quot;&gt;Attached screenhot&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;tweet&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;gekkio&#x2F;status&#x2F;1329195506027929616&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;2020-11-19_2.png&quot; alt=&quot;Screenshot of the original tweet&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;I&#x27;ve published the Inkscape SVG here:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;Gekkio&#x2F;sm83-research&quot;&gt;https:&#x2F;&#x2F;github.com&#x2F;Gekkio&#x2F;sm83-research&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Note that the signal names are still based on &quot;educated guesswork&quot; and might be incorrect and&#x2F;or misleading.&lt;&#x2F;p&gt;
&lt;p&gt;...and yes, I know stage 1 is still missing from the repository 😅&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;&#x2F;div&gt;
&lt;h3 id=&quot;2020-12-10&quot;&gt;2020-12-10&lt;&#x2F;h3&gt;
&lt;div class=&quot;tweet&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;gekkio&#x2F;status&#x2F;1337118677284622339&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;2020-12-10.png&quot; alt=&quot;Screenshot of the original tweet&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Game Boy SM83 CPU core RE status: since finishing decoder stage 2 and tracing its outputs, I&#x27;ve noticed how we&#x27;ve got a &quot;everything is connected to everything&quot; -type of situation...&lt;br&gt;
So now I&#x27;m doing the ALU, the register file, and decoder stage 3 at the same time. 😅&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;tweet&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;gekkio&#x2F;status&#x2F;1337121255158321153&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;2020-12-10_2.png&quot; alt=&quot;Screenshot of the original tweet&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Back when I started this RE work, I imagined a decoder connected like this:&lt;br&gt;
opcode + CPU state -&amp;gt; stage1 -&amp;gt; stage2 -&amp;gt; stage3 -&amp;gt; various places like ALU and reg file&lt;&#x2F;p&gt;
&lt;p&gt;Reality:&lt;br&gt;
stage1 -&amp;gt; stage2 -&amp;gt; stage3 -&amp;gt; places&lt;br&gt;
stage1 -&amp;gt; places&lt;br&gt;
stage2 -&amp;gt; places&lt;br&gt;
ALU has extra local decoding logic&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;&#x2F;div&gt;
&lt;h2 id=&quot;2021&quot;&gt;2021 SM83 CPU work burnout, focus on better microscope and random GB projects&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;2021-03-09&quot;&gt;2021-03-09&lt;&#x2F;h3&gt;
&lt;div class=&quot;tweet&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;gekkio&#x2F;status&#x2F;1369342559089266690&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;2021-03-09.png&quot; alt=&quot;Screenshot of the original tweet&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;It&#x27;s interesting to watch the value of my stock market investments go down, and the value of the 60+ Game Boys I bought 4-7 years ago to go up 😅&lt;br&gt;
Maybe one day I&#x27;ll actually sell some on Ebay for profit&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;&#x2F;div&gt;
&lt;h3 id=&quot;2021-04-05&quot;&gt;2021-04-05&lt;&#x2F;h3&gt;
&lt;div class=&quot;tweet&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;gekkio&#x2F;status&#x2F;1379158254400471042&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;2021-04-05.png&quot; alt=&quot;Screenshot of the original tweet&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Writing a blog post about Game Boy flash cartridge power consumption. Pretty interesting measurement results!&lt;&#x2F;p&gt;
&lt;p&gt;It makes me wonder how optimized existing designs are, and what are the practical limitations in designing low power carts...&lt;&#x2F;p&gt;
&lt;p&gt;Blog post will be available soon™&lt;br&gt;
&lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;1379158254400471042-EyO_upCWQAMa88A.jpg&quot;&gt;Attached screenshot&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;&#x2F;div&gt;
&lt;h3 id=&quot;2021-04-16&quot;&gt;2021-04-16&lt;&#x2F;h3&gt;
&lt;div class=&quot;tweet&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;gekkio&#x2F;status&#x2F;1383148933678006272&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;2021-04-16.png&quot; alt=&quot;Screenshot of the original tweet&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;TIL: A 30-year old Game Boy cartridge can still have a battery in a very healthy condition. I just measured 3.257V battery voltage on a cart from 1991.&lt;&#x2F;p&gt;
&lt;p&gt;I initially didn&#x27;t believe it, but datasheets confirm 10-80 times difference in data retention current specs between RAM chips.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;tweet&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;gekkio&#x2F;status&#x2F;1383150970050338820&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;2021-04-16_2.png&quot; alt=&quot;Screenshot of the original tweet&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;gbhwdb.gekkio.fi&#x2F;cartridges&#x2F;DMG-GWJ-0&#x2F;gekkio-1.html&quot;&gt;https:&#x2F;&#x2F;gbhwdb.gekkio.fi&#x2F;cartridges&#x2F;DMG-GWJ-0&#x2F;gekkio-1.html&lt;&#x2F;a&gt;
The cart in question uses Sharp LH5168 with 0.6 uA MAX spec. Carts sometimes use chips which have 10uA or 50 uA MAX specs. Conditions may vary slightly, but even if the difference in reality is something like 1:5, it can mean 50 vs 10 year data retention.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;&#x2F;div&gt;
&lt;h3 id=&quot;2021-04-17&quot;&gt;2021-04-17&lt;&#x2F;h3&gt;
&lt;div class=&quot;tweet&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;gekkio&#x2F;status&#x2F;1383410961759932418&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;2021-04-17.png&quot; alt=&quot;Screenshot of the original tweet&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;New blog post: Power Consumption of Game Boy Flash Cartridges&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2021&#x2F;power-consumption-of-game-boy-flash-cartridges&#x2F;&quot;&gt;link&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Short summary:&lt;br&gt;
Everdrive GB X5 beats other SD-card flash cartridges. Genuine carts beat Everdrive GB X5. My designs usually beat genuine carts&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;&#x2F;div&gt;
&lt;h3 id=&quot;2021-05-08&quot;&gt;2021-05-08&lt;&#x2F;h3&gt;
&lt;div class=&quot;tweet&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;gekkio&#x2F;status&#x2F;1391098901059579905&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;2021-05-08.png&quot; alt=&quot;Screenshot of the original tweet&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;It&#x27;s been a while since I&#x27;ve done any work on this, but I finally have a rough but working MVP of this &quot;magic&quot; tool useful for chip reverse engineering.&lt;&#x2F;p&gt;
&lt;p&gt;Current focus is Game Boy DMG-CPU B simulation and testing, but I plan to use the same approach on other chips as well.&lt;br&gt;
&lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;1391098901059579905-E04rPrcWUAA97kk.png&quot;&gt;Attached screenshot&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;tweet&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;gekkio&#x2F;status&#x2F;1391101118474764288&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;2021-05-08_2.png&quot; alt=&quot;Screenshot of the original tweet&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;I already have a tool that generates a flat VHDL model from a KiCad netlist. But this is better, because I can isolate and test any part of the hierarchy separately.&lt;&#x2F;p&gt;
&lt;p&gt;For example, I can write a VHDL testbench just for the &quot;System clocks&quot; module which is defined in clock_gen.vhd&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;tweet&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;gekkio&#x2F;status&#x2F;1391102658090520577&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;2021-05-08_3.png&quot; alt=&quot;Screenshot of the original tweet&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;And it turns out testing is crucial when dealing with a model of a large chip.&lt;br&gt;
Maybe some cell has been misidentified or signal polarity is wrong in some cell model. A simple mistake can ruin the entire model, so I find testing and building trust piece by piece very important&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;&#x2F;div&gt;
&lt;h3 id=&quot;2021-05-29&quot;&gt;2021-05-29&lt;&#x2F;h3&gt;
&lt;div class=&quot;tweet&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;gekkio&#x2F;status&#x2F;1398736569029345283&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;2021-05-29.png&quot; alt=&quot;Screenshot of the original tweet&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;GhidraBoy for Ghidra 9.2.4 has been released 🎉&lt;&#x2F;p&gt;
&lt;p&gt;Developing new GhidraBoy features is not on top of my list at the moment, but I &lt;em&gt;do&lt;&#x2F;em&gt; try to keep up with Ghidra releases so you should never find yourself unable to upgrade Ghidra just because GhidraBoy is holding you back.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;&#x2F;div&gt;
&lt;h3 id=&quot;2021-06-30&quot;&gt;2021-06-30&lt;&#x2F;h3&gt;
&lt;div class=&quot;tweet&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;gekkio&#x2F;status&#x2F;1410264175599931396&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;2021-06-30.png&quot; alt=&quot;Screenshot of the original tweet&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;GhidraBoy for Ghidra 10.0 has been released 🎉&lt;&#x2F;p&gt;
&lt;p&gt;As usual, a prebuilt binary package is available on the releases page:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;Gekkio&#x2F;GhidraBoy&#x2F;releases&#x2F;tag&#x2F;20210630_ghidra_10.0&quot;&gt;https:&#x2F;&#x2F;github.com&#x2F;Gekkio&#x2F;GhidraBoy&#x2F;releases&#x2F;tag&#x2F;20210630_ghidra_10.0&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;&#x2F;div&gt;
&lt;h3 id=&quot;2021-07-07&quot;&gt;2021-07-07&lt;&#x2F;h3&gt;
&lt;div class=&quot;tweet&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;gekkio&#x2F;status&#x2F;1412814144349347847&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;2021-07-07.png&quot; alt=&quot;Screenshot of the original tweet&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Fairly quick&#x27;n&#x27;dirty decap of Nintendo Game Boy Advance SP SoC chip (CPU AGB B) with 4x microscope magnification.&lt;&#x2F;p&gt;
&lt;p&gt;Way too modern for detailed RE work, but some info can be collected from this photo.&lt;br&gt;
Chip die labeled as &quot;CBUG04&quot;. Package is QFP-156, die has 156 pads so no unused&lt;br&gt;
&lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;1412814144349347847-E5tRVpvWEAMOzQm.jpg&quot;&gt;Attached photo&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;tweet&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;gekkio&#x2F;status&#x2F;1412814463292542982&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;2021-07-07_2.png&quot; alt=&quot;Screenshot of the original tweet&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Max quality stitched photo is available here:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;files&#x2F;decapped-chips&#x2F;Frankenscope&#x2F;CPU-AGB-B&#x2F;&quot;&gt;https:&#x2F;&#x2F;gekkio.fi&#x2F;files&#x2F;decapped-chips&#x2F;Frankenscope&#x2F;CPU-AGB-B&#x2F;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;&#x2F;div&gt;
&lt;h3 id=&quot;2021-09-01&quot;&gt;2021-09-01&lt;&#x2F;h3&gt;
&lt;div class=&quot;tweet&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;gekkio&#x2F;status&#x2F;1433112545280335876&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;2021-09-01.png&quot; alt=&quot;Screenshot of the original tweet&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;I&#x27;ve released the schematic for the original Game Boy LCD board (version DMG-LCD-06)&lt;&#x2F;p&gt;
&lt;p&gt;Not terribly exciting, but these are (hopefully) accurate unlike the older schematics you can find online.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;Gekkio&#x2F;gb-schematics#original-game-boy-lcd-board-dmg-lcd-06&quot;&gt;https:&#x2F;&#x2F;github.com&#x2F;Gekkio&#x2F;gb-schematics#original-game-boy-lcd-board-dmg-lcd-06&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;&#x2F;div&gt;
&lt;h3 id=&quot;2021-10-31&quot;&gt;2021-10-31&lt;&#x2F;h3&gt;
&lt;div class=&quot;tweet&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;gekkio&#x2F;status&#x2F;1454910696454598656&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;2021-10-31.png&quot; alt=&quot;Screenshot of the original tweet&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;The test ROMs bundled with Mooneye GB emulator are now known as &quot;Mooneye Test Suite&quot;, and are now in a separate repository:
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;Gekkio&#x2F;mooneye-test-suite&#x2F;&quot;&gt;https:&#x2F;&#x2F;github.com&#x2F;Gekkio&#x2F;mooneye-test-suite&#x2F;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;I&#x27;m still sorting out some practical things and the mooneye-gb repository hasn&#x27;t been cleaned up yet, but this is a first step.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;&#x2F;div&gt;
&lt;h3 id=&quot;2021-12-11&quot;&gt;2021-12-11&lt;&#x2F;h3&gt;
&lt;div class=&quot;tweet&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;gekkio&#x2F;status&#x2F;1469607573053661189&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;2021-12-11.png&quot; alt=&quot;Screenshot of the original tweet&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;GhidraBoy for Ghidra 10.1 has been released, so you no longer need to fear Java logging library CVEs when doing Game Boy ROM reverse engineering :)&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;Gekkio&#x2F;GhidraBoy&#x2F;releases&#x2F;tag&#x2F;20211211_ghidra_10.1&quot;&gt;https:&#x2F;&#x2F;github.com&#x2F;Gekkio&#x2F;GhidraBoy&#x2F;releases&#x2F;tag&#x2F;20211211_ghidra_10.1&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;&#x2F;div&gt;
&lt;h2 id=&quot;2022&quot;&gt;2022: More schematics, SM83 CPU core fully reverse engineered&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;2022-01-02&quot;&gt;2022-01-02&lt;&#x2F;h3&gt;
&lt;div class=&quot;tweet&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;gekkio&#x2F;status&#x2F;1477635068814401540&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;2022-01-02.png&quot; alt=&quot;Screenshot of the original tweet&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;I&#x27;ve just released schematics for the first two Original Game Boy (DMG) power board revisions (unofficially known as type A &#x2F; B) 🎉&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;Gekkio&#x2F;gb-schematics&#x2F;blob&#x2F;main&#x2F;DC-CONV-DMG-AB&#x2F;schematic&#x2F;DC-CONV-DMG-AB.pdf&quot;&gt;https:&#x2F;&#x2F;github.com&#x2F;Gekkio&#x2F;gb-schematics&#x2F;blob&#x2F;main&#x2F;DC-CONV-DMG-AB&#x2F;schematic&#x2F;DC-CONV-DMG-AB.pdf&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Type C and D will be released later after I clean them a bit.&lt;&#x2F;p&gt;
&lt;p&gt;Other schematics in the repo also got some minor updates 🙂&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;&#x2F;div&gt;
&lt;h3 id=&quot;2022-01-12&quot;&gt;2022-01-12&lt;&#x2F;h3&gt;
&lt;div class=&quot;tweet&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;gekkio&#x2F;status&#x2F;1481381078631956483&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;2022-01-12.png&quot; alt=&quot;Screenshot of the original tweet&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;As promised earlier, I&#x27;ve released the schematics for the remaining original Game Boy (DMG) power boards (type C &#x2F; D) 😃&lt;&#x2F;p&gt;
&lt;p&gt;I&#x27;ve also documented known differences and added visual component references since the boards have no component reference designators&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;Gekkio&#x2F;gb-schematics#original-game-boy-dcdc-power-board-dc-conv-dmg--dc-conv2-dmg&quot;&gt;https:&#x2F;&#x2F;github.com&#x2F;Gekkio&#x2F;gb-schematics#original-game-boy-dcdc-power-board-dc-conv-dmg--dc-conv2-dmg&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;&#x2F;div&gt;
&lt;h3 id=&quot;2022-02-19&quot;&gt;2022-02-19&lt;&#x2F;h3&gt;
&lt;div class=&quot;tweet&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;gekkio&#x2F;status&#x2F;1494796818298855425&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;2022-02-19.png&quot; alt=&quot;Screenshot of the original tweet&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;🎶&lt;br&gt;
Might as well jump&lt;br&gt;
Go ahead and jump&lt;br&gt;
Get it in, jump&lt;br&gt;
Go ahead and jump&lt;br&gt;
🎶&lt;&#x2F;p&gt;
&lt;p&gt;For some strange reason I sometimes think about this song whenever I install more than 1 of these things...&lt;br&gt;
&lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;1494796818298855425-FL6T0KFXMAEsbKW.jpg&quot;&gt;Attached photo 1&lt;&#x2F;a&gt;&lt;br&gt;
&lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;1494796818298855425-FL6T2ilWUAUanmh.jpg&quot;&gt;Attached photo 2&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;This lovely board would eventually make it much easier to capture all cartridge bus signals with a logic analyzer...at the time of writing (2022), it&#x27;s not open source but perhaps I&#x27;ll release it at some point.&lt;&#x2F;p&gt;
&lt;div class=&quot;tweet&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;gekkio&#x2F;status&#x2F;1494799536321179655&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;2022-02-19_2.png&quot; alt=&quot;Screenshot of the original tweet&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Here&#x27;s a sneak peek of my next Game Boy schematics project. I&#x27;ve already desoldered and characterized all components and am now doing tracing. After that it&#x27;s time for schematics...&lt;&#x2F;p&gt;
&lt;p&gt;This time the trace SVG is also nicer since I have two separate but aligned BG layers&lt;br&gt;
&lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;1494799536321179655-FL6XyVRX0AELY2W.jpg&quot;&gt;Attached screenshot&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;&#x2F;div&gt;
&lt;h3 id=&quot;2022-03-09&quot;&gt;2022-03-09&lt;&#x2F;h3&gt;
&lt;div class=&quot;tweet&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;gekkio&#x2F;status&#x2F;1501611657537241092&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;2022-03-09.png&quot; alt=&quot;Screenshot of the original tweet&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;My current chip decap project: Game Boy MBC1B memory bank controller chip found on many cartridges. This chip is already well understood, but decided to RE it thoroughly anyway.&lt;&#x2F;p&gt;
&lt;p&gt;I&#x27;ve already traced everything and just need to finish the schematics...&lt;br&gt;
&lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;1501611657537241092-FNbKMpYWYAI_cqo.jpg&quot;&gt;Attached screenshot 1&lt;&#x2F;a&gt;&lt;br&gt;
&lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;1501611657537241092-FNbLmVqXMAAPIej.jpg&quot;&gt;Attached screenshot 2&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;tweet&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;gekkio&#x2F;status&#x2F;1501614894633959426&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;2022-03-09_2.png&quot; alt=&quot;Screenshot of the original tweet&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Image quality is pretty bad since I used a low-quality 20x objective 😅 lots of optical aberrations...&lt;&#x2F;p&gt;
&lt;p&gt;It&#x27;s good enough to identify cells and connections, but I took some extra photos with a good 40x objective to study internal cell structures.&lt;&#x2F;p&gt;
&lt;p&gt;Just look at the difference 😻&lt;br&gt;
&lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;1501614894633959426-FNbN299XsAAwFNp.jpg&quot;&gt;Attached screenshot&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;tweet&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;gekkio&#x2F;status&#x2F;1501616502352580614&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;2022-03-09_3.png&quot; alt=&quot;Screenshot of the original tweet&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;&quot;I didn&#x27;t do anything! I&#x27;m sure it was like this when I found it!&quot;&lt;br&gt;
😐&lt;&#x2F;p&gt;
&lt;p&gt;Turns out I was a bit careless with decapping and the die took some damage. Luckily the connections were obvious and easy to guess...&lt;br&gt;
&lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;1501616502352580614-FNbPCMtXoAcjnWa.jpg&quot;&gt;Attached screenshot&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;&#x2F;div&gt;
&lt;h3 id=&quot;2022-03-13&quot;&gt;2022-03-13&lt;&#x2F;h3&gt;
&lt;div class=&quot;tweet&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;gekkio&#x2F;status&#x2F;1502987288107786240&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;2022-03-13.png&quot; alt=&quot;Screenshot of the original tweet&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;I&#x27;ve just released my Game Boy MBC1B chip research 🎉&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;Gekkio&#x2F;gb-research&#x2F;tree&#x2F;main&#x2F;mbc1b&quot;&gt;https:&#x2F;&#x2F;github.com&#x2F;Gekkio&#x2F;gb-research&#x2F;tree&#x2F;main&#x2F;mbc1b&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;fully traced SVG file based on decapped chip photo&lt;br&gt;&lt;&#x2F;li&gt;
&lt;li&gt;KiCad schematics&lt;br&gt;&lt;&#x2F;li&gt;
&lt;li&gt;automatically generated VHDL model&lt;br&gt;&lt;&#x2F;li&gt;
&lt;li&gt;VHDL testbench, also verified on real HW&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Let&#x27;s take a look at what&#x27;s in the repo 🧵&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;This was an important &quot;practice project&quot;, because I was going to use the same techniques for the SM83 CPU core and the full SoC.&lt;&#x2F;p&gt;
&lt;div class=&quot;tweet&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;gekkio&#x2F;status&#x2F;1502987966892974081&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;2022-03-13_2.png&quot; alt=&quot;Screenshot of the original tweet&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Firstly we have the SVG file using a decapped die photo as a background.&lt;&#x2F;p&gt;
&lt;p&gt;All connections are traced and cells are identified. I&#x27;ve even added start&#x2F;end markers to connections: for example, &quot;FE&quot; OAI21 cell has one output (top left) and three inputs (2x top right, and 1x bottom)&lt;br&gt;
&lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;1502987966892974081-FNuvAtdXoAAi1Du.jpg&quot;&gt;Attached screenshot&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;tweet&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;gekkio&#x2F;status&#x2F;1502988513914068999&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;2022-03-13_3.png&quot; alt=&quot;Screenshot of the original tweet&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Then we have the KiCad schematics (top level sheet in the screenshot). I&#x27;ve tried to make them as readable as possible, but this is still a 1:1 cell-level mapping to the SVG so nothing should be missing.&lt;br&gt;
&lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;1502988513914068999-FNuvtPqXsAE5ALj.png&quot;&gt;Attached screenshot&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;tweet&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;gekkio&#x2F;status&#x2F;1502989656224419843&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;2022-03-13_4.png&quot; alt=&quot;Screenshot of the original tweet&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Then we have a VHDL model generated from the schematics using my Kingfish KiCad-to-HDL generator.&lt;br&gt;
Not very readable since this is a raw mapping from the KiCad netlist, but the main point is to run a VHDL testbench &quot;against the schematics&quot; without error-prone manual work.&lt;br&gt;
&lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;1502989656224419843-FNuwOtYWQAYqR9h.jpg&quot;&gt;Attached screenshot&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;tweet&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;gekkio&#x2F;status&#x2F;1502990663788511239&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;2022-03-13_5.png&quot; alt=&quot;Screenshot of the original tweet&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Finally, a VHDL testbench tests and describes the expected behaviour of the generated model. These tests were taken from my old &quot;gpio-bench&quot; hardware system which ran peek&#x2F;poke -style tests on a real MBC1 chip, so the tests have been previously verified on real hw.&lt;br&gt;
&lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;1502990663788511239-FNuxVLfXsAQEBat.png&quot;&gt;Attached screenshot&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;tweet&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;gekkio&#x2F;status&#x2F;1502991857965580297&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;2022-03-13_6.png&quot; alt=&quot;Screenshot of the original tweet&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Having a way to &quot;test the schematics&quot; has been invaluable...even on a simple chip like this I had one misidentified cell, which was only caught once I started running tests. Staring at schematics and trying to reason about them is way too slow and error-prone for me 😅&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;&#x2F;div&gt;
&lt;h3 id=&quot;2022-03-19&quot;&gt;2022-03-19&lt;&#x2F;h3&gt;
&lt;div class=&quot;tweet&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;gekkio&#x2F;status&#x2F;1505214010349785091&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;2022-03-19.png&quot; alt=&quot;Screenshot of the original tweet&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;I proudly present the schematics of Game Boy Light (a.k.a MGL) 🎉&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;Gekkio&#x2F;gb-schematics&#x2F;blob&#x2F;main&#x2F;MGL-CPU-01&#x2F;schematic&#x2F;MGL-CPU-01.pdf&quot;&gt;https:&#x2F;&#x2F;github.com&#x2F;Gekkio&#x2F;gb-schematics&#x2F;blob&#x2F;main&#x2F;MGL-CPU-01&#x2F;schematic&#x2F;MGL-CPU-01.pdf&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;As expected, it&#x27;s 95% identical to Game Boy Pocket (a.k.a MGB), but that 5% includes some important differences that are now documented.&lt;&#x2F;p&gt;
&lt;p&gt;Only &lt;em&gt;one&lt;&#x2F;em&gt; MGL was harmed to make these 😅&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;RIP my only Game Boy Light...it was kind of an expensive sacrifice, but I never used it anyway...🥲&lt;&#x2F;p&gt;
&lt;h3 id=&quot;2022-05-07&quot;&gt;2022-05-07&lt;&#x2F;h3&gt;
&lt;div class=&quot;tweet&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;gekkio&#x2F;status&#x2F;1523011738551164929&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;2022-05-07.png&quot; alt=&quot;Screenshot of the original tweet&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;My gb-hardware repo now has a &quot;naughty list&quot; of people who violated the very liberal CC BY 4.0 license of my designs.&lt;&#x2F;p&gt;
&lt;p&gt;License summary: just don&#x27;t erase my name and claim you made the design 100% yourself. That&#x27;s all. You can modify and&#x2F;or sell freely.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;gekkio&#x2F;gb-hardware#license-violations-aka-naughty-list&quot;&gt;https:&#x2F;&#x2F;github.com&#x2F;gekkio&#x2F;gb-hardware#license-violations-aka-naughty-list&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;&#x2F;div&gt;
&lt;h3 id=&quot;2022-05-30&quot;&gt;2022-05-30&lt;&#x2F;h3&gt;
&lt;div class=&quot;tweet&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;gekkio&#x2F;status&#x2F;1531336881429958657&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;2022-05-30.png&quot; alt=&quot;Screenshot of the original tweet&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Time for another Game Boy -related schematics release: I&#x27;ve RE&#x27;d 2 types of Game Boy Pocket DC&#x2F;DC conversion boards! AFAIK there are no others.&lt;&#x2F;p&gt;
&lt;p&gt;LSEP01088A1 (a.k.a. type A):&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;Gekkio&#x2F;gb-schematics&#x2F;blob&#x2F;main&#x2F;LSEP01088A1&#x2F;schematic&#x2F;LSEP01088A1.pdf&quot;&gt;https:&#x2F;&#x2F;github.com&#x2F;Gekkio&#x2F;gb-schematics&#x2F;blob&#x2F;main&#x2F;LSEP01088A1&#x2F;schematic&#x2F;LSEP01088A1.pdf&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;A different one with the text &quot;MGB&quot; (a.k.a. type B):&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;Gekkio&#x2F;gb-schematics&#x2F;blob&#x2F;main&#x2F;MGB-DCDC-B&#x2F;schematic&#x2F;MGB-DCDC-B.pdf&quot;&gt;https:&#x2F;&#x2F;github.com&#x2F;Gekkio&#x2F;gb-schematics&#x2F;blob&#x2F;main&#x2F;MGB-DCDC-B&#x2F;schematic&#x2F;MGB-DCDC-B.pdf&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;&#x2F;div&gt;
&lt;h3 id=&quot;2022-09-12&quot;&gt;2022-09-12&lt;&#x2F;h3&gt;
&lt;div class=&quot;tweet&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;gekkio&#x2F;status&#x2F;1569340023992119298&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;2022-09-12.png&quot; alt=&quot;Screenshot of the original tweet&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;When I woke up yesterday, I had no idea I&#x27;d end up reverse engineering the Game Boy MBC2A mapper chip 😅&lt;&#x2F;p&gt;
&lt;p&gt;Yesterday was spent on tracing, so now I just need to do schematics and simulation.&lt;&#x2F;p&gt;
&lt;p&gt;Original background microscope photo by Raphael Boichot: &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;Raphael-Boichot&#x2F;Game-Boy-chips-decapping-project&#x2F;&quot;&gt;https:&#x2F;&#x2F;github.com&#x2F;Raphael-Boichot&#x2F;Game-Boy-chips-decapping-project&#x2F;&lt;&#x2F;a&gt;&lt;br&gt;
&lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;1569340023992119298-FcdqX8BWYAE3xD4.jpg&quot;&gt;Attached screenshot&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;&lt;em&gt;Narrator&#x27;s voice&lt;&#x2F;em&gt;: &quot;Just schematics and simulation&quot; would end up taking months...&lt;&#x2F;p&gt;
&lt;div class=&quot;tweet&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;gekkio&#x2F;status&#x2F;1569426101721612288&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;2022-09-12_2.png&quot; alt=&quot;Screenshot of the original tweet&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;The main motivation was two pins: &quot;VCC_RAM&quot; and &quot;GND_RAM&quot;. I realized I never questioned previous research which claimed these to be supply pins for embedded RAM. A quick look at the decap photo made it clear that they are I&#x2F;O pins! I had to RE the whole chip to understand them&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;tweet&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;gekkio&#x2F;status&#x2F;1569427215338577932&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;2022-09-12_3.png&quot; alt=&quot;Screenshot of the original tweet&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;&quot;GND_RAM&quot; seems to be an active-low global output enable pin. On PCBs it&#x27;s always tied low, so all outputs are enabled.&lt;&#x2F;p&gt;
&lt;p&gt;&quot;VCC_RAM&quot; seems to be an active-low async clear pin, which resets all flip-flops. On PCBs it&#x27;s always tied high, so it&#x27;s deasserted.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;tweet&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;gekkio&#x2F;status&#x2F;1569427855737487361&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;2022-09-12_4.png&quot; alt=&quot;Screenshot of the original tweet&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;The chip also has an active-low RESET pin, which is actually used on PCBs and it too resets all flip-flops.&lt;&#x2F;p&gt;
&lt;p&gt;Why two pins for reset? RESET also gates inputs, so it does more than the other pin. Perhaps the CLEAR pin was used for testing, or is just an unused leftover feature.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;&#x2F;div&gt;
&lt;h3 id=&quot;2022-10-16&quot;&gt;2022-10-16&lt;&#x2F;h3&gt;
&lt;div class=&quot;tweet&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;gekkio&#x2F;status&#x2F;1581674682842955776&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;2022-10-16.png&quot; alt=&quot;Screenshot of the original tweet&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Getting ready to release my Game Boy SM83 CPU core research I started more than 2 years ago. I have a complete HDL model (written in VHDL), understand pretty much all the signals and have assigned good names for them.&lt;&#x2F;p&gt;
&lt;p&gt;Here&#x27;s a screenshot of the huge manually traced SVG file 😅&lt;br&gt;
&lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;1581674682842955776-FfM6_oQXEAU0EVV.jpg&quot;&gt;Attached screenshot&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;I was way too excited about this project and ended up tweeting this when I still had more work to do before release...perhaps I should&#x27;ve just tweeted the actual release, which happened just a week later.&lt;&#x2F;p&gt;
&lt;div class=&quot;tweet&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;gekkio&#x2F;status&#x2F;1581676477984124928&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;2022-10-16_2.png&quot; alt=&quot;Screenshot of the original tweet&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Here&#x27;s a zoomed in section of the ALU. The background is a massive stitched photo taken with my microscope using a 40x objective. Some educated guesswork based on my understanding of the chip was needed, because I can&#x27;t see what&#x27;s under the top metal layer.&lt;br&gt;
&lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;1581676477984124928-FfM9J6iWQAIzzF-.jpg&quot;&gt;Attached screenshot&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;tweet&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;gekkio&#x2F;status&#x2F;1581686531529457664&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;2022-10-16_3.png&quot; alt=&quot;Screenshot of the original tweet&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;I originally started this work using a stitched microscope photo from &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;siliconpr0n.org&quot;&gt;siliconpr0n.org&lt;&#x2F;a&gt;. Here&#x27;s one section as an example.&lt;&#x2F;p&gt;
&lt;p&gt;This was sufficient for a lot of things, but some fine structures were a bit too difficult to figure out, so I started building my own microscope.&lt;br&gt;
&lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;1581686531529457664-FfNHJI8XgAEcXmt.jpg&quot;&gt;Attached photo&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;tweet&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;gekkio&#x2F;status&#x2F;1581688258953547778&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;2022-10-16_4.png&quot; alt=&quot;Screenshot of the original tweet&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Using a microscope with a 40x objective, I was able to selectively capture some areas with finer details. Without a motorized stage this was a lot of work, and as a result I had several photos and had to switch back-and-forth between them when tracing common signals&lt;br&gt;
&lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;1581688258953547778-FfNHkZ1XkAEIPfQ.jpg&quot;&gt;Attached photo&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;tweet&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;gekkio&#x2F;status&#x2F;1581689411107897344&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;2022-10-16_5.png&quot; alt=&quot;Screenshot of the original tweet&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;The solution: capture the whole CPU core at 40x and make one big photo. This summer after a lot of work, I finally had a motorized scope and was able to do it. I&#x27;ve moved most of my previous work to this new single photo, fixed mistakes, and worked on the last ~10% I was missing&lt;br&gt;
&lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;1581689411107897344-FfNJ2zqXkAIMxdx.jpg&quot;&gt;Attached photo&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;tweet&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;gekkio&#x2F;status&#x2F;1581691747591077888&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;2022-10-16_6.png&quot; alt=&quot;Screenshot of the original tweet&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;This turned out to be very useful 😄 As an example, here&#x27;s one output from decoder stage 1, used by stage 2 and 3 and also the ALU. Previously I had 4 separate SVG files and had to jump between them to understand the whole signal. Now it&#x27;s enough to look at one trace in one file&lt;br&gt;
&lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;1581691747591077888-FfNLmj5XkAIPZzz.jpg&quot;&gt;Attached photo&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;&#x2F;div&gt;
&lt;h3 id=&quot;2022-10-23&quot;&gt;2022-10-23&lt;&#x2F;h3&gt;
&lt;div class=&quot;tweet&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;gekkio&#x2F;status&#x2F;1584234589442441219&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;2022-10-23.png&quot; alt=&quot;Screenshot of the original tweet&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;After 2+ years of research, it&#x27;s time to release my Game Boy SM83 CPU core RE work!&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;Gekkio&#x2F;gb-research&#x2F;tree&#x2F;main&#x2F;sm83-cpu-core&quot;&gt;https:&#x2F;&#x2F;github.com&#x2F;Gekkio&#x2F;gb-research&#x2F;tree&#x2F;main&#x2F;sm83-cpu-core&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Includes non-synthesizable HDL model and an SVG with almost all important stuff traced.&lt;&#x2F;p&gt;
&lt;p&gt;Passes Blargg&#x27;s cpu_instrs tests, except &quot;02 interrupts&quot; which needs a full SoC&lt;br&gt;
&lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;1584234589442441219-FfxTpFrWQAA0xkx.jpg&quot;&gt;Attached screenshot&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;This was a massive milestone and the result of a lot of work...I could finally run test ROMs with my DMG-CPU B SoC model and continue that work. Many questions about the SM83 CPU core also got answered.&lt;&#x2F;p&gt;
&lt;div class=&quot;tweet&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;gekkio&#x2F;status&#x2F;1584236637932126208&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;2022-10-23_2.png&quot; alt=&quot;Screenshot of the original tweet&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Let&#x27;s take a tour! 😄&lt;&#x2F;p&gt;
&lt;p&gt;Here&#x27;s the register file: you can see all main registers, including the WZ temporary register, which is not directly visible to programmers. 8 &quot;rows&quot; where each row contains everything to handle one bit. 16-bit regs are built as 2x 8-bit adjacent regs&lt;br&gt;
&lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;1584236637932126208-FfxVt4jXEAEn_YH.jpg&quot;&gt;Attached screenshot&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;tweet&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;gekkio&#x2F;status&#x2F;1584237201411305472&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;2022-10-23_3.png&quot; alt=&quot;Screenshot of the original tweet&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Next to the reg file we have the Increment&#x2F;Decrement Unit (IDU) and some interrupt handling logic. The IDU is a separate unit from ALU, and does 16-bit increment&#x2F;decrement&#x2F;load operations, and also outputs the 16-bit address to the rest of the SoC.&lt;br&gt;
&lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;1584237201411305472-FfxW5Q5XgAE-s90.jpg&quot;&gt;Attached screenshot&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;tweet&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;gekkio&#x2F;status&#x2F;1584238102335610880&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;2022-10-23_4.png&quot; alt=&quot;Screenshot of the original tweet&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;The interrupt logic block contains e.g. interrupt priority and address handling and also the IE (Interrupt Enable) register. The IF (Interrupt Flag) register is not in the CPU but elsewhere in the SoC!&lt;&#x2F;p&gt;
&lt;p&gt;The CPU core supports 8 interrupts + NMI, but some are disabled in the GB SoC&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;tweet&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;gekkio&#x2F;status&#x2F;1584238514769575937&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;2022-10-23_5.png&quot; alt=&quot;Screenshot of the original tweet&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Next we have a massive 3-stage instruction decoder using dynamic logic. The decoder takes the current opcode and a bunch of other state as input, and outputs a lot of control signals to various parts of the CPU core.&lt;br&gt;
&lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;1584238514769575937-FfxYQbIXgAAPolR.jpg&quot;&gt;Attached screenshot&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;tweet&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;gekkio&#x2F;status&#x2F;1584239205903142913&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;2022-10-23_6.png&quot; alt=&quot;Screenshot of the original tweet&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Next to the decoder we have the control unit, which consists of a lot of logic cells. It contains some CPU state such as the IME register, and control various parts of the system while taking inputs from the decoder and other areas.&lt;br&gt;
&lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;1584239205903142913-FfxYqV_X0AAmZ7l.jpg&quot;&gt;Attached screenshot&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;tweet&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;gekkio&#x2F;status&#x2F;1584240032910839808&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;2022-10-23_7.png&quot; alt=&quot;Screenshot of the original tweet&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;A very important part of the system is the 8-bit Arithmetic and Logic Unit (ALU), which handles 8-bit calculations (the IDU does some 16-bit stuff instead). I&#x27;ve also included the flag registers here, but it&#x27;s debatable whether they are truly part of the ALU or not.&lt;br&gt;
&lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;1584240032910839808-FfxZR3hWQAA9JVv.jpg&quot;&gt;Attached screenshot&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;tweet&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;gekkio&#x2F;status&#x2F;1584241140391239681&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;2022-10-23_8.png&quot; alt=&quot;Screenshot of the original tweet&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;What about the HDL?&lt;&#x2F;p&gt;
&lt;p&gt;Non-synthesizable HDL = you can&#x27;t just put this on an FPGA and expect it to work. Why not? The core uses dynamic logic and other ASIC stuff that FPGAs simply can&#x27;t do and need to emulate instead.&lt;&#x2F;p&gt;
&lt;p&gt;The main goal here is to support simulation and understanding&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;tweet&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;gekkio&#x2F;status&#x2F;1584242705923612672&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;2022-10-23_9.png&quot; alt=&quot;Screenshot of the original tweet&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;What we &lt;em&gt;can&lt;&#x2F;em&gt; do is use this HDL as a reference model to build a more FPGA-friendly model. Many things can be simplified and improved, and the result can be compared to the reference.&lt;&#x2F;p&gt;
&lt;p&gt;No plans to do this myself (for now), but I hope the HDL helps other people 😄&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;tweet&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;gekkio&#x2F;status&#x2F;1584246690294693889&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2022&#x2F;8-years-of-game-boy-tweets&#x2F;2022-10-23_10.png&quot; alt=&quot;Screenshot of the original tweet&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;It&#x27;s also important to understand that this is not a HDL model of a Game Boy...it&#x27;s just the CPU core, so it can&#x27;t run any games.&lt;&#x2F;p&gt;
&lt;p&gt;A full and accurate HDL model of the whole Game Boy SoC is a separate thing, and there are multiple projects attempting it (yes I have one too).&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;&#x2F;div&gt;
&lt;h2 id=&quot;final-words&quot;&gt;Final words&lt;&#x2F;h2&gt;
&lt;p&gt;What a rollercoaster these 8 years have been! I&#x27;ve never been a huge fan of twitter, but it has been one of the main communication channels where I&#x27;ve announced new info about my various Game Boy projects. In the future, I&#x27;ll probably focus on Mastodon instead of Twitter, despite having less than 1&#x2F;10 followers there.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Power consumption of Game Boy flash cartridges</title>
        <published>2021-04-17T00:00:00+00:00</published>
        <updated>2021-04-17T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Joonas Javanainen
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://gekkio.fi/blog/2021/power-consumption-of-game-boy-flash-cartridges/"/>
        <id>https://gekkio.fi/blog/2021/power-consumption-of-game-boy-flash-cartridges/</id>
        
        <content type="html" xml:base="https://gekkio.fi/blog/2021/power-consumption-of-game-boy-flash-cartridges/">&lt;p&gt;Flash cartridges (= &quot;carts&quot;) are commonly used to run Game Boy ROMs, such as homebrew games or dumped officially released games, on real hardware. Different kinds of flash carts with various features and performance characteristics have been available for a long time, but flash carts have in general the reputation of consuming a lot of power, greatly reducing the battery life of a Game Boy system, and possibly causing other additional problems. System stability might suffer, especially on Game Boy Pocket, and flash carts can also increase audible noise. Many of these problems have become more obvious in the recent years, since Game Boy modding is nowadays very popular and many modern mods, such as IPS screens, consume a lot of extra power. Some people claim that certain mods are simply incompatible with flash carts, and sometimes people say an extra regluator mod is needed in order to safely use flash carts. There is some truth to these claims, but unfortunately the fine details tend to matter and these kind of blanket statements can be misleading!&lt;&#x2F;p&gt;
&lt;p&gt;In order to research the topic, I tested the power consumption of several commonly available flash carts and some of my own designs. In this blog post I intend to show that there is more variation in flash cart power consumption than people might think, and a flash cart can even be more power efficient than a genuine cart!&lt;&#x2F;p&gt;
&lt;h2 id=&quot;tested-cartridges&quot;&gt;Tested cartridges&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;genuine-tetris-from-1997&quot;&gt;Genuine Tetris from 1997&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2021&#x2F;power-consumption-of-game-boy-flash-cartridges&#x2F;tetris_front.jpg&quot;&gt;
  
  &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;gekkio.fi&amp;#x2F;processed_images&amp;#x2F;tetris_front.b11ed78ead1a4558.jpg&quot; width=&quot;261&quot; height=&quot;300&quot; &#x2F;&gt;
&lt;&#x2F;a&gt;

&lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2021&#x2F;power-consumption-of-game-boy-flash-cartridges&#x2F;tetris_pcb_front.jpg&quot;&gt;
  
  &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;gekkio.fi&amp;#x2F;processed_images&amp;#x2F;tetris_pcb_front.049a00476fd35465.jpg&quot; width=&quot;347&quot; height=&quot;300&quot; &#x2F;&gt;
&lt;&#x2F;a&gt;

&lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2021&#x2F;power-consumption-of-game-boy-flash-cartridges&#x2F;tetris_pcb_back.jpg&quot;&gt;
  
  &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;gekkio.fi&amp;#x2F;processed_images&amp;#x2F;tetris_pcb_back.b0805d573879ae0e.jpg&quot; width=&quot;343&quot; height=&quot;300&quot; &#x2F;&gt;
&lt;&#x2F;a&gt;
&lt;&#x2F;p&gt;
&lt;p&gt;This is a genuine Tetris cart from 1997 that uses a glop top mask ROM. Since there are no other chips (e.g. MBC or RAM) on the board and the mask ROM capacity is small, the power consumption is very low. This simplicity means the cartridge presents a tough challenge for more complicated flash carts in power consumption tests.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;genuine-pokemon-blue-from-1998&quot;&gt;Genuine Pokemon Blue from 1998&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2021&#x2F;power-consumption-of-game-boy-flash-cartridges&#x2F;blue_genuine_front.jpg&quot;&gt;
  
  &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;gekkio.fi&amp;#x2F;processed_images&amp;#x2F;blue_genuine_front.b5183a4a8044e02b.jpg&quot; width=&quot;262&quot; height=&quot;300&quot; &#x2F;&gt;
&lt;&#x2F;a&gt;

&lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2021&#x2F;power-consumption-of-game-boy-flash-cartridges&#x2F;blue_genuine_pcb_front.jpg&quot;&gt;
  
  &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;gekkio.fi&amp;#x2F;processed_images&amp;#x2F;blue_genuine_pcb_front.b441d69420aa32d5.jpg&quot; width=&quot;250&quot; height=&quot;300&quot; &#x2F;&gt;
&lt;&#x2F;a&gt;

&lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2021&#x2F;power-consumption-of-game-boy-flash-cartridges&#x2F;blue_genuine_pcb_back.jpg&quot;&gt;
  
  &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;gekkio.fi&amp;#x2F;processed_images&amp;#x2F;blue_genuine_pcb_back.dcf82d2c08d0663a.jpg&quot; width=&quot;252&quot; height=&quot;300&quot; &#x2F;&gt;
&lt;&#x2F;a&gt;
&lt;&#x2F;p&gt;
&lt;p&gt;This is a genuine Pokemon Blue cartridge with a very typical ROM+RAM+MBC chip combination. While the exact chips used may vary, this kind of combination is very common in officially released Game Boy games. This is why it provides a more realistic comparison point than Tetris.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;cheap-reproduction-pokemon-blue&quot;&gt;Cheap reproduction Pokemon Blue&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2021&#x2F;power-consumption-of-game-boy-flash-cartridges&#x2F;blue_repro_front.jpg&quot;&gt;
  
  &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;gekkio.fi&amp;#x2F;processed_images&amp;#x2F;blue_repro_front.48cf562a1d02a819.jpg&quot; width=&quot;267&quot; height=&quot;300&quot; &#x2F;&gt;
&lt;&#x2F;a&gt;

&lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2021&#x2F;power-consumption-of-game-boy-flash-cartridges&#x2F;blue_repro_pcb_front.jpg&quot;&gt;
  
  &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;gekkio.fi&amp;#x2F;processed_images&amp;#x2F;blue_repro_pcb_front.bc685f03ecf9adf1.jpg&quot; width=&quot;282&quot; height=&quot;300&quot; &#x2F;&gt;
&lt;&#x2F;a&gt;

&lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2021&#x2F;power-consumption-of-game-boy-flash-cartridges&#x2F;blue_repro_pcb_back.jpg&quot;&gt;
  
  &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;gekkio.fi&amp;#x2F;processed_images&amp;#x2F;blue_repro_pcb_back.9623dd639e5383eb.jpg&quot; width=&quot;281&quot; height=&quot;300&quot; &#x2F;&gt;
&lt;&#x2F;a&gt;
&lt;&#x2F;p&gt;
&lt;p&gt;This is a cheap reproduction cartridge I bought from AliExpress for research purposes. It has clearly been designed with only cost in mind, because the design violates some chip ratings and does not even have PCB edge gold fingers. A poorly designed cartridge that would undoubtedly not survive constant use for very long, but it&#x27;s still interesting to include it in the comparison.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;genuine-wario-land-ii-gbc-release-from-1998&quot;&gt;Genuine Wario Land II (GBC release) from 1998&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2021&#x2F;power-consumption-of-game-boy-flash-cartridges&#x2F;wario_front.jpg&quot;&gt;
  
  &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;gekkio.fi&amp;#x2F;processed_images&amp;#x2F;wario_front.06f4dd11aaccb8f0.jpg&quot; width=&quot;261&quot; height=&quot;300&quot; &#x2F;&gt;
&lt;&#x2F;a&gt;

&lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2021&#x2F;power-consumption-of-game-boy-flash-cartridges&#x2F;wario_pcb_front.jpg&quot;&gt;
  
  &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;gekkio.fi&amp;#x2F;processed_images&amp;#x2F;wario_pcb_front.16ef77022465e9b4.jpg&quot; width=&quot;252&quot; height=&quot;300&quot; &#x2F;&gt;
&lt;&#x2F;a&gt;

&lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2021&#x2F;power-consumption-of-game-boy-flash-cartridges&#x2F;wario_pcb_back.jpg&quot;&gt;
  
  &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;gekkio.fi&amp;#x2F;processed_images&amp;#x2F;wario_pcb_back.2941be0be95d21d8.jpg&quot; width=&quot;258&quot; height=&quot;300&quot; &#x2F;&gt;
&lt;&#x2F;a&gt;
&lt;&#x2F;p&gt;
&lt;p&gt;This is a genuine Wario Land II cartridge. Like Pokemon Blue, it uses a very typical set of chips, but this one uses MBC5 instead of MBC3. Note that Wario Land II had more than one release, and this is the western Game Boy Color -enhanced release that is still compatible with all Game Boy consoles.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;everdrive-gb&quot;&gt;Everdrive GB&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2021&#x2F;power-consumption-of-game-boy-flash-cartridges&#x2F;edgb_front.jpg&quot;&gt;
  
  &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;gekkio.fi&amp;#x2F;processed_images&amp;#x2F;edgb_front.fbd80205b66f6e5d.jpg&quot; width=&quot;269&quot; height=&quot;300&quot; &#x2F;&gt;
&lt;&#x2F;a&gt;

&lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2021&#x2F;power-consumption-of-game-boy-flash-cartridges&#x2F;edgb_pcb_front.jpg&quot;&gt;
  
  &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;gekkio.fi&amp;#x2F;processed_images&amp;#x2F;edgb_pcb_front.9c1d9921b5f995ad.jpg&quot; width=&quot;247&quot; height=&quot;300&quot; &#x2F;&gt;
&lt;&#x2F;a&gt;

&lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2021&#x2F;power-consumption-of-game-boy-flash-cartridges&#x2F;edgb_pcb_back.jpg&quot;&gt;
  
  &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;gekkio.fi&amp;#x2F;processed_images&amp;#x2F;edgb_pcb_back.c0fd9fb008c28fff.jpg&quot; width=&quot;251&quot; height=&quot;300&quot; &#x2F;&gt;
&lt;&#x2F;a&gt;
&lt;&#x2F;p&gt;
&lt;p&gt;The original Everdrive used to be a very popular flash cartridge, but has recently been obsoleted by newer products. It uses an SD card, so multiple games can be stored and easily switched with the initial menu program that appears when the system powers up.&lt;&#x2F;p&gt;
&lt;p&gt;The tested cartridge PCB is labeled as &quot;v1.2&quot;, &quot;13.03.2014&quot;, and was used with firmware v4.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;everdrive-gb-x5&quot;&gt;Everdrive GB X5&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2021&#x2F;power-consumption-of-game-boy-flash-cartridges&#x2F;edgbx5_front.jpg&quot;&gt;
  
  &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;gekkio.fi&amp;#x2F;processed_images&amp;#x2F;edgbx5_front.2f29443070dd619e.jpg&quot; width=&quot;264&quot; height=&quot;300&quot; &#x2F;&gt;
&lt;&#x2F;a&gt;

&lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2021&#x2F;power-consumption-of-game-boy-flash-cartridges&#x2F;edgbx5_pcb_front.jpg&quot;&gt;
  
  &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;gekkio.fi&amp;#x2F;processed_images&amp;#x2F;edgbx5_pcb_front.a0186765f8608960.jpg&quot; width=&quot;253&quot; height=&quot;300&quot; &#x2F;&gt;
&lt;&#x2F;a&gt;

&lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2021&#x2F;power-consumption-of-game-boy-flash-cartridges&#x2F;edgbx5_pcb_back.jpg&quot;&gt;
  
  &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;gekkio.fi&amp;#x2F;processed_images&amp;#x2F;edgbx5_pcb_back.48136710f8cec209.jpg&quot; width=&quot;261&quot; height=&quot;300&quot; &#x2F;&gt;
&lt;&#x2F;a&gt;
&lt;&#x2F;p&gt;
&lt;p&gt;Everdrive GB X5 is a newer Everdrive model with greatly improved design and performance. Like its predecessor, it uses an SD card. The X-series also includes X3 and X7, but I only tested the X5 model, which omits some features like RTC from the most expensive X7 model. Note that the circuit board says &quot;X7&quot; but several components are missing, so it seems the same board design is used in both X5 and X7.&lt;&#x2F;p&gt;
&lt;p&gt;The tested cartridge PCB is labeled as &quot;Model 17&quot;, &quot;Rev B&quot;, &quot;26.08.2017&quot;, and was used with firmware v1.04.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;ez-flash-junior&quot;&gt;EZ-FLASH Junior&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2021&#x2F;power-consumption-of-game-boy-flash-cartridges&#x2F;ezflash_front.jpg&quot;&gt;
  
  &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;gekkio.fi&amp;#x2F;processed_images&amp;#x2F;ezflash_front.d0d4cf21cc1d213e.jpg&quot; width=&quot;268&quot; height=&quot;300&quot; &#x2F;&gt;
&lt;&#x2F;a&gt;

&lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2021&#x2F;power-consumption-of-game-boy-flash-cartridges&#x2F;ezflash_pcb_front.jpg&quot;&gt;
  
  &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;gekkio.fi&amp;#x2F;processed_images&amp;#x2F;ezflash_pcb_front.94da67b51efe0293.jpg&quot; width=&quot;254&quot; height=&quot;300&quot; &#x2F;&gt;
&lt;&#x2F;a&gt;

&lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2021&#x2F;power-consumption-of-game-boy-flash-cartridges&#x2F;ezflash_pcb_back.jpg&quot;&gt;
  
  &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;gekkio.fi&amp;#x2F;processed_images&amp;#x2F;ezflash_pcb_back.6ff2fa98b2e5023e.jpg&quot; width=&quot;252&quot; height=&quot;300&quot; &#x2F;&gt;
&lt;&#x2F;a&gt;
&lt;&#x2F;p&gt;
&lt;p&gt;EZ-FLASH Junior is another flash cart that uses an SD card. Its product page boasts about it having a lot of features, like RTC support, and it costs quite a lot less than an Everdrive GB X5.&lt;&#x2F;p&gt;
&lt;p&gt;The tested cartridge PCB is labeled as &quot;1320&quot;, and was used with kernel 1.04e and firmware v4.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;ems64&quot;&gt;EMS64&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2021&#x2F;power-consumption-of-game-boy-flash-cartridges&#x2F;ems64_front.jpg&quot;&gt;
  
  &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;gekkio.fi&amp;#x2F;processed_images&amp;#x2F;ems64_front.4dd7ddcd431171b9.jpg&quot; width=&quot;262&quot; height=&quot;300&quot; &#x2F;&gt;
&lt;&#x2F;a&gt;

&lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2021&#x2F;power-consumption-of-game-boy-flash-cartridges&#x2F;ems64_pcb_front.jpg&quot;&gt;
  
  &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;gekkio.fi&amp;#x2F;processed_images&amp;#x2F;ems64_pcb_front.95f2754060b6ec7c.jpg&quot; width=&quot;244&quot; height=&quot;300&quot; &#x2F;&gt;
&lt;&#x2F;a&gt;

&lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2021&#x2F;power-consumption-of-game-boy-flash-cartridges&#x2F;ems64_pcb_back.jpg&quot;&gt;
  
  &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;gekkio.fi&amp;#x2F;processed_images&amp;#x2F;ems64_pcb_back.e43ea95506fb8cce.jpg&quot; width=&quot;250&quot; height=&quot;300&quot; &#x2F;&gt;
&lt;&#x2F;a&gt;
&lt;&#x2F;p&gt;
&lt;p&gt;This one is a fairly old USB-based cartridge. Instead of using an SD card, you simply flash it using a USB Note that there are several EMS64 versions with very different designs, so results for this particular version might be different compared to other versions.&lt;&#x2F;p&gt;
&lt;p&gt;The tested cartridge PCB is labeled as &quot;GB64USB-12&quot;.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;gb-cart32k-a&quot;&gt;GB-CART32K-A&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2021&#x2F;power-consumption-of-game-boy-flash-cartridges&#x2F;cart32k_front.jpg&quot;&gt;
  
  &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;gekkio.fi&amp;#x2F;processed_images&amp;#x2F;cart32k_front.678305448678cbe5.jpg&quot; width=&quot;263&quot; height=&quot;300&quot; &#x2F;&gt;
&lt;&#x2F;a&gt;

&lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2021&#x2F;power-consumption-of-game-boy-flash-cartridges&#x2F;cart32k_pcb_front.jpg&quot;&gt;
  
  &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;gekkio.fi&amp;#x2F;processed_images&amp;#x2F;cart32k_pcb_front.bd563c55d96597ce.jpg&quot; width=&quot;254&quot; height=&quot;300&quot; &#x2F;&gt;
&lt;&#x2F;a&gt;

&lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2021&#x2F;power-consumption-of-game-boy-flash-cartridges&#x2F;cart32k_pcb_back.jpg&quot;&gt;
  
  &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;gekkio.fi&amp;#x2F;processed_images&amp;#x2F;cart32k_pcb_back.ebfca832d9aa5efa.jpg&quot; width=&quot;258&quot; height=&quot;300&quot; &#x2F;&gt;
&lt;&#x2F;a&gt;
&lt;&#x2F;p&gt;
&lt;p&gt;This is one of my designs and a simple 32 kB flash cartridge with support for only one 32 kB ROM. It&#x27;s very limited but a good choice if you only need a cartridge to run a simple game. The design is open source and can be found in my &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;Gekkio&#x2F;gb-hardware&#x2F;tree&#x2F;master&#x2F;GB-CART32K-A&quot;&gt;gb-hardware repository&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;The tested version was GB-CART32K-A v1.0 with an SST39SF020A flash chip.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;gb-cart256k-a&quot;&gt;GB-CART256K-A&lt;&#x2F;h4&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2021&#x2F;power-consumption-of-game-boy-flash-cartridges&#x2F;cart256k_front.jpg&quot;&gt;
  
  &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;gekkio.fi&amp;#x2F;processed_images&amp;#x2F;cart256k_front.4794402ea76ffe5a.jpg&quot; width=&quot;262&quot; height=&quot;300&quot; &#x2F;&gt;
&lt;&#x2F;a&gt;

&lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2021&#x2F;power-consumption-of-game-boy-flash-cartridges&#x2F;cart256k_pcb_front.jpg&quot;&gt;
  
  &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;gekkio.fi&amp;#x2F;processed_images&amp;#x2F;cart256k_pcb_front.57afa70847c2e979.jpg&quot; width=&quot;260&quot; height=&quot;300&quot; &#x2F;&gt;
&lt;&#x2F;a&gt;

&lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2021&#x2F;power-consumption-of-game-boy-flash-cartridges&#x2F;cart256k_pcb_back.jpg&quot;&gt;
  
  &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;gekkio.fi&amp;#x2F;processed_images&amp;#x2F;cart256k_pcb_back.41b50c92a99f9d53.jpg&quot; width=&quot;255&quot; height=&quot;300&quot; &#x2F;&gt;
&lt;&#x2F;a&gt;
&lt;&#x2F;p&gt;
&lt;p&gt;This is one of my designs and a ROM-only flash cartridge with support for 256 kB ROM and either MBC1 or MBC5 emulation using a CPLD. There&#x27;s no support for save games, but it&#x27;s a good choice for games that need a larger ROM size than 32 kB. The design is open source and can be found in my &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;Gekkio&#x2F;gb-hardware&#x2F;tree&#x2F;master&#x2F;GB-CART256K-A&quot;&gt;gb-hardware repository&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Note: the circuit board says GB-CART2M-A, because that&#x27;s the old name of the project before I renamed it for consistency with my other cartridges.&lt;&#x2F;p&gt;
&lt;p&gt;The tested version was GB-CART256K-A v1.1 with an SST39SF020A flash chip.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;gb-cart8m-a&quot;&gt;GB-CART8M-A&lt;&#x2F;h4&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2021&#x2F;power-consumption-of-game-boy-flash-cartridges&#x2F;cart8m_front.jpg&quot;&gt;
  
  &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;gekkio.fi&amp;#x2F;processed_images&amp;#x2F;cart8m_front.bde3c6193640072f.jpg&quot; width=&quot;273&quot; height=&quot;300&quot; &#x2F;&gt;
&lt;&#x2F;a&gt;

&lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2021&#x2F;power-consumption-of-game-boy-flash-cartridges&#x2F;cart8m_pcb_front.jpg&quot;&gt;
  
  &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;gekkio.fi&amp;#x2F;processed_images&amp;#x2F;cart8m_pcb_front.e95a78810e7ea59c.jpg&quot; width=&quot;254&quot; height=&quot;300&quot; &#x2F;&gt;
&lt;&#x2F;a&gt;

&lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2021&#x2F;power-consumption-of-game-boy-flash-cartridges&#x2F;cart8m_pcb_back.jpg&quot;&gt;
  
  &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;gekkio.fi&amp;#x2F;processed_images&amp;#x2F;cart8m_pcb_back.d0bb82030504673a.jpg&quot; width=&quot;251&quot; height=&quot;300&quot; &#x2F;&gt;
&lt;&#x2F;a&gt;
&lt;&#x2F;p&gt;
&lt;p&gt;This is one of my designs and a &quot;maxed-out&quot; design with support for 8 MB ROM and 128 kB save RAM. It only supports MBC5 emulation but can handle the largest ROM&#x2F;RAM official MBC chips can support so any Game Boy game will fit. There&#x27;s no support for RTC or other extra features. The design is intended to be open source but hasn&#x27;t yet been published.&lt;&#x2F;p&gt;
&lt;p&gt;The tested version was GB-CART8M-A v2.1 with an MX29LV640E flash chip and an IS62WV1024E RAM chip.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;test-setup&quot;&gt;Test setup&lt;&#x2F;h2&gt;
&lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2021&#x2F;power-consumption-of-game-boy-flash-cartridges&#x2F;test_setup.jpg&quot;&gt;
  
  &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;gekkio.fi&amp;#x2F;processed_images&amp;#x2F;test_setup.e9823b1aa3f78b42.jpg&quot; width=&quot;799&quot; height=&quot;300&quot; &#x2F;&gt;
&lt;&#x2F;a&gt;
&lt;p&gt;An original Game Boy (DMG) was powered with a &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.rohde-schwarz.com&#x2F;us&#x2F;products&#x2F;test-and-measurement&#x2F;dc-power-supplies&#x2F;rs-hmc804x-dc-power-supply-series_63493-61542.html&quot;&gt;Rohde &amp;amp; Schwarz HMC8043&lt;&#x2F;a&gt; programmable power supply using the DC jack input providing a stable +6V input voltage. The power supply was controlled with SCPI commands via USBTMC by an automated test running on a PC. Testing some cartridges involves going through an initial menu after powering on the system, and in these cases some manual steps were necessary to complete the test.&lt;&#x2F;p&gt;
&lt;p&gt;The used console has the serial number &lt;strong&gt;G38953646&lt;&#x2F;strong&gt;, and uses a B version SoC chip and a type C power board. You can read more details about the test console on its &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;gbhwdb.gekkio.fi&#x2F;consoles&#x2F;dmg&#x2F;G38953646.html&quot;&gt;Game Boy hardware database entry page&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Input voltage and current data was collected using the data logging functionality of HMC8043 with a 1ms sampling interval, which according to the device datasheet results in a resolution of 10mV &#x2F; 1mA. Using a fairly short sampling interval for the raw data allows collecting data about short spikes in current and other fine-grained detail. However, too much detail is not very useful when comparing power consumption from a high-level point of view. For example, with 1ms sampling interval it&#x27;s possible to see even the vblank times of drawn frames, because the Game Boy PPU (= Pixel Processing Unit) consumes less power at that point of time and there&#x27;s a dip in the measured input current! It&#x27;s an interesting research topic, but right now we&#x27;re interested in the more high level differences between cartridges, so a rolling mean with 50ms window was used in postprocessing to smooth out the unnecessary detail from the data.&lt;&#x2F;p&gt;
&lt;p&gt;The following extra steps were taken to minimize potential inconsistencies in the test setup:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;The screen contrast was turned all the way up, so the screen was completely black. If an SD card cartridge was used, I learned in advance how to navigate the menu and load the test ROM without looking at the screen&lt;&#x2F;li&gt;
&lt;li&gt;Audio volume was turned all the way up&lt;&#x2F;li&gt;
&lt;li&gt;The exactly same SD card was used to test all SD flash cartridges. I don&#x27;t know if the cartridges keep the SD card powered when a game is running, but using the same SD card is in any case a good idea for consistency&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3 id=&quot;pseudo-code-of-the-automated-test&quot;&gt;Pseudo-code of the automated test&lt;&#x2F;h3&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #24292E; background-color: #FFFFFF;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;hmc&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;instrument_select&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;Channel&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;Ch3&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;hmc&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;voltage&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt;6.0&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;hmc&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;current&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt;3.0&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;hmc&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;fuse&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt;true&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;hmc&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;voltage_protection&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt;true&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;hmc&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;voltage_protection_level&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;Limit&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;Max&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;hmc&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;power_protection&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt;true&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;hmc&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;power_protection_level&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;Limit&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;Max&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;hmc&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;voltage_ramp&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt;true&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;hmc&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;voltage_ramp_duration&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;Duration&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;from_millis&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt;10&lt;&#x2F;span&gt;&lt;span&gt;))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;hmc&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;output_channel&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt;true&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;hmc&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;log_file&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;&amp;quot;test.csv&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; FileLocation&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;External&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;hmc&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;log_channel&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt;true&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;hmc&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;log_mode&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;LogMode&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;Unlimited&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;hmc&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;log_interval&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;Duration&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;from_millis&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt;100&lt;&#x2F;span&gt;&lt;span&gt;))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;hmc&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;log&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt;true&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;hmc&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;output_master&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt;true&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;pause_until_manual_stop&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;hmc&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;log&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt;false&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;hmc&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;output_master&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt;false&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;power-consumption-at-startup&quot;&gt;Power consumption at startup&lt;&#x2F;h2&gt;
&lt;p&gt;In our first test, we&#x27;ll take a look at the power consumption immediately after the system has powered up before the actual cartridge ROM starts executing. This will give us some idea of static power consumption of the cartridge when the cartridge is not actually being accessed most of the time.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;no-cartridge-inserted-startup-measurement&quot;&gt;No cartridge inserted - startup measurement&lt;&#x2F;h3&gt;
&lt;p&gt;First, let&#x27;s take a look at a measurement done without any cartridge inserted in the system.&lt;&#x2F;p&gt;
&lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2021&#x2F;power-consumption-of-game-boy-flash-cartridges&#x2F;no_cartridge.svg&quot;&gt;
  &lt;img height=&quot;400&quot; src=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2021&#x2F;power-consumption-of-game-boy-flash-cartridges&#x2F;no_cartridge.svg&quot; &gt;
&lt;&#x2F;a&gt;
&lt;p&gt;There are three especially interesting highlights in the figure:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;There is a large initial inrush current immediately after the system has been powered up. This is perfectly normal, but extremely large inrush currents can blow a fuse in a system. Note that the 50ms rolling mean used in data postprocessing actually hides the real peak in the data and we&#x27;re seeing a smoothed version of the peak! The actual peak can be very high and sharp, and could be measured using a different technique. However, this time we&#x27;re not focusing on accurate inrush current testing.&lt;&#x2F;li&gt;
&lt;li&gt;There is another much smaller peak after the initial inrush current has almost settled. I suspect this is caused by the system getting released from reset state, so many things are powering up at the same time.&lt;&#x2F;li&gt;
&lt;li&gt;The third peak is much wider, and is caused by the &quot;cha ding!&quot; sound after the logo has scrolled down. Since we&#x27;re using the system at max volume, we can sometimes see the audio the console is playing as input power variations in the data!&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;If we ignore the peaks and look at the more stable time periods, it looks like the system input power normally hovers around ~235 mW. The peaks are also interesting and especially the third peak will be important in later tests, because the &quot;cha ding!&quot; sound will be used to align measurements from different flash carts.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;genuine-cartridges-startup-measurement&quot;&gt;Genuine cartridges - startup measurement&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2021&#x2F;power-consumption-of-game-boy-flash-cartridges&#x2F;genuine_startup.svg&quot;&gt;
  &lt;img height=&quot;400&quot; src=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2021&#x2F;power-consumption-of-game-boy-flash-cartridges&#x2F;genuine_startup.svg&quot; &gt;
&lt;&#x2F;a&gt;

&lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2021&#x2F;power-consumption-of-game-boy-flash-cartridges&#x2F;genuine_startup_zoom.svg&quot;&gt;
  &lt;img height=&quot;400&quot; src=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2021&#x2F;power-consumption-of-game-boy-flash-cartridges&#x2F;genuine_startup_zoom.svg&quot; &gt;
&lt;&#x2F;a&gt;
&lt;&#x2F;p&gt;
&lt;p&gt;It looks like Tetris consumes almost no extra power compared to having no cartridge inserted, while Pokemon Blue and Wario Land II consume slightly more with the normal input power hovering around ~250 mW. It also seems like Pokemon Blue might be consuming a tiny amount more than Wario Land II, but this difference is very minor.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;reproduction-pokemon-blue-startup-measurement&quot;&gt;Reproduction Pokemon Blue - startup measurement&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2021&#x2F;power-consumption-of-game-boy-flash-cartridges&#x2F;repro_startup.svg&quot;&gt;
  &lt;img height=&quot;400&quot; src=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2021&#x2F;power-consumption-of-game-boy-flash-cartridges&#x2F;repro_startup.svg&quot; &gt;
&lt;&#x2F;a&gt;

&lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2021&#x2F;power-consumption-of-game-boy-flash-cartridges&#x2F;repro_startup_zoom.svg&quot;&gt;
  &lt;img height=&quot;400&quot; src=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2021&#x2F;power-consumption-of-game-boy-flash-cartridges&#x2F;repro_startup_zoom.svg&quot; &gt;
&lt;&#x2F;a&gt;
&lt;&#x2F;p&gt;
&lt;p&gt;The reproduction cart is interesting: &lt;em&gt;it consumes less power than the genuine cart&lt;&#x2F;em&gt; in the startup measurement.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;gekkio-flash-carts-startup-measurement&quot;&gt;Gekkio flash carts - startup measurement&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2021&#x2F;power-consumption-of-game-boy-flash-cartridges&#x2F;gekkio_startup.svg&quot;&gt;
  &lt;img height=&quot;400&quot; src=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2021&#x2F;power-consumption-of-game-boy-flash-cartridges&#x2F;gekkio_startup.svg&quot; &gt;
&lt;&#x2F;a&gt;

&lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2021&#x2F;power-consumption-of-game-boy-flash-cartridges&#x2F;gekkio_startup_zoom.svg&quot;&gt;
  &lt;img height=&quot;400&quot; src=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2021&#x2F;power-consumption-of-game-boy-flash-cartridges&#x2F;gekkio_startup_zoom.svg&quot; &gt;
&lt;&#x2F;a&gt;
&lt;&#x2F;p&gt;
&lt;p&gt;My flash cart designs consume very little power in this test and are roughly comparable to having no cartridge, although if we zoom in, we can see the flash carts consuming a tiny bit more power. GB-CART8M-A consumes slightly more power than the other two, and it looks like GB-CART256K-A might just barely lose to GB-CART32K-A.&lt;&#x2F;p&gt;
&lt;p&gt;This figure also shows an interesting extra detail: GB-CART8M-A has different behaviour than others and generates different kinds of peaks. Firstly, the smaller peak after the large inrush current event is missing, and we actually see &lt;em&gt;a wide dip&lt;&#x2F;em&gt; until the input power goes to the normal state. The &quot;cha ding!&quot; sound peak also happens later but looks otherwise normal. These differences are caused by power supervisor circuitry in GB-CART8M-A, which keeps the system in reset state until the system voltage has been stable for a certain duration of time. This is a safety feature to help keep inrush current at reasonable levels, and to ensure the cartridge has a stable voltage before it starts doing anything important. Genuine carts that support saves also have a supervisor mechanism to help keep your save games safe, but they use different kind of chips which get out of reset state much more quickly, so we don&#x27;t see the behaviour in the figure in this test scenario.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;ems64m-startup-measurement&quot;&gt;EMS64M - startup measurement&lt;&#x2F;h3&gt;
&lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2021&#x2F;power-consumption-of-game-boy-flash-cartridges&#x2F;ems64m_startup.svg&quot;&gt;
  &lt;img height=&quot;400&quot; src=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2021&#x2F;power-consumption-of-game-boy-flash-cartridges&#x2F;ems64m_startup.svg&quot; &gt;
&lt;&#x2F;a&gt;
&lt;p&gt;Like GB-CART8M-A, EMS64M seems to have some kind of supervisor circuitry on the cartridge, but it results in a narrower dip during startup and the &quot;cha ding!&quot; sound peak has less delay than GB-CART8M-A does. Overall the cartridge consumes more power than the genuine carts, my flash carts, and the reproduction cart. However, the difference isn&#x27;t huge, so I&#x27;d say EMS64M performs pretty well in this measurement.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;everdrive-gb-startup-measurement&quot;&gt;Everdrive GB - startup measurement&lt;&#x2F;h3&gt;
&lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2021&#x2F;power-consumption-of-game-boy-flash-cartridges&#x2F;everdrive_startup.svg&quot;&gt;
  &lt;img height=&quot;400&quot; src=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2021&#x2F;power-consumption-of-game-boy-flash-cartridges&#x2F;everdrive_startup.svg&quot; &gt;
&lt;&#x2F;a&gt;
&lt;p&gt;The original Everdrive cartridge generates a curve shaped very much like the previously tested cartridges. However, there&#x27;s a &lt;em&gt;massive&lt;&#x2F;em&gt; vertical offset so the cartridge consumes a lot more power than the others. The normal stable input power in this measurement was around ~465 mW, which is almost double compared to a genuine Tetris cartridge!&lt;&#x2F;p&gt;
&lt;h3 id=&quot;everdrive-gb-x5-startup-measurement&quot;&gt;Everdrive GB X5 - startup measurement&lt;&#x2F;h3&gt;
&lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2021&#x2F;power-consumption-of-game-boy-flash-cartridges&#x2F;everdrive_x5_startup.svg&quot;&gt;
  &lt;img height=&quot;400&quot; src=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2021&#x2F;power-consumption-of-game-boy-flash-cartridges&#x2F;everdrive_x5_startup.svg&quot; &gt;
&lt;&#x2F;a&gt;
&lt;p&gt;Everdrive X5 performs much better than the original Everdrive, bringing the power consumption closer to the competition. However, it still loses to genuine cartridges, EMS64M, and my designs.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;ez-flash-junior-startup-measurement&quot;&gt;EZ-FLASH Junior - startup measurement&lt;&#x2F;h3&gt;
&lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2021&#x2F;power-consumption-of-game-boy-flash-cartridges&#x2F;ezflash_startup.svg&quot;&gt;
  &lt;img height=&quot;400&quot; src=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2021&#x2F;power-consumption-of-game-boy-flash-cartridges&#x2F;ezflash_startup.svg&quot; &gt;
&lt;&#x2F;a&gt;
&lt;p&gt;EZ-FLASH Junior has the worst performance of all in this measurement. Input power during inrush current event goes off the chart, it consumes overall the most input power of all tested cartridges, and the input power does not even seem to fully stabilize during the test time. Not great at all.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;power-consumption-of-tetris&quot;&gt;Power consumption of Tetris&lt;&#x2F;h2&gt;
&lt;p&gt;In this second test we measure power consumption of various carts when Tetris (v1.1, the more common version) is being played. The measurement data has been aligned to start from the &quot;cha ding!&quot; sound peak to make different cartridges easy to compare. This is necessary, because some carts keep the system in reset state for some time during startup, and the SD card -based flash carts need to go through a menu before they load the correct ROM.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;genuine-cartridge-tetris&quot;&gt;Genuine cartridge - Tetris&lt;&#x2F;h3&gt;
&lt;p&gt;Let&#x27;s start with the genuine cartridge so we can understand what the power consumption graph looks like by default.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2021&#x2F;power-consumption-of-game-boy-flash-cartridges&#x2F;genuine_tetris.svg&quot;&gt;
  &lt;img height=&quot;400&quot; src=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2021&#x2F;power-consumption-of-game-boy-flash-cartridges&#x2F;genuine_tetris.svg&quot; &gt;
&lt;&#x2F;a&gt;

&lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2021&#x2F;power-consumption-of-game-boy-flash-cartridges&#x2F;genuine_tetris_zoom.svg&quot;&gt;
  &lt;img height=&quot;400&quot; src=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2021&#x2F;power-consumption-of-game-boy-flash-cartridges&#x2F;genuine_tetris_zoom.svg&quot; &gt;
&lt;&#x2F;a&gt;
&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;After the &quot;cha ding!&quot;, this is where the boot ROM code embedded in the console ends, and the code on the cartridge starts executing. Power consumption goes up because data gets read from the cartridge very often and this consumes more power than the cartridge being just on standby. The exact behaviour depends on what the cartridge code is doing, but in the case of Tetris, the code makes some preparations, shows the &quot;copyright screen&quot; which has no music, and simply waits for a couple of seconds in a hot loop executing from the cartridge.&lt;&#x2F;li&gt;
&lt;li&gt;This is where the title screen is shown and music starts to play. Audio consumes some extra power, and you can even see many of the individual notes of the title screen melody in the power graph if you look carefully and try to imagine the music in your head!&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;h3 id=&quot;gekkio-flash-carts-tetris&quot;&gt;Gekkio flash carts - Tetris&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2021&#x2F;power-consumption-of-game-boy-flash-cartridges&#x2F;gekkio_tetris.svg&quot;&gt;
  &lt;img height=&quot;400&quot; src=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2021&#x2F;power-consumption-of-game-boy-flash-cartridges&#x2F;gekkio_tetris.svg&quot; &gt;
&lt;&#x2F;a&gt;

&lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2021&#x2F;power-consumption-of-game-boy-flash-cartridges&#x2F;gekkio_tetris_zoom.svg&quot;&gt;
  &lt;img height=&quot;400&quot; src=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2021&#x2F;power-consumption-of-game-boy-flash-cartridges&#x2F;gekkio_tetris_zoom.svg&quot; &gt;
&lt;&#x2F;a&gt;
&lt;&#x2F;p&gt;
&lt;p&gt;My flash carts remain competitive with the genuine cart, but do consume slightly more power. In startup measurements differences between my flash carts were very tiny, but here you can clearly see the flash carts ordered by power consumption: GB-CART32K-A consumes the least, and GB-CART8M-A and consumes the most.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;For simplicity, I&#x27;ll leave out GB-CART32K-A and GB-CART256K-A from further comparisons and only include the &quot;worst&quot; of my flash carts: GB-CART8M-A.&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;h3 id=&quot;the-grand-power-consumption-comparison-tetris&quot;&gt;The grand power consumption comparison - Tetris&lt;&#x2F;h3&gt;
&lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2021&#x2F;power-consumption-of-game-boy-flash-cartridges&#x2F;all_tetris.svg&quot;&gt;
  &lt;img height=&quot;400&quot; src=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2021&#x2F;power-consumption-of-game-boy-flash-cartridges&#x2F;all_tetris.svg&quot; &gt;
&lt;&#x2F;a&gt;
&lt;p&gt;Unsurprisingly all flash carts lose to the genuine cart, but there&#x27;s a large amount of variation between different carts. As an example, if we calculate the mean power consumption in the 2s - 9s time interval and compare the flash carts to genuine Tetris, we get the following relative power consumption values:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;GB-CART8M-A: +6%&lt;&#x2F;li&gt;
&lt;li&gt;Everdrive GB X5: +30%&lt;&#x2F;li&gt;
&lt;li&gt;EZ-FLASH Junior: +66%&lt;&#x2F;li&gt;
&lt;li&gt;EMS64M: +96%&lt;&#x2F;li&gt;
&lt;li&gt;Everdrive GB: +120%&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;If we assume the relative power consumption remains roughly similar all the time, using an original Everdrive to play Tetris gives you &lt;em&gt;less than half&lt;&#x2F;em&gt; the battery life compared to a genuine cart.&lt;&#x2F;p&gt;
&lt;p&gt;It&#x27;s also interesting that EMS64M starts with much lower power consumption during the &quot;cha ding!&quot; sound, but then the power consumption increases massively. When the game is actually running, it manages to only beat the original Everdrive. It seems that the cartridge has reasonable static power consumption but very high dynamic power consumption.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;power-consumption-of-wario-land-ii&quot;&gt;Power consumption of Wario Land II&lt;&#x2F;h2&gt;
&lt;p&gt;Now, let&#x27;s take a look at a more complicated game: Wario Land II.&lt;&#x2F;p&gt;
&lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2021&#x2F;power-consumption-of-game-boy-flash-cartridges&#x2F;all_wario.svg&quot;&gt;
  &lt;img height=&quot;400&quot; src=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2021&#x2F;power-consumption-of-game-boy-flash-cartridges&#x2F;all_wario.svg&quot; &gt;
&lt;&#x2F;a&gt;
&lt;ol&gt;
&lt;li&gt;At this point something strange happens: the genuine cart and GB-CART8M-A show a narrow power consumption peak, while all other flash carts have a wider peak and the rest of the figure is delayed slightly. This suggests the other flash carts end up executing slightly different code for some reason. I don&#x27;t have a good explanation for this, but I suspect the flash carts may have initialized the save RAM contents with zeroes or some other pattern, and the RAM contains a different kind of pattern than in the other carts. If the code is calculating a checksum of the RAM contents or something like that, the code might take different amount of time to execute depending on the RAM contents.&lt;&#x2F;li&gt;
&lt;li&gt;This is where the intro animation with clouds and music starts. The power consumption of EMS64M drops significantly, which might be caused by the CPU spending more time sleeping in HALT mode instead of reading bytes from the cartridge all the time.&lt;&#x2F;li&gt;
&lt;li&gt;This is where the music changes and an island appears from behind the clouds. Once again, the power consumption of EMS64M drops. I suspect that playing back the different kind of music here requires reading less bytes from the cartridge, so the CPU is spending even more time sleeping in HALT mode.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;In most cases the power consumption looks quite similar to Tetris. This makes sense, because a more complicated game with a bigger ROM and&#x2F;or RAM probably won&#x27;t greatly affect power consumption of a flash cartridge. However, EMS64M ranks a bit more favourably here than with Tetris, possibly due to the CPU HALT mode reducing dynamic power consumption as suggested earlier. Also, this time GB-CART8M-A beats the genuine cart. The difference is very small, but this proves a flash cart can consume less power than a genuine cart!&lt;&#x2F;p&gt;
&lt;h2 id=&quot;power-consumption-of-pokemon-blue&quot;&gt;Power consumption of Pokemon Blue&lt;&#x2F;h2&gt;
&lt;p&gt;Finally, let&#x27;s test Pokemon Blue. This time a repro cart is also included.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;genuine-vs-repro-pokemon-blue&quot;&gt;Genuine vs repro - Pokemon Blue&lt;&#x2F;h3&gt;
&lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2021&#x2F;power-consumption-of-game-boy-flash-cartridges&#x2F;genuine_vs_repro_blue.svg&quot;&gt;
  &lt;img height=&quot;400&quot; src=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2021&#x2F;power-consumption-of-game-boy-flash-cartridges&#x2F;genuine_vs_repro_blue.svg&quot; &gt;
&lt;&#x2F;a&gt;
&lt;p&gt;I honestly didn&#x27;t expect the repro to beat the genuine cart in power consumption, but it has a slight advantage here. It&#x27;s also worth noting that the repro figure shape looks a bit different, because it&#x27;s executing a patched ROM and not the original genuine ROM. This repro cart uses only flash memory and doesn&#x27;t have battery-backed save RAM on the circuit board, so it needs a patched ROM which uses a portion of the flash memory as &quot;save RAM&quot;.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;the-grand-power-consumption-comparison-pokemon-blue&quot;&gt;The grand power consumption comparison - Pokemon Blue&lt;&#x2F;h3&gt;
&lt;p&gt;Now that we&#x27;ve looked at the repro, we can drop it from the test and focus on the flash cartridges.&lt;&#x2F;p&gt;
&lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2021&#x2F;power-consumption-of-game-boy-flash-cartridges&#x2F;all_blue.svg&quot;&gt;
  &lt;img height=&quot;400&quot; src=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2021&#x2F;power-consumption-of-game-boy-flash-cartridges&#x2F;all_blue.svg&quot; &gt;
&lt;&#x2F;a&gt;
&lt;p&gt;This flash cart test with Pokemon Blue tells a similar story as Wario Land II, but with one big difference: this time EMS64M is actually competing with Everdrive GB X5 during most of the time in the test! Perhaps Pokemon Blue intro spends even less time reading cartridge bytes than Wario Land II? I don&#x27;t think this result improves my general opinion of EMS64M, but it confirms its power consumption can vary greatly depending on how often and in what manner the cartridge is accessed.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;conclusions&quot;&gt;Conclusions&lt;&#x2F;h2&gt;
&lt;p&gt;All the tested flash carts except EMS64M had fairly stable behaviour so it&#x27;s possible to rank them from best to worst based on these power consumption tests.&lt;&#x2F;p&gt;
&lt;p&gt;My cartridge designs prove that flash carts can consume less power than genuine cartridges, but they are are not widely available and are mostly interesting to people with the right skills and equipment to assemble them. The best widely available flash cartridge seems to be Everdrive GB X5, which is a massive improvement compared to the original Everdrive GB, which in turn was the worst cartridge. EZ-FLASH Junior was disappointing, and I was personally expecting it to perform much better. EMS64M power consumption varied greatly, so battery life depends on what game you play and how the game has been programmed.&lt;&#x2F;p&gt;
&lt;p&gt;My personal recommendations in case you&#x27;re looking to buy a flash cartridge:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Don&#x27;t buy the original Everdrive GB or any of its clones. I&#x27;ve heard some clones have a &quot;power saving module&quot; (most likely a switching regulator), but I don&#x27;t think it can make a big enough difference if the design is otherwise the same&lt;&#x2F;li&gt;
&lt;li&gt;If you want an SD-card based flash cart, buy an Everdrive GB X-series cartridge if you can afford it. If you go with EZ-FLASH Junior, be prepared for a much lower battery life and potential problems if you have modded your console&lt;&#x2F;li&gt;
&lt;li&gt;Avoid EMS64M&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3 id=&quot;raw-csv-data-files&quot;&gt;Raw CSV data files&lt;&#x2F;h3&gt;
&lt;p&gt;Here are the raw data files of all measurements. Note that these files have not been postprocessed with the 50ms rolling mean mentioned earlier, so there&#x27;s more fine detail and fast transients than in the figures shown in this blog post.&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2021&#x2F;power-consumption-of-game-boy-flash-cartridges&#x2F;no_cartridge.csv&quot;&gt;No cartridge&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;Genuine cart: &lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2021&#x2F;power-consumption-of-game-boy-flash-cartridges&#x2F;genuine_tetris.csv&quot;&gt;Tetris&lt;&#x2F;a&gt;, &lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2021&#x2F;power-consumption-of-game-boy-flash-cartridges&#x2F;genuine_wario.csv&quot;&gt;Wario Land II&lt;&#x2F;a&gt;, &lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2021&#x2F;power-consumption-of-game-boy-flash-cartridges&#x2F;genuine_blue.csv&quot;&gt;Pokemon Blue&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;Reproduction cart: &lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2021&#x2F;power-consumption-of-game-boy-flash-cartridges&#x2F;repro_blue.csv&quot;&gt;Pokemon Blue&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;GB-CART32K-A: &lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2021&#x2F;power-consumption-of-game-boy-flash-cartridges&#x2F;gb_cart32k_tetris.csv&quot;&gt;Tetris&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;GB-CART256K-A: &lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2021&#x2F;power-consumption-of-game-boy-flash-cartridges&#x2F;gb_cart256k_tetris.csv&quot;&gt;Tetris&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;GB-CART8M-A: &lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2021&#x2F;power-consumption-of-game-boy-flash-cartridges&#x2F;gb_cart8m_tetris.csv&quot;&gt;Tetris&lt;&#x2F;a&gt;, &lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2021&#x2F;power-consumption-of-game-boy-flash-cartridges&#x2F;gb_cart8m_wario.csv&quot;&gt;Wario Land II&lt;&#x2F;a&gt;, &lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2021&#x2F;power-consumption-of-game-boy-flash-cartridges&#x2F;gb_cart8m_blue.csv&quot;&gt;Pokemon Blue&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;EMS64M: &lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2021&#x2F;power-consumption-of-game-boy-flash-cartridges&#x2F;ems64m_tetris.csv&quot;&gt;Tetris&lt;&#x2F;a&gt;, &lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2021&#x2F;power-consumption-of-game-boy-flash-cartridges&#x2F;ems64m_wario.csv&quot;&gt;Wario Land II&lt;&#x2F;a&gt;, &lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2021&#x2F;power-consumption-of-game-boy-flash-cartridges&#x2F;ems64m_blue.csv&quot;&gt;Pokemon Blue&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;Everdrive GB: &lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2021&#x2F;power-consumption-of-game-boy-flash-cartridges&#x2F;everdrive_tetris.csv&quot;&gt;Tetris&lt;&#x2F;a&gt;, &lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2021&#x2F;power-consumption-of-game-boy-flash-cartridges&#x2F;everdrive_wario.csv&quot;&gt;Wario Land II&lt;&#x2F;a&gt;, &lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2021&#x2F;power-consumption-of-game-boy-flash-cartridges&#x2F;everdrive_blue.csv&quot;&gt;Pokemon Blue&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;Everdrive GB X5: &lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2021&#x2F;power-consumption-of-game-boy-flash-cartridges&#x2F;everdrive_x5_tetris.csv&quot;&gt;Tetris&lt;&#x2F;a&gt;, &lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2021&#x2F;power-consumption-of-game-boy-flash-cartridges&#x2F;everdrive_x5_wario.csv&quot;&gt;Wario Land II&lt;&#x2F;a&gt;, &lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2021&#x2F;power-consumption-of-game-boy-flash-cartridges&#x2F;everdrive_x5_blue.csv&quot;&gt;Pokemon Blue&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;EZ-FLASH Junior: &lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2021&#x2F;power-consumption-of-game-boy-flash-cartridges&#x2F;ezflash_tetris.csv&quot;&gt;Tetris&lt;&#x2F;a&gt;, &lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2021&#x2F;power-consumption-of-game-boy-flash-cartridges&#x2F;ezflash_wario.csv&quot;&gt;Wario Land II&lt;&#x2F;a&gt;, &lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2021&#x2F;power-consumption-of-game-boy-flash-cartridges&#x2F;ezflash_blue.csv&quot;&gt;Pokemon Blue&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;tl-dr&quot;&gt;TL;DR&lt;&#x2F;h2&gt;
&lt;ul&gt;
&lt;li&gt;In these tests, Everdrive GB X5 was the best widely available flash cartridge&lt;&#x2F;li&gt;
&lt;li&gt;GB-CART8M-A proves a flash cartridge can consume &lt;em&gt;less power&lt;&#x2F;em&gt; than a genuine cartridge&lt;&#x2F;li&gt;
&lt;li&gt;A repro cart can also consume less power than a genuine cartridge. Note: this doesn&#x27;t mean using repro carts is a good idea, unless you treat the cartridges and your save games as disposable goods&lt;&#x2F;li&gt;
&lt;li&gt;Typical power consumption ranking (ordered from least consuming to most consuming; EMS64M is not ranked; numbers are based on Pokemon Blue):
&lt;ol&gt;
&lt;li&gt;GB-CART8M-A (around -5% vs genuine)&lt;&#x2F;li&gt;
&lt;li&gt;Genuine cartridge&lt;&#x2F;li&gt;
&lt;li&gt;Everdrive GB X5 (around +25% vs genuine)&lt;&#x2F;li&gt;
&lt;li&gt;EZ-FLASH Junior (around +75% vs genuine)&lt;&#x2F;li&gt;
&lt;li&gt;Everdrive GB (around +120% vs genuine)&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;EMS64M power consumption varies greatly depending on what the ROM on the cartridge is doing, but it seems to always lose to Everdrive GB X5 and more power efficient cartridges&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>HHL Bivert Module V2 - technical review</title>
        <published>2020-08-22T00:00:00+00:00</published>
        <updated>2020-08-22T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Joonas Javanainen
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://gekkio.fi/blog/2020/hhl-bivert-v2-technical-review/"/>
        <id>https://gekkio.fi/blog/2020/hhl-bivert-v2-technical-review/</id>
        
        <content type="html" xml:base="https://gekkio.fi/blog/2020/hhl-bivert-v2-technical-review/">&lt;p&gt;Biverting a greyscale Game Boy screen is a very popular mod, because it&#x27;s widely
considered to increase the screen contrast. The principle of biverting is
fairly simple: we invert the LCD pixels once digitally, and then again
optically. As a result, the pixels have the originally intended colors just
like without biverting (black is black, light grey is light grey, etc...). This
mod might sound pointless at first, but since the second inversion is done
optically, the screen behaves slightly differently and contrast is improved.
For the first inversion, we need a circuit that inverts the digital values of
the pixels pushed to the screen, and to achieve the second inversion, we can
simply rotate the screen polarizer 90 degrees.&lt;&#x2F;p&gt;
&lt;div class=&quot;framed&quot;&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2020&#x2F;hhl-bivert-v2-technical-review&#x2F;bivert.svg&quot; alt=&quot;Biverting diagram&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;The popularity of this mod has given rise to several bivert boards (sometimes
incorrectly referred to as &quot;chips&quot;). In this review I&#x27;ll take a look at Bivert
Module V2 by Hand-Held Legend and see how good it is from a technical point of
view. Even a bare chip and several wires can do the job, but there are slight
differences in the results depending on how well the circuit is designed and
what components have been chosen. A simple well-designed board can make
biverting much easier than using a bare chip.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;hhl-store-page-captured-on-2020-04-25&quot;&gt;HHL store page (captured on 2020-04-25)&lt;&#x2F;h2&gt;
&lt;p&gt;First, here&#x27;s a captured screenshot of the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;handheldlegend.com&#x2F;products&#x2F;game-boy-bivert-biversion-module&quot;&gt;HHL store
page&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;div class=&quot;framed&quot;&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2020&#x2F;hhl-bivert-v2-technical-review&#x2F;store-screenshot.png&quot; alt=&quot;HHL store screenshot&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;And this is the description of the module:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Bivert modules are an effective way to upgrade the appearance of your LCD
display. This easy to install module increases contrast by biverting
(inverting) the orientation of the pixels of your screen. Once installed,
pixels will have a blue appearance and enhanced gray scale saturation. The
board lies flat on the PCB and lines up with the exact solder points you need
to use!&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;0.6mm board - super thin!&lt;&#x2F;li&gt;
&lt;li&gt;2mm added to the bottom of the board for easy soldering (V1 -&amp;gt; V2)&lt;&#x2F;li&gt;
&lt;li&gt;Compatible with the Game Boy Original (DMG) and the Game Boy Pocket (MGB)
(Extra wires needed)&lt;&#x2F;li&gt;
&lt;li&gt;Only 1 wire required for install in the DMG | 1 Wire is included!&lt;&#x2F;li&gt;
&lt;li&gt;Hex inverter is already soldered for you&lt;&#x2F;li&gt;
&lt;li&gt;Grounding for the remaining pins for increased reliability&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;blockquote&gt;
&lt;h3 id=&quot;store-page-analysis&quot;&gt;Store page analysis&lt;&#x2F;h3&gt;
&lt;p&gt;Based on the photo, we can see that the board has only one component: an
Nexperia 74HC04D chip. This chip is a &lt;em&gt;hex inverter&lt;&#x2F;em&gt;: basically 6 digital
inverter circuits in one package (hex = 6, see
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;6#Hexa&quot;&gt;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;6#Hexa&lt;&#x2F;a&gt;).  Each inverter circuit has one digital
input and one digital output, and the chip also has one power pin and one
ground pin which are shared by all the six inverters in the same package. A
perfectly fine chip for the job, although we&#x27;ll see later in this review why
there are better alternatives.&lt;&#x2F;p&gt;
&lt;p&gt;The description on the store page is mostly fine, although it sounds slightly
inaccurate from a technical point of view. What does &quot;biverting the orientation
of the pixels&quot; mean? Orientation usually refers to relative position or
direction, which is something this board doesn&#x27;t change. The text also seems to
suggest biverting is the same as inverting, which it&#x27;s not.&lt;&#x2F;p&gt;
&lt;p&gt;Another slightly problematic part of the description is &quot;grounding for the
remaining pins for increased reliability&quot;. What are the remaining pins, and how
is reliability increased by grounding them? We&#x27;ll see later in this review what
this means and more importantly, what it doesn&#x27;t mean.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;board-analysis&quot;&gt;Board analysis&lt;&#x2F;h2&gt;
&lt;div class=&quot;framed&quot;&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2020&#x2F;hhl-bivert-v2-technical-review&#x2F;board.jpg&quot; alt=&quot;Board&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;I bought one of these boards back in 2016 when I was doing backlight mods to
some Game Boys. This 2016 module looks exactly like the one in the store photo,
so presumably the design is still the same.&lt;&#x2F;p&gt;
&lt;p&gt;By using the continuity function of my multimeter, I checked all the
connections on the board, and ended up with the following photo with different
signals emphasized with different colours (next to the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;assets.nexperia.com&#x2F;documents&#x2F;data-sheet&#x2F;74HC_HCT04.pdf&quot;&gt;chip
datasheet&lt;&#x2F;a&gt;
pinout for reference):&lt;&#x2F;p&gt;
&lt;div class=&quot;framed&quot;&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2020&#x2F;hhl-bivert-v2-technical-review&#x2F;board_colored.jpg&quot; alt=&quot;Board with signals marked with colours&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;framed&quot;&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2020&#x2F;hhl-bivert-v2-technical-review&#x2F;chip_pinout.png&quot; alt=&quot;74HC04D chip pinout&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;As you can see, the board is very simple. We have three round holes for VCC and
the inputs, one pad for GND, and two pads on the bottom edge for the outputs.
Every connection is between just two points, so this is pretty much a minimal
design needed for the use case. In the chip pinout, &quot;A&quot; signals are the inputs,
and &quot;Y&quot; signals are the outputs. VCC is the main power supply (+5V in this
case), and GND is the ground connection. Note also how more than half of the
chip pins have no connections (3A, 3Y, 4A, 4Y, 5A, 5Y, 6A, 6Y): they are just
soldered to pads which are not connected electrically to anything.&lt;&#x2F;p&gt;
&lt;p&gt;If this board was designed by me, I would&#x27;ve added a bypass capacitor next to
the chip for power supply smoothing since it adds only a tiny cost to the
board. Luckily the board is mounted very close to a ceramic bypass capacitor on
the Game Boy mainboard, so having no bypass capacitor here is not the end of
the world.&lt;&#x2F;p&gt;
&lt;div class=&quot;framed&quot;&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2020&#x2F;hhl-bivert-v2-technical-review&#x2F;HHL_schematic.png&quot; alt=&quot;HHL board schematic&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;h2 id=&quot;the-main-design-fault-a-k-a-how-hard-can-it-be-to-invert-two-digital-signals&quot;&gt;The main design fault (a.k.a &quot;how hard can it be to invert two digital signals?&quot;)&lt;&#x2F;h2&gt;
&lt;p&gt;At first, the circuit design might seem perfectly reasonable, because it does
what it is supposed to do: it inverts two digital signals. However, some
problems arise from the choice of using a &lt;em&gt;hex inverter chip&lt;&#x2F;em&gt; (6 digital
inverters) when only two inverters are required to do the job. This means 4 out
of 6 inverter circuits on the chip are unused, and we have a total of 4 unused
inputs and 4 unused outputs. The problem with unused pins is that you can&#x27;t
assume they can just be left unconnected. Especially &lt;em&gt;floating inputs&lt;&#x2F;em&gt;
(basically inputs that are not connected to a stable voltage level of some
sort) can lead to seemingly random problems.&lt;&#x2F;p&gt;
&lt;p&gt;Integrated circuits (IC) chips come in many technologies and families, but
today almost everything uses CMOS technology. In general, &lt;strong&gt;CMOS inputs should
not float&lt;&#x2F;strong&gt;, so unless some extra circuitry is providing a valid voltage level
to an input, it should not be left unconnected. Some people mistakenly think
that an unconnected pin is at 0V voltage level and it would be the same as
connecting the pin to ground, but this is not true.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;grounding-for-the-remaining-pins-for-increased-reliability&quot;&gt;&quot;Grounding for the remaining pins for increased reliability&quot;&lt;&#x2F;h3&gt;
&lt;p&gt;Let&#x27;s go back to this statement on the store page... Grounding means creating
an electrical connection between something and a common ground point. A circuit
might actually have multiple grounds, but in this case there is only one common
ground, conveniently labeled as &quot;GND&quot; on the board. So, when they say
&quot;remaining pins are grounded&quot;, I immediately assume those pins have a
connection to GND. However, the previously conducted continuity test with a
multimeter confirmed that the unused pins are not connected electrically to
anything on this board.&lt;&#x2F;p&gt;
&lt;p&gt;So, when they say &quot;grounding for the remaining pins&quot;, they just mean those pins
are soldered to pads on the board and not left completely unsoldered. Compared
to using a bare chip and wires, having all pins soldered to a board does
decrease the risk of them touching something accidentally, which kinda
&lt;em&gt;&quot;increases reliability&quot;&lt;&#x2F;em&gt;. But this is &lt;strong&gt;not the same as grounding them&lt;&#x2F;strong&gt;. Note
that connecting all unused pins of a chip to GND is not what you should do
either, because unused &lt;em&gt;outputs&lt;&#x2F;em&gt; are better left unconnected!&lt;&#x2F;p&gt;
&lt;h3 id=&quot;handling-unused-pins&quot;&gt;Handling unused pins&lt;&#x2F;h3&gt;
&lt;p&gt;What should we do with unused pins then? The &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;assets.nexperia.com&#x2F;documents&#x2F;data-sheet&#x2F;74HC_HCT04.pdf&quot;&gt;chip
datasheet&lt;&#x2F;a&gt;
doesn&#x27;t have any info about handling unused pins, but Nexperia has a convenient
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;assets.nexperia.com&#x2F;documents&#x2F;user-manual&#x2F;HCT_USER_GUIDE.pdf&quot;&gt;74HC&#x2F;HCT&#x2F;HCU family user
guide&lt;&#x2F;a&gt;,
which has the information we&#x27;re looking for:&lt;&#x2F;p&gt;
&lt;div class=&quot;framed&quot;&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2020&#x2F;hhl-bivert-v2-technical-review&#x2F;nxp_hc_user_guide.png&quot; alt=&quot;74HC user guide mandates unused input termination&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;So, Nexperia&#x27;s own documentation says &lt;strong&gt;floating inputs are bad&lt;&#x2F;strong&gt;, and since
we&#x27;re dealing with a 74HC family chip, we can just connect unused inputs
directly to either VCC or GND to properly terminate them.&lt;&#x2F;p&gt;
&lt;p&gt;74HC04 is a very common chip manufactured by many companies, so what about some
other manufacturers? Texas Instruments has some information directly in the
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.ti.com&#x2F;lit&#x2F;ds&#x2F;symlink&#x2F;sn74hc04.pdf&quot;&gt;SN74HC04 datasheet&lt;&#x2F;a&gt;:&lt;&#x2F;p&gt;
&lt;div class=&quot;framed&quot;&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2020&#x2F;hhl-bivert-v2-technical-review&#x2F;ti_sn74hc04_1.png&quot; alt=&quot;&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;framed&quot;&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2020&#x2F;hhl-bivert-v2-technical-review&#x2F;ti_sn74hc04_2.png&quot; alt=&quot;&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;TI also says &lt;strong&gt;floating inputs are bad&lt;&#x2F;strong&gt;, and specifically mention multi-input
chips with only some part of the chip used.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;real-world-measurements&quot;&gt;Real-world measurements&lt;&#x2F;h2&gt;
&lt;p&gt;We know that floating inputs are bad from a theoretical point of view, but
surely it can&#x27;t be that bad since so many people have installed the HHL V2
bivert boards without problems...?&lt;&#x2F;p&gt;
&lt;p&gt;The good news is that in many cases you just get more power consumption and
possibly a bit more noise in the system. The bad news is that the overall
results are a bit random since they depend on the environment. The floating
inputs are basically like antennas and will pick up noise that then gets
inverted. As long as the Game Boy doesn&#x27;t burst into flames, people don&#x27;t
necessarily even notice the problems caused by this bivert module. But in the
absolute worst case, I can imagine something getting fried due to excessive
power consumption.&lt;&#x2F;p&gt;
&lt;p&gt;To conduct some real-world tests, I soldered wires to a backlit Game Boy that
has an inverted polarizer, so it just needs some kind of digital inverter to
complete the bivert solution. This setup allowed me to change the inverter
chip&#x2F;board easily. I also soldered wires to the HHL board so it could be
plugged to a breadboard. In all tests, the VCC line was not connected directly
to the chip&#x2F;board but via a multimeter in series so current measurement was
possible.&lt;&#x2F;p&gt;
&lt;div class=&quot;framed&quot;&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2020&#x2F;hhl-bivert-v2-technical-review&#x2F;test_dmg.jpg&quot; alt=&quot;Game Boy used in the tests&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;h3 id=&quot;testing-the-hhl-board&quot;&gt;Testing the HHL board&lt;&#x2F;h3&gt;
&lt;p&gt;In this first test I simply connected the HHL board to the Game Boy using a
breadboard. Note: this setup performs slightly worse than a real bivert module
installation, because there&#x27;s fairly long wires that can pick up noise and
there&#x27;s also no decoupling capacitor nearby.&lt;&#x2F;p&gt;
&lt;p&gt;When turning on the Game Boy without any cartridge inserted, we can see a
wildly changing input current between 1-5 mA.&lt;&#x2F;p&gt;
&lt;video controls&gt;
  &lt;source src=&quot;test_HHL.mp4&quot;&gt;
&lt;&#x2F;video&gt;
&lt;h3 id=&quot;testing-a-bare-chip&quot;&gt;Testing a bare chip&lt;&#x2F;h3&gt;
&lt;p&gt;When I bought the bivert board from HHL in 2016, I also purchased a bare
74HC0D chip for testing. In this second test, I decided to solder this chip on
a breakout board so I could easily test different connections. I connected the
breakout board to the Game Boy exactly like the HHL board, but this setup is
even worse due to the fairly long breadboard connections that go to the
floating inputs. In other words, the antennas are longer.&lt;&#x2F;p&gt;
&lt;p&gt;When turning on the Game Boy without any cartridge inserted, we can see massive
input current around ~20-30 mA! That is a significant current wasted when we&#x27;re
supposed to just invert two digital signals.&lt;&#x2F;p&gt;
&lt;video controls&gt;
  &lt;source src=&quot;test_chip1.mp4&quot;&gt;
&lt;&#x2F;video&gt;
&lt;h3 id=&quot;testing-a-bare-chip-connected-correctly&quot;&gt;Testing a bare chip connected correctly&lt;&#x2F;h3&gt;
&lt;p&gt;In the previous test we saw that a bare chip could easily consume 30 mA when
floating inputs are not terminated correctly, but what about when everything
&lt;em&gt;is&lt;&#x2F;em&gt; connected correctly? In this test I connected all unused inputs to GND,
which is one of the correct ways to handle them, as mentioned by the TI
datasheet in the earlier section. The outputs are not connected to anything,
because they don&#x27;t have to be! Since the inputs are connected to a stable
digital 0, the outputs will simply output a stable digital 1.&lt;&#x2F;p&gt;
&lt;div class=&quot;framed&quot;&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2020&#x2F;hhl-bivert-v2-technical-review&#x2F;test_chip2.png&quot; alt=&quot;Schematic of correct connections&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;When turning on the Game Boy without any cartridge inserted, we can see a tiny
input current around ~0.8 µA. Note in the following video how I need to change
change the scale to µA to even see a non-zero value, and how the current is
stable instead of oscillating like crazy! The exact power consumption depends
on how much switching the inverters need to do, but overall this is a &lt;em&gt;huge&lt;&#x2F;em&gt;
difference.&lt;&#x2F;p&gt;
&lt;video controls&gt;
  &lt;source src=&quot;test_chip2.mp4&quot;&gt;
&lt;&#x2F;video&gt;
&lt;h3 id=&quot;testing-the-forbidden-zone&quot;&gt;Testing the &quot;forbidden zone&quot;&lt;&#x2F;h3&gt;
&lt;p&gt;Floating inputs cause extra power consumption due to two main reasons.
Firstly, power is consumed when switching happens. With unused inputs we&#x27;re
basically inverting random noise, which can change rapidly causing power to be
wasted on switching the unused outputs. Secondly, standard CMOS chip inputs
have a &quot;forbidden zone&quot; between low and high states, where a lot of power is
consumed. During switching, the voltage passes through this forbidden zone, so
for a very short time power consumption goes high. Normally this state only
happens during the quick transition, and most of the time the voltage is either
in the valid low or valid high state. However, if random noise in the
environment happens to cause unused inputs to settle in this forbidden zone for
long periods of time, this can add massive power consumption and even cause
damage.&lt;&#x2F;p&gt;
&lt;p&gt;I wanted to further test the worst possible case, so I used 1M resistors to
create voltage dividers for all the unused inputs so that the unused inputs
would see around 2.5V, which happens to be in the forbidden zone.&lt;&#x2F;p&gt;
&lt;div class=&quot;framed&quot;&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2020&#x2F;hhl-bivert-v2-technical-review&#x2F;test_chip3.png&quot; alt=&quot;Schematic of &amp;quot;forbidden zone&amp;quot; test&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;After turning on the Game Boy without any cartridge inserted, we can see input
current go as high as 52 mA in this test!&lt;&#x2F;p&gt;
&lt;video controls&gt;
  &lt;source src=&quot;test_chip3.mp4&quot;&gt;
&lt;&#x2F;video&gt;
&lt;h3 id=&quot;measurement-result-summary&quot;&gt;Measurement result summary&lt;&#x2F;h3&gt;
&lt;p&gt;Based on this set of quick tests, the HHL board wastes unnecessary power due to
the main design flaw, although the wasted power wasn&#x27;t even close to the worst
case scenario. However, this greatly depends on the environment and the noise
picked up by the floating inputs. In some previous tests I&#x27;ve done with the HHL
board, I&#x27;ve seen higher numbers and the input current has been affected by nearby
electronical devices and even random pieces of unconnected wires!&lt;&#x2F;p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Test&lt;&#x2F;th&gt;&lt;th&gt;Input current&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;HHL board&lt;&#x2F;td&gt;&lt;td&gt;1-5 mA&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Correctly used bare chip&lt;&#x2F;td&gt;&lt;td&gt;0.0008 mA&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;HHL-style bare chip&lt;&#x2F;td&gt;&lt;td&gt;20-30 mA&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Worst case bare chip&lt;&#x2F;td&gt;&lt;td&gt;52 mA&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;h2 id=&quot;verdict&quot;&gt;Verdict&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;strong&gt;Not terrible, but definitely not recommended&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;HHL Bivert Module V2 is not a bad product, but I can&#x27;t recommend it due to the
fundamental problems in the circuit design. It&#x27;s probably better than using a
bare chip, but an even better choice would be to use a properly designed
alternative. If you already have a HHL board, you can fix the main flaw with 4
extra wires by connecting the unused inputs to either GND or +5V, but in my
opinion this defeats the point of using this board.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2020&#x2F;hhl-bivert-v2-technical-review&#x2F;verdict.jpg&quot; alt=&quot;Verdict&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;h3 id=&quot;better-alternatives&quot;&gt;Better alternatives&lt;&#x2F;h3&gt;
&lt;p&gt;A better alternative is a board that uses a dual inverter and preferably also
includes a bypass capacitor. When a dual inverter is used, there are no unused
circuits so there&#x27;s no need to handle them in any way!&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;Disclaimer: The following alternatives look good from a circuit design point
of view. I haven&#x27;t actually tested them, and have no idea if they are good
based on different criteria (e.g. ease of installation, price)&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;h4 id=&quot;hhl-game-boy-pocket-bivert-module&quot;&gt;HHL Game Boy Pocket Bivert module&lt;&#x2F;h4&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;handheldlegend.com&#x2F;collections&#x2F;game-boy-pocket-mgb&#x2F;products&#x2F;game-boy-pocket-bivert-module-mini&quot;&gt;https:&#x2F;&#x2F;handheldlegend.com&#x2F;collections&#x2F;game-boy-pocket-mgb&#x2F;products&#x2F;game-boy-pocket-bivert-module-mini&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;HHL&#x27;s own bivert module for &lt;em&gt;Game Boy Pocket&lt;&#x2F;em&gt; is fine since it uses a dual
inverter.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;j-rodrigo-s-dmg-and-mgb-bivert-boards&quot;&gt;J.Rodrigo&#x27;s DMG and MGB bivert boards&lt;&#x2F;h4&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.tindie.com&#x2F;products&#x2F;jrodrigo&#x2F;bivert-module-for-nintendo-game-boy-dmg&#x2F;&quot;&gt;https:&#x2F;&#x2F;www.tindie.com&#x2F;products&#x2F;jrodrigo&#x2F;bivert-module-for-nintendo-game-boy-dmg&#x2F;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.tindie.com&#x2F;products&#x2F;jrodrigo&#x2F;bivert-module-for-nintendo-game-boy-pocket&#x2F;&quot;&gt;https:&#x2F;&#x2F;www.tindie.com&#x2F;products&#x2F;jrodrigo&#x2F;bivert-module-for-nintendo-game-boy-pocket&#x2F;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;These are good dual inverter designs.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;thursday-customs-hex-inverter&quot;&gt;Thursday Customs Hex Inverter&lt;&#x2F;h4&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;store.thursdaycustoms.com&#x2F;product&#x2F;hex-dmg&quot;&gt;https:&#x2F;&#x2F;store.thursdaycustoms.com&#x2F;product&#x2F;hex-dmg&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;This seems like a good dual inverter design, although the product description
is &lt;em&gt;very misleading&lt;&#x2F;em&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Like several other alternatives, it uses a dual inverter, so calling it &quot;hex
inverter&quot; is complete nonsense. Even the installation instructions say &quot;Your
MGB is now hex inverted&quot;, which makes no sense. If somebody installed a
single-core CPU to their PC and called it &quot;quad-coring the PC&quot;, they would
probably be laughed at...&lt;&#x2F;p&gt;
&lt;h2 id=&quot;tl-dr&quot;&gt;TL;DR&lt;&#x2F;h2&gt;
&lt;ul&gt;
&lt;li&gt;A poorly designed bivert solution can consume more than 50 000 times the
power compared to a properly designed one&lt;&#x2F;li&gt;
&lt;li&gt;In a random test this HHL board consumed &quot;just&quot; ~1000 times the power
compared to a proper design, which would add zero extra cost to the board&lt;&#x2F;li&gt;
&lt;li&gt;Is this a good bivert board? No&lt;&#x2F;li&gt;
&lt;li&gt;Will it destroy my Game Boy? &lt;em&gt;Probably&lt;&#x2F;em&gt; not&lt;&#x2F;li&gt;
&lt;li&gt;Will it unnecessarily waste power and generate heat? Yes&lt;&#x2F;li&gt;
&lt;li&gt;Will it increase audible noise in the system? Maybe&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Decapped random chip - Microchip PIC16LC72A</title>
        <published>2020-08-12T00:00:00+00:00</published>
        <updated>2020-08-12T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Joonas Javanainen
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://gekkio.fi/blog/2020/decapped-random-chip-microchip-pic16lc72a/"/>
        <id>https://gekkio.fi/blog/2020/decapped-random-chip-microchip-pic16lc72a/</id>
        
        <content type="html" xml:base="https://gekkio.fi/blog/2020/decapped-random-chip-microchip-pic16lc72a/">&lt;p&gt;This time I&#x27;ve decapped a &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.microchip.com&#x2F;wwwproducts&#x2F;en&#x2F;PIC16C72A&quot;&gt;Microchip PIC16LC72A&lt;&#x2F;a&gt;, an 8-bit PIC microcontroller chip.&lt;&#x2F;p&gt;
&lt;div class=&quot;framed&quot;&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2020&#x2F;decapped-random-chip-microchip-pic16lc72a&#x2F;PIC16LC72A_chip.jpg&quot; alt=&quot;PIC16LC72A chip photo&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;The chip is in SOIC-28 package and is the LC variant which supports lower VDD
voltage than the normal C variant. Based on the package marking information
described in the datasheet, the chip is from year 2000 week 50.&lt;&#x2F;p&gt;
&lt;p&gt;Here&#x27;s the raw die after decapping (click for max resolution photo. &lt;em&gt;Warning: it&#x27;s 16MB&lt;&#x2F;em&gt;):&lt;&#x2F;p&gt;
&lt;div class=&quot;framed&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;files&#x2F;decapped-chips&#x2F;Frankenscope&#x2F;Microchip_PIC16LC72A&#x2F;Microchip_PIC16LC72A_10x.jpg&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2020&#x2F;decapped-random-chip-microchip-pic16lc72a&#x2F;PIC16LC72A_thumb.jpg&quot; alt=&quot;PIC16LC72A decapped&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;&lt;em&gt;This photo was captured using my &quot;Frankenscope&quot;, and is licensed under Creative
Commons Attribution 4.0 International.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;This die has 33 bonding pads with wires but the package has only 28 pins.  The
datasheet specifies that some pins change their input buffer type (e.g. Schmitt
Trigger &#x2F; CMOS &#x2F; TTL) depending on the currently selected function. Perhaps in
these cases the external pin connects to two separate pads with different input
buffer structures.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Decapped random chip - STMicro L78M05CV</title>
        <published>2020-08-12T00:00:00+00:00</published>
        <updated>2020-08-12T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Joonas Javanainen
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://gekkio.fi/blog/2020/decapped-random-chip-stmicro-l78m05cv/"/>
        <id>https://gekkio.fi/blog/2020/decapped-random-chip-stmicro-l78m05cv/</id>
        
        <content type="html" xml:base="https://gekkio.fi/blog/2020/decapped-random-chip-stmicro-l78m05cv/">&lt;p&gt;This time I&#x27;ve decapped an &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.st.com&#x2F;en&#x2F;power-management&#x2F;l78m.html&quot;&gt;STMicro
L78M05CV&lt;&#x2F;a&gt;, a fixed 5.0V
linear regulator chip. &lt;em&gt;Disclaimer: there&#x27;s a small possibility I&#x27;ve mixed two
chips and the raw die photo is actually L7805CV instead...&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;div class=&quot;framed&quot;&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2020&#x2F;decapped-random-chip-stmicro-l78m05cv&#x2F;L78M05CV_chip.jpg&quot; alt=&quot;L78M05CV chip photo&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;This version of the chip is in the TO-220 package, which requires more heat
than usual during thermal decapping, or the raw die might not detach cleanly
from the packaging. I actually decapped this one after a failed attempt with an
L7805CV chip in a similar package...&lt;&#x2F;p&gt;
&lt;p&gt;Here&#x27;s the raw die after decapping (click for max resolution photo):&lt;&#x2F;p&gt;
&lt;div class=&quot;framed&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;files&#x2F;decapped-chips&#x2F;Frankenscope&#x2F;STMicro_L78M05CV&#x2F;STMicro_L78M05CV.jpg&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2020&#x2F;decapped-random-chip-stmicro-l78m05cv&#x2F;L78M05CV_thumb.jpg&quot; alt=&quot;L78M05CV decapped&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;&lt;em&gt;This photo was captured using my &quot;Frankenscope&quot;, and is licensed under Creative
Commons Attribution 4.0 International.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Decapped random chip - Samsung S4L85K1X01</title>
        <published>2020-08-04T00:00:00+00:00</published>
        <updated>2020-08-04T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Joonas Javanainen
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://gekkio.fi/blog/2020/random-chip-decap-samsung-s4l85k1x01/"/>
        <id>https://gekkio.fi/blog/2020/random-chip-decap-samsung-s4l85k1x01/</id>
        
        <content type="html" xml:base="https://gekkio.fi/blog/2020/random-chip-decap-samsung-s4l85k1x01/">&lt;p&gt;I&#x27;ve decided to start decapping random chips I&#x27;ve harvested from various boards
to practice both the decapping procedure and imaging&#x2F;stitching of microscope
photos. Today&#x27;s specimen is a Samsung S4L8K1X01 chip, which I think came from a
mobile phone (Samsung S3 mini perhaps??). There&#x27;s no public data sheet
available, but based on some searches it seems to be some kind of memory chip.&lt;&#x2F;p&gt;
&lt;div class=&quot;framed&quot;&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2020&#x2F;random-chip-decap-samsung-s4l85k1x01&#x2F;S4L85K1X01_chip.jpg&quot; alt=&quot;S4L85K1X01 chip photo&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;The chip is in a 20-pin SSOP-like package with leads on two sides. Here&#x27;s the
raw die after decapping (click for max resolution photo):&lt;&#x2F;p&gt;
&lt;div class=&quot;framed&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;files&#x2F;decapped-chips&#x2F;Frankenscope&#x2F;Samsung_S4L85K1X01&#x2F;Samsung_S4L85K1X01.jpg&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2020&#x2F;random-chip-decap-samsung-s4l85k1x01&#x2F;S4L85K1X01_thumb.jpg&quot; alt=&quot;S4L85K1X01_chip decapped&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;&lt;em&gt;This photo was captured using my &quot;Frankenscope&quot;, and is licensed under Creative
Commons Attribution 4.0 International.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;The bonding pads are laid out on four sides, which is different than the layout
of the leads on the package. Luckily some of the bonding pads have helpful
numbers on them, so we can easily tell pin 1 is on the left, and the rest are
laid out in a counter-clockwise order.&lt;&#x2F;p&gt;
&lt;p&gt;So, is it a memory chip? I really can&#x27;t tell 😊 With higher magnification and
less damaged sample it would be possible to do deeper reverse engineering, but
I&#x27;ll save my time for more interesting chips.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Decapped random chip - Texas Instruments OPA1632</title>
        <published>2020-08-04T00:00:00+00:00</published>
        <updated>2020-08-04T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Joonas Javanainen
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://gekkio.fi/blog/2020/random-chip-decap-ti-opa1632/"/>
        <id>https://gekkio.fi/blog/2020/random-chip-decap-ti-opa1632/</id>
        
        <content type="html" xml:base="https://gekkio.fi/blog/2020/random-chip-decap-ti-opa1632/">&lt;p&gt;This time I&#x27;ve decapped a &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.ti.com&#x2F;product&#x2F;OPA1632&quot;&gt;Texas Instruments
OPA1632&lt;&#x2F;a&gt;, a fully-differential operational
amplifier chip.&lt;&#x2F;p&gt;
&lt;div class=&quot;framed&quot;&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2020&#x2F;random-chip-decap-ti-opa1632&#x2F;OPA1632_chip.jpg&quot; alt=&quot;OPA1632 chip photo&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;This specimen is an OPA1632D, which is the SOIC-8 -packaged version of the
chip. Here&#x27;s the raw die after decapping (click for max resolution photo):&lt;&#x2F;p&gt;
&lt;div class=&quot;framed&quot;&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;files&#x2F;decapped-chips&#x2F;Frankenscope&#x2F;TI_OPA1632&#x2F;TI_OPA1632.jpg&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2020&#x2F;random-chip-decap-ti-opa1632&#x2F;OPA1632_thumb.jpg&quot; alt=&quot;OPA1632 decapped&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;&lt;em&gt;This photo was captured using my &quot;Frankenscope&quot;, and is licensed under Creative
Commons Attribution 4.0 International.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;There&#x27;s one very interesting detail here: the label says THS4131, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.ti.com&#x2F;product&#x2F;THS4131&quot;&gt;which is a
different product&lt;&#x2F;a&gt; and much more expensive!
What&#x27;s going on?&lt;&#x2F;p&gt;
&lt;p&gt;Some people on the Internet have already noticed that OPA1632 and THS4131 have
almost identical characteristics based on their datasheets. Both most likely
use the same chip design, but the dies are tested after manufacture and labeled
either as OPA1632 or THS4131 depending on their characteristics. Apparently
THS4131 has slightly better specs, so the slightly worse performing chips are
probably sold as OPA1632.&lt;&#x2F;p&gt;
&lt;p&gt;There&#x27;s nothing surprising or new about this, since many manufacturers sell
lower-performing parts as different models. It makes perfect sense, since the
chips are still functional but simply don&#x27;t satisfy the full specs of the more
expensive chips.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>PCB gallery 1</title>
        <published>2020-04-25T00:00:00+00:00</published>
        <updated>2020-04-25T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Joonas Javanainen
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://gekkio.fi/blog/2020/pcb-gallery-1/"/>
        <id>https://gekkio.fi/blog/2020/pcb-gallery-1/</id>
        
        <content type="html" xml:base="https://gekkio.fi/blog/2020/pcb-gallery-1/">&lt;p&gt;This time I wanted to post some photos of old PCBs I&#x27;ve designed in the last
couple of years. All these boards are related to my Game Boy research
activities, which started back in 2014. I was building a Game Boy emulator
(&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;Gekkio&#x2F;mooneye-gb&quot;&gt;Mooneye GB&lt;&#x2F;a&gt;) and found existing
documentation about the system lacking in detail, so I started doing my own
research. In order to find information about the system, I started studying the
hardware with the help of custom circuit boards. I had very little experience
with electronics, having barely passed the basic electronics course at the
university after multiple attempts, but I started from very simple designs so
deep knowledge was not required at first.&lt;&#x2F;p&gt;
&lt;p&gt;My initial choice of PCB design software was CadSoft Eagle, which had a free
version with some limitations that didn&#x27;t affect my designs at first. However,
At some point I was starting to hit both size and layer limitations of Eagle,
and had to choose between paying for Eagle or switch to some alternative. I
don&#x27;t remember exactly what the pricing model of Eagle looked like, but having
support for a smallish 4-layer design was way too expensive, so I started
slowly switching to &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.kicad.org&#x2F;&quot;&gt;KiCad&lt;&#x2F;a&gt;. This process took a
fairly long time, because the workflow was quite different and KiCad had (and
still has) some very rough edges. However, I can now say the transition was
100% worth it, and I&#x27;m very happy with KiCad.&lt;&#x2F;p&gt;
&lt;p&gt;Almost all of the following PCBs were manufactured by
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.elecrow.com&#x2F;&quot;&gt;Elecrow&lt;&#x2F;a&gt;, who I used for a long time as the primary
manufacturer for all my designs. I was and still am very happy with them, but
unfortunately my current designs often require more advanced manufacturing
capabilities (e.g. minimum track size) than what is supported by Elecrow, so I
haven&#x27;t used their services recently.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;gb-brk-m-v2-1&quot;&gt;GB-BRK-M v2.1&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2020&#x2F;pcb-gallery-1&#x2F;GB-BRK-M-v2.1-top.jpg&quot;&gt;
  
  &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;gekkio.fi&amp;#x2F;processed_images&amp;#x2F;GB-BRK-M-v2.1-top.3ec710c9bb96e25b.jpg&quot; width=&quot;343&quot; height=&quot;400&quot; &#x2F;&gt;
&lt;&#x2F;a&gt;

&lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2020&#x2F;pcb-gallery-1&#x2F;GB-BRK-M-v2.1-bottom.jpg&quot;&gt;
  
  &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;gekkio.fi&amp;#x2F;processed_images&amp;#x2F;GB-BRK-M-v2.1-bottom.61c4c09a103d057b.jpg&quot; width=&quot;341&quot; height=&quot;400&quot; &#x2F;&gt;
&lt;&#x2F;a&gt;
&lt;&#x2F;p&gt;
&lt;p&gt;Designed with Eagle, manufactured in 2016 by Elecrow.&lt;&#x2F;p&gt;
&lt;p&gt;This board was an updated version of GB-BRK-M, the breakout cartridge that
started my PCB design journey in 2014. The basic idea is to have a Game Boy
cartridge that has no other functionality than just giving me access to all the
signals. This could then be connected to some actual circuitry in a breadboard
or other PCBs. The original v1.0 version had just a PTH pin header and the NPTH
holes used by official cartridge shells. It turns out using a PTH part is a bad
idea because &lt;em&gt;the pins stick out from the bottom&lt;&#x2F;em&gt; so the PCB won&#x27;t fit nicely
in a cartridge shell. I also screwed up the NPTH hole sizes and placements, so
the v1.0 board was quickly followed up by GB-BRK-M v2.0, which switched the pin
header to SMT and had correct NPTH holes. Or at least that&#x27;s what I
thought...turns out I screwed up the NPTH holes again, so they were fixed in
v2.1, which is the version you can see in the photos.&lt;&#x2F;p&gt;
&lt;p&gt;This v2.1 board also has an interesting manufacturing flaw: I chose white silkscreen (I&#x27;ve double-checked the order confirmation e-mail), but Elecrow made a mistake and gave me black silkscreen. Black text on red background has poor contrast, but this is a fairly harmless mistake, so I didn&#x27;t even complain about it. 😊&lt;&#x2F;p&gt;
&lt;h2 id=&quot;gb-brk-m-v3-0&quot;&gt;GB-BRK-M v3.0&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2020&#x2F;pcb-gallery-1&#x2F;GB-BRK-M-v3.0-top.jpg&quot;&gt;
  
  &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;gekkio.fi&amp;#x2F;processed_images&amp;#x2F;GB-BRK-M-v3.0-top.b7d66688bc0e04d7.jpg&quot; width=&quot;334&quot; height=&quot;400&quot; &#x2F;&gt;
&lt;&#x2F;a&gt;

&lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2020&#x2F;pcb-gallery-1&#x2F;GB-BRK-M-v3.0-bottom.jpg&quot;&gt;
  
  &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;gekkio.fi&amp;#x2F;processed_images&amp;#x2F;GB-BRK-M-v3.0-bottom.47b5ec3d7e5f147f.jpg&quot; width=&quot;329&quot; height=&quot;400&quot; &#x2F;&gt;
&lt;&#x2F;a&gt;
&lt;&#x2F;p&gt;
&lt;p&gt;Designed with KiCad, manufactured in 2017 by Elecrow.&lt;&#x2F;p&gt;
&lt;p&gt;One of the first things I did when learning KiCad was a redesign of the
GB-BRK-M board with it. This time I also added LEDs for control signals, so the
board is quite a lot more complicated than the original Eagle one.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;gb-brk-cart-v4-0&quot;&gt;GB-BRK-CART v4.0&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2020&#x2F;pcb-gallery-1&#x2F;GB-BRK-CART-v4.0-top.jpg&quot;&gt;
  
  &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;gekkio.fi&amp;#x2F;processed_images&amp;#x2F;GB-BRK-CART-v4.0-top.095777c61ff48784.jpg&quot; width=&quot;338&quot; height=&quot;400&quot; &#x2F;&gt;
&lt;&#x2F;a&gt;

&lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2020&#x2F;pcb-gallery-1&#x2F;GB-BRK-CART-v4.0-bottom.jpg&quot;&gt;
  
  &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;gekkio.fi&amp;#x2F;processed_images&amp;#x2F;GB-BRK-CART-v4.0-bottom.cb3cb4eb978b638b.jpg&quot; width=&quot;326&quot; height=&quot;400&quot; &#x2F;&gt;
&lt;&#x2F;a&gt;
&lt;&#x2F;p&gt;
&lt;p&gt;Designed with KiCad, manufactured in 2018 by JLCPCB.&lt;&#x2F;p&gt;
&lt;p&gt;After designing GB-BRK-M, I started having second thoughts about the control
LEDs, because I wanted to keep the board as simple as possible and avoid
affecting the signals too much with extra circuitry. I also decided to rename
the board to GB-BRK-CART to emphasize that this is a cartridge, instead of
using &quot;male&#x2F;female&quot; terminology which is not so obvious.&lt;&#x2F;p&gt;
&lt;p&gt;The green board in the photo above came from JLCPCB, who I tried out of
curiosity at this point. In order to compare manufacturers, I also got some
blue boards from Elecrow using the exactly same Gerber files. The results were interesting, because after hearing many good comments about JLCPCB, the board was inferior to the Elecrow board.&lt;&#x2F;p&gt;
&lt;p&gt;In these microscope photos, you can clearly see how the JLCPCB board (green) has lower silkscreen quality and soldermask accuracy compared to the Elecrow board (blue).&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2020&#x2F;pcb-gallery-1&#x2F;GB-BRK-CART-jlcpcb.jpg&quot;&gt;
  
  &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;gekkio.fi&amp;#x2F;processed_images&amp;#x2F;GB-BRK-CART-jlcpcb.6eaa36ceda3a2db5.jpg&quot; width=&quot;375&quot; height=&quot;300&quot; &#x2F;&gt;
&lt;&#x2F;a&gt;

&lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2020&#x2F;pcb-gallery-1&#x2F;GB-BRK-CART-elecrow.jpg&quot;&gt;
  
  &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;gekkio.fi&amp;#x2F;processed_images&amp;#x2F;GB-BRK-CART-elecrow.0e3de211aad913d2.jpg&quot; width=&quot;375&quot; height=&quot;300&quot; &#x2F;&gt;
&lt;&#x2F;a&gt;
&lt;&#x2F;p&gt;
&lt;p&gt;After doing this comparison, I didn&#x27;t feel very impressed by JLCPCB, so I
continued using Elecrow. However, as time passed, my designs started getting
more complicated so eventually I had to stop using Elecrow and make the switch.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;gb-brk-f-v1-0&quot;&gt;GB-BRK-F v1.0&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2020&#x2F;pcb-gallery-1&#x2F;GB-BRK-F-v1.0-top.jpg&quot;&gt;
  
  &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;gekkio.fi&amp;#x2F;processed_images&amp;#x2F;GB-BRK-F-v1.0-top.f3c91ccff174cddf.jpg&quot; width=&quot;392&quot; height=&quot;400&quot; &#x2F;&gt;
&lt;&#x2F;a&gt;

&lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2020&#x2F;pcb-gallery-1&#x2F;GB-BRK-F-v1.0-bottom.jpg&quot;&gt;
  
  &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;gekkio.fi&amp;#x2F;processed_images&amp;#x2F;GB-BRK-F-v1.0-bottom.bf62e0191412bc7a.jpg&quot; width=&quot;398&quot; height=&quot;400&quot; &#x2F;&gt;
&lt;&#x2F;a&gt;
&lt;&#x2F;p&gt;
&lt;p&gt;Designed with Eagle, manufactured in 2016 by Elecrow.&lt;&#x2F;p&gt;
&lt;p&gt;This board is the counterpart to GB-BRK-M and allows access to cartridge slot signals using a double-row pin header. The cartridge slot footprint was designed for DX 37787 replacement part (no longer available), but I forgot about the mounting pins on it so it never fit very well on this board. Oops!&lt;&#x2F;p&gt;
&lt;h2 id=&quot;gb-brk-f-v2-0&quot;&gt;GB-BRK-F v2.0&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2020&#x2F;pcb-gallery-1&#x2F;GB-BRK-F-v2.0-top.jpg&quot;&gt;
  
  &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;gekkio.fi&amp;#x2F;processed_images&amp;#x2F;GB-BRK-F-v2.0-top.2f45b22b1b37eacc.jpg&quot; width=&quot;398&quot; height=&quot;400&quot; &#x2F;&gt;
&lt;&#x2F;a&gt;

&lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2020&#x2F;pcb-gallery-1&#x2F;GB-BRK-F-v2.0-bottom.jpg&quot;&gt;
  
  &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;gekkio.fi&amp;#x2F;processed_images&amp;#x2F;GB-BRK-F-v2.0-bottom.3735437573bb00eb.jpg&quot; width=&quot;400&quot; height=&quot;400&quot; &#x2F;&gt;
&lt;&#x2F;a&gt;
&lt;&#x2F;p&gt;
&lt;p&gt;Designed with Eagle, manufactured in 2016 by Elecrow.&lt;&#x2F;p&gt;
&lt;p&gt;After doing GB-BRK-F, I realized it would be useful to have &lt;em&gt;two pin headers&lt;&#x2F;em&gt; for easy bypass functionality while still having access to the signals, so I designed v2.0. The slot footprint is still poor in this one...&lt;&#x2F;p&gt;
&lt;h2 id=&quot;gb-inv-dmg-v1-0&quot;&gt;GB-INV-DMG v1.0&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2020&#x2F;pcb-gallery-1&#x2F;GB-INV-DMG-v1.0-top.jpg&quot;&gt;
  
  &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;gekkio.fi&amp;#x2F;processed_images&amp;#x2F;GB-INV-DMG-v1.0-top.9ca3def1a24c22df.jpg&quot; width=&quot;242&quot; height=&quot;200&quot; &#x2F;&gt;
&lt;&#x2F;a&gt;

&lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2020&#x2F;pcb-gallery-1&#x2F;GB-INV-DMG-v1.0-bottom.jpg&quot;&gt;
  
  &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;gekkio.fi&amp;#x2F;processed_images&amp;#x2F;GB-INV-DMG-v1.0-bottom.609f0b3ae246bcbf.jpg&quot; width=&quot;240&quot; height=&quot;200&quot; &#x2F;&gt;
&lt;&#x2F;a&gt;
&lt;&#x2F;p&gt;
&lt;p&gt;Designed with Eagle, manufactured in 2016 by Elecrow.&lt;&#x2F;p&gt;
&lt;p&gt;This board was one of my many experimental designs of a simple dual inverter
board used for DMG biverting.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;picdev-18f45k50-v1-0&quot;&gt;PICDEV-18F45K50 v1.0&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2020&#x2F;pcb-gallery-1&#x2F;PICDEV-18F45K50-v1.0-top.jpg&quot;&gt;
  
  &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;gekkio.fi&amp;#x2F;processed_images&amp;#x2F;PICDEV-18F45K50-v1.0-top.576c515c88a66f31.jpg&quot; width=&quot;409&quot; height=&quot;400&quot; &#x2F;&gt;
&lt;&#x2F;a&gt;

&lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2020&#x2F;pcb-gallery-1&#x2F;PICDEV-18F45K50-v1.0-bottom.jpg&quot;&gt;
  
  &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;gekkio.fi&amp;#x2F;processed_images&amp;#x2F;PICDEV-18F45K50-v1.0-bottom.ec56b0ddda6da808.jpg&quot; width=&quot;400&quot; height=&quot;400&quot; &#x2F;&gt;
&lt;&#x2F;a&gt;
&lt;&#x2F;p&gt;
&lt;p&gt;Designed with Eagle, manufactured in 2016 by Elecrow.&lt;&#x2F;p&gt;
&lt;p&gt;This board was an experiment to see if I could design a very simple development
board for the PIC18F45K50 MCU, which is one of the cheapest MCUs with built-in
USB support. It worked, but there were several flaws:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;it uses MAX603&#x2F;604 LDO, which is overkill for this and fairly expensive&lt;&#x2F;li&gt;
&lt;li&gt;it uses a USB Micro connector which is worse than USB Mini. At the time I also didn&#x27;t have a hot air station so soldering this connector was pretty much impossible. I got it to work, but the soldering quality was &lt;em&gt;awful&lt;&#x2F;em&gt;.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Even with these flaws it was a good experiment, and I still sometimes use
PIC18(L)F45K50 for applications where USB support is needed.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;gb-live32-v1-1&quot;&gt;GB-LIVE32 v1.1&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2020&#x2F;pcb-gallery-1&#x2F;GB-LIVE32-v1.1-top.jpg&quot;&gt;
  
  &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;gekkio.fi&amp;#x2F;processed_images&amp;#x2F;GB-LIVE32-v1.1-top.5c8a191498d0a64b.jpg&quot; width=&quot;339&quot; height=&quot;400&quot; &#x2F;&gt;
&lt;&#x2F;a&gt;

&lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2020&#x2F;pcb-gallery-1&#x2F;GB-LIVE32-v1.1-bottom.jpg&quot;&gt;
  
  &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;gekkio.fi&amp;#x2F;processed_images&amp;#x2F;GB-LIVE32-v1.1-bottom.e79d1179a745d851.jpg&quot; width=&quot;335&quot; height=&quot;400&quot; &#x2F;&gt;
&lt;&#x2F;a&gt;
&lt;&#x2F;p&gt;
&lt;p&gt;Designed with Eagle, manufactured in 2016 by Elecrow.&lt;&#x2F;p&gt;
&lt;p&gt;This is the second version of &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;Gekkio&#x2F;gb-hardware#gb-live32&quot;&gt;GB-LIVE32&lt;&#x2F;a&gt;, a rapid development cartridge for Game Boy. Basically it&#x27;s a Game Boy cartridge backed by a 32 kB SRAM, which is seen as the &quot;cartridge ROM&quot; by the Game Boy.&lt;&#x2F;p&gt;
&lt;p&gt;I made the terrible mistake of using HASL as the surface finish. This is a bad
idea for Game Boy cartridges, because HASL is not really suitable for PCB edge
connections. All of the boards started having reliability issues after maybe 20
insertions, so I learned from this mistake and have since then always
remembered to use ENIG.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;gb-bench-v1-0&quot;&gt;GB-BENCH v1.0&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2020&#x2F;pcb-gallery-1&#x2F;GB-BENCH-v1.0-top.jpg&quot;&gt;
  
  &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;gekkio.fi&amp;#x2F;processed_images&amp;#x2F;GB-BENCH-v1.0-top.4ddf9d32921ab84b.jpg&quot; width=&quot;481&quot; height=&quot;400&quot; &#x2F;&gt;
&lt;&#x2F;a&gt;

&lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2020&#x2F;pcb-gallery-1&#x2F;GB-BENCH-v1.0-bottom.jpg&quot;&gt;
  
  &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;gekkio.fi&amp;#x2F;processed_images&amp;#x2F;GB-BENCH-v1.0-bottom.24b956023e7ec56d.jpg&quot; width=&quot;493&quot; height=&quot;400&quot; &#x2F;&gt;
&lt;&#x2F;a&gt;
&lt;&#x2F;p&gt;
&lt;p&gt;Designed with Eagle, manufactured in 2016 by Elecrow.&lt;&#x2F;p&gt;
&lt;p&gt;This is the first Game Boy test bench board I designed. The basic idea is to desolder a Game Boy CPU chip from a real unit, and put it on a board with the necessary basic circuitry to make it work. Pin headers provide access to all signals, and a GB-BRK-F board can be used to connect a real cartridge to the system.&lt;&#x2F;p&gt;
&lt;p&gt;This board worked pretty well, but simply required too much wiring and other
tools to be useful in the long term. It was later replaced by GB-BENCH-G1,
which has more functionality integrated on the same board.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;gb-bench-sram-64k-a-v1-0&quot;&gt;GB-BENCH-SRAM-64K-A v1.0&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2020&#x2F;pcb-gallery-1&#x2F;GB-BENCH-SRAM-64K-A-v1.0-top.jpg&quot;&gt;
  
  &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;gekkio.fi&amp;#x2F;processed_images&amp;#x2F;GB-BENCH-SRAM-64K-A-v1.0-top.aa85d0536db9a00b.jpg&quot; width=&quot;449&quot; height=&quot;400&quot; &#x2F;&gt;
&lt;&#x2F;a&gt;

&lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2020&#x2F;pcb-gallery-1&#x2F;GB-BENCH-SRAM-64K-A-v1.0-bottom.jpg&quot;&gt;
  
  &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;gekkio.fi&amp;#x2F;processed_images&amp;#x2F;GB-BENCH-SRAM-64K-A-v1.0-bottom.90e4ae379be0c1a6.jpg&quot; width=&quot;432&quot; height=&quot;400&quot; &#x2F;&gt;
&lt;&#x2F;a&gt;
&lt;&#x2F;p&gt;
&lt;p&gt;Designed with Eagle, manufactured in 2016 by Elecrow.&lt;&#x2F;p&gt;
&lt;p&gt;This is an addon board for GB-BENCH v1.0 and the original 8 kB (64 kilobit)
SRAM chips found on a DMG Game Boy. Two of these would be plugged in to a
GB-BENCH v1.0 board to have a full system with 8 kB video RAM and 8 kB work
RAM.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;gb-brk-cpu-g1-v0-1&quot;&gt;GB-BRK-CPU-G1 v0.1&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2020&#x2F;pcb-gallery-1&#x2F;GB-BRK-CPU-G1-v0.1-top.jpg&quot;&gt;
  
  &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;gekkio.fi&amp;#x2F;processed_images&amp;#x2F;GB-BRK-CPU-G1-v0.1-top.3ea08d86da7b5583.jpg&quot; width=&quot;397&quot; height=&quot;400&quot; &#x2F;&gt;
&lt;&#x2F;a&gt;

&lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2020&#x2F;pcb-gallery-1&#x2F;GB-BRK-CPU-G1-v0.1-bottom.jpg&quot;&gt;
  
  &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;gekkio.fi&amp;#x2F;processed_images&amp;#x2F;GB-BRK-CPU-G1-v0.1-bottom.351f09f1daf6d3b1.jpg&quot; width=&quot;399&quot; height=&quot;400&quot; &#x2F;&gt;
&lt;&#x2F;a&gt;
&lt;&#x2F;p&gt;
&lt;p&gt;Designed with KiCad, manufactured in 2018 by Elecrow.&lt;&#x2F;p&gt;
&lt;p&gt;This board can be seen as one of the successors to GB-BENCH v1.0. GB-BENCH-G1
replaced it, but sometimes all you need is a breakout board for the CPU when
just having access to pins is enough.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;gb-brk-cpu-g2-v0-1&quot;&gt;GB-BRK-CPU-G2 v0.1&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2020&#x2F;pcb-gallery-1&#x2F;GB-BRK-CPU-G2-v0.1-top.jpg&quot;&gt;
  
  &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;gekkio.fi&amp;#x2F;processed_images&amp;#x2F;GB-BRK-CPU-G2-v0.1-top.98d82fb49d39fa0d.jpg&quot; width=&quot;392&quot; height=&quot;400&quot; &#x2F;&gt;
&lt;&#x2F;a&gt;

&lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2020&#x2F;pcb-gallery-1&#x2F;GB-BRK-CPU-G2-v0.1-bottom.jpg&quot;&gt;
  
  &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;gekkio.fi&amp;#x2F;processed_images&amp;#x2F;GB-BRK-CPU-G2-v0.1-bottom.be6d7ee6487dd82c.jpg&quot; width=&quot;397&quot; height=&quot;400&quot; &#x2F;&gt;
&lt;&#x2F;a&gt;
&lt;&#x2F;p&gt;
&lt;p&gt;Designed with KiCad, manufactured in 2018 by Elecrow.&lt;&#x2F;p&gt;
&lt;p&gt;This is just like GB-BRK-CPU-G1, but for 2nd generation Game Boy CPUs (Game Boy
Pocket, Super Game Boy 2) which use a different pinout. When I made this
initial v0.1 design, I wasn&#x27;t sure about some pins, so the test pins are
labeled &lt;em&gt;T?&lt;&#x2F;em&gt;, and there are some other minor differences compared to the later
versions.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;gb-brk-cpu-g3-v0-1&quot;&gt;GB-BRK-CPU-G3 v0.1&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2020&#x2F;pcb-gallery-1&#x2F;GB-BRK-CPU-G3-v0.1-top.jpg&quot;&gt;
  
  &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;gekkio.fi&amp;#x2F;processed_images&amp;#x2F;GB-BRK-CPU-G3-v0.1-top.80097bea52d4901f.jpg&quot; width=&quot;395&quot; height=&quot;400&quot; &#x2F;&gt;
&lt;&#x2F;a&gt;

&lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2020&#x2F;pcb-gallery-1&#x2F;GB-BRK-CPU-G3-v0.1-bottom.jpg&quot;&gt;
  
  &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;gekkio.fi&amp;#x2F;processed_images&amp;#x2F;GB-BRK-CPU-G3-v0.1-bottom.37637cd64538ec7a.jpg&quot; width=&quot;394&quot; height=&quot;400&quot; &#x2F;&gt;
&lt;&#x2F;a&gt;
&lt;&#x2F;p&gt;
&lt;p&gt;Designed with KiCad, manufactured in 2018 by Elecrow.&lt;&#x2F;p&gt;
&lt;p&gt;This breakout board is for 3rd generation Game Boy CPUs (Game Boy Color). When
I made the design, I wasn&#x27;t sure about the pins at all so I just used numeric
labeling.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;useful-links&quot;&gt;Useful links&lt;&#x2F;h2&gt;
&lt;ul&gt;
&lt;li&gt;KiCad PCB design software: &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.kicad.org&#x2F;&quot;&gt;https:&#x2F;&#x2F;www.kicad.org&#x2F;&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;Eagle PCB design software: &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.autodesk.com&#x2F;products&#x2F;eagle&quot;&gt;https:&#x2F;&#x2F;www.autodesk.com&#x2F;products&#x2F;eagle&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;JLCPCB PCB manufacturer: &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;jlcpcb.com&quot;&gt;https:&#x2F;&#x2F;jlcpcb.com&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;Elecrow PCB manufacturer: &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.elecrow.com&quot;&gt;https:&#x2F;&#x2F;www.elecrow.com&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;My current Game Boy hardware designs: &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;Gekkio&#x2F;gb-hardware&quot;&gt;https:&#x2F;&#x2F;github.com&#x2F;Gekkio&#x2F;gb-hardware&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;My KiCad libraries, including a lot Game Boy -related stuff: &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;Gekkio&#x2F;gekkio-kicad-libs&quot;&gt;https:&#x2F;&#x2F;github.com&#x2F;Gekkio&#x2F;gekkio-kicad-libs&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Errata for &quot;Reverse engineering fine details of Game Boy hardware&quot;</title>
        <published>2018-02-05T00:00:00+00:00</published>
        <updated>2018-02-05T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Joonas Javanainen
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://gekkio.fi/blog/2018/errata-for-reverse-engineering-fine-details-of-game-boy-hardware/"/>
        <id>https://gekkio.fi/blog/2018/errata-for-reverse-engineering-fine-details-of-game-boy-hardware/</id>
        
        <content type="html" xml:base="https://gekkio.fi/blog/2018/errata-for-reverse-engineering-fine-details-of-game-boy-hardware/">&lt;p&gt;I gave a presentation about Game Boy reverse engineering at Disobey 2018, a
security&#x2F;hacking-oriented conference held in Helsinki. It was a really nice
chance to show off some of my tools and research results, and at least from my
point of view the presentation went really well! Here&#x27;s a YouTube video of the
presentation:&lt;&#x2F;p&gt;
&lt;div class=&quot;youtube&quot;&gt;
    &lt;iframe
        src=&quot;https:&#x2F;&#x2F;www.youtube-nocookie.com&#x2F;embed&#x2F;GBYwjch6oEE&quot;
        webkitallowfullscreen
        mozallowfullscreen
        allowfullscreen&gt;
    &lt;&#x2F;iframe&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;Unfortunately, even with a lot of preparation, some errors managed to creep
into the last section of the talk, because I happened to misread some of my own
notes about my very recent findings. Looks like I foreshadowed this in the talk
when I said &quot;I&#x27;m not sure about all of this yet&quot; ;)&lt;&#x2F;p&gt;
&lt;h3 id=&quot;data-sampling&quot;&gt;Data sampling&lt;&#x2F;h3&gt;
&lt;p&gt;In the data sampling part (~31:00) I claim that by looking at the cartridge bus
signals, we can see that the data bus is sampled on the falling edge of the
machine cycle, so the sampling point is basically in the middle of the cycle.
However, there&#x27;s an off-by-one error here, and the data sampling actually
happens one clock cycle later.&lt;&#x2F;p&gt;
&lt;img src=&quot;&#x2F;images&#x2F;2018&#x2F;data-sample-wrong.svg&quot; style=&quot;width: 100%&quot;&gt;
&lt;img src=&quot;&#x2F;images&#x2F;2018&#x2F;data-sample-correct.svg&quot; style=&quot;width: 100%&quot;&gt;
&lt;p&gt;Slightly later (~33:35) I explain that by abusing serial IO, we can see that
the CPU actually samples data internally at a different time (rising machine
clock edge). This is still correct, so the main points of this part are still
valid.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;interrupt-handling&quot;&gt;Interrupt handling&lt;&#x2F;h3&gt;
&lt;p&gt;In the interrupt handling part (~40:00) I explain how there are two different
clock edges involved in interrupt handling: &quot;should we dispatch&quot; and &quot;where do
we jump to&quot;. The first edge (= &quot;should we dispatch&quot;) is correct, but the second
clock edge is early by an entire machine cycle. So, the &quot;where do we jump to&quot;
edge is still on a falling machine clock edge, but it&#x27;s the last one in the
interrupt dispatching phase and just 4 clock edges before the first interrupt
handler instruction clock edge!&lt;&#x2F;p&gt;
&lt;img src=&quot;&#x2F;images&#x2F;2018&#x2F;intr-wrong.svg&quot; style=&quot;width: 100%&quot;&gt;
&lt;img src=&quot;&#x2F;images&#x2F;2018&#x2F;intr-correct.svg&quot; style=&quot;width: 100%&quot;&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Replacing a Super Famicom front panel flexible flat cable</title>
        <published>2017-10-02T00:00:00+00:00</published>
        <updated>2017-10-02T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Joonas Javanainen
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://gekkio.fi/blog/2017/replacing-a-super-famicom-front-panel-flexible-flat-cable/"/>
        <id>https://gekkio.fi/blog/2017/replacing-a-super-famicom-front-panel-flexible-flat-cable/</id>
        
        <content type="html" xml:base="https://gekkio.fi/blog/2017/replacing-a-super-famicom-front-panel-flexible-flat-cable/">&lt;p&gt;I own an SFC (Super Famicom, &quot;Japanese SNES&quot;) that I use for running hardware
tests on Super Game Boy and Super Game Boy 2 systems. My SFC has been modded
with a SuperCIC mod so I can also use a PAL Super Game Boy with it.
Unfortunately I got the SFC a fairly long time ago when I didn&#x27;t have that much
experience with electronics and console hardware, so I was very sloppy and
ended up damaging the unit in multiple ways.&lt;&#x2F;p&gt;
&lt;p&gt;Time for some SFC modding hall-of-shame photos!&lt;&#x2F;p&gt;
&lt;h2 id=&quot;sfc-modding-gore&quot;&gt;SFC modding gore&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;2017&#x2F;sfc_modding_gore_1.jpg&quot; alt=&quot;CIC pads should not look like this after desoldering the chip&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;2017&#x2F;sfc_modding_gore_2.jpg&quot; alt=&quot;Horror...none of these pins even need to be touched in this mod!&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;2017&#x2F;sfc_modding_gore_3.jpg&quot; alt=&quot;The front panel flat cable doesn&amp;#39;t like it when you bend it like this...&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;fixing-my-mistakes&quot;&gt;Fixing my mistakes&lt;&#x2F;h2&gt;
&lt;p&gt;Undoing the mainboard damage was straightforward: I just got a replacement
board and redid the mod, but this time I was much more careful and had better
tools available. For example, desoldering the CIC was much easier with hot air,
and no pads were lifted.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;2017&#x2F;desoldered_cic.jpg&quot; alt=&quot;Much better CIC desoldering result&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;The flat cable was another story: I only had a mainboard replacement and no
other spare parts. After doing some measurements, I estimated the cable pitch
to be 1.27mm. For some reason 1.27mm FFC parts are extremely rare, even on ebay
and AliExpress. However, the cable is just a 11-way cable so I figured a 1.25mm
pitch cable would only have a very small alignment error. I managed to find
potentially suitable 11-way 1.25mm FFC parts, but they were out of stock! It
looks like 11 signals is a very unpopular choice. In the end I decided to buy a
12-way 1.25mm cable from Digi-Key and try to mod it into a 11-way cable. A
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.digikey.fi&#x2F;product-detail&#x2F;en&#x2F;molex-llc&#x2F;0982680177&#x2F;WM14922-ND&#x2F;3470362&quot;&gt;Molex 0982680177&lt;&#x2F;a&gt;
cable seemed to be a good candidate.&lt;&#x2F;p&gt;
&lt;p&gt;The Molex cable was eventually shipped, and I found out that it fit nicely in
the connectors on both ends after cutting a tiny bit off.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;2017&#x2F;molex_ffc_cut.jpg&quot; alt=&quot;Cut Molex cable&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;This particular cable is 6&quot; (~15cm) in length, so it&#x27;s a bit longer than the
original. However, there&#x27;s enough room in the case for the cable so it&#x27;s not a
big problem. The length is not optimal but everything worked fine!&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;2017&#x2F;molex_ffc_installed.jpg&quot; alt=&quot;Final result with replacement cable installed&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;&#x2F;h2&gt;
&lt;p&gt;There you have it! If you ever need to replace a SFC front panel flexible flat
cable, look for 1.25mm pitch FFC parts, and buy a 11-way cable or cut a bit off
a 12-way cable.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Game Boy research status, March 2017</title>
        <published>2017-04-02T00:00:00+00:00</published>
        <updated>2017-04-02T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Joonas Javanainen
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://gekkio.fi/blog/2017/game-boy-research-status/"/>
        <id>https://gekkio.fi/blog/2017/game-boy-research-status/</id>
        
        <content type="html" xml:base="https://gekkio.fi/blog/2017/game-boy-research-status/">&lt;p&gt;I&#x27;ve made some progress in my research, but don&#x27;t have any mindblowing findings
to share yet.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;cpu-versions&quot;&gt;CPU versions&lt;&#x2F;h2&gt;
&lt;p&gt;I&#x27;ve finally acquired all of the Game Boy CPU versions. CPU CGB A was the
trickiest one, and the serial number of the unit doesn&#x27;t make much sense when
compared to data from my other units. So, unfortunately the data doesn&#x27;t make
it possible to predict which units would have that CPU version. The CPU CGB A
unit doesn&#x27;t work at the moment due to pretty bad battery leakage, but I&#x27;ll
attempt some repairs or even a CPU transplant if necessary. The board is
CGB-CPU-01 and I&#x27;ve got several units with that board and CPU CGB and CPU CGB
B.&lt;&#x2F;p&gt;
&lt;p&gt;I&#x27;ve also acquired a Game Boy Micro, but the CPU AGB E and the OXY-CPU-01 board
are too small for any practical research with my tools. On the other hand, it
doesn&#x27;t really matter since OXY doesn&#x27;t support pre-GBA games.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;game-boy-reset-clk-vs-phi&quot;&gt;Game Boy reset, CLK vs PHI&lt;&#x2F;h2&gt;
&lt;p&gt;On my SGB test bench, I found out that after RST is pulsed low, the Game Boy
requires around 131072 clock cycles before the CPU wakes up and starts from
$0000. The amount is not always the same, but clearly 2^17 = 131072 cycles is
meaningful here. The first falling edge of CLK typically seemed to happen after
131076 T-cycles.&lt;&#x2F;p&gt;
&lt;p&gt;I also noticed that the CPU seems to have some activity four T-cycles before
the first falling edge of CLK. At first this didn&#x27;t make any sense, because
I&#x27;ve always assumed the actual CPU machine cycles start with a rising edge on
CLK because this always seemed to make sense based on the memory access timings
and patterns. However, when cleaning up an AGB mainboard, I noticed the Ø (PHI)
silk screen label on the pin I usually call CLK. I&#x27;ve seen it before, but this
time something clicked in my head since I had read some 6502 CPU datasheets a
while ago: what if the pin is not like the PHI0 or SYNC 6502 pin but more like
the PHI1 pin. That is, what if it&#x27;s a delayed or inverted version of the
machine cycle clock, intended for external devices to let them know when they
can do certain actions.&lt;&#x2F;p&gt;
&lt;p&gt;This realization calls into question my previous ideas about the CLK pin and
the relative offset of timings.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;joypad-interrupts&quot;&gt;Joypad interrupts&lt;&#x2F;h2&gt;
&lt;p&gt;Joypad interrupts seem to be fully synchronous and don&#x27;t trigger from a single
falling edge or a quick low value on a P1 pin. It looks like there might be
some hardware debouncing going on, because when a low value is sampled at a
clock edge, the interrupt is triggered if and only if another low value is
sampled a couple of clocks later. The intermediate values don&#x27;t even seem to
matter, so the interrupt triggers even if the pin is high for all the time
except for two very specific clock edges. I can&#x27;t remember the exact number of
clocks, but roughly speaking something like this could trigger the interrupt:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #24292E; background-color: #FFFFFF;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;4MHz clock: _|‾|_|‾|_|‾|_|‾|_|‾|_|‾|_|‾|_|‾|_|&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;1MHz clock: _|‾‾‾‾‾‾‾|_______|‾‾‾‾‾‾‾|_______|&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Select btn: ‾‾‾‾‾‾‾‾|_|‾‾‾‾‾‾‾‾‾‾‾‾‾|_|‾‾‾‾‾‾‾&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Moving the second low pulse even one clock edge earlier or later would
not trigger the interrupt. And the signal could do anything between
these two pulses and it would still trigger the same way. More research is needed...&lt;&#x2F;p&gt;
&lt;h2 id=&quot;serial-interrupts&quot;&gt;Serial interrupts&lt;&#x2F;h2&gt;
&lt;p&gt;Serial interrupts seem to be unrelated to the main clock when an external clock
is select with the SC register. I did an experiment where I enabled serial
interrupts, stopped the main clock completely, and pulsed the SCLK pin 8 times.
The serial interrupt was triggered as soon as possible once the main clock was
resumed. This seems to suggest the SCLK is directly connected to a shift
register, and an internal flag is set after 8 bits have been shifted,
regardless of what the main clock is doing.&lt;&#x2F;p&gt;
&lt;p&gt;I&#x27;ll need to do more research, but if my findings are correct, I&#x27;ll be able to
trigger the internal serial interrupt flag at any time with one clock edge
accuracy. This leads to several opportunities to have a better understanding of
how HALT, STOP, and interrupts work.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;automated-hardware-testing&quot;&gt;Automated hardware testing&lt;&#x2F;h2&gt;
&lt;p&gt;My work on automated testing has required a lot of time learning the world of
FPGA&#x2F;CPLD devices. My current focus is supporting these things in an automated
way:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;hardware breakpoints&lt;&#x2F;li&gt;
&lt;li&gt;clock edge counting&lt;&#x2F;li&gt;
&lt;li&gt;full signal traces&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Some things can already be done almost at full speed (in the MHz scale), but
full signal traces are currently very slow (~1 KHz) which limits their
usefulness.&lt;&#x2F;p&gt;
&lt;p&gt;I took a big signal trace of Tetris, starting from a hardware breakpoint at
$0100 when the first instruction from the ROM is read. Here&#x27;s a GIF in which I
zoom the results in GTKWave until a single byte read from $0040 is visible:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;tetris_zoom.gif&quot; alt=&quot;&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Game Boy test ROM do&#x27;s and don&#x27;ts</title>
        <published>2016-10-10T00:00:00+00:00</published>
        <updated>2016-10-10T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Joonas Javanainen
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://gekkio.fi/blog/2016/game-boy-test-rom-dos-and-donts/"/>
        <id>https://gekkio.fi/blog/2016/game-boy-test-rom-dos-and-donts/</id>
        
        <content type="html" xml:base="https://gekkio.fi/blog/2016/game-boy-test-rom-dos-and-donts/">&lt;p&gt;Game Boy test ROMs are crucial tools for verifying the collective understanding
of the Game Boy hardware. Test ROMs can be executed on real Game Boys to check
that they test the right things, and they can also be executed on emulators to
check whether the emulator implements certain behaviour correctly.
Unfortunately writing good test ROMs is surprisingly difficult, and a badly
written test or incorrect interpretation of test results can greatly mislead a
hardware researcher or an emulator developer. In this blog post I describe some
ideas and recommendations I try to apply when writing test ROMs.&lt;&#x2F;p&gt;
&lt;p&gt;There are already some large test ROM suites:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;gbdev.gg8.se&#x2F;files&#x2F;roms&#x2F;blargg-gb-tests&#x2F;&quot;&gt;Blargg&#x27;s test ROMs&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;del&gt;gambatte test ROMs&lt;&#x2F;del&gt; (2023 edit: removed dead link)&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;AntonioND&#x2F;gbc-hw-tests&quot;&gt;AntonioND&#x27;s test ROMs&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;Gekkio&#x2F;mooneye-test-suite&quot;&gt;Mooneye Test Suite&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Even though many test ROMs exist, I strongly recommend serious emulator
developers to write their own tests as well. I believe in independent
verification, so having multiple people implement tests independently should
give us more confidence that our collective knowledge is correct. On the other
hand, this of course assumes that the test ROMs are correct. I can personally
only vouch for my own tests, because I&#x27;ve executed them on all models and
hardware versions I have access to (which happens to be almost every existing
one). My test ROM code varies in quality, but the results are solid.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;do-test-your-rom-on-real-hardware&quot;&gt;&lt;em&gt;Do&lt;&#x2F;em&gt; test your ROM on real hardware&lt;&#x2F;h2&gt;
&lt;p&gt;This might seem a no-brainer, but testing your ROM on real hardware is an
absolute must, unless your test ROM is intended for other purpose than testing
real hardware behaviour. You don&#x27;t need to personally own all possible Game Boy
models and versions, but I recommend having more than one model, and asking
other developers to run your ROMs on their devices. We do want to understand
the differences between versions, but it&#x27;s just misleading to claim some
behaviour as universal if it&#x27;s limited to a single model or version.&lt;&#x2F;p&gt;
&lt;p&gt;As an example, Blargg&#x27;s test ROMs are considered by many to be very fundamental
tests and some of the first ROMs a new emulator should attempt to pass.
However, not all of them pass on real hardware. For example, &lt;code&gt;cpu_instrs&lt;&#x2F;code&gt;
freezes on MGB (Game Boy Pocket) and SGB2 (Super Game Boy 2) devices and
emulators emulating them correctly. I find it shocking that I seem to be the
first one who has noticed this. I&#x27;m pretty sure the test would pass if it
wouldn&#x27;t freeze, but this is a clear oversight and things like this could mask
real differences between models.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;don-t-assume-emulators-or-other-test-roms-are-always-correct&quot;&gt;&lt;em&gt;Don&#x27;t&lt;&#x2F;em&gt; assume emulators or other test ROMs are always correct&lt;&#x2F;h2&gt;
&lt;p&gt;I strongly recommend not using emulators as the main platform while writing
test ROMs. While emulators provide a much quicker compile-test-observe
-workflow, you&#x27;re not testing real hardware and the emulator might not
implement all tested behaviour correctly. In the end you might still end up
with a test ROM that also works on hardware, but you might miss some insights
you could&#x27;ve had while developing the test ROM on real hardware. For example,
when I was making some OAM DMA tests ages ago, I made some mistakes which led
to a greater understanding of how OAM DMA behaves in conflict situations. If I
had developed the test ROM on an existing emulator that doesn&#x27;t emulate the OAM
DMA conflicts correctly, I wouldn&#x27;t have learned those things at the time.&lt;&#x2F;p&gt;
&lt;p&gt;You shouldn&#x27;t assume other test ROMs are always correct either. If a test ROM
is verified on real hardware, the results might be certain but the test itself
might be testing the wrong thing. Even when your test and some other test are
superficially similar, it&#x27;s possible they give very different results if one is
relying on some behaviour that is not the main focus of the test. For example,
PPU mode timings can be measured using at least these methods:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;interrupts&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;NOP&lt;&#x2F;code&gt; chains + &lt;code&gt;STAT&lt;&#x2F;code&gt; memory reads&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;LY&lt;&#x2F;code&gt; reads&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Even though superficially you would be measuring the same thing, different
methods may lead to different results.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;do-try-to-write-focused-tests&quot;&gt;&lt;em&gt;Do&lt;&#x2F;em&gt; try to write focused tests&lt;&#x2F;h2&gt;
&lt;p&gt;Your goal for most test ROMs should be to focus on a single aspect of the Game
Boy hardware. It&#x27;s perfectly fine to have more than one test case per test ROM,
but try to avoid relying on too many things. Every test builds on certain
assumptions about the hardware, but focusing on one thing makes it much easier
to develop the test and to debug the test on emulators and real hardware.&lt;&#x2F;p&gt;
&lt;p&gt;That being said, there is significant value in combination tests as well. I
plan to split my test development focus into two paths in the future:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Simple and focused tests. For example, keep everything else constant, but
vary SCX and measure some timings of the PPU&lt;&#x2F;li&gt;
&lt;li&gt;Combination tests based on &quot;data tables&quot; of random data. For example,
I could have a parameterized test that sets SCX, WX, sprites and measures PPU
timings. Then I would randomly generate a big amount of parameter values, and
save the parameters and corresponding result expectations into a big data
table.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Simple tests are the most important tests, but combination tests can reveal
unexpected interplay between things and&#x2F;or incorrect understanding of the
hardware. For example, some emulators claim to pass my sprite tests, but I have
100% confidence that they don&#x27;t implement the underlying behaviour correctly
when we also consider mid-scanline register writes and interplay between
different register values.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;don-t-use-halt-if-you-want-to-measure-interrupt-timings&quot;&gt;&lt;em&gt;Don&#x27;t&lt;&#x2F;em&gt; use &lt;code&gt;HALT&lt;&#x2F;code&gt; if you want to measure interrupt timings&lt;&#x2F;h2&gt;
&lt;p&gt;I mentioned briefly in my &lt;a href=&quot;&#x2F;blog&#x2F;2016-10-04-game-boy-research-status.html&quot;&gt;previous status blog post&lt;&#x2F;a&gt;
that the &lt;code&gt;HALT&lt;&#x2F;code&gt; instruction affects the timing of interrupt handlers on pre-CGB
devices.  The timing difference is not random, so for example if a test works
on a certain DMG unit, the &lt;code&gt;HALT&lt;&#x2F;code&gt; effects will be the same on all other pre-CGB
devices. There are several Mooneye GB tests that are split into separate &lt;code&gt;-GS&lt;&#x2F;code&gt;
(pre-CGB) and &lt;code&gt;-C&lt;&#x2F;code&gt; (CGB and beyond) tests because the timings are different.
This &lt;code&gt;HALT&lt;&#x2F;code&gt; weirdness is the reason, and in retrospect I should&#x27;ve used a simple
&quot;field of &lt;code&gt;NOP&lt;&#x2F;code&gt;s&quot; technique to wait for interrupts. I will at some point fix my
tests, but for now I will simply try to warn other people. My test ROM results
are still valid, but the effect of &lt;code&gt;HALT&lt;&#x2F;code&gt; mangles the resulting timing values
so it&#x27;s more difficult to see the timing patterns of the thing being tested.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;do-publish-your-results-and-source-code-and-try-to-make-it-readable&quot;&gt;&lt;em&gt;Do&lt;&#x2F;em&gt; publish your results and source code, and try to make it readable&lt;&#x2F;h2&gt;
&lt;p&gt;This one might seem quite obvious as well, but you should make your test ROM
source code public. Even if the ROM is perfectly correct, our collective
understanding depends on sharing of information, which includes source code.
Making assembly source code readable is a much more difficult task. There are
two main competing assemblers with differences in syntax and semantics, and
assembly language itself is challenging due to its low-level nature.&lt;&#x2F;p&gt;
&lt;p&gt;Personally I have the sources of all of my published tests in the Mooneye GB
Github repository. I have more tests on local hard drives, but they haven&#x27;t
been tested yet on real hardware, or are otherwise incomplete. I also try to
leave some important comments in the source code.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;don-t-limit-your-mental-model-to-the-world-of-1mhz-cycles&quot;&gt;&lt;em&gt;Don&#x27;t&lt;&#x2F;em&gt; limit your mental model to the world of 1MHz cycles&lt;&#x2F;h2&gt;
&lt;p&gt;This is the reason why I don&#x27;t use test ROMs at the moment as the main tool for
research. Since test ROMs run on the Game Boy CPU and the CPU executes memory
reads and writes in machine cycles, the ROMs see the hardware through &quot;1MHz
machine cycle glasses&quot;. However, the real world actually works with 4MHz clock
cycles or even 8MHz clock edges. This leads to the fact that it&#x27;s sometimes
very difficult to understand what the underlying hardware is doing. It&#x27;s also
why I choose to use test ROMs mainly for verification and focus my research
efforts on more invasive but effective methods.&lt;&#x2F;p&gt;
&lt;p&gt;Let&#x27;s take a simple example: interrupt handling. Here I have an example timing
diagram of a program that executes two instructions: &lt;code&gt;INC B&lt;&#x2F;code&gt; and &lt;code&gt;INC C&lt;&#x2F;code&gt;.  We
assume that &lt;code&gt;B=0&lt;&#x2F;code&gt;, &lt;code&gt;C=0&lt;&#x2F;code&gt; and interrupts are enabled before these two
instructions start executing. Now, the question is: if we could trigger an
interrupt at will in any of the moments labeled &lt;code&gt;a&lt;&#x2F;code&gt; to &lt;code&gt;q&lt;&#x2F;code&gt;, what is the
first moment (starting from &lt;code&gt;a&lt;&#x2F;code&gt;) where the interrupt happens too late to
prevent the instruction &lt;code&gt;INC C&lt;&#x2F;code&gt; from running? In other words, when should an
interrupt happen so that we have &lt;code&gt;B=1&lt;&#x2F;code&gt; and &lt;code&gt;C=0&lt;&#x2F;code&gt; in the interrupt handler?&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #24292E; background-color: #FFFFFF;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            a b c d e f g h i j k l m n o p q&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            |   |   |   |   |   |   |   |   |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;              |   |   |   |   |   |   |   |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;4MHz clock: _|‾|_|‾|_|‾|_|‾|_|‾|_|‾|_|‾|_|‾|_|&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;1MHz clock: _|‾‾‾‾‾‾‾|_______|‾‾‾‾‾‾‾|_______|&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Address:         |   $0200   |   |   $0201   |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Data:            |   $04     |   |   $0C     |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Instruction:     |   INC B   |   |   INC C   |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;It&#x27;s probably obvious that if an interrupt happens at &lt;code&gt;a&lt;&#x2F;code&gt;, we jump to the
interrupt handler quite early, the instruction &lt;code&gt;INC C&lt;&#x2F;code&gt; is not executed and even
&lt;code&gt;INC B&lt;&#x2F;code&gt; might be skipped.  But what about &lt;code&gt;g&lt;&#x2F;code&gt; or &lt;code&gt;i&lt;&#x2F;code&gt;? Is one of them the right
answer, and if not, which one is closer? If we control the interrupt, we could
just run a test case for each of the moments of time and see when the behaviour
changes. This is what is possible with more invasive tools than test ROMs.&lt;&#x2F;p&gt;
&lt;p&gt;In practice, with test ROMs we face the opposite challenge: we can alter the
interrupt timing, possibly even at 4MHz accuracy (e.g. add sprites to delay PPU
STAT interrupts), but we don&#x27;t know at which time the interrupt triggers
exactly. With careful planning we can count the number of full instructions
executed and measure a ballpark number with 1MHz cycle accuracy. But if our
goal is to understand the internal behaviour of the system to develop an
accurate model, guessing &lt;code&gt;a&lt;&#x2F;code&gt; when the right moment is &lt;code&gt;h&lt;&#x2F;code&gt; is a massive error in
the 4MHz world in which the hardware works. In some cases it might not matter,
while in other cases we will have an incorrect model. A simple 4MHz world
hardware state machine might be converted into a horribly complicated
1MHz-based model with magic +1 or -1 cycle amounts with no explanation. If this
is the only type of evidence guiding our way of thinking, we are doomed.&lt;&#x2F;p&gt;
&lt;p&gt;I hope this explains why I haven&#x27;t followed the gambatte way of writing
hundreds of test ROMs (which still didn&#x27;t give a model accurate enough to pass
my tests!!). I&#x27;m still hoping that the underlying hardware makes more sense
than it seems, and we just haven&#x27;t seen it through the right 4MHz (or 8MHz!)
point of view.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;PS. It&#x27;s too early to talk about the right answer to this interrupt question,
but I can tell that it&#x27;s probably not &lt;code&gt;a&lt;&#x2F;code&gt; or &lt;code&gt;i&lt;&#x2F;code&gt;, and the timing might depend
on the interrupt source.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;do-mention-test-rom-versions-when-you-talk-about-them&quot;&gt;&lt;em&gt;Do&lt;&#x2F;em&gt; mention test ROM versions when you talk about them&lt;&#x2F;h2&gt;
&lt;p&gt;This one is extremely important: if you claim that your emulator passes certain
tests, always mention the test ROM versions!  Blargg&#x27;s test ROMs are numbered,
so the version is clear if you use the right name, but for example Mooneye GB
tests change once in a while, and the test names themselves don&#x27;t indicate
which version was used. Either use a timestamp (e.g. &lt;code&gt;2016-09-31&lt;&#x2F;code&gt;) or a git
commit hash (e.g. &lt;code&gt;4d8e5be71eb539be783eb4e0b807b907954e7d49&lt;&#x2F;code&gt;). Also provide
some version scheme for your own tests; if you use git (like you should!), a
simple commit hash should be fine.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Game Boy research status, September 2016</title>
        <published>2016-10-04T00:00:00+00:00</published>
        <updated>2016-10-04T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Joonas Javanainen
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://gekkio.fi/blog/2016/game-boy-research-status/"/>
        <id>https://gekkio.fi/blog/2016/game-boy-research-status/</id>
        
        <content type="html" xml:base="https://gekkio.fi/blog/2016/game-boy-research-status/">&lt;p&gt;It&#x27;s been a while since the last time I wrote anything about Game Boys. Unlike
what it might seem, I haven&#x27;t stopped doing research or working on my emulator.
It&#x27;s the complete opposite: I&#x27;ve been very busy setting up better tooling for
hardware testing, which will hopefully lead us to the &quot;end-game&quot; of Game Boy
research where most questions are answered. I&#x27;ve decided to start writing a
monthly or bi-monthly summary of stuff I&#x27;ve studied and results I&#x27;ve
discovered. The main focus is on pulling back the curtain a bit on my Game Boy
work, so I will mostly just list random things instead of trying to write very
clearly thought posts. Lowering the barrier of writing should make it easier to
have enough time to write these things.&lt;&#x2F;p&gt;
&lt;p&gt;Anyway, without further ado, here are some things I&#x27;ve worked on or thought
about recently:&lt;&#x2F;p&gt;
&lt;h2 id=&quot;early-dmg-boot-rom-dump-and-cpu-differences&quot;&gt;Early DMG boot ROM dump and CPU differences&lt;&#x2F;h2&gt;
&lt;p&gt;I found out that early DMG units had a different boot ROM, which flashes the
screen instead of scrolling a block if the Game Boy is started without a
cartridge. I successfully dumped this boot ROM, and it&#x27;s now in the No-Intro
database.&lt;&#x2F;p&gt;
&lt;p&gt;That being said, I also realized something today: I&#x27;ve got an early unit with
CPU labeled as &quot;LR35902&quot; and another unit with CPU labeled as &quot;DMG-CPU&quot;. I
can&#x27;t remember which one I dumped, and there&#x27;s also a possibility that these
are two different versions. At the moment I&#x27;m still assuming they are the same,
but this needs more testing.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;hardware-revisions&quot;&gt;Hardware revisions&lt;&#x2F;h2&gt;
&lt;p&gt;I&#x27;ve watched ebay very closely and acquired a lot of Game Boy hardware
versions. Very soon I should have all the CPU versions, which are the most
important things for research. I already have all known mainboard versions of
everything except SGB and AGS units.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;game-boy-hardware-database&quot;&gt;Game Boy hardware database&lt;&#x2F;h2&gt;
&lt;p&gt;I&#x27;m building a website that will have a big database and photo album of Game
Boy units, games, and accessories. I have around 70 Game Boy units, and I&#x27;m
collecting precise data from them, including stuff like chip date codes, board
stamps, and serial numbers. The serial numbers have already been a huge help in
making educated guesses about which Game Boys to buy from ebay.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;gb-live32-rapid-development-cart&quot;&gt;GB-LIVE32 rapid development cart&lt;&#x2F;h2&gt;
&lt;p&gt;The GB-LIVE32 rapid development cart is the main hardware project I&#x27;ve been
working on for two years. It&#x27;s nothing very complicated, but I&#x27;ve had to learn
a lot of skills to make the cart reality. The first PCB I designed was the
GB-BRK-M board, but the main goal has always been to practice things bit by bit
to finally have the skillset to create this rapid development cart.&lt;&#x2F;p&gt;
&lt;p&gt;The cart is based on some very simple requirements:&lt;&#x2F;p&gt;
&lt;p&gt;I want to have a USB cable connected to a cart in a Game Boy, and update the
ROM without unplugging any cables. The Game Boy should also restart
automatically after a ROM update without any manual touching of power switches
or other things. Updates can be done in parallel to multiple Game Boy units
with a USB hub + multiple carts.&lt;&#x2F;p&gt;
&lt;p&gt;No cartridge RAM or any kind of MBC is needed for running my test ROMs, so the
implementation can be quite simple:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Program memory for the $0000-$7FFF area --&amp;gt; &lt;em&gt;32 Kbit SRAM chip&lt;&#x2F;em&gt;&lt;&#x2F;li&gt;
&lt;li&gt;A way to isolate the SRAM from the Game Boy cartridge bus --&amp;gt; &lt;em&gt;5V tolerant 3-state buffers&lt;&#x2F;em&gt;&lt;&#x2F;li&gt;
&lt;li&gt;A way to toggle the RST pin --&amp;gt; &lt;em&gt;5 V tolerant open-collector buffer&lt;&#x2F;em&gt;&lt;&#x2F;li&gt;
&lt;li&gt;A microcontroller for updates and control --&amp;gt; &lt;em&gt;PIC microcontroller&lt;&#x2F;em&gt;&lt;&#x2F;li&gt;
&lt;li&gt;USB connectivity --&amp;gt; &lt;em&gt;the chosen PIC MCU also has USB, so no extra chip is needed&lt;&#x2F;em&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;I plan to open source everything (including the board design) once I work out
some kinks and improve the software. The cart itself has worked since the v1.0
design and software, so the improvements are relatively minor. Parallel testing
made it much quicker to run mooneye-gb tests on real hardware, so I was able to
very quickly confirm test results on previously untested but accessible
hardware revisions.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;automated-hardware-testing&quot;&gt;Automated hardware testing&lt;&#x2F;h2&gt;
&lt;p&gt;While I&#x27;m still improving the GB-LIVE32 cart, my main focus has shifted to an
automated Game Boy hardware testing system. The idea is to have the capability
to run a huge amount of tests with slightly different parameters and gather
results without human intervention. For example, PPU timings are very
complicated and depend on multiple factors, and it would make research much
easier if I could simply write a simple test generator that runs a certain test
with slightly different parameters. Even a simple thing like measuring how many
cycles something takes is much more difficult to implement in a test ROM than
with a hardware testing platform that could simply control the clock and count
the number of clock edges until a certain event happens.&lt;&#x2F;p&gt;
&lt;p&gt;I already have the first version of the system working, but it needs a lot of
improvements to make things truly automated. However, I already have full
control of the clock and the CPU, so I can for example do these things:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;count clock cycles&#x2F;edges&lt;&#x2F;li&gt;
&lt;li&gt;inject a byte to any memory read (= I can inject instructions or data to
the CPU)&lt;&#x2F;li&gt;
&lt;li&gt;skip the boot ROM if I want to (= replace the instruction at $0000
with &lt;code&gt;JP $0100&lt;&#x2F;code&gt;)&lt;&#x2F;li&gt;
&lt;li&gt;observe addresses of some memory accesses normally not visible in the
cartridge bus (e.g. boot ROM reads)&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;halt-on-dmg-sgb-mgb-sgb2-has-strange-delays&quot;&gt;HALT on DMG&#x2F;SGB&#x2F;MGB&#x2F;SGB2 has strange delays&lt;&#x2F;h2&gt;
&lt;p&gt;Using HALT on pre-CGB devices can lead to the CPU waking up later than
intended. I don&#x27;t understand this behaviour yet, but I&#x27;m pretty sure I&#x27;ve seen
delays up to 6 cycles. The following diagram is from my notes and might be
inaccurate:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #24292E; background-color: #FFFFFF;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;time in M-cycles&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;---------------------&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;EH...........I&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;E.H................I&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;E..H.........I&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;E...H.........I&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;E....H..........I&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;E.....H.........I&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;E......H..........I&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;E = EI instruction&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;H = HALT instruction&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;. = NOP instruction&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;I = interrupt handler&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;In all cases the interrupt source is unchanged so the interrupt happens at the
same time, but for some reason the interrupt handler timing varies. The only
thing that changes is the amount of NOP instructions between EI and HALT.
There&#x27;s plenty of NOPs after HALT so the problem can&#x27;t be that HALT and the
interrupt would be too close together.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Game Boy cartridge PCB photos</title>
        <published>2016-03-19T00:00:00+00:00</published>
        <updated>2016-03-19T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Joonas Javanainen
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://gekkio.fi/blog/2016/game-boy-cartridge-pcb-photos/"/>
        <id>https://gekkio.fi/blog/2016/game-boy-cartridge-pcb-photos/</id>
        
        <content type="html" xml:base="https://gekkio.fi/blog/2016/game-boy-cartridge-pcb-photos/">&lt;p&gt;Last year I took PCB photos of all Game Boy games I own, but I never managed to
categorize or publish the photos I&#x27;m not going to analyze all of these in
detail, so I&#x27;m just going to leave the photos and basic information here for
those who are interested in such things.&lt;&#x2F;p&gt;
&lt;p&gt;The titles are based on the current No-Intro Game Boy and Game Boy Color
databases, and there might be slight differences compared to more commonly seen
names (e.g. Robot Poncots vs.  Robot Ponkottsu).&lt;&#x2F;p&gt;
&lt;p&gt;There&#x27;s a lot of games here, but here are some especially interesting ones:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Tamagotchi 3 is unique and has several custom chips (TAMA5, TAMA6, TAMA7)&lt;&#x2F;li&gt;
&lt;li&gt;The Game Boy Camera is unique&lt;&#x2F;li&gt;
&lt;li&gt;Mortal Kombat &amp;amp; Mortal Kombat II collection uses a normal MBC1, but it is
wired differently! Emulators that blindly trust the cartridge header (which
says MBC1) fail to emulate the game properly, and immediately take the player
back to the game selection screen after a game is selected&lt;&#x2F;li&gt;
&lt;li&gt;Wario Land II has both GB and GBC releases&lt;&#x2F;li&gt;
&lt;li&gt;Dragon Quest Monsters has the &lt;em&gt;largest ROM of all MBC1 games&lt;&#x2F;em&gt;&lt;&#x2F;li&gt;
&lt;li&gt;Densha de Go! 2 has the &lt;em&gt;largest ROM of all Game Boy games&lt;&#x2F;em&gt;. The PCB actually
has two separate 32Mb roms, which makes 64Mb in total&lt;&#x2F;li&gt;
&lt;li&gt;Tetris uses a glob top chip instead of more typical packaging&lt;&#x2F;li&gt;
&lt;li&gt;Japanese Pokemon Crystal uses MBC30, which seems to be a special variant of MBC3&lt;&#x2F;li&gt;
&lt;li&gt;Net de Get uses MBC6, and has &lt;em&gt;a flash chip for downloadable minigames&lt;&#x2F;em&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;strong&gt;Update 2018-02-25: Please check out the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;gbhwdb.gekkio.fi&#x2F;cartridges&#x2F;&quot;&gt;Game Boy Hardware Database&lt;&#x2F;a&gt; for photos and data of a huge amount of cartridges&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Mooneye GB 0.1.0 released</title>
        <published>2015-09-27T00:00:00+00:00</published>
        <updated>2015-09-27T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Joonas Javanainen
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://gekkio.fi/blog/2015/mooneye-gb-0-1-0-released/"/>
        <id>https://gekkio.fi/blog/2015/mooneye-gb-0-1-0-released/</id>
        
        <content type="html" xml:base="https://gekkio.fi/blog/2015/mooneye-gb-0-1-0-released/">&lt;p class=&quot;text-center&quot;&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;2015&#x2F;mooneye-gb-0.1.0.png&quot; alt=&quot;Mooneye GB 0.1.0 screenshot&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;p&gt;
&lt;p&gt;I&#x27;ve decided that it&#x27;s time to do a proper release of Mooneye GB after more than one year of
development. &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;Gekkio&#x2F;mooneye-gb&quot;&gt;Mooneye GB&lt;&#x2F;a&gt; is a Game Boy emulator project I
started last year, and it has been my main hobby project since then.&lt;&#x2F;p&gt;
&lt;p&gt;The first public commit in the repository is from Dec 18, 2014, but the project has actually a
longer history. The initial commit for my &lt;em&gt;private&lt;&#x2F;em&gt; Mooneye GB repository was done on Aug 31, 2014,
and some code was adapted from ocamlboy, which was an earlier attempt to build a Game Boy emulator
with OCaml. The initial commit for ocamlboy was made on June 2, 2014, but eventually my growing
interest in Rust won, and I ported all the existing code to something that later became Mooneye GB.&lt;&#x2F;p&gt;
&lt;p&gt;In case you are curious, here&#x27;s a snippet of some early ocamlboy code:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #24292E; background-color: #FFFFFF;&quot;&gt;&lt;code data-lang=&quot;ocaml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;text-decoration: underline;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; read_addr8&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #005CC5;text-decoration: underline;&quot;&gt;cpu&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt; :&lt;&#x2F;span&gt;&lt;span&gt; cpu) (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #005CC5;text-decoration: underline;&quot;&gt;mem&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt; :&lt;&#x2F;span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt; Memory&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;mem) (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #005CC5;text-decoration: underline;&quot;&gt;mode&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt; :&lt;&#x2F;span&gt;&lt;span&gt; addr8_mode)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt; :&lt;&#x2F;span&gt;&lt;span&gt; int&lt;&#x2F;span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; match&lt;&#x2F;span&gt;&lt;span&gt; mode&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; with&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt;  |&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Immediate&lt;&#x2F;span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;text-decoration: underline;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; v&lt;&#x2F;span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt; = Memory&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;read8 mem cpu&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;background-color: #F0FFF4;&quot;&gt;regs&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;background-color: #F0FFF4;&quot;&gt;pc&lt;&#x2F;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;text-decoration: underline;&quot;&gt;in&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    begin&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      cpu&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;background-color: #F0FFF4;&quot;&gt;regs&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;background-color: #F0FFF4;&quot;&gt;pc&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; &amp;lt;-&lt;&#x2F;span&gt;&lt;span&gt; cpu&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;background-color: #F0FFF4;&quot;&gt;regs&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;background-color: #F0FFF4;&quot;&gt;pc&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt; +&lt;&#x2F;span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt; 1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    end&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    v&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;So, during the period of more than one year of research and emulator programming, what did I do?&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Wrote an emulator that passes several Blargg&#x27;s tests&lt;&#x2F;li&gt;
&lt;li&gt;Discovered a lot of inaccuracies in existing emulators. Even Gambatte is not perfect!&lt;&#x2F;li&gt;
&lt;li&gt;Bought several Game Boy devices for hardware testing&lt;&#x2F;li&gt;
&lt;li&gt;Bought almost 40 Game Boy games for in-detail cartridge analysis&lt;&#x2F;li&gt;
&lt;li&gt;Wrote a lot of test ROMs&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;Gekkio&#x2F;gb-hardware&quot;&gt;Designed breakout boards for the Game Boy cartridge slot&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;&#x2F;blog&#x2F;2015-09-13-dumping-the-super-game-boy-2-boot-rom.html&quot;&gt;Dumped the boot ROM of Super Game Boy 2&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;Did some logic analysis on the Game Boy cartridge slot signals&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;And this is just the beginning...I think I have gotten more new questions than answers from my
research.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;what-s-in-mooneye-gb-v0-1-0&quot;&gt;What&#x27;s in Mooneye GB v0.1.0?&lt;&#x2F;h2&gt;
&lt;p&gt;This 0.1.0 release is not very exciting, but it is still an important milestone for the project. I&#x27;m
hoping that more Game Boy emulation enthusiasts will notice the project, and some people might
actually test the emulator on their systems.&lt;&#x2F;p&gt;
&lt;p&gt;Please note that Mooneye GB is above all a research project, and &lt;strong&gt;if you want to actually play Game
Boy games, Mooneye GB is probably not the emulator for you&lt;&#x2F;strong&gt;. Use
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;sinamas&#x2F;gambatte&quot;&gt;Gambatte&lt;&#x2F;a&gt; or &lt;a rel=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;bgb.bircd.org&#x2F;&quot;&gt;BGB&lt;&#x2F;a&gt; instead.&lt;&#x2F;p&gt;
&lt;p&gt;Mooneye GB &lt;strong&gt;does not&lt;&#x2F;strong&gt; currently have:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;support for save games&lt;&#x2F;li&gt;
&lt;li&gt;audio&lt;&#x2F;li&gt;
&lt;li&gt;a nice user interface&lt;&#x2F;li&gt;
&lt;li&gt;full screen mode&lt;&#x2F;li&gt;
&lt;li&gt;configurable key bindings&lt;&#x2F;li&gt;
&lt;li&gt;configurable resolution&lt;&#x2F;li&gt;
&lt;li&gt;Game Boy link support&lt;&#x2F;li&gt;
&lt;li&gt;support for most Game Boy cartridge mappers&lt;&#x2F;li&gt;
&lt;li&gt;support for any extra Game Boy cartridge features (e.g. infrared, rumble)&lt;&#x2F;li&gt;
&lt;li&gt;support for any extra peripherals (e.g. camera, printer)&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;While developing Mooneye GB I&#x27;ve discovered inaccuracies in existing emulators and have discovered a
lot of knowledge about the Game Boy that has been so far undocumented. I&#x27;m very confident that other
people have found out some of the same things before, but so far it looks like people haven&#x27;t often
documented their findings publicly. All you need to do is look at Pandocs; this document is widely
considered to be very valuable, but it is missing a huge amount of crucial details needed for
accurate Game Boy emulation.&lt;&#x2F;p&gt;
&lt;p&gt;My ultimate goal is to answer unanswered questions about the Game Boy, and provide some kind of
documentation that others can look at. So far the documentation has been mostly random notes and
comments in test ROMs and markdown files, but I might write a better document one day. And even
these small comments and document files are better than not having any information.&lt;&#x2F;p&gt;
&lt;p&gt;Since I&#x27;m releasing all information freely and publicly, other emulators can and probably will use
that information to improve their accuracy. This is perfectly ok, and I don&#x27;t mind having competing
emulators that are better than Mooneye GB. My main goal is to improve Game Boy emulation for
everyone, so I don&#x27;t really care at all if people use Mooneye GB or a better alternative.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;where-can-i-get-it&quot;&gt;Where can I get it?&lt;&#x2F;h2&gt;
&lt;p&gt;Windows 32-bit and 64-bit binaries are available from the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;Gekkio&#x2F;mooneye-gb&#x2F;releases&#x2F;tag&#x2F;v0.1.0&quot;&gt;Github release page&lt;&#x2F;a&gt;.
Unfortunately I have no OS X or Linux binaries, because I don&#x27;t have good build environments for them.
For these environments my recommendation is to check out the v0.1.0 tag from Github and build the
binaries yourself.&lt;&#x2F;p&gt;
&lt;p&gt;The source code package does not include dependencies, so building will require internet access and
I cannot guarantee the package will continue to build in the future. This is an unfortunate problem
with no good solutions at the moment (no, cargo-vendor is not yet good enough).&lt;&#x2F;p&gt;
&lt;h4 id=&quot;special-thanks-to-scyther-eagleflo-and-many-other-people-for-their-interest-in-the-project-which-has-been-a-major-motivator-to-me&quot;&gt;Special thanks to scyther, eagleflo, and many other people for their interest in the project, which has been a major motivator to me&lt;&#x2F;h4&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Dumping the Super Game Boy 2 boot ROM</title>
        <published>2015-09-13T00:00:00+00:00</published>
        <updated>2015-09-13T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Joonas Javanainen
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://gekkio.fi/blog/2015/dumping-the-super-game-boy-2-boot-rom/"/>
        <id>https://gekkio.fi/blog/2015/dumping-the-super-game-boy-2-boot-rom/</id>
        
        <content type="html" xml:base="https://gekkio.fi/blog/2015/dumping-the-super-game-boy-2-boot-rom/">&lt;p&gt;I&#x27;m happy to announce that I&#x27;ve succeeded in dumping the Super Game Boy 2 boot ROM. I take my hat off to Costis Sideris, who managed to &lt;a rel=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;www.its.caltech.edu&#x2F;~costis&#x2F;sgb_hack&#x2F;&quot;&gt;dump the original Super Game Boy boot ROM&lt;&#x2F;a&gt;, and documented the procedure with enough details for other people to follow his footsteps. I basically just replicated the same steps on the SGB2 with slightly different tools. The entire process took all my free time on three evenings, but it was fun and we finally have a verified dump of the SGB2 boot ROM! While doing hardware research for my &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;gekkio&#x2F;mooneye-gb&quot;&gt;Mooneye GB emulator&lt;&#x2F;a&gt;, I&#x27;ve acquired a lot of hardware that made it possible to do this. Unlike in the original SGB hack, no FPGA was used.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2015&#x2F;dumping-the-super-game-boy-2-boot-rom&#x2F;#cool-so-where-can-i-get-the-rom&quot;&gt;Skip to the end if you just care about the result&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;h1 id=&quot;how-was-it-done&quot;&gt;How was it done?&lt;&#x2F;h1&gt;
&lt;p&gt;From a high-level perspective, we basically just want to prevent the boot ROM from hiding itself. One of the last instructions in the boot ROM writes to the register $FF50, which hides the boot ROM permanently. There is no way to execute custom code before this, so we need to completely prevent the instruction from executing. There are a few things that are needed:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;The CPU clock needs to be controlled&lt;&#x2F;li&gt;
&lt;li&gt;We need the ability to raise the clock to 24 MHz to overclock the CPU. Overclocking confuses the CPU, so it goes crazy and hopefully will not execute the instruction that hides the boot ROM&lt;&#x2F;li&gt;
&lt;li&gt;There needs to be a trigger that can turn overclocking on at the right time&lt;&#x2F;li&gt;
&lt;li&gt;Once we get past the boot ROM to cartridge space, we need a program that dumps the low 256 bytes containing the boot ROM&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;controlling-the-cpu-clock&quot;&gt;Controlling the CPU clock&lt;&#x2F;h2&gt;
&lt;p&gt;The first step was to find out how the CPU clock is generated and how it could be substituted with an external clock. The CPU in SGB2 uses the same amount of pins as SGB but a different pinout. Therefore, even though there are schematics for SGB, I had to trace some signals to understand the clock generation in detail. In the end I decided to trace &lt;em&gt;all&lt;&#x2F;em&gt; signals on the board, and I plan to publish an interactive PCB visualization of the SGB2 in a later blog post. But for the purposes of this blog post, it&#x27;s enough to know that CPU pin 67 is connected to ICD2 pin 3, which has the CPU clock signal.&lt;&#x2F;p&gt;
&lt;p class=&quot;text-center&quot;&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;2015-09-13-clock-pin.jpg&quot; alt=&quot;Clock pin (pin 67)&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;p&gt;
&lt;p&gt;The SGB uses a divided clock signal from the SNES&#x2F;SFC, while the SGB2 uses a separate clock crystal. Therefore an SGB is always slightly off from the normal Game Boy frequency (4.194304MHz), while an SGB2 is not. In both cases the ICD2 chip handles the low-level clock generation, and the CPU simply gets the clock using one pin from the ICD.&lt;&#x2F;p&gt;
&lt;p&gt;My solution was to very surgically lift the clock pin of the CPU without causing any other permanent damage. I did not want to take out the crystal, because it&#x27;s part of a small circuit and as far as I know could not be directly replaced with a clock signal. One option would&#x27;ve been to lift two ICD2 clock pins, but I decided that one CPU pin would be easier and less risky. I managed to lift the clock pin (pin 67), and soldered a simple connector to make it easy to plug different clock sources. This would later enable me to also connect it back to the ICD2 to restore normal behaviour.&lt;&#x2F;p&gt;
&lt;p class=&quot;text-center&quot;&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;2015-09-13-lifted-pin.jpg&quot; alt=&quot;Lifted pin + connector&quot; &#x2F;&gt;&lt;br&gt;
Lifted pin + connector&lt;&#x2F;p&gt;
&lt;&#x2F;p&gt;
&lt;h2 id=&quot;first-experiments-with-an-arduino&quot;&gt;First experiments with an Arduino&lt;&#x2F;h2&gt;
&lt;p&gt;I wanted to quickly test if controlling the clock would even work on SGB2, and whether the SGB2 survived the soldering or not. I have an &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.arduino.cc&#x2F;en&#x2F;Main&#x2F;arduinoBoardUno&quot;&gt;Arduino Uno&lt;&#x2F;a&gt; device I normally use for peeking and poking Game Boy cartridges. It&#x27;s quite simple to make the Arduino output a 50% duty cycle PWM signal, but the small CPU frequency (16 MHz) limits the possible output frequencies, so the Arduino would not suffice for overclocking in the final dumping procedure. I wrote a simple Arduino program that set up a 2 MHz PWM signal, and connected everything. The Arduino uses 5 V levels, so it was directly compatible with the SGB2.&lt;&#x2F;p&gt;
&lt;p&gt;After connecting everything, I started the Arduino and the SGB2, and was greeted by SGB2 and Nintendo logos, and a half-speed Tetris! So, even an Arduino could be used as a clock for the SGB2. However, I needed something a bit more powerful to reach that 24MHz frequency needed for the overclock.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;triggering-the-overclocking&quot;&gt;Triggering the overclocking&lt;&#x2F;h2&gt;
&lt;p&gt;Generating a clock signal was a nice milestone, but I still needed to implement the higher frequency signal and a trigger for it. The original solution used the FPGA to listen to the address bus, and counted cycles to know exactly when to start overclocking the CPU. Since I wasn&#x27;t using an FPGA, I needed some clever way to implement the triggering.&lt;&#x2F;p&gt;
&lt;p&gt;Earlier this year I designed breakout boards for Game Boy cartridges so I could use my &lt;a rel=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;dangerousprototypes.com&#x2F;docs&#x2F;Open_Bench_Logic_Sniffer&quot;&gt;Open Bench Logic Sniffer&lt;&#x2F;a&gt; to do logic analysis on the cartridge bus. The logic sniffer has a TRGO pin that is connected directly to the FPGA chip. I realized that I could connect it to a microcontroller and use an interrupt to trigger the overclocking. Interrupt handling has a significant delay, so the overclocking would not be triggered immediately, but by nudging timings back and forth I could align the overclocking where I wanted it.&lt;&#x2F;p&gt;
&lt;p&gt;Boot ROM opcode fetches are not visible in the cartridge bus, but IO register and cartridge accesses are. At first I triggered sniffing when the $FF50 register was written to, but this would be too late to start overclocking, especially considering the interrupt handling delay. However, a couple of instructions before writing to $FF50, the boot ROM accesses $FF13 and $FF14, and I was able to set up a chained trigger that would trigger the logic analyser on the $FF14 access. This would also be visible in the TRGO pin and could be used to start the overclocking in the microcontroller.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;teensy-to-the-rescue&quot;&gt;Teensy to the rescue!&lt;&#x2F;h2&gt;
&lt;p&gt;In addition to the Arduino, I also have a &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.pjrc.com&#x2F;teensy&#x2F;teensy31.html&quot;&gt;Teensy 3.1&lt;&#x2F;a&gt; microcontroller. It&#x27;s based on a ARM Cortex-M4 core, which is significantly more powerful than the simple Atmel in the Arduino. I ran the Teensy in 96 MHz mode, which made it very straightforward to set up 2 MHz and 24 MHz signals. The basic idea is still the same: set up 50% duty cycle PWM and set up an interrupt handler that temporarily raises the frequency. Teensy uses 3.3 V logic, but is 5 V tolerant in most pins. Initially I was preparing to use an &lt;a rel=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;www.adafruit.com&#x2F;product&#x2F;395&quot;&gt;Adafruit #395&lt;&#x2F;a&gt; level converter, but a quick test confirmed that 3.3 V clock signal was enough for the SGB2.&lt;&#x2F;p&gt;
&lt;p&gt;Here&#x27;s the Teensyduino program I ended up using:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #24292E; background-color: #FFFFFF;&quot;&gt;&lt;code data-lang=&quot;cpp&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;const int&lt;&#x2F;span&gt;&lt;span&gt; TRIGGER_PIN &lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt; 2&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;const int&lt;&#x2F;span&gt;&lt;span&gt; CLKOUT_PIN &lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt; 6&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;const int&lt;&#x2F;span&gt;&lt;span&gt; BASE_HZ  &lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt;  2000000&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;const int&lt;&#x2F;span&gt;&lt;span&gt; TURBO_HZ &lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt; 24000000&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;void&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; setup&lt;&#x2F;span&gt;&lt;span&gt;() {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;  pinMode&lt;&#x2F;span&gt;&lt;span&gt;(TRIGGER_PIN, INPUT);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;  pinMode&lt;&#x2F;span&gt;&lt;span&gt;(CLKOUT_PIN, OUTPUT);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;  analogWriteResolution&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;  analogWriteFrequency&lt;&#x2F;span&gt;&lt;span&gt;(CLKOUT_PIN, BASE_HZ);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;  analogWrite&lt;&#x2F;span&gt;&lt;span&gt;(CLKOUT_PIN,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt; 2&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;  attachInterrupt&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;digitalPinToInterrupt&lt;&#x2F;span&gt;&lt;span&gt;(TRIGGER_PIN), intr, CHANGE);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;#define&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; NOP&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; __asm__&lt;&#x2F;span&gt;&lt;span&gt; _&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;_volatile__&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;&amp;quot;nop&lt;&#x2F;span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt;\n\t&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;void&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; intr&lt;&#x2F;span&gt;&lt;span&gt;() {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  NOP; NOP; NOP; NOP; NOP;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;  analogWriteFrequency&lt;&#x2F;span&gt;&lt;span&gt;(CLKOUT_PIN, TURBO_HZ);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;  analogWrite&lt;&#x2F;span&gt;&lt;span&gt;(CLKOUT_PIN,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt; 2&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;  analogWriteFrequency&lt;&#x2F;span&gt;&lt;span&gt;(CLKOUT_PIN, BASE_HZ);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;  analogWrite&lt;&#x2F;span&gt;&lt;span&gt;(CLKOUT_PIN,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt; 2&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;void&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; loop&lt;&#x2F;span&gt;&lt;span&gt;() {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The program is fairly straightforward: we set up PWM with a specific frequency and wait for an interrupt. In the interrupt routine we do a few nops to nudge the timing a bit, then quickly switch to a turbo frequency and then back. The amount of nops was something I had to test with trial and error, and 5 nops is the final amount that made the entire procedure work.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-dumper-program&quot;&gt;The dumper program&lt;&#x2F;h2&gt;
&lt;p&gt;Once the CPU skips the $FF50 register write, we need some kind of dumper program in the cartridge address space that can perform the actual dumping. The &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;Gekkio&#x2F;gb-hardware&quot;&gt;GB-BRK-M&#x2F;F boards&lt;&#x2F;a&gt; made it possible for me to use my EMS 64M flash cart for this purpose. Since the triggering was already done using a logic analyser, the cartridge itself doesn&#x27;t need to do anything special. It just needs to be there when the CPU recovers from the overclocking and continues executing code.&lt;&#x2F;p&gt;
&lt;p&gt;I wrote a small dumper program that simply copies the first 256 bytes of the address space to the cartridge RAM. The dumper program also shows a small amount of bytes on the screen, so it was easy to visually verify whether the hack worked or not. A huge amount of nops was included in the beginning of the program, because the overclocking can cause the PC value to be pretty much anything. Adding $1000 nops means that basically any PC value under $1000 would lead the CPU to eventually execute the actual program.&lt;&#x2F;p&gt;
&lt;p&gt;Here&#x27;s the code in wla-dx format. It uses an external &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;Gekkio&#x2F;mooneye-gb&#x2F;blob&#x2F;a5059b128cccd9b9532e3cbd1dd93b3350e76927&#x2F;tests&#x2F;common&#x2F;common.s&quot;&gt;common.s&lt;&#x2F;a&gt; file from my Mooneye GB emulator repository.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #24292E; background-color: #FFFFFF;&quot;&gt;&lt;code data-lang=&quot;asm&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;.define CART_TYPE &lt;&#x2F;span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt;3&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6A737D;&quot;&gt; ; MBC1+RAM+BATTERY&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;.define CART_ROM_BANKS &lt;&#x2F;span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt;4&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;.define CART_RAM_SIZE &lt;&#x2F;span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt;1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;.incdir &amp;quot;..&#x2F;common&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;.include &amp;quot;common.s&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6A737D;&quot;&gt;  ; If the PC gets messed up, lots of NOPs makes it more probable that&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6A737D;&quot;&gt;  ; the CPU might still manage to take us to the following code&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  nops &lt;&#x2F;span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt;$1000&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6A737D;&quot;&gt;  ; Set stack pointer just in case overclocking the CPU messed&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6A737D;&quot;&gt;  ; it up somehow. We are going to call memcpy so the stack has to work&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  ld &lt;&#x2F;span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt;sp&lt;&#x2F;span&gt;&lt;span&gt;, $FFFE&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6A737D;&quot;&gt;  ; Enable cartridge RAM&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  ld a, &lt;&#x2F;span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt;$0A&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  ld (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt;$0000&lt;&#x2F;span&gt;&lt;span&gt;), a&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6A737D;&quot;&gt;  ; Copy first 256 bytes to cartridge RAM&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  ld hl, $A000&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  ld bc, &lt;&#x2F;span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt;$100&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  ld de, &lt;&#x2F;span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt;$0000&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;  call&lt;&#x2F;span&gt;&lt;span&gt; memcpy&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6A737D;&quot;&gt;  ; Disable cartridge RAM&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;  xor&lt;&#x2F;span&gt;&lt;span&gt; a&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  ld (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt;$0000&lt;&#x2F;span&gt;&lt;span&gt;), a&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6A737D;&quot;&gt;  ; Memory dump of first couple of bytes makes it quick to check&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6A737D;&quot;&gt;  ; if $FF50 failed or not&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  ld hl, &lt;&#x2F;span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt;$0000&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  ld a, &lt;&#x2F;span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt;$40&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;  jp&lt;&#x2F;span&gt;&lt;span&gt; dump_mem&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6A737D;&quot;&gt;; Recognizable pattern&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;.org &lt;&#x2F;span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt;$0000&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  .repeat &lt;&#x2F;span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt;$50&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    .&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;db&lt;&#x2F;span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt; $42&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt;$24&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  .endr&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;final-setup&quot;&gt;Final setup&lt;&#x2F;h2&gt;
&lt;p&gt;The final setup is a tall stack of devices and a mess of wires. Beautiful!&lt;&#x2F;p&gt;
&lt;p class=&quot;text-center&quot;&gt;
&lt;p&gt;&lt;a href=&quot;&#x2F;images&#x2F;2015-09-13-final-setup.jpg&quot;&gt;&lt;img src=&quot;&#x2F;images&#x2F;2015-09-13-final-setup.small.jpg&quot; alt=&quot;Final setup&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;br&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;p&gt;
&lt;h1 id=&quot;performing-the-dump&quot;&gt;Performing the dump&lt;&#x2F;h1&gt;
&lt;p&gt;The dumping required many attempts because there were multiple issues:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;There were random $FF13 and $FF14 addresses visible in the bus, which sometimes caused the logic analyser to trigger early&lt;&#x2F;li&gt;
&lt;li&gt;The interrupt on Teensy did not always trigger correctly&lt;&#x2F;li&gt;
&lt;li&gt;Sometimes the CPU stopped completely after the overclocking&lt;&#x2F;li&gt;
&lt;li&gt;Sometimes the CPU ended up having a crazy PC value (e.g. $BCC0) after the overclocking&lt;&#x2F;li&gt;
&lt;li&gt;Sometimes the CPU still executed the $FF50 write successfully&lt;&#x2F;li&gt;
&lt;li&gt;Sometimes the SGB2 stopped working until the SNES was power cycled&lt;&#x2F;li&gt;
&lt;li&gt;Sometimes the EMS cartridge stopped working until the SNES was power cycled&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Some issues with the CPU behaviour were random, while some of them were dependent on exact timing. By adding some nops to the Teensy interrupt code I was able to slightly nudge the timing, which in the end gave me the result I wanted: the CPU failed to execute the $FF50 write and ended up having a PC register value in a sane range. The CPU then executed all the nops and ended up in the dumper program. Afterwards I just dumped the cartridge RAM using a USB cable and the &lt;code&gt;ems-flasher&lt;&#x2F;code&gt; tool. Success!&lt;&#x2F;p&gt;
&lt;p&gt;Here&#x27;s some logic analyser pictures (click to enlarge). The zoom levels and positions are a bit different, so they are not directly comparable (sorry!).&lt;&#x2F;p&gt;
&lt;p class=&quot;text-center&quot;&gt;
&lt;p&gt;&lt;a href=&quot;&#x2F;images&#x2F;2015-09-13-sgb2-normal.png&quot;&gt;&lt;img src=&quot;&#x2F;images&#x2F;2015-09-13-sgb2-normal.small.png&quot; alt=&quot;Normal behaviour&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;br&gt;
Normal behaviour&lt;&#x2F;p&gt;
&lt;&#x2F;p&gt;
&lt;p class=&quot;text-center&quot;&gt;
&lt;p&gt;&lt;a href=&quot;&#x2F;images&#x2F;2015-09-13-sgb2-overclock.png&quot;&gt;&lt;img src=&quot;&#x2F;images&#x2F;2015-09-13-sgb2-overclock.small.png&quot; alt=&quot;Overclocked behaviour&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;br&gt;
Overclocked behaviour&lt;&#x2F;p&gt;
&lt;&#x2F;p&gt;
&lt;p&gt;Let&#x27;s take a closer look at some important moments in the pictures!&lt;&#x2F;p&gt;
&lt;p class=&quot;text-center&quot;&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;2015-09-13-highlight-a.png&quot; alt=&quot;Trigger point&quot; &#x2F;&gt;&lt;br&gt;
Trigger point (time 0.0s) is exactly at the $FF14 access. We can still see the $FF13 address latched in the bus even though the access happened much earlier.&lt;&#x2F;p&gt;
&lt;&#x2F;p&gt;
&lt;p class=&quot;text-center&quot;&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;2015-09-13-highlight-b.png&quot; alt=&quot;Normal behaviour&quot; &#x2F;&gt;&lt;br&gt;
This is what the normal behaviour looks like. We can see the $FF50 access, and then the CPU starts fetching and executing code from $0100, $0101, $0102, etc.&lt;&#x2F;p&gt;
&lt;&#x2F;p&gt;
&lt;p class=&quot;text-center&quot;&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;2015-09-13-highlight-c.png&quot; alt=&quot;Overclocked behaviour&quot; &#x2F;&gt;&lt;br&gt;
This is the overclocked behaviour. We see that the clock stops for a moment, while Teensy is reconfiguring the pin. Then we see the CPU going crazy once the overclocked signal appears.
At this zoom level we can&#x27;t see all the addresses, but I took a closer look in the logic analyser software and $FF50 is not there!&lt;&#x2F;p&gt;
&lt;&#x2F;p&gt;
&lt;p class=&quot;text-center&quot;&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;2015-09-13-highlight-d.png&quot; alt=&quot;CPU going crazy&quot; &#x2F;&gt;&lt;br&gt;
Here we can see the CPU still going crazy and accessing silly addresses. It even reads backwards ($0377, then $0376)! However, once the clock stabilizes, it continues execution from $0377 normally (unfortunately not visible in the picture).&lt;&#x2F;p&gt;
&lt;&#x2F;p&gt;
&lt;h1 id=&quot;cool-so-where-can-i-get-the-rom&quot;&gt;Cool! So where can I get the ROM?&lt;&#x2F;h1&gt;
&lt;p&gt;The ROM itself is probably the most anticlimatic and boring part of the entire thing. The SGB2 ROM differs from the SGB ROM by one byte. It&#x27;s exactly the same difference as with DMG (Game Boy) vs MGB (Game Boy Pocket). &lt;strong&gt;I have no plans to host the ROM anywhere, so you can just create your own if you already have an SGB boot ROM&lt;&#x2F;strong&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;The only difference is the byte at position $00FD. At that position SGB and DMG have the value $01, while MGB and SGB2 have the value $FF. This affects the value of register A that is written to the $FF50 register that hides the boot ROM. The register is never cleared, so the value is also visible to the actual program on the cartridge and can be used to differentiate between different hardware. In disassembled form the last two instructions are:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #24292E; background-color: #FFFFFF;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;LD A, $FF          ; $00FC&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;LD ($FF00+$50), A  ; $00FE&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                   ; $0100: cartridge ROM starts here&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Here&#x27;s some checksums of the SGB2 boot ROM for verification purposes:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;CRC32: &lt;code&gt;53d0dd63&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;MD5: &lt;code&gt;e0430bca9925fb9882148fd2dc2418c1&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;SHA-256: &lt;code&gt;fd243c4fb27008986316ce3df29e9cfbcdc0cd52704970555a8bb76edbec3988&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Mooneye GB: Cartridge analysis - three games with DMG-BEAN-02 boards</title>
        <published>2015-05-18T00:00:00+00:00</published>
        <updated>2015-05-18T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Joonas Javanainen
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://gekkio.fi/blog/2015/mooneye-gb-cartridge-analysis-dmg-bean-02/"/>
        <id>https://gekkio.fi/blog/2015/mooneye-gb-cartridge-analysis-dmg-bean-02/</id>
        
        <content type="html" xml:base="https://gekkio.fi/blog/2015/mooneye-gb-cartridge-analysis-dmg-bean-02/">&lt;p&gt;In my previous blog post I analyzed a Gameboy cartridge with a DMG-BEAN-01 circuit board. This time
we&#x27;ll take a look at three DMG-BEAN-02 games. I didn&#x27;t trace the connections, because the
DMG-BEAN-02 board seems to be identical to DMG-BEAN-01. I&#x27;m sure there&#x27;s some kind of slight change
to justify the version number, but I wasn&#x27;t able to find any practical difference.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;bomber-boy&quot;&gt;Bomber Boy&lt;&#x2F;h2&gt;
&lt;p&gt;Bomber Boy a.k.a Atomic Punk a.k.a Dynablaster is the first Bomberman game released on the Gameboy.
For some reason they decided to have a different name for the game in every major region (JP, EU,
US).&lt;&#x2F;p&gt;
&lt;p class=&quot;text-center&quot;&gt;
&lt;a href=&quot;&#x2F;images&#x2F;gameboy-boards&#x2F;DMG-BEAN-02.DMG-HBA.jpg&quot;&gt;
&lt;img alt=&quot;&quot; width=&quot;600&quot; src=&quot;&#x2F;images&#x2F;gameboy-boards&#x2F;DMG-BEAN-02.DMG-HBA.small.jpg&quot;&gt;
&lt;&#x2F;a&gt;
&lt;&#x2F;p&gt;
&lt;p&gt;My cartridge has the code &lt;em&gt;DMG-HBA&lt;&#x2F;em&gt;, which is the Japanese release of the game (= Bomber Boy), and
the ROM dump matches with &quot;Bomber Boy (J) [!].gb&quot; in the GoodGBX database. This time we have a
1 Mbit (= 128 KB) ROM, which is larger than in the previous blog post. We have one extra address
line, so we have a 17-bit address space ($00000 - $1FFFF).&lt;&#x2F;p&gt;
&lt;div class=&quot;gbpcbvis&quot;&gt;
  &lt;a href=&quot;&#x2F;images&#x2F;gameboy-boards&#x2F;DMG-BEAN-02.DMG-HBA.front.jpg&quot;&gt;
    &lt;img alt=&quot;&quot; width=&quot;400&quot; src=&quot;&#x2F;images&#x2F;gameboy-boards&#x2F;DMG-BEAN-02.DMG-HBA.front.small.jpg&quot;&gt;
  &lt;&#x2F;a&gt;
  &lt;a href=&quot;&#x2F;images&#x2F;gameboy-boards&#x2F;DMG-BEAN-02.DMG-HBA.back.jpg&quot;&gt;
    &lt;img alt=&quot;&quot; width=&quot;400&quot; src=&quot;&#x2F;images&#x2F;gameboy-boards&#x2F;DMG-BEAN-02.DMG-HBA.back.small.jpg&quot;&gt;
  &lt;&#x2F;a&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;As expected, the board has an MBC1 chip, and a Sharp LH5308ND ROM chip labeled with DMG-HBA-0. The
connections are the same as last time with one exception: this time M16 is connected to a valid pin
on the ROM. I used a &lt;strong&gt;Sharp LH530800A&lt;&#x2F;strong&gt; datasheet as a comparison point, but the pin layout is
actually a JEDEC standard so there&#x27;s nothing surprising here.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;wwf-superstars&quot;&gt;WWF Superstars&lt;&#x2F;h2&gt;
&lt;p class=&quot;text-center&quot;&gt;
&lt;a href=&quot;&#x2F;images&#x2F;gameboy-boards&#x2F;DMG-BEAN-02.DMG-LW-USA.jpg&quot;&gt;
&lt;img alt=&quot;&quot; width=&quot;600&quot; src=&quot;&#x2F;images&#x2F;gameboy-boards&#x2F;DMG-BEAN-02.DMG-LW-USA.small.jpg&quot;&gt;
&lt;&#x2F;a&gt;
&lt;&#x2F;p&gt;
&lt;p&gt;My cartridge has the code &lt;em&gt;DMG-LW-USA&lt;&#x2F;em&gt;, so it&#x27;s the US release. The corresponding GoodGBX entry is
&quot;WWF Superstars (UE) [!].gb&quot;, so apparently the European version has the same ROM. This game is also
1 Mbit (= 128 KB).&lt;&#x2F;p&gt;
&lt;div class=&quot;gbpcbvis&quot;&gt;
  &lt;a href=&quot;&#x2F;images&#x2F;gameboy-boards&#x2F;DMG-BEAN-02.DMG-LW-USA.front.jpg&quot;&gt;
    &lt;img alt=&quot;&quot; width=&quot;400&quot; src=&quot;&#x2F;images&#x2F;gameboy-boards&#x2F;DMG-BEAN-02.DMG-LW-USA.front.small.jpg&quot;&gt;
  &lt;&#x2F;a&gt;
  &lt;a href=&quot;&#x2F;images&#x2F;gameboy-boards&#x2F;DMG-BEAN-02.DMG-LW-USA.back.jpg&quot;&gt;
    &lt;img alt=&quot;&quot; width=&quot;400&quot; src=&quot;&#x2F;images&#x2F;gameboy-boards&#x2F;DMG-BEAN-02.DMG-LW-USA.back.small.jpg&quot;&gt;
  &lt;&#x2F;a&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;Once again, we have an MBC1 chip, but this time we have a Toshiba ROM chip: TC531001CF labeled with
DMG-LWE-0. Unlike the previous ROM chips, this chip actually has a public data sheet! However, it
uses the standard layout so there&#x27;s nothing special about it.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;gauntlet-ii&quot;&gt;Gauntlet II&lt;&#x2F;h2&gt;
&lt;p class=&quot;text-center&quot;&gt;
&lt;a href=&quot;&#x2F;images&#x2F;gameboy-boards&#x2F;DMG-BEAN-02.DMG-G2-UKV.jpg&quot;&gt;
&lt;img alt=&quot;&quot; width=&quot;600&quot; src=&quot;&#x2F;images&#x2F;gameboy-boards&#x2F;DMG-BEAN-02.DMG-G2-UKV.small.jpg&quot;&gt;
&lt;&#x2F;a&gt;
&lt;&#x2F;p&gt;
&lt;p&gt;My cartridge has the code &lt;em&gt;DMG-G2-UKV&lt;&#x2F;em&gt;, so it&#x27;s the UK release, and the dump matches with &quot;Gauntlet
II (U) [!].gb&quot; in the GoodGBX database. The game has a 2MBit (= 256 KB) ROM.&lt;&#x2F;p&gt;
&lt;div class=&quot;gbpcbvis&quot;&gt;
  &lt;a href=&quot;&#x2F;images&#x2F;gameboy-boards&#x2F;DMG-BEAN-02.DMG-G2-UKV.front.jpg&quot;&gt;
    &lt;img alt=&quot;&quot; width=&quot;400&quot; src=&quot;&#x2F;images&#x2F;gameboy-boards&#x2F;DMG-BEAN-02.DMG-G2-UKV.front.small.jpg&quot;&gt;
  &lt;&#x2F;a&gt;
  &lt;a href=&quot;&#x2F;images&#x2F;gameboy-boards&#x2F;DMG-BEAN-02.DMG-G2-UKV.back.jpg&quot;&gt;
    &lt;img alt=&quot;&quot; width=&quot;400&quot; src=&quot;&#x2F;images&#x2F;gameboy-boards&#x2F;DMG-BEAN-02.DMG-G2-UKV.back.small.jpg&quot;&gt;
  &lt;&#x2F;a&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;Once again we have an MBC1 chip, and a Toshiba ROM chip: TC532000BF labeled with DMG-G2E-0. Since it
is a bigger ROM than previously, now also M17 is connected to a valid pin.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;what-s-next&quot;&gt;What&#x27;s next?&lt;&#x2F;h2&gt;
&lt;p&gt;This time we didn&#x27;t see anything exciting in the cartridges. The DMG-BEAN boards seem to be very
common, so I think most RAMless classic Gameboy games use that same board layout. Having said that,
I&#x27;m going to analyze an exception to that rule in the next blog post: Super Chinese Fighter GB. It
has an 8Mbit (= 1 MB) ROM chip, so it needs 20 address pins and thus doesn&#x27;t fit the DMG-BEAN
layout.&lt;&#x2F;p&gt;
&lt;p&gt;After analysing Super Chinese Fighter, I&#x27;m going to move on to games with RAM chips. We&#x27;re going to
look at two different RAM sizes, and also an MBC1 game that has a 16Mbit ROM chip, which is the
maximum supported by MBC1. Then it&#x27;s time to peek and poke the cartidges with some test software,
and we can summarize the analysis of MBC1 and figure out how to emulate the chip&#x27;s behaviour
properly.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Mooneye GB: Cartridge analysis - Wizards &amp; Warriors X: Fortress of Fear (MBC1)</title>
        <published>2015-05-17T00:00:00+00:00</published>
        <updated>2015-05-17T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Joonas Javanainen
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://gekkio.fi/blog/2015/mooneye-gb-cartridge-analysis-fortress-of-fear/"/>
        <id>https://gekkio.fi/blog/2015/mooneye-gb-cartridge-analysis-fortress-of-fear/</id>
        
        <content type="html" xml:base="https://gekkio.fi/blog/2015/mooneye-gb-cartridge-analysis-fortress-of-fear/">&lt;p&gt;In this blog post we&#x27;ll take a look at a slightly more advanced cartridge than we saw in the
previous post. This time the cartridge ROM does not fit in the address space $0000 - $7FFF, so an
MBC (memory bank controller) chip is used to map different parts of the physical ROM into the
address space. There are multiple MBC chip types, but we&#x27;ll start with the simplest one: MBC1. The
game we are going analyze is called &lt;em&gt;Wizards &amp;amp; Warriors X: Fortress of Fear&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p class=&quot;text-center&quot;&gt;
&lt;a href=&quot;&#x2F;images&#x2F;gameboy-boards&#x2F;DMG-BEAN-01.DMG-WW-UKV.jpg&quot;&gt;
&lt;img alt=&quot;&quot; width=&quot;600&quot; src=&quot;&#x2F;images&#x2F;gameboy-boards&#x2F;DMG-BEAN-01.DMG-WW-UKV.small.jpg&quot;&gt;
&lt;&#x2F;a&gt;
&lt;&#x2F;p&gt;
&lt;p&gt;My cartridge has the code &lt;em&gt;DMG-WW-UKV&lt;&#x2F;em&gt;, which is probably the UK release of the game (?). The ROM
dump matches with &quot;Wizards &amp;amp; Warriors Chapter X - The Fortress of Fear (E) [!].gb&quot; in the GoodGBX
database, and the database doesn&#x27;t have any other versions, so both European and American releases
might have the same ROM. The ROM size is 512 Kbit (= 64 KB), which corresponds to a 16-bit address
space ($0000 - $FFFF).&lt;&#x2F;p&gt;
&lt;h2 id=&quot;cartridge-pcb-printed-circuit-board&quot;&gt;Cartridge PCB (printed circuit board)&lt;&#x2F;h2&gt;
&lt;script src=&quot;&#x2F;js&#x2F;gb-pcb-vis.js&quot;&gt;&lt;&#x2F;script&gt;
&lt;div data-is=&quot;gbpcbvis&quot; class=&quot;gbpcbvis&quot;&gt;
  &lt;noscript&gt;
    &lt;a href=&quot;&#x2F;images&#x2F;gameboy-boards&#x2F;DMG-BEAN-01.DMG-WW-UKV.front.jpg&quot;&gt;
      &lt;img alt=&quot;&quot; width=&quot;400&quot; src=&quot;&#x2F;images&#x2F;gameboy-boards&#x2F;DMG-BEAN-01.DMG-WW-UKV.front.small.jpg&quot;&gt;
    &lt;&#x2F;a&gt;
    &lt;a href=&quot;&#x2F;images&#x2F;gameboy-boards&#x2F;DMG-BEAN-01.DMG-WW-UKV.back.jpg&quot;&gt;
      &lt;img alt=&quot;&quot; width=&quot;400&quot; src=&quot;&#x2F;images&#x2F;gameboy-boards&#x2F;DMG-BEAN-01.DMG-WW-UKV.back.small.jpg&quot;&gt;
    &lt;&#x2F;a&gt;
  &lt;&#x2F;noscript&gt;
&lt;&#x2F;div&gt;
&lt;script&gt;
  gbPcbVis.mount(&#x27;gbpcbvis&#x27;, {
    connections: gbPcbVis.connections.cartridge.concat([
      &#x27;M14&#x27;, &#x27;M15&#x27;, &#x27;M16&#x27;, &#x27;M17&#x27;, &#x27;M18&#x27;, &#x27;Unused&#x27;
    ]),
    images: [{
      thumb: &#x27;&#x2F;images&#x2F;gameboy-boards&#x2F;DMG-BEAN-01.DMG-WW-UKV.front.small.jpg&#x27;,
      href: &#x27;&#x2F;images&#x2F;gameboy-boards&#x2F;DMG-BEAN-01.DMG-WW-UKV.front.jpg&#x27;,
      svg: &#x27;&#x2F;images&#x2F;gameboy-boards&#x2F;DMG-BEAN-01.DMG-WW-UKV.front.svg&#x27;
    }, {
      thumb: &#x27;&#x2F;images&#x2F;gameboy-boards&#x2F;DMG-BEAN-01.DMG-WW-UKV.back.small.jpg&#x27;,
      href: &#x27;&#x2F;images&#x2F;gameboy-boards&#x2F;DMG-BEAN-01.DMG-WW-UKV.back.jpg&#x27;,
      svg: &#x27;&#x2F;images&#x2F;gameboy-boards&#x2F;DMG-BEAN-01.DMG-WW-UKV.back.svg&#x27;
    }]
  });
&lt;&#x2F;script&gt;
&lt;p&gt;The PCB is DMG-BEAN-01, which is a very common board used in a lot of MBC1 games. MBC1 was the most
common chip in original Gameboy games, so most RAMless MBC1 games have a similar layout. Unlike in
the previous analysis, this time we can actually see the ROM chip on the right side of the board. A
Gameboy ROM chip usually has a game- and version-specific code and a manufacturer part code, which
in this case are DMG-WWE-0 and LH5314B4. On the left side we can see the MBC chip, which is labeled
&quot;MBC1-B&quot;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;connections-on-the-pcb&quot;&gt;Connections on the PCB&lt;&#x2F;h2&gt;
&lt;p&gt;This time we can see all the connections, so things are a bit more interesting. Only CLK and VIN are
not connected, although MREQ, WR and RS are in practice unused because no RAM chip is present. The
address lines A0-A12 are only connected to the ROM chip, so the MBC doesn&#x27;t care about those address
bits. A13 is connected to both the MBC and the ROM, A14 is connected only to the MBC. A15 is
connected to both, but it has a special purpose as outlined in the previous blog post.&lt;&#x2F;p&gt;
&lt;p&gt;In order to understand the purposes of the ROM pins, we need a data sheet for the ROM, but custom
ROMs like this don&#x27;t have public data sheets. However, it seems that the same pin layout can be
found in similar off-the-shelf components from the same manufacturer. In this case, the same layout
can be found in DIP&#x2F;SOP-packaged &lt;strong&gt;Sharp LH531V00&lt;&#x2F;strong&gt; even though it is a 1 MBit chip. So, we expect
the layout to have 20 address pins, where one is unused in the 512 KBit ROM chip.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;Update = Actually, many chips seem to follow the JEDEC 21-C standard, which defines a standard pin
layout for ROM chips up to 8Mbit&lt;&#x2F;em&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Based on the data sheet we can see that A0-A13 are directly connected to the corresponding pins in
the ROM. Address pins 14-15 are connected to the MBC, so the MBC controls the upper 2 bits of the
address the ROM chip sees. In the visualization I&#x27;m using the M14-M18 naming as used by Jeff
Frohwein in his MBC1 schematics. M16, M17 and M18 are connected to the ROM chip, but the data sheet
confirms they are unused. So, as a summary, the ROM address is composed of A0-A13 and M14-M15 giving
us the full 16-bit address space as expected.&lt;&#x2F;p&gt;
&lt;p&gt;The data pins D0-D4 in the cartridge header are connected to both the MBC and the ROM. The remaining
pins D5-D7 are connected only to the ROM. In practice this means that the MBC can only handle 5-bit
values, while the ROM works with the full 8 bits.&lt;&#x2F;p&gt;
&lt;p&gt;The ROM data sheet also mentions the OE (= Output Enable) and CE (Chip Enable) pins. The OE pin is
connected to the RD pin in the cartridge, and the CE pin is connected to the A15 pin in the
cartridge. So, in order to read from the ROM, we need to have RD low and A15 low, so in practice the
ROM chip will respond to reads in the $0000 - $7FFF address range, which is exactly as expected.&lt;&#x2F;p&gt;
&lt;p&gt;There&#x27;s also 4 unused pins in the MBC chip, but I&#x27;ll analyze them in a later blog post once we get
to more complex cartridges where they are actually used.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;notes-for-emulators&quot;&gt;Notes for emulators&lt;&#x2F;h2&gt;
&lt;p&gt;Based on the connections in the PCB, we can summarize the following findings:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Reading $0000 - $7FFF activates the ROM chip, but the physical ROM address is a combination of
14 bits from the address and 2 bits from the MBC&lt;&#x2F;li&gt;
&lt;li&gt;MBC1 can access only address bits 13-15&lt;&#x2F;li&gt;
&lt;li&gt;MBC1 can access only data bits 0-5&lt;&#x2F;li&gt;
&lt;li&gt;MBC1 can access the WR, MREQ, and RS pins (this will be important later)&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;This is not yet enough information to emulate MBC1, but we&#x27;ll get there after we analyze a couple
more cartridges with the chip. In a later blog post I&#x27;ll also show how MBC1 behaves when we peek and
poke some addresses, and we&#x27;ll find out what what bits the M14-M18 pins have in practice.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Mooneye GB: Cartridge analysis - Tetris (no MBC)</title>
        <published>2015-02-28T00:00:00+00:00</published>
        <updated>2015-02-28T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Joonas Javanainen
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://gekkio.fi/blog/2015/mooneye-gb-cartridge-analysis-tetris/"/>
        <id>https://gekkio.fi/blog/2015/mooneye-gb-cartridge-analysis-tetris/</id>
        
        <content type="html" xml:base="https://gekkio.fi/blog/2015/mooneye-gb-cartridge-analysis-tetris/">&lt;p&gt;In my previous blog post, I described the reasons why MBC chips are included in Gameboy game cartridges. Before we start looking at such cartridges, it&#x27;s a good idea to first look at a game that doesn&#x27;t use an MBC. We start our Gameboy cartridge analysis journey by first looking at a very popular game with very simple hardware: Tetris.&lt;&#x2F;p&gt;
&lt;p class=&quot;text-center&quot;&gt;
&lt;a href=&quot;&#x2F;images&#x2F;gameboy-boards&#x2F;DMG-TRA-1.DMG-TR-SCN-1.jpg&quot;&gt;
&lt;img alt=&quot;&quot; width=&quot;600&quot; src=&quot;&#x2F;images&#x2F;gameboy-boards&#x2F;DMG-TRA-1.DMG-TR-SCN-1.small.jpg&quot;&gt;
&lt;&#x2F;a&gt;
&lt;&#x2F;p&gt;
&lt;p&gt;The cartridge I own has the code &lt;em&gt;DMG-TR-SCN-1&lt;&#x2F;em&gt;. &lt;a rel=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;www.gamefaqs.com&#x2F;gameboy&#x2F;585960-tetris&#x2F;data&quot;&gt;The release data at Gamefaqs&lt;&#x2F;a&gt; doesn&#x27;t include this ID for some reason, but based on the patterns in other IDs I think SCN might be a Scandinavian release. I&#x27;ve also dumped the ROM, and it matches with &quot;Tetris (W) (V1.1) [!].gb&quot; in the well-known GoodGBX database.&lt;br&gt;
So, we are probably looking at a &lt;strong&gt;Scandinavian release of Tetris 1.1&lt;&#x2F;strong&gt;, although the GoodTools code &lt;code&gt;(W)&lt;&#x2F;code&gt; suggests the ROM seems to be same worldwide, so the regional differences are probably only in packaging and labels.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;pcb-visualization&quot;&gt;PCB visualization&lt;&#x2F;h3&gt;
&lt;p&gt;I like using visualization to understand things, so I&#x27;ve built an SVG-based Gameboy cartridge PCB visualization tool, which can be used to inspect the connections between the different components and pins on a board. The code is very hacky, but works fairly well (but only in modern browsers!). This tool is included in this post and I&#x27;ll try to have it in future posts as well!&lt;&#x2F;p&gt;
&lt;p&gt;Try the tool by pressing the loading button below, and hovering or clicking on the image and the connection list.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;cartridge-pcb-printed-circuit-board&quot;&gt;Cartridge PCB (printed circuit board)&lt;&#x2F;h2&gt;
&lt;script src=&quot;&#x2F;js&#x2F;gb-pcb-vis.js&quot;&gt;&lt;&#x2F;script&gt;
&lt;div data-is=&quot;gbpcbvis&quot; class=&quot;gbpcbvis&quot;&gt;
  &lt;noscript&gt;
    &lt;a href=&quot;&#x2F;images&#x2F;gameboy-boards&#x2F;DMG-TRA-1.DMG-TR-SCN-1.front.jpg&quot;&gt;
      &lt;img alt=&quot;&quot; width=&quot;400&quot; src=&quot;&#x2F;images&#x2F;gameboy-boards&#x2F;DMG-TRA-1.DMG-TR-SCN-1.front.small.jpg&quot;&gt;
    &lt;&#x2F;a&gt;
    &lt;a href=&quot;&#x2F;images&#x2F;gameboy-boards&#x2F;DMG-TRA-1.DMG-TR-SCN-1.back.jpg&quot;&gt;
      &lt;img alt=&quot;&quot; width=&quot;400&quot; src=&quot;&#x2F;images&#x2F;gameboy-boards&#x2F;DMG-TRA-1.DMG-TR-SCN-1.back.small.jpg&quot;&gt;
    &lt;&#x2F;a&gt;
  &lt;&#x2F;noscript&gt;
&lt;&#x2F;div&gt;
&lt;script&gt;
  gbPcbVis.mount(&#x27;gbpcbvis&#x27;, {
    connections: gbPcbVis.connections.cartridge,
    images: [{
      thumb: &#x27;&#x2F;images&#x2F;gameboy-boards&#x2F;DMG-TRA-1.DMG-TR-SCN-1.front.small.jpg&#x27;,
      href: &#x27;&#x2F;images&#x2F;gameboy-boards&#x2F;DMG-TRA-1.DMG-TR-SCN-1.front.jpg&#x27;,
      svg: &#x27;&#x2F;images&#x2F;gameboy-boards&#x2F;DMG-TRA-1.DMG-TR-SCN-1.front.svg&#x27;
    }, {
      thumb: &#x27;&#x2F;images&#x2F;gameboy-boards&#x2F;DMG-TRA-1.DMG-TR-SCN-1.back.small.jpg&#x27;,
      href: &#x27;&#x2F;images&#x2F;gameboy-boards&#x2F;DMG-TRA-1.DMG-TR-SCN-1.back.jpg&#x27;,
      svg: &#x27;&#x2F;images&#x2F;gameboy-boards&#x2F;DMG-TRA-1.DMG-TR-SCN-1.back.svg&#x27;
    }]
  });
&lt;&#x2F;script&gt;
&lt;p&gt;The first important thing to notice is the PCB IDs: &lt;em&gt;DMG-TRA-1&lt;&#x2F;em&gt; (front) and &lt;em&gt;AAAC S&lt;&#x2F;em&gt; (back). Gameboy games with similar hardware usually have similar PCBs, although there might be minor differences between revisions. The ROM is of course always different, but the PCB layout might be identical between several games.&lt;&#x2F;p&gt;
&lt;p&gt;The second thing to notice is the low amount of components on the board. The only IC (integrated circuit) is the &lt;a rel=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Electronic_packaging#Glob-top&quot;&gt;&quot;Glob-top&quot;&lt;&#x2F;a&gt;-packaged ROM. This type of packaging unfortunately prevents us from seeing the chip itself, so we can&#x27;t see the ROM chip model or any actual pins.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;connections-on-the-pcb&quot;&gt;Connections on the PCB&lt;&#x2F;h3&gt;
&lt;p&gt;The following pins are not connected: CLK, WR, MREQ, RS, VIN. On the other hand, all address pins and data pins are connected, so they could be used to address the full 16-bit address space (2^16 = $0000 - $FFFF), and transfer complete 8-bit bytes.&lt;&#x2F;p&gt;
&lt;p&gt;So, we have 16 address lines connected, but an MBC-less ROM only supports two ROM banks, which corresponds to a 15-bit address space (2^15 = $0000 - $7FFF). This might seem odd at first, but there&#x27;s a job for the 16th address pin: the address lines are shared between multiple components, so when a read request is issued, there has to be a way to control which device handles the request. The solution is to have CS (chip select) active-low signals, which let a component know it should handle the read request.&lt;&#x2F;p&gt;
&lt;p&gt;We can&#x27;t see the actual pins or the ROM chip, but I&#x27;m making an educated guess: A15 is actually connected to the CS pin in the ROM chip. Since CS is an active-low signal, having 0 in bit 15 causes the ROM chip to handle read requests. When does the address bit 15 have the value 0? When the address is $0000 - $7FFF, which is exactly what the ROM address space is.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Fun fact:&lt;&#x2F;strong&gt; Since RS is not connected, you can actually take the Tetris cartridge out of a Gameboy without the console resetting itself. An internal pull-up resistor in the Gameboy keeps the RS line up (= inactive).&lt;&#x2F;p&gt;
&lt;h3 id=&quot;notes-for-emulators&quot;&gt;Notes for emulators&lt;&#x2F;h3&gt;
&lt;p&gt;What things should we consider when emulating ROMs like this?&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;The two ROM banks in $0000 - $7FFF could be emulated with just an array of bytes&lt;&#x2F;li&gt;
&lt;li&gt;WR is not connected, so writes are ignored&lt;&#x2F;li&gt;
&lt;li&gt;The cartridge header data doesn&#x27;t allow ROMs smaller than 32Kbit, so there&#x27;s always exactly two ROM banks if no MBC is used&lt;&#x2F;li&gt;
&lt;li&gt;It&#x27;s in theory possible to have a RAM chip as well, but there are no official games that have RAM but no MBC&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Mooneye GB: Gameboy cartridge types</title>
        <published>2015-02-14T00:00:00+00:00</published>
        <updated>2015-02-14T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Joonas Javanainen
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://gekkio.fi/blog/2015/mooneye-gb-gameboy-cartridge-types/"/>
        <id>https://gekkio.fi/blog/2015/mooneye-gb-gameboy-cartridge-types/</id>
        
        <content type="html" xml:base="https://gekkio.fi/blog/2015/mooneye-gb-gameboy-cartridge-types/">&lt;p&gt;When I started developing &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;Gekkio&#x2F;mooneye-gb&quot;&gt;Mooneye GB&lt;&#x2F;a&gt;, I did the initial work in small gradual steps. I started by emulating things that the Gameboy bootrom uses, so I could see the Nintendo logo animation. After that, I only focused on games which have only a simple 32K ROM (e.g. Tetris). I could&#x27;ve continued with Tetris for a long time, for example by perfecting the GPU emulation or adding sound support, but eventually I got bored and wanted to try some more interesting games. This meant I had to start emulating the Gameboy cartridge hardware.&lt;&#x2F;p&gt;
&lt;p&gt;Like many other old game consoles, Gameboy uses cartridges which can in theory contain any custom hardware, as long as the cartridge pinout is the same and makes sense from the Gameboy&#x27;s point of view. This is a major challenge for emulator writers, because testing and successfully emulating known games might not be possible just by focusing on the main system. For example, some Super Nintendo games contain extra DSP chips (e.g. Super-FX) which significantly complicate development.&lt;&#x2F;p&gt;
&lt;p&gt;Luckily most official Gameboy games can be grouped into a small amount of categories based on which MBC (memory bank controller) and other chips they have. Unlicensed games can have more obscure chips or cheap replicas, but we are going to focus only on the official games.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-need-for-mbcs&quot;&gt;The need for MBCs&lt;&#x2F;h2&gt;
&lt;p&gt;Most Gameboy games contain some kind of MBC chip. The most obvious reason for this is the limited 16-bit address space of the Gameboy CPU. In order to support bigger games, the MBC chips are used to do banking, which provides games with the ability to map different parts of the ROM into the Gameboy memory.&lt;&#x2F;p&gt;
&lt;p&gt;The Gameboy memory map has two areas for ROM banks: $0000 - $3FFF and $4000 - $7FFF. The first area always contains bank 0, which is at $0000 - $3FFF on the actual ROM chip. The second area can point to some other bank, which is determined by the MBC hardware.&lt;&#x2F;p&gt;
&lt;p&gt;In order to better understand what is really happening, it is necessary to look at the actual cartridge hardware. We&#x27;ll start with the cartridge pinout, which is the &quot;interface&quot; between the Gameboy CPU and the cartridge hardware.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;gameboy-cartridge-pinout&quot;&gt;Gameboy cartridge pinout&lt;&#x2F;h2&gt;
&lt;p&gt;The cartridge connector has 32 pins, where most of the pins are used for the individual data and address bits:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #24292E; background-color: #FFFFFF;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt; 1: VCC   5V voltage&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt; 2: CLK   CPU clock signal (AFAIK unused)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt; 3: WR    Write signal&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt; 4: RD    Read signal&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt; 5: CS    Chip select (used for SRAM). Sometimes called MREQ&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt; 6: A0  -\&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  ....    Address&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;21: A15 -&#x2F;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;22: D0  -\&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  ....    Data&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;29: D7  -&#x2F;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;30: RST   Reset signal&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;31: VIN   Cartridge audio signal (AFAIK unused)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;32: GND   Ground&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;reading-from-the-rom&quot;&gt;Reading from the ROM&lt;&#x2F;h2&gt;
&lt;p&gt;Now, let&#x27;s assume the CPU wants to read a byte from address $4242. The CPU sets the bits in the address lines A0-A15 according to the address (e.g. 0100 0010 0100 0010), and signals a read request using the RD pin. The first 14 address lines are usually directly connected to the ROM, so the ROM can see a &quot;masked view&quot; of the actual address. Note that the ROM chip might have much more address lines! The high bits of the final address are actually coming from MBC output lines. For example, a 1 MB rom (2^20 bytes) has 20 address lines, and requires an MBC chip with enough output lines. So, we could have A0-A13 connected to the cartridge header, and A14-A19 connected to the MBC chip. The ROM itself has no knowledge of banking. If it has more than 14 address lines, an MBC chip always manages the high bits of the address. So, in practice an emulator could model the ROM as a big byte array, and model the MBC internal state and thus the high bits of the final address. Also, note that the ROM always has exactly the right amount of address lines (depending on the ROM size), so it is not possible to use &quot;out of bounds&quot; addresses to read from the ROM. Any wrapping or other behaviour with incorrect addresses is caused by other factors.&lt;&#x2F;p&gt;
&lt;p&gt;The exact details of how the MBC chip is connected depends on the MBC chip, other hardware, and the ROM&#x2F;RAM sizes. We&#x27;ll have to look at each combination individually.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;analysis-of-known-mbc-chips&quot;&gt;Analysis of known MBC chips&lt;&#x2F;h2&gt;
&lt;p&gt;I own cartridges with almost all the possible combinations of MBC chips, ROM and RAM sizes. In future blog posts, my plan is to analyze both from a hardware and software point of view all these combinations. I recently bought a &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.insidegadgets.com&#x2F;projects&#x2F;gameboy-cart-shield&#x2F;&quot;&gt;InsideGadgets Gameboy Cart Shield&lt;&#x2F;a&gt; v1.2, which I&#x27;m using to peek and poke (haha) the cartridges.&lt;&#x2F;p&gt;
&lt;p&gt;So, here&#x27;s all the MBC types, and links to blog posts about them if I&#x27;ve written any. There is no MBC4.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;no-mbc&quot;&gt;No MBC&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;a href=&quot;&#x2F;blog&#x2F;2015-02-28-mooneye-gb-cartridge-analysis-tetris.html&quot;&gt;Mooneye GB: Cartridge analysis - Tetris (no MBC)&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;h3 id=&quot;mbc1&quot;&gt;MBC1&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;a href=&quot;&#x2F;blog&#x2F;2015-05-17-mooneye-gb-cartridge-analysis-fortress-of-fear.html&quot;&gt;Mooneye GB: Cartridge analysis - Wizards &amp;amp; Warriors X: Fortress of Fear (MBC1)&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;h3 id=&quot;mbc2&quot;&gt;MBC2&lt;&#x2F;h3&gt;
&lt;h3 id=&quot;mbc3&quot;&gt;MBC3&lt;&#x2F;h3&gt;
&lt;h3 id=&quot;mbc5&quot;&gt;MBC5&lt;&#x2F;h3&gt;
&lt;h3 id=&quot;mbc6&quot;&gt;MBC6&lt;&#x2F;h3&gt;
&lt;h3 id=&quot;mbc7&quot;&gt;MBC7&lt;&#x2F;h3&gt;
&lt;h3 id=&quot;pocket-camera&quot;&gt;Pocket Camera&lt;&#x2F;h3&gt;
&lt;h3 id=&quot;tama5&quot;&gt;TAMA5&lt;&#x2F;h3&gt;
&lt;h3 id=&quot;huc-1&quot;&gt;HuC-1&lt;&#x2F;h3&gt;
&lt;h3 id=&quot;huc-3&quot;&gt;HuC-3&lt;&#x2F;h3&gt;
&lt;h3 id=&quot;mmm01&quot;&gt;MMM01&lt;&#x2F;h3&gt;
&lt;h2 id=&quot;unreliable-cartridge-header-documentation-on-the-internet&quot;&gt;Unreliable cartridge header documentation on the internet&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;strong&gt;If you are building any Gameboy tool or emulator that inspects the cartridge header data, don&#x27;t trust even the Pandocs!!&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Github user AntonioND has correct documentation here: &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;AntonioND&#x2F;giibiiadvance&#x2F;tree&#x2F;master&#x2F;docs&quot;&gt;https:&#x2F;&#x2F;github.com&#x2F;AntonioND&#x2F;giibiiadvance&#x2F;tree&#x2F;master&#x2F;docs&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Here&#x27;s a list of common issues with the cartridge type, rom size, and ram size information:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Includes MBC4 which doesn&#x27;t exist&lt;&#x2F;li&gt;
&lt;li&gt;Wrong type for Pocket Camera (0x1F is incorrect, 0xFC is correct)&lt;&#x2F;li&gt;
&lt;li&gt;Doesn&#x27;t include MBC5&lt;&#x2F;li&gt;
&lt;li&gt;Doesn&#x27;t include MBC6&lt;&#x2F;li&gt;
&lt;li&gt;Doesn&#x27;t include MBC7&lt;&#x2F;li&gt;
&lt;li&gt;Includes weird ROM sizes $52, $53, $53 (72, 80, 96 banks). They don&#x27;t exist (at least in official games)&lt;&#x2F;li&gt;
&lt;li&gt;Doesn&#x27;t include ROM sizes $07, $08 (256, 512 banks).&lt;&#x2F;li&gt;
&lt;li&gt;Incorrect RAM sizes (e.g. $03 = 128Kbit is wrong, 256Kbit is right)&lt;&#x2F;li&gt;
&lt;li&gt;Doesn&#x27;t include RAM size $05 (512 Kbit, 8 banks)&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Here&#x27;s some tools and documents that have issues:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Pandocs&lt;&#x2F;li&gt;
&lt;li&gt;GB crib sheet&lt;&#x2F;li&gt;
&lt;li&gt;The &quot;file&quot; utility on most Linux&#x2F;BSD systems&lt;&#x2F;li&gt;
&lt;li&gt;GBCPUMan&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Mooneye GB: A Gameboy emulator written in Rust</title>
        <published>2015-01-13T00:00:00+00:00</published>
        <updated>2015-01-13T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Joonas Javanainen
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://gekkio.fi/blog/2015/mooneye-gb-a-gameboy-emulator-written-in-rust/"/>
        <id>https://gekkio.fi/blog/2015/mooneye-gb-a-gameboy-emulator-written-in-rust/</id>
        
        <content type="html" xml:base="https://gekkio.fi/blog/2015/mooneye-gb-a-gameboy-emulator-written-in-rust/">&lt;p&gt;Recently my main hobby project has been &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;Gekkio&#x2F;mooneye-gb&quot;&gt;Mooneye GB&lt;&#x2F;a&gt;, a Gameboy emulator written in Rust. There&#x27;s quite a lot of Rust Gameboy emulators, but Mooneye GB is unique: my main focus is accuracy based on rigorous hardware testing. If we move our focus away from Rust, the king of all Gameboy emulators is Gambatte, which is based on similar principles but the documentation is not that good.&lt;&#x2F;p&gt;
&lt;p&gt;While writing my emulator, I noticed that there&#x27;s actually quite little precise documentation about the Gameboy hardware even though I&#x27;ve studied all the well-known documentation (Pan docs, GBCPUMan, Nintendo&#x27;s Gameboy Programming Manual, crib sheets, even the Nintendo patents). Since I have some real hardware and a flash cart, I now develop Mooneye GB by combining knowledge from existing documentation with results of test ROMs which are run using real devices (currently Gameboy Pocket, Gameboy Color, Gameboy Advance SP). I also try to document things well enough for others to follow, so my emulator could work as a reference if someone is curious about some corner cases or hardware behaviour.&lt;&#x2F;p&gt;
&lt;p&gt;As an example, let&#x27;s look at the PUSH&#x2F;POP instructions, which work on a target 16-bit register. POP takes 3 machine cycles (= 12 clock cycles, but I like to use m cycles instead), while PUSH takes 4 machine cycles. Most emulators implement POP BC and PUSH BC like this:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #24292E; background-color: #FFFFFF;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; op&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; read_op&lt;&#x2F;span&gt;&lt;span&gt;();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;match&lt;&#x2F;span&gt;&lt;span&gt; op {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6A737D;&quot;&gt;  &#x2F;&#x2F; ...&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt;  0xC1&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6A737D;&quot;&gt; &#x2F;&#x2F; POP BC&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    cpu&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;bc &lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; mem_read_u16&lt;&#x2F;span&gt;&lt;span&gt;(cpu&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;sp);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    cpu&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;sp &lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;+=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt; 2&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    cpu&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;cycles &lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;+=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt; 3&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  },&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt;  0xC5&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6A737D;&quot;&gt; &#x2F;&#x2F; PUSH BC&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    cpu&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;sp &lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;-=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt; 2&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;    mem_write_u16&lt;&#x2F;span&gt;&lt;span&gt;(cpu&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;sp, cpu&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;bc);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    cpu&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;cycles &lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;+=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt; 4&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6A737D;&quot;&gt;  &#x2F;&#x2F; ...&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This might seem perfectly fine, but is actually inaccurate if we look at the itty-bitty details. If we access a part of memory where timing matters, we might end up emulating the real hardware incorrectly. For example, the VRAM in the Gameboy is only accessible during certain times. If we try to access the VRAM when it&#x27;s inaccessible, our reads will return 0xFF and writes will have no effect.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;pop-timing&quot;&gt;POP timing&lt;&#x2F;h2&gt;
&lt;p&gt;Let&#x27;s imagine that the stack pointer points to some part of VRAM, and we have the following timing:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #24292E; background-color: #FFFFFF;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;0  1  2  3  4  5  6  7  | time (cycles)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;----------------------------+++&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;*  *  *  *  *  *        | VRAM accessibility (* = inaccessible)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            P0 P1 P2    | CPU (POP instruction cycles)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The previous emulation code essentially runs the entire instruction at t=4, but VRAM accessibility changes while the instruction is being executed. We need per-cycle accurate emulation. Based on a &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;Gekkio&#x2F;mooneye-test-suite&#x2F;blob&#x2F;8d742b9d55055f6878a2f3017e0ccf2234cd692c&#x2F;acceptance&#x2F;pop_timing.s&quot;&gt;POP test&lt;&#x2F;a&gt;, the individual cycles execute the following operations:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #24292E; background-color: #FFFFFF;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;P0: Memory read and instruction decoding&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;P1: Memory read for the low byte&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;P2: Memory read for the high byte&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;So, with real hardware the CPU would see 0xFF for the low byte, but the real value for the high byte.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;push-timing&quot;&gt;PUSH timing&lt;&#x2F;h2&gt;
&lt;p&gt;What about PUSH? We essentially do the same thing in reverse, but we now have 4 cycles in total:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #24292E; background-color: #FFFFFF;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;0  1  2  3  4  5  6  7  | time (cycles)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;----------------------------+++&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;*  *  *  *  *  *        | VRAM accessibility (* = inaccessible)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            P0 P1 P2 P3 | CPU (PUSH instruction cycles)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Once again, the previous emulation code runs everything at t=4. Also, PUSH actually has one cycle of some kind of internal delay, so the memory accesses have even more possible timings. Based on a &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;Gekkio&#x2F;mooneye-test-suite&#x2F;blob&#x2F;8d742b9d55055f6878a2f3017e0ccf2234cd692c&#x2F;acceptance&#x2F;push_timing.s&quot;&gt;PUSH test&lt;&#x2F;a&gt;, the individual cycles execute the following operations:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #24292E; background-color: #FFFFFF;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;P0: Memory read and instruction decoding&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;P1: Internal delay&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;P2: Memory write for the high byte&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;P3: Memory write for the low byte&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;So, with real hardware the push would succeed normally, even though VRAM is only accessible 50% of the time spent executing the instruction!&lt;&#x2F;p&gt;
&lt;p&gt;PUSH timing is actually something that Gambatte gets wrong, because the internal delay is at the end of the instruction. So, with Gambatte we would have memory writes at P1-P2, and only the low byte would be written.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;accurate-emulation&quot;&gt;Accurate emulation&lt;&#x2F;h2&gt;
&lt;p&gt;If we aim for accuracy, we must emulate correctly the individual cycles and all observable behaviour of hardware during these cycles. A fairly simple and accurate way of emulation would look something like this:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #24292E; background-color: #FFFFFF;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; op&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; read_op&lt;&#x2F;span&gt;&lt;span&gt;();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;cycle_tick_emulate_hardware&lt;&#x2F;span&gt;&lt;span&gt;();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;match&lt;&#x2F;span&gt;&lt;span&gt; op {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6A737D;&quot;&gt;  &#x2F;&#x2F; ...&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt;  0xC1&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6A737D;&quot;&gt; &#x2F;&#x2F; POP BC&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span&gt; lo&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; mem_read_u8&lt;&#x2F;span&gt;&lt;span&gt;(cpu&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;sp);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    cpu&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;sp &lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;+=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;    cycle_tick_emulate_hardware&lt;&#x2F;span&gt;&lt;span&gt;();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span&gt; hi&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; mem_read_u8&lt;&#x2F;span&gt;&lt;span&gt;(cpu&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;sp);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    cpu&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;sp &lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;+=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;    cycle_tick_emulate_hardware&lt;&#x2F;span&gt;&lt;span&gt;();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    cpu&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;bc &lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt; ((hi&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; as&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; u16&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; &amp;lt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt; 8&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; |&lt;&#x2F;span&gt;&lt;span&gt; (lo&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; as&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; u16&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  },&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt;  0xC5&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6A737D;&quot;&gt; &#x2F;&#x2F; PUSH BC&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;    cycle_tick_emulate_hardware&lt;&#x2F;span&gt;&lt;span&gt;();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    cpu&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;sp &lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;-=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;    mem_write_u8&lt;&#x2F;span&gt;&lt;span&gt;(cpu&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;sp, (cpu&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;bc &lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;&amp;gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt; 8&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; as&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; u8&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;    cycle_tick_emulate_hardware&lt;&#x2F;span&gt;&lt;span&gt;();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    cpu&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;sp &lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;-=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;    mem_write_u8&lt;&#x2F;span&gt;&lt;span&gt;(cpu&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;sp, cpu&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;bc &lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;as&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; u8&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;    cycle_tick_emulate_hardware&lt;&#x2F;span&gt;&lt;span&gt;();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6A737D;&quot;&gt;  &#x2F;&#x2F; ...&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This is what Mooneye GB does currently, but I&#x27;m working on improving the efficiency by only emulating things that have observable side-effects. For example, if the memory writes of PUSH are done to internal RAM, we don&#x27;t have to emulate any other hardware at that point. Essentially the hardware state should be lazily evaluated. I&#x27;m honestly curious how easily this would work with lazily evaluated languages such as Haskell...&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Calling Win32 API with Rust FFI</title>
        <published>2014-10-08T00:00:00+00:00</published>
        <updated>2014-10-08T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Joonas Javanainen
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://gekkio.fi/blog/2014/calling-win32-api-with-rust-ffi/"/>
        <id>https://gekkio.fi/blog/2014/calling-win32-api-with-rust-ffi/</id>
        
        <content type="html" xml:base="https://gekkio.fi/blog/2014/calling-win32-api-with-rust-ffi/">&lt;p&gt;I was recently looking for a simple Windows utility to turn off the screen, and I wanted it to be open source so I could compile it myself and be sure it doesn&#x27;t do anything malicious. There are plenty of options available, but in the end I decided to implement it myself to learn a bit about &lt;a rel=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;rust-lang.org&quot;&gt;Rust&lt;&#x2F;a&gt; on Windows.&lt;&#x2F;p&gt;
&lt;p&gt;Rust is a systems programming language focusing on safety while retaining low-level programming language features whenever possible. I find it extremely interesting, because it feels fresh and modern, but allows me to develop programs for use cases typically restricted to C&#x2F;C++. So far Rust has had a similar effect to me as Haskell: writing code changes the way I think about programming in general. Rust forces you to think about ownership and scoping, and incorrect or unsafe code does not compile by default.&lt;&#x2F;p&gt;
&lt;p&gt;Rust is still very much in flux, so I cannot guarantee the code in this post works at the time of reading.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;how-to-incorrectly-turn-off-the-screen-on-windows&quot;&gt;How to (incorrectly) turn off the screen on Windows&lt;&#x2F;h2&gt;
&lt;p&gt;I had very little knowledge about the Win32 API, so I started by searching for some ideas about how to turn off the screen. Stackoverflow showed me that &lt;a rel=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;superuser.com&#x2F;questions&#x2F;321342&#x2F;turn-off-display-in-windows-7-without-additional-software&quot;&gt;a single Win32 API call&lt;&#x2F;a&gt; could do the trick. So, we need to use the &lt;code&gt;SendMessage&lt;&#x2F;code&gt; call to broadcast a &lt;code&gt;WM_SYSCOMMAND&lt;&#x2F;code&gt; message with &lt;code&gt;SC_MONITORPOWER&lt;&#x2F;code&gt;, although the API call I ended up using is actually the more asynchronous call &lt;code&gt;SendNotifyMessage&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;&#x2F;strong&gt; This is actually &lt;em&gt;not&lt;&#x2F;em&gt; the right way, but seems to work so we can focus on wrapping just a single Win32 API call with the FFI. More information about the wrong way(s) and the right way can be found in &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;devblogs.microsoft.com&#x2F;oldnewthing&#x2F;20060613-05&#x2F;?p=30893&quot;&gt;Raymond Chen&#x27;s blog&lt;&#x2F;a&gt;. In a nutshell, broadcasting is wrong and the right way would be to create our own window to be passed to the call.&lt;&#x2F;p&gt;
&lt;p&gt;By looking at the &lt;a rel=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;msdn.microsoft.com&#x2F;en-us&#x2F;library&#x2F;windows&#x2F;desktop&#x2F;ms644953(v=vs.85).aspx&quot;&gt;MSDN documentation about SendNotifyMessage&lt;&#x2F;a&gt;, it seems that we need to know the types &lt;code&gt;BOOL&lt;&#x2F;code&gt;, &lt;code&gt;HWND&lt;&#x2F;code&gt;, &lt;code&gt;UINT&lt;&#x2F;code&gt;, &lt;code&gt;WPARAM&lt;&#x2F;code&gt;, &lt;code&gt;LPARAM&lt;&#x2F;code&gt; in our FFI interface. MSDN also has a comprehensive list of &lt;a rel=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;msdn.microsoft.com&#x2F;en-us&#x2F;library&#x2F;windows&#x2F;desktop&#x2F;aa383751(v=vs.85).aspx&quot;&gt;Windows data types&lt;&#x2F;a&gt;, which contains information about all the types we need. The list also explains that many of the mentioned types are actually just typedefs to other things, so in practice we also need to know the types &lt;code&gt;HANDLE&lt;&#x2F;code&gt;, &lt;code&gt;PVOID&lt;&#x2F;code&gt;, &lt;code&gt;UINT_PTR&lt;&#x2F;code&gt;, &lt;code&gt;LONG_PTR&lt;&#x2F;code&gt;,&lt;&#x2F;p&gt;
&lt;h2 id=&quot;creating-the-ffi-module&quot;&gt;Creating the FFI module&lt;&#x2F;h2&gt;
&lt;p&gt;Rust FFI doesn&#x27;t support directly importing a C&#x2F;C++ header file unless some extra tools (e.g. rust-bindgen) are used, so we have to fully understand what&#x27;s going on in the header file, and replicate the same interface in the Rust code. This is actually surprisingly tricky, because the header file might include a lot of preprocessor macros, including #ifdefs for different platforms and different compilation settings. We need to be able call this function: &lt;code&gt;BOOL SendNotifyMessage(HWND, UINT, WPARAM, LPARAM)&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;types&quot;&gt;Types&lt;&#x2F;h3&gt;
&lt;p&gt;In order to minimize extra work, we&#x27;ll first look at Rust libc module, which contains many of the types and functions for platform libraries. At the time of writing, the Rust API docs show everything from a POSIX operating system&#x27;s point of view. So, for example the list of re-exported (pub use) symbols in the documentation don&#x27;t include any Windows stuff, so we have to look at the Rust module source code to figure out what symbols are available and which of them are re-exported. The types &lt;code&gt;BOOL&lt;&#x2F;code&gt;, &lt;code&gt;HANDLE&lt;&#x2F;code&gt;, &lt;code&gt;LONG_PTR&lt;&#x2F;code&gt; are already available, and having &lt;code&gt;HANDLE&lt;&#x2F;code&gt; drops the need for &lt;code&gt;PVOID&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;By looking at the Windows data types list, &lt;a rel=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;msdn.microsoft.com&#x2F;en-us&#x2F;library&#x2F;323b6b3k.aspx&quot;&gt;MSDN C Runtime Reference&lt;&#x2F;a&gt;, and the Rust libc module source code, it looks like the rest of the types are actually just C95&#x2F;C99 types. &lt;code&gt;UINT&lt;&#x2F;code&gt; corresponds to &lt;code&gt;libc::c_uint&lt;&#x2F;code&gt;, and &lt;code&gt;UINT_PTR&lt;&#x2F;code&gt; corresponds to &lt;code&gt;libc::uintptr_t&lt;&#x2F;code&gt;. This holds for both 32-bit and 64-bit platforms.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;constants&quot;&gt;Constants&lt;&#x2F;h3&gt;
&lt;p&gt;Constants are quite annoying, because have to duplicate them in the FFI module. Luckily the documentation for &lt;code&gt;SendNotifyMessage&lt;&#x2F;code&gt; and &lt;a rel=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;msdn.microsoft.com&#x2F;en-us&#x2F;library&#x2F;windows&#x2F;desktop&#x2F;ms646360(v=vs.85).aspx&quot;&gt;WM_SYSCOMMAND&lt;&#x2F;a&gt; include the actual values for &lt;code&gt;HWND_BROADCAST&lt;&#x2F;code&gt;, &lt;code&gt;WM_SYSCOMMAND&lt;&#x2F;code&gt; and &lt;code&gt;SC_MONITORPOWER&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;functions&quot;&gt;Functions&lt;&#x2F;h3&gt;
&lt;p&gt;On Windows, many of the functions have Unicode and ANSI versions, and the standard names are actually just #ifdef aliases to the specific functions. Rust doesn&#x27;t care, so we link to the Unicode function directly (&lt;code&gt;SendNotifyMessageW&lt;&#x2F;code&gt;). Two important things have to be considered when creating a function call binding: linking to the right library, and using the right call convention. The function documentation on MSDN specifies that the right library is &lt;code&gt;user32&lt;&#x2F;code&gt;. Call convention has to be figured out from the header. The original C function definition uses the &lt;code&gt;WINAPI&lt;&#x2F;code&gt; macro, which resolves to &lt;code&gt;__stdcall&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;wrapping-up-the-module&quot;&gt;Wrapping up the module&lt;&#x2F;h3&gt;
&lt;p&gt;I think it&#x27;s a good idea to keep all the names of types and functions exactly the same as in the target API. By default Rust warns about non-camel-case types such as &lt;code&gt;BOOL&lt;&#x2F;code&gt;, so we need to explicitly allow them with an annotation. Combining all the earlier work we end up with the following FFI module:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #24292E; background-color: #FFFFFF;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;#[allow(non_camel_case_types)]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;mod&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; ffi&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;  use&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; libc&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span&gt;{c_uint, uintptr_t};&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;  use&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; libc&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;types&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;os&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;arch&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;extra&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;BOOL&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; HANDLE&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; LONG_PTR&lt;&#x2F;span&gt;&lt;span&gt;};&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;  type&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; UINT&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; c_uint;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;  type&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; UINT_PTR&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; uintptr_t;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;  type&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; HWND&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt; HANDLE&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;  type&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; WPARAM&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt; UINT_PTR&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;  type&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; LPARAM&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt; LONG_PTR&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;  pub static&lt;&#x2F;span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt; HWND_BROADCAST&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt; HWND&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt; 0xffff&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; as&lt;&#x2F;span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt; HWND&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;  pub static&lt;&#x2F;span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt; WM_SYSCOMMAND&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt; UINT&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt; 0x0112&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;  pub static&lt;&#x2F;span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt; SC_MONITORPOWER&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt; WPARAM&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt; 0xf170&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  #[link(name &lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt; &amp;quot;user32&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;  extern&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt; &amp;quot;stdcall&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;    pub fn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; SendNotifyMessageW&lt;&#x2F;span&gt;&lt;span&gt;(hwnd&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt; HWND&lt;&#x2F;span&gt;&lt;span&gt;, msg&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt; UINT&lt;&#x2F;span&gt;&lt;span&gt;, wParam&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt; WPARAM&lt;&#x2F;span&gt;&lt;span&gt;, lParam&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt; LPARAM&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt; BOOL&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The extra cast in &lt;code&gt;0xffff as HWND&lt;&#x2F;code&gt; is needed, because the type &lt;code&gt;HWND&lt;&#x2F;code&gt; is a void pointer, which is not compatible with integer literals.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;using-the-ffi-module&quot;&gt;Using the FFI module&lt;&#x2F;h2&gt;
&lt;p&gt;Calling the module is straightforward because we are wrapping a very simple function. All FFI calls require an unsafe block, so let&#x27;s encapsulate the call in a normal function:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #24292E; background-color: #FFFFFF;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;fn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; lcd_off&lt;&#x2F;span&gt;&lt;span&gt;() {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;  unsafe&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6A737D;&quot;&gt;    &#x2F;&#x2F; 2 (the display is being shut off)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;    ffi&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;SendNotifyMessageW&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;ffi&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt;HWND_BROADCAST&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; ffi&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt;WM_SYSCOMMAND&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; ffi&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt;SC_MONITORPOWER&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt; 2&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;finishing-touches&quot;&gt;Finishing touches&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;console-window-flash&quot;&gt;Console window flash&lt;&#x2F;h3&gt;
&lt;p&gt;If you compile the application and run it, you&#x27;ll notice a quick console window flash. This is caused by the fact that Rust compiles applications by default as Windows console applications. To avoid the annoying flash, we need to add linker arguments specifying subsystem as &quot;windows&quot;. As far as I know, the only way to do this is to pass raw arguments using &lt;code&gt;link_args&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #24292E; background-color: #FFFFFF;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6A737D;&quot;&gt;&#x2F;&#x2F; Link as &amp;quot;Windows application&amp;quot; to avoid console window flash&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;#[link_args &lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt; &amp;quot;-Wl,--subsystem,windows&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;extern&lt;&#x2F;span&gt;&lt;span&gt; {}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;removal-of-std&quot;&gt;Removal of std&lt;&#x2F;h3&gt;
&lt;p&gt;This little application doesn&#x27;t need the Rust standard library, which increases the binary size to megabytes. It&#x27;s possible to avoid the standard library, which results in a binary with size in the scale of tens of kilobytes.
&lt;a rel=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;doc.rust-lang.org&#x2F;guide-unsafe.html&quot;&gt;Writing Unsafe and Low-Level Code in Rust&lt;&#x2F;a&gt; describes the required steps in detail.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;final-words&quot;&gt;Final words&lt;&#x2F;h2&gt;
&lt;p&gt;The application is fairly simple and works fine. However, the use of &lt;code&gt;HWND_BROADCAST&lt;&#x2F;code&gt; is incorrect, so using a custom window would be much better.&lt;&#x2F;p&gt;
&lt;p&gt;Source code for the application can be found in &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;Gekkio&#x2F;lcdoff-rs&quot;&gt;Github lcdoff-rs project&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Wandboard Quad</title>
        <published>2014-05-30T13:07:58+02:00</published>
        <updated>2014-05-30T13:07:58+02:00</updated>
        
        <author>
          <name>
            
              Joonas Javanainen
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://gekkio.fi/blog/2014/wandboard-quad/"/>
        <id>https://gekkio.fi/blog/2014/wandboard-quad/</id>
        
        <content type="html" xml:base="https://gekkio.fi/blog/2014/wandboard-quad/">&lt;p&gt;I blogged last year about compiling Cyanogenmod for YW9300, but you might guess from the lack of updates that I never succeeded. The YW9300 had a lot of operating system problems, and I eventually lost interest in the device. The online shop w2comp.com even stopped selling the devices due to the problems, but it looks like they are back in stock now. The manufacturer might have fixed the problems, but I moved on to a different device for my personal Android hacking needs.&lt;&#x2F;p&gt;
&lt;p&gt;So, my current device is a quad-core &lt;a rel=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;wandboard.org&#x2F;&quot;&gt;Wandboard&lt;&#x2F;a&gt;, which is a very nice little device with a Freescale iMX6 SoC. Freescale, Wandboard developers, and a company called Boundary Devices provide the source code of various different versions of iMX6 Android, which makes porting Cyanogenmod a doable task. Wandboard doesn&#x27;t have Android 4.4 yet, but I&#x27;m sure it will be released at some point! Overall I&#x27;m very happy with the device, and I find the overall software and hardware quality to be superior to most cheap Android devices in the similar price range.&lt;&#x2F;p&gt;
&lt;p&gt;One annoying thing about Wandboard is the lack of NAND memory, which means I have to boot using an SD card, which is obviously much slower. The quad model has a SATA port, but using a SATA SSD with Wandboard would require routing of power and a much bigger case than my current one. Using the SD card makes the operating system quite slow, so I might have to connect an SSD anyway at some point to be able to do anything meaningful with the device.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Android hacking with YW9300: Introduction</title>
        <published>2013-06-22T18:48:00+02:00</published>
        <updated>2013-06-22T18:48:00+02:00</updated>
        
        <author>
          <name>
            
              Joonas Javanainen
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://gekkio.fi/blog/2013/android-hacking-with-yw9300-introduction/"/>
        <id>https://gekkio.fi/blog/2013/android-hacking-with-yw9300-introduction/</id>
        
        <content type="html" xml:base="https://gekkio.fi/blog/2013/android-hacking-with-yw9300-introduction/">&lt;p&gt;I&#x27;ve spent a huge chunk of my free time this week on learning Android internals by tinkering with an Android device called YW9300. It&#x27;s a reasonably cheap device with a powerful SoC (system-on-a-chip) called Exynos 4412 (officially &quot;Exynos 4 Quad&quot;). This is the same chip that exists in every Galaxy S III phone, and is also used in some other Samsung and 3rd party products. My goal was to create a bootable custom ROM with Android 4.2 (&quot;Jelly Bean&quot;), because I was unsatisfied with the stock ROM supplied by the manufacturer (I&#x27;ll explain later why). &lt;del&gt;I ended up failing my goal and bricking the device, but&lt;&#x2F;del&gt; I thought I should share my experiences, so other people could use the knowledge I have gained, and avoid the mistakes I did. &lt;ins&gt;Update = I thought I had already tried it, but I managed to recover using an original update.zip!&lt;&#x2F;ins&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;what-exactly-is-yw9300&quot;&gt;What exactly is YW9300?&lt;&#x2F;h2&gt;
&lt;p&gt;YW9300 is an Android TV box device from a Chinese manufacturer called YW Terminal. The device is marketed as a cheap multimedia device to be used with a TV, and it comes with XBMC and a media player preinstalled. The device includes a built-in 802.11n wireless adapter, but has no Bluetooth or Ethernet. At the moment of writing the price of the cheaper model with 1GB memory and 8GB internal storage was $120.&lt;&#x2F;p&gt;
&lt;p&gt;Exynos 4412 is a very powerful SoC at this price point, and the only real competitors are some Allwinner, Rockchip, and i.MX devices. There is a cheaper device (ODROID U2) with Exynos 4412, but I like the minimalistic approach of YW9300 and the fact that it already has a case. The only problem in my opinion is the software, which was a major disappointment.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;issues-with-the-stock-rom&quot;&gt;Issues with the stock ROM&lt;&#x2F;h3&gt;
&lt;h4 id=&quot;android-version&quot;&gt;Android version&lt;&#x2F;h4&gt;
&lt;p&gt;The manufacturer and sellers claim that it contains Android 4.2.1, but actually it is 4.0.x. This is easily verifiable by looking at the build.prop file that I will explain in a later post. Even the device itself says Android 4.2.1 in the About-section, but that is wrong and seems to be just the manufacturer trying to trick people. Claiming they have Android 4.2.1 &lt;em&gt;and&lt;&#x2F;em&gt; support for Flash should already ring the alarm bells, because Flash does &lt;em&gt;not&lt;&#x2F;em&gt; work on Android 4.2+.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;usb-camera-support&quot;&gt;USB camera support&lt;&#x2F;h4&gt;
&lt;p&gt;The marketing material correctly mentions that there is no internal camera or microphone, but they still give the impression that external devices could be used for video chat (e.g. Skype). Based on my testing their kernel does NOT include the uvcvideo driver, which would be required for most USB webcams.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;hardware-decoding&quot;&gt;Hardware decoding&lt;&#x2F;h4&gt;
&lt;p&gt;While Exynos 4412 supports hardware decoding of many formats, the MediaCodec API required for using such codecs in Android apps was added in API level 16 (= Android 4.1.x). The native hardware decoding libraries exist in the system, but as far as I know they are pretty much useless without the MediaCodec API. Claiming support for hardware decoding is most likely just a result of the Android version confusion mentioned above.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;1080p-freezing-hdmi-problems&quot;&gt;1080P freezing &#x2F; HDMI problems&lt;&#x2F;h4&gt;
&lt;p&gt;I haven&#x27;t seen these problems myself, but W2comp.com has stopped selling the boxes due to these issues. These might of course be issues with Samsung source code, which would then appear in custom ROMs too, but at least with a custom build there would be no need to wait for the manufacturer to fix the issues.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;cyanogenmod-10-1-as-the-custom-rom&quot;&gt;Cyanogenmod 10.1 as the custom ROM&lt;&#x2F;h2&gt;
&lt;p&gt;The software wasn&#x27;t good enough for me, and this was a great opportunity to learn more about Android internals, so I decided to build my own custom ROM with Android 4.2.x, and all the needed features. &lt;strong&gt;I strongly recommend all serious Android developers to do some tinkering with custom ROMs, because it is an extremely useful learning experience.&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;At this point you might be wondering why I chose CM (Cyanogenmod):&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;It is the most popular custom ROM, and is actively developed and maintained&lt;&#x2F;li&gt;
&lt;li&gt;I&#x27;m already using it on my HTC One X, so I&#x27;m familiar with it&lt;&#x2F;li&gt;
&lt;li&gt;At the time of writing, CM 10.1 nightlies had experimental support for Exynos 4412 devices like Galaxy S III&lt;&#x2F;li&gt;
&lt;li&gt;The standard AOSP source code doesn&#x27;t support Exynos 4, and while the necessary source code is available from other sources, CM has already retrieved everything into their Github repositories&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;On the other hand, choosing CM did lead to some issues:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;The Exynos 4412 code was still too much in flux, and mixed sometimes incompatible versions of third party libraries&lt;&#x2F;li&gt;
&lt;li&gt;The codebase is geared towards phones and tablets, while the YW9300 is a TV box. This made it a bit difficult to strip away all the phone-like stuff (radio, camera, gps, nfc, etc.)&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;The first issue was a major source of complications, because some libraries simply didn&#x27;t compile correctly due to too old dependencies. The second issue is getting better all the time, because CM 10.1 has introduced support for the ODROID-U2 development board. Too bad I initially missed this and used Galaxy S III code as the template :cry:&lt;&#x2F;p&gt;
&lt;p&gt;Still, even with these two issues I think CM was the right choice. Most other notable ROMs use CM as the base and just add some cool extra stuff, so I think it was simpler to just use the default CM code without any additions. In the next blog post I&#x27;ll take a closer look at the hardware so we&#x27;ll know what we are dealing with.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Increased compile-time safety with phantom types</title>
        <published>2013-02-07T21:22:07+01:00</published>
        <updated>2013-02-07T21:22:07+01:00</updated>
        
        <author>
          <name>
            
              Joonas Javanainen
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://gekkio.fi/blog/2013/increased-compile-time-safety-with-phantom-types/"/>
        <id>https://gekkio.fi/blog/2013/increased-compile-time-safety-with-phantom-types/</id>
        
        <content type="html" xml:base="https://gekkio.fi/blog/2013/increased-compile-time-safety-with-phantom-types/">&lt;h2 id=&quot;introduction&quot;&gt;Introduction&lt;&#x2F;h2&gt;
&lt;p&gt;Using phantom types is a very simple technique that can be used to increase the compile-time safety of code. There are a lot of potential use cases with different levels of complexity, but even a very lightweight usage of phantom types can significantly increase the compile-time safety.&lt;&#x2F;p&gt;
&lt;p&gt;A phantom type is simply a parameterized type with an unused type parameter. For example:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #24292E; background-color: #FFFFFF;&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;public class&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; MyPhantomType&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;T&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;  public&lt;&#x2F;span&gt;&lt;span&gt; String&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; sayHello&lt;&#x2F;span&gt;&lt;span&gt;() {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;     return&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt; &amp;quot;hello&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6A737D;&quot;&gt;  &#x2F;&#x2F; other methods&#x2F;fields that never refer to T&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This example class has a type parameter T, but it is never actually used in the code. At first glance this doesn&#x27;t seem to be very useful, but that&#x27;s not true! All object instances of phantom types carry the type information, so this technique can be used to &quot;tag&quot; values with some extra information that can be compile-time checked. We can of course escape the typing at any time by writing code without the generics, but that should be avoided at all costs. Some languages, such as Scala completely disallow dropping type parameters, so with Scala you would always have to keep the type information completely.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;example-use-case-and-implementation&quot;&gt;Example use case and implementation&lt;&#x2F;h2&gt;
&lt;p&gt;One of the simplest and most useful use cases for phantom types is database ids. If we have a typical three-layer (data, service, web) Java web application, we can gain a lot of compile-time safety by replacing the use of raw ids with phantom types everywhere except at the &quot;endpoints&quot; of the architecture. So, the data layer will put raw ids to database queries, and the web layer might get raw ids from external sources (e.g. HTTP parameters), but otherwise we are always dealing with phantom types. In this example I assume that the database id type is always 64-bit long number. First we&#x27;ll need marker interface that will be implemented by all &quot;entity classes&quot;, which should be supported by the phantom type id mechanism:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #24292E; background-color: #FFFFFF;&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;public interface&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Entity&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  Long&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; getId&lt;&#x2F;span&gt;&lt;span&gt;();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The only purpose of this marker interface is to restrict our phantom typed id to a certain set of tagged classes, and provide the getId method that will be used in the implementation. The actual phantom type is an immutable container for a single id value. The type parameter represents the &quot;target type&quot; of the id, which makes it possible to differentiate between id values of different entities in a compile-time safe way. I like to call this class Ref (shorthand for Reference), but this is just a personal choice.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #24292E; background-color: #FFFFFF;&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;@&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;Value&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;@&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;RequiredArgsConstructor&lt;&#x2F;span&gt;&lt;span&gt;(AccessLevel.PRIVATE)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;public final class&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Ref&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;T extends Entity&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; implements&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Serializable&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;  public final long&lt;&#x2F;span&gt;&lt;span&gt; id;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;  public static&lt;&#x2F;span&gt;&lt;span&gt; &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;T extends Entity&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; Ref&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;T&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; of&lt;&#x2F;span&gt;&lt;span&gt;(T&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt; value&lt;&#x2F;span&gt;&lt;span&gt;) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;    return new&lt;&#x2F;span&gt;&lt;span&gt; Ref&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;T&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;(value.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;getId&lt;&#x2F;span&gt;&lt;span&gt;());&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;  public static&lt;&#x2F;span&gt;&lt;span&gt; &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;T extends Entity&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; Ref&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;T&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; of&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;long&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt; id&lt;&#x2F;span&gt;&lt;span&gt;, Class&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;T&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt; clazz&lt;&#x2F;span&gt;&lt;span&gt;) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;    return new&lt;&#x2F;span&gt;&lt;span&gt; Ref&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;T&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;(id);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  @&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;Override&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;  public&lt;&#x2F;span&gt;&lt;span&gt; String&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; toString&lt;&#x2F;span&gt;&lt;span&gt;() {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;    return&lt;&#x2F;span&gt;&lt;span&gt; String.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;valueOf&lt;&#x2F;span&gt;&lt;span&gt;(id);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This example class uses the @Value and @RequiredArgsConstructor annotations from Project Lombok. If you don&#x27;t use Lombok, add the constructor, getter, equals, and hashCode implementations manually (or look for the complete implementation below). Note how the type parameter T is never used anywhere. This also means that you cannot at runtime know the type of the Ref, but that is not usually necessary.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;using-the-example-implementation&quot;&gt;Using the example implementation&lt;&#x2F;h2&gt;
&lt;p&gt;Now, we&#x27;ll replace the use of raw ids with Refs whenever possible. For example, we could have a service-level method that add a user to a group:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #24292E; background-color: #FFFFFF;&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;void&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; addUserToGroup&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;long&lt;&#x2F;span&gt;&lt;span&gt; userId,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; long&lt;&#x2F;span&gt;&lt;span&gt; groupId);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6A737D;&quot;&gt;&#x2F;&#x2F; without parameter names&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;void&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; addUserToGroup&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;long&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; long&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6A737D;&quot;&gt;&#x2F;&#x2F; VS&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;void&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; addUserToGroup&lt;&#x2F;span&gt;&lt;span&gt;(Ref&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span&gt;User&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; userRef, Ref&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span&gt;Group&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; groupRef);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6A737D;&quot;&gt;&#x2F;&#x2F; without parameter names&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;void&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; addUserToGroup&lt;&#x2F;span&gt;&lt;span&gt;(Ref&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span&gt;User&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;, Ref&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span&gt;Group&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Now, when we want to call this method, we&#x27;ll always need Ref objects instead of raw long values. In this example there are two ways to get Ref values.&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;If you have an instance of the actual object, call Ref.of(object). This is the most common method in layers other than web&lt;&#x2F;li&gt;
&lt;li&gt;If you have a raw id, and you know the target type, call Ref.of(id, TargetType.class). This is usually required in the web layer if the raw id comes from an external source&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;In order to extract the raw id value from the Ref, you can read the field or use the getter. This is typically only needed right before database query construction.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;closing-thoughts&quot;&gt;Closing thoughts&lt;&#x2F;h2&gt;
&lt;p&gt;In order to understand the benefits of Refs, try to think about the following cases:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;What happens if you change the order of parameters in a method call which takes ids of different types? (for example our addUserToGroup)&lt;&#x2F;li&gt;
&lt;li&gt;What happens if you change the type of the database id (e.g. Integer -&amp;gt; Long, or Long -&amp;gt; UUID)?&lt;&#x2F;li&gt;
&lt;li&gt;How likely will you get runtime errors, if you often have method parameters of the same type as the id, but they are not ids? For example, if you have Integer ids and you mix ids and some sort of list indexes in the same method&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;In all of these cases, the use of Refs guarantees that you get a compile-time error in places where the code is not correct. In a typical codebase this is a huge win with very little effort. Compile-time safety decreases the cost and difficulty of refactoring, which makes maintaining the codebase much, much easier and safer.&lt;&#x2F;p&gt;
&lt;p&gt;Database ids are just a simple example of phantom types. Other typical use cases include some sort of state machines (e.g. Order&amp;lt;InProcess&amp;gt;, Order&amp;lt;Completed&amp;gt; vs just Order objects), and some kind of unit information for values (e.g. LongNumber&amp;lt;Weight&amp;gt;, LongNumber&amp;lt;Temperature&amp;gt; vs just longs).&lt;&#x2F;p&gt;
&lt;h2 id=&quot;ref-t-implementation-without-lombok&quot;&gt;Ref&amp;lt;T&amp;gt; implementation (without Lombok)&lt;&#x2F;h2&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #24292E; background-color: #FFFFFF;&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;public final class&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Ref&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;T extends Entity&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; implements&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Serializable&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;  public final long&lt;&#x2F;span&gt;&lt;span&gt; id;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;  public static&lt;&#x2F;span&gt;&lt;span&gt; &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;T extends Entity&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; Ref&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;T&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; of&lt;&#x2F;span&gt;&lt;span&gt;(T&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt; value&lt;&#x2F;span&gt;&lt;span&gt;) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;    return new&lt;&#x2F;span&gt;&lt;span&gt; Ref&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;T&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;(value.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;getId&lt;&#x2F;span&gt;&lt;span&gt;());&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;  public static&lt;&#x2F;span&gt;&lt;span&gt; &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;T extends Entity&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; Ref&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;T&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; of&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;long&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt; id&lt;&#x2F;span&gt;&lt;span&gt;, Class&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;T&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt; clazz&lt;&#x2F;span&gt;&lt;span&gt;) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;    return new&lt;&#x2F;span&gt;&lt;span&gt; Ref&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;T&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;(id);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  @&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;Override&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;  public&lt;&#x2F;span&gt;&lt;span&gt; String&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; toString&lt;&#x2F;span&gt;&lt;span&gt;() {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;    return&lt;&#x2F;span&gt;&lt;span&gt; String.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;valueOf&lt;&#x2F;span&gt;&lt;span&gt;(id);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;  private&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Ref&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;long&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt; id&lt;&#x2F;span&gt;&lt;span&gt;) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt;    this&lt;&#x2F;span&gt;&lt;span&gt;.id&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; id;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;  public long&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; getId&lt;&#x2F;span&gt;&lt;span&gt;() {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;    return&lt;&#x2F;span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt; this&lt;&#x2F;span&gt;&lt;span&gt;.id;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  @&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;Override&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;  public int&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; hashCode&lt;&#x2F;span&gt;&lt;span&gt;() {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;    return&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;int&lt;&#x2F;span&gt;&lt;span&gt;) (id &lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;^&lt;&#x2F;span&gt;&lt;span&gt; (id &lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt; 32&lt;&#x2F;span&gt;&lt;span&gt;));&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  @&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;Override&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;  public boolean&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; equals&lt;&#x2F;span&gt;&lt;span&gt;(Object&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt; o&lt;&#x2F;span&gt;&lt;span&gt;) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;    if&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt;this&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; ==&lt;&#x2F;span&gt;&lt;span&gt; o)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;      return&lt;&#x2F;span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt; true&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;    if&lt;&#x2F;span&gt;&lt;span&gt; (o &lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;==&lt;&#x2F;span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt; null&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; ||&lt;&#x2F;span&gt;&lt;span&gt; o.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;getClass&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; !=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt; this&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;getClass&lt;&#x2F;span&gt;&lt;span&gt;())&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;      return&lt;&#x2F;span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt; false&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    Ref&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;?&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; other&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; (Ref&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;&amp;lt;?&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;) o;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;    return&lt;&#x2F;span&gt;&lt;span&gt; other.id&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; ==&lt;&#x2F;span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt; this&lt;&#x2F;span&gt;&lt;span&gt;.id;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;</content>
        
    </entry>
    <entry xml:lang="en">
        <title>ZK Gritter: Growl-like notifications for ZK apps</title>
        <published>2012-10-22T13:08:40+02:00</published>
        <updated>2012-10-22T13:08:40+02:00</updated>
        
        <author>
          <name>
            
              Joonas Javanainen
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://gekkio.fi/blog/2012/zk-gritter-growl-like-notifications-for-zk-apps/"/>
        <id>https://gekkio.fi/blog/2012/zk-gritter-growl-like-notifications-for-zk-apps/</id>
        
        <content type="html" xml:base="https://gekkio.fi/blog/2012/zk-gritter-growl-like-notifications-for-zk-apps/">&lt;h2 id=&quot;introduction&quot;&gt;Introduction&lt;&#x2F;h2&gt;
&lt;p&gt;Jawwa ZK Gritter is an open source library that can be used to add Growl-like notifications to ZK apps. The library provides a simple-to-use server-side Java API that can be used to control notifications in the application. Installation instructions are available in the reference manual.&lt;&#x2F;p&gt;
&lt;p&gt;A sample app that demonstrates all the customization options is available at Github:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;Gekkio&#x2F;blog&#x2F;tree&#x2F;master&#x2F;2012&#x2F;10&#x2F;zk-gritter&quot;&gt;https:&#x2F;&#x2F;github.com&#x2F;Gekkio&#x2F;blog&#x2F;tree&#x2F;master&#x2F;2012&#x2F;10&#x2F;zk-gritter&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;usage&quot;&gt;Usage&lt;&#x2F;h2&gt;
&lt;p&gt;The library provides a class called Gritter, which contains multiple static methods. Notifications are added using the builder pattern, so you must first obtain a notification builder, build the notification by calling the appropriate methods, and finally complete the builder and show the notification.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #24292E; background-color: #FFFFFF;&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Gritter.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;notification&lt;&#x2F;span&gt;&lt;span&gt;().&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;withTitle&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;&amp;quot;ZK Gritter demo&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;).&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;withText&lt;&#x2F;span&gt;&lt;span&gt;(LOREM_IPSUM).&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;  show&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;All notifications require both the title and text parameters, and you must remember to call show or the notification will not be actually shown to the user.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;customization&quot;&gt;Customization&lt;&#x2F;h2&gt;
&lt;p&gt;The library supports multiple parameters that can be used to customize the appearance and behaviour of the notifications. The API is fully documented with Javadoc.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;timeout-and-stickiness&quot;&gt;Timeout and stickiness&lt;&#x2F;h3&gt;
&lt;p&gt;By default all notifications fade out in 6 seconds, but this can be overridden by setting a custom timeout in milliseconds.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #24292E; background-color: #FFFFFF;&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Gritter.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;notification&lt;&#x2F;span&gt;&lt;span&gt;().&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;withTitle&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;&amp;quot;ZK Gritter demo&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;).&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;withText&lt;&#x2F;span&gt;&lt;span&gt;(LOREM_IPSUM).&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;  withTime&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt;500&lt;&#x2F;span&gt;&lt;span&gt;).&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;show&lt;&#x2F;span&gt;&lt;span&gt;();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;You can also add sticky notifications that don&#x27;t fade out at all unless the user closes them or they are removed programmatically.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #24292E; background-color: #FFFFFF;&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Gritter.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;notification&lt;&#x2F;span&gt;&lt;span&gt;().&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;withTitle&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;&amp;quot;ZK Gritter demo&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;).&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;withText&lt;&#x2F;span&gt;&lt;span&gt;(LOREM_IPSUM).&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;  withSticky&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt;true&lt;&#x2F;span&gt;&lt;span&gt;).&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;show&lt;&#x2F;span&gt;&lt;span&gt;();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;All visible notifications can be cleared manually. Calling removeAll removes both normal and sticky notifications.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #24292E; background-color: #FFFFFF;&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Gritter.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;removeAll&lt;&#x2F;span&gt;&lt;span&gt;();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;custom-css&quot;&gt;Custom CSS&lt;&#x2F;h3&gt;
&lt;p&gt;The sclass parameter can be used to set a custom CSS class.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #24292E; background-color: #FFFFFF;&quot;&gt;&lt;code data-lang=&quot;css&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #22863A;&quot;&gt;style&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;  .gritter-red .gritter-top&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt;    background-image&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt; url&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt;gritter-red.png&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;  .gritter-red .gritter-item&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt;    background-image&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt; url&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt;gritter-red.png&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;  .gritter-red .gritter-bottom&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt;    background-image&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt; url&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt;gritter-red.png&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #22863A;&quot;&gt;style&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;pre class=&quot;giallo&quot; style=&quot;color: #24292E; background-color: #FFFFFF;&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Gritter.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;notification&lt;&#x2F;span&gt;&lt;span&gt;().&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;withTitle&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;&amp;quot;ZK Gritter demo&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;).&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;withText&lt;&#x2F;span&gt;&lt;span&gt;(LOREM_IPSUM).&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;  withSclass&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;&amp;quot;gritter-red&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;).&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;show&lt;&#x2F;span&gt;&lt;span&gt;();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;custom-image&quot;&gt;Custom image&lt;&#x2F;h3&gt;
&lt;p&gt;Notifications can also include an optional 48x48px image.&lt;&#x2F;p&gt;
&lt;p&gt;Java code:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #24292E; background-color: #FFFFFF;&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Gritter.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;notification&lt;&#x2F;span&gt;&lt;span&gt;().&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;withTitle&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;&amp;quot;ZK Gritter demo&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;).&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;withText&lt;&#x2F;span&gt;&lt;span&gt;(LOREM_IPSUM).&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;  withImage&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;&amp;quot;&#x2F;warning.png&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;).&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;show&lt;&#x2F;span&gt;&lt;span&gt;();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Advanced ZK: Asynchronous UI updates and background processing – part 2</title>
        <published>2012-10-20T23:02:56+02:00</published>
        <updated>2012-10-20T23:02:56+02:00</updated>
        
        <author>
          <name>
            
              Joonas Javanainen
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://gekkio.fi/blog/2012/advanced-zk-asynchronous-ui-updates-and-background-processing-part-2/"/>
        <id>https://gekkio.fi/blog/2012/advanced-zk-asynchronous-ui-updates-and-background-processing-part-2/</id>
        
        <content type="html" xml:base="https://gekkio.fi/blog/2012/advanced-zk-asynchronous-ui-updates-and-background-processing-part-2/">&lt;h2 id=&quot;introduction&quot;&gt;Introduction&lt;&#x2F;h2&gt;
&lt;p&gt;In part 1 I showed how server push and threads can be used to execute background tasks in a ZK application. However, the simple example had a major flaw that makes it a bad approach for real-world applications: it starts a new thread for each background task.&lt;&#x2F;p&gt;
&lt;p&gt;JDK5 introduced the ExecutorService class, which abstracts away the threading details, and gives us a nice interface which can be used to submit tasks for background processing.&lt;&#x2F;p&gt;
&lt;p&gt;In this blog post I will describe the most important parts of creating a ZK app, which contains a background task that takes a string, and returns it in uppercase. The complete sample project is available at Github:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;Gekkio&#x2F;blog&#x2F;tree&#x2F;master&#x2F;2012&#x2F;10&#x2F;async-zk-part-2&quot;&gt;https:&#x2F;&#x2F;github.com&#x2F;Gekkio&#x2F;blog&#x2F;tree&#x2F;master&#x2F;2012&#x2F;10&#x2F;async-zk-part-2&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;1-create-an-executorservice-instance&quot;&gt;1. Create an ExecutorService instance&lt;&#x2F;h2&gt;
&lt;p&gt;First we need an ExecutorService that we can use in our ZK code. In most cases we want a shared singleton instance, which could be configured and managed by dependency injection (e.g. Spring). It is very important to make sure that the ExecutorService is created only once, and it&#x27;s shut down properly with the application.&lt;&#x2F;p&gt;
&lt;p&gt;In this sample project I will use a simple holder class, which manages the lifecycle of a single statically available ExecutorService instance. This holder &lt;em&gt;must be configured as a listener&lt;&#x2F;em&gt; in zk.xml.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #24292E; background-color: #FFFFFF;&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;package&lt;&#x2F;span&gt;&lt;span&gt; sample;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;import&lt;&#x2F;span&gt;&lt;span&gt; java.util.concurrent.ExecutorService;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;import&lt;&#x2F;span&gt;&lt;span&gt; java.util.concurrent.Executors;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;import&lt;&#x2F;span&gt;&lt;span&gt; org.zkoss.zk.ui.WebApp;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;import&lt;&#x2F;span&gt;&lt;span&gt; org.zkoss.zk.ui.util.WebAppCleanup;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;import&lt;&#x2F;span&gt;&lt;span&gt; org.zkoss.zk.ui.util.WebAppInit;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;public class&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; SampleExecutorHolder&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; implements&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; WebAppInit&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; WebAppCleanup&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;    private static volatile&lt;&#x2F;span&gt;&lt;span&gt; ExecutorService executor;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;    public static&lt;&#x2F;span&gt;&lt;span&gt; ExecutorService&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; getExecutor&lt;&#x2F;span&gt;&lt;span&gt;() {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;        return&lt;&#x2F;span&gt;&lt;span&gt; executor;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    @&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;Override&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;    public void&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; cleanup&lt;&#x2F;span&gt;&lt;span&gt;(WebApp&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt; wapp&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; throws&lt;&#x2F;span&gt;&lt;span&gt; Exception {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;        if&lt;&#x2F;span&gt;&lt;span&gt; (executor &lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;!=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt; null&lt;&#x2F;span&gt;&lt;span&gt;) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            executor.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;shutdown&lt;&#x2F;span&gt;&lt;span&gt;();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            System.out.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;println&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;&amp;quot;ExecutorService shut down&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    @&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;Override&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;    public void&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; init&lt;&#x2F;span&gt;&lt;span&gt;(WebApp&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt; wapp&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; throws&lt;&#x2F;span&gt;&lt;span&gt; Exception {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        executor &lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt; Executors.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;newFixedThreadPool&lt;&#x2F;span&gt;&lt;span&gt;(Runtime.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;getRuntime&lt;&#x2F;span&gt;&lt;span&gt;().&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;availableProcessors&lt;&#x2F;span&gt;&lt;span&gt;());&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        System.out.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;println&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;&amp;quot;Initialized an ExecutorService&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Note that the thread pool is configured using a fixed size based on processors in the system. Proper thread pool sizing is very important, and depends on the type of tasks you intend to execute. The maximum number of threads is also the maximum amount of simultaneous concurrent tasks!&lt;&#x2F;p&gt;
&lt;h2 id=&quot;2-write-event-classes-that-model-the-results-of-the-background-task&quot;&gt;2. Write event classes that model the results of the background task&lt;&#x2F;h2&gt;
&lt;p&gt;We&#x27;ll use ZK server push to communicate the task results back to the UI, so the results must be modeled as ZK events. It&#x27;s always a good idea to create custom subclasses of Event instead of adding the results in the data parameter, because a custom class is more typesafe and can supports multiple fields.&lt;&#x2F;p&gt;
&lt;p&gt;The first event class represents a status update that is sent while the task is still running. In this example it will contain the amount of characters in the input string.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #24292E; background-color: #FFFFFF;&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;package&lt;&#x2F;span&gt;&lt;span&gt; sample;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;import&lt;&#x2F;span&gt;&lt;span&gt; org.zkoss.zk.ui.event.Event;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;public class&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; FirstStepEvent&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; extends&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Event&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;    public final int&lt;&#x2F;span&gt;&lt;span&gt; amountOfCharacters;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;    public&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; FirstStepEvent&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;int&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt; amountOfCharacters&lt;&#x2F;span&gt;&lt;span&gt;) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt;        super&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;&amp;quot;onFirstStepCompleted&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt; null&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt;        this&lt;&#x2F;span&gt;&lt;span&gt;.amountOfCharacters&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; amountOfCharacters;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}```&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;The second event &lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;class&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; represents&lt;&#x2F;span&gt;&lt;span&gt; the fully completed task. In this example it contains the input string in upper case.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;```java&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;package sample;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;import org.zkoss.zk.ui.event.Event;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;public class&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; SecondStepEvent&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; extends&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Event&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;    public final&lt;&#x2F;span&gt;&lt;span&gt; String upperCaseResult;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;    public&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; SecondStepEvent&lt;&#x2F;span&gt;&lt;span&gt;(String&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt; upperCaseResult&lt;&#x2F;span&gt;&lt;span&gt;) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt;        super&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;&amp;quot;onSecondStepCompleted&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt; null&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt;        this&lt;&#x2F;span&gt;&lt;span&gt;.upperCaseResult&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; upperCaseResult;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}```&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;## &lt;&#x2F;span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt;3.&lt;&#x2F;span&gt;&lt;span&gt; Write the task class&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;The task &lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;class&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; should&lt;&#x2F;span&gt;&lt;span&gt; have the following characteristics:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;*   It &lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;implements&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Runnable&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;*   &lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;It&lt;&#x2F;span&gt;&lt;span&gt; takes all required input data as constructor arguments (the data should be immutable if possible!). &lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;This&lt;&#x2F;span&gt;&lt;span&gt; input data must be thread-safe, and generally should not include any &lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;ZK&lt;&#x2F;span&gt;&lt;span&gt;-related stuff (no components, sessions, etc.). &lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;For&lt;&#x2F;span&gt;&lt;span&gt; example, if you want to use a &lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;Textbox&lt;&#x2F;span&gt;&lt;span&gt; value as input, read the value in advance and _don&amp;#39;t pass the &lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;Textbox&lt;&#x2F;span&gt;&lt;span&gt; itself as an argument_.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;*   &lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;It&lt;&#x2F;span&gt;&lt;span&gt; takes a &lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;Desktop&lt;&#x2F;span&gt;&lt;span&gt;, and at least one &lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;EventListener&lt;&#x2F;span&gt;&lt;span&gt; as constructor arguments. &lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;They&lt;&#x2F;span&gt;&lt;span&gt; are needed for sending the results back to the &lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;UI&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;In&lt;&#x2F;span&gt;&lt;span&gt; this example the only input data is a string that will be used to compute the task results.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;```java&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;package sample;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;import java.util.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;Locale&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;import org.zkoss.zk.ui.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;Desktop&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;import org.zkoss.zk.ui.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;DesktopUnavailableException&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;import org.zkoss.zk.ui.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;Executions&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;import org.zkoss.zk.ui.event.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;Event&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;import org.zkoss.zk.ui.event.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;EventListener&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;public class &lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;SampleTask&lt;&#x2F;span&gt;&lt;span&gt; implements &lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;Runnable&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;    private final&lt;&#x2F;span&gt;&lt;span&gt; String input;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;    private final&lt;&#x2F;span&gt;&lt;span&gt; Desktop desktop;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;    private final&lt;&#x2F;span&gt;&lt;span&gt; EventListener&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;Event&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; eventListener;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    @&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;SuppressWarnings&lt;&#x2F;span&gt;&lt;span&gt;({&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt; &amp;quot;rawtypes&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt; &amp;quot;unchecked&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt; })&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;    public&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; SampleTask&lt;&#x2F;span&gt;&lt;span&gt;(String&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt; input&lt;&#x2F;span&gt;&lt;span&gt;, Desktop&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt; desktop&lt;&#x2F;span&gt;&lt;span&gt;, EventListener&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt; eventListener&lt;&#x2F;span&gt;&lt;span&gt;) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt;        this&lt;&#x2F;span&gt;&lt;span&gt;.input&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; input;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt;        this&lt;&#x2F;span&gt;&lt;span&gt;.desktop&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; desktop;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt;        this&lt;&#x2F;span&gt;&lt;span&gt;.eventListener&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; eventListener;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    @&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;Override&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;    public void&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; run&lt;&#x2F;span&gt;&lt;span&gt;() {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;        try&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6A737D;&quot;&gt;            &#x2F;&#x2F; Step 1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            Thread.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;sleep&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt;10000&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            Executions.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;schedule&lt;&#x2F;span&gt;&lt;span&gt;(desktop, eventListener,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; new&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; FirstStepEvent&lt;&#x2F;span&gt;&lt;span&gt;(input.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;length&lt;&#x2F;span&gt;&lt;span&gt;()));&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6A737D;&quot;&gt;            &#x2F;&#x2F; Step 2&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            Thread.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;sleep&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt;10000&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            Executions.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;schedule&lt;&#x2F;span&gt;&lt;span&gt;(desktop, eventListener,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; new&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; SecondStepEvent&lt;&#x2F;span&gt;&lt;span&gt;(input.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;toUpperCase&lt;&#x2F;span&gt;&lt;span&gt;(Locale.ENGLISH)));&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        }&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; catch&lt;&#x2F;span&gt;&lt;span&gt; (DesktopUnavailableException&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt; e&lt;&#x2F;span&gt;&lt;span&gt;) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            System.err.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;println&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;&amp;quot;Desktop is no longer available: &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; +&lt;&#x2F;span&gt;&lt;span&gt; desktop);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        }&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; catch&lt;&#x2F;span&gt;&lt;span&gt; (InterruptedException&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt; e&lt;&#x2F;span&gt;&lt;span&gt;) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Note how all the constructor arguments are stored in private final fields, and how the input data is immutable (Strings are immutable in Java!). The task simulates long-running processing by using Thread.sleep, and submits a status event when the &quot;processing&quot; is half done.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;4-schedule-tasks-in-zk-composers&quot;&gt;4. Schedule tasks in ZK composers&lt;&#x2F;h2&gt;
&lt;p&gt;Using the task in composers is very simple. You only need to enable server push, and submit a new task instance to the executor. This automatically starts the task once a free background thread is available.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #24292E; background-color: #FFFFFF;&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;desktop.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;enableServerPush&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt;true&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6A737D;&quot;&gt;&#x2F;&#x2F; Get the executor from somewhere&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;executor &lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt; SampleExecutorHolder.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;getExecutor&lt;&#x2F;span&gt;&lt;span&gt;();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;executor.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;execute&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;new&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; SampleTask&lt;&#x2F;span&gt;&lt;span&gt;(input.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;getValue&lt;&#x2F;span&gt;&lt;span&gt;(), desktop,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt; this&lt;&#x2F;span&gt;&lt;span&gt;));&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;In this sample the composer extends GenericForwardComposer, which implements EventListener, so it can itself handle the resulting task events. Both events are handled by methods that update the UI with status information.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #24292E; background-color: #FFFFFF;&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;public void&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; onFirstStepCompleted&lt;&#x2F;span&gt;&lt;span&gt;(FirstStepEvent event) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    status.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;setValue&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;&amp;quot;Task running: &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; +&lt;&#x2F;span&gt;&lt;span&gt; event.amountOfCharacters&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; +&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt; &amp;quot; characters in input&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;public void&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; onSecondStepCompleted&lt;&#x2F;span&gt;&lt;span&gt;(SecondStepEvent event) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    status.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;setValue&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;&amp;quot;Task finished: &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; +&lt;&#x2F;span&gt;&lt;span&gt; event.upperCaseResult);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;final-words&quot;&gt;Final words&lt;&#x2F;h2&gt;
&lt;p&gt;It&#x27;s quite easy to add robust support for long-running tasks in a ZK application by using this technique. The resulting code in ZK composers is very simple, because the results are passed using the typical Event&#x2F;EventListener paradigm that is very common within ZK apps.&lt;&#x2F;p&gt;
&lt;p&gt;The biggest dangers in this technique are thread-safety bugs, which can be very difficult to debug. It is absolutely crucial to fully understand the threads where every piece of code is executed, and ensure that all shared state is fully thread-safe. Using immutable input data, and immutable output events is usually enough to ensure safety as long as the background task itself doesn&#x27;t access other non-thread-safe resources. Some common mistakes are:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Invoking thread-local dependent library methods in the background task (e.g. any method that seems to magically get the &quot;current&quot; value of some type). The background threads will not automatically contain the same thread-local values as servlet threads, so by default all these kind of methods will fail. For example Sessions.getCurrent(), Executions.getCurrent() in ZK, many Spring Security static methods.&lt;&#x2F;li&gt;
&lt;li&gt;Passing non-thread-safe parameters to the background task. For example, passing a mutable List that might be modified by the composer while the task is running (always make copies of mutable collections!).&lt;&#x2F;li&gt;
&lt;li&gt;Passing non-thread-safe result data in events. For example, passing a List in a result event, while the List will be modified later on in the task (always make copies of mutable collections!).&lt;&#x2F;li&gt;
&lt;li&gt;Accessing non-thread-safe methods in the desktop. Even though you have access to the desktop in the background task, most desktop methods are not thread-safe. For example, calling desktop.isAlive() is not guaranteed to return the status correctly (at least in ZK 6.5 the method relies on non-volatile fields, so writes are not guaranteed to be visible in the background thread)&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Java pitfalls: Field access in inner classes</title>
        <published>2012-02-28T09:51:40+01:00</published>
        <updated>2012-02-28T09:51:40+01:00</updated>
        
        <author>
          <name>
            
              Joonas Javanainen
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://gekkio.fi/blog/2012/java-pitfalls-field-access-in-inner-classes/"/>
        <id>https://gekkio.fi/blog/2012/java-pitfalls-field-access-in-inner-classes/</id>
        
        <content type="html" xml:base="https://gekkio.fi/blog/2012/java-pitfalls-field-access-in-inner-classes/">&lt;p&gt;This is not a &quot;pitfall&quot; per se, but an implementation detail worth knowing. Let&#x27;s say I have a inner class with a field. Such a field is visible to the enclosing class, but which one of the following ways is the fastest way to access it? &lt;strong&gt;Note! I&#x27;m only looking here at the generated bytecode, and not considering any JIT optimizations, so this &quot;performance analysis&quot; is very naïve&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #24292E; background-color: #FFFFFF;&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;public class&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Test&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;  public void&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; testAlternatives&lt;&#x2F;span&gt;&lt;span&gt;() {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6A737D;&quot;&gt;    &#x2F;&#x2F; Alternative 1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    System.out.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;println&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;new&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Inner&lt;&#x2F;span&gt;&lt;span&gt;().field);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6A737D;&quot;&gt;    &#x2F;&#x2F; Alternative 2&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    System.out.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;println&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;new&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Inner&lt;&#x2F;span&gt;&lt;span&gt;().&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;getField&lt;&#x2F;span&gt;&lt;span&gt;());&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6A737D;&quot;&gt;    &#x2F;&#x2F; Alternative 3&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    System.out.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;println&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;new&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Inner2&lt;&#x2F;span&gt;&lt;span&gt;().field);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6A737D;&quot;&gt;    &#x2F;&#x2F; Alternative 4&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    System.out.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;println&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;new&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Inner2&lt;&#x2F;span&gt;&lt;span&gt;().&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;getField&lt;&#x2F;span&gt;&lt;span&gt;());&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;  class&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Inner&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;    private int&lt;&#x2F;span&gt;&lt;span&gt; field;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;    public int&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; getField&lt;&#x2F;span&gt;&lt;span&gt;() {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;      return&lt;&#x2F;span&gt;&lt;span&gt; field;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;  class&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Inner2&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;    int&lt;&#x2F;span&gt;&lt;span&gt; field;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;    public int&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; getField&lt;&#x2F;span&gt;&lt;span&gt;() {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;      return&lt;&#x2F;span&gt;&lt;span&gt; field;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;An intuitive answer is that alternatives 1 and 3 are equally fast because the field is always visible to the enclosing class, and both use field access which is overall slightly faster than method access used in alternatives 2 and 4. However, there&#x27;s an implementation detail that causes this to be untrue. The JVM itself does not have a concept called &quot;inner classes&quot;. The whole concept is implemented by the Java compiler and in the bytecode level everything consists of normal classes.&lt;&#x2F;p&gt;
&lt;p&gt;The issue here is that if the inner class has a private field, and the compiler will eventually compile the inner class as a normal class. A private field in a normal class cannot be accessed by other classes, so the enclosing Test class cannot &quot;see&quot; the field without some tricks. Here&#x27;s the above code &quot;desugared&quot; to what the compiler actually compiles to bytecode:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #24292E; background-color: #FFFFFF;&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;public class&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Test&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;  public void&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; testAlternatives&lt;&#x2F;span&gt;&lt;span&gt;() {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6A737D;&quot;&gt;    &#x2F;&#x2F; Alternative 1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    System.out.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;println&lt;&#x2F;span&gt;&lt;span&gt;(Test$Inner.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;access$000&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;new&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Test$Inner&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt;this&lt;&#x2F;span&gt;&lt;span&gt;)));&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6A737D;&quot;&gt;    &#x2F;&#x2F; Alternative 2&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    System.out.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;println&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;new&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Test$Inner&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt;this&lt;&#x2F;span&gt;&lt;span&gt;).&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;getField&lt;&#x2F;span&gt;&lt;span&gt;());&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6A737D;&quot;&gt;    &#x2F;&#x2F; Alternative 3&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    System.out.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;println&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;new&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Test$Inner2&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt;this&lt;&#x2F;span&gt;&lt;span&gt;).field);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6A737D;&quot;&gt;    &#x2F;&#x2F; Alternative 4&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    System.out.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;println&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;new&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Test$Inner2&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt;this&lt;&#x2F;span&gt;&lt;span&gt;).&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;getField&lt;&#x2F;span&gt;&lt;span&gt;());&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;class&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Test$Inner&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;  final&lt;&#x2F;span&gt;&lt;span&gt; Test this$0;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;  private int&lt;&#x2F;span&gt;&lt;span&gt; field;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  Test$&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;Inner&lt;&#x2F;span&gt;&lt;span&gt;(Test&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt; test&lt;&#x2F;span&gt;&lt;span&gt;) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt;    this&lt;&#x2F;span&gt;&lt;span&gt;$0 &lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt; test;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;  public int&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; getField&lt;&#x2F;span&gt;&lt;span&gt;() {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;    return&lt;&#x2F;span&gt;&lt;span&gt; field;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;  static&lt;&#x2F;span&gt;&lt;span&gt; int access$&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;000&lt;&#x2F;span&gt;&lt;span&gt;(Test$Inner&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt; inner&lt;&#x2F;span&gt;&lt;span&gt;) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;    return&lt;&#x2F;span&gt;&lt;span&gt; inner.field;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;class&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Test$Inner2&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;  final&lt;&#x2F;span&gt;&lt;span&gt; Test this$0;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;  int&lt;&#x2F;span&gt;&lt;span&gt; field;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  Test$&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;Inner2&lt;&#x2F;span&gt;&lt;span&gt;(Test&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt; test&lt;&#x2F;span&gt;&lt;span&gt;) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt;    this&lt;&#x2F;span&gt;&lt;span&gt;$0 &lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt; test;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;  public int&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; getField&lt;&#x2F;span&gt;&lt;span&gt;() {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;    return&lt;&#x2F;span&gt;&lt;span&gt; field;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;As you can see, a &lt;em&gt;package-level&lt;&#x2F;em&gt; static accessor method called access$000 is generated in order to grant access to the private field. Now it&#x27;s easier to see that alternative 3 will most likely be the fastest one, because it is the only one that uses direct field access. Using package access in fields is a micro-optimization, but this whole thing is definitely a detail that should be known by Java developers. In performance-critical parts of code it might actually matter, and &lt;del&gt;the Android performance guide&lt;&#x2F;del&gt; (2023 edit: removed dead link) actually mentions this implementation detail.&lt;&#x2F;p&gt;
&lt;p&gt;This implementation detail may also cause slight confusion when field access is attempted on a null reference of the inner class. Consider the following code:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #24292E; background-color: #FFFFFF;&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;public class&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; NullTest&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;  class&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Inner&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;    private int&lt;&#x2F;span&gt;&lt;span&gt; field;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;  public void&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; test&lt;&#x2F;span&gt;&lt;span&gt;() {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    Inner inner&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt; null&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    System.out.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;println&lt;&#x2F;span&gt;&lt;span&gt;(inner.field);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;  public static void&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; main&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;String&lt;&#x2F;span&gt;&lt;span&gt;[]&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt; args&lt;&#x2F;span&gt;&lt;span&gt;) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;    new&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; NullTest&lt;&#x2F;span&gt;&lt;span&gt;().&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;test&lt;&#x2F;span&gt;&lt;span&gt;();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The variable &quot;inner&quot; is null, so a NullPointerException is obviously thrown. However, what is not apparent from the original code is that the exception is thrown inside the compiler-generated static accessor method!&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #24292E; background-color: #FFFFFF;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;$ java NullTest&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Exception in thread &amp;quot;main&amp;quot; java.lang.NullPointerException&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	at NullTest$Inner.access$000(NullTest.java:2)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	at NullTest.test(NullTest.java:8)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	at NullTest.main(NullTest.java:12)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The stack trace contains the intuitive exception source (line 8), but the real source will confuse developers who don&#x27;t know about compiler-generated accessor methods.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Advanced ZK: Asynchronous UI updates and background processing - part 1</title>
        <published>2011-12-30T21:42:30+01:00</published>
        <updated>2011-12-30T21:42:30+01:00</updated>
        
        <author>
          <name>
            
              Joonas Javanainen
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://gekkio.fi/blog/2011/advanced-zk-asynchronous-ui-updates-and-background-processing-part-1/"/>
        <id>https://gekkio.fi/blog/2011/advanced-zk-asynchronous-ui-updates-and-background-processing-part-1/</id>
        
        <content type="html" xml:base="https://gekkio.fi/blog/2011/advanced-zk-asynchronous-ui-updates-and-background-processing-part-1/">&lt;h2 id=&quot;use-cases&quot;&gt;Use cases&lt;&#x2F;h2&gt;
&lt;p&gt;Asynchronous UI updates are very useful, because they typically improve the responsiveness, usability and the general feel of user interfaces. I&#x27;ll be focusing here on the &lt;a rel=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;www.zkoss.org&quot;&gt;ZK&lt;&#x2F;a&gt; framework, but generally the same principles apply for desktop UIs too (Swing, SWT).&lt;&#x2F;p&gt;
&lt;h3 id=&quot;long-running-processing&quot;&gt;Long-running processing&lt;&#x2F;h3&gt;
&lt;p&gt;Sometimes you might have a database query, or an external web service call that takes a long time. Typically these jobs are synchronous, so basically there is a specific point in the code where the system will have to wait for a result and will block the thread that runs the code. If you end up running code like that in an UI thread, it will usually block the UI completely.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;real-time-updates&quot;&gt;Real-time updates&lt;&#x2F;h3&gt;
&lt;p&gt;Sometimes you don&#x27;t know in advance the exact time when something in the UI should be updated. For example, you could have a visual meter that shows the amount of users in an application. When a new user enters the application, the UIs of the current users should be updated as soon as possible to reflect the new user count. You could use a timer-based mechanism to continuously check if the amount of users has changed, but if there&#x27;s too many simultaneous users, the continuous checking will cause a very heavy load even if there is nothing to actually update in the UIs.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;basic-concepts&quot;&gt;Basic concepts&lt;&#x2F;h2&gt;
&lt;p&gt;Let&#x27;s first digest the title of this blog post: &quot;Asyncronous UI updates and background processing&quot;&lt;&#x2F;p&gt;
&lt;h3 id=&quot;background-processing&quot;&gt;Background processing&lt;&#x2F;h3&gt;
&lt;p&gt;In the &lt;em&gt;long-running processing&lt;&#x2F;em&gt; use case the most obvious way to reduce UI blocking is to move expensive processing from the UI threads to some background threads. It&#x27;s very important to be able to understand what kind of thread will run the code in different parts of your application. For example, in ZK applications, most code is executed by servlet threads which are basically servlet world equivalents to UI threads. In order to execute code in some background thread, we&#x27;ll need a thread pool. The easiest way is to use java.util.concurrent.ExecutorService that was introduced in JDK5. We can push Runnable objects to the ExecutorService, so we are basically asking the ExecutorService to run a specific block of code in some background thread.&lt;&#x2F;p&gt;
&lt;p&gt;It is absolutely crucial to understand that frameworks that use ThreadLocals will have problems with this approach because the ThreadLocals that are set in the servlet thread will not be visible in the background thread. An example is Spring Security which by default uses a ThreadLocal to store the security context (= user identity + other things).&lt;&#x2F;p&gt;
&lt;h3 id=&quot;asynchronous-ui-updates&quot;&gt;Asynchronous UI updates&lt;&#x2F;h3&gt;
&lt;p&gt;What does an asynchronous UI update mean in this context? Basically the idea is that once we have some information that we&#x27;d like to present in the UI, we&#x27;ll inform the UI of the new data (= asynchronous) instead of directly updating the UI in the background thread (= synchronous). We cannot know in advance when the new information is available, so we cannot ask for the information from the client side (unless we use polling which is expensive).&lt;&#x2F;p&gt;
&lt;h2 id=&quot;server-push-in-zk&quot;&gt;Server push in ZK&lt;&#x2F;h2&gt;
&lt;p&gt;With ZK we have basically two different approaches we can use to update the UI once a background thread has new information. The name &quot;server push&quot; comes from the fact that the server has some new data that has to be pushed to the client instead of the typical workflow (client asks the server for information). Firstly, you can do synchronous updates by grabbing exclusive access to a desktop by using Executions.activate&#x2F;deactivate. Personally I discourage this because once you have exclusive access, UI threads will have to wait until you deactivate the desktop. That&#x27;s why I won&#x27;t cover this method at all in this blog post.&lt;&#x2F;p&gt;
&lt;p&gt;On the other hand, asynchronous updates are done by using Executions.schedule, which conforms to the Event&#x2F;EventListener model of normal event processing. The idea is that we can push normal ZK Event objects to EventListeners, and the client side will be informed of these events. After that ZK does a normal AJAX request using Javascript and the Events will be processed by the EventListeners. This means that if we use asynchronous updates, all actual event processing will be done by servlet threads and all ThreadLocals are available as usual. This makes the programming model very simple, because you need to only have normal event listener methods without complex concurrent programming.&lt;&#x2F;p&gt;
&lt;p&gt;Here&#x27;s a small example:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #24292E; background-color: #FFFFFF;&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;public class&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; TestComposer&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; extends&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; GenericForwardComposer&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;  private&lt;&#x2F;span&gt;&lt;span&gt; Textbox search;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;  public&lt;&#x2F;span&gt;&lt;span&gt; void onClick$&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;startButton&lt;&#x2F;span&gt;&lt;span&gt;() {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;    if&lt;&#x2F;span&gt;&lt;span&gt; (desktop.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;isServerPushEnabled&lt;&#x2F;span&gt;&lt;span&gt;()) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      desktop.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;enableServerPush&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt;true&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;    final&lt;&#x2F;span&gt;&lt;span&gt; String searchString&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; search.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;getValue&lt;&#x2F;span&gt;&lt;span&gt;();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;    final&lt;&#x2F;span&gt;&lt;span&gt; EventListener el&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt; this&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6A737D;&quot;&gt; &#x2F;&#x2F; All GenericForwardComposers are also EventListeners&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6A737D;&quot;&gt;    &#x2F;&#x2F; Don&amp;#39;t do this in a real-world application. Use thread pools instead.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    Thread backgroundThread&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; = new&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Thread&lt;&#x2F;span&gt;&lt;span&gt;() {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;       public void&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; run&lt;&#x2F;span&gt;&lt;span&gt;() {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6A737D;&quot;&gt;         &#x2F;&#x2F; In this part of code the ThreadLocals ARE NOT available&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6A737D;&quot;&gt;         &#x2F;&#x2F; You must NOT touch any ZK related things (e.g. components, desktops)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6A737D;&quot;&gt;         &#x2F;&#x2F; If you need some information from ZK, you need to get them before this code&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6A737D;&quot;&gt;         &#x2F;&#x2F; For example here I&amp;#39;ve read searchString from a textbox, so I can use the searchString variable without problems&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;         String result&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; ...&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6A737D;&quot;&gt; &#x2F;&#x2F; Retrieve the result from somewhere&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;         Executions.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;schedule&lt;&#x2F;span&gt;&lt;span&gt;(desktop, el,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; new&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Event&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;&amp;quot;onNewData&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt; null&lt;&#x2F;span&gt;&lt;span&gt;, result));&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;       }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    };&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    backgroundThread.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;start&lt;&#x2F;span&gt;&lt;span&gt;();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;  public void&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; onNewData&lt;&#x2F;span&gt;&lt;span&gt;(Event&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt; event&lt;&#x2F;span&gt;&lt;span&gt;) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6A737D;&quot;&gt;    &#x2F;&#x2F; In this part of code the ThreadLocals ARE available&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    String result&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; (String) event.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;getData&lt;&#x2F;span&gt;&lt;span&gt;();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6A737D;&quot;&gt;    &#x2F;&#x2F; Do something with result. You can touch any ZK stuff freely, just like when a normal event is posted.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;In part 2 I show you how to use JDK5 ExecutorServices to run tasks without manually creating threads. If you truly want to understand ZK server push, you should also read the &lt;a rel=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;books.zkoss.org&#x2F;wiki&#x2F;ZK%20Developer%27s%20Reference&#x2F;Server%20Push&quot;&gt;relevant ZK documentation&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>In defense of Scala: Understanding the ++ operator</title>
        <published>2011-11-29T12:13:07+01:00</published>
        <updated>2011-11-29T12:13:07+01:00</updated>
        
        <author>
          <name>
            
              Joonas Javanainen
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://gekkio.fi/blog/2011/in-defense-of-scala-understanding-the-operator/"/>
        <id>https://gekkio.fi/blog/2011/in-defense-of-scala-understanding-the-operator/</id>
        
        <content type="html" xml:base="https://gekkio.fi/blog/2011/in-defense-of-scala-understanding-the-operator/">&lt;p&gt;Many people, including &lt;a rel=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;blog.joda.org&#x2F;2011&#x2F;11&#x2F;scala-feels-like-ejb-2-and-other.html&quot;&gt;Stephen Colebourne&lt;&#x2F;a&gt;, have complained about some of the methods in the Scala collections API. A common example is the ++ operator:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #24292E; background-color: #FFFFFF;&quot;&gt;&lt;code data-lang=&quot;scala&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6A737D;&quot;&gt;&#x2F;&#x2F; There are many variants but this is what Stephen Colebourne used as an example&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;def&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; ++&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;B&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; &amp;gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; A&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;That&lt;&#x2F;span&gt;&lt;span&gt;] (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt;that&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; TraversableOnce&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;B&lt;&#x2F;span&gt;&lt;span&gt;])(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;implicit&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt; bf&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; CanBuildFrom&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;List&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;A&lt;&#x2F;span&gt;&lt;span&gt;], &lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;B&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;That&lt;&#x2F;span&gt;&lt;span&gt;])&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; :&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; That&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Here&#x27;s an example of its use:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #24292E; background-color: #FFFFFF;&quot;&gt;&lt;code data-lang=&quot;scala&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;val&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt; first&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; List&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt;3&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;val&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt; second&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; List&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt;4&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt;5&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt;6&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;println(first &lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;++&lt;&#x2F;span&gt;&lt;span&gt; second)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6A737D;&quot;&gt;&#x2F;&#x2F; List(1, 2, 3, 4, 5, 6)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;In this blog post I&#x27;ll try to show that the perceived complexity of the definition is a necessary thing arising from several design goals. I&#x27;ll try to show code examples in Java so that the overall syntax is familiar for most people. Basically I&#x27;m trying to say that by following the following three goals you end up with the same kind of definition that Scala has (except that it cannot be represented with Java without violating any of the goals). If you feel that your grasp of Java generics is lacking or just want the TLDR version, you can &lt;a href=&quot;https:&#x2F;&#x2F;gekkio.fi&#x2F;blog&#x2F;2011&#x2F;in-defense-of-scala-understanding-the-operator&#x2F;#overview-of-the-final-java-version&quot;&gt;skip right away to the monstrosity&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;design-goals&quot;&gt;Design goals&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;1-immutability&quot;&gt;1. Immutability&lt;&#x2F;h3&gt;
&lt;ul&gt;
&lt;li&gt;The collection classes should be immutable.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3 id=&quot;2-type-safety&quot;&gt;2. Type safety&lt;&#x2F;h3&gt;
&lt;ul&gt;
&lt;li&gt;The API should be as type safe as possible (explicit instanceofs or casts should not be needed)&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3 id=&quot;3-conformity-with-oop&quot;&gt;3. Conformity with OOP&lt;&#x2F;h3&gt;
&lt;ul&gt;
&lt;li&gt;Common methods should also be abstracted to interfaces if possible&lt;&#x2F;li&gt;
&lt;li&gt;The collection classes should work with element subtypes&#x2F;supertypes correctly&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;common-code&quot;&gt;Common code&lt;&#x2F;h2&gt;
&lt;p&gt;First we have a naive ImmutableList implementation that just wraps a standard Java list:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #24292E; background-color: #FFFFFF;&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6A737D;&quot;&gt;&#x2F;&#x2F; ImmutableList.java&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;public class&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; ImmutableList&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;A&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;  private final&lt;&#x2F;span&gt;&lt;span&gt; List&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;A&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; inner;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;  private&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; ImmutableList&lt;&#x2F;span&gt;&lt;span&gt;(List&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;A&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt; inner&lt;&#x2F;span&gt;&lt;span&gt;) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt;    this&lt;&#x2F;span&gt;&lt;span&gt;.inner&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; inner;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;  public static&lt;&#x2F;span&gt;&lt;span&gt; ImmutableList&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;A&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; of&lt;&#x2F;span&gt;&lt;span&gt;(A&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt; value1&lt;&#x2F;span&gt;&lt;span&gt;, A&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt; value2&lt;&#x2F;span&gt;&lt;span&gt;) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    List&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;A&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; inner&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; = new&lt;&#x2F;span&gt;&lt;span&gt; ArrayList&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;A&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    inner.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;add&lt;&#x2F;span&gt;&lt;span&gt;(value1);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    inner.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;add&lt;&#x2F;span&gt;&lt;span&gt;(value2);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;    return new&lt;&#x2F;span&gt;&lt;span&gt; ImmutableList&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;A&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;(inner);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We&#x27;ll also use some data types to demonstrate design goal 3:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #24292E; background-color: #FFFFFF;&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;public interface&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Animal&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  String&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; getSound&lt;&#x2F;span&gt;&lt;span&gt;();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;public class&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Cat&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; implements&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Animal&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;  public&lt;&#x2F;span&gt;&lt;span&gt; String&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; getSound&lt;&#x2F;span&gt;&lt;span&gt;() {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;    return&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt; &amp;quot;meow&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;public class&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Dog&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; implements&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Animal&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;  public&lt;&#x2F;span&gt;&lt;span&gt; String&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; getSound&lt;&#x2F;span&gt;&lt;span&gt;() {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;    return&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt; &amp;quot;woof&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;attempt-1&quot;&gt;Attempt 1&lt;&#x2F;h2&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #24292E; background-color: #FFFFFF;&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6A737D;&quot;&gt;&#x2F;&#x2F; ImmutableList.java&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;public&lt;&#x2F;span&gt;&lt;span&gt; ImmutableList&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span&gt;A&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; concat&lt;&#x2F;span&gt;&lt;span&gt;(ImmutableList&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span&gt;A&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; other) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  List&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;A&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; newInner&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; = new&lt;&#x2F;span&gt;&lt;span&gt; ArrayList&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;A&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  newInner.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;addAll&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt;this&lt;&#x2F;span&gt;&lt;span&gt;.inner);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  newInner.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;addAll&lt;&#x2F;span&gt;&lt;span&gt;(other.inner);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;  return new&lt;&#x2F;span&gt;&lt;span&gt; ImmutableList&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;A&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;(newInner);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Well that was easy, right?&lt;&#x2F;p&gt;
&lt;p&gt;Nope, the implementation doesn&#x27;t support variances (return element type can be super type of T, argument element type can be sub type of T).&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #24292E; background-color: #FFFFFF;&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;ImmutableList&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;Cat&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; cats&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; ImmutableList.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;of&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;new&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Cat&lt;&#x2F;span&gt;&lt;span&gt;(),&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; new&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Cat&lt;&#x2F;span&gt;&lt;span&gt;());&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;ImmutableList&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;Dog&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; dogs&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; ImmutableList.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;of&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;new&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Dog&lt;&#x2F;span&gt;&lt;span&gt;(),&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; new&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Dog&lt;&#x2F;span&gt;&lt;span&gt;());&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;ImmutableList&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;Animal&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; animals&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; cats.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;concat&lt;&#x2F;span&gt;&lt;span&gt;(dogs);&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6A737D;&quot;&gt; &#x2F;&#x2F; Will NOT compile&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;attempt-2&quot;&gt;Attempt 2&lt;&#x2F;h2&gt;
&lt;p&gt;As far as I know, it&#x27;s not possible to make the above code compile with Java unless you drop generics (= violate goal 2). It&#x27;s possible to play with wildcards if you make it a static method instead:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #24292E; background-color: #FFFFFF;&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6A737D;&quot;&gt;&#x2F;&#x2F; ImmutableList.java&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;public static &amp;lt;&lt;&#x2F;span&gt;&lt;span&gt;S&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; ImmutableList&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span&gt;S&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; concat&lt;&#x2F;span&gt;&lt;span&gt;(ImmutableList&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;&amp;lt;?&lt;&#x2F;span&gt;&lt;span&gt; extends S&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; first, ImmutableList&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;&amp;lt;?&lt;&#x2F;span&gt;&lt;span&gt; extends S&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; second) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  List&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;S&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; newInner&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; = new&lt;&#x2F;span&gt;&lt;span&gt; ArrayList&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;S&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  newInner.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;addAll&lt;&#x2F;span&gt;&lt;span&gt;(first.inner);   &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  newInner.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;addAll&lt;&#x2F;span&gt;&lt;span&gt;(second.inner);  &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;  return new&lt;&#x2F;span&gt;&lt;span&gt; ImmutableList&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;S&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;(newInner);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;But a static method is a completely different beast, so let&#x27;s just ignore this problem for a moment and forget the support for variances. We are violating goal 3, but let&#x27;s just go on.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;attempt-3&quot;&gt;Attempt 3&lt;&#x2F;h2&gt;
&lt;p&gt;Now let&#x27;s imagine we extend our immutable collection library with another type: ImmutableSet. We want to be able to concat sets too, so we create a concat method (still violating goal 3 regarding variances):&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #24292E; background-color: #FFFFFF;&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6A737D;&quot;&gt;&#x2F;&#x2F; ImmutableSet.java&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;public&lt;&#x2F;span&gt;&lt;span&gt; ImmutableSet&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span&gt;A&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; concat&lt;&#x2F;span&gt;&lt;span&gt;(ImmutableSet&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span&gt;A&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; other);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Now, based on goal 3 we must abstract this concat method to an interface called ImmutableCollection:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #24292E; background-color: #FFFFFF;&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6A737D;&quot;&gt;&#x2F;&#x2F; ImmutableCollection.java&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;public interface&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; ImmutableCollection&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;A&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  ImmutableCollection&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;A&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; concat&lt;&#x2F;span&gt;&lt;span&gt;(ImmutableCollection&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;A&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt; other&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Looks good, right?&lt;&#x2F;p&gt;
&lt;p&gt;Nope, the concat method now returns a generic collection, and the actual type is lost. It&#x27;s very reasonable to expect this to work:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #24292E; background-color: #FFFFFF;&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;ImmutableList&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;Dog&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; dogs&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; ImmutableList.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;of&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;new&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Dog&lt;&#x2F;span&gt;&lt;span&gt;(),&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; new&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Dog&lt;&#x2F;span&gt;&lt;span&gt;());&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;ImmutableList&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;Dog&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; moreDogs&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; ImmutableList.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;of&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;new&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Dog&lt;&#x2F;span&gt;&lt;span&gt;(),&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; new&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Dog&lt;&#x2F;span&gt;&lt;span&gt;());&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;ImmutableList&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;Dog&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; fourDogs&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; dogs.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;concat&lt;&#x2F;span&gt;&lt;span&gt;(moreDogs);&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6A737D;&quot;&gt; &#x2F;&#x2F; Won&amp;#39;t compile because concat returns ImmutableCollection&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The point here is that &lt;em&gt;the returned object is an ImmutableList&lt;&#x2F;em&gt;, but at compile time we cannot abstract the method in ImmutableCollection AND preserve the return type. We can of course cast the return value but we&#x27;ll violate goal 3.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;attempt-4&quot;&gt;Attempt 4&lt;&#x2F;h2&gt;
&lt;p&gt;We need a way to describe the implementation type in the interface:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #24292E; background-color: #FFFFFF;&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6A737D;&quot;&gt;&#x2F;&#x2F; ImmutableCollection.java&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span&gt;THAT extends ImmutableCollection&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span&gt;A&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;&amp;gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; THAT&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; concat&lt;&#x2F;span&gt;&lt;span&gt;(ImmutableCollection&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span&gt;A&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; other);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6A737D;&quot;&gt;&#x2F;&#x2F; ImmutableList.java&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;public &amp;lt;&lt;&#x2F;span&gt;&lt;span&gt;THAT extends ImmutableCollection&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span&gt;A&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;&amp;gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; THAT&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; concat&lt;&#x2F;span&gt;&lt;span&gt;(ImmutableCollection&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span&gt;A&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; other) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6A737D;&quot;&gt;  &#x2F;&#x2F; ...&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;  return new&lt;&#x2F;span&gt;&lt;span&gt; ImmutableList&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;A&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;(newInner);&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6A737D;&quot;&gt; &#x2F;&#x2F; Won&amp;#39;t compile!!&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Now the interface compiles and the dog example works, but the implementation of concat will not compile anymore. The problem is that the implementation of concat must support all ImmutableCollections while the implementation is providing only a subtype (= ImmutableList).&lt;&#x2F;p&gt;
&lt;h2 id=&quot;attempt-5&quot;&gt;Attempt 5&lt;&#x2F;h2&gt;
&lt;p&gt;We must somehow abstract away the construction of the new collection:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #24292E; background-color: #FFFFFF;&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6A737D;&quot;&gt;&#x2F;&#x2F; ImmutableBuilder.java&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;public interface&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; ImmutableBuilder&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;THAT&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  THAT&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; build&lt;&#x2F;span&gt;&lt;span&gt;(Collection&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt; elements&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;I&#x27;ve violated goal 2 and dropped generics from elements in advance because I know they won&#x27;t work. An ImmutableBuilder is just a factory that knows how to create objects of type THAT from a collection of elements. Now we&#x27;ll change the signatures of both the interface and the implementation:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #24292E; background-color: #FFFFFF;&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6A737D;&quot;&gt;&#x2F;&#x2F; ImmutableCollection.java&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span&gt;THAT&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; THAT&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; concat&lt;&#x2F;span&gt;&lt;span&gt;(ImmutableCollection&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span&gt;A&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; other, ImmutableBuilder&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span&gt;THAT&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; builder);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6A737D;&quot;&gt;&#x2F;&#x2F; ImmutableList.java&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;public &amp;lt;&lt;&#x2F;span&gt;&lt;span&gt;THAT&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; THAT&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; concat&lt;&#x2F;span&gt;&lt;span&gt;(ImmutableCollection&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span&gt;A&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; other, ImmutableBuilder&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span&gt;THAT&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; builder) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  List&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;A&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; inner&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6A737D;&quot;&gt; &#x2F;&#x2F; ...&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;  return&lt;&#x2F;span&gt;&lt;span&gt; builder.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;build&lt;&#x2F;span&gt;&lt;span&gt;(inner);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Everything compiles now, so now we only need an implementation of a builder:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #24292E; background-color: #FFFFFF;&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6A737D;&quot;&gt;&#x2F;&#x2F; ImmutableList.java&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;public static &amp;lt;&lt;&#x2F;span&gt;&lt;span&gt;T&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; ImmutableBuilder&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span&gt;ImmutableList&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span&gt;T&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;&amp;gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; builder&lt;&#x2F;span&gt;&lt;span&gt;() {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;  return new&lt;&#x2F;span&gt;&lt;span&gt; ImmutableBuilder&amp;lt;ImmutableList&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;T&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&amp;gt;() {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;    public&lt;&#x2F;span&gt;&lt;span&gt; ImmutableList&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;T&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; build&lt;&#x2F;span&gt;&lt;span&gt;(Collection&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt; elements&lt;&#x2F;span&gt;&lt;span&gt;) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;      return new&lt;&#x2F;span&gt;&lt;span&gt; ImmutableList&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;T&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;new&lt;&#x2F;span&gt;&lt;span&gt; ArrayList&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;T&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;(elements));&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  };&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;overview-of-the-final-java-version&quot;&gt;Overview of the final Java version&lt;&#x2F;h2&gt;
&lt;p&gt;We now have everything in place for our immutable collection API. On our journey we have violated goals 2 and 3 (due to language limitations) and added complexity to our implementation. However, the complexity cannot be avoided without violating the design goals. Our API is also pretty clunky to use:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #24292E; background-color: #FFFFFF;&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;ImmutableBuilder&amp;lt;ImmutableList&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;Dog&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&amp;gt; listBuilder&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; ImmutableList.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;builder&lt;&#x2F;span&gt;&lt;span&gt;();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;ImmutableList&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;Dog&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; dogs&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; ImmutableList.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;of&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;new&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Dog&lt;&#x2F;span&gt;&lt;span&gt;(),&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; new&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Dog&lt;&#x2F;span&gt;&lt;span&gt;());&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;ImmutableList&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;Dog&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; moreDogs&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; ImmutableList.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;of&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;new&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Dog&lt;&#x2F;span&gt;&lt;span&gt;(),&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; new&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Dog&lt;&#x2F;span&gt;&lt;span&gt;());&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;ImmutableList&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;Dog&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; fourDogs&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; dogs.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;concat&lt;&#x2F;span&gt;&lt;span&gt;(moreDogs, listBuilder);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We don&#x27;t support variances and we have to pass around a builder for most of the operations. Due to goal 1, most interesting operations on the collections will return new ones, and thus will need a builder instance!&lt;&#x2F;p&gt;
&lt;p&gt;Stephen Colebourne wrote about ++ in his blog post:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;&quot;In fact this is the equivalent to Java&#x27;s addAll() on a list&quot;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;Reading this made me completely lose my respect to the guy. &lt;strong&gt;This is absolutely wrong and misses completely the crucial difference&lt;&#x2F;strong&gt;: immutability (= goal 1). Java&#x27;s addAll() doesn&#x27;t return a new collection, so it does not need ImmutableBuilder and variances cause less problems because there is no return type. However, Java collections are generally not immutable and thus violate goal 1. &lt;strong&gt;It is a completely different thing if you want mutable collections, but then you would have completely different requirements and you are not talking about Scala&#x27;s ++ operator anymore.&lt;&#x2F;strong&gt; If you want OOP-compatible, immutable, type-safe collections, you will end up with something that Scala has. That is why I consider complexity arising from goal 1 to be &lt;em&gt;necessary&lt;&#x2F;em&gt;. It&#x27;s also worth nothing that you don&#x27;t always have to understand the exact details of a method signature, and in the collections API the CanBuildFrom stuff is pretty much same everywhere.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;comparison-with-the-scala-version&quot;&gt;Comparison with the Scala version&lt;&#x2F;h2&gt;
&lt;p&gt;Java:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #24292E; background-color: #FFFFFF;&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span&gt;THAT&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; THAT&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; concat&lt;&#x2F;span&gt;&lt;span&gt;(ImmutableCollection&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span&gt;A&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; other, ImmutableBuilder&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span&gt;THAT&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; builder);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Scala:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #24292E; background-color: #FFFFFF;&quot;&gt;&lt;code data-lang=&quot;scala&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;def&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; ++&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;B&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; &amp;gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; A&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;That&lt;&#x2F;span&gt;&lt;span&gt;] (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt;that&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; TraversableOnce&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;B&lt;&#x2F;span&gt;&lt;span&gt;])(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;implicit&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt; bf&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; CanBuildFrom&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;List&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;A&lt;&#x2F;span&gt;&lt;span&gt;], &lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;B&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;That&lt;&#x2F;span&gt;&lt;span&gt;])&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; :&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; That&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;First thing you should note is that they are not actually equivalent. The Scala version does not violate any goal, but the Java version violates goals 2 and 3. Let&#x27;s look at all the type parameters we have here:&lt;&#x2F;p&gt;
&lt;dl&gt;
&lt;dt&gt;A&lt;&#x2F;dt&gt;
&lt;dd&gt;Element type of the first collection&lt;&#x2F;dd&gt;
&lt;dt&gt;That&#x2F;THAT&lt;&#x2F;dt&gt;
&lt;dd&gt;The type that we expect to get out of the operation&lt;&#x2F;dd&gt;
&lt;dt&gt;B&lt;&#x2F;dt&gt;
&lt;dd&gt;Element type of the second collection. The definition essentially says that type B can be a supertype of A.&lt;&#x2F;dd&gt;
&lt;&#x2F;dl&gt;
&lt;p&gt;The next thing you should note is CanBuildFrom in the Scala version. CanBuildFrom[List[A], B, That] is a factory object that can create objects with type That, element type B from Lists of element type A. Sounds complex, but it&#x27;s not that difficult to understand. Our Java version is simpler (no A&#x2F;B type parameters), but it violates our design goals. The presence of parameters B and That in the Scala version makes my previous dog&#x2F;cat example possible and if you run that with Scala you will get a list of animals.&lt;&#x2F;p&gt;
&lt;p&gt;The CanBuildFrom parameter in the Scala version is implicit, meaning that it will automatically be added by the compiler to invocations based on the import scoping if possible. So 99% of the time you will not need to actually handle the parameter yourself. In the Java version you have to include the builder parameter all the time. I really have trouble understanding the fear of implicits. Many things that would be implicits in good Scala code are typically pushed to static variables or ThreadLocals in Java (this is of course not the case with the collections API).&lt;&#x2F;p&gt;
&lt;h2 id=&quot;about-the-syntax&quot;&gt;About the syntax&lt;&#x2F;h2&gt;
&lt;p&gt;Finally I must also mention that many people complain the use of operators instead of named methods. Personally I have no problem with this as long at it is not overused. The ++ operator is probably based on Haskell where list concat is done with that operator.&lt;&#x2F;p&gt;
&lt;p&gt;I&#x27;d also like to ask why don&#x27;t the complainers complain about other operators? The trivial answer is of course that most operators like +, - are based on mathematics and as such are &quot;common knowledge&quot;. But what about operators like modulo (% in some languages, mod in others)? What about the power operator (^, ^^ or **)? I don&#x27;t see many Python programmers crying about ** even though the syntax is not based on mathematics directly.&lt;&#x2F;p&gt;
&lt;p&gt;On the other hand, good syntax is always a matter of taste. I like the fact that for example scalaz has both named and operator versions of most important methods.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Spring vs Guice: The one critical difference that matters</title>
        <published>2011-11-29T08:42:50+01:00</published>
        <updated>2011-11-29T08:42:50+01:00</updated>
        
        <author>
          <name>
            
              Joonas Javanainen
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://gekkio.fi/blog/2011/spring-vs-guice-the-one-critical-difference-that-matters/"/>
        <id>https://gekkio.fi/blog/2011/spring-vs-guice-the-one-critical-difference-that-matters/</id>
        
        <content type="html" xml:base="https://gekkio.fi/blog/2011/spring-vs-guice-the-one-critical-difference-that-matters/">&lt;h2 id=&quot;spring-objects-are-recognized-based-on-their-names&quot;&gt;Spring objects are recognized based on their names&lt;&#x2F;h2&gt;
&lt;p&gt;It doesn&#x27;t matter whether you use XML or Java config, a Spring scope is roughly like a Map&amp;lt;String, Object&amp;gt; structure. This means that &lt;strong&gt;you cannot have two objects with the same name&lt;&#x2F;strong&gt;. Why is this a bad thing? If you have a large application with lots of @Configuration classes or XML files, it&#x27;s very easy to accidentally use the same name twice.&lt;&#x2F;p&gt;
&lt;p&gt;The worst part of this is that using the same with several objects, they silently override each other until only one actually remains in the ApplicationContext. These objects can also be of different types and the declaration order is what really determines which object wins. The problem here is that if you want to make reusable modules based on Spring, you will basically be forced to use a prefix in the name or something else to ensure you won&#x27;t have a name clash.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;guice-objects-are-recognized-based-on-their-classes&quot;&gt;Guice objects are recognized based on their classes&lt;&#x2F;h2&gt;
&lt;p&gt;A Guice scope is basically like a Map&amp;lt;Class&amp;lt;?, &amp;gt;, Object&amp;gt; structure. This means that &lt;strong&gt;you cannot have two objects of the same type&lt;&#x2F;strong&gt; without using extra metadata (e.g. qualifiers). This design choice has different pros and cons, but overall I think it&#x27;s the saner one. If you create reusable modules, you mostly have to make sure that you don&#x27;t export any objects of common types (e.g. String). With type-based scopes you can always create a wrapped class for common types, while with name-based scopes you would always have to use unique names based on lucky guesses. Guice also has PrivateModules so you can use Guice for all injection, but only export some of the objects in the scope.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;example-code&quot;&gt;Example code&lt;&#x2F;h2&gt;
&lt;p&gt;Here&#x27;s a naive example of a Spring application that breaks runtime because of silent bean overriding.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;main-java&quot;&gt;Main.java&lt;&#x2F;h3&gt;
&lt;p&gt;This class instantiates the application context, registers the configuration classes and tries to get a MyBean from the context.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #24292E; background-color: #FFFFFF;&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;package&lt;&#x2F;span&gt;&lt;span&gt; springbreak;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;import&lt;&#x2F;span&gt;&lt;span&gt; org.springframework.context.annotation.AnnotationConfigApplicationContext;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;public class&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Main&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;  public static void&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; main&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;String&lt;&#x2F;span&gt;&lt;span&gt;[]&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt; args&lt;&#x2F;span&gt;&lt;span&gt;) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    AnnotationConfigApplicationContext ctx&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; = new&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; AnnotationConfigApplicationContext&lt;&#x2F;span&gt;&lt;span&gt;();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    ctx.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;register&lt;&#x2F;span&gt;&lt;span&gt;(GoodConfig.class);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    ctx.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;register&lt;&#x2F;span&gt;&lt;span&gt;(EvilConfig.class);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    ctx.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;refresh&lt;&#x2F;span&gt;&lt;span&gt;();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    ctx.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;start&lt;&#x2F;span&gt;&lt;span&gt;();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    System.out.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;println&lt;&#x2F;span&gt;&lt;span&gt;(ctx.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;getBean&lt;&#x2F;span&gt;&lt;span&gt;(MyBean.class).&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;getValue&lt;&#x2F;span&gt;&lt;span&gt;());&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    ctx.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;stop&lt;&#x2F;span&gt;&lt;span&gt;();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;mybean-java&quot;&gt;MyBean.java&lt;&#x2F;h3&gt;
&lt;p&gt;This is just an example type of bean that we expect to get from the application context.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #24292E; background-color: #FFFFFF;&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;package&lt;&#x2F;span&gt;&lt;span&gt; springbreak;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;public interface&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; MyBean&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  String&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; getValue&lt;&#x2F;span&gt;&lt;span&gt;();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;goodconfig-java&quot;&gt;GoodConfig.java&lt;&#x2F;h3&gt;
&lt;p&gt;This is a configuration class that exports a MyBean&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #24292E; background-color: #FFFFFF;&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;package&lt;&#x2F;span&gt;&lt;span&gt; springbreak;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;import&lt;&#x2F;span&gt;&lt;span&gt; org.springframework.context.annotation.Bean;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;import&lt;&#x2F;span&gt;&lt;span&gt; org.springframework.context.annotation.Configuration;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;@&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;Configuration&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;public class&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; GoodConfig&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;  private static class&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; MyBeanImpl&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; implements&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; MyBean&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;    public&lt;&#x2F;span&gt;&lt;span&gt; String&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; getValue&lt;&#x2F;span&gt;&lt;span&gt;() {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;      return&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt; &amp;quot;I&amp;#39;m a bean&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  @&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;Bean&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;  public&lt;&#x2F;span&gt;&lt;span&gt; MyBean&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; myBean&lt;&#x2F;span&gt;&lt;span&gt;() {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;    return new&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; MyBeanImpl&lt;&#x2F;span&gt;&lt;span&gt;();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;evilconfig-java&quot;&gt;EvilConfig.java&lt;&#x2F;h3&gt;
&lt;p&gt;This configuration class exports a String with the name myBean. It&#x27;s not a very realistic example but shows the basic idea.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #24292E; background-color: #FFFFFF;&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;package&lt;&#x2F;span&gt;&lt;span&gt; springbreak;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;import&lt;&#x2F;span&gt;&lt;span&gt; org.springframework.context.annotation.Bean;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;import&lt;&#x2F;span&gt;&lt;span&gt; org.springframework.context.annotation.Configuration;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;@&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;Configuration&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;public class&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; EvilConfig&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  @&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;Bean&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;  public&lt;&#x2F;span&gt;&lt;span&gt; String&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; myBean&lt;&#x2F;span&gt;&lt;span&gt;() {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;    return&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt; &amp;quot;I&amp;#39;m a string!&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;analyzing-the-example&quot;&gt;Analyzing the example&lt;&#x2F;h2&gt;
&lt;p&gt;Can you guess what happens when you run the example? Here&#x27;s the basic idea:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;GoodConfig exports a MyBeanImpl with the name &quot;myBean&quot;&lt;&#x2F;li&gt;
&lt;li&gt;EvilConfig exports a String with the name &quot;myBean&quot; replacing the one from GoodConfig &lt;strong&gt;even though the types won&#x27;t match&lt;&#x2F;strong&gt;&lt;&#x2F;li&gt;
&lt;li&gt;Main gets a NoSuchBeanDefinitionException &quot;No unique bean of type [springbreak.MyBean] is defined&quot;&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;So, basically a MyBeanImpl is replaced by a String and there won&#x27;t be a bean that implements MyBean. The worst part is that &lt;em&gt;if you reverse the @Configuration class registration order, the code will work&lt;&#x2F;em&gt; because then a String will be replaced by a MyBeanImpl. Now, imagine you have 20 nicely encapsulated modules with potentially conflicting names...I&#x27;ve banged my head against the wall several times trying to debug problems in a situation like that.&lt;&#x2F;p&gt;
&lt;p&gt;Spring (as of version 3.0.6) offers no possibility to alter the naming of @Configuration class exported beans. If you want to create safely reusable modules, you will have to use some kind of fully qualified names in the methods that export beans (e.g goodConfigMyBean, evilConfigMyBean).&lt;&#x2F;p&gt;
&lt;p&gt;I like Spring (especially non-DI-container parts), but in new projects I will refuse to use a library that is so fundamentally broken. And yes, using the same name twice is a developer error, but any library that is prone to such errors can be considered worse than an alternative that attempts to minimize them.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>sbt-jrebel-plugin 0.9.0 released</title>
        <published>2011-10-01T09:09:02+02:00</published>
        <updated>2011-10-01T09:09:02+02:00</updated>
        
        <author>
          <name>
            
              Joonas Javanainen
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://gekkio.fi/blog/2011/sbt-jrebel-plugin-0-9-0-released/"/>
        <id>https://gekkio.fi/blog/2011/sbt-jrebel-plugin-0-9-0-released/</id>
        
        <content type="html" xml:base="https://gekkio.fi/blog/2011/sbt-jrebel-plugin-0-9-0-released/">&lt;p&gt;I&#x27;ve finally managed to convert &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;Gekkio&#x2F;sbt-jrebel-plugin&quot;&gt;sbt-jrebel-plugin&lt;&#x2F;a&gt; to SBT 0.9+. Check out the &lt;a rel=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;implicit.ly&#x2F;sbt-jrebel-plugin-090&quot;&gt;short release notes at implicit.ly&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;I guess it&#x27;s time to start converting SBT 0.7 projects to 0.11...&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Thoughts about the ZK Web Framework: Technical stuff</title>
        <published>2011-09-27T09:12:19+02:00</published>
        <updated>2011-09-27T09:12:19+02:00</updated>
        
        <author>
          <name>
            
              Joonas Javanainen
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://gekkio.fi/blog/2011/thoughts-about-the-zk-web-framework-technical-stuff/"/>
        <id>https://gekkio.fi/blog/2011/thoughts-about-the-zk-web-framework-technical-stuff/</id>
        
        <content type="html" xml:base="https://gekkio.fi/blog/2011/thoughts-about-the-zk-web-framework-technical-stuff/">&lt;p&gt;As I mentioned in my previous post, ZK has a tendency to &quot;just work&quot;. The overall technical quality is impressive and on par with most Java web frameworks, but I believe there are some parts of ZK that are less impressive.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;stuck-on-java-1-4&quot;&gt;Stuck on Java 1.4&lt;&#x2F;h2&gt;
&lt;p&gt;ZK is built with Java 1.4, which greatly limits the flexibility of their API and internal code quality&lt;&#x2F;p&gt;
&lt;h3 id=&quot;negative-effects-on-zk-internal-code&quot;&gt;Negative effects on ZK internal code&lt;&#x2F;h3&gt;
&lt;ul&gt;
&lt;li&gt;ThreadLocals not removed with remove() &lt;em&gt;(calling set(null) does prevent leaking the contained object but does not properly remove a ThreadLocal)!&lt;&#x2F;em&gt;&lt;&#x2F;li&gt;
&lt;li&gt;Lots of custom synchronization code where simple java.util.concurrent data structures or objects would work (ConcurrentHashMap, Semaphore, Atomic*, etc)&lt;&#x2F;li&gt;
&lt;li&gt;StringBuffer is used where StringBuilder would be appropriate&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3 id=&quot;no-annotations&quot;&gt;No annotations&lt;&#x2F;h3&gt;
&lt;p&gt;Personally I&#x27;m not a fan of annotation-heavy frameworks because annotations are an extralinquistic feature and usually you end up annotations with string-based values that have no type safety. However, I know that some people would be overjoyed to have an API based on them.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;no-enums&quot;&gt;No enums&lt;&#x2F;h3&gt;
&lt;p&gt;There are many places in the ZK API where proper enums would be much better than the hacks that are used at the moment. The worst offender is Messagebox. Just look at this signature:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #24292E; background-color: #FFFFFF;&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;public static int&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; show&lt;&#x2F;span&gt;&lt;span&gt;(String message,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                       String title,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;                       int&lt;&#x2F;span&gt;&lt;span&gt; buttons,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                       java.lang.String icon,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;                       int&lt;&#x2F;span&gt;&lt;span&gt; focus)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Ugh..the magic integers remind me of SWT (which is a great library with an awful API). Let&#x27;s imagine an alternative version with enums and generics:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #24292E; background-color: #FFFFFF;&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;public static&lt;&#x2F;span&gt;&lt;span&gt; Messagebox.Button&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; show&lt;&#x2F;span&gt;&lt;span&gt;(String message,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                       String title,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                       Set&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span&gt;Messagebox.Button&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; buttons,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                       Messagebox.Icon icon,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                       Messagebox.Button focus)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Much, much better and more typesafe. No more bitwise OR magic. I could code this in 10 minutes into ZK if it would use Java 1.5.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;no-generics&quot;&gt;No generics&lt;&#x2F;h3&gt;
&lt;p&gt;This is the worst part of being stuck on Java 1.4.&lt;&#x2F;p&gt;
&lt;p&gt;I&#x27;ll just list some of the places where I&#x27;d like to see generics:&lt;&#x2F;p&gt;
&lt;h4 id=&quot;collection-values-in-api-signatures&quot;&gt;Collection values in API signatures&lt;&#x2F;h4&gt;
&lt;p&gt;Example in org.zkoss.zk.ui.util.Initiator:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #24292E; background-color: #FFFFFF;&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;void&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; doInit&lt;&#x2F;span&gt;&lt;span&gt;(Page page, Map args);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;vs&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #24292E; background-color: #FFFFFF;&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;void&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; doInit&lt;&#x2F;span&gt;&lt;span&gt;(Page page, Map&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span&gt;String, Object&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; args);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Example in org.zkoss.zk.ui.Component:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #24292E; background-color: #FFFFFF;&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;List&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; getChildren&lt;&#x2F;span&gt;&lt;span&gt;();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;vs&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #24292E; background-color: #FFFFFF;&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;List&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span&gt;Component&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; getChildren&lt;&#x2F;span&gt;&lt;span&gt;();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h4 id=&quot;collection-like-classes&quot;&gt;Collection-like classes&lt;&#x2F;h4&gt;
&lt;p&gt;Example in ListModel:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #24292E; background-color: #FFFFFF;&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;public interface&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; ListModel&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  ...&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  Object&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; getElementAt&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;int&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt; index&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  ...&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;vs&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #24292E; background-color: #FFFFFF;&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;public interface&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; ListModel&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;T&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  ...&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  T&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; getElementAt&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;int&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt; index&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  ...&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;All ListModel* classes should also be generic (most extend java.util.Collection).&lt;&#x2F;p&gt;
&lt;h4 id=&quot;org-zkoss-zk-ui-event-eventlistener&quot;&gt;org.zkoss.zk.ui.event.EventListener&lt;&#x2F;h4&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #24292E; background-color: #FFFFFF;&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;public interface&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; EventListener&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;  public void&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; onEvent&lt;&#x2F;span&gt;&lt;span&gt;(Event&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt; event&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;vs&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #24292E; background-color: #FFFFFF;&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;public interface&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; EventListener&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;T extends Event&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;  public void&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; onEvent&lt;&#x2F;span&gt;&lt;span&gt;(T&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt; event&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h4 id=&quot;org-zkoss-zk-ui-util-genericautowirecomposer&quot;&gt;org.zkoss.zk.ui.util.GenericAutowireComposer&lt;&#x2F;h4&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #24292E; background-color: #FFFFFF;&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;public class&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; GenericAutowireComposer&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;  protected&lt;&#x2F;span&gt;&lt;span&gt; Component self;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  ...&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;vs&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #24292E; background-color: #FFFFFF;&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;public class&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; GenericAutowireComposer&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;T extends Component&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;  protected&lt;&#x2F;span&gt;&lt;span&gt; T self;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  ...&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h4 id=&quot;all-renderer-classes&quot;&gt;All *Renderer classes&lt;&#x2F;h4&gt;
&lt;p&gt;Example in org.zkoss.zul.RowRenderer:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #24292E; background-color: #FFFFFF;&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;public interface&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; RowRenderer&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;  void&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; render&lt;&#x2F;span&gt;&lt;span&gt;(Row&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt; row&lt;&#x2F;span&gt;&lt;span&gt;, Object&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt; data&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;vs&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #24292E; background-color: #FFFFFF;&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;public interface&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; RowRenderer&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;T&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;  void&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; render&lt;&#x2F;span&gt;&lt;span&gt;(Row&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt; row&lt;&#x2F;span&gt;&lt;span&gt;, T&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt; data&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;unimpressive-server-push-implementations&quot;&gt;Unimpressive server push implementations&lt;&#x2F;h2&gt;
&lt;p&gt;The default PollingServerPush has latency and will absolutely kill your application server if there are many active users. CometServerPush is better, but it does not use non-blocking IO and will block servlet threads in your servlet container. Let&#x27;s put this into perspective:&lt;&#x2F;p&gt;
&lt;p&gt;Tomcat 7.0 default configuration sets connector max threads to 200. This means that if you have 200 comet-enabled desktops, Tomcat will stop responding to other requests because all the threads are in use by comet. If the implementation used Servlet 3.0 or container-specific async APIs instead, you could run Tomcat even with one thread. It would of course be slow but it would not stop working!&lt;&#x2F;p&gt;
&lt;p&gt;Also, CometServerPush requires ZK EE so regular users are stuck with PollingServerPush. I&#x27;d say that&#x27;s a pretty big limitation considering how server push is marketed. However, it&#x27;s not surprising: proper non-blocking comet is hard to implement and requires non-blocking components in all parts of the pathway from the browser to the servlet code.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;zscript&quot;&gt;Zscript&lt;&#x2F;h2&gt;
&lt;p&gt;I don&#x27;t like zscript. It might have been a good feature many years ago, but I believe that today it should not be used at all. Why, oh why would someone want to replace typesafe compiled Java code with non-typechecked zscript mixed with ZUL templates?&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&quot;I can use Python&#x2F;Ruby&#x2F;...&quot;. This might be a valid point for some people but you&#x27;ll end up with unmaintainable code mangled inside ZUL templates&lt;&#x2F;li&gt;
&lt;li&gt;&quot;Changes are visible when you save the file&quot;. True, but I would never sacrifice so much just for this feature. And besides, you can get a similar effect with &lt;a rel=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;www.zeroturnaround.com&#x2F;jrebel&quot;&gt;JRebel&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;So, if you put &quot;Java code&quot; (=BeanShell code) in zscript, you might want to rethink that.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;reliance-on-reflection&quot;&gt;Reliance on reflection&lt;&#x2F;h2&gt;
&lt;p&gt;Many useful features rely on reflection, which limits what things the compiler can check for you. This is very typical thing in many Java libraries&#x2F;frameworks, so it&#x27;s not really a ZK-specific thing. As a Scala user I can see how the limitations of Java have guided most frameworks to the path of reflection&#x2F;annotations. Reflection cannot always be avoided but I think it&#x27;s a bad sign if most of the useful features rely on reflection. Here are some features in ZK that use reflection:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Any kind of event listening that does not use component.addEventListener. This includes any classes that extend GenericEventListener (such as all ZK-provided Composer classes except MultiComposer)&lt;&#x2F;li&gt;
&lt;li&gt;Data binding&lt;&#x2F;li&gt;
&lt;li&gt;EL expressions in ZUL templates&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Thoughts about the ZK Web Framework: Overall experience</title>
        <published>2011-09-08T20:25:29+02:00</published>
        <updated>2011-09-08T20:25:29+02:00</updated>
        
        <author>
          <name>
            
              Joonas Javanainen
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://gekkio.fi/blog/2011/thoughts-about-the-zk-web-framework-overall-experience/"/>
        <id>https://gekkio.fi/blog/2011/thoughts-about-the-zk-web-framework-overall-experience/</id>
        
        <content type="html" xml:base="https://gekkio.fi/blog/2011/thoughts-about-the-zk-web-framework-overall-experience/">&lt;p&gt;I&#x27;ve been asked several times to present some of my opinions about &lt;a rel=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;www.zkoss.org&#x2F;&quot;&gt;ZK&lt;&#x2F;a&gt;. So, based of my experience of 4 years as a ZK user, here&#x27;s some thoughts:&lt;&#x2F;p&gt;
&lt;h2 id=&quot;overall-developer-experience-the-community-and-documentation&quot;&gt;Overall developer experience, the community and documentation&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;it-just-works&quot;&gt;&quot;It just works&quot;&lt;&#x2F;h3&gt;
&lt;p&gt;Most of the stuff that ZK offers works very well, and the functionality is usually very intuitive to use if you have developed any desktop Java applications before. In 2007 I did a comparison of RIA technologies that included Echo2, ZK, GWT, OpenLaszlo and Flex. Echo2 and OpenLaszlo felt incomplete and buggy and didn&#x27;t seem to have proper Maven artifacts anywhere. GWT seemed more of a technical experiment than a good platform to build on. Flex was dropped because some important Maven artifacts were missing and Flash was an unrealistic requirement for the application. On the other hand, ZK felt the most &quot;natural&quot; and I was able to quickly get productive with it. During my 4 year long journey with ZK, I&#x27;ve gotten plenty of those &quot;wow&quot; moments when I&#x27;ve learned more and more of ZK and improved my architectural understanding of the framework.&lt;&#x2F;p&gt;
&lt;p&gt;Nowadays I&#x27;ve got a pretty good understanding of what in ZK works, what doesn&#x27;t, and what has problems and what doesn&#x27;t. But still, after gaining all this good and bad insight, I consider ZK to be a very impressive product out of the box. The downside of this is of course the fact that the framework hides a lot of things from newcomers in order to be easy to use, and &lt;em&gt;some of these things will bite you later on,&lt;&#x2F;em&gt; especially if your application has lots of users.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;it-s-very-very-very-flexible&quot;&gt;It&#x27;s very, very, very flexible&lt;&#x2F;h3&gt;
&lt;p&gt;ZK is very flexible and has plenty of integrations. Do you want use declarative markup to build component trees? Use ZUL files. Do you want to stick to plain Java? Use richlets. You can also integrate JSP, JSF, Spring, and use plenty of languages in zscript. The core framework is also pretty flexible and you can override a lot of stuff if you run into problems.&lt;&#x2F;p&gt;
&lt;p&gt;The downside is that there are very many ways of doing things correctly, and even more ways of screwing up. Flexibility itself is not a negative point, but I think that the ZK documentation doesn&#x27;t guide users enough towards the best practices of ZK. What are the best practices anyway? Many tutorials use zscript, but the docs also recommend to avoid it due to performance reasons.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;the-forum-is-quite-active&quot;&gt;The forum is quite active&lt;&#x2F;h3&gt;
&lt;p&gt;I think that the ZK forum is one of the best places to learn about ZK. It&#x27;s pretty active and the threads vary from beginner level to deep technical stuff. I read the forums myself almost every day and sometimes help people with their problems. There&#x27;s one thing that troubles me a bit: the English language in the forums isn&#x27;t usually very good and people often ask too broad questions. I know, it&#x27;s not fair to criticize the writings of non-native English speakers, especially when I&#x27;m not a native speaker myself. Regardless, I think that such a barrier exists. For example, take 5 random threads from the ZK forum and Spring Web forum. The threads in the Spring forums are typically more detailed and focused instead of &lt;em&gt;&quot;I&#x27;m a newbie and I need to create application x with tons of features, please tell me how to do everything&quot;&lt;&#x2F;em&gt;-type threads you see in the ZK forums and people clearly spend some time formulating good and detailed questions. You&#x27;ll see that you have to spend a bit more time in the ZK forum in order to understand the threads. It&#x27;s not anybody&#x27;s fault or anything, nor a bad thing, this is just an observation. Unfortunately for me it means that some of my limited time I have for the ZK community is spent just trying to understand what people are saying. Usually I answer a thread only when I know the answer right away, or if the thread concerns some deep technical stuff.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;there-s-plenty-of-documentation&quot;&gt;There&#x27;s plenty of documentation&lt;&#x2F;h3&gt;
&lt;p&gt;In the past the ZK documentation was scattered, out of date and some of the more important stuff was completely missing. In the recent years the docs have improved a lot, and there&#x27;s now separate comprehensive references for &lt;a rel=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;books.zkoss.org&#x2F;wiki&#x2F;ZK_Configuration_Reference&quot;&gt;ZK configuration&lt;&#x2F;a&gt;, &lt;a rel=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;books.zkoss.org&#x2F;wiki&#x2F;ZK_Client-side_Reference&quot;&gt;client-side ZK&lt;&#x2F;a&gt;, and &lt;a rel=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;books.zkoss.org&#x2F;wiki&#x2F;ZK_Style_Guide&quot;&gt;styling&lt;&#x2F;a&gt;. I think the documentation is today very good, and most basic questions can be easily answered by reading the docs.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>SBTEI technical challenges: Project metadata</title>
        <published>2011-04-28T23:15:41+02:00</published>
        <updated>2011-04-28T23:15:41+02:00</updated>
        
        <author>
          <name>
            
              Joonas Javanainen
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://gekkio.fi/blog/2011/sbtei-technical-challenges-project-metadata/"/>
        <id>https://gekkio.fi/blog/2011/sbtei-technical-challenges-project-metadata/</id>
        
        <content type="html" xml:base="https://gekkio.fi/blog/2011/sbtei-technical-challenges-project-metadata/">&lt;h2 id=&quot;overview-of-the-challenge&quot;&gt;Overview of the challenge&lt;&#x2F;h2&gt;
&lt;p&gt;The biggest challenge in SBTEI is the most fundamental one: project metadata. SBT is very customizable, so many things that are needed for Eclipse integration are customizable:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Source folders (src&#x2F;main&#x2F;scala, src&#x2F;test&#x2F;scala)&lt;&#x2F;li&gt;
&lt;li&gt;Managed libraries (lib_managed&#x2F;&lt;em&gt;&#x2F;&lt;&#x2F;em&gt;.jar)&lt;&#x2F;li&gt;
&lt;li&gt;Unmanaged libraries (lib&#x2F;*.jar)&lt;&#x2F;li&gt;
&lt;li&gt;Project-to-project dependencies (multi-module projects)&lt;&#x2F;li&gt;
&lt;li&gt;Webapp files (src&#x2F;main&#x2F;webapp)&lt;&#x2F;li&gt;
&lt;li&gt;Webapp name&lt;&#x2F;li&gt;
&lt;li&gt;Extra plugins (e.g. sbt-jrebel-plugin)&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;All these things might vary on a per-project basis so trusting these defaults will not be sufficient.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;accessing-the-metadata&quot;&gt;Accessing the metadata&lt;&#x2F;h2&gt;
&lt;p&gt;There are generally two ways to gain access to the metadata:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Read the metadata with Eclipse from the project definition&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;This is what M2Eclipse does easily because Maven project definitions are XML files and thus parseable by other things than Maven. With SBT this is not an option because SBT project files are code that has to be run in order to calculate the needed metadata. This leaves us with option two:&lt;&#x2F;p&gt;
&lt;ol start=&quot;2&quot;&gt;
&lt;li&gt;Write the metadata with SBT in some parseable format&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;This is the approach what I&#x27;m currently using. I wrote a processor for SBT called &lt;a rel=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;github.com&#x2F;Gekkio&#x2F;sbt-metadata-exporter&quot;&gt;sbt-metadata-exporter&lt;&#x2F;a&gt; that exports some common project metadata into an XML file. While XML is maybe not the optimal format, I chose it because Scala has great support for it without the need of external libraries.&lt;&#x2F;p&gt;
&lt;p&gt;In SBTEI repository there is a branch called &lt;strong&gt;wip-metadata-export&lt;&#x2F;strong&gt;, where I&#x27;m developing a version of SBTEI that uses project metadata exported by &lt;em&gt;sbt-metadata-exporter&lt;&#x2F;em&gt;. The downside of this version is that the SBT support absolutely requires metadata exporting and vanilla SBT projects are no longer supported!&lt;&#x2F;p&gt;
&lt;p&gt;At the moment I don&#x27;t intend to continue my work on the master branch, because think metadata access is crucial and there is no point to go on without it. If the metadata approach is considered a necessary evil and the correct way to move forward, the wip-metadata-export branch can then be merged to master.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>SBTEI technical challenges: Scala versions</title>
        <published>2011-04-24T15:37:17+02:00</published>
        <updated>2011-04-24T15:37:17+02:00</updated>
        
        <author>
          <name>
            
              Joonas Javanainen
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://gekkio.fi/blog/2011/sbtei-technical-challenges-scala-versions/"/>
        <id>https://gekkio.fi/blog/2011/sbtei-technical-challenges-scala-versions/</id>
        
        <content type="html" xml:base="https://gekkio.fi/blog/2011/sbtei-technical-challenges-scala-versions/">&lt;p&gt;Scala is generally not backwards compatible, so matching Scala versions pose a challenge. SBTEI depends on Scala IDE, which in turn depends on a specific version of Scala that is bundled with the plugin. On the other hand, SBT projects themselves define their own Scala version(s). Having matching Scala versions is very important in order to prevent potential compilation&#x2F;runtime problems. Java users probably frown on this because binary compatibility in Java libraries is typically decent. However, even Java is not safe from binary incompatibilities unless library updates are handled with extra care.&lt;&#x2F;p&gt;
&lt;p&gt;At the moment it seems that Scala versions x.y.z are binary compatible between different z versions, but not compatible between different x or y versions. In SBTEI, a Scala version check is done in order to prevent errors. If the versions defined by SBT and Scala IDE don&#x27;t match, an error marker is added to the project. This approach is good for end users, but some questions remain: is this version check sufficient and does it work well enough with snapshot builds of Scala IDE? That will remain to be seen.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>SBTEI vs SbtEclipsify</title>
        <published>2011-04-17T15:27:28+02:00</published>
        <updated>2011-04-17T15:27:28+02:00</updated>
        
        <author>
          <name>
            
              Joonas Javanainen
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://gekkio.fi/blog/2011/sbtei-vs-sbteclipsify/"/>
        <id>https://gekkio.fi/blog/2011/sbtei-vs-sbteclipsify/</id>
        
        <content type="html" xml:base="https://gekkio.fi/blog/2011/sbtei-vs-sbteclipsify/">&lt;h2 id=&quot;comparing-sbtei-and-sbteclipsify&quot;&gt;Comparing SBTEI and SbtEclipsify&lt;&#x2F;h2&gt;
&lt;p&gt;In addition to SBT plugins for Eclipse, there&#x27;s also an &lt;em&gt;Eclipse plugin for SBT&lt;&#x2F;em&gt; called &lt;a rel=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;github.com&#x2F;musk&#x2F;SbtEclipsify&quot;&gt;SbtEclipsify&lt;&#x2F;a&gt;. It uses a completely different approach and generates Eclipse project files, so it&#x27;s similar to the &lt;em&gt;eclipse:eclipse&lt;&#x2F;em&gt; task in Maven.&lt;&#x2F;p&gt;
&lt;p&gt;When comparing SBTEI and SbtEclipsify, it&#x27;s useful to look at &lt;del&gt;some comparisons&lt;&#x2F;del&gt; (2023 edit: removed dead link) between M2Eclipse and eclipse:eclipse, which are the equivalents in the Maven ecosystem. As you can  see from the comparison, eclipse:eclipse provides adequate basic  support, but some advanced things (e.g. workspace dependency resolution)  require a plugin for Eclipse. This is especially useful when you have multi-module projects &lt;strong&gt;and separate library projects&lt;&#x2F;strong&gt; which you share between some of your projects. Let&#x27;s say you have a project called MyLibrary and MyProject like this:&lt;&#x2F;p&gt;
&lt;p&gt;MyLibrary:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;mylibrary-commons&lt;&#x2F;strong&gt;: contains some useful code you intend to share between your projects&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;MyProject:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;myproject-api&lt;&#x2F;strong&gt;: External API for your project&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;myproject-webapp&lt;&#x2F;strong&gt;: Webapp for your project&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;myproject-client&lt;&#x2F;strong&gt;: A command line client for your project&#x27;s REST API&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;If I want to develop these four projects at the same time, SbtEclipsify will not work! Even if it would support multi-module projects, you would still be unable to develop mylibrary-commons because there would be no project-to-project dependencies. You could of course add these dependencies manually but that defeats the point of integration.&lt;&#x2F;p&gt;
&lt;p&gt;On the SBTEI side I&#x27;m aiming for this hypothetical workflow:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Import all four projects in Eclipse&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;Enjoy workspace resolution and multi-module support&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;(If you use JRebel, also enjoy live class file change reloading &lt;strong&gt;across these four projects&lt;&#x2F;strong&gt;)&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;&lt;strong&gt;This almost works already in SBTEI. It still needs some work, but this is a goal that is possible to achieve!&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;recap&quot;&gt;Recap&lt;&#x2F;h2&gt;
&lt;p&gt;Personally I belive it&#x27;s ok to generate the initial Eclipse  project with a tool such as SbtEclipsify, but for keeping the Eclipse  project up to date (e.g. dependencies), a plugin in the Eclipse side is  much, much better. Pushing changes directly to Eclipse project files reminds me of old school database-based integration techniques that are typically very fragile. The SBT plugin simply cannot understand fully the Eclipse world, and also has no knowledge of the used Eclipse version or the plugins installed. Giving the possibility and responsibility of updating the files directly seems like a potentially fragile choice to me. This is why I&#x27;m investing some of my time in SBTEI.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>SBTEI development resumed</title>
        <published>2011-04-10T20:42:12+02:00</published>
        <updated>2011-04-10T20:42:12+02:00</updated>
        
        <author>
          <name>
            
              Joonas Javanainen
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://gekkio.fi/blog/2011/sbtei-development-resumed/"/>
        <id>https://gekkio.fi/blog/2011/sbtei-development-resumed/</id>
        
        <content type="html" xml:base="https://gekkio.fi/blog/2011/sbtei-development-resumed/">&lt;p&gt;As an Eclipse user I&#x27;ve always been trouble by the lackluster support of SBT in Eclipse. In order to combat this problem, I forked &lt;del&gt;sbt-eclipse-plugin&lt;&#x2F;del&gt; (2023 edit: removed dead link) and added more features and improved the code. That project later became stale and now I&#x27;m concentrating my effort on &lt;a rel=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;www.assembla.com&#x2F;spaces&#x2F;sbt-eclipse-integration&quot;&gt;SBT Eclipse Integration&lt;&#x2F;a&gt;; also known as SBTEI or SEI.&lt;&#x2F;p&gt;
&lt;p&gt;SBTEI has been stalled for a while as I&#x27;ve been busy with non-Scala projects. However, I&#x27;ll be resuming my work in the near future. I still dream of being able to do this:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Clone a project from source code repository&lt;&#x2F;li&gt;
&lt;li&gt;Import it to Eclipse&lt;&#x2F;li&gt;
&lt;li&gt;Start coding!&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;This incredibly easy and fast workflow works in Maven, so I&#x27;m wondering why Eclipse&#x2F;SBT&#x2F;Scala users aren&#x27;t really interested in the same thing. Or maybe all Eclipse users have already been lost to Intellij IDEA?&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Client-side ZK, Part 1: Integrating simple jQuery plugins</title>
        <published>2011-04-03T12:00:21+02:00</published>
        <updated>2011-04-03T12:00:21+02:00</updated>
        
        <author>
          <name>
            
              Joonas Javanainen
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://gekkio.fi/blog/2011/client-side-zk-part-1/"/>
        <id>https://gekkio.fi/blog/2011/client-side-zk-part-1/</id>
        
        <content type="html" xml:base="https://gekkio.fi/blog/2011/client-side-zk-part-1/">&lt;h2 id=&quot;jquery-zk-a-perfect-match&quot;&gt;jQuery + ZK = A perfect match?&lt;&#x2F;h2&gt;
&lt;p&gt;So, you&#x27;re a ZK 5.0 user and you&#x27;ve heard it uses &lt;a rel=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;www.jquery.com&#x2F;&quot;&gt;jQuery&lt;&#x2F;a&gt; instead of &lt;a rel=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;www.prototypejs.org&#x2F;&quot;&gt;Prototype&lt;&#x2F;a&gt; like ZK 3 did. You must be thinking: &quot;Yay! I can easily integrate all my favourite jQuery plugins easily&quot;. Well, sorry if I&#x27;m ruining all the fun but there are a few things you need to know first. ZK is a RIA framework, so pages created with it have a slightly different life cycle than simple HTML+Ajax pages.&lt;&#x2F;p&gt;
&lt;p&gt;Let&#x27;s try integrating a plugin then! We&#x27;ll start with a very simple plugin which doesn&#x27;t have to be integrated as a ZK component. I chose &lt;a rel=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;www.steamdev.com&#x2F;imgr&#x2F;&quot;&gt;jQuery Image Rounder&lt;&#x2F;a&gt; because it&#x27;s a very simple plugin and it was on the &quot;Most Popular Plugins&quot; list.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;preparations&quot;&gt;Preparations&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;strong&gt;I&#x27;m assuming you have a working ZK project in your favourite IDE using your favourite build tool. The very basics of doing that are out of the scope of this blog post.&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;First we&#x27;ll download the minified JS file from the plugin website, and put it to classpath so that ZK can find it. ZK supports loading resources from classpath, but you have to place your files to &lt;em&gt;web&lt;&#x2F;em&gt; directory in the classpath. I also recommend to add an application-specific subdirectory for the files. For example if you&#x27;re a Maven&#x2F;SBT user, the correct place for the minified JS would be &lt;em&gt;src&#x2F;main&#x2F;resources&#x2F;web&#x2F;myapp&#x2F;jquery.imgr.min.js&lt;&#x2F;em&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Because we&#x27;re integrating an image rounder plugin, we&#x27;ll of course need an image too! I used &lt;a rel=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;www.4freephotos.com&#x2F;Eye_of_a_tiger-limage-cf588d8583db5bc2f8e049d5abb8891b.html&quot;&gt;this cool CC-licensed photo of a tiger&#x27;s eye&lt;&#x2F;a&gt;. Put it in the same directory as the minified JS.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;zul-scala-code&quot;&gt;ZUL + Scala code&lt;&#x2F;h3&gt;
&lt;p&gt;Although ZK applications can be developed entirely in Java, I typically like to use ZUL pages for defining the &lt;em&gt;component structure&lt;&#x2F;em&gt; of applications. ZUL pages can be added directly to the webapp root directory (&lt;em&gt;src&#x2F;main&#x2F;webapp&lt;&#x2F;em&gt; in Maven&#x2F;SBT). Let&#x27;s add index.zul:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #24292E; background-color: #FFFFFF;&quot;&gt;&lt;code data-lang=&quot;xml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&amp;lt;?&lt;&#x2F;span&gt;&lt;span style=&quot;color: #22863A;&quot;&gt;xml&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; version&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;&amp;quot;1.0&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; encoding&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;&amp;quot;UTF-8&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;?&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #22863A;&quot;&gt;window&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; title&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;&amp;quot;Client-side ZK Part 1&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; border&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;&amp;quot;normal&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; apply&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;&amp;quot;myapp.WindowComposer&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #22863A;&quot;&gt;script&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; src&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;&amp;quot;~.&#x2F;myapp&#x2F;jquery.imgr.min.js&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt; &#x2F;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #22863A;&quot;&gt;panel&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; title&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;&amp;quot;Not rounded&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #22863A;&quot;&gt;panelchildren&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #22863A;&quot;&gt;image&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; src&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;&amp;quot;~.&#x2F;myapp&#x2F;Eye-of-a-tiger412.jpg&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt; &#x2F;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    &amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #22863A;&quot;&gt;panelchildren&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  &amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #22863A;&quot;&gt;panel&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #22863A;&quot;&gt;panel&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; title&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;&amp;quot;Rounded&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #22863A;&quot;&gt;panelchildren&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; id&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;&amp;quot;rounded&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #22863A;&quot;&gt;image&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; src&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;&amp;quot;~.&#x2F;myapp&#x2F;Eye-of-a-tiger412.jpg&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; sclass&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;&amp;quot;rounded&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt; &#x2F;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    &amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #22863A;&quot;&gt;panelchildren&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  &amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #22863A;&quot;&gt;panel&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #22863A;&quot;&gt;button&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; id&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;&amp;quot;button&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; label&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;&amp;quot;Add another rounded image!&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt; &#x2F;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #22863A;&quot;&gt;script&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    jq(function() {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      jq(&amp;#39;.rounded&amp;#39;).imgr({ radius: &amp;#39;20px&amp;#39; });&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    })&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  &amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #22863A;&quot;&gt;script&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #22863A;&quot;&gt;window&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Notice the use of &lt;strong&gt;jq instead of $&lt;&#x2F;strong&gt;, which is the recommended way of using jQuery with ZK. The &lt;strong&gt;~.&#x2F;&lt;&#x2F;strong&gt; prefix in resource paths means the &lt;em&gt;web&lt;&#x2F;em&gt; directory in classpath.&lt;&#x2F;p&gt;
&lt;p&gt;As you might notice, we&#x27;re using a composer for the top-level window. For actual code I will be using Scala, but all my code could also be implemented with plain Java. Here&#x27;s WindowComposer.scala:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #24292E; background-color: #FFFFFF;&quot;&gt;&lt;code data-lang=&quot;scala&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;package&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; myapp&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;import&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; org&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;zkoss&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;zk&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;ui&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;event&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;_&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;import&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; org&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;zkoss&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;zk&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;ui&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;util&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;_&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;import&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; org&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;zkoss&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;zul&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;_&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;class&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; WindowComposer&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; extends&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; GenericForwardComposer&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;  private var&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt; rounded&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; PanelChildren&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; _&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;  def&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; onClick$button&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt;event&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Event&lt;&#x2F;span&gt;&lt;span&gt;) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;    val&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt; image&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; = new&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Image&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;&amp;quot;~.&#x2F;myapp&#x2F;Eye-of-a-tiger412.jpg&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    image.setSclass(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;&amp;quot;rounded&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    rounded.appendChild(image)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The composer simply adds a new image to the rounded panel.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;del&gt;Ok looks like we&#x27;re done! Wow that was easy.&lt;&#x2F;del&gt; The second image won&#x27;t be rounded! What went wrong? If you open the page in a browser and check the source code, you&#x27;ll see that the HTML content is almost empty. All the ZK components are defined in JavaScript! So when the jQuery standard document.ready function runs the image rounding code, the ZK components haven&#x27;t been rendered yet and nothing happens.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;making-the-plugin-work-with-zk&quot;&gt;Making the plugin work with ZK&lt;&#x2F;h3&gt;
&lt;p&gt;Luckily ZK provides it&#x27;s own callback mechanism called &lt;strong&gt;zk.afterMount&lt;&#x2F;strong&gt;. We&#x27;ll just replace the original script element with this:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #24292E; background-color: #FFFFFF;&quot;&gt;&lt;code data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #22863A;&quot;&gt;script&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  zk.afterMount(function() {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;    jq&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;&amp;#39;.rounded&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;).&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;imgr&lt;&#x2F;span&gt;&lt;span&gt;({ radius:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt; &amp;#39;20px&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt; });&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  })&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #22863A;&quot;&gt;script&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Finally it works! However, if you click the button, the new images won&#x27;t be rounded. This of course happens because the jQuery selector isn&#x27;t used after the initial page load. In Scala&#x2F;Java code, we can use &lt;strong&gt;Clients.evalJavascript&lt;&#x2F;strong&gt; to run custom JS. This time we won&#x27;t need afterMount because the code is executed in the button click listener:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #24292E; background-color: #FFFFFF;&quot;&gt;&lt;code data-lang=&quot;scala&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;rounded.appendChild(image)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;Clients&lt;&#x2F;span&gt;&lt;span&gt;.evalJavascript(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;&amp;quot;jq(&amp;#39;.rounded&amp;#39;).imgr({ radius: &amp;#39;20px&amp;#39; })&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Now it works! But we&#x27;re running imgr on all elements with class=&quot;rounded&quot; on the page. Maybe we could make a more exact selection and run it only on the new image component. We can use DOM id selection instead of class selection to narrow down the operation:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #24292E; background-color: #FFFFFF;&quot;&gt;&lt;code data-lang=&quot;scala&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;rounded.appendChild(image)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;Clients&lt;&#x2F;span&gt;&lt;span&gt;.evalJavaScript(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;&amp;quot;jq(&amp;#39;#&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; +&lt;&#x2F;span&gt;&lt;span&gt; image.getUuid &lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;+&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt; &amp;quot;&amp;#39;).imgr({ radius: &amp;#39;20px&amp;#39; })&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Notice that &lt;strong&gt;ZK component uuid == DOM id. ZK component ids are not rendered in DOM at all!&lt;&#x2F;strong&gt; So a component with id=&quot;something&quot; is not rendered as id=&quot;something&quot; in the resulting HTML.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;success&quot;&gt;Success!&lt;&#x2F;h3&gt;
&lt;p&gt;Finally everything works as intended. Here&#x27;s a quick recap of the important things:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;ZK id != DOM id&lt;&#x2F;li&gt;
&lt;li&gt;ZK uuid == DOM id&lt;&#x2F;li&gt;
&lt;li&gt;Use zk.afterMount instead of document.ready&lt;&#x2F;li&gt;
&lt;li&gt;You can run custom Javascript in Java&#x2F;Scala code with Clients.evalJavaScript&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Up next: &lt;strong&gt;Part 2: From jQuery plugin to a ZK component&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>JPA entity scanning with Spring</title>
        <published>2010-07-01T20:17:02+02:00</published>
        <updated>2010-07-01T20:17:02+02:00</updated>
        
        <author>
          <name>
            
              Joonas Javanainen
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://gekkio.fi/blog/2010/jpa-entity-scanning-with-spring/"/>
        <id>https://gekkio.fi/blog/2010/jpa-entity-scanning-with-spring/</id>
        
        <content type="html" xml:base="https://gekkio.fi/blog/2010/jpa-entity-scanning-with-spring/">&lt;p&gt;If you&#x27;ve used JPA, does this look familiar?&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #24292E; background-color: #FFFFFF;&quot;&gt;&lt;code data-lang=&quot;xml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #22863A;&quot;&gt;persistence&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #22863A;&quot;&gt;persistence-unit&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #22863A;&quot;&gt;class&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;my.entities.package.Entity&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #22863A;&quot;&gt;class&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #22863A;&quot;&gt;class&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;my.entities.package.Another&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #22863A;&quot;&gt;class&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #22863A;&quot;&gt;class&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;my.entities.package.More&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #22863A;&quot;&gt;class&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #22863A;&quot;&gt;class&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;my.entities.package.EvenMore&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #22863A;&quot;&gt;class&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #22863A;&quot;&gt;class&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;my.entities.package.AndMore&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #22863A;&quot;&gt;class&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #22863A;&quot;&gt;class&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;my.entities.package.AndEvenMore&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #22863A;&quot;&gt;class&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  &amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #22863A;&quot;&gt;persistence-unit&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #22863A;&quot;&gt;persistence&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Writing JPA entity class names into persistence.xml can be a pain. How could a &lt;span class=&quot;line-through&quot;&gt;lazy&lt;&#x2F;span&gt; wise programmer make it easier?&lt;&#x2F;p&gt;
&lt;p&gt;By implementing entity scanning of course!&lt;&#x2F;p&gt;
&lt;p&gt;JPA has its own class scanning system, but it has some fundamental limitations.&lt;&#x2F;p&gt;
&lt;p&gt;As far as I know, it only scans the JAR where persistence.xml resides so it cannot be used to include other entities into the same persistence context. Spring supports &lt;a rel=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;static.springsource.org&#x2F;spring&#x2F;docs&#x2F;3.0.x&#x2F;javadoc-api&#x2F;org&#x2F;springframework&#x2F;orm&#x2F;jpa&#x2F;persistenceunit&#x2F;PersistenceUnitPostProcessor.html&quot;&gt;PersistenceUnitPostProcessor&lt;&#x2F;a&gt;s that can modify a persistence context and add new entities into it!&lt;&#x2F;p&gt;
&lt;p&gt;A post processor could for example scan a base package for entities and add all entities which have proper JPA annotations.&lt;&#x2F;p&gt;
&lt;p&gt;Here&#x27;s a post processor written in Scala:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #24292E; background-color: #FFFFFF;&quot;&gt;&lt;code data-lang=&quot;scala&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;import&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; javax&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;persistence&lt;&#x2F;span&gt;&lt;span&gt;.{&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;Entity&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;Embeddable&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;MappedSuperclass&lt;&#x2F;span&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;import&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; org&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;slf4j&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;LoggerFactory&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;import&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; org&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;springframework&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;beans&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;factory&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;config&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;BeanDefinition&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;import&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; org&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;springframework&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;context&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;annotation&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;ClassPathScanningCandidateComponentProvider&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;import&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; org&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;springframework&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;core&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;`type`&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;filter&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;AnnotationTypeFilter&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;import&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; org&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;springframework&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;orm&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;jpa&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;persistenceunit&lt;&#x2F;span&gt;&lt;span&gt;.{&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;MutablePersistenceUnitInfo&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;PersistenceUnitPostProcessor&lt;&#x2F;span&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;import&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; scala&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;collection&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;JavaConversions&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;_&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;class&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; EntityScanningPersistenceUnitPostProcessor&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt;basePackage&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; String&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;    extends&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; ClassPathScanningCandidateComponentProvider&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt;false&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;    with&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; PersistenceUnitPostProcessor&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  addIncludeFilter(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;new&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; AnnotationTypeFilter&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt;classOf&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;Entity&lt;&#x2F;span&gt;&lt;span&gt;]))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  addIncludeFilter(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;new&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; AnnotationTypeFilter&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt;classOf&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;Embeddable&lt;&#x2F;span&gt;&lt;span&gt;]))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  addIncludeFilter(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;new&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; AnnotationTypeFilter&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt;classOf&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;MappedSuperclass&lt;&#x2F;span&gt;&lt;span&gt;]))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;  private val&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt; log&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; LoggerFactory&lt;&#x2F;span&gt;&lt;span&gt;.getLogger(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt;this&lt;&#x2F;span&gt;&lt;span&gt;.getClass)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;  override def&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; postProcessPersistenceUnitInfo&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt;info&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; MutablePersistenceUnitInfo&lt;&#x2F;span&gt;&lt;span&gt;) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;    val&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt; count&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; =&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      findCandidateComponents(basePackage).foldLeft(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt;0L&lt;&#x2F;span&gt;&lt;span&gt;) { (count, beanDefinition)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; =&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        info.addManagedClassName(beanDefinition.getBeanClassName)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        count &lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;+&lt;&#x2F;span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt; 1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    log.info(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;&amp;quot;Registered {} entities from base package {}&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, count, basePackage)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Here&#x27;s how to use it with Spring JavaConfig:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #24292E; background-color: #FFFFFF;&quot;&gt;&lt;code data-lang=&quot;scala&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;@&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;Bean&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;def&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; entityManagerFactory&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;  val&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt; bean&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; = new&lt;&#x2F;span&gt;&lt;span&gt; org.springframework.orm.jpa.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;LocalContainerEntityManagerFactoryBean&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6A737D;&quot;&gt;  &#x2F;&#x2F; ... normal configuration&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  bean.setPersistenceUnitPostProcessors(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;Array&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;new&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; EntityScanningPersistenceUnitPostProcessor&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;&amp;quot;my.entities.package&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  bean&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The major downside in this approach is that some JPA tooling assumes that persistence.xml contains the entities that will be used.&lt;&#x2F;p&gt;
&lt;p&gt;They will fail because they at compile-time the persistence context seems empty!&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>IE6 incompatibilities in ZK</title>
        <published>2010-03-18T15:57:43+01:00</published>
        <updated>2010-03-18T15:57:43+01:00</updated>
        
        <author>
          <name>
            
              Joonas Javanainen
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://gekkio.fi/blog/2010/ie6-incompatibilities-in-zk/"/>
        <id>https://gekkio.fi/blog/2010/ie6-incompatibilities-in-zk/</id>
        
        <content type="html" xml:base="https://gekkio.fi/blog/2010/ie6-incompatibilities-in-zk/">&lt;p&gt;There&#x27;s a very annoying IE6 incompatibility in ZK.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #24292E; background-color: #FFFFFF;&quot;&gt;&lt;code data-lang=&quot;xml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #22863A;&quot;&gt;window&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; title&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;&amp;quot;I hate IE6&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; border&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;&amp;quot;normal&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #22863A;&quot;&gt;popup&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; id&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;&amp;quot;popup&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #22863A;&quot;&gt;label&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; value&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;&amp;quot;Fail&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt; &#x2F;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  &amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #22863A;&quot;&gt;popup&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #22863A;&quot;&gt;label&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; value&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;&amp;quot;Click me&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; popup&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;&amp;quot;popup&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt; &#x2F;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #22863A;&quot;&gt;window&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;When you click the label &quot;Fail&quot;, you&#x27;ll get a popup that is sized by its contents....
.... except in IE6 where the popup always has 100% width.&lt;&#x2F;p&gt;
&lt;p&gt;This can of course be fixed by specifying a fixed width for the popup, but this is typically ugly. If the application supports localization, you&#x27;ll be forced to guess a good width for all localizations.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>SBT and JRebel</title>
        <published>2010-01-21T17:34:08+01:00</published>
        <updated>2010-01-21T17:34:08+01:00</updated>
        
        <author>
          <name>
            
              Joonas Javanainen
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://gekkio.fi/blog/2010/sbt-and-jrebel/"/>
        <id>https://gekkio.fi/blog/2010/sbt-and-jrebel/</id>
        
        <content type="html" xml:base="https://gekkio.fi/blog/2010/sbt-and-jrebel/">&lt;p&gt;I was at first sceptical about &lt;a rel=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;www.zeroturnaround.com&#x2F;jrebel&#x2F;&quot;&gt;JRebel&lt;&#x2F;a&gt;, but after using it for a while, I must say that it&#x27;s awesome!&lt;&#x2F;p&gt;
&lt;p&gt;It&#x27;s compatible with SBT, so you can get a good boost to your productivity when you combine JRebel with the incremental compilation of Scala code in SBT.&lt;&#x2F;p&gt;
&lt;p&gt;However, when using JRebel, you don&#x27;t want Jetty to redeploy the webapp automatically. You could just disable Jetty manually but then people who don&#x27;t use JRebel would have to reload manually.&lt;&#x2F;p&gt;
&lt;p&gt;Here&#x27;s how to disable Jetty redeploying in SBT only if JRebel is active:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #24292E; background-color: #FFFFFF;&quot;&gt;&lt;code data-lang=&quot;scala&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;class&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; YourProject&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt;info&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; ProjectInfo&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; extends&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; DefaultWebProject&lt;&#x2F;span&gt;&lt;span&gt;(info) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;  lazy val&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt; jrebelInUse&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; List&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;&amp;quot;jrebel.lic&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;&amp;quot;javarebel.lic&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;).exists(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt;this&lt;&#x2F;span&gt;&lt;span&gt;.getClass.getClassLoader.getResource(_)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; !=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt; null&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;  override def&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; scanDirectories&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; = if&lt;&#x2F;span&gt;&lt;span&gt; (jrebelInUse)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Nil&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; else&lt;&#x2F;span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt; super&lt;&#x2F;span&gt;&lt;span&gt;.scanDirectories&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;strong&gt;Update:&lt;&#x2F;strong&gt; Consider using &lt;a rel=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;github.com&#x2F;Gekkio&#x2F;sbt-jrebel-plugin&quot;&gt;sbt-jrebel-plugin&lt;&#x2F;a&gt; instead because it can also generate &lt;em&gt;rebel.xml&lt;&#x2F;em&gt; files for you!&lt;&#x2F;p&gt;
</content>
        
    </entry>
</feed>
