1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-12-25 03:32:01 +00:00

Commutes the Atari 2600 to the JoystickMachine interface.

This commit is contained in:
Thomas Harte 2017-10-15 20:44:59 -04:00
parent ee179aa7bd
commit 7aaf27389c
4 changed files with 67 additions and 49 deletions

View File

@ -27,7 +27,13 @@ class Joystick {
// Host interface.
virtual void set_digital_input(DigitalInput digital_input, bool is_active) = 0;
virtual void reset_all_inputs() = 0;
virtual void reset_all_inputs() {
set_digital_input(DigitalInput::Up, false);
set_digital_input(DigitalInput::Down, false);
set_digital_input(DigitalInput::Left, false);
set_digital_input(DigitalInput::Right, false);
set_digital_input(DigitalInput::Fire, false);
}
};
}

View File

@ -30,6 +30,33 @@ namespace {
namespace Atari2600 {
class Joystick: public Inputs::Joystick {
public:
Joystick(Bus *bus, size_t shift, size_t fire_tia_input) :
bus_(bus), shift_(shift), fire_tia_input_(fire_tia_input) {}
void set_digital_input(DigitalInput digital_input, bool is_active) {
switch(digital_input) {
case DigitalInput::Up: bus_->mos6532_.update_port_input(0, 0x10 >> shift_, is_active); break;
case DigitalInput::Down: bus_->mos6532_.update_port_input(0, 0x20 >> shift_, is_active); break;
case DigitalInput::Left: bus_->mos6532_.update_port_input(0, 0x40 >> shift_, is_active); break;
case DigitalInput::Right: bus_->mos6532_.update_port_input(0, 0x80 >> shift_, is_active); break;
// TODO: latching
case DigitalInput::Fire:
if(is_active)
bus_->tia_input_value_[fire_tia_input_] &= ~0x80;
else
bus_->tia_input_value_[fire_tia_input_] |= 0x80;
break;
}
}
private:
size_t shift_, fire_tia_input_;
Bus *bus_;
};
class ConcreteMachine:
public Machine,
public Outputs::CRT::Delegate {
@ -44,7 +71,7 @@ class ConcreteMachine:
close_output();
}
void configure_as_target(const StaticAnalyser::Target &target) {
void configure_as_target(const StaticAnalyser::Target &target) override {
const std::vector<uint8_t> &rom = target.media.cartridges.front()->get_segments().front().data;
switch(target.atari.paging_model) {
case StaticAnalyser::Atari2600PagingModel::ActivisionStack: bus_.reset(new Cartridge::Cartridge<Cartridge::ActivisionStack>(rom)); break;
@ -79,34 +106,20 @@ class ConcreteMachine:
}
break;
}
joysticks_.push_back(new Joystick(bus_.get(), 0, 0));
joysticks_.push_back(new Joystick(bus_.get(), 4, 1));
}
bool insert_media(const StaticAnalyser::Media &media) {
bool insert_media(const StaticAnalyser::Media &media) override {
return false;
}
void set_digital_input(Atari2600DigitalInput input, bool state) {
switch (input) {
case Atari2600DigitalInputJoy1Up: bus_->mos6532_.update_port_input(0, 0x10, state); break;
case Atari2600DigitalInputJoy1Down: bus_->mos6532_.update_port_input(0, 0x20, state); break;
case Atari2600DigitalInputJoy1Left: bus_->mos6532_.update_port_input(0, 0x40, state); break;
case Atari2600DigitalInputJoy1Right: bus_->mos6532_.update_port_input(0, 0x80, state); break;
case Atari2600DigitalInputJoy2Up: bus_->mos6532_.update_port_input(0, 0x01, state); break;
case Atari2600DigitalInputJoy2Down: bus_->mos6532_.update_port_input(0, 0x02, state); break;
case Atari2600DigitalInputJoy2Left: bus_->mos6532_.update_port_input(0, 0x04, state); break;
case Atari2600DigitalInputJoy2Right: bus_->mos6532_.update_port_input(0, 0x08, state); break;
// TODO: latching
case Atari2600DigitalInputJoy1Fire: if(state) bus_->tia_input_value_[0] &= ~0x80; else bus_->tia_input_value_[0] |= 0x80; break;
case Atari2600DigitalInputJoy2Fire: if(state) bus_->tia_input_value_[1] &= ~0x80; else bus_->tia_input_value_[1] |= 0x80; break;
default: break;
}
std::vector<Inputs::Joystick *> &get_joysticks() override {
return joysticks_;
}
void set_switch_is_enabled(Atari2600Switch input, bool state) {
void set_switch_is_enabled(Atari2600Switch input, bool state) override {
switch(input) {
case Atari2600SwitchReset: bus_->mos6532_.update_port_input(1, 0x01, state); break;
case Atari2600SwitchSelect: bus_->mos6532_.update_port_input(1, 0x02, state); break;
@ -116,36 +129,36 @@ class ConcreteMachine:
}
}
void set_reset_switch(bool state) {
void set_reset_switch(bool state) override {
bus_->set_reset_line(state);
}
// to satisfy CRTMachine::Machine
void setup_output(float aspect_ratio) {
void setup_output(float aspect_ratio) override {
bus_->tia_.reset(new TIA);
bus_->speaker_.reset(new Speaker);
bus_->speaker_->set_input_rate((float)(get_clock_rate() / (double)CPUTicksPerAudioTick));
bus_->tia_->get_crt()->set_delegate(this);
}
void close_output() {
void close_output() override {
bus_.reset();
}
std::shared_ptr<Outputs::CRT::CRT> get_crt() {
std::shared_ptr<Outputs::CRT::CRT> get_crt() override {
return bus_->tia_->get_crt();
}
std::shared_ptr<Outputs::Speaker> get_speaker() {
std::shared_ptr<Outputs::Speaker> get_speaker() override {
return bus_->speaker_;
}
void run_for(const Cycles cycles) {
void run_for(const Cycles cycles) override {
bus_->run_for(cycles);
}
// to satisfy Outputs::CRT::Delegate
void crt_did_end_batch_of_frames(Outputs::CRT::CRT *crt, unsigned int number_of_frames, unsigned int number_of_unexpected_vertical_syncs) {
void crt_did_end_batch_of_frames(Outputs::CRT::CRT *crt, unsigned int number_of_frames, unsigned int number_of_unexpected_vertical_syncs) override {
const size_t number_of_frame_records = sizeof(frame_records_) / sizeof(frame_records_[0]);
frame_records_[frame_record_pointer_ % number_of_frame_records].number_of_frames = number_of_frames;
frame_records_[frame_record_pointer_ % number_of_frame_records].number_of_unexpected_vertical_syncs = number_of_unexpected_vertical_syncs;
@ -182,7 +195,6 @@ class ConcreteMachine:
}
}
private:
// the bus
std::unique_ptr<Bus> bus_;
@ -196,6 +208,7 @@ class ConcreteMachine:
} frame_records_[4];
unsigned int frame_record_pointer_;
bool is_ntsc_;
std::vector<Inputs::Joystick *> joysticks_;
};
}

View File

@ -11,6 +11,7 @@
#include "../ConfigurationTarget.hpp"
#include "../CRTMachine.hpp"
#include "../JoystickMachine.hpp"
#include "Atari2600Inputs.h"
@ -21,16 +22,14 @@ namespace Atari2600 {
*/
class Machine:
public CRTMachine::Machine,
public ConfigurationTarget::Machine {
public ConfigurationTarget::Machine,
public JoystickMachine::Machine {
public:
virtual ~Machine();
/// Creates and returns an Atari 2600 on the heap.
static Machine *Atari2600();
/// Sets @c input to @c state.
virtual void set_digital_input(Atari2600DigitalInput input, bool state) = 0;
/// Sets the switch @c input to @c state.
virtual void set_switch_is_enabled(Atari2600Switch input, bool state) = 0;

View File

@ -25,23 +25,23 @@
}
- (void)setDirection:(CSJoystickDirection)direction onPad:(NSUInteger)pad isPressed:(BOOL)isPressed {
Atari2600DigitalInput input;
switch(direction)
{
case CSJoystickDirectionUp: input = pad ? Atari2600DigitalInputJoy2Up : Atari2600DigitalInputJoy1Up; break;
case CSJoystickDirectionDown: input = pad ? Atari2600DigitalInputJoy2Down : Atari2600DigitalInputJoy1Down; break;
case CSJoystickDirectionLeft: input = pad ? Atari2600DigitalInputJoy2Left : Atari2600DigitalInputJoy1Left; break;
case CSJoystickDirectionRight: input = pad ? Atari2600DigitalInputJoy2Right : Atari2600DigitalInputJoy1Right; break;
}
@synchronized(self) {
_atari2600->set_digital_input(input, isPressed ? true : false);
}
// Atari2600DigitalInput input;
// switch(direction)
// {
// case CSJoystickDirectionUp: input = pad ? Atari2600DigitalInputJoy2Up : Atari2600DigitalInputJoy1Up; break;
// case CSJoystickDirectionDown: input = pad ? Atari2600DigitalInputJoy2Down : Atari2600DigitalInputJoy1Down; break;
// case CSJoystickDirectionLeft: input = pad ? Atari2600DigitalInputJoy2Left : Atari2600DigitalInputJoy1Left; break;
// case CSJoystickDirectionRight: input = pad ? Atari2600DigitalInputJoy2Right : Atari2600DigitalInputJoy1Right; break;
// }
// @synchronized(self) {
// _atari2600->set_digital_input(input, isPressed ? true : false);
// }
}
- (void)setButtonAtIndex:(NSUInteger)button onPad:(NSUInteger)pad isPressed:(BOOL)isPressed {
@synchronized(self) {
_atari2600->set_digital_input(pad ? Atari2600DigitalInputJoy2Fire : Atari2600DigitalInputJoy1Fire, isPressed ? true : false);
}
// @synchronized(self) {
// _atari2600->set_digital_input(pad ? Atari2600DigitalInputJoy2Fire : Atari2600DigitalInputJoy1Fire, isPressed ? true : false);
// }
}
- (void)setResetLineEnabled:(BOOL)enabled {