mirror of
https://github.com/TomHarte/CLK.git
synced 2025-02-03 07:33:29 +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:
parent
7361e7ec34
commit
3ced31043a
@ -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);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -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
|
||||
|
||||
|
@ -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 {
|
||||
|
@ -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_;
|
||||
};
|
||||
|
@ -49,7 +49,8 @@ typedef NS_ENUM(NSInteger, CSMachineOricModel) {
|
||||
typedef NS_ENUM(NSInteger, CSMachineOricDiskInterface) {
|
||||
CSMachineOricDiskInterfaceNone,
|
||||
CSMachineOricDiskInterfaceMicrodisc,
|
||||
CSMachineOricDiskInterfacePravetz
|
||||
CSMachineOricDiskInterfacePravetz,
|
||||
CSMachineOricDiskInterfaceJasmin
|
||||
};
|
||||
|
||||
typedef NS_ENUM(NSInteger, CSMachineVic20Region) {
|
||||
|
@ -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));
|
||||
}
|
||||
|
@ -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">
|
||||
|
@ -195,6 +195,7 @@ class MachinePicker: NSObject {
|
||||
switch oricDiskInterfaceButton!.selectedTag() {
|
||||
case 1: diskInterface = .microdisc
|
||||
case 2: diskInterface = .pravetz
|
||||
case 3: diskInterface = .jasmin
|
||||
default: break;
|
||||
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user