mirror of
https://github.com/TomHarte/CLK.git
synced 2025-01-12 00:30:31 +00:00
Proceeds the ColecoVision to booting.
This commit is contained in:
parent
5530b96446
commit
23c47e21de
@ -8,11 +8,141 @@
|
|||||||
|
|
||||||
#include "ColecoVision.hpp"
|
#include "ColecoVision.hpp"
|
||||||
|
|
||||||
|
#include "../../Processors/Z80/Z80.hpp"
|
||||||
|
|
||||||
|
#include "../../Components/9918/9918.hpp"
|
||||||
|
|
||||||
|
#include "../CRTMachine.hpp"
|
||||||
|
|
||||||
|
#include "../../ClockReceiver/ForceInline.hpp"
|
||||||
|
|
||||||
namespace Coleco {
|
namespace Coleco {
|
||||||
namespace Vision {
|
namespace Vision {
|
||||||
|
|
||||||
class ConcreteMachine:
|
class ConcreteMachine:
|
||||||
public Machine {
|
public Machine,
|
||||||
|
public CPU::Z80::BusHandler,
|
||||||
|
public CRTMachine::Machine {
|
||||||
|
|
||||||
|
public:
|
||||||
|
ConcreteMachine() : z80_(*this) {
|
||||||
|
set_clock_rate(3579545);
|
||||||
|
}
|
||||||
|
|
||||||
|
void setup_output(float aspect_ratio) override {
|
||||||
|
vdp_.reset(new TI::TMS9918(TI::TMS9918::TMS9918A));
|
||||||
|
get_crt()->set_output_device(Outputs::CRT::OutputDevice::Television);
|
||||||
|
}
|
||||||
|
|
||||||
|
void close_output() override {
|
||||||
|
vdp_.reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
Outputs::CRT::CRT *get_crt() override {
|
||||||
|
return vdp_->get_crt();
|
||||||
|
}
|
||||||
|
|
||||||
|
Outputs::Speaker::Speaker *get_speaker() override {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void run_for(const Cycles cycles) override {
|
||||||
|
z80_.run_for(cycles);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Obtains the system ROMs.
|
||||||
|
bool set_rom_fetcher(const std::function<std::vector<std::unique_ptr<std::vector<uint8_t>>>(const std::string &machine, const std::vector<std::string> &names)> &roms_with_names) override {
|
||||||
|
auto roms = roms_with_names(
|
||||||
|
"ColecoVision",
|
||||||
|
{
|
||||||
|
"coleco.rom"
|
||||||
|
});
|
||||||
|
|
||||||
|
if(!roms[0]) return false;
|
||||||
|
|
||||||
|
bios_ = *roms[0];
|
||||||
|
bios_.resize(8192);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: Z80::BusHandler
|
||||||
|
forceinline HalfCycles perform_machine_cycle(const CPU::Z80::PartialMachineCycle &cycle) {
|
||||||
|
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_);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t address = cycle.address ? *cycle.address : 0x0000;
|
||||||
|
switch(cycle.operation) {
|
||||||
|
case CPU::Z80::PartialMachineCycle::ReadOpcode:
|
||||||
|
case CPU::Z80::PartialMachineCycle::Read:
|
||||||
|
if(address < 0x2000) {
|
||||||
|
*cycle.value = bios_[address];
|
||||||
|
} else if(address >= 0x6000 && address < 0x8000) {
|
||||||
|
*cycle.value = ram_[address & 1023];
|
||||||
|
} else {
|
||||||
|
*cycle.value = 0xff;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CPU::Z80::PartialMachineCycle::Write:
|
||||||
|
if(address >= 0x6000 && address < 0x8000) {
|
||||||
|
ram_[address & 1023] = *cycle.value;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CPU::Z80::PartialMachineCycle::Input:
|
||||||
|
switch((address >> 5) & 7) {
|
||||||
|
case 5:
|
||||||
|
vdp_->run_for(time_since_vdp_update_.flush());
|
||||||
|
*cycle.value = vdp_->get_register(address);
|
||||||
|
z80_.set_non_maskable_interrupt_line(vdp_->get_interrupt_line());
|
||||||
|
time_until_interrupt_ = vdp_->get_time_until_interrupt();
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
*cycle.value = 0xff;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CPU::Z80::PartialMachineCycle::Output:
|
||||||
|
switch((address >> 5) & 7) {
|
||||||
|
case 5:
|
||||||
|
vdp_->run_for(time_since_vdp_update_.flush());
|
||||||
|
vdp_->set_register(address, *cycle.value);
|
||||||
|
z80_.set_non_maskable_interrupt_line(vdp_->get_interrupt_line());
|
||||||
|
time_until_interrupt_ = vdp_->get_time_until_interrupt();
|
||||||
|
break;
|
||||||
|
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
time_since_vdp_update_ += cycle.length;
|
||||||
|
return HalfCycles(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void flush() {
|
||||||
|
vdp_->run_for(time_since_vdp_update_.flush());
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
CPU::Z80::Processor<ConcreteMachine, false, false> z80_;
|
||||||
|
std::unique_ptr<TI::TMS9918> vdp_;
|
||||||
|
|
||||||
|
std::vector<uint8_t> bios_;
|
||||||
|
uint8_t ram_[1024];
|
||||||
|
|
||||||
|
HalfCycles time_since_vdp_update_;
|
||||||
|
HalfCycles time_until_interrupt_;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1001,12 +1001,12 @@ bool ProcessorBase::get_interrupt_line() {
|
|||||||
return irq_line_;
|
return irq_line_;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ProcessorBase::set_non_maskable_interrupt_line(bool value, int offset) {
|
void ProcessorBase::set_non_maskable_interrupt_line(bool value, HalfCycles offset) {
|
||||||
// NMIs are edge triggered and cannot be masked.
|
// NMIs are edge triggered and cannot be masked.
|
||||||
nmi_line_ = value;
|
nmi_line_ = value;
|
||||||
if(value) {
|
if(value) {
|
||||||
request_status_ |= Interrupt::NMI;
|
request_status_ |= Interrupt::NMI;
|
||||||
if(offset < 0) {
|
if(offset.as_int() < 0) {
|
||||||
last_request_status_ |= Interrupt::NMI;
|
last_request_status_ |= Interrupt::NMI;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -206,7 +206,7 @@ class ProcessorBase: public ProcessorStorage {
|
|||||||
|
|
||||||
@param offset See discussion in set_interrupt_line.
|
@param offset See discussion in set_interrupt_line.
|
||||||
*/
|
*/
|
||||||
inline void set_non_maskable_interrupt_line(bool value, int offset = 0);
|
inline void set_non_maskable_interrupt_line(bool value, HalfCycles offset = 0);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
Gets the value of the non-maskable interrupt line.
|
Gets the value of the non-maskable interrupt line.
|
||||||
|
5
ROMImages/ColecoVision/readme.txt
Normal file
5
ROMImages/ColecoVision/readme.txt
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
ROM files would ordinarily go here; the copyright status of these is uncertain so they have not been included in this repository.
|
||||||
|
|
||||||
|
Expected files:
|
||||||
|
|
||||||
|
coleco.rom; an 8kb image of the ColecoVision's BIOS ROM.
|
Loading…
x
Reference in New Issue
Block a user