mirror of
https://github.com/TomHarte/CLK.git
synced 2024-11-19 08:31:11 +00:00
Made a first attempt to hash out the ZX80's bus. Video output isn't yet going though. Can't seem to find clarity on whether horizontal sync is really programmatic. Let's see.
This commit is contained in:
parent
c485c460f7
commit
096551ab3e
@ -10,17 +10,64 @@
|
|||||||
|
|
||||||
using namespace ZX8081;
|
using namespace ZX8081;
|
||||||
|
|
||||||
Machine::Machine() {
|
Machine::Machine() :
|
||||||
|
vertical_sync_(false),
|
||||||
|
ram_(65536) {
|
||||||
// run at 3.25 Mhz
|
// run at 3.25 Mhz
|
||||||
set_clock_rate(3250000);
|
set_clock_rate(3250000);
|
||||||
}
|
}
|
||||||
|
|
||||||
int Machine::perform_machine_cycle(const CPU::Z80::MachineCycle &cycle) {
|
int Machine::perform_machine_cycle(const CPU::Z80::MachineCycle &cycle) {
|
||||||
|
cycles_since_display_update_ += cycle.length;
|
||||||
|
|
||||||
|
uint8_t r;
|
||||||
|
switch(cycle.operation) {
|
||||||
|
case CPU::Z80::BusOperation::Output:
|
||||||
|
if(*cycle.address == 0xff) {
|
||||||
|
update_display();
|
||||||
|
set_sync(false);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CPU::Z80::BusOperation::Input:
|
||||||
|
if(*cycle.address == 0xfe) {
|
||||||
|
update_display();
|
||||||
|
set_sync(true);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CPU::Z80::BusOperation::Interrupt:
|
||||||
|
*cycle.value = 0xff;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CPU::Z80::BusOperation::ReadOpcode:
|
||||||
|
r = (uint8_t)get_value_of_register(CPU::Z80::Register::R);
|
||||||
|
set_interrupt_line(!(r & 0x40));
|
||||||
|
case CPU::Z80::BusOperation::Read:
|
||||||
|
if(*cycle.address < rom_.size()) *cycle.value = rom_[*cycle.address];
|
||||||
|
else {
|
||||||
|
uint8_t value = ram_[*cycle.address];
|
||||||
|
if(*cycle.address > 32768 && !(value & 0x40) && cycle.operation == CPU::Z80::BusOperation::ReadOpcode) {
|
||||||
|
// TODO: character lookup.
|
||||||
|
output_byte(value);
|
||||||
|
*cycle.value = 0;
|
||||||
|
}
|
||||||
|
else *cycle.value = value;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CPU::Z80::BusOperation::Write:
|
||||||
|
ram_[*cycle.address] = *cycle.value;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Machine::setup_output(float aspect_ratio) {
|
void Machine::setup_output(float aspect_ratio) {
|
||||||
crt_.reset(new Outputs::CRT::CRT(207 * 8, 8, Outputs::CRT::DisplayType::PAL50, 1));
|
crt_.reset(new Outputs::CRT::CRT(207, 1, Outputs::CRT::DisplayType::PAL50, 1));
|
||||||
crt_->set_rgb_sampling_function(
|
crt_->set_rgb_sampling_function(
|
||||||
"vec3 rgb_sample(usampler2D sampler, vec2 coordinate, vec2 icoordinate)"
|
"vec3 rgb_sample(usampler2D sampler, vec2 coordinate, vec2 icoordinate)"
|
||||||
"{"
|
"{"
|
||||||
@ -29,6 +76,7 @@ void Machine::setup_output(float aspect_ratio) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Machine::flush() {
|
void Machine::flush() {
|
||||||
|
update_display();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Machine::close_output() {
|
void Machine::close_output() {
|
||||||
@ -46,6 +94,8 @@ void Machine::run_for_cycles(int number_of_cycles) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Machine::configure_as_target(const StaticAnalyser::Target &target) {
|
void Machine::configure_as_target(const StaticAnalyser::Target &target) {
|
||||||
|
// TODO: pay attention to the target
|
||||||
|
rom_ = zx80_rom_;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Machine::set_rom(ROMType type, std::vector<uint8_t> data) {
|
void Machine::set_rom(ROMType type, std::vector<uint8_t> data) {
|
||||||
@ -54,3 +104,16 @@ void Machine::set_rom(ROMType type, std::vector<uint8_t> data) {
|
|||||||
case ZX81: zx81_rom_ = data; break;
|
case ZX81: zx81_rom_ = data; break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#pragma mark - Video
|
||||||
|
|
||||||
|
void Machine::update_display() {
|
||||||
|
// TODO.
|
||||||
|
cycles_since_display_update_ = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Machine::set_sync(bool sync) {
|
||||||
|
}
|
||||||
|
|
||||||
|
void Machine::output_byte(uint8_t byte) {
|
||||||
|
}
|
||||||
|
@ -49,6 +49,13 @@ class Machine:
|
|||||||
std::shared_ptr<Outputs::CRT::CRT> crt_;
|
std::shared_ptr<Outputs::CRT::CRT> crt_;
|
||||||
std::vector<uint8_t> zx81_rom_, zx80_rom_, rom_;
|
std::vector<uint8_t> zx81_rom_, zx80_rom_, rom_;
|
||||||
std::vector<uint8_t> ram_;
|
std::vector<uint8_t> ram_;
|
||||||
|
|
||||||
|
bool vertical_sync_;
|
||||||
|
|
||||||
|
int cycles_since_display_update_;
|
||||||
|
void update_display();
|
||||||
|
void set_sync(bool sync);
|
||||||
|
void output_byte(uint8_t byte);
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -38,7 +38,7 @@ enum Register {
|
|||||||
|
|
||||||
IXh, IXl, IX,
|
IXh, IXl, IX,
|
||||||
IYh, IYl, IY,
|
IYh, IYl, IY,
|
||||||
R, I,
|
R, I, Refresh,
|
||||||
|
|
||||||
IFF1, IFF2, IM
|
IFF1, IFF2, IM
|
||||||
};
|
};
|
||||||
@ -1652,10 +1652,11 @@ template <class T> class Processor {
|
|||||||
|
|
||||||
case Register::R: return r_;
|
case Register::R: return r_;
|
||||||
case Register::I: return i_;
|
case Register::I: return i_;
|
||||||
|
case Register::Refresh: return (uint16_t)(r_ | (i_ << 8));
|
||||||
|
|
||||||
case Register::IFF1: return iff1_ ? 1 : 0;
|
case Register::IFF1: return iff1_ ? 1 : 0;
|
||||||
case Register::IFF2: return iff2_ ? 1 : 0;
|
case Register::IFF2: return iff2_ ? 1 : 0;
|
||||||
case Register::IM: return interrupt_mode_;
|
case Register::IM: return (uint16_t)interrupt_mode_;
|
||||||
|
|
||||||
default: return 0;
|
default: return 0;
|
||||||
}
|
}
|
||||||
@ -1710,6 +1711,7 @@ template <class T> class Processor {
|
|||||||
|
|
||||||
case Register::R: r_ = (uint8_t)value; break;
|
case Register::R: r_ = (uint8_t)value; break;
|
||||||
case Register::I: i_ = (uint8_t)value; break;
|
case Register::I: i_ = (uint8_t)value; break;
|
||||||
|
case Register::Refresh: r_ = (uint8_t)value; i_ = (uint8_t)(value >> 8); break;
|
||||||
|
|
||||||
case Register::IFF1: iff1_ = !!value; break;
|
case Register::IFF1: iff1_ = !!value; break;
|
||||||
case Register::IFF2: iff2_ = !!value; break;
|
case Register::IFF2: iff2_ = !!value; break;
|
||||||
|
Loading…
Reference in New Issue
Block a user