mirror of
https://github.com/TomHarte/CLK.git
synced 2024-11-26 08:49:37 +00:00
Merge pull request #69 from TomHarte/FastOricTape
Introduces fast loading for Oric tapes
This commit is contained in:
commit
2d7c6ad03b
@ -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);
|
||||
}
|
||||
|
@ -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();
|
||||
|
@ -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>
|
||||
|
@ -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>
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user