1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-11-17 10:06:21 +00:00

Further relax Apple GCR static analysis requirements.

This commit is contained in:
Thomas Harte 2020-07-20 19:50:33 -04:00
parent 84dd194afd
commit 5ebbab6f35
2 changed files with 28 additions and 25 deletions

View File

@ -21,9 +21,9 @@ struct Sector {
Describes the location of a sector, implementing < to allow for use as a set key.
*/
struct Address {
struct {
union {
/// For Apple II-type sectors, provides the volume number.
uint_fast8_t volume = 0;
uint_fast8_t volume;
/// For Macintosh-type sectors, provides the format from the sector header.
uint_fast8_t format = 0;
};

View File

@ -57,14 +57,14 @@ uint8_t unmap_five_and_three(uint8_t source) {
return five_and_three_unmapping[source - 0xab];
}
std::unique_ptr<Sector> decode_macintosh_sector(const std::array<uint_fast8_t, 8> &header, const std::unique_ptr<Sector> &original) {
// There must be at least 704 bytes to decode from.
if(original->data.size() < 704) return nullptr;
std::unique_ptr<Sector> decode_macintosh_sector(const std::array<uint_fast8_t, 8> *header, const std::unique_ptr<Sector> &original) {
// There must be a header and at least 704 bytes to decode from.
if(!header || original->data.size() < 704) return nullptr;
// Attempt a six-and-two unmapping of the header.
std::array<uint_fast8_t, 5> decoded_header;
for(size_t c = 0; c < decoded_header.size(); ++c) {
decoded_header[c] = unmap_six_and_two(header[c]);
decoded_header[c] = unmap_six_and_two((*header)[c]);
if(decoded_header[c] == 0xff) {
return nullptr;
}
@ -140,29 +140,32 @@ std::unique_ptr<Sector> decode_macintosh_sector(const std::array<uint_fast8_t, 8
return sector;
}
std::unique_ptr<Sector> decode_appleii_sector(const std::array<uint_fast8_t, 8> &header, const std::unique_ptr<Sector> &original, bool is_five_and_three) {
std::unique_ptr<Sector> decode_appleii_sector(const std::array<uint_fast8_t, 8> *header, const std::unique_ptr<Sector> &original, bool is_five_and_three) {
// There must be at least 411 bytes to decode a five-and-three sector from;
// there must be only 343 if this is a six-and-two sector.
const size_t data_size = is_five_and_three ? 411 : 343;
if(original->data.size() < data_size) return nullptr;
// Check for apparent four and four encoding.
uint_fast8_t header_mask = 0xff;
for(auto c : header) header_mask &= c;
header_mask &= 0xaa;
if(header_mask != 0xaa) return nullptr;
// Allocate a sector and fill the header fields.
// Allocate a sector.
auto sector = std::make_unique<Sector>();
sector->data.resize(data_size);
sector->address.volume = ((header[0] << 1) | 1) & header[1];
sector->address.track = ((header[2] << 1) | 1) & header[3];
sector->address.sector = ((header[4] << 1) | 1) & header[5];
// If there is a header, check for apparent four and four encoding.
if(header) {
uint_fast8_t header_mask = 0xff;
for(auto c : *header) header_mask &= c;
header_mask &= 0xaa;
if(header_mask != 0xaa) return nullptr;
// Fill the header fields.
sector->address.volume = (((*header)[0] << 1) | 1) & (*header)[1];
sector->address.track = (((*header)[2] << 1) | 1) & (*header)[3];
sector->address.sector = (((*header)[4] << 1) | 1) & (*header)[5];
// Check the header checksum.
const uint_fast8_t checksum = ((header[6] << 1) | 1) & header[7];
const uint_fast8_t checksum = (((*header)[6] << 1) | 1) & (*header)[7];
if(checksum != (sector->address.volume^sector->address.track^sector->address.sector)) return nullptr;
}
// Unmap the sector contents.
for(size_t index = 0; index < data_size; ++index) {
@ -178,9 +181,6 @@ std::unique_ptr<Sector> decode_appleii_sector(const std::array<uint_fast8_t, 8>
}
if(sector->data.back()) return nullptr;
// Having checked the checksum, remove it.
sector->data.resize(sector->data.size() - 1);
if(is_five_and_three) {
// TODO: the below is almost certainly incorrect; Beneath Apple DOS partly documents
// the process, enough to give the basic outline below of how five source bytes are
@ -250,6 +250,7 @@ std::map<std::size_t, Sector> Storage::Encodings::AppleGCR::sectors_from_segment
size_t bit = 0;
int header_delay = 0;
bool is_five_and_three = false;
bool has_header = false;
while(bit < segment.data.size() || pointer != scanning_sentinel || header_delay) {
shift_register = uint_fast8_t((shift_register << 1) | (segment.data[bit % segment.data.size()] ? 1 : 0));
++bit;
@ -290,6 +291,7 @@ std::map<std::size_t, Sector> Storage::Encodings::AppleGCR::sectors_from_segment
sector_location = size_t(bit % segment.data.size());
header_delay = 200; // Allow up to 200 bytes to find the body, if the
// track split comes in between.
has_header = true;
}
}
} else {
@ -308,18 +310,19 @@ std::map<std::size_t, Sector> Storage::Encodings::AppleGCR::sectors_from_segment
pointer = scanning_sentinel;
// Potentially this is a Macintosh sector.
auto macintosh_sector = decode_macintosh_sector(header, sector);
auto macintosh_sector = decode_macintosh_sector(has_header ? &header : nullptr, sector);
if(macintosh_sector) {
result.insert(std::make_pair(sector_location, std::move(*macintosh_sector)));
continue;
}
// Apple II then?
auto appleii_sector = decode_appleii_sector(header, sector, is_five_and_three);
auto appleii_sector = decode_appleii_sector(has_header ? &header : nullptr, sector, is_five_and_three);
if(appleii_sector) {
result.insert(std::make_pair(sector_location, std::move(*appleii_sector)));
}
has_header = false;
} else {
new_sector->data.push_back(value);
}