diff --git a/devices/video/atimach64gx.cpp b/devices/video/atimach64gx.cpp index 91ec258cf1..8d928308b8 100644 --- a/devices/video/atimach64gx.cpp +++ b/devices/video/atimach64gx.cpp @@ -525,6 +525,7 @@ void AtiMach64Gx::write_reg(uint32_t reg_offset, uint32_t value, uint32_t size) new_value = (old_value & bits_read_only) | (new_value & ~bits_read_only); WRITE_VALUE_AND_LOG(ATIINTERRUPT); + this->update_interrupt(); return; } case ATI_CRTC_GEN_CNTL: @@ -904,7 +905,7 @@ void AtiMach64Gx::get_cursor_position(int& x, int& y) { int AtiMach64Gx::device_postinit() { this->vbl_cb = [this](uint8_t irq_line_state) { - insert_bits(this->regs[ATI_CRTC_INT_CNTL], irq_line_state, ATI_CRTC_VBLANK, irq_line_state); + insert_bits(this->regs[ATI_CRTC_INT_CNTL], irq_line_state, ATI_CRTC_VBLANK, 1); if (irq_line_state) { set_bit(this->regs[ATI_CRTC_INT_CNTL], ATI_CRTC_VBLANK_INT); set_bit(this->regs[ATI_CRTC_INT_CNTL], ATI_CRTC_VLINE_INT); @@ -914,26 +915,28 @@ int AtiMach64Gx::device_postinit() #endif } - bool do_interrupt = - bit_set(this->regs[ATI_CRTC_INT_CNTL], ATI_CRTC_VBLANK_INT_EN) || - bit_set(this->regs[ATI_CRTC_INT_CNTL], ATI_CRTC_VLINE_INT_EN) || -#if 1 -#else - bit_set(this->regs[ATI_CRTC_GEN_CNTL], ATI_CRTC_VSYNC_INT_EN) || -#endif - 0; - - LOG_F(ATIINTERRUPT, "%s: irq_line_state:%d do_interrupt:%d CRTC_INT_CNTL:%08x", - this->name.c_str(), irq_line_state, do_interrupt, - this->regs[ATI_CRTC_INT_CNTL]); - - if (do_interrupt) { - this->pci_interrupt(irq_line_state); - } + this->update_interrupt(); }; return 0; } +void AtiMach64Gx::update_interrupt() +{ + uint32_t int_cntl = this->regs[ATI_CRTC_INT_CNTL]; + bool new_pci_irq_line_state = + (bit_set(int_cntl, ATI_CRTC_VBLANK_INT_EN) && + bit_set(int_cntl, ATI_CRTC_VBLANK_INT)) || + (bit_set(int_cntl, ATI_CRTC_VLINE_INT_EN) && + bit_set(int_cntl, ATI_CRTC_VLINE_INT)); + + if (new_pci_irq_line_state != this->pci_irq_line_state) { + this->pci_irq_line_state = new_pci_irq_line_state; + LOG_F(ATIINTERRUPT, "%s: pci_irq_line_state:%d CRTC_INT_CNTL:%08x", + this->name.c_str(), this->pci_irq_line_state, int_cntl); + this->pci_interrupt(this->pci_irq_line_state); + } +} + // ========================== IBM RGB514 related code ========================== const char* AtiMach64Gx::rgb514_get_reg_name(uint32_t reg_addr) { diff --git a/devices/video/atimach64gx.h b/devices/video/atimach64gx.h index 582975578d..43fc8e142b 100644 --- a/devices/video/atimach64gx.h +++ b/devices/video/atimach64gx.h @@ -76,8 +76,10 @@ class AtiMach64Gx : public PCIDevice, public VideoCtrlBase { private: void change_one_bar(uint32_t &aperture, uint32_t aperture_size, uint32_t aperture_new, int bar_num); + void update_interrupt(); uint32_t regs[256] = {}; // internal registers + bool pci_irq_line_state = false; int vram_size; diff --git a/devices/video/atirage.cpp b/devices/video/atirage.cpp index e56a1b28ae..1fd54d32fb 100644 --- a/devices/video/atirage.cpp +++ b/devices/video/atirage.cpp @@ -658,6 +658,8 @@ void ATIRage::write_reg(uint32_t reg_offset, uint32_t value, uint32_t size) { } WRITE_VALUE_AND_LOG(9); + if (reg_num == ATI_CRTC_INT_CNTL) + this->update_interrupt(); } bool ATIRage::io_access_allowed(uint32_t offset) { @@ -1033,7 +1035,7 @@ void ATIRage::get_cursor_position(int& x, int& y) { int ATIRage::device_postinit() { this->vbl_cb = [this](uint8_t irq_line_state) { - insert_bits(this->regs[ATI_CRTC_INT_CNTL], irq_line_state, ATI_CRTC_VBLANK, irq_line_state); + insert_bits(this->regs[ATI_CRTC_INT_CNTL], irq_line_state, ATI_CRTC_VBLANK, 1); if (irq_line_state) { set_bit(this->regs[ATI_CRTC_INT_CNTL], ATI_CRTC_VBLANK_INT); set_bit(this->regs[ATI_CRTC_INT_CNTL], ATI_CRTC_VLINE_INT); @@ -1043,22 +1045,26 @@ int ATIRage::device_postinit() #endif } - bool do_interrupt = - bit_set(this->regs[ATI_CRTC_INT_CNTL], ATI_CRTC_VBLANK_INT_EN) || - bit_set(this->regs[ATI_CRTC_INT_CNTL], ATI_CRTC_VLINE_INT_EN) || -#if 1 -#else - bit_set(this->regs[ATI_CRTC_GEN_CNTL], ATI_CRTC_VSYNC_INT_EN) || -#endif - 0; - - if (do_interrupt) { - this->pci_interrupt(irq_line_state); - } + this->update_interrupt(); }; return 0; } +void ATIRage::update_interrupt() +{ + uint32_t int_cntl = this->regs[ATI_CRTC_INT_CNTL]; + bool new_pci_irq_line_state = + (bit_set(int_cntl, ATI_CRTC_VBLANK_INT_EN) && + bit_set(int_cntl, ATI_CRTC_VBLANK_INT)) || + (bit_set(int_cntl, ATI_CRTC_VLINE_INT_EN) && + bit_set(int_cntl, ATI_CRTC_VLINE_INT)); + + if (new_pci_irq_line_state != this->pci_irq_line_state) { + this->pci_irq_line_state = new_pci_irq_line_state; + this->pci_interrupt(this->pci_irq_line_state); + } +} + // =================================== Draw Engine ===================================== void ATIRage::begin_drawing(uint32_t initiator, uint32_t value) { switch(initiator) { diff --git a/devices/video/atirage.h b/devices/video/atirage.h index 2b636197e5..0bd6853384 100644 --- a/devices/video/atirage.h +++ b/devices/video/atirage.h @@ -89,6 +89,7 @@ class ATIRage : public PCIDevice, public VideoCtrlBase { private: void change_one_bar(uint32_t &aperture, uint32_t aperture_size, uint32_t aperture_new, int bar_num); + void update_interrupt(); void begin_drawing(uint32_t initiator, uint32_t value); void draw_rect(uint32_t width, uint32_t height); @@ -102,6 +103,7 @@ class ATIRage : public PCIDevice, public VideoCtrlBase { uint8_t plls[64] = {}; // internal PLL registers uint8_t cmd_fifo_size = 0; + bool pci_irq_line_state = false; bool host_data_active = false; uint32_t host_dst_width = 0;