rlm@1: // VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator. rlm@1: // Copyright (C) 1999-2003 Forgotten rlm@1: // Copyright (C) 2004 Forgotten and the VBA development team rlm@1: rlm@1: // This program is free software; you can redistribute it and/or modify rlm@1: // it under the terms of the GNU General Public License as published by rlm@1: // the Free Software Foundation; either version 2, or(at your option) rlm@1: // any later version. rlm@1: // rlm@1: // This program is distributed in the hope that it will be useful, rlm@1: // but WITHOUT ANY WARRANTY; without even the implied warranty of rlm@1: // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the rlm@1: // GNU General Public License for more details. rlm@1: // rlm@1: // You should have received a copy of the GNU General Public License rlm@1: // along with this program; if not, write to the Free Software Foundation, rlm@1: // Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. rlm@1: rlm@1: #include "screenarea.h" rlm@1: rlm@1: #include rlm@1: rlm@1: namespace VBA rlm@1: { rlm@1: rlm@1: ScreenArea::ScreenArea(int _iWidth, int _iHeight, int _iScale) : rlm@1: m_puiPixels(NULL), rlm@1: m_puiDelta(NULL), rlm@1: m_vFilter2x(NULL), rlm@1: m_vFilterIB(NULL), rlm@1: m_bShowCursor(true) rlm@1: { rlm@1: g_assert(_iWidth >= 1 && _iHeight >= 1 && _iScale >= 1); rlm@1: rlm@1: m_iWidth = _iWidth; rlm@1: m_iHeight = _iHeight; rlm@1: m_iScale = _iScale; rlm@1: vUpdateSize(); rlm@1: rlm@1: set_events(Gdk::EXPOSURE_MASK rlm@1: | Gdk::POINTER_MOTION_MASK rlm@1: | Gdk::ENTER_NOTIFY_MASK rlm@1: | Gdk::LEAVE_NOTIFY_MASK); rlm@1: rlm@1: char aiEmptyData[8]; rlm@1: memset(aiEmptyData, 0, sizeof(aiEmptyData)); rlm@1: Glib::RefPtr poSource = Gdk::Bitmap::create(aiEmptyData, 8, 8); rlm@1: Glib::RefPtr poMask = Gdk::Bitmap::create(aiEmptyData, 8, 8); rlm@1: Gdk::Color oFg; rlm@1: Gdk::Color oBg; rlm@1: oFg.set_rgb(0, 0, 0); rlm@1: oBg.set_rgb(0, 0, 0); rlm@1: rlm@1: m_poEmptyCursor = new Gdk::Cursor(poSource, poMask, oFg, oBg, 0, 0); rlm@1: } rlm@1: rlm@1: ScreenArea::~ScreenArea() rlm@1: { rlm@1: if (m_puiPixels != NULL) rlm@1: { rlm@1: delete[] m_puiPixels; rlm@1: } rlm@1: rlm@1: if (m_puiDelta != NULL) rlm@1: { rlm@1: delete[] m_puiDelta; rlm@1: } rlm@1: rlm@1: if (m_poEmptyCursor != NULL) rlm@1: { rlm@1: delete m_poEmptyCursor; rlm@1: } rlm@1: } rlm@1: rlm@1: void ScreenArea::vSetSize(int _iWidth, int _iHeight) rlm@1: { rlm@1: g_return_if_fail(_iWidth >= 1 && _iHeight >= 1); rlm@1: rlm@1: if (_iWidth != m_iWidth || _iHeight != m_iHeight) rlm@1: { rlm@1: m_iWidth = _iWidth; rlm@1: m_iHeight = _iHeight; rlm@1: vUpdateSize(); rlm@1: } rlm@1: } rlm@1: rlm@1: void ScreenArea::vSetScale(int _iScale) rlm@1: { rlm@1: g_return_if_fail(_iScale >= 1); rlm@1: rlm@1: if (_iScale != m_iScale) rlm@1: { rlm@1: m_iScale = _iScale; rlm@1: vUpdateSize(); rlm@1: } rlm@1: } rlm@1: rlm@1: void ScreenArea::vSetFilter2x(EFilter2x _eFilter2x) rlm@1: { rlm@1: m_vFilter2x = pvGetFilter2x(_eFilter2x, FilterDepth32); rlm@1: } rlm@1: rlm@1: void ScreenArea::vSetFilterIB(EFilterIB _eFilterIB) rlm@1: { rlm@1: m_vFilterIB = pvGetFilterIB(_eFilterIB, FilterDepth32); rlm@1: } rlm@1: rlm@1: void ScreenArea::vDrawPixels(u8 * _puiData) rlm@1: { rlm@1: if (m_vFilterIB != NULL) rlm@1: { rlm@1: m_vFilterIB(_puiData + m_iAreaWidth * 2 + 4, rlm@1: m_iAreaWidth * 2 + 4, rlm@1: m_iWidth, rlm@1: m_iHeight); rlm@1: } rlm@1: rlm@1: if (m_iScale == 1) rlm@1: { rlm@1: u32 * puiSrc = (u32 *)_puiData + m_iWidth + 1; rlm@1: u32 * puiPixel = m_puiPixels; rlm@1: for (int y = 0; y < m_iHeight; y++) rlm@1: { rlm@1: for (int x = 0; x < m_iWidth; x++) rlm@1: { rlm@1: *puiPixel++ = *puiSrc++; rlm@1: } rlm@1: puiSrc++; rlm@1: } rlm@1: } rlm@1: else if (m_iScale == 2 && m_vFilter2x != NULL) rlm@1: { rlm@1: m_vFilter2x(_puiData + m_iAreaWidth * 2 + 4, rlm@1: m_iAreaWidth * 2 + 4, rlm@1: m_puiDelta, rlm@1: (u8 *)m_puiPixels, rlm@1: m_iRowStride, rlm@1: m_iWidth, rlm@1: m_iHeight); rlm@1: } rlm@1: else rlm@1: { rlm@1: u32 * puiSrc = (u32 *)_puiData + m_iWidth + 1; rlm@1: u32 * puiSrc2; rlm@1: u32 * puiPixel = m_puiPixels; rlm@1: for (int y = 0; y < m_iHeight; y++) rlm@1: { rlm@1: for (int j = 0; j < m_iScale; j++) rlm@1: { rlm@1: puiSrc2 = puiSrc; rlm@1: for (int x = 0; x < m_iWidth; x++) rlm@1: { rlm@1: for (int i = 0; i < m_iScale; i++) rlm@1: { rlm@1: *puiPixel++ = *puiSrc2; rlm@1: } rlm@1: puiSrc2++; rlm@1: } rlm@1: } rlm@1: puiSrc = puiSrc2 + 1; rlm@1: } rlm@1: } rlm@1: rlm@1: queue_draw_area(0, 0, m_iAreaWidth, m_iAreaHeight); rlm@1: } rlm@1: rlm@1: void ScreenArea::vDrawColor(u32 _uiColor) rlm@1: { rlm@1: _uiColor = GUINT32_TO_BE(_uiColor) << 8; rlm@1: rlm@1: u32 * puiPixel = m_puiPixels; rlm@1: u32 * puiEnd = m_puiPixels + m_iAreaWidth * m_iAreaHeight; rlm@1: while (puiPixel != puiEnd) rlm@1: { rlm@1: *puiPixel++ = _uiColor; rlm@1: } rlm@1: rlm@1: queue_draw_area(0, 0, m_iAreaWidth, m_iAreaHeight); rlm@1: } rlm@1: rlm@1: void ScreenArea::vUpdateSize() rlm@1: { rlm@1: if (m_puiPixels != NULL) rlm@1: { rlm@1: delete[] m_puiPixels; rlm@1: } rlm@1: rlm@1: if (m_puiDelta != NULL) rlm@1: { rlm@1: delete[] m_puiDelta; rlm@1: } rlm@1: rlm@1: m_iAreaWidth = m_iScale * m_iWidth; rlm@1: m_iAreaHeight = m_iScale * m_iHeight; rlm@1: m_iRowStride = m_iAreaWidth * 4; rlm@1: rlm@1: m_puiPixels = new u32[m_iAreaWidth * m_iAreaHeight]; rlm@1: rlm@1: m_puiDelta = new u8[(m_iWidth + 2) * (m_iHeight + 2) * 4]; rlm@1: memset(m_puiDelta, 255, (m_iWidth + 2) * (m_iHeight + 2) * 4); rlm@1: rlm@1: set_size_request(m_iAreaWidth, m_iAreaHeight); rlm@1: } rlm@1: rlm@1: void ScreenArea::vStartCursorTimeout() rlm@1: { rlm@1: m_oCursorSig.disconnect(); rlm@1: m_oCursorSig = Glib::signal_timeout().connect( rlm@1: SigC::slot(*this, &ScreenArea::bOnCursorTimeout), rlm@1: 2000); rlm@1: } rlm@1: rlm@1: void ScreenArea::vStopCursorTimeout() rlm@1: { rlm@1: m_oCursorSig.disconnect(); rlm@1: } rlm@1: rlm@1: void ScreenArea::vHideCursor() rlm@1: { rlm@1: get_window()->set_cursor(*m_poEmptyCursor); rlm@1: m_bShowCursor = false; rlm@1: } rlm@1: rlm@1: void ScreenArea::vShowCursor() rlm@1: { rlm@1: get_window()->set_cursor(); rlm@1: m_bShowCursor = true; rlm@1: } rlm@1: rlm@1: bool ScreenArea::on_expose_event(GdkEventExpose * _pstEvent) rlm@1: { rlm@1: if (_pstEvent->area.x + _pstEvent->area.width > m_iAreaWidth rlm@1: || _pstEvent->area.y + _pstEvent->area.height > m_iAreaHeight) rlm@1: { rlm@1: return false; rlm@1: } rlm@1: rlm@1: guchar * puiAreaPixels = (guchar *)m_puiPixels; rlm@1: rlm@1: if (_pstEvent->area.x != 0) rlm@1: { rlm@1: puiAreaPixels += _pstEvent->area.x << 2; rlm@1: } rlm@1: rlm@1: if (_pstEvent->area.y != 0) rlm@1: { rlm@1: puiAreaPixels += _pstEvent->area.y * m_iRowStride; rlm@1: } rlm@1: rlm@1: get_window()->draw_rgb_32_image(get_style()->get_fg_gc(get_state()), rlm@1: _pstEvent->area.x, rlm@1: _pstEvent->area.y, rlm@1: _pstEvent->area.width, rlm@1: _pstEvent->area.height, rlm@1: Gdk::RGB_DITHER_MAX, rlm@1: puiAreaPixels, rlm@1: m_iRowStride); rlm@1: return true; rlm@1: } rlm@1: rlm@1: bool ScreenArea::on_motion_notify_event(GdkEventMotion * _pstEvent) rlm@1: { rlm@1: if (! m_bShowCursor) rlm@1: { rlm@1: vShowCursor(); rlm@1: } rlm@1: vStartCursorTimeout(); rlm@1: return false; rlm@1: } rlm@1: rlm@1: bool ScreenArea::on_enter_notify_event(GdkEventCrossing * _pstEvent) rlm@1: { rlm@1: vStartCursorTimeout(); rlm@1: return false; rlm@1: } rlm@1: rlm@1: bool ScreenArea::on_leave_notify_event(GdkEventCrossing * _pstEvent) rlm@1: { rlm@1: vStopCursorTimeout(); rlm@1: if (! m_bShowCursor) rlm@1: { rlm@1: vShowCursor(); rlm@1: } rlm@1: return false; rlm@1: } rlm@1: rlm@1: bool ScreenArea::bOnCursorTimeout() rlm@1: { rlm@1: vHideCursor(); rlm@1: return false; rlm@1: } rlm@1: rlm@1: } // namespace VBA