Overtaken by eventsJekyll2023-10-01T12:41:55+01:00https://www.overtakenbyevents.com/David Blackhttps://www.overtakenbyevents.com/david_black_uk@yahoo.comhttps://www.overtakenbyevents.com/Atari-ST-HDD-Image-For-My-YouTube-Series2023-05-27T00:00:00+01:002023-05-27T00:00:00+01:00David Blackhttps://www.overtakenbyevents.comdavid_black_uk@yahoo.com
<h1 id="the--hdd-image-for-my-st-from-zero-to-hero-series">The HDD image for my ST From Zero to Hero Series</h1>
<p>I’ve been presenting two series on YouTube around installing configuring and extending an Atari ST and an Atari Falcon.</p>
<p>While recording these series I’ve been asked if I could make the hard drive images available. This page is where I am going to host that image.</p>
<p>The current image will contain all that was covered in all previous ones</p>
<p>I’ll try to keep this page up to date with the series, but updates might be some what asynchronous, unless I can easily automate it.</p>
<p>This is a zip file containing a single file called <code class="language-plaintext highlighter-rouge">512.img</code> which is a 512 MB Atari ST Hard drive suitable for using in emulators. I use Hatari for recording purposes, it boots fine in EmuTos. It almost certainly won’t boot into real TOS because no HD drivers are installed.</p>
<p>There are two Hard drive images that are available, these are for the Atari ST image and the Falcon Image.</p>
<p>The video describing how to use these images is available <a href="https://youtu.be/WRRTCyj7Xfs">here</a> though it’s getting very out of date.</p>
<p>If you’re interested in the ST image, it’s at the end of the page.</p>
<p>If you are going to watch the video on <a href="https://youtu.be/WRRTCyj7Xfs">how to install and use the ST image</a> it covers the ST version</p>
<p>If you are following the Atari Falcon / Mint series see the extra instructions below before watching that video</p>
<h2 id="episode-29---polishing-mint-2-adding-an-ext2-file-system-to-mint">Episode 29 - Polishing Mint #2: Adding an Ext2 file system to MiNT</h2>
<ul>
<li>The system needs to be an Atari Falcon</li>
<li>The CPU needs to be 68040 at 32 MHz (or 32 if you wish) and a 68882 FPU</li>
<li>Memory I used 14 MB of ST RAM and 128 of TT/Fast RAM</li>
<li>There are now two hard drive images that need to be used.
<ul>
<li>The file drive-0.img should be mounted as SCSI device 0</li>
<li>and drive-1.img as SCSI device 1</li>
</ul>
</li>
<li>finally the drives are now packed as bzip2 compressed tar files, use
<ul>
<li>tar xvjf file.tar.bz2 <em>On MAC and Linux</em></li>
<li>7zip <em>on windows</em> or the above command on <em>WSL</em></li>
</ul>
</li>
</ul>
<p>Also as I noted in the video, GEMDOS drives are not available in MiNT</p>
<p><img src="../thumbs/ep-029-ext2.png" alt="Thumbnail for the episode" /></p>
<div class="downloadButton">
<a href="https://www.dropbox.com/scl/fi/s8rx9e8pc2qk5hdvsq2cc/ep-029-hdd-images.tar.bz2?rlkey=bm1m141q4l8x1zb87tzpfhyaf&dl=1" class="downloadLink">Download DISK Image </a>
</div>
<h2 id="the-atrai-st-image">THe Atrai ST image</h2>
<p>This is the ‘512.img’ file from the original ST from hero to zero series</p>
<p><img src="../thumbs/ep-019-fonts.png" alt="Thumbnail for the episode" /></p>
<div class="downloadButton">
<a href="https://www.dropbox.com/scl/fi/xpcmrwevwayxzu6y9pvk9/ep_019_hdd_img.zip?rlkey=wnmc6jm8799np5f5u05fix4uq&dl=1" class="downloadLink">Download DISK Image </a>
</div>
<hr />
<p><a href="https://www.overtakenbyevents.com/Atari-ST-HDD-Image-For-My-YouTube-Series/">Atari ST: The HDD image for my ST From Zero to Hero Series</a> was originally published by David Black at <a href="https://www.overtakenbyevents.com">Overtaken by events</a> on May 27, 2023.</p>https://www.overtakenbyevents.com/a-youtube-series-on-installing-and-upgrading-an-atari-st2023-04-14T00:00:00+01:002023-04-14T00:00:00+01:00David Blackhttps://www.overtakenbyevents.comdavid_black_uk@yahoo.com
<h1 id="a-youtube-series">A YouTube series</h1>
<p>Recently I’ve been recording a series on YouTube where I take a stock Atari STFM, upgrade it and build it into a daily driver.</p>
<p>The beginning of the series is this video, where I take a screw driver and a soldering iron to my ST in an attempt to upgrade it from TOS 1.02 to 1.04. It worked, eventually…</p>
<iframe width="560" height="315" src="https://www.youtube.com/embed/2GJyBVxgKpQ" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen=""></iframe>
<p>Staring with that as the baseline I began installing software upgrades to improve performance and capabilities, by updating the VDI, GDOS, installing a new desktop and finally adding multitasking.</p>
<iframe width="560" height="315" src="https://www.youtube.com/embed/WLyK9nhnptA" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen=""></iframe>
<p>which resulted in a much faster, more attractive ST.</p>
<p>Then I moved on to quality of life improvements and adding a CLI to our system.</p>
<iframe width="560" height="315" src="https://www.youtube.com/embed/-PMGnu_MPJc" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen=""></iframe>
<p>Running different ST configurations requires a boot manager. Here I install and configure XBoot.</p>
<iframe width="560" height="315" src="https://www.youtube.com/embed/bIsZyks0kPc" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen=""></iframe>
<p>We need to decompress files in a variety of formats, here how to install and configure PAC Shell</p>
<iframe width="560" height="315" src="https://www.youtube.com/embed/skrYTKl8EyQ" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen=""></iframe>
<p>It’s no good having software without knowing how to use it. In this episode I install ST-Guide a hyper text help system for the atari ST</p>
<iframe width="560" height="315" src="https://www.youtube.com/embed/xrkXTFx5hGY" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen=""></iframe>
<p>There are a couple of Quality of life improvements next, a Font Selector and an AV Server, just to make life better. Finally I add
more bling to the ST by adding custom Icons into the mix</p>
<iframe width="560" height="315" src="https://www.youtube.com/embed/8_05R2MSBd0" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen=""></iframe>
<p>Thats all for now but more episodes incoming.</p>
<p><a href="https://www.overtakenbyevents.com/a-youtube-series-on-installing-and-upgrading-an-atari-st/">Atari ST: Installation and configuration series</a> was originally published by David Black at <a href="https://www.overtakenbyevents.com">Overtaken by events</a> on April 14, 2023.</p>https://www.overtakenbyevents.com/the-manual-for-neodesk-cli2023-04-13T00:00:00+01:002023-04-13T00:00:00+01:00David Blackhttps://www.overtakenbyevents.comdavid_black_uk@yahoo.com
<h1 id="neodesk-cli-manual">NeoDesk CLI Manual</h1>
<p>In a recent youtube video I put out a call for help, to locate a copy of the manual for the Atari ST app, NeoDesc CLI.</p>
<p>Joe Ceklosky came to the rescue and scanned it for us. Many, <em>many</em>, thanks to him. Here’s <a href="/docs/neodesk-cli.pdf">a link to the manual</a>.</p>
<p><a href="https://www.overtakenbyevents.com/the-manual-for-neodesk-cli/">Atari ST: The manual for NeoDesk CLI</a> was originally published by David Black at <a href="https://www.overtakenbyevents.com">Overtaken by events</a> on April 13, 2023.</p>https://www.overtakenbyevents.com/cpc-telera-setting-break-points-in-code2022-10-08T00:00:00+01:002022-10-08T00:00:00+01:00David Blackhttps://www.overtakenbyevents.comdavid_black_uk@yahoo.com
<h1 id="im-at-breaking-point">I’m at breaking point!</h1>
<p>I’ve started experimenting with the awesome CPCtelera, which is a fast, low level, CPC games library / engine. You can write games in CPCtelera in a mixture as assembly language or C.</p>
<p>It was the C programming aspect of CPCtelera that first attracted me to it. I’ve always wondered how slow (or not) games written in C would be for a retro system.</p>
<p>There are a lot of YouTube videos that describe CPCtelera and how to use it on the <a href="https://www.youtube.com/c/ProfesorRetroMan">Profesor Retroman</a> youtube channel. The videos are in spanish so I mostly watch them using auto translated sub titles.</p>
<p>Today I found a very recent stream and while watching it with the sound off (there were no sub titles), I saw the Prof, add the following line of code to his C source:</p>
<figure class="highlight"><pre><code class="language-c" data-lang="c"><span class="n">WinwApe_Brk</span></code></pre></figure>
<p>He then ran the app via the WinApe emulator and it switched to the debugger at the point where the <code class="language-plaintext highlighter-rouge">WinwApe_Brk</code> command was. What magic is this? I thought. There was no reference to this being unusual or new in the stream and the only includes he had were <code class="language-plaintext highlighter-rouge">cpctelera.h</code> and <code class="language-plaintext highlighter-rouge">utils.h</code>. I ransacked the CPCtelera source code but couldn’t find the macro, so I guess it was in the utils include file. Harrumph, not a file I had.</p>
<p>But there was a clue, in the tool tip as as he hovered over the macro it showed a partial representation of the macros definition, enough for me to reverse engineer what was going on (after a little googling).</p>
<div class="dbImg centeredImg" data-src="cpc/cpc-telera-video screenshot.png" title="WinApe degugger"></div>
<p>WinApe supports a custom OpCode to break the program at a specific point, that Opcode is <code class="language-plaintext highlighter-rouge">0xED 0xFF</code>. By default this OpCode is disabled, to enable it start WinApe and open the debugger (F7 on PC). This shows the debugger window, just make sure you check the option <em>‘Break Instructions’</em> at the bottom of the window.</p>
<div class="dbImg centeredImg" data-src="cpc/win-ape-debugger.png" title="WinApe degugger"></div>
<p>Now we need to add the breakpoint from C code. To do this we create a macro that emits the opcode for the WinApe breakpoint command. Here it is</p>
<figure class="highlight"><pre><code class="language-c" data-lang="c"><span class="cp">#define WinwApe_Brk __asm__(".dw #0xFFED");</span></code></pre></figure>
<p>The bytes are swapped because they are stored little endian in a dword value.</p>
<p>We run WinApe using the CPCtelera command <code class="language-plaintext highlighter-rouge">cpct_winape -as</code>, this starts the app running in WinAp paused at the start address of the game. We press run, play through to the code that contains the breakpoint
and the emulator breaks. The final result is <em>satisfying</em>, this for me is game changing.</p>
<div class="dbImg centeredImg" data-src="cpc/win-ape-breakpoint.png" title="WinApe degugger"></div>
<p>Not my idea, but i had to share.</p>
<p>Ill be creating more CPCtelera posts as i gain more experience with it. So look out for those.</p>
<hr />
<p><a href="https://www.overtakenbyevents.com/cpc-telera-setting-break-points-in-code/">CPC Telera: Setting breakpoints in code</a> was originally published by David Black at <a href="https://www.overtakenbyevents.com">Overtaken by events</a> on October 08, 2022.</p>https://www.overtakenbyevents.com/cpc-my-rombox2022-08-31T00:00:00+01:002022-08-31T00:00:00+01:00David Blackhttps://www.overtakenbyevents.comdavid_black_uk@yahoo.com
<h1 id="roms-to-the-left-of-me-roms-to-the-right-here-i-am">ROMs to the left of me, ROMs to the right, here I am</h1>
<p>ROM-box, now there’s a term you don’t hear much anymore. I used an Amstrad CPC-464 as a daily driver for my job as a games programmer. One of my most abiding memories of that time was my heavy use of ROM based applications.</p>
<p>When the CPC was my main work machine, loading apps from tape was appallingly slow. Working with an assembler / editor loaded from a c-15 tape with game files stored on 10 other C-15 cassettes made me a very unhappy chappie. An external FD-1 disc drive when it finally released would help a lot, but still I wanted:</p>
<div class="dbImg centeredImg" data-src="../memes/more-power.png" alt="MORE POWER"></div>
<div class="dbCaption"> MORE POWER.</div>
<p>Pre-internet, pre-google, I went to the only search engine I had: WH Smiths the news agent. I bought a copy of Amstrad Action.</p>
<div class="dbImg zoom50 centeredImg" data-src="cpc/amstrad-action-001.png" alt="MORE POWER"></div>
<p>Inside amstrad action, on page 25 I found this advert:</p>
<div class="dbImg centeredImg" data-src="cpc/maxam-rom-advert.png" alt="MORE POWER"></div>
<div class="dbCaption"> They're advertising heaven</div>
<p>The cartridge approach didn’t appeal to me as it was fairly obvious from the get go that I’d want more ROMs as time went by. So I kept digging and found the following add on page 93 of issue one.</p>
<div class="dbImg centeredImg" data-src="cpc/rom-box-advert.png" alt="MORE POWER"></div>
<div class="dbCaption">A sideways ROM advert from Honeysoft</div>
<blockquote>
<p>Dave from the present here: You won’t believe the amount of time I spent thumbing through the PDFs of Amstrad Action when researching this. More power?, more nostalgia really.</p>
</blockquote>
<p>Back to the past.</p>
<p>Obviously I’m hooked on getting these, lets tally up what I’m spending:</p>
<table>
<thead>
<tr>
<th style="text-align: right">item</th>
<th style="text-align: right">price</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align: right">4 socket sideways ROM expansion card</td>
<td style="text-align: right">£18.95</td>
</tr>
<tr>
<td style="text-align: right">ARNOR MAXAM Assembler</td>
<td style="text-align: right">£39.95</td>
</tr>
<tr>
<td style="text-align: right"><strong>total</strong></td>
<td style="text-align: right">£58.90</td>
</tr>
</tbody>
</table>
<p>At this time I was using a green screen CPC-464 (with a MP-1 TV adaptor for color testing). That £58.90 represented a significant investment for me, 30% of the purchase price of the CPC. But I was a PRO and this was going to make me faster…</p>
<p>To be fair, it did.</p>
<p>An instantly available text editor and Z80 assembler, even before I had a floppy drive I felt privileged.</p>
<h2 id="more-roms">More ROMs</h2>
<p>As my needs changed I added more and more ROMS to the mix, I was running a business as a developer and I needed to invoice companies, file my taxes, write complaint letters to Amstrad about how late my order of a FD-1 was, etc</p>
<table>
<thead>
<tr>
<th>ROM</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>Utopia</td>
<td>A somewhat esoteric collection of utilities for extending BASIC, handling discs, tapes and ROMS.</td>
</tr>
<tr>
<td>Parados</td>
<td>An AMSDOS replacement / upgrade that supports a number of extra floppy disk formats included double sided discs on external drives.</td>
</tr>
<tr>
<td>Protext</td>
<td>A word processor</td>
</tr>
<tr>
<td>Prospell</td>
<td>A generic spell checker which was also integrated with Protext</td>
</tr>
</tbody>
</table>
<p>At some point a new ROM box was required as I exceeded the limit of 4 ROMs, I can’t remember which one I used, it was a kit from Everyday Electronics magazine (soldering required).</p>
<p>The final total is</p>
<table>
<thead>
<tr>
<th style="text-align: right">item</th>
<th style="text-align: right">price</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align: right">4 socket sideways ROM expansion card</td>
<td style="text-align: right">£18.95</td>
</tr>
<tr>
<td style="text-align: right">MAXAM Assembler (Arnor)</td>
<td style="text-align: right">£39.95</td>
</tr>
<tr>
<td style="text-align: right">Utopia (Arnor)</td>
<td style="text-align: right">£29.95</td>
</tr>
<tr>
<td style="text-align: right">Parados (Quantum)</td>
<td style="text-align: right">£14.99</td>
</tr>
<tr>
<td style="text-align: right">Protext (Arnor)</td>
<td style="text-align: right">£39.95</td>
</tr>
<tr>
<td style="text-align: right">Prospell (Arnor)</td>
<td style="text-align: right">£29.95</td>
</tr>
<tr>
<td style="text-align: right"><strong>total</strong></td>
<td style="text-align: right">£173.74</td>
</tr>
</tbody>
</table>
<p>At £173 that’s 87% of the purchase cost of the CPC-464. I’m surprised I didn’t get a Christmas card from Arnor every year.</p>
<h2 id="back-to-the-future">Back to the future</h2>
<p>In the middle of COVID lockdown one, like many others I started searching around for things to do. In the attic I had a CPC-6128, with a broken monitor and liquid drive belts. Once I got that machine working (not the monitor, I’m not HV approved) I started thinking what to do with it; when the expression ROM-box floated across my mind. So I decided to recreate my old set up and have a play.</p>
<div class="dbImg zoom50 centeredImg" data-src="cpc/rom-box.png" alt="My ROM box populated with ROMS."></div>
<div class="dbCaption">
My populated Rombo Redux v4.
</div>
<p>The ROM box is the <em>Rombo Redux v4</em>, I bought it on <em>sell my retro</em> (more on which in a bit). It cost £40 and while that’s more than the original Honey soft device, it is an 8 bay beast. Though to be fair the lower 8 ROMS have some restrictions.</p>
<p>Other than just hosting ROMS, the <em>Rombo Redux V4</em> also comes with</p>
<ul>
<li>a reset switch for the CPC (Red)</li>
<li>an LED power light (Blue)</li>
<li>A bank select jumper (Green)</li>
<li>A set of ROM enable DIP switched (Yellow)</li>
<li>A 3D printed case (without lid, but it protects the PCB from shorting)</li>
</ul>
<div class="dbImg zoom75 centeredImg" data-src="cpc/rom-box-bits.png" alt="My ROM box populated with ROMS."></div>
<p>The CPC 464 didn’t come with a reset key, the only way to reset it was to power cycle the wall socket, or yank the power cable in and out. So the addition of a reset switch is a very welcome one.</p>
<p>The CPC family of computers supported up to 16 ROMs. The bank selection jumper allows you to map your ROM box for ROMS 0..7 or 8..15. THe PCB has very detailed silkscreens showing what slot the ROMS will be in, e.g. ROM 2/10.</p>
<p>The DIP switches allow the user to specify what ROMS are enabled or not. I currently have all populated ROMs enabled, but there are times when ROMs might clash, or when a application is trying to use the small number of memory addresses these ROMs use. The board has a downstream edge connector so you should be able to daisy-chain two of these for 16 ROMS, though I haven’t tried this.</p>
<p>You might think you could just remove the ROM box when not needed, but as the vendor warned me, the connector on the ribbon cable now has a death like grip on the CPC. I would be fearful of detaching the CPC edge connector pads if I tried it.</p>
<p>Along with the ROM box I ordered the Utopia, Parados, Prospell and Protext ROMS. Maxam I ordered separately form another supplier. When they were all socketed I was in heaven, except: except, Noooo…</p>
<div class="dbImg zoom50 centeredImg" data-src="cpc/rom-box-triggered.png" alt="One of my labels was upside down, argggh."></div>
<div class="dbCaption">
Feel a little triggered yet?
</div>
<p>I mean you’d think there would be an ANSI or ECMA standard for labels on ROMs but no, not for the important stuff like that, just for the unimportant stuff like programming languages and safety critical systems.</p>
<p>A quick look at the previous image of my ROM box shows that I do however own a label printer. Problem solved. Trigger mitigated. Phew.</p>
<p>So once installed your Amstrad boot screen goes from this proletarian screen</p>
<div class="dbImg centeredImg" data-src="cpc/boot-no-roms.png" alt="Boot screen no ROMs."></div>
<p>to the super elitist version</p>
<div class="dbImg centeredImg" data-src="cpc/boot-with-roms.png" alt="A boot screen with ROMS."></div>
<p>and all is good. In fact if we get ahead of our selves a little and use the Utopia ROMs <code class="language-plaintext highlighter-rouge">|help</code> command we can see more</p>
<div class="dbImg centeredImg" data-src="cpc/utopia-help.png" alt="A ROM list from utopia."></div>
<p>this indeed is <em>my Utopia</em>!</p>
<h2 id="sources">Sources</h2>
<p>I bought the Rombo Redux v4 from <a href="https://www.sellmyretro.com/offer/details/rombo-redux-deluxe-61511">sell my retro.com</a> but before you click that link <em>please</em> read on. The seller was the user
<code class="language-plaintext highlighter-rouge">TheEqualizor</code> I can’t say enough good things about this guy, he answered all my questions quickly and accurately. The box is made to order and arrived very promptly.</p>
<p>“Sell my Retro” however is a different matter. It may be a coincidence that after I payed for this item, over several days, I received alerts from PayPal about attempted accesses to my account. MFA for the win, but I think the site was compromised.</p>
<p>However I have tracked down a <a href="https://www.youtube.com/watch?v=k0q76PNmoiU&ab_channel=TheEqualizor">youtube video</a> by the seller of the Retro Redux and it has contact details, so you can approach him yourself. Note: the Rombo Redux in that video is not the same as the model I purchased.</p>
<p>I bought MAXAM from an <a href="https://www.ebay.co.uk/itm/233463843334">eBay seller</a> before I bought the Rombo Redux, it may have been more expensive than it needed to be, but, it came with a printed manual.</p>
<p>So what did my little experiment cost:</p>
<table>
<thead>
<tr>
<th style="text-align: right">item</th>
<th style="text-align: right">price</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align: right">Rombo Redux v4</td>
<td style="text-align: right">£40.00</td>
</tr>
<tr>
<td style="text-align: right">MAXAM Assembler (Arnor)<sup>1</sup></td>
<td style="text-align: right">£14.00</td>
</tr>
<tr>
<td style="text-align: right">Utopia (Arnor)</td>
<td style="text-align: right">£4.00</td>
</tr>
<tr>
<td style="text-align: right">Parados (Quantum)</td>
<td style="text-align: right">£4.00</td>
</tr>
<tr>
<td style="text-align: right">Protext (Arnor)</td>
<td style="text-align: right">£4.00</td>
</tr>
<tr>
<td style="text-align: right">Prospell (Arnor)</td>
<td style="text-align: right">£4.00</td>
</tr>
</tbody>
<tbody>
<tr>
<td style="text-align: right"><strong>total</strong></td>
<td style="text-align: right">£70:00</td>
</tr>
</tbody>
</table>
<p><sup>1</sup>Maxam price includes P&P and that was the price I paid then. The price has since gone up.</p>
<h2 id="wrap-up">Wrap up</h2>
<p>I achieved my goal of recreating my setup from 1985. I have had a blast playing around with the ROMs and reminiscing.</p>
<p>Modern day pricing was cheaper though, *cough*, I’m not sure of the ‘authenticity’ of the ROMS :-)</p>
<p>ROMS are great, they extend the capabilities of your Amstrad computer with instant access functionality. Amazingly they were mainly forwards compatible in the vanilla CPC line (the Rombo Redux is not compatible with the CPC plus series). Mine worked in my CPC 464 and 6128.</p>
<p>If I look for downsides, I can only think of two:</p>
<ul>
<li>Sometimes they didn’t play well together (rare)</li>
<li>You bought them at a certain version number and updating them wasn’t easy or even possible.</li>
</ul>
<p>I think part of the allure of ROMs were that they where fairly niche. Those of us that used them felt like we were power users, and we’re all snobs at heart aren’t we!</p>
<p>That’s it for this blog. I’m following up this article with a detailed description of each of the ROMs that are in the box and I’ll tweet when each article is published. Could be a bit of a wait though, these articles take a long time to put together.</p>
<p><a href="https://www.overtakenbyevents.com/cpc-my-rombox/">Amstrad CPC: My ROM box</a> was originally published by David Black at <a href="https://www.overtakenbyevents.com">Overtaken by events</a> on August 31, 2022.</p>https://www.overtakenbyevents.com/amstrad-cpc-amsdos-commands2022-08-19T00:00:00+01:002022-08-19T00:00:00+01:00David Blackhttps://www.overtakenbyevents.comdavid_black_uk@yahoo.com
<h1 id="getting-around-to-it">Getting around to it</h1>
<p>I pulled an old CPC 6128 out of the loft recently, by recently I mean during lock down 1, over a year ago. So having had it sit on the shelf in my home-office for a year, I decided to start playing with it, after a re-cap and of course the inevitable disc drive belt replacement.</p>
<div class="dbImg zoom50 centeredImg" data-src="cpc/cpc-128-replacement-belt.png" alt="Picture of a replacement belt in a bag."></div>
<div class="dbCaption">
The replacement belt, source url in the photo.
</div>
<p>That year between pulling the CPC out of the attic and actually getting around to doing something about it, is a good example of why I called this blog “Over taken by events”. The fact that the last post on this site was a year ago also, is equally indicative!</p>
<p>When I first had a plugged in and working system, via a hodgepodge of adaptors, I inserted a disc, typed <code class="language-plaintext highlighter-rouge">cat</code>, got a directory listing then typed <code class="language-plaintext highlighter-rouge">run"custard</code> to start the game, I thought I’d bossed it, What a memory!</p>
<div class="dbImg zoom200 centeredImg" data-src="cpc/cpc-custard-pie-factory.png" alt="Picture of a replacement belt in a bag."></div>
<div class="dbCaption">
Ahh, my first CPC game published by Tynesoft.
</div>
<p>However I pretty quickly realized I couldn’t remember any of the other disc commands. This post is the culmination of my head scratching around this which, I hope, might save you time if you’re getting back into the CPC.</p>
<p>The CPC had two distinct ways of accessing a floppy disc, AMSDOS: which was the native CPC disc access method, used to run CPC programs; and CPM, used to run business apps and Zork. CPM is beyond the scope of this article but I will cover it in a later post.</p>
<h2 id="beginnings">Beginnings</h2>
<p>The Amstrad CPC 464, the original Amstrad Color Personal Computer didn’t come with floppy support at all, it had a built in cassette deck. To add support external floppies you plugged in and expansion card, the snappily named DDI-1. This contained a 765 disc drive controller and a ROM that extended Locomotive BASIC with AMSDOS.The CPC 664, 6128 and the 6128plus all had the AMSDOS ROM built into the mainboard.</p>
<p>The tape oriented nature of the original CPC means that AMSDOS has a number of commands that deal with backwards and forwards compatibility. You can, for example disable the disc system completely and revert to all I/O being performed to tape again. On later CPCs with built in disc drives, tape based games and apps became rarer and for me at least, these commands were less frequently used.</p>
<p>The commands that you use to access and control discs are a mixture of built in BASIC commands and external commands in the ROM.</p>
<p>Internal basic commands e.g. <code class="language-plaintext highlighter-rouge">cat</code> are typed as is:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>cat
</code></pre></div></div>
<p>External commands, e.g. <code class="language-plaintext highlighter-rouge">dir</code> are prefixed with a vertical bar:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>¦dir
</code></pre></div></div>
<p>Commands are not case sensitive. You can find the <code class="language-plaintext highlighter-rouge">¦</code> symbol by pressing shift on the ‘@’ key.</p>
<p>Some commands take one or more parameters, these are separate from one another by a comma, <em>but more importantly</em> and frustratingly also from the command (this looks strange to modern eyes)</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>¦ERA,"Hello.bas"
¦REN,"hello2.bas","hello.bas"
</code></pre></div></div>
<p>You do get used to it.</p>
<h2 id="internal-commands">Internal commands</h2>
<p>These commands operate on either the disc or the cassette depending on the current mode (covered in the next section)</p>
<table>
<thead>
<tr>
<th>command</th>
<th>overview</th>
</tr>
</thead>
<tbody>
<tr>
<td>CAT</td>
<td>Catalogue (list) the files on the current device</td>
</tr>
<tr>
<td>LOAD</td>
<td>Load a file into memory</td>
</tr>
<tr>
<td>RUN</td>
<td>Load a basic file and run it</td>
</tr>
<tr>
<td>SAVE</td>
<td>Save data to a file</td>
</tr>
<tr>
<td>CHAIN</td>
<td>Load a basic file into memory replacing any existing program</td>
</tr>
<tr>
<td>CHAIN MERGE</td>
<td>Load a basic file into memory merging it with any existing program</td>
</tr>
<tr>
<td>OPENIN</td>
<td>Opens a file for reading via stream #9</td>
</tr>
<tr>
<td>OPENOUT</td>
<td>Opens a file for writing via stream #9</td>
</tr>
<tr>
<td>CLOSEIN</td>
<td>Closes the current input stream</td>
</tr>
<tr>
<td>CLOSEOUT</td>
<td>Closes the current output stream</td>
</tr>
</tbody>
</table>
<p>This isn’t a locomotive BASIC post so I’ll skip the detail on most of these. The most commonly used command is <code class="language-plaintext highlighter-rouge">cat</code> which lists the files on the current device, <code class="language-plaintext highlighter-rouge">load</code> whick loads basic files and <code class="language-plaintext highlighter-rouge">run</code>, which executes basic programs.</p>
<div class="dbImg zoom200 centeredImg" data-src="cpc/custard-loading.png" alt="Screenshot of a file being loaded"></div>
<div class="dbCaption">
Listing and running a program from disc
</div>
<h2 id="external-commands">External commands</h2>
<p>AMSDOS contains the following following external commands</p>
<table>
<thead>
<tr>
<th>command</th>
<th>description</th>
</tr>
</thead>
<tbody>
<tr>
<td><code class="language-plaintext highlighter-rouge">¦A</code></td>
<td>Select disc A as the current disc</td>
</tr>
<tr>
<td><code class="language-plaintext highlighter-rouge">¦B</code></td>
<td>Select disc B as the current disc</td>
</tr>
<tr>
<td><code class="language-plaintext highlighter-rouge">¦CPM</code></td>
<td>Clear all memory and boot CPM from disc A</td>
</tr>
<tr>
<td><code class="language-plaintext highlighter-rouge">¦DIR</code></td>
<td>Show a listing of the current directory</td>
</tr>
<tr>
<td><code class="language-plaintext highlighter-rouge">¦DISC</code></td>
<td>Swap to disc mode for both input and output</td>
</tr>
<tr>
<td><code class="language-plaintext highlighter-rouge">¦DISC.IN</code></td>
<td>Swap to disc mode for input, leaving output as it was</td>
</tr>
<tr>
<td><code class="language-plaintext highlighter-rouge">¦DISC.OUT</code></td>
<td>Swap to disc mode for output, leaving input as it was</td>
</tr>
<tr>
<td><code class="language-plaintext highlighter-rouge">¦DRIVE</code></td>
<td>Swap drive</td>
</tr>
<tr>
<td><code class="language-plaintext highlighter-rouge">¦ERA</code></td>
<td>Erase a file</td>
</tr>
<tr>
<td><code class="language-plaintext highlighter-rouge">¦REN</code></td>
<td>Rename a file</td>
</tr>
<tr>
<td><code class="language-plaintext highlighter-rouge">¦TAPE</code></td>
<td>Swap to tape mode for both input and output</td>
</tr>
<tr>
<td><code class="language-plaintext highlighter-rouge">¦TAPE.IN</code></td>
<td>Swap to tape mode for input, leaving output as it was</td>
</tr>
<tr>
<td><code class="language-plaintext highlighter-rouge">¦TAPE.OUT</code></td>
<td>Swap to tape mode for output, leaving input as it was</td>
</tr>
<tr>
<td><code class="language-plaintext highlighter-rouge">¦USER</code></td>
<td>Set the current user</td>
</tr>
</tbody>
</table>
<h3 id="setting-the-disc-mode">Setting the disc mode</h3>
<p>The CPC uses chanel / stream #9 in BASIC to read and write files. On an AMSDOS enabled CPC this stream is routed to either disc or tape and can have a different route for both input and output.</p>
<p>The <code class="language-plaintext highlighter-rouge">¦DISC</code> command sets both the input and output media to disc. It is the equivalent of executing the two commands:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>¦DISC.IN
¦DISC.OUT
</code></pre></div></div>
<p>which set the input and output media separately.</p>
<p>The <code class="language-plaintext highlighter-rouge">¦TAPE</code> command sets both the input and output media to tape. It is the equivalent of executing the two commands:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>¦TAPE.IN
¦TAPE.OUT
</code></pre></div></div>
<p>As an example of the use of these commands we can copy a file from tape to disk as follows</p>
<div class="dbImg zoom200 centeredImg" data-src="cpc/disc-tap-mode.png" alt="Screen shot of file copying from tape to disc."></div>
<div class="dbCaption">
Copying from tape to disc with a typo!
</div>
<h3 id="working-with-drives-drives">Working with drives drives</h3>
<p>AMSDOS and the CPC support two drives <code class="language-plaintext highlighter-rouge">A</code> and <code class="language-plaintext highlighter-rouge">B</code>. Notionally the chipset that controls the floppy drives can handle up to four devices, but I have never seen a setup for more than a pair of drives that didn’t require a hardware mod.</p>
<p>To swap to the <code class="language-plaintext highlighter-rouge">B</code> drive we can use either of the following commands:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>¦B
¦DRIVE,"B"
</code></pre></div></div>
<p>To swap back to the <code class="language-plaintext highlighter-rouge">A</code> drive we can similarly use:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>¦A
¦DRIVE,"A"
</code></pre></div></div>
<p>trying to swap to a drive that is has no disk in it, leads to the message</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Drive B: disc missing
Retry, Ignore or Cancel
</code></pre></div></div>
<p>And as in most disc commands, Retry and Ignore are wholely useless and Cancel is the only one to choose.</p>
<h3 id="listing-files">Listing files</h3>
<p>To get a list of files on the disc we can use either the internal <code class="language-plaintext highlighter-rouge">cat</code> command or the external <code class="language-plaintext highlighter-rouge">¦DIR</code> command.</p>
<p><code class="language-plaintext highlighter-rouge">CAT</code> returns the list of files on the currently selected device in the order that it encounters them, <em>and</em> also shows the file size.</p>
<p><code class="language-plaintext highlighter-rouge">¦DIR</code> returns the list of files on the disc but in alphabetical order, however it does not report the size of files. <code class="language-plaintext highlighter-rouge">¦DIR</code> does however always show disc content even when BASIC is in tape mode and supports:</p>
<ul>
<li>wildcards</li>
<li>multi-users</li>
<li>showing the content of a drive even if it isn’t the currently selected one</li>
</ul>
<p>Both commands display the free space on the disc in kilobytes</p>
<div class="dbImg zoom200 centeredImg" data-src="cpc/cat-vs-dir.png" alt="Screen shot of cat and dir commands."></div>
<div class="dbCaption">
cat vs dir.
</div>
<p>To use wildcards, <code class="language-plaintext highlighter-rouge">¦DIR</code> can be invoked as follows:</p>
<div class="dbImg zoom200 centeredImg" data-src="cpc/dir-wildcards.png" alt="Screen shot of cat and dir commands."></div>
<div class="dbCaption">
|dir with wild cards.
</div>
<p>To view the content of a non-selected drive:</p>
<div class="dbImg zoom200 centeredImg" data-src="cpc/dir-b.png" alt="Screen shot of a directory for an alternative drive."></div>
<div class="dbCaption">
Listing of the contents of drive B when drive A is the current drive.
</div>
<h3 id="deleting-files">Deleting files</h3>
<p>The erase command <code class="language-plaintext highlighter-rouge">¦ERA</code> is used to delete files, presumably erase was chose as the keyword because <code class="language-plaintext highlighter-rouge">delete</code> is already present Locomotive BASIC.</p>
<p><code class="language-plaintext highlighter-rouge">¦ERA</code> like <code class="language-plaintext highlighter-rouge">¦DIR</code> can operate on multiple files via wildcards and delete files on alternative drives</p>
<div class="dbImg zoom200 centeredImg" data-src="cpc/era.png" alt="Screen shot of erasing files."></div>
<div class="dbCaption">
Erasing files on drive A while drive B is selected. Rad!
</div>
<h3 id="multi-user-access">Multi user access</h3>
<p>If you read through this post a thousand times one thing you won’t find is any commands to create or change directories, they don’t exist in AMSDOS.</p>
<p>If multiple people are using the same computer and disc, how do we segregate the files for different users? The answer to this is via the <code class="language-plaintext highlighter-rouge">¦USER</code> command. AMSDOS supports up to 16 users, identified by a number 0 to 15.</p>
<p>You may have noticed this when listing files, if you look at the preceding screenshots the <code class="language-plaintext highlighter-rouge">¦DIR</code> command outputs and a header <code class="language-plaintext highlighter-rouge">Drive A: user 0</code>, showing that by default we operate as user 0 and see the files for that user.</p>
<div class="dbImg zoom200 centeredImg" data-src="cpc/user.png" alt="Snippet of the user line"></div>
<div class="dbCaption">
User 0 is the default user
</div>
<p>If we perform a directory listing on drive A as user 0, then swap to user 10 and do the same, then we will see no files. The disk free space is still that same of course as there is no magic disc space pixie.</p>
<div class="dbImg zoom200 centeredImg" data-src="cpc/user-10.png" alt="User 10 has no files"></div>
<p>we can create a file as user 10 and save it, the file will then show up when listing files as user 10, but not user 0.</p>
<div class="dbImg zoom200 centeredImg" data-src="cpc/user-10-new-file.png" alt="Snippet of the user line"></div>
<div class="dbCaption">
User 0 is the default user
</div>
<p>Finally when acting as user 10 you can view any other users content by prefixing a filename, or wild card with the desired user number and a colon.</p>
<div class="dbImg zoom200 centeredImg" data-src="cpc/user-10-see-user-0-file.png" alt="Cross user dir"></div>
<div class="dbCaption">
User 10 taking a sneak peek at user 0's files
</div>
<p>Similarly you can specify the specify the user number for run save and load commands too.</p>
<p>What can’t do however combine a drive letter and a user as far as I can tell. If you are user 10 on drive A, then you are user 10 on drive B. If you want to see user 0’s files on another drive, swap to it.</p>
<h3 id="renaming-files">Renaming files</h3>
<p>The rename command changes file names, it is also used to assign files to different users.</p>
<p>to rename a file use the <code class="language-plaintext highlighter-rouge">|ren</code> command and specify the new name, then the original name</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>|REN,"NEWNAME.BAS","ORIGINAL.BAS"
</code></pre></div></div>
<p>which will result in the file having the new name.</p>
<div class="dbImg zoom200 centeredImg" data-src="cpc/rename.png" alt="Renaming a file"></div>
<p><code class="language-plaintext highlighter-rouge">|ERA</code> can also be used to move files between numbered users on the disc.</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>|REN,"0:NEWNAME.BAS","10:ORIGINAL.BAS"
</code></pre></div></div>
<p>The file <code class="language-plaintext highlighter-rouge">original.bas</code> owned by user <code class="language-plaintext highlighter-rouge">10</code>, is being renamed to <code class="language-plaintext highlighter-rouge">newname.bas</code> owned by user <code class="language-plaintext highlighter-rouge">0</code>. I’m showing it this way to highlight the name can change as well as the user, in practice the name stays the same.</p>
<p>So to move <code class="language-plaintext highlighter-rouge">hello.bas</code> from user 10 to user 0, we do:</p>
<div class="dbImg zoom200 centeredImg" data-src="cpc/rename-change-user.png" alt="moving a file between users"></div>
<p>if you omit the user number for the destination file name it defaults to the current user. So in our previous example I logged in as user 0, the following two commands are identical</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>|REN,"0:NEWNAME.BAS","10:ORIGINAL.BAS"
|REN,"NEWNAME.BAS","10:ORIGINAL.BAS"
</code></pre></div></div>
<h3 id="the-cpm-command">The CP/M command</h3>
<p>With a CP/M boot disc in drive A, running the <code class="language-plaintext highlighter-rouge">¦CPM</code> command clears memory and boots in to CP/M. The CPC-464 came with CP/M version 2.2, the CPC-6128 came with both version 2.2 and the newer CP/M Plus edition.</p>
<div class="dbImg zoom200 centeredImg" data-src="cpc/cpm-plus.png" alt="Screen shot CP/M plus."></div>
<div class="dbCaption">
CPC booted into CP/M plus
</div>
<h2 id="wrap-up">Wrap up</h2>
<p>Looking at AMSDOS in retrospect, it’s a quirky beast, however that’s looking through a lens that’s nearly 30 years wide. Across DOS and Unix, we’ve become used to directories and modern command syntax. However, working as a jobbing games programmer on the CPC series of computers for several years, AMSDOS just felt modern and dare I say it: cool?</p>
<p>I’ve really enjoyed playing around with AMSDOS and re-learning forgotten skills, its helped me reengage with the CPC and kick started a minor collecting mania for ROMS that extend it (more of which in a later post).</p>
<p>This concludes my quick (or long and rambling) run through the capabilities of AMSDOS and how to manipulate files. Hope it’s been of help.</p>
<p><a href="https://www.overtakenbyevents.com/amstrad-cpc-amsdos-commands/">Amstrad CPC: AMSDOS, disk commands</a> was originally published by David Black at <a href="https://www.overtakenbyevents.com">Overtaken by events</a> on August 19, 2022.</p>https://www.overtakenbyevents.com/fireman-fred-written-in-godot2021-04-02T00:00:00+01:002021-04-02T00:00:00+01:00David Blackhttps://www.overtakenbyevents.comdavid_black_uk@yahoo.com
<p>I wrote before about my first published game <a href="/Tell-us-about-the-war-granddad/">Fireman Fred</a>, how bad it was, and how fond of it I am.</p>
<p>I started and mostly completed a re-write of Fred in Z80 assembly language for the spectrum, but progress was realy, really slow. Recently
I got thinking about how easy it might be to try re-writing Fred using a modern game engine, and progress has been really, really, rapid.</p>
<p>I chose the Godot game engine for my rewrite, some pretty strict limitations for colors and resolutions, and the result is:</p>
<video class="centeredImg" src="../images/fireman-fred-written-in-godot/fred-demo1.mp4" poster="../images/fireman-fred-written-in-godot/demo-poster.png" width="512" height="384" controls="" preload=""></video>
<p>About a week of effort, and of course, you can <strong><em>»</em></strong> <a href="../fred">play it online</a> <strong><em>«</em></strong>.</p>
<p>Hope you enjoy playing this, check back for future updates.</p>
<p><a href="https://www.overtakenbyevents.com/fireman-fred-written-in-godot/">Son of Fred: Fireman Fred, rises from the dead</a> was originally published by David Black at <a href="https://www.overtakenbyevents.com">Overtaken by events</a> on April 02, 2021.</p>https://www.overtakenbyevents.com/onmi-128hq-part3-video2019-02-24T00:00:00+00:002019-02-24T00:00:00+00:00David Blackhttps://www.overtakenbyevents.comdavid_black_uk@yahoo.com
<h1 id="intro">Intro</h1>
<p>This is part three of a series covering my Omni 128HQ Desktop from <a href="https://retroradionics.co.uk/">retro-radionics</a>. The Omni 128HQ is a modern Sinclair Spectrum recreation with many special features. So far in this series I have covered: <a href="/onmi-128hq-part1-overview/">An overview / review of the Omni device</a> and <a href="/onmi-128hq-part2-switches/">a guide to configuring the Omni via DIP switches</a>.</p>
<p>In this post we head off into the unchartered waters of video output, which is, surprisingly tricky.</p>
<p>First of all let me address the elephant in the room: HDMI. While there is a port on the Omni for HDMI, currently it is inoperative. I bought the Omni because of HDMI and was very unhappy to discover that it wasn’t implemented.</p>
<p>There has been talk of firmware updates and of a daughter board being developed, but so far there is no official word on a release timeframe. It is very likely, because HDMI is a licensed standard, that when the feature is enabled, there will be a cost. If HDMI does require a daughter board there will also be an additional three to four months delay for manufacturing and shipping.</p>
<p>In the spirt of not being too salty about HDMI, let’s look at the available options to view your omni on a TV or monitor. Unfortunately everyone of them currently comes at a cost.</p>
<h2 id="scart-direct-to-tv">SCART direct to TV</h2>
<p>When I first connected my Omni to my living room TV I was amazed at how sharp, bright and colourful it was. However it soon became apparent that it was <em>too</em> bright.</p>
<p>Here’s a bit of Spectrum basic to show bright and normal colours side-by-side.</p>
<div class="dbImg centeredImg" data-src="omni-128-desktop/bright_code.png" alt="Code to descriminate bright pixels from non-bright pixels"></div>
<div class="dbCaption">
A bit of basic to show how bright the omni is
</div>
<p>When we run this on a real ZX Spectrum we get the result shown below on the left. When we run the same code on the omni, we get the results one the right.</p>
<div class="dbImg centeredImg" data-src="omni-128-desktop/bright_fail.png" alt="Results of running the code on a real speccy"></div>
<div class="dbCaption">
My eyes, they burn!
</div>
<p>This is a known issue with the current revision of the Omni Desktop. The board as shipped has zero Ohm resistors in positions R19, R20 and R21. These should be 68 Ohms.</p>
<div class="dbImg centeredImg" data-src="omni-128-desktop/bright_resistors.png" alt="Results of running the code on a real Speccy"></div>
<div class="dbCaption">
My eyes, they burn!
</div>
<p>If soldering surface mount resistors is not your cup of tea, and it absolutely isn’t mine, you have two choices if you want SCART to your TV.</p>
<ul>
<li>Open up the provided SCART cable and solder in three non-surface mount resistors inline in the R/G/B wires (a task I would be confident in doing)</li>
<li>By a SEGA Megadrive RGB to SCART adaptor, or even a custom OMNI one</li>
</ul>
<p>For TV output I went with the pre-made <a href="https://www.ebay.co.uk/itm/OMNI-128-HQ-High-Quality-RGB-Scart-TV-Lead-Video-Cable/253568142226">OMNI 128 HQ High Quality RGB SCART TV Lead Video Cable</a>, which cost £12 and worked like a dream on my TV.</p>
<div class="dbImg centeredImg" data-src="omni-128-desktop/rcs.png" alt="Results of running the code on a real Speccy"></div>
<div class="dbCaption">
<a href="https://retrocomputershack.com/">Have a hunt around the retro computer shack, lots of cool adaptors for many platforms.</a>
</div>
<h2 id="hdmi">HDMI</h2>
<p>Let’s face it, HDMI is what I want, so my thoughts turned to RGB to HDMI conversion. Like every thing else related to video on the Omni this proved to be a challenge, however none of it was the Omni’s fault.</p>
<h3 id="making-a-mistake">Making a mistake</h3>
<p>My first attempt at getting HDMI conversion to work was to buy the <a href="https://www.amazon.co.uk/gp/product/B0784JCCXS/ref=ppx_yo_dt_b_asin_title_o05__o00_s00?ie=UTF8&psc=1">AMANKA SCART To HDMI Converter 1080P SCART to HDMI Adapter</a> for £17. <strong>Do not buy this</strong>.</p>
<div class="dbImg zoom50 centeredImg" data-src="omni-128-desktop/rgb-to-scart.png" alt="Picture of my rgb to scart converter i prurchased from Amazon."></div>
<div class="dbCaption">
A cheap and cheerful RGB to SCART converter.
</div>
<p>What it appears to do, is only process the composite signal. I guess it’s a fair reflection of what the spectrum would have looked like on a TV (i.e. fuzzy and out of focus!)</p>
<p>The following clip shows the output of the Omni running through this converter. It’s worth noting how <em>fuzzy</em> the miner willy characters are at the bottom of the screen. However being composite, the bright mode issue is not present and this was captured using the standard SCART cable provided with the Omni.</p>
<video class="centeredImg" src="../images/omni-128-desktop/capture_composite.mp4" width="640" height="360" controls="" preload=""></video>
<h3 id="correcting-the-mistakeish">Correcting the mistake(ish)</h3>
<p>So Plan A failed, there must be a Plan B, correct? And there was. As usual the answer was to throw (slightly) more money at the problem!</p>
<p>Plan B was the snappily named <a href="https://www.ebay.co.uk/itm/New-SCART-HDMI-To-HDMI-HD-Video-Converter-Box-720P-1080P-3-5mm-Coaxial-Audio-Out/292855206364?ssPageName=STRK%3AMEBIDX%3AIT&var=591628881354&_trksid=p2057872.m2749.l2649">New SCART+HDMI To HDMI HD Video Converter Box 720P 1080P 3.5mm Coaxial Audio Out</a>.</p>
<div class="dbImg zoom50 centeredImg" data-src="omni-128-desktop/rgb_converter.png" alt="Code to descriminate bright pixels from non-bright pixels"></div>
<div class="dbCaption">
A better class of converter
</div>
<p>This was a little more expensive at £20 than the AMANKA, but much better quality. Would I recommend this? The answer is yes, with a caveat (read about the power adapter later).</p>
<video class="centeredImg" src="../images/omni-128-desktop/capture_rgb.mp4" width="640" height="360" controls="" preload=""></video>
<p>This capture shows the crisp output from the new SCART to HDMI converter. The miner willies marching at the bottom of the screen are finely detailed. All in all a night and day different from the previous composite solution. The bright mode issue is still present, but that’s because I didn’t use the correct SCART cable to record the capture.</p>
<h4 id="but">But…</h4>
<p>It’s never easy is it? The second SCART to HDMI adaptor I ordered was from eBay (hence the cheap price I guess). What it shipped with was the wrong power adaptor. The terminal connector did not fit the unit as supplied.</p>
<p>A couple of exchanges with their support people, which was painless and polite, got me a refund sufficient to buy a matching power supply on amazon UK.</p>
<p>So as I mentioned with that Caveat in mind I would recommend this adaptor. Perhaps you could enquire up front and make sure they do dispatch the correct adapter!</p>
<h2 id="conclusions">Conclusions</h2>
<p>The Omni 128k Desktop is not without issues when it comes to video all of these are, or will be, fixable by throwing money at them. It’s a pity that the board does not come with built in HDMI. It’s a bigger pity that the 68 ohm resisters missing from the board mandate the purchase of a separate cable.</p>
<p>To achieve HDMI output from the Omni I had to buy an HDMI converter for £20 and a RGB to SCART cable for £12, if you add this to the base price for the Omni we are now looking at north of £120 to get a functional, Omni. Worth it? Hell yes, but for the love of God, can get the HDMI output on the board working.</p>
<p>Next up: my LCD screen has arrived, Stay tuned…</p>
<p><a href="https://www.overtakenbyevents.com/onmi-128hq-part3-video/">Omni 128HQ Desktop #3 - Video</a> was originally published by David Black at <a href="https://www.overtakenbyevents.com">Overtaken by events</a> on February 24, 2019.</p>https://www.overtakenbyevents.com/onmi-128hq-part2-switches2019-01-27T00:00:00+00:002019-01-27T00:00:00+00:00David Blackhttps://www.overtakenbyevents.comdavid_black_uk@yahoo.com
<h1 id="intro">Intro</h1>
<p>In <a href="/onmi-128hq-part1-overview/">part one of this series</a> I outlined the functionality of the Omni 128HQ Desktop from <a href="https://retroradionics.co.uk/">retro-radionics</a>, In this post I’m going to discuss how to configure the Omni via DIP switches.</p>
<p>The DIP (Dual Inline Package, should you care) switches are located on the right hand side of the Omni. The defaults that came with my Omni are shown below.</p>
<div class="dbImg zoom100 centeredImg" data-src="omni-128-desktop/omni_switches.png" alt="Picture of the default configuration settings for the DIP switches."></div>
<div class="dbCaption">
Out of the box settings for <em>my</em> Omni.
</div>
<p>The switches are divided into sections by function. The following diagram shows the default switch configuration that my Omni shipped with.</p>
<table class="omni-dip">
<tr>
<td class="h"><div class="i"></div></td> <td class="h"><div class="i"></div></td><td class="h"><div class="i"></div></td><td class="d"><div class="i"></div></td>
<td class="d"><div class="o"></div></td><td class="r"><div class="i"></div></td><td class="r"><div class="i"></div></td><td class="r"><div class="i"></div></td>
</tr>
<tr>
<td class="h"><div class="o"></div></td> <td class="h"><div class="o"></div></td><td class="h"><div class="o"></div></td><td class="d"><div class="o"></div></td>
<td class="d"><div class="i"></div></td><td class="r"><div class="o"></div></td><td class="r"><div class="o"></div></td><td class="r"><div class="o"></div></td>
</tr>
<tr>
<td class="h">1</td><td class="h">2</td><td class="h">3</td><td class="d">4</td><td class="d">5</td><td class="r">6</td><td class="r">7</td><td class="r">8</td>
</tr>
</table>
<p>Switches are either on (up position) or off (down position), in the preceding example all switches are on except switch 5.</p>
<p>There are three banks of switches:</p>
<ul>
<li>1, 2, 3: Hardware settings (purple area)</li>
<li>4, 5: divMMC configuration (cyan area)</li>
<li>6, 7, 8: Rom Selection (green area)</li>
</ul>
<p>Not all switches in all combinations necessarily have meaning.</p>
<p>The switches themselves are very small and you will need to use a tool to set them. The perfect tool for the job is the humble cocktail stick. Don’t use sharp objects as they may damage the switches.</p>
<div class="dbImg zoom50 centeredImg" data-src="omni-128-desktop/picks.png" alt="Picture of some cocktail sticks."></div>
<div class="dbCaption">
A £1 investment will get you a lifetime supply of DIP switch manipulation tools (unless you decide to put blocks of cheese and cocktail onions on them).
</div>
<h2 id="official-documentation">Official documentation</h2>
<p>The official FAQ for the Omni is available on the <a href="https://www.facebook.com/groups/519934131721262/files/">ZX omni Facebook page</a> (You’ll have to apply for membership, I don’t think it’ll be refused!)</p>
<p>The DIP Switch settings outlined there formed the basis of this text, but I found that the implementation of the Omni differs from the description posted there.</p>
<h2 id="hardware-switches">Hardware switches</h2>
<p>The first switch bank (purple) has three switches (1, 2, 3) that control the hardware configuration.</p>
<table>
<thead>
<tr>
<th>switch</th>
<th>description</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td>On enables divMMC system support, off disables it.</td>
</tr>
<tr>
<td>2</td>
<td>On allows the divMMC firmware to be flashed, off means read-only</td>
</tr>
<tr>
<td>3</td>
<td>On enables Kempston joystick support</td>
</tr>
</tbody>
</table>
<p>Several of the ROMs that are supported require divMMC support to be disabled as they conflict.</p>
<h2 id="divmmc-switches">divMMC switches</h2>
<p>The second (cyan) bank of switches specify the of firmware supported by divMMC. There are two switches and so 4 options.</p>
<table>
<tr>
<th>Switches</th><th>Description</th>
</tr>
<tr>
<td>
<table class="omni-dip">
<tr>
<td class="d"><div class="o"></div></td>
<td class="d"><div class="o"></div></td>
</tr>
<tr>
<td class="d"><div class="i"></div></td>
<td class="d"><div class="i"></div></td>
</tr>
<tr>
<td class="d">4</td>
<td class="d">5</td>
</tr>
</table>
</td>
<td> 00 - Enable UnoDOS 3 support </td>
</tr>
<tr>
<td>
<table class="omni-dip">
<tr>
<td class="d"><div class="o"></div></td>
<td class="d"><div class="i"></div></td>
</tr>
<tr>
<td class="d"><div class="i"></div></td>
<td class="d"><div class="o"></div></td>
</tr>
<tr>
<td class="d">4</td>
<td class="d">5</td>
</tr>
</table>
</td>
<td> 01 - Enable UnoDOS 3 support </td>
</tr>
<tr>
<td>
<table class="omni-dip">
<tr>
<td class="d"><div class="i"></div></td>
<td class="d"><div class="o"></div></td>
</tr>
<tr>
<td class="d"><div class="o"></div></td>
<td class="d"><div class="i"></div></td>
</tr>
<tr>
<td class="d">4</td>
<td class="d">5</td>
</tr>
</table>
</td>
<td> 10 - Enable esxDOS 0.8.6 support. This is one area where my switches a flat out different to the ones mentioned in the FAQ, the FAQ has the two divMMC switch settings the wrong way round for my setup.. </td>
</tr>
<tr>
<td>
<table class="omni-dip">
<tr>
<td class="d"><div class="i"></div></td>
<td class="d"><div class="i"></div></td>
</tr>
<tr>
<td class="d"><div class="o"></div></td>
<td class="d"><div class="o"></div></td>
</tr>
<tr>
<td class="d">4</td>
<td class="d">5</td>
</tr>
</table>
</td>
<td> 11 - Enable esxDOS 0.8.5 support see above</td>
</tr>
</table>
<p>I expect the meanings of these switches to change over time as different versions of firmware are released.</p>
<h2 id="rom-selection-switches">ROM selection switches</h2>
<p>The final bank of three switches (green) configure what ROM is being used for the emulation. Three switches give us 8 combinations, all of which are used.</p>
<table>
<tr>
<th>Switches</th><th>Description</th>
</tr>
<tr>
<td>
<table class="omni-dip">
<tr><td class="r"><div class="o"></div></td><td class="r"><div class="o"></div></td><td class="r"><div class="o"></div></td></tr>
<tr><td class="r"><div class="i"></div></td><td class="r"><div class="i"></div></td><td class="r"><div class="i"></div></td></tr>
<tr><td class="r">6</td><td class="r">7</td><td class="r">8</td></tr>
</table>
</td>
<td> 000 - Boots into the Retroleum (1.3.4) test ROM <sup>1</sup>. This can test various configurations, physical memory, graphics etc. </td>
</tr>
<tr>
<td>
<table class="omni-dip">
<tr><td class="r"><div class="o"></div></td><td class="r"><div class="o"></div></td><td class="r"><div class="i"></div></td></tr>
<tr><td class="r"><div class="i"></div></td><td class="r"><div class="i"></div></td><td class="r"><div class="o"></div></td></tr>
<tr><td class="r">6</td><td class="r">7</td><td class="r">8</td></tr>
</table>
</td>
<td> 001 - This is documented as running the Jupiter ACE emulator. But on my revision this runs a set of diagnostics from the <a href="https://github.com/brendanalford/zx-diagnostics/wiki">ZX Spectrum Diagnostics project</a> when divMMC is disabled. However when divMMC is enabled this jumps straight into the divMMC interface without the need to press the NMI button (Not too sure this is a supported config). </td>
</tr>
<tr>
<td>
<table class="omni-dip">
<tr><td class="r"><div class="o"></div></td><td class="r"><div class="i"></div></td><td class="r"><div class="o"></div></td></tr>
<tr><td class="r"><div class="i"></div></td><td class="r"><div class="o"></div></td><td class="r"><div class="i"></div></td></tr>
<tr><td class="r">6</td><td class="r">7</td><td class="r">8</td></tr>
</table>
</td>
<td> 010 - Runs the ZX81+ Emulator<sup>1</sup> 3.09 by <a href="http://www.fruitcake.plus.com/"> Paul Farrow</a>. Available RAM is configurable up to a whopping 32k!
</td>
</tr>
<tr>
<td>
<table class="omni-dip">
<tr><td class="r"><div class="o"></div></td><td class="r"><div class="i"></div></td><td class="r"><div class="i"></div></td></tr>
<tr><td class="r"><div class="i"></div></td><td class="r"><div class="o"></div></td><td class="r"><div class="o"></div></td></tr>
<tr><td class="r">6</td><td class="r">7</td><td class="r">8</td></tr>
</table>
</td>
<td> 011 - Boots the 1985 128K basic ROM<sup>1</sup>.</td>
</tr>
<tr>
<td>
<table class="omni-dip">
<tr><td class="r"><div class="i"></div></td><td class="r"><div class="o"></div></td><td class="r"><div class="i"></div></td></tr>
<tr><td class="r"><div class="o"></div></td><td class="r"><div class="i"></div></td><td class="r"><div class="o"></div></td></tr>
<tr><td class="r">6</td><td class="r">7</td><td class="r">8</td></tr>
</table>
</td>
<td> 101 - Runs the Amstrad +2e BASIC, with 128K available. When divMMC is on, USR0 mode zero is available. USR0 mode allows applications to access all of the hardware functionality of the device (sound cards etc). Try this mode if a hardware demo isn't working for you. </td>
</tr>
<tr>
<td>
<table class="omni-dip">
<tr><td class="r"><div class="i"></div></td><td class="r"><div class="i"></div></td><td class="r"><div class="o"></div></td></tr>
<tr><td class="r"><div class="o"></div></td><td class="r"><div class="o"></div></td><td class="r"><div class="i"></div></td></tr>
<tr><td class="r">6</td><td class="r">7</td><td class="r">8</td></tr>
</table>
</td>
<td> 110 - Emulates the classic 48k Spectrum basic from 1982. The best mode for compatibility with <em>ahem...</em> your saved games. </td>
</tr>
</table>
<p><sup>1</sup> divMMC support must be disabled to support these modes.</p>
<h2 id="wrapping-it-up">Wrapping it up</h2>
<p>There is a lot of flexibility in the design of the Omni, accessible via the configuration switches.</p>
<p>The derby BASIC ROM lets me experience functionality that was unavailable to me during my time using the Spectrum as a daily driver. The divMMC support allows me to try games I never had a chance to play. Finally the AY-3-8912 sound chip support brings a whole experience to gaming.</p>
<p>In the near term the Omni is here to serve two purposes for me:</p>
<ul>
<li>To test my own code, created on a PC, accessed via divMMC</li>
<li>To let me experience Spectrum games once again on hardware that feels real.</li>
</ul>
<p>So my DIP switch settings for the near future are going to be:</p>
<table class="omni-dip">
<tr>
<td class="h"><div class="i"></div></td> <td class="h"><div class="o"></div></td><td class="h"><div class="i"></div></td><td class="d"><div class="i"></div></td>
<td class="d"><div class="i"></div></td><td class="r"><div class="i"></div></td><td class="r"><div class="i"></div></td><td class="r"><div class="o"></div></td>
</tr>
<tr>
<td class="h"><div class="o"></div></td> <td class="h"><div class="i"></div></td><td class="h"><div class="o"></div></td><td class="d"><div class="o"></div></td>
<td class="d"><div class="o"></div></td><td class="r"><div class="o"></div></td><td class="r"><div class="o"></div></td><td class="r"><div class="i"></div></td>
</tr>
<tr>
<td class="h">1</td><td class="h">2</td><td class="h">3</td><td class="d">4</td><td class="d">5</td><td class="r">6</td><td class="r">7</td><td class="r">8</td>
</tr>
</table>
<p>So i’ll have: divMMC, hold the firmware update, Kempston joystick, heavy on the divMMC 8.6 support and a vanilla 48K Spectrum for dessert.</p>
<p><a href="https://www.overtakenbyevents.com/onmi-128hq-part2-switches/">Omni 128HQ Desktop #2 - Configuration</a> was originally published by David Black at <a href="https://www.overtakenbyevents.com">Overtaken by events</a> on January 27, 2019.</p>https://www.overtakenbyevents.com/onmi-128hq-part1-overview2019-01-19T00:00:00+00:002019-01-19T00:00:00+00:00David Blackhttps://www.overtakenbyevents.comdavid_black_uk@yahoo.com
<h1 id="intro">Intro</h1>
<p>While software emulators are fun, they’re not the real thing. One thing I missed was the visceral feel of the dead flesh keyboard!</p>
<p>I have a couple of reconditioned spectrums, most with composite video conversions. However loading games was always an issue. I had just decided to buy a DIVMMC from <a href="https://www.thefuturewas8bit.com/">TF8b</a> to allow me to load speccy games from an SD card, when I came across the <em>Omni 128HQ Desktop</em> from <a href="https://retroradionics.co.uk/">RetroRadionics</a>. While the Omni was twice the price, it does come with an entire new spectrum attached!</p>
<p>Let’s be clear, the Omni took a long time to arrive. A very long time. However considering it’s hand assembled in China, you shouldn’t be too surprised. Once I received the shipping notice (elevated heart rate of happiness time), I noticed the shipping time was <em>two months</em> (Dry mouth of disappointment time). But it did arrive and yes it was worth the wait.</p>
<div class="dbImg zoom80 centeredImg" data-src="omni-128-desktop/omni_top.png" alt="Picture of the Omni 128HQ Desktop from above."></div>
<div class="dbCaption">
Omni 128HQ Desktop is almost indistinguishable from the original; top-down. Just a
few buttons peeking out.
</div>
<h2 id="whats-in-the-box">What’s in the box?</h2>
<p>The Omni comes in the box with an RGB to SCART lead, a modern power supply and of course the Omni 128HQ Desktop device itself.</p>
<div class="dbImg zoom80 centeredImg" data-src="omni-128-desktop/boxcontent.png" alt="Picture of the Omni 128HQ Desktop box content including device, power supply and scart cable."></div>
<div class="dbCaption">
This is what's in the box on delivery
</div>
<p>That’s everything you need to load games from tape. In other words, SD card not included!</p>
<h2 id="omni-specifications">Omni Specifications</h2>
<p>The Omni is based on the Harlequin Board designed and open sourced by <a href="http://trastero.speccy.org/cosas/JL/Superfo-Harlequin-128K/128K-i.html">SuperFo</a>. It offers:</p>
<ul>
<li>128K ram</li>
<li>Integrated divMMC double SD card interface</li>
<li>Two 9 pin Joystick ports</li>
<li>RGB out</li>
<li>Composite out</li>
<li>HDMI out <sup>1</sup></li>
<li>Power button</li>
<li>Reset switch button</li>
<li>Battery operation <sup>2</sup></li>
</ul>
<p>Let’s get those pesky footnotes out of the way first:</p>
<p><sup>1</sup> There is an HDMI port, but it doesn’t work at the moment, may need a daughter board to
work in the future, may never work. Brutal, but true. Don’t buy this to use via HDMI, you
will be disappointed. Or use a converter.</p>
<p><sup>2</sup> There are empty slots for batteries in the desktop edition, these are really there for the laptop version. These do work on the Desktop Omni, but there are concerns that the power brick, supplied with the the Omni Desktop may not be able to power them and may get really <em>hot</em>. The screen for the laptop comes with a beefier power supply to charge the batteries (apparently). I don’t know I don’t own the screen, <em>yet</em>.</p>
<p>Those two caveats aside this really is a great toy.</p>
<h3 id="128k-ram">128k ram</h3>
<p>So the amount of RAM available is not exactly a headline grabbing amount in today’s world. But it does hint that the Omni is capable of emulating more than just the 48K Spectrum. In fact the Omni can operate as a:</p>
<ul>
<li>ZX81 <sup>3</sup></li>
<li>Jupiter Ace <sup>3</sup></li>
<li>Spectrum 48k</li>
<li>Spectrum 128 (Toast Rack) - AY-3-8912 sound chip</li>
<li>Spectrum +2e - AY-3-8912 sound chip</li>
</ul>
<p><sup>3</sup> No support for divMMC in these modes.</p>
<h2 id="a-tour-around-the-omni">A tour around the Omni</h2>
<p>Let’s take a look around the Omni and see the available ports and switches</p>
<h3 id="the-right-side">The right side</h3>
<p>The right side of the Omni is the busiest in terms of ports and switches. There’s a lot going on here!</p>
<div class="dbImg zoom80 centeredImg" data-src="omni-128-desktop/omni_right.png" alt="Picture of the Omni 128HQ Desktop from the right."></div>
<div class="dbCaption">
Omni 128HQ Desktop ports and switches.
</div>
<h4 id="integrated-divmmc-double-sd-card-interface">Integrated divMMC double SD card interface</h4>
<p>Situated to the left of the image above are the two SD card slots for the divMMC.
This was one of the major deciding factors for me. The divMMC allows you to load games and applications from SD Card media. It supports both standard and mini SD cards. One thing to be aware of is that the divMMC and associated firmware is a little sensitive about what cards they support. I went with a <a href="https://www.amazon.co.uk/gp/product/B00MZ5T98M/ref=ppx_yo_dt_b_asin_title_o02__o00_s00?ie=UTF8&psc=1">4GB Kingston card</a> (that’s not an affiliate link!).</p>
<p>There are two operating systems that the hardware supports: ESXDOS; a DOS like operating system and UNODOS; a more Unix like operating system. I will cover the installation and operation of these two systems in a future post.</p>
<p>Both of these systems are configured by setting DIP switches and both are accessed by pressing the red, NMI (non maskable interrupt) switch on the right side of the Omni.</p>
<h4 id="switches">Switches</h4>
<p>So, so, many switches, too many to detail in this post, but these switches are used to:</p>
<ul>
<li>Configure the version of ZX Spectrum being run</li>
<li>Set the amount of available memory</li>
<li>Test the ZX Omni hardware</li>
<li>Update the ZX Omni Firmware</li>
</ul>
<h4 id="two-9-pin-joystick-ports">Two 9 pin Joystick ports</h4>
<p>Situated at the right hand side of the image above are the two 9 pin Joystick ports.
One port is for Kempston style joysticks (and therefore Sega Megadrive controllers should work) and one is for Sinclair/Atari style joysticks (<em>not Amstrad ones, they don’t work</em>)</p>
<h3 id="the-back-side">The back side</h3>
<p>The back side of the Omni is similar to the original spectrum with a couple of nice additions.</p>
<div class="dbImg zoom80 centeredImg" data-src="omni-128-desktop/omni_back.png" alt="Picture of the Omni 128HQ Desktop from the right."></div>
<div class="dbCaption">
Omni 128HQ Desktop rear view.
</div>
<h4 id="power-expansion-and-cassette">Power, expansion and cassette</h4>
<p>At the far left of the back side of the Omni is the blue on/off switch for the device. This was a feature sorely missed from the original 48K Spectrum and a welcome addition.</p>
<p>The power supply input is situated below the on/off switch. The provided power supply is rated as 9V at 3.0A it has a quality feel about it.</p>
<p>The expansion bus is situated to the right of the power socket. Comparing the Omni to an original spectrum shows that the circuit board is thinner by a significant amount. I’m not sure if the thinner board will grip older addons with thicker edge connectors. Actually I’d think long and hard before connecting anything to this!</p>
<p>To the right of the expansion slot is the mic and ear connectors for the cassette system. This is one of the few areas where the Omni differs from the Spectrum in branding, these ports are not marked.</p>
<p>The Mic and ear connectors also differ from the spectrum in function, the ear connector is stereo out for the AY-3-8912 sound chip and the mic connector functions as both the input and output for the cassette.</p>
<h4 id="rgb-composite-and-hdmi-out">RGB, Composite and HDMI out</h4>
<p>At the right hand side of the back of the Omni are the HDMI and RGB out. I’ve mentioned previously the issues with the Omni and HDMI and I’m not going to rehash that.</p>
<p>The provided SCART cable that comes with the Omni when attached to the RGB input of a modern TV is pin sharp, but the colour calibration is incorrect. This should have been the best quality output I have seen on a Spectrum when attached to a real TV, but normal and bright colours are the same. Pity.</p>
<h3 id="the-left-side">The left side</h3>
<div class="dbImg zoom80 centeredImg" data-src="omni-128-desktop/omni_left.png" alt="Picture of the Omni 128HQ Desktop from the left."></div>
<div class="dbCaption">
Omni 128HQ left view. Nothing to see here, please move on
</div>
<p>There’s not a lot going on here. One solitary reset button. However like the power switch on the rear, the reset switch is another feature missing from the Spectrum and a welcome addition here.</p>
<h2 id="wrapping-up">Wrapping up</h2>
<p>The retro computing scene has seen a plethora of hardware projects in the last year or so. The <em>Spectrum next</em> group appears to be grinding along but with very little hardware available. The <em>Spectrum Vega</em> team appears to be spending more time in court than they did in development. The Omni desktop project by comparison appears to be a solid offering.</p>
<p>The Omni 128HQ Desktop is a great piece of kit. There are a few snags with it at the moment but there are work arounds for some of them (more on that in another post) and others will be remedied by firmware updates or daughter boards.</p>
<p>Go on, treat yourself (just be prepared to wait a little while for delivery).</p>
<p><a href="https://www.overtakenbyevents.com/onmi-128hq-part1-overview/">Omni 128HQ Desktop #1 - Overview</a> was originally published by David Black at <a href="https://www.overtakenbyevents.com">Overtaken by events</a> on January 19, 2019.</p>https://www.overtakenbyevents.com/calculate-the-memory-and-t-states-that-Z80-code-takes2018-11-17T00:00:00+00:002018-11-17T00:00:00+00:00David Blackhttps://www.overtakenbyevents.comdavid_black_uk@yahoo.com
<h1 id="so-">So …</h1>
<p>I’ve been writing quite a bit of code of late (and certainly no blog posts). I’ve been focusing on getting my display update code as efficient as possible. So I wanted to examine my code to see what the space/time trade-off was in terms of memory consumption and number of processor cycles used.</p>
<p>I talked a little about space/time trade-offs in an <a href="/lets-talk-about-the-zx-specrum-screen-layout-part-three/">earlier post on calculating screen positions</a>, in that post I manually calculated the t-states using a document I found online.</p>
<p>When I was writing <a href="/Spectrum-development-then-and-now/">production Z80 code</a> my old assembler (OCP’s Full screen editor assembler) used to be able to output the information that I needed as part of the assembly process. A quick look at my current tooling shows it doesn’t give me the functionality I need.</p>
<h2 id="of-course-then-">Of course then …</h2>
<p>I went to work and wrote an <a href="../tstates">online z80 t-state analyser</a>.</p>
<p>I have included as many of the undocumented Z80 instructions that I am aware of and have run it against several large online code bases (manic miner etc) and it handles them without issues.</p>
<div class="dbImg centeredImg zoom50" data-src="t-stating.png"></div>
<p>It’s easy to use, paste in your z80 assembly code and it’ll automatically process it. <a href="../tstates">Give it a go</a> and let me know if it’s of any use (If you see any red lines, please let me know as that’s an unrecognised instruction).</p>
<p>I’m looking to extend the app to produce syntax highlighted code with t-states for use in blogs and articles. if you think that’s a decent idea, or have features you’d like to see then contact me via twitter or discord.</p>
<p><a href="https://www.overtakenbyevents.com/calculate-the-memory-and-t-states-that-Z80-code-takes/">Calculate the memory and t-states that Z80 code takes</a> was originally published by David Black at <a href="https://www.overtakenbyevents.com">Overtaken by events</a> on November 17, 2018.</p>https://www.overtakenbyevents.com/lets-talk-about-the-zx-specrum-screen-layout-part-three2018-03-11T00:00:00+00:002018-03-11T00:00:00+00:00David Blackhttps://www.overtakenbyevents.comdavid_black_uk@yahoo.com
<h1 id="the-code">The code</h1>
<p>In previous posts I’ve discussed the Spectrum’s <a href="/lets-talk-about-the-zx-specrum-screen-layout/">attribute map</a>, and <a href="/lets-talk-about-the-zx-specrum-screen-layout-part-two/">screen layout</a>. Give those posts a read over if you’ve not done so already, it’ll help you understand what I’m about to cover.</p>
<p>In this post I’m going to describe two ways to to find the pixel address of a screen location. Both of these solutions address the same problem: Given a pixel y address (0..191) in register <code class="language-plaintext highlighter-rouge">B</code> and a character x address (0..31) in register <code class="language-plaintext highlighter-rouge">C</code>, calculate the screen address that represents those coordinates and return it in <code class="language-plaintext highlighter-rouge">HL</code>. It’s assumed the subroutine will trash all registers.</p>
<p>The two approaches to solving this problem, are calculating the address programmatically and using a look up table. Once we’ve covered the implementations, we’ll talk about the relative performance and trade-offs in storage, time and complexity.</p>
<h2 id="calculating-a-screen-address">Calculating a screen address</h2>
<p>The Spectrum’s screen memory starts at #4000 so the most significant three bits of our address will always be <code class="language-plaintext highlighter-rouge">010</code>. The 5 least significant bits will always be the <code class="language-plaintext highlighter-rouge">X</code> (column) address. The 8 bits from 5 - 12 represent the pixel <code class="language-plaintext highlighter-rouge">Y</code>, but not in the way you might imagine.</p>
<table>
<thead>
<tr>
<th>15</th><th>14</th><th>13</th><th>12</th><th>11</th><th>10</th><th>9</th><th>8</th><th>7</th><th>6</th><th>5 </th><th>4</th><th>3</th><th>2</th><th>1</th><th>0</th>
</tr>
</thead>
<tbody>
<tr>
<td> 0 </td><td> 1 </td><td>0 </td> <td>Y<sub>7</sub> </td><td>Y<sub>6</sub></td>
<td>Y<sub>2</sub></td><td>Y<sub>1</sub></td><td>Y<sub>0</sub></td>
<td>Y<sub>5</sub></td><td>Y<sub>4</sub></td><td>Y<sub>3</sub></td>
<td> X<sub>4</sub> </td><td> X<sub>3</sub> </td><td> X<sub>2</sub> </td><td> X<sub>1</sub> </td><td> X<sub>0</sub> </td>
</tr>
</tbody>
</table>
<p>The first two bits of the y address (Y<sub>0</sub> ) and Y<sub>1</sub>) have been picked up and dropped into the middle of the other 6 bits of the address. This is part of the reason why the spectrum screen address calculation is a strange beast.</p>
<p>However putting the first two bits of the screen Y coordinate into the first two bits of the upper byte of the address, is why adding #100 to the address of a character moves down one character row on the screen.</p>
<p>The subroutine to calculate the address from the coordinates as set out above, is:</p>
<table class="t-state">
<thead>
<tr>
<th>Instruction</th> <th>T</th> <th>M</th> <th>Comment</th>
</tr>
</thead>
<tbody>
<tr><td class="t-instr">ld a,b </td><td>4</td><td>1</td><td class="t-comment">; Work on the upper byte of the address</td></tr>
<tr><td class="t-instr">and %00000111 </td><td>7</td><td>2</td><td class="t-comment">; a = Y2 Y1 y0 </td></tr>
<tr><td class="t-instr">or %01000000 </td><td>7</td><td>2</td><td class="t-comment">; first three bits are always 010 </td></tr>
<tr><td class="t-instr">ld h,a </td><td>4</td><td>1</td><td class="t-comment">; store in h </td></tr>
<tr><td class="t-instr">ld a,b </td><td>4</td><td>1</td><td class="t-comment">; get bits Y7, Y6 </td></tr>
<tr><td class="t-instr">rra </td><td>4</td><td>1</td><td class="t-comment">; move them into place </td></tr>
<tr><td class="t-instr">rra </td><td>4</td><td>1</td><td class="t-comment">; </td></tr>
<tr><td class="t-instr">rra </td><td>4</td><td>1</td><td class="t-comment">; </td></tr>
<tr><td class="t-instr">and %00011000 </td><td>7</td><td>2</td><td class="t-comment">; mask off </td></tr>
<tr><td class="t-instr">or h </td><td>4</td><td>1</td><td class="t-comment">; a = 0 1 0 Y7 Y6 Y2 Y1 Y0 </td></tr>
<tr><td class="t-instr">ld h,a </td><td>4</td><td>1</td><td class="t-comment">; calculation of h is now complete </td></tr>
<tr><td class="t-instr">ld a,b </td><td>4</td><td>1</td><td class="t-comment">; get y </td></tr>
<tr><td class="t-instr">rla </td><td>4</td><td>1</td><td class="t-comment">; </td></tr>
<tr><td class="t-instr">rla </td><td>4</td><td>1</td><td class="t-comment">; </td></tr>
<tr><td class="t-instr">and %11100000 </td><td>7</td><td>2</td><td class="t-comment">; a = y5 y4 y3 0 0 0 0 0 </td></tr>
<tr><td class="t-instr">ld l,a </td><td>4</td><td>1</td><td class="t-comment">; store in l </td></tr>
<tr><td class="t-instr">ld a,c </td><td>4</td><td>1</td><td class="t-comment">; </td></tr>
<tr><td class="t-instr">and %00011111 </td><td>7</td><td>2</td><td class="t-comment">; a = X4 X3 X2 X1 </td></tr>
<tr><td class="t-instr">or l </td><td>4</td><td>1</td><td class="t-comment">; a = Y5 Y4 Y3 X4 X3 X2 X1 </td></tr>
<tr><td class="t-instr">ld l,a </td><td>4</td><td>1</td><td class="t-comment">; calculation of l is complete </td></tr>
<tr><td class="t-instr">ret </td><td>10</td><td>1</td><td class="t-comment"> </td></tr>
</tbody>
</table>
<p>For a total of 105 T-States in 26 bytes of memory.</p>
<h2 id="looking-up-a-screen-address">Looking up a screen address</h2>
<p>Instead of calculating the screen address every time we need it, a better alternative may be pre-calculating the results and placing them in a lookup table.</p>
<p>In current programming terms we store the address of the first pixel in each screen row, in an array (let’s call it <code class="language-plaintext highlighter-rouge">screen_map</code>). We then calculate the address as <code class="language-plaintext highlighter-rouge">screen_map[y*2] + x</code>. The multiplier of 2 is because it is an array of bytes and the addresses are words.</p>
<p>I remember writing a basic program to print the hex addresses for the first pixel of each screen row and write it to the Sinclair printer. Then spinning up my assembler (from tape) and entering in the values by hand.</p>
<div class="dbImg zoom50 centeredImg" data-src="2018-03-11-lets-talk-about-the-zx-specrum-screen-layout-part-three/sinclair_printer.jpg" title="Sinclair printer"></div>
<p style="color:gray; font-size: 80%; text-align: center;"><a href="https://en.wikipedia.org/wiki/ZX_Printer#/media/File:Sinclair.zx.thermal.printer.jpg">Image Copyright: Jbattersby. Open sourced</a></p>
<p>The code to perform our address translation (remember <code class="language-plaintext highlighter-rouge">B</code> is the <code class="language-plaintext highlighter-rouge">Y</code> coordinate and <code class="language-plaintext highlighter-rouge">C</code> the character <code class="language-plaintext highlighter-rouge">X</code>) becomes:</p>
<table class="t-state">
<thead>
<tr>
<th>Instruction</th> <th>T</th> <th>M</th> <th>Comment</th>
</tr>
</thead>
<tbody>
<tr><td class="t-instr"> ld h, 0 </td><td> 7 </td><td> 2 </td><td class="t-comment"> </td></tr>
<tr><td class="t-instr"> ld l, b </td><td> 4 </td><td> 1 </td><td class="t-comment"> ; hl = Y</td></tr>
<tr><td class="t-instr"> add hl, hl </td><td> 11 </td><td> 1 </td><td class="t-comment"> ; hl = Y * 2 </td></tr>
<tr><td class="t-instr"> ld de, screen_map </td><td> 10 </td><td> 3 </td><td class="t-comment"> ; de = screen_map </td></tr>
<tr><td class="t-instr"> add hl, de </td><td> 11 </td><td> 1 </td><td class="t-comment"> ; hl = screen_map + (row * 2) </td></tr>
<tr><td class="t-instr"> ld a, (hl) </td><td> 7 </td><td> 1 </td><td class="t-comment"> ; implements ld hl, (hl) </td> </tr>
<tr><td class="t-instr"> inc hl </td><td> 6 </td><td> 1 </td><td class="t-comment"> </td></tr>
<tr><td class="t-instr"> ld h, (hl) </td><td> 7 </td><td> 1 </td><td class="t-comment"> </td></tr>
<tr><td class="t-instr"> ld l, a </td><td> 4 </td><td> 1 </td><td class="t-comment"> ; hl = address of first pixel from screen_map </td></tr>
<tr><td class="t-instr"> ld d, 0 </td><td> 7 </td><td> 2 </td><td class="t-comment"> </td></tr>
<tr><td class="t-instr"> ld e, c </td><td> 4 </td><td> 1 </td><td class="t-comment"> ; de = X </td></tr>
<tr><td class="t-instr"> add hl, de </td><td> 11 </td><td> 1 </td><td class="t-comment"> ; add the char X offset </td></tr>
<tr><td class="t-instr"> ret </td><td> 10 </td><td> 1 </td><td class="t-comment"> ; return screen_map[Y*2] + X </td></tr>
<tr><td class="t-instr" colspan="4"> </td></tr>
<tr><td class="t-instr" colspan="4"> screen_map: .defw #4000, #4100, #4200, #4300, #4400, #4500, #4600, #4700, #4020, #4120, #4220, #4320 </td></tr>
<tr><td class="t-instr" colspan="4"> </td></tr>
</tbody>
</table>
<p>That’s 99 T-States and 401 bytes of memory (17 bytes of code and 384 bytes for the lookup table.</p>
<p>I’m not a mean spirited guy. If you want to play along at home here’s a link to a <a href="https://gist.github.com/davidblackuk/7b5e71a3c226bf9fe93e715002667e67">gist</a> that contains the code and more importantly
the lookup table!</p>
<h2 id="space-time-trade-off">Space time trade off</h2>
<p>So which one of these approaches is the best? The answer is, as usual, it depends. Let’s compare the results</p>
<table>
<thead>
<tr>
<th>Approach</th>
<th>Lines of code</th>
<th>T-States</th>
<th>Total memory</th>
</tr>
</thead>
<tbody>
<tr>
<td>Calculation</td>
<td>21</td>
<td>105</td>
<td>26</td>
</tr>
<tr>
<td>Look up</td>
<td>13</td>
<td>99</td>
<td>384</td>
</tr>
</tbody>
</table>
<p>The calculated approach is slower (about 6%) more complex (61% longer method) but really efficient in memory (14 times less memory!). So for <em>space</em> constrained applications like ROMs, calculation is the approach to take.</p>
<p>However for games, well, speed is king. Even small margins make a difference, especially in crucial areas like screen rendering. So it’d be a rare spectrum game that didn’t use techniques like this.</p>
<p>As a simple example of the difference in timing of these two approaches I coded a race. On the left the contender is <em>calculated addresses</em> and on the right; <em>lookup tables</em>. Each function is tested by filling the screen with pixels many times, alternating the border colour after each iteration.</p>
<video class="centeredImg" src="../images/2018-03-11-lets-talk-about-the-zx-specrum-screen-layout-part-three/side-by-side.mp4" width="320" height="240" controls="" preload=""></video>
<p>You can see that by the end of the test, the lookup table function was in the lead by about a second. Winer, Winer, Chicken Dinner :-)</p>
<p><a href="https://www.overtakenbyevents.com/lets-talk-about-the-zx-specrum-screen-layout-part-three/">The ZX-Spectrum screen layout: Part III</a> was originally published by David Black at <a href="https://www.overtakenbyevents.com">Overtaken by events</a> on March 11, 2018.</p>https://www.overtakenbyevents.com/lets-talk-about-the-zx-specrum-screen-layout-part-two2018-03-10T00:00:00+00:002018-03-10T00:00:00+00:00David Blackhttps://www.overtakenbyevents.comdavid_black_uk@yahoo.com
<h1 id="pixel-layout">Pixel layout</h1>
<p>In <a href="/lets-talk-about-the-zx-specrum-screen-layout/">part one of this article</a> I discussed the attribute map, how attributes work and how they are addressed in memory. In this post we move on to the pixel layout of the screen.
Apologies for the small amount of repetition here if you read the original post.</p>
<p>The original 48K Spectrum had a character resolution of 32 columns by 24 rows, implemented using a pixel resolution of 256 by 192 pixels. Each pixel could be individually manipulated, this was a major departure from previous ZX computers which (by default) only allowed the screen to be manipulated at the character level.</p>
<table>
<thead>
<tr><th>Start</th> <th>End</th> <th>Length</th> <th>Description</th></tr>
</thead>
<tbody>
<tr> <td> #FF58 </td> <td> #FFFF </td> <td> 168 </td> <td> Reserved </td> </tr>
<tr> <td> #5CCB </td> <td> #FF57 </td> <td> 41,612 </td> <td> Free memory </td> </tr>
<tr> <td> #5CC0 </td> <td> #5CCA </td> <td> 11 </td> <td> Reserved </td> </tr>
<tr> <td> #5C00 </td> <td> #5CBF </td> <td> 192 </td> <td> System variables </td> </tr>
<tr> <td> #5B00 </td> <td> #5BFF </td> <td> 256 </td> <td> Printer buffer </td> </tr>
<tr> <td> #5800 </td> <td> #5AFF </td> <td> 768 </td> <td> Attributes </td> </tr>
<tr> <td> #4000 </td> <td> #57FF </td> <td> 6,144 </td> <td> <span class="memory-slot">Pixel data</span> </td> </tr>
<tr> <td> #0000 </td> <td> #3FFF </td> <td> 16,384 </td> <td> Basic ROM </td> </tr>
</tbody>
</table>
<p>The spectrum’s screen memory started in memory immediately after the spectrum rom, at address #4000 (16384d). Our 256x192 pixels are stored 8 pixels to the byte in 6,144 byes of memory (32 bytes by 192 rows).</p>
<p>Each of the 32 bytes in a row represented 8 pixels on the screen with the most significant bit (7) being the left most bit and the least significant bit (0) being the rightmost pixel. So the byte values 24, 60, 126, 219, 255, 90, 129, 68 stacked on top of one another might just give you a space invader.</p>
<table>
<thead>
<tr>
<th>7</th>
<th>6</th>
<th>5</th>
<th>4</th>
<th>3</th>
<th>2</th>
<th>1</th>
<th>0</th>
<th>dec</th>
</tr>
</thead>
<tbody>
<tr>
<td> </td>
<td> </td>
<td> </td>
<td>◉</td>
<td>◉</td>
<td> </td>
<td> </td>
<td> </td>
<td>24</td>
</tr>
<tr>
<td> </td>
<td> </td>
<td>◉</td>
<td>◉</td>
<td>◉</td>
<td>◉</td>
<td> </td>
<td> </td>
<td>60</td>
</tr>
<tr>
<td> </td>
<td>◉</td>
<td>◉</td>
<td>◉</td>
<td>◉</td>
<td>◉</td>
<td>◉</td>
<td> </td>
<td>126</td>
</tr>
<tr>
<td>◉</td>
<td>◉</td>
<td> </td>
<td>◉</td>
<td>◉</td>
<td> </td>
<td>◉</td>
<td>◉</td>
<td>219</td>
</tr>
<tr>
<td>◉</td>
<td>◉</td>
<td>◉</td>
<td>◉</td>
<td>◉</td>
<td>◉</td>
<td>◉</td>
<td>◉</td>
<td>255</td>
</tr>
<tr>
<td> </td>
<td>◉</td>
<td> </td>
<td>◉</td>
<td>◉</td>
<td> </td>
<td>◉</td>
<td> </td>
<td>90</td>
</tr>
<tr>
<td>◉</td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
<td>◉</td>
<td>129</td>
</tr>
<tr>
<td> </td>
<td>◉</td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
<td>◉</td>
<td> </td>
<td>68</td>
</tr>
</tbody>
</table>
<p>However the expression ‘Stacked on to of one another’ does raise an interesting point. Unlike the spectrum’s attributes, the pixels are not stored in a linear manner. Intuitively, the pixels for row 0 would be stored in the first 32 bytes of screen memory, then the pixels for row 1 would be in the next 32 bytes. However that’s simply not the case.</p>
<p>Let’s write a little speccy basic program to poke each address in the screen map in a linear manner and see what gives.</p>
<div class="dbImg zoom100 centeredImg" data-src="2018-03-10-lets-talk-about-the-zx-specrum-screen-layout-part-two/listing01.png" title="Sinclair basic program listing in the emulator."></div>
<p>Which produces the following results:</p>
<video class="centeredImg" src="../images/2018-03-10-lets-talk-about-the-zx-specrum-screen-layout-part-two/screen-lines.mp4" width="320" height="240" controls="" preload=""></video>
<p>So definitely not linear then…</p>
<p>As you can see the spectrum screen memory is divided into three sections (or banks), each of which represents 8 character rows. The first row of 32 bytes of screen memory is indeed the first row of pixels, though it’s best to think of it as the first row of pixels for the first character row in the bank.</p>
<p>The second physical row of pixels in screen memory represents the first row of pixels for the second character row.</p>
<p>The next 6 groups of 32 bytes of physical memory in the screen buffer are the first row of pixels for character rows 3, 4, 5, 6, 7 and 8.</p>
<p>After that the next blocks of 32 bytes represent the second row of pixels for character 1. Then characters 2, 3, 4, 5, 5 ,6 ,7 and 8.</p>
<p>We proceeded character row, by character row, until the first bank of pixels is filled. This bank of pixels is 8 * 8 * 32 bytes in length (2,048 bytes) from #4000 to #47FF.</p>
<p>The second bank of memory starts at #4800 with the first pixel row for character row 9, then the first row for character row 10 etc. This bank stretches from #4800 to 4FFF.</p>
<p>The third and final bank representing the pixel memory for screen character rows 17 through 24 is represented by the memory in address range #5000 to #57FF.</p>
<p>Got that? Excellent! If you take nothing else away from this post, hopefully, you have an understanding of how unintuitive the screen was for early programmers on the spectrum. It caused a lot of head scratching (perhaps the start of my bald head).</p>
<h2 id="why-oh-why-oh-why">Why, oh why, oh why?</h2>
<p>There are two reasons that this screen layout made sense to Sinclair:</p>
<h3 id="think-of-the-poor-hardware">Think of the poor hardware</h3>
<p>The rendering of the screen to video was performed by an Uncommitted Logic Array (ULA), rather than a dedicated graphics chip. A ULA is a programmable chip similar to modern PLCs, but the programming was done in hardware at the foundry. It’s utility to Sinclair was that it removed the need for a lots of discrete chips on the Spectrum’s PCB. It’s all about the money, money; when you are trying to build a sub £100 computer in 1982.</p>
<p>The ULA however was no speed daemon. So the screen memory layout was designed to make it easy for the hardware to access and render it, not the programmer to write to it.</p>
<h3 id="character-addressing">Character addressing</h3>
<p>The second reason for the memory layout is, that on the whole, Spectrum BASIC is character based (I know there is a draw and plot command, but still…)</p>
<p>If you are at the start of a character location on the screen (in any bank) and have the address in the 16 bit register HL, then the second pixel row of the character is at offset #100 from HL, the third at offset #200, then #300, #400, #500, #600 and finally #700.</p>
<p>Now adding #100 to HL is the same as performing <code class="language-plaintext highlighter-rouge">inc h</code> and that’s a really quick way of stepping down a screen row for a character when rendering it. This only works when dealing with addresses of character cells and won’t work if rendering 8 lines of character data starting anywhere on screen.</p>
<p>But this implementation detail will have helped keep the size of the Spectrum ROM down.</p>
<p>In <a href="/lets-talk-about-the-zx-specrum-screen-layout-part-three/">part three</a> of this post we’ll start examining the assembly language to address the screen in a sane manner.</p>
<p><a href="https://www.overtakenbyevents.com/lets-talk-about-the-zx-specrum-screen-layout-part-two/">The ZX-Spectrum screen layout: Part II</a> was originally published by David Black at <a href="https://www.overtakenbyevents.com">Overtaken by events</a> on March 10, 2018.</p>https://www.overtakenbyevents.com/lets-talk-about-the-zx-specrum-screen-layout2018-03-03T00:00:00+00:002018-03-03T00:00:00+00:00David Blackhttps://www.overtakenbyevents.comdavid_black_uk@yahoo.com
<h1 id="attributes">Attributes</h1>
<p>The original 48K Spectrum had a character resolution of 32 columns by 24 rows, implemented using a pixel resolution of 256 by 192 pixels. Each pixel could be individually manipulated, this was a major departure from previous ZX computers which (by default) only allowed the screen to be manipulated at the character level.</p>
<p>While visibility could be controlled on a pixel-by-pixel basis, colour was set in 8 by 8 pixel squares at the character level with all pixels in a particular character cell sharing the same foreground and background colours. The nature of the attribute level colour setting is what produces attribute clashes (which we’ll cover later) and what gave many spectrum games their distinctive looks.</p>
<p>The 48K ZX Spectrum memory map is shown below, #xxxx denotes a hexadecimal number, lengths are decimal</p>
<table>
<thead>
<tr><th>Start</th> <th>End</th> <th>Length</th> <th>Description</th></tr>
</thead>
<tbody>
<tr> <td> #FF58 </td> <td> #FFFF </td> <td> 168 </td> <td> Reserved </td> </tr>
<tr> <td> #5CCB </td> <td> #FF57 </td> <td> 41,612 </td> <td> Free memory </td> </tr>
<tr> <td> #5CC0 </td> <td> #5CCA </td> <td> 11 </td> <td> Reserved </td> </tr>
<tr> <td> #5C00 </td> <td> #5CBF </td> <td> 192 </td> <td> System variables </td> </tr>
<tr> <td> #5B00 </td> <td> #5BFF </td> <td> 256 </td> <td> Printer buffer </td> </tr>
<tr> <td> #5800 </td> <td> #5AFF </td> <td> 768 </td> <td> <span class="memory-slot">Attributes</span> </td> </tr>
<tr> <td> #4000 </td> <td> #57FF </td> <td> 6,144 </td> <td> Pixel data </td> </tr>
<tr> <td> #0000 </td> <td> #3FFF </td> <td> 16,384 </td> <td> Basic ROM </td> </tr>
</tbody>
</table>
<p>The spectrum’s screen memory starts in memory immediately after the spectrum rom, at address #4000 (16384d). Our 256x192 pixels are stored 8 pixels to the byte in 6,144 byes of memory (32 bytes by 192 rows). The colour attributes were stored immediately after the pixel data from address #5800 (22,628) in 768 bytes (32 x 24 character of data).</p>
<h2 id="addressing-attributes">Addressing attributes</h2>
<p>Addressing attributes is as easy as you would expect, starting at #5800 there are 32 attributes per screen row and 24 rows.</p>
<table>
<thead>
<tr>
<th> </th>
<th>0</th>
<th>1</th>
<th>2</th>
<th>3</th>
<th>4</th>
<th>5</th>
<th>6</th>
<th>7</th>
<th>8</th>
<th>9</th>
<th>A</th>
<th>B</th>
<th>C</th>
<th>D</th>
<th>E</th>
<th>F</th>
<th>…</th>
<th>1F</th>
</tr>
</thead>
<tbody>
<tr>
<td>#5800</td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
</tr>
<tr>
<td>#5820</td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
</tr>
<tr>
<td>#5840</td>
<td> </td>
<td> </td>
<td> </td>
<td>X</td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
</tr>
<tr>
<td>#5860</td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
</tr>
<tr>
<td>…</td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
</tr>
<tr>
<td>#5EAO</td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
</tr>
</tbody>
</table>
<p>To set the attributes for character (3, 2) assuming (0,0) is at the top left of the screen you write to address <code class="language-plaintext highlighter-rouge">#5800 + ((2*32)+ 3)</code> or
#5843 (and X marks the spot).</p>
<h2 id="attribute-values">Attribute values</h2>
<p>Each block of 8x8 pixels has a single byte of attribute data packed as follows</p>
<table>
<thead>
<tr>
<th>7</th>
<th>6</th>
<th>5</th>
<th>4</th>
<th>3</th>
<th>2</th>
<th>1</th>
<th>0</th>
</tr>
</thead>
<tbody>
<tr>
<td>F</td>
<td>B</td>
<td>P<sub>2</sub></td>
<td>P<sub>2</sub></td>
<td>P<sub>1</sub></td>
<td>I<sub>0</sub></td>
<td>I<sub>1</sub></td>
<td>I<sub>0</sub></td>
</tr>
</tbody>
</table>
<ul>
<li>Bit 7 if set indicates the colour flashes between the fore and back colours.</li>
<li>Bit 6 if set indicates the colours are rendered bright.</li>
<li>Bits 5 to 3 contain the paper (background) colour 0..7</li>
<li>Bits 2 to 0 contain the ink (foreground) colour 0..7</li>
</ul>
<p>The flash attribute alternates a cell between its foreground and background colours on a timer, it is of limited use in games.</p>
<p>The bright attribute makes the foreground and background colours, err…, brighter. The bright attribute nearly doubles the effective number of colours the spectrum could display. I say nearly because bright black is still black.</p>
<p>The colour value 0..7 is the index into the colour table, the colour values at those indexes and their bright equivalents are<sup>*</sup>:</p>
<table>
<thead>
<tr>
<th>Decimal</th>
<th>Binary</th>
<th>Colour</th>
<th>Normal</th>
<th>Bright</th>
</tr>
</thead>
<tbody>
<tr>
<td>0</td>
<td>000</td>
<td>Black</td>
<td><span class="spec-color spec-color-0-n"></span></td>
<td><span class="spec-color spec-color-0-b"></span></td>
</tr>
<tr>
<td>1</td>
<td>001</td>
<td>Blue</td>
<td><span class="spec-color spec-color-1-n"></span></td>
<td><span class="spec-color spec-color-2-b"></span></td>
</tr>
<tr>
<td>2</td>
<td>010</td>
<td>Red</td>
<td><span class="spec-color spec-color-2-n"></span></td>
<td><span class="spec-color spec-color-3-b"></span></td>
</tr>
<tr>
<td>3</td>
<td>011</td>
<td>Magenta</td>
<td><span class="spec-color spec-color-3-n"></span></td>
<td><span class="spec-color spec-color-4-b"></span></td>
</tr>
<tr>
<td>4</td>
<td>100</td>
<td>Green</td>
<td><span class="spec-color spec-color-4-n"></span></td>
<td><span class="spec-color spec-color-5-b"></span></td>
</tr>
<tr>
<td>5</td>
<td>101</td>
<td>Cyan</td>
<td><span class="spec-color spec-color-5-n"></span></td>
<td><span class="spec-color spec-color-6-b"></span></td>
</tr>
<tr>
<td>6</td>
<td>110</td>
<td>Yellow</td>
<td><span class="spec-color spec-color-6-n"></span></td>
<td><span class="spec-color spec-color-7-b"></span></td>
</tr>
<tr>
<td>7</td>
<td>111</td>
<td>White</td>
<td><span class="spec-color spec-color-7-n"></span></td>
<td><span class="spec-color spec-color-8-b"></span></td>
</tr>
</tbody>
</table>
<h3 id="putting-it-all-together">Putting it all together</h3>
<p>Here is an example to how attributes work. I know we’re assembly language gurus here, but well do this with a little speccy basic.</p>
<p>I want to demonstrate attribute values, bright and normal colours and blacks stubborn refusal to change no matter what. We are going to set the background colour of four characters to green, the foreground of the first two to black and the second pair to red. Finally alternate between normal and bright colours between each cell.</p>
<p>This gives us the following four values, note since the paper is bits 5 to 3 we take the value 4 for green (100b) and shift it left 3 places to get 32 (100000b) and set those bits.</p>
<table>
<tbody>
<tr>
<td>Flash</td>
<td>Bright</td>
<td>Paper</td>
<td>Ink</td>
<td>Value</td>
<td>Decimal</td>
<td>Description</td>
</tr>
<tr>
<td>0</td>
<td>1</td>
<td>100</td>
<td>000</td>
<td>01100000</td>
<td>96</td>
<td>Bright - black on green</td>
</tr>
<tr>
<td>0</td>
<td>0</td>
<td>100</td>
<td>000</td>
<td>00100000</td>
<td>32</td>
<td>Normal - black on green</td>
</tr>
<tr>
<td>0</td>
<td>1</td>
<td>100</td>
<td>010</td>
<td>01100010</td>
<td>98</td>
<td>Bright - red on green</td>
</tr>
<tr>
<td>0</td>
<td>0</td>
<td>100</td>
<td>010</td>
<td>00100010</td>
<td>34</td>
<td>Normal - red on green</td>
</tr>
</tbody>
</table>
<p>We print a word at the top left of the screen and then colour it by setting the attributes directly (address of the top left attribute is 22528.)</p>
<div class="dbImg zoom80 centeredImg" data-src="2018-03-03-lets-talk-about-the-zx-specrum-screen-layout/listing01.png" title="Sinclair basic program listing in the emulator."></div>
<p>Which give us:</p>
<div class="dbImg zoom80 centeredImg" data-src="2018-03-03-lets-talk-about-the-zx-specrum-screen-layout/result01.png" title="The word poke on the spectrum screen with the attributes set as described previouslu"></div>
<p>An a pretty clear demonstration of how attributes work, you can see the green background vary in colour when bright and also that while the black colour remains the same the red foreground colour does change intensity when marked as bright.</p>
<p>Which means there are thirty one possible colours on a spectrum screen fifteen colours that can be normal or bright and black.</p>
<h3 id="some-assembly-language-constants-and-code-for-attributes">Some assembly language constants and code for attributes</h3>
<p>The shift operator <code class="language-plaintext highlighter-rouge"><<</code> is used to move a value like red (010) to its paper equivalent pRed (010000). The rest of the constants values should be apparent from the rest of this post.</p>
<figure class="highlight"><pre><code class="language-csharp" data-lang="csharp"><span class="n">screen_width_pixels</span><span class="p">:</span> <span class="p">.</span><span class="n">equ</span> <span class="m">256</span>
<span class="n">screen_height_pixels</span><span class="p">:</span> <span class="p">.</span><span class="n">equ</span> <span class="m">192</span>
<span class="n">screen_width_chars</span><span class="p">:</span> <span class="p">.</span><span class="n">equ</span> <span class="m">32</span>
<span class="n">screen_height_chars</span><span class="p">:</span> <span class="p">.</span><span class="n">equ</span> <span class="m">24</span>
<span class="n">screen_start</span><span class="p">:</span> <span class="p">.</span><span class="n">equ</span> <span class="err">#</span><span class="m">4000</span>
<span class="n">screen_size</span><span class="p">:</span> <span class="p">.</span><span class="n">equ</span> <span class="n">screen_width_chars</span> <span class="p">*</span> <span class="n">screen_height_pixels</span>
<span class="n">attr_start</span><span class="p">:</span> <span class="p">.</span><span class="n">equ</span> <span class="err">#</span><span class="m">5800</span>
<span class="n">attributes_length</span><span class="p">:</span> <span class="p">.</span><span class="n">equ</span> <span class="n">screen_width_chars</span> <span class="p">*</span> <span class="n">screen_height_chars</span>
<span class="n">black</span><span class="p">:</span> <span class="p">.</span><span class="n">equ</span> <span class="p">%</span><span class="m">000000</span>
<span class="n">blue</span><span class="p">:</span> <span class="p">.</span><span class="n">equ</span> <span class="p">%</span><span class="m">000001</span>
<span class="n">red</span><span class="p">:</span> <span class="p">.</span><span class="n">equ</span> <span class="p">%</span><span class="m">000010</span>
<span class="n">magenta</span><span class="p">:</span> <span class="p">.</span><span class="n">equ</span> <span class="p">%</span><span class="m">000011</span>
<span class="n">green</span><span class="p">:</span> <span class="p">.</span><span class="n">equ</span> <span class="p">%</span><span class="m">000100</span>
<span class="n">cyan</span><span class="p">:</span> <span class="p">.</span><span class="n">equ</span> <span class="p">%</span><span class="m">000101</span>
<span class="n">yellow</span><span class="p">:</span> <span class="p">.</span><span class="n">equ</span> <span class="p">%</span><span class="m">000110</span>
<span class="n">white</span><span class="p">:</span> <span class="p">.</span><span class="n">equ</span> <span class="p">%</span><span class="m">000111</span>
<span class="n">pBlack</span><span class="p">:</span> <span class="p">.</span><span class="n">equ</span> <span class="n">black</span> <span class="p"><<</span> <span class="m">3</span>
<span class="n">pBlue</span><span class="p">:</span> <span class="p">.</span><span class="n">equ</span> <span class="n">blue</span> <span class="p"><<</span> <span class="m">3</span>
<span class="n">pRed</span><span class="p">:</span> <span class="p">.</span><span class="n">equ</span> <span class="n">red</span> <span class="p"><<</span> <span class="m">3</span>
<span class="n">pMagenta</span><span class="p">:</span> <span class="p">.</span><span class="n">equ</span> <span class="n">magenta</span> <span class="p"><<</span> <span class="m">3</span>
<span class="n">pGreen</span><span class="p">:</span> <span class="p">.</span><span class="n">equ</span> <span class="n">green</span> <span class="p"><<</span> <span class="m">3</span>
<span class="n">pCyan</span><span class="p">:</span> <span class="p">.</span><span class="n">equ</span> <span class="n">cyan</span> <span class="p"><<</span> <span class="m">3</span>
<span class="n">pYellow</span><span class="p">:</span> <span class="p">.</span><span class="n">equ</span> <span class="n">yellow</span> <span class="p"><<</span> <span class="m">3</span>
<span class="n">pWhite</span><span class="p">:</span> <span class="p">.</span><span class="n">equ</span> <span class="n">white</span> <span class="p"><<</span> <span class="m">3</span>
<span class="n">bright</span><span class="p">:</span> <span class="p">.</span><span class="n">equ</span> <span class="p">%</span><span class="m">1000000</span></code></pre></figure>
<p>The <code class="language-plaintext highlighter-rouge">cls_attributes</code> sub-routine is used to set all attributes for the screen to the same value</p>
<figure class="highlight"><pre><code class="language-csharp" data-lang="csharp"><span class="p">;</span>
<span class="p">;</span> <span class="n">IN</span> <span class="p">-</span> <span class="n">A</span> <span class="n">contains</span> <span class="n">the</span> <span class="n">attribute</span> <span class="k">value</span> <span class="n">to</span> <span class="n">initialize</span> <span class="n">the</span> <span class="n">screen</span> <span class="n">to</span>
<span class="p">;</span> <span class="n">OUT</span> <span class="p">-</span> <span class="n">Trashes</span> <span class="n">HL</span><span class="p">,</span> <span class="n">DE</span><span class="p">,</span> <span class="n">BC</span>
<span class="p">;</span>
<span class="n">cls_attributes</span><span class="p">:</span>
<span class="n">ld</span> <span class="n">hl</span><span class="p">,</span> <span class="n">attr_start</span> <span class="p">;</span> <span class="n">start</span> <span class="n">at</span> <span class="n">attribute</span> <span class="n">start</span>
<span class="n">ld</span> <span class="n">de</span><span class="p">,</span> <span class="n">attr_start</span> <span class="p">+</span> <span class="m">1</span> <span class="p">;</span> <span class="n">copy</span> <span class="n">to</span> <span class="n">next</span> <span class="n">address</span> <span class="k">in</span> <span class="n">attributes</span>
<span class="n">ld</span> <span class="n">bc</span><span class="p">,</span> <span class="n">attributes_length</span> <span class="p">-</span> <span class="m">1</span> <span class="p">;</span> <span class="err">'</span><span class="n">loop</span><span class="err">'</span> <span class="n">attribute</span> <span class="n">size</span> <span class="n">minus</span> <span class="m">1</span> <span class="n">times</span>
<span class="nf">ld</span> <span class="p">(</span><span class="n">hl</span><span class="p">),</span> <span class="n">a</span> <span class="p">;</span> <span class="n">initialize</span> <span class="n">the</span> <span class="n">first</span> <span class="n">attribute</span>
<span class="n">ldir</span> <span class="p">;</span> <span class="n">fill</span> <span class="n">the</span> <span class="n">attributes</span>
<span class="n">ret</span></code></pre></figure>
<p>Using the <code class="language-plaintext highlighter-rouge">cls_attributes</code> method is as simple as:</p>
<figure class="highlight"><pre><code class="language-csharp" data-lang="csharp"> <span class="n">ld</span> <span class="n">a</span><span class="p">,</span> <span class="n">pBlue</span> <span class="p">|</span> <span class="n">yellow</span> <span class="p">|</span> <span class="n">bright</span>
<span class="n">call</span> <span class="n">cls_attributes</span></code></pre></figure>
<p>which sets the whole screen to have a blue background and yellow text, both of which are bright.</p>
<p>In <a href="/lets-talk-about-the-zx-specrum-screen-layout-part-two/">part two</a> we’ll address the pixel layout of the screen.</p>
<hr />
<p><sup>*</sup>These colours are approximations based on <em>science</em>, or a close approximation to science. Which is to say guess work :-)</p>
<p><a href="https://www.overtakenbyevents.com/lets-talk-about-the-zx-specrum-screen-layout/">The ZX-Spectrum screen layout: Part I</a> was originally published by David Black at <a href="https://www.overtakenbyevents.com">Overtaken by events</a> on March 03, 2018.</p>https://www.overtakenbyevents.com/Spectrum-development-then-and-now-part22018-02-04T00:00:00+00:002018-02-04T00:00:00+00:00David Blackhttps://www.overtakenbyevents.comdavid_black_uk@yahoo.com
<p>Two years ago I wrote about <a href="/Tell-us-about-the-war-granddad/">Fireman Fred</a> a ZX-Spectrum game I wrote in 1984 (worst game ever?). That got me to thinking about the development workflow back in the ’80s and how it might be <a href="/Spectrum-development-then-and-now/">done in 2015</a>. That post is worth reading still, for mac users now and for people curious about how development worked back in the ’80s. At the time of writing the previous post I put together a tool chain based on sublime text and a command line assembler on OSX.</p>
<p>The two year hiatus between then and now had a lot to do with a round of redundancies and a new job. I was just too busy to write anything outside of work.</p>
<p>So spinning on two years and being absent a Mac, I started looking into PC options for spectrum development. Embarrassingly for a mac user they started at just much better and ended up way, way better.</p>
<p>I’m not going to go trough the alternatives, just the system that I found. And by system I mean a single IDE for spectrum games built in Visual Studio 2017. That system is the snappily named
<em>ZX Spectrum IDE with Visual Studio 2017 integration</em>. It is written by GitHub user <a href="https://github.com/Dotneteer">Dotneteer</a> (Istvan Novak) and is located on <a href="https://github.com/Dotneteer/spectnetide">GitHub</a>. I’ll be calling it SpecNetIde from now on as my fingers get tired.</p>
<p>SpecNetIde has two main thrusts to its implementation: code discovery and development.</p>
<p>Code discovery includes tools to allow you to reverse engineer existing applications, disassemble code, annotate the disassembly, inspect memory etc. SpecNet IDE even comes with a completely annotated BASIC rom disassembly. So if you’re looking to work out how classic titles work, create pokes, then this is the tool for you.</p>
<p>The second aspect of the SpecNetIde is application development. The IDE comes with a z80 assembler, dockable IDE windows for the emulator, debugger (yeah!), memory map, z80 registers, compiler output and the list goes on. In fact I can’t cover all the feature in one post, so I won’t, just the ones that excite me.</p>
<p>Before I continue there is one caveat that need mentioning. SpecNetIde is in its early days and the following needs to be born in mind.</p>
<ul>
<li>There are a couple of <a href="https://github.com/Dotneteer/spectnetide/blob/master/Documentation/GettingStarted/GetSpectNetIde.md">hoops that need to be jumped through</a> to run it (installing the VS extensions SDK and running the SpecNetIDE from source).</li>
<li>There are some bugs but as I said it’s early days.</li>
</ul>
<p>However those two points aside I really recommend having a go. I’ve been following this project for a while now (and even tried a couple of cheeky little commits myself) and its
become really, really good. And if you do spot issues or have feature requests, Istvan is ridiculously quick at turning things around.</p>
<h2 id="integrated-development">Integrated development</h2>
<p>I doesn’t come much more integrated than this…</p>
<div class="dbImg zoom80 centeredImg" data-src="spectrum-development-then-and-now-partII/ide01.png" title="SpecNetIde screenshot with lots of docked windows."></div>
<p>Of course being visual studio that’s not how you’ll run it. The windows can be undocked and placed on separate monitors and usually that’s what I do.</p>
<p>The current features that excite me are:</p>
<ul>
<li>Visual studio syntax colouring</li>
<li>Masses of menu options in the solution explorer to, compile, run debug etc</li>
<li>Error list support (double click and error to jump to it)</li>
<li>Task list support (add TODOs into visual studios task pane via code comments, and double click to navigate to the file)</li>
<li>Assembly output is in Visual studio’s output pane</li>
</ul>
<p>The features I wish were present are: Navigate to a symbol definition from the editor (F12 support) and a shortcut key to execute the project (F5 / control-F5). Perhaps I’ll get off my backside and implement them.</p>
<h3 id="assembling">Assembling</h3>
<p>You can’t run it, if you can’t write it. SpecNet IDE has a good assembler that has been getting better with each iteration. Again if you find issues, report them on GitHub, they will get fixed. The assembler has full support for:</p>
<ul>
<li>All z80 instructions including the <em>secret</em> ones.</li>
<li>Pseudo instruction support for operations like <code class="language-plaintext highlighter-rouge">org</code>, <code class="language-plaintext highlighter-rouge">defs</code>, etc</li>
<li>Basic macro support for #if (never used it, but it’s there)</li>
</ul>
<p>Personally, the only feature that is currently missing, is macro definition syntax (defm / rept n etc). But I can just unroll my loops.</p>
<h3 id="debugging">Debugging</h3>
<p>In my previous post on Mac based development I used the term integrated, but the environment was far from it. The workflow had a separate editor (sublime), build tool (make), assembler (z8asm) and execution / debug environment (zxsp). And when debugging there was no symbol support it was done at the disassembly level.</p>
<p>SpecNetIde is a true, one stop shop when it comes to spectrum development. Here we see the IDE stopped at a breakpoint</p>
<div class="dbImg zoom80 centeredImg" data-src="spectrum-development-then-and-now-partII/ide02.png" title="SpecNetIde screenshot of the ide paused at a breakpoint."></div>
<p>this is freakin awesome. From this point I can:</p>
<ul>
<li>Single step into / over the next instruction</li>
<li>Examine the register</li>
<li>View the call stack and memory (not shown in that screen shot)</li>
<li>Continue execution as normal</li>
</ul>
<p>Doesn’t sound like a lot? Oh boy are you too spoiled by modern technology!</p>
<h3 id="exporting">Exporting</h3>
<p>Well if you can write your game in an integrated development environment, assemble it, debug it and play it. It isn’t much use if that’s the end of the process. Thankfully SpecNetIde offers options to export your current application in <code class="language-plaintext highlighter-rouge">.tzx</code> and <code class="language-plaintext highlighter-rouge">.tap</code> formats.</p>
<div class="dbImg zoom80 centeredImg" data-src="spectrum-development-then-and-now-partII/ide03.png" title="Screenshot of the SpecNetIde export options."></div>
<p>From there it’s a short hop to another emulator or a physical device via an SD card.</p>
<h3 id="wrap-up">Wrap up</h3>
<p>I hope this post has given you a feel for SpecNetIde and its functionality. SpecNetIde has excited me into recommencing a project that I definitely
didn’t start; to rewrite <em>Fireman Fred</em> using better techniques. Absolutely not doing that. Nope, no way.</p>
<p>Give the video a play. The animations smooth, back buffered and not XOR based. Definitely better than the original (for something that doesn’t exist).</p>
<video class="centeredImg" src="../images/spectrum-development-then-and-now-partII/fred001.mp4" poster="../images/spectrum-development-then-and-now-partII/fred-poster.png" width="320" height="240" controls="" preload=""></video>
<p>And finally… To make this clip I needed to export from SpecNetIde to Fuse and that’s the thing about SpecNetIde, I didn’t know that option to export existed until I needed it. Went looking for it and there it was.</p>
<p><a href="https://www.overtakenbyevents.com/Spectrum-development-then-and-now-part2/">Spectrum development then and now: Part II</a> was originally published by David Black at <a href="https://www.overtakenbyevents.com">Overtaken by events</a> on February 04, 2018.</p>https://www.overtakenbyevents.com/how-to-tell-how-much-memory-your-z80-application-is-using2018-02-03T00:00:00+00:002018-02-03T00:00:00+00:00David Blackhttps://www.overtakenbyevents.comdavid_black_uk@yahoo.com
<p>Programing z80 applications is an exercise in minimalism. Maintaining a tight control on the amount of memory you use and more importantly knowing how much memory is left, is vital. Some assemblers make this process easy, others, less so.</p>
<p>There is a pseudo-symbol <code class="language-plaintext highlighter-rouge">$</code> supported on most if not all assemblers. <code class="language-plaintext highlighter-rouge">$</code> evaluates to the current memory location of the instruction being output. You can assign the value of <code class="language-plaintext highlighter-rouge">$</code> to a symbol at any point.</p>
<p>Here’s a cut down version of Fred’s main file, with a very much truncated list of includes!</p>
<figure class="highlight"><pre><code class="language-csharp" data-lang="csharp"><span class="p">.</span><span class="n">org</span> <span class="err">#</span><span class="m">8000</span>
<span class="n">start</span><span class="p">:</span>
<span class="n">ld</span> <span class="n">hl</span><span class="p">,</span> <span class="m">0</span> <span class="p">;</span> <span class="n">start</span> <span class="n">level</span> <span class="k">is</span> <span class="m">0</span>
<span class="n">call</span> <span class="n">start_game</span> <span class="p">;</span> <span class="n">run</span> <span class="n">the</span> <span class="n">game</span> <span class="n">loop</span>
<span class="p">;</span> <span class="p">...</span>
<span class="err">#</span><span class="n">include</span> <span class="s">"./src/constants.z80asm"</span>
<span class="p">;</span> <span class="n">lots</span> <span class="n">of</span> <span class="n">other</span> <span class="n">includes</span><span class="p">...</span>
<span class="err">#</span><span class="n">include</span> <span class="s">"./src/back_buffer.z80asm"</span>
<span class="n">z_total_bytes</span><span class="p">:</span> <span class="p">.</span><span class="n">equ</span> <span class="err">$</span><span class="p">-</span><span class="n">start</span></code></pre></figure>
<p>The last line assigns the difference between the current code gen location and the start of the application to the symbl <code class="language-plaintext highlighter-rouge">z_total_bytes</code>.</p>
<p>Now, if you assembler supports the output of the symbol file at the end of the process (and it should,) then when you look at the symbol table, you will see
the total number of bytes used.</p>
<p>In my case</p>
<table>
<thead>
<tr>
<th>VALUE</th>
<th style="text-align: left">SYMBOL</th>
</tr>
</thead>
<tbody>
<tr>
<td>0007</td>
<td style="text-align: left">WHITE</td>
</tr>
<tr>
<td>A0BD</td>
<td style="text-align: left">XLOOP</td>
</tr>
<tr>
<td>0006</td>
<td style="text-align: left">YELLOW</td>
</tr>
<tr>
<td>A0BA</td>
<td style="text-align: left">YLOOP</td>
</tr>
<tr>
<td>41F8</td>
<td style="text-align: left">Z_TOTAL_BYTES</td>
</tr>
</tbody>
</table>
<p>And showing me that I’m using <code class="language-plaintext highlighter-rouge">41f8</code> bytes of data or 16888 in decimal money. So with all my game graphics loaded and may be a tenth of the logic implemented I have a hair under half the available memory left. Which puts me in a pretty good position. I have not even started cheating yet and stuffing data into the screen buffer :-)</p>
<h3 id="modern-tooling">Modern tooling</h3>
<p>If like myself you are a user of the Visual Studio ZX Spectrum IDE by Istvan Novak (<a href="https://github.com/Dotneteer/spectnetide">Git Hub</a> repo) , then this process is made <em>much</em> easier. In visual studio navigate to
the menu item</p>
<p><code class="language-plaintext highlighter-rouge">ZX Spectrum IDE > Z80 Assembler output</code></p>
<p>This will pop open a window within the IDE, that in addition to the symbols list, has a summary tab that shows the total amount of memory used.</p>
<div class="dbImg zoom80 centeredImg" data-src="z80/how-to-tell-how-much-memory-your-z80-application-is-using.png" title="SpecNet IDE Assembler output window"></div>
<p>As usual SpecNet IDE is proving to be my IDE of choice for spectrum development. Which you can read about here.</p>
<p><a href="https://www.overtakenbyevents.com/how-to-tell-how-much-memory-your-z80-application-is-using/">How much memory is my z80 program using?</a> was originally published by David Black at <a href="https://www.overtakenbyevents.com">Overtaken by events</a> on February 03, 2018.</p>https://www.overtakenbyevents.com/Think-before-you-type2015-12-13T00:00:00+00:002015-12-13T00:00:00+00:00David Blackhttps://www.overtakenbyevents.comdavid_black_uk@yahoo.com
<p>Don’t take this too seriously but it made me chuckle.</p>
<p>I was just looking at the home page for the <a href="http://www.x-plane.com/desktop/home/">X-Plane flight simulator</a> and under the section on what our customers are saying I came across this little pearl of wisdom.</p>
<blockquote>
<p>I’m speechless! There are absolutely no words that
can describe the beauty in X-Plane 10. I’m an avid
flight simmer and current student pilot.<br />
X-Plane 10 is the closest to reality that I’ve experienced.</p>
<ul>
<li>Kendal, from Texas</li>
</ul>
</blockquote>
<p>It’s amazing just how many characters a speechless person can consume to say how words can’t describe something.</p>
<p>However the fact that: “X-Plane 10 is the closest to reality that I’ve experienced”, begs two questions: Is Kendal in The Matrix? or has he ever tried just looking out of the window?</p>
<p>Although you can forgive him for the hyperbole as, well, it is rather sexy.</p>
<hr />
<div class="dbImg zoom30 centeredImg" data-src="2015-12-13/1.jpg" title="Image from Youtube"></div>
<hr />
<div class="dbImg zoom80 centeredImg" data-src="2015-12-13/2.jpg" title="mage from Youtube"></div>
<hr />
<div class="dbImg zoom80 centeredImg" data-src="2015-12-13/3.jpg" title="mage from Youtube"></div>
<p><a href="https://www.overtakenbyevents.com/Think-before-you-type/">Think before you type</a> was originally published by David Black at <a href="https://www.overtakenbyevents.com">Overtaken by events</a> on December 13, 2015.</p>https://www.overtakenbyevents.com/Spectrum-development-then-and-now2015-10-15T00:00:00+01:002015-10-15T00:00:00+01:00David Blackhttps://www.overtakenbyevents.comdavid_black_uk@yahoo.com
<p>The other month I wrote about Fireman Fred a ZX-Spectrum game I wrote in 1984. This got me to thinking about the development workflow back then. I also started wondering just how much better it might be today.</p>
<p>I definitely wasn’t thinking about rewriting Fred. Definitely not. No.</p>
<h2 id="development-environment-then">Development environment then</h2>
<p>In 1984 the ultimate development environment for a Sinclair ZX Spectrum was a Tandy TRS-80 model 3 and a custom hardware bridge that allowed binaries assembled on the trash 80 to be loaded into the spectrum memory. Reputedly this is how Mathew Smith wrote manic miner and Jet Set Willy, it had floppy disks and everything!</p>
<div class="dbImg zoom60 centeredImg" data-src="2015-10-05/trs-80-III.jpg" title="Image Copyright: Bilby - Own work. Licensed under CC BY 3.0 via Commons"></div>
<p style="color:gray; font-size: 80%; text-align: center;"><a href="https://commons.wikimedia.org/wiki/File:TRS-80_Model_3_01.jpg#/media/File:TRS-80_Model_3_01.jpg">Image Copyright: Bilby - Own work. Licensed under CC BY 3.0 via Commons</a></p>
<p>Anybody like myself who had to save up for two years to buy a Spectrum wasn’t going to be able to go that route. So we went with using the spectrum to assemble, cassette tapes to store code and a 15 inch portable tv as a monitor.</p>
<div class="dbImg speccy centeredImg" data-src="2015-10-05/spec-with-cassette.jpg" title="Image of spectrum"></div>
<p>The tv was black and white too. I had to go downstairs after everyone else was asleep and test it on the colour TV in the living room.</p>
<h3 id="ide">IDE</h3>
<p>Don’t laugh :-) There was an IDE of sorts. It was <em>Oxford Computer Publishing’s</em>, Full Screen Editor Assembler.</p>
<div class="dbImg zoom80 centeredImg" data-src="2015-10-05/ocp.jpg" title="Box art for OCP Assembler"></div>
<p style="color:gray; font-size: 80%; text-align: center;"><a href="http://www.worldofspectrum.org/infoseekid.cgi?id=0008187">Image Source: World of spectrum</a></p>
<p>There was an integrated editor and assembler. Memory was tight on the spectrum so that influenced the workflow.</p>
<h3 id="workflow">Workflow</h3>
<p>The program was written in modules, each module was saved to its own C15 Cassette tape. So one module might be the sprite library, another the level data etc. There were in total about 7 tapes IIRC.</p>
<p>Editing assembly modules consisted of loading the tape into the assembler , editing and then saving back (always remembering to rewind).</p>
<p>To build the program you put the dev environment into assemble mode, then you loaded the tapes in order one after another. Get the order wrong and start again.</p>
<p>Once the last tape was loaded you inserted the output tape and wrote the game to that. Then you rewound the output tape, reset the specie and loaded the game. Then you tested it, reset the spectrum, loaded the assembler and off you went round the loop again.</p>
<p>Apart of course when you make a disastrous mistake: like rewinding the last module tape, forgetting to eject it overwriting your entire last module with the game. Loosing potentially weeks of work (did that, the scars still linger).</p>
<p>Backups were made of course at the backup of last resort was a printout from my old trusty Epson RX80FT. It got used a lot.</p>
<p>The entire assembly process from start to execution of the game could easily be 10 to 15 minutes. I really did measure twice back then.</p>
<h2 id="development-environment-now">Development environment now</h2>
<p>My current development machine is a quad core i7 4790K Hackintosh with 32GB RAM and an NVIDIA GTX980 (well alright 2 of em) and of course three monitors. Thinking about it, the chair I’m sitting on cost more than my Spectrum did.</p>
<h3 id="ide-1">IDE</h3>
<p>I had a lot of fun sorting out a development environment for Spectrum gaming on OS X. Obviously an integrated development environment was going to be a bit of a stretch, but by combining a few different packages I was able to achieve it.</p>
<p>First we start with the editor, for this I chose Sublime Text. When looking for a Syntax highlighting package for Z80 assembly language and Sublime, I found the <a href="https://github.com/psbhlw/sublime-text-z80asm">Z80 Asm plugin for Sublime Text 2</a> project on GitHub. In addition to syntax highlighting the plug in offers tons of features like snippets and goto symbol etc.</p>
<p>The Z80 Asm plugin recommends the use of other supporting sofware, however I went with my own tooling. Günter Woigk works on the <a href="http://k1.spdns.de">Zasm Z80 Assembler</a> and the <a href="http://k1.spdns.de">zxsp Spectrum emulator</a>. These tools are awesome.</p>
<p>To glue the whole thing together I create a make file in the root of my project:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>zasm = ~/Downloads/zasm-4.0.12-osx10.9/zasm
main:
$(zasm) -u fred.asm
open fred.tap
</code></pre></div></div>
<p>Now when I press <code class="language-plaintext highlighter-rouge">command-b</code> in sublime it builds and runs the app.</p>
<div class="dbImg zoom60 centeredImg" data-src="2015-10-05/sublime.png" title="Speccy IDE"></div>
<h3 id="workflow-1">Workflow</h3>
<p>This is the modern digital workflow. Edit in Sublime, hit command-b test in <code class="language-plaintext highlighter-rouge">zxsp.</code> The interesting thing is the time it takes: End-to-end from starting to assemble, to Fred loaded and running, is less than a second! Zxsp has a debugger where you can create break points, inspect registers and single step. Where was this in 1984?</p>
<h2 id="silly-stats-and-why-it-wasnt-there-in-84">Silly stats and why it wasn’t there in ‘84</h2>
<p>OK, this is just a bit of fun but:</p>
<p>In 1984 a cheap 32K Ram pack for the spectrum cost $60.80, so my 32GB of ram would have cost me: $63,761,699 and I didn’t have that much money at hand (and that’s 1984 money).</p>
<div class="dbImg zoom80 centeredImg" data-src="2015-10-05/cheetah.jpg" title="Advert for RAM"></div>
<p>My GTX 980 has a peak shader arithmetic rate of 5 tera flops each. According to <a href="https://en.wikipedia.org/wiki/FLOPS">Wikipedia</a> In 1984 a giga flop cost $18,750,000 so my 5 tera flops come in at the low, low price of $93,750,000,000 and I have two of em.</p>
<p>Now multiply those figures by 2.3 and you’ve got the prices as they would be today. Future me would have been rich back then :-)</p>
<p><em>Update:</em> I’ve written a follow up to this article describing a <a href="/Spectrum-development-then-and-now-part2/">new pc based approach to Spectrum development in 2018</a>.</p>
<p><a href="https://www.overtakenbyevents.com/Spectrum-development-then-and-now/">Spectrum development then and now: Part I</a> was originally published by David Black at <a href="https://www.overtakenbyevents.com">Overtaken by events</a> on October 15, 2015.</p>https://www.overtakenbyevents.com/Tell-us-about-the-war-granddad2015-07-15 09:30:10 +0100T00:00:00-00:002015-09-18T00:00:00+01:00David Blackhttps://www.overtakenbyevents.comdavid_black_uk@yahoo.com
<p>I wrote that title as a joke, then realized that I am actually old enough to be a Grandad. Where on earth did the intervening 31 years go?</p>
<p>So in 1984 (Eek) I bought my first ever computer the awesome Sinclair ZX-Spectrum. I wanted a Sinclair ZX-81 but it took me almost two years to save up the money.</p>
<div class="dbImg speccy centeredImg" data-src="2015-09-18/speccy.jpg" title="Image Copyright: Bill Bertram (aka Pixel8)"></div>
<p style="color:gray; font-size: 80%; text-align: center;"><a href="http://en.wikipedia.org/wiki/User:Pixel8">Image Copyright: Bill Bertram (aka Pixel8)</a></p>
<p>With the absolute confidence of youth I started off not with <em>hello world</em>, but with a game written in basic. While I was saving for my computer I had been reading magazine articles and library books on programming, so I did know something about what I was trying. Just not enough, it was <em>slow</em> and <em>terrible</em>.</p>
<p>The conventional wisdom of the time was that to make a game you had to write it in assembly language (this was absolutely true). So I wrote my second game: which was <em>fast</em> and <em>terrible</em>. It was also <strong>published</strong>.</p>
<h2 id="meet-fireman-fred">Meet: Fireman fred</h2>
<p>My first published game was <em>Fireman Fred</em>, named in the way of all Spectrum games, with gratuitous alliteration. It was a total Manic miner rip off, just far, far worse.</p>
<div class="dbImg centeredImg" data-src="2015-09-18/firemanFred.gif"></div>
<p>You had to climb the ladders collect the people (and cats too) and take them to the ambulance. Once all the poor wretches had been collected you got to go to the next level.</p>
<p>I demoed Fireman Fred to the owner of a local record/games shop in Sunderland (I worked there part-time, I wasn’t just showing it to random strangers) he kept the tape and showed it to a rep for Tynesoft Computer Software. They were desperate for almost anything to sell back then so they signed me up.</p>
<div class="dbImg centeredImg" data-src="2015-09-18/loading-screen.gif"></div>
<p>I think the deal was an advance of £1,000 on royalties of 50p a copy sold (rrp £5.50).</p>
<p>Tynesoft leaped into action with a massive marketing campaign:</p>
<div class="dbImg centeredImg zoom70" data-src="2015-09-18/advert.png"></div>
<p style="color:gray; font-size: 80%; text-align: center;"><a href="http://wos.meulie.net">Image From: Wos, text copy right Home Computing Weekly </a></p>
<p>Then surprisingly, Fred made money. Who’d of thunk.</p>
<p>Here he is in all his box art glory (and following the rules of the day when box art had nothing to do with the game itself).</p>
<div class="dbImg centeredImg" data-src="2015-09-18/cassette-inlay.jpg"></div>
<h3 id="mechanics">Mechanics</h3>
<p>OK, Fred did flicker, didn’t have a proper game loop and got slower when there was a lot of on screen movement, but it’s still my baby! I did learn from Fred and things got better in the next games (and there were quite a few of them.)</p>
<p>I like the mechanic of rescuing the wretches and carrying them to the ambulance vs the standard system of just touching keys to collect them, then moving to the door that ends the level.</p>
<p>I think it’s funny that it never occurred to me to use a fire engine rather than an ambulance. The game could easily have been Ambulance Artisan Alan the way it plays :-).</p>
<h3 id="levels">Levels</h3>
<p>Fred had I think twenty one levels here’s the level map that shows most of them (click for a larger image.)</p>
<div class="dbImg centeredImg zoom50" data-src="2015-09-18/level-map.png"></div>
<h3 id="unbelievably">Unbelievably</h3>
<p>You tube user <a href="https://www.youtube.com/channel/UC_dvo6BqXid0v470tVDseOA">zxspectrumgames64</a> did a play through of Fred and put it on youtube. I’ve played Fred on emulators before but seeing that video (bad as the game was) brought a lump to my throat.</p>
<iframe width="560" height="315" src="http://www.youtube.com/embed/t4LkLHSqbj8" frameborder="0"> </iframe>
<p><a href="https://www.overtakenbyevents.com/Tell-us-about-the-war-granddad/">Tell us about the war Grandad</a> was originally published by David Black at <a href="https://www.overtakenbyevents.com">Overtaken by events</a> on September 18, 2015.</p>https://www.overtakenbyevents.com/Lost-phone2015-07-15 09:30:10 +0100T00:00:00-00:002015-07-19T00:00:00+01:00David Blackhttps://www.overtakenbyevents.comdavid_black_uk@yahoo.com
<p>Ok, not a biggie, I lost my phone (understatement alert). However that little apple device I have strapped to my wrist is missing the little red icon of loneliness:
<img class="dosShot screenShot centeredImg" src="../../images/2015-07-19-Lost-phone/no-phone.png" /></p>
<p>So at least I lost it in the comfort of my own home. Now, off to the land-line to call it and track it down. Eek, not so fast, I’ve got the blasted ringer muted. Hmmm…</p>
<p>After a moment of genuine head scratching I remember that the apple watch has a function for this. Going to the glances view and selecting the left most glance you get the following preferences pane.</p>
<p><img class="dosShot screenShot centeredImg" src="../../images/2015-07-19-Lost-phone/find-my-watch.png" /></p>
<p>Tapping the ‘<em>locate my phone</em>’ button makes your phone sound a pinging noise. Hurrah! phone found (at the top of the laundry basket, where it was sitting in my jeans pocket).</p>
<p>Trying to find your phone in the dark? pressing the ‘<em>locate my phone</em>’ button and holding your finger down will make the led on the iPhone’s back strobe. Very cool.</p>
<p>Now where did I put my glasses…</p>
<p><a href="https://www.overtakenbyevents.com/Lost-phone/">Lost iPhone woes</a> was originally published by David Black at <a href="https://www.overtakenbyevents.com">Overtaken by events</a> on July 19, 2015.</p>