1
0
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:
Thomas Harte 2017-07-12 21:23:59 -04:00
parent 33eadb5549
commit f09fe30af5
2 changed files with 51 additions and 20 deletions

View File

@ -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_;
} }

View File

@ -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_;
}; };
} }