Jump to content
  • 0

Using Sprites (in C with CC65)?


rje
 Share

Question

I'm trying to define and show a sprite, in C, using CC65.  It's a mess and I'm not sure what I'm doing wrong, so I'm going to write it afresh here and see if anyone can see what I'm doing wrong.

I am thinking that the following code should be sufficient to define and display a sprite, assuming of course that VRAM has been initialized with the sprite data at location $4000.

First, I have to set the port address in VERA.  I'll use port 0.

(Version 2)

#define     SPRITE_REGISTERS(spritenum)    ((spritenum << 3) + 0xfc00)
//
// set port 0 address and increment
// 
VERA.control = 0;   // port 0
VERA.address = SPRITE_REGISTERS(1);
VERA.address_hi = VERA_INC_1 + 1; // the "+1" is the VRAM high address bit. 

// So $1FC08 begins the registers for sprite 1.  Right?

Now I should be able to define sprites.

// sprite blocks are in 32 byte chunks.
#define	    SPRITE_BLOCK(addr)			(addr >> 5)
#define     SPRITE_MODE_8BPP     		128
#define	    SPRITE_32_BY_32		        (128 + 32)
#define	    SPRITE_64_BY_64		        (196 + 48)

#define	    SPRITE_DISABLED		        0
#define	    SPRITE_LAYER_BACKGROUND		(1 << 2)
#define	    SPRITE_LAYER_0		        (2 << 2)
#define	    SPRITE_LAYER_1		        (3 << 2)

int block = SPRITE_BLOCK(0x4000); 
int mode = SPRITE_MODE_8BPP;
int x = 100;
int y = 100;
int z = SPRITE_LAYER_1;
int dimensions = SPRITE_32_BY_32;
int palette_offset = 0;

vera_sprites_enable(1); // cx16.h

VERA.data0 = block & 0xff; // lower VRAM address bits
VERA.data0 = mode + ((block >> 8) & 0x1f);
VERA.data0 = x & 0xff;
VERA.data0 = x >> 8;
VERA.data0 = y & 0xff;
VERA.data0 = y >> 8;
VERA.data0 = z;                 // leave collision mask and flips alone for now.
VERA.data0 = dimensions + palette_offset;

 

Edited by rje
Link to comment
Share on other sites

Recommended Posts

  • 0

Correct me if I'm wrong, but you have SPRITE_64_BY_64 set to 196+48, which is 244, which I believe is 0b11110100 in binary.  This results in a palette offset of 0b0100.  I'm guessing that's not what you want since your palette_offset is 0.  I think what you want is 240 for the dimensions.

Edited by Ender
  • Thanks 1
Link to comment
Share on other sites

  • 0
43 minutes ago, Ender said:

Correct me if I'm wrong, but you have SPRITE_64_BY_64 set to 196+48, which is 244, which I believe is 0b11110100 in binary.  This results in a palette offset of 0b0100.  I'm guessing that's not what you want since your palette_offset is 0.  I think what you want is 240 for the dimensions.

Yep, that should be 192+48, but the palette index shouldn't matter for 8bpp. Weird.

That is unless these are in fact 4bpp, in which case the palette being off by 4 does make a difference. 

  • Thanks 1
Link to comment
Share on other sites

  • 0

Okay with that minor crisis averted, now I can do some real work.  My map is 8 x 8 terrain sprites, and I'm going to scroll them.

I THINK what I'll have to do is:

* put the map-sprites behind the default text layer
* draw a thick "frame" slightly overlapping the map using reverse-spaces

Now the tricky part. 

* When the player moves, the SCROLL X/Y OFFSET is changed, NOT the actual "position"
* When the X OFFSET < -24, Then the x position is decremented and the x offset is changed to +24.
* When the X OFFSET > 24, Then the x position is incremented and the x offset is changed to -24.
* Similarly for the Y OFFSET.

"Position" tells us what terrain to draw in each tile.

"Offset" tells us what screen position to draw that tile.

 

...something like that anyway.

Edited by rje
Link to comment
Share on other sites

  • 0
On 9/23/2021 at 1:58 PM, rje said:

So far, so good!

 

It doesn't look like smooth sailing as there's little freeboard showing. Perhaps someone should be managing the bilge pumps! 🙄 

Congrats on getting the sprites in C going!

Edited by Edmond D
sprites spellcheck, not spites!
  • Thanks 1
Link to comment
Share on other sites

  • 0
1 hour ago, rje said:

So far, so good!

pk1.gif.cc84863a466c842a6f95c35087e061c1.gif

spacer.png

Some 16x16 sprites could smooth out those coastlines. If a big square is water, check each corner for the neighboring squares, if both present a little curved piece can go there. Or a 64x8 sprite can go on one edge of a water square if only one of the four neighbors is land. One horizontal 64x8 beach,  one vertical 8x64 beach, and one corner piece 16x16 would really smooth out the map.

Edit: there's really only 16 combinations of neighbors being land or water, so for a water tile check all four neighbors and then select the appropriate one of 16.

Edited by Ed Minchau
Link to comment
Share on other sites

  • 0
1 hour ago, Ed Minchau said:

Some 16x16 sprites could smooth out those coastlines.

Yep... I was thinking 8 x 64 and 64 x 8 too, but yep.

 

The sprite block swapping is causing a bit of flashing effects.  I'll think about that too... I might have to swap out sprite definitions off-screen.  Don't want to go as far as double buffering, but...

Edited by rje
Link to comment
Share on other sites

  • 0
4 hours ago, rje said:

Yep... I was thinking 8 x 64 and 64 x 8 too, but yep.

 

The sprite block swapping is causing a bit of flashing effects.  I'll think about that too... I might have to swap out sprite definitions off-screen.  Don't want to go as far as double buffering, but...

It looks like you've got a maximum of 88 sprites for the terrain. Maybe another 16 for coastlines, and then your ship... that's a lot of sprites.

I'd set aside 1kb of low RAM for all your sprite attributes.  When you're making changes, say to the XY values or the VRAM location, you just do the changes in that low RAM area.  Then when you're ready to change all the sprites, you just copy that whole 1kb from low RAM to 1FC00 all at once on a VSYNC, and that should stop the flickering.

Edited by Ed Minchau
Link to comment
Share on other sites

  • 0
10 hours ago, Ed Minchau said:

It looks like you've got a maximum of 88 sprites for the terrain. Maybe another 16 for coastlines, and then your ship... that's a lot of sprites.

I'd set aside 1kb of low RAM for all your sprite attributes.  When you're making changes, say to the XY values or the VRAM location, you just do the changes in that low RAM area.  Then when you're ready to change all the sprites, you just copy that whole 1kb from low RAM to 1FC00 all at once on a VSYNC, and that should stop the flickering.

Good idea, thank you.

I'm also thinking about using characters for the ocean background instead of sprites.  I guess that means I'd have to scroll a character layer too.

Going to characters for the background "ocean" also has the benefit of not overlapping the terrain sprites (I overlap because each terrain sprite is, by itself, essentially an "island" with a jaggy "coastline").

*** UPDATE.  VSYNC!  Can C code do that?  Ohhhh, I'd write an assembly interrupt.  OK.

Edited by rje
Link to comment
Share on other sites

  • 0

So.  Yeah.  I'll have to revert to the old school method of using shoreline sprites.  I figure one 8 x 64 "vertical shoreline", one 64 x 8 "horizontal shoreline" (I can flip them based on what I need), and a 16 x 16 "inner corner adapter" (which I can flip on either axis as needed).  I'll sacrifice one of the terrain sprites (4K) for this.

512b: Horiz Shoreline
512b: Vert Shoreline
256b: Corner

Also, I can stop overlapping the sprites.  Current overlap is 8 pixels on every side, which means my 8 x 8 grid covers 384 x 384 pixels.  I can now move down to a much more reasonable 6 x 6 sprites, stay at 384 x 384 pixels, but have more interesting terrain.

AND this gives me room for a couple of badly-needed tactical sprites.

 

Edited by rje
Link to comment
Share on other sites

  • 0

I've started thinking about how I'm going to interact with the map.  

  1. The ship should "stop" when it hits land, and a landing party should take over movement.
  2. The ship's movement needs to be finer grained.  (easy)
  3. The landing party should interact with settlements.

If I have enough VERA RAM left, I want sprites to define a few key buildings (maybe 16 x 16?).  In this way, the landing party can interact with the town without requiring a separate town map, and it keeps essential things without adding stuff I don't want to do.

Replacing the "settlement" sprites gives me 8K VERA RAM to define buildings and groups of people.  I can re-use the settlement graphics and chop them up into some of these smaller, 16 x 16 sprites.

 

Edited by rje
Link to comment
Share on other sites

  • 0
On 9/26/2021 at 11:05 PM, Ed Minchau said:

How about using tiles for the towns? Not everything needs to be a sprite. 

Very true.  That's a good option.  But I'll have to stew on it for awhile.

 

However, I think before I get to that point, I want to write a simple PSG interface in C.

 

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

Guest
Answer this question...

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

 Share

×
×
  • Create New...

Important Information

Please review our Terms of Use