コード例 #1
0
ファイル: cliprect.cpp プロジェクト: AdamRi/scummvm-pink
/**
 * Adds velocities and creates clipping rectangles for all the
 * objects that have moved on the specified object list.
 * @param pObjList			Playfield display list to draw
 * @param pWin				Playfield window top left position
 * @param pClip				Playfield clipping rectangle
 * @param bNoVelocity		When reset, objects pos is updated with velocity
 * @param bScrolled)		When set, playfield has scrolled
 */
void FindMovingObjects(OBJECT **pObjList, Common::Point *pWin, Common::Rect *pClip, bool bNoVelocity, bool bScrolled) {
	OBJECT *pObj;			// object list traversal pointer

	for (pObj = *pObjList; pObj != NULL; pObj = pObj->pNext) {
		if (!bNoVelocity) {
			// we want to add velocities to objects position

			if (bScrolled) {
				// this playfield has scrolled

				// indicate change
				pObj->flags |= DMA_CHANGED;
			}
		}

		if ((pObj->flags & DMA_CHANGED) ||	// object changed
			HasPalMoved(pObj->pPal)) {	// or palette moved
			// object has changed in some way

			Common::Rect rcClip;	// objects clipped bounding rectangle
			Common::Rect rcObj;	// objects bounding rectangle

			// calc intersection of objects previous bounding rectangle
			// NOTE: previous position is in screen co-ords
			if (IntersectRectangle(rcClip, pObj->rcPrev, *pClip)) {
				// previous position is within clipping rect
				AddClipRect(rcClip);
			}

			// calc objects current bounding rectangle
			if (pObj->flags & DMA_ABS) {
				// object position is absolute
				rcObj.left = fracToInt(pObj->xPos);
				rcObj.top  = fracToInt(pObj->yPos);
			} else {
				// object position is relative to window
				rcObj.left = fracToInt(pObj->xPos) - pWin->x;
				rcObj.top  = fracToInt(pObj->yPos) - pWin->y;
			}
			rcObj.right  = rcObj.left + pObj->width;
			rcObj.bottom = rcObj.top  + pObj->height;

			// calc intersection of object with clipping rect
			if (IntersectRectangle(rcClip, rcObj, *pClip)) {
				// current position is within clipping rect
				AddClipRect(rcClip);

				// update previous position
				pObj->rcPrev = rcClip;
			} else {
				// clear previous position
				pObj->rcPrev = Common::Rect();
			}

			// clear changed flag
			pObj->flags &= ~DMA_CHANGED;
		}
	}
}
コード例 #2
0
/**
 * Returns the x,y position of an objects animation point.
 * @param pObj			Pointer to object
 * @param pPosX			Gets set to objects X animation position
 * @param pPosY			Gets set to objects Y animation position
 */
void GetAniPosition(OBJECT *pObj, int *pPosX, int *pPosY) {
	// validate object pointer
	assert(isValidObject(pObj));

	// get the animation offset of the object
	GetAniOffset(pObj->hImg, pObj->flags, pPosX, pPosY);

	// from animation offset and objects position - determine objects animation point
	*pPosX += fracToInt(pObj->xPos);
	*pPosY += fracToInt(pObj->yPos);
}
コード例 #3
0
ファイル: background.cpp プロジェクト: Templier/scummvm-test
void PlayfieldGetPos(int which, int *pXpos, int *pYpos) {
	PLAYFIELD *pPlayfield;	// pointer to relavent playfield

	// make sure there is a background
	assert(pCurBgnd != NULL);

	// make sure the playfield number is in range
	assert(which >= 0 && which < pCurBgnd->numPlayfields);

	// get playfield pointer
	pPlayfield = pCurBgnd->fieldArray + which;

	// get current integer position
	*pXpos = fracToInt(pPlayfield->fieldX);
	*pYpos = fracToInt(pPlayfield->fieldY);
}
コード例 #4
0
ファイル: opengl-graphics.cpp プロジェクト: 86400/scummvm
void OpenGLGraphicsManager::setActualScreenSize(uint width, uint height) {
	_outputScreenWidth = width;
	_outputScreenHeight = height;

	// Setup backbuffer size.
	_backBuffer.setDimensions(width, height);

	uint overlayWidth = width;
	uint overlayHeight = height;

	// WORKAROUND: We can only support surfaces up to the maximum supported
	// texture size. Thus, in case we encounter a physical size bigger than
	// this maximum texture size we will simply use an overlay as big as
	// possible and then scale it to the physical display size. This sounds
	// bad but actually all recent chips should support full HD resolution
	// anyway. Thus, it should not be a real issue for modern hardware.
	if (   overlayWidth  > (uint)g_context.maxTextureSize
	    || overlayHeight > (uint)g_context.maxTextureSize) {
		const frac_t outputAspect = intToFrac(_outputScreenWidth) / _outputScreenHeight;

		if (outputAspect > (frac_t)FRAC_ONE) {
			overlayWidth  = g_context.maxTextureSize;
			overlayHeight = intToFrac(overlayWidth) / outputAspect;
		} else {
			overlayHeight = g_context.maxTextureSize;
			overlayWidth  = fracToInt(overlayHeight * outputAspect);
		}
	}

	// HACK: We limit the minimal overlay size to 256x200, which is the
	// minimum of the dimensions of the two resolutions 256x240 (NES) and
	// 320x200 (many DOS games use this). This hopefully assure that our
	// GUI has working layouts.
	overlayWidth = MAX<uint>(overlayWidth, 256);
	overlayHeight = MAX<uint>(overlayHeight, 200);

	if (!_overlay || _overlay->getFormat() != _defaultFormatAlpha) {
		delete _overlay;
		_overlay = nullptr;

		_overlay = createSurface(_defaultFormatAlpha);
		assert(_overlay);
		// We always filter the overlay with GL_LINEAR. This assures it's
		// readable in case it needs to be scaled and does not affect it
		// otherwise.
		_overlay->enableLinearFiltering(true);
	}
	_overlay->allocate(overlayWidth, overlayHeight);
	_overlay->fill(0);

	// Re-setup the scaling for the screen and cursor
	recalculateDisplayArea();
	recalculateCursorScaling();

	// Something changed, so update the screen change ID.
	++_screenChangeID;
}
コード例 #5
0
ファイル: anim.cpp プロジェクト: AdamRi/scummvm-pink
/**
 * Init a ANIM structure for single stepping through a animation script.
 * @param pAnim				Animation data structure
 * @param pAniObj			Object to animate
 * @param hNewScript		Script of multipart frames
 * @param aniSpeed			Sets speed of animation in frames
 */
void InitStepAnimScript(ANIM *pAnim, OBJECT *pAniObj, SCNHANDLE hNewScript, int aniSpeed) {
	OBJECT *pObj;			// multi-object list iterator

	debugC(DEBUG_DETAILED, kTinselDebugAnimations,
		"InitStepAnimScript Object=(%d,%d,%xh) script=%xh aniSpeed=%d rec=%ph",
		!pAniObj ? 0 : fracToInt(pAniObj->xPos),
		!pAniObj ? 0 : fracToInt(pAniObj->yPos),
		!pAniObj ? 0 : pAniObj->hImg, hNewScript, aniSpeed, (byte *)pAnim);

	pAnim->aniDelta = 1;		// will animate on next call to NextAnimRate
	pAnim->pObject = pAniObj;	// set object to animate
	pAnim->hScript = hNewScript;	// set animation script
	pAnim->scriptIndex = 0;		// start of script
	pAnim->aniRate = aniSpeed;	// set speed of animation

	// reset flip flags for the object - let the script do the flipping
	for (pObj = pAniObj; pObj != NULL; pObj = pObj->pSlave) {
		AnimateObjectFlags(pObj, pObj->flags & ~(DMA_FLIPH | DMA_FLIPV),
			pObj->hImg);
	}
}
コード例 #6
0
ファイル: multiobj.cpp プロジェクト: havlenapetr/Scummvm
int MultiLeftmost(OBJECT *pMulti) {
	int left;

	// validate object pointer
	assert(pMulti >= objectList && pMulti <= objectList + NUM_OBJECTS - 1);

	// init leftmost point to first object
	left = fracToInt(pMulti->xPos);

	// for all the objects in this multi
	while ((pMulti = pMulti->pSlave) != NULL) {
		if (pMulti->hImg != 0) {
			// non null object part

			if (fracToInt(pMulti->xPos) < left)
				// this object is further left
				left = fracToInt(pMulti->xPos);
		}
	}

	// return left-most point
	return left;
}
コード例 #7
0
ファイル: multiobj.cpp プロジェクト: havlenapetr/Scummvm
int MultiRightmost(OBJECT *pMulti) {
	int right;

	// validate object pointer
	assert(pMulti >= objectList && pMulti <= objectList + NUM_OBJECTS - 1);

	// init right-most point to first object
	right = fracToInt(pMulti->xPos) + pMulti->width;

	// for all the objects in this multi
	while ((pMulti = pMulti->pSlave) != NULL) {
		if (pMulti->hImg != 0) {
			// non null object part

			if (fracToInt(pMulti->xPos) + pMulti->width > right)
				// this object is further right
				right = fracToInt(pMulti->xPos) + pMulti->width;
		}
	}

	// return right-most point
	return right - 1;
}
コード例 #8
0
ファイル: multiobj.cpp プロジェクト: AdamRi/scummvm-pink
int MultiHighest(OBJECT *pMulti) {
	int highest;

	// validate object pointer
	assert(isValidObject(pMulti));

	// init highest point to first object
	highest = fracToInt(pMulti->yPos);

	// for all the objects in this multi
	while ((pMulti = pMulti->pSlave) != NULL) {
		if (pMulti->hImg != 0) {
			// non null object part

			if (fracToInt(pMulti->yPos) < highest)
				// this object is higher
				highest = fracToInt(pMulti->yPos);
		}
	}

	// return highest point
	return highest;
}
コード例 #9
0
ファイル: multiobj.cpp プロジェクト: havlenapetr/Scummvm
int MultiLowest(OBJECT *pMulti) {
	int lowest;

	// validate object pointer
	assert(pMulti >= objectList && pMulti <= objectList + NUM_OBJECTS - 1);

	// init lowest point to first object
	lowest = fracToInt(pMulti->yPos) + pMulti->height;

	// for all the objects in this multi
	while ((pMulti = pMulti->pSlave) != NULL) {
		if (pMulti->hImg != 0) {
			// non null object part

			if (fracToInt(pMulti->yPos) + pMulti->height > lowest)
				// this object is lower
				lowest = fracToInt(pMulti->yPos) + pMulti->height;
		}
	}

	// return lowest point
	return lowest - 1;
}
コード例 #10
0
ファイル: background.cpp プロジェクト: Templier/scummvm-test
int PlayfieldGetCentreX(int which) {
	PLAYFIELD *pPlayfield; // pointer to relavent playfield

	// make sure there is a background
	assert(pCurBgnd != NULL);

	// make sure the playfield number is in range
	assert(which >= 0 && which < pCurBgnd->numPlayfields);

	// get playfield pointer
	pPlayfield = pCurBgnd->fieldArray + which;

	// get current integer position
	return fracToInt(pPlayfield->fieldX) + SCREEN_WIDTH/2;
}
コード例 #11
0
ファイル: paula.cpp プロジェクト: segrax/openfodder
inline int mixBuffer(int16 *&buf, const int8 *data, Paula::Offset &offset, frac_t rate, int neededSamples, size_t bufSize, size_t volume, uint8 panning) {
	int samples;
	for (samples = 0; samples < neededSamples && offset.int_off < bufSize; ++samples) {
		const int32 tmp = (int32) (((int32) data[offset.int_off]) * volume);
		if (stereo) {
			*buf++ += (tmp * (255 - panning)) >> 7;
			*buf++ += (tmp * (panning)) >> 7;
		} else
			*buf++ += tmp;

		// Step to next source sample
		offset.rem_off += rate;
		if (offset.rem_off >= (frac_t)FRAC_ONE) {
			offset.int_off += fracToInt(offset.rem_off);
			offset.rem_off &= FRAC_LO_MASK;
		}
	}
コード例 #12
0
ファイル: list.cpp プロジェクト: Templier/residual
void ListWidget::reflowLayout() {
	Widget::reflowLayout();

	_leftPadding = g_gui.xmlEval()->getVar("Globals.ListWidget.Padding.Left", 0);
	_rightPadding = g_gui.xmlEval()->getVar("Globals.ListWidget.Padding.Right", 0);
	_topPadding = g_gui.xmlEval()->getVar("Globals.ListWidget.Padding.Top", 0);
	_bottomPadding = g_gui.xmlEval()->getVar("Globals.ListWidget.Padding.Bottom", 0);
	_hlLeftPadding = g_gui.xmlEval()->getVar("Globals.ListWidget.hlLeftPadding", 0);
	_hlRightPadding = g_gui.xmlEval()->getVar("Globals.ListWidget.hlRightPadding", 0);

	_scrollBarWidth = g_gui.xmlEval()->getVar("Globals.Scrollbar.Width", 0);

	// HACK: Once we take padding into account, there are times where
	// integer rounding leaves a big chunk of white space in the bottom
	// of the list.
	// We do a rough rounding on the decimal places of Entries Per Page,
	// to add another entry even if it goes a tad over the padding.
	frac_t entriesPerPage = intToFrac(_h - _topPadding - _bottomPadding) / kLineHeight;

	// Our threshold before we add another entry is 0.9375 (0xF000 with FRAC_BITS being 16).
	const frac_t threshold = intToFrac(15) / 16;

	if ((frac_t)(entriesPerPage & FRAC_LO_MASK) >= threshold)
		entriesPerPage += FRAC_ONE;

	_entriesPerPage = fracToInt(entriesPerPage);
	assert(_entriesPerPage > 0);

	delete[] _textWidth;
	_textWidth = new int[_entriesPerPage];

	for (int i = 0; i < _entriesPerPage; i++)
		_textWidth[i] = 0;

	if (_scrollBar) {
		_scrollBar->resize(_w - _scrollBarWidth + 1, 0, _scrollBarWidth, _h);
		scrollBarRecalc();
		scrollToCurrent();
	}
}
コード例 #13
0
ファイル: opengl-graphics.cpp プロジェクト: SinSiXX/scummvm
void OpenGLGraphicsManager::recalculateDisplayArea() {
	if (!_gameScreen || _outputScreenHeight == 0) {
		return;
	}

	const frac_t outputAspect = intToFrac(_outputScreenWidth) / _outputScreenHeight;
	const frac_t desiredAspect = getDesiredGameScreenAspect();

	_displayWidth = _outputScreenWidth;
	_displayHeight = _outputScreenHeight;

	// Adjust one dimension for mantaining the aspect ratio.
	if (outputAspect < desiredAspect) {
		_displayHeight = intToFrac(_displayWidth) / desiredAspect;
	} else if (outputAspect > desiredAspect) {
		_displayWidth = fracToInt(_displayHeight * desiredAspect);
	}

	// We center the screen in the middle for now.
	_displayX = (_outputScreenWidth  - _displayWidth ) / 2; 
	_displayY = (_outputScreenHeight - _displayHeight) / 2; 
}
コード例 #14
0
ファイル: opengl-graphics.cpp プロジェクト: 86400/scummvm
bool OpenGLGraphicsManager::getGLPixelFormat(const Graphics::PixelFormat &pixelFormat, GLenum &glIntFormat, GLenum &glFormat, GLenum &glType) const {
#ifdef SCUMM_LITTLE_ENDIAN
	if (pixelFormat == Graphics::PixelFormat(4, 8, 8, 8, 8, 0, 8, 16, 24)) { // ABGR8888
#else
	if (pixelFormat == Graphics::PixelFormat(4, 8, 8, 8, 8, 24, 16, 8, 0)) { // RGBA8888
#endif
		glIntFormat = GL_RGBA;
		glFormat = GL_RGBA;
		glType = GL_UNSIGNED_BYTE;
		return true;
	} else if (pixelFormat == Graphics::PixelFormat(2, 5, 6, 5, 0, 11, 5, 0, 0)) { // RGB565
		glIntFormat = GL_RGB;
		glFormat = GL_RGB;
		glType = GL_UNSIGNED_SHORT_5_6_5;
		return true;
	} else if (pixelFormat == Graphics::PixelFormat(2, 5, 5, 5, 1, 11, 6, 1, 0)) { // RGBA5551
		glIntFormat = GL_RGBA;
		glFormat = GL_RGBA;
		glType = GL_UNSIGNED_SHORT_5_5_5_1;
		return true;
	} else if (pixelFormat == Graphics::PixelFormat(2, 4, 4, 4, 4, 12, 8, 4, 0)) { // RGBA4444
		glIntFormat = GL_RGBA;
		glFormat = GL_RGBA;
		glType = GL_UNSIGNED_SHORT_4_4_4_4;
		return true;
#if !USE_FORCED_GLES && !USE_FORCED_GLES2
	// The formats below are not supported by every GLES implementation.
	// Thus, we do not mark them as supported when a GLES context is setup.
	} else if (isGLESContext()) {
		return false;
#ifdef SCUMM_LITTLE_ENDIAN
	} else if (pixelFormat == Graphics::PixelFormat(4, 8, 8, 8, 8, 24, 16, 8, 0)) { // RGBA8888
		glIntFormat = GL_RGBA;
		glFormat = GL_RGBA;
		glType = GL_UNSIGNED_INT_8_8_8_8;
		return true;
#endif
	} else if (pixelFormat == Graphics::PixelFormat(2, 5, 5, 5, 0, 10, 5, 0, 0)) { // RGB555
		glIntFormat = GL_RGB;
		glFormat = GL_BGRA;
		glType = GL_UNSIGNED_SHORT_1_5_5_5_REV;
		return true;
	} else if (pixelFormat == Graphics::PixelFormat(2, 4, 4, 4, 4, 8, 4, 0, 12)) { // ARGB4444
		glIntFormat = GL_RGBA;
		glFormat = GL_BGRA;
		glType = GL_UNSIGNED_SHORT_4_4_4_4_REV;
		return true;
#ifdef SCUMM_BIG_ENDIAN
	} else if (pixelFormat == Graphics::PixelFormat(4, 8, 8, 8, 8, 0, 8, 16, 24)) { // ABGR8888
		glIntFormat = GL_RGBA;
		glFormat = GL_RGBA;
		glType = GL_UNSIGNED_INT_8_8_8_8_REV;
		return true;
#endif
	} else if (pixelFormat == Graphics::PixelFormat(4, 8, 8, 8, 8, 8, 16, 24, 0)) { // BGRA8888
		glIntFormat = GL_RGBA;
		glFormat = GL_BGRA;
		glType = GL_UNSIGNED_INT_8_8_8_8;
		return true;
	} else if (pixelFormat == Graphics::PixelFormat(2, 5, 6, 5, 0, 0, 5, 11, 0)) { // BGR565
		glIntFormat = GL_RGB;
		glFormat = GL_RGB;
		glType = GL_UNSIGNED_SHORT_5_6_5_REV;
		return true;
	} else if (pixelFormat == Graphics::PixelFormat(2, 5, 5, 5, 1, 1, 6, 11, 0)) { // BGRA5551
		glIntFormat = GL_RGBA;
		glFormat = GL_BGRA;
		glType = GL_UNSIGNED_SHORT_5_5_5_1;
		return true;
	} else if (pixelFormat == Graphics::PixelFormat(2, 4, 4, 4, 4, 0, 4, 8, 12)) { // ABGR4444
		glIntFormat = GL_RGBA;
		glFormat = GL_RGBA;
		glType = GL_UNSIGNED_SHORT_4_4_4_4_REV;
		return true;
	} else if (pixelFormat == Graphics::PixelFormat(2, 4, 4, 4, 4, 4, 8, 12, 0)) { // BGRA4444
		glIntFormat = GL_RGBA;
		glFormat = GL_BGRA;
		glType = GL_UNSIGNED_SHORT_4_4_4_4;
		return true;
#endif // !USE_FORCED_GLES && !USE_FORCED_GLES2
	} else {
		return false;
	}
}

frac_t OpenGLGraphicsManager::getDesiredGameScreenAspect() const {
	const uint width  = _currentState.gameWidth;
	const uint height = _currentState.gameHeight;

	if (_currentState.aspectRatioCorrection) {
		// In case we enable aspect ratio correction we force a 4/3 ratio.
		// But just for 320x200 and 640x400 games, since other games do not need
		// this.
		if ((width == 320 && height == 200) || (width == 640 && height == 400)) {
			return intToFrac(4) / 3;
		}
	}

	return intToFrac(width) / height;
}

void OpenGLGraphicsManager::recalculateDisplayArea() {
	if (!_gameScreen || _outputScreenHeight == 0) {
		return;
	}

	const frac_t outputAspect = intToFrac(_outputScreenWidth) / _outputScreenHeight;
	const frac_t desiredAspect = getDesiredGameScreenAspect();

	_displayWidth = _outputScreenWidth;
	_displayHeight = _outputScreenHeight;

	// Adjust one dimension for mantaining the aspect ratio.
	if (outputAspect < desiredAspect) {
		_displayHeight = intToFrac(_displayWidth) / desiredAspect;
	} else if (outputAspect > desiredAspect) {
		_displayWidth = fracToInt(_displayHeight * desiredAspect);
	}

	// We center the screen in the middle for now.
	_displayX = (_outputScreenWidth  - _displayWidth ) / 2;
	_displayY = (_outputScreenHeight - _displayHeight) / 2;

	// Setup drawing limitation for game graphics.
	// This invovles some trickery because OpenGL's viewport coordinate system
	// is upside down compared to ours.
	_backBuffer.setScissorBox(_displayX,
	                          _outputScreenHeight - _displayHeight - _displayY,
	                          _displayWidth,
	                          _displayHeight);
	// Clear the whole screen for the first three frames to remove leftovers.
	_scissorOverride = 3;

	// Update the cursor position to adjust for new display area.
	setMousePosition(_cursorX, _cursorY);

	// Force a redraw to assure screen is properly redrawn.
	_forceRedraw = true;
}

void OpenGLGraphicsManager::updateCursorPalette() {
	if (!_cursor || !_cursor->hasPalette()) {
		return;
	}

	if (_cursorPaletteEnabled) {
		_cursor->setPalette(0, 256, _cursorPalette);
	} else {
		_cursor->setPalette(0, 256, _gamePalette);
	}

	_cursor->setColorKey(_cursorKeyColor);
}

void OpenGLGraphicsManager::recalculateCursorScaling() {
	if (!_cursor || !_gameScreen) {
		return;
	}

	// By default we use the unscaled versions.
	_cursorHotspotXScaled = _cursorHotspotX;
	_cursorHotspotYScaled = _cursorHotspotY;
	_cursorWidthScaled = _cursor->getWidth();
	_cursorHeightScaled = _cursor->getHeight();

	// In case scaling is actually enabled we will scale the cursor according
	// to the game screen.
	if (!_cursorDontScale) {
		const frac_t screenScaleFactorX = intToFrac(_displayWidth)  / _gameScreen->getWidth();
		const frac_t screenScaleFactorY = intToFrac(_displayHeight) / _gameScreen->getHeight();

		_cursorHotspotXScaled = fracToInt(_cursorHotspotXScaled * screenScaleFactorX);
		_cursorWidthScaled    = fracToInt(_cursorWidthScaled    * screenScaleFactorX);

		_cursorHotspotYScaled = fracToInt(_cursorHotspotYScaled * screenScaleFactorY);
		_cursorHeightScaled   = fracToInt(_cursorHeightScaled   * screenScaleFactorY);
	}
}

#ifdef USE_OSD
const Graphics::Font *OpenGLGraphicsManager::getFontOSD() {
	return FontMan.getFontByUsage(Graphics::FontManager::kLocalizedFont);
}
#endif

void OpenGLGraphicsManager::saveScreenshot(const Common::String &filename) const {
	const uint width  = _outputScreenWidth;
	const uint height = _outputScreenHeight;

	// A line of a BMP image must have a size divisible by 4.
	// We calculate the padding bytes needed here.
	// Since we use a 3 byte per pixel mode, we can use width % 4 here, since
	// it is equal to 4 - (width * 3) % 4. (4 - (width * Bpp) % 4, is the
	// usual way of computing the padding bytes required).
	const uint linePaddingSize = width % 4;
	const uint lineSize        = width * 3 + linePaddingSize;

	// Allocate memory for screenshot
	uint8 *pixels = new uint8[lineSize * height];

	// Get pixel data from OpenGL buffer
	GL_CALL(glReadPixels(0, 0, width, height, GL_RGB, GL_UNSIGNED_BYTE, pixels));

	// BMP stores as BGR. Since we can't assume that GL_BGR is supported we
	// will swap the components from the RGB we read to BGR on our own.
	for (uint y = height; y-- > 0;) {
		uint8 *line = pixels + y * lineSize;

		for (uint x = width; x > 0; --x, line += 3) {
			SWAP(line[0], line[2]);
		}
	}

	// Open file
	Common::DumpFile out;
	out.open(filename);

	// Write BMP header
	out.writeByte('B');
	out.writeByte('M');
	out.writeUint32LE(height * lineSize + 54);
	out.writeUint32LE(0);
	out.writeUint32LE(54);
	out.writeUint32LE(40);
	out.writeUint32LE(width);
	out.writeUint32LE(height);
	out.writeUint16LE(1);
	out.writeUint16LE(24);
	out.writeUint32LE(0);
	out.writeUint32LE(0);
	out.writeUint32LE(0);
	out.writeUint32LE(0);
	out.writeUint32LE(0);
	out.writeUint32LE(0);

	// Write pixel data to BMP
	out.write(pixels, lineSize * height);

	// Free allocated memory
	delete[] pixels;
}

} // End of namespace OpenGL
コード例 #15
0
ファイル: cliprect.cpp プロジェクト: AdamRi/scummvm-pink
/**
 * Redraws all objects within this clipping rectangle.
 * @param pObjList		Object list to draw
 * @param pWin			Window top left position
 * @param pClip			Pointer to clip rectangle
 */
void UpdateClipRect(OBJECT **pObjList, Common::Point *pWin, Common::Rect *pClip) {
	int x, y, right, bottom;	// object corners
	int hclip, vclip;			// total size of object clipping
	DRAWOBJECT currentObj;		// filled in to draw the current object in list
	OBJECT *pObj;				// object list iterator

	// Initialize the fields of the drawing object to empty
	memset(&currentObj, 0, sizeof(DRAWOBJECT));

	for (pObj = *pObjList; pObj != NULL; pObj = pObj->pNext) {
		if (pObj->flags & DMA_ABS) {
			// object position is absolute
			x = fracToInt(pObj->xPos);
			y = fracToInt(pObj->yPos);
		} else {
			// object position is relative to window
			x = fracToInt(pObj->xPos) - pWin->x;
			y = fracToInt(pObj->yPos) - pWin->y;
		}

		// calc object right
		right = x + pObj->width;
		if (right < 0)
			// totally clipped if negative
			continue;

		// calc object bottom
		bottom = y + pObj->height;
		if (bottom < 0)
			// totally clipped if negative
			continue;

		// bottom clip = low right y - clip low right y
		currentObj.botClip = bottom - pClip->bottom;
		if (currentObj.botClip < 0) {
			// negative - object is not clipped
			currentObj.botClip = 0;
		}

		// right clip = low right x - clip low right x
		currentObj.rightClip = right - pClip->right;
		if (currentObj.rightClip < 0) {
			// negative - object is not clipped
			currentObj.rightClip = 0;
		}

		// top clip = clip top left y - top left y
		currentObj.topClip = pClip->top - y;
		if (currentObj.topClip < 0) {
			// negative - object is not clipped
			currentObj.topClip = 0;
		} else {	// clipped - adjust start position to top of clip rect
			y = pClip->top;
		}

		// left clip = clip top left x - top left x
		currentObj.leftClip = pClip->left - x;
		if (currentObj.leftClip < 0) {
			// negative - object is not clipped
			currentObj.leftClip = 0;
		} else {
			// NOTE: This else statement is disabled in tinsel v1
			// clipped - adjust start position to left of clip rect
			x = pClip->left;
		}

		// calc object total horizontal clipping
		hclip = currentObj.leftClip + currentObj.rightClip;

		// calc object total vertical clipping
		vclip = currentObj.topClip + currentObj.botClip;

		if (hclip + vclip != 0) {
			// object is clipped in some way

			if (pObj->width <= hclip)
				// object totally clipped horizontally - ignore
				continue;

			if (pObj->height <= vclip)
				// object totally clipped vertically - ignore
				continue;

			// set clip bit in objects flags
			currentObj.flags = pObj->flags | DMA_CLIP;
		} else {	// object is not clipped - copy flags
			currentObj.flags = pObj->flags;
		}

		// copy objects properties to local object
		currentObj.width    = pObj->width;
		currentObj.height   = pObj->height;
		currentObj.xPos     = (short)x;
		currentObj.yPos     = (short)y;
		currentObj.pPal     = pObj->pPal;
		currentObj.constant = pObj->constant;
		currentObj.hBits    = pObj->hBits;

		// draw the object
		DrawObject(&currentObj);
	}
}
コード例 #16
0
ファイル: sound_2gs.cpp プロジェクト: bluegr/scummvm
/**
 * Fill output buffer by advancing the generators for a 1/60th of a second.
 * @return Number of generated samples
 */
uint SoundGen2GS::generateOutput() {
	memset(_out, 0, _outSize * 2 * 2);

	if (!_playing || _playingSound == -1)
		return _outSize * 2;

	int16 *p = _out;
	int n = _outSize;
	while (n--) {
		int outl = 0;
		int outr = 0;
		for (int k = 0; k < MAX_GENERATORS; k++) {
			IIgsGenerator *g = &_generators[k];
			if (!g->ins)
				continue;
			const IIgsInstrumentHeader *i = g->ins;

			// Advance envelope
			int vol = fracToInt(g->a);
			if (g->a <= i->env[g->seg].bp) {
				g->a += i->env[g->seg].inc * ENVELOPE_COEF;
				if (g->a > i->env[g->seg].bp) {
					g->a = i->env[g->seg].bp;
					g->seg++;
				}
			} else {
				g->a -= i->env[g->seg].inc * ENVELOPE_COEF;
				if (g->a < i->env[g->seg].bp) {
					g->a = i->env[g->seg].bp;
					g->seg++;
				}
			}

			// TODO: Advance vibrato here. The Apple IIGS uses a LFO with
			// triangle wave to modulate the frequency of both oscillators.
			// In Apple IIGS the vibrato and the envelope are updated at the
			// same time, so the vibrato speed depends on ENVELOPE_COEF.

			// Advance oscillators
			int s0 = 0;
			int s1 = 0;
			if (!g->osc[0].halt) {
				s0 = g->osc[0].base[fracToInt(g->osc[0].p)];
				g->osc[0].p += g->osc[0].pd;
				if ((uint)fracToInt(g->osc[0].p) >= g->osc[0].size) {
					g->osc[0].p -= intToFrac(g->osc[0].size);
					if (!g->osc[0].loop)
						g->osc[0].halt = 1;
					if (g->osc[0].swap) {
						g->osc[0].halt = 1;
						g->osc[1].halt = 0;
					}
				}
			}
			if (!g->osc[1].halt) {
				s1 = g->osc[1].base[fracToInt(g->osc[1].p)];
				g->osc[1].p += g->osc[1].pd;
				if ((uint)fracToInt(g->osc[1].p) >= g->osc[1].size) {
					g->osc[1].p -= intToFrac(g->osc[1].size);
					if (!g->osc[1].loop)
						g->osc[1].halt = 1;
					if (g->osc[1].swap) {
						g->osc[0].halt = 0;
						g->osc[1].halt = 1;
					}
				}
			}

			// Take envelope and MIDI volume information into account.
			// Also amplify.
			s0 *= vol * g->vel / 127 * 80 / 256;
			s1 *= vol * g->vel / 127 * 80 / 256;

			// Select output channel.
			if (g->osc[0].chn)
				outl += s0;
			else
				outr += s0;

			if (g->osc[1].chn)
				outl += s1;
			else
				outr += s1;
		}

		if (outl > 32768)
			outl = 32768;
		if (outl < -32767)
			outl = -32767;
		if (outr > 32768)
			outr = 32768;
		if (outr < -32767)
			outr = -32767;

		*p++ = outl;
		*p++ = outr;
	}

	return _outSize * 2;
}
コード例 #17
0
void Sprite::blit(const Sprite &from, const Common::Rect &area, int32 x, int32 y, bool transp) {
	// Sanity checks
	assert((x >= 0) && (y >= 0) && (x <= 0x7FFF) && (y <= 0x7FFF));

	if (!exists() || !from.exists())
		return;

	Common::Rect toArea = getArea(true);

	toArea.left = x;
	toArea.top  = y;
	if (toArea.isEmpty())
		return;

	Common::Rect fromArea = from.getArea();

	fromArea.clip(area);
	fromArea.setWidth (MIN(fromArea.width() , toArea.width()));
	fromArea.setHeight(MIN(fromArea.height(), toArea.height()));
	if (fromArea.isEmpty() || !fromArea.isValidRect())
		return;

	int32 w = fromArea.width();
	int32 h = fromArea.height();

	const int32 fromTop   = fracToInt(fromArea.top  * from._scaleInverse);
	const int32 fromLeft  = fracToInt(fromArea.left * from._scaleInverse);

	const byte *src = (const byte *) from._surfaceTrueColor.getBasePtr(fromLeft, fromTop);
	      byte *dst = (      byte *)      _surfaceTrueColor.getBasePtr(x, y);

	const uint8 *srcT = from._transparencyMap + fromTop * from._surfaceTrueColor.w + fromLeft;
	      uint8 *dstT =      _transparencyMap +       y *      _surfaceTrueColor.w + x;

	frac_t posW = 0, posH = 0;
	while (h-- > 0) {
		posW = 0;

		const byte *srcRow = src;
		      byte *dstRow = dst;

		const uint8 *srcRowT = srcT;
		      uint8 *dstRowT = dstT;

		for (int32 j = 0; j < w; j++, dstRow += _surfaceTrueColor.bytesPerPixel, dstRowT++) {
			if (!transp || (*srcRowT == 0)) {
				// Ignore transparency or source is solid => copy
				memcpy(dstRow, srcRow, _surfaceTrueColor.bytesPerPixel);
				*dstRowT = *srcRowT;
			} else if (*srcRowT == 2) {
				// Half-transparent
				if (*dstRowT == 1)
					// But destination is transparent => propagate
					memcpy(dstRow, srcRow, _surfaceTrueColor.bytesPerPixel);
				else
					// Destination is solid => mix
					ImgConv.mixTrueColor(dstRow, srcRow);

				*dstRowT = *srcRowT;
			}

			// Advance source data
			posW += from._scaleInverse;
			while (posW >= ((frac_t) FRAC_ONE)) {
				srcRow += from._surfaceTrueColor.bytesPerPixel;
				srcRowT++;
				posW -= FRAC_ONE;
			}

		}

		dst  += _surfaceTrueColor.pitch;
		dstT += _surfaceTrueColor.w;

		// Advance source data
		posH += from._scaleInverse;
		while (posH >= ((frac_t) FRAC_ONE)) {
			src  += from._surfaceTrueColor.pitch;
			srcT += from._surfaceTrueColor.w;
			posH -= FRAC_ONE;
		}

	}
}
コード例 #18
0
ファイル: background.cpp プロジェクト: Templier/scummvm-test
void DrawBackgnd() {
	int i;			// playfield counter
	PLAYFIELD *pPlay;	// playfield pointer
	int prevX, prevY;	// save interger part of position
	Common::Point ptWin;	// window top left

	if (pCurBgnd == NULL)
		return;		// no current background

	// scroll each background playfield
	for (i = 0; i < pCurBgnd->numPlayfields; i++) {
		// get pointer to correct playfield
		pPlay = pCurBgnd->fieldArray + i;

		// save integer part of position
		prevX = fracToInt(pPlay->fieldX);
		prevY = fracToInt(pPlay->fieldY);

		// update scrolling
		pPlay->fieldX += pPlay->fieldXvel;
		pPlay->fieldY += pPlay->fieldYvel;

		// convert fixed point window pos to a int
		ptWin.x = fracToInt(pPlay->fieldX);
		ptWin.y = fracToInt(pPlay->fieldY);

		// set the moved flag if the playfield has moved
		if (prevX != ptWin.x || prevY != ptWin.y)
			pPlay->bMoved = true;

		// sort the display list for this background - just in case somebody has changed object Z positions
		SortObjectList((OBJECT *)&pPlay->pDispList);

		// generate clipping rects for all objects that have moved etc.
		FindMovingObjects((OBJECT *)&pPlay->pDispList, &ptWin,
			&pPlay->rcClip,	false, pPlay->bMoved);

		// clear playfield moved flag
		pPlay->bMoved = false;
	}

	// merge the clipping rectangles
	MergeClipRect();

	// redraw all playfields within the clipping rectangles
	const RectList &clipRects = GetClipRects();
	for (RectList::const_iterator r = clipRects.begin(); r != clipRects.end(); ++r) {
		// clear the clip rectangle on the virtual screen
		// for each background playfield
		for (i = 0; i < pCurBgnd->numPlayfields; i++) {
			Common::Rect rcPlayClip;	// clip rect for this playfield

			// get pointer to correct playfield
			pPlay = pCurBgnd->fieldArray + i;

			// convert fixed point window pos to a int
			ptWin.x = fracToInt(pPlay->fieldX);
			ptWin.y = fracToInt(pPlay->fieldY);

			if (IntersectRectangle(rcPlayClip, pPlay->rcClip, *r))
				// redraw all objects within this clipping rect
				UpdateClipRect((OBJECT *)&pPlay->pDispList,
						&ptWin,	&rcPlayClip);
		}
	}

	// transfer any new palettes to the video DAC
	PalettesToVideoDAC();

	// update the screen within the clipping rectangles
	for (RectList::const_iterator r = clipRects.begin(); r != clipRects.end(); ++r) {
		UpdateScreenRect(*r);
	}

	g_system->updateScreen();

	// delete all the clipping rectangles
	ResetClipRect();
}
コード例 #19
0
int32 Sprite::getDefaultX(bool unscaled) const {
	if (unscaled || (_scale == FRAC_ONE))
		return _defaultX;

	return fracToInt(_defaultX * _scale);
}
コード例 #20
0
int32 Sprite::getFeetY(bool unscaled) const {
	if (unscaled || (_scale == FRAC_ONE))
		return _feetY;

	return fracToInt(_feetY * _scale);
}
コード例 #21
0
int32 Sprite::getHeight(bool unscaled) const {
	if (unscaled || (_scale == FRAC_ONE))
		return _surfacePaletted.h;

	return fracToInt(_surfacePaletted.h * _scale);
}
コード例 #22
0
int32 Sprite::getWidth(bool unscaled) const {
	if (unscaled || (_scale == FRAC_ONE))
		return _surfacePaletted.w;

	return fracToInt(_surfacePaletted.w * _scale);
}
コード例 #23
0
bool OpenGLGraphicsManager::getGLPixelFormat(const Graphics::PixelFormat &pixelFormat, GLenum &glIntFormat, GLenum &glFormat, GLenum &glType) const {
#ifdef SCUMM_LITTLE_ENDIAN
	if (pixelFormat == Graphics::PixelFormat(4, 8, 8, 8, 8, 0, 8, 16, 24)) { // ABGR8888
#else
	if (pixelFormat == Graphics::PixelFormat(4, 8, 8, 8, 8, 24, 16, 8, 0)) { // RGBA8888
#endif
		glIntFormat = GL_RGBA;
		glFormat = GL_RGBA;
		glType = GL_UNSIGNED_BYTE;
		return true;
	} else if (pixelFormat == Graphics::PixelFormat(2, 5, 6, 5, 0, 11, 5, 0, 0)) { // RGB565
		glIntFormat = GL_RGB;
		glFormat = GL_RGB;
		glType = GL_UNSIGNED_SHORT_5_6_5;
		return true;
	} else if (pixelFormat == Graphics::PixelFormat(2, 5, 5, 5, 1, 11, 6, 1, 0)) { // RGBA5551
		glIntFormat = GL_RGBA;
		glFormat = GL_RGBA;
		glType = GL_UNSIGNED_SHORT_5_5_5_1;
		return true;
	} else if (pixelFormat == Graphics::PixelFormat(2, 4, 4, 4, 4, 12, 8, 4, 0)) { // RGBA4444
		glIntFormat = GL_RGBA;
		glFormat = GL_RGBA;
		glType = GL_UNSIGNED_SHORT_4_4_4_4;
		return true;
#ifndef USE_GLES
#ifdef SCUMM_LITTLE_ENDIAN
	} else if (pixelFormat == Graphics::PixelFormat(4, 8, 8, 8, 8, 24, 16, 8, 0)) { // RGBA8888
		glIntFormat = GL_RGBA;
		glFormat = GL_RGBA;
		glType = GL_UNSIGNED_INT_8_8_8_8;
		return true;
#endif
	} else if (pixelFormat == Graphics::PixelFormat(2, 5, 5, 5, 0, 10, 5, 0, 0)) { // RGB555
		// GL_BGRA does not exist in every GLES implementation so should not be configured if
		// USE_GLES is set.
		glIntFormat = GL_RGB;
		glFormat = GL_BGRA;
		glType = GL_UNSIGNED_SHORT_1_5_5_5_REV;
		return true;
	} else if (pixelFormat == Graphics::PixelFormat(4, 8, 8, 8, 8, 16, 8, 0, 24)) { // ARGB8888
		glIntFormat = GL_RGBA;
		glFormat = GL_BGRA;
		glType = GL_UNSIGNED_INT_8_8_8_8_REV;
		return true;
	} else if (pixelFormat == Graphics::PixelFormat(2, 4, 4, 4, 4, 8, 4, 0, 12)) { // ARGB4444
		glIntFormat = GL_RGBA;
		glFormat = GL_BGRA;
		glType = GL_UNSIGNED_SHORT_4_4_4_4_REV;
		return true;
#ifdef SCUMM_BIG_ENDIAN
	} else if (pixelFormat == Graphics::PixelFormat(4, 8, 8, 8, 8, 0, 8, 16, 24)) { // ABGR8888
		glIntFormat = GL_RGBA;
		glFormat = GL_RGBA;
		glType = GL_UNSIGNED_INT_8_8_8_8_REV;
		return true;
#endif
	} else if (pixelFormat == Graphics::PixelFormat(4, 8, 8, 8, 8, 8, 16, 24, 0)) { // BGRA8888
		glIntFormat = GL_RGBA;
		glFormat = GL_BGRA;
		glType = GL_UNSIGNED_INT_8_8_8_8;
		return true;
	} else if (pixelFormat == Graphics::PixelFormat(2, 5, 6, 5, 0, 0, 5, 11, 0)) { // BGR565
		glIntFormat = GL_RGB;
		glFormat = GL_BGR;
		glType = GL_UNSIGNED_SHORT_5_6_5;
		return true;
	} else if (pixelFormat == Graphics::PixelFormat(2, 5, 5, 5, 1, 1, 6, 11, 0)) { // BGRA5551
		glIntFormat = GL_RGBA;
		glFormat = GL_BGRA;
		glType = GL_UNSIGNED_SHORT_5_5_5_1;
		return true;
	} else if (pixelFormat == Graphics::PixelFormat(2, 4, 4, 4, 4, 0, 4, 8, 12)) { // ABGR4444
		glIntFormat = GL_RGBA;
		glFormat = GL_RGBA;
		glType = GL_UNSIGNED_SHORT_4_4_4_4_REV;
		return true;
	} else if (pixelFormat == Graphics::PixelFormat(2, 4, 4, 4, 4, 4, 8, 12, 0)) { // BGRA4444
		glIntFormat = GL_RGBA;
		glFormat = GL_BGRA;
		glType = GL_UNSIGNED_SHORT_4_4_4_4;
		return true;
#endif
	} else {
		return false;
	}
}

frac_t OpenGLGraphicsManager::getDesiredGameScreenAspect() const {
	const uint width  = _currentState.gameWidth;
	const uint height = _currentState.gameHeight;

	if (_currentState.aspectRatioCorrection) {
		// In case we enable aspect ratio correction we force a 4/3 ratio.
		// But just for 320x200 and 640x400 games, since other games do not need
		// this.
		if ((width == 320 && height == 200) || (width == 640 && height == 400)) {
			return intToFrac(4) / 3;
		}
	}

	return intToFrac(width) / height;
}

void OpenGLGraphicsManager::recalculateDisplayArea() {
	if (!_gameScreen || _outputScreenHeight == 0) {
		return;
	}

	const frac_t outputAspect = intToFrac(_outputScreenWidth) / _outputScreenHeight;
	const frac_t desiredAspect = getDesiredGameScreenAspect();

	_displayWidth = _outputScreenWidth;
	_displayHeight = _outputScreenHeight;

	// Adjust one dimension for mantaining the aspect ratio.
	if (outputAspect < desiredAspect) {
		_displayHeight = intToFrac(_displayWidth) / desiredAspect;
	} else if (outputAspect > desiredAspect) {
		_displayWidth = fracToInt(_displayHeight * desiredAspect);
	}

	// We center the screen in the middle for now.
	_displayX = (_outputScreenWidth  - _displayWidth ) / 2; 
	_displayY = (_outputScreenHeight - _displayHeight) / 2; 
}

void OpenGLGraphicsManager::updateCursorPalette() {
	if (!_cursor || !_cursor->hasPalette()) {
		return;
	}

	if (_cursorPaletteEnabled) {
		_cursor->setPalette(0, 256, _cursorPalette);
	} else {
		_cursor->setPalette(0, 256, _gamePalette);
	}

	// We remove all alpha bits from the palette entry of the color key.
	// This makes sure its properly handled as color key.
	const Graphics::PixelFormat &hardwareFormat = _cursor->getHardwareFormat();
	const uint32 aMask = (0xFF >> hardwareFormat.aLoss) << hardwareFormat.aShift;

	if (hardwareFormat.bytesPerPixel == 2) {
		uint16 *palette = (uint16 *)_cursor->getPalette() + _cursorKeyColor;
		*palette &= ~aMask;
	} else if (hardwareFormat.bytesPerPixel == 4) {
		uint32 *palette = (uint32 *)_cursor->getPalette() + _cursorKeyColor;
		*palette &= ~aMask;
	} else {
		warning("OpenGLGraphicsManager::updateCursorPalette: Unsupported pixel depth %d", hardwareFormat.bytesPerPixel);
	}
}

void OpenGLGraphicsManager::recalculateCursorScaling() {
	if (!_cursor || !_gameScreen) {
		return;
	}

	// By default we use the unscaled versions.
	_cursorHotspotXScaled = _cursorHotspotX;
	_cursorHotspotYScaled = _cursorHotspotY;
	_cursorWidthScaled = _cursor->getWidth();
	_cursorHeightScaled = _cursor->getHeight();

	// In case scaling is actually enabled we will scale the cursor according
	// to the game screen.
	if (!_cursorDontScale) {
		const frac_t screenScaleFactorX = intToFrac(_displayWidth)  / _gameScreen->getWidth();
		const frac_t screenScaleFactorY = intToFrac(_displayHeight) / _gameScreen->getHeight();

		_cursorHotspotXScaled = fracToInt(_cursorHotspotXScaled * screenScaleFactorX);
		_cursorWidthScaled    = fracToInt(_cursorWidthScaled    * screenScaleFactorX);

		_cursorHotspotYScaled = fracToInt(_cursorHotspotYScaled * screenScaleFactorY);
		_cursorHeightScaled   = fracToInt(_cursorHeightScaled   * screenScaleFactorY);
	}
}

#ifdef USE_OSD
const Graphics::Font *OpenGLGraphicsManager::getFontOSD() {
	return FontMan.getFontByUsage(Graphics::FontManager::kLocalizedFont);
}
#endif

void OpenGLGraphicsManager::saveScreenshot(const Common::String &filename) const {
	const uint width  = _outputScreenWidth;
	const uint height = _outputScreenHeight;

	// A line of a BMP image must have a size divisible by 4.
	// We calculate the padding bytes needed here.
	// Since we use a 3 byte per pixel mode, we can use width % 4 here, since
	// it is equal to 4 - (width * 3) % 4. (4 - (width * Bpp) % 4, is the
	// usual way of computing the padding bytes required).
	const uint linePaddingSize = width % 4;
	const uint lineSize        = width * 3 + linePaddingSize;

	// Allocate memory for screenshot
	uint8 *pixels = new uint8[lineSize * height];

	// Get pixel data from OpenGL buffer
	GLCALL(glReadPixels(0, 0, width, height, GL_RGB, GL_UNSIGNED_BYTE, pixels));

	// BMP stores as BGR. Since we can't assume that GL_BGR is supported we
	// will swap the components from the RGB we read to BGR on our own.
	for (uint y = height; y-- > 0;) {
		uint8 *line = pixels + y * lineSize;

		for (uint x = width; x > 0; --x, line += 3) {
			SWAP(line[0], line[2]);
		}
	}

	// Open file
	Common::DumpFile out;
	out.open(filename);

	// Write BMP header
	out.writeByte('B');
	out.writeByte('M');
	out.writeUint32LE(height * lineSize + 54);
	out.writeUint32LE(0);
	out.writeUint32LE(54);
	out.writeUint32LE(40);
	out.writeUint32LE(width);
	out.writeUint32LE(height);
	out.writeUint16LE(1);
	out.writeUint16LE(24);
	out.writeUint32LE(0);
	out.writeUint32LE(0);
	out.writeUint32LE(0);
	out.writeUint32LE(0);
	out.writeUint32LE(0);
	out.writeUint32LE(0);

	// Write pixel data to BMP
	out.write(pixels, lineSize * height);

	// Free allocated memory
	delete[] pixels;
}

} // End of namespace OpenGL
コード例 #24
0
void OpenGLGraphicsManager::setActualScreenSize(uint width, uint height) {
	_outputScreenWidth = width;
	_outputScreenHeight = height;

	// Setup coordinates system.
	GLCALL(glViewport(0, 0, _outputScreenWidth, _outputScreenHeight));

	GLCALL(glMatrixMode(GL_PROJECTION));
	GLCALL(glLoadIdentity());
#ifdef USE_GLES
	GLCALL(glOrthof(0, _outputScreenWidth, _outputScreenHeight, 0, -1, 1));
#else
	GLCALL(glOrtho(0, _outputScreenWidth, _outputScreenHeight, 0, -1, 1));
#endif
	GLCALL(glMatrixMode(GL_MODELVIEW));
	GLCALL(glLoadIdentity());

	uint overlayWidth = width;
	uint overlayHeight = height;

	// WORKAROUND: We can only support surfaces up to the maximum supported
	// texture size. Thus, in case we encounter a physical size bigger than
	// this maximum texture size we will simply use an overlay as big as
	// possible and then scale it to the physical display size. This sounds
	// bad but actually all recent chips should support full HD resolution
	// anyway. Thus, it should not be a real issue for modern hardware.
	if (   overlayWidth  > (uint)Texture::getMaximumTextureSize()
	    || overlayHeight > (uint)Texture::getMaximumTextureSize()) {
		const frac_t outputAspect = intToFrac(_outputScreenWidth) / _outputScreenHeight;

		if (outputAspect > (frac_t)FRAC_ONE) {
			overlayWidth  = Texture::getMaximumTextureSize();
			overlayHeight = intToFrac(overlayWidth) / outputAspect;
		} else {
			overlayHeight = Texture::getMaximumTextureSize();
			overlayWidth  = fracToInt(overlayHeight * outputAspect);
		}
	}

	// HACK: We limit the minimal overlay size to 256x200, which is the
	// minimum of the dimensions of the two resolutions 256x240 (NES) and
	// 320x200 (many DOS games use this). This hopefully assure that our
	// GUI has working layouts.
	overlayWidth = MAX<uint>(overlayWidth, 256);
	overlayHeight = MAX<uint>(overlayHeight, 200);

	if (!_overlay || _overlay->getFormat() != _defaultFormatAlpha) {
		delete _overlay;
		_overlay = nullptr;

		_overlay = createTexture(_defaultFormatAlpha);
		assert(_overlay);
		// We always filter the overlay with GL_LINEAR. This assures it's
		// readable in case it needs to be scaled and does not affect it
		// otherwise.
		_overlay->enableLinearFiltering(true);
	}
	_overlay->allocate(overlayWidth, overlayHeight);
	_overlay->fill(0);

#ifdef USE_OSD
	if (!_osd || _osd->getFormat() != _defaultFormatAlpha) {
		delete _osd;
		_osd = nullptr;

		_osd = createTexture(_defaultFormatAlpha);
		assert(_osd);
		// We always filter the osd with GL_LINEAR. This assures it's
		// readable in case it needs to be scaled and does not affect it
		// otherwise.
		_osd->enableLinearFiltering(true);
	}
	_osd->allocate(_overlay->getWidth(), _overlay->getHeight());
	_osd->fill(0);
#endif

	// Re-setup the scaling for the screen and cursor
	recalculateDisplayArea();
	recalculateCursorScaling();

	// Something changed, so update the screen change ID.
	++_screenChangeID;
}
コード例 #25
0
uint32 SoundGen2GS::mixSound() {
	int i, b;

	memset(_sndBuffer, 0, BUFFER_SIZE << 1);

	if (!_playing || _playingSound == -1)
		return BUFFER_SIZE;

	// Handle Apple IIGS sound mixing here
	// TODO: Implement playing both waves in an oscillator
	// TODO: Implement swap-mode in an oscillator
	for (uint midiChan = 0; midiChan < _midiChannels.size(); midiChan++) {
		for (uint gsChan = 0; gsChan < _midiChannels[midiChan]._gsChannels.size(); gsChan++) {
			IIgsChannelInfo &channel = _midiChannels[midiChan]._gsChannels[gsChan];
			if (channel.playing()) { // Only mix in actively playing channels
				// Frequency multiplier was 1076.0 based on tests made with MESS 0.117.
				// Tests made with KEGS32 averaged the multiplier to around 1045.
				// So this is a guess but maybe it's 1046.5... i.e. C6's frequency?
				double hertz = C6_FREQ * pow(SEMITONE, fracToDouble(channel.note));
				channel.posAdd = doubleToFrac(hertz / getRate());
				channel.vol = doubleToFrac(fracToDouble(channel.envVol) * fracToDouble(channel.chanVol) / 127.0);
				double tempVol = fracToDouble(channel.vol)/127.0;
				for (i = 0; i < IIGS_BUFFER_SIZE; i++) {
					b = channel.relocatedSample[fracToInt(channel.pos)];
					// TODO: Find out what volume/amplification setting is loud enough
					//       but still doesn't clip when playing many channels on it.
					_sndBuffer[i] += (int16) (b * tempVol * 256/4);
					channel.pos += channel.posAdd;

					if (channel.pos >= intToFrac(channel.size)) {
						if (channel.loop) {
							// Don't divide by zero on zero length samples
							channel.pos %= intToFrac(channel.size + (channel.size == 0));
							// Probably we should loop the envelope too
							channel.envSeg = 0;
							channel.envVol = channel.startEnvVol;
						} else {
							channel.pos = channel.chanVol = 0;
							channel.end = true;
							break;
						}
					}
				}

				if (channel.envSeg < ENVELOPE_SEGMENT_COUNT) {
					const IIgsEnvelopeSegment &seg = channel.ins->env.seg[channel.envSeg];
					// I currently assume enveloping works with the same speed as the MIDI
					// (i.e. with 1/60ths of a second ticks).
					// TODO: Check if enveloping really works with the same speed as MIDI
					frac_t envVolDelta = doubleToFrac(seg.inc/256.0);
					if (intToFrac(seg.bp) >= channel.envVol) {
						channel.envVol += envVolDelta;
						if (channel.envVol >= intToFrac(seg.bp)) {
							channel.envVol = intToFrac(seg.bp);
							channel.envSeg += 1;
						}
					} else {
						channel.envVol -= envVolDelta;
						if (channel.envVol <= intToFrac(seg.bp)) {
							channel.envVol = intToFrac(seg.bp);
							channel.envSeg += 1;
						}
					}
				}
			}
		}
	}

	removeStoppedSounds();

	return IIGS_BUFFER_SIZE;
}