Jump to content
  • entries
    41
  • comments
    373
  • views
    63,866

2600 compression


batari

2,299 views

Now that Gingerbread Man is done, I am already starting to think about the next project, or more accurately, working on my previous project (Superbug.) Also, a few people tried out a demo cart of the game at NWCGE and it was generally well-received.

 

The biggest problem with the game, I think, is that the track data takes a lot of space. Right now, each 128x128 track takes up 2k, and the supporting data, like powerup locations and the code to read the track data fills out enough additional space that only one track can fit per bank. With 3 banks already nearly full of program code, I'd only have 5 tracks in a 32k game, which would get boring quickly.

 

The arcade game uses a 256x256 random track, made from pieces of pre-defined curves and straightaways, and a few pieces containing sand, an oil slick, and another bug parked on the side of the road. (I also made a MAME infinite time and invincibility cheats to help examine how the game works.) It probably would be possible to make my game work this way and it would solve the space issues.

 

I'd prefer the bitmapped tracks, the only way these will work with a good number of tracks is to use a 64k or larger board (e.g. EF bankswitching) and/or some sort of compression. A compression method would need to be fast, maybe even faster than reading bitmapped data. The decompressor shouldn't be cumbersome in size or cycles, it should compress at least 50%, preferably more, and should be fully capable of random access of compressed data without huge loops. Unfortunately, I know of only one compression scheme that can be adapted to have all of these properties - RLE.

 

My best guess is RLE would either need to have a fixed number of "runs" in a line, say 8 (currently 16 bytes per line are needed) so data could be accessed randomly and the only traversal is a check of the numbers in the set of "runs." This would unfortunately have a large number of unused bytes.

 

Or, put in a table of addresses that contain the start of each line, though this would need 256 bytes in itself for a 128-high bitmap. Still might reduce to <1k though.

 

Well, if not compression, I'd be willing to invest in larger boards, though I'd probably prefer something based on 0840 to simplify the bankswitching logic to use two TTL chips and a 32-pin EPROM (128K-512k.) Supercat had this to say about it:

Even a lowly 16V8 would have no problem supporting a 64-bank scheme with 08xx hotspots. A 22V10 could push it up to 256 banks. That would be a megabyte worth of code. The same result could be achieved using two common TTL chips (a 74HC00 and a 74HC373, or any of many other combinations). The advantage of 0840 is that it doesn't require programming a PLD before assembly.

Also mentioned was adding an EEPROM to a board, which is also a good idea for a number of reasons, but I'm not sure would be fast enough to handle the 4-way scrolling in Superbug.

41 Comments


Recommended Comments



Advancing to other tracks only upon meeting criteria, like beating time and/or not crashing works, but what other goals can you think of?

How about a race where you have to hit fuel power-ups to keep going, and if you don't maintain a certain speed, or miss too many, you'll run out of gas and fail.

 

Or, a "Power-up Rally" where you have a series of power-ups to deal with, but way more than in a normal game, and they're strategically placed to either mess you up if you hit the wrong ones, or zip you through the race super-fast if you hit them just right.

 

There could also be races taking place completely on icy roads, or other adverse conditions (rain? fog? night? bouncy walls?).

You could even do weird things like races where you're forced to drive backwards. Might be a little gimmicky though.

 

The thing is, most of those still ultimately come down to finishing the race by a certain time, just with some variation.

 

You could also have one where you accumulate damage. Hit the wall, and your car takes on damage, slowing down, and eventually stopping. Maybe in the bouncy walls variation. Although that would mean putting in a damage meter someplace.

 

I'm just tossing out some random ideas. How well any of these would actually work is just a guess. :lol:

Link to comment
The thing is, most of those still ultimately come down to finishing the race by a certain time, just with some variation.

Well, it is a racing game! :lol:

 

I will try out those multiple-track bitmaps and see how well they compress. That may be a deciding factor. If they work, the small tracks could be called racetracks, i.e. intended for multiple laps, while any large tracks could be classified as rally courses or something like that.

That would be brilliant.

 

As far as various extra features, goals, etc., probably one of the best things you could do would be to play/examine various good modern racing games and get some ideas. People have been making racing games for 30 years, seems like you should be able to see what has worked and what hasn't.

Link to comment
I don't see how you want to unpack a random closeup window of the track based on a seeded algorithm, unless you're talking fractals or so?

Why unpack?

 

You could e.g. define a center line which moves forward at randomly generated angles. At right angle to that line you put another (maybe variable length) line which defines the width of the road. That's all.

 

Closing a track and avoiding crossings is another problem. A solution for the former could be to give one direction a slight preference and also those directions which lead lead you back to the starting point. For the latter, I don't know. :lol:

 

Though because you only see a small portion of the track, IMO it really doesn't matter if the track is 100% right.

Link to comment
As far as various extra features, goals, etc., probably one of the best things you could do would be to play/examine various good modern racing games and get some ideas. People have been making racing games for 30 years, seems like you should be able to see what has worked and what hasn't.

That's where I've gotten some of the ideas I've suggested here. I own more racing games than any other genre. At least as far as modern consoles go.

 

A few recommendations, for a few different systems (most of these are in the bargain bins by now):

Link to comment

There is one element present in most racing games that is conspicuously absent in this one: other cars. I don't plan to add other cars, except maybe as a 2-player mode (which may not work anyway, given that the screen is smallish already, so splitting it may make it too small.) I did talk about 2-console play a long time ago and we even worked out protocols, cables and such but I wonder if anyone would ever actually play that way?

 

So the lack of cars (and therefore the lack of "placing" in a race) does change things somewhat. I suppose I could just say it's a rally race where starting times are staggered to prevent competitors from encountering one another. Are there any other driving games (preferably freely downloadable) that play this way? Though the smaller racetracks would need another explanation, such as time trials? Regardless, track design is going to be really important here, maybe not so much the layout of the track but placement of powerups and hazards.

 

Back to deltas: one problem I'm seeing here is that going "offroad" wouldn't work. I suppose going offroad is strictly cheating, even if the game does detect this somewhat, but I kind of like the idea of being able to get to different parts of the track this way (it makes the game more cohesive to me, like you're in a mini-world, and it would be a good way to place easter eggs, i.e. you would need to "explore" to find them.)

 

FWIW, I did try both sets of smaller tracks above and they both will work with RLE compression. For the moment, that's the direction I'm heading, if nothing else, as a proof of concept. I've got the C program now generating RLE-encoded 2600 asm code from a 256x256 Windows .bmp file, so now I just need to make the 2600 decompress the code and display it on the screen (which probably won't be easy...)

Link to comment
I did talk about 2-console play a long time ago and we even worked out protocols, cables and such but I wonder if anyone would ever actually play that way?

I think if you could add it, it would be worth doing. How many people would actually use it? No idea. But the number will be zero if it's not there at all. :lol: If nothing else, it's a completely unique selling point for the game, and I'm sure it'd be a hit at game expos and get-togethers.

 

The other possibility, for a single console, is having a couple of the tracks be for two-player racing. It's easy enough to make them wider - they just wouldn't be as complex. The trick is when one car gets left behind offscreen - what do you do then? Unless it's a split-screen game (like Marble Craze), you're going to have to give some sort of automatic catch-up to the car lagging behind.

Link to comment
I did talk about 2-console play a long time ago and we even worked out protocols, cables and such but I wonder if anyone would ever actually play that way?

I think if you could add it, it would be worth doing. How many people would actually use it? No idea. But the number will be zero if it's not there at all. :lol: If nothing else, it's a completely unique selling point for the game, and I'm sure it'd be a hit at game expos and get-togethers.

 

The other possibility, for a single console, is having a couple of the tracks be for two-player racing. It's easy enough to make them wider - they just wouldn't be as complex. The trick is when one car gets left behind offscreen - what do you do then? Unless it's a split-screen game (like Marble Craze), you're going to have to give some sort of automatic catch-up to the car lagging behind.

The more I think about it, the more I think that multi-console play is the only way it will really work. Split-screen is just too small, and same-screen leads to many problems where one player lags and the other zooms ahead. You could not keep one player centered and allow the other to move - both would need to move about the screen. Then the leading player would move to the edge of the screen and not be able to see anything, which might actually give an advantage to the trailing player once the leader crashes and the trailing player is forced ahead by staying on the edge of the screen. There's also the matter of all those extra physics involved, relative velocities abound and extra position variables that I don't have room for.

 

For multi-console play, I think my first attempt at that would be a simple demo unrelated to the game, just to see how well it would work at all. It would have to be simple enough to program in an evening yet complex enough to actually make sense in a multi-console setting.

 

Yes, it would work at expos but I still wonder how many at home would actually buy two carts and set up two consoles and two televisions, especially if you're like me and haven't played the 2600 with another player for years?

Link to comment

Just occurred to me: the Micro Machines series of games might be a very good place to look for ideas.

 

They are top-down, scrolling racing games where there is no split screen for multiplayer. I think if you fall behind (off screen) it places you back on the track up with the leader and penalizes you somehow (can't remember the details right now).

 

But basically, the Micro Machines games are a modern version of Super Bug.

 

As for using two consoles...I dunno. It would be cool, but it would be very rare.

Link to comment
Just occurred to me: the Micro Machines series of games might be a very good place to look for ideas.

I think Karnaaj Rally was done by the same developers.

Link to comment

Finally got RLE working somewhat. Still buggy but it is displaying a 256x256 track. However, even though I've gotten it sorta working, decompression is proving to be just too slow.

 

For reading rows of data, there is no problem. Just find where a "run" ends, and count pixels along the run (checking if the run ends, then incrementing to the next run) until we've finished drawing. There is a loop involved but it seems fast enough.

 

For columns of data, there's a problem. We need to find whether a pixel is on or off by looping through the run data, and once we're done, start again on a new run. This leads to a loop within a loop, and it can take so many cycles that and I don't see any way to make it work.

 

As a first test, I started with two 256-byte data tables holding pointers into the RLE data (which saves RAM at the expense of ROM, but eliminates the need to search linearly through the data, as it seems that this would be even slower.)

 

Here is the current code to render new data to be scrolled onto the left edge of the screen:

  ldx temp3; either 0 or 3 for L/R edge of screen
keepgoingleft
 ldy temp1
 lda lookuptablelo,y
 sta temp5
 lda lookuptablehi,y; set pointers into RLE data
 sta temp6
 inc temp1; increment Y pos into RLE data

 ldy #$FF
 lda temp2
findRl; find first run > x value
 iny
 cmp (temp5),y
 bcs findRl  

 tya 
 lsr; carry on/off depending on odd/even run
 lda playfield,x
 bcc pixon
 and #%01111111
 .byte $0c
pixon
 ora #%10000000
pixoff
 sta playfield,x
 txa
 sbx #252
 cpx #48
 bcc keepgoingleft

The big time-waster here is the inner loop findRl, as when temp2 is large enough, it can loop many times. The outer loop exists in the original version of the game and it wasn't a problem when it was reading uncompressed data. This inner loop is adding upwards of 100 cycles more than the original code (and it's repeated 12 times in the outer loop!) So unless someone has some magical code that will fix this, I'm back to the drawing board.

 

That said, storing RLE data in both row-major and column-major format would probably work, but at about twice the space, we're back to BIG carts based on 0840 design. The ideas presented by Supercat with two TTL chips seem very promising.

 

I have not abandoned the idea of uncompressed bitmap data either if a BIG cart design becomes a reality, as I'm now thinking that tracks could still be larger if data were spread across several banks. I probably could add Stella support for such carts if needed.

 

I'm still going to look into the deltas idea, but I wonder if I might run into timing problems here as well?

Link to comment

BIG cart, based on Supercat's suggestion

 

(Is this correct, or did I miss something?)

3 gates from a 7400:

				+-GND			 
	EPROM /CS  ___
A12-+-|\	|	  ___ 0.01 uF
| | |()-+-|\	|
+-|/	  | |()-+-|\
A11-----------|/	| | |()--LE (of '373)
				+-|/

74373/74374 (level/edge triggered seems the only difference.  Don't think it matters, or ?)

	+---------+
Vcc-|Vcc   /OE|--GND
GND-|GND	LE|--Above
VCS A0--|D0  7  Q0|--A12 (EPROM)
VCS A1--|D1  4  Q1|--A13
VCS A2--|D2  3  Q2|--A14
VCS A3--|D3  7  Q3|--A15
VCS A4--|D4  3  Q4|--A16
VCS A5--|D5	 Q5|--A17
VCS A6--|D6	 Q6|--A18
VCS A7--|D7	 Q7|--A19 = 1024kB!
	+---------+

Link to comment
This inner loop is adding upwards of 100 cycles more than the original code (and it's repeated 12 times in the outer loop!) So unless someone has some magical code that will fix this, I'm back to the drawing board.

 

Probably won't help it much, but when ran in RAM, you could do CMP ABS,Y.

Link to comment
74373/74374 (level/edge triggered seems the only difference. Don't think it matters, or ?)

 

It does matter. You either need an edge-triggered latch, or else you need an RC delay on all the inputs to the latch. When there's only one bit being latched (as with 0840) that means one resistor and one cap either way. But if you're latching eight bits, it's far cheaper to use one edge-triggered clock with a delay than to put delays on all eight bits to be latched.

In that case, we definitely want the '374.

 

However, I'm wondering if two chips is really a good idea. You said a 16v8 could do 64 banks, or 256k. That, and 16v8 chips are still readily available and inexpensive, so the price difference would likely be negligible. I can't imagine that programming a PLD would be harder than soldering 14 extra pins, all else being equal.

 

I did check Digikey for various 270x0 DIP EPROMs. 128Kx8 is $2.60 and 256Kx8 is $5. Larger chips were starting to get too expensive (e.g. 1024k chips were $10/ea.) So maybe the 256k limit isn't a big deal. Seems like there are diminishing returns for those larger sizes anyway.

Link to comment

I wrote VHDL code for the 256k cart, and it does fit on a 16v8 with no macrocells to spare. I'm about 99% sure the implementation is correct (the output logic equations are spot-on, even if my VHDL code isn't particularly easy to follow.)

 

My VHDL compiler is an old DOS-based tool from Cypress. It works just fine for simple projects like this. The only problem is that I don't have any Cypress chips left, and they don't seem to be readily available anymore (I think Cypress doesn't even make them anymore.)

 

I've read that Atmel chips are versatile enough to act like devices from other manufacturers, and can use their JEDEC files for programming, but I'm not sure about that. Hopefully it's true, as Atmel's crappy software doesn't appear to allow you to compile VHDL into their smaller chips. That, and I don't know any other HDL.

 

Anyway, here's the pin mapping:

								 C16V8C
	 __________________________________________
capin =| 1|								  |20|* not used
 addr_5 =| 2|								  |19|= capout
 addr_4 =| 3|								  |18|= cerom
 addr_3 =| 4|								  |17|= eprom_a_12
 addr_2 =| 5|								  |16|= eprom_a_13
 addr_1 =| 6|								  |15|= eprom_a_14
 addr_0 =| 7|								  |14|= eprom_a_15
 addr12 =| 8|								  |13|= eprom_a_16
 addr11 =| 9|								  |12|= eprom_a_17
not used *|10|								  |11|* Reserved
	 __________________________________________

capout is intended to drive a simple RC and connect to capin (for timing.)

 

Utilization is here:

  Information: Macrocell Utilization.

				 Description		Used	 Max
			 ______________________________________
			 | Dedicated Inputs   |	8  |	8  |
			 | Clock/Inputs	   |	1  |	1  |
			 | Enable/Inputs	  |	0  |	1  |
			 | Output Macrocells  |	8  |	8  |
			 ______________________________________
									  17  /   18   = 94  %

It claims to have a free input but looking above in the pinout, it's marked "Reserved" for some reason. Not sure why :lol:

 

Anyway, in the spirit of sharing, I've uploaded my VHDL source and the JEDEC file.

 

Next step: build a prototype (and pray it works :))

Link to comment
It claims to have a free input but looking above in the pinout, it's marked "Reserved" for some reason. Not sure why :lol:

 

Most 16V8 chips have three modes of operation, which vary in terms of whether they allow latched or unlatched inputs, or individual control of chip-selects. The only mode that allows latched outputs requires the use of pin 11 as a common chip-select for all the latched outputs. An 18CV8 would not have that limitation but would otherwise be pinout compatible (the "16" in "16V8" refers to there being 16 inputs to the array. In the mode that allows latches, there are eight inputs and eight feedback inputs. The other two input signals are used for clock and output enable, but do not feed the array.

 

If you don't mind requiring that any bank-switch instructions be run from ROM rather than RIOT RAM, you may be able to add another banking bit. Use the same PLD output for the EPROM /OE and the RC feedback circuit. Since /OE goes high during any banking address, that should let you save an output pin provided that your latching terms will keep their current value if A12/A11 aren't "0/1". Not sure what one extra output pin would be good for in the absence of an extra input pin to go with it.

Link to comment

Guest
Add a comment...

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