<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="3.10.0">Jekyll</generator><link href="https://calc84maniac.github.io/tiboyce/feed.xml" rel="self" type="application/atom+xml" /><link href="https://calc84maniac.github.io/tiboyce/" rel="alternate" type="text/html" /><updated>2025-08-22T04:01:39+00:00</updated><id>https://calc84maniac.github.io/tiboyce/feed.xml</id><title type="html">TI-Boy CE</title><subtitle>A Game Boy emulator for the TI-84 Plus CE and TI-83 Premium CE.</subtitle><author><name>Brendan Fletcher</name></author><entry><title type="html">Alpha v0.3.1 Released</title><link href="https://calc84maniac.github.io/tiboyce/releases/2025/08/22/alpha-v0.3.1-released.html" rel="alternate" type="text/html" title="Alpha v0.3.1 Released" /><published>2025-08-22T00:00:00+00:00</published><updated>2025-08-22T00:00:00+00:00</updated><id>https://calc84maniac.github.io/tiboyce/releases/2025/08/22/alpha-v0.3.1-released</id><content type="html" xml:base="https://calc84maniac.github.io/tiboyce/releases/2025/08/22/alpha-v0.3.1-released.html"><![CDATA[<p>It’s been a while since the last release, partially because I’ve been working on other projects (including <a href="https://github.com/CE-Programming/CEmu">CEmu</a>,
which now fully supports all versions of TI-Boy CE), but I’d like to finally push out the changes I’ve been sitting on for a while.</p>

<p>Alongside some bugfixes for several games, small optimizations, and interface improvements, the major feature of this release is a smoother upscaling mode.
This mode uses flicker-based blending to approximate linear upscaling (not bilinear, since the horizontal scaling is always an integer upscale).</p>

<p>The <a href="/tiboyce/converter">ROM converter</a>’s trimming logic has also been updated to allow further reducing the size of some ROMs.</p>

<p>You can download the release from <a href="https://github.com/calc84maniac/tiboyce/releases">GitHub</a>.</p>

<h2 id="changelog">Changelog</h2>

<h3 id="added">Added</h3>
<ul>
  <li>Linear upscaling mode for fullscreen, using flicker-based blending.
    <ul>
      <li>The previous, slightly faster, nearest-neighbor upscaling mode is still available.</li>
    </ul>
  </li>
  <li>Enhanced ROM trimming, allowing the ROM converter to further reduce the size of certain ROMs.</li>
  <li>Joypad interrupt support, along with increased key polling rate.</li>
  <li>Screen rotation option, to allow flipping the calculator 180 degrees to put the arrow keys on the left.
    <ul>
      <li>The configured arrow keys are also automatically rotated in this mode.</li>
    </ul>
  </li>
</ul>

<h3 id="changed">Changed</h3>
<ul>
  <li>Online ROM converter is now compiled to WASM instead of JavaScript.</li>
  <li>User-configured A, B, Menu buttons can now be used to control the menu.
    <ul>
      <li>Also, the control configuration menu can now be navigated using all four arrow keys.</li>
    </ul>
  </li>
  <li>Expansion of 15-bit color to 18-bit now uses an intensity bit, producing more consistent grays.</li>
  <li>LCD SPI initialization for Python models now uses a direct method instead of reinitializing all hardware.</li>
  <li>Various optimizations.
    <ul>
      <li>Use the hardware stack protector to optimize call stack emulation.</li>
      <li>Reduce complexity of DAA emulation, with more consistent timing for different cases.</li>
      <li>Optimize zero flag reset for ADD SP instructions.</li>
    </ul>
  </li>
  <li>Internal restructuring to ease development of future features.
    <ul>
      <li>Modularize large code files into smaller, categorized files.</li>
      <li>Make direct memory reads hookable, which supports the enhanced ROM trimming but has more potential uses.</li>
      <li>Make accesses to save state data indirect, allowing for prior memory insertion (e.g. dynamic library loading).</li>
    </ul>
  </li>
</ul>

<h3 id="fixed">Fixed</h3>
<ul>
  <li>Fix incorrect rounding for ROM bank trim length. Fixes Dragon Warriors Monsters 2: Cobi’s Journey.</li>
  <li>Treat STOP opcode as 2 bytes. Fixes Dr. Rin ni Kiitemite! - Koi no Rin Fuusui.</li>
  <li>Fix stack usage in RST slow case, fix direct stack pointer adjustment. Fixes The Machine.
    <ul>
      <li>Also, prevent hard crashes if a bug causes the SPS and SPL stacks to desync.</li>
    </ul>
  </li>
  <li>Allow throttling non-rendered frames to reduce dropped inputs.</li>
  <li>Fix flickering in screen transitions and menu redrawing.</li>
  <li>Fix some cases where the emulator message overlay would become corrupted.</li>
  <li>Prevent turning off the calculator during the Garbage Collect prompt, which would leak memory.</li>
</ul>]]></content><author><name>Brendan Fletcher</name></author><category term="Releases" /><category term="Release" /><summary type="html"><![CDATA[It’s been a while since the last release, partially because I’ve been working on other projects (including CEmu, which now fully supports all versions of TI-Boy CE), but I’d like to finally push out the changes I’ve been sitting on for a while.]]></summary></entry><entry><title type="html">Just-In-Time Recompiling the Game Boy: Part 2 (Recompiler Design)</title><link href="https://calc84maniac.github.io/tiboyce/design/2022/12/22/just-in-time-recompiling-the-game-boy-part-2-recompiler-design.html" rel="alternate" type="text/html" title="Just-In-Time Recompiling the Game Boy: Part 2 (Recompiler Design)" /><published>2022-12-22T00:00:00+00:00</published><updated>2022-12-22T00:00:00+00:00</updated><id>https://calc84maniac.github.io/tiboyce/design/2022/12/22/just-in-time-recompiling-the-game-boy-part-2-recompiler-design</id><content type="html" xml:base="https://calc84maniac.github.io/tiboyce/design/2022/12/22/just-in-time-recompiling-the-game-boy-part-2-recompiler-design.html"><![CDATA[<p><a href="/tiboyce/design/2020/08/27/just-in-time-recompiling-the-game-boy-part-1-introduction.html">Last time</a>, we went over the design goals leading to the use of JIT recompilation to make a Game Boy emulator on a calculator. Now, let’s dig more into how this is accomplished.</p>

<h2 id="the-execution-environment">The Execution Environment</h2>

<p>As briefly mentioned in the previous post, the TI-84+ CE runs on a Zilog eZ80 processor, which has both 24-bit and 16-bit addressing modes. The processor can execute in either of these modes, which determines the width of the PC (Program Counter) register and the default width of operations on other multi-byte registers. However, there are also opcode prefixes which allow individual instructions to explicitly use an addressing mode, or in the case of branches, change the mode. So, it is possible (at a slight cost) to access 24-bit addresses in 16-bit mode, or vice versa.</p>

<p>TI-Boy runs recompiled code in 16-bit mode for several reasons:</p>

<ul>
  <li>16-bit code is smaller and more efficient than 24-bit code – multi-byte immediate values (including for branches like JP and CALL) are one byte smaller, and stack pushes/pops (including for branches like CALL and RET) also access one fewer byte.</li>
  <li>Since the base of the 16-bit address space within the 24-bit address space is configurable, it can be set to an entire 64 KiB of RAM. This means that any special addresses (like the RST vectors) are under control of the emulator, unlike the 24-bit equivalents which are under control of Texas Instruments’ read-only boot code. Being able to use RST vectors allows further improvements to generated code size and efficiency, because the RST instruction is effectively a CALL that’s only 1 byte in size instead of 3, with the limitation that only 8 call destinations are usable.</li>
  <li>Most values kept in multi-byte registers during CPU emulation need only be 16-bit, because they mostly represent Game Boy CPU registers. Additionally, this means no opcode prefixes are necessary for emulating the Game Boy’s few 16-bit operations.</li>
</ul>

<p>There are a couple of downsides to using 16-bit mode, which are arguably not dealbreakers:</p>

<ul>
  <li>The 16-bit address space puts a hard limit on the amount of recompiled code that can be cached at a time. However, given the relatively small amount of RAM available on the system in the first place, there would have had to be some kind of limit regardless. In practice, I’ve not seen any games where the 50-something KB limit on JIT code (accounting for statically allocated 16-bit subroutines) was so small that it couldn’t cache all the code for many game frames in a row.</li>
  <li>Accesses to the emulated Game Boy address space (such as ROM and RAM) require usage of 24-bit pointers. This means either using opcode prefixes or switching entirely to 24-bit mode, depending on how much data is being accessed. However, the largest source of memory accesses – opcode fetches – are implicitly eliminated by the usage of recompiled code. For other typical memory accesses by an emulated CPU instruction, only 3 prefixed instructions are needed (load base address, add offset, and access memory), which is already balanced out by the reduced CALL and RET overhead. Additionally, the Game Boy’s OAM, I/O, and HRAM are allocated in the 16-bit address space at their original addresses (0xFE00 to 0xFFFF), which allows direct access via 16-bit pointers.</li>
</ul>

<h2 id="jit-code-management">JIT Code Management</h2>

<p>Now that we’ve gone over where the recompiled code is executed, how is it put there and tracked? To start, here’s the layout of the 16-bit address space:</p>

<ul>
  <li>RST routines (64 bytes)</li>
  <li>Statically allocated routines (around 10 KB as of this writing)</li>
  <li>JIT code space (grows forward)</li>
  <li>JIT trampoline space (grows backward)</li>
  <li>CPU flags translation table (256 bytes)</li>
  <li>Hardware stack (256 bytes)</li>
  <li>Game Boy OAM (256 bytes)</li>
  <li>Game Boy I/O (128 bytes)</li>
  <li>Game Boy HRAM (128 bytes)</li>
</ul>

<p>JIT code is allocated using a bump allocator, and JIT trampolines are allocated in the same buffer, but growing back from the end. I’ll cover trampolines at a later time, but just know that they’re used to patch recompiled instructions which are later determined to need more space than was originally allocated. When newly allocated JIT code collides with the trampolines, or vice versa, the buffer is flushed of all code.</p>

<p>The JIT code, like in most JIT implementations, is organized in “blocks” of contiguous code. However, unlike many other JITs, these blocks are not limited to <a href="https://en.wikipedia.org/wiki/Basic_block">basic blocks</a>. The only requirement is that execution can flow all the way from the beginning to the end of the block – meaning blocks may continue through conditional branches, or even through unconditional CALL instructions (since execution is extremely likely to flow back through the corresponding RET). However, basic blocks contained within blocks are still used as the fundamental unit of cycle counting.</p>

<p>Blocks are uniquely tagged by a representation of their starting Game Boy virtual and physical addresses. This sounds like a lot of data, but it’s really just the 16-bit virtual address combined with an 8-bit physical memory bank for swappable regions (since the remainder of the physical address is implied by the virtual address). The virtual address is required because each block may implicitly use the value of the PC register in any instruction, and it’s possible for the same physical address to be mapped to multiple virtual addresses (for example, ROM bank 0 in MBC5 cartridges). Note that this representation excludes 8 MiB cartridges with 512 ROM banks, but the calculator’s usable Flash storage is only 3 MiB, so it’s not worth the effort of tracking 9-bit banks.</p>

<p>Each block is tracked in an 11 KiB array of structures of the following information (allowing for up to around 1400 blocks at a time in total):</p>

<ul>
  <li>JIT code start address (2 bytes)</li>
  <li>Block tag (3 bytes)</li>
  <li>Opcode byte count (1 byte)</li>
  <li>Reserved (formerly upper byte count) (1 byte)</li>
  <li>Cycle count of first basic block (1 byte)</li>
</ul>

<h2 id="jit-code-lookups">JIT Code Lookups</h2>

<p>Another different design choice from many other JITs is having a clear border between each emulated instruction where the registers are in a consistent state, which allows entry into a block starting at any instruction. This is made possible without a large amount of overhead mainly due to the CPU flag similarities between the Game Boy and eZ80 processors. This allows much more effective block reuse, saving a lot of memory and justifying the larger block size. Additionally, this allows for <em>exiting</em> a block between any two instructions, which I’ll discuss later when we get to interrupt handling.</p>

<p>The block tag, combined with the opcode byte count, is used as a range check to determine if a desired code address may be present in the block. It only <em>may</em> be present because Game Boy opcodes are variable-length, so it’s not known whether an address is at the start of an instruction until the block is scanned.</p>

<p>Blocks can be easily scanned without storing auxiliary information about each instruction in the block, aside from referencing the original opcodes. This is because with a few exceptions, a given opcode always translates to the same number of bytes when recompiled and takes the same number of cycles, no matter which block it’s contained in or what its operands are. The only special cases needed are for opcodes which terminate a basic block (after which the cycle count for the next basic block must be extracted from the JIT code) and the few opcodes with variable-length JIT implementations.</p>

<p>Similarly, the code can be scanned to translate a JIT code address back to a Game Boy code address (which is primarily used for trampoline generation for memory accesses), or to scan forward by a given number of cycles within a basic block (which is primarily used for interrupt scheduling). Both of these usages will be discussed in more detail later.</p>

<h2 id="cached-lookups">Cached Lookups</h2>

<p>Code scanning is very nice for memory usage, but not so great for performance if done repeatedly. Ideally, a given Game Boy code address should only be looked up once, and the result cached for future uses.</p>

<h3 id="block-linking">Block Linking</h3>

<p>The most basic form of JIT address caching is through direct block linking. That is, when a branch instruction with a constant destination address (such as JR, JP, or CALL) is executed, after looking up the JIT target, that target address can be patched directly into the implementation to avoid any future lookups. This is known as “block linking” because it often creates a direct reference to another JIT block, though my implementation easily allows intra-block linking as well.</p>

<p>The most likely case for the same branch target being looked up from multiple different instructions is from CALLs, but I suspect that the cost of doing so is not very high due to CALL targets likely being at the very start of a block, which has no instruction scanning overhead. As such, it’s not worth having an additional cache for such lookups.</p>

<p>There is one hitch with block linking, which is that the branch instruction only specifies the <em>virtual</em> address being branched to. In the context of memory bank swapping, this may cause some links to be invalid if a different bank is swapped in at the time of the branch. In fact, I discovered this the hard way when some games did this intentionally. My solution to this was to use a special implementation when branching into a banked memory region, which validates the current bank. You might think this would cause a huge dip in performance, but fortunately this is only necessary when jumping from <em>outside</em> the banked region. Jumps within the banked region are guaranteed not to have a bank mismatch, so this doesn’t really cause a lot of extra checks in the end.</p>

<h3 id="variable-jumps">Variable Jumps</h3>

<p>Of course, not all jumps in a game will be to absolute addresses. Using function pointers or jump tables is a very common technique, and on the Game Boy this is accomplished through the JP HL or RET instructions.</p>

<p>To deal with these kinds of jumps, I use a simple hash map of tagged Game Boy addresses to JIT address and cycle count. In fact, when I say simple, it’s <em>extremely</em> simple. There are 256 fixed hash buckets with expandable lists, and each bucket corresponds to the low byte of the Game Boy address. This trick allows the low byte to be omitted from the list entries, reducing each entry’s size to 5 bytes. This technically makes lookups linear time, but it’s linear with a constant factor of 256 divided out, which in practice is almost constant time with typical usage of this cache.</p>

<p>How does this cache avoid getting thrashed with the large number of RET destinations from CALLs, or worse, interrupts? That leads to the final type of cached lookup:</p>

<h3 id="return-prediction">Return Prediction</h3>

<p>Just like for branch prediction in modern CPU design, it’s quite effective to assume a RET will return to the same place as the most recent CALL. This is the primary reason I allow JIT blocks to continue through even unconditional CALL instructions – the JIT address of the following code can be placed directly onto a return prediction stack. In fact, by storing this stack on the eZ80’s hardware stack, this address can be directly pushed by calling the CALL implementation.</p>

<p>I store four pieces of information on the prediction stack:</p>

<ul>
  <li>The predicted JIT return address (2 bytes)</li>
  <li>The cycle count at that JIT address (1 byte)</li>
  <li>The relative level of the Game Boy stack (1 byte)</li>
  <li>The predicted Game Boy return address, tagged with a memory bank change sentinel (3 bytes)</li>
</ul>

<p>Much like for block linking, changes to the memory bank must be detected to know if the prediction is valid. However, it would be quite inconvenient when emulating RET to check which memory region the predicted return address is in, load the appropriate bank index, and compare to it. This is especially wasteful when most CALL/RET pairs perform no bank swaps inbetween whatsoever.</p>

<p>So, instead of storing the predicted memory bank on the prediction stack, instead a sentinel is placed on the stack, always initialized to 0. Then, whenever a bank is swapped, the topmost entry of the prediction stack which corresponds to that region is updated, using the XOR of the old and new bank values. Eventually, if the bank is swapped back to what it was when the CALL occurred, the sentinel value will return to 0.</p>

<p>Now, when emulating RET, the real 16-bit return address is popped from the Game Boy’s stack, and is compared to both the predicted return address and the sentinel by using a 24-bit comparison. If the comparison matches (as it would in the vast majority of cases), it simply counts cycles using the predicted cycle count and returns to the predicted JIT address.</p>

<p>If the comparison mismatches, it first checks the relative stack level (based on the low bits of the Game Boy’s SP register). If the popped return address was higher on the stack than the prediction, then it is assumed that the prediction may still be valid in the future, and ensures anything that was popped is pushed back. Otherwise, the prediction is removed from the stack, and any non-zero memory bank sentinel is propagated down to the next entry in that region. If the popped return address was <em>lower</em> on the stack than the prediction, it loops back and attempts to pop the next prediction entry. Finally, if no prediction matched, it falls back on the variable jump cache.</p>

<p>The final consideration is stack overflow – naturally, I must bound the return prediction stack in order not to overflow the hardware stack. This is done using a simple comparison when pushing in the CALL implementation, to avoid exceeding 32 stack entries. If the limit is exceeded, the stack is flushed, meaning any predictions on the stack that would have been valid will end up falling back on the variable jump cache. This is a fairly rare situation in practice, however.</p>

<h2 id="self-modifying-code">Self-Modifying Code</h2>

<p>So far, I’ve ignored the elephant in the room – JIT blocks which are sourced from code in RAM, which may change after (or during!) their initial execution. My current solution is not very cleverly designed, but because the frequency of RAM-based code in Game Boy games is quite low, I used a potentially inefficient solution which doesn’t interfere with other emulator operations, such as memory writes.</p>

<p>For RAM-based JIT blocks, I copy the original opcode bytes to the end of the block, and add a prologue at the beginning which compares this copy of the opcodes to the actual opcode bytes in Game Boy RAM. If the bytes all match, the block is allowed to run normally. Otherwise, the JIT engine will attempt to recompile the new opcodes within the space originally allocated for the block. If this causes a buffer overflow, it flushes the JIT code and increases a global RAM block padding amount by the amount of overflow, to avoid that overflow in the future. It’s potentially wasteful, but it works.</p>

<p>Since RAM-based blocks may be recompiled in-place, it is not allowed to perform block linking or variable jump caching into the middle of a block. Return prediction is allowed, but the return prediction stack is checked after an in-place recompile to remove any predictions pointing to that block.</p>

<p>However, lack of block linking could make RAM-based loops extremely slow, since it would perform the opcode comparison on every loop iteration. As such, I do specifically allow <em>intra-block</em> linking for RAM-based code. This is fine because any such links are implicitly destroyed along with the old block when the in-place recompile occurs.</p>

<p>One other performance consideration is dealing with a relatively common self-modifying code idiom in Game Boy games: implementing function pointers by placing an absolute JP opcode in RAM, which is often more efficient than loading HL from memory and using JP HL. In my emulator’s case, it is quite inconvenient to perform an in-place recompile every time the jump target changes, so instead I use a special block prologue which only verifies the JP opcode, then uses the variable jump cache on the current jump target.</p>

<p>One final consideration, especially due to the JIT block size, is how to handle when a block modifies itself (the true form of “self-modifying” code). My current solution is to assume that such modifications are performed via absolute address writes, and I do analysis of such writes during recompilation. If such a write is targeting an address close ahead of PC, I end the current block early, which allows the next block’s prologue to perform opcode comparison and do any recompilation which may be needed. This simple heuristic doesn’t seem to have failed in any games I’ve tested.</p>

<h2 id="conclusion">Conclusion</h2>

<p>Hopefully, now you understand more about how my JIT is organized, and how I try to avoid redundant JIT code lookups, as well as how self-modifying code fits into the picture.</p>

<p>Next time, I may talk about cycle counting, scheduling, and interrupts. Until then, happy coding!</p>]]></content><author><name>Brendan Fletcher</name></author><category term="Design" /><category term="Emulator Design" /><category term="JIT Recompiler" /><summary type="html"><![CDATA[Last time, we went over the design goals leading to the use of JIT recompilation to make a Game Boy emulator on a calculator. Now, let’s dig more into how this is accomplished.]]></summary></entry><entry><title type="html">Alpha v0.3.0 Released</title><link href="https://calc84maniac.github.io/tiboyce/releases/2022/12/04/alpha-v0-3-0-released.html" rel="alternate" type="text/html" title="Alpha v0.3.0 Released" /><published>2022-12-04T00:00:00+00:00</published><updated>2022-12-04T00:00:00+00:00</updated><id>https://calc84maniac.github.io/tiboyce/releases/2022/12/04/alpha-v0-3-0-released</id><content type="html" xml:base="https://calc84maniac.github.io/tiboyce/releases/2022/12/04/alpha-v0-3-0-released.html"><![CDATA[<p>After a long year of work, TI-Boy CE finally supports Game Boy Color!
This involved an extensive rewrite of the memory system to support both GB and GBC memory maps, also allowing improved compatibility and performance.
The color correction feature was also greatly improved from what was used in colorization for previous releases. The full change log is below.</p>

<p>You can download the release from <a href="https://github.com/calc84maniac/tiboyce/releases">GitHub</a>.</p>

<p>I’ve also recorded a video showing gameplay of Pokémon Crystal and Mario Golf:</p>

<div class="video-container">
  <iframe class="video" src="https://www.youtube-nocookie.com/embed/vJ7nHP612eQ" frameborder="0" allowfullscreen=""></iframe>
</div>

<p>The next main work for the project will be updating the GBC renderer to handle mid-frame palette changes, without which some games have incorrect colors.</p>

<h2 id="changelog">Changelog</h2>

<h3 id="added">Added</h3>
<ul>
  <li>Game Boy Color support.</li>
  <li>GBA backwards-compatibility to unlock features in some GBC games.</li>
  <li>Color correction to approximate the color spectrum of a GBC or GBA screen, leveraging native gamma settings.</li>
  <li>Game Boy Color skin for no-scaling mode.</li>
  <li>Brightness change hotkeys usable in menus.</li>
</ul>

<h3 id="changed">Changed</h3>
<ul>
  <li>Confirmation setting for Load State now also applies to Restart Game.</li>
  <li>Various improvements to the menu, courtesy of <a href="https://github.com/runer112">runer112</a>:
    <ul>
      <li>Mark per-game options instead of global options with an asterisk.</li>
      <li>Improved menu item alignment and font.</li>
    </ul>
  </li>
  <li>Majorly rewrite the CPU emulation to improve performance and flexibility of memory access emulation.
    <ul>
      <li>Rearrange the JIT’s static register allocation and the ABI of routines called from it.</li>
      <li>Remove dynamically-generated per-opcode memory routines, reducing overhead of memory region selection.</li>
      <li>For special memory accesses (I/O reads or non-RAM writes), dynamically generate minimal trampolines instead.</li>
      <li>For writes to MBC registers, directly use a routine for the specific register to remove range-checking overhead.</li>
      <li>Always pass valid timing info to memory accesses which may require it, removing the need for validity checks.</li>
      <li>Enable complex memory instructions to directly read/write RAM, such as bitwise operations and INC/DEC (HL).</li>
      <li>Allow absolute reads/writes to have variable-length implementations, for better performance with banked memory.</li>
      <li>Change stack bounds-checking to speed up close SP modifications (INC/DEC/ADD SP) and free up a register.</li>
      <li>Use inclusive bounds for the stack to avoid thrashing when touching the high edge of a memory region.</li>
      <li>Improve performance of return prediction by ignoring the stack offset unless the prediction misses.</li>
      <li>Improve performance of self-modifying code checks by using 24-bit comparisons.</li>
      <li>Improve performance of self-modifying JP instructions by using dynamic dispatch instead of recompiling.</li>
      <li>Expand the list of supported instructions in waitloop detection to reduce false negatives.</li>
      <li>Optimize ROM bank switching routine at ROM load time based on the ROM size, to eliminate redundant masking.</li>
      <li>Simplify MBC3 RTC bank switching by handling RTC updates immediately before register writes.</li>
    </ul>
  </li>
  <li>Refactor the PPU scheduler to speed up writes to STAT and LYC registers.
    <ul>
      <li>Predict future writes to the LYC register based on previous frames, to avoid excessive rescheduling.</li>
      <li>Remove post-vblank event cache to simplify all reschedules, and determine the event only when vblank is reached.</li>
    </ul>
  </li>
</ul>

<h3 id="fixed">Fixed</h3>
<ul>
  <li>Reduce SPI transfer clock to fix glitchy display on some calculator revisions.</li>
  <li>Increase Flash wait states for increased stability on some calculator revisions.</li>
  <li>Fix game screen corruption in the main menu when showing a confirmation dialog.</li>
  <li>Fix garbled character display when internal ROM title contains invalid characters.</li>
  <li>Fix corruption of a couple of pixels when restoring the home screen.</li>
  <li>Implement more accurate open-bus read behavior for disabled cartridge RAM.</li>
  <li>Implement correct mirroring behavior for MBC2 cartridge RAM.</li>
  <li>Fix reads past the end of ROM banks trimmed by the ROM converter.</li>
  <li>Fix conditions for the window trigger to include writes to LCDC or WY during hblank.</li>
  <li>Fix display of mid-frame sprite changes resulting from direct OAM writes.</li>
  <li>Allow NR30 writes to disable audio channel 3.</li>
  <li>Fix a scheduler edge case which could cause crashes in some games. Fixes Space Invaders (Japan).</li>
</ul>]]></content><author><name>Brendan Fletcher</name></author><category term="Releases" /><category term="Release" /><category term="Video" /><summary type="html"><![CDATA[After a long year of work, TI-Boy CE finally supports Game Boy Color! This involved an extensive rewrite of the memory system to support both GB and GBC memory maps, also allowing improved compatibility and performance. The color correction feature was also greatly improved from what was used in colorization for previous releases. The full change log is below.]]></summary></entry><entry><title type="html">TI-Boy CE GBC Preview #1 (Super Mario Bros. Deluxe and Magi Nation)</title><link href="https://calc84maniac.github.io/tiboyce/videos/2022/11/19/ti-boy-ce-gbc-preview-1.html" rel="alternate" type="text/html" title="TI-Boy CE GBC Preview #1 (Super Mario Bros. Deluxe and Magi Nation)" /><published>2022-11-19T00:00:00+00:00</published><updated>2022-11-19T00:00:00+00:00</updated><id>https://calc84maniac.github.io/tiboyce/videos/2022/11/19/ti-boy-ce-gbc-preview-1</id><content type="html" xml:base="https://calc84maniac.github.io/tiboyce/videos/2022/11/19/ti-boy-ce-gbc-preview-1.html"><![CDATA[<p>I took some new gameplay footage from the upcoming Game Boy Color support:</p>

<div class="video-container">
  <iframe class="video" src="https://www.youtube-nocookie.com/embed/zd2bvCtXtBE" frameborder="0" allowfullscreen=""></iframe>
</div>

<p>Development is mostly complete, while doing game testing to find remaining issues. As of this post, there’s a specific bug that causes random crashes in multiple games, but it’s been difficult to replicate it in a way that I can identify the problem. As soon as this bug is squashed, there won’t be much standing in the way of a release. Wish me luck!</p>]]></content><author><name>Brendan Fletcher</name></author><category term="Videos" /><category term="Preview" /><category term="Video" /><summary type="html"><![CDATA[I took some new gameplay footage from the upcoming Game Boy Color support:]]></summary></entry><entry><title type="html">TI-Boy CE GBC Preview</title><link href="https://calc84maniac.github.io/tiboyce/videos/2022/10/14/ti-boy-ce-gbc-preview.html" rel="alternate" type="text/html" title="TI-Boy CE GBC Preview" /><published>2022-10-14T00:00:00+00:00</published><updated>2022-10-14T00:00:00+00:00</updated><id>https://calc84maniac.github.io/tiboyce/videos/2022/10/14/ti-boy-ce-gbc-preview</id><content type="html" xml:base="https://calc84maniac.github.io/tiboyce/videos/2022/10/14/ti-boy-ce-gbc-preview.html"><![CDATA[<p>Hey all! I’ve been slowly but surely working on Game Boy Color support, and I’m approaching completion of all the features needed to run games.</p>

<p>There are a few remaining issues that I’ll save for after the next release, including:</p>

<ul>
  <li>Lack of support for mid-frame palette changes (used by some games to display more than 56 colors at a time)</li>
  <li>Poor performance in some games (though I’ll try to work on anything that’s easy to fix)</li>
  <li>Storage space limitations (most 4MB ROMs are not usable simply because they don’t fit in storage)</li>
</ul>

<p>My plan moving forward is to try out as many games as I can, and address any remaining stability issues. Hopefully, I can make a release in the near future.</p>

<p>In the meantime, <a href="https://github.com/adriweb">Adriweb</a> has recorded a video showcasing the opening cutscene of Pokemon Crystal in the emulator! Watch here:</p>

<div class="video-container">
  <iframe class="video" src="https://www.youtube-nocookie.com/embed/AXLLm5DT8sk" frameborder="0" allowfullscreen=""></iframe>
</div>

<p>I’ve also recorded some direct gameplay footage of Metal Gear Solid: Ghost Babel using <a href="https://ce-programming.github.io/CEmu/">CEmu</a>:</p>

<p><img alt="Metal Gear Solid gameplay" src="https://i.imgur.com/jRxJAi4.gif" /></p>]]></content><author><name>Brendan Fletcher</name></author><category term="Videos" /><category term="Preview" /><category term="Video" /><summary type="html"><![CDATA[Hey all! I’ve been slowly but surely working on Game Boy Color support, and I’m approaching completion of all the features needed to run games.]]></summary></entry><entry><title type="html">Alpha v0.2.1 Released</title><link href="https://calc84maniac.github.io/tiboyce/releases/2022/03/20/alpha-v0-2-1-released.html" rel="alternate" type="text/html" title="Alpha v0.2.1 Released" /><published>2022-03-20T00:00:00+00:00</published><updated>2022-03-20T00:00:00+00:00</updated><id>https://calc84maniac.github.io/tiboyce/releases/2022/03/20/alpha-v0-2-1-released</id><content type="html" xml:base="https://calc84maniac.github.io/tiboyce/releases/2022/03/20/alpha-v0-2-1-released.html"><![CDATA[<p>This is a minor release which uses newly discovered LCD documentation to eliminate diagonal screen tearing in fullscreen display mode.</p>

<p>Additionally, it lays groundwork for future Game Boy Color rendering by allowing 8 bits per pixel without doubling the framebuffer RAM usage.</p>

<p>In this release, I also leverage the 8-bit framebuffers to greatly improve performance when sprite palettes are changed mid-frame.</p>

<p>You can download the release from <a href="https://github.com/calc84maniac/tiboyce/releases">GitHub</a>.</p>

<h2 id="changelog">Changelog</h2>

<h3 id="changed">Changed</h3>
<ul>
  <li>Now using 8 bits per pixel in all display modes, eliminating code for special-casing 4-bit pixels.</li>
  <li>Emulator overlays are horizontally stretched in fullscreen mode, as required by the tearing fix.</li>
</ul>

<h3 id="fixed">Fixed</h3>
<ul>
  <li>Fixed diagonal screen tearing in fullscreen display modes by using VSYNC interface and interlaced scan.</li>
  <li>Greatly improved performance of frame rendering when sprite palettes are changed mid-frame.</li>
</ul>]]></content><author><name>Brendan Fletcher</name></author><category term="Releases" /><category term="Release" /><summary type="html"><![CDATA[This is a minor release which uses newly discovered LCD documentation to eliminate diagonal screen tearing in fullscreen display mode.]]></summary></entry><entry><title type="html">Alpha v0.2.0b Released</title><link href="https://calc84maniac.github.io/tiboyce/releases/2021/12/17/alpha-v0-2-0b-released.html" rel="alternate" type="text/html" title="Alpha v0.2.0b Released" /><published>2021-12-17T00:00:00+00:00</published><updated>2021-12-17T00:00:00+00:00</updated><id>https://calc84maniac.github.io/tiboyce/releases/2021/12/17/alpha-v0-2-0b-released</id><content type="html" xml:base="https://calc84maniac.github.io/tiboyce/releases/2021/12/17/alpha-v0-2-0b-released.html"><![CDATA[<p>This is a minor bugfix update to v0.2.0a, which fixes occasional freezes in some games like Donkey Kong Land as well as some potential runtime errors.</p>

<p>You can download the release from <a href="https://github.com/calc84maniac/tiboyce/releases">GitHub</a>.</p>

<h2 id="changelog">Changelog</h2>

<h3 id="fixed">Fixed</h3>
<ul>
  <li>Fix a game freeze occuring in certain conditions after a delayed EI is followed by a HALT. Fixes Donkey Kong Land.</li>
  <li>Fix a likely runtime error when a memory access instruction reads an I/O register and later reads other memory.</li>
</ul>]]></content><author><name>Brendan Fletcher</name></author><category term="Releases" /><category term="Release" /><summary type="html"><![CDATA[This is a minor bugfix update to v0.2.0a, which fixes occasional freezes in some games like Donkey Kong Land as well as some potential runtime errors.]]></summary></entry><entry><title type="html">Alpha v0.2.0a Released</title><link href="https://calc84maniac.github.io/tiboyce/releases/2021/12/09/alpha-v0-2-0a-released.html" rel="alternate" type="text/html" title="Alpha v0.2.0a Released" /><published>2021-12-09T00:00:00+00:00</published><updated>2021-12-09T00:00:00+00:00</updated><id>https://calc84maniac.github.io/tiboyce/releases/2021/12/09/alpha-v0-2-0a-released</id><content type="html" xml:base="https://calc84maniac.github.io/tiboyce/releases/2021/12/09/alpha-v0-2-0a-released.html"><![CDATA[<p>This is a minor bugfix update to v0.2.0 which fixes occasional runtime errors when loading auto save states for RTC cartridges.
This should help prevent loss of progress in games that have a clock, like Pokémon Gold and Silver.
As always though, it’s best practice not to rely entirely on auto save states, but to save in-game as well.</p>

<p>You can download the release from <a href="https://github.com/calc84maniac/tiboyce/releases">GitHub</a>.</p>

<h2 id="changelog">Changelog</h2>

<h3 id="fixed">Fixed</h3>
<ul>
  <li>Fix an intermittent code corruption when loading RTC save states.</li>
</ul>]]></content><author><name>Brendan Fletcher</name></author><category term="Releases" /><category term="Release" /><summary type="html"><![CDATA[This is a minor bugfix update to v0.2.0 which fixes occasional runtime errors when loading auto save states for RTC cartridges. This should help prevent loss of progress in games that have a clock, like Pokémon Gold and Silver. As always though, it’s best practice not to rely entirely on auto save states, but to save in-game as well.]]></summary></entry><entry><title type="html">Alpha v0.2.0 Released</title><link href="https://calc84maniac.github.io/tiboyce/releases/2021/12/07/alpha-v0-2-0-released.html" rel="alternate" type="text/html" title="Alpha v0.2.0 Released" /><published>2021-12-07T00:00:00+00:00</published><updated>2021-12-07T00:00:00+00:00</updated><id>https://calc84maniac.github.io/tiboyce/releases/2021/12/07/alpha-v0-2-0-released</id><content type="html" xml:base="https://calc84maniac.github.io/tiboyce/releases/2021/12/07/alpha-v0-2-0-released.html"><![CDATA[<p>As a culmination of the last two years of work, finally a new TI-Boy CE release is available!
The primary focus has been performance and accuracy improvements, fixing all reported game issues and improving playability of many games such as Pokémon Gen 2.
There are also some user experience improvements, such as per-game configuration support and improved colorization. The full change log is below.</p>

<p>You can download the release from <a href="https://github.com/calc84maniac/tiboyce/releases">GitHub</a>.</p>

<p>I’ve also recorded a comparison video showing the improvements to the opening cutscene of Pokémon Gold:</p>

<div class="video-container">
  <iframe class="video" src="https://www.youtube-nocookie.com/embed/lMxI3kxr9Ss" frameborder="0" allowfullscreen=""></iframe>
</div>

<p>The next goal for this project is to add Game Boy Color support, so please look forward to future updates!</p>

<h2 id="changelog">Changelog</h2>

<h3 id="added">Added</h3>
<ul>
  <li>Per-game configuration settings.</li>
  <li>Backlight adjustment hotkeys.</li>
  <li>Classic Game Boy palette option.</li>
  <li>Color adjustment option to more closely match a GBC screen when colorizing.</li>
  <li>Configurable confirmation dialog for loading and/or overwriting save states.</li>
  <li>Ability to delete save states and ROM files through the emulator menu.</li>
  <li>Ability to unmap most emulator hotkeys.</li>
</ul>

<h3 id="changed">Changed</h3>
<ul>
  <li>Darkened menu background color to improve text contrast.</li>
  <li>Load State option is no longer shown for state slots that do not exist.</li>
</ul>

<h3 id="fixed">Fixed</h3>
<ul>
  <li>Majorly improve performance in many games. Notably, Pokémon Gold and Silver now run at playable speeds.
    <ul>
      <li>Refactor cycle counting and event scheduling to speed up branches and avoid speculative event schedules.</li>
      <li>Bind cycle offsets to memory access instructions dynamically, rather than using a fixed-size cache.</li>
      <li>Make address mapping cache use bucket-based linear lookup instead of binary search.</li>
      <li>Speed up callstack caching by tracking aggregated memory bank deltas using the bank switches themselves.</li>
      <li>Create a dynamic PPU state machine that caches LY and STAT register values with expiration times.</li>
      <li>Use tables of overlapped pixel data to speed up Game Boy VRAM writes and native palette generation.</li>
      <li>Speed up VRAM caching up to 2x by deferring pixel generation until the second byte is written.</li>
      <li>Queue BGP writes to handle at end of frame, allowing the maximum number of scanlines to use native palettes.</li>
    </ul>
  </li>
  <li>Potentially fix white screen issue on Python models by reinitializing hardware on emulator start.</li>
  <li>Improve double-buffering logic, fixing occasional display of incomplete frames when frameskip is disabled.</li>
  <li>Implement bounds checking and full memory side effects on stack accesses. Fixes emulator glitches and crashes in many games.</li>
  <li>Implement MBC RAM protection. May help prevent cartridge save corruption in the case of game bugs or crashes.</li>
  <li>Prevent the emulator from freezing if a game turns the LCD on and off repeatedly.</li>
  <li>Add simple support for APU enable/disable and channel length counters.</li>
  <li>Implement delayed update of IME flag when an EI instruction is executed.</li>
  <li>Implement emulation of the CPU’s HALT bug. Fixes a game crash in The Smurfs.</li>
  <li>Support changing interrupt target during dispatch. Fixes a game crash in Pinball Deluxe.</li>
  <li>Implement STAT interrupt blocking behavior. Fixes a game crash in Joust.</li>
  <li>Support executing instructions overlapping memory regions. Fixes emulator crashes in FIFA 2000 and Hyper Lode Runner.</li>
  <li>Skip rendering the first frame after the LCD turns on to avoid glitch frames. Fixes a graphical glitch in Tetris Blast.</li>
  <li>Use correct window triggering behavior (window is active after LY==WY). Fixes a graphical glitch in Tetris Blast.</li>
  <li>Catch up rendering on VRAM writes. Fixes a graphical glitch in V-Rally Championship Edition.</li>
  <li>Support mid-frame sprite palette changes. Fixes a graphical glitch in V-Rally Championship Edition.</li>
  <li>Fix mid-frame sprite size changes. Fixes a graphical glitch in the dmg-acid2 test ROM.</li>
  <li>Improve accuracy when fast-forwarding LY-based waitloops, and add support for STAT-based waitloops.</li>
  <li>Emulate differing flag outputs of RLA/RRA/RLCA/RRCA/CCF. Fully passes Blargg’s cpu_instrs test ROM.</li>
  <li>Implement many timing and accuracy improvements for MBC, PPU, timer, serial, DMA, and RTC to pass test ROMs.</li>
</ul>]]></content><author><name>Brendan Fletcher</name></author><category term="Releases" /><category term="Release" /><category term="Video" /><summary type="html"><![CDATA[As a culmination of the last two years of work, finally a new TI-Boy CE release is available! The primary focus has been performance and accuracy improvements, fixing all reported game issues and improving playability of many games such as Pokémon Gen 2. There are also some user experience improvements, such as per-game configuration support and improved colorization. The full change log is below.]]></summary></entry><entry><title type="html">Just-In-Time Recompiling the Game Boy: Part 1 (Introduction)</title><link href="https://calc84maniac.github.io/tiboyce/design/2020/08/27/just-in-time-recompiling-the-game-boy-part-1-introduction.html" rel="alternate" type="text/html" title="Just-In-Time Recompiling the Game Boy: Part 1 (Introduction)" /><published>2020-08-27T00:00:00+00:00</published><updated>2020-08-27T00:00:00+00:00</updated><id>https://calc84maniac.github.io/tiboyce/design/2020/08/27/just-in-time-recompiling-the-game-boy-part-1-introduction</id><content type="html" xml:base="https://calc84maniac.github.io/tiboyce/design/2020/08/27/just-in-time-recompiling-the-game-boy-part-1-introduction.html"><![CDATA[<p>This will be a series of blog posts describing how JIT recompilation is used in the TI-Boy CE emulator.
A general familiarity with assembly languages, especially Game Boy or Z80, is recommended background for
reading.</p>

<p>Let’s start with some information about the platforms we’re working with, shall we?</p>

<h2 id="the-ti-84-ce-processor">The TI-84+ CE Processor</h2>

<p>The TI-84+ CE calculator runs on a Zilog eZ80 processor, which is a slightly more modern Z80
with a larger address space of 24 bits, compared to the Z80’s 16 bits. This allows all memory to be
directly addressed without memory paging. It is still classified as an 8-bit processor, however.
The eZ80 also has a Z80 backwards-compatibility mode, which allows Z80 code to execute within
a specified 16-bit subset of the address space. TI-Boy makes extensive use of this mode, partially
because it allows for smaller, more efficient code and also to simplify emulation of 16-bit
Game Boy operations.</p>

<p>The CPU is clocked to 48 MHz and the improved pipeline of the eZ80 allows for single-cycle execution
of many instructions. However, the TI-84+ CE has a slow memory bus which adds wait states to all
memory accesses, preventing the processor from reaching its full potential.
Specifically, 3 wait states are added to reads from RAM, and 1 wait state is added to writes.
Since the CPU has no instruction cache, the opcode fetches multiply most instruction cycle times
by a factor of 4. This makes the cycles per instruction closer to that of the original Z80 processor,
though 16-bit additions and address offsets are still considerably faster on the eZ80.</p>

<p>Note: The TI-84+ CE added significantly more wait states for reads from Flash memory, so execution
from Flash was less viable for speed-critical code. However, on newer CE hardware revisions, the Flash
chip was replaced with one that had extremely slow random access but relatively fast sequential access.
To compensate for this, TI added a transparent cache on top of the Flash memory region which would
sequentially load data into cache lines on miss. Only 2 wait states are added for cached reads,
which are even faster than RAM reads as long as the cache hits. TI-Boy has not yet been updated to
take advantage of this, though notably a large portion of the emulation cannot benefit from the cache
because JIT recompiled code must run from RAM. It does implicitly make reads from the Game Boy ROM
a bit faster, however.</p>

<h2 id="the-game-boy-processor">The Game Boy Processor</h2>

<p>The original Game Boy runs on a custom 8-bit Sharp CPU, which has many similarities to the Z80 processor
(though in some ways it’s closer to the Z80’s predecessor, the Intel 8080, in terms of feature set).
These similarities include a 16-bit address space, a mostly identical set of commonly used registers,
and mostly identical flag outputs from arithmetic and logical operations. Notably however, the Game Boy’s
processor is missing index registers, shadow registers, and sign/overflow/parity flags, as well as many of
Z80’s extended instructions like 16-bit subtraction and memory block operations. The Game Boy also has
no instructions to deal with an I/O port address space, opting instead to memory-map its I/O ports.</p>

<p>The Game Boy’s CPU is clocked to 4 MHz, but unlike the Z80, all of its machine cycles are exactly 4 clock
cycles long (whereas the Z80’s would vary from 1 to 6). So, it tends to be useful to count machine cycles
rather than clock cycles when emulating timing of the CPU, to reduce the range of the counter values.
For example, the number of clock cycles in a single video frame is 70224 clock cycles (which can’t fit
in a 16-bit counter) but only 17556 machine cycles (which can). From this point on, any mention of
Game Boy CPU cycles in these posts should be assumed to be machine cycles.</p>

<h2 id="why-jit-recompile">Why JIT Recompile?</h2>

<p>You may be wondering, why not just make a normal CPU interpreter? That’s what everyone does for
these old systems! Your processor is more than 10 times as powerful as the one you’re
emulating anyway, right? That’s the rule of thumb!</p>

<p>The simple answer: I’ve always really wanted to try this back on the Z80 with the original TI-84+,
but there just wasn’t enough memory or address space to reasonably do so. The TI-84+ CE has 256 KiB
of RAM plus 150 KiB of frame buffer RAM, which is more than decent enough to do JIT recompilation
without running over memory capacity every frame.</p>

<p>The technical answer: I sincerely believe an interpreter wouldn’t have given the performance I needed.
At its core, the eZ80 is still a legacy 8-bit system and doesn’t lend itself well to many operations
that seem trivial on more modern systems, like dispatching through a jump table (or at a higher level,
using a switch statement). The instruction pipeline makes this even worse than on the Z80, due to
needing to refill the pipeline after each dispatch. The overhead from the interpreter dispatch alone,
which I estimate at around 50 clock cycles per instruction in the best case, puts the emulator in a
dangerous area of not emulating the simplest common Game Boy instructions at full speed.</p>

<p>That’s not even considering the overhead of using CPU registers which would otherwise be available for
storing Game Boy registers, or emulating the memory map of the Game Boy (which can’t leverage
any native CE hardware due to its flat memory map, meaning even more switch statements or at least
table lookups). Cycle counting for accurate timing is also out of the question at that point. And forget
any future prospects of emulating the Game Boy Color, which can clock its processor twice as fast!</p>

<p>In comparison, JIT recompilation offers these runtime advantages for TI-Boy, among others:</p>

<ul>
  <li>One-time cost for translation – at least until running out of code memory, which should be infrequent.
Additional one-time costs (such as taking a jump for the first time) are deferred until needed.</li>
  <li>No register swapping between most instructions – all common Game Boy registers can be made
directly available in the main eZ80 registers, and CPU flags don’t need to be saved and restored.</li>
  <li>Fast emulation of instructions once recompiled – many common instructions run 12 times as fast
as they would on the Game Boy, and a few (such as 16-bit operations) even run 24 times as fast!
This is thanks to both the register availability mentioned above and the similarity of flag outputs.</li>
  <li>Coalesced cycle counting – allows determining before entering a recompiled block whether a time-based
event (e.g. a CPU interrupt) would occur at some point within that block, in most cases allowing the
emulator to avoid counting cycles for each individual instruction. When individual instructions do need
to be counted, their counts are dynamically coalesced as needed prior to entering the block.</li>
  <li>Abusing locality of reference – specializing individual memory access instructions based on their most
recently accessed memory region, greatly reducing the average overhead of memory map emulation.</li>
  <li>Identifying waitloop patterns – when Game Boy code is in a loop waiting for an external
change (either a hardware state change reflected by the value of an I/O port or the value of a RAM address
to be modified by an interrupt), the emulator can determine that it is safe to skip redundant executions
of the loop until the first time that external change can occur.</li>
</ul>

<p>However, there are also disadvantages to JIT, aside from the obvious aspect of increased code complexity:</p>

<ul>
  <li>Arbitrary jumps in Game Boy code can be slow – these cannot be resolved at recompilation time because
they cannot be known until each time they are executed. This includes both register-based jumps
and subroutine returns (for which the return address may have been modified or entirely fabricated).</li>
  <li>Precise timing for memory accesses and CPU interrupts becomes difficult – memory accesses must be able
to determine their relative cycle count within the recompiled block, and interrupts must be dispatchable
from an arbitrary point within any recompiled block. Additionally, some memory accesses to hardware I/O
may cause a hardware state change which needs to schedule a new interrupt within the currently executing
recompiled block.</li>
  <li>Dealing with memory mapping – code on the Game Boy can be mapped in and out of its address space, so it
is important to avoid making assumptions when emulating jumps between different areas of memory. Since
jumps on the Game Boy refer to only a 16-bit address and exclude any mapping information, it cannot
be assumed that the same jump instruction will always target the same recompiled code block, unless
both the jump and destination are within the same memory page (or the destination is in an area that
cannot be remapped). There are also issues when code is allowed to run straight from one memory area
to the next without jumping.</li>
  <li>Detecting and responding to self-modifying code – when Game Boy code is executed from RAM, there is
a possibility the code may be replaced at a later time, or even just one byte of the code may be modified.
At that point, the recompiled block does not match the current state of the code, which will cause
inaccuracies. This issue is compounded if Game Boy code modifies data within its own currently executing
block. Fortunately, most Game Boy code executes from ROM, but certain games do tricky things when copying
code to RAM.</li>
  <li>Testing can be inconsistent – the inherent extra context involved in JIT means that even if individual
instructions are confirmed to emulate properly in isolation, there are many different contexts in which
they can be executed, which can hide subtle bugs (not just in inputs/outputs, but also in timing).
One thing I do when stress testing the emulator is reduce the size of the code pool to force more
frequent recompilation, which greatly increases coverage of the different situations that can crop up.</li>
</ul>

<p>Some of these disadvantages have been partially or fully mitigated in TI-Boy through various strategies,
which will likely be discussed in future posts. Overall, I’ve found that the advantages have greatly
outweighed the disadvantages, allowing the emulator to make great strides in both performance and accuracy.</p>

<h2 id="what-about-static-recompilation">What about static recompilation?</h2>

<p>Since I get asked this question sometimes, static recompilation is not a suitable option for many reasons.
The biggest reason is that it’s not feasible to differentiate between code and data when not actively
running the game. Even if that were possible, it would also greatly increase the amount of storage space
taken by ROMs, and most likely cycle counting would have to be thrown out. Add to that the slowness of
executing from Flash memory on many calculators, and it’s a very suboptimal solution.</p>

<p>Next time, we’ll take a look at some of the JIT recompiler design details. Until then, happy coding!</p>]]></content><author><name>Brendan Fletcher</name></author><category term="Design" /><category term="Emulator Design" /><category term="JIT Recompiler" /><summary type="html"><![CDATA[This will be a series of blog posts describing how JIT recompilation is used in the TI-Boy CE emulator. A general familiarity with assembly languages, especially Game Boy or Z80, is recommended background for reading.]]></summary></entry></feed>