2020-11-01 00:39:32 +00:00
|
|
|
//
|
|
|
|
// Video.hpp
|
|
|
|
// Clock Signal
|
|
|
|
//
|
|
|
|
// Created by Thomas Harte on 31/10/2020.
|
|
|
|
// Copyright © 2020 Thomas Harte. All rights reserved.
|
|
|
|
//
|
|
|
|
|
|
|
|
#ifndef Apple_IIgs_Video_hpp
|
|
|
|
#define Apple_IIgs_Video_hpp
|
|
|
|
|
|
|
|
#include "../AppleII/VideoSwitches.hpp"
|
2020-11-08 01:42:34 +00:00
|
|
|
#include "../../../Outputs/CRT/CRT.hpp"
|
2020-11-05 22:56:20 +00:00
|
|
|
#include "../../../ClockReceiver/ClockReceiver.hpp"
|
2020-11-01 00:39:32 +00:00
|
|
|
|
|
|
|
namespace Apple {
|
|
|
|
namespace IIgs {
|
|
|
|
namespace Video {
|
|
|
|
|
2020-11-08 00:40:26 +00:00
|
|
|
/*!
|
|
|
|
Provides IIgs video output; assumed clocking here is twice the usual Apple II clock.
|
|
|
|
So it'll produce a single line of video every 131 cycles — 65*2 + 1, allowing for the
|
|
|
|
stretched cycle.
|
|
|
|
*/
|
2020-11-01 00:39:32 +00:00
|
|
|
class VideoBase: public Apple::II::VideoSwitches<Cycles> {
|
|
|
|
public:
|
|
|
|
VideoBase();
|
2020-11-05 23:17:21 +00:00
|
|
|
void set_internal_ram(const uint8_t *);
|
2020-11-01 00:39:32 +00:00
|
|
|
|
2020-11-05 22:56:20 +00:00
|
|
|
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();
|
2020-11-08 04:14:50 +00:00
|
|
|
|
2020-11-08 03:03:05 +00:00
|
|
|
void set_border_colour(uint8_t);
|
2020-11-08 04:14:50 +00:00
|
|
|
void set_text_colour(uint8_t);
|
2020-11-05 22:56:20 +00:00
|
|
|
|
2020-11-10 02:54:25 +00:00
|
|
|
void set_composite_is_colour(bool);
|
|
|
|
bool get_composite_is_colour();
|
|
|
|
|
2020-11-08 01:42:34 +00:00
|
|
|
/// Sets the scan target.
|
|
|
|
void set_scan_target(Outputs::Display::ScanTarget *scan_target);
|
|
|
|
|
|
|
|
/// Gets the current scan status.
|
|
|
|
Outputs::Display::ScanStatus get_scaled_scan_status() const;
|
|
|
|
|
|
|
|
/// Sets the type of output.
|
|
|
|
void set_display_type(Outputs::Display::DisplayType);
|
|
|
|
|
|
|
|
/// Gets the type of output.
|
|
|
|
Outputs::Display::DisplayType get_display_type() const;
|
|
|
|
|
2020-11-16 19:42:50 +00:00
|
|
|
/// Determines the period until video might autonomously update its interrupt lines.
|
|
|
|
Cycles get_next_sequence_point() const;
|
|
|
|
|
2020-11-01 00:39:32 +00:00
|
|
|
private:
|
2020-11-08 01:42:34 +00:00
|
|
|
Outputs::CRT::CRT crt_;
|
|
|
|
|
2020-11-07 22:45:03 +00:00
|
|
|
void advance(Cycles);
|
2020-11-05 22:56:20 +00:00
|
|
|
|
|
|
|
uint8_t new_video_ = 0x01;
|
|
|
|
uint8_t interrupts_ = 0x00;
|
|
|
|
void set_interrupts(uint8_t);
|
|
|
|
|
|
|
|
int cycles_into_frame_ = 0;
|
2020-11-05 23:17:21 +00:00
|
|
|
const uint8_t *ram_ = nullptr;
|
2020-11-08 04:14:50 +00:00
|
|
|
|
|
|
|
// The modal colours.
|
2020-11-08 03:03:05 +00:00
|
|
|
uint16_t border_colour_ = 0;
|
2020-11-08 22:04:04 +00:00
|
|
|
uint16_t text_colour_ = 0xffff;
|
2020-11-08 04:14:50 +00:00
|
|
|
uint16_t background_colour_ = 0;
|
2020-11-08 01:42:34 +00:00
|
|
|
|
2020-11-08 22:01:23 +00:00
|
|
|
// Current pixel output buffer.
|
|
|
|
uint16_t *pixels_ = nullptr, *next_pixel_ = nullptr;
|
|
|
|
|
2020-11-08 01:42:34 +00:00
|
|
|
void output_row(int row, int start, int end);
|
2020-11-15 22:16:52 +00:00
|
|
|
|
|
|
|
uint16_t *output_super_high_res(uint16_t *target, int start, int end, int row) const;
|
|
|
|
uint16_t *output_text(uint16_t *target, int start, int end, int row) const;
|
2020-11-15 23:36:24 +00:00
|
|
|
|
|
|
|
// Super high-res per-line state.
|
|
|
|
uint8_t line_control_;
|
|
|
|
uint16_t palette_[16];
|
2020-11-01 00:39:32 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
class Video: public VideoBase {
|
|
|
|
public:
|
|
|
|
using VideoBase::VideoBase;
|
|
|
|
};
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif /* Video_hpp */
|