Пример #1
0
void sd_move_save(sd_writer *writer, sd_move *move) {
    // Save animation
    sd_animation_save(writer, move->animation);

    // Save move footer
    sd_write_buf(writer, move->unknown, 21);
    sd_write_buf(writer, move->move_string, 21);
    if (move->footer_string) {
        uint16_t fs_size = strlen(move->footer_string);
        sd_write_uword(writer, fs_size+1);
        sd_write_buf(writer, move->footer_string, fs_size+1);
    } else {
        sd_write_uword(writer, 0); // no footer string, thus a length of 0
    }
}
Пример #2
0
int sd_sounds_save(const sd_sound_file *sf, const char* filename) {
    if(sf == NULL || filename == NULL) {
        return SD_INVALID_INPUT;
    }

    sd_writer *w = sd_writer_open(filename);
    if(!w) {
        return SD_FILE_OPEN_ERROR;
    }

    // Write header. Zero start + data block start.
    size_t s_offset = 4 * SD_SOUNDS_MAX + 4;
    sd_write_udword(w, 0);

    // First pass -- write offsets
    size_t ptr = 0;
    for(int i = 0; i < SD_SOUNDS_MAX; i++) {
        sd_write_udword(w, ptr + s_offset);
        ptr += sf->sounds[i].len;
    }

    // Second pass -- Write sounds
    for(int i = 0; i < SD_SOUNDS_MAX; i++) {
        sd_write_uword(w, sf->sounds[i].len);
        if(sf->sounds[i].len > 0) {
            sd_write_ubyte(w, sf->sounds[i].unknown);
            sd_write_buf(w, sf->sounds[i].data, sf->sounds[i].len);
        }
    }

    sd_writer_close(w);
    return SD_SUCCESS;
}
Пример #3
0
int sd_sound_to_au(const sd_sound_file *sf, int num, const char *filename) {
    if(sf == NULL || filename == NULL || num < 0 || num >= 299) {
        return SD_INVALID_INPUT;
    }

    sd_writer *w = sd_writer_open(filename);
    if(!w) {
        return SD_FILE_OPEN_ERROR;
    }

    // Write AU header
    sd_write_udword(w, 0x2e736e64); // Magic number (".snd")
    sd_write_udword(w, 32); // Data start
    sd_write_udword(w, 0xffffffff); // Data size
    sd_write_udword(w, 2); // Type (8bit signed pcm), needs conversion from our unsigned
    sd_write_udword(w, 8000); // Freq
    sd_write_udword(w, 1); // Channels

    // Annotation field (terminate with 0)
    sd_write_buf(w, "omf2097", 7);
    sd_write_ubyte(w, 0);

    // Write data
    int8_t sample = 0;
    for(int i = 0; i < sf->sounds[num].len; i++) {
        sample = sf->sounds[num].data[i] - 128;
        sd_write_byte(w, sample);
    }

    // All done!
    sd_writer_close(w);
    return SD_SUCCESS;
}
Пример #4
0
void sd_animation_save(sd_writer *writer, sd_animation *ani) {
    // Animation header
    sd_write_word(writer, ani->start_x);
    sd_write_word(writer, ani->start_y);
    sd_write_buf(writer, ani->unknown_a, 4);
    sd_write_uword(writer, ani->col_coord_count);
    sd_write_ubyte(writer, ani->frame_count);
    
    // collision table
    uint32_t tmp;
    for(int i = 0; i < ani->col_coord_count; i++) {
        tmp = (ani->col_coord_table[i].y_ext & 0x3f);
        tmp = tmp << 10;
        tmp = (tmp | (ani->col_coord_table[i].y & 0x3ff));
        tmp = tmp << 6;
        tmp = (tmp | (ani->col_coord_table[i].x_ext & 0x3f));
        tmp = tmp << 10;
        tmp = (tmp | (ani->col_coord_table[i].x & 0x3ff));
        sd_write_udword(writer, tmp);
    }

    // Animation string header
    uint16_t a_size = strlen(ani->anim_string);
    sd_write_uword(writer, a_size);
    sd_write_buf(writer, ani->anim_string, a_size);
    sd_write_ubyte(writer, 0);

    // Extra animation strings
    uint16_t s_size = 0;
    sd_write_ubyte(writer, ani->extra_string_count);
    for(int i = 0; i < ani->extra_string_count; i++) {
        s_size = strlen(ani->extra_strings[i]);
        sd_write_uword(writer, s_size);
        sd_write_buf(writer, ani->extra_strings[i], s_size);
        sd_write_ubyte(writer, 0);
    }

    // Sprites
    for(int i = 0; i < ani->frame_count; i++) {
        sd_sprite_save(writer, ani->sprites[i]);
    }
}
Пример #5
0
int sd_sprite_save(sd_writer *w, const sd_sprite *sprite) {
    if(w == NULL || sprite == NULL) {
        return SD_INVALID_INPUT;
    }
    sd_write_uword(w, sprite->len);
    sd_write_word(w, sprite->pos_x);
    sd_write_word(w, sprite->pos_y);
    sd_write_uword(w, sprite->width);
    sd_write_uword(w, sprite->height);
    sd_write_ubyte(w, sprite->index);
    sd_write_ubyte(w, sprite->missing);
    if(!sprite->missing) {
        sd_write_buf(w, sprite->data, sprite->len);
    }
    return SD_SUCCESS;
}
Пример #6
0
int sd_af_save(const sd_af_file *af, const char* filename) {
    int ret;
    sd_writer *w;

    if(!(w = sd_writer_open(filename))) {
        return SD_FILE_OPEN_ERROR;
    }

    // Header
    sd_write_uword(w, af->file_id);
    sd_write_uword(w, af->exec_window);
    sd_write_udword(w, (int)(af->endurance * 256));
    sd_write_ubyte(w, af->unknown_b);
    sd_write_uword(w, af->health);
    sd_write_dword(w, (int)(af->forward_speed * 256));
    sd_write_dword(w, (int)(af->reverse_speed * 256));
    sd_write_dword(w, (int)(af->jump_speed * 256));
    sd_write_dword(w, (int)(af->fall_speed * 256));
    sd_write_ubyte(w, af->unknown_c);
    sd_write_ubyte(w, af->unknown_d);

    // Write animations
    for(uint8_t i = 0; i < MAX_AF_MOVES; i++) {
        if(af->moves[i] != NULL) {
            sd_write_ubyte(w, i);
            if((ret = sd_move_save(w, af->moves[i])) != SD_SUCCESS) {
                sd_writer_close(w);
                return ret;
            }
        }
    }

    // This marks the end of animations
    sd_write_ubyte(w, 250); 

    // Soundtable
    sd_write_buf(w, af->soundtable, 30);

    // All done!
    sd_writer_close(w);
    return SD_SUCCESS;
}
Пример #7
0
int sd_tournament_save(const sd_tournament_file *trn, const char *filename) {
    if(trn == NULL || filename == NULL) {
        return SD_INVALID_INPUT;
    }

    sd_writer *w = sd_writer_open(filename);
    if(!w) {
        return SD_FILE_OPEN_ERROR;
    }

    // Header
    sd_write_dword(w, trn->enemy_count);
    sd_write_dword(w, 0); // Write this later!
    sd_write_buf(w, trn->bk_name, 14);
    sd_write_float(w, trn->winnings_multiplier);
    sd_write_dword(w, trn->unknown_a);
    sd_write_dword(w, trn->registration_fee);
    sd_write_dword(w, trn->assumed_initial_value);
    sd_write_dword(w, trn->tournament_id);

    // Write null until offset 300
    // Nothing of consequence here.
    sd_write_fill(w, 0, 300 - sd_writer_pos(w));

    // Write first offset
    sd_write_udword(w, 1100);

    // Write null until offset 1100
    // Nothing of consequence here.
    sd_write_fill(w, 0, 1100 - sd_writer_pos(w));

    // Walk through the enemies list, and write
    // offsets and blocks as we go
    for(int i = 0; i < trn->enemy_count; i++) {
        // Save pilot
        sd_pilot_save(w, trn->enemies[i]);

        // Update catalog
        long c_pos = sd_writer_pos(w);
        if (c_pos< 0) {
            goto error;
        }
        if (sd_writer_seek_start(w, 300 + (i+1) * 4) < 0) {
            goto error;
        }
        sd_write_udword(w, (uint32_t)c_pos);
        if (sd_writer_seek_start(w, (uint32_t)c_pos) < 0) {
            goto error;
        }
    }

    // Write logos
    for(int i = 0; i < MAX_TRN_LOCALES; i++) {
        if(trn->locales[i] != NULL) {
            sd_sprite_save(w, trn->locales[i]->logo);
        } else {
            sd_sprite s;
            sd_sprite_create(&s);
            sd_sprite_save(w, &s);
            sd_sprite_free(&s);
        }
    }

    // Save 40 colors
    sd_palette_save_range(w, &trn->pal, 128, 40);

    // Pic filename
    sd_write_variable_str(w, trn->pic_file);

    // Write tournament descriptions
    for(int i = 0; i < MAX_TRN_LOCALES; i++) {
        if(trn->locales[i] != NULL) {
            sd_write_variable_str(w, trn->locales[i]->title);
            sd_write_variable_str(w, trn->locales[i]->description);
        } else {
            sd_write_variable_str(w, "");
            sd_write_variable_str(w, "");
        }
    }

    // Let's write our current offset to the victory text offset position
    long offset = sd_writer_pos(w);
    if (offset < 0) {
        goto error;
    }
    if (sd_writer_seek_start(w, 4) < 0) {
        goto error;
    }
    sd_write_dword(w, (uint32_t)offset);
    if (sd_writer_seek_start(w, offset) < 0) {
        goto error;
    }

    // Write texts
    for(int i = 0; i < MAX_TRN_LOCALES; i++) {
        for(int har = 0; har < 11; har++) {
            for(int page = 0; page < 10; page++) {
                if(trn->locales[i] != NULL) {
                    sd_write_variable_str(w, trn->locales[i]->end_texts[har][page]);
                } else {
                    sd_write_variable_str(w, "");
                }
            }
        }
    }

    if (sd_writer_errno(w)) {
        goto error;
    }

    // All done. Flush and close.
    sd_writer_close(w);
    return SD_SUCCESS;

error:
    unlink(filename);
    sd_writer_close(w);
    return SD_FILE_WRITE_ERROR;
}
Пример #8
0
int sd_bk_save(const sd_bk_file *bk, const char* filename) {
    long rpos = 0;
    long opos = 0;
    sd_writer *w;
    int ret;

    if(!(w = sd_writer_open(filename))) {
        return SD_FILE_OPEN_ERROR;
    }

    // Write header
    sd_write_udword(w, bk->file_id);
    sd_write_ubyte(w, bk->unknown_a);

    // Write background size. In practice, this is always 320x200.
    // Still, let's take it srsly.
    if(bk->background != NULL) {
        sd_write_uword(w, bk->background->w);
        sd_write_uword(w, bk->background->h);
    } else {
        sd_write_uword(w, 320);
        sd_write_uword(w, 200);
    }

    // Write animations
    for(uint8_t i = 0; i < MAX_BK_ANIMS; i++) {
        if(bk->anims[i] != NULL) {
            opos = sd_writer_pos(w); // remember where we need to fill in the blank
            if (opos < 0) {
                goto error;
            }
            sd_write_udword(w, 0); // write a 0 as a placeholder
            sd_write_ubyte(w, i);
            if((ret = sd_bk_anim_save(w, bk->anims[i])) != SD_SUCCESS) {
                sd_writer_close(w);
                return ret;
            }
            rpos = sd_writer_pos(w);
            if (rpos < 0) {
                goto error;
            }
            if (sd_writer_seek_start(w, opos) < 0) {
                goto error;
            }
            sd_write_udword(w, rpos); // write the actual size
            if (sd_writer_seek_start(w, rpos) < 0) {
                goto error;
            }
        }
    }
    sd_write_udword(w, rpos);
    sd_write_ubyte(w, MAX_BK_ANIMS+1); // indicate end of animations

    // Write background image. If none exists, write black image.
    if(bk->background != NULL) {
        sd_write_buf(w, bk->background->data, bk->background->len);
    } else {
        sd_write_fill(w, 0, 64000);
    }

    // Write palettes
    sd_write_ubyte(w, bk->palette_count);
    for(uint8_t i = 0; i < bk->palette_count; i++) {
        sd_palette_save(w, bk->palettes[i]);
    }

    // Write soundtable
    sd_write_buf(w, bk->soundtable, 30);

    if (sd_writer_errno(w)) {
        goto error;
    }

    // All done, close writer
    sd_writer_close(w);
    return SD_SUCCESS;

error:
    unlink(filename);
    sd_writer_close(w);
    return SD_FILE_WRITE_ERROR;
}