Jump to content
IGNORED

Wormy for the 7800


EricBall

Recommended Posts

From Misguided criticism of the Atari 7800

 

Also, it's been ages since I read the 7800 specs.  Can the Maria clock out enough data to put up a full screen of 4-color 8-pixel wide tiles in 320 mode if there are no other sprites that need to be drawn?

884953[/snapback]

 

Hrmm.  Maybe.  Let's see (worst case), 455 cycles/line minus 7 * 4 cycles for the CPU after WSYNC, minus 9 cyles DMA start, minus 13 cycles zone end = 405 cycles for the display list.  You've said 4 color (2 bit per pixel) 320 mode, i.e. 320B (although 7800 Graphics Modes shows that 320B has some quirks.)  So that's 4 pixels per byte, or 2 bytes per tile at 9 cycles per tile.  And there'd be 40 tiles per line (41 if you are scrolling), so you'd need at least two 5 byte headers at 12 cycles per header. 

2 * 12 + 41 * 9 = 24 + 369 = 393 < 405

So, yes, it looks like you would have the cycles, but that's all that you could do.  (Well, you might be able to stick in one 8 pixel wide direct sprite, but that's it.)

886555[/snapback]

 

Cool.  Means if I ever got by Dodgson cart working again I might be able to do Wormy for the 7800 in 320B mode.  BTW, it needs exactly 40 columns, not 41.  The game was written for a CGA, and uses simulated 8x8 character drawing (320x200x4 colors) to draw things quickly.  Most of the motion in the game is done by manipulating the character set, so if memory allowed it should be possible to make Wormy run nice and zippy.  The primary requirement would be recopying the shape data for thirty-two characters each frame.  Since the character shapes would be 16 bytes each, that would be 512 bytes.  If the code uses a tight loop:
LOOP:
 LDA CSROM0,X
 STA CSRAM,X
 LDA CSROM0+128,X
 STA CSRAM+128,X
 LDA CSROM0+256,X
 STA CSRAM+256,X
 LDA CSROM0+384,X
 STA CSRAM+384,X
 DEX
 BPL  LOOP

That's 41 cycles/loop, times 128 loops.  That's 5248 cycles, or 69 scan lines.  A little over where I'd like to be, though maybe the top part of the screen could be in lower-color mode.  Would the CPU get any time during the displayed part of the frame?

 

I suppose things could probably be improved slightly if one took advantage of the fact that only 15 of the 32 characters will ever be on screen at once  Would be a little more complicated than always copying all 32 characters, but the cycle saviings could be worth it.

 

Either that, or else can the MARIA get data out of external ROM without copying it to RAM first?  If so, that'd be the way to go.  There are about 48 character shapes, of which 32 are animated.  There are eight character sets, so they'd take up 6144 bytes total.  Too much to fit in RAM, but well within the capacity of a ROM.

886627[/snapback]

 

You'd only have a little over 62 scan lines, or 7068 CPU cycles.

 

Question - are there more than 128 distinct shapes?  'Cause if there aren't then you can simply store the 40x25 character map in RAM.

 

But why use character mode at all?  Why not just make each worm a sprite?

886909[/snapback]

 

There are 32 characters that are used for animating the worm, of which at most 15 can be on screen at once (12 may be on screen in arbitrary combination, then one head front, one head-body join, and one tail back).  There are about 16 other non-animated characters shapes (walls, mines, gold bags, power-ups, etc.).  Each of the worm characters has eight variations.  The non-animated characters have only one each.

 

If the MARIA can read graphics from ROM, it would be a simple matter to have eight character sets and simply change the 20 display lists for the rows containing worm segments to change character sets from one frame to the next.  Duplicating the non-animated characters would be somewhat wasteful, but not too bad.  The other approach would be to copy the animated part of the character set between frames.  If I only copy the 240 bytes that are actually needed, this might be workable.

 

Well, there's one worm [which actually looks more like a centipede] and it's animated along its entire length.  I would think 38 8x8 sprites on a scan line in 320B mode would be even more of a bandwidth drain than 40 8x8 tiles.

887116[/snapback]

Link to comment
Share on other sites

Yes, Maria typically reads graphics data from ROM. (It could read from RAM, but with only 4K available and limitted CPU time, it's not really the best way.)

 

Okay, let's stick with the 40x25 8x8 character grid, which is set up in RAM as a 1000 byte table. You have a static DLL and 25 static display lists, each of which is simply two 5 byte headers (left & right halves of the screen) and the 2 byte terminator. That's around 400 bytes total.

 

Each 5 byte header has a pointer to the appropriate byte in the character grid and width=20 bytes. Maria then reads the byte at the pointer position and uses that as the LSB to the bottom of the sprite data, which is stored in ROM. The MSB comes from the Maria CHARBASE register.

 

Hrmm, one problem. Each header also contains the palette info, so you'll be limitted to 4 colors for the entire screen. Very CGA. You'll also need to watch out for artifacting. Unless you figure out how to use 320C, then you will have more colors, but less flexibility in using them.

 

Anyway, where was I. Oh right, the graphics data in ROM. Okay, since we're using 2 byte characters (8 pixels wide, 4 colors = 2 bits per pixel) you have 128 characters to play with. However, you could change CHARBASE every frame and have multiple character sets. Each character set would be 2K, so with 8 character sets you'll need 16K of graphics data. (Actually, you'll only be using around 48 of the 128 characters, so you could put more than one worm character set into a single 2K block.)

 

So, each frame you only need to modify the 40x25 character grid and CHARBASE as necessary.

Link to comment
Share on other sites

Each 5 byte header has a pointer to the appropriate byte in the character grid and width=20 bytes.  Maria then reads the byte at the pointer position and uses that as the LSB to the bottom of the sprite data, which is stored in ROM.  The MSB comes from the Maria CHARBASE register.

 

So if I wanted to use 2K-byte character sets, eight of them would take 16K but I'd only have one register to update per frame; if I wanted to use smaller character sets, I'd have to update 40 display lists? Tough call, since using 2K character sets would not have to be wasteful if other data were interspersed with them. I could imagine Wormy working quite nicely as a 32K cartridge with 16K of that consisting of interleaved screens and characters.

 

Hrmm, one problem.  Each header also contains the palette info, so you'll be limitted to 4 colors for the entire screen.  Very CGA.  You'll also need to watch out for artifacting.  Unless you figure out how to use 320C, then you will have more colors, but less flexibility in using them.

 

Well, Wormy II was a CGA game. If you like I could enclose a copy; it sorta plays on modern machines though it runs too fast [cued off frame rate]. And with artifacting, I think you'd sorta get 16 colors on sorta 320x200 resolution [since different combinations of colors in pixel pairs would yield differnet colors on screen]. Remind me how 320C works?

 

Anyway, where was I.  Oh right, the graphics data in ROM.  Okay, since we're using 2 byte characters (8 pixels wide, 4 colors = 2 bits per pixel) you have 128 characters to play with.  However, you could change CHARBASE every frame and have multiple character sets.  Each character set would be 2K, so with 8 character sets you'll need 16K of graphics data.  (Actually, you'll only be using around 48 of the 128 characters, so you could put more than one worm character set into a single 2K block.)

 

But using multiple character sets within a 2K block would entail updating 40 display lists? Not that that'd be impossible, but it would seem more work.

 

So, each frame you only need to modify the 40x25 character grid and CHARBASE as necessary.

887651[/snapback]

 

Cool.

Link to comment
Share on other sites

Well, Wormy II was a CGA game.  If you like I could enclose a copy; it sorta plays on modern machines though it runs too fast [cued off frame rate].  And with artifacting, I think you'd sorta get 16 colors on sorta 320x200 resolution [since different combinations of colors in pixel pairs would yield differnet colors on screen].  Remind me how 320C works?

In 320C the pixel color indexes are:

P2|S3|S2|S7|0 P2|S3|S2|S6|0 P2|S1|S0|S5|0 P2|S1|S0|S4|0

 

where P2|P1|P0 is the palette bits from the display list header and S7|S6|S5|S4|S3|S2|S1|S0 is the graphics data bits.

 

So with 320C you can have 8 colors + background, though with some dependencies between adjacent pixels.

 

But using multiple character sets within a 2K block would entail updating 40 display lists?  Not that that'd be impossible, but it would seem more work.

887895[/snapback]

Nope, you'd only need to update the 15 character grid entries for the worm. So for frame 1 you'd use characters 0-31 for the worm, frame 2 you'd use 32-63 and frame 3 you'd use characters 64-95, with characters 96-127 being the background and other non-animated shapes. Then change CHARBASE to point to the second set of graphics, lather, rise, repeat.

 

Oh, and there's only 25 display lists. One for each row of characters.

Link to comment
Share on other sites

So with 320C you can have 8 colors + background, though with some dependencies between adjacent pixels.

Interesting. So each pair of pixels is two colors from one of four palettes. Sounds nice in theory, and could probably be made to work, but one would probably end up with about the same color limits as what one has now. The game was actually designed around a black+green+red+yellow palette and for the most part that is quite satisfactory. Too bad modern computers seem to use the black+cyan+magenta+white palette which doesn't look nearly as nice.

 

Nope, you'd only need to update the 15 character grid entries for the worm.  So for frame 1 you'd use characters 0-31 for the worm, frame 2 you'd use 32-63 and frame 3 you'd use characters 64-95, with characters 96-127 being the background and other non-animated shapes.  Then change CHARBASE to point to the second set of graphics, lather, rise, repeat.

 

The worm may occupy hundreds of character cells. Only 15 different characters at a time, but some of those characters repeated many times. I wish I knew how to get a screen shot of this thing; winXP doesn't seem to support the print-screen function to grab screens from DOS games. Would updating display lists suffice as an alternative to redrawing lots of characters, or would it be better to plan on using 16K for charactersets and fill in the space that's not used for characters with other stuff.

 

Oh, and there's only 25 display lists.  One for each row of characters.

888284[/snapback]

 

For some reason I thought there were two/row. Oh well, 20 display lists, then (the top three rows are text, then a wall, then 20 that the worm can occupy, then the bottom row).

Link to comment
Share on other sites

Yeah, I realized later that 320C only really gives you one more color than 320B at the cost of flexibility between the two half pixels. Stick with 320B, that maps exactly to the old CGA modes.

 

Let's make sure we understand how the worm is animated. The worm is made up of 15 different characters (of 32 possible characters), and there are 8 possible variations of each of the 32 possible characters. The characters making up the are worm are stored in a 40x25 character map along with the background (which is another 16 characters). Hmm, let me see if I can do a primitive example. Is the worm animated like this?

frame 1: >:---!
frame 2: };///?
frame 3: ]:|||?
frame 4: };\\\!
frame 5: >:---!

where frame 5 = frame 1 etc. So the character map doesn't change, but the graphics for each of the characters is from one of 8 complete sets of 32 characters. (Versus 32 different characters which are dynamically selected from 8 different possible variations. So character 1 may be from a different character set than character 2.)

 

Note: you could have two 40x25 character maps in RAM. Be updating one while MARIA displays the other. In that case you'd also have two DLLs and display lists, and just change the DLL pointer register.

Link to comment
Share on other sites

Let's make sure we understand how the worm is animated.  The worm is made up of 15 different characters (of 32 possible characters), and there are 8 possible variations of each of the 32 possible characters.  The characters making up the are worm are stored in a 40x25 character map along with the background (which is another 16 characters).

 

Yup. I wish I could figure out how to do a screen shot--it would make things so much eaiser to explain.

 

Hmm, let me see if I can do a primitive example.  Is the worm animated like this?

frame 1: >:---!
frame 2: };///?
frame 3: ]:|||?
frame 4: };\\\!
frame 5: >:---!

where frame 5 = frame 1 etc.  So the character map doesn't change, but the graphics for each of the characters is from one of 8 complete sets of 32 characters.  (Versus 32 different characters which are dynamically selected from 8 different possible variations.  So character 1 may be from a different character set than character 2.)

Despite the name, the 'worm' looks a lot like a Centipede (complete with animated legs). The play mechanic moves things a character at a time, but the visual effect is smooth motion. To accomplish this, I defined character shapes for e.g. "worm entering from left and leaving out top". In the first character set, this character shape would feature an up-facing worm segment that was one pixel above center (cropped at the top) superimposed with the rightmost column of a right-facing worm segment that was seven pixels left of center. In the second character set, these segments would be two pixels above center and six pixels left. In the seventh, they would be seven pixels above center and one pixel left. In the eighth, the right-facing segment would appear centered with nothing superimposed, the up-facing segment having shifted completely out of the character block.

 

The effect of this is that the entire length of an arbitrarily-long worm can be smoothly animated by simply changing character sets. There are twelve shapes to deal with the interior of the worm body, four to deal with the rear of the last segment, four to deal with the front of the head, and twelve to deal with head-body joins.

 

Note: you could have two 40x25 character maps in RAM.  Be updating one while MARIA displays the other.  In that case you'd also have two DLLs and display lists, and just change the DLL pointer register.

890340[/snapback]

 

Well, the original game was animated at 60Hz so I would want an Atari 7800 version to be so as well. Double-buffering the display would thus not be terribly helpful--either stuff would happen fast enough or it wouldn't. I'm thinking the best approach would be to simply use character-set cycling in a 16K ROM; the second-best approach would be to copy 240 bytes of character-shape data each frame.

Link to comment
Share on other sites

Ahh, okay. So you do have 8 distinct sets of 32 possible characters. So every 8 frames you update only 5 character map entries:

1. new head

2. head -> neck

3. neck -> body

4. body -> tail

5. tail -> blank

the remaining body segments just cycle through their 8 animations until they are changed to the tail (which then cycles through it's 8 animation cycle). So everything animates in lock-step. Then you'll need 8 character sets, each taking up 2K of ROM space. Tthere will be 160 bytes per 256 byte page which won't be used, which you could use for other data, or even code. I did the same thing for the 4K version of SpaceWar! 7800. One bonus is you can animate any of the "static" items too.

 

Double buffering just adds a 1 frame, 16.7ms, delay to the display and means you can do wholesale updates to the character map without mucking up the display.

Link to comment
Share on other sites

Ahh, okay.  So you do have 8 distinct sets of 32 possible characters.  So every 8 frames you update only 5 character map entries:

1. new head

2. head -> neck

3. neck -> body

4. body -> tail

5. tail -> blank

the remaining body segments just cycle through their 8 animations until they are changed to the tail (which then cycles through it's 8 animation cycle).  So everything animates in lock-step.

 

You got it. Sound like a workable approach for the 7800? It shouldn't take too many CPU cycles to update those five character map entries, meaning that the game would play just fine even with MARIA stealing 90% of the CPU cycles.

 

Then you'll need 8 character sets, each taking up 2K of ROM space.  Tthere will be 160 bytes per 256 byte page which won't be used, which you could use for other data, or even code.  I did the same thing for the 4K version of SpaceWar! 7800.  One bonus is you can animate any of the "static" items too.

For some reason I'd forgotten the data was laid out that way. Any way to make the rows be 128 bytes instead of 256? Otherwise I can think of a use for double-buffering the "text" display--have one copy contain character values that are offset by $40 [or whatever the highest character I use is, plus one]. Then I could get by using half as many fonts.

 

Double buffering just adds a 1 frame, 16.7ms, delay to the display and means you can do wholesale updates to the character map without mucking up the display.

891689[/snapback]

 

Well, it has another possible purpose as well. BTW, animating the static items would be possible, but the speed of the animation would change depending upon the speed of the worm (which changes under user control). Not sure that would look good. It might be possible to do things creatively, however, and either (1) change character map entries for static items to animate them at whatever speed is desired (possible, but might be too slow unless the game uses dynamically-created code for that purpose; in that case, speed would be adequate but RAM would likely be inadequate); (2) use an address mapping PLD :) The latter might require a custom board design :( but if anything could be adapted to work with it, it'd be really cool and would also make possible a two-player version of Wormy. That would be positively sweet. Put A6, A7, A11, A12, A13, A14, and A15 through a Xilinx 95C36 and configure it to provide three separate character-set selections (one for characters 0-31 [player 1 snake], one for 32-63 [player 2 snake], and one for characters 64-127 [static stuff]). How does that sound for an idea?

 

BTW, do you like the idea of doing Wormy as I've suggested? Do you agree with my judgement that tiles would be the way to go?

Link to comment
Share on other sites

You got it.  Sound like a workable approach for the 7800?  It shouldn't take too many CPU cycles to update those five character map entries, meaning that the game would play just fine even with MARIA stealing 90% of the CPU cycles.

 

BTW, do you like the idea of doing Wormy as I've suggested?  Do you agree with my judgement that tiles would be the way to go?

Yes, very do-able on the 7800. Keeping the character map will probably make porting the code fairly easy; maybe even easier since you can lose the character graphics update code.

 

Any way to make the rows be 128 bytes instead of 256?

Nope. You're constrained by CHARBASE. This does mean you can use $C000-$FF7F for the graphics since it won't overlap the digital signature at $FF80-$FFF9. And I'm sure you will find some use for 63 chunks of 128 bytes (assuming that you use all 64 characters).

 

... Xilinx 95C36 ... How does that sound for an idea?

891913[/snapback]

You lost me there. But custom HW probably should be avoided; just too expensive. It will also make coding and testing tough.

 

FYI I've got a framework ASM about half done for Wormy 7800. Need to cut & paste the startup code and a placeholder mainline. I'll try to get it done & posted this weekend.

Edited by EricBall
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...