Issue with SGDK's VDP_setTileMapRect (possible bug?)

SGDK only sub forum

Moderator: Stef

Post Reply
djcouchycouch
Very interested
Posts: 710
Joined: Sat Feb 18, 2012 2:44 am

Issue with SGDK's VDP_setTileMapRect (possible bug?)

Post by djcouchycouch » Tue Feb 21, 2012 9:23 pm

Hi,

I'm encountering an issue with VPD_setTileMapRect. I'm not sure if it's a bug or I'm just not using it properly.

I've tried to simplify the problem as much as possible. Here's some basic code I have.

Code: Select all

const u16 map2[4] = 
{
	0, 1, 
	2, 3
};
	

VDP_setTileMapRect(APLAN, map2, TILE_ATTR_FULL(PAL3, 0, 0, 0, 0), 0, 0, 2, 2);
So I'm trying to set some background tiles based on an array I've set up. Strangely, I'm getting this as the result:

Image

But I'm expecting:

Image


If I look at VPD_setTileMapRect's code,

Code: Select all

    while (i--)
    {
	    *plctrl = GFX_WRITE_VRAM_ADDR(addr);

        j = w;
        while (j--) *pwdata = basetile | *src++;
     
    ...

When it's setting the tile, if I switch the or operator to an addition

Code: Select all

        // "fixed" version
        while (j--) *pwdata = basetile + *src++;
The map setting code works.

My first impression is that the behaviour should be identical, but it's obviously not.

Could this be a bug in VDP_setTileMapRect or am I just not using it correctly?

Thanks!
DJCC.

Chilly Willy
Very interested
Posts: 2984
Joined: Fri Aug 17, 2007 9:33 pm

Post by Chilly Willy » Tue Feb 21, 2012 11:19 pm

The difference between (x | y) and (x + y) is the former assumes y will never be greater or equal to x, while the latter doesn't. Let's say you load the first 128 tiles with a font and set basetiles to 128. Now let's say you load 256 more tiles... the first 128 will be fine, but the next 128 will overwrite the first 128 because of the OR... 128 | 128 = 128.

I believe I pointed out this "limitation" once before... it's not quite a bug, but it's not going to do what people expect under certain circumstances.

Stef
Very interested
Posts: 3131
Joined: Thu Nov 30, 2006 9:46 pm
Location: France - Sevres
Contact:

Post by Stef » Wed Feb 22, 2012 12:26 am

Chilly Willy wrote:The difference between (x | y) and (x + y) is the former assumes y will never be greater or equal to x, while the latter doesn't. Let's say you load the first 128 tiles with a font and set basetiles to 128. Now let's say you load 256 more tiles... the first 128 will be fine, but the next 128 will overwrite the first 128 because of the OR... 128 | 128 = 128.

I believe I pointed out this "limitation" once before... it's not quite a bug, but it's not going to do what people expect under certain circumstances.
There is definitely something which mess users with that method.. It's the third time someone report me it as a bug :p
Actually i modified it this way in the next version so i guess it will be easier and more flexible to use :

Code: Select all

void VDP_setTileMapRect(u16 plan, const u16 *data, u16 base_index, u16 base_flags, u16 x, u16 y, u16 w, u16 h);
In the current method, basetile does *not* refer the base tile index but the base tile "value", it's intended to contains default flags as palette, priority, HV flip dataflags but not the base index. The data table should contains the plain index values.

djcouchycouch
Very interested
Posts: 710
Joined: Sat Feb 18, 2012 2:44 am

Post by djcouchycouch » Wed Feb 22, 2012 12:35 am

Ah, I see.

So in my case, if the base tile is 1, then my array would be computed like so:

const u16 map2[4] =
{
0, // -> 0 | 1 -> 1
1, // -> 1 | 1 -> 1
2, // -> 2 | 1 -> 3
3 // -> 3 | 1 -> 3
};



As Stef mentions, several people have been tripped up by this. The function doesn't work as most people expect, so I'd see this as a bug. Is there a use case for it's current behaviour?

sega16
Very interested
Posts: 251
Joined: Sat Jan 29, 2011 3:16 pm
Location: U.S.A.

Post by sega16 » Wed Feb 22, 2012 9:54 pm

I don't get the point of seperating the flags and the base tile why would you need to do that if you want the tile map to be on the next line all you need to do is add 1024 if you want it to be one the next line and start at tile 20 all you need to do is 1024+20 why do you need two variables for this?

Chilly Willy
Very interested
Posts: 2984
Joined: Fri Aug 17, 2007 9:33 pm

Post by Chilly Willy » Thu Feb 23, 2012 7:05 am

sega16 wrote:I don't get the point of seperating the flags and the base tile why would you need to do that if you want the tile map to be on the next line all you need to do is add 1024 if you want it to be one the next line and start at tile 20 all you need to do is 1024+20 why do you need two variables for this?
It may be easier to keep track of things by having two separate vars for those in your app. Rather than wonder if you forgot to add the flags, just keep them separate. Once you have separate vars for them, then it becomes of matter of having a cleaner API to pass both to the function rather than add them (or OR them...).

Stef
Very interested
Posts: 3131
Joined: Thu Nov 30, 2006 9:46 pm
Location: France - Sevres
Contact:

Post by Stef » Thu Feb 23, 2012 8:08 pm

sega16 wrote:I don't get the point of seperating the flags and the base tile why would you need to do that if you want the tile map to be on the next line all you need to do is add 1024 if you want it to be one the next line and start at tile 20 all you need to do is 1024+20 why do you need two variables for this?
As Chilly Willy said, this is just an helper feature, so this way you can store only the tile address in your tilemap data and set the flag in the parameter.
The function doesn't work as most people expect, so I'd see this as a bug. Is there a use case for it's current behaviour?
Well i can not say it is a bug as actually the function does what i was expecting from it :p problem is more related to the way i named parameter maybe.
A use case is exactly what you did in your first post :

Code: Select all

VDP_setTileMapRect(APLAN, map2, TILE_ATTR_FULL(PAL3, 0, 0, 0, 0), 0, 0, 2, 2); 
This way you force the tilemap to use palette 3.
If you have + and your tilemap data contains also information about palette then uploaded value could be completely wrong, using | just override flags value without adding (and mess) them.

djcouchycouch
Very interested
Posts: 710
Joined: Sat Feb 18, 2012 2:44 am

Post by djcouchycouch » Thu Feb 23, 2012 8:59 pm

Stef wrote: A use case is exactly what you did in your first post :

Code: Select all

VDP_setTileMapRect(APLAN, map2, TILE_ATTR_FULL(PAL3, 0, 0, 0, 0), 0, 0, 2, 2); 
I'll try to clarify what I meant.

The use case I meant was the behavior of the or operator on the basetile and the dereferenced src.

Ignoring TILE_ATTR_FULL, if my basetile is one and the map array I'm passing has nothing but ones, I'd expect the background plane to be filled with tiles of index two. But currently the result would be that the background plane would be filled with tiles of index one. So I was wondering if that behavior is considered useful, as opposed to the one I'd expect.

I understand why you'd want to or the tile attributes, but I don't think that works well for the tile indexes. When it comes to tile indexes, I want them to add, not bitwise or. Maybe the function tries to to do much?

If the function's current behavior is expected and wanted, then it's no problem. I can use a modified version for my needs. But preferably I'd use the built in functions in SGDK rather than forking my own versions.

But it all could be moot as soon as the new version is out :)

Stef
Very interested
Posts: 3131
Joined: Thu Nov 30, 2006 9:46 pm
Location: France - Sevres
Contact:

Post by Stef » Thu Feb 23, 2012 10:56 pm

djcouchycouch wrote: I understand why you'd want to or the tile attributes, but I don't think that works well for the tile indexes. When it comes to tile indexes, I want them to add, not bitwise or. Maybe the function tries to to do much?

If the function's current behavior is expected and wanted, then it's no problem. I can use a modified version for my needs. But preferably I'd use the built in functions in SGDK rather than forking my own versions.

But it all could be moot as soon as the new version is out :)
Of course, it does not work for tile index because basically i did not though to use the method in this way ;) But as severals people (and you) requested to have the base index i changed the method :

Code: Select all

void VDP_setTileMapRect(u16 plan, const u16 *data, u16 base_index, u16 base_flags, u16 x, u16 y, u16 w, u16 h);
where the parameter "base_index" is used for what you want and "base_flags" correspond to the old "basetile" parameter :)

djcouchycouch
Very interested
Posts: 710
Joined: Sat Feb 18, 2012 2:44 am

Post by djcouchycouch » Fri Feb 24, 2012 3:24 am

Great! Can't wait.

How often are releases done?

Chilly Willy
Very interested
Posts: 2984
Joined: Fri Aug 17, 2007 9:33 pm

Post by Chilly Willy » Fri Feb 24, 2012 5:12 am

Every twenty years... to the second! :lol:

Stef
Very interested
Posts: 3131
Joined: Thu Nov 30, 2006 9:46 pm
Location: France - Sevres
Contact:

Post by Stef » Fri Feb 24, 2012 9:04 am

haha, yeah it really depends...
I will try to make a new one soon, i always publish a new post in the SGDK topic when i release a new version :)

Post Reply