Exemplo n.º 1
0
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;
}
Exemplo n.º 2
0
void print_sprites(int i, sd_animation *anim, sd_palette *palette) {
    char buf[256];
    printf("animation %d with %d frames\n", i, anim->frame_count);
    for(int j = 0; j < anim->frame_count; j++) {
        if (anim->sprites[j]->missing > 0) {
            printf("missing sprite: %d-%d\n", i, j);
            continue;
        }
        if (anim->sprites[j]->img->len == 0) {
            printf("warning, 0 length sprite: %d-%d\n", i, j);
            continue;
        }
        sprintf(buf, "sprite-%d-%d.ppm", i, j);
        /*printf("decoding sprite to %s\n", buf);*/
        sd_rgba_image_to_ppm(sd_sprite_image_decode(anim->sprites[j]->img, palette, -1), buf);
    }
}
Exemplo n.º 3
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;
}
Exemplo n.º 4
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();
}
Exemplo n.º 5
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;
}