2016-06-25 20:09:32 +00:00
|
|
|
//
|
|
|
|
// CommodoreTAP.cpp
|
|
|
|
// Clock Signal
|
|
|
|
//
|
|
|
|
// Created by Thomas Harte on 25/06/2016.
|
|
|
|
// Copyright © 2016 Thomas Harte. All rights reserved.
|
|
|
|
//
|
|
|
|
|
|
|
|
#include "CommodoreTAP.hpp"
|
|
|
|
#include <cstdio>
|
|
|
|
#include <cstring>
|
|
|
|
|
2016-08-27 21:18:12 +00:00
|
|
|
using namespace Storage::Tape;
|
2016-06-25 20:09:32 +00:00
|
|
|
|
2016-11-21 12:14:09 +00:00
|
|
|
CommodoreTAP::CommodoreTAP(const char *file_name) :
|
2017-11-03 02:32:00 +00:00
|
|
|
file_(file_name)
|
2016-06-25 20:09:32 +00:00
|
|
|
{
|
2017-11-03 02:32:00 +00:00
|
|
|
if(!file_.check_signature("C64-TAPE-RAW"))
|
2016-06-25 20:09:32 +00:00
|
|
|
throw ErrorNotCommodoreTAP;
|
|
|
|
|
|
|
|
// check the file version
|
2017-11-03 02:32:00 +00:00
|
|
|
switch(file_.get8())
|
2016-06-25 20:09:32 +00:00
|
|
|
{
|
2016-11-21 12:14:09 +00:00
|
|
|
case 0: updated_layout_ = false; break;
|
|
|
|
case 1: updated_layout_ = true; break;
|
2016-06-25 20:09:32 +00:00
|
|
|
default: throw ErrorNotCommodoreTAP;
|
|
|
|
}
|
|
|
|
|
|
|
|
// skip reserved bytes
|
2017-11-03 02:32:00 +00:00
|
|
|
file_.seek(3, SEEK_CUR);
|
2016-06-25 20:09:32 +00:00
|
|
|
|
|
|
|
// read file size
|
2017-11-03 02:32:00 +00:00
|
|
|
file_size_ = file_.get32le();
|
2016-06-25 20:09:32 +00:00
|
|
|
|
|
|
|
// set up for pulse output at the PAL clock rate, with each high and
|
|
|
|
// low being half of whatever length values will be read; pretend that
|
|
|
|
// a high pulse has just been distributed to imply that the next thing
|
|
|
|
// that needs to happen is a length check
|
2016-11-21 12:14:09 +00:00
|
|
|
current_pulse_.length.clock_rate = 985248 * 2;
|
|
|
|
current_pulse_.type = Pulse::High;
|
2016-06-25 20:09:32 +00:00
|
|
|
}
|
|
|
|
|
2016-09-11 21:09:00 +00:00
|
|
|
void CommodoreTAP::virtual_reset()
|
2016-06-25 20:09:32 +00:00
|
|
|
{
|
2017-11-03 02:32:00 +00:00
|
|
|
file_.seek(0x14, SEEK_SET);
|
2016-11-21 12:14:09 +00:00
|
|
|
current_pulse_.type = Pulse::High;
|
|
|
|
is_at_end_ = false;
|
2016-08-30 01:53:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
bool CommodoreTAP::is_at_end()
|
|
|
|
{
|
2016-11-21 12:14:09 +00:00
|
|
|
return is_at_end_;
|
2016-06-25 20:09:32 +00:00
|
|
|
}
|
|
|
|
|
2016-09-11 21:09:00 +00:00
|
|
|
Storage::Tape::Tape::Pulse CommodoreTAP::virtual_get_next_pulse()
|
2016-06-25 20:09:32 +00:00
|
|
|
{
|
2016-11-21 12:14:09 +00:00
|
|
|
if(is_at_end_)
|
2016-08-30 01:53:06 +00:00
|
|
|
{
|
2016-11-21 12:14:09 +00:00
|
|
|
return current_pulse_;
|
2016-08-30 01:53:06 +00:00
|
|
|
}
|
|
|
|
|
2016-11-21 12:14:09 +00:00
|
|
|
if(current_pulse_.type == Pulse::High)
|
2016-06-25 20:09:32 +00:00
|
|
|
{
|
|
|
|
uint32_t next_length;
|
2017-11-03 02:32:00 +00:00
|
|
|
uint8_t next_byte = file_.get8();
|
2016-11-21 12:14:09 +00:00
|
|
|
if(!updated_layout_ || next_byte > 0)
|
2016-06-25 20:09:32 +00:00
|
|
|
{
|
|
|
|
next_length = (uint32_t)next_byte << 3;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2017-11-03 02:32:00 +00:00
|
|
|
next_length = file_.get24le();
|
2016-06-25 20:09:32 +00:00
|
|
|
}
|
|
|
|
|
2017-11-03 02:32:00 +00:00
|
|
|
if(file_.eof())
|
2016-08-30 01:53:06 +00:00
|
|
|
{
|
2016-11-21 12:14:09 +00:00
|
|
|
is_at_end_ = true;
|
|
|
|
current_pulse_.length.length = current_pulse_.length.clock_rate;
|
|
|
|
current_pulse_.type = Pulse::Zero;
|
2016-08-30 01:53:06 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2016-11-21 12:14:09 +00:00
|
|
|
current_pulse_.length.length = next_length;
|
|
|
|
current_pulse_.type = Pulse::Low;
|
2016-08-30 01:53:06 +00:00
|
|
|
}
|
2016-06-25 20:09:32 +00:00
|
|
|
}
|
|
|
|
else
|
2016-11-21 12:14:09 +00:00
|
|
|
current_pulse_.type = Pulse::High;
|
2016-06-25 20:09:32 +00:00
|
|
|
|
2016-11-21 12:14:09 +00:00
|
|
|
return current_pulse_;
|
2016-06-25 20:09:32 +00:00
|
|
|
}
|