diff --git a/Analyser/Static/Enterprise/StaticAnalyser.cpp b/Analyser/Static/Enterprise/StaticAnalyser.cpp index f12557d6e..ffd895e5e 100644 --- a/Analyser/Static/Enterprise/StaticAnalyser.cpp +++ b/Analyser/Static/Enterprise/StaticAnalyser.cpp @@ -102,8 +102,9 @@ Analyser::Static::TargetList Analyser::Static::Enterprise::GetTargets( }; // Check for a .COM by inspecting the header. - const auto type = FileType(file.get_le()); - const uint16_t size = file.get_le(); + using Storage::FileUtils::LittleEndian::get; + const auto type = FileType(get(file)); + const uint16_t size = get(file); // There are then 12 bytes of 0 padding that could be tested for. if((type != FileType::COM && type != FileType::BAS) || size > file.stats().st_size - 16) { diff --git a/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj b/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj index 013a73035..c8e245198 100644 --- a/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj +++ b/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj @@ -7629,7 +7629,6 @@ "$(PROJECT_DIR)/../../", ); LD_RUNPATH_SEARCH_PATHS = "$(USER_LIBRARY_DIR)/Frameworks"; - MACOSX_DEPLOYMENT_TARGET = 11.0; PRODUCT_NAME = "$(TARGET_NAME)"; }; name = Debug; @@ -7655,7 +7654,6 @@ "$(PROJECT_DIR)/../../", ); LD_RUNPATH_SEARCH_PATHS = "$(USER_LIBRARY_DIR)/Frameworks"; - MACOSX_DEPLOYMENT_TARGET = 11.0; ONLY_ACTIVE_ARCH = YES; PRODUCT_NAME = "$(TARGET_NAME)"; }; @@ -7713,7 +7711,7 @@ GCC_WARN_UNUSED_PARAMETER = YES; GCC_WARN_UNUSED_VARIABLE = YES; HEADER_SEARCH_PATHS = "$(PROJECT_DIR)/../../"; - MACOSX_DEPLOYMENT_TARGET = 14.6; + MACOSX_DEPLOYMENT_TARGET = 11.0; MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; MTL_FAST_MATH = YES; ONLY_ACTIVE_ARCH = YES; @@ -7771,7 +7769,7 @@ GCC_WARN_UNUSED_PARAMETER = YES; GCC_WARN_UNUSED_VARIABLE = YES; HEADER_SEARCH_PATHS = "$(PROJECT_DIR)/../../"; - MACOSX_DEPLOYMENT_TARGET = 14.6; + MACOSX_DEPLOYMENT_TARGET = 11.0; MTL_FAST_MATH = YES; SDKROOT = macosx; STRING_CATALOG_GENERATE_SYMBOLS = YES; diff --git a/Storage/Cartridge/Formats/PRG.cpp b/Storage/Cartridge/Formats/PRG.cpp index 7a746c889..96de04dde 100644 --- a/Storage/Cartridge/Formats/PRG.cpp +++ b/Storage/Cartridge/Formats/PRG.cpp @@ -15,7 +15,8 @@ using namespace Storage::Cartridge; PRG::PRG(const std::filesystem::path &path) { Storage::FileHolder file(path, FileMode::Read); - const auto loading_address = file.get_le(); + using Storage::FileUtils::LittleEndian::get; + const auto loading_address = get(file); if(loading_address != 0xa000) { throw ErrorNotROM; } diff --git a/Storage/Disk/DiskImage/Formats/2MG.cpp b/Storage/Disk/DiskImage/Formats/2MG.cpp index dc606940e..e487b3c6a 100644 --- a/Storage/Disk/DiskImage/Formats/2MG.cpp +++ b/Storage/Disk/DiskImage/Formats/2MG.cpp @@ -33,17 +33,18 @@ Disk2MG::DiskOrMassStorageDevice Disk2MG::open(const std::filesystem::path &path const auto creator = file.read(4); // Grab the header size, version number and image format. - const auto header_size = file.get_le(); - const auto version = file.get_le(); - const auto format = file.get_le(); - const auto flags = file.get_le(); + using Storage::FileUtils::LittleEndian::get; + const auto header_size = get(file); + const auto version = get(file); + const auto format = get(file); + const auto flags = get(file); // Skip the number of ProDOS blocks; this is surely implicit from the data size? file.seek(4, Whence::CUR); // Get the offset and size of the disk image data. - const auto data_start = file.get_le(); - auto data_size = file.get_le(); + const auto data_start = get(file); + auto data_size = get(file); // Correct for the Sweet 16 emulator, which writes broken 2MGs. if(!data_size && !memcmp(creator.data(), "WOOF", 4)) { diff --git a/Storage/Disk/DiskImage/Formats/CPCDSK.cpp b/Storage/Disk/DiskImage/Formats/CPCDSK.cpp index 1fae557ee..a65315f10 100644 --- a/Storage/Disk/DiskImage/Formats/CPCDSK.cpp +++ b/Storage/Disk/DiskImage/Formats/CPCDSK.cpp @@ -20,6 +20,8 @@ using namespace Storage::Disk; CPCDSK::CPCDSK(const std::filesystem::path &path) : path_(path), is_extended_(false) { + using Storage::FileUtils::LittleEndian::get; + FileHolder file(path); is_read_only_ = file.is_known_read_only(); @@ -48,7 +50,7 @@ CPCDSK::CPCDSK(const std::filesystem::path &path) : track_sizes.push_back(size_t(file.get()) << 8); } } else { - size_of_a_track = file.get_le(); + size_of_a_track = get(file); } long file_offset = 0x100; @@ -140,7 +142,7 @@ CPCDSK::CPCDSK(const std::filesystem::path &path) : // sector was weak or fuzzy and that multiple samplings are provided. If the greater size // is not an exact multiple then my reading of the documentation is that this is an invalid // disk image. - std::size_t declared_data_size = file.get_le(); + std::size_t declared_data_size = get(file); if(declared_data_size != stored_data_size) { if(declared_data_size > data_size) { number_of_samplings = declared_data_size / data_size; @@ -222,6 +224,8 @@ std::unique_ptr CPCDSK::track_at_position(::Storage::Disk::Track::Address } void CPCDSK::set_tracks(const std::map> &tracks) { + using Storage::FileUtils::LittleEndian::put; + // Patch changed tracks into the disk image. for(auto &pair: tracks) { // Assume MFM for now; with extensions DSK can contain FM tracks. @@ -368,7 +372,7 @@ void CPCDSK::set_tracks(const std::map(uint16_t(data_size)); + put(output, uint16_t(data_size)); } // Move to next 256-byte boundary. diff --git a/Storage/Disk/DiskImage/Formats/DMK.cpp b/Storage/Disk/DiskImage/Formats/DMK.cpp index 5d5fd0af9..0eafe0f75 100644 --- a/Storage/Disk/DiskImage/Formats/DMK.cpp +++ b/Storage/Disk/DiskImage/Formats/DMK.cpp @@ -16,7 +16,10 @@ using namespace Storage::Disk; namespace { -std::unique_ptr new_encoder(Storage::Disk::PCMSegment &segment, bool is_double_density) { +std::unique_ptr new_encoder( + Storage::Disk::PCMSegment &segment, + const bool is_double_density +) { std::unique_ptr encoder; if(is_double_density) { @@ -34,6 +37,8 @@ std::unique_ptr new_encoder(Storage::Disk::PCM DMK::DMK(const std::filesystem::path &path) : file_(path) { + using Storage::FileUtils::LittleEndian::get; + // Determine whether this DMK represents a read-only disk (whether intentionally, // or by virtue of filesystem placement). uint8_t read_only_byte = file_.get(); @@ -42,7 +47,7 @@ DMK::DMK(const std::filesystem::path &path) : // Read track count and size. head_position_count_ = int(file_.get()); - track_length_ = long(file_.get_le()); + track_length_ = long(get(file_)); // Track length must be at least 0x80, as that's the size of the IDAM // table before track contents. @@ -57,7 +62,7 @@ DMK::DMK(const std::filesystem::path &path) : // Skip to the end of the header and check that this is // "in the emulator's native format". file_.seek(0xc, Whence::SET); - const auto format = file_.get_le(); + const auto format = get(file_); if(format) throw Error::InvalidFormat; } @@ -80,13 +85,15 @@ long DMK::get_file_offset_for_position(const Track::Address address) const { } std::unique_ptr<::Storage::Disk::Track> DMK::track_at_position(const ::Storage::Disk::Track::Address address) const { + using Storage::FileUtils::LittleEndian::get; + file_.seek(get_file_offset_for_position(address), Whence::SET); // Read the IDAM table. uint16_t idam_locations[64]; std::size_t idam_count = 0; for(std::size_t c = 0; c < sizeof(idam_locations) / sizeof(*idam_locations); ++c) { - idam_locations[idam_count] = file_.get_le(); + idam_locations[idam_count] = get(file_); if((idam_locations[idam_count] & 0x7fff) >= 128) { idam_count++; } diff --git a/Storage/Disk/DiskImage/Formats/FAT12.cpp b/Storage/Disk/DiskImage/Formats/FAT12.cpp index 72f6c6668..1b778e2fc 100644 --- a/Storage/Disk/DiskImage/Formats/FAT12.cpp +++ b/Storage/Disk/DiskImage/Formats/FAT12.cpp @@ -21,13 +21,14 @@ FAT12::FAT12(const std::filesystem::path &path) : if(file_size < 512) throw Error::InvalidFormat; // Inspect the FAT. + using Storage::FileUtils::LittleEndian::get; file_.seek(11, Whence::SET); - sector_size_ = file_.get_le(); + sector_size_ = get(file_); file_.seek(19, Whence::SET); - const auto total_sectors = file_.get_le(); + const auto total_sectors = get(file_); file_.seek(24, Whence::SET); - sector_count_ = file_.get_le(); - head_count_ = file_.get_le(); + sector_count_ = get(file_); + head_count_ = get(file_); // Throw if there would seemingly be an incomplete track. if(file_size != total_sectors*sector_size_) throw Error::InvalidFormat; diff --git a/Storage/Disk/DiskImage/Formats/G64.cpp b/Storage/Disk/DiskImage/Formats/G64.cpp index 7c174e864..cc4479881 100644 --- a/Storage/Disk/DiskImage/Formats/G64.cpp +++ b/Storage/Disk/DiskImage/Formats/G64.cpp @@ -27,7 +27,8 @@ G64::G64(const std::filesystem::path &path) : // get the number of tracks and track size number_of_tracks_ = file_.get(); - maximum_track_size_ = file_.get_le(); + using Storage::FileUtils::LittleEndian::get; + maximum_track_size_ = get(file_); } HeadPosition G64::maximum_head_position() const { @@ -37,40 +38,42 @@ HeadPosition G64::maximum_head_position() const { } std::unique_ptr G64::track_at_position(const Track::Address address) const { - // seek to this track's entry in the track table + using Storage::FileUtils::LittleEndian::get; + + // Seek to this track's entry in the track table. file_.seek(long((address.position.as_half() * 4) + 0xc), Whence::SET); - // read the track offset - const auto track_offset = file_.get_le(); + // Read the track offset. + const auto track_offset = get(file_); - // if the track offset is zero, this track doesn't exist, so... + // If the track offset is zero, this track doesn't exist, so... if(!track_offset) return nullptr; - // seek to the track start + // Seek to track start. file_.seek(long(track_offset), Whence::SET); - // get the real track length - const auto track_length = file_.get_le(); + // Get the real track length. + const auto track_length = get(file_); - // grab the byte contents of this track + // Grab the byte contents of this track. const std::vector track_contents = file_.read(track_length); - // seek to this track's entry in the speed zone table + // Seek to this track's entry in the speed zone table. file_.seek(long((address.position.as_half() * 4) + 0x15c), Whence::SET); - // read the speed zone offsrt - const auto speed_zone_offset = file_.get_le(); + // Read the speed zone offset. + const auto speed_zone_offset = get(file_); - // if the speed zone is not constant, create a track based on the whole table; otherwise create one that's constant + // If the speed zone is not constant, create a track based on the whole table; otherwise create one that's constant. if(speed_zone_offset > 3) { - // seek to start of speed zone + // Seek to start of speed zone. file_.seek(long(speed_zone_offset), Whence::SET); - // read the speed zone bytes + // Read the speed zone bytes. const uint16_t speed_zone_length = (track_length + 3) >> 2; const auto speed_zone_contents = file_.read(speed_zone_length); - // divide track into appropriately timed PCMSegments + // Divide track into appropriately timed PCMSegments. std::vector segments; unsigned int current_speed = speed_zone_contents[0] >> 6; unsigned int start_byte_in_current_speed = 0; diff --git a/Storage/Disk/DiskImage/Formats/HFE.cpp b/Storage/Disk/DiskImage/Formats/HFE.cpp index cae6f8e7e..4df269f74 100644 --- a/Storage/Disk/DiskImage/Formats/HFE.cpp +++ b/Storage/Disk/DiskImage/Formats/HFE.cpp @@ -22,7 +22,8 @@ HFE::HFE(const std::filesystem::path &path) : head_count_ = file_.get(); file_.seek(7, Whence::CUR); - track_list_offset_ = long(file_.get_le()) << 9; + using Storage::FileUtils::LittleEndian::get; + track_list_offset_ = long(get(file_)) << 9; } HeadPosition HFE::maximum_head_position() const { @@ -45,8 +46,9 @@ uint16_t HFE::seek_track(const Track::Address address) const { // based on an assumption of two heads. file_.seek(track_list_offset_ + address.position.as_int() * 4, Whence::SET); - long track_offset = long(file_.get_le()) << 9; // Track offset, in units of 512 bytes. - const auto track_length = file_.get_le(); // Track length, in bytes, containing both the front and back track. + using Storage::FileUtils::LittleEndian::get; + long track_offset = long(get(file_)) << 9; // Track offset, in units of 512 bytes. + const auto track_length = get(file_); // Track length, in bytes, containing both the front and back track. file_.seek(track_offset, Whence::SET); if(address.head) file_.seek(256, Whence::CUR); diff --git a/Storage/Disk/DiskImage/Formats/IPF.cpp b/Storage/Disk/DiskImage/Formats/IPF.cpp index 78f527efc..237723e4a 100644 --- a/Storage/Disk/DiskImage/Formats/IPF.cpp +++ b/Storage/Disk/DiskImage/Formats/IPF.cpp @@ -37,15 +37,16 @@ size_t block_size(Storage::FileHolder &file, const uint8_t header) { } IPF::IPF(const std::filesystem::path &path) : file_(path) { + using Storage::FileUtils::BigEndian::get; std::map tracks_by_data_key; // For now, just build up a list of tracks that exist, noting the file position at which their data begins // plus the other fields that'll be necessary to convert them into flux on demand later. while(true) { const auto start_of_block = file_.tell(); - const auto type = file_.get_be(); - auto length = file_.get_be(); // Can't be const because of the dumb encoding of DATA blocks. - [[maybe_unused]] const auto crc = file_.get_be(); + const auto type = get(file_); + auto length = get(file_); // Can't be const because of the dumb encoding of DATA blocks. + [[maybe_unused]] const auto crc = get(file_); if(file_.eof()) break; // Sanity check: the first thing in a file should be the CAPS record. @@ -71,21 +72,21 @@ IPF::IPF(const std::filesystem::path &path) : file_(path) { // aren't that interesting. // Make sure this is a floppy disk. - const auto media_type = file_.get_be(); + const auto media_type = get(file_); if(media_type != 1) { throw Error::InvalidFormat; } // Determine whether this is a newer SPS-style file. - is_sps_format_ = file_.get_be() > 1; + is_sps_format_ = get(file_) > 1; // Skip: revision, file key and revision, CRC of the original .ctr, and minimum track. file_.seek(20, Whence::CUR); - track_count_ = int(1 + file_.get_be()); + track_count_ = int(1 + get(file_)); // Skip: min side. file_.seek(4, Whence::CUR); - head_count_ = int(1 + file_.get_be()); + head_count_ = int(1 + get(file_)); // Skip: creation date, time. file_.seek(8, Whence::CUR); @@ -117,8 +118,8 @@ IPF::IPF(const std::filesystem::path &path) : file_(path) { case block("IMGE"): { // Get track location. - const auto track = file_.get_be(); - const auto side = file_.get_be(); + const auto track = get(file_); + const auto side = get(file_); const Track::Address address{int(side), HeadPosition(int(track))}; // Hence generate a TrackDescription. @@ -128,31 +129,31 @@ IPF::IPF(const std::filesystem::path &path) : file_(path) { // Read those fields of interest... // Bit density. I've no idea why the density can't just be given as a measurement. - description.density = TrackDescription::Density(file_.get_be()); + description.density = TrackDescription::Density(get(file_)); if(description.density > TrackDescription::Density::Max) { description.density = TrackDescription::Density::Unknown; } file_.seek(12, Whence::CUR); // Skipped: signal type, track bytes, start byte position. - description.start_bit_pos = file_.get_be(); - description.data_bits = file_.get_be(); - description.gap_bits = file_.get_be(); + description.start_bit_pos = get(file_); + description.data_bits = get(file_); + description.gap_bits = get(file_); file_.seek(4, Whence::CUR); // Skipped: track bits, which is entirely redundant. - description.block_count = file_.get_be(); + description.block_count = get(file_); file_.seek(4, Whence::CUR); // Skipped: encoder process. - description.has_fuzzy_bits = file_.get_be() & 1; + description.has_fuzzy_bits = get(file_) & 1; // For some reason the authors decided to introduce another primary key, // in addition to that which naturally exists of (track, side). So set up // a mapping from the one to the other. - const auto data_key = file_.get_be(); + const auto data_key = get(file_); tracks_by_data_key.emplace(data_key, address); } break; case block("DATA"): { - length += file_.get_be(); + length += get(file_); file_.seek(8, Whence::CUR); // Skipped: bit size, CRC. @@ -160,7 +161,7 @@ IPF::IPF(const std::filesystem::path &path) : file_(path) { // position for this track. // // Assumed here: DATA records will come after corresponding IMGE records. - const auto data_key = file_.get_be(); + const auto data_key = get(file_); const auto pair = tracks_by_data_key.find(data_key); if(pair == tracks_by_data_key.end()) { break; @@ -187,6 +188,8 @@ int IPF::head_count() const { } std::unique_ptr IPF::track_at_position(const Track::Address address) const { + using Storage::FileUtils::BigEndian::get; + // Get the track description, if it exists, and check either that the file has contents for the track. auto pair = tracks_.find(address); if(pair == tracks_.end()) { @@ -220,24 +223,24 @@ std::unique_ptr IPF::track_at_position(const Track::Address address) cons blocks.reserve(description.block_count); for(uint32_t c = 0; c < description.block_count; c++) { auto &block = blocks.emplace_back(); - block.data_bits = file_.get_be(); - block.gap_bits = file_.get_be(); + block.data_bits = get(file_); + block.gap_bits = get(file_); if(is_sps_format_) { - block.gap_offset = file_.get_be(); + block.gap_offset = get(file_); file_.seek(4, Whence::CUR); // Skip 'cell type' which appears to provide no content. } else { // Skip potlower-resolution copies of data_bits and gap_bits. file_.seek(8, Whence::CUR); } - block.is_mfm = file_.get_be() == 1; + block.is_mfm = get(file_) == 1; - const auto flags = file_.get_be(); + const auto flags = get(file_); block.has_forward_gap = flags & 1; block.has_backwards_gap = flags & 2; block.data_unit_is_bits = flags & 4; - block.default_gap_value = file_.get_be(); - block.data_offset = file_.get_be(); + block.default_gap_value = get(file_); + block.data_offset = get(file_); } std::vector segments; diff --git a/Storage/Disk/DiskImage/Formats/MOOF.cpp b/Storage/Disk/DiskImage/Formats/MOOF.cpp index 2f05512af..68fe416c6 100644 --- a/Storage/Disk/DiskImage/Formats/MOOF.cpp +++ b/Storage/Disk/DiskImage/Formats/MOOF.cpp @@ -106,7 +106,8 @@ MOOF::MOOF(const std::filesystem::path &path) : } // Test the file's CRC32. - const auto crc = file_.get_le(); + using Storage::FileUtils::LittleEndian::get; + const auto crc = get(file_); post_crc_contents_ = file_.read(size_t(file_.stats().st_size - 12)); const uint32_t computed_crc = CRC::CRC32::crc_of(post_crc_contents_); if(crc != computed_crc) { @@ -119,8 +120,8 @@ MOOF::MOOF(const std::filesystem::path &path) : std::fill(std::begin(track_map_), std::end(track_map_), 0xff); std::fill(std::begin(flux_map_), std::end(flux_map_), 0xff); while(true) { - const auto chunk_id = file_.get_le(); - const auto chunk_size = file_.get_le(); + const auto chunk_id = get(file_); + const auto chunk_size = get(file_); const auto end_of_chunk = file_.tell() + long(chunk_size); if(file_.eof()) break; @@ -184,6 +185,7 @@ int MOOF::head_count() const { } std::unique_ptr MOOF::track_at_position(const Track::Address address) const { + using Storage::FileUtils::LittleEndian::get; const int table_position = address.position.as_int() * 2 + address.head; if(table_position > 255) { return nullptr; @@ -192,9 +194,9 @@ std::unique_ptr MOOF::track_at_position(const Track::Address address) con const auto location = [&](const uint8_t offset) -> TrackLocation { file_.seek(tracks_offset_ + 8 * long(offset), Whence::SET); TrackLocation location; - location.starting_block = file_.get_le(); - location.block_count = file_.get_le(); - location.bit_count = file_.get_le(); + location.starting_block = get(file_); + location.block_count = get(file_); + location.bit_count = get(file_); return location; }; diff --git a/Storage/Disk/DiskImage/Formats/MSA.cpp b/Storage/Disk/DiskImage/Formats/MSA.cpp index ebe683d19..0c8a87db4 100644 --- a/Storage/Disk/DiskImage/Formats/MSA.cpp +++ b/Storage/Disk/DiskImage/Formats/MSA.cpp @@ -16,17 +16,19 @@ using namespace Storage::Disk; MSA::MSA(const std::filesystem::path &path) : file_(path) { - const auto signature = file_.get_be(); + using FileUtils::BigEndian::get; + + const auto signature = get(file_); if(signature != 0x0e0f) throw Error::InvalidFormat; - sectors_per_track_ = file_.get_be(); - sides_ = 1 + file_.get_be(); - starting_track_ = file_.get_be(); - ending_track_ = file_.get_be(); + sectors_per_track_ = get(file_); + sides_ = 1 + get(file_); + starting_track_ = get(file_); + ending_track_ = get(file_); // Create the uncompressed track list. while(true) { - const auto data_length = file_.get_be(); + const auto data_length = get(file_); if(file_.eof()) break; if(data_length == sectors_per_track_ * 512) { @@ -55,7 +57,7 @@ MSA::MSA(const std::filesystem::path &path) : if(pointer > data_length) break; const auto value = file_.get(); - auto count = file_.get_be(); + auto count = get(file_); while(count--) { track.push_back(value); } diff --git a/Storage/Disk/DiskImage/Formats/MacintoshIMG.cpp b/Storage/Disk/DiskImage/Formats/MacintoshIMG.cpp index 09486e101..120ca57fc 100644 --- a/Storage/Disk/DiskImage/Formats/MacintoshIMG.cpp +++ b/Storage/Disk/DiskImage/Formats/MacintoshIMG.cpp @@ -75,10 +75,11 @@ MacintoshIMG::MacintoshIMG(const std::filesystem::path &path) : // Get the length of the data and tag blocks. file_.seek(64, Whence::SET); - const auto data_block_length = file_.get_be(); - const auto tag_block_length = file_.get_be(); - const auto data_checksum = file_.get_be(); - const auto tag_checksum = file_.get_be(); + using Storage::FileUtils::BigEndian::get; + const auto data_block_length = get(file_); + const auto tag_block_length = get(file_); + const auto data_checksum = get(file_); + const auto tag_checksum = get(file_); // Don't continue with no data. if(!data_block_length) { @@ -98,7 +99,7 @@ MacintoshIMG::MacintoshIMG(const std::filesystem::path &path) : format_ = file_.get(); // Check the magic number. - const auto magic_number = file_.get_be(); + const auto magic_number = get(file_); if(magic_number != 0x0100) throw Error::InvalidFormat; @@ -332,8 +333,9 @@ void MacintoshIMG::set_tracks(const std::map("MFM_DISK")) throw Error::InvalidFormat; - head_count_ = file_.get_le(); - track_count_ = file_.get_le(); - geometry_type_ = file_.get_le(); + using Storage::FileUtils::LittleEndian::get; + head_count_ = get(file_); + track_count_ = get(file_); + geometry_type_ = get(file_); if(geometry_type_ < 1 || geometry_type_ > 2) throw Error::InvalidFormat; diff --git a/Storage/Disk/DiskImage/Formats/SAP.cpp b/Storage/Disk/DiskImage/Formats/SAP.cpp index 8e5a0c832..749fa361b 100644 --- a/Storage/Disk/DiskImage/Formats/SAP.cpp +++ b/Storage/Disk/DiskImage/Formats/SAP.cpp @@ -91,7 +91,7 @@ std::unique_ptr SAP::track_at_position(const Track::Address address) cons // Also it includes the four SAP-specific fields in its CRC so this definitely isn't supposed to be the one that // appears on the imaged disk itself even if bit order were conventional. const auto calculated = CRC::Generator::crc_of(contents); - const auto crc = file_.get_be(); + const auto crc = FileUtils::get(file_); contents.erase(contents.begin(), contents.begin() + 4); sector.samples.push_back(contents); diff --git a/Storage/Disk/DiskImage/Formats/STX.cpp b/Storage/Disk/DiskImage/Formats/STX.cpp index 3ba07a202..4f28431cd 100644 --- a/Storage/Disk/DiskImage/Formats/STX.cpp +++ b/Storage/Disk/DiskImage/Formats/STX.cpp @@ -391,9 +391,11 @@ private: } STX::STX(const std::filesystem::path &path) : file_(path) { + using FileUtils::LittleEndian::get; + // Require that this be a version 3 Pasti. if(!file_.check_signature("RSY")) throw Error::InvalidFormat; - if(file_.get_le() != 3) throw Error::InvalidFormat; + if(get(file_) != 3) throw Error::InvalidFormat; // Skip: tool used, 2 reserved bytes. file_.seek(4, Whence::CUR); @@ -423,7 +425,7 @@ STX::STX(const std::filesystem::path &path) : file_(path) { head_count_ = 1; while(true) { const long offset = file_.tell(); - const auto size = file_.get_le(); + const auto size = get(file_); if(file_.eof()) break; // Skip fields other than track position, then fill in table position and advance. @@ -461,10 +463,11 @@ std::unique_ptr STX::track_at_position(const Track::Address address) cons file_.seek(offset_by_track_[track_index] + 4, Whence::SET); // Grab the track description. - const auto fuzzy_size = file_.get_le(); - const auto sector_count = file_.get_le(); - const auto flags = file_.get_le(); - const size_t track_length = file_.get_le(); + using FileUtils::LittleEndian::get; + const auto fuzzy_size = get(file_); + const auto sector_count = get(file_); + const auto flags = get(file_); + const size_t track_length = get(file_); file_.seek(2, Whence::CUR); // Skip track type; despite being named, it's apparently unused. // If this is a trivial .ST-style sector dump, life is easy. @@ -481,9 +484,9 @@ std::unique_ptr STX::track_at_position(const Track::Address address) cons // Sector records come first. for(uint16_t c = 0; c < sector_count; ++c) { sectors.emplace_back(); - sectors.back().data_offset = file_.get_le(); - sectors.back().bit_position = file_.get_le(); - sectors.back().data_duration = file_.get_le(); + sectors.back().data_offset = get(file_); + sectors.back().bit_position = get(file_); + sectors.back().data_duration = get(file_); file_.read(sectors.back().address); sectors.back().status = file_.get(); file_.seek(1, Whence::CUR); @@ -520,11 +523,11 @@ std::unique_ptr STX::track_at_position(const Track::Address address) cons // Bit 6 => there is a track to read; // bit if(flags & 0x80) { - first_sync = file_.get_le(); - const auto image_size = file_.get_le(); + first_sync = get(file_); + const auto image_size = get(file_); track_data = file_.read(image_size); } else { - const auto image_size = file_.get_le(); + const auto image_size = get(file_); track_data = file_.read(image_size); } } @@ -572,7 +575,8 @@ std::unique_ptr STX::track_at_position(const Track::Address address) cons // This is going to be a new-format record. for(size_t c = 0; c < timing_record_size; ++c) { - sector.timing[c] = file_.get_be(); // These values are big endian, unlike the rest of the file. + // WARNING: these values are big endian, unlike the rest of the file. + sector.timing[c] = FileUtils::get(file_); } } diff --git a/Storage/Disk/DiskImage/Formats/WOZ.cpp b/Storage/Disk/DiskImage/Formats/WOZ.cpp index d4fb764c6..b3554d6b6 100644 --- a/Storage/Disk/DiskImage/Formats/WOZ.cpp +++ b/Storage/Disk/DiskImage/Formats/WOZ.cpp @@ -24,6 +24,7 @@ constexpr uint32_t chunk(const char *str) { WOZ::WOZ(const std::filesystem::path &path) : file_(path) { + using FileUtils::LittleEndian::get; static constexpr char signature1[8] = { 'W', 'O', 'Z', '1', @@ -42,7 +43,7 @@ WOZ::WOZ(const std::filesystem::path &path) : type_ = isWoz2 ? Type::WOZ2 : Type::WOZ1; // Get the file's CRC32. - const auto crc = file_.get_le(); + const auto crc = get(file_); // Get the collection of all data that contributes to the CRC. post_crc_contents_ = file_.read(size_t(file_.stats().st_size - 12)); @@ -59,8 +60,8 @@ WOZ::WOZ(const std::filesystem::path &path) : // Parse all chunks up front. bool has_tmap = false; while(true) { - const auto chunk_id = file_.get_le(); - const auto chunk_size = file_.get_le(); + const auto chunk_id = get(file_); + const auto chunk_size = get(file_); const auto end_of_chunk = file_.tell() + long(chunk_size); if(file_.eof()) break; @@ -148,6 +149,8 @@ bool WOZ::tracks_differ(const Track::Address lhs, const Track::Address rhs) cons } std::unique_ptr WOZ::track_at_position(const Track::Address address) const { + using FileUtils::LittleEndian::get; + const long offset = file_offset(address); if(offset == NoSuchTrack) { return nullptr; @@ -167,15 +170,16 @@ std::unique_ptr WOZ::track_at_position(const Track::Address address) cons // of bits that were used. Other information follows but is not intended for emulation. track_contents = file_.read(6646); file_.seek(2, Whence::CUR); - number_of_bits = std::min(file_.get_le(), uint16_t(6646*8)); + number_of_bits = std::min(get(file_), uint16_t(6646*8)); break; default: case Type::WOZ2: { // In WOZ 2 an extra level of indirection allows for variable track sizes. - const auto starting_block = file_.get_le(); - file_.seek(2, Whence::CUR); // Skip the block count; the amount of data to read is implied by the number of bits. - number_of_bits = file_.get_le(); + const auto starting_block = get(file_); + file_.seek(2, Whence::CUR); // Skip the block count; the amount of data to read is implied + // by the number of bits. + number_of_bits = get(file_); file_.seek(starting_block * 512, Whence::SET); track_contents = file_.read((number_of_bits + 7) >> 3); @@ -214,7 +218,7 @@ void WOZ::set_tracks(const std::map> &tra // Grab the file lock, then write the CRC, then just dump the entire file buffer. std::lock_guard lock_guard(file_.file_access_mutex()); file_.seek(8, Whence::SET); - file_.put_le(crc); + FileUtils::put(file_, crc); file_.write(post_crc_contents_); } diff --git a/Storage/FileHolder.hpp b/Storage/FileHolder.hpp index 828fff94e..5cb400cf3 100644 --- a/Storage/FileHolder.hpp +++ b/Storage/FileHolder.hpp @@ -12,6 +12,7 @@ #include #include +#include #include #include #include @@ -62,59 +63,6 @@ public: FileHolder(const std::filesystem::path &, FileMode ideal_mode = FileMode::ReadWrite); FileHolder(FileHolder &&); - /*! - Writes @c value using successive @c puts, in little endian order. - Optionally limits itself to only @c size bytes. - */ - template - void put_le(IntT value) { - for(size_t c = 0; c < size; c++) { - put(uint8_t(value)); - value >>= 8; - } - } - - /*! - Writes @c value using successive @c puts, in big endian order. - Optionally limits itself to only @c size bytes. - */ - template - void put_be(const IntT value) { - auto shift = size * 8; - while(shift) { - shift -= 8; - put((value >> shift)&0xff); - } - } - - /*! - Reads a value of type @c IntT using successive @c gets, in little endian order. - Optionally limits itself to only @c size bytes. - */ - template - IntT get_le() { - IntT result{}; - for(size_t c = 0; c < size; c++) { - result >>= 8; - result |= IntT(get() << ((size - 1) * 8)); - } - return result; - } - - /*! - Reads a value of type @c IntT using successive @c gets, in big endian order. - Optionally limits itself to only @c size bytes. - */ - template - IntT get_be() { - IntT result{}; - for(size_t c = 0; c < size; c++) { - result <<= 8; - result |= get(); - } - return result; - } - /*! Reads a single byte from @c file. */ uint8_t get(); @@ -156,15 +104,6 @@ public: /*! @returns @c true if the end-of-file indicator is set, @c false otherwise. */ bool eof() const; - /*! - Obtains a BitStream for reading from the file from the current reading cursor. - */ - template - Numeric::BitStream bitstream() { - return Numeric::BitStream([&] { - return get(); - }); - } /*! For SignatureType::Binary: @@ -231,4 +170,121 @@ inline std::vector contents_of(const std::filesystem::path &path) { return file.read(size_t(file.stats().st_size)); } +/*! + Various free functions that work with an open file. +*/ +namespace FileUtils { + +/*! + Obtains a BitStream for reading from the file from the current reading cursor. +*/ +template +Numeric::BitStream bitstream(FileHolder &file) { + return Numeric::BitStream([&] { + return file.get(); + }); +} + +/*! + A local implementation of std::byteswap, which I cannot currently use because it's C++23. +*/ +template +requires (sizeof(IntT) == 1 || sizeof(IntT) == 2 || sizeof(IntT) == 4 || sizeof(IntT) == 8) +IntT byteswap(IntT value) { + if constexpr (sizeof(IntT) == 1) { + return value; + } + if constexpr (sizeof(IntT) == 2) { + return __builtin_bswap16(value); + } + if constexpr (sizeof(IntT) == 4) { + return __builtin_bswap32(value); + } + if constexpr (sizeof(IntT) == 8) { + return __builtin_bswap64(value); + } +} + +/*! + Writes @c value to @c file according to @c endian. + Optionally limits itself to only @c size bytes. +*/ +template +void put(FileHolder &file, IntT value) { + if constexpr (size != sizeof(IntT) && endian == std::endian::big) { + // Little on little: relevant bytes are the first ones. + // Little on big: low bytes were swapped into high. Still the first ones. Do nothing. + + // Big on little: pull bytes up to top ready to be swapped into bottom. + // Big on bug: pull meaningful bytes up to the front. + value <<= ((sizeof(IntT) - size) / 8); + } + + if constexpr (endian != std::endian::native && sizeof(IntT) > 1) { + value = byteswap(value); + } + + file.write(&value, size); +} + +/*! + Reads a value of type @c IntT from @c file using @c endian byte order. + Optionally limits itself to only @c size bytes. +*/ +template +IntT get(FileHolder &file) { + IntT result; + if constexpr (size != sizeof(IntT)) { + result = 0; + } + + file.read(reinterpret_cast(&result), size); + if constexpr (endian != std::endian::native) { + result = byteswap(result); + } + + if constexpr (size != sizeof(IntT) && endian == std::endian::big) { + // Little on little: read into low bytes. Do nothing. + // Little on big: read into high bytes, swapped into low. Do nothing. + // Big on little: read into low bytes, swapped into high. Shift downward. + // Big on big: read into high bytes. Shift downward. + result >>= ((sizeof(IntT) - size) / 8); + } + + return result; +} + +/* + Helpers below are designed to allow more-compact syntax elsewhere; e.g. + `using FileUtils::LittleEndian::get`. +*/ +namespace LittleEndian { + +template +IntT get(Storage::FileHolder &file) { + return Storage::FileUtils::get(file); +} + +template +void put(FileHolder &file, IntT value) { + return Storage::FileUtils::put(file, value); +} + +} + +namespace BigEndian { + +template +IntT get(Storage::FileHolder &file) { + return Storage::FileUtils::get(file); +} + +template +void put(FileHolder &file, IntT value) { + return Storage::FileUtils::put(file, value); +} + +} + +} } diff --git a/Storage/MassStorage/Formats/VHD.cpp b/Storage/MassStorage/Formats/VHD.cpp index 923428462..7f4b1085d 100644 --- a/Storage/MassStorage/Formats/VHD.cpp +++ b/Storage/MassStorage/Formats/VHD.cpp @@ -17,6 +17,8 @@ constexpr size_t SectorSize = 512; } VHD::VHD(const std::filesystem::path &path) : file_(path) { + using FileUtils::BigEndian::get; + // Find footer; this may be the final 511 or final 512 bytes of the file. // Find what might be the start of the 'conectix' [sic] signature. file_.seek(-511, Whence::END); @@ -32,22 +34,22 @@ VHD::VHD(const std::filesystem::path &path) : file_(path) { } file_.seek(4, Whence::CUR); // Skip 'Features', which would at best classify this disk as temporary or not. - const auto major_version = file_.get_be(); + const auto major_version = get(file_); if(major_version > 1) { throw std::exception(); } file_.seek(2, Whence::CUR); // Skip minor version number. - data_offset_ = file_.get_be(); + data_offset_ = get(file_); file_.seek(32, Whence::CUR); // Skip creator and timestamp fields, original size and current size. -// const auto current_size = file_.get_be(); +// const auto current_size = get(); - cylinders_ = file_.get_be(); + cylinders_ = get(file_); heads_ = file_.get(); sides_ = file_.get(); - switch(file_.get_be()) { + switch(get(file_)) { case 2: type_ = Type::Fixed; break; case 3: type_ = Type::Dynamic; break; case 4: type_ = Type::Differencing; break; @@ -67,11 +69,11 @@ VHD::VHD(const std::filesystem::path &path) : file_(path) { } file_.seek(8, Whence::CUR); // Skip data offset. - table_offset_ = file_.get_be(); + table_offset_ = get(file_); file_.seek(4, Whence::CUR); // Skip table version. TODO: validate. - max_table_entries_ = file_.get_be(); - block_size_ = file_.get_be(); + max_table_entries_ = get(file_); + block_size_ = get(file_); total_blocks_ = block_size_ * max_table_entries_; } diff --git a/Storage/State/SNA.cpp b/Storage/State/SNA.cpp index f8d785966..c3e027da2 100644 --- a/Storage/State/SNA.cpp +++ b/Storage/State/SNA.cpp @@ -45,18 +45,20 @@ std::unique_ptr SNA::load(const std::filesystem::path // 00 I const uint8_t i = file.get(); + using FileUtils::LittleEndian::get; + // 01 HL'; 03 DE'; 05 BC'; 07 AF' - state->z80.registers.hl_dash = file.get_le(); - state->z80.registers.de_dash = file.get_le(); - state->z80.registers.bc_dash = file.get_le(); - state->z80.registers.af_dash = file.get_le(); + state->z80.registers.hl_dash = get(file); + state->z80.registers.de_dash = get(file); + state->z80.registers.bc_dash = get(file); + state->z80.registers.af_dash = get(file); // 09 HL; 0B DE; 0D BC; 0F IY; 11 IX - state->z80.registers.hl = file.get_le(); - state->z80.registers.de = file.get_le(); - state->z80.registers.bc = file.get_le(); - state->z80.registers.iy = file.get_le(); - state->z80.registers.ix = file.get_le(); + state->z80.registers.hl = get(file); + state->z80.registers.de = get(file); + state->z80.registers.bc = get(file); + state->z80.registers.iy = get(file); + state->z80.registers.ix = get(file); // 13 IFF2 (in bit 2) const uint8_t iff = file.get(); @@ -69,7 +71,7 @@ std::unique_ptr SNA::load(const std::filesystem::path // 15 AF; 17 SP; 19 interrupt mode state->z80.registers.flags = file.get(); state->z80.registers.a = file.get(); - state->z80.registers.stack_pointer = file.get_le(); + state->z80.registers.stack_pointer = get(file); state->z80.registers.interrupt_mode = file.get(); // 1A border colour @@ -87,7 +89,7 @@ std::unique_ptr SNA::load(const std::filesystem::path return result; } - state->z80.registers.program_counter = file.get_le(); + state->z80.registers.program_counter = get(file); state->last_7ffd = file.get(); const bool trdos_paged = file.get(); diff --git a/Storage/State/SZX.cpp b/Storage/State/SZX.cpp index 9ea18f095..e03cbfb75 100644 --- a/Storage/State/SZX.cpp +++ b/Storage/State/SZX.cpp @@ -71,9 +71,10 @@ std::unique_ptr SZX::load(const std::filesystem::path [[maybe_unused]] const bool uses_late_timings = file_flags & 1; // Now parse all included blocks. + using FileUtils::LittleEndian::get; while(true) { - const auto blockID = file.get_le(); - const auto size = file.get_le(); + const auto blockID = get(file); + const auto size = get(file); if(file.eof()) break; const auto location = file.tell(); @@ -87,19 +88,19 @@ std::unique_ptr SZX::load(const std::filesystem::path state->z80.registers.flags = file.get(); state->z80.registers.a = file.get(); - state->z80.registers.bc = file.get_le(); - state->z80.registers.de = file.get_le(); - state->z80.registers.hl = file.get_le(); + state->z80.registers.bc = get(file); + state->z80.registers.de = get(file); + state->z80.registers.hl = get(file); - state->z80.registers.af_dash = file.get_le(); - state->z80.registers.bc_dash = file.get_le(); - state->z80.registers.de_dash = file.get_le(); - state->z80.registers.hl_dash = file.get_le(); + state->z80.registers.af_dash = get(file); + state->z80.registers.bc_dash = get(file); + state->z80.registers.de_dash = get(file); + state->z80.registers.hl_dash = get(file); - state->z80.registers.ix = file.get_le(); - state->z80.registers.iy = file.get_le(); - state->z80.registers.stack_pointer = file.get_le(); - state->z80.registers.program_counter = file.get_le(); + state->z80.registers.ix = get(file); + state->z80.registers.iy = get(file); + state->z80.registers.stack_pointer = get(file); + state->z80.registers.program_counter = get(file); const uint8_t i = file.get(); const uint8_t r = file.get(); @@ -109,7 +110,7 @@ std::unique_ptr SZX::load(const std::filesystem::path state->z80.registers.iff2 = file.get(); state->z80.registers.interrupt_mode = file.get(); - state->video.half_cycles_since_interrupt = int(file.get_le()) * 2; + state->video.half_cycles_since_interrupt = int(get(file)) * 2; // SZX includes a count of remaining cycles that interrupt should be asserted for // because it supports hardware that might cause an interrupt other than the display. @@ -123,7 +124,7 @@ std::unique_ptr SZX::load(const std::filesystem::path // verdict but I'm unclear what the effect of an invalid DD or FD is so // have not yet implemented this. - state->z80.registers.memptr = file.get_le(); + state->z80.registers.memptr = get(file); } break; // ZXSTAYBLOCK @@ -138,7 +139,7 @@ std::unique_ptr SZX::load(const std::filesystem::path // ZXSTRAMPAGE case block("RAMP"): { - const uint16_t flags = file.get_le(); + const uint16_t flags = get(file); const uint8_t page = file.get(); std::vector contents; diff --git a/Storage/State/Z80.cpp b/Storage/State/Z80.cpp index be8565ff3..3c24584fb 100644 --- a/Storage/State/Z80.cpp +++ b/Storage/State/Z80.cpp @@ -63,6 +63,7 @@ std::vector read_memory(Storage::FileHolder &file, const size_t size, c std::unique_ptr Z80::load(const std::filesystem::path &path) { FileHolder file(path); + using FileUtils::LittleEndian::get; // Construct a target with a Spectrum state. using Target = Analyser::Static::ZXSpectrum::Target; @@ -73,11 +74,11 @@ std::unique_ptr Z80::load(const std::filesystem::path // Read version 1 header. state->z80.registers.a = file.get(); state->z80.registers.flags = file.get(); - state->z80.registers.bc = file.get_le(); - state->z80.registers.hl = file.get_le(); - state->z80.registers.program_counter = file.get_le(); - state->z80.registers.stack_pointer = file.get_le(); - state->z80.registers.ir = file.get_be(); // Stored I then R. + state->z80.registers.bc = get(file); + state->z80.registers.hl = get(file); + state->z80.registers.program_counter = get(file); + state->z80.registers.stack_pointer = get(file); + state->z80.registers.ir = FileUtils::get(file); // Stored I then R. // Bit 7 of R is stored separately; likely this relates to an // optimisation in the Z80 emulator that for some reason was @@ -86,13 +87,13 @@ std::unique_ptr Z80::load(const std::filesystem::path const uint8_t misc = (raw_misc == 0xff) ? 1 : raw_misc; state->z80.registers.ir = uint16_t((state->z80.registers.ir & ~0x80) | ((misc&1) << 7)); - state->z80.registers.de = file.get_le(); - state->z80.registers.bc_dash = file.get_le(); - state->z80.registers.de_dash = file.get_le(); - state->z80.registers.hl_dash = file.get_le(); - state->z80.registers.af_dash = file.get_be(); // Stored A' then F'. - state->z80.registers.iy = file.get_le(); - state->z80.registers.ix = file.get_le(); + state->z80.registers.de = get(file); + state->z80.registers.bc_dash = get(file); + state->z80.registers.de_dash = get(file); + state->z80.registers.hl_dash = get(file); + state->z80.registers.af_dash = FileUtils::get(file); // Stored A' then F'. + state->z80.registers.iy = get(file); + state->z80.registers.ix = get(file); state->z80.registers.iff1 = bool(file.get()); state->z80.registers.iff2 = bool(file.get()); @@ -113,12 +114,12 @@ std::unique_ptr Z80::load(const std::filesystem::path } // This was a version 1 or 2 snapshot, so keep going... - const auto bonus_header_size = file.get_le(); + const auto bonus_header_size = get(file); if(bonus_header_size != 23 && bonus_header_size != 54 && bonus_header_size != 55) { return nullptr; } - state->z80.registers.program_counter = file.get_le(); + state->z80.registers.program_counter = get(file); const uint8_t model = file.get(); switch(model) { default: return nullptr; @@ -148,7 +149,7 @@ std::unique_ptr Z80::load(const std::filesystem::path if(bonus_header_size != 23) { // More Z80, the emulator, lack of encapsulation to deal with here. - const auto low_t_state = file.get_le(); + const auto low_t_state = get(file); const uint16_t high_t_state = file.get(); switch(result->model) { case Target::Model::SixteenK: @@ -183,7 +184,7 @@ std::unique_ptr Z80::load(const std::filesystem::path } while(true) { - const auto block_size = file.get_le(); + const auto block_size = get(file); const uint8_t page = file.get(); const auto location = file.tell(); if(file.eof()) break; diff --git a/Storage/Tape/Formats/CSW.cpp b/Storage/Tape/Formats/CSW.cpp index 4ddd6020a..e0cd3ddbc 100644 --- a/Storage/Tape/Formats/CSW.cpp +++ b/Storage/Tape/Formats/CSW.cpp @@ -36,7 +36,7 @@ CSW::CSW(const std::filesystem::path &path) { // The header now diverges based on version. CompressionType compression_type; if(major_version == 1) { - pulse_.length.clock_rate = file.get_le(); + pulse_.length.clock_rate = FileUtils::get(file); if(file.get() != 1) throw ErrorNotCSW; compression_type = CompressionType::RLE; @@ -45,7 +45,7 @@ CSW::CSW(const std::filesystem::path &path) { file.seek(0x20, Whence::SET); } else { - pulse_.length.clock_rate = file.get_le(); + pulse_.length.clock_rate = FileUtils::get(file); file.seek(4, Whence::CUR); // Skip number of waves. switch(file.get()) { case 1: compression_type = CompressionType::RLE; break; diff --git a/Storage/Tape/Formats/CommodoreTAP.cpp b/Storage/Tape/Formats/CommodoreTAP.cpp index 3220a4761..0b6eac482 100644 --- a/Storage/Tape/Formats/CommodoreTAP.cpp +++ b/Storage/Tape/Formats/CommodoreTAP.cpp @@ -89,7 +89,7 @@ Storage::Tape::Pulse CommodoreTAP::Serialiser::next_pulse() { if(!updated_layout_ || next_byte > 0) { next_length = uint32_t(next_byte) << 3; } else { - next_length = file_.get_le(); + next_length = FileUtils::get(file_); } if(file_.eof()) { diff --git a/Storage/Tape/Formats/MSXCAS.cpp b/Storage/Tape/Formats/MSXCAS.cpp index 852ca6c45..8cde3ede7 100644 --- a/Storage/Tape/Formats/MSXCAS.cpp +++ b/Storage/Tape/Formats/MSXCAS.cpp @@ -114,7 +114,7 @@ MSXCAS::MSXCAS(const std::filesystem::path &path) { } else { // Raw data appears now. Grab its length and keep going. file.seek(header_position + 8, Whence::SET); - const auto length = file.get_le(); + const auto length = FileUtils::get(file); file.seek(header_position + 8, Whence::SET); chunks_.emplace_back(false, false, file.read(size_t(length) + 2)); @@ -136,8 +136,8 @@ MSXCAS::MSXCAS(const std::filesystem::path &path) { // Get the start and end addresses in order to figure out how much data // is here. file.seek(header_position + 8, Whence::SET); - const auto start_address = file.get_le(); - const auto end_address = file.get_le(); + const auto start_address = FileUtils::get(file); + const auto end_address = FileUtils::get(file); file.seek(header_position + 8, Whence::SET); const auto length = end_address - start_address + 1; @@ -152,7 +152,7 @@ MSXCAS::MSXCAS(const std::filesystem::path &path) { file.seek(header_position + 8, Whence::SET); uint16_t address = 0x8001; // the BASIC start address. while(true) { - const auto next_line_address = file.get_le(); + const auto next_line_address = FileUtils::get(file); if(!next_line_address || file.eof()) break; file.seek(next_line_address - address - 2, Whence::CUR); address = next_line_address; diff --git a/Storage/Tape/Formats/TZX.cpp b/Storage/Tape/Formats/TZX.cpp index b23bbc6bf..5df192525 100644 --- a/Storage/Tape/Formats/TZX.cpp +++ b/Storage/Tape/Formats/TZX.cpp @@ -108,11 +108,13 @@ void TZX::Serialiser::push_next_pulses() { } void TZX::Serialiser::get_csw_recording_block() { - const auto block_length = file_.get_le(); - const auto pause_after_block = file_.get_le(); - const auto sampling_rate = file_.get_le(); + using FileUtils::LittleEndian::get; + + const auto block_length = get(file_); + const auto pause_after_block = get(file_); + const auto sampling_rate = get(file_); const auto compression_type = file_.get(); - const auto number_of_compressed_pulses = file_.get_le(); + const auto number_of_compressed_pulses = get(file_); std::vector raw_block = file_.read(block_length - 10); @@ -134,15 +136,17 @@ void TZX::Serialiser::get_csw_recording_block() { } void TZX::Serialiser::get_generalised_data_block() { - const auto block_length = file_.get_le(); - const long endpoint = file_.tell() + long(block_length); - const auto pause_after_block = file_.get_le(); + using FileUtils::LittleEndian::get; - const auto total_pilot_symbols = file_.get_le(); + const auto block_length = get(file_); + const long endpoint = file_.tell() + long(block_length); + const auto pause_after_block = get(file_); + + const auto total_pilot_symbols = get(file_); const uint8_t maximum_pulses_per_pilot_symbol = file_.get(); const uint8_t symbols_in_pilot_table = file_.get(); - const auto total_data_symbols = file_.get_le(); + const auto total_data_symbols = get(file_); const uint8_t maximum_pulses_per_data_symbol = file_.get(); const uint8_t symbols_in_data_table = file_.get(); @@ -160,6 +164,7 @@ void TZX::Serialiser::get_generalised_segment( const uint8_t number_of_symbols, const bool is_data ) { + using FileUtils::LittleEndian::get; if(!output_symbols) return; // Construct the symbol table. @@ -172,13 +177,13 @@ void TZX::Serialiser::get_generalised_segment( Symbol symbol; symbol.flags = file_.get(); for(int ic = 0; ic < max_pulses_per_symbol; ic++) { - symbol.pulse_lengths.push_back(file_.get_le()); + symbol.pulse_lengths.push_back(get(file_)); } symbol_table.push_back(symbol); } // Hence produce the output. - auto stream = file_.bitstream<8, false>(); + auto stream = FileUtils::bitstream<8, false>(file_); int base = 2; size_t bits = 1; while(base < number_of_symbols) { @@ -193,7 +198,7 @@ void TZX::Serialiser::get_generalised_segment( count = 1; } else { symbol_value = file_.get(); - count = file_.get_le(); + count = get(file_); } if(symbol_value > number_of_symbols) { continue; @@ -227,8 +232,9 @@ void TZX::Serialiser::get_standard_speed_data_block() { data_block.data.length_of_one_bit_pulse = 1710; data_block.data.number_of_bits_in_final_byte = 8; - data_block.data.pause_after_block = file_.get_le(); - data_block.data.data_length = file_.get_le(); + using FileUtils::LittleEndian::get; + data_block.data.pause_after_block = get(file_); + data_block.data.data_length = get(file_); if(!data_block.data.data_length) return; const uint8_t first_byte = file_.get(); @@ -240,15 +246,16 @@ void TZX::Serialiser::get_standard_speed_data_block() { void TZX::Serialiser::get_turbo_speed_data_block() { DataBlock data_block; - data_block.length_of_pilot_pulse = file_.get_le(); - data_block.length_of_sync_first_pulse = file_.get_le(); - data_block.length_of_sync_second_pulse = file_.get_le(); - data_block.data.length_of_zero_bit_pulse = file_.get_le(); - data_block.data.length_of_one_bit_pulse = file_.get_le(); - data_block.length_of_pilot_tone = file_.get_le(); + using FileUtils::LittleEndian::get; + data_block.length_of_pilot_pulse = get(file_); + data_block.length_of_sync_first_pulse = get(file_); + data_block.length_of_sync_second_pulse = get(file_); + data_block.data.length_of_zero_bit_pulse = get(file_); + data_block.data.length_of_one_bit_pulse = get(file_); + data_block.length_of_pilot_tone = get(file_); data_block.data.number_of_bits_in_final_byte = file_.get(); - data_block.data.pause_after_block = file_.get_le(); - data_block.data.data_length = file_.get_le(); + data_block.data.pause_after_block = get(file_); + data_block.data.data_length = get(file_); get_data_block(data_block); } @@ -284,28 +291,31 @@ void TZX::Serialiser::get_data(const Data &data) { } void TZX::Serialiser::get_pure_tone_data_block() { - const auto length_of_pulse = file_.get_le(); - const auto nunber_of_pulses = file_.get_le(); + using FileUtils::LittleEndian::get; + const auto length_of_pulse = get(file_); + const auto nunber_of_pulses = get(file_); post_pulses(nunber_of_pulses, length_of_pulse); } void TZX::Serialiser::get_pure_data_block() { Data data; - data.length_of_zero_bit_pulse = file_.get_le(); - data.length_of_one_bit_pulse = file_.get_le(); + using FileUtils::LittleEndian::get; + data.length_of_zero_bit_pulse = get(file_); + data.length_of_one_bit_pulse = get(file_); data.number_of_bits_in_final_byte = file_.get(); - data.pause_after_block = file_.get_le(); - data.data_length = file_.get_le(); + data.pause_after_block = get(file_); + data.data_length = get(file_); get_data(data); } void TZX::Serialiser::get_direct_recording_block() { - const Storage::Time length_per_sample(unsigned(file_.get_le()), StandardTZXClock); - const auto pause_after_block = file_.get_le(); + using FileUtils::LittleEndian::get; + const Storage::Time length_per_sample(unsigned(get(file_)), StandardTZXClock); + const auto pause_after_block = get(file_); const uint8_t used_bits_in_final_byte = std::clamp(file_.get(), 1, 8); - const auto length_of_data = file_.get_le(); + const auto length_of_data = get(file_); unsigned int bits_at_level = 0; bool level = false; @@ -341,12 +351,12 @@ void TZX::Serialiser::get_direct_recording_block() { void TZX::Serialiser::get_pulse_sequence() { uint8_t number_of_pulses = file_.get(); while(number_of_pulses--) { - post_pulse(file_.get_le()); + post_pulse(FileUtils::get(file_)); } } void TZX::Serialiser::get_pause() { - const auto duration = file_.get_le(); + const auto duration = FileUtils::get(file_); if(!duration) { // TODO (maybe): post a 'pause the tape' suggestion } else { @@ -361,14 +371,15 @@ void TZX::Serialiser::get_set_signal_level() { } void TZX::Serialiser::get_kansas_city_block() { - auto block_length = file_.get_le(); + using FileUtils::LittleEndian::get; + auto block_length = get(file_); - const auto pause_after_block = file_.get_le(); - const auto pilot_pulse_duration = file_.get_le(); - const auto pilot_length = file_.get_le(); + const auto pause_after_block = get(file_); + const auto pilot_pulse_duration = get(file_); + const auto pilot_length = get(file_); uint16_t pulse_durations[2]; - pulse_durations[0] = file_.get_le(); - pulse_durations[1] = file_.get_le(); + pulse_durations[0] = get(file_); + pulse_durations[1] = get(file_); const uint8_t packed_pulse_counts = file_.get(); const unsigned int pulse_counts[2] = { unsigned((((packed_pulse_counts >> 4) - 1) & 15) + 1), @@ -452,12 +463,12 @@ void TZX::Serialiser::ignore_group_end() { } void TZX::Serialiser::ignore_jump_to_block() { - const auto target = file_.get_le(); + const auto target = FileUtils::get(file_); (void)target; } void TZX::Serialiser::ignore_loop_start() { - const auto number_of_repetitions = file_.get_le(); + const auto number_of_repetitions = FileUtils::get(file_); (void)number_of_repetitions; } @@ -465,7 +476,7 @@ void TZX::Serialiser::ignore_loop_end() { } void TZX::Serialiser::ignore_call_sequence() { - const auto number_of_entries = file_.get_le(); + const auto number_of_entries = FileUtils::get(file_); file_.seek(number_of_entries * sizeof(uint16_t), Whence::CUR); } @@ -473,7 +484,7 @@ void TZX::Serialiser::ignore_return_from_sequence() { } void TZX::Serialiser::ignore_select_block() { - const auto length_of_block = file_.get_le(); + const auto length_of_block = FileUtils::get(file_); file_.seek(length_of_block, Whence::CUR); } @@ -483,7 +494,7 @@ void TZX::Serialiser::ignore_stop_tape_if_in_48kb_mode() { void TZX::Serialiser::ignore_custom_info_block() { file_.seek(0x10, Whence::CUR); - const auto length = file_.get_le(); + const auto length = FileUtils::get(file_); file_.seek(length, Whence::CUR); } @@ -502,7 +513,7 @@ void TZX::Serialiser::ignore_message_block() { } void TZX::Serialiser::ignore_archive_info() { - const auto length = file_.get_le(); + const auto length = FileUtils::get(file_); file_.seek(length, Whence::CUR); } diff --git a/Storage/Tape/Formats/TapePRG.cpp b/Storage/Tape/Formats/TapePRG.cpp index 64541f8c8..1f2af0851 100644 --- a/Storage/Tape/Formats/TapePRG.cpp +++ b/Storage/Tape/Formats/TapePRG.cpp @@ -56,7 +56,7 @@ PRG::PRG(const std::filesystem::path &path) : path_(path) { if(file.stats().st_size >= 65538 || file.stats().st_size < 3) throw ErrorBadFormat; - load_address_ = file.get_le(); + load_address_ = FileUtils::get(file); length_ = uint16_t(file.stats().st_size - 2); if(load_address_ + length_ >= 65536) diff --git a/Storage/Tape/Formats/ZXSpectrumTAP.cpp b/Storage/Tape/Formats/ZXSpectrumTAP.cpp index fe09d4255..4105af470 100644 --- a/Storage/Tape/Formats/ZXSpectrumTAP.cpp +++ b/Storage/Tape/Formats/ZXSpectrumTAP.cpp @@ -27,7 +27,7 @@ ZXSpectrumTAP::ZXSpectrumTAP(const std::filesystem::path &path) : path_(path) { // To consider: could also check those blocks of type 0 // and type ff for valid checksums? while(file.tell() != file.stats().st_size) { - const uint16_t block_length = file.get_le(); + const uint16_t block_length = FileUtils::get(file); if(file.eof() || file.tell() + block_length > file.stats().st_size) { throw ErrorNotZXSpectrumTAP; } @@ -121,7 +121,7 @@ void ZXSpectrumTAP::Serialiser::read_next_block() { if(file_.tell() == file_.stats().st_size) { phase_ = Phase::Gap; } else { - block_length_ = file_.get_le(); + block_length_ = FileUtils::get(file_); data_byte_ = block_type_ = file_.get(); phase_ = Phase::PilotTone; }