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

Attempts to do just enough with video to get a functioning vertical blank query.

This commit is contained in:
Thomas Harte 2020-11-05 17:56:20 -05:00
parent 5126163c5d
commit f466cbadec
3 changed files with 121 additions and 22 deletions

View File

@ -26,6 +26,12 @@
#include <cassert>
#include <array>
namespace {
constexpr int CLOCK_RATE = 14318180;
}
namespace Apple {
namespace IIgs {
@ -39,7 +45,7 @@ class ConcreteMachine:
ConcreteMachine(const Analyser::Static::AppleIIgs::Target &target, const ROMMachine::ROMFetcher &rom_fetcher) :
m65816_(*this) {
set_clock_rate(14318180.0);
set_clock_rate(double(CLOCK_RATE));
using Target = Analyser::Static::AppleIIgs::Target;
std::vector<ROMMachine::ROM> rom_descriptions;
@ -101,8 +107,6 @@ class ConcreteMachine:
const auto &region = MemoryMapRegion(memory_, address);
static bool log = false;
// TODO: potentially push time to clock_.
if(region.flags & MemoryMap::Region::IsIO) {
// Ensure classic auxiliary and language card accesses have effect.
const bool is_read = isReadOperation(operation);
@ -114,11 +118,29 @@ class ConcreteMachine:
// New video register.
case 0xc029:
if(is_read) {
*value = 0x01;
*value = video_.get_new_video();;
} else {
printf("New video: %02x\n", *value);
// TODO: this bit should affect memory bank selection, somehow?
// Cf. Page 90.
video_.set_new_video(*value);
// TODO: I think bits 7 and 0 might also affect the memory map.
// The descripton isn't especially clear — P.90 of the Hardware Reference.
// Revisit if necessary.
}
break;
// Video [and clock] interrupt register.
case 0xc023:
if(is_read) {
*value = video_.get_interrupt_register();
} else {
video_.set_interrupt_register(*value);
}
break;
// Video onterrupt-clear register.
case 0xc032:
if(!is_read) {
video_.clear_interrupts(*value);
}
break;
@ -183,21 +205,15 @@ class ConcreteMachine:
case 0xc015: AuxiliaryRead(internal_CX_rom); break;
case 0xc016: AuxiliaryRead(alternative_zero_page); break;
case 0xc017: AuxiliaryRead(slot_C3_rom); break;
case 0xc018: VideoRead(get_80_store()); break;
// case 0xc019: VideoRead(get_is_vertical_blank(cycles_since_video_update_)); break;
case 0xc019: {
printf("TODO: vertical blank check\n");
static uint8_t vblank = 0x80;
*value = vblank;
vblank ^= 0x80;
} break;
case 0xc01a: VideoRead(get_text()); break;
case 0xc01b: VideoRead(get_mixed()); break;
case 0xc01c: VideoRead(get_page2()); break;
case 0xc01d: VideoRead(get_high_resolution()); break;
case 0xc01e: VideoRead(get_alternative_character_set()); break;
case 0xc01f: VideoRead(get_80_columns()); break;
case 0xc046: VideoRead(get_annunciator_3()); break;
case 0xc018: VideoRead(get_80_store()); break;
case 0xc019: VideoRead(get_is_vertical_blank()); break;
case 0xc01a: VideoRead(get_text()); break;
case 0xc01b: VideoRead(get_mixed()); break;
case 0xc01c: VideoRead(get_page2()); break;
case 0xc01d: VideoRead(get_high_resolution()); break;
case 0xc01e: VideoRead(get_alternative_character_set()); break;
case 0xc01f: VideoRead(get_80_columns()); break;
case 0xc046: VideoRead(get_annunciator_3()); break;
#undef VideoRead
#undef AuxiliaryRead
#undef LanguageRead
@ -472,6 +488,22 @@ class ConcreteMachine:
// }
fast_access_phase_ = (fast_access_phase_ + duration.as<int>()) % 5; // TODO: modulo something else, to allow for refresh.
slow_access_phase_ = (slow_access_phase_ + duration.as<int>()) % 14; // TODO: modulo something else, to allow for stretched cycles.
// Propagate time far and wide.
cycles_since_clock_tick_ += duration;
auto ticks = cycles_since_clock_tick_.divide(Cycles(CLOCK_RATE)).as_integral();
while(ticks--) {
clock_.update();
video_.notify_clock_tick(); // The video controller marshalls the one-second interrupt.
}
video_.run_for(duration);
// Update the interrupt line. TODO: should include the sound GLU too.
m65816_.set_irq_line(video_.get_interrupt_register() & 0x80);
return duration;
}
@ -498,6 +530,7 @@ class ConcreteMachine:
Apple::IIgs::ADB::GLU adb_glu_;
Apple::IIgs::Sound::GLU sound_glu_;
Zilog::SCC::z8530 scc_;
Cycles cycles_since_clock_tick_;
// MARK: - Cards.

View File

@ -10,9 +10,56 @@
using namespace Apple::IIgs::Video;
namespace {
constexpr int CyclesPerLine = 910;
constexpr int Lines = 263;
constexpr int FinalPixelLine = 192;
}
VideoBase::VideoBase() :
VideoSwitches<Cycles>(Cycles(2), [] (Cycles) {}) {
}
void VideoBase::did_set_annunciator_3(bool) {}
void VideoBase::did_set_alternative_character_set(bool) {}
void VideoBase::run_for(Cycles cycles) {
// TODO: everything else!
cycles_into_frame_ = (cycles_into_frame_ + cycles.as<int>()) % (CyclesPerLine * Lines);
}
bool VideoBase::get_is_vertical_blank() {
return cycles_into_frame_ >= FinalPixelLine * CyclesPerLine;
}
void VideoBase::set_new_video(uint8_t new_video) {
new_video_ = new_video;
}
uint8_t VideoBase::get_new_video() {
return new_video_;
}
void VideoBase::clear_interrupts(uint8_t mask) {
set_interrupts(interrupts_ & ~(mask & 0x60));
}
void VideoBase::set_interrupt_register(uint8_t mask) {
set_interrupts(interrupts_ | (mask & 0x6));
}
uint8_t VideoBase::get_interrupt_register() {
return interrupts_;
}
void VideoBase::notify_clock_tick() {
set_interrupts(interrupts_ | 0x40);
}
void VideoBase::set_interrupts(uint8_t new_value) {
interrupts_ = new_value & 0x7f;
if((interrupts_ >> 4) & 0x6)
interrupts_ |= 0x80;
}

View File

@ -10,6 +10,7 @@
#define Apple_IIgs_Video_hpp
#include "../AppleII/VideoSwitches.hpp"
#include "../../../ClockReceiver/ClockReceiver.hpp"
namespace Apple {
namespace IIgs {
@ -19,9 +20,27 @@ class VideoBase: public Apple::II::VideoSwitches<Cycles> {
public:
VideoBase();
void run_for(Cycles);
bool get_is_vertical_blank();
void set_new_video(uint8_t);
uint8_t get_new_video();
void clear_interrupts(uint8_t);
uint8_t get_interrupt_register();
void set_interrupt_register(uint8_t);
void notify_clock_tick();
private:
void did_set_annunciator_3(bool) override;
void did_set_alternative_character_set(bool) override;
uint8_t new_video_ = 0x01;
uint8_t interrupts_ = 0x00;
void set_interrupts(uint8_t);
int cycles_into_frame_ = 0;
};
class Video: public VideoBase {