struggling with loading bitmap

SGDK only sub forum

Moderator: Stef

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

Post by Stef » Fri Feb 21, 2014 10:02 am

SGDK only support 4bit or 8bit PNG right now.
I could add support for 2bit or 1bit later but anyway i will have to convert to 4bpp internally. Even if your PNG has only two colors you need to save it as 4bpp PNG at least, some tools authorize that, others not :-/ You may try to manually add some unused colors in the palette to force it.

matteus
Very interested
Posts: 336
Joined: Mon Feb 04, 2008 1:41 pm

Post by matteus » Fri Feb 21, 2014 10:08 am

Stef wrote:SGDK only support 4bit or 8bit PNG right now.
I could add support for 2bit or 1bit later but anyway i will have to convert to 4bpp internally. Even if your PNG has only two colors you need to save it as 4bpp PNG at least, some tools authorize that, others not :-/ You may try to manually add some unused colors in the palette to force it.
I tried 2bit and now understand why it wasn't working :D Cool I'll add a 8x8 cube of additional colours to the bottom corner of each single colour animation frame for now.

I could just do the fade in software via a palette increment but I want to keep it simple for now!

I hope you add 2bit and 1bit support soon, I know its ridiculous really given you could just do a background colour but I need it haha

matteus
Very interested
Posts: 336
Joined: Mon Feb 04, 2008 1:41 pm

Post by matteus » Fri Feb 21, 2014 12:20 pm

I have a question. The code example below is obviously fictional but say I had a series of images in res each one was a frame number: frame1, frame2, frame3, frame4, etc.

Is there a way I can do a for loop for each frame without having to manually enter the code over and over again?

Code: Select all


for (i = 0; i < 10; i++) 
{ 
	
	// load background 
	ind = TILE_USERINDEX; 

	// set present plan
	int setPlan = 0; // 0 = PLAN A, 1 = PLAN B
	
	if setPlan == 0) {
		
		//set frameI to equal the frame within the loop
		&frameI = frame + i
		
		
		// draw image
		VDP_drawImageEx(APLAN, &frameI, TILE_ATTR_FULL(PAL0, FALSE, FALSE, FALSE, ind), 22, 5, FALSE, TRUE); 
		ind += frameI.tileset->numTile; 
		
		// set pallettes 
		VDP_setPalette(0, frameI.palette->data); 
		
		setPlan = 1;
		
	} else {
	
		// draw image
		VDP_drawImageEx(BPLAN, &frameI, TILE_ATTR_FULL(PAL1, FALSE, FALSE, FALSE, ind), 22, 5, FALSE, TRUE); 
		ind += frameI.tileset->numTile; 
		
		// set pallettes 
		VDP_setPalette(1, frameI.palette->data); 

		setPlan = 0;			
		
	}

	// wait
	waitTick(150); 
		
} 

I could create a method to make each call but I'd prefer a nice loop.

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

Post by Stef » Fri Feb 21, 2014 1:05 pm

You can use a const array of image pointers:

Code: Select all

const Image *images[NUM_IMAGE] = {
  &image1,
  &image2,
  &image3,
  &image4,
  ...
}

then do:

Code: Select all

for(i = 0; i < NUM_IMAGE; i++)
{
  VDP_drawImageEx(APLAN, images[i], TILE_ATTR_FULL(PAL0, FALSE, FALSE, FALSE, ind), 22, 5, FALSE, TRUE); 
  ...
}

matteus
Very interested
Posts: 336
Joined: Mon Feb 04, 2008 1:41 pm

Post by matteus » Fri Feb 21, 2014 1:14 pm

Stef wrote:You can use a const array of image pointers:

Code: Select all

const Image *images[NUM_IMAGE] = {
  &image1,
  &image2,
  &image3,
  &image4,
  ...
}

then do:

Code: Select all

for(i = 0; i < NUM_IMAGE; i++)
{
  VDP_drawImageEx(APLAN, images[i], TILE_ATTR_FULL(PAL0, FALSE, FALSE, FALSE, ind), 22, 5, FALSE, TRUE); 
  ...
}

I'm confused we pass a pointer to the drawImageEx method but directly reference things in the main :) I'm guessing this is a memory management thing :D

Would:

Code: Select all

for(i = 0; i < NUM_IMAGE; i++)
{

Image currentImage = images[i]

  VDP_drawImageEx(APLAN, images[i], TILE_ATTR_FULL(PAL0, FALSE, FALSE, FALSE, ind), 22, 5, FALSE, TRUE); 
ind +=  currentImage.tileset->numTile; 
       
      // set pallettes 
      VDP_setPalette(1, currentImage.palette->data); 

}
or

Code: Select all

for(i = 0; i < NUM_IMAGE; i++)
{

  VDP_drawImageEx(APLAN, images[i], TILE_ATTR_FULL(PAL0, FALSE, FALSE, FALSE, ind), 22, 5, FALSE, TRUE); 
ind +=  images[i].tileset->numTile; 
       
      // set pallettes 
      VDP_setPalette(1, images[i].palette->data); 
}
Work?

matteus
Very interested
Posts: 336
Joined: Mon Feb 04, 2008 1:41 pm

Post by matteus » Fri Feb 21, 2014 1:24 pm

Silly me I remember you saying in theory all I need is that one line for things to work >_< I'll give it a go later!

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

Post by Stef » Fri Feb 21, 2014 4:13 pm

1 line to display a single image yeah.
Not to do an animation :p
I forgot about the palette change, you have to keep the pal info in a variable.
So you can do :

Code: Select all

pal ^= 1;
to switch palette at each frame.

This should work :

Code: Select all

pal = PAL0;
ypos = 0;
for(i = 0; i < NUM_IMAGE; i++)
{
  u16 nextypos =  ypos ^ 0x20;
  VDP_setVerticalScroll(APLAN, vpos);
  VDP_drawImageEx(APLAN, images[i], TILE_ATTR_FULL(pal, FALSE, FALSE, FALSE, ind), 22, vpos + 5, TRUE, TRUE);
  ind +=  images[i]->tileset->numTile;
  pal ^= 1;
  ypos = nextypos;
}


Problems you are talking about now is more C related programming issues that megadrive programming itself.
Last edited by Stef on Fri Feb 21, 2014 4:51 pm, edited 1 time in total.

matteus
Very interested
Posts: 336
Joined: Mon Feb 04, 2008 1:41 pm

Post by matteus » Fri Feb 21, 2014 4:23 pm

Stef wrote:1 line to display a single image yeah.
Not to do an animation :p
I forgot about the palette change, you have to keep the pal info in a variable.
So you can do :

Code: Select all

pal ^= 1;
to switch palette at each frame.

This should work :

Code: Select all

pal = PAL0;
for(i = 0; i < NUM_IMAGE; i++)
{
  VDP_drawImageEx(APLAN, images[i], TILE_ATTR_FULL(pal, FALSE, FALSE, FALSE, ind), 22, 5, TRUE, TRUE);
  ind +=  images[i]->tileset->numTile;
  pal ^= 1;
}


Problems you are talking about now is more C related programming issues that megadrive programming itself.
Haha so my drawImageEx technique is frowned upon for animation? :) I just want to get something up and running and then I'll switch to using the scrolling pane buffer method using a similar loop :D

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

Post by Stef » Fri Feb 21, 2014 4:47 pm

oh i again forgot something, indeed the scrolling stuff is missing...
Here is the complete code :

Code: Select all

pal = PAL0;
ypos = 0;
for(i = 0; i < NUM_IMAGE; i++)
{
  u16 nextypos =  ypos ^ 0x20;
  VDP_setVerticalScroll(APLAN, vpos);
  VDP_drawImageEx(APLAN, images[i], TILE_ATTR_FULL(pal, FALSE, FALSE, FALSE, ind), 22, vpos + 5, TRUE, TRUE);
  ind +=  images[i]->tileset->numTile;
  pal ^= 1;
  ypos = nextypos;
}
I used vertical scroll but the idea is the same.

matteus
Very interested
Posts: 336
Joined: Mon Feb 04, 2008 1:41 pm

Post by matteus » Fri Feb 21, 2014 4:58 pm

Stef wrote:oh i again forgot something, indeed the scrolling stuff is missing...
Here is the complete code :

Code: Select all

pal = PAL0;
ypos = 0;
for(i = 0; i < NUM_IMAGE; i++)
{
  u16 nextypos =  ypos ^ 0x20;
  VDP_setVerticalScroll(APLAN, vpos);
  VDP_drawImageEx(APLAN, images[i], TILE_ATTR_FULL(pal, FALSE, FALSE, FALSE, ind), 22, vpos + 5, TRUE, TRUE);
  ind +=  images[i]->tileset->numTile;
  pal ^= 1;
  ypos = nextypos;
}
I used vertical scroll but the idea is the same.
ha-ha oh wow thank you! :D You do know once I've figured out how to do all this I'll be moving onto learning about sprites ;)

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

Post by Chilly Willy » Fri Feb 21, 2014 5:55 pm

matteus wrote:
matteus wrote:I'm getting an new error when processing the pngs:

"1 bpp PNG not supported"
So by optimising my PNGS to be less than 16 colours have I shot myself in the foot?
Pretty much. Since 16 color is the only pixel mode on the MD, it's the only format supported. :lol:

matteus
Very interested
Posts: 336
Joined: Mon Feb 04, 2008 1:41 pm

Post by matteus » Fri Feb 21, 2014 9:00 pm

Video update https://www.youtube.com/watch?v=tDjrtof ... ata_player

Updated with code :)

I've got nasty background flicker I'm guessing its to do with the palette changing every frame and the background colour being wired into it?

Any suggestions?

matteus
Very interested
Posts: 336
Joined: Mon Feb 04, 2008 1:41 pm

Post by matteus » Sun Feb 23, 2014 6:38 pm

So everything goes fine until I hit frame 36. I repeated frame 36 to see it had a problem but found none. Is it possible I'm running out of VRAM or something? and if so how'd I clear the vram out during the loop to have it successfully work?

Code: Select all

#include <genesis.h>

#include "gfx.h"
#include "music.h"

int main()
{

   // initialization
    VDP_setScreenWidth320();

    const Image *images[46] = {
      &frame1,
      &frame2,
      &frame3,
      &frame4,
      &frame5,
      &frame6,
      &frame7,
      &frame8,
      &frame9,
      &frame10,
      &frame11,
      &frame12,
      &frame13,
      &frame14,
      &frame15,
      &frame16,
      &frame17,
      &frame18,
      &frame19,
      &frame20,
      &frame21,
      &frame22,
      &frame23,
      &frame24,
      &frame25,
      &frame26,
      &frame27,
      &frame28,
      &frame29,
      &frame30,
      &frame31,
      &frame32,
      &frame33,
      &frame34,
      &frame35,
      &frame36,
      &frame36,
      &frame36,
      &frame36,
      &frame36,
      &frame36,
      &frame36,
      &frame36,
      &frame36,
      &frame36,
      &frame36,
    };

    u16 ind;

    // music
    //SND_startPlay_PCM(thundercats_music, sizeof(thundercats_music), SOUND_RATE_32000, SOUND_PAN_CENTER, FALSE);

    u16 i = 0;

    u16 pal = PAL0;
    u16 ypos = 0;
    u16 vpos = 0;

    ind += images[0]->tileset->numTile;

    VDP_setBackgroundColor(0);

    for(i = 0; i < 46; i++)
    {

        u16 nextypos =  ypos ^ 0x20;
        VDP_setVerticalScroll(APLAN, vpos);
        VDP_drawImageEx(APLAN, images[i], TILE_ATTR_FULL(pal, FALSE, FALSE, FALSE, ind), 6, vpos + 4, TRUE, TRUE);
        ind += images[i]->tileset->numTile;
        pal ^= 1;
        ypos = nextypos;
        waitTick(50);

    }

    while(1)
    {
            VDP_waitVSync();
    }
    return 0;
}

matteus
Very interested
Posts: 336
Joined: Mon Feb 04, 2008 1:41 pm

Post by matteus » Mon Feb 24, 2014 12:32 am

Code: Select all

            if ((ind + images[i]->tileset->numTile) > 1310) {
                ind = images[i]->tileset->numTile;
            } else {
                ind += images[i]->tileset->numTile;
            }
makeshift fix for now lol :)

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

Post by Stef » Mon Feb 24, 2014 8:57 am

Exactly ! you were just running out of VRAM.
A nasty fix is just to roll over VRAM, when you rise the memory limit just restart to TILE_USERINDEX (more or less what you did).

Post Reply