mirror of
https://github.com/TomHarte/CLK.git
synced 2025-01-14 13:33:42 +00:00
Adds the necessary call-outs to allow implementation of video generation.
This commit is contained in:
parent
71adb964e5
commit
61659faeaa
@ -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_;
|
||||
|
@ -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");
|
||||
}
|
||||
|
@ -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_;
|
||||
};
|
||||
|
Loading…
x
Reference in New Issue
Block a user