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_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; }