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

Makes Jasmin autoboot optional, adds a Jasmin reset key, adds the Jasmin to File -> New... .

Also finally implements KeyNMI.
This commit is contained in:
Thomas Harte 2020-01-05 21:57:33 -05:00
parent 7361e7ec34
commit 3ced31043a
9 changed files with 67 additions and 17 deletions

View File

@ -167,8 +167,8 @@ Analyser::Static::TargetList Analyser::Static::Oric::GetTargets(const Media &med
target->media.disks.push_back(disk);
} else if(IsJasmin(parser)) {
target->disk_interface = Target::DiskInterface::Jasmin;
target->should_start_jasmin = true;
target->media.disks.push_back(disk);
}
}
}

View File

@ -33,6 +33,7 @@ struct Target: public ::Analyser::Static::Target {
ROM rom = ROM::BASIC11;
DiskInterface disk_interface = DiskInterface::None;
std::string loading_command;
bool should_start_jasmin = false;
};
}

View File

@ -45,6 +45,9 @@ uint16_t KeyboardMapper::mapped_key_for_key(Inputs::Keyboard::Key key) {
BIND(Space, KeySpace);
BIND(Enter, KeyReturn);
BIND(F12, KeyNMI);
BIND(F1, KeyJasminReset);
}
#undef BIND

View File

@ -33,6 +33,7 @@ enum Key: uint16_t {
KeyForwardSlash = 0x0700 | 0x08, Key0 = 0x0700 | 0x04, KeyL = 0x0700 | 0x02, Key8 = 0x0700 | 0x01,
KeyNMI = 0xfffd,
KeyJasminReset = 0xfffc,
};
struct KeyboardMapper: public KeyboardMachine::MappedMachine::KeyboardMapper {

View File

@ -66,17 +66,32 @@ std::vector<std::unique_ptr<Configurable::Option>> get_options() {
*/
class Keyboard {
public:
Keyboard() {
struct SpecialKeyHandler {
virtual void perform_special_key(Oric::Key key) = 0;
};
Keyboard(SpecialKeyHandler *handler) : special_key_handler_(handler) {
clear_all_keys();
}
/// Sets whether @c key is or is not pressed, per @c is_pressed.
void set_key_state(uint16_t key, bool is_pressed) {
const uint8_t mask = key & 0xff;
const int line = key >> 8;
switch(key) {
default: {
const uint8_t mask = key & 0xff;
const int line = key >> 8;
if(is_pressed) rows_[line] |= mask;
else rows_[line] &= ~mask;
if(is_pressed) rows_[line] |= mask;
else rows_[line] &= ~mask;
} break;
case KeyNMI:
case KeyJasminReset:
if(is_pressed) {
special_key_handler_->perform_special_key(Oric::Key(key));
}
break;
}
}
/// Sets all keys as unpressed.
@ -97,6 +112,7 @@ class Keyboard {
private:
uint8_t row_ = 0;
uint8_t rows_[8];
SpecialKeyHandler *const special_key_handler_;
};
/*!
@ -211,7 +227,8 @@ template <Analyser::Static::Oric::Target::DiskInterface disk_interface> class Co
public Jasmin::Delegate,
public ClockingHint::Observer,
public Activity::Source,
public Machine {
public Machine,
public Keyboard::SpecialKeyHandler {
public:
ConcreteMachine(const Analyser::Static::Oric::Target &target, const ROMMachine::ROMFetcher &rom_fetcher) :
@ -221,6 +238,7 @@ template <Analyser::Static::Oric::Target::DiskInterface disk_interface> class Co
speaker_(ay8910_),
via_port_handler_(audio_queue_, ay8910_, speaker_, tape_player_, keyboard_),
via_(via_port_handler_),
keyboard_(this),
diskii_(2000000) {
set_clock_rate(1000000);
speaker_.set_input_rate(1000000.0f);
@ -310,6 +328,12 @@ template <Analyser::Static::Oric::Target::DiskInterface disk_interface> class Co
type_string(target.loading_command);
}
if(target.should_start_jasmin) {
// If Jasmin autostart is requested then plan to do so in 3 seconds; empirically long enough
// for the Oric to boot normally, before the Jasmin intercedes.
jasmin_reset_counter_ = 3000000;
}
switch(target.rom) {
case Analyser::Static::Oric::Target::ROM::BASIC10:
tape_get_byte_address_ = 0xe630;
@ -482,9 +506,7 @@ template <Analyser::Static::Oric::Target::DiskInterface disk_interface> class Co
if(jasmin_reset_counter_) {
--jasmin_reset_counter_;
if(!jasmin_reset_counter_) {
jasmin_.write(0x3fa, 0);
jasmin_.write(0x3fb, 1);
m6502_.set_power_on(true);
perform_special_key(KeyJasminReset);
}
}
break;
@ -681,8 +703,7 @@ template <Analyser::Static::Oric::Target::DiskInterface disk_interface> class Co
// the Jasmin, if in use.
Jasmin jasmin_;
int jasmin_reset_counter_ = 3000000; // i.e. 3 seconds; empirically long enough for the Oric to boot normally,
// before the Jasmin intercedes.
int jasmin_reset_counter_ = 0;
// the Pravetz/Disk II, if in use.
Apple::DiskII diskii_;
@ -715,6 +736,26 @@ template <Analyser::Static::Oric::Target::DiskInterface disk_interface> class Co
m6502_.set_irq_line(irq_line);
}
// Keys that aren't read by polling.
void perform_special_key(Oric::Key key) override {
switch(key) {
default: break;
case KeyJasminReset:
jasmin_.write(0x3fa, 0);
jasmin_.write(0x3fb, 1);
m6502_.set_power_on(true);
break;
case KeyNMI:
// As luck would have it, the 6502's NMI line is edge triggered.
// So just forcing through an edge will work here.
m6502_.set_nmi_line(true);
m6502_.set_nmi_line(false);
break;
}
}
// MARK - typing
std::unique_ptr<Utility::StringSerialiser> string_serialiser_;
};

View File

@ -49,7 +49,8 @@ typedef NS_ENUM(NSInteger, CSMachineOricModel) {
typedef NS_ENUM(NSInteger, CSMachineOricDiskInterface) {
CSMachineOricDiskInterfaceNone,
CSMachineOricDiskInterfaceMicrodisc,
CSMachineOricDiskInterfacePravetz
CSMachineOricDiskInterfacePravetz,
CSMachineOricDiskInterfaceJasmin
};
typedef NS_ENUM(NSInteger, CSMachineVic20Region) {

View File

@ -102,6 +102,7 @@
case CSMachineOricDiskInterfaceNone: target->disk_interface = Target::DiskInterface::None; break;
case CSMachineOricDiskInterfaceMicrodisc: target->disk_interface = Target::DiskInterface::Microdisc; break;
case CSMachineOricDiskInterfacePravetz: target->disk_interface = Target::DiskInterface::Pravetz; break;
case CSMachineOricDiskInterfaceJasmin: target->disk_interface = Target::DiskInterface::Jasmin; break;
}
_targets.push_back(std::move(target));
}

View File

@ -18,7 +18,7 @@
<windowStyleMask key="styleMask" titled="YES" documentModal="YES"/>
<windowPositionMask key="initialPositionMask" leftStrut="YES" rightStrut="YES" topStrut="YES" bottomStrut="YES"/>
<rect key="contentRect" x="196" y="240" width="720" height="205"/>
<rect key="screenRect" x="0.0" y="0.0" width="1440" height="900"/>
<rect key="screenRect" x="0.0" y="0.0" width="3840" height="2137"/>
<view key="contentView" wantsLayer="YES" id="EiT-Mj-1SZ">
<rect key="frame" x="0.0" y="0.0" width="720" height="205"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
@ -64,7 +64,7 @@ Gw
<tabViewItems>
<tabViewItem label="Apple II" identifier="appleii" id="P59-QG-LOa">
<view key="view" id="dHz-Yv-GNq">
<rect key="frame" x="10" y="33" width="604" height="94"/>
<rect key="frame" x="10" y="33" width="674" height="94"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="V5Z-dX-Ns4">
@ -305,7 +305,7 @@ Gw
</tabViewItem>
<tabViewItem label="Oric" identifier="oric" id="NSx-DC-p4M">
<view key="view" id="sOR-e0-8iZ">
<rect key="frame" x="10" y="33" width="604" height="94"/>
<rect key="frame" x="10" y="33" width="674" height="94"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="0ct-tf-uRH">
@ -339,6 +339,7 @@ Gw
<items>
<menuItem title="None" state="on" id="XhK-Jh-oTW"/>
<menuItem title="Microdisc" tag="1" id="1jS-Lz-FRj"/>
<menuItem title="Jasmin" tag="3" id="CGU-gd-xov"/>
<menuItem title="8DOS" tag="2" id="edb-fl-C8Y"/>
</items>
</menu>
@ -370,7 +371,7 @@ Gw
</tabViewItem>
<tabViewItem label="Vic-20" identifier="vic20" id="cyO-PU-hSU">
<view key="view" id="fLI-XB-QCr">
<rect key="frame" x="10" y="33" width="604" height="94"/>
<rect key="frame" x="10" y="33" width="674" height="94"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<popUpButton verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="ueK-gq-gaF">

View File

@ -195,6 +195,7 @@ class MachinePicker: NSObject {
switch oricDiskInterfaceButton!.selectedTag() {
case 1: diskInterface = .microdisc
case 2: diskInterface = .pravetz
case 3: diskInterface = .jasmin
default: break;
}