Saturday, December 22, 2018

The last few days I have been trying to track down a few regressions, as I have got other parts of the VIC-IV behaving more compatibly.  A couple of weeks back, I fixed the colour selection for multi-colour mode and variants, as it was doing some strange things.  

In the process, I thought it might also be useful to make the illegal video modes that combine the EBC (Extended Background Colour)  and MCM (Multi-Colour Mode) of the VIC-II do something useful instead of just showing a black screen.  
So I made this combination allow the selection of foreground and background of each character using the upper and lower nybls of the colour RAM (since it is 8-bit on the C65/M65).  It seemed like a good idea.  So I made the little change, and went off and did some other things.

More recently, went and tested a few games, and found that some things were broken now that used to be fine.  In particular, Ghosts'n'Goblins was displaying a line of rubbish on certain screens:


I had been working on some improvements to the CPU/VIC timing, e.g., adding emulation for badlines, adjusting the relationship of when the screen is being drawn and when raster interrupts are actually triggered and making CPU interrupts take the correct number of cycles.  Thus I had expected things to become better, not worse. And indeed some games were a lot better. For example, almost all of the timing jitter glitching around the text notices in Gyrrus suddenly disappeared, but Ghosts'n'Goblins and a few other programs were noticeably worse.  

As I had been fiddling around with timing, I initially suspected that it might have been something like a badline triggering before $D018 was written to in a raster interrupt, and thus causing the wrong row of stuff to be displayed.  I chased my tail around on this for quite a while, before realising that that could not be the problem, and that it must instead be something else.  

After being faced with this, I eventually remembered that I had messed with the multi-colour rendering stuff.  Then using the ethernet real-time instruction logging program I wrote recently, I captured a frame's worth of instructions, and sure enough, it turns out that Ghosts'n'Goblins blanks out that row of stuff by selecting one of the illegal VIC-II modes, as can be seen from the instruction logs below:

 $31FE : AD 11 D0   LDA $D011  
 $3201 : 09 60      ORA #$60  
VIC-II raster $09a (VIC-IV raster $c05) [NEW RASTER]
 $3203 : 8D 11 D0   STA $D011  
 $3206 : AD 16 D0   LDA $D016  
 $3209 : 29 F8      AND #$F8   
 $320B : 8D 16 D0   STA $D016 
 $3252 : AD 11 D0   LDA $D011  
 $3255 : 29 9F      AND #$9F  
VIC-II raster $09c (VIC-IV raster $c0e) [NEW RASTER]
 $3257 : 8D 11 D0   STA $D011 

The instruction logger also gets VIC-IV raster line and badline notifications in the stream, which  makes it very handy for debugging this kind of thing, as we can see that these events are happening at about the right place on the screen, although I need to make those values actually reflect the raster numbering that we are all used to.

So, I reversed out my "clever" re-use of the illegal video mode, and made it correctly display black when in one of these illegal modes, and the result was:

Substantially better, although we can still see that the timing is not yet exact.  However, it is good enough to work for lots of things.

What this whole little adventure has reminded me is how complex it is to achieve a high level of compatibility with even a simple legacy system.  You basically have to assume that any strange behaviour will have been abused at some point, and needs to be reproduced.  Also that good debug tools are a life saver.

Now I just need to work out what has gone wrong with sprite rendering (see the thin gaps between the sprites in the GHOSTS'N'GOBLINS banners).  This seems to be a problem from adapting the sprite pipeline to the new (and otherwise much better and more accurate) video pixel driver rework I did recently.  I think the pixel strobes are not being delayed correctly for the sprites and so the pixel edges are not falling where they should, resulting in stretched or skinny pixels, which if they occur in the last pixel of a sprite on a given raster, can leave these tiny half-pixel wide gaps.  But that will have to wait for another post...