1
0
mirror of https://github.com/TomHarte/CLK.git synced 2025-08-08 14:25:05 +00:00

I think this should lead to a full representation of files on an Acorn tape, but subject to is_at_end working.

This commit is contained in:
Thomas Harte
2016-08-31 19:57:09 -04:00
parent 7b5d5858ff
commit d8c0da7ccb
3 changed files with 56 additions and 6 deletions

View File

@@ -71,6 +71,6 @@ void StaticAnalyser::Acorn::AddTargets(
{ {
std::shared_ptr<Storage::Tape::Tape> tape = tapes.front(); std::shared_ptr<Storage::Tape::Tape> tape = tapes.front();
tape->reset(); tape->reset();
GetNextFile(tape); GetFiles(tape);
} }
} }

View File

@@ -185,6 +185,7 @@ static std::unique_ptr<File::Chunk> GetNextChunk(TapeParser &parser)
if(!name[name_ptr]) break; if(!name[name_ptr]) break;
name_ptr++; name_ptr++;
} }
new_chunk->name = name;
// addresses // addresses
new_chunk->load_address = (uint32_t)parser.get_next_word(); new_chunk->load_address = (uint32_t)parser.get_next_word();
@@ -206,7 +207,7 @@ static std::unique_ptr<File::Chunk> GetNextChunk(TapeParser &parser)
new_chunk->data.push_back((uint8_t)parser.get_next_byte()); new_chunk->data.push_back((uint8_t)parser.get_next_byte());
} }
if(new_chunk->block_length) if(new_chunk->block_length && !new_chunk->block_flag&0x40)
{ {
uint16_t calculated_data_crc = parser.get_crc(); uint16_t calculated_data_crc = parser.get_crc();
uint16_t stored_data_crc = (uint16_t)parser.get_next_short(); uint16_t stored_data_crc = (uint16_t)parser.get_next_short();
@@ -221,11 +222,59 @@ static std::unique_ptr<File::Chunk> GetNextChunk(TapeParser &parser)
return parser.get_error_flag() ? nullptr : std::move(new_chunk); return parser.get_error_flag() ? nullptr : std::move(new_chunk);
} }
std::unique_ptr<File> StaticAnalyser::Acorn::GetNextFile(const std::shared_ptr<Storage::Tape::Tape> &tape) std::unique_ptr<File> GetNextFile(TapeParser &parser)
{
std::unique_ptr<File::Chunk> chunk;
// find next chunk with a block number of 0
while(!parser.is_at_end())
{
chunk = GetNextChunk(parser);
if(!chunk) continue;
if(chunk->block_number) continue;
}
// accumulate chunks for as long as block number is sequential and the end-of-file bit isn't set
std::unique_ptr<File> file(new File);
file->chunks.push_back(*chunk);
while(!parser.is_at_end())
{
std::unique_ptr<File::Chunk> next_chunk = GetNextChunk(parser);
if(!next_chunk) return nullptr;
if(next_chunk->block_number != chunk->block_number + 1) return nullptr;
file->chunks.push_back(*next_chunk);
chunk = std::move(next_chunk);
if(chunk->block_flag&0x80) break;
}
// accumulate total data, copy flags appropriately
file->name = file->chunks.front().name;
file->load_address = file->chunks.front().load_address;
file->execution_address = file->chunks.front().execution_address;
file->is_protected = !!(file->chunks.back().block_flag & 0x01); // I think the last flags are the ones that count; TODO: check.
// copy all data into a single big block
for(File::Chunk chunk : file->chunks)
{
file->data.insert(file->data.end(), chunk.data.begin(), chunk.data.end());
}
return file;
}
std::list<File> StaticAnalyser::Acorn::GetFiles(const std::shared_ptr<Storage::Tape::Tape> &tape)
{ {
TapeParser parser(tape); TapeParser parser(tape);
std::list<File> file_list;
GetNextChunk(parser); while(!parser.is_at_end())
{
return nullptr; std::unique_ptr<File> next_file = GetNextFile(parser);
if(next_file)
{
file_list.push_back(*next_file);
}
}
return file_list;
} }

View File

@@ -27,6 +27,7 @@ struct File {
std::vector<uint8_t> data; std::vector<uint8_t> data;
struct Chunk { struct Chunk {
std::string name;
uint32_t load_address; uint32_t load_address;
uint32_t execution_address; uint32_t execution_address;
uint16_t block_number; uint16_t block_number;
@@ -42,7 +43,7 @@ struct File {
std::list<Chunk> chunks; std::list<Chunk> chunks;
}; };
std::unique_ptr<File> GetNextFile(const std::shared_ptr<Storage::Tape::Tape> &tape); std::list<File> GetFiles(const std::shared_ptr<Storage::Tape::Tape> &tape);
} }
} }