/** This file handles scanning the images directory and loading images into memory. It also keeps track of named images' indexes. */ #include "Image.h" #define TAR_BLOCK_SIZE 512 #define TAR_NAME_SIZE 100 #define TAR_SIZE_SIZE 12 #define TAR_SIZE_OFFSET 124 SDL_Surface *title, *score_image; SDL_Surface *tom[13]; Image *images[256]; int image_count; int img_brick, img_rock, img_back, img_key, img_door, img_door2, img_key, img_smash, img_smash2, img_smash3, img_smash4; int img_water, img_spring, img_spring2, img_spider, img_spider2, img_health; int img_balloon[3], img_gem[3], img_bullet[4], img_slide_left[3], img_slide_right[3], img_slideback; int alphacount = 0; int alphas[256]; /** Store the image in an array or a named img buffer. */ void doLoadImage(char *filename, char *name) { int type = TYPE_WALL; int monster = -1; SDL_Surface *image; fprintf(stderr, "\tLoading %s [%s]...\n", filename, name); fflush(stderr); image = SDL_LoadBMP(filename); if(image == NULL) { fprintf(stderr, "Couldn't load %s: %s\n", filename, SDL_GetError()); fflush(stderr); return; } // set black as the transparent color key SDL_SetColorKey(image, SDL_SRCCOLORKEY, SDL_MapRGBA(image->format, 0x00, 0x00, 0x00, SDL_ALPHA_OPAQUE)); // save the image if(!strcmp(name, "abe")) { title = image; } else if(!strcmp(name, "fonts")) { initFonts(image); } else if(!strcmp(name, "score")) { score_image = image; } else if(!strcmp(name, "tom1")) { tom[0] = image; } else if(!strcmp(name, "tom2")) { tom[1] = image; } else if(!strcmp(name, "tom3")) { tom[2] = image; } else if(!strcmp(name, "tom4")) { tom[3] = image; } else if(!strcmp(name, "tom5")) { tom[4] = image; } else if(!strcmp(name, "tom6")) { tom[5] = image; } else if(!strcmp(name, "tom7")) { tom[6] = image; } else if(!strcmp(name, "tom8")) { tom[7] = image; } else if(!strcmp(name, "jump1")) { tom[8] = image; } else if(!strcmp(name, "jump2")) { tom[9] = image; } else if(!strcmp(name, "climb1")) { tom[10] = image; } else if(!strcmp(name, "climb2")) { tom[11] = image; } else if(!strcmp(name, "climb3")) { tom[12] = image; } else { // a primitive hashtable if(!strcmp(name, "brick2")) { img_brick = image_count; } else if(!strcmp(name, "rock")) { img_rock = image_count; } else if(!strcmp(name, "back3d")) { img_back = image_count; } else if(!strcmp(name, "door")) { img_door = image_count; type = TYPE_DOOR; } else if(!strcmp(name, "door2")) { img_door2 = image_count; type = TYPE_DOOR; } else if(!strcmp(name, "key")) { type = TYPE_OBJECT; img_key = image_count; } else if(!strcmp(name, "health")) { type = TYPE_OBJECT; img_health = image_count; } else if(!strcmp(name, "balloon")) { type = TYPE_OBJECT; img_balloon[0] = image_count; } else if(!strcmp(name, "balloon2")) { type = TYPE_OBJECT; img_balloon[1] = image_count; } else if(!strcmp(name, "balloon3")) { type = TYPE_OBJECT; img_balloon[2] = image_count; } else if(!strcmp(name, "bullet1")) { img_bullet[0] = image_count; monster = MONSTER_BULLET; } else if(!strcmp(name, "bullet2")) { img_bullet[1] = image_count; monster = MONSTER_BULLET; } else if(!strcmp(name, "bullet3")) { img_bullet[2] = image_count; monster = MONSTER_BULLET; } else if(!strcmp(name, "bullet4")) { img_bullet[3] = image_count; monster = MONSTER_BULLET; } else if(!strcmp(name, "gem")) { type = TYPE_OBJECT; img_gem[0] = image_count; } else if(!strcmp(name, "gem2")) { type = TYPE_OBJECT; img_gem[1] = image_count; } else if(!strcmp(name, "gem3")) { type = TYPE_OBJECT; img_gem[2] = image_count; } else if(!strcmp(name, "endgame")) { monster = MONSTER_END_GAME; } else if(!strcmp(name, "wave")) { type = TYPE_HARMFUL; alphas[alphacount++] = image_count; } else if(!strcmp(name, "water")) { img_water = image_count; type = TYPE_HARMFUL; alphas[alphacount++] = image_count; } else if(!strcmp(name, "ladder")) { type = TYPE_LADDER; } else if(!strcmp(name, "spring")) { type = TYPE_SPRING; img_spring = image_count; } else if(!strcmp(name, "spring2")) { type = TYPE_SPRING; img_spring2 = image_count; } else if(!strcmp(name, "crab1") || !strcmp(name, "crab2")) { monster = MONSTER_CRAB; } else if(!strcmp(name, "ghost") || !strcmp(name, "ghost2")) { monster = MONSTER_GHOST; alphas[alphacount++] = image_count; } else if(!strcmp(name, "smash")) { monster = MONSTER_SMASHER; img_smash = image_count; } else if(!strcmp(name, "smash2")) { img_smash2 = image_count; } else if(!strcmp(name, "smash3")) { monster = MONSTER_SMASHER2; img_smash3 = image_count; } else if(!strcmp(name, "smash4")) { img_smash4 = image_count; } else if(!strcmp(name, "demon") || !strcmp(name, "demon2")) { monster = MONSTER_DEMON; } else if(!strcmp(name, "platform")) { monster = MONSTER_PLATFORM; } else if(!strcmp(name, "platform2")) { monster = MONSTER_PLATFORM2; } else if(!strcmp(name, "spider")) { monster = MONSTER_SPIDER; img_spider = image_count; } else if(!strcmp(name, "spider2")) { img_spider2 = image_count; } else if(!strcmp(name, "bear1")) { monster = MONSTER_BEAR; } else if(!strcmp(name, "bear2")) { monster = MONSTER_BEAR; } else if(!strcmp(name, "bear3")) { monster = MONSTER_BEAR; } else if(!strcmp(name, "bear4")) { monster = MONSTER_BEAR; } else if(!strcmp(name, "bear5")) { monster = MONSTER_BEAR; } else if(!strcmp(name, "bear6")) { monster = MONSTER_BEAR; } else if(!strcmp(name, "cannon")) { monster = MONSTER_CANNON; } else if(!strcmp(name, "cannon2")) { monster = MONSTER_CANNON2; } else if(!strcmp(name, "torch1") || !strcmp(name, "torch2") || !strcmp(name, "torch3")) { monster = MONSTER_TORCH; } else if(!strcmp(name, "star1") || !strcmp(name, "star2") || !strcmp(name, "star3") || !strcmp(name, "star4")) { monster = MONSTER_STAR; } else if(!strcmp(name, "arrow1") || !strcmp(name, "arrow2")) { monster = MONSTER_ARROW; } else if(!strcmp(name, "fire1") || !strcmp(name, "fire2") || !strcmp(name, "fire3")) { monster = MONSTER_FIRE; } else if(!strcmp(name, "bat1") || !strcmp(name, "bat2")) { monster = MONSTER_BAT; } else if(!strcmp(name, "slide1")) { type = TYPE_SLIDE; img_slide_right[0] = image_count; } else if(!strcmp(name, "slide2")) { type = TYPE_SLIDE; img_slide_right[1] = image_count; } else if(!strcmp(name, "slide3")) { type = TYPE_SLIDE; img_slide_right[2] = image_count; } else if(!strcmp(name, "slide4")) { type = TYPE_SLIDE; img_slide_left[0] = image_count; } else if(!strcmp(name, "slide5")) { type = TYPE_SLIDE; img_slide_left[1] = image_count; } else if(!strcmp(name, "slide6")) { type = TYPE_SLIDE; img_slide_left[2] = image_count; } else if(!strcmp(name, "slideback")) { img_slideback = image_count; } else if(!strcmp(name, "crystal")) { type = TYPE_DECORATION; } // store the image if(!(images[image_count] = (Image *) malloc(sizeof(Image)))) { fprintf(stderr, "Out of memory."); fflush(stderr); exit(0); } images[image_count]->image = image; images[image_count]->name = strdup(name); images[image_count]->type = type; // create a monster if needed if(monster > -1) { addMonsterImage(monster, image_count); } images[image_count]->monster_index = monster; showLoadingProgress(); image_count++; } } int selectDirEntry(const struct dirent *d) { return (strstr(d->d_name, ".bmp") || strstr(d->d_name, ".BMP") ? 1 : 0); } char * getImageName(char *s) { char *r = strdup(s); *(r + strlen(r) - 4) = 0; return r; } /** Load every bmp file from the ./images directory. */ void loadImages() { loadImagesFromTar(); setAlphaBlends(); /* image_count = 0; fprintf(stderr, "Looking for images in %s \n", xstr(BASE_DIR) PATH_SEP IMAGES_DIR PATH_SEP); fflush(stderr); // it's important to always load the images in the same order. struct dirent **namelist; int n; n = scandir(xstr(BASE_DIR) PATH_SEP IMAGES_DIR PATH_SEP, &namelist, selectDirEntry, alphasort); if(n < 0) { fprintf(stderr, "Can't sort directory: %s\n", xstr(BASE_DIR) PATH_SEP IMAGES_DIR PATH_SEP); fflush(stderr); exit(0); } else { char *name; char path[PATH_SIZE]; while(n--) { name = getImageName(namelist[n]->d_name); sprintf(path, xstr(BASE_DIR) PATH_SEP IMAGES_DIR PATH_SEP "%s", namelist[n]->d_name); doLoadImage(path, name); free(name); free(namelist[n]); } free(namelist); } */ } /** Loading from the tar has several benefits: -only 1 file to deal with -keeps the order of images constant -allows me to append new images to the tar while the order of the existing ones doesn't change. */ void loadImagesFromTar() { char tmp_path[PATH_SIZE]; FILE *tmp = NULL, *fp; char path[PATH_SIZE]; char buff[TAR_BLOCK_SIZE]; // a tar block int end = 0; int i; int mode = 0; // 0-header, 1-file char name[TAR_NAME_SIZE + 1], size[TAR_SIZE_SIZE + 1]; long filesize = 0; int found; int blocks_read = 0; int block = 0; image_count = 0; mkshuae(); sprintf(tmp_path, "%s%s", getHomeUserAbe(), "tmp.bmp"); sprintf(path, xstr(BASE_DIR) PATH_SEP IMAGES_DIR PATH_SEP "images.tar"); fprintf(stderr, "Opening %s for reading.\n", path); fflush(stderr); fp = fopen(path, "rb"); if(!fp) { fprintf(stderr, "Can't open tar file.\n"); fflush(stderr); exit(-1); } while(1) { if(fread(buff, 1, TAR_BLOCK_SIZE, fp) < TAR_BLOCK_SIZE) break; // EOF or error if(!mode) { // are we at the end? found = 0; for(i = 0; i < TAR_BLOCK_SIZE; i++) { if(buff[i]) { found = 1; break; } } if(!found) { end++; // a tar file ends with 2 NULL blocks if(end >= 2) break; } else { // Get the name memcpy(name, buff, TAR_NAME_SIZE); // add a NUL if needed found = 0; for(i = 0; i < TAR_NAME_SIZE; i++) { if(!name[i]) { found = 1; break; } } if(!found) name[TAR_NAME_SIZE] = '\0'; // Remove the .tmp *(name + strlen(name) - 4) = 0; // Get the size memcpy(size, buff + TAR_SIZE_OFFSET, TAR_SIZE_SIZE); size[TAR_SIZE_SIZE] = '\0'; filesize = strtol(size, NULL, 8); blocks_read = filesize / TAR_BLOCK_SIZE + (filesize % TAR_BLOCK_SIZE ? 1 : 0); fprintf(stderr, "Found: >%s< size=>%ld< blocks=>%d<\n", name, filesize, blocks_read); fflush(stderr); mode = 1; // open a temp file to extract this image to if(!(tmp = fopen(tmp_path, "wb"))) { fprintf(stderr, "Cannot open temp file for writing: %s\n", tmp_path); fflush(stderr); exit(0); } } } else { blocks_read--; // write to temp file fwrite(buff, (!blocks_read ? filesize % TAR_BLOCK_SIZE : TAR_BLOCK_SIZE), 1, tmp); if(!blocks_read) { mode = 0; fclose(tmp); // load the image doLoadImage(tmp_path, name); } } block++; } fclose(fp); // remove the tmp file remove(tmp_path); } void setAlphaBlends() { int i; for(i = 0; i < alphacount; i++) { if(mainstruct.alphaBlend) { SDL_SetAlpha(images[alphas[i]]->image, SDL_RLEACCEL | SDL_SRCALPHA, 128); } else { SDL_SetAlpha(images[alphas[i]]->image, 0, 0); } } }