mirror of
https://github.com/TomHarte/CLK.git
synced 2024-10-20 06:25:01 +00:00
Adds a couple of joystick inputs.
SG1000 titles all seem to work now.
This commit is contained in:
parent
2253341904
commit
5b9e7213dd
@ -29,10 +29,50 @@ const int sn76489_divider = 2;
|
|||||||
namespace Sega {
|
namespace Sega {
|
||||||
namespace MasterSystem {
|
namespace MasterSystem {
|
||||||
|
|
||||||
|
class Joystick: public Inputs::ConcreteJoystick {
|
||||||
|
public:
|
||||||
|
Joystick() :
|
||||||
|
ConcreteJoystick({
|
||||||
|
Input(Input::Up),
|
||||||
|
Input(Input::Down),
|
||||||
|
Input(Input::Left),
|
||||||
|
Input(Input::Right),
|
||||||
|
|
||||||
|
Input(Input::Fire, 0),
|
||||||
|
Input(Input::Fire, 1)
|
||||||
|
}) {}
|
||||||
|
|
||||||
|
void did_set_input(const Input &digital_input, bool is_active) override {
|
||||||
|
switch(digital_input.type) {
|
||||||
|
default: return;
|
||||||
|
|
||||||
|
case Input::Up: if(is_active) state_ &= ~0x01; else state_ |= 0x01; break;
|
||||||
|
case Input::Down: if(is_active) state_ &= ~0x02; else state_ |= 0x02; break;
|
||||||
|
case Input::Left: if(is_active) state_ &= ~0x04; else state_ |= 0x04; break;
|
||||||
|
case Input::Right: if(is_active) state_ &= ~0x08; else state_ |= 0x08; break;
|
||||||
|
case Input::Fire:
|
||||||
|
switch(digital_input.info.control.index) {
|
||||||
|
default: break;
|
||||||
|
case 0: if(is_active) state_ &= ~0x10; else state_ |= 0x10; break;
|
||||||
|
case 1: if(is_active) state_ &= ~0x20; else state_ |= 0x20; break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t get_state() {
|
||||||
|
return state_;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
uint8_t state_ = 0xff;
|
||||||
|
};
|
||||||
|
|
||||||
class ConcreteMachine:
|
class ConcreteMachine:
|
||||||
public Machine,
|
public Machine,
|
||||||
public CPU::Z80::BusHandler,
|
public CPU::Z80::BusHandler,
|
||||||
public CRTMachine::Machine {
|
public CRTMachine::Machine,
|
||||||
|
public JoystickMachine::Machine {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ConcreteMachine(const Analyser::Static::Sega::Target &target, const ROMMachine::ROMFetcher &rom_fetcher) :
|
ConcreteMachine(const Analyser::Static::Sega::Target &target, const ROMMachine::ROMFetcher &rom_fetcher) :
|
||||||
@ -42,6 +82,11 @@ class ConcreteMachine:
|
|||||||
speaker_.set_input_rate(3579545.0f / static_cast<float>(sn76489_divider));
|
speaker_.set_input_rate(3579545.0f / static_cast<float>(sn76489_divider));
|
||||||
set_clock_rate(3579545);
|
set_clock_rate(3579545);
|
||||||
|
|
||||||
|
// Instantiate the joysticks.
|
||||||
|
joysticks_.emplace_back(new Joystick);
|
||||||
|
joysticks_.emplace_back(new Joystick);
|
||||||
|
|
||||||
|
// Clear the memory map.
|
||||||
for(auto &pointer: read_pointers_) {
|
for(auto &pointer: read_pointers_) {
|
||||||
pointer = nullptr;
|
pointer = nullptr;
|
||||||
}
|
}
|
||||||
@ -116,15 +161,15 @@ class ConcreteMachine:
|
|||||||
case CPU::Z80::PartialMachineCycle::Input:
|
case CPU::Z80::PartialMachineCycle::Input:
|
||||||
switch(address & 0xc1) {
|
switch(address & 0xc1) {
|
||||||
case 0x00:
|
case 0x00:
|
||||||
printf("TODO: memory control\n");
|
printf("TODO: [input] memory control\n");
|
||||||
*cycle.value = 0xff;
|
*cycle.value = 0xff;
|
||||||
break;
|
break;
|
||||||
case 0x01:
|
case 0x01:
|
||||||
printf("TODO: I/O port control\n");
|
printf("TODO: [input] I/O port control\n");
|
||||||
*cycle.value = 0xff;
|
*cycle.value = 0xff;
|
||||||
break;
|
break;
|
||||||
case 0x40: case 0x41:
|
case 0x40: case 0x41:
|
||||||
printf("TODO: get current line\n");
|
printf("TODO: [input] get current line\n");
|
||||||
*cycle.value = 0xff;
|
*cycle.value = 0xff;
|
||||||
break;
|
break;
|
||||||
case 0x80: case 0x81:
|
case 0x80: case 0x81:
|
||||||
@ -133,17 +178,18 @@ class ConcreteMachine:
|
|||||||
z80_.set_interrupt_line(vdp_->get_interrupt_line());
|
z80_.set_interrupt_line(vdp_->get_interrupt_line());
|
||||||
time_until_interrupt_ = vdp_->get_time_until_interrupt();
|
time_until_interrupt_ = vdp_->get_time_until_interrupt();
|
||||||
break;
|
break;
|
||||||
case 0xc0:
|
case 0xc0: {
|
||||||
printf("TODO: I/O port A/N\n");
|
Joystick *const joypad1 = static_cast<Joystick *>(joysticks_[0].get());
|
||||||
*cycle.value = 0;
|
Joystick *const joypad2 = static_cast<Joystick *>(joysticks_[1].get());
|
||||||
break;
|
*cycle.value = static_cast<uint8_t>(joypad1->get_state() | (joypad2->get_state() << 6));
|
||||||
case 0xc1:
|
} break;
|
||||||
printf("TODO: I/O port B/misc\n");
|
case 0xc1: {
|
||||||
*cycle.value = 0;
|
Joystick *const joypad2 = static_cast<Joystick *>(joysticks_[1].get());
|
||||||
break;
|
*cycle.value = (joypad2->get_state() >> 2) | 0xf;
|
||||||
|
} break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
printf("Clearly some sort of typo\n");
|
printf("[input] Clearly some sort of typo\n");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -151,10 +197,10 @@ class ConcreteMachine:
|
|||||||
case CPU::Z80::PartialMachineCycle::Output:
|
case CPU::Z80::PartialMachineCycle::Output:
|
||||||
switch(address & 0xc1) {
|
switch(address & 0xc1) {
|
||||||
case 0x00:
|
case 0x00:
|
||||||
printf("TODO: memory control\n");
|
printf("TODO: [output] memory control\n");
|
||||||
break;
|
break;
|
||||||
case 0x01:
|
case 0x01:
|
||||||
printf("TODO: I/O port control\n");
|
printf("TODO: [output] I/O port control\n");
|
||||||
break;
|
break;
|
||||||
case 0x40: case 0x41:
|
case 0x40: case 0x41:
|
||||||
update_audio();
|
update_audio();
|
||||||
@ -167,14 +213,14 @@ class ConcreteMachine:
|
|||||||
time_until_interrupt_ = vdp_->get_time_until_interrupt();
|
time_until_interrupt_ = vdp_->get_time_until_interrupt();
|
||||||
break;
|
break;
|
||||||
case 0xc0:
|
case 0xc0:
|
||||||
printf("TODO: I/O port A/N\n");
|
// printf("TODO: [output] I/O port A/N [%02x]\n", *cycle.value);
|
||||||
break;
|
break;
|
||||||
case 0xc1:
|
case 0xc1:
|
||||||
printf("TODO: I/O port B/misc\n");
|
printf("TODO: [output] I/O port B/misc\n");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
printf("Clearly some sort of typo\n");
|
printf("[output] Clearly some sort of typo\n");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -203,6 +249,10 @@ class ConcreteMachine:
|
|||||||
audio_queue_.perform();
|
audio_queue_.perform();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::vector<std::unique_ptr<Inputs::Joystick>> &get_joysticks() override {
|
||||||
|
return joysticks_;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
inline void update_audio() {
|
inline void update_audio() {
|
||||||
speaker_.run_for(audio_queue_, time_since_sn76489_update_.divide_cycles(Cycles(sn76489_divider)));
|
speaker_.run_for(audio_queue_, time_since_sn76489_update_.divide_cycles(Cycles(sn76489_divider)));
|
||||||
@ -218,6 +268,8 @@ class ConcreteMachine:
|
|||||||
TI::SN76489 sn76489_;
|
TI::SN76489 sn76489_;
|
||||||
Outputs::Speaker::LowpassSpeaker<TI::SN76489> speaker_;
|
Outputs::Speaker::LowpassSpeaker<TI::SN76489> speaker_;
|
||||||
|
|
||||||
|
std::vector<std::unique_ptr<Inputs::Joystick>> joysticks_;
|
||||||
|
|
||||||
HalfCycles time_since_vdp_update_;
|
HalfCycles time_since_vdp_update_;
|
||||||
HalfCycles time_since_sn76489_update_;
|
HalfCycles time_since_sn76489_update_;
|
||||||
HalfCycles time_until_interrupt_;
|
HalfCycles time_until_interrupt_;
|
||||||
|
Loading…
Reference in New Issue
Block a user