Compare commits

...

12 Commits

Author SHA1 Message Date
joevt 5f37421ceb atirage: Add ability to read from PCI option rom.
Usually there is not PCI option rom if the chip is built-in to the motherboard such as in the Beige G3.
2024-04-23 08:01:54 -07:00
dingusdev 6f64e729c8 Tweak logging value for compiling 2024-04-23 07:59:23 -07:00
joevt 288e088f8a atirage: Fix hardware cursor update.
Switching from Watch to Arrow cursor at vertical position zero (top of the screen) would sometimes cut off the top half of the Arrow cursor. The following changes fix this:

Use the new cursor_dirty flag to signal when the cursor should be updated. This reduces the number of cursor updates and doesn't depend on registers being accessed in a specific order.

Set the cursor_dirty flag for any change that should cause the hardware cursor to be updated:
- CUR_CLR0, CUR_CLR1: Cursor color changes. We don't check if the colors actually changed (all cursors are usually black and white). Rather, writes to these registers usually means the cursor bytes have changed or will change.
- CUR_OFFSET: Offset to cursor bytes.
- CUR_VERT_OFF: First vertical line of cursor to draw.
Other changes that don't require the cursor to be updated:
- CUR_HORZ_OFF: Horizontal offset of cursor position. The cursor is unchanged - just need to adjust the drawing position.
- CUR_HORZ_VERT_POSN: The cursor is unchanged - only the drawing position is changed.
The only thing that could change the cursor that we don't check is a change to the cursor bytes.
2024-04-23 07:58:20 -07:00
joevt 3797fdbf1b atirage: Move fb_pitch calculation. 2024-04-23 07:55:51 -07:00
joevt 3036f4676d Use default window size in constructor.
The window size should be changed later by the mon_id property.
2024-04-23 07:27:52 -07:00
joevt e14b6677b2 displayid: Fix non-extended sense codes.
Sense codes for displays like the 12 inch RGB display (512x384) weren't working since they had the extended part set to 0xff.
Related to issues #25.
Also added some descriptive information and sizes which may be used for UI purposes such as creating a menu of displays to choose from. The sizes may be used to set the default window size for the display.
2024-04-23 06:52:38 -07:00
joevt 76f966845d viacuda: Use timer ids instead of timer flags. 2024-04-23 06:44:02 -07:00
joevt 288d97f24c atimach64gx: Add missing WRITE_VALUE_AND_LOG.
This commit fixes conflict resolution mistakes in the following commits:
"atimach64gx: Let crtc_update calculate fb_ptr."
"atimach64gx: Redraw only when necessary."

"atimach64gx: Log unhandled overlay registers." was mistakenly included in "atimach64gx: Let crtc_update calculate fb_ptr.". The OVR_ registers were included because they may be needed for 2D acceleration in System 7.5.3 and later.
2024-04-23 06:43:08 -07:00
joevt 755dd7f60a atimach64gx: Redraw only when necessary. 2024-04-22 20:13:37 -07:00
joevt e6d669d187 atimach64gx: Check end of regs region.
There's only up to 256 regs.
2024-04-22 20:02:38 -07:00
joevt 0d1a2d3010 atimach64gx: Cleanup. 2024-04-22 20:00:54 -07:00
joevt 51af94f12d atimach64gx: Add properties. 2024-04-22 20:00:38 -07:00
9 changed files with 353 additions and 81 deletions

View File

@ -68,9 +68,7 @@ ViaCuda::ViaCuda() {
// intialize counters/timers
this->t1_counter = 0xFFFF;
this->t1_active = false;
this->t2_counter = 0xFFFF;
this->t2_active = false;
// calculate VIA clock duration in ns
this->via_clk_dur = 1.0f / VIA_CLOCK_HZ * NS_PER_SEC;
@ -102,17 +100,17 @@ ViaCuda::ViaCuda() {
ViaCuda::~ViaCuda()
{
if (this->sr_timer_on) {
if (this->sr_timer_id) {
TimerManager::get_instance()->cancel_timer(this->sr_timer_id);
this->sr_timer_on = false;
this->sr_timer_id = 0;
}
if (this->t1_active) {
if (this->t1_timer_id) {
TimerManager::get_instance()->cancel_timer(this->t1_timer_id);
this->t1_active = false;
this->t1_timer_id = 0;
}
if (this->t2_active) {
if (this->t2_timer_id) {
TimerManager::get_instance()->cancel_timer(this->t2_timer_id);
this->t2_active = false;
this->t2_timer_id = 0;
}
if (this->treq_timer_id) {
TimerManager::get_instance()->cancel_timer(this->treq_timer_id);
@ -226,9 +224,9 @@ void ViaCuda::write(int reg, uint8_t value) {
ABORT_F("Unsupported VIA T1 mode, ACR=0x%X", this->via_regs[VIA_ACR]);
}
// cancel active T1 timer task
if (this->t1_active) {
if (this->t1_timer_id) {
TimerManager::get_instance()->cancel_timer(this->t1_timer_id);
this->t1_active = false;
this->t1_timer_id = 0;
}
// clear T1 flag in IFR
this->_via_ifr &= ~VIA_IF_T1;
@ -242,19 +240,19 @@ void ViaCuda::write(int reg, uint8_t value) {
this->t1_timer_id = TimerManager::get_instance()->add_oneshot_timer(
static_cast<uint64_t>(this->via_clk_dur * (this->t1_counter + 3) + 0.5f),
[this]() {
this->t1_timer_id = 0;
this->assert_t1_int();
}
);
this->t1_active = true;
break;
case VIA_T2CH:
if (this->via_regs[VIA_ACR] & 0x20) {
ABORT_F("VIA T2 pulse count mode not supported!");
}
// cancel active T2 timer task
if (this->t2_active) {
if (this->t2_timer_id) {
TimerManager::get_instance()->cancel_timer(this->t2_timer_id);
this->t2_active = false;
this->t2_timer_id = 0;
}
// clear T2 flag in IFR
this->_via_ifr &= ~VIA_IF_T2;
@ -268,10 +266,10 @@ void ViaCuda::write(int reg, uint8_t value) {
this->t2_timer_id = TimerManager::get_instance()->add_oneshot_timer(
static_cast<uint64_t>(this->via_clk_dur * (this->t2_counter + 3) + 0.5f),
[this]() {
this->t2_timer_id = 0;
this->assert_t2_int();
}
);
this->t2_active = true;
break;
case VIA_SR:
this->_via_ifr &= ~VIA_IF_SR;
@ -310,20 +308,17 @@ void ViaCuda::update_irq()
}
void ViaCuda::assert_sr_int() {
this->sr_timer_on = false;
this->_via_ifr |= VIA_IF_SR;
update_irq();
}
void ViaCuda::assert_t1_int() {
this->_via_ifr |= VIA_IF_T1;
this->t1_active = false;
update_irq();
}
void ViaCuda::assert_t2_int() {
this->_via_ifr |= VIA_IF_T2;
this->t2_active = false;
update_irq();
}
@ -356,14 +351,17 @@ void ViaCuda::assert_ctrl_line(ViaLine line)
}
void ViaCuda::schedule_sr_int(uint64_t timeout_ns) {
if (this->sr_timer_on) {
if (this->sr_timer_id) {
TimerManager::get_instance()->cancel_timer(this->sr_timer_id);
this->sr_timer_on = false;
this->sr_timer_id = 0;
}
this->sr_timer_id = TimerManager::get_instance()->add_oneshot_timer(
timeout_ns,
[this]() { this->assert_sr_int(); });
this->sr_timer_on = true;
[this]() {
this->sr_timer_id = 0;
this->assert_sr_int();
}
);
}
void ViaCuda::write(uint8_t new_state) {

View File

@ -182,16 +182,13 @@ private:
// VIA internal state
uint32_t sr_timer_id = 0;
bool sr_timer_on = false;
// timer 1 state
bool t1_active;
uint16_t t1_counter;
uint32_t t1_timer_id = 0;
uint64_t t1_start_time = 0;
// timer 2 state
bool t2_active;
uint16_t t2_counter;
uint32_t t2_timer_id = 0;
uint64_t t2_start_time = 0;

View File

@ -34,7 +34,7 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
using namespace Platinum;
PlatinumCtrl::PlatinumCtrl() : MemCtrlBase(), VideoCtrlBase(640, 480) {
PlatinumCtrl::PlatinumCtrl() : MemCtrlBase(), VideoCtrlBase() {
set_name("Platinum");
supports_types(HWCompType::MEM_CTRL | HWCompType::MMIO_DEV);

View File

@ -123,7 +123,7 @@ static const std::map<uint16_t, std::string> rgb514_reg_names = {
};
AtiMach64Gx::AtiMach64Gx()
: PCIDevice("ati-mach64-gx"), VideoCtrlBase(1024, 768)
: PCIDevice("ati-mach64-gx"), VideoCtrlBase()
{
supports_types(HWCompType::MMIO_DEV | HWCompType::PCI_DEV);
@ -148,10 +148,10 @@ AtiMach64Gx::AtiMach64Gx()
}
// initialize display identification
this->disp_id = std::unique_ptr<DisplayID> (new DisplayID(0x07, 0x3A));
this->disp_id = std::unique_ptr<DisplayID> (new DisplayID());
// allocate video RAM
this->vram_size = 2 << 20; // 2MB ; up to 6MB supported
this->vram_size = GET_INT_PROP("gfxmem_size") << 20; // convert MBs to bytes
this->vram_ptr = std::unique_ptr<uint8_t[]> (new uint8_t[this->vram_size]);
// set up RAMDAC identification
@ -362,6 +362,15 @@ uint32_t AtiMach64Gx::read_reg(uint32_t reg_offset, uint32_t size)
return static_cast<uint32_t>(result);
}
#define WRITE_VALUE_AND_LOG() \
do { \
this->regs[reg_num] = new_value; \
LOG_F(9, "%s: write %s %04x.%c = %0*x = %08x", this->name.c_str(), \
get_reg_name(reg_num), reg_offset, SIZE_ARG(size), size * 2, \
(uint32_t)extract_bits<uint64_t>(value, offset * 8, size * 8), new_value \
); \
} while (0)
void AtiMach64Gx::write_reg(uint32_t reg_offset, uint32_t value, uint32_t size)
{
uint32_t reg_num = reg_offset >> 2;
@ -389,6 +398,7 @@ void AtiMach64Gx::write_reg(uint32_t reg_offset, uint32_t value, uint32_t size)
break;
case ATI_CRTC_OFF_PITCH:
new_value = value;
WRITE_VALUE_AND_LOG();
this->crtc_update();
return;
case ATI_CRTC_INT_CNTL:
@ -502,6 +512,44 @@ void AtiMach64Gx::write_reg(uint32_t reg_offset, uint32_t value, uint32_t size)
}
break;
}
case ATI_OVR_CLR:
case ATI_OVR_WID_LEFT_RIGHT:
case ATI_OVR_WID_TOP_BOTTOM:
new_value = value;
WRITE_VALUE_AND_LOG();
if (value != 0) {
LOG_F(ERROR, "%s: Unhandled value 0x%08x.", this->name.c_str(), value);
}
return;
case ATI_CUR_CLR0:
case ATI_CUR_CLR1:
new_value = value;
this->cursor_dirty = true;
draw_fb = true;
WRITE_VALUE_AND_LOG();
return;
case ATI_CUR_OFFSET:
new_value = value;
if (old_value != new_value)
this->cursor_dirty = true;
draw_fb = true;
WRITE_VALUE_AND_LOG();
return;
case ATI_CUR_HORZ_VERT_OFF:
new_value = value;
if (
extract_bits<uint32_t>(new_value, ATI_CUR_VERT_OFF, ATI_CUR_VERT_OFF_size) !=
extract_bits<uint32_t>(old_value, ATI_CUR_VERT_OFF, ATI_CUR_VERT_OFF_size)
)
this->cursor_dirty = true;
draw_fb = true;
WRITE_VALUE_AND_LOG();
return;
case ATI_CUR_HORZ_VERT_POSN:
new_value = value;
draw_fb = true;
WRITE_VALUE_AND_LOG();
return;
case ATI_DAC_REGS:
new_value = old_value; // no change
if (size == 1) { // only byte accesses are allowed for DAC registers
@ -539,7 +587,7 @@ uint32_t AtiMach64Gx::read(uint32_t rgn_start, uint32_t offset, int size)
if (offset < this->vram_size) {
return read_mem(&this->vram_ptr[offset], size);
}
if (offset >= this->mm_regs_offset) {
if (offset >= this->mm_regs_offset && offset < this->mm_regs_offset + 0x400) {
return BYTESWAP_SIZED(read_reg(offset - this->mm_regs_offset, size), size);
}
return 0;
@ -559,9 +607,10 @@ void AtiMach64Gx::write(uint32_t rgn_start, uint32_t offset, uint32_t value, int
{
if (rgn_start == this->aperture_base[0]) {
if (offset < this->vram_size) {
draw_fb = true;
return write_mem(&this->vram_ptr[offset], value, size);
}
if (offset >= this->mm_regs_offset) {
if (offset >= this->mm_regs_offset && offset < this->mm_regs_offset + 0x400) {
return write_reg(offset - this->mm_regs_offset, BYTESWAP_SIZED(value, size), size);
}
return;
@ -574,9 +623,6 @@ void AtiMach64Gx::verbose_pixel_format(int crtc_index) {
return;
}
/*
int fmt = extract_bits<uint32_t>(this->regs[ATI_CRTC_GEN_CNTL], ATI_CRTC_PIX_WIDTH, ATI_CRTC_PIX_WIDTH_size);
*/
int pix_fmt = this->pixel_format;
const char* what = "Pixel format:";
@ -680,6 +726,8 @@ void AtiMach64Gx::crtc_update()
if (!need_recalc)
return;
this->draw_fb = true;
// calculate display refresh rate
this->refresh_rate = this->pixel_clock / this->hori_total / this->vert_total;
@ -693,26 +741,31 @@ void AtiMach64Gx::crtc_update()
switch (this->pixel_format) {
case 2:
this->convert_fb_cb = [this](uint8_t *dst_buf, int dst_pitch) {
draw_fb = false;
this->convert_frame_4bpp_indexed(dst_buf, dst_pitch);
};
break;
case 3:
this->convert_fb_cb = [this](uint8_t *dst_buf, int dst_pitch) {
draw_fb = false;
this->convert_frame_8bpp_indexed(dst_buf, dst_pitch);
};
break;
case 4:
this->convert_fb_cb = [this](uint8_t *dst_buf, int dst_pitch) {
draw_fb = false;
this->convert_frame_15bpp_BE(dst_buf, dst_pitch);
};
break;
case 5:
this->convert_fb_cb = [this](uint8_t *dst_buf, int dst_pitch) {
draw_fb = false;
this->convert_frame_24bpp(dst_buf, dst_pitch);
};
break;
case 6:
this->convert_fb_cb = [this](uint8_t *dst_buf, int dst_pitch) {
draw_fb = false;
this->convert_frame_32bpp_BE(dst_buf, dst_pitch);
};
break;
@ -815,6 +868,7 @@ void AtiMach64Gx::rgb514_write_reg(uint8_t reg_addr, uint8_t value)
clut_color[1], clut_color[2], 0xFF);
this->clut_index++;
this->comp_index = 0;
draw_fb = true;
}
break;
case Rgb514::CLUT_MASK:
@ -864,8 +918,15 @@ void AtiMach64Gx::rgb514_write_ind_reg(uint8_t reg_addr, uint8_t value)
}
}
static const PropMap AtiMach64gx_Properties = {
{"gfxmem_size",
new IntProperty( 2, vector<uint32_t>({2, 4, 6}))},
{"mon_id",
new StrProperty("")},
};
static const DeviceDescription AtiMach64Gx_Descriptor = {
AtiMach64Gx::create, {}, {}
AtiMach64Gx::create, {}, AtiMach64gx_Properties
};
REGISTER_DEVICE(AtiMach64Gx, AtiMach64Gx_Descriptor);

View File

@ -89,7 +89,7 @@ static const std::map<uint16_t, std::string> mach64_reg_names = {
};
ATIRage::ATIRage(uint16_t dev_id)
: PCIDevice("ati-rage"), VideoCtrlBase(640, 480)
: PCIDevice("ati-rage"), VideoCtrlBase()
{
uint8_t asic_id;
@ -275,6 +275,17 @@ uint32_t ATIRage::read_reg(uint32_t reg_offset, uint32_t size) {
return static_cast<uint32_t>(result);
}
#define WRITE_VALUE_AND_LOG(level) \
do { \
this->regs[reg_num] = new_value; \
if (reg_num != ATI_CRTC_INT_CNTL) { \
LOG_F(level, "%s: write %s %04x.%c = %0*x = %08x", this->name.c_str(), \
get_reg_name(reg_num), reg_offset, SIZE_ARG(size), size * 2, \
(uint32_t)extract_bits<uint64_t>(value, offset * 8, size * 8), new_value \
); \
} \
} while (0)
void ATIRage::write_reg(uint32_t reg_offset, uint32_t value, uint32_t size) {
uint32_t reg_num = reg_offset >> 2;
uint32_t offset = reg_offset & 3;
@ -301,11 +312,9 @@ void ATIRage::write_reg(uint32_t reg_offset, uint32_t value, uint32_t size) {
break;
case ATI_CRTC_OFF_PITCH:
new_value = value;
if (old_value != new_value) {
this->regs[reg_num] = new_value;
this->crtc_update();
}
break;
WRITE_VALUE_AND_LOG(9);
this->crtc_update();
return;
case ATI_CRTC_INT_CNTL: {
uint32_t bits_read_only =
(1 << ATI_CRTC_VBLANK) |
@ -395,11 +404,29 @@ void ATIRage::write_reg(uint32_t reg_offset, uint32_t value, uint32_t size) {
break;
case ATI_CUR_CLR0:
case ATI_CUR_CLR1:
this->setup_hw_cursor();
// fallthrough
new_value = value;
this->cursor_dirty = true;
draw_fb = true;
WRITE_VALUE_AND_LOG(9);
return;
case ATI_CUR_OFFSET:
case ATI_CUR_HORZ_VERT_POSN:
new_value = value;
if (old_value != new_value)
this->cursor_dirty = true;
draw_fb = true;
WRITE_VALUE_AND_LOG(9);
return;
case ATI_CUR_HORZ_VERT_OFF:
new_value = value;
if (
extract_bits<uint32_t>(new_value, ATI_CUR_VERT_OFF, ATI_CUR_VERT_OFF_size) !=
extract_bits<uint32_t>(old_value, ATI_CUR_VERT_OFF, ATI_CUR_VERT_OFF_size)
)
this->cursor_dirty = true;
draw_fb = true;
WRITE_VALUE_AND_LOG(9);
return;
case ATI_CUR_HORZ_VERT_POSN:
new_value = value;
draw_fb = true;
break;
@ -463,7 +490,7 @@ void ATIRage::write_reg(uint32_t reg_offset, uint32_t value, uint32_t size) {
new_value = value;
if (bit_changed(old_value, new_value, ATI_GEN_CUR_ENABLE)) {
if (bit_set(new_value, ATI_GEN_CUR_ENABLE))
this->setup_hw_cursor();
this->cursor_on = true;
else
this->cursor_on = false;
draw_fb = true;
@ -503,7 +530,7 @@ void ATIRage::write_reg(uint32_t reg_offset, uint32_t value, uint32_t size) {
break;
}
this->regs[reg_num] = new_value;
WRITE_VALUE_AND_LOG(9);
}
bool ATIRage::io_access_allowed(uint32_t offset) {
@ -564,6 +591,15 @@ uint32_t ATIRage::read(uint32_t rgn_start, uint32_t offset, int size)
return 0;
}
// memory mapped expansion ROM region
if (rgn_start == this->exp_rom_addr) {
if (offset < this->exp_rom_size)
return read_mem(&this->exp_rom_data[offset], size);
LOG_F(WARNING, "%s: read unmapped ROM region %08x.%c",
this->name.c_str(), offset, SIZE_ARG(size));
return 0;
}
LOG_F(WARNING, "%s: read unmapped aperture region %08x.%c",
this->name.c_str(), offset, SIZE_ARG(size));
return 0;
@ -699,6 +735,21 @@ void ATIRage::crtc_update() {
need_recalc = true;
}
static uint8_t bits_per_pixel[8] = {0, 4, 8, 16, 16, 24, 32, 0};
int new_fb_pitch = extract_bits<uint32_t>(this->regs[ATI_CRTC_OFF_PITCH],
ATI_CRTC_PITCH, ATI_CRTC_PITCH_size) * bits_per_pixel[this->pixel_format];
if (new_fb_pitch != this->fb_pitch) {
this->fb_pitch = new_fb_pitch;
need_recalc = true;
}
uint8_t* new_fb_ptr = &this->vram_ptr[extract_bits<uint32_t>(this->regs[ATI_CRTC_OFF_PITCH],
ATI_CRTC_OFFSET, ATI_CRTC_OFFSET_size) * 8];
if (new_fb_ptr != this->fb_ptr) {
this->fb_ptr = new_fb_ptr;
need_recalc = true;
}
// look up which VPLL ouput is requested
int clock_sel = extract_bits<uint32_t>(this->regs[ATI_CLOCK_CNTL], ATI_CLOCK_SEL,
ATI_CLOCK_SEL_size);
@ -781,14 +832,6 @@ void ATIRage::crtc_update() {
LOG_F(ERROR, "%s: unsupported pixel format %d", this->name.c_str(), this->pixel_format);
}
static uint8_t bits_per_pixel[8] = {0, 4, 8, 16, 16, 24, 32, 0};
this->fb_pitch = extract_bits<uint32_t>(this->regs[ATI_CRTC_OFF_PITCH],
ATI_CRTC_PITCH, ATI_CRTC_PITCH_size) * (bits_per_pixel[this->pixel_format & 7] * 8) >> 3;
this->fb_ptr = &this->vram_ptr[extract_bits<uint32_t>(this->regs[ATI_CRTC_OFF_PITCH],
ATI_CRTC_OFFSET, ATI_CRTC_OFFSET_size) * 8];
LOG_F(INFO, "%s: primary CRT controller enabled:", this->name.c_str());
LOG_F(INFO, "Video mode: %s",
bit_set(this->regs[ATI_CRTC_GEN_CNTL], ATI_CRTC_EXT_DISP_EN) ? "extended" : "VGA");

View File

@ -1 +0,0 @@

View File

@ -57,7 +57,7 @@ namespace loguru {
}
ControlVideo::ControlVideo()
: PCIDevice("Control-Video"), VideoCtrlBase(640, 480)
: PCIDevice("Control-Video"), VideoCtrlBase()
{
supports_types(HWCompType::PCI_HOST | HWCompType::PCI_DEV);

View File

@ -1,6 +1,6 @@
/*
DingusPPC - The Experimental PowerPC Macintosh emulator
Copyright (C) 2018-23 divingkatae and maximum
Copyright (C) 2018-24 divingkatae and maximum
(theweirdo) spatium
(Contact divingkatae#1017 or powermax#2286 on Discord for more info)
@ -29,26 +29,197 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
#include <map>
#include <string>
typedef struct {
uint16_t h;
uint16_t v;
float pixel_clock; // MHz
float h_freq; // kHz
float refresh; // Hz
} MonitorRes;
typedef struct {
uint8_t std_sense_code;
uint8_t ext_sense_code;
const char * apple_enum;
const char * name;
const char * description;
MonitorRes resolutions[4];
} MonitorInfo;
/** Mapping between monitor IDs and their sense codes. */
static const std::map<std::string, uint16_t> MonitorIdToCode = {
{ "MacColor21in" , 0x00FF },
{ "PortraitGS" , 0x01FF },
{ "MacRGB12in" , 0x02FF },
{ "TwoPageGS" , 0x03FF },
{ "NTSC" , 0x04FF },
{ "MacRGB15in" , 0x05FF },
{ "HiRes12-14in" , 0x06FF },
{ "Multiscan15in" , 0x0603 },
{ "Multiscan17in" , 0x060B },
{ "Multiscan20in" , 0x0623 },
{ "AppleVision1710" , 0x062B }, // this code is assigned to several different monitors!
{ "PALEncoder" , 0x0700 }, // no clue what it means
{ "NTSCEncoder" , 0x0714 }, // no clue what it means
{ "VGA-SVGA" , 0x0717 },
{ "MacRGB16in" , 0x072D },
{ "MacRGB19in" , 0x073A },
{ "PAL" , 0x0730 },
{ "NotConnected" , 0x07FF }
static const std::map<std::string, MonitorInfo> MonitorIdToCode = {
{ "MacColor21in", {
0, 0x00,
"kESCZero21Inch",
"21\" RGB",
"RGB 21\", 21\" Color, Apple 21S Color", {
{1152, 870, 100 , 68.7 , 75 }
}
}},
{ "PortraitGS", {
1, 0x14,
"kESCOnePortraitMono",
"Portrait Monochrome",
"B&W 15\", Apple Portrait", {
{ 640, 870, 57.2832, 68.9 , 75 }
}
}},
{ "MacRGB12in", {
2, 0x21,
"kESCTwo12Inch",
"12\" RGB",
"12\" Apple RGB", {
{ 512, 384, 15.6672, 24.48 , 60.15}
}
}},
{ "Radius21in", {
3, 0x31,
"kESCThree21InchRadius",
"21\" RGB (Radius)",
"", {
{1152, 870, 100 , 68.7 , 75 }
}
}},
{ "Radius21inGS", {
3, 0x34,
"kESCThree21InchMonoRadius",
"21\" Monochrome (Radius)",
"", {
{1152, 870, 100 , 68.7 , 75 }
}
}},
{ "TwoPageGS", {
3, 0x35,
"kESCThree21InchMono",
"21\" Monochrome",
"B&W 21\", Apple 2 Page Mono", {
{1152, 870, 100 , 68.7 , 75 }
}
}},
{ "NTSC", {
4, 0x0A,
"kESCFourNTSC",
"NTSC",
"NTSC underscan 512x384, overscan", {
{ 640, 480, 12.2727, 15.7 , 59.94}
}
}},
{ "MacRGB15in", {
5, 0x1E,
"kESCFivePortrait",
"Portrait RGB",
"RGB 15\", 15\" Tilt", {
{ 640, 870, 57.2834, 0 , 0 }
}
}},
{ "Multiscan15in", {
6, 0x03,
"kESCSixMSB1",
"MultiScan Band-1 (12\" thru 16\")",
"Multiple Scan 13, 14\"", {
{ 640, 480, 67 , 0 , 0 },
{ 832, 624, 75 , 0 , 0 }
}
}},
{ "Multiscan17in", {
6, 0x0B,
"kESCSixMSB2",
"MultiScan Band-2 (13\" thru 19\")",
"Multiple Scan 16, 17\"", {
{ 640, 480, 67 , 0 , 0 },
{ 832, 624, 75 , 0 , 0 },
{1024, 768, 75 , 0 , 0 }
}
}},
{ "Multiscan20in", {
6, 0x23,
"kESCSixMSB3",
"MultiScan Band-3 (13\" thru 21\")",
"Multiple Scan 20, 21\"", {
{ 640, 480, 67 , 0 , 0 },
{ 832, 624, 75 , 0 , 0 },
{1024, 768, 75 , 0 , 0 },
{1152, 870, 75 , 0 , 0 }
}
}},
{ "HiRes12-14in", {
6, 0x2B,
"kESCSixStandard",
"13\"/14\" RGB or 12\" Monochrome",
"B&W 12\", 12\" Apple Monochrome, 13\" Apple RGB, Hi-Res 12-14\"", {
{ 640, 480, 30.24 , 35.0 , 66.7 },
}
}},
{ "PALEncoder", {
7, 0x00,
"kESCSevenPAL",
"PAL",
"PAL, NTSC/PAL (Option 1)", {
{ 640, 480, 14.75 , 15.625, 50 },
{ 768, 576, 14.75 , 15.625, 50 }
}
}},
{ "NTSCEncoder", {
7, 0x14,
"kESCSevenNTSC",
"NTSC",
"NTSC w/convolution (Alternate)", {
{ 640, 480, 12.2727, 0 , 0 }
}
}},
{ "VGA-SVGA", {
7, 0x17,
"kESCSevenVGA",
"VGA",
"VGA", {
{ 640, 480, 25.175 , 31.47 , 59.95},
{ 800, 600, 36 , 35.16 , 56 },
{1024, 768, 35.16 , 60 }
}
}},
{ "MacRGB16in", {
7, 0x2D,
"kESCSeven16Inch",
"16\" RGB (GoldFish)",
"RGB 16\", 16\" Color", {
{ 832, 624, 57.2832, 49.7 , 75 }
}
}},
{ "PAL", {
7, 0x30,
"kESCSevenPALAlternate",
"PAL (Alternate)",
"PAL w/convolution (Alternate) (Option 2)", {
{ 640, 480, 14.75 , 15.625, 50 },
{ 768, 576, 14.75 , 15.625, 50 }
}
}},
{ "MacRGB19in", {
7, 0x3A,
"kESCSeven19Inch",
"Third-Party 19",
"RGB 19\", 19\" Color", {
{1024, 768, 80 , 0 , 0 }
}
}},
{ "DDC", {
7, 0x3E,
"kESCSevenDDC",
"DDC display",
"EDID", {
{1024, 768, 80 , 0 , 0 }
}
}},
{ "NotConnected", {
7, 0x3F,
"kESCSevenNoDisplay",
"No display connected",
"no-connect"
}},
};
static const std::map<std::string, std::string> MonitorAliasToId = {
{ "AppleVision1710", "HiRes12-14in" }
};
DisplayID::DisplayID()
@ -58,14 +229,17 @@ DisplayID::DisplayID()
std::string mon_id = GET_STR_PROP("mon_id");
if (!mon_id.empty()) {
if (MonitorAliasToId.count(mon_id)) {
mon_id = MonitorAliasToId.at(mon_id);
}
if (MonitorIdToCode.count(mon_id)) {
auto sense_code = MonitorIdToCode.at(mon_id);
this->std_sense_code = (sense_code >> 8) & 0xFFU;
this->ext_sense_code = (sense_code >> 0) & 0xFFU;
auto monitor = MonitorIdToCode.at(mon_id);
this->std_sense_code = monitor.std_sense_code;
this->ext_sense_code = monitor.ext_sense_code;
this->id_kind = Disp_Id_Kind::AppleSense;
LOG_F(INFO, "DisplayID mode set to AppleSense");
LOG_F(INFO, "Standard sense code: 0x%d", this->std_sense_code);
LOG_F(INFO, "Extended sense code: 0x%X", this->ext_sense_code);
LOG_F(INFO, "Standard sense code: %d", this->std_sense_code);
LOG_F(INFO, "Extended sense code: 0x%02X", this->ext_sense_code);
}
}

View File

@ -33,7 +33,7 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
#include <string>
TaosVideo::TaosVideo() : VideoCtrlBase(640, 480) {
TaosVideo::TaosVideo() : VideoCtrlBase() {
set_name("Taos");
supports_types(HWCompType::MMIO_DEV);