Grab full first file for analysis.
This commit is contained in:
1 parent
296c5ed1a7
commit
602b6a115e
4 files changed
+67
-17
No files matched your search
@@ -81,30 +81,27 @@ Analyser::Static::TargetList Analyser::Static::Thomson::GetTargets(
|
||||
Storage::Tape::Thomson::MO::Parser parser;
|
||||
auto &tape = media.tapes.front();
|
||||
const auto serialiser = tape->serialiser();
|
||||
const auto first = parser.block(*serialiser);
|
||||
const auto first = parser.file(*serialiser);
|
||||
|
||||
if(first && first->checksum_valid()) {
|
||||
if(first && first->checksums_valid) {
|
||||
target->media.tapes = media.tapes;
|
||||
|
||||
// Cf. https://pulkomandy.tk/wiki/doku.php?id=documentations:monitor:tape.format for leader block format;
|
||||
// my parser provides block type separately and length implicitly so the type at offset 0xd is at 0xb
|
||||
// in ->data.
|
||||
static constexpr size_t TypeOffset = 0xb;
|
||||
if(!first->type && first->data.size() > TypeOffset) {
|
||||
const auto command = [&]() -> std::wstring {
|
||||
if(!first->data[TypeOffset]) { // File type; 0 = BASIC, 1 = DATA; 2 = binary.
|
||||
return L"RUN\"";
|
||||
} else {
|
||||
return L"LOADM\"\",,R";
|
||||
}
|
||||
};
|
||||
|
||||
// TODO: determine whether BASIC 1 or BASIC 128 is appropriate.
|
||||
if(DefaultMO6) {
|
||||
target->loading_command = std::wstring(L"2 ") + command() + L"\n";
|
||||
const auto command = [&]() -> std::wstring {
|
||||
if(!first->type) { // File type; 0 = BASIC, 1 = DATA; 2 = binary.
|
||||
return L"RUN\"";
|
||||
} else {
|
||||
target->loading_command = command() + L"\n";
|
||||
return L"LOADM\"\",,R";
|
||||
}
|
||||
};
|
||||
|
||||
// TODO: determine whether BASIC 1 or BASIC 128 is appropriate.
|
||||
if(DefaultMO6) {
|
||||
target->loading_command = std::wstring(L"2 ") + command() + L"\n";
|
||||
} else {
|
||||
target->loading_command = command() + L"\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -286,7 +286,7 @@ private:
|
||||
}
|
||||
|
||||
#ifndef NDEBUG
|
||||
std::atomic_flag flush_concurrency_check_{};
|
||||
std::atomic_flag flush_concurrency_check_ = ATOMIC_FLAG_INIT;
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
@@ -92,6 +92,44 @@ std::optional<Block> Parser::block(Storage::Tape::TapeSerialiser &serialiser) {
|
||||
return result;
|
||||
}
|
||||
|
||||
std::optional<File> Parser::file(Storage::Tape::TapeSerialiser &serialiser) {
|
||||
std::optional<File> result;
|
||||
|
||||
do {
|
||||
// Find next leader.
|
||||
const auto leader = block(serialiser);
|
||||
if(!leader.has_value()) break;
|
||||
if(leader->type != 0) continue;
|
||||
if(leader->data.size() != 14) continue;
|
||||
|
||||
// Create file.
|
||||
result = File();
|
||||
const auto copy_string = [&](auto &target, const size_t offset) {
|
||||
std::copy_n(leader->data.data() + offset, sizeof(target) - 1, target);
|
||||
|
||||
auto end = std::find_if(std::rbegin(target) + 1, std::rend(target), [](const char c) {
|
||||
return c != ' ';
|
||||
});
|
||||
*(end - 1) = '\0';
|
||||
};
|
||||
|
||||
copy_string(result->name, 0);
|
||||
copy_string(result->extension, 8);
|
||||
|
||||
result->type = leader->data[11];
|
||||
result->mode = uint16_t((leader->data[12] << 8) | leader->data[13]);
|
||||
|
||||
// Accumulate data for as long as it comes.
|
||||
while(true) {
|
||||
const auto next = block(serialiser);
|
||||
if(next->type != 1) break;
|
||||
std::copy(next->data.begin(), next->data.end(), std::back_inserter(result->data));
|
||||
}
|
||||
} while(false);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
uint8_t Block::check_digit() const {
|
||||
return uint8_t(checksum - std::accumulate(data.begin(), data.end(), 0));
|
||||
}
|
||||
@@ -27,11 +27,26 @@ struct Block {
|
||||
uint8_t check_digit() const;
|
||||
};
|
||||
|
||||
struct File {
|
||||
char name[9]{};
|
||||
char extension[4]{};
|
||||
std::string filename() const {
|
||||
return std::string(name) + '.' + extension;
|
||||
}
|
||||
|
||||
uint8_t type = 0;
|
||||
uint16_t mode = 0;
|
||||
|
||||
std::vector<uint8_t> data;
|
||||
bool checksums_valid = true;
|
||||
};
|
||||
|
||||
class Parser {
|
||||
public:
|
||||
std::optional<bool> bit(Storage::Tape::TapeSerialiser &);
|
||||
std::optional<uint8_t> byte(Storage::Tape::TapeSerialiser &);
|
||||
std::optional<Block> block(Storage::Tape::TapeSerialiser &);
|
||||
std::optional<File> file(Storage::Tape::TapeSerialiser &);
|
||||
|
||||
void seed_level(Pulse::Type);
|
||||
|
||||
|
||||
Reference in new issue
Block a user