mirror of
https://github.com/TomHarte/CLK.git
synced 2025-02-08 11:32:02 +00:00
Attempts to pull reimplementations of TAPION and TAPIN better into line with originals.
Also improves whole flow of the fast tape hack that uses them.
This commit is contained in:
parent
11b73a9c0b
commit
5fd0a2b9ea
@ -181,26 +181,53 @@ class ConcreteMachine:
|
|||||||
case CPU::Z80::PartialMachineCycle::ReadOpcode:
|
case CPU::Z80::PartialMachineCycle::ReadOpcode:
|
||||||
if(address == 0x1a63) {
|
if(address == 0x1a63) {
|
||||||
// TAPION
|
// TAPION
|
||||||
tape_player_.set_motor_control(true);
|
|
||||||
|
// Enable the tape motor.
|
||||||
|
i8255_.set_register(0xab, 0x8);
|
||||||
|
|
||||||
|
// Disable interrupts.
|
||||||
|
z80_.set_value_of_register(CPU::Z80::Register::IFF1, 0);
|
||||||
|
z80_.set_value_of_register(CPU::Z80::Register::IFF2, 0);
|
||||||
|
|
||||||
|
// Use the parser to find a header, and if one is found then populate
|
||||||
|
// LOWLIM and WINWID, and reset carry. Otherwise set carry.
|
||||||
using Parser = Storage::Tape::MSX::Parser;
|
using Parser = Storage::Tape::MSX::Parser;
|
||||||
std::unique_ptr<Parser::FileSpeed> new_speed = Parser::find_header(tape_player_);
|
std::unique_ptr<Parser::FileSpeed> new_speed = Parser::find_header(tape_player_);
|
||||||
ram_[0xFCA4] = new_speed->minimum_start_bit_duration;
|
if(new_speed) {
|
||||||
ram_[0xFCA5] = new_speed->low_high_disrimination_duration;
|
ram_[0xfca4] = new_speed->minimum_start_bit_duration;
|
||||||
|
ram_[0xfca5] = new_speed->low_high_disrimination_duration;
|
||||||
|
z80_.set_value_of_register(CPU::Z80::Register::Flags, 0);
|
||||||
|
} else {
|
||||||
|
z80_.set_value_of_register(CPU::Z80::Register::Flags, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// RET.
|
||||||
*cycle.value = 0xc9;
|
*cycle.value = 0xc9;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(address == 0x1abc) {
|
if(address == 0x1abc) {
|
||||||
// TAPIN
|
// TAPIN
|
||||||
|
|
||||||
|
// Grab the current values of LOWLIM and WINWID.
|
||||||
using Parser = Storage::Tape::MSX::Parser;
|
using Parser = Storage::Tape::MSX::Parser;
|
||||||
Parser::FileSpeed tape_speed;
|
Parser::FileSpeed tape_speed;
|
||||||
tape_speed.minimum_start_bit_duration = ram_[0xFCA4];
|
tape_speed.minimum_start_bit_duration = ram_[0xfca4];
|
||||||
tape_speed.low_high_disrimination_duration = ram_[0xFCA5];
|
tape_speed.low_high_disrimination_duration = ram_[0xfca5];
|
||||||
// printf("Low lim: %02x / win wid: %02x\n", ram_[0xFCA4], ram_[0xFCA5]);
|
|
||||||
int next_byte = Parser::get_byte(tape_speed, tape_player_);
|
|
||||||
z80_.set_value_of_register(CPU::Z80::Register::A, static_cast<uint16_t>(next_byte));
|
|
||||||
|
|
||||||
|
// Ask the tape parser to grab a byte.
|
||||||
|
int next_byte = Parser::get_byte(tape_speed, tape_player_);
|
||||||
|
|
||||||
|
// If a byte was found, return it with carry unset. Otherwise set carry to
|
||||||
|
// indicate error.
|
||||||
|
if(next_byte >= 0) {
|
||||||
|
z80_.set_value_of_register(CPU::Z80::Register::A, static_cast<uint16_t>(next_byte));
|
||||||
|
z80_.set_value_of_register(CPU::Z80::Register::Flags, 0);
|
||||||
|
} else {
|
||||||
|
z80_.set_value_of_register(CPU::Z80::Register::Flags, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// RET.
|
||||||
*cycle.value = 0xc9;
|
*cycle.value = 0xc9;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -69,11 +69,11 @@ std::unique_ptr<Parser::FileSpeed> Parser::find_header(Storage::Tape::BinaryTape
|
|||||||
*/
|
*/
|
||||||
total_length = total_length / 256.0f; // To get the average, in microseconds.
|
total_length = total_length / 256.0f; // To get the average, in microseconds.
|
||||||
// To convert to the loop count format used by the MSX BIOS.
|
// To convert to the loop count format used by the MSX BIOS.
|
||||||
uint8_t int_result = static_cast<uint8_t>(total_length / (0.00001145f * 1.5f));
|
uint8_t int_result = static_cast<uint8_t>(total_length / (0.00001145f * 0.75f));
|
||||||
|
|
||||||
std::unique_ptr<FileSpeed> result(new FileSpeed);
|
std::unique_ptr<FileSpeed> result(new FileSpeed);
|
||||||
result->minimum_start_bit_duration = int_result + ((int_result + 1) >> 1);
|
result->minimum_start_bit_duration = int_result;
|
||||||
result->low_high_disrimination_duration = int_result;
|
result->low_high_disrimination_duration = (int_result * 3) >> 2;
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@ -99,19 +99,27 @@ int Parser::get_byte(const FileSpeed &speed, Storage::Tape::BinaryTapePlayer &ta
|
|||||||
*/
|
*/
|
||||||
float minimum_start_bit_duration = static_cast<float>(speed.minimum_start_bit_duration) * 0.00001145f;
|
float minimum_start_bit_duration = static_cast<float>(speed.minimum_start_bit_duration) * 0.00001145f;
|
||||||
while(!tape_player.get_tape()->is_at_end()) {
|
while(!tape_player.get_tape()->is_at_end()) {
|
||||||
while(!tape_player.get_tape()->is_at_end() && !tape_player.get_input()) {
|
// Find a negative transition.
|
||||||
|
while(!tape_player.get_tape()->is_at_end() && tape_player.get_input()) {
|
||||||
tape_player.run_for_input_pulse();
|
tape_player.run_for_input_pulse();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool level = true;
|
// Measure the following cycle (i.e. two transitions).
|
||||||
|
bool level = tape_player.get_input();
|
||||||
float time_to_transition = 0.0f;
|
float time_to_transition = 0.0f;
|
||||||
|
int transitions = 0;
|
||||||
while(!tape_player.get_tape()->is_at_end()) {
|
while(!tape_player.get_tape()->is_at_end()) {
|
||||||
time_to_transition += static_cast<float>(tape_player.get_cycles_until_next_event()) / static_cast<float>(tape_player.get_input_clock_rate());
|
time_to_transition += static_cast<float>(tape_player.get_cycles_until_next_event()) / static_cast<float>(tape_player.get_input_clock_rate());
|
||||||
tape_player.run_for_input_pulse();
|
tape_player.run_for_input_pulse();
|
||||||
if(level != tape_player.get_input())
|
if(level != tape_player.get_input()) {
|
||||||
|
level = tape_player.get_input();
|
||||||
|
transitions++;
|
||||||
|
if(transitions == 2)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check length against 'LOWLIM' (i.e. the minimum start bit duration).
|
||||||
if(time_to_transition > minimum_start_bit_duration) {
|
if(time_to_transition > minimum_start_bit_duration) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -125,10 +133,10 @@ int Parser::get_byte(const FileSpeed &speed, Storage::Tape::BinaryTapePlayer &ta
|
|||||||
*/
|
*/
|
||||||
int result = 0;
|
int result = 0;
|
||||||
const int cycles_per_window = static_cast<int>(
|
const int cycles_per_window = static_cast<int>(
|
||||||
|
0.5f +
|
||||||
static_cast<float>(speed.low_high_disrimination_duration) *
|
static_cast<float>(speed.low_high_disrimination_duration) *
|
||||||
0.0000173f *
|
0.0000173f *
|
||||||
static_cast<float>(tape_player.get_input_clock_rate()) *
|
static_cast<float>(tape_player.get_input_clock_rate())
|
||||||
2.0f
|
|
||||||
);
|
);
|
||||||
int bits_left = 8;
|
int bits_left = 8;
|
||||||
bool level = tape_player.get_input();
|
bool level = tape_player.get_input();
|
||||||
@ -139,8 +147,10 @@ int Parser::get_byte(const FileSpeed &speed, Storage::Tape::BinaryTapePlayer &ta
|
|||||||
while(!tape_player.get_tape()->is_at_end() && cycles_remaining) {
|
while(!tape_player.get_tape()->is_at_end() && cycles_remaining) {
|
||||||
const int cycles_until_next_event = static_cast<int>(tape_player.get_cycles_until_next_event());
|
const int cycles_until_next_event = static_cast<int>(tape_player.get_cycles_until_next_event());
|
||||||
const int cycles_to_run_for = std::min(cycles_until_next_event, cycles_remaining);
|
const int cycles_to_run_for = std::min(cycles_until_next_event, cycles_remaining);
|
||||||
|
|
||||||
cycles_remaining -= cycles_to_run_for;
|
cycles_remaining -= cycles_to_run_for;
|
||||||
tape_player.run_for(Cycles(cycles_to_run_for));
|
tape_player.run_for(Cycles(cycles_to_run_for));
|
||||||
|
|
||||||
if(level != tape_player.get_input()) {
|
if(level != tape_player.get_input()) {
|
||||||
level = tape_player.get_input();
|
level = tape_player.get_input();
|
||||||
transitions++;
|
transitions++;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user