Page 1 of 1

Draw image

Posted: Tue Sep 29, 2015 12:35 am
by orlanrod
I'm having an issue with what i think is corruption with a drawn image's palette. The player is rendered correctly, but when i draw the background it looks corrupt and not using its own palette. Here is the code bellow. I used the example sprite code.

// set all palette
VDP_setPalette(PAL0, bgb_image.palette->data);
VDP_setPalette(PAL2, jason_sprite.palette->data);


// load background

VDP_drawImage(VDP_PLAN_B, &bgb_image, 0, 0);


// init jason sprite
SPR_initSprite(&sprites[0], &jason_sprite, 4, 4, TILE_ATTR(PAL2, TRUE, FALSE, FALSE));
SPR_update(sprites, 1);

// prepare palettes
memcpy(&palette[0], bgb_image.palette->data, 16 * 2);
memcpy(&palette[32], jason_sprite.palette->data, 16 * 2);

Re: Draw image

Posted: Tue Sep 29, 2015 9:02 am
by Stef
How many tiles you reserve for the sprite engine (SPR_init(..) call) ?
Also i don't understand what you are doing with the palette preparation after actually setting them ?

Re: Draw image

Posted: Tue Sep 29, 2015 11:38 am
by orlanrod
Stef wrote:How many tiles you reserve for the sprite engine (SPR_init(..) call) ?
Also i don't understand what you are doing with the palette preparation after actually setting them ?
It's set to 256, but now i set it to 0 and still nothing. The background image i am trying to draw is 1024x1024

Here is the full main code

#include <genesis.h>
#include <vdp.h>
#include <vdp_pal.h>
#include <gfx.h>

#define ANIM_STANDSIDES 0
#define ANIM_WALKSIDES 1
#define ANIM_SLEEPSIDES 3
#define ANIM_STANDDOWN 4
#define ANIM_WALKDOWN 5
#define ANIM_SLEEPDOWN 6
#define ANIM_STANDUP 7
#define ANIM_WALKUP 8

#define MIN_POSX FIX32(10)
#define MAX_POSX FIX32(400)
#define MIN_POSY FIX32(10)
#define MAX_POSY FIX32(400)



// forward
static void handleInput();
static void joyEvent(u16 joy, u16 changed, u16 state);

static void updateAnim();
static void updateCamera(fix32 x, fix32 y);

// sprites structure
Sprite sprites[2];

fix32 camx;
fix32 camy;
fix32 posx;
fix32 posy;
fix32 movx;
fix32 movy;
s16 xorder;
s16 yorder;
u16 current_anim;


u16 php = 99; //player hp
u16 psp = 0; //player special power.
char str[8];


int main()
{
u16 palette[64];
u16 ind;

// disable interrupt when accessing VDP
SYS_disableInts();
// initialization
VDP_setScreenWidth320();

// init sprites engine
SPR_init(0);

VDP_setPaletteColors(0, palette_black, 64);

// load background
ind = TILE_USERINDEX;
VDP_drawImageEx(BPLAN, &bgb_image, TILE_ATTR_FULL(PAL0, FALSE, FALSE, FALSE, ind), 0, 0, FALSE, TRUE);
ind += bgb_image.tileset->numTile;

// VDP process done, we can re enable interrupts
SYS_enableInts();

camx = -1;
camy = -1;
posx = 150;
posy = 100;
xorder = 0;
yorder = 0;
current_anim = 0;


// init jason sprite
SPR_initSprite(&sprites[0], &jason_sprite, posx, posy, TILE_ATTR(PAL2, TRUE, FALSE, FALSE));
SPR_update(sprites, 1);

// prepare palettes
memcpy(&palette[0], bgb_image.palette->data, 16 * 2);
memcpy(&palette[32], jason_sprite.palette->data, 16 * 2);

// fade in
VDP_fadeIn(0, (3 * 16) - 1, palette, 20, FALSE);

JOY_setEventHandler(joyEvent);

while(TRUE)
{
handleInput();

updateAnim();
updateCamera(camx, camy);


//VDP_drawText("Hello World!", 1, 1);

// update sprites (only one to update here)
SPR_update(sprites, 1);

VDP_waitVSync();
}

return 0;
}

static void updateCamera(fix32 x, fix32 y)
{
fix32 cx = x;
fix32 cy = y;
VDP_setHorizontalScroll(PLAN_B, cx);
VDP_setVerticalScroll(PLAN_B, cy);

u16 value = JOY_readJoypad(JOY_1);
if ((value & BUTTON_RIGHT) && camx > -352) camx -= 1;
if ((value & BUTTON_LEFT) && camx < -1) camx += 1;
if ((value & BUTTON_UP) && camy > -1) camy -= 1;
if ((value & BUTTON_DOWN) && camy < 256) camy += 1;

}

static void updateAnim()
{
if (current_anim == ANIM_WALKSIDES) SPR_setAnim(&sprites[0], ANIM_WALKSIDES);
if (current_anim == ANIM_WALKUP) SPR_setAnim(&sprites[0], ANIM_WALKUP);
if (current_anim == ANIM_WALKDOWN) SPR_setAnim(&sprites[0], ANIM_WALKDOWN);

if (yorder == 0 && xorder == -1) current_anim = ANIM_WALKSIDES;

if (yorder == 0 && xorder == +1) current_anim = ANIM_WALKSIDES;

if (yorder == -1 && xorder == 0) current_anim = ANIM_WALKUP;

if (yorder == +1 && xorder == 0) current_anim = ANIM_WALKDOWN;

if (yorder == 0 && xorder == 0)
{
if (current_anim == ANIM_WALKSIDES) SPR_setAnim(&sprites[0], ANIM_STANDSIDES);
if (current_anim == ANIM_WALKUP) SPR_setAnim(&sprites[0], ANIM_STANDUP);
if (current_anim == ANIM_WALKDOWN) SPR_setAnim(&sprites[0], ANIM_STANDDOWN);
}
}


static void handleInput()
{
u16 value = JOY_readJoypad(JOY_1);

if ((value & BUTTON_RIGHT) && posx < 300 && camx <= -352)
{
posx += 1;
SPR_setPosition(&sprites[0], posx, posy);
}

if ((value & BUTTON_RIGHT) && posx < 150)
{
posx += 1;
SPR_setPosition(&sprites[0], posx, posy);
}

if ((value & BUTTON_RIGHT))
{
SPR_setAttribut(&sprites[0], TILE_ATTR(PAL2,TRUE,FALSE,FALSE));
}

if ((value & BUTTON_LEFT) && posx > 5 && camx >= -1)
{
posx -= 1;
SPR_setPosition(&sprites[0], posx, posy);
}

if ((value & BUTTON_LEFT) && posx > 150)
{
posx -= 1;
SPR_setPosition(&sprites[0], posx, posy);
}

if ((value & BUTTON_LEFT))
{
SPR_setAttribut(&sprites[0], TILE_ATTR(PAL2,TRUE,FALSE,TRUE));
}

if (value & BUTTON_LEFT) xorder = -1;
else if (value & BUTTON_RIGHT) xorder = +1;
else xorder = 0;


if ((value & BUTTON_UP) && posy > 5 && camy >= -1)
{
posy -= 1;
SPR_setPosition(&sprites[0], posx, posy);
}

if ((value & BUTTON_DOWN) && posy < 240 && camy >= 256)
{
posy += 1;
SPR_setPosition(&sprites[0], posx, posy);
}

if (value & BUTTON_UP) yorder = -1;
else if (value & BUTTON_DOWN) yorder = +1;
else yorder = 0;
}

static void joyEvent(u16 joy, u16 changed, u16 state)
{
// START button state changed
if (changed & BUTTON_START)
{

}

}

Re: Draw image

Posted: Tue Sep 29, 2015 12:33 pm
by Stef
Your code is correct, i think the problem comes from your background image which excess the tile capacity in VRAM. The sprite engine will consume 256 tiles by default, leaving about 1200 for the background. If your 1024x1024 image consume more than 1200 different tiles then you're done :-/
Also now i am thinking about it, 1024x1024 is above the plan size (64x64 tiles = 512x512) so that might be your problem.
To handle large image like that you need to first upload the tiles to VRAM :

Code: Select all

ind_tileset = TILE_USERINDEX;
// load image tileset with DMA
VDP_loadTileSet(bgb_image.tileset, ind_tileset, TRUE);
Then load sub part of your image map in the background plan depending the current camera / scrolling position :

Code: Select all

VDP_setMapEx(BPLAN, bgb_image.map, TILE_ATTR_FULL(PAL0, FALSE, FALSE, FALSE, ind_tileset), PlanXPosInTile, PlanYPosInTile, MapXPosInTile, MapYPosInTile, MapWidthInTile, MapHeigthInTile);
Be careful with bgb_image.map, if the map is compressed then the VDP_setMapEx(..) method will unpack it each time so it's better to unpack it first if needed with :

Code: Select all

Map *map = unpackMap(bgb_image.map, NULL);
and use the map variable then :)

Re: Draw image

Posted: Wed Sep 30, 2015 8:42 am
by orlanrod
Stef wrote:Your code is correct, i think the problem comes from your background image which excess the tile capacity in VRAM. The sprite engine will consume 256 tiles by default, leaving about 1200 for the background. If your 1024x1024 image consume more than 1200 different tiles then you're done :-/
Also now i am thinking about it, 1024x1024 is above the plan size (64x64 tiles = 512x512) so that might be your problem.
To handle large image like that you need to first upload the tiles to VRAM :

Code: Select all

ind_tileset = TILE_USERINDEX;
// load image tileset with DMA
VDP_loadTileSet(bgb_image.tileset, ind_tileset, TRUE);
Then load sub part of your image map in the background plan depending the current camera / scrolling position :

Code: Select all

VDP_setMapEx(BPLAN, bgb_image.map, TILE_ATTR_FULL(PAL0, FALSE, FALSE, FALSE, ind_tileset), PlanXPosInTile, PlanYPosInTile, MapXPosInTile, MapYPosInTile, MapWidthInTile, MapHeigthInTile);
Be careful with bgb_image.map, if the map is compressed then the VDP_setMapEx(..) method will unpack it each time so it's better to unpack it first if needed with :

Code: Select all

Map *map = unpackMap(bgb_image.map, NULL);
and use the map variable then :)
Thanks, that works great. Performance! 8D

Re: Draw image

Posted: Wed Sep 30, 2015 1:20 pm
by Stef
Glad you got it to work :)

Re: Draw image

Posted: Wed Sep 30, 2015 6:58 pm
by orlanrod
Stef wrote:Glad you got it to work :)
How would i update the map already drawn? Like say, revealing the next tile column, while removing the back tile column if the player moves right. I'm trying to tie it to the player's movement, so it increments/decrements as the player walks.

Re: Draw image

Posted: Wed Sep 30, 2015 8:16 pm
by orlanrod
Nevermind, i got it working. Thanks.

Re: Draw image

Posted: Thu Oct 01, 2015 7:44 am
by Stef
I would say that you need to handle that part by software and correctly update part of map into the hardware tilemap, that is all up to the game engine and its implementation ;)

Re: Draw image

Posted: Mon Oct 05, 2015 4:32 am
by orlanrod
It seems the tilemap is not displaying 16+ a few pixels on top of the screen (using Gens emulator) I have the vdp set at 224 height.

int PlanXPosInTile = 0;
int PlanYPosInTile = -3;
int MapXPosInTile = 0;
int MapYPosInTile = 0;
int MapWidthInTile = 40;
int MapHeightInTile = 28;

indb = TILE_USERINDEX;
VDP_loadTileSet(bgb_image.tileset, indb, TRUE);
VDP_setMapEx(BPLAN, map, TILE_ATTR_FULL(PAL0, FALSE, FALSE, FALSE, indb), PlanXPosInTile, PlanYPosInTile, MapXPosInTile, MapYPosInTile, MapWidthInTile, MapHeightInTile);
indb += bgb_image.tileset->numTile;

Re: Draw image

Posted: Mon Oct 05, 2015 8:28 am
by Stef
Do you mean they have background color ? If yes that is just Gens display using the PAL vertical resolution (240) so in NTSC resolution (224) you always have top and bottom blank areas... Of course on a real TV that does not necessary display the same.

Re: Draw image

Posted: Mon Oct 05, 2015 3:27 pm
by orlanrod
Stef wrote:Do you mean they have background color ? If yes that is just Gens display using the PAL vertical resolution (240) so in NTSC resolution (224) you always have top and bottom blank areas... Of course on a real TV that does not necessary display the same.
Yeah, i am using NTSC.

I was thinking of changing the tilemap ypos to -1 but that causes corruption for some reason. It does not if i do +1, but the map is pushed further up the screen. Trying to push down the tilemap so it displays the remaining 16+ pixels.

Re: Draw image

Posted: Thu Sep 29, 2016 10:03 pm
by ronin68k
Hi! Talking about image.tileset->numTile, can i get image tileset from array?
For example, we have an array of BG images...
const void ImageArray[]=
{
&image0,
&image1,
&image2,
&image3
};


i can use ImageArray with VDP_drawImage and this will work fine.

But now, i should tell the program, what tileset to use.
ind += ImageArray.tileset->numTile just won't work, cuz tileset is not a structure thing.

Is there a way to solve this problem? So i won't have to write imageX.tileset->numTile for each image.
Thank you! :*

Re: Draw image

Posted: Thu Sep 29, 2016 10:17 pm
by Stef
I don't get it: if you have an array of BG iamges then you should declare the array that way:

Code: Select all

const [b]Image[/b] ImageArray[]=
{
&image0,
&image1,
&image2,
&image3
};
So you could use the normal tileset structure inside.

Re: Draw image

Posted: Thu Sep 29, 2016 11:08 pm
by ronin68k
Hi, Stef! Thanks for the reply. After some time, i got it to work.
I made 2 arrays, one for VDP_drawImage - const * Arr_images[]
and (thank you for advice) another one for tileset - const Image Arr_imageMaps[].
Somehow, rendering more than 1 picture causes glitches to second one... weird, but thanks anyway :)