Jump to content
  • entries
    657
  • comments
    2,699
  • views
    900,557

Flickerama


SpiceWare

1,223 views

Think I figured out the cause of the glitch.

 

I use 4 datastreams to draw all the players(sprites in 2600 terminology) on the screen. Each player gets 2 datastreams, one for the image and one for the color. A 0 value in the color datastream is used to trigger a reposition of a player. The color datastreams are pre filled with 15 (white) so that missiles will be visible on scanlines without the corresponding player present.

 

When a reposition is triggered, 2 bytes in the image datastream are used to point to the reposition routine (there's 11 per player), and an additional byte in the color datastream holds the fine-adjustment value that goes into HMP0 or HMP1.

 

This sets it for Player 0

		gP0DataStream[y + position    ] = flashdata[P0_HMOVE + hmove * 2    ];
	gP0DataStream[y + position + 1] = flashdata[P0_HMOVE + hmove * 2 +1 ];
	gC0DataStream[y + position    ] = 0; // 0 triggers reposition
	gC0DataStream[y + position + 1] = x; // HMP0			
 

 

while this sets it for Player 1

		gP1DataStream[y + position + 1] = flashdata[P1_HMOVE + hmove * 2    ];
	gP1DataStream[y + position + 2] = flashdata[P1_HMOVE + hmove * 2 +1 ];
	gC1DataStream[y + position    ] = 0; // 0 triggers reposition
	gC1DataStream[y + position + 2] = x; // HMP1	
 

 

Player 0 takes 2 scanlines for a reposition, player 1 takes 3.

 

2 repositions cannot be occuring at the same time, so each routine looks for a conflicting 0 in the color datastream, and adjusts if necessary so no conflict occurs. Player 0 uses:

	// it takes 2 scanlines to reposition Player 0
	// make sure we don't conflict with a reposition of Player 1, which takes 3 scanlines
	
	// -6                   0   -6
	// -5   1           0   0   -5
	// -4   1       0   0   1   -4
	// -3   1   0   0   1   1   -3
	// -2   0   0   1   1   1   -2
	// -1   0   1   1   1       -1
	
	position = -2; // it takes 2 scanlines to reposition Player 0					
	// make sure we don't conflict with a reposition of Player 1, which takes 3 scanlines
	if (gC1DataStream[y-1] == 0) position = -3;
	if (gC1DataStream[y-2] == 0) position = -4;
	if (gC1DataStream[y-3] == 0) position = -5;
	if (gC1DataStream[y-4] == 0) position = -6;
 

 

while player 1 uses:

		// it takes 3 scanlines to reposition Player 1					
	// make sure we don't conflict with a reposition of Player 0, which takes 2 scanlines

	// -7                   1   -7
	// -6               1   1   -6
	// -5   0       1   1   1   -5
	// -4   0   1   1   1   0   -4
	// -3   1   1   1   0   0   -3
	// -2   1   1   0   0       -2
	// -1   1   0   0           -1

	position = -3; 
	if (gC0DataStream[y-1] == 0) position = -4;
	if (gC0DataStream[y-2] == 0) position = -5;
	if (gC0DataStream[y-3] == 0) position = -6;
	if (gC0DataStream[y-4] == 0) position = -7;
 

 

The conflict was happening when the HMP0 or HMP1 value was 0. If HMP1 was 0, then the routines to position player 0 became confused when it was checking for a reposition conflict. Likewise if HMP1 was 0 then player 1's routine became confused.

 

The HMPx register only needs the upper 4 bits of the byte, so to prevent the 0 conflict I set the bottommost bit to 1.

 

The last digit of the score is the worst case flicker for at last 1 player on the current display.

0 = no flicker

1 = 30 hz (every other frame)

2 = 20 hz (every 3rd frame)

3 = 15 hz (every 4th frame)

 

Stella only does the phosphor effect over 2 frames, so if anything is at a flicker level of 2 or higher then robots will be missing from snapshots.

 

The Berzerk style maze with 5 robots per horizontal band ends up with 1 or 2

blogentry-3056-0-01790900-1308429575_thumb.png blogentry-3056-0-53786300-1308429608_thumb.png

 

The Frenzy style maze with 6 robots per horizontal band ends up with 2, with a rare appearance of 1

blogentry-3056-0-91464500-1308429615_thumb.png blogentry-3056-0-82617900-1308429628_thumb.png

 

This is the worse-case for the starting point of the display. In an actual game you won't always see the maximum number of robots on a particular level, so 0 flicker is possible.

blogentry-3056-0-88821700-1308430550_thumb.png blogentry-3056-0-50090500-1308430557_thumb.png

 

I've also re-evaluted the PAL version and decided to do it as PAL60.

 

ROM

f20110618_NTSC.bin

 

Source

Frantic20110618.zip

5 Comments


Recommended Comments

The flickering robot sprites look great on a real TV.

 

I do find the flashing wall segments very distracting though. Would it be possible to decrease the rate of flashing a bit, or draw them in a different way, e.g. without flicker but with every second line blank?

 

Chris

Link to comment

Yeah, that can be distracting. I have some ideas, but it'll be a bit before I get around to trying them. In the meantime, you can use the left difficulty switch to change the walls between "flicker" and "animate".

 

I'm using the fractional datafetchers for the walls, they're set to 256/5 for NTSC and 256/6 for PAL which minimizes the RAM needed to hold the room layout. The room layout is double-buffered, I swap buffers to flicker/animate.

 

I still need to squeeze in the STA ENAxx for the shots. One thing I've been thinking about is unrolling the data streams for the 2 PF0 updates and using them for PF0 updates and ENAxx updates. That'll let me updating 2 shots with just 4 additional cycles, I still need to work out the timing so the shots don't shear.

 

If I unroll PF0, that'll actually unroll 4 datastreams (due to the double buffering). At that point, just a small increase in RAM usage would let me unroll all 6 PFx datastreams and drop the double-buffering. If that works I plan to try stripes instead of flicker.

 

* there's a 2K buffer set aside for audio playback, which uses half the DD RAM. By using PAL60 my display datastreams are shorter, plus I can use single bytes for each X-Y value instead of doubling that up for fractional increment support. The 2K buffer also means less RAM is available for the datastreams for drawing the screen and holding all the state info (the ARM can't see ZP RAM)

Link to comment

I spent today trying to revamp the routines so I could do the walls at single line detail to avoid flicker. Don't think it's going to happen:

 

2048 = audio playback buffer

1116 = playfield data @ single line resolution (186 x 6) *

740 = sprite color/shape/reposition data (185 x 4) *

120 = 24 objects x,y,etc data

80 = digit data for score

----

4104 > 4K Display Data and there's more that needs to be stored in there.

 

* the playfield data has an extra 0 at the end, it triggers end-of-kernel.

Link to comment

Would have to decrease the Hz so "humanoid" would fit into the playback buffer, and the lower Hz didn't go over well in testing.

 

I suppose it might be possible to break the longer samples in half so the Hz could stay the same, might cause some mid-word "clicks" though. However, I'm mid-kernel revamp and don't wish to divert my attention at this time.

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