I’ve done an initial implementation of the blending in Cool Riders, turns out the basic logic is
If a sprite has palette value of 0x8000 it’s transparent, always.
A value < 0x8000 is a solid 555RGB colour
A value > 0x8000 is a blended 555RGB colour
when a Colour is blended a sprite attribute is used to decide the blending level, this goes between 0x0 (full blend, MAYBE 100% invisible) to 0x7 (no blend, solid)
Implementing this was more work than I expected, mainly because it broke my zbuffer implementation, because in some cases transparent sprites were being sent to the display by the game before the sprites they were meant to cover, causing them to cut holes in sprites and show the background instead. The only real way to fix this was to sort all the sprites based on their z value before drawing which meant a slight change in the way things were being done was needed.
Having done that, I was able to get the above screens, and blending seems correct in the cases where it’s used now.
One thing that threw me off when trying to figure out the blending at first was that ALL the road pixels had the 0x8000 bits set, why would you want to blend the road? The only thing underneath it is the background! It turns out that most sections of the road actually have the 0x7 value set for the blend level, meaning they render as solid, but during my testing (rendering different values of that register as random colours every frame) I noticed that some bits of the road actually had different blend values set, in increasing amount. It turns out the blending is used for a most unexpected effect too, blending the end of one road terrain type with the start of the next! The screenshots below show the road between stages first, on the left from an earlier build without blending, and the right the current code, with blending applied, kinda neat.
(Left, old code, no blending | Right, new code, blending used between road sections)
This is also used to great effect on short tunnels and the like. The road blending also gets used to show sprites below the tunnel for a special effect when entering the extra stage, as the first lot of screenshots show.
Of course doing all this slows things down a bit, so I’ve actually spent most of the past 2 days coming up with optimizations, including an object tile caching system so that we can avoid calling the RLE decoder too often, as decoding entire rows of 16×16 tiles each time just to draw a tiny road line in the background is not an insignificant waste of CPU power! All that got it up to a decent enough speed on my system, before all the extra effects dragged us to around where we were before, so time well sent.
Additionally I improved the full-screen RGB effect logic, so it now actually gets applied to the full screen instead of just the tilemaps, but it will need a video to demonstrate that, and I don’t have time to do one tonight, later maybe.
(Video showing the latest progress, cropped to a single screen)
(same video, without cropping so you can see the attract on the 2nd screen)
A few graphical glitches remain, but nothing major and it’s feasible the ones we have left could be original bugs although I do have a few things to try first. The sound is still buggy, but as of now the game is marked as WORKING.
Another interesting aspect of the Cool Riders hardware is the way the palettes work, and this is also tied directly to the compression.
Due to the palettes for the sprites being hardcoded in the compressed gfx ROM with the sprite data it would be quite tricky to do colour cycle type effects without storing an entire extra copy of the palettes just for one or two changes. Sega realised this and covered it by allowing secondary ‘partial’ palette entries to be used, substituting a specified range of colours in the original palette if enabled. This is how the tyres and brakelights on the Player and Rival bikes work. If you look at the older screenshots like the one below:
(old screenshot from previous update, note the tyres / light on the bikes are wrong)
You’ll see that the wheels and brakelights appear are bright blue/green colours. This is because those data entries are a actually meant to use data from the 2nd palette index specified, not the first. This means that by cycling the secondary palette index value, and leaving the first alone the wheels of the wheels can be animated without storing the colours needed for the rest of the object. If you render just the second palette index values, ignoring the primary one you end up with the following, note, the tyres and brakelight are correct
(test screenshot, just the using the 2nd palette index instead of the first, note for the bikes ONLY the tyres / light are correct)
Interestingly, if you render the scene using ONLY the second palette indexes get a lot of objects are still correct, because for most they duplicate the same palette entry in both.
Combining the two you get this
(new screenshot, all bike graphics are correct)
How does this work? Well we know the basics, it’s done when decompressing the RLE sprites, using the 2nd index in certain situations, but beyond that is where things become confusing. The problem is this effect seems ONLY to be used on the bikes, giving little evidence of how it should actually work. Maybe for certain sprite type it’s always enabled, so they have to ensure both palette indexes point to the same place, but even then there is what should be a mask / threshold value which is set to 00 for everything except the bike anyway, and there is a bit ONLY set on the bike which would seem a sensible bit in a sensible location to use to enable the effect. Either way, it works, but that’s sometimes the downside of hardware with only one game, making limited use of something. If the game didn’t use this here we wouldn’t know about it at all. Another point of interest is that OutRunners also uses a special way to do the brakelights on the bikes, although a different one to the one we have here, but again it points at some of the System32 thought processes going into the design here.
One effect used more widely is the RGB brightness control, and it’s the reason some things turn an odd colour in the background in the current video. Kale has done a preliminary hookup of this effect, but right now it’s not quite right (has various modes) and in addition it should apply to the full screen, including sprites, so you can’t even see if if you’re in a tunnel right now, or you have a background partially made of sprites. It’s used for various thing, including flashing the screen red when you crash, and a white ‘flash’ when you come out of a tunnel, as an attempt to simulate the time it takes for your eyes to readjust to the light.
Kale also added an interpretation of some other registers, allowing the InVision logo, and filmstrip part of the attract to render with solid backgrounds, rather than the background tilemaps which shouldn’t appear there.
The filmstrip also uses another feature, clipping windows. For each part of the filmstrip a window is specified, this clips all graphics to within the specified area and is noticeable on a number of the animations, especially the zooming one (we’re still missing a heart on the TV there, but that’s another matter) This effect is also used between stages (not quite sure why) and occasionally gets set to erroneous(?) values on certain levels like Romania, the second time you encounter Dracula. Not sure what that should do, if anything. I’ve implemented this effect, interestingly the format for these windows is basically the same as the format used for the framebuffer copy params. Furthermore there might be yet another way to specify this using another set of blitter registers, used in the end sequence (you can’t notice with the ending in the video, but for the one in the previous video the text should get clipped to the TV screen area, currently the game just sends a ‘full-screen’ setting via the usual method so that needs further investigation)
Anyway, that’s yesterday’s work. I might take a break from things today before looking at the blending.
The routes, for people interested
Stage 0: Prestage
1st Stages: Niagra Falls
2nd Stages: Greenland, West Indies, Brazil
3rd Stages: Rumania, England(1), Spain, Egypt, Kenya
4th Stages: Arctic, Russia, China, Japan(1), Hong Kong, India, Antarctic
1st Stages: New York
2nd Stages: Washington, Niagra Falls (2), Chicago
3rd Stages: Atlanta, Mississippi, Desert, Grand Canyon (2), Rocky Mountains
4th Stages: Florida, Houston, Texas, Hawaii (1), Las Vegas, San Francisco, Alaska
1st Stages: Grand Canyon (1)
2nd Stages: polynesia, Hawaii(2), Canada
3rd Stages: Australia, Indonesia, Japan(2), Mongolia, Russia
4th Stages: Antarctic(2), Kenya, France, Switzerland, England(2), Sweden, Arctic(2)
One of the most significant improvements to the Cool Riders emulation over the last day and a bit has been the addition of Priority handling, allowing you to see most of the objects as they were meant to appear.
It turns out the system uses what appears to be a 12 + 2 bit z-buffer (although it could possible be full 16-bit, and the 2 separate bits MIGHT have additional separate meaning) This is a lot more priority depth than most 2D systems have, and is actually closer to what you’d find on a 3D system. Either way, simply implementing it as a 14-bit z-buffer and doing a z-compare for every pixel write at least fixes most priorities, leaving the game mostly playable again.
The other fix made over the last few days involves the transparent pens. Previously there were pixels missing from most objects (not the zoom gaps, I’ll talk about those later) This was caused by us filtering out all 0x0000 value pixels when copying our framebuffer to the screen. This was actually incorrect because 0x0000 means the pen is black, instead pens which should be (fully) transparent have a value of 0x8000. The most significant bit also seems to have other meanings tho, and is set on some objects which should be alpha-blended, as well as the text and various other objects for reasons I don’t yet understand. We actually have a 2nd palette offset with some sprites too, although it’s usually set to the same value. Either way there are still questions to be answered, because if the 0x8000 bit specifies alpha blending, how do you blend a black pen? It could of course be additive blending, in which case a black pen would blend to the same colour as the source, but I’m not sure of this yet. At least now however objects look a bit better.
There are still imperfections, other than the missing transparency effects my zoom precision is still inaccurate, this is what is causing the gaps between sprite tiles in many cases. It’s easy to understand why, each tile is 16-pixels wide, sprites can be made of multiple tiles (and usually are) The zoom value for 1:1 drawing is 0x40 (128) to draw 16 pixels, and so the lower bits of the zoom, if looked at on a per-tile scale have no effect, you’d need to span multiple tiles to see them. The problem is my zoom drawing currently only considers the current tile when drawing it, but the full zoomed width of the sprite when placing it, hence gaps. It shouldn’t be too hard to come up with a better algorithm and elimiate the gaps, but zooming in emulation is rarely perfect because the actual algorithms applied by hardware when deciding which pixels to shrink / expand vary wildly, and only in some cases is it obviously contains in a ROM table (NeoGeo being one such example)
Performance is currently an issue too. For all I’ve said about this being a sprite-scaler it can throw as much at the screen as most 3D systems, make that 2 screens, each running at a medium resolution (same as Daytona etc.) with lots of scaling, z-checking, and (once implemented) blending and you can see it’s expensive. Currently for good performance you’ll need a decent i3/i5, my Core2 doesn’t quite cut it in places. I’m still trying to optimize it, and there is definitely room for improvement in some area. I was hoping that threading the sprite rendering would help some, but it doesn’t, it helps a little, but also becomes very sensitive to any other use of the 2nd core by the host PC (are MAME threads running at a really low priority or something?) so while you get some gains you can get nasty performance spikes if the PC decides to do something else in the background. I’m not out of ideas yet, but I thought it fair to warn people that in the current state it is kinda slow. Just emulating the CPUs, and sound chips alone (even with SH2 recompiler) is actually quite a drag, so I don’t have THAT much room for maneuver.
There are still other missing features too, quite a few registers are ignored, and there are definitely clipping window effects I need to implement. How the tilemaps get enabled / disabled isn’t known either.
*edit* Zoom handling has been improved, gaps (mostly) gone
Here’s the video to go with this update, sorry for the delay, I’ve probably hit some kind of unwritten monthly upload limit because my uploads are terribly slow right now ;-) A few changes have been made since this was recorded, but they’ll have to wait.
I like to do articles about interesting / unique things I find when emulating a platform, and the way the road is drawn on Cool Riders is one of those things.
While most hardware uses a ’tilemap’ like chip to draw a road with linescroll and lineselect type parameters to do bends and curves (that’s how it works on OutRunners for example) or simply throw a ton of layered sprites at the job (F1 Super Lap) Cool Riders takes a hybrid approach.
You’ll have noticed that in the previous update, even the latest video I added to it was lacking the center of the road, this is because the road is somewhat special. While it does still use the regular sprites / blits it has an extra parameters on them. This parameter allows every line in the sprite to use a lookup value specifying the zoom and scroll offsets for that line of the sprite. This essentially allows you trapezoid shaped sprites by having a table of increasing zoom values. That’s exactly what Cool Riders does, meaning this extension to the sprite system lets them use normal sprites in a way more suited to drawing the road.
Here are some screenshots, sorry about the bad colours and priority, I haven’t figured those things out yet. Also there are gaps in the zooming because my algorithm is imperfect.
Hooking up the road has actually made it much harder to play for now, because it gets drawn over the bike, the priority scheme looks to be non-trivial at this point.
Anyway, Cool Riders also sports another fairly uncommon feature. As well as being able to flip sprites in the horizontal and vertical direction it can also rotate them by 90 degrees. This is used on the map screen. All 3 forks of the main tree are the same sprite with rotation applied. Quite why all roads lead to New York at opposite ends of the earth I don’t know, especially not when it’s the 2nd stage. From memory some Dynax hardware supports a similar effect.
What happens if you enable both effects at once? I haven’t seen the game do that, and I likely don’t want to know ;-)
Overnight Kale confirmed something I’d been thinking for a while, the Sprite palettes are in the compressed ROMs (they appear to be uncompressed tho) This allowed him to fix the palettes for the text in test mode, but still needs work for actual game graphics etc.
CRT test screens can be handy, I’ve started to (hopefully) improve the palette addressing based on it
That’s better.. fixes some ingame objects too (but still not right ingame)
Some Ingame colours, note still broken transparencies, imperfect zoom, and broken priority.. so you can’t actually see much
So.. I spent all night looking at the sprites, it’s 7am now.. I should probably get some sleep
There is a video to go with this too… didn’t have time to do it last night
Anyway, as discussed before the game uses compressed sprites. The actual compression isn’t TOO complex, it’s just several RLE modes in the end (although the current implementation is still incomplete, many sprites have holes, and I don’t know if the palettes are encoded in there too)
The main issue is the weird arrangement of the ROMs, the compression works on 10-bits at a time, which is unusual, and means that the game actually has 10 sprite roms, which need to be correctly ordered and divided up to get the right data to process.
One area Cool Riders differs to practically every other Sega game is that the sprites are actually TILE based, every sprite is made of a number of 16×16 tiles, and the layout of these tiles for each sprite is also stored in the compressed graphics roms. The spritelist actually references a tile arrangement in these roms, with that tile arrangement further referencing the compressed data located at some position after it (allowing for the same compressed data to be shared with multiple tile arrangements)
Anyway, for now the temp zoom code is gone, so you can see things break up quite badly in the video, and the lack of flipping becomes VERY obvious now we have somewhat correct sprite data. Improving these is on my todo list. Likewise I still need to figure out where the framebuffer clear bits are because right now it flickers badly, it’s migraine inducing.
Here is a video from yesterday with temp zoom code reinstated, some stupid bugs with flipped-zoomed sprites that have since been fixed tho.
Cool Riders by Sega is another one of those titles where the hardware is so odd it has Mamedev stumped. The driver hasn’t really seen much attention over the last year so I decided to at least correct a few things in it.
First of all it’s a dual screen game, and we were sending all the blit commands to just one screen, I fixed that, setting it up with a dual screen layout in MAME, and hooked up the different backgrounds for each screen too.
I also added code to interpret some more of the blit parameters, rather than ignoring them. This allows you to see roughly where the road should be, and follow the attract sequences compared to videos of the real thing.
Additionally I made it possible to load a fake ASCII font rom in debug versions of MAME so that the test mode can be navigated, allowing for further fixes.
None of this is really much help tho, because the biggest problem remains the missing / not understood compression used on all the blitter objects / sprites. The compression is used on EVERYTHING except the backgrounds hence having to load the fake ASCII rom just to be able to see the test mode properly. Not even the backgrounds make sense entirely, I can’t find the scroll registers for them.
With the changes the emulation now looks like this
I hope we can figure it out, it’s Sega’s final sprite scaler game, and actually runs at the same resolution as the Model 2 boards, I guess they just decided that this unique H1 board was a dead-end and 3D tech was the way forward. As mentioned in previous updates about the game it’s really just a re-worked version of OutRunners with bikes, so many bits of the game are clearly just re-skinned versions of that game it’s quite amazing to see!
Anyway, after doing this, and recording the video, Kale has also put some effort into figuring things out, actually hooking up the inputs now by using test mode enabled by use of the fake ASCII characters, he has also attempted to hook up sound, but that too seems more complex and involves both the sub SH1, a 68k, 2 SCSPs and likely some sound DMAs in addition to a complex interrupts setup, so for now it still remains silent. You can now coin the game up and ‘drive’ the random squares you see around, so that’s certainly progress.
Additionally I found that the ‘ingame’ palette wasn’t always right, and found out there are additional palette writes in the same place as the ‘sprites’ get uploaded, and these are used to fade between level backgrounds. Here is a second video showing the inputs working as per Kale’s fix, and the fading. (sorry about the excessive flicker on this one, I think frameskip was turned on)
Nothing about this hardware is straightforward, but that’s why it’s taken so long to even make this much progress.
Kale also added some (very) preliminary sound
Can’t guarantee any more progress in the short term, but I think it’s good to remind people that drivers are rarely forgotten completely.
The cookie settings on this website are set to "allow cookies" to give you the best browsing experience possible. If you continue to use this website without changing your cookie settings or you click "Accept" below then you are consenting to this.