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
- 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.
- 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.
- 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.
- A sprite's colour byte can be set to 0 (transparent) to render the sprite invisible
- 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
- 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
Post a Comment