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

Started working towards capturing everything there is to know about a file. CRC calculation appears to be flawed somehow at the moment.

This commit is contained in:
Thomas Harte
2016-08-30 07:38:08 -04:00
parent 6218f05b8c
commit b3521ed187
2 changed files with 138 additions and 30 deletions

View File

@@ -11,36 +11,33 @@
using namespace StaticAnalyser::Acorn; using namespace StaticAnalyser::Acorn;
struct TapeParser { struct TapeParser {
float wave_lengths[4];
int wave_length_pointer;
TapeParser() : wave_length_pointer(0) {} TapeParser(const std::shared_ptr<Storage::Tape::Tape> &tape) : _wave_length_pointer(0), _tape(tape) {}
int GetNextBit(const std::shared_ptr<Storage::Tape::Tape> &tape) int get_next_bit()
{ {
while(!tape->is_at_end()) while(!_tape->is_at_end())
{ {
// skip any gaps // skip any gaps
Storage::Tape::Tape::Pulse next_pulse = tape->get_next_pulse(); Storage::Tape::Tape::Pulse next_pulse = _tape->get_next_pulse();
while(next_pulse.type == Storage::Tape::Tape::Pulse::Zero) while(next_pulse.type == Storage::Tape::Tape::Pulse::Zero)
{ {
next_pulse = tape->get_next_pulse(); next_pulse = _tape->get_next_pulse();
} }
wave_lengths[wave_length_pointer] = next_pulse.length.get_float(); _wave_lengths[_wave_length_pointer] = next_pulse.length.get_float();
wave_length_pointer++; _wave_length_pointer++;
// if first wave is too short or too long, drop it // if first wave is too short or too long, drop it
if(wave_lengths[0] < 1.0f / 4800.0f || wave_lengths[0] >= 5.0f / 4800.0f) if(_wave_lengths[0] < 1.0f / 4800.0f || _wave_lengths[0] >= 5.0f / 4800.0f)
{ {
rotate(1); rotate(1);
continue;
} }
// if first two waves add up to a correct-length cycle, pop them and this is a 0 // if first two waves add up to a correct-length cycle, pop them and this is a 0
if(wave_length_pointer >= 2) if(_wave_length_pointer >= 2)
{ {
float length = wave_lengths[0] + wave_lengths[1]; float length = _wave_lengths[0] + _wave_lengths[1];
if(length >= 3.0f / 4800.0f && length < 5.0f / 4800.0f) if(length >= 3.0f / 4800.0f && length < 5.0f / 4800.0f)
{ {
rotate(2); rotate(2);
@@ -49,70 +46,165 @@ struct TapeParser {
} }
// if all four waves add up to a correct-length cycle, pop them and this is a 1 // if all four waves add up to a correct-length cycle, pop them and this is a 1
if(wave_length_pointer >= 4) if(_wave_length_pointer == 4)
{ {
float length = wave_lengths[0] + wave_lengths[1] + wave_lengths[2] + wave_lengths[3]; float length = _wave_lengths[0] + _wave_lengths[1] + _wave_lengths[2] + _wave_lengths[3];
if(length >= 3.0f / 4800.0f && length < 5.0f / 4800.0f) if(length >= 3.0f / 4800.0f && length < 5.0f / 4800.0f)
{ {
rotate(4); rotate(4);
return 1; return 1;
} }
else
{
rotate(1);
}
} }
} }
return 0; return 0;
} }
int GetNextByte(const std::shared_ptr<Storage::Tape::Tape> &tape) int get_next_byte()
{ {
int value = 0; int value = 0;
int c = 8; int c = 8;
if(GetNextBit(tape)) return -1; if(get_next_bit())
{
_error_flag = true;
return -1;
}
while(c--) while(c--)
{ {
value = (value >> 1) | (GetNextBit(tape) << 7); value = (value >> 1) | (get_next_bit() << 7);
} }
if(!GetNextBit(tape)) return -1; if(!get_next_bit())
{
_error_flag = true;
return -1;
}
add_to_crc((uint8_t)value);
return value; return value;
} }
int get_next_short()
{
int result = get_next_byte();
result |= get_next_byte() << 8;
return result;
}
int get_next_word()
{
int result = get_next_short();
result |= get_next_short() << 8;
return result;
}
void reset_error_flag()
{
_error_flag = false;
}
bool get_error_flag()
{
return _error_flag;
}
void reset_crc()
{
_crc = 0;
}
void add_to_crc(uint8_t value)
{
_crc ^= (uint16_t)value << 8;
for(int c = 0; c < 8; c++)
{
uint16_t exclusive_or = (_crc&0x8000) ? 0x1021 : 0x0000;
_crc = (uint16_t)(_crc << 1) ^ exclusive_or;
}
}
uint16_t get_crc()
{
return _crc;
}
bool is_at_end()
{
return _tape->is_at_end();
}
private: private:
void rotate(int places) void rotate(int places)
{ {
wave_length_pointer -= places; _wave_length_pointer -= places;
if(places < 4) memmove(wave_lengths, &wave_lengths[places], (size_t)(4 - places) * sizeof(float)); if(places < 4) memmove(_wave_lengths, &_wave_lengths[places], (size_t)(4 - places) * sizeof(float));
} }
uint16_t _crc;
bool _error_flag;
float _wave_lengths[4];
int _wave_length_pointer;
std::shared_ptr<Storage::Tape::Tape> _tape;
}; };
std::unique_ptr<File> StaticAnalyser::Acorn::GetNextFile(const std::shared_ptr<Storage::Tape::Tape> &tape) static std::unique_ptr<File::Chunk> GetNextChunk(TapeParser &parser)
{ {
std::unique_ptr<File::Chunk> new_chunk(new File::Chunk);
int shift_register = 0; int shift_register = 0;
TapeParser parser;
#define shift() \ #define shift() \
shift_register = (shift_register >> 1) | (parser.GetNextBit(tape) << 9) shift_register = (shift_register >> 1) | (parser.get_next_bit() << 9)
// find next area of high tone // find next area of high tone
while(!tape->is_at_end() && (shift_register != 0x3ff)) while(!parser.is_at_end() && (shift_register != 0x3ff))
{ {
shift(); shift();
} }
// find next 0x2a (swallowing stop bit) // find next 0x2a (swallowing stop bit)
while(!tape->is_at_end() && (shift_register != 0x254)) while(!parser.is_at_end() && (shift_register != 0x254))
{ {
shift(); shift();
} }
parser.reset_crc();
parser.reset_error_flag();
// read out name // read out name
char name[10]; char name[10];
int name_ptr = 0; int name_ptr = 0;
while(!tape->is_at_end() && name_ptr < 10) while(!parser.is_at_end() && name_ptr < 10)
{ {
name[name_ptr] = (char)parser.GetNextByte(tape); name[name_ptr] = (char)parser.get_next_byte();
if(!name[name_ptr]) break; if(!name[name_ptr]) break;
name_ptr++; name_ptr++;
} }
// addresses
new_chunk->load_address = (uint32_t)parser.get_next_word();
new_chunk->execution_address = (uint32_t)parser.get_next_word();
new_chunk->block_number = (uint16_t)parser.get_next_short();
new_chunk->block_length = (uint16_t)parser.get_next_short();
new_chunk->block_flag = (uint8_t)parser.get_next_byte();
new_chunk->next_address = (uint32_t)parser.get_next_word();
uint16_t calculated_crc = parser.get_crc();
uint16_t stored_crc = (uint16_t)parser.get_next_short();
printf("%04x v %04x", calculated_crc, stored_crc);
return nullptr;
}
std::unique_ptr<File> StaticAnalyser::Acorn::GetNextFile(const std::shared_ptr<Storage::Tape::Tape> &tape)
{
TapeParser parser(tape);
GetNextChunk(parser);
return nullptr; return nullptr;
} }

View File

@@ -9,6 +9,7 @@
#ifndef StaticAnalyser_Acorn_Tape_hpp #ifndef StaticAnalyser_Acorn_Tape_hpp
#define StaticAnalyser_Acorn_Tape_hpp #define StaticAnalyser_Acorn_Tape_hpp
#include <list>
#include <memory> #include <memory>
#include <string> #include <string>
#include <vector> #include <vector>
@@ -20,10 +21,25 @@ namespace Acorn {
struct File { struct File {
std::string name; std::string name;
uint16_t load_address; uint32_t load_address;
uint16_t execution_address; uint32_t execution_address;
bool is_protected; bool is_protected;
std::vector<uint8_t> data; std::vector<uint8_t> data;
struct Chunk {
uint32_t load_address;
uint32_t execution_address;
uint16_t block_number;
uint16_t block_length;
uint8_t block_flag;
uint32_t next_address;
bool header_crc_matched;
bool data_crc_matched;
std::vector<uint8_t> data;
};
std::list<Chunk> chunks;
}; };
std::unique_ptr<File> GetNextFile(const std::shared_ptr<Storage::Tape::Tape> &tape); std::unique_ptr<File> GetNextFile(const std::shared_ptr<Storage::Tape::Tape> &tape);