diff --git a/devices/video/atimach64defs.h b/devices/video/atimach64defs.h index 14f60a8..13079f1 100644 --- a/devices/video/atimach64defs.h +++ b/devices/video/atimach64defs.h @@ -1,6 +1,6 @@ /* DingusPPC - The Experimental PowerPC Macintosh emulator -Copyright (C) 2018-22 divingkatae and maximum +Copyright (C) 2018-23 divingkatae and maximum (theweirdo) spatium (Contact divingkatae#1017 or powermax#2286 on Discord for more info) @@ -31,150 +31,154 @@ enum { /** Mach64 register offsets. */ enum { - ATI_CRTC_H_TOTAL_DISP = 0x0000, - ATI_CRTC_H_SYNC_STRT_WID = 0x0004, - ATI_CRTC_V_TOTAL_DISP = 0x0008, - ATI_CRTC_V_SYNC_STRT_WID = 0x000C, - ATI_CRTC_VLINE_CRNT_VLINE = 0x0010, - ATI_CRTC_OFF_PITCH = 0x0014, - ATI_CRTC_INT_CNTL = 0x0018, - ATI_CRTC_GEN_CNTL = 0x001C, - ATI_DSP_CONFIG = 0x0020, - ATI_DSP_ON_OFF = 0x0024, - ATI_TIMER_CFG = 0x0028, - ATI_MEM_BUF_CNTL = 0x002C, - ATI_MEM_ADDR_CFG = 0x0034, - ATI_CRT_TRAP = 0x0038, - ATI_I2C_CNTL_0 = 0x003C, - ATI_OVR_CLR = 0x0040, - ATI_OVR_WID_LEFT_RIGHT = 0x0044, - ATI_OVR_WID_TOP_BOTTOM = 0x0048, - ATI_VGA_DSP_CFG = 0x004C, - ATI_VGA_DSP_TGL = 0x0050, - ATI_DSP2_CONFIG = 0x0054, - ATI_DSP2_TOGGLE = 0x0058, - ATI_CRTC2_OFF_PITCH = 0x005C, - ATI_CUR_CLR0 = 0x0060, - ATI_CUR_CLR1 = 0x0064, - ATI_CUR_OFFSET = 0x0068, - ATI_CUR_HORZ_VERT_POSN = 0x006C, - ATI_CUR_HORZ_VERT_OFF = 0x0070, - ATI_GP_IO = 0x0078, - ATI_HW_DEBUG = 0x007C, - ATI_SCRATCH_REG0 = 0x0080, - ATI_SCRATCH_REG1 = 0x0084, - ATI_SCRATCH_REG2 = 0x0088, - ATI_SCRATCH_REG3 = 0x008C, - ATI_CLOCK_CNTL = 0x0090, - ATI_CONFIG_STAT1 = 0x0094, - ATI_CONFIG_STAT2 = 0x0098, - ATI_BUS_CNTL = 0x00A0, - ATI_EXT_MEM_CNTL = 0x00AC, - ATI_MEM_CNTL = 0x00B0, - ATI_MEM_VGA_WP_SEL = 0x00B4, - ATI_MEM_VGA_RP_SEL = 0x00B8, - ATI_I2C_CNTL_1 = 0x00BC, - ATI_DAC_REGS = 0x00C0, + ATI_CRTC_H_TOTAL_DISP = 0x000, // 0x0000 + ATI_CRTC_H_SYNC_STRT_WID = 0x001, // 0x0004 + ATI_CRTC_V_TOTAL_DISP = 0x002, // 0x0008 + ATI_CRTC_V_SYNC_STRT_WID = 0x003, // 0x000C + ATI_CRTC_VLINE_CRNT_VLINE = 0x004, // 0x0010 + ATI_CRTC_OFF_PITCH = 0x005, // 0x0014 + ATI_CRTC_INT_CNTL = 0x006, // 0x0018 + ATI_CRTC_GEN_CNTL = 0x007, // 0x001C + ATI_DSP_CONFIG = 0x008, // 0x0020 + ATI_DSP_ON_OFF = 0x009, // 0x0024 + ATI_TIMER_CFG = 0x00A, // 0x0028 + ATI_MEM_BUF_CNTL = 0x00B, // 0x002C + ATI_MEM_ADDR_CFG = 0x00D, // 0x0034 + ATI_CRT_TRAP = 0x00E, // 0x0038 + ATI_I2C_CNTL_0 = 0x00F, // 0x003C + ATI_OVR_CLR = 0x010, // 0x0040 + ATI_OVR_WID_LEFT_RIGHT = 0x011, // 0x0044 + ATI_OVR_WID_TOP_BOTTOM = 0x012, // 0x0048 + ATI_VGA_DSP_CFG = 0x013, // 0x004C + ATI_VGA_DSP_ON_OFF = 0x014, // 0x0050 + ATI_DSP2_CONFIG = 0x015, // 0x0054 <-- LT specific + ATI_DSP2_ON_OFF = 0x016, // 0x0058 <-- LT specific + ATI_CRTC2_OFF_PITCH = 0x017, // 0x005C <-- LT specific + ATI_CUR_CLR0 = 0x018, // 0x0060 + ATI_CUR_CLR1 = 0x019, // 0x0064 + ATI_CUR_OFFSET = 0x01A, // 0x0068 + ATI_CUR_HORZ_VERT_POSN = 0x01B, // 0x006C + ATI_CUR_HORZ_VERT_OFF = 0x01C, // 0x0070 + ATI_GP_IO = 0x01E, // 0x0078 + ATI_HW_DEBUG = 0x01F, // 0x007C + ATI_SCRATCH_REG0 = 0x020, // 0x0080 + ATI_SCRATCH_REG1 = 0x021, // 0x0084 + ATI_SCRATCH_REG2 = 0x022, // 0x0088 + ATI_SCRATCH_REG3 = 0x023, // 0x008C + ATI_CLOCK_CNTL = 0x024, // 0x0090 + ATI_CONFIG_STAT1 = 0x025, // 0x0094 + ATI_CONFIG_STAT2 = 0x026, // 0x0098 + ATI_BUS_CNTL = 0x028, // 0x00A0 + ATI_EXT_MEM_CNTL = 0x02B, // 0x00AC + ATI_MEM_CNTL = 0x02C, // 0x00B0 + ATI_MEM_VGA_WP_SEL = 0x02D, // 0x00B4 + ATI_MEM_VGA_RP_SEL = 0x02E, // 0x00B8 + ATI_I2C_CNTL_1 = 0x02F, // 0x00BC + ATI_DAC_REGS = 0x030, // 0x00C0 + + // byte offsets for the built-in DAC registers ATI_DAC_W_INDEX = 0x00C0, ATI_DAC_DATA = 0x00C1, ATI_DAC_MASK = 0x00C2, ATI_DAC_R_INDEX = 0x00C3, - ATI_DAC_CNTL = 0x00C4, - ATI_GEN_TEST_CNTL = 0x00D0, - ATI_CUSTOM_MACRO_CNTL = 0x00D4, - ATI_CONFIG_CNTL = 0x00DC, - ATI_CONFIG_CHIP_ID = 0x00E0, - ATI_CONFIG_STAT0 = 0x00E4, - ATI_GX_CONFIG_STAT1 = 0x00E8, // GX only - ATI_CRC_SIG = 0x00E8, - ATI_DST_Y_X_ALIAS1 = 0x00F4, - ATI_DST_OFF_PITCH = 0x0100, - ATI_DST_X = 0x0104, - ATI_DST_Y = 0x0108, - ATI_DST_Y_X = 0x010C, - ATI_DST_WIDTH = 0x0110, - ATI_DST_HEIGHT = 0x0114, - ATI_DST_HEIGHT_WIDTH = 0x0118, - ATI_DST_X_WIDTH = 0x011C, - ATI_DST_BRES_LNTH = 0x0120, - ATI_DST_BRES_ERR = 0x0124, - ATI_DST_BRES_INC = 0x0128, - ATI_DST_BRES_DEC = 0x012C, - ATI_DST_CNTL = 0x0130, - ATI_DST_Y_X_ALIAS2 = 0x0134, - ATI_TRAIL_BRES_ERR = 0x0138, - ATI_TRAIL_BRES_INC = 0x013C, - ATI_TRAIL_BRES_DEC = 0x0140, - ATI_DST_BRES_LNTH_ALIAS1 = 0x0144, - ATI_Z_OFF_PITCH = 0x0148, - ATI_Z_CNTL = 0x014C, - ATI_ALPHA_TST_CNTL = 0x0150, - ATI_SRC_OFF_PITCH = 0x0180, - ATI_SRC_X = 0x0184, - ATI_SRC_Y = 0x0188, - ATI_SRC_Y_X = 0x018C, - ATI_SRC_WIDTH1 = 0x0190, - ATI_SRC_HEIGHT1 = 0x0194, - ATI_SRC_HEIGHT1_WIDTH1 = 0x0198, - ATI_SRC_X_START = 0x019C, - ATI_SRC_Y_START = 0x01A0, - ATI_SRC_Y_X_START = 0x01A4, - ATI_SRC_WIDTH2 = 0x01A8, - ATI_SRC_HEIGHT2 = 0x01AC, - ATI_SRC_HEIGHT2_WIDTH2 = 0x01B0, - ATI_SRC_CNTL = 0x01B4, - ATI_SCALE_OFF = 0x01C0, - ATI_SCALE_WIDTH = 0x01DC, - ATI_SCALE_HEIGHT = 0x01E0, - ATI_SCALE_PITCH = 0x01EC, - ATI_SCALE_X_INC = 0x01F0, - ATI_SCALE_Y_INC = 0x01F4, - ATI_SCALE_VACC = 0x01F8, - ATI_SCALE_3D_CNTL = 0x01FC, - ATI_HOST_CNTL = 0x0240, - ATI_PAT_REG0 = 0x0280, - ATI_PAT_REG1 = 0x0284, - ATI_PAT_CNTL = 0x0288, - ATI_SC_LEFT = 0x02A0, - ATI_SC_RIGHT = 0x02A4, - ATI_SC_LEFT_RIGHT = 0x02A8, - ATI_SC_TOP = 0x02AC, - ATI_SC_BOTTOM = 0x02B0, - ATI_SC_TOP_BOTTOM = 0x02B4, - ATI_DP_BKGD_CLR = 0x02C0, - ATI_DP_FOG_CLR = 0x02C0, - ATI_DP_WRITE_MSK = 0x02C8, - ATI_DP_PIX_WIDTH = 0x02D0, - ATI_DP_MIX = 0x02D4, - ATI_DP_SRC = 0x02D8, - ATI_FRGD_CLR_MIX = 0x02DC, - ATI_FRGD_BKGD_CLR = 0x02E0, - ATI_DST_X_Y = 0x02E8, - ATI_DST_WIDTH_HEIGHT = 0x02EC, - ATI_USR_DST_PITCH = 0x02F0, - ATI_DP_SET_GUI_ENGINE2 = 0x02F4, - ATI_DP_SET_GUI_ENGINE = 0x02F8, - ATI_CLR_CMP_CLR = 0x0300, - ATI_CLR_CMP_MSK = 0x0304, - ATI_CLR_CMP_CNTL = 0x0308, - ATI_FIFO_STAT = 0x0310, - ATI_CONTEXT_MASK = 0x0320, - ATI_GUI_TRAJ_CNTL = 0x0330, - ATI_GUI_STAT = 0x0338, - ATI_MPP_CONFIG = 0x04C0, - ATI_MPP_STROBE_SEQ = 0x04C4, - ATI_MPP_ADDR = 0x04C8, - ATI_MPP_DATA = 0x04CC, - ATI_TVO_CNTL = 0x0500, - ATI_SETUP_CNTL = 0x0704, + + ATI_DAC_CNTL = 0x031, // 0x00C4 + ATI_GEN_TEST_CNTL = 0x034, // 0x00D0 + ATI_CUSTOM_MACRO_CNTL = 0x035, // 0x00D4 + ATI_CONFIG_CNTL = 0x037, // 0x00DC + ATI_CONFIG_CHIP_ID = 0x038, // 0x00E0 + ATI_CONFIG_STAT0 = 0x039, // 0x00E4 + ATI_GX_CONFIG_STAT1 = 0x03A, // 0x00E8 <-- GX/CT specific + ATI_CRC_SIG = 0x03A, // 0x00E8 + + ATI_DST_OFF_PITCH = 0x040, // 0x0100 + ATI_DST_X = 0x041, // 0x0104 + ATI_DST_Y = 0x042, // 0x0108 + ATI_DST_Y_X = 0x043, // 0x010C + ATI_DST_WIDTH = 0x044, // 0x0110 + ATI_DST_HEIGHT = 0x045, // 0x0114 + ATI_DST_HEIGHT_WIDTH = 0x046, // 0x0118 + ATI_DST_X_WIDTH = 0x047, // 0x011C + ATI_DST_BRES_LNTH = 0x048, // 0x0120 + ATI_DST_BRES_ERR = 0x049, // 0x0124 + ATI_DST_BRES_INC = 0x04A, // 0x0128 + ATI_DST_BRES_DEC = 0x04B, // 0x012C + ATI_DST_CNTL = 0x04C, // 0x0130 + ATI_DST_Y_X_ALIAS1 = 0x04D, // 0x0134 + ATI_TRAIL_BRES_ERR = 0x04E, // 0x0138 + ATI_TRAIL_BRES_INC = 0x04F, // 0x013C + ATI_TRAIL_BRES_DEC = 0x050, // 0x0140 + ATI_DST_BRES_LNTH_ALIAS1 = 0x051, // 0x0144 + ATI_Z_OFF_PITCH = 0x052, // 0x0148 + ATI_Z_CNTL = 0x053, // 0x014C + ATI_ALPHA_TST_CNTL = 0x054, // 0x0150 + ATI_SRC_OFF_PITCH = 0x060, // 0x0180 + ATI_SRC_X = 0x061, // 0x0184 + ATI_SRC_Y = 0x062, // 0x0188 + ATI_SRC_Y_X = 0x063, // 0x018C + ATI_SRC_WIDTH1 = 0x064, // 0x0190 + ATI_SRC_HEIGHT1 = 0x065, // 0x0194 + ATI_SRC_HEIGHT1_WIDTH1 = 0x066, // 0x0198 + ATI_SRC_X_START = 0x067, // 0x019C + ATI_SRC_Y_START = 0x068, // 0x01A0 + ATI_SRC_Y_X_START = 0x069, // 0x01A4 + ATI_SRC_WIDTH2 = 0x06A, // 0x01A8 + ATI_SRC_HEIGHT2 = 0x06B, // 0x01AC + ATI_SRC_HEIGHT2_WIDTH2 = 0x06C, // 0x01B0 + ATI_SRC_CNTL = 0x06D, // 0x01B4 + ATI_SCALE_OFF = 0x070, // 0x01C0 + ATI_SCALE_WIDTH = 0x077, // 0x01DC + ATI_SCALE_HEIGHT = 0x078, // 0x01E0 + ATI_SCALE_PITCH = 0x07B, // 0x01EC + ATI_SCALE_X_INC = 0x07C, // 0x01F0 + ATI_SCALE_Y_INC = 0x07D, // 0x01F4 + ATI_SCALE_VACC = 0x07E, // 0x01F8 + ATI_SCALE_3D_CNTL = 0x07F, // 0x01FC + ATI_HOST_CNTL = 0x090, // 0x0240 + ATI_PAT_REG0 = 0x0A0, // 0x0280 + ATI_PAT_REG1 = 0x0A1, // 0x0284 + ATI_PAT_CNTL = 0x0A2, // 0x0288 + ATI_SC_LEFT = 0x0A8, // 0x02A0 + ATI_SC_RIGHT = 0x0A9, // 0x02A4 + ATI_SC_LEFT_RIGHT = 0x0AA, // 0x02A8 + ATI_SC_TOP = 0x0AB, // 0x02AC + ATI_SC_BOTTOM = 0x0AC, // 0x02B0 + ATI_SC_TOP_BOTTOM = 0x0AD, // 0x02B4 + ATI_DP_BKGD_CLR = 0x0B0, // 0x02C0 + ATI_DP_FRGD_CLR = 0x0B1, // 0x02C4 + ATI_DP_FOG_CLR = 0x0B1, // 0x02C4 + ATI_DP_WRITE_MSK = 0x0B2, // 0x02C8 + ATI_DP_PIX_WIDTH = 0x0B4, // 0x02D0 + ATI_DP_MIX = 0x0B5, // 0x02D4 + ATI_DP_SRC = 0x0B6, // 0x02D8 + ATI_DP_FRGD_CLR_MIX = 0x0B7, // 0x02DC + ATI_DP_FRGD_BKGD_CLR = 0x0B8, // 0x02E0 + ATI_DST_X_Y = 0x0BA, // 0x02E8 + ATI_DST_WIDTH_HEIGHT = 0x0BB, // 0x02EC + ATI_USR_DST_PITCH = 0x0BC, // 0x02F0 + ATI_DP_SET_GUI_ENGINE2 = 0x0BE, // 0x02F8 + ATI_DP_SET_GUI_ENGINE = 0x0BF, // 0x02FC + ATI_CLR_CMP_CLR = 0x0C0, // 0x0300 + ATI_CLR_CMP_MSK = 0x0C1, // 0x0304 + ATI_CLR_CMP_CNTL = 0x0C2, // 0x0308 + ATI_FIFO_STAT = 0x0C4, // 0x0310 + ATI_CONTEXT_MASK = 0x0C8, // 0x0320 <-- 264VT specific + ATI_GUI_TRAJ_CNTL = 0x0CC, // 0x0330 + ATI_GUI_STAT = 0x0CE, // 0x0338 + ATI_MPP_CONFIG = 0x130, // 0x04C0 + ATI_MPP_STROBE_SEQ = 0x131, // 0x04C4 + ATI_MPP_ADDR = 0x132, // 0x04C8 + ATI_MPP_DATA = 0x133, // 0x04CC + ATI_TVO_CNTL = 0x140, // 0x0500 + ATI_SETUP_CNTL = 0x1C1, // 0x0704 ATI_INVALID = 0xFFFF }; -constexpr auto APERTURE_SIZE = 0x01000000UL; /* Mach64 aperture size */ -constexpr auto MM_REGS_0_OFF = 0x007FFC00UL; /* offset to memory mapped registers, block 0 */ -constexpr auto MM_REGS_1_OFF = 0x007FF800UL; /* offset to memory mapped registers, block 1 */ -constexpr auto MM_REGS_2_OFF = 0x003FFC00UL; /* offset to memory mapped registers, 4MB aperture */ -constexpr auto BE_FB_OFFSET = 0x00800000UL; /* Offset to the big-endian frame buffer */ +constexpr auto APERTURE_SIZE = 0x01000000UL; // Mach64 aperture size +constexpr auto MM_REGS_0_OFF = 0x007FFC00UL; // offset to memory mapped registers, block 0 +constexpr auto MM_REGS_1_OFF = 0x007FF800UL; // offset to memory mapped registers, block 1 +constexpr auto MM_REGS_2_OFF = 0x003FFC00UL; // offset to memory mapped registers, 4MB aperture +constexpr auto BE_FB_OFFSET = 0x00800000UL; // Offset to the big-endian frame buffer constexpr auto ATI_XTAL = 14318180.0f; // external crystal oscillator frequency diff --git a/devices/video/atimach64gx.cpp b/devices/video/atimach64gx.cpp index 74f7c88..3f0c7b7 100644 --- a/devices/video/atimach64gx.cpp +++ b/devices/video/atimach64gx.cpp @@ -66,7 +66,7 @@ AtiMach64Gx::AtiMach64Gx() this->vram_ptr = std::unique_ptr (new uint8_t[this->vram_size]); // set up RAMDAC identification - this->regs[ATI_CONFIG_STAT0 >> 2] = 1 << 9; + this->regs[ATI_CONFIG_STAT0] = 1 << 9; } void AtiMach64Gx::notify_bar_change(int bar_num) @@ -121,10 +121,10 @@ bool AtiMach64Gx::pci_io_read(uint32_t offset, uint32_t size, uint32_t* res) } // convert ISA-style I/O address to MMIO register offset - offset = io_idx_to_reg_offset[(offset >> 10) & 0x1F] + (offset & 3); + offset = io_idx_to_reg_offset[(offset >> 10) & 0x1F] * 4 + (offset & 3); // CONFIG_CNTL is accessible from I/O space only - if ((offset & ~3) == ATI_CONFIG_CNTL) { + if ((offset >> 2) == ATI_CONFIG_CNTL) { *res = read_mem(((uint8_t *)&this->config_cntl) + (offset & 3), size); } else { *res = BYTESWAP_SIZED(this->read_reg(offset, size), size); @@ -141,10 +141,10 @@ bool AtiMach64Gx::pci_io_write(uint32_t offset, uint32_t value, uint32_t size) } // convert ISA-style I/O address to MMIO register offset - offset = io_idx_to_reg_offset[(offset >> 10) & 0x1F] + (offset & 3); + offset = io_idx_to_reg_offset[(offset >> 10) & 0x1F] * 4 + (offset & 3); // CONFIG_CNTL is accessible from I/O space only - if ((offset & ~3) == ATI_CONFIG_CNTL) { + if ((offset >> 2) == ATI_CONFIG_CNTL) { write_mem(((uint8_t *)&this->config_cntl) + (offset & 3), value, size); switch (this->config_cntl & 3) { case 0: @@ -190,24 +190,24 @@ void AtiMach64Gx::write_reg(uint32_t reg_offset, uint32_t value, uint32_t size) int crtc_en; uint32_t offset = reg_offset & 3; + reg_offset >>= 2; if (offset || size != 4) { // slow path if ((offset + size) > 4) { ABORT_F("%s: unaligned DWORD writes not implemented", this->name.c_str()); } - uint64_t old_val = this->regs[reg_offset >> 2]; + uint64_t old_val = this->regs[reg_offset]; insert_bits(old_val, value, offset * 8, size * 8); value = old_val; } - switch (reg_offset & ~3) { + switch (reg_offset) { case ATI_CRTC_OFF_PITCH: - this->regs[reg_offset >> 2] = value; this->fb_pitch = extract_bits(value, 22, 10) * 8; this->fb_ptr = &this->vram_ptr[extract_bits(value, 0, 20) * 8]; break; case ATI_CRTC_GEN_CNTL: - if (bit_changed(this->regs[reg_offset >> 2], value, 6)) { + if (bit_changed(this->regs[reg_offset], value, 6)) { if (value & 0x40) { this->blank_on = true; this->blank_display(); @@ -216,7 +216,7 @@ void AtiMach64Gx::write_reg(uint32_t reg_offset, uint32_t value, uint32_t size) } } - if (bit_changed(this->regs[reg_offset >> 2], value, 25)) { + if (bit_changed(this->regs[reg_offset], value, 25)) { if (!bit_set(value, 25)) { this->disable_crtc_internal(); } else { @@ -226,7 +226,7 @@ void AtiMach64Gx::write_reg(uint32_t reg_offset, uint32_t value, uint32_t size) break; case ATI_DAC_REGS: if (size == 1) { // only byte accesses are allowed for DAC registers - int dac_reg_addr = ((this->regs[ATI_DAC_CNTL >> 2] & 1) << 2) | offset; + int dac_reg_addr = ((this->regs[ATI_DAC_CNTL] & 1) << 2) | offset; rgb514_write_reg(dac_reg_addr, extract_bits(value, offset * 8, 8)); } break; @@ -243,7 +243,7 @@ void AtiMach64Gx::write_reg(uint32_t reg_offset, uint32_t value, uint32_t size) return; // prevent writes to this read-only register } - this->regs[reg_offset >> 2] = value; + this->regs[reg_offset] = value; } uint32_t AtiMach64Gx::read(uint32_t rgn_start, uint32_t offset, int size) @@ -280,19 +280,19 @@ void AtiMach64Gx::enable_crtc_internal() uint32_t new_width, new_height; // check for unsupported modes and fail early - if (!bit_set(this->regs[ATI_CRTC_GEN_CNTL >> 2], 24)) + if (!bit_set(this->regs[ATI_CRTC_GEN_CNTL], 24)) ABORT_F("%s: VGA not supported", this->name.c_str()); - new_width = (extract_bits(this->regs[ATI_CRTC_H_TOTAL_DISP >> 2], 16, 8) + 1) * 8; - new_height = extract_bits(this->regs[ATI_CRTC_V_TOTAL_DISP >> 2], 16, 11) + 1; + new_width = (extract_bits(this->regs[ATI_CRTC_H_TOTAL_DISP], 16, 8) + 1) * 8; + new_height = extract_bits(this->regs[ATI_CRTC_V_TOTAL_DISP], 16, 11) + 1; if (new_width != this->active_width || new_height != this->active_height) { this->create_display_window(new_width, new_height); } // calculate display refresh rate - this->hori_total = (extract_bits(this->regs[ATI_CRTC_H_TOTAL_DISP >> 2], 0, 9) + 1) * 8; - this->vert_total = extract_bits(this->regs[ATI_CRTC_V_TOTAL_DISP >> 2], 0, 11) + 1; + this->hori_total = (extract_bits(this->regs[ATI_CRTC_H_TOTAL_DISP], 0, 9) + 1) * 8; + this->vert_total = extract_bits(this->regs[ATI_CRTC_V_TOTAL_DISP], 0, 11) + 1; this->refresh_rate = this->pixel_clock / this->hori_total / this->vert_total; diff --git a/devices/video/atirage.cpp b/devices/video/atirage.cpp index 58ad412..acef23a 100644 --- a/devices/video/atirage.cpp +++ b/devices/video/atirage.cpp @@ -136,14 +136,14 @@ ATIRage::ATIRage(uint16_t dev_id) }; // stuff default values into chip registers - this->regs[ATI_CONFIG_CHIP_ID >> 2] = (asic_id << 24) | dev_id; + this->regs[ATI_CONFIG_CHIP_ID] = (asic_id << 24) | dev_id; // initialize display identification this->disp_id = std::unique_ptr (new DisplayID()); uint8_t mon_code = this->disp_id->read_monitor_sense(0, 0); - this->regs[ATI_GP_IO >> 2] = ((mon_code & 6) << 11) | ((mon_code & 1) << 8); + this->regs[ATI_GP_IO] = ((mon_code & 6) << 11) | ((mon_code & 1) << 8); } void ATIRage::notify_bar_change(int bar_num) @@ -212,16 +212,16 @@ uint32_t ATIRage::read_reg(uint32_t reg_offset, uint32_t size) { uint64_t result; uint32_t offset = reg_offset & 3; - switch (reg_offset & ~3) { + switch (reg_offset >> 2) { case ATI_CLOCK_CNTL: - result = this->regs[ATI_CLOCK_CNTL >> 2]; + result = this->regs[ATI_CLOCK_CNTL]; if ((offset + size - 1) >= 2) { - uint8_t pll_addr = (this->regs[ATI_CLOCK_CNTL >> 2] >> 10) & 0x3F; + uint8_t pll_addr = (this->regs[ATI_CLOCK_CNTL] >> 10) & 0x3F; insert_bits(result, this->plls[pll_addr], 16, 8); } break; case ATI_DAC_REGS: - result = this->regs[ATI_DAC_REGS >> 2]; + result = this->regs[ATI_DAC_REGS]; switch (reg_offset) { case ATI_DAC_W_INDEX: insert_bits(result, this->dac_wr_index, 0, 8); @@ -260,74 +260,75 @@ uint32_t ATIRage::read_reg(uint32_t reg_offset, uint32_t size) { } void ATIRage::write_reg(uint32_t reg_offset, uint32_t value, uint32_t size) { - uint32_t offset = reg_offset & 3; + uint32_t offset = reg_offset & 3; + reg_offset >>= 2; if (offset || size != 4) { // slow path if ((offset + size) > 4) { ABORT_F("%s: unaligned DWORD writes not implemented", this->name.c_str()); } - uint64_t old_val = this->regs[reg_offset >> 2]; + uint64_t old_val = this->regs[reg_offset]; insert_bits(old_val, value, offset * 8, size * 8); value = old_val; } - switch (reg_offset & ~3) { + switch (reg_offset) { case ATI_CRTC_H_TOTAL_DISP: LOG_F(9, "%s: ATI_CRTC_H_TOTAL_DISP set to 0x%08X", this->name.c_str(), value); break; case ATI_CRTC_OFF_PITCH: - this->regs[reg_offset >> 2] = value; + this->regs[reg_offset] = value; this->fb_pitch = extract_bits(value, 22, 10) * 8; this->fb_ptr = &this->vram_ptr[extract_bits(value, 0, 20) * 8]; - if (bit_set(this->regs[ATI_CRTC_GEN_CNTL >> 2], 25) && - !bit_set(this->regs[ATI_CRTC_GEN_CNTL >> 2], 6)) { + if (bit_set(this->regs[ATI_CRTC_GEN_CNTL], 25) && + !bit_set(this->regs[ATI_CRTC_GEN_CNTL], 6)) { this->crtc_update(); } break; case ATI_CRTC_GEN_CNTL: - if (bit_changed(this->regs[reg_offset >> 2], value, 6)) { + if (bit_changed(this->regs[reg_offset], value, 6)) { if (value & 0x40) { - this->regs[reg_offset >> 2] |= (1 << 6); + this->regs[reg_offset] |= (1 << 6); this->blank_on = true; this->blank_display(); } else { - this->regs[reg_offset >> 2] &= ~(1 << 6); + this->regs[reg_offset] &= ~(1 << 6); this->blank_on = false; } } - if (bit_changed(this->regs[reg_offset >> 2], value, 25)) { - this->regs[reg_offset >> 2] = value; - if (bit_set(this->regs[reg_offset >> 2], 25) && - !bit_set(this->regs[reg_offset >> 2], 6)) { + if (bit_changed(this->regs[reg_offset], value, 25)) { + this->regs[reg_offset] = value; + if (bit_set(this->regs[reg_offset], 25) && + !bit_set(this->regs[reg_offset], 6)) { this->crtc_update(); } return; } break; case ATI_GP_IO: - this->regs[reg_offset >> 2] = value; + this->regs[reg_offset] = value; if (offset < 2 && (offset + size - 1) >= 1) { - uint8_t gpio_levels = (this->regs[ATI_GP_IO >> 2] >> 8) & 0xFFU; + uint8_t gpio_levels = (this->regs[ATI_GP_IO] >> 8) & 0xFFU; gpio_levels = ((gpio_levels & 0x30) >> 3) | (gpio_levels & 1); - uint8_t gpio_dirs = (this->regs[ATI_GP_IO >> 2] >> 24) & 0xFFU; + uint8_t gpio_dirs = (this->regs[ATI_GP_IO] >> 24) & 0xFFU; gpio_dirs = ((gpio_dirs & 0x30) >> 3) | (gpio_dirs & 1); gpio_levels = this->disp_id->read_monitor_sense(gpio_levels, gpio_dirs); - insert_bits(this->regs[ATI_GP_IO >> 2], + insert_bits(this->regs[ATI_GP_IO], ((gpio_levels & 6) << 3) | (gpio_levels & 1), 8, 8); } return; case ATI_CLOCK_CNTL: - this->regs[reg_offset >> 2] = value; - if ((offset + size - 1) >= 2 && bit_set(this->regs[ATI_CLOCK_CNTL >> 2], 9)) { - uint8_t pll_addr = (this->regs[ATI_CLOCK_CNTL >> 2] >> 10) & 0x3F; + this->regs[reg_offset] = value; + if ((offset + size - 1) >= 2 && bit_set(this->regs[ATI_CLOCK_CNTL], 9)) { + uint8_t pll_addr = (this->regs[ATI_CLOCK_CNTL] >> 10) & 0x3F; uint8_t pll_data = (value >> 16) & 0xFF; this->plls[pll_addr] = pll_data; LOG_F(9, "%s: PLL #%d set to 0x%02X", this->name.c_str(), pll_addr, pll_data); } return; case ATI_DAC_REGS: - switch (reg_offset) { + switch (reg_offset * 4 + offset) { case ATI_DAC_W_INDEX: this->dac_wr_index = value & 0xFFU; this->comp_index = 0; @@ -350,17 +351,17 @@ void ATIRage::write_reg(uint32_t reg_offset, uint32_t value, uint32_t size) { } return; case ATI_GEN_TEST_CNTL: - if (bit_changed(this->regs[reg_offset >> 2], value, 7)) { + if (bit_changed(this->regs[reg_offset], value, 7)) { if (bit_set(value, 7)) this->setup_hw_cursor(); else this->cursor_on = false; } - if (bit_changed(this->regs[reg_offset >> 2], value, 8)) { + if (bit_changed(this->regs[reg_offset], value, 8)) { if (!bit_set(value, 8)) LOG_F(9, "%s: reset GUI engine", this->name.c_str()); } - if (bit_changed(this->regs[reg_offset >> 2], value, 9)) { + if (bit_changed(this->regs[reg_offset], value, 9)) { if (bit_set(value, 9)) LOG_F(9, "%s: reset memory controller", this->name.c_str()); } @@ -373,7 +374,7 @@ void ATIRage::write_reg(uint32_t reg_offset, uint32_t value, uint32_t size) { return; // prevent writes to this read-only register } - this->regs[reg_offset >> 2] = value; + this->regs[reg_offset] = value; } bool ATIRage::io_access_allowed(uint32_t offset) { @@ -457,7 +458,7 @@ void ATIRage::verbose_pixel_format(int crtc_index) { return; } - uint32_t fmt = extract_bits(this->regs[ATI_CRTC_GEN_CNTL >> 2], 8, 3); + uint32_t fmt = extract_bits(this->regs[ATI_CRTC_GEN_CNTL], 8, 3); const char* what = "Pixel format:"; @@ -467,7 +468,7 @@ void ATIRage::verbose_pixel_format(int crtc_index) { break; case 2: // check the undocumented DAC_DIRECT bit - if (bit_set(this->regs[ATI_DAC_CNTL >> 2], 10)) { + if (bit_set(this->regs[ATI_DAC_CNTL], 10)) { LOG_F(INFO, "%s 8 bpp direct color (RGB322)", what); } else { LOG_F(INFO, "%s 8 bpp with DAC palette", what); @@ -494,7 +495,7 @@ void ATIRage::crtc_update() { uint32_t new_width, new_height, new_htotal, new_vtotal; // check for unsupported modes and fail early - if (!bit_set(this->regs[ATI_CRTC_GEN_CNTL >> 2], 24)) + if (!bit_set(this->regs[ATI_CRTC_GEN_CNTL], 24)) ABORT_F("%s: VGA not supported", this->name.c_str()); if ((this->plls[PLL_VCLK_CNTL] & 3) != 3) @@ -502,16 +503,16 @@ void ATIRage::crtc_update() { bool need_recalc = false; - new_width = (extract_bits(this->regs[ATI_CRTC_H_TOTAL_DISP >> 2], 16, 8) + 1) * 8; - new_height = extract_bits(this->regs[ATI_CRTC_V_TOTAL_DISP >> 2], 16, 11) + 1; + new_width = (extract_bits(this->regs[ATI_CRTC_H_TOTAL_DISP], 16, 8) + 1) * 8; + new_height = extract_bits(this->regs[ATI_CRTC_V_TOTAL_DISP], 16, 11) + 1; if (new_width != this->active_width || new_height != this->active_height) { this->create_display_window(new_width, new_height); need_recalc = true; } - new_htotal = (extract_bits(this->regs[ATI_CRTC_H_TOTAL_DISP >> 2], 0, 9) + 1) * 8; - new_vtotal = extract_bits(this->regs[ATI_CRTC_V_TOTAL_DISP >> 2], 0, 11) + 1; + new_htotal = (extract_bits(this->regs[ATI_CRTC_H_TOTAL_DISP], 0, 9) + 1) * 8; + new_vtotal = extract_bits(this->regs[ATI_CRTC_V_TOTAL_DISP], 0, 11) + 1; if (new_htotal != this->hori_total || new_vtotal != this->vert_total) { this->hori_total = new_htotal; @@ -523,7 +524,7 @@ void ATIRage::crtc_update() { return; // look up which VPLL ouput is requested - int clock_sel = this->regs[ATI_CLOCK_CNTL >> 2] & 3; + int clock_sel = this->regs[ATI_CLOCK_CNTL] & 3; // calculate VPLL output frequency float vpll_freq = calc_pll_freq(2, this->plls[VCLK0_FB_DIV + clock_sel]); @@ -541,11 +542,11 @@ void ATIRage::crtc_update() { this->refresh_rate = pixel_clock / this->hori_total / this->vert_total; // set up frame buffer converter - int pix_fmt = extract_bits(this->regs[ATI_CRTC_GEN_CNTL >> 2], 8, 3); + int pix_fmt = extract_bits(this->regs[ATI_CRTC_GEN_CNTL], 8, 3); switch (pix_fmt) { case 2: - if (bit_set(this->regs[ATI_DAC_CNTL >> 2], 10)) { + if (bit_set(this->regs[ATI_DAC_CNTL], 10)) { ABORT_F("%s: DAC_DIRECT set!", this->name.c_str()); } this->convert_fb_cb = [this](uint8_t *dst_buf, int dst_pitch) { @@ -558,7 +559,7 @@ void ATIRage::crtc_update() { 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 >> 2], 24) ? "extended" : "VGA"); + bit_set(this->regs[ATI_CRTC_GEN_CNTL], 24) ? "extended" : "VGA"); LOG_F(INFO, "Video width: %d px", this->active_width); LOG_F(INFO, "Video height: %d px", this->active_height); verbose_pixel_format(0); @@ -584,14 +585,14 @@ void ATIRage::crtc_update() { void ATIRage::draw_hw_cursor(uint8_t *dst_buf, int dst_pitch) { uint8_t *src_buf, *src_row, *dst_row, px4; - int vert_offset = extract_bits(this->regs[ATI_CUR_HORZ_VERT_OFF >> 2], 16, 5); + int vert_offset = extract_bits(this->regs[ATI_CUR_HORZ_VERT_OFF], 16, 5); - src_buf = &this->vram_ptr[this->regs[ATI_CUR_OFFSET >> 2] * 8]; + src_buf = &this->vram_ptr[this->regs[ATI_CUR_OFFSET] * 8]; int cur_height = 64 - vert_offset; - uint32_t color0 = this->regs[ATI_CUR_CLR0 >> 2] | 0x000000FFUL; - uint32_t color1 = this->regs[ATI_CUR_CLR1 >> 2] | 0x000000FFUL; + uint32_t color0 = this->regs[ATI_CUR_CLR0] | 0x000000FFUL; + uint32_t color1 = this->regs[ATI_CUR_CLR1] | 0x000000FFUL; for (int h = 0; h < cur_height; h++) { dst_row = &dst_buf[h * dst_pitch]; @@ -620,8 +621,8 @@ void ATIRage::draw_hw_cursor(uint8_t *dst_buf, int dst_pitch) { } void ATIRage::get_cursor_position(int& x, int& y) { - x = this->regs[ATI_CUR_HORZ_VERT_POSN >> 2] & 0xFFFFU; - y = (this->regs[ATI_CUR_HORZ_VERT_POSN >> 2] >> 16) & 0xFFFFU; + x = this->regs[ATI_CUR_HORZ_VERT_POSN] & 0xFFFFU; + y = (this->regs[ATI_CUR_HORZ_VERT_POSN] >> 16) & 0xFFFFU; } static const PropMap AtiRage_Properties = {