<?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="http://ste.vet/feed.xml" rel="self" type="application/atom+xml" /><link href="http://ste.vet/" rel="alternate" type="text/html" /><updated>2026-01-25T17:59:18+00:00</updated><id>http://ste.vet/feed.xml</id><title type="html">Steve Taylor</title><subtitle>A blog by Steve &quot;Schtee&quot; Taylor</subtitle><author><name>Steve Taylor</name></author><entry><title type="html">Windows x86 C++ Calling Conventions Cheat Sheet</title><link href="http://ste.vet/2026/01/25/windows-x86-calling-conventions.html" rel="alternate" type="text/html" title="Windows x86 C++ Calling Conventions Cheat Sheet" /><published>2026-01-25T00:00:00+00:00</published><updated>2026-01-25T00:00:00+00:00</updated><id>http://ste.vet/2026/01/25/windows-x86-calling-conventions</id><content type="html" xml:base="http://ste.vet/2026/01/25/windows-x86-calling-conventions.html"><![CDATA[<p>Noodling with reverse engineering Windows applications needs me to know these things but they refuse to stick in my brain, so I have put them in one place.</p>

<p>All stack parameters are passed in right-to-left order.</p>

<table>
  <thead>
    <tr>
      <th>Name</th>
      <th>Stack cleaned by</th>
      <th>Parameters</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">thiscall</code></td>
      <td>Callee</td>
      <td><code class="language-plaintext highlighter-rouge">this</code> in <code class="language-plaintext highlighter-rouge">ECX</code>, params on stack</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">fastcall</code></td>
      <td>Callee</td>
      <td>First in <code class="language-plaintext highlighter-rouge">ECX</code>, second in <code class="language-plaintext highlighter-rouge">EDX</code>, rest on stack</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">cdecl</code></td>
      <td>Caller</td>
      <td>Stack</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">stdcall</code></td>
      <td>Callee</td>
      <td>Stack</td>
    </tr>
  </tbody>
</table>]]></content><author><name>Steve Taylor</name></author><summary type="html"><![CDATA[Noodling with reverse engineering Windows applications needs me to know these things but they refuse to stick in my brain, so I have put them in one place.]]></summary></entry><entry><title type="html">PortMaster Releases RSS Feed</title><link href="http://ste.vet/2026/01/04/portmaster-releases-rss-feed.html" rel="alternate" type="text/html" title="PortMaster Releases RSS Feed" /><published>2026-01-04T00:00:00+00:00</published><updated>2026-01-04T00:00:00+00:00</updated><id>http://ste.vet/2026/01/04/portmaster-releases-rss-feed</id><content type="html" xml:base="http://ste.vet/2026/01/04/portmaster-releases-rss-feed.html"><![CDATA[<p>I love me an open handheld games console and I love playing games on them which were never intended to be, so I love <a href="https://portmaster.games/faq.html#what-is-portmaster">PortMaster</a>. I don’t like <em>having to do stuff</em>, such as keeping tabs on which games have been ported. So I threw together <a href="https://github.com/Schtee/portmaster-rss">a little project</a> to scrape the <a href="https://github.com/PortsMaster/PortMaster-Info/blob/main/ports.json">PortMaster releases JSON</a> and generate an RSS feed I (and you) can subscribe to and keep track of releases as they happen. The feed lives here <a href="https://ste.vet/portmaster-rss/feed.xml">https://ste.vet/portmaster-rss/feed.xml</a> and is updated at 2:22 (🤷) every day.</p>]]></content><author><name>Steve Taylor</name></author><summary type="html"><![CDATA[I love me an open handheld games console and I love playing games on them which were never intended to be, so I love PortMaster. I don’t like having to do stuff, such as keeping tabs on which games have been ported. So I threw together a little project to scrape the PortMaster releases JSON and generate an RSS feed I (and you) can subscribe to and keep track of releases as they happen. The feed lives here https://ste.vet/portmaster-rss/feed.xml and is updated at 2:22 (🤷) every day.]]></summary></entry><entry><title type="html">Ultima IX: Ascension Asset Archaeology</title><link href="http://ste.vet/2026/01/02/u9-archaeology.html" rel="alternate" type="text/html" title="Ultima IX: Ascension Asset Archaeology" /><published>2026-01-02T00:00:00+00:00</published><updated>2026-01-02T00:00:00+00:00</updated><id>http://ste.vet/2026/01/02/u9-archaeology</id><content type="html" xml:base="http://ste.vet/2026/01/02/u9-archaeology.html"><![CDATA[<p>I found myself looking at screenshots of the early development of Ultima IX. <a href="https://wiki.ultimacodex.com/wiki/File:U9Editor.jpg">This one in particular caught my eye</a> - seeing these dev tools from the 90s got me wondering if there was any trace of this editor, or this original isometric version of Ultima 9, in the very different game that eventually shipped in 1999.</p>

<p><img src="/images/2026-01-02-u9-archaeology/U9Editor.jpg" alt="A screenshot of a map editor for an early iteration of Ultima IX: Ascension" /></p>

<p>I couldn’t find any modern-Windows-compatible tools for viewing the U9 asset files, but I found some pretty <a href="https://wiki.ultimacodex.com/wiki/Ultima_IX_internal_formats">extensive documentation</a>, so I figured I’d just roll my own. You can now <a href="https://github.com/Schtee/u9ed">find it on Github</a>.</p>

<p>After a lot of scrolling through images, I found these:</p>

<div class="inline">

  <p><img src="/images/2026-01-02-u9-archaeology/EditorA.png" alt="Editor tool palette: A" />
<img src="/images/2026-01-02-u9-archaeology/EditorABYSS.png" alt="Editor tool palette: Abyss" />
<img src="/images/2026-01-02-u9-archaeology/EditorAMBROSIA.png" alt="Editor tool palette: Ambrosia" />
<img src="/images/2026-01-02-u9-archaeology/EditorANGRYDEAD.png" alt="Editor tool palette: Angry dead" />
<img src="/images/2026-01-02-u9-archaeology/EditorANIMA.png" alt="Editor tool palette: Animals" />
<img src="/images/2026-01-02-u9-archaeology/EditorARMOR.png" alt="Editor tool palette: Armor" />
<img src="/images/2026-01-02-u9-archaeology/EditorASYLUM.png" alt="Editor tool palette: Asylum" />
<img src="/images/2026-01-02-u9-archaeology/EditorB.png" alt="Editor tool palette: B" />
<img src="/images/2026-01-02-u9-archaeology/EditorBLDGS.png" alt="Editor tool palette: Buildings" />
<img src="/images/2026-01-02-u9-archaeology/EditorBRITAIN.png" alt="Editor tool palette: Britain" />
<img src="/images/2026-01-02-u9-archaeology/EditorBUCCANEERSDEN.png" alt="Editor tool palette: Buccaneer's Den" />
<img src="/images/2026-01-02-u9-archaeology/EditorC.png" alt="Editor tool palette: C" />
<img src="/images/2026-01-02-u9-archaeology/EditorCAVERNS.png" alt="Editor tool palette: Caverns" />
<img src="/images/2026-01-02-u9-archaeology/EditorCITADL.png" alt="Editor tool palette: Citadel" />
<img src="/images/2026-01-02-u9-archaeology/EditorCITIES.png" alt="Editor tool palette: Cities" />
<img src="/images/2026-01-02-u9-archaeology/EditorCLOTH.png" alt="Editor tool palette: Clothing" />
<img src="/images/2026-01-02-u9-archaeology/EditorCONTA.png" alt="Editor tool palette: Containers" />
<img src="/images/2026-01-02-u9-archaeology/EditorCOURT.png" alt="Editor tool palette: Court" />
<img src="/images/2026-01-02-u9-archaeology/EditorCOVE.png" alt="Editor tool palette: COVE" />
<img src="/images/2026-01-02-u9-archaeology/EditorCOVETOUS.png" alt="Editor tool palette: COVETOUS" />
<img src="/images/2026-01-02-u9-archaeology/EditorD.png" alt="Editor tool palette: D" />
<img src="/images/2026-01-02-u9-archaeology/EditorDECIET.png" alt="Editor tool palette: Deceit" />
<img src="/images/2026-01-02-u9-archaeology/EditorDESPISE.png" alt="Editor tool palette: Despise" />
<img src="/images/2026-01-02-u9-archaeology/EditorDESTARD.png" alt="Editor tool palette: Destard" />
<img src="/images/2026-01-02-u9-archaeology/EditorDOORS.png" alt="Editor tool palette: Doors" />
<img src="/images/2026-01-02-u9-archaeology/EditorDUNGEONS.png" alt="Editor tool palette: Dungeons" />
<img src="/images/2026-01-02-u9-archaeology/EditorE.png" alt="Editor tool palette: E" />
<img src="/images/2026-01-02-u9-archaeology/EditorEBONWOOD.png" alt="Editor tool palette: Ebonwood" />
<img src="/images/2026-01-02-u9-archaeology/EditorETHERIALVOID.png" alt="Editor tool palette: Etherial Void" />
<img src="/images/2026-01-02-u9-archaeology/EditorF.png" alt="Editor tool palette: F" />
<img src="/images/2026-01-02-u9-archaeology/EditorFAUNA.png" alt="Editor tool palette: Fauna" />
<img src="/images/2026-01-02-u9-archaeology/EditorFLORA.png" alt="Editor tool palette: Flora" />
<img src="/images/2026-01-02-u9-archaeology/EditorFOOD.png" alt="Editor tool palette: Food" />
<img src="/images/2026-01-02-u9-archaeology/EditorFURNI.png" alt="Editor tool palette: Furniture" />
<img src="/images/2026-01-02-u9-archaeology/EditorG.png" alt="Editor tool palette: G" />
<img src="/images/2026-01-02-u9-archaeology/EditorGRAVE.png" alt="Editor tool palette: Grave" />
<img src="/images/2026-01-02-u9-archaeology/EditorGYPSY.png" alt="Editor tool palette: Gypsy" />
<img src="/images/2026-01-02-u9-archaeology/EditorH.png" alt="Editor tool palette: H" />
<img src="/images/2026-01-02-u9-archaeology/EditorHOUSE.png" alt="Editor tool palette: House" />
<img src="/images/2026-01-02-u9-archaeology/EditorHYTHLOTH.png" alt="Editor tool palette: Hythloth" />
<img src="/images/2026-01-02-u9-archaeology/EditorI.png" alt="Editor tool palette: I" />
<img src="/images/2026-01-02-u9-archaeology/EditorITEMS.png" alt="Editor tool palette: Items" />
<img src="/images/2026-01-02-u9-archaeology/EditorJ.png" alt="Editor tool palette: J" />
<img src="/images/2026-01-02-u9-archaeology/EditorK.png" alt="Editor tool palette: K" />
<img src="/images/2026-01-02-u9-archaeology/EditorL.png" alt="Editor tool palette: L" />
<img src="/images/2026-01-02-u9-archaeology/EditorM.png" alt="Editor tool palette: M" />
<img src="/images/2026-01-02-u9-archaeology/EditorMACHI.png" alt="Editor tool palette: Machines" />
<img src="/images/2026-01-02-u9-archaeology/EditorMAGIC.png" alt="Editor tool palette: Magic" />
<img src="/images/2026-01-02-u9-archaeology/EditorMINES.png" alt="Editor tool palette: Mines" />
<img src="/images/2026-01-02-u9-archaeology/EditorMISC.png" alt="Editor tool palette: Misc" />
<img src="/images/2026-01-02-u9-archaeology/EditorMONST.png" alt="Editor tool palette: Monsters" />
<img src="/images/2026-01-02-u9-archaeology/EditorMOONGLOW.png" alt="Editor tool palette: Moonglow" />
<img src="/images/2026-01-02-u9-archaeology/EditorN.png" alt="Editor tool palette: N" />
<img src="/images/2026-01-02-u9-archaeology/EditorNEWMAGINCIA.png" alt="Editor tool palette: New Magincia" />
<img src="/images/2026-01-02-u9-archaeology/EditorO.png" alt="Editor tool palette: O" />
<img src="/images/2026-01-02-u9-archaeology/EditorP.png" alt="Editor tool palette: P" />
<img src="/images/2026-01-02-u9-archaeology/EditorPAWS.png" alt="Editor tool palette: Paws" />
<img src="/images/2026-01-02-u9-archaeology/EditorPEOPL.png" alt="Editor tool palette: People" />
<img src="/images/2026-01-02-u9-archaeology/EditorPROVI.png" alt="Editor tool palette: Provisions" />
<img src="/images/2026-01-02-u9-archaeology/EditorROCKS.png" alt="Editor tool palette: Rocks" />
<img src="/images/2026-01-02-u9-archaeology/EditorSCARABRAE.png" alt="Editor tool palette: Scara Brae" />
<img src="/images/2026-01-02-u9-archaeology/EditorSEWERS.png" alt="Editor tool palette: Sewers" />
<img src="/images/2026-01-02-u9-archaeology/EditorSHAME.png" alt="Editor tool palette: Shame" />
<img src="/images/2026-01-02-u9-archaeology/EditorSHRINES.png" alt="Editor tool palette: Shrines" />
<img src="/images/2026-01-02-u9-archaeology/EditorSITES.png" alt="Editor tool palette: Sites" />
<img src="/images/2026-01-02-u9-archaeology/EditorSTONEGATE.png" alt="Editor tool palette: Stonegate" />
<img src="/images/2026-01-02-u9-archaeology/EditorSTONEHENGE.png" alt="Editor tool palette: Stonehenge" />
<img src="/images/2026-01-02-u9-archaeology/EditorSUTEKSISLE.png" alt="Editor tool palette: Sutek's Isle" />
<img src="/images/2026-01-02-u9-archaeology/EditorTOOLS.png" alt="Editor tool palette: Tools" />
<img src="/images/2026-01-02-u9-archaeology/EditorTOWEROFEXULTATION.png" alt="Editor tool palette: Tower Of Exultation" />
<img src="/images/2026-01-02-u9-archaeology/EditorTRINSIC.png" alt="Editor tool palette: Trinsic" />
<img src="/images/2026-01-02-u9-archaeology/EditorTROLLKING.png" alt="Editor tool palette: Troll King" />
<img src="/images/2026-01-02-u9-archaeology/EditorUNDER.png" alt="Editor tool palette: Underground" />
<img src="/images/2026-01-02-u9-archaeology/EditorVALORIA.png" alt="Editor tool palette: Valoria" />
<img src="/images/2026-01-02-u9-archaeology/EditorVEHIC.png" alt="Editor tool palette: Vehicles" />
<img src="/images/2026-01-02-u9-archaeology/EditorWATER.png" alt="Editor tool palette: Water" />
<img src="/images/2026-01-02-u9-archaeology/EditorWEAPO.png" alt="Editor tool palette: Weapons" />
<img src="/images/2026-01-02-u9-archaeology/EditorWORK.png" alt="Editor tool palette: Work in progress(/?)" />
<img src="/images/2026-01-02-u9-archaeology/EditorWRONG.png" alt="Editor tool palette: Wrong" /></p>

</div>

<p>I didn’t find anything more from the editor in the assets or from poking around in the executable but it’s neat to find traces of the developer tools tucked away in the game files. I did find these terrain tiles, which have a suspiciously similar noisy dithering to the old screenshots, and a green marbley tileset that looks to date back to then:</p>

<div class="inline">

  <p><img src="/images/2026-01-02-u9-archaeology/OldGrassTile.png" alt="A grass tile featuring dithering" />
<img src="/images/2026-01-02-u9-archaeology/OldWaterTile.png" alt="A water tile featuring dithering" />
<img src="/images/2026-01-02-u9-archaeology/TilesTile.png" alt="A tile consisting of green marble tiles" /></p>

  <p>Compare with:</p>

  <p><a href="https://wiki.ultimacodex.com/wiki/File:Coveiso.jpg"><img src="/images/2026-01-02-u9-archaeology/Coveiso.png" alt="A screenshot featuring grass with a dithering pattern" /></a>
<a href="https://wiki.ultimacodex.com/wiki/File:Covebrid.jpg"><img src="/images/2026-01-02-u9-archaeology/Covebrid.png" alt="A screenshot featuring water with a dithering pattern" /></a>
<a href="https://wiki.ultimacodex.com/wiki/File:U91palace.jpg"><img src="/images/2026-01-02-u9-archaeology/U91palace.png" alt="A screenshot featuring green marble tiles" /></a></p>

</div>

<p>The final interesting find was this character art, featuring Teenage Mutant Ninja Turtle-esque green, four-armed alien folk wielding swords, spears and what looks to be an actual gun. I would love to know more about this - as far as I can tell it doesn’t feature in the game and it’s not buried alongside other assets that explain it.</p>

<p><img src="/images/2026-01-02-u9-archaeology/AlienConceptArt.png" alt="An image of two four-armed alien folk" /></p>

<p>If you’re interested in having a poke around these files, you can check out my <a href="https://github.com/Schtee/u9ed">projecet on Github</a>, or I later found that <a href="http://jfregnault.free.fr/Ultima9/Ultima9.htm">this person</a> has already dumped the images online. I shall now resume my wait for the digital playground for the new millennium.</p>

<div class="inline">

  <p><img src="/images/2026-01-02-u9-archaeology/UO2-1.png" alt="A frame from the Ultima Online 2 trailer in Ultima IX of a CRT PC monitor with white text reading &quot;enter the playground for the new millennium&quot;" />
<img src="/images/2026-01-02-u9-archaeology/UO2-2.png" alt="A frame from the Ultima Online 2 trailer in Ultima IX of a CRT PC monitor with text reading &quot;ultima online 2 coming in 2000&quot;" /></p>

</div>]]></content><author><name>Steve Taylor</name></author><summary type="html"><![CDATA[I found myself looking at screenshots of the early development of Ultima IX. This one in particular caught my eye - seeing these dev tools from the 90s got me wondering if there was any trace of this editor, or this original isometric version of Ultima 9, in the very different game that eventually shipped in 1999.]]></summary></entry><entry><title type="html">UltraHLE Technical Information</title><link href="http://ste.vet/2025/12/29/ultrahle-tech-info.html" rel="alternate" type="text/html" title="UltraHLE Technical Information" /><published>2025-12-29T00:00:00+00:00</published><updated>2025-12-29T00:00:00+00:00</updated><id>http://ste.vet/2025/12/29/ultrahle-tech-info</id><content type="html" xml:base="http://ste.vet/2025/12/29/ultrahle-tech-info.html"><![CDATA[<p>I recently stumbled on <a href="https://www.reddit.com/r/emulation/comments/dhr47f/comment/f3qy9je/">this comment on a Reddit post</a> about MVG’s <a href="https://en.wikipedia.org/wiki/UltraHLE">UltraHLE</a> retrospective. They didn’t link to the source they were quoting and no amount of Googling gave me what I was looking for. Many clicks around archive.org eventually gave me <a href="https://web.archive.org/web/19990508162905/http://www.emuunlim.com/UltraHLE/techinfo.htm">the goods</a>. Turns out the comment containted all the text from the page, but always good to have the source. While very much not exhaustive, the page provides an interesting peek at the thinking behind an amazing technical achievement, emulating <em>at least some games</em> from a 3D-focused console during its lifespan, at a time when consumer 3D cards were relatively novel (the Voodoo2 was released the year before UltraHLE).</p>

<p>Some quotes:</p>

<blockquote>
  <p>There has been no attempt to translate the RSP code, since it works so closely with the hardware and uses integer arithmetic. Instead the C-code can use floating point, which is easier and faster on the PC. This means the results are not 100% same as those on the real console, but on the plus side things are a lot faster, and often results look better (for example increasing game resolution is trivial).</p>
</blockquote>

<blockquote>
  <p>What helps us, is that the games don’t use the CPU to its full extent. Practically no 64-bit code is used, and virtual memory usage is limited.</p>
</blockquote>

<blockquote>
  <p>On a Pentium II the R4300 emulation speed is now close enough to allow real time operation on many games and demos. Of course the PC has to do the work of the Reality Co-Processor too, so that will slow things down. But PCs are getting faster, and a 450Mhz Pentium II should run at excellent speed.</p>
</blockquote>

<details>
  <summary>Expand for the full text!</summary>

  <h3 id="ultrahle-architecture">UltraHLE Architecture</h3>

  <p>If you are interested in programming or emulators in general, this text is for you. The purpose is the explain the basic architecture behind UltraHLE and tell how it differs from many other emulators.</p>

  <p>The HLE in the name pretty much sums it up. It stands for High Level Emulation. Instead of trying to emulate the hardware as closely as possible and supporting low level operations, the approach is just the opposite: Emulate as little as possible and try to detect operatios as early as possible, and emulate them using optimized C-code.</p>

  <p>For example there is no boot rom and even boot code in rom images is ignored. Common operating system routines like interrupt adjustments are intercepted and ignored. When dealing with graphics and sound, the abstraction level is high (display lists and sound lists). CPU and DMA emulation is at a lower level, but still uses some tricks to detect common operations and perform them more efficiently.</p>

  <p>This probably wouldn’t work on an older console, where low level programming and hand tuned assembly were the rule. But the Nintendo64 is quite different. Most of the code is written in high level C eliminating need for 100% exact CPU emulation (so things like exceptions or virtual memory can be emulated only approximately). Graphics and sound both use command lists, that are reasonably standard between different games.</p>

  <h3 id="graphics-and-sound">Graphics and Sound</h3>
  <p>On the real console display and sound lists are executed using the Reality Signal Processor (RSP) which executes code from the rom image. It is a vector processor with operations specifically designed for fast geometry and audio, and as such is difficult to emulate efficiently. In UltraHLE the lists are interpreted with C-code, which has been created by studying the lists games generate. There has been no attempt to translate the RSP code, since it works so closely with the hardware and uses integer arithmetic. Instead the C-code can use floating point, which is easier and faster on the PC. This means the results are not 100% same as those on the real console, but on the plus side things are a lot faster, and often results look better (for example increasing game resolution is trivial).</p>

  <p>It is also possible to do things the original code doesn’t do. For example, on the N64 loading new textures is a rather fast process, and all textures are loaded each frame. On the PC 3D-architectures, texture loading is generally a slower operation. The solution is to cache textures on the PC side and eliminate all unnecessary loads. This give a big performance boost and practically all textures can be cached, since PC has so much more texture memory.</p>

  <p>Other display optimizations include removal of hidden triangles, extra matrix loads, unused mode changes and the like. Since texture and mode changes are more expensive on the PC, it makes sense to do extra geometry processing to eliminate as many changes as possible. Triangles are also collected into larger groups (sorted by mode) to allow faster rendering.</p>

  <p>Finally, the graphics emulation has to cope with all the different rendering modes of the N64. The RCP contains a very configurable 3D-rendering unit which supports many modes that are impossible to emulate directly on 3DFX, even when using glide. UltraHLE performs pretty complex mode conversion to find the best PC-modes for each N64-mode. Things that the N64 does in a single pass are converted to 1-3 passes on the PC, depeneding on mode complexity. The modes are cached like textures, so the relatively slow mode decoding process does not slow things in practice.</p>

  <p>Since there is so little information on Nintendo64 hardware, emulating sound and graphics on hardware level would probably have been extremely difficult (unless one had access to all N64 documentation, which we didn’t). So in a way this high level approach was pretty much the only way to proceed. But it was a good way nevertheless, as the results show.</p>

  <h3 id="cpu-emulation">CPU Emulation</h3>
  <p>The high level approach doesn’t extend that well to CPU emulation, but luckily the CPU is a standard MIPS R4300 with excellent documentation available. So it’s just a matter of following instructions, and then making it fast (which is the hard part). What helps us, is that the games don’t use the CPU to its full extent. Practically no 64-bit code is used, and virtual memory usage is limited.</p>

  <p>Initially the CPU was emulated in C like in most emulators to get things started, but that was way too slow. The next logical step also was to compile MIPS code into Intel code. All instruction decoding overhead is eliminated, but it still takes multiple Intel instructions to emulate a MIPS instruction (since MIPS has more registers and because the Intel FPU implementation just plain sucks). Also things like branches are not that easy to handle. The speedup was about 5-10x compared to C-emulation.</p>

  <p>The next step was to add optimizations to the compiler. By allocating MIPS registers temporarily into the few Intel registers, many memory accesses can be eliminated. This allows compiling small connected instruction groups into about 2 Intel ops for each MIPS ops ratio. Nearby memory accesses with similar addresses can be simplified by caching the base addresses in registers. It is also possible to replace some RISC instruction pairs with single CISC instructions. Since our target (Pentium II) does out of order execution, it was not necessary to reorder instructions, which made optimizations a lot easier. These optimizations increased speed 2x.</p>

  <p>On a Pentium II the R4300 emulation speed is now close enough to allow real time operation on many games and demos. Of course the PC has to do the work of the Reality Co-Processor too, so that will slow things down. But PCs are getting faster, and a 450Mhz Pentium II should run at excellent speed. And there are probably more possible optimizations, just waiting to be done.</p>

  <h3 id="compatibility">Compatibility</h3>
  <p>UltraHLE is a very unusual emulator. It doesn’t run many titles (yet), but what it runs, it runs well. This is because the high level emulation routines either work (if what they assume of the game is corrent) or they fail (if the game uses a totally different display list format, for example).</p>

  <p>The goal of UltraHLE is not to run as many titles as possible. It is to run the best titles as well as possible. And looking at the current compatibility list, this is exactly what UltraHLE does. Compatibility will no doubt improve in the future, but the emphasis will still be on quality instead of quantity.</p>
</details>]]></content><author><name>Steve Taylor</name></author><summary type="html"><![CDATA[I recently stumbled on this comment on a Reddit post about MVG’s UltraHLE retrospective. They didn’t link to the source they were quoting and no amount of Googling gave me what I was looking for. Many clicks around archive.org eventually gave me the goods. Turns out the comment containted all the text from the page, but always good to have the source. While very much not exhaustive, the page provides an interesting peek at the thinking behind an amazing technical achievement, emulating at least some games from a 3D-focused console during its lifespan, at a time when consumer 3D cards were relatively novel (the Voodoo2 was released the year before UltraHLE).]]></summary></entry><entry><title type="html">Omnivore Alternatives</title><link href="http://ste.vet/2024/11/04/omnivore-alternatives.html" rel="alternate" type="text/html" title="Omnivore Alternatives" /><published>2024-11-04T00:00:00+00:00</published><updated>2024-11-04T00:00:00+00:00</updated><id>http://ste.vet/2024/11/04/omnivore-alternatives</id><content type="html" xml:base="http://ste.vet/2024/11/04/omnivore-alternatives.html"><![CDATA[<blockquote>
  <p><a href="/2023/10/12/omnivore.html">As I’m not currently self-hosting there is every chance the hosted service may go away or my data get lost</a></p>
</blockquote>

<p>It is with great prescience that I sadly relay news that Omnivore is <a href="https://blog.omnivore.app/p/details-on-omnivore-shutting-down">going away</a>:</p>

<blockquote>
  <p>We’re excited to share that Omnivore is joining forces with [some AI thing] […] All Omnivore users will be able to export their information from the service through November 15 2024, after which all information will be deleted.</p>
</blockquote>

<p>So I’ve gone back to comparing self-hostable alternatives to avoid this happening again. My main criteria are:</p>
<ul>
  <li>easily self-hostable</li>
  <li>a read-it-later service for articles, not just a bookmark manager</li>
  <li>Nice to have:
    <ul>
      <li>highlights/annotations</li>
      <li>a mobile app for offline viewing and OS-level sharing of links</li>
    </ul>
  </li>
</ul>

<p>Here are the options I’ve found:</p>

<table>
  <thead>
    <tr>
      <th>Name</th>
      <th>Highlights/annotations</th>
      <th>Mobile app</th>
      <th>Notes</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><a href="https://linkwarden.app/">Linkwarden</a></td>
      <td>❌</td>
      <td>❌</td>
      <td><a href="https://demo.linkwarden.app/">Demo instance</a>. General UX is actually pretty nice. Seems to be <em>primarily</em> a bookmark management service. Does save archived snapshots of pages in various formats, but these are a little fiddly to navigate to - the default interaction is to just open the live link</td>
    </tr>
    <tr>
      <td><a href="https://github.com/wallabag/wallabag">wallabag</a></td>
      <td>✅</td>
      <td>✅</td>
      <td>I was using wallabag for a while before moving to Omnivore. The feature set is perfect, but both the web interface and mobile app feel a little clunky and the Android context menu to annotate/highlight doesn’t behave consistently</td>
    </tr>
    <tr>
      <td><a href="https://readeck.org/en/">Readeck</a></td>
      <td>✅</td>
      <td>❌</td>
      <td>Despite not having a native mobile app, there’s a lot of great stuff here. The UX is clean and simple (quite similar to Omnivore’s), it’ll grab video transcripts where available, it can export to epub and there’s a browser extension (which works on Firefox Android) to send the contents of weird JavaScript festivals that it can’t scrape directly from the HTML alone. As a bonus, the dev <a href="https://codeberg.org/readeck/readeck/pulls/270">knocked together an importer from Omnivore right after they announced they were shutting down</a></td>
    </tr>
  </tbody>
</table>

<p>Wallabag ticks all the boxes, but Readeck feels so much nicer to work with…it’s just not going to be with me on the tube. Between the browser plugin and some <a href="https://http-shortcuts.rmy.ch/">HTTP Shortcuts</a> workflow, sharing to the service is covered. It’s really just the offline syncing I’m missing. I’ll be sticking with Readeck for a while, and ultimately if the  lack of apps becomes a deal breaker, I’m sure I’ll be able to move everything to wallabag easily enough.</p>

<p>I’d really love someone to fork the open source Omnivore <a href="https://github.com/omnivore-app/omnivore">mobile apps</a> and make them talk Readeck instead. Maybe if I can find some time…</p>]]></content><author><name>Steve Taylor</name></author><summary type="html"><![CDATA[As I’m not currently self-hosting there is every chance the hosted service may go away or my data get lost]]></summary></entry><entry><title type="html">2024-10-06 Sunday Links</title><link href="http://ste.vet/2024/10/06/sunday-links.html" rel="alternate" type="text/html" title="2024-10-06 Sunday Links" /><published>2024-10-06T00:00:00+00:00</published><updated>2024-10-06T00:00:00+00:00</updated><id>http://ste.vet/2024/10/06/sunday-links</id><content type="html" xml:base="http://ste.vet/2024/10/06/sunday-links.html"><![CDATA[<ul>
  <li><a href="https://aschmelyun.com/blog/getting-my-daily-news-from-a-dot-matrix-printer/">Getting my daily news from a dot matrix printer - Andrew Schmelyun</a> via <a href="https://werd.io/2024/getting-my-daily-news-from-a-dot-matrix-printer">Ben Werdmuller</a> - we had (old) printers like this in the home growing up and there would be something very nostalgic about reading a daily roundup on dot matrix paper</li>
  <li><a href="https://www.gamingonlinux.com/2024/10/doom-ported-to-run-almost-entirely-on-amd-gpus/">DOOM ported to run almost entirely on AMD GPUs - GamingOnLinux</a> - don’t waste your spare GPUs mining crypto or generating derivative artwork- play Doom instead! More importantly, today I learnt that LLVM can compile C++ to run on the GPU, via <a href="https://llvm.org/docs/AMDGPUUsage.html">AMDGPU</a> and <a href="https://llvm.org/docs/NVPTXUsage.html">NVPTX</a> backends.</li>
  <li><a href="https://brainbaking.com/post/2024/09/experiencing-old-games-in-new-eras/">Experiencing Old Games In New Eras - Brain Baking</a> - thoughts on how even playing games on original hardware can’t recreate the original experience
    <blockquote>
      <p>even if you manage to grab a few other nerdy friends that cling onto their original hardware like I do. There’s nothing left to explore: everything is available on the internet; on GameFAQs, Wikis, fan pages, disassembly articles, generators</p>
    </blockquote>
  </li>
  <li><a href="https://jesse.tg/projects/ruffle">Ruffle for Libretro - Jesse Makes Things</a> - I stumbled upon a RetroArch/libretro core for Adobe/Macromedia Flash. I’d love to get this building for ARM handhelds. Maybe I shall try!</li>
</ul>]]></content><author><name>Steve Taylor</name></author><summary type="html"><![CDATA[Getting my daily news from a dot matrix printer - Andrew Schmelyun via Ben Werdmuller - we had (old) printers like this in the home growing up and there would be something very nostalgic about reading a daily roundup on dot matrix paper DOOM ported to run almost entirely on AMD GPUs - GamingOnLinux - don’t waste your spare GPUs mining crypto or generating derivative artwork- play Doom instead! More importantly, today I learnt that LLVM can compile C++ to run on the GPU, via AMDGPU and NVPTX backends. Experiencing Old Games In New Eras - Brain Baking - thoughts on how even playing games on original hardware can’t recreate the original experience even if you manage to grab a few other nerdy friends that cling onto their original hardware like I do. There’s nothing left to explore: everything is available on the internet; on GameFAQs, Wikis, fan pages, disassembly articles, generators Ruffle for Libretro - Jesse Makes Things - I stumbled upon a RetroArch/libretro core for Adobe/Macromedia Flash. I’d love to get this building for ARM handhelds. Maybe I shall try!]]></summary></entry><entry><title type="html">2024-09-29 Sunday Links</title><link href="http://ste.vet/2024/09/29/sunday-links.html" rel="alternate" type="text/html" title="2024-09-29 Sunday Links" /><published>2024-09-29T00:00:00+00:00</published><updated>2024-09-29T00:00:00+00:00</updated><id>http://ste.vet/2024/09/29/sunday-links</id><content type="html" xml:base="http://ste.vet/2024/09/29/sunday-links.html"><![CDATA[<ul>
  <li><a href="https://alistairshepherd.uk/writing/selling-web-project/">Selling a small front-end web project — what I learned - Alistair Shepherd</a> - a nice writeup on the process and experience of selling a small website, <em>My Top for Spotify</em></li>
  <li><a href="https://thehistoryoftheweb.com/its-lists-all-the-way-down/">It’s Lists All the Way Down - The History of the Web</a> - the wolrd wide web is lists</li>
</ul>

<blockquote>
  <p>lists have been really foundational for the transmission of information. Writing in New York Mag, Kyle Chakra explores how Wikipedia, in some ways a logical extension of Otlet’s original idea for a a Universal Bibliography, has even gone as far as creating meta “lists of lists,” which help organize and rearrange the lists of information. There’s even a lists of lists of lists.</p>
</blockquote>

<ul>
  <li><a href="https://mastodon.social/@shiflett/113194298332588671">Chris Shiflett: “There’s nothing quite like tight kerning to make a design look dean and modem.” - Mastodon</a> - an 11/10 joke</li>
  <li><a href="https://tonydowler.substack.com/p/i-implore-you-to-do-something-useless">I implore you to do something useless - TonyD’s Substack</a> - the importance of being idle</li>
</ul>

<blockquote>
  <p>Creativity requires a mélange of experiences that cannot be quantifiable. They include but are not limited to: quiet contemplation, boredom, inspiration, taste, style, genre, motif, and dozens of others. These experiences do not come on-demand. They require a specific state of being that can only be acquired away from the measured and regimented processes that society loves too much.</p>
</blockquote>

<ul>
  <li><a href="https://uo.com/2024/09/25/ultima-online-classic-client-upgrade/">Ultima Online Classic Client Upgrade – Ultima Online</a>, via <a href="https://massivelyop.com/2024/09/26/ultima-online-devs-are-working-with-classicuo-modders-to-rehab-the-ancient-client-and-renderer/">Massively</a> - UO played a huge part of my youth and it’s amazing to hear that the devs are working on with the <a href="https://www.classicuo.eu/">ClassicUO</a> folks to keep the classic client (or at least <em>a</em> classic client alive)</li>
</ul>

<blockquote>
  <p>we are working with the developers of the third-party client “ClassicUO” with the goal of making available an officially sanctioned version for use on all shards</p>
</blockquote>

<ul>
  <li><strong>Playing</strong>: I’m a few hours into <a href="https://www.nintendo.com/en-gb/Games/Nintendo-Switch-games/The-Legend-of-Zelda-Echoes-of-Wisdom-2590490.html">Zelda: Echoes of Wisdom</a> and it’s a lovely, chill time so far, with some vague Scribblenauts vibes.</li>
  <li><strong>Reading</strong>: <a href="https://www.penguin.co.uk/books/316825/the-practice-of-not-thinking-by-koike-ryunosuke/9780141994611">The Practice of Not Thinking</a> - more importance of being idle</li>
</ul>]]></content><author><name>Steve Taylor</name></author><summary type="html"><![CDATA[Selling a small front-end web project — what I learned - Alistair Shepherd - a nice writeup on the process and experience of selling a small website, My Top for Spotify It’s Lists All the Way Down - The History of the Web - the wolrd wide web is lists]]></summary></entry><entry><title type="html">Jekyll Short URL Generator</title><link href="http://ste.vet/2024/09/25/jekyll-short-url-generator.html" rel="alternate" type="text/html" title="Jekyll Short URL Generator" /><published>2024-09-25T00:00:00+00:00</published><updated>2024-09-25T00:00:00+00:00</updated><id>http://ste.vet/2024/09/25/jekyll-short-url-generator</id><content type="html" xml:base="http://ste.vet/2024/09/25/jekyll-short-url-generator.html"><![CDATA[<p>I was reading <a href="https://heavydeck.net/project/jsredir/">this post by J about setting up a simple URL shortener with no server-side logic</a> and it got me wondering if there was a Jekyll/GitHub Pages “native” way to implement something similar. It turned out to be very simple to put together!</p>

<h3 id="redirecthtml-layout"><code class="language-plaintext highlighter-rouge">redirect.html</code> layout</h3>

<p>Basically my regular layout with a couple of changes:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>&lt;script&gt;
	const url = new URL(window.location.href);
	const stay = url.searchParams.get("stay") != null;
	if (!stay) {
		window.location = ""
	}
&lt;/script&gt;

&lt;noscript&gt;
	&lt;meta http-equiv="refresh" content="0; url=" /&gt;
&lt;/noscript&gt;
</code></pre></div></div>

<p>Some simple JavaScript to redirect to the target page, unless a <code class="language-plaintext highlighter-rouge">stay</code> query parameter exists. If JS isn’t available it’ll use the <code class="language-plaintext highlighter-rouge">meta</code> tag to redirect.</p>

<h3 id="_configyml"><code class="language-plaintext highlighter-rouge">_config.yml</code></h3>

<h4 id="add-a-new-scope">Add a new <code class="language-plaintext highlighter-rouge">scope</code></h4>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>  - scope:
      path: ""
      type: "redirects"
    values:
      layout: "redirect"
</code></pre></div></div>

<p>…so that <code class="language-plaintext highlighter-rouge">redirect</code> entries use the new layout</p>

<h4 id="add-a-new-collection-type">Add a new <code class="language-plaintext highlighter-rouge">collection</code> type</h4>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>collections:
  redirects:
    output: true
    permalink: /s/:name/index.html
</code></pre></div></div>

<p>…which will cause redirect pages to be generated at http://ste.vet/[redirectname]/index.html. This allows them to be accessible at http://ste.vet/[redirectname] with no special serverside logic or web server config to handle these paths.</p>

<h3 id="add-the-redirect-entries">Add the redirect entries</h3>

<p>Now I’m able to add a [redirectname.md] to my a <code class="language-plaintext highlighter-rouge">_redirects</code> folder, and all they need to contain is:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>---
redirect: [url]
---
</code></pre></div></div>

<p>So you can now hit <a href="http://ste.vet/s/mastodon">http://ste.vet/s/mastodon</a> to get to my Mastodon page, or <a href="http://ste.vet/s/mastodon?stay">http://ste.vet/s/mastodon?stay</a> to hold on the redirect page! I didn’t have any particular usecase for this and it was more idle noodling, but <a href="https://heavydeck.net/blog/lost-and-found-stickers/">J’s application of theirs for QR codes to stick on luggage pointing to a Lost &amp; Found page</a> is very smart!</p>]]></content><author><name>Steve Taylor</name></author><summary type="html"><![CDATA[I was reading this post by J about setting up a simple URL shortener with no server-side logic and it got me wondering if there was a Jekyll/GitHub Pages “native” way to implement something similar. It turned out to be very simple to put together!]]></summary></entry><entry><title type="html">2024-09-22 Sunday Links</title><link href="http://ste.vet/2024/09/22/sunday-links.html" rel="alternate" type="text/html" title="2024-09-22 Sunday Links" /><published>2024-09-22T00:00:00+00:00</published><updated>2024-09-22T00:00:00+00:00</updated><id>http://ste.vet/2024/09/22/sunday-links</id><content type="html" xml:base="http://ste.vet/2024/09/22/sunday-links.html"><![CDATA[<ul>
  <li><a href="https://www.timeextension.com/news/2024/09/cristiano-ronaldo-is-in-fatal-fury-city-of-the-wolves-for-some-reason">Cristiano Ronaldo Is In Fatal Fury: City Of The Wolves, For Some Reason</a> - their title, not mine</li>
  <li><a href="https://www.timeextension.com/news/2024/09/anniversary-tekken-is-now-30-years-old">Anniversary: Tekken Is Now 30 Years Old</a> - While that is indeed a very long time, the thing that caught my eye here was
    <blockquote>
      <p>Created by Seiichi Ishii, the original Tekken was released on 21st September 1994 on the System 11 arcade board, which was based on the PS1 hardware.</p>
    </blockquote>

    <p>which I had not been aware of. <a href="https://en.wikipedia.org/wiki/Namco_System_11#:~:text=system%2011%20is%20based%20on%20a%20prototype%20of%20the%20playstation">Wikipedia</a> corroborates</p>
  </li>
</ul>

<blockquote>
  <p>System 11 is based on a prototype of the PlayStation</p>
</blockquote>

<ul>
  <li><a href="https://www.deviantart.com/himynamesjakob/art/Legend-of-Zelda-Majora-s-Mask-Isometric-Diorama-1020466588"><img src="https://images-wixmp-ed30a86b8c4ca887773594c2.wixmp.com/f/cdaf0c9b-4436-482f-9b19-bfeb262aa2d9/dgvk524-20597588-4168-4b00-97e1-4a76b5dd4be7.png/v1/fill/w_177,h_250,q_70,strp/legend_of_zelda__majora_s_mask_isometric_diorama_by_himynamesjakob_dgvk524-250t.jpg?token=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJ1cm46YXBwOjdlMGQxODg5ODIyNjQzNzNhNWYwZDQxNWVhMGQyNmUwIiwiaXNzIjoidXJuOmFwcDo3ZTBkMTg4OTgyMjY0MzczYTVmMGQ0MTVlYTBkMjZlMCIsIm9iaiI6W1t7ImhlaWdodCI6Ijw9MTgxMSIsInBhdGgiOiJcL2ZcL2NkYWYwYzliLTQ0MzYtNDgyZi05YjE5LWJmZWIyNjJhYTJkOVwvZGd2azUyNC0yMDU5NzU4OC00MTY4LTRiMDAtOTdlMS00YTc2YjVkZDRiZTcucG5nIiwid2lkdGgiOiI8PTEyODAifV1dLCJhdWQiOlsidXJuOnNlcnZpY2U6aW1hZ2Uub3BlcmF0aW9ucyJdfQ._LxuHm82V8lKxyEEdXW7ZzIn1D27pWw3-N05ylsOkdM" alt="Illustration of an N64 pulled apart with a scene from Legend of Zelda: Majora's Mask between the top and bottom halves" /></a></li>
  <li><a href="https://www.pcgamesn.com/half-life/cd-discovery">‘New’ version of Half-Life discovered with cut content and secrets</a> - a late beta test of Half-Life has been rediscovered, dated about a month before the final release</li>
  <li><a href="https://heavydeck.net/blog/lost-and-found-stickers/">Lost &amp; Found stickers</a> - Smart idea: Lost &amp; Found QR code stickers for luggage etc</li>
  <li><a href="https://github.com/hoarder-app/hoarder">hoarder-app/hoarder: A self-hostable bookmark-everything app (links, notes and images) with AI-based automatic tagging and full text search</a> - a nice-looking self-hosted bookmark and snapshot archive app. Also a really great reference for <a href="https://github.com/hoarder-app/hoarder?tab=readme-ov-file#alternatives">other self-hosted alternatives</a></li>
</ul>]]></content><author><name>Steve Taylor</name></author><summary type="html"><![CDATA[Cristiano Ronaldo Is In Fatal Fury: City Of The Wolves, For Some Reason - their title, not mine Anniversary: Tekken Is Now 30 Years Old - While that is indeed a very long time, the thing that caught my eye here was Created by Seiichi Ishii, the original Tekken was released on 21st September 1994 on the System 11 arcade board, which was based on the PS1 hardware.]]></summary></entry><entry><title type="html">2024-09-15 Sunday Links</title><link href="http://ste.vet/2024/09/15/sunday-links.html" rel="alternate" type="text/html" title="2024-09-15 Sunday Links" /><published>2024-09-15T00:00:00+00:00</published><updated>2024-09-15T00:00:00+00:00</updated><id>http://ste.vet/2024/09/15/sunday-links</id><content type="html" xml:base="http://ste.vet/2024/09/15/sunday-links.html"><![CDATA[<ul>
  <li><a href="https://modem.io/blog/blog-monetization/">How to Monetize a Blog</a> - A literal satirical art piece on monetising blogs</li>
  <li><a href="https://worrydream.com/TheWebOfAlexandria/2.html">The Web of Alexandria (follow-up)</a> (2015) - A thoughtful piece on why both the ephemerality <em>and</em> the preservation of the web are problematic
    <blockquote>
      <p>historically, people have relied on different media for different social purposes, and have relied on a clear understanding of how the technical properties of each medium determine the social and temporal scope of its messages.
Think about speech, letters, newspapers, books, smoke signals… Each medium serves only a particular subset of social purposes, and each medium is technically transparent enough that people can understand what’s happening when they use it.</p>
    </blockquote>
  </li>
  <li><a href="https://robertheaton.com/pyskywifi/">PySkyWiFi: completely free, unbelievably stupid wi-fi on long-haul flights</a> - My new favourite dumb computer project: a system to proxy the web through fields in an airmiles profile to allow free, unrestricted browsing in the sky</li>
</ul>]]></content><author><name>Steve Taylor</name></author><summary type="html"><![CDATA[How to Monetize a Blog - A literal satirical art piece on monetising blogs The Web of Alexandria (follow-up) (2015) - A thoughtful piece on why both the ephemerality and the preservation of the web are problematic historically, people have relied on different media for different social purposes, and have relied on a clear understanding of how the technical properties of each medium determine the social and temporal scope of its messages. Think about speech, letters, newspapers, books, smoke signals… Each medium serves only a particular subset of social purposes, and each medium is technically transparent enough that people can understand what’s happening when they use it. PySkyWiFi: completely free, unbelievably stupid wi-fi on long-haul flights - My new favourite dumb computer project: a system to proxy the web through fields in an airmiles profile to allow free, unrestricted browsing in the sky]]></summary></entry></feed>