mirror of
https://github.com/TomHarte/CLK.git
synced 2024-11-23 03:32:32 +00:00
Attempted a full implementation of CSW. All in memory for now.
This commit is contained in:
parent
33eadb5549
commit
f09fe30af5
@ -11,7 +11,8 @@
|
|||||||
using namespace Storage::Tape;
|
using namespace Storage::Tape;
|
||||||
|
|
||||||
CSW::CSW(const char *file_name) :
|
CSW::CSW(const char *file_name) :
|
||||||
Storage::FileHolder(file_name) {
|
Storage::FileHolder(file_name),
|
||||||
|
source_data_pointer_(0) {
|
||||||
if(file_stats_.st_size < 0x20) throw ErrorNotCSW;
|
if(file_stats_.st_size < 0x20) throw ErrorNotCSW;
|
||||||
|
|
||||||
// Check signature.
|
// Check signature.
|
||||||
@ -31,6 +32,7 @@ CSW::CSW(const char *file_name) :
|
|||||||
if(major_version > 2 || !major_version || minor_version > 1) throw ErrorNotCSW;
|
if(major_version > 2 || !major_version || minor_version > 1) throw ErrorNotCSW;
|
||||||
|
|
||||||
// The header now diverges based on version.
|
// The header now diverges based on version.
|
||||||
|
uint32_t number_of_waves = 0;
|
||||||
if(major_version == 1) {
|
if(major_version == 1) {
|
||||||
pulse_.length.clock_rate = fgetc16le();
|
pulse_.length.clock_rate = fgetc16le();
|
||||||
|
|
||||||
@ -42,7 +44,7 @@ CSW::CSW(const char *file_name) :
|
|||||||
fseek(file_, 0x20, SEEK_SET);
|
fseek(file_, 0x20, SEEK_SET);
|
||||||
} else {
|
} else {
|
||||||
pulse_.length.clock_rate = fgetc32le();
|
pulse_.length.clock_rate = fgetc32le();
|
||||||
number_of_waves_ = fgetc32le();
|
number_of_waves = fgetc32le();
|
||||||
switch(fgetc(file_)) {
|
switch(fgetc(file_)) {
|
||||||
case 1: compression_type_ = RLE; break;
|
case 1: compression_type_ = RLE; break;
|
||||||
case 2: compression_type_ = ZRLE; break;
|
case 2: compression_type_ = ZRLE; break;
|
||||||
@ -57,31 +59,54 @@ CSW::CSW(const char *file_name) :
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(compression_type_ == ZRLE) {
|
if(compression_type_ == ZRLE) {
|
||||||
inflation_stream_.zalloc = Z_NULL;
|
source_data_.resize((size_t)number_of_waves);
|
||||||
inflation_stream_.zfree = Z_NULL;
|
|
||||||
inflation_stream_.opaque = Z_NULL;
|
std::vector<uint8_t> file_data;
|
||||||
inflation_stream_.avail_in = 0;
|
size_t remaining_data = (size_t)file_stats_.st_size - (size_t)ftell(file_);
|
||||||
inflation_stream_.next_in = Z_NULL;
|
file_data.resize(remaining_data);
|
||||||
int result = inflateInit(&inflation_stream_);
|
fread(file_data.data(), sizeof(uint8_t), remaining_data, file_);
|
||||||
if(result != Z_OK) throw ErrorNotCSW;
|
|
||||||
|
uLongf output_length = (uLongf)remaining_data;
|
||||||
|
uncompress(source_data_.data(), &output_length, file_data.data(), file_data.size());
|
||||||
|
} else {
|
||||||
|
rle_start_ = ftell(file_);
|
||||||
|
}
|
||||||
|
|
||||||
|
invert_pulse();
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t CSW::get_next_byte() {
|
||||||
|
switch(compression_type_) {
|
||||||
|
case RLE: return (uint8_t)fgetc(file_);
|
||||||
|
case ZRLE: {
|
||||||
|
if(source_data_pointer_ == source_data_.size()) return 0xff;
|
||||||
|
uint8_t result = source_data_[source_data_pointer_];
|
||||||
|
source_data_pointer_++;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
CSW::~CSW() {
|
void CSW::invert_pulse() {
|
||||||
if(compression_type_ == ZRLE) {
|
pulse_.type = (pulse_.type == Pulse::High) ? Pulse::Low : Pulse::High;
|
||||||
inflateEnd(&inflation_stream_);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool CSW::is_at_end() {
|
bool CSW::is_at_end() {
|
||||||
return true;
|
switch(compression_type_) {
|
||||||
|
case RLE: return (bool)feof(file_);
|
||||||
|
case ZRLE: return source_data_pointer_ == source_data_.size();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSW::virtual_reset() {
|
void CSW::virtual_reset() {
|
||||||
|
switch(compression_type_) {
|
||||||
|
case RLE: fseek(file_, rle_start_, SEEK_SET); break;
|
||||||
|
case ZRLE: source_data_pointer_ = 0; break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Tape::Pulse CSW::virtual_get_next_pulse() {
|
Tape::Pulse CSW::virtual_get_next_pulse() {
|
||||||
Tape::Pulse pulse;
|
invert_pulse();
|
||||||
return pulse;
|
pulse_.length.length = get_next_byte();
|
||||||
|
return pulse_;
|
||||||
}
|
}
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
#include "../../FileHolder.hpp"
|
#include "../../FileHolder.hpp"
|
||||||
|
|
||||||
#include <zlib.h>
|
#include <zlib.h>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
namespace Storage {
|
namespace Storage {
|
||||||
namespace Tape {
|
namespace Tape {
|
||||||
@ -28,7 +29,6 @@ class CSW: public Tape, public Storage::FileHolder {
|
|||||||
@throws ErrorNotCSW if this file could not be opened and recognised as a valid CSW file.
|
@throws ErrorNotCSW if this file could not be opened and recognised as a valid CSW file.
|
||||||
*/
|
*/
|
||||||
CSW(const char *file_name);
|
CSW(const char *file_name);
|
||||||
~CSW();
|
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
ErrorNotCSW
|
ErrorNotCSW
|
||||||
@ -46,8 +46,14 @@ class CSW: public Tape, public Storage::FileHolder {
|
|||||||
RLE,
|
RLE,
|
||||||
ZRLE
|
ZRLE
|
||||||
} compression_type_;
|
} compression_type_;
|
||||||
uint32_t number_of_waves_;
|
|
||||||
z_stream inflation_stream_;
|
uint8_t get_next_byte();
|
||||||
|
void invert_pulse();
|
||||||
|
|
||||||
|
std::vector<uint8_t> source_data_;
|
||||||
|
size_t source_data_pointer_;
|
||||||
|
|
||||||
|
long rle_start_;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user