// PrintToStream void ResourceFile::PrintToStream(bool longInfo) { if (longInfo) { off_t resourcesOffset = fFile.GetOffset(); printf("ResourceFile:\n"); printf("file type : %s\n", kFileTypeNames[fFileType]); printf("endianess : %s\n", (fHostEndianess == (bool)B_HOST_IS_LENDIAN) ? "little" : "big"); printf("resource section offset: 0x%08Lx (%Ld)\n", resourcesOffset, resourcesOffset); if (fInfoTableItem) { int32 offset = fInfoTableItem->GetOffset(); int32 size = fInfoTableItem->GetSize(); printf("resource info table : offset: 0x%08lx (%ld), " "size: 0x%08lx (%ld)\n", offset, offset, size, size); } printf("number of resources : %ld\n", fResourceCount); for (int32 i = 0; i < fResourceCount; i++) { ResourceItem* item = ItemAt(i); item->PrintToStream(); } } else { printf(" Type ID Size Name\n"); printf(" ------ ----- -------- --------------------\n"); for (int32 i = 0; i < fResourceCount; i++) { ResourceItem* item = ItemAt(i); type_code type = item->GetType(); char typeName[4] = { type >> 24, (type >> 16) & 0xff, (type >> 8) & 0xff, type & 0xff }; printf(" '%.4s' %5ld %8lu %s\n", typeName, item->GetID(), item->GetSize(), item->GetName()); } } }
// GetResourcesSize uint32 ResourceFile::GetResourcesSize() const { if (!fInfoTableItem || fFile.InitCheck()) throw Exception("Resource file not initialized."); // header uint32 size = kResourcesHeaderSize; // index section uint32 indexSectionSize = kResourceIndexSectionHeaderSize + fResourceCount * kResourceIndexEntrySize; indexSectionSize = align_value(indexSectionSize, kResourceIndexSectionAlignment); size += indexSectionSize; // unknown section size += kUnknownResourceSectionSize; // data uint32 dataSize = 0; for (int32 i = 0; i < fResourceCount; i++) { ResourceItem* item = ItemAt(i); dataSize += item->GetSize(); } size += dataSize; // info table uint32 infoTableSize = 0; type_code type = 0; for (int32 i = 0; i < fResourceCount; i++) { ResourceItem* item = ItemAt(i); if (i == 0 || type != item->GetType()) { if (i != 0) infoTableSize += kResourceInfoSeparatorSize; type = item->GetType(); infoTableSize += kMinResourceInfoBlockSize; } else infoTableSize += kMinResourceInfoSize; uint32 nameLen = strlen(item->GetName()); if (nameLen != 0) infoTableSize += nameLen + 1; } infoTableSize += kResourceInfoSeparatorSize + kResourceInfoTableEndSize; size += infoTableSize; return size; }
// WriteResources uint32 ResourceFile::WriteResources(void* buffer, uint32 bufferSize) { // calculate sizes and offsets // header uint32 size = kResourcesHeaderSize; // index section uint32 indexSectionOffset = size; uint32 indexSectionSize = kResourceIndexSectionHeaderSize + fResourceCount * kResourceIndexEntrySize; indexSectionSize = align_value(indexSectionSize, kResourceIndexSectionAlignment); size += indexSectionSize; // unknown section uint32 unknownSectionOffset = size; uint32 unknownSectionSize = kUnknownResourceSectionSize; size += unknownSectionSize; // data uint32 dataOffset = size; uint32 dataSize = 0; for (int32 i = 0; i < fResourceCount; i++) { ResourceItem* item = ItemAt(i); dataSize += item->GetSize(); } size += dataSize; // info table uint32 infoTableOffset = size; uint32 infoTableSize = 0; type_code type = 0; for (int32 i = 0; i < fResourceCount; i++) { ResourceItem* item = ItemAt(i); if (i == 0 || type != item->GetType()) { if (i != 0) infoTableSize += kResourceInfoSeparatorSize; type = item->GetType(); infoTableSize += kMinResourceInfoBlockSize; } else infoTableSize += kMinResourceInfoSize; uint32 nameLen = strlen(item->GetName()); if (nameLen != 0) infoTableSize += nameLen + 1; } infoTableSize += kResourceInfoSeparatorSize + kResourceInfoTableEndSize; size += infoTableSize; // check whether the buffer is large enough if (!buffer) throw Exception("Supplied buffer is NULL."); if (bufferSize < size) throw Exception("Supplied buffer is too small."); // write... void* data = buffer; // header resources_header* resourcesHeader = (resources_header*)data; resourcesHeader->rh_resources_magic = kResourcesHeaderMagic; resourcesHeader->rh_resource_count = fResourceCount; resourcesHeader->rh_index_section_offset = indexSectionOffset; resourcesHeader->rh_admin_section_size = indexSectionOffset + indexSectionSize; for (int32 i = 0; i < 13; i++) resourcesHeader->rh_pad[i] = 0; // index section // header data = skip_bytes(buffer, indexSectionOffset); resource_index_section_header* indexHeader = (resource_index_section_header*)data; indexHeader->rish_index_section_offset = indexSectionOffset; indexHeader->rish_index_section_size = indexSectionSize; indexHeader->rish_unknown_section_offset = unknownSectionOffset; indexHeader->rish_unknown_section_size = unknownSectionSize; indexHeader->rish_info_table_offset = infoTableOffset; indexHeader->rish_info_table_size = infoTableSize; fill_pattern(buffer, &indexHeader->rish_unused_data1, 1); fill_pattern(buffer, indexHeader->rish_unused_data2, 25); fill_pattern(buffer, &indexHeader->rish_unused_data3, 1); // index table data = skip_bytes(data, kResourceIndexSectionHeaderSize); resource_index_entry* entry = (resource_index_entry*)data; uint32 entryOffset = dataOffset; for (int32 i = 0; i < fResourceCount; i++, entry++) { ResourceItem* item = ItemAt(i); uint32 entrySize = item->GetSize(); entry->rie_offset = entryOffset; entry->rie_size = entrySize; entry->rie_pad = 0; entryOffset += entrySize; } // padding + unknown section data = skip_bytes(buffer, dataOffset); fill_pattern(buffer, entry, data); // data for (int32 i = 0; i < fResourceCount; i++) { ResourceItem* item = ItemAt(i); status_t error = item->LoadData(fFile); if (error != B_OK) throw Exception(error, "Error loading resource data."); uint32 entrySize = item->GetSize(); memcpy(data, item->GetData(), entrySize); data = skip_bytes(data, entrySize); } // info table data = skip_bytes(buffer, infoTableOffset); type = 0; for (int32 i = 0; i < fResourceCount; i++) { ResourceItem* item = ItemAt(i); resource_info* info = NULL; if (i == 0 || type != item->GetType()) { if (i != 0) { resource_info_separator* separator = (resource_info_separator*)data; separator->ris_value1 = 0xffffffff; separator->ris_value2 = 0xffffffff; data = skip_bytes(data, kResourceInfoSeparatorSize); } type = item->GetType(); resource_info_block* infoBlock = (resource_info_block*)data; infoBlock->rib_type = type; info = infoBlock->rib_info; } else info = (resource_info*)data; // info info->ri_id = item->GetID(); info->ri_index = i + 1; info->ri_name_size = 0; data = info->ri_name; uint32 nameLen = strlen(item->GetName()); if (nameLen != 0) { memcpy(info->ri_name, item->GetName(), nameLen + 1); data = skip_bytes(data, nameLen + 1); info->ri_name_size = nameLen + 1; } } // separator resource_info_separator* separator = (resource_info_separator*)data; separator->ris_value1 = 0xffffffff; separator->ris_value2 = 0xffffffff; // table end data = skip_bytes(data, kResourceInfoSeparatorSize); resource_info_table_end* tableEnd = (resource_info_table_end*)data; void* infoTable = skip_bytes(buffer, infoTableOffset); tableEnd->rite_check_sum = calculate_checksum(infoTable, infoTableSize - kResourceInfoTableEndSize); tableEnd->rite_terminator = 0; // final check data = skip_bytes(data, kResourceInfoTableEndSize); uint32 bytesWritten = (char*)data - (char*)buffer; if (bytesWritten != size) { throw Exception("Bad boy error: Wrote %lu bytes, though supposed to " "write %lu bytes.", bytesWritten, size); } return size; }