mirror of
https://github.com/TomHarte/CLK.git
synced 2025-01-11 08:30:55 +00:00
Spotted that pilot and data segments have different encodings — of course! — and attempted to adapt.
This commit is contained in:
parent
b63971caf7
commit
fa617eac6b
@ -71,6 +71,49 @@ class FileHolder {
|
|||||||
*/
|
*/
|
||||||
void ensure_file_is_at_least_length(long length);
|
void ensure_file_is_at_least_length(long length);
|
||||||
|
|
||||||
|
class BitStream {
|
||||||
|
public:
|
||||||
|
BitStream(FILE *f, bool lsb_first) :
|
||||||
|
file_(f),
|
||||||
|
lsb_first_(lsb_first),
|
||||||
|
next_value_(0),
|
||||||
|
bits_remaining_(0) {}
|
||||||
|
|
||||||
|
uint8_t get_bits(int q) {
|
||||||
|
uint8_t result = 0;
|
||||||
|
while(q--) {
|
||||||
|
result = (uint8_t)((result << 1) | get_bit());
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
FILE *file_;
|
||||||
|
bool lsb_first_;
|
||||||
|
uint8_t next_value_;
|
||||||
|
int bits_remaining_;
|
||||||
|
|
||||||
|
uint8_t get_bit() {
|
||||||
|
if(!bits_remaining_) {
|
||||||
|
bits_remaining_ = 8;
|
||||||
|
next_value_ = (uint8_t)fgetc(file_);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t bit;
|
||||||
|
if(lsb_first_) {
|
||||||
|
bit = next_value_ & 1;
|
||||||
|
next_value_ >>= 1;
|
||||||
|
} else {
|
||||||
|
bit = next_value_ >> 7;
|
||||||
|
next_value_ <<= 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
bits_remaining_--;
|
||||||
|
|
||||||
|
return bit;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
FILE *file_;
|
FILE *file_;
|
||||||
struct stat file_stats_;
|
struct stat file_stats_;
|
||||||
bool is_read_only_;
|
bool is_read_only_;
|
||||||
|
@ -77,12 +77,12 @@ void TZX::get_generalised_data_block() {
|
|||||||
uint8_t maximum_pulses_per_data_symbol = (uint8_t)fgetc(file_);
|
uint8_t maximum_pulses_per_data_symbol = (uint8_t)fgetc(file_);
|
||||||
uint8_t symbols_in_data_table = (uint8_t)fgetc(file_);
|
uint8_t symbols_in_data_table = (uint8_t)fgetc(file_);
|
||||||
|
|
||||||
get_generalised_segment(total_pilot_symbols, maximum_pulses_per_pilot_symbol, symbols_in_pilot_table);
|
get_generalised_segment(total_pilot_symbols, maximum_pulses_per_pilot_symbol, symbols_in_pilot_table, false);
|
||||||
get_generalised_segment(total_data_symbols, maximum_pulses_per_data_symbol, symbols_in_data_table);
|
get_generalised_segment(total_data_symbols, maximum_pulses_per_data_symbol, symbols_in_data_table, true);
|
||||||
emplace_back(Tape::Pulse::Zero, Storage::Time((unsigned int)pause_after_block, 1000u));
|
emplace_back(Tape::Pulse::Zero, Storage::Time((unsigned int)pause_after_block, 1000u));
|
||||||
}
|
}
|
||||||
|
|
||||||
void TZX::get_generalised_segment(uint32_t output_symbols, uint8_t max_pulses_per_symbol, uint8_t number_of_symbols) {
|
void TZX::get_generalised_segment(uint32_t output_symbols, uint8_t max_pulses_per_symbol, uint8_t number_of_symbols, bool is_data) {
|
||||||
if(!output_symbols) return;
|
if(!output_symbols) return;
|
||||||
|
|
||||||
// Construct the symbol table.
|
// Construct the symbol table.
|
||||||
@ -97,27 +97,48 @@ void TZX::get_generalised_segment(uint32_t output_symbols, uint8_t max_pulses_pe
|
|||||||
for(int ic = 0; ic < max_pulses_per_symbol; ic++) {
|
for(int ic = 0; ic < max_pulses_per_symbol; ic++) {
|
||||||
symbol.pulse_lengths.push_back(fgetc16le());
|
symbol.pulse_lengths.push_back(fgetc16le());
|
||||||
}
|
}
|
||||||
|
symbol_table.push_back(symbol);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Hence produce the output.
|
// Hence produce the output.
|
||||||
|
BitStream stream(file_, false);
|
||||||
|
int base = 2;
|
||||||
|
int bits = 1;
|
||||||
|
while(base < number_of_symbols) {
|
||||||
|
base <<= 1;
|
||||||
|
bits++;
|
||||||
|
}
|
||||||
for(int c = 0; c < output_symbols; c++) {
|
for(int c = 0; c < output_symbols; c++) {
|
||||||
uint8_t symbol_value = (uint8_t)fgetc(file_);
|
uint8_t symbol_value;
|
||||||
|
int count;
|
||||||
|
if(is_data) {
|
||||||
|
symbol_value = stream.get_bits(bits);
|
||||||
|
count = 1;
|
||||||
|
} else {
|
||||||
|
symbol_value = (uint8_t)fgetc(file_);
|
||||||
|
count = fgetc16le();
|
||||||
|
}
|
||||||
|
if(symbol_value > number_of_symbols) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
Symbol &symbol = symbol_table[symbol_value];
|
Symbol &symbol = symbol_table[symbol_value];
|
||||||
|
|
||||||
// Mutate initial output level.
|
while(count--) {
|
||||||
switch(symbol.flags & 3) {
|
// Mutate initial output level.
|
||||||
case 0: break;
|
switch(symbol.flags & 3) {
|
||||||
case 1: is_high_ ^= true; break;
|
case 0: break;
|
||||||
case 2: is_high_ = true; break;
|
case 1: is_high_ ^= true; break;
|
||||||
case 3: is_high_ = false; break;
|
case 2: is_high_ = true; break;
|
||||||
}
|
case 3: is_high_ = false; break;
|
||||||
|
}
|
||||||
|
|
||||||
// Output waves.
|
// Output waves.
|
||||||
for(auto length : symbol.pulse_lengths) {
|
for(auto length : symbol.pulse_lengths) {
|
||||||
if(!length) break;
|
if(!length) break;
|
||||||
|
|
||||||
is_high_ ^= true;
|
is_high_ ^= true;
|
||||||
emplace_back(is_high_ ? Tape::Pulse::High : Tape::Pulse::Low, Storage::Time((unsigned int)length, StandardTZXClock));
|
emplace_back(is_high_ ? Tape::Pulse::High : Tape::Pulse::Low, Storage::Time((unsigned int)length, StandardTZXClock));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -38,7 +38,7 @@ class TZX: public PulseQueuedTape, public Storage::FileHolder {
|
|||||||
bool is_high_;
|
bool is_high_;
|
||||||
|
|
||||||
void get_generalised_data_block();
|
void get_generalised_data_block();
|
||||||
void get_generalised_segment(uint32_t output_symbols, uint8_t max_pulses_per_symbol, uint8_t number_of_symbols);
|
void get_generalised_segment(uint32_t output_symbols, uint8_t max_pulses_per_symbol, uint8_t number_of_symbols, bool is_data);
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user