1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-11-26 23:52:26 +00:00
CLK/StaticAnalyser/Oric/Tape.cpp

86 lines
2.8 KiB
C++

//
// Tape.cpp
// Clock Signal
//
// Created by Thomas Harte on 06/11/2016.
// Copyright © 2016 Thomas Harte. All rights reserved.
//
#include "Tape.hpp"
#include "../../Storage/Tape/Parsers/Oric.hpp"
using namespace StaticAnalyser::Oric;
std::list<File> StaticAnalyser::Oric::GetFiles(const std::shared_ptr<Storage::Tape::Tape> &tape) {
std::list<File> files;
Storage::Tape::Oric::Parser parser;
while(!tape->is_at_end()) {
// sync to next lead-in, check that it's one of three 0x16s
bool is_fast = parser.sync_and_get_encoding_speed(tape);
int next_bytes[2];
next_bytes[0] = parser.get_next_byte(tape, is_fast);
next_bytes[1] = parser.get_next_byte(tape, is_fast);
if(next_bytes[0] != 0x16 || next_bytes[1] != 0x16) continue;
// get the first byte that isn't a 0x16, check it was a 0x24
int byte = 0x16;
while(!tape->is_at_end() && byte == 0x16) {
byte = parser.get_next_byte(tape, is_fast);
}
if(byte != 0x24) continue;
// skip two empty bytes
parser.get_next_byte(tape, is_fast);
parser.get_next_byte(tape, is_fast);
// get data and launch types
File new_file;
switch(parser.get_next_byte(tape, is_fast)) {
case 0x00: new_file.data_type = File::ProgramType::BASIC; break;
case 0x80: new_file.data_type = File::ProgramType::MachineCode; break;
default: new_file.data_type = File::ProgramType::None; break;
}
switch(parser.get_next_byte(tape, is_fast)) {
case 0x80: new_file.launch_type = File::ProgramType::BASIC; break;
case 0xc7: new_file.launch_type = File::ProgramType::MachineCode; break;
default: new_file.launch_type = File::ProgramType::None; break;
}
// read end and start addresses
new_file.ending_address = static_cast<uint16_t>(parser.get_next_byte(tape, is_fast) << 8);
new_file.ending_address |= static_cast<uint16_t>(parser.get_next_byte(tape, is_fast));
new_file.starting_address = static_cast<uint16_t>(parser.get_next_byte(tape, is_fast) << 8);
new_file.starting_address |= static_cast<uint16_t>(parser.get_next_byte(tape, is_fast));
// skip an empty byte
parser.get_next_byte(tape, is_fast);
// read file name, up to 16 characters and null terminated
char file_name[17];
int name_pos = 0;
while(name_pos < 16) {
file_name[name_pos] = (char)parser.get_next_byte(tape, is_fast);
if(!file_name[name_pos]) break;
name_pos++;
}
file_name[16] = '\0';
new_file.name = file_name;
// read body
size_t body_length = new_file.ending_address - new_file.starting_address + 1;
new_file.data.reserve(body_length);
for(size_t c = 0; c < body_length; c++) {
new_file.data.push_back(static_cast<uint8_t>(parser.get_next_byte(tape, is_fast)));
}
// only one validation check: was there enough tape?
if(!tape->is_at_end()) {
files.push_back(new_file);
}
}
return files;
}