1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-09-28 09:54:49 +00:00

Adds a Master System class, so that SMSs can end up somewhere.

This commit is contained in:
Thomas Harte 2018-09-21 22:13:07 -04:00
parent 0d01346ad4
commit e511261b04
3 changed files with 125 additions and 1 deletions

View File

@ -7,3 +7,112 @@
//
#include "MasterSystem.hpp"
#include "../../Processors/Z80/Z80.hpp"
#include "../../Components/9918/9918.hpp"
#include "../../Components/SN76489/SN76489.hpp"
#include "../CRTMachine.hpp"
#include "../JoystickMachine.hpp"
#include "../../ClockReceiver/ForceInline.hpp"
#include "../../Outputs/Speaker/Implementation/LowpassSpeaker.hpp"
namespace {
const int sn76489_divider = 2;
}
namespace Sega {
namespace MasterSystem {
class ConcreteMachine:
public Machine,
public CPU::Z80::BusHandler,
public CRTMachine::Machine {
public:
ConcreteMachine(const Analyser::Static::Target &target, const ROMMachine::ROMFetcher &rom_fetcher) :
z80_(*this),
sn76489_(TI::SN76489::Personality::SN76489, audio_queue_, sn76489_divider),
speaker_(sn76489_) {
speaker_.set_input_rate(3579545.0f / static_cast<float>(sn76489_divider));
set_clock_rate(3579545);
}
~ConcreteMachine() {
audio_queue_.flush();
}
void setup_output(float aspect_ratio) override {
vdp_.reset(new TI::TMS::TMS9918(TI::TMS::TMS9918A));
get_crt()->set_video_signal(Outputs::CRT::VideoSignal::Composite);
}
void close_output() override {
vdp_.reset();
}
Outputs::CRT::CRT *get_crt() override {
return vdp_->get_crt();
}
Outputs::Speaker::Speaker *get_speaker() override {
return &speaker_;
}
void run_for(const Cycles cycles) override {
z80_.run_for(cycles);
}
forceinline HalfCycles perform_machine_cycle(const CPU::Z80::PartialMachineCycle &cycle) {
time_since_vdp_update_ += cycle.length;
time_since_sn76489_update_ += cycle.length;
if(time_until_interrupt_ > 0) {
time_until_interrupt_ -= cycle.length;
if(time_until_interrupt_ <= HalfCycles(0)) {
z80_.set_non_maskable_interrupt_line(true, time_until_interrupt_);
}
}
return HalfCycles(0);
}
void flush() {
update_video();
update_audio();
audio_queue_.perform();
}
private:
inline void update_audio() {
speaker_.run_for(audio_queue_, time_since_sn76489_update_.divide_cycles(Cycles(sn76489_divider)));
}
inline void update_video() {
vdp_->run_for(time_since_vdp_update_.flush());
}
CPU::Z80::Processor<ConcreteMachine, false, false> z80_;
std::unique_ptr<TI::TMS::TMS9918> vdp_;
Concurrency::DeferringAsyncTaskQueue audio_queue_;
TI::SN76489 sn76489_;
Outputs::Speaker::LowpassSpeaker<TI::SN76489> speaker_;
HalfCycles time_since_vdp_update_;
HalfCycles time_since_sn76489_update_;
HalfCycles time_until_interrupt_;
};
}
}
using namespace Sega::MasterSystem;
Machine *Machine::MasterSystem(const Analyser::Static::Target *target, const ROMMachine::ROMFetcher &rom_fetcher) {
return new ConcreteMachine(*target, rom_fetcher);
}
Machine::~Machine() {}

View File

@ -9,6 +9,19 @@
#ifndef MasterSystem_hpp
#define MasterSystem_hpp
#include <stdio.h>
#include "../../Analyser/Static/StaticAnalyser.hpp"
#include "../ROMMachine.hpp"
namespace Sega {
namespace MasterSystem {
class Machine {
public:
virtual ~Machine();
static Machine *MasterSystem(const Analyser::Static::Target *target, const ROMMachine::ROMFetcher &rom_fetcher);
};
}
}
#endif /* MasterSystem_hpp */

View File

@ -14,6 +14,7 @@
#include "../ColecoVision/ColecoVision.hpp"
#include "../Commodore/Vic-20/Vic20.hpp"
#include "../Electron/Electron.hpp"
#include "../MasterSystem/MasterSystem.hpp"
#include "../MSX/MSX.hpp"
#include "../Oric/Oric.hpp"
#include "../ZX8081/ZX8081.hpp"
@ -36,6 +37,7 @@ namespace {
Bind(Atari2600)
BindD(Coleco::Vision, ColecoVision)
Bind(Electron)
BindD(Sega::MasterSystem, MasterSystem)
Bind(MSX)
Bind(Oric)
BindD(Commodore::Vic20, Vic20)