1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-12-27 01:31:42 +00:00

Merge pull request #69 from TomHarte/FastOricTape

Introduces fast loading for Oric tapes
This commit is contained in:
Thomas Harte 2016-11-03 08:03:20 -04:00 committed by GitHub
commit 2d7c6ad03b
7 changed files with 159 additions and 14 deletions

View File

@ -11,10 +11,10 @@
using namespace Oric;
Machine::Machine() : _cycles_since_video_update(0)
Machine::Machine() : _cycles_since_video_update(0), _use_fast_tape_hack(false)
{
set_clock_rate(1000000);
_via.tape.reset(new Storage::Tape::BinaryTapePlayer(1000000));
_via.tape.reset(new TapePlayer);
_via.set_interrupt_delegate(this);
_keyboard.reset(new Keyboard);
_via.keyboard = _keyboard;
@ -41,6 +41,16 @@ unsigned int Machine::perform_bus_operation(CPU6502::BusOperation operation, uin
if(address >= 0xc000)
{
if(isReadOperation(operation)) *value = _rom[address&16383];
// 024D = 0 => fast; otherwise slow
// E6C9 = read byte: return byte in A
if(address == 0xe6c9 && _use_fast_tape_hack && operation == CPU6502::BusOperation::ReadOpcode)
{
uint8_t next_byte = _via.tape->get_next_byte(!_ram[0x024d]);
set_value_of_register(CPU6502::A, next_byte);
set_value_of_register(CPU6502::Flags, next_byte ? 0 : CPU6502::Flag::Zero);
*value = 0x60; // i.e. RTS
}
}
else
{
@ -62,7 +72,6 @@ unsigned int Machine::perform_bus_operation(CPU6502::BusOperation operation, uin
}
_via.run_for_cycles(1);
_via.tape->run_for_cycles(1);
_cycles_since_video_update++;
return 1;
}
@ -117,6 +126,11 @@ void Machine::clear_all_keys()
memset(_keyboard->rows, 0, sizeof(_keyboard->rows));
}
void Machine::set_use_fast_tape_hack(bool activate)
{
_use_fast_tape_hack = activate;
}
void Machine::tape_did_change_input(Storage::Tape::BinaryTapePlayer *tape_player)
{
// set CB1
@ -187,6 +201,7 @@ void Machine::VIA::run_for_cycles(unsigned int number_of_cycles)
{
_cycles_since_ay_update += number_of_cycles;
MOS::MOS6522<VIA>::run_for_cycles(number_of_cycles);
tape->run_for_cycles((int)number_of_cycles);
}
void Machine::VIA::update_ay()
@ -195,3 +210,83 @@ void Machine::VIA::update_ay()
_cycles_since_ay_update = 0;
ay8910->set_control_lines( (GI::AY38910::ControlLines)((_ay_bdir ? GI::AY38910::BCDIR : 0) | (_ay_bc1 ? GI::AY38910::BC1 : 0) | GI::AY38910::BC2));
}
#pragma mark - TapePlayer
Machine::TapePlayer::TapePlayer() :
Storage::Tape::BinaryTapePlayer(1000000),
_is_catching_bytes(false)
{}
uint8_t Machine::TapePlayer::get_next_byte(bool fast)
{
_is_in_fast_mode = fast;
_is_catching_bytes = true;
_was_high = get_input();
_queued_lengths_pointer = 0;
_data_register = 0;
_cycle_length = 0.0f;
_bit_count = 0;
while(_bit_count < 10)
{
process_next_event();
}
_is_catching_bytes = false;
return (uint8_t)(_data_register >> 1);
}
void Machine::TapePlayer::process_input_pulse(Storage::Tape::Tape::Pulse pulse)
{
Storage::Tape::BinaryTapePlayer::process_input_pulse(pulse);
if(_is_catching_bytes)
{
_cycle_length += pulse.length.get_float();
bool is_high = get_input();
if(is_high != _was_high)
{
// queue up the new length
_queued_lengths[_queued_lengths_pointer] = _cycle_length;
_cycle_length = 0.0f;
_queued_lengths_pointer++;
// search for bits
if(_is_in_fast_mode)
{
if(_queued_lengths_pointer >= 2)
{
float first_two = _queued_lengths[0] + _queued_lengths[1];
if(first_two < 0.000512*2.0 && _queued_lengths[0] >= _queued_lengths[1] - 0.000256)
{
int new_bit = (first_two < 0.000512) ? 1 : 0;
if(_bit_count || !new_bit)
{
_data_register |= (new_bit << _bit_count);
_bit_count++;
}
memmove(_queued_lengths, &_queued_lengths[2], sizeof(float)*14);
_queued_lengths_pointer -= 2;
}
else
{
memmove(_queued_lengths, &_queued_lengths[1], sizeof(float)*15);
_queued_lengths_pointer--;
}
}
}
else
{
// TODO
}
}
_was_high = is_high;
}
}
void Machine::TapePlayer::run_for_cycles(int number_of_cycles)
{
if(!_is_catching_bytes) Storage::Tape::BinaryTapePlayer::run_for_cycles(number_of_cycles);
}

View File

@ -61,6 +61,8 @@ class Machine:
void set_key_state(Key key, bool isPressed);
void clear_all_keys();
void set_use_fast_tape_hack(bool activate);
// to satisfy ConfigurationTarget::Machine
void configure_as_target(const StaticAnalyser::Target &target);
@ -97,6 +99,30 @@ class Machine:
uint8_t rows[8];
};
// The tape
class TapePlayer: public Storage::Tape::BinaryTapePlayer {
public:
TapePlayer();
uint8_t get_next_byte(bool fast);
void run_for_cycles(int number_of_cycles);
private:
bool _is_catching_bytes; // `true` to enable tape byte parsing, `false` otherwise
bool _is_in_fast_mode; // `true` to indicate that tape byte parsing should use the Oric's fast encoding, `false` otherwise
float _cycle_length; // a counter for the amount of time since the tape input changed
bool _was_high; // a latch to spot when the tape input changes
float _queued_lengths[16]; // a history of previous half-wave lengths
int _queued_lengths_pointer; // a pointer into the history, showing the number of lengths waiting to be parsed
int _data_register; // the accumulation of input bits
int _bit_count; // a counter of accumulated bits
virtual void process_input_pulse(Storage::Tape::Tape::Pulse pulse);
};
bool _use_fast_tape_hack;
// VIA (which owns the tape and the AY)
class VIA: public MOS::MOS6522<VIA>, public MOS::MOS6522IRQDelegate {
public:
@ -109,7 +135,7 @@ class Machine:
inline void run_for_cycles(unsigned int number_of_cycles);
std::shared_ptr<GI::AY38910> ay8910;
std::shared_ptr<Storage::Tape::BinaryTapePlayer> tape;
std::shared_ptr<TapePlayer> tape;
std::shared_ptr<Keyboard> keyboard;
void synchronise();

View File

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="11201" systemVersion="16A323" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="11201" systemVersion="16B2555" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
<dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="11201"/>
</dependencies>
@ -60,7 +60,7 @@
<outlet property="displayTypeButton" destination="rh8-km-57n" id="FB2-Zg-VKq"/>
<outlet property="fastLoadingButton" destination="e1J-pw-zGw" id="jj7-OZ-mOH"/>
</connections>
<point key="canvasLocation" x="129" y="46.5"/>
<point key="canvasLocation" x="175" y="45"/>
</window>
</objects>
</document>

View File

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="11201" systemVersion="16A323" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="11201" systemVersion="16B2555" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
<dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="11201"/>
</dependencies>
@ -14,12 +14,22 @@
<window title="Options" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" hidesOnDeactivate="YES" oneShot="NO" releasedWhenClosed="NO" showsToolbarButton="NO" visibleAtLaunch="NO" frameAutosaveName="" animationBehavior="default" id="ZW7-Bw-4RP" customClass="OricOptionsPanel" customModule="Clock_Signal" customModuleProvider="target">
<windowStyleMask key="styleMask" titled="YES" closable="YES" utility="YES" nonactivatingPanel="YES" HUD="YES"/>
<windowPositionMask key="initialPositionMask" leftStrut="YES" rightStrut="YES" topStrut="YES" bottomStrut="YES"/>
<rect key="contentRect" x="83" y="102" width="200" height="61"/>
<rect key="contentRect" x="83" y="102" width="200" height="83"/>
<rect key="screenRect" x="0.0" y="0.0" width="1366" height="768"/>
<view key="contentView" id="tpZ-0B-QQu">
<rect key="frame" x="0.0" y="0.0" width="200" height="61"/>
<rect key="frame" x="0.0" y="0.0" width="200" height="83"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<button translatesAutoresizingMaskIntoConstraints="NO" id="zPG-yW-4Gy">
<rect key="frame" x="18" y="47" width="164" height="18"/>
<buttonCell key="cell" type="check" title="Load Quickly" bezelStyle="regularSquare" imagePosition="left" state="on" inset="2" id="alI-Mw-35c">
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
<font key="font" metaFont="system"/>
</buttonCell>
<connections>
<action selector="setFastLoading:" target="ZW7-Bw-4RP" id="yyv-gz-xoa"/>
</connections>
</button>
<popUpButton verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="rh8-km-57n">
<rect key="frame" x="18" y="17" width="165" height="26"/>
<popUpButtonCell key="cell" type="push" title="SCART" bezelStyle="rounded" alignment="left" lineBreakMode="truncatingTail" state="on" borderStyle="borderAndBezel" imageScaling="proportionallyDown" inset="2" selectedItem="tJM-kX-gaK" id="8SX-c5-ud1">
@ -38,15 +48,20 @@
</popUpButton>
</subviews>
<constraints>
<constraint firstAttribute="trailing" secondItem="zPG-yW-4Gy" secondAttribute="trailing" constant="20" id="Mtb-hf-4ap"/>
<constraint firstItem="rh8-km-57n" firstAttribute="top" secondItem="zPG-yW-4Gy" secondAttribute="bottom" constant="8" id="ScX-pe-t0x"/>
<constraint firstItem="rh8-km-57n" firstAttribute="leading" secondItem="tpZ-0B-QQu" secondAttribute="leading" constant="20" id="VRo-6R-IKd"/>
<constraint firstAttribute="bottom" secondItem="rh8-km-57n" secondAttribute="bottom" constant="20" id="g0Y-mW-nla"/>
<constraint firstItem="zPG-yW-4Gy" firstAttribute="leading" secondItem="tpZ-0B-QQu" secondAttribute="leading" constant="20" id="imk-5k-8nm"/>
<constraint firstItem="zPG-yW-4Gy" firstAttribute="top" secondItem="tpZ-0B-QQu" secondAttribute="top" constant="20" id="jAt-iF-uaT"/>
<constraint firstAttribute="trailing" secondItem="rh8-km-57n" secondAttribute="trailing" constant="20" id="urO-Ac-aqK"/>
<constraint firstItem="rh8-km-57n" firstAttribute="top" secondItem="tpZ-0B-QQu" secondAttribute="top" constant="20" id="xJx-0U-vUw"/>
</constraints>
</view>
<connections>
<outlet property="displayTypeButton" destination="rh8-km-57n" id="FB2-Zg-VKq"/>
<outlet property="fastLoadingButton" destination="zPG-yW-4Gy" id="aMA-R2-EL8"/>
</connections>
<point key="canvasLocation" x="129" y="35.5"/>
<point key="canvasLocation" x="-50" y="16.5"/>
</window>
</objects>
</document>

View File

@ -8,9 +8,11 @@
#import "CSMachine.h"
#import "CSKeyboardMachine.h"
#import "CSFastLoading.h"
@interface CSOric : CSMachine <CSKeyboardMachine>
@interface CSOric : CSMachine <CSKeyboardMachine, CSFastLoading>
@property(nonatomic, assign) BOOL useCompositeOutput;
@property (nonatomic, assign) BOOL useFastLoadingHack;
@property (nonatomic, assign) BOOL useCompositeOutput;
@end

View File

@ -135,6 +135,13 @@
#pragma mark - Options
- (void)setUseFastLoadingHack:(BOOL)useFastLoadingHack {
@synchronized(self) {
_useFastLoadingHack = useFastLoadingHack;
_oric.set_use_fast_tape_hack(useFastLoadingHack ? true : false);
}
}
- (void)setUseCompositeOutput:(BOOL)useCompositeOutput {
@synchronized(self) {
_useCompositeOutput = useCompositeOutput;

View File

@ -117,7 +117,7 @@ class BinaryTapePlayer: public TapePlayer {
};
void set_delegate(Delegate *delegate);
private:
protected:
Delegate *_delegate;
virtual void process_input_pulse(Storage::Tape::Tape::Pulse pulse);
bool _input_level;