Jump to content
  • Advertisement
Sign in to follow this  
kratz

Allegro direct vidmem access help

This topic is 3330 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Can anyone see what I'm doing wrong here? I'm trying to read each line of the screen bitmap, test and fade each pixel. I'm trying to do this by reading 32bits at a time (following the exflame example) but I'm doing something wrong because only half of the screen is being faded. Color depth is 16bpp
unsigned short buffer[SCREEN_W];
unsigned long address;
.
.
.
.
//Direct video memory access
//Check each pixel, if it has color, reduce color
for(int i = 0; i < SCREEN_H; i++)
{
       //Get the video memory address for reading
        address = bmp_read_line(screen, i);
        for(int j = 0; j < SCREEN_W; j+= sizeof(uint32_t))
	{
	     *((uint32_t *)&buffer[j]) = bmp_read32(address+j);
	} 
	//Fade the color
	for(int j = 0; j< SCREEN_W; j++)
	    if(buffer[j] > 0)
		buffer[j]--;

	//Get the video memory address for writing
	address = bmp_write_line(screen, i);
	for(int j = 0; j < SCREEN_W; j+= sizeof(uint32_t))
	{
	   bmp_write32(address+j, *((uint32_t *)&buffer[j]));
	}
}

Also could someone put the left side of this into English for me. *((uint32_t *)&buffer[j]) = bmp_read32(address+j); Thanks in advance, kratz

Share this post


Link to post
Share on other sites
Advertisement
Try changing the type of the buffer variable to be a unsigned byte array, instead of an unsigned short one (like in the exflame example).
(If this isn't viable because you use buffer elsewhere, instead change both *((uint32_t *)&buffer[j]) to *((uint32_t *)&buffer[j / 2])).

Currently when do you *((uint32_t *)&buffer[j]) you are moving over 8 bytes of the buffer for every 4 from the screen bitmap.

Quote:
Original post by kratz
Also could someone put the left side of this into English for me.
*((uint32_t *)&buffer[j]) = bmp_read32(address+j);


Start from the innermost part:
buffer is obviously your temporary array
buffer[j] is the j'th item in this array (note that it is indexed by item (so unsigned short in this case), not bytes!)
&buffer[j] is a pointer to the above item
(uint32_t *)&buffer[j] casts the pointer so that it has unsigned long width
*((uint32_t *)&buffer[j]) refers to an unsigned long at this location.

[Edited by - mattd on October 27, 2009 1:33:08 AM]

Share this post


Link to post
Share on other sites
Thanks for the reply matt but I tried your suggestion and it doesn't work. Besides, don't I need each item in buffer[] to be 16 bits since they represent each pixel in 16 bit depth?

Also, I think uint32_t is defined as unsigned int = 4 bytes right?

Thanks,
kratz

Share this post


Link to post
Share on other sites
Quote:
Besides, don't I need each item in buffer[] to be 16 bits since they represent each pixel in 16 bit depth?


Well, when you cast the buffer pointer to (uint32_t *) you are treating it as an unsigned int array, so it should make no difference. But yes, it will make processing the data after reading it easier.

Quote:
Also, I think uint32_t is defined as unsigned int = 4 bytes right?


Yes it is, sorry :)


Having another read of your code, I think this is the problem after all:
for(int j = 0; j < SCREEN_W; j+= sizeof(uint32_t))

The exflame code runs in 8-bit colour, so since 1 pixel fits in 1 byte, we can just treat the offset j as a pixel width as well, so we need to range j from 0 to SCREEN_W, so the comparison j < SCREEN_W is valid.

But with 16-bit mode in your application, 1 pixel fits in 2 bytes, so we need to make the offset j range from 0 to SCREEN_W * 2 to get all SCREEN_W pixels, so the comparison needs to be j < SCREEN_W * 2.

Try changing the comparison in both for loops. Note that you'll still want to have changed both *((uint32_t *)&buffer[j]) to *((uint32_t *)&buffer[j / 2])), otherwise you'll overwrite buffer with this newly expanded offset range.


Also, note that you will probably want to do something like this to process the pixel data to fade it, since you are using 16-bit pixels, not 8-bit:

for(int j = 0; j< SCREEN_W; j++)
buffer[j] = makecol16(max(0, getr16(buffer[j]) - 1), max(0, getg16(buffer[j]) - 1), max(0, getb16(buffer[j]) - 1));

I.e., treat each of the R, G, B components seperately.

Share this post


Link to post
Share on other sites
I don't think that will work either since buffer is buffer[SCREEN_W] I can't let j be over SCREEN_W. I could change the size of the buffer but I don't think that makes sense either. It should be the perfect size to hold 1 line of the screen.

Thanks for the help,
kratz

Share this post


Link to post
Share on other sites
But note:

Quote:

Note that you'll still want to have changed both *((uint32_t *)&buffer[j]) to *((uint32_t *)&buffer[j / 2])), otherwise you'll overwrite buffer with this newly expanded offset range.


The / 2 converts back from offset to pixel width.

Share this post


Link to post
Share on other sites
Oh I get it now.... Sorry I missed that. It works perfectly.

Thanks for the pointers matt

Rating++

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!