Jump to content
IGNORED

Formula 18A / Formula 99 / Formula 99+ development


Asmusr

Recommended Posts

3 hours ago, Asmusr said:

Here is the first demo of the new engine. This is running on an ordinary console with 32K. The green horizontal lines are for debugging, telling me the position of the road segments.

Love the use of multi-color mode.

  • Like 1
Link to comment
Share on other sites

9 hours ago, OLD CS1 said:

Love the use of multi-color mode.

Well it's not multicolor mode. In multicolor each pixel is 4x4 small pixels. Here they are 4x1 small pixels. You achieve this mode, which is not a real 9918A mode, from bitmap mode by setting all patterns to >f0. Now you can use the color table as if it was a real bitmap mode with 4 bits per pixel and no color restrictions. One advantage is that it's much simpler to draw scaled graphics when you don't have to think about color restrictions and patterns. Another is that the whole screen is now only 6 KiB so it's faster to update, and finally you can't get into problems from updating colors and patterns out of sync. The downside is the lack of detail, but it doesn't seem to matter much when the screen is updating fast. The completely opposite solution, which has the same advantages, is to drop the colors and only update the patterns. And as we have seen here that has already been used on the MSX for a driving game.

 

Edited by Asmusr
spelling
  • Like 7
  • Thanks 2
Link to comment
Share on other sites

But your implementation is by far more impressive, the color road is awesome and scaled objects like trees and signs work very well.

Large objects and squared items work better with this resolution.

You could try with large rocks and maybe poles on the side of the road.

Do you store in rom pre scaled items and you add them to the scene after the road has been computed?

Do you clip their height in case of hills accordingly to the distance and the top of the hill defining the horizon?

Will the same thing work for other cars and other opponents ? 

 

 

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

6 hours ago, Asmusr said:

Well it's not multicolor mode. In multicolor each pixel is 4x4 small pixels. Here they are 4x1 small pixels. You achieve this mode, which is not a real 9918A mode, from bitmap mode by setting all patterns to >f0. Now you can use the color table as if it was a real bitmap mode with 4 bits per pixel and no color restrictions. One advantage is that it's much simpler to draw scaled graphics when you don't have to think about color restrictions and patterns. Another is that the whole screen is now only 6 KiB so it's faster to update, and finally you can't get into problems from updating colors and patterns out of sync. The downside is the lack of detail, but it doesn't seem to matter much when the screen is updating fast. The completely opposite solution, which has the same advantages, is to drop the colors and only update the patterns. And as we have seen here that has already been used on the MSX for a driving game.

 

Sorcery.  That explains why the green line does not look four pixels-tall, then?

Link to comment
Share on other sites

5 hours ago, artrag said:

But your implementation is by far more impressive, the color road is awesome and scaled objects like trees and signs work very well.

Large objects and squared items work better with this resolution.

You could try with large rocks and maybe poles on the side of the road.

Do you store in rom pre scaled items and you add them to the scene after the road has been computed?

Do you clip their height in case of hills accordingly to the distance and the top of the hill defining the horizon?

Will the same thing work for other cars and other opponents ? 

Currently the segments with the banner and the trees are full screen recordings from Java, where I have made a reference implementation. The banner segments has 32 images and the tree segment has 48 images, so they take up a bit of ROM. You can still move the car sideways and control the speed while you're in one of those segments. I have been thinking about storing only the objects at different scales, but then I don't see how I could avoid building the image in RAM before sending it to the VDP, which would be a lot slower. So unfortunately I cannot just use this type of graphics for anything I want. An alternative would be to draw the graphics directly to the VDP after the road image had been 'uploaded', but that would require double buffering, and I actually made a version where I used your double buffering method (the one where the top 3rd of the screen is unusable), but then I would only be able to use sprites 0-7 because of the sprite doubling issue, so I abandoned that idea. It would also be slow to draw directly to the VDP.

  • Like 1
Link to comment
Share on other sites

I was thinking that you were plotting the scene in ram and then upload it to vram.

Anyway maybe also other cars could be plotted as bitmap graphic. 

Maybe also the player's car could be bitmap.

This could open to the use of the double buffer technique, and you could plot the scene directly in vram.

 

In this case 8 sprites could be sufficient for the clouds and/or score in the top 3rd of the screen.

 

 

Maybe I am too optimistic here but I think that the squareness of the cars could help to get something recognizable even with 4x1 pixels 

This is an example from outrun

 

If I may add, probably the road stripes could be plotted in VRAM deferentially, i.e. updating only the parts of the lines that have changed color. 

 

To simplify differential plotting, each horizontal road stripe can be stored in ram as and array of couples (color,length),(color,length),(color,length) etc etc

 

Assume, e.g., only 3 colors on a stripe (left border, road, right border)

The current line is (_color1,_length1),(_color2,_length2),(_color3,_length3)

the new line is (color1,length1),(color2,length2),(color3,length3)

 

If _color1== color1 then you can plot only |length1-_length1|  pixels (color depends on which length is longer)

If _color2== color2 then you can plot only |length1-_length1+ length2-_length2|  pixels 

If _color3== color3 then you can plot only |length1-_length1+ length2-_length2+length3-_length3| pixels 

 

Just brainstorming, I could be wrong.

 

Edited by artrag
Change of mind
Link to comment
Share on other sites

On 10/16/2021 at 3:51 AM, Asmusr said:

... You achieve this mode, which is not a real 9918A mode, from bitmap mode by setting all patterns to >f0. Now you can use the color table as if it was a real bitmap mode with 4 bits per pixel and no color restrictions...

This is a pretty clever use of GM2.

On 10/16/2021 at 3:51 AM, Asmusr said:

... Another is that the whole screen is now only 6 KiB...

I assume you are referring to just the color table here?  You still need at least one 2K pattern segment full of >F0 patterns, yes?.  I assume the Pattern Table Base Address is either "000" or "100" (and the CTBA would be "011xxxxx" or "111xxxxx" (MSbit opposite the PTBA)), to keep the pattern table to a single 2K segment (which would leave 8K of VRAM for sprites and other data).

 

The video is very impressive!  Maybe the F18A is over-engineered.  It would be much easier to just implement original functionality. ;)  You continue to prove there was much untapped capability in the stock 9918A.

 

  • Like 1
Link to comment
Share on other sites

8 hours ago, matthew180 said:

I assume you are referring to just the color table here?  You still need at least one 2K pattern segment full of >F0 patterns, yes?.  I assume the Pattern Table Base Address is either "000" or "100" (and the CTBA would be "011xxxxx" or "111xxxxx" (MSbit opposite the PTBA)), to keep the pattern table to a single 2K segment (which would leave 8K of VRAM for sprites and other data).

Sure, you actually need a full 6 KiB pattern table if you want to be able to use all the sprites, but you only have to update 6 KiB on the fly.

This is the same setup I used for the textured raycaster, so nothing really new here.

  • Like 1
Link to comment
Share on other sites

On 10/16/2021 at 8:33 PM, artrag said:

If I may add, probably the road stripes could be plotted in VRAM deferentially, i.e. updating only the parts of the lines that have changed color. 

 

To simplify differential plotting, each horizontal road stripe can be stored in ram as and array of couples (color,length),(color,length),(color,length) etc etc

 

Assume, e.g., only 3 colors on a stripe (left border, road, right border)

The current line is (_color1,_length1),(_color2,_length2),(_color3,_length3)

the new line is (color1,length1),(color2,length2),(color3,length3)

 

If _color1== color1 then you can plot only |length1-_length1|  pixels (color depends on which length is longer)

If _color2== color2 then you can plot only |length1-_length1+ length2-_length2|  pixels 

If _color3== color3 then you can plot only |length1-_length1+ length2-_length2+length3-_length3| pixels 

Perhaps something can be done to optimize the drawing, but it has to be very simple to perform better than the current code, which can plot almost 2 wide pixels per instruction in an unrolled loop. And as you can see from the images, I have more than 3 colors per stripe.

 

road1.png.88c183272d03e7db4db89b26108efb33.pngroad2.png.d30aae1b4c63913beb975b1d12c4f83f.png

 

The whole screen can also scroll sideways. This isn't shown on the video where the car stays in the center, but when you steer the car, the screen generally scrolls instead of the car.

 

Regarding the road side objects, they can fill quite a large part of the screen, so I still think drawing them to the VDP after the road would be too slow. You would have to deal with transparency and clipping, so it would definitely not be 2 pixels per instruction here.

 

js99er-20211018063917.png.34ee197f06e5f66dcd52572f3a60a366.pngjs99er-20211018064237.png.ce5f23d1871030cd3fb8519dc70ff197.png

 

One problem I have with the recordings is that the sideways scrolling I mentioned is not possible without storing at least twice as much data in ROM as I do now, so currently in those segments it's the car sprite that moves instead of the road, which gives me a few headaches. :-) 

  • Like 9
Link to comment
Share on other sites

Sorry for the brainstorming, but your project is too fascinating to me so I cannot resits think to it.  

 

 

If I correctly understand, your plotting strategy is to copy a line from one of the two reference images to a ram buffer and from there to VRAM  (actually four images are needed to take into account of the nibble offsets). How do you deal with the character boundaries ? 

 

Usually the PNT is organised like this

0,1,2,3....,31,

32,33,34,...63,

64,65,66,.. etc

ect.

 

This implies that in order to plot an horizontal line, you need to offset the vram address by 8 positions each byte you send

This layout is not very handy when you plot software sprites. Starting by generic Y, you need to keep track also of the character boundaries and this adds overhead.

 

A better layout for sw sprites should be this:

0,8,16....

1,9,17...

2,10,18..

3,11,etc

4,12,etc

5,13,etc

6,14,etc

7,15,etc

 

Drawing lines implies that you need to offset the vram address by 64 positions each byte you send (same cost as above)

When you plot sw sprites, instead, starting by generic Y, if y and y+Ysize are within the same tile bank, all you need is to plot by columns, byte by byte the sprite without testing boundaries.

 

Moreover, about copying... you have long runs of constant colors. Why not to store the reference images as set of couples (color, run length) and use an unrolled loop to plot color constants?

Edited by artrag
Link to comment
Share on other sites

11 hours ago, artrag said:

If I correctly understand, your plotting strategy is to copy a line from one of the two reference images to a ram buffer and from there to VRAM  (actually four images are needed to take into account of the nibble offsets). How do you deal with the character boundaries ? 

I always appreciate your comments. My raycaster project, for instance, would never have turned out as good without your help.  

 

You're correct that I copy from four images (+ two sky images), but I copy directly to VRAM. The images are stored in natural order: line by line, column by column. In order to transfer a row of 8 lines to the VDP, I utilize that the 9900 CPU has lots of 16-bit registers. So I can set up 8 registers to keep track of each their line, and then transfer one byte from each register - with auto-increment - in an unrolled loop. In Z80 it would be something like doing 8 OUTI instructions with different HL registers.   

 

So to draw an image of the road on the fly, I first build a list of 128 words pointing to the start source addresses of each line. I then transfer 16 rows of 8 lines to the VDP as described above. How to determine the offsets of each line is described in Lou's tutorial. The images are twice as wide as the screen resolution, and if the offsets are too extreme they just overflow to the next/previous line. 

 

In order to add soft sprites on the fly, I would need to store each row of 8 lines in an intermediate RAM buffer, and then draw the sprites on top of that, but I haven't actually tried that. So as I wrote, the segments with soft sprites are simply full screen recordings stored in ROM. I have tried to compress those screens with a simple RLE, and it can compress them to approximately 50%, but so far I'm using uncompressed images.

 

It would, of course, be a lot cooler to be able to draw soft sprites to any screen at will, but on the TI-99/4A I think the cost in frame rate would be too high. [That's even though the drawing takes place in the most natural order for sprite drawing.] But one thing I do consider is to display the main car with a soft sprite background, since it's always displayed in the same spot.

 

Edited by Asmusr
Added sentence
  • Like 3
Link to comment
Share on other sites

 I see. What you do is very optimized.

Still I think that using the fact that lines are constant in color could lead to further gains. At least on z80 sending a constant value from a CPU register is faster than copying ram data.

Also differential plotting is interesting, as stripes generally change only few dots between frames  but I do not see a way to set the vram pointer that wouldn't waste the gain of not copying an intere line.

 

  • Like 2
Link to comment
Share on other sites

  • 2 weeks later...

Here is the latest video. Sorry, no playable demo. Thank you to @TheMole for suggesting a tunnel. 

 

Improvements in this version include that the screen is always moving instead of the car, the new tunnel animation, and the more colorful car.

 

 

The sound is currently quite bad, the beeping is a placeholder for the real sound when the car is skidding. To free up the noise generator, I think the car engine will have to use  a tone generator instead of periodic noise. I would also like to do a swoosh sound when you pass a tunnel, and maybe the trees. Any ideas for how that would work?

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

46 minutes ago, OLD CS1 said:

Rough ideas.


BYTE >05,>C8,>01,>DF,>E7,>FD,>08
BYTE >01,>FB,>06
BYTE >01,>F9,>04
BYTE >01,>FE,>06
BYTE >01,>9F,>00

or


BYTE >05,>C8,>01,>DF,>E7,>FD,>06
BYTE >01,>FB,>06
BYTE >01,>F9,>04
BYTE >01,>FE,>02
BYTE >01,>9F,>00

 

Thanks, but maybe you could describe in words what you are suggesting? ?

 

Link to comment
Share on other sites

12 minutes ago, Asmusr said:

Thanks, but maybe you could describe in words what you are suggesting? ?

Those are sound lists.

 

The white noise is harsh, so a high pitch on gen 3 and low volume from the noise generator seems to work. I tried a couple of patterns of increase then decrease in the volume.

  • Like 1
Link to comment
Share on other sites

3 minutes ago, OLD CS1 said:

Those are sound lists.

Yes I can see that, but I don't use sound lists. I can decipher by hand that the lists produce white noise controlled by the frequency of channel 3, but you didn't write anything about how that should be used. I was looking for suggestions for how best to utilize the PSG to produce engine sound, skidding sound and sound of the environment together. Sorry if that wasn't clear.

Link to comment
Share on other sites

I was wondering if some kind of minimal indication of the wheels turning is possible, possibly the reflection line on the tires moving up and down or something along those lines... I think that would go a long way in enhancing the realism of the car motion. Regardless, awesome work...

  • Like 2
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.

Guest
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.

Loading...
  • Recently Browsing   0 members

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