SDL_Surface* render_text(sd_font *font, const char *text, int area_w) { // Vars unsigned int rmask,gmask,bmask,amask; int char_w, char_h; int pix_w, pix_h; int slen; SDL_Surface *surface; SDL_Surface *tmp; SDL_Rect dst; sd_rgba_image *img = 0; // Required surface size slen = strlen(text); char_h = (slen * 8) / area_w + 1; pix_h = char_h * font->h; if(char_h == 1) { char_w = slen; pix_w = slen * 8; } else { char_w = area_w / 8; pix_w = area_w; } // Create an empty SDL surface rmask = 0x000000ff; gmask = 0x0000ff00; bmask = 0x00ff0000; amask = 0xff000000; if((surface = SDL_CreateRGBSurface(0, pix_w, pix_h, 32, rmask, gmask, bmask, amask)) == 0) { return 0; } if((tmp = SDL_CreateRGBSurface(0, 8, font->h, 32, rmask, gmask, bmask, amask)) == 0) { SDL_FreeSurface(surface); return 0; } // Render text dst.w = 8; dst.h = font->h; img = sd_rgba_image_create(8, font->h); for(int i = 0; i < slen; i++) { sd_font_decode(font, img, text[i] - 32, 64, 128, 64); memcpy(tmp->pixels, img->data, 4*8*font->h); dst.y = i / char_w * font->h; dst.x = i % char_w * 8; SDL_BlitSurface(tmp, 0, surface, &dst); } // All done. SDL_FreeSurface(tmp); sd_rgba_image_delete(img); return surface; }
int animation_create(animation *ani, sd_animation *sdani, sd_palette *pal, int overlay, char *soundtable) { ani->sdani = sdani; array_create(&ani->sprites); ani->soundtable = soundtable; // Load textures sd_rgba_image *img = 0; for(int i = 0; i < sdani->frame_count; i++) { img = sd_sprite_image_decode(sdani->sprites[i]->img, pal, overlay); texture *tex = malloc(sizeof(texture)); texture_create(tex, img->data, img->w, img->h); array_set(&ani->sprites, i, tex); sd_rgba_image_delete(img); } return 0; }
int font_load(font *font, const char* filename, unsigned int size) { sd_rgba_image *img; sd_font *sdfont; int pixsize; texture *tex; // Find vertical size switch(size) { case FONT_BIG: pixsize = 8; break; case FONT_SMALL: pixsize = 6; break; default: return 1; } // Open font file sdfont = sd_font_create(); if(sd_font_load(sdfont, filename, pixsize)) { sd_font_delete(sdfont); return 2; } // Load into textures img = sd_rgba_image_create(pixsize, pixsize); for(int i = 0; i < 224; i++) { tex = malloc(sizeof(texture)); sd_font_decode(sdfont, img, i, 0xFF, 0xFF, 0xFF); texture_create(tex); texture_init(tex, img->data, img->w, img->h); vector_append(&font->textures, &tex); } // Set font info vars font->w = pixsize; font->h = pixsize; font->size = size; // Free resources sd_rgba_image_delete(img); sd_font_delete(sdfont); return 0; }
// extract part of a sprite as a new sprite // we need this because the HAR portraits are one single sprite, unlike the player portraits // so we need to chunk them up into individual sprites and strip out the black background sd_rgba_image* sub_sprite(sd_sprite *sprite, sd_palette *pal, int x, int y, int w, int h) { sd_rgba_image *img = 0; sd_rgba_image *out = sd_rgba_image_create(w, h); img = sd_sprite_image_decode(sprite->img, pal, -1); for(int i = y; i < y+h; i++) { for(int j = x; j < x+w; j++) { int offset = (i*sprite->img->w*4)+(j*4); int local_offset = ((i-y)*w*4)+((j-x)*4); out->data[local_offset] = (char)img->data[offset]; out->data[local_offset+1] = (char)img->data[offset+1]; out->data[local_offset+2] = (char)img->data[offset+2]; if (!out->data[local_offset] && !out->data[local_offset+1] && !out->data[local_offset+2]) { // all three colors are black, set the pixel to be transparent! out->data[local_offset+3] = 0; } else { out->data[local_offset+3] = (char)img->data[offset+3]; } } } sd_rgba_image_delete(img); return out; }
int melee_init(scene *scene) { char bitmap[51*36*4]; memset(&bitmap, 255, 51*36*4); ticks = 0; pulsedir = 0; selection = 0; row_a = 0; column_a = 0; row_b = 0; column_b = 4; done_a = 0; done_b = 0; for(int i = 0; i < 10; i++) { players[i].sprite = scene->bk->anims[3]->animation->sprites[i]; DEBUG("found sprite %d x %d at %d, %d", players[i].sprite->img->w, players[i].sprite->img->h, players[i].sprite->pos_x, players[i].sprite->pos_y); players_big[i].sprite = scene->bk->anims[4]->animation->sprites[i]; int row = i / 5; int col = i % 5; sd_rgba_image * out = sub_sprite(scene->bk->anims[1]->animation->sprites[0], scene->bk->palettes[0], (62*col), (42*row), 51, 36); texture_create(&harportraits[i], out->data, 51, 36); sd_rgba_image_delete(out); } menu_background2_create(&feh, 90, 61); menu_background2_create(&bleh, 160, 43); texture_create(&select_hilight, bitmap, 51, 36); // set up the magic controller hooks if (scene->player1.ctrl->type == CTRL_TYPE_NETWORK) { controller_add_hook(scene->player2.ctrl, scene->player1.ctrl, scene->player1.ctrl->controller_hook); } if (scene->player2.ctrl->type == CTRL_TYPE_NETWORK) { controller_add_hook(scene->player1.ctrl, scene->player2.ctrl, scene->player2.ctrl->controller_hook); } const color bar_color = color_create(0, 190, 0, 255); const color bar_bg_color = color_create(80, 220, 80, 0); const color bar_border_color = color_create(0, 96, 0, 255); const color bar_top_left_border_color = color_create(0, 255, 0, 255); const color bar_bottom_right_border_color = color_create(0, 125, 0, 255); progressbar_create(&bar_power[0], 74, 12, 20*4, 8, bar_border_color, bar_border_color, bar_bg_color, bar_top_left_border_color, bar_bottom_right_border_color, bar_color, PROGRESSBAR_LEFT); progressbar_create(&bar_agility[0], 74, 30, 20*4, 8, bar_border_color, bar_border_color, bar_bg_color, bar_top_left_border_color, bar_bottom_right_border_color, bar_color, PROGRESSBAR_LEFT); progressbar_create(&bar_endurance[0], 74, 48, 20*4, 8, bar_border_color, bar_border_color, bar_bg_color, bar_top_left_border_color, bar_bottom_right_border_color, bar_color, PROGRESSBAR_LEFT); progressbar_create(&bar_power[1], 320-66-feh.w, 12, 20*4, 8, bar_border_color, bar_border_color, bar_bg_color, bar_top_left_border_color, bar_bottom_right_border_color, bar_color, PROGRESSBAR_LEFT); progressbar_create(&bar_agility[1], 320-66-feh.w, 30, 20*4, 8, bar_border_color, bar_border_color, bar_bg_color, bar_top_left_border_color, bar_bottom_right_border_color, bar_color, PROGRESSBAR_LEFT); progressbar_create(&bar_endurance[1], 320-66-feh.w, 48, 20*4, 8, bar_border_color, bar_border_color, bar_bg_color, bar_top_left_border_color, bar_bottom_right_border_color, bar_color, PROGRESSBAR_LEFT); for(int i = 0;i < 2;i++) { progressbar_set(&bar_power[i], 50); progressbar_set(&bar_agility[i], 50); progressbar_set(&bar_endurance[i], 50); } refresh_pilot_stats(); memset(&harplayer_a, 0, sizeof(harplayer_a)); memset(&harplayer_b, 0, sizeof(harplayer_b)); // All done return 0; }
void sprite_play(sd_bk_file *bk, int scale, int anim, int sprite) { if(!check_anim_sprite(bk, anim, sprite)) return; SDL_Surface *surface; SDL_Texture *texture; SDL_Texture *background; SDL_Texture *rendertarget; SDL_Rect rect; SDL_Rect dstrect; sd_sprite *s = bk->anims[anim]->animation->sprites[sprite]; SDL_Window *window = SDL_CreateWindow( "OMF2097 Remake", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 320 * scale, 200 * scale, SDL_WINDOW_SHOWN | SDL_WINDOW_OPENGL ); if (!window) { printf("Could not create window: %s\n", SDL_GetError()); return; } printf("Sprite Info: pos=(%d,%d) size=(%d,%d) len=%d\n", s->pos_x, s->pos_y, s->img->w, s->img->h, s->img->len); SDL_Renderer *renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED); uint32_t rmask, gmask, bmask, amask; rmask = 0x000000ff; gmask = 0x0000ff00; bmask = 0x00ff0000; amask = 0xff000000; sd_rgba_image *img = sd_vga_image_decode(bk->background, bk->palettes[0], -1); if(!(surface = SDL_CreateRGBSurfaceFrom((void*)img->data, img->w, img->h, 32, img->w*4, rmask, gmask, bmask, amask))) { printf("Could not create surface: %s\n", SDL_GetError()); return; } if ((background = SDL_CreateTextureFromSurface(renderer, surface)) == 0) { printf("Could not create texture: %s\n", SDL_GetError()); return; } if((rendertarget = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, 320, 200)) == 0) { printf("Could not create texture: %s\n", SDL_GetError()); return; } SDL_FreeSurface(surface); sd_rgba_image_delete(img); img = sd_sprite_image_decode(s->img, bk->palettes[0], -1); if(!(surface = SDL_CreateRGBSurfaceFrom((void*)img->data, img->w, img->h, 32, img->w*4, rmask, gmask, bmask, amask))) { printf("Could not create surface: %s\n", SDL_GetError()); return; } if ((texture = SDL_CreateTextureFromSurface(renderer, surface)) == 0) { printf("Could not create texture: %s\n", SDL_GetError()); return; } SDL_FreeSurface(surface); sd_rgba_image_delete(img); rect.x = s->pos_x; rect.y = s->pos_y; rect.w = s->img->w; rect.h = s->img->h; dstrect.x = 0; dstrect.y = 0; dstrect.w = 320 * scale; dstrect.h = 200 * scale; while(1) { SDL_Event e; if (SDL_PollEvent(&e)) { if (e.type == SDL_QUIT) { break; } else if (e.type == SDL_KEYUP) { int i = anim; int changed = 0; switch (e.key.keysym.sym) { case SDLK_RIGHT: sprite = (sprite+1) % bk->anims[anim]->animation->frame_count; printf("sprite is now %u\n", sprite); changed = 1; break; case SDLK_LEFT: sprite--; if (sprite < 0) { sprite = bk->anims[anim]->animation->frame_count - 1; } changed = 1; break; case SDLK_UP: i++; while (!check_anim(bk, i) && i < 50) { i++; } if (i == 50) { printf("no more animations\n"); } else { anim = i; printf("UP: animation is now %u\n", anim); sd_bk_anim *bka = bk->anims[anim]; sd_animation *ani = bka->animation; bkanim_info(bka, ani, anim); sprite = 0; } changed = 1; break; case SDLK_DOWN: i--; while (!check_anim(bk, i) && i >= 0) { i--; } if (i < 0) { printf("no previous animations\n"); } else { anim = i; printf("DOWN: animation is now %u\n", anim); sd_bk_anim *bka = bk->anims[anim]; sd_animation *ani = bka->animation; bkanim_info(bka, ani, anim); sprite = 0; } changed = 1; break; default: changed = 0; } if (changed) { s = bk->anims[anim]->animation->sprites[sprite]; img = sd_sprite_image_decode(s->img, bk->palettes[0], -1); int x = s->pos_x + bk->anims[anim]->animation->start_x; int y = s->pos_y + bk->anims[anim]->animation->start_y; printf("Sprite Info: pos=(%d,%d) size=(%d,%d) len=%d\n", x, y, s->img->w, s->img->h, s->img->len); if(!(surface = SDL_CreateRGBSurfaceFrom((void*)img->data, img->w, img->h, 32, img->w*4, rmask, gmask, bmask, amask))) { printf("Could not create surface: %s\n", SDL_GetError()); return; } if ((texture = SDL_CreateTextureFromSurface(renderer, surface)) == 0) { printf("Could not create texture: %s\n", SDL_GetError()); return; } SDL_FreeSurface(surface); rect.x = x; rect.y = y; rect.w = s->img->w; rect.h = s->img->h; } } } SDL_RenderClear(renderer); SDL_SetRenderTarget(renderer, rendertarget); SDL_RenderCopy(renderer, background, NULL, NULL); SDL_RenderCopy(renderer, texture, NULL, &rect); // render the collision data SDL_SetRenderDrawColor(renderer, 255, 0, 0, 255); for(int i = 0; i < bk->anims[anim]->animation->col_coord_count; i++) { int x = bk->anims[anim]->animation->col_coord_table[i].x; int y = bk->anims[anim]->animation->col_coord_table[i].y; int y_ext = bk->anims[anim]->animation->col_coord_table[i].y_ext; if (y_ext == sprite) { SDL_RenderDrawPoint(renderer, x, y); } } SDL_SetRenderTarget(renderer, NULL); SDL_RenderCopy(renderer, rendertarget, NULL, &dstrect); SDL_RenderPresent(renderer); SDL_Delay(10); // don't chew too much CPU } // Close and destroy the window SDL_DestroyWindow(window); // Clean up SDL_Quit(); }
// Loads BK file etc. int scene_load(scene *scene, unsigned int scene_id) { scene->bk = sd_bk_create(); scene->loop = 1; scene->local = NULL; int ret = 0; // Load BK switch(scene_id) { case SCENE_INTRO: ret = sd_bk_load(scene->bk, "resources/INTRO.BK"); break; case SCENE_MENU: ret = sd_bk_load(scene->bk, "resources/MAIN.BK"); break; case SCENE_ARENA0: ret = sd_bk_load(scene->bk, "resources/ARENA0.BK"); break; case SCENE_ARENA1: ret = sd_bk_load(scene->bk, "resources/ARENA1.BK"); break; case SCENE_ARENA2: ret = sd_bk_load(scene->bk, "resources/ARENA2.BK"); break; case SCENE_ARENA3: ret = sd_bk_load(scene->bk, "resources/ARENA3.BK"); break; case SCENE_ARENA4: ret = sd_bk_load(scene->bk, "resources/ARENA4.BK"); break; case SCENE_ARENA5: ret = sd_bk_load(scene->bk, "resources/ARENA5.BK"); break; case SCENE_NEWSROOM: ret = sd_bk_load(scene->bk, "resources/NEWSROOM.BK"); break; case SCENE_END: ret = sd_bk_load(scene->bk, "resources/END.BK"); break; case SCENE_END1: ret = sd_bk_load(scene->bk, "resources/END1.BK"); break; case SCENE_END2: ret = sd_bk_load(scene->bk, "resources/END2.BK"); break; case SCENE_CREDITS: ret = sd_bk_load(scene->bk, "resources/CREDITS.BK"); break; case SCENE_MECHLAB: ret = sd_bk_load(scene->bk, "resources/MECHLAB.BK"); break; case SCENE_MELEE: ret = sd_bk_load(scene->bk, "resources/MELEE.BK"); break; case SCENE_VS: ret = sd_bk_load(scene->bk, "resources/VS.BK"); break; case SCENE_NORTHAM: ret = sd_bk_load(scene->bk, "resources/NORTH_AM.BK"); break; case SCENE_KATUSHAI: ret = sd_bk_load(scene->bk, "resources/KATUSHAI.BK"); break; case SCENE_WAR: ret = sd_bk_load(scene->bk, "resources/WAR.BK"); break; case SCENE_WORLD: ret = sd_bk_load(scene->bk, "resources/WORLD.BK"); break; default: sd_bk_delete(scene->bk); PERROR("Unknown scene_id!"); return 1; } if(ret) { sd_bk_delete(scene->bk); PERROR("Unable to load BK file!"); return 1; } scene->this_id = scene_id; scene->next_id = scene_id; // optional callback scene->post_init = NULL; // Load specific stuff switch(scene_id) { case SCENE_INTRO: intro_load(scene); break; case SCENE_MENU: mainmenu_load(scene); break; case SCENE_CREDITS: credits_load(scene); break; case SCENE_MELEE: fixup_palette(scene->bk->palettes[0]); melee_load(scene); break; case SCENE_VS: fixup_palette(scene->bk->palettes[0]); vs_load(scene); break; case SCENE_MECHLAB: mechlab_load(scene); break; case SCENE_ARENA0: case SCENE_ARENA1: case SCENE_ARENA2: case SCENE_ARENA3: case SCENE_ARENA4: case SCENE_ARENA5: fixup_palette(scene->bk->palettes[0]); arena_load(scene); break; default: scene->render = NULL; scene->event = NULL; scene->init = NULL; scene->deinit = NULL; } // Init scene if(scene->init != NULL) { if(scene->init(scene)) { sd_bk_delete(scene->bk); return 1; } } // Convert background sd_rgba_image *bg = sd_vga_image_decode(scene->bk->background, scene->bk->palettes[0], -1); texture_create(&scene->background, bg->data, bg->w, bg->h); sd_rgba_image_delete(bg); // Players list list_create(&scene->child_players); list_create(&scene->root_players); // Handle animations animation *ani; sd_bk_anim *bka; array_create(&scene->animations); for(unsigned int i = 0; i < 50; i++) { bka = scene->bk->anims[i]; if(bka) { // Create animation + textures, etc. ani = malloc(sizeof(animation)); animation_create(ani, bka->animation, scene->bk->palettes[0], -1, scene->bk->soundtable); array_set(&scene->animations, i, ani); // Start playback on those animations, that have load_on_start flag as true // or if we are handling animation 25 of intro // TODO: Maybe make the exceptions a bit more generic or something ? // TODO check other probabilites here if(bka->load_on_start || bka->probability == 1 || (scene_id == SCENE_INTRO && i == 25)) { animationplayer player; player.x = ani->sdani->start_x; player.y = ani->sdani->start_y; animationplayer_create(&player, i, ani); player.userdata = scene; player.add_player = scene_add_ani_player; player.del_player = scene_set_ani_finished; list_append(&scene->root_players, &player, sizeof(animationplayer)); DEBUG("Create animation %d @ x,y = %d,%d", i, player.x, player.y); } } } // run post init, if defined if(scene->post_init != NULL) { DEBUG("running post init"); scene->post_init(scene); } // All done DEBUG("Scene %i loaded! Textures now using %d bytes of (v)ram!", scene_id, texturelist_get_bsize()); return 0; }
int main(int argc, char *argv[]) { // commandline argument parser options struct arg_lit *help = arg_lit0("h", "help", "print this help and exit"); struct arg_lit *vers = arg_lit0("v", "version", "print version information and exit"); struct arg_file *file = arg_file1("f", "file", "<file>", "Input .BK file"); struct arg_str *outdir = arg_str1("o", "outdir", "<str>", "Output directory"); struct arg_str *name = arg_str1("n", "name", "<str>", "Output name"); struct arg_end *end = arg_end(20); void* argtable[] = {help,vers,file,outdir,name,end}; const char* progname = "bkhtmlprinter"; // Make sure everything got allocated if(arg_nullcheck(argtable) != 0) { printf("%s: insufficient memory\n", progname); goto exit_0; } // Parse arguments int nerrors = arg_parse(argc, argv, argtable); // Handle help if(help->count > 0) { printf("Usage: %s", progname); arg_print_syntax(stdout, argtable, "\n"); printf("\nArguments:\n"); arg_print_glossary(stdout, argtable, "%-30s %s\n"); goto exit_0; } // Handle version if(vers->count > 0) { printf("%s v0.1\n", progname); printf("Command line One Must Fall 2097 .BK html printer.\n"); printf("Source code is available at https://github.com/omf2097 under MIT license.\n"); printf("(C) 2013 Tuomas Virtanen\n"); goto exit_0; } // Handle errors if(nerrors > 0) { arg_print_errors(stdout, end, progname); printf("Try '%s --help' for more information.\n", progname); goto exit_0; } // Load file sd_bk_file *bk = sd_bk_create(); int ret = sd_bk_load(bk, file->filename[0]); if(ret) { printf("Unable to load BK file! Make sure the file exists and is a valid BK file.\n"); goto exit_1; } // Some vars FILE *fp; char namebuf[256]; // Open output file FILE *f; sprintf(namebuf, "%s/%s.html", outdir->sval[0], name->sval[0]); f = fopen(namebuf, "w"); if(f == NULL) { printf("Error while opening file!"); goto exit_1; } // Write background sprintf(namebuf, "%s/%s_bg.png", outdir->sval[0], name->sval[0]); fp = fopen(namebuf, "wb"); if(f == NULL) { printf("Error while opening background file for writing!"); goto exit_1; } sd_rgba_image *bg = sd_vga_image_decode(bk->background, bk->palettes[0], 0); write_png(fp, bg->data, bg->w, bg->h); sd_rgba_image_delete(bg); fclose(fp); // Print header to file fprintf(f, "%s", header); fprintf(f, "<h1>%s</h1>", file->filename[0]); // Root fprintf(f, "<h2>General information</h2><table><tr><th>Key</th><th>Value</th></tr>"); fprintf(f, "<tr><td>File ID</td><td>%d</td></tr>", bk->file_id); fprintf(f, "</table>"); // Image fprintf(f, "<h2>Background</h2>"); sprintf(namebuf, "%s_bg.png", name->sval[0]); fprintf(f, "<img src=\"%s\" width=\"640\" height=\"400\" />", namebuf); // Palettes if(bk->num_palettes > 0) { fprintf(f, "<h2>Palettes</h2>"); for(int i = 0; i < bk->num_palettes; i++) { sd_palette *pal = bk->palettes[i]; fprintf(f, "<h3>Palette %d</h3>", i+1); fprintf(f, "<table>"); for(int y = 0; y < 16; y++) { fprintf(f, "<tr>"); for(int x = 0; x < 16; x++) { fprintf(f, "<td style=\"background-color: rgb(%d,%d,%d); text-align: middle; width: 30px; height: 30px; color: white;\">%d</td>", pal->data[y*16+x][0], pal->data[y*16+x][1], pal->data[y*16+x][2], y*16 + x); } fprintf(f, "</tr>"); } fprintf(f, "</table>"); } } // Animations fprintf(f, "<h2>Animations</h2><div id=\"animations\">"); for(int m = 0; m < 50; m++) { if(bk->anims[m]) { sd_bk_anim *bka = bk->anims[m]; sd_animation *ani = bka->animation; fprintf(f, "<h3>Animation %d</h3><div class=\"animation\">", m); fprintf(f, "<div class=\"iblock\"><h4>General information</h4>"); fprintf(f, "<table><tr><th>Key</th><th>Value</th></tr>"); fprintf(f, "<tr><td>Null</td><td>%d</td></tr>", bka->null); fprintf(f, "<tr><td>Chain if hit</td><td>%d</td></tr>", bka->chain_hit); fprintf(f, "<tr><td>Chain if not hit</td><td>%d</td></tr>", bka->chain_no_hit); fprintf(f, "<tr><td>Load on start</td><td>%d</td></tr>", bka->load_on_start); fprintf(f, "<tr><td>Probability</td><td>%d</td></tr>", bka->probability); fprintf(f, "<tr><td>Hazard damage</td><td>%d</td></tr>", bka->hazard_damage); fprintf(f, "<tr><td>Unknown</td><td>%s</td></tr>", bka->unknown_data); fprintf(f, "<tr><td>Start X</td><td>%d</td></tr>", ani->start_x); fprintf(f, "<tr><td>Start Y</td><td>%d</td></tr>", ani->start_y); fprintf(f, "<tr><td>Animation string</td><td>%s</td></tr>", ani->anim_string); fprintf(f, "</table></div>"); // Extra strings if(ani->extra_string_count) { fprintf(f, "<div class=\"iblock\"><h4>Extra strings</h4>"); fprintf(f, "<table><tr><th>#</th><th>String</th></tr>"); for(int e = 0; e < ani->extra_string_count; e++) { fprintf(f, "<tr><td>%d</td><td>%s</td></tr>", e, ani->extra_strings[e]); } fprintf(f, "</table></div>"); } // Coords if(ani->col_coord_count > 0) { fprintf(f, "<div class=\"iblock\"><h4>Collision coordinates</h4>"); fprintf(f, "<table><tr><th>X</th><th>Y</th><th>X-ext</th><th>Y-ext</th></tr>"); for(int c = 0; c < ani->col_coord_count; c++) { col_coord *coord = &ani->col_coord_table[c]; fprintf(f, "<tr><td>%d</td><td>%d</td><td>%d</td><td>%d</td></tr>", coord->x, coord->y, coord->x_ext, coord->y_ext); } fprintf(f, "</table></div>"); } // Frames fprintf(f, "<div class=\"iblock\"><h4>Frames</h4>"); fprintf(f, "<table><tr><th>#</th><th>X</th><th>Y</th><th>W</th><th>H</th><th>Index</th><th>Missing</th><th>Sprite</th></tr>"); for(int b = 0; b < ani->frame_count; b++) { sd_sprite *sprite = ani->sprites[b]; // Write sprite if(sprite->img->len > 0 && sprite->img->w > 0 && sprite->img->h > 0) { sprintf(namebuf, "%s/%s_sprite_%d_%d.png", outdir->sval[0], name->sval[0], m, b); fp = fopen(namebuf, "wb"); sd_rgba_image *img = sd_sprite_image_decode(sprite->img, bk->palettes[0], 0); write_png(fp, img->data, img->w, img->h); sd_rgba_image_delete(img); fclose(fp); sprintf(namebuf, "%s_sprite_%d_%d.png", name->sval[0], m, b); } else { namebuf[0] = 0; } // Print html fprintf(f, "<tr><td>%d</td><td>%d</td><td>%d</td><td>%d</td><td>%d</td><td>%d</td><td>%d</td><td><img src=\"%s\" /></td></tr>", b, sprite->pos_x, sprite->pos_y, sprite->img->w, sprite->img->h, sprite->index, sprite->missing, namebuf); } fprintf(f, "</table>"); fprintf(f, "</div></div>"); } } fprintf(f, "</div>"); // Sounds fprintf(f, "<h2>Sound table</h2><table><tr><th>Local ID</th><th>Sound ID</th></tr>"); for(int i = 0; i < 30; i++) { fprintf(f, "<tr><td>%d</td><td>%d</td></tr>", i, (int)bk->soundtable[i]); } fprintf(f, "</table>"); // Print footer to file fprintf(f, "%s", footer); // Quit fclose(f); exit_1: sd_bk_delete(bk); exit_0: arg_freetable(argtable, sizeof(argtable)/sizeof(argtable[0])); return 0; }