Jump to content

F18A Karts demo

Recommended Posts

In January 2024 there was a bit of discussion about games similar to Mario Kart:
That made me wonder what we could do on the TI.


@TheMole linked to a demo on the MSX1 using the TMS9918A VDP, but I soon came to the conclusion that in order to produce something playable on the TI we needed help from the F18A.


The F18A supports two types of bitmap layers that would be suitable for something like this: a 4 color bitmap with up to 256 horizontal pixels and a 16 color bitmap with up to 128 'fat' pixels. I decided on the latter in order to get a more colorful display. The image below is not included in the demo, but shows what the F18A is capable of.




3D view

Mario Kart uses the ability of the SNES hardware to scale and rotate a 2D image to make it look like 3D (aka. Mode 7). The source images could be as big as 1024x1024 pixels. I thought the F18A GPU would be fast enough to do something similar, but where would I store the source image? The F18A has only 18K RAM, and a 1024x1024 bitmap would take 512K! And it takes 12K just to display a bitmap that covers the whole screen on the F18A, so after displaying the bitmap there would only be 6K left for the source image and everything else, like sprites and the GPU program.


My first approach was to build the source image from 8x8 meta-tiles, which again consisted of standard 8x8 pixel characters/tiles (64 x 64 pixels in total). The meta-tile map for a 1024x1024 image would then only take 256 bytes, plus 1024 bytes to store 16 meta-tiles, plus the space to store the tiles they consisted of. However, my attempts to use this approach turned out to be way too slow for the GPU  (drawing an image took several seconds).


For my next approach I looked at Mario Kart, which has a 3D image at the top and an overview image at the bottom (also 3D but seen more from above). Maybe I could have a 2D overview image at the bottom of the screen and use that as the source image for the 3D image at the top of the screen? The source image would have a much smaller resolution than 1024x1024 (actually 128x128 fat pixels) so the 3D result would also be much more pixelated. But the transformation from one bitmap to another could be done much faster than the attempt to use meta-tiles.


Super Mario Kart - Wikipedia


And it turned out to work even faster than I would have thought, actually more than 60 FPS when generating a 128x64 pixels 3D image. It took a lot of time to figure out how to make a proper 3D perspective transformation without any distortion such as fish-eye effects, but I'm not going into details about that here. The resolution wasn't bad either, although nowhere nearly as good as Mario Kart. At this point I had used 12K VDP RAM, plus some more for GPU code in the upper 2K RAM.





I also wanted a horizontally scrolling background (trees, mountains) at the top of the 3D screen like in Mario Kart. I decided to do that using the normal tile mode and the hardware scrolling of the F18A rather than the bitmap layer in order to speed things up and perhaps save some VDP RAM. I had already used 192 vertical lines (64 lines for the 3D image and 128 lines for the source/overview image), but here the F18A ROW30 mode, which expands the vertical resolution to 240 pixels, came to my rescue, so the top 48 lines could be used for the background and to display other information like time and position.


First I added a single layer with mountains, which took little VDP RAM since I only needed 16 characters/tiles plus 6 rows of the name table to implement this. Then I tried adding another layer using F18A TL2 with trees that scrolls at another speed, and I liked it so much I couldn't bring myself to remove it again. Unfortunately that took up much more VDP RAM since TL2 cannot be displayed below the bitmap layer, so I needed space for an additional, full name table, with mostly transparent tiles. All that used about 1.6K VDP RAM, so now I only had about 2.4K left. Still better than using the bitmap layer for background, which would have required about 2 times as much RAM.



The last part of the graphics was to look at how to do the sprites for the player's karts, other karts, and other objects on the track. At first, I thought I could use hardware sprites for everything, but a single sprite pattern in 32x16 pixels 4 colors takes 128 bytes, and for any kind of reasonable 3D scaling effect I would need something like 16 patterns per angle per sprite. Already one sprite would take up the VDP RAM I had left, so I decided only to use hardware sprites for the player's kart, which consists of two magnified 16x16 sprites in 4 colors. The other sprites would have to be scaled and drawn on the 3D bitmap by the GPU.


I could foresee two problems with that: firstly the GPU might not be fast enough to also draw the sprites, and secondly, since there was no VDP RAM left for double buffering, maybe the sprites would flicker horrible when the 3D image and the sprites were repeatedly drawn on top of each other? Back in the days scanline renderers, where everything was drawn one scanline at a time, were sometimes used, but I didn't want to go into that kind of trouble yet. But again, it turned out not to be a bad as I feared. Even though you see some flickering, it's not, for instance, hiding important details to the player. But how I wish I had some more VDP RAM to do some proper double buffering...


The hardware sprites for the player's kart took 256 bytes for the patterns plus 128 bytes for sprite attributes, now there was only about 2K VDP RAM left for the software sprites. The current demo only includes 6 different software sprite patterns: 4 patterns for the other karts seen from different angles, one for the green oil drum, and one for the stack of tires. Together they take up about 1K, so there is still a bit of VDP RAM left to expand the demo, but not enough, for instance, to make different patterns for each kart.


I also used hardware sprites for the top display of time, position, and laps, and for the small karts at the bottom of the screen. Interestingly, the F18A allows you to choose whether each sprite is 8x8 or 16x16 pixels, but the magnification setting is the same for all sprites, so the bottom sprites are magnified 8x8 sprites with very few pixels.


What the TMS9900 is doing


Although the F18A is continuously drawing the 3D image and the software sprites, there is plenty left for the TMS9900 to do:


  • Reading the joystick
  • Moving the player on the track
  • Updating attributes for hardware sprites
  • Checking that you stay on track
  • Moving the other karts
  • "Uploading" kart data to the VDP 
  • Playing sound and music
  • Speech


For the player's kart movement I asked in the forum (https://forums.atariage.com/topic/362756-physics-model-for-car/#comment-5425008) and @sometimes99er suggested this  approach https://github.com/pakastin/car, which I adopted. All numbers are stored as 8.8 fixed point numbers, where the most significant byte contains the integer part.


To move the other karts, I created a low resolution version of the map, where each byte value determines a direction of 8 at that position, whether it's inside the track, and whether it's a checkpoint. In addition to that, each other kart has a base speed and a setting for how much it drifts. This is enough to move the karts around the track for the demo, but hardly enough to make them interesting opponents. So a lot more work would be required to change this from a graphics demo into an exciting game.

And here is a video of the current demo, which looks much better on real hardware. You will also find the demo in https://js99er.net under Software/F18A specific, or use the attached file on your real hardware.



The source code is available from https://github.com/Rasmus-M/f18a-karts




Edited by Asmusr
  • Like 28
  • Thanks 10
Link to comment
Share on other sites

38 minutes ago, WhataKowinkydink said:

Holy guacamole!

Small beans - but two things on the speech:
1) for racing in English we typically say "Lap" not "Round"
2) the word "Checkpoint" should be sped up if it is to be said at each checkpoint.

Other than that, i can't wait to mess around with it!  Thanks!

Right, but neither lap nor checkpoint are in the speech synth's resident vocabulary.

  • Like 3
Link to comment
Share on other sites

Amazing feat. Well done! One thing I thought I'd mention however: there is no indication of tire movement on the cart, which robs a bit of the motion effect. Perhaps the reflection horizontal line on the tires can move up and down a little to indicate motion?

  • Like 3
Link to comment
Share on other sites

6 hours ago, TheMole said:

Do I understand it correctly that the software sprites are scaled in real-time and rendered to the bitmap layer?

Yes that's right, and the routine should be generic enough to be used for other games as well. The only thing is I haven't implemented left and right clipping.

  • Like 1
Link to comment
Share on other sites

5 hours ago, Vorticon said:

Amazing feat. Well done! One thing I thought I'd mention however: there is no indication of tire movement on the cart, which robs a bit of the motion effect. Perhaps the reflection horizontal line on the tires can move up and down a little to indicate motion?

Are you suggesting I should spend 192 bytes of VDP RAM on alternating sprite patterns? 🙂

Link to comment
Share on other sites

4 hours ago, OX. said:

Does this only work with JS99er or is there a way to get it working in Classic99?

Only js99er has a full working F18A implementation right now, Classic99 will only support F18A 80 column stuff and the GPU, but none of the enhanced graphics modes (as far as I know).

  • Like 1
Link to comment
Share on other sites

3 hours ago, TheMole said:

Only js99er has a full working F18A implementation right now, Classic99 will only support F18A 80 column stuff and the GPU, but none of the enhanced graphics modes (as far as I know).

Classic99 supports a significant subset of the enhanced graphics, but it does not support the 30 row mode.


(I expected more to work than does, though.. odd. I support the BML but none of it appears to show. Oh well, it's not expected to work in Classic99.)


Edited by Tursi
Link to comment
Share on other sites

On 4/27/2024 at 4:24 AM, Asmusr said:

Right, but neither lap nor checkpoint are in the speech synth's resident vocabulary.

So you added "checkpoint" but not "lap"?

(Edit- Nevermind, I see what you did there....... I'm still groggy - anyway, the Speech Syth for a long time was .... far from my favorite bit of TI kit, so not familiar with what words are resident (I've only started having the Speech Synth. plugged in full time in the last few years) ) 

Edited by WhataKowinkydink
  • Like 1
Link to comment
Share on other sites

  • 2 weeks later...

This is just a minor update that includes the title screen, which in these times obviously has been drawn by an AI, and the suggestion from @Vorticon to add a bit of animation to the tires (I reduced the waste of VDP RAM from 192 bytes to 64 bytes by only updating one sprite pattern 🙂).


Could this be the first time, after 12 years, that anyone has drawn a 240 pixels tall bitmap on the F18A?


  • Like 9
  • Thanks 1
Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

  • Recently Browsing   0 members

    • No registered users viewing this page.
  • Create New...