void scene_free(scene *scene) { if(!scene) return; // Deinit scene if(scene->deinit != NULL) { scene->deinit(scene); } // Release background texture_free(&scene->background); // Free players iterator it; animationplayer *tmp = 0; list_iter_begin(&scene->child_players, &it); while((tmp = iter_next(&it)) != NULL) { animationplayer_free(tmp); } list_iter_begin(&scene->root_players, &it); while((tmp = iter_next(&it)) != NULL) { animationplayer_free(tmp); } list_free(&scene->child_players); list_free(&scene->root_players); // Free animations animation *ani = 0; array_iter_begin(&scene->animations, &it); while((ani = iter_next(&it)) != 0) { animation_free(ani); free(ani); } array_free(&scene->animations); // XXX do NOT free hars/controllers here! // Free BK sd_bk_delete(scene->bk); }
void test_sd_bk_delete(void) { sd_bk_delete(bk_file); //CU_ASSERT_PTR_NULL(bk_file); }
int main(int argc, char **argv) { char buf[256]; char *ext; if (argc <= 1) { printf("Usage %s [-p palette] <filename>\n", argv[0]); return 1; } strncpy(buf, argv[argc-1], 255); buf[255] = '0'; basename(buf); ext = strrchr(buf, '.'); if (ext == NULL) { printf("cannot determine file extension for %s\n", buf); return 1; } if (strncmp(ext, ".AF", 3) == 0) { if (argc < 3 || strncmp(argv[1], "-p", 2)) { printf("AF files need a corresponding palette, please supply one with -p (eg ARENA0.BK)\n"); return 1; } sd_bk_file *bk_file; sd_af_file *file; printf("Loading AF file: %s\n", argv[argc-1]); file = sd_af_load(argv[argc-1]); if (file) { printf("File loaded.\n"); printf("Reading palette from %s\n", argv[2]); bk_file = sd_bk_load(argv[2]); if (bk_file) { printf("Palette loaded.\n"); for(int i = 0; i < 50; i++) { if (file->moves[i]) { print_sprites(i, &file->moves[i]->animation, bk_file->palettes[0]); } } printf("Destroying resources ...\n"); sd_bk_delete(bk_file); sd_af_delete(file); } else { printf("Unable to load palette from file.\n"); return 1; } } else { printf("Unable to load file!\n"); return 1; } return 0; } else if (strncmp(ext, ".BK", 3) == 0) { sd_bk_file *file; printf("Loading BK file: %s\n", argv[1]); file = sd_bk_load(argv[1]); if(file) { printf("File loaded.\n"); printf("ID: %d\n", file->file_id); for (int i = 0; i < file->num_palettes; i++) { printf("drawing background with pallete %d to background-%d.ppm\n", i, i); sprintf(buf, "background-%d.ppm", i); sd_rgba_image_to_ppm(sd_vga_image_decode(file->background, file->palettes[i], -1), buf); } for(int i = 0; i < 50; i++) { if (file->animations[i]) { print_sprites(i, file->animations[i], file->palettes[0]); } else { /*printf("skipping blank animation %d\n", i);*/ } } printf("Destroying resources ...\n"); sd_bk_delete(file); } else { printf("Unable to load file!\n"); } } else { printf("Unrecognized file extenion %s\n", ext); return 1; } printf("Exiting.\n"); 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_file *output = arg_file0("o", "output", "<file>", "Output .BK file"); struct arg_int *anim = arg_int0("a", "anim", "<animation_id>", "Select animation"); struct arg_lit *all_anims = arg_lit0("A", "all_anims", "All animations"); struct arg_int *sprite = arg_int0("s", "sprite", "<sprite_id>", "Select sprite (requires --anim)"); struct arg_lit *keylist = arg_lit0(NULL, "keylist", "Prints a list of valid fields for --key."); struct arg_str *key = arg_strn("k", "key", "<key>", 0, 2, "Select key"); struct arg_str *value = arg_str0(NULL, "value", "<value>", "Set value (requires --key)"); struct arg_lit *play = arg_lit0(NULL, "play", "Play animation or sprite (requires --anim)"); struct arg_int *scale = arg_int0(NULL, "scale", "<factor>", "Scales sprites (requires --play)"); struct arg_lit *parse = arg_lit0(NULL, "parse", "Parse value (requires --key)"); struct arg_end *end = arg_end(20); void* argtable[] = {help,vers,file,output,anim,all_anims,sprite,keylist,key,value,play,scale,parse,end}; const char* progname = "bktool"; // 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 file editor.\n"); printf("Source code is available at https://github.com/omf2097 under MIT license.\n"); printf("(C) 2013 Tuomas Virtanen\n"); goto exit_0; } // Argument dependencies if(anim->count == 0) { if(sprite->count > 0) { printf("--sprite requires --anim\n"); printf("Try '%s --help' for more information.\n", progname); goto exit_0; } if(play->count > 0) { printf("--play requires --anim\n"); printf("Try '%s --help' for more information.\n", progname); goto exit_0; } } if(key->count == 0) { if(value->count > 0) { printf("--value requires --key\n"); printf("Try '%s --help' for more information.\n", progname); goto exit_0; } } if(output->count == 0) { if(value->count > 0) { printf("--value requires --output\n"); printf("Try '%s --help' for more information.\n", progname); goto exit_0; } } if(play->count == 0) { if(scale->count > 0) { printf("--scale requires --play\n"); printf("Try '%s --help' for more information.\n", progname); 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; } // Init SDL SDL_Init(SDL_INIT_VIDEO); // 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; } // Scaling variable int _sc = 1; if(scale->count > 0) { _sc = scale->ival[0]; if(_sc > 4) _sc = 4; if(_sc < 1) _sc = 1; } // Handle args if(sprite->count > 0) { // Make sure sprite exists. if(!check_anim_sprite(bk, anim->ival[0], sprite->ival[0])) { goto exit_1; } sd_sprite *sp = bk->anims[anim->ival[0]]->animation->sprites[sprite->ival[0]]; // Handle arguments if(key->count > 0) { if(value->count > 0) { sprite_set_key(sp, key->sval, key->count, value->sval[0]); } else { sprite_get_key(sp, key->sval, key->count); } } else if(keylist->count > 0) { sprite_keylist(); } else if(play->count > 0) { sprite_play(bk, _sc, anim->ival[0], sprite->ival[0]); } else { sprite_info(sp, anim->ival[0], sprite->ival[0]); } } else if(anim->count > 0) { // Make sure the bkanim exists if(!check_anim(bk, anim->ival[0])) { goto exit_1; } sd_bk_anim *bka = bk->anims[anim->ival[0]]; sd_animation *ani = bka->animation; if(key->count > 0) { if(value->count > 0) { bkanim_set_key(bka, ani, key->sval, key->count, value->sval[0]); } else { bkanim_get_key(bka, ani, key->sval, key->count, parse->count); } } else if(keylist->count > 0) { bkanim_keylist(); } else if(play->count > 0) { anim_play(bk, _sc, anim->ival[0]); } else { bkanim_info(bka, ani, anim->ival[0]); } } else if(all_anims->count > 0) { sd_bk_anim *bka; sd_animation *ani; for(int i = 0; i < 50; i++) { if (bk->anims[i]) { bka = bk->anims[i]; ani = bka->animation; if(key->count > 0) { if(value->count > 0) { bkanim_set_key(bka, ani, key->sval, key->count, value->sval[0]); } else { printf("Animation %2u: ", i); bkanim_get_key(bka, ani, key->sval, key->count, parse->count); } } else { printf("\n"); bkanim_info(bka, ani, i); } } } } else { if(key->count > 0) { if(value->count > 0) { bk_set_key(bk, key->sval, key->count, value->sval[0]); } else { bk_get_key(bk, key->sval, key->count); } } else if(keylist->count > 0) { bk_keylist(); } else { bk_info(bk); } } // Write output file if(output->count > 0) { sd_bk_save(bk, output->filename[0]); } // Quit exit_1: sd_bk_delete(bk); SDL_Quit(); exit_0: arg_freetable(argtable, sizeof(argtable)/sizeof(argtable[0])); return 0; }
// 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; }