Sunday 23 October 2022

Valkyr - One Game, so many changes.

One of the things that have come out of the work on the Minstrel 4D is I am getting to try out so many more Jupiter Ace games. It is now so easy to load any tap files that I have been trying quite a few one.

Tetris and Snakez++ are ones I keep going back to.

Another one that stands out is Valkyr by Colin Dooley. It is a very good game, but has led to much work and many design changes during the development of the Minstrel 4D  (even though it turns out that although it was written in 1985, it was never actually released)

None of them are exclusively for this game, it is just that it was a good test case to demonstrate a few things that came up during development.

1) Bus pull ups.

This was sparked by a question on Twitter -  what values is returned when an unimplemnted address is read. On a real Jupiter Ace, this seems to be 0x20 most of the time, but not always. (0x20 is the ASCII code for a space, so is probably caused by that being read from the video RAM during a screen update).

Emulators such as EightyOne return 0xFF, as I would have expected. (N.B., since writing the original version of this post on Patreon, it seems EightyOne has been updated to return 0x20)

The Minstrel 4th seems to always return 0x58 (88 in decimal). The Minstrel 4D is the same.

This become important as Valkyr uses Z80 Interrupt Mode 2, where the interrupt address is composed of the interrupt address and whatever value is read from the databus. This is normally triggered by hardware (such as the Z80 SIO/2) which provides the appropriate value on the databus. In this case, it is triggered by the screen interrupt, an no such data is provided.

The Valkyr code seems to assume it is 0x20, and if it is not, you get the introductory screens, but as soon as the game itself starts, it locks up.

Valkyr is distributed with a second version (valkyr-em) which has been modified to expect the value of 0xFF, which meant it worked with emulators.

Many Z80 and 6502 machines have a bus pullup resistor to ensure a value of 0xFF will be read for any unallocated addresses, so it seemed like a useful thing to add to the Minstrel 4D design.

My first try was just adding a resistor network to one of the spare RC2014 connectors.

That seems to be working as expected, let's give Valkyr a go.

That is now working correctly as well. I am not aware of any problem caused by having the bus pullup resistors being present, so I have added that to the design, in almost the same position.

I also added a spot to add a bus pullup resistor network to the RC2014 Joystick card I made, so you can play Valkyr on a Minstrel 4th if you want.

2) Boldfield Joystick

I am sure I looked around several times for Jupiter Ace joysticks, and all I found was a magazine article about a DIY version that was one of those one that presses a different key on the keyboard for each direction.

In the absence of any existing standard, I decided to adopt one from the Spectrum world, and implemented a Kempston compatible interface for the Minstrel 4D.

It seems I somehow missed the Boldfield Limited Computing Joystick. (yes, they are Boldfield. They do a limited amount of computing. Just enough, but not too much).

This is much the same as the Kempston joystick interface I had already implemented, just at a different address, and with the bits in a different order. Since there is currently 1 game that supports Kempston (which I wrote), and at least 3 existing titles that support the Boldfield one, it seems sensible to change over to that.

It was time to start making mods to my beautiful, pristine development board I had just built.

That first mod was to the address decoding, just a case of changing to address to match from 0x1F to 0x01. The second was a little more intrusive, this time to the buffer IC, rearranging the bits to match to Boldfield design.

It wasn't just for that one game. As part of the load testing I have been doing, I have been lucky enough to be able to borrow a selection of real Jupiter Ace tapes. One of these is Atic Raid, a little bit of a rip off of Atic Atac for the Spectrum.

This supports the Boldfield joystick (since it was published by them).

And indeed, my modified joystick allows me to navigate around the screen.

Since writing the original post, George Beckett has adapted his ports of Tut-Tut and 3D Monster Maze to also support the Boldfield Joystick - https://github.com/markgbeckett/jupiter_ace

3 - Sound

The game supports* two sound modes, Ace sound and the Boldfield sound box.

* is meant to support.

It seems the sound support is not working, other than an initial beep.

This was tracked down to the only instance I have found so far of any software writing to the speaker using any address other than 0xFE.

The Ace used the same IO address decoding as the ZX80, "any even address", so it ties up half of the addresses from 0x00 through to 0xFE, but only ever accesses 0xFE. The Minstrel 4th and the Minstrel 4D both refined this to only 0xFE, to free up 127 more addresses for use with RC2014 expansions.

Side note: The Boldfield joystick is nominally address 0x01, but decoded "any odd address", so tied up the other half the addresses. An original Ace with an original Boldfield joystick interface would have no free IO addresses, despite only needing to use two.

Back in the development versions of the Minstrel 4th, I did have a jumper to select between the wide or narrow address decoding, but it didn't seem necessary, so didn't make it to production.

Since it was just this one game, rather than altering the decoding, George Beckett has modified the code to always use 0xFE, and now the Ace sound is working, and driving the Piezo sounder on the Minstrel 4th and 4D.

There were also some issues with the SoundBox, and George has also modified the code to be able to drive an RC2014 YM2149 card.

https://github.com/markgbeckett/jupiter_ace/tree/master/valkyr-minstrel

4) Snow

It was whilst testing the joystick, that the third problem started to annoy me.

It is difficult to take pictures of because it is only there for a second. But there is noticeable snow on something like this simple forth program to read the value of a port and print it on the screen. Most evidently in the part where it is scrolling the screen up, which involves a lot of reading a line of characters and writing them back at a different position.

This is caused by the CPU and the video circuitry both trying to access the video RAM at the same time. The way the 4th works, if the video is accessing RAM and the CPU tries to read exactly the same address, the Z80 CPU is put in a wait state until the video has finished.

If the CPU is first, when the video tries to access it is blocked and the video output is set to black, which is the spec of black snow you see. (incidentally, you don't see this if you have the inverted screen set as the snow is black, on a black background, so you only notice it if it is part of a white character).

The Jupiter Ace did things differently. It had two modes, depending on which address range you used to access the video RAM.

  • 0x2000-23FF is CPU priority. If you read or write to the video RAM via this address, the Z80 CPU always wins and if the video RAM wants to access it gets blocked (and will just display whatever data is on the bus, giving a snow effect.
  • 0x2400-27FF is video priority. If you read or write the video RAM via this address and the video circuitry is currently generating a screen line, the Z80 will be halted until the video line is complete and will then continue.

The Minstrel 4th Approach.

The Minstrel 4th relied on the dual port RAM chip to handle arbitration. It would allow simultaneous access by both video and CPU unless they happened to access the exact same address. If the video was first, /Wait would be pulled low briefly. If CPU was first, /blank would be pulled low, generating a black speckle on the output, the snow.

Here yellow shows the Z80 access, green the video access and blue the conflict signal from the dual port RAM. As you can see most of the accesses are fine, just the very occasional incidence when they both want the same address at the same time.

This was the same for either address range, it works fine most of the time. You get the occasional snow and it's otherwise fine.

Valkyr for some reason was particularly bad on a few of the information screens, with quite a lot of snow. (not sure why, but it seemed to be continually redrawing the screen?)

So, what can I do about it?

Well, I will spare you the details. There is a very long Patreon post going over all the things I tried. I was basically trying to apply the Jupiter Ace addressing mode with a CPU priority and a video priority address range.

I tried various ways, all of which mostly worked, but had the odd issue.

I even hard wired a couple of the options, in case it was the long wires which were causing issues, but to no avail.

In the end, I decided to take a different approach.

The video circuitry has a lot to do in a short time. The shift register shifts out 8 bits of each line of each character in 8 clock cycles at 6.5MHz. This means the CRTC has 8 instruction cycles to read the character from video RAM, and then look up the appropriate line of the character in the font ROM and load it into the shift register just in time for the previous character to have finished.

Whilst doing all that, it just keeps the video RAM chip select line low, as there isn't really time to switch it on and off, even though it is only actually being accessed for two of the eight cycles. Yellow is the video side select line. Green shows the Z80 accessing video RAM when the screen is not being drawn, and blue shows the "busy" signal that halts the Z80 whilst drawing the screen.

The way it is implemented, when a conflict is detected, the /Busy line on the dual port RAM causes the output to blank, so you get black dots on the display. It shares the /Blank signal that the CRTC uses to blank the pixel output during the borders and sync pulses.

I decided to try just unhooking the /Busy line, leaving everything as it was in the Minstrel 4th, relying on the conflict resolution system to deal with the issues. The only difference was it now wouldn't put a black dot on the screen if it detected a possible conflict.

What that means is when there is a conflict, the video display will not be blanked, it will just continue as normal, and for 6/8 of the cycles, this will continue correctly.

For 2/8 cycles, the read may fail or return the wrong value but in practice, I am not seeing any snow any more. Any errors are appearing in the background colour rather than in black, so the display is nice a clean.

Links to the games mentioned in this post:


Advertisements


Minstrel 4D

The Minstrel 4D is available for preorder from The Future Was 8 bit. The parts are all here and the kits are currently being assembled to ship in the next few months.

https://www.thefuturewas8bit.com/minstrel4d.html

More info in a previous post:

http://blog.tynemouthsoftware.co.uk/2022/08/minstrel-4d-overview.html

Joystick for RC2014 PCB Only

https://www.sellmyretro.com/offer/details/9-way-d-joystick-card-for-rc2014-or-minstrel-4th-pcb-62828

As it says, this is just the PCB. You need to source the rest of the parts yourself. A full parts list and schematic will be provided in the datasheet.

Joystick for RC2014 PCB + Kit

https://www.sellmyretro.com/offer/details/9-way-d-joystick-card-for-rc2014-or-minstrel-4th-full-kit-62829

The kit version includes all the parts required, including sockets and jumpers and the bus pullup array. You can omit any of all of those if you like.

So you can build a minimal or fully loaded version as required.

Patreon

You can support me via Patreon, and get access to advance previews of posts like this and behind the scenes updates. These are often in more detail than I can fit in here, so check it out if you want to read about all the different approaches I tried to video RAM priority access control. This now includes access to my Patreon only Discord server for even more regular updates.

https://www.patreon.com/tynemouthsoftware