int sd_move_load(sd_reader *r, sd_move *move) { // Read animation move->animation = sd_animation_create(); sd_animation_load(r, move->animation); // Move footer sd_read_buf(r, move->unknown, 21); sd_read_buf(r, move->move_string, 21); int len = sd_read_uword(r); if (len > 0) { move->footer_string = (char*)malloc(len); sd_read_buf(r, move->footer_string, len); // ensure it has a terminating NULL assert(move->footer_string[len-1] == '\0'); } else { // no footer string move->footer_string = NULL; } // Return success if reader is still ok if(!sd_reader_ok(r)) { return SD_FILE_PARSE_ERROR; } return SD_SUCCESS; }
int sd_animation_load(sd_reader *r, sd_animation *ani) { // Animation header ani->start_x = sd_read_word(r); ani->start_y = sd_read_word(r); sd_read_buf(r, ani->unknown_a, 4); ani->col_coord_count = sd_read_uword(r); ani->frame_count = sd_read_ubyte(r); // Read collision point data ani->col_coord_table = (col_coord*)malloc(sizeof(col_coord)*ani->col_coord_count); uint32_t tmp; int32_t a,b; for(int i = 0; i < ani->col_coord_count; i++) { tmp = sd_read_udword(r); a = tmp & 0xffff; b = (tmp & 0xffff0000) >> 16; ani->col_coord_table[i].x = ((a & 0x3ff) << (6+16)) >> (6+16); ani->col_coord_table[i].x_ext = (a >> 10); ani->col_coord_table[i].y = ((b & 0x3ff) << (6+16)) >> (6+16); ani->col_coord_table[i].y_ext = (b >> 10); } // Animation string header uint16_t anim_string_len = sd_read_uword(r); ani->anim_string = (char*)malloc(anim_string_len + 1); sd_read_buf(r, ani->anim_string, anim_string_len + 1); if(ani->anim_string[anim_string_len] != 0) { return SD_FILE_PARSE_ERROR; } // Extra animation strings ani->extra_string_count = sd_read_ubyte(r); ani->extra_strings = (char**)malloc(sizeof(char*)*ani->extra_string_count); for(int i = 0; i < ani->extra_string_count; i++) { uint16_t size = sd_read_uword(r); ani->extra_strings[i] = malloc(size+1); sd_read_buf(r, ani->extra_strings[i], size+1); if(ani->extra_strings[i][size] != 0) { return SD_FILE_PARSE_ERROR; } } // Sprites ani->sprites = (sd_sprite**)malloc(sizeof(sd_sprite*) * ani->frame_count); for(int i = 0; i < ani->frame_count; i++) { // finally, the actual sprite! ani->sprites[i] = sd_sprite_create(); if(sd_sprite_load(r, ani->sprites[i])) { return SD_FILE_PARSE_ERROR; } } // Return success return SD_SUCCESS; }
int sd_af_load(sd_af_file *af, const char *filename) { int ret = SD_SUCCESS; uint8_t moveno = 0; sd_reader *r; // Initialize reader if(!(r = sd_reader_open(filename))) { return SD_FILE_OPEN_ERROR; } // Header af->file_id = sd_read_uword(r); af->exec_window = sd_read_uword(r); // Always 10 af->endurance = sd_read_udword(r) / 256.0f; af->unknown_b = sd_read_ubyte(r); // Always 1 or 2 af->health = sd_read_uword(r); af->forward_speed = sd_read_dword(r) / 256.0f; af->reverse_speed = sd_read_dword(r) / 256.0f; af->jump_speed = sd_read_dword(r) / 256.0f; af->fall_speed = sd_read_dword(r) / 256.0f; af->unknown_c = sd_read_ubyte(r); // Always 0x32 ? af->unknown_d = sd_read_ubyte(r); // Always 0x14 ? // Read animations while(1) { moveno = sd_read_ubyte(r); if(moveno >= MAX_AF_MOVES || !sd_reader_ok(r)) { break; } // Read move if((af->moves[moveno] = malloc(sizeof(sd_move))) == NULL) { ret = SD_OUT_OF_MEMORY; goto cleanup; } if((ret = sd_move_create(af->moves[moveno])) != SD_SUCCESS) { goto cleanup; } if((ret = sd_move_load(r, af->moves[moveno])) != SD_SUCCESS) { goto cleanup; } } // Read soundtable sd_read_buf(r, af->soundtable, 30); // Fix missing sprites sd_af_postprocess(af); cleanup: // Close & return sd_reader_close(r); return ret; }
int sd_sounds_load(sd_sound_file *sf, const char *filename) { if(sf == NULL || filename == NULL) { return SD_INVALID_INPUT; } sd_reader *r = sd_reader_open(filename); if(!r) { return SD_FILE_OPEN_ERROR; } // Read header uint32_t first_udword = sd_read_udword(r); if(first_udword != 0) { sd_reader_close(r); return SD_FILE_INVALID_TYPE; } uint32_t header_size = sd_read_udword(r); int data_block_count = header_size / 4 - 2; // Find block sizes for(int i = 0; i < data_block_count; i++) { sd_read_udword(r); } // Read blocks for(int i = 0; i <= data_block_count; i++) { sf->sounds[i].len = sd_read_uword(r); if(sf->sounds[i].len > 0) { sf->sounds[i].unknown = sd_read_ubyte(r); sf->sounds[i].data = malloc(sf->sounds[i].len); sd_read_buf(r, sf->sounds[i].data, sf->sounds[i].len); } } sd_reader_close(r); return SD_SUCCESS; }
int sd_sprite_load(sd_reader *r, sd_sprite *sprite) { sprite->len = sd_read_uword(r); sprite->pos_x = sd_read_word(r); sprite->pos_y = sd_read_word(r); sprite->width = sd_read_uword(r); sprite->height = sd_read_uword(r); sprite->index = sd_read_ubyte(r); sprite->missing = sd_read_ubyte(r); // Copy sprite data, if there is any. if(sprite->missing == 0) { if((sprite->data = malloc(sprite->len)) == NULL) { return SD_OUT_OF_MEMORY; } sd_read_buf(r, sprite->data, sprite->len); } else { sprite->data = NULL; } if(!sd_reader_ok(r)) { return SD_FILE_PARSE_ERROR; } return SD_SUCCESS; }
int sd_tournament_load(sd_tournament_file *trn, const char *filename) { int ret = SD_FILE_PARSE_ERROR; if(trn == NULL || filename == NULL) { return SD_INVALID_INPUT; } sd_reader *r = sd_reader_open(filename); if(!r) { return SD_FILE_OPEN_ERROR; } // Make sure that the file looks at least relatively okay // TODO: Add other checks. if(sd_reader_filesize(r) < 1582) { goto error_0; } // Read enemy count and make sure it seems somwhat correct int32_t enemy_count = sd_read_dword(r); if(enemy_count >= MAX_TRN_ENEMIES || enemy_count <= 0) { goto error_0; } trn->enemy_count = (int16_t)enemy_count; // Read tournament data int victory_text_offset = sd_read_dword(r); sd_read_buf(r, trn->bk_name, 14); trn->winnings_multiplier = sd_read_float(r); trn->unknown_a = sd_read_dword(r); trn->registration_fee = sd_read_dword(r); trn->assumed_initial_value = sd_read_dword(r); trn->tournament_id = sd_read_dword(r); // Read enemy block offsets sd_reader_set(r, 300); int offset_list[MAX_TRN_ENEMIES + 2]; // Should be large enough memset(offset_list, 0, sizeof(offset_list)); for(int i = 0; i < trn->enemy_count + 1; i++) { offset_list[i] = sd_read_dword(r); } // Read enemy data for(int i = 0; i < trn->enemy_count; i++) { trn->enemies[i] = malloc(sizeof(sd_pilot)); // Find data length sd_reader_set(r, offset_list[i]); // Read enemy pilot information sd_pilot_create(trn->enemies[i]); sd_pilot_load(r, trn->enemies[i]); // Check for errors if(!sd_reader_ok(r)) { goto error_1; } } // Seek sprite start offset sd_reader_set(r, offset_list[trn->enemy_count]); // Allocate locales for(int i = 0; i < MAX_TRN_LOCALES; i++) { trn->locales[i] = malloc(sizeof(sd_tournament_locale)); trn->locales[i]->logo = NULL; trn->locales[i]->description = NULL; trn->locales[i]->title = NULL; for(int har = 0; har < 11; har++) { for(int page = 0; page < 10; page++) { trn->locales[i]->end_texts[har][page] = NULL; } } } // Load logos to locales for(int i = 0; i < MAX_TRN_LOCALES; i++) { trn->locales[i]->logo = malloc(sizeof(sd_sprite)); sd_sprite_create(trn->locales[i]->logo); if((ret = sd_sprite_load(r, trn->locales[i]->logo)) != SD_SUCCESS) { goto error_2; } } // Read palette. Only 40 colors are defined, starting // from palette position 128. Remember to convert VGA pal. memset((void*)&trn->pal, 0, sizeof(sd_palette)); sd_palette_load_range(r, &trn->pal, 128, 40); // Read pic filename trn->pic_file = sd_read_variable_str(r); // Read tournament descriptions for(int i = 0; i < MAX_TRN_LOCALES; i++) { trn->locales[i]->title = sd_read_variable_str(r); trn->locales[i]->description = sd_read_variable_str(r); } // Make sure we are in correct position if(sd_reader_pos(r) != victory_text_offset) { goto error_2; } // Load texts for(int i = 0; i < MAX_TRN_LOCALES; i++) { for(int har = 0; har < 11; har++) { for(int page = 0; page < 10; page++) { trn->locales[i]->end_texts[har][page] = sd_read_variable_str(r); } } } // Close & return sd_reader_close(r); return SD_SUCCESS; error_2: free_locales(trn); error_1: free_enemies(trn); error_0: sd_reader_close(r); return ret; }
int sd_bk_load(sd_bk_file *bk, const char *filename) { uint16_t img_w, img_h; uint8_t animno = 0; sd_reader *r; int ret = SD_SUCCESS; // Initialize reader if(!(r = sd_reader_open(filename))) { return SD_FILE_OPEN_ERROR; } // Header bk->file_id = sd_read_udword(r); bk->unknown_a = sd_read_ubyte(r); img_w = sd_read_uword(r); img_h = sd_read_uword(r); // Read animations while(1) { sd_skip(r, 4); // offset of next animation animno = sd_read_ubyte(r); if(animno >= MAX_BK_ANIMS || !sd_reader_ok(r)) { break; } // Initialize animation if((bk->anims[animno] = malloc(sizeof(sd_bk_anim))) == NULL) { ret = SD_OUT_OF_MEMORY; goto exit_0; } if((ret = sd_bk_anim_create(bk->anims[animno])) != SD_SUCCESS) { goto exit_0; } if((ret = sd_bk_anim_load(r, bk->anims[animno])) != SD_SUCCESS) { goto exit_0; } } // Read background image if((bk->background = malloc(sizeof(sd_vga_image))) == NULL) { ret = SD_OUT_OF_MEMORY; goto exit_0; } if((ret = sd_vga_image_create(bk->background, img_w, img_h)) != SD_SUCCESS) { goto exit_0; } int bsize = img_w * img_h; sd_read_buf(r, bk->background->data, bsize); // Read palettes bk->palette_count = sd_read_ubyte(r); for(uint8_t i = 0; i < bk->palette_count; i++) { if((bk->palettes[i] = malloc(sizeof(sd_palette))) == NULL) { ret = SD_OUT_OF_MEMORY; goto exit_0; } if((ret = sd_palette_load(r, bk->palettes[i])) != SD_SUCCESS) { goto exit_0; } } // Read soundtable sd_read_buf(r, bk->soundtable, 30); // Fix missing sprites sd_bk_postprocess(bk); exit_0: sd_reader_close(r); return ret; }