diff --git a/extract-xiso.c b/extract-xiso.c index 91169dc..bc7a0ee 100644 --- a/extract-xiso.c +++ b/extract-xiso.c @@ -441,8 +441,9 @@ #endif -#define GLOBAL_LSEEK_OFFSET 0xFD90000ul -#define XGD3_LSEEK_OFFSET 0x2080000ul +#define GLOBAL_LSEEK_OFFSET 0x0FD90000ul +#define XGD3_LSEEK_OFFSET 0x02080000ul +#define XGD1_LSEEK_OFFSET 0x18300000ul #define n_sectors( size ) ( ( size ) / XISO_SECTOR_SIZE + ( ( size ) % XISO_SECTOR_SIZE ? 1 : 0 ) ) @@ -882,18 +883,24 @@ int verify_xiso( int in_xiso, int32_t *out_root_dir_sector, int32_t *out_root_di if ( ! err && read( in_xiso, buffer, XISO_HEADER_DATA_LENGTH ) != XISO_HEADER_DATA_LENGTH ) read_err(); if ( ! err && memcmp( buffer, XISO_HEADER_DATA, XISO_HEADER_DATA_LENGTH ) ) { - if ( lseek( in_xiso, (xoff_t) XISO_HEADER_OFFSET + GLOBAL_LSEEK_OFFSET, SEEK_SET ) == -1 ) seek_err(); - if ( ! err && read( in_xiso, buffer, XISO_HEADER_DATA_LENGTH ) != XISO_HEADER_DATA_LENGTH ) read_err(); - if ( ! err && memcmp( buffer, XISO_HEADER_DATA, XISO_HEADER_DATA_LENGTH ) ) { - - if ( lseek( in_xiso, (xoff_t) XISO_HEADER_OFFSET + XGD3_LSEEK_OFFSET, SEEK_SET ) == -1 ) seek_err(); - if ( ! err && read( in_xiso, buffer, XISO_HEADER_DATA_LENGTH ) != XISO_HEADER_DATA_LENGTH ) read_err(); - if ( ! err && memcmp( buffer, XISO_HEADER_DATA, XISO_HEADER_DATA_LENGTH ) ) misc_err( "%s does not appear to be a valid xbox iso image\n", in_iso_name, 0, 0 ) - else s_xbox_disc_lseek = XGD3_LSEEK_OFFSET; - } - else s_xbox_disc_lseek = GLOBAL_LSEEK_OFFSET; - } - else s_xbox_disc_lseek = 0; + if ( lseek( in_xiso, (xoff_t) XISO_HEADER_OFFSET + GLOBAL_LSEEK_OFFSET, SEEK_SET ) == -1 ) seek_err(); + if ( ! err && read( in_xiso, buffer, XISO_HEADER_DATA_LENGTH ) != XISO_HEADER_DATA_LENGTH ) read_err(); + if ( ! err && memcmp( buffer, XISO_HEADER_DATA, XISO_HEADER_DATA_LENGTH ) ) + { + if ( lseek( in_xiso, (xoff_t) XISO_HEADER_OFFSET + XGD3_LSEEK_OFFSET, SEEK_SET ) == -1 ) seek_err(); + if ( ! err && read( in_xiso, buffer, XISO_HEADER_DATA_LENGTH ) != XISO_HEADER_DATA_LENGTH ) read_err(); + if (!err && memcmp(buffer, XISO_HEADER_DATA, XISO_HEADER_DATA_LENGTH)) + { + if (lseek(in_xiso, (xoff_t)XISO_HEADER_OFFSET + XGD1_LSEEK_OFFSET, SEEK_SET) == -1) seek_err(); + if (!err && read(in_xiso, buffer, XISO_HEADER_DATA_LENGTH) != XISO_HEADER_DATA_LENGTH) read_err(); + if (!err && memcmp(buffer, XISO_HEADER_DATA, XISO_HEADER_DATA_LENGTH)) misc_err("%s does not appear to be a valid xbox iso image\n", in_iso_name, 0, 0) + else s_xbox_disc_lseek = XGD1_LSEEK_OFFSET; + } + else s_xbox_disc_lseek = XGD3_LSEEK_OFFSET; + } + else s_xbox_disc_lseek = GLOBAL_LSEEK_OFFSET; + } + else s_xbox_disc_lseek = 0; // read root directory information if ( ! err && read( in_xiso, out_root_dir_sector, XISO_SECTOR_OFFSET_SIZE ) != XISO_SECTOR_OFFSET_SIZE ) read_err(); @@ -1022,7 +1029,7 @@ int create_xiso( char *in_root_directory, char *in_output_directory, dir_node_av } if ( ! err ) { if ( in_root ) { - if ( lseek( in_xiso, (xoff_t) XISO_HEADER_OFFSET + XISO_HEADER_DATA_LENGTH + XISO_SECTOR_OFFSET_SIZE + XISO_DIRTABLE_SIZE, SEEK_SET ) == -1 ) seek_err(); + if ( lseek( in_xiso, (xoff_t) XISO_HEADER_OFFSET + XISO_HEADER_DATA_LENGTH + XISO_SECTOR_OFFSET_SIZE + XISO_DIRTABLE_SIZE + s_xbox_disc_lseek, SEEK_SET ) == -1 ) seek_err(); if ( ! err && read( in_xiso, buf, XISO_FILETIME_SIZE ) != XISO_FILETIME_SIZE ) read_err(); if ( ! err && write( xiso, buf, XISO_FILETIME_SIZE ) != XISO_FILETIME_SIZE ) write_err(); @@ -1197,9 +1204,16 @@ int traverse_xiso( int in_xiso, dir_node *in_dir_node, xoff_t in_dir_start, char if ( ! err ) { if ( tmp == XISO_PAD_SHORT ) { + if ( l_offset == 0 ) { // Directory is empty + if (in_mode == k_generate_avl) { + avl_insert(in_root, EMPTY_SUBDIRECTORY); + } + goto end_traverse; + } + l_offset = l_offset * XISO_DWORD_SIZE + ( XISO_SECTOR_SIZE - ( l_offset * XISO_DWORD_SIZE ) % XISO_SECTOR_SIZE ); err = lseek( in_xiso, in_dir_start + (xoff_t) l_offset, SEEK_SET ) == -1 ? 1 : 0; - + if ( ! err ) goto read_entry; // me and my silly comments } else { l_offset = tmp; @@ -1246,7 +1260,7 @@ int traverse_xiso( int in_xiso, dir_node *in_dir_node, xoff_t in_dir_start, char avl->file_size = dir->file_size; avl->old_start_sector = dir->start_sector; - + if ( avl_insert( in_root, avl ) == k_avl_error ) misc_err( "this iso appears to be corrupt\n", 0, 0, 0 ); } } @@ -1291,7 +1305,10 @@ int traverse_xiso( int in_xiso, dir_node *in_dir_node, xoff_t in_dir_start, char if ( ( err = mkdir( dir->filename, 0755 ) ) ) mkdir_err( dir->filename ); if ( ! err && dir->start_sector && ( err = chdir( dir->filename ) ) ) chdir_err( dir->filename ); } - if ( ! err && in_mode != k_list && in_mode != k_generate_avl ) exiso_log( "creating %s (0 bytes) [OK]\n", path ); + if( ! err && in_mode != k_generate_avl ) { + exiso_log("%s%s%s%s (0 bytes)%s", in_mode == k_extract ? "creating " : "", in_path, dir->filename, PATH_CHAR_STR, in_mode == k_extract ? " [OK]" : ""); flush(); + exiso_log("\n"); + } } } @@ -1344,6 +1361,8 @@ int traverse_xiso( int in_xiso, dir_node *in_dir_node, xoff_t in_dir_start, char } } +end_traverse: + if ( dir->filename ) free( dir->filename ); if ( ( dir = dir->parent ) ) goto left_processed; @@ -1717,6 +1736,10 @@ int write_tree( dir_node_avl *in_avl, write_tree_context *in_context, int in_dep } if ( context.path ) free( context.path ); + } else { + memset(sector, XISO_PAD_BYTE, XISO_SECTOR_SIZE); + if ((pos = lseek(in_context->xiso, in_avl->start_sector * XISO_SECTOR_SIZE, SEEK_SET)) == -1) seek_err(); + if (!err && write(in_context->xiso, sector, XISO_SECTOR_SIZE) != XISO_SECTOR_SIZE) write_err(); } } } @@ -1738,7 +1761,7 @@ int write_file( dir_node_avl *in_avl, write_tree_context *in_context, int in_dep if ( in_context->from == -1 ) { if ( ( fd = open( in_avl->filename, READFLAGS, 0 ) ) == -1 ) open_err( in_avl->filename ); } else { - if ( lseek( fd = in_context->from, (xoff_t) in_avl->old_start_sector * XISO_SECTOR_SIZE, SEEK_SET ) == -1 ) seek_err(); + if ( lseek( fd = in_context->from, (xoff_t) in_avl->old_start_sector * XISO_SECTOR_SIZE + s_xbox_disc_lseek, SEEK_SET ) == -1 ) seek_err(); } } @@ -1799,6 +1822,7 @@ int write_directory( dir_node_avl *in_avl, int in_xiso, int in_depth ) { xoff_t pos; int err = 0, pad; unsigned short l_offset, r_offset; + unsigned long file_size = in_avl->file_size + (in_avl->subdirectory ? (XISO_SECTOR_SIZE - (in_avl->file_size % XISO_SECTOR_SIZE)) % XISO_SECTOR_SIZE : 0); char length = (char) strlen( in_avl->filename ), attributes = in_avl->subdirectory ? XISO_ATTRIBUTE_DIR : XISO_ATTRIBUTE_ARC, sector[ XISO_SECTOR_SIZE ]; little32( in_avl->file_size ); @@ -1817,7 +1841,7 @@ int write_directory( dir_node_avl *in_avl, int in_xiso, int in_depth ) { if ( ! err && write( in_xiso, &l_offset, XISO_TABLE_OFFSET_SIZE ) != XISO_TABLE_OFFSET_SIZE ) write_err(); if ( ! err && write( in_xiso, &r_offset, XISO_TABLE_OFFSET_SIZE ) != XISO_TABLE_OFFSET_SIZE ) write_err(); if ( ! err && write( in_xiso, &in_avl->start_sector, XISO_SECTOR_OFFSET_SIZE ) != XISO_SECTOR_OFFSET_SIZE ) write_err(); - if ( ! err && write( in_xiso, &in_avl->file_size, XISO_FILESIZE_SIZE ) != XISO_FILESIZE_SIZE ) write_err(); + if ( ! err && write( in_xiso, &file_size, XISO_FILESIZE_SIZE ) != XISO_FILESIZE_SIZE ) write_err(); if ( ! err && write( in_xiso, &attributes, XISO_ATTRIBUTES_SIZE ) != XISO_ATTRIBUTES_SIZE ) write_err(); if ( ! err && write( in_xiso, &length, XISO_FILENAME_LENGTH_SIZE ) != XISO_FILENAME_LENGTH_SIZE ) write_err(); if ( ! err && write( in_xiso, in_avl->filename, length ) != length ) write_err(); @@ -1833,7 +1857,10 @@ int calculate_directory_offsets( dir_node_avl *in_avl, unsigned long *io_current wdsafp_context context; if ( in_avl->subdirectory ) { - if ( in_avl->subdirectory == EMPTY_SUBDIRECTORY ) in_avl->start_sector = 0; + if (in_avl->subdirectory == EMPTY_SUBDIRECTORY) { + in_avl->start_sector = *io_current_sector; + *io_current_sector += 1; + } else { context.current_sector = io_current_sector; context.dir_start = (xoff_t) ( in_avl->start_sector = *io_current_sector ) * XISO_SECTOR_SIZE; @@ -1862,10 +1889,8 @@ int write_dir_start_and_file_positions( dir_node_avl *in_avl, wdsafp_context *io int calculate_total_files_and_bytes( dir_node_avl *in_avl, void *in_context, int in_depth ) { - if ( in_avl->subdirectory ) { - if ( in_avl->subdirectory != EMPTY_SUBDIRECTORY ) { - avl_traverse_depth_first( in_avl->subdirectory, (traversal_callback) calculate_total_files_and_bytes, nil, k_prefix, 0 ); - } + if ( in_avl->subdirectory && in_avl->subdirectory != EMPTY_SUBDIRECTORY ) { + avl_traverse_depth_first( in_avl->subdirectory, (traversal_callback) calculate_total_files_and_bytes, nil, k_prefix, 0 ); } else { ++s_total_files; s_total_bytes += in_avl->file_size; @@ -1876,9 +1901,13 @@ int calculate_total_files_and_bytes( dir_node_avl *in_avl, void *in_context, int int calculate_directory_requirements( dir_node_avl *in_avl, void *in_context, int in_depth ) { - if ( in_avl->subdirectory && in_avl->subdirectory != EMPTY_SUBDIRECTORY ) { - avl_traverse_depth_first( in_avl->subdirectory, (traversal_callback) calculate_directory_size, &in_avl->file_size, k_prefix, 0 ); - avl_traverse_depth_first( in_avl->subdirectory, (traversal_callback) calculate_directory_requirements, in_context, k_prefix, 0 ); + if ( in_avl->subdirectory ) { + if (in_avl->subdirectory != EMPTY_SUBDIRECTORY) { + avl_traverse_depth_first(in_avl->subdirectory, (traversal_callback)calculate_directory_size, &in_avl->file_size, k_prefix, 0); + avl_traverse_depth_first(in_avl->subdirectory, (traversal_callback)calculate_directory_requirements, in_context, k_prefix, 0); + } else { + in_avl->file_size = XISO_SECTOR_SIZE; + } } return 0;