source/graphics.cpp
void Graphics::copyStretchSpriteToScreen(
	uint8_t spritebuffer[],
	int spr_x,
	int spr_y,
	int spr_w,
	int spr_h,
	int scr_x,
	int scr_y,
	int scr_w,
	int scr_h,
	bool flip_x,
	bool flip_y)
{
	if (false || (spr_h == scr_h && spr_w == scr_w)) {
		// use faster non stretch blitter if sprite is not stretched
		copySpriteToScreen(spritebuffer, scr_x, scr_y, spr_x, spr_y, scr_w, scr_h, flip_x, flip_y);
		return;
	}

	applyCameraToPoint(&scr_x, &scr_y);

	//shift bits to avoid floating point math
	spr_x = spr_x << 16;
	spr_y = spr_y << 16;
	spr_w = spr_w << 16;
	spr_h = spr_h << 16;

	int dx = spr_w / scr_w;
	int dy = spr_h / scr_h;

	// left clip
	if (scr_x < _memory->_gfxState_clip_xb) {
		int nclip = _memory->_gfxState_clip_xb - scr_x;
		scr_x = _memory->_gfxState_clip_xb;
		scr_w -= nclip;
		if (!flip_x) {
			spr_x += nclip * dx;
		} else {
			spr_w -= nclip * dx;
		}
	}

	// right clip
	if (scr_x + scr_w > _memory->_gfxState_clip_xe) {
		int nclip = (scr_x + scr_w) - _memory->_gfxState_clip_xe;
		scr_w -= nclip;
	}

	// top clip
	if (scr_y < _memory->_gfxState_clip_yb) {
		int nclip = _memory->_gfxState_clip_yb - scr_y;
		scr_y = _memory->_gfxState_clip_yb;
		scr_h -= nclip;
		if (!flip_y) {
			spr_y += nclip * dy;
		} else {
			spr_h -= nclip * dy;
		}
	}

	// bottom clip
	if (scr_y + scr_h > _memory->_gfxState_clip_ye) {
		int nclip = (scr_y + scr_h) - _memory->_gfxState_clip_ye;
		scr_h -= nclip;
	}

	if (flip_y) {
		spr_y += spr_h - 1 * dy;
		dy = -dy;
	}

	for (int y = 0; y < scr_h; y++) {
		uint8_t* spr = spritebuffer + (((spr_y + y * dy) >> 16) & 0x7f) * 64;

		if (!flip_x) {
			for (int x = 0; x < scr_w; x++) {
				int pixIndex = (spr_x + x * dx);
				int combinedPixIdx = ((pixIndex / 2) >> 16) & 0x7f;
				uint8_t bothPix = spr[combinedPixIdx];

				uint8_t c = (pixIndex >> 16) % 2 == 0
					? bothPix & 0x0f //just first 4 bits
					: bothPix >> 4;  //just last 4 bits
				if (_memory->_gfxState_transparencyPalette[c] == false) {
					_private_pset(scr_x + x, scr_y + y, c);
				}
			}
		} else {
			for (int x = 0; x < scr_w; x++) {
				int pixIndex = (spr_x + spr_w - (x + 1) * dx);
				int combinedPixIdx = ((pixIndex / 2) >> 16) & 0x7f;
				uint8_t bothPix = spr[combinedPixIdx];

				uint8_t c = (pixIndex >> 16) % 2 == 0
					? bothPix >> 4 //just first 4 bits
					: bothPix & 0x0f;  //just last 4 bits
				if (_memory->_gfxState_transparencyPalette[c] == false) {
					_private_pset(scr_x + x, scr_y + y, c);
				}
			}
		}
	}
}
//based on tac08 implementation of stretch_blitter()
//uses ints so we can shift bits and do integer division instead of floating point
based on tac08 implementation of stretch_blitter()
uses ints so we can shift bits and do integer division instead of floating point
based on tac08 implementation of stretch_blitter () uses ints so we can shift bits and do integer division instead of floating point
void Graphics::copyStretchSpriteToScreen(
	uint8_t spritebuffer[],
	int spr_x,
	int spr_y,
	int spr_w,
	int spr_h,
	int scr_x,
	int scr_y,
	int scr_w,
	int scr_h,
	bool flip_x,
	bool flip_y)
{
	if (false || (spr_h == scr_h && spr_w == scr_w)) {
		copySpriteToScreen(spritebuffer, scr_x, scr_y, spr_x, spr_y, scr_w, scr_h, flip_x, flip_y);
		return;
	}
	applyCameraToPoint(&scr_x, &scr_y);
	spr_x = spr_x << 16;
	spr_y = spr_y << 16;
	spr_w = spr_w << 16;
	spr_h = spr_h << 16;
	int dx = spr_w / scr_w;
	int dy = spr_h / scr_h;
	if (scr_x < _memory->_gfxState_clip_xb) {
		int nclip = _memory->_gfxState_clip_xb - scr_x;
		scr_x = _memory->_gfxState_clip_xb;
		scr_w -= nclip;
		if (!flip_x) {
			spr_x += nclip * dx;
		} else {
			spr_w -= nclip * dx;
		}
	}
	if (scr_x + scr_w > _memory->_gfxState_clip_xe) {
		int nclip = (scr_x + scr_w) - _memory->_gfxState_clip_xe;
		scr_w -= nclip;
	}
	if (scr_y < _memory->_gfxState_clip_yb) {
		int nclip = _memory->_gfxState_clip_yb - scr_y;
		scr_y = _memory->_gfxState_clip_yb;
		scr_h -= nclip;
		if (!flip_y) {
			spr_y += nclip * dy;
		} else {
			spr_h -= nclip * dy;
		}
	}
	if (scr_y + scr_h > _memory->_gfxState_clip_ye) {
		int nclip = (scr_y + scr_h) - _memory->_gfxState_clip_ye;
		scr_h -= nclip;
	}
	if (flip_y) {
		spr_y += spr_h - 1 * dy;
		dy = -dy;
	}
	for (int y = 0; y < scr_h; y++) {
		uint8_t* spr = spritebuffer + (((spr_y + y * dy) >> 16) & 0x7f) * 64;
		if (!flip_x) {
			for (int x = 0; x < scr_w; x++) {
				int pixIndex = (spr_x + x * dx);
				int combinedPixIdx = ((pixIndex / 2) >> 16) & 0x7f;
				uint8_t bothPix = spr[combinedPixIdx];
				uint8_t c = (pixIndex >> 16) % 2 == 0
					? bothPix & 0x0f 
					: bothPix >> 4;  
				if (_memory->_gfxState_transparencyPalette[c] == false) {
					_private_pset(scr_x + x, scr_y + y, c);
				}
			}
		} else {
			for (int x = 0; x < scr_w; x++) {
				int pixIndex = (spr_x + spr_w - (x + 1) * dx);
				int combinedPixIdx = ((pixIndex / 2) >> 16) & 0x7f;
				uint8_t bothPix = spr[combinedPixIdx];
				uint8_t c = (pixIndex >> 16) % 2 == 0
					? bothPix >> 4 
					: bothPix & 0x0f;  
				if (_memory->_gfxState_transparencyPalette[c] == false) {
					_private_pset(scr_x + x, scr_y + y, c);
				}
			}
		}
	}
}
void Graphics :: copyStretchSpriteToScreen ( uint8_t spritebuffer [ ] , int spr_x , int spr_y , int spr_w , int spr_h , int scr_x , int scr_y , int scr_w , int scr_h , bool flip_x , bool flip_y ) { if ( false || ( spr_h == scr_h && spr_w == scr_w ) ) { copySpriteToScreen ( spritebuffer , scr_x , scr_y , spr_x , spr_y , scr_w , scr_h , flip_x , flip_y ) ; return ; } applyCameraToPoint ( & scr_x , & scr_y ) ; spr_x = spr_x << 16 ; spr_y = spr_y << 16 ; spr_w = spr_w << 16 ; spr_h = spr_h << 16 ; int dx = spr_w / scr_w ; int dy = spr_h / scr_h ; if ( scr_x < _memory -> _gfxState_clip_xb ) { int nclip = _memory -> _gfxState_clip_xb - scr_x ; scr_x = _memory -> _gfxState_clip_xb ; scr_w -= nclip ; if ( ! flip_x ) { spr_x += nclip * dx ; } else { spr_w -= nclip * dx ; } } if ( scr_x + scr_w > _memory -> _gfxState_clip_xe ) { int nclip = ( scr_x + scr_w ) - _memory -> _gfxState_clip_xe ; scr_w -= nclip ; } if ( scr_y < _memory -> _gfxState_clip_yb ) { int nclip = _memory -> _gfxState_clip_yb - scr_y ; scr_y = _memory -> _gfxState_clip_yb ; scr_h -= nclip ; if ( ! flip_y ) { spr_y += nclip * dy ; } else { spr_h -= nclip * dy ; } } if ( scr_y + scr_h > _memory -> _gfxState_clip_ye ) { int nclip = ( scr_y + scr_h ) - _memory -> _gfxState_clip_ye ; scr_h -= nclip ; } if ( flip_y ) { spr_y += spr_h - 1 * dy ; dy = - dy ; } for ( int y = 0 ; y < scr_h ; y ++ ) { uint8_t * spr = spritebuffer + ( ( ( spr_y + y * dy ) >> 16 ) & 0x7f ) * 64 ; if ( ! flip_x ) { for ( int x = 0 ; x < scr_w ; x ++ ) { int pixIndex = ( spr_x + x * dx ) ; int combinedPixIdx = ( ( pixIndex / 2 ) >> 16 ) & 0x7f ; uint8_t bothPix = spr [ combinedPixIdx ] ; uint8_t c = ( pixIndex >> 16 ) % 2 == 0 ? bothPix & 0x0f : bothPix >> 4 ; if ( _memory -> _gfxState_transparencyPalette [ c ] == false ) { _private_pset ( scr_x + x , scr_y + y , c ) ; } } } else { for ( int x = 0 ; x < scr_w ; x ++ ) { int pixIndex = ( spr_x + spr_w - ( x + 1 ) * dx ) ; int combinedPixIdx = ( ( pixIndex / 2 ) >> 16 ) & 0x7f ; uint8_t bothPix = spr [ combinedPixIdx ] ; uint8_t c = ( pixIndex >> 16 ) % 2 == 0 ? bothPix >> 4 : bothPix & 0x0f ; if ( _memory -> _gfxState_transparencyPalette [ c ] == false ) { _private_pset ( scr_x + x , scr_y + y , c ) ; } } } } }
based on tac08 implementation of stretch_blitter()
uses ints so we can shift bits and do integer division instead of floating point
based on tac08 implementation of stretch_blitter () uses ints so we can shift bits and do integer division instead of floating point
// use faster non stretch blitter if sprite is not stretched //shift bits to avoid floating point math // left clip // right clip // top clip // bottom clip //just first 4 bits //just last 4 bits //just first 4 bits //just last 4 bits