[PS2 SDL] Problema con el for solucionado ya cargo img, por favor sugerencias para mejorar el código

La semana del Black Friday en PcComponentes y Amazon
Carga imágenes BMP pasadas por bin2c las cuales son de 24 bits con 256 colores tenía problemas.

main.c
#include <SDL/SDL.h>
#include <SDL/SDL_image.h>
#include "logo.c"
#include "start.c"


#define W_IMG 640
#define H_IMG 480



SDL_Surface *screen;
int w=640;
int h=480;
int contador_rgb = 122;

void putpixel(SDL_Surface *surface, int x, int y, SDL_Color* color)
{    
   Uint32 pixel = SDL_MapRGBA (surface->format, color->b, color->g, color->r, color->unused);
    int bpp = surface->format->BytesPerPixel;
    /* Here p is the address to the pixel we want to set */
    Uint8 *p = (Uint8 *)surface->pixels + y * surface->pitch + x * bpp;
   
    switch(bpp) {
    case 1:
        *p = pixel;
        break;

    case 2:
        *(Uint16 *)p = pixel;
        break;

    case 3:
        if(SDL_BYTEORDER == SDL_BIG_ENDIAN) {
            p[0] = (pixel >> 16) & 0xff;
            p[1] = (pixel >> 8) & 0xff;
            p[2] = pixel & 0xff;
        } else {
            p[0] = pixel & 0xff;
            p[1] = (pixel >> 8) & 0xff;
            p[2] = (pixel >> 16) & 0xff;
        }
        break;

    case 4:
        *(Uint32 *)p = pixel;
        break;
    }
}

void put_linea(SDL_Surface* surface, int y)
{
   const int columnas = W_IMG;
   int j=0;
   
   SDL_Color* colorines = malloc(sizeof(SDL_Color*));
   for(j=0; j < columnas; j++)
   {
      colorines->r=start[contador_rgb++];
      colorines->g=start[contador_rgb++];
      colorines->b=start[contador_rgb++];
      colorines->unused = 0x00;
      
      putpixel(surface, j, y, colorines);
      
   }   
}

void put_image(SDL_Surface* surface)
{
   int filas =H_IMG - 1;
   SDL_LockSurface(surface);
   while(filas >= 0)
   {
      put_linea(surface, filas);
      filas--;
   }
   SDL_UnlockSurface(surface);
}

int main(int argc, char *argv[] )
{
   SDL_Init(SDL_INIT_VIDEO);
   screen=SDL_SetVideoMode(w,h,24,SDL_HWSURFACE);
   
   const SDL_VideoInfo *vi;
   vi = SDL_GetVideoInfo();
      
   //int req_format = STBI_rgb_alpha;
   Uint32 rmask, gmask, bmask, amask;
   int shift = 8;
   //int shift = (req_format == STBI_rgb) ? 8 : 0;
   //#if SDL_BYTEORDER == SDL_BIG_ENDIAN
   rmask = 0xff000000 >> shift;
   gmask = 0x00ff0000 >> shift;
   bmask = 0x0000ff00 >> shift;
   amask = 0x000000ff >> shift;
   /*#else // little endian, like x86
   rmask = 0x000000ff;
   gmask = 0x0000ff00;
   bmask = 0x00ff0000;
   amask = (req_format == STBI_rgb) ? 0 : 0xff000000;
   #endif*/

   SDL_Surface* img = SDL_CreateRGBSurface(SDL_SWSURFACE, W_IMG, H_IMG, vi->vfmt->BitsPerPixel,
                               rmask, gmask, bmask, amask);


   //SDL_FillRect (img, NULL, SDL_MapRGB(img->format, 255, 255, 255));
   

   put_image(img);



   SDL_Rect destino;
      destino.x = 0;
      destino.y = 0;
      destino.w = screen->w;
      destino.h = screen->h;
   SDL_BlitSurface(img, NULL, screen, &destino);
   //free memory allocated to the temp SDL_Surface
   SDL_FreeSurface(img);
   while(1){
      SDL_Flip(screen);
   }
   
   return 0;
}


Makefile
EE_BIN = ejecutable.elf
EE_BIN_PKD = EJECUTABLE.ELF
EE_OBJS = main.o
EE_LIBS = -L$(PS2SDK)/ports/lib -L$(GSKIT)/lib -lgskit -ldmakit -static -lSDL_image -lgskit_toolkit -ldraw -lgraph -lmath3d -lmf -lpacket -ldma -lSDL -lm
EE_INCS += -I$(PS2SDK)/ports/include -I$(GSKIT)/include -I$(GSKIT)/ee/dma/include -I$(GSKIT)/ee/gs/include -I$(GSKIT)/ee/toolkit/include

all: $(EE_BIN)
   $(EE_STRIP) --strip-all $(EE_BIN)
#   ps2-packer -v $(EE_BIN) $(EE_BIN_PKD) > /dev/null

clean:
   rm -f $(EE_BIN) $(EE_OBJS)

run: $(EE_BIN)
   ps2client execee host:$(EE_BIN)

reset:
   ps2client reset

include $(PS2SDK)/samples/Makefile.pref
include $(PS2SDK)/samples/Makefile.eeglobal
SDL tiene una librería adicional para trabajar con imágenes llamada SDL_image, que permite cargar un fichero PNG por ejemplo y te da la imagen en una surface para poder pintarla. En tu código lo estás haciendo a mano pixel a pixel de la imagen, pero aunque tengas la imagen en binario no es muy eficiente. Es mejor tratar con bloques.

Sobre el código, lo típico es hacer el pintado dentro del bucle while (lo que se llama un frame) cada vez, para que se refresque la pantalla. Con una imagen no pasa nada, pero si quieres mover algo por encima de esa imagen, como un personaje hay que repintar la pantalla en cada frame. Además en el while se puede poner un SDL_Delay de unos pocos microsegundos para que descanse la cpu entre frame y frame. Sino lo quemas :D, es decir se pone al 100%.

Un saludo
1 respuesta