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 } }
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; }
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; }
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]); } }
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; }
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; }
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; }
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; }