diff --git a/devices/video/atimach64gx.cpp b/devices/video/atimach64gx.cpp index 404c6a0..a4ec6f4 100644 --- a/devices/video/atimach64gx.cpp +++ b/devices/video/atimach64gx.cpp @@ -668,6 +668,81 @@ void AtiMach64Gx::crtc_update() this->crtc_on = true; } +void AtiMach64Gx::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], ATI_CUR_VERT_OFF, ATI_CUR_VERT_OFF_size); + //int horz_offset = extract_bits(this->regs[ATI_CUR_HORZ_VERT_OFF], ATI_CUR_HORZ_OFF, ATI_CUR_HORZ_OFF_size); + + 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] | 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]; + src_row = &src_buf[h * 16]; + + for (int x = 0; x < 16; x++) { + px4 = src_row[x]; + + for (int p = 0; p < 4; p++, px4 >>= 2, dst_row += 4) { + switch(px4 & 3) { + case 0: // cursor color 0 + WRITE_DWORD_BE_A(dst_row, color0); + break; + case 1: // cursor color 1 + WRITE_DWORD_BE_A(dst_row, color1); + break; + case 2: // transparent + WRITE_DWORD_BE_A(dst_row, 0); + break; + case 3: // 1's complement of display pixel + break; + } + } + } + } +} + +void AtiMach64Gx::get_cursor_position(int& x, int& y) { + x = extract_bits(this->regs[ATI_CUR_HORZ_VERT_POSN], ATI_CUR_HORZ_POSN, ATI_CUR_HORZ_POSN_size); + y = extract_bits(this->regs[ATI_CUR_HORZ_VERT_POSN], ATI_CUR_VERT_POSN, ATI_CUR_VERT_POSN_size); +} + +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, 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); +#if 1 +#else + set_bit(this->regs[ATI_CRTC_GEN_CNTL], ATI_CRTC_VSYNC_INT); +#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(WARNING, "%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); + } + }; + return 0; +} + // ========================== IBM RGB514 related code ========================== void AtiMach64Gx::rgb514_write_reg(uint8_t reg_addr, uint8_t value) { diff --git a/devices/video/atimach64gx.h b/devices/video/atimach64gx.h index c49889f..e48bf82 100644 --- a/devices/video/atimach64gx.h +++ b/devices/video/atimach64gx.h @@ -49,6 +49,9 @@ public: bool pci_io_read(uint32_t offset, uint32_t size, uint32_t* res); bool pci_io_write(uint32_t offset, uint32_t value, uint32_t size); + // HWComponent methods + int device_postinit(); + // MMIODevice methods uint32_t read(uint32_t rgn_start, uint32_t offset, int size); void write(uint32_t rgn_start, uint32_t offset, uint32_t value, int size); @@ -64,6 +67,8 @@ protected: void rgb514_write_reg(uint8_t reg_addr, uint8_t value); void rgb514_write_ind_reg(uint8_t reg_addr, uint8_t value); void verbose_pixel_format(int crtc_index); + void draw_hw_cursor(uint8_t *dst_buf, int dst_pitch); + void get_cursor_position(int& x, int& y); private: void change_one_bar(uint32_t &aperture, uint32_t aperture_size, uint32_t aperture_new, int bar_num);