1
0
mirror of https://github.com/TomHarte/CLK.git synced 2025-01-11 08:30:55 +00:00

Made a quick first attempt at getting a file name from Acorn tape, failing terribly but at least formalising tapes being able to signal their end.

This commit is contained in:
Thomas Harte 2016-08-29 21:53:06 -04:00
parent 0032ad2634
commit 963a479908
9 changed files with 163 additions and 13 deletions

View File

@ -8,6 +8,8 @@
#include "AcornAnalyser.hpp"
#include "Tape.hpp"
using namespace StaticAnalyser::Acorn;
static std::list<std::shared_ptr<Storage::Cartridge::Cartridge>>
@ -68,8 +70,7 @@ void StaticAnalyser::Acorn::AddTargets(
if(tapes.size() > 0)
{
std::shared_ptr<Storage::Tape::Tape> tape = tapes.front();
tape->reset();
GetNextFile(tape);
}
}

View File

@ -10,7 +10,110 @@
using namespace StaticAnalyser::Acorn;
struct TapeParser {
float wave_lengths[4];
int wave_length_pointer;
TapeParser() : wave_length_pointer(0) {}
int GetNextBit(const std::shared_ptr<Storage::Tape::Tape> &tape)
{
while(!tape->is_at_end())
{
// skip any gaps
Storage::Tape::Tape::Pulse next_pulse = tape->get_next_pulse();
while(next_pulse.type == Storage::Tape::Tape::Pulse::Zero)
{
next_pulse = tape->get_next_pulse();
}
wave_lengths[wave_length_pointer] = next_pulse.length.get_float();
wave_length_pointer++;
// 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)
{
rotate(1);
continue;
}
// if first two waves add up to a correct-length cycle, pop them and this is a 0
if(wave_length_pointer >= 2)
{
float length = wave_lengths[0] + wave_lengths[1];
if(length >= 3.0f / 4800.0f && length < 5.0f / 4800.0f)
{
rotate(2);
return 0;
}
}
// if all four waves add up to a correct-length cycle, pop them and this is a 1
if(wave_length_pointer >= 4)
{
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)
{
rotate(4);
return 1;
}
}
}
return 0;
}
int GetNextByte(const std::shared_ptr<Storage::Tape::Tape> &tape)
{
int value = 0;
int c = 10;
if(GetNextBit(tape)) return -1;
while(c--)
{
value = (value >> 1) | (GetNextBit(tape) << 9);
}
if(!GetNextBit(tape)) return -1;
return c;
}
private:
void rotate(int places)
{
wave_length_pointer -= places;
memmove(wave_lengths, &wave_lengths[places], (size_t)(4 - places) * sizeof(float));
}
};
std::unique_ptr<File> StaticAnalyser::Acorn::GetNextFile(const std::shared_ptr<Storage::Tape::Tape> &tape)
{
int shift_register = 0;
TapeParser parser;
#define shift() \
shift_register = (shift_register >> 1) | (parser.GetNextBit(tape) << 9)
// find next area of high tone
while(!tape->is_at_end() && (shift_register != 0x3ff))
{
shift();
}
// find next 0x2a (swallowing stop bit)
while(!tape->is_at_end() && (shift_register != 0x055))
{
shift();
if(shift_register != 0x3ff) printf("%d\n", shift_register >> 9);
}
// read out name
char name[10];
int name_ptr = 0;
while(!tape->is_at_end() && name_ptr < 10)
{
name[name_ptr] = (char)parser.GetNextByte(tape);
if(!name[name_ptr]) break;
name_ptr++;
}
return nullptr;
}

View File

@ -12,7 +12,7 @@
using namespace Storage::Tape;
CommodoreTAP::CommodoreTAP(const char *file_name)
CommodoreTAP::CommodoreTAP(const char *file_name) : _is_at_end(false)
{
_file = fopen(file_name, "rb");
@ -62,10 +62,21 @@ void CommodoreTAP::reset()
{
fseek(_file, 0x14, SEEK_SET);
_current_pulse.type = Pulse::High;
_is_at_end = false;
}
bool CommodoreTAP::is_at_end()
{
return _is_at_end;
}
Storage::Tape::Tape::Pulse CommodoreTAP::get_next_pulse()
{
if(_is_at_end)
{
return _current_pulse;
}
if(_current_pulse.type == Pulse::High)
{
uint32_t next_length;
@ -81,8 +92,17 @@ Storage::Tape::Tape::Pulse CommodoreTAP::get_next_pulse()
next_length |= (uint32_t)(fgetc(_file) << 16);
}
_current_pulse.length.length = next_length;
_current_pulse.type = Pulse::Low;
if(feof(_file))
{
_is_at_end = true;
_current_pulse.length.length = _current_pulse.length.clock_rate;
_current_pulse.type = Pulse::Zero;
}
else
{
_current_pulse.length.length = next_length;
_current_pulse.type = Pulse::Low;
}
}
else
_current_pulse.type = Pulse::High;

View File

@ -35,6 +35,7 @@ class CommodoreTAP: public Tape {
// implemented to satisfy @c Tape
Pulse get_next_pulse();
void reset();
bool is_at_end();
private:
FILE *_file;
@ -42,6 +43,7 @@ class CommodoreTAP: public Tape {
uint32_t _file_size;
Pulse _current_pulse;
bool _is_at_end;
};
}

View File

@ -109,6 +109,11 @@ void PRG::reset()
_copy_mask = 0x80;
}
bool PRG::is_at_end()
{
return _filePhase == FilePhaseAtEnd;
}
void PRG::get_next_output_token()
{
static const int block_length = 192; // not counting the checksum
@ -116,10 +121,10 @@ void PRG::get_next_output_token()
static const int leadin_length = 20000;
static const int block_leadin_length = 5000;
if(_filePhase == FilePhaseHeaderDataGap)
if(_filePhase == FilePhaseHeaderDataGap || _filePhase == FilePhaseAtEnd)
{
_outputToken = Silence;
_filePhase = FilePhaseData;
if(_filePhase != FilePhaseAtEnd) _filePhase = FilePhaseData;
return;
}

View File

@ -37,6 +37,8 @@ class PRG: public Tape {
// implemented to satisfy @c Tape
Pulse get_next_pulse();
void reset();
bool is_at_end();
private:
FILE *_file;
uint16_t _load_address;
@ -47,6 +49,7 @@ class PRG: public Tape {
FilePhaseHeader,
FilePhaseHeaderDataGap,
FilePhaseData,
FilePhaseAtEnd
} _filePhase;
int _phaseOffset;

View File

@ -45,7 +45,8 @@ static float gzgetfloat(gzFile file)
UEF::UEF(const char *file_name) :
_chunk_id(0), _chunk_length(0), _chunk_position(0),
_time_base(1200)
_time_base(1200),
_is_at_end(false)
{
_file = gzopen(file_name, "rb");
@ -77,12 +78,26 @@ UEF::~UEF()
void UEF::reset()
{
gzseek(_file, 12, SEEK_SET);
_is_at_end = false;
}
bool UEF::is_at_end()
{
return _is_at_end;
}
Storage::Tape::Tape::Pulse UEF::get_next_pulse()
{
Pulse next_pulse;
if(_is_at_end)
{
next_pulse.type = Pulse::Zero;
next_pulse.length.length = _time_base * 4;
next_pulse.length.clock_rate = _time_base * 4;
return next_pulse;
}
if(!_bit_position && chunk_is_finished())
{
find_next_tape_chunk();
@ -149,7 +164,6 @@ Storage::Tape::Tape::Pulse UEF::get_next_pulse()
void UEF::find_next_tape_chunk()
{
int reset_count = 0;
_chunk_position = 0;
_bit_position = 0;
@ -170,10 +184,8 @@ void UEF::find_next_tape_chunk()
if(gzeof(_file))
{
reset_count++;
if(reset_count == 2) break;
reset();
continue;
_is_at_end = true;
return;
}
switch(_chunk_id)

View File

@ -36,6 +36,7 @@ class UEF : public Tape {
// implemented to satisfy @c Tape
Pulse get_next_pulse();
void reset();
bool is_at_end();
private:
gzFile _file;
@ -59,6 +60,7 @@ class UEF : public Tape {
uint8_t _current_byte;
uint32_t _chunk_position;
bool _is_at_end;
bool _current_bit;
uint32_t _bit_position;

View File

@ -36,7 +36,9 @@ class Tape {
};
virtual Pulse get_next_pulse() = 0;
virtual void reset() = 0;
virtual bool is_at_end() = 0;
virtual void seek(Time seek_time); // TODO
};