1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-07-05 10:28:58 +00:00

Adds the necessary call-outs to allow implementation of video generation.

This commit is contained in:
Thomas Harte 2018-04-15 15:13:07 -04:00
parent 71adb964e5
commit 61659faeaa
3 changed files with 103 additions and 16 deletions

View File

@ -47,23 +47,58 @@ class ConcreteMachine:
return nullptr;
}
void run_for(const Cycles cycles) override {
m6502_.run_for(cycles);
Cycles perform_bus_operation(CPU::MOS6502::BusOperation operation, uint16_t address, uint8_t *value) {
++ cycles_since_video_update_;
switch(address) {
default:
if(isReadOperation(operation)) {
if(address < sizeof(ram_)) {
*value = ram_[address];
} else if(address >= rom_start_address_) {
*value = rom_[address - rom_start_address_];
} else {
switch(address) {
default: *value = 0xff; break;
case 0xc000:
// TODO: read keyboard.
*value = 0;
break;
}
}
} else {
if(address < sizeof(ram_)) {
update_video(); // TODO: be more selective.
ram_[address] = *value;
}
}
break;
case 0xc050: update_video(); video_->set_graphics_mode(); break;
case 0xc051: update_video(); video_->set_text_mode(); break;
case 0xc052: update_video(); video_->set_mixed_mode(false); break;
case 0xc053: update_video(); video_->set_mixed_mode(true); break;
case 0xc054: update_video(); video_->set_video_page(0); break;
case 0xc055: update_video(); video_->set_video_page(1); break;
case 0xc056: update_video(); video_->set_low_resolution(); break;
case 0xc057: update_video(); video_->set_high_resolution(); break;
}
// The Apple II has a slightly weird timing pattern: every 65th CPU cycle is stretched
// by an extra 1/7th. That's because one cycle lasts 3.5 NTSC colour clocks, so after
// 65 cycles a full line of 227.5 colour clocks have passed. But the high-rate binary
// signal approximation that produces colour needs to be in phase, so a stretch of exactly
// 0.5 further colour cycles is added.
cycles_into_current_line_ = (cycles_into_current_line_ + 1) % 65;
if(!cycles_into_current_line_) {
// Do something. Do something else.
}
return Cycles(1);
}
Cycles perform_bus_operation(CPU::MOS6502::BusOperation operation, uint16_t address, uint8_t *value) {
if(isReadOperation(operation)) {
if(address < sizeof(ram_)) {
*value = ram_[address];
} else if(address >= rom_start_address_) {
*value = rom_[address - rom_start_address_];
}
} else {
if(address < sizeof(ram_)) {
ram_[address] = *value;
}
}
return Cycles(1);
void flush() {
update_video();
}
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 {
@ -80,9 +115,19 @@ class ConcreteMachine:
return true;
}
void run_for(const Cycles cycles) override {
m6502_.run_for(cycles);
}
private:
CPU::MOS6502::Processor<ConcreteMachine, false> m6502_;
std::unique_ptr<AppleII::Video> video_;
int cycles_into_current_line_ = 0;
Cycles cycles_since_video_update_;
void update_video() {
video_->run_for(cycles_since_video_update_.flush());
}
uint8_t ram_[48*1024];
std::vector<uint8_t> rom_;

View File

@ -11,7 +11,7 @@
using namespace AppleII;
Video::Video() :
crt_(new Outputs::CRT::CRT(65, 1, Outputs::CRT::DisplayType::NTSC60, 1)) {
crt_(new Outputs::CRT::CRT(455, 1, Outputs::CRT::DisplayType::NTSC60, 1)) {
// Set a composite sampling function that assumes 1bpp input, and uses just 7 bits per byte.
crt_->set_composite_sampling_function(
@ -30,3 +30,30 @@ Video::Video() :
Outputs::CRT::CRT *Video::get_crt() {
return crt_.get();
}
void Video::run_for(const Cycles) {
}
void Video::set_graphics_mode() {
printf("Graphics mode\n");
}
void Video::set_text_mode() {
printf("Text mode\n");
}
void Video::set_mixed_mode(bool mixed_mode) {
printf("Mixed mode: %s\n", mixed_mode ? "true" : "false");
}
void Video::set_video_page(int page) {
printf("Video page: %d\n", page);
}
void Video::set_low_resolution() {
printf("Low resolution\n");
}
void Video::set_high_resolution() {
printf("High resolution\n");
}

View File

@ -21,6 +21,21 @@ class Video {
/// @returns The CRT this video feed is feeding.
Outputs::CRT::CRT *get_crt();
/*!
Advances time by @c cycles; expects to be fed by the CPU clock.
Implicitly adds an extra half a colour clock at the end of every
line.
*/
void run_for(const Cycles);
// Inputs for the various soft switches.
void set_graphics_mode();
void set_text_mode();
void set_mixed_mode(bool);
void set_video_page(int);
void set_low_resolution();
void set_high_resolution();
private:
std::unique_ptr<Outputs::CRT::CRT> crt_;
};