Skip to main content

Diagnosing and fixing a couple of sprite issues with my TMS9918A emulator

Recently I've been working on a small hardware enhancement for my TMSEMU board for RC2014 to allow it to be used with my MSX2014 and perhaps more importantly, with MSX ROMs running on the CP/M RC2014

Anyway, I've reduced the additional circuit to a single logic IC and couple of passives, so I'll be adding that to the TMSEMU board very soon. You can see the additional circuitry on a bit of proto board in this picture, and you can see the fantastic picture that the TMSEMU gives to my MSX2014 (and to any RC2014).

However, this showed up a couple of problems that I hadn't been aware of with my TMS emulation, specifically with sprites.

The first happens with the game 'The Goblin' (sorry for the reflection). The screen should be blank other than the decorative border at that point but many sprites are still showing.

The second shot shows one of my favourite games, Keystone Kapers, you can see bits of sprites appearing in the top border. These problems may or may not be unrelated. 

Obviously in both cases, sprites should be hidden but are showing.

Ways to hide sprites when you don't need them on the screen

  1. There's a special bit in the sprite's attributes which moves the sprite 32 pixels to the left. It's used for moving a sprite into the screen from the left. The documentation does say 32 pixels, so even for a magnified sprite which is 32 pixels wide, it should be totally off screen if its x coord is zero. A 16x16 sprite could definitely be shifted offscreen using this method.
  2. It may be moved entirely off the top/bottom of the screen. There are only 192 scanlines in the picture area, which means that Y values in the C0-E0 range will put a 16x16 or 32x32 sprite entirely in the border area and therefore not visible.
  3. If a sprite contains a special value D0 in its Y position, then that means 'stop processing' and all sprites after that in the table will be invisible. This is very useful because you can blank out many or all sprites by changing a single byte.
  4. A sprite's colour byte can be set to 0 (transparent) to render the sprite invisible 
  5. A sprites 'name' byte (pointer to the sprite data table) can be changed to point to sprite data that contains all zeros - then the sprite will have no visible pixels
  6. Sprites are not active in text mode

There may be more. Let me know if I've missed something off this list.

Some of these can be ruled out for the Goblin issue. The most likely suspect would be number 3, the D0 trick. 

I was confident that I had implemented and tested this feature in TMSEMU (as well as all of the other things in this list). 

Analysing these problem was tricky because they happened with a couple of specific games on my MSX computer. I couldn't easily examine the code to see what they were doing to hide the sprites at that point.

I thought about disassembly. I guess I could have spoken to the authors of the games.

It would be very helpful to examine the data in the sprite attribute table, and the VDP registers, at the point that the problem happens. Looking back now, maybe one of the emulators has a monitor that I could have used for this purpose.

I'm a printf person when it comes to debugging. My emulator is based on an RP2040 which can do serial, in fact it already monitors the serial line on the bus to act as a terminal when in text mode.

Here is my answer. It looks unsightly but it worked beautifully. Behind the regular TMSEMU with its currently-bodged-on circuitry is another TMSEMU which has been butchered. Parts of the hardware are removed because it doesn't need to put anything on the bus, just listen. And the software is severely cut-down to take out the DVI functionality and other things, and to send debugging information. (It would have been nice to use the micro-USB for serial out, but for reasons I don't understand, the way that I'm using interrupts in TMSEMU breaks the built-in serial, leaving me with PIO UART). 

It took a lot of work to develop that, but  it works beautifully!

It shows me a dump of the sprite attribute table as well as a couple of registers I wanted to see. At the point when the problem happens in the Goblin game, we can see clearly that the D0 trick is being used to turn off all the sprites as suspected (highlighted in the above shot.)

I don't know whether to admit this or not, but I've made an ass out of u and me by believing my own memory of implementing that feature. When I looked at the appropriate code I found this:

What that means is that I did implement the feature, it was working. But then I fixed another minor issue with the sprite display order which broke the D0 feature. I was well aware of that and left a note for myself to fix it. Which I did not do.

That fixed the problem with the Goblin game. The screen now looks as it should in between levels or after losing a life. 

But it didn't fix the Keystone Kapers problem, so they were unrelated. 

The spurious sprites were appearing in the border area, which shouldn't happen under any conditions. 

I wrote a program (or adapted an existing demo) to display these sprites and decrement the Y positions slowly pixel by pixel, for all 256 values of the Y position byte. I watched it without daring to blink until my eyes dried out, but it correctly disappeared as it went up into the border and reappeared at the bottom within the screen area.

once again the debug data came into its own! No D0 trick here (though they are being moved up into the border area - see the E0's). The sprites are once again 16x16 and unmagnified, as per my little test program. But those two status registers show that the screen mode is in 'graphics mode 1' or tile mode, not graphics II / bitmap. And this made the difference - bingo!

Again, the hard part was diagnosing and reprocuding the problem. The fix was simple.

Now I can play Keystone Kapers with sharp video and no disembodied bits of enemy in the screen border!

I'll apply the sprite fix to TMSEMU modules that leave here from now on. The addition to the hardware to help with MSX ROMs will probably take a couple of weeks.


Comments

Popular posts from this blog

How to convert images for TMS9918A graphics on the RC2014

For me, graphics capability is essential for an 8-bit computer. My graphics chip of choice for the RC2014 is the very capable TMS9918A. It has 15 colours, sprites, several modes and a max resolution of 256x192. It makes arcade-style games possible, such as Tut-Tut above.  I enjoy simply displaying images and have a bunch on my CF card (my 'hard drive') and have written image viewer and slideshow apps to display them. Some useful links: Convert9918 Tutorial of Convert9918's settings Multipaint J B Langston's TMS9918A video module my own TMSEMU video module my respository of TMS9918A software, games and .s2/.sc3 images Image conversion I did dabble in writing my own utility to convert .png images but then settled on the Multipaint app which can open a png in a MSX 'screen 2', allow you to tidy it up with paint tools and save as a .sc2 file. (An sc2 file is little more than a video-memory dump and so it's easy to blast that back into vram to display the image.

Driving NeoPixels with Z80

I 've long been thinking about a version two   RC2014 LED matrix module . I've had a matrix with a MAX 7219 on a module. It's a nice enhancement. But there's only so much you can do with a single-colour LED array right? Wouldn't it be cool to have RGB LEDs?  At Liverpool MakeFest I saw a wall-sized ping-pong ball NeoPixel display and picked up some NeoPixels with the intention of making one. Possibly driven by my RC2014.  I enjoy learning about protocols and have had some SPI devices working with the RC2014 - bit-banging SPI works really well because it doesn't care about timing. NeoPixels really do care about timing though. From Adafruit's web page about their 8x8  NeoPixel matrix: If there's one thing I want to get across in this blog post, it's don't just accept what you're told . Question everything. Learn about what's going on and find out why you're being told something isn't possible. Get creative with workarounds. I'

ZX81 reversible internal 16k upgrade

T his post is an upvote for Tynemouth Software's  ZX81 reversible Internal 16K RAM upgrade . Their instructions are easy enough for even me to follow and don't involve cutting tracks. This is the ZX81 I've had out on display and used whenever I wanted to. It's an issue 1 and was probably a kit judging by some very untidy assembly. It has a ZX8-CCB  composite video mod and an external keyboard fitted. On board it has two 1k x 4-bit chips.  The ZX81 originally came with 1k on board. Thanks to a trick with compressing the display in ram, that was enough to type and run a small program but you soon felt the limitations. Back in the early 80s, the solution was a 16k ram pack which plugged into the back[1] and this is the way I've been using this particular machine. These ram packs are notorious for 'ram pack wobble'. Even if fastened into place, you can still randomly find your work disappearing. This is a very reliable solution using a more modern 32k chip (half