⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 screen.cpp

📁 SNES game emulator. C and asm files.
💻 CPP
📖 第 1 页 / 共 3 页
字号:
				scrstart += PRELINESIZE;
			}
			dwpal_or = (ctilemap->pal_or << 24) | (ctilemap->pal_or << 16) | (ctilemap->pal_or << 8) | ctilemap->pal_or;
			((dword*)scrstart)[0] = ctilemap->tile->dwpixel[offsy] | dwpal_or;
			((dword*)scrstart)[1] = ctilemap->tile->dwpixel[offsy + 1] | dwpal_or;
			if (ctilemap->prio) {
				scrstart -= PRELINESIZE;
				((dword*)scrstart)[0] = ((dword*)scrstart)[1] = 0;
				mustcopy[1]++;
			} else {
				((dword*)(scrstart + PRELINESIZE))[0] = ((dword*)(scrstart + PRELINESIZE))[1] = 0;
				mustcopy[0]++;
			}
		}
	}
#else
	blitbgline_frontend (ctilemap, offsy, col, scrstart, mustcopy);
#endif
}

#ifndef USE_C_SCREEN_CODE
extern void blitscanlinetransparent (byte *source, byte *dest, dword pal_and);
/* // FIRST VERSION
#pragma aux blitscanlinetransparent = \
		"      mov eax, [edi]"\
		"      mov ecx, 64"\
		"again: mov eax, [esi]"\
		"      nop"\
		"      test al, bl"\
		"      jz not1"\
		"      mov [edi], al"\
		"not1: test ah, bh"\
		"      jz not2"\
		"      mov [edi+1], ah"\
		"not2: shr eax, 16"\
		"      nop"\
		"      test al, bl"\
		"      jz not3"\
		"      mov [edi+2], al"\
		"not3: test ah, bh"\
		"      jz not4"\
		"      mov [edi+3], ah"\
		"not4: add esi, 4"\
		"      add edi, 4"\
		"      dec ecx"\
		"      jnz again"\
		parm [esi] [edi] [ebx]\
        modify [eax ebx ecx esi edi];
*/
#pragma aux blitscanlinetransparent = \
		"      mov cl, 64"    /**/\
		"again:mov eax, [esi]"/**/\
		"      mov ebx, [edi]"/**/\
		"      test al, ch"   /**/\
		"      jz not1"       /**/\
		"      mov bl, al"\
		"not1: test ah, ch"\
		"      jz not2"\
		"      mov bh, ah"\
		"not2: ror eax, 16"\
		"      ror ebx, 16"\
		"      test al, ch"\
		"      jz not3"\
		"      mov bl, al"\
		"not3: test ah, ch"\
		"      jz not4"\
		"      mov bh, ah"\
		"not4: rol ebx, 16"\
		"      add esi, 4"\
		"      mov [edi], ebx"\
		"      add edi, 4"\
		"      dec cl"\
		"      jnz again"\
		parm [esi] [edi] [ecx]\
        modify [eax ebx ecx esi edi];
#else
// C VERSION
void blitscanlinetransparent (byte *source, byte *dest, dword pal_and)
{
	register int x;
	for (x = 64; x != 0; x--, source += 4, dest += 4) {
		if ((source[0] & pal_and) != 0) dest[0] = source[0];
		if ((source[1] & pal_and) != 0) dest[1] = source[1];
		if ((source[2] & pal_and) != 0) dest[2] = source[2];
		if ((source[3] & pal_and) != 0) dest[3] = source[3];
	}
}
#endif

inline void blitscanline (dword *source, dword *dest, dword pal_and)
{
	memcpy_16 (dest, source, 16);
	//register int x;
	//for (x = 64; x != 0; x--)
	//	*(dest++) = *(source++);
}

inline void dobglinedraw (int plane, int on, boolean priority)
{
	if (mustcopybgline[plane][priority] && (on & (1 << plane)))
		blitscanlinetransparent (bgline[plane][priority] + 8, screen,
		bg[plane].cdepth==0 ? 0x03030303 : bg[plane].cdepth==1 ? 0x0F0F0F0F : 0xFFFFFFFF);
}
	
inline void dobglinedrawsolid (int plane, int on, boolean priority)
{	if (on & (1 << plane))
		blitscanline ((dword*)(bgline[plane][priority] + 8), (dword*)screen,
		bg[plane].cdepth==0 ? 0x03030303 : bg[plane].cdepth==0 ? 0x0F0F0F0F : 0xFFFFFFFF);
}

inline int mode7sx (int v)
{
	return (v & 0x1000) ? (v | ~0xFFF) : (v & 0xFFF);
}

void blitmode7line (void)
{
	int x, t, p, colorand = (*REG2133 & 0x40 ? 127 : 255);
	int pseudoscanline = ((*REG211A & 2) ? scans_before_vbl() - screen_scanline - 1 : screen_scanline);
	float xmap_per_xpix =  (float)state.m7var[0] / 256;
	float ymap_per_xpix = -(float)state.m7var[1] / 256;
	float xmap_per_ypix = -(float)state.m7var[2] / 256;
	float ymap_per_ypix =  (float)state.m7var[3] / 256;
	float centerx = (float)(1.0 - xmap_per_xpix) * mode7sx (state.m7var[4]) - xmap_per_ypix * mode7sx (state.m7var[5]);
	float centery = (float)(1.0 - ymap_per_ypix) * mode7sx (state.m7var[5]) - ymap_per_xpix * mode7sx (state.m7var[4]);
	float scrollx = (float)mode7sx (state.scrollreg[0]+1);
	float scrolly = (float)mode7sx (state.scrollreg[1]+1);
	float starting_x = centerx + ((scrollx)*xmap_per_xpix) + ((scrolly+screen_scanline)*xmap_per_ypix);
	float starting_y = centery + ((scrollx)*ymap_per_xpix) + ((scrolly+screen_scanline)*ymap_per_ypix);
	byte *scr = bgline[0][0]+8;

	for (x = 0; x < 256; x++) {
		t = vram [((((int)starting_y >> 3) & 0x7F) * 128 + (((int)starting_x >> 3) & 0x7F)) << 1];
		p = vram [((t * 8*8 + ((int)starting_y & 7) * 8 + ((int)starting_x & 7)) << 1) + 1];
		if (*REG211A & 1)
			scr [256 - x] = p & colorand;
		else
			scr [x] = p & colorand;
		starting_y += ymap_per_xpix;
		starting_x += xmap_per_xpix;
	}
	mustcopybgline[0][0] = true;
}

//-------------------------------------------------------Sprite scanline blit funcs

boolean oamposchange;
byte sprhere [256][32];
byte nsprhere [256];

inline void dospritelinedraw (int priority)
{	if (mustcopysprline[priority])
		blitscanlinetransparent (sprline[priority] + 8, screen, 0x0F0F0F0F);
}
inline void dospritelinedrawsolid (int priority)
{	if (mustcopysprline[priority])
		blitscanline ((dword*)(sprline[priority] + 8), (dword*)screen, 0x0F0F0F0F);
}

void generatespritescanlines ()
{
	int bits, xpos, ypos, size, row, col, pixoffsy, numtiles, obj, obji, prio;
	byte *thisscanline;

	if (!(curgs->bgs & 0x10))
		return;
	memset (sprline, 0, sizeof (sprline));
	for (obji = 0; obji < nsprhere[screen_scanline]; obji++) {
		obj = sprhere[screen_scanline][obji];
		thisscanline = sprline [prio = ((oam [(obj << 2) + 3] & 0x30) >> 4)];
		bits = (oam [512 + (obj >> 2)] & (3 << ( (obj & 3) << 1 ) )) >> ( (obj & 3) << 1);
		xpos = oam [(obj << 2)] + ((bits & 1) << 8);
		ypos = oam [(obj << 2) + 1];
		size = spr8x8size[obj] << 3;

		pixoffsy = (screen_scanline - ypos) & 0xFF;
		row = pixoffsy >> 3;
		pixoffsy &= 7;
		if (xpos >= 256) {
			col = (512-xpos) >> 3;
			numtiles = spr8x8size[obj] - col;
		} else {
			col = 0;
			numtiles = (256+7-xpos) >> 3;
			if (numtiles > spr8x8size[obj])
				numtiles = spr8x8size[obj];
		}
		blitspriteline (&sprmap[obj][row][col], numtiles, pixoffsy, thisscanline + ((xpos+(col<<3)+8)&0xFF), mustcopysprline[prio]);
	}
}

void blitspriteline (struct cachetilemap *ctmap, int numtiles, int yoffs, byte *scrstart, byte &mustcopy)
{
	int flagand = (1 << yoffs), pixoffsy = (yoffs << 3);
	byte *pixels;
	dword dwpal_or;
	
	for (;numtiles != 0; numtiles--, scrstart += 8, ctmap++) {
		if (ctmap->empty & flagand) {
			continue;
		}
		else if (ctmap->solid & flagand) {
			dwpal_or = (ctmap->pal_or << 24) | (ctmap->pal_or << 16) | (ctmap->pal_or << 8) | ctmap->pal_or;
			((dword*)scrstart)[0] = ctmap->tile->dwpixel[(yoffs << 1)] | dwpal_or;
			((dword*)scrstart)[1] = ctmap->tile->dwpixel[(yoffs << 1) + 1] | dwpal_or;
			mustcopy = true;
			continue;
		}
		pixels = &ctmap->tile->pixel[pixoffsy];
		if (pixels[0]) scrstart[0] = pixels[0] | ctmap->pal_or;
		if (pixels[1]) scrstart[1] = pixels[1] | ctmap->pal_or;
		if (pixels[2]) scrstart[2] = pixels[2] | ctmap->pal_or;
		if (pixels[3]) scrstart[3] = pixels[3] | ctmap->pal_or;
		if (pixels[4]) scrstart[4] = pixels[4] | ctmap->pal_or;
		if (pixels[5]) scrstart[5] = pixels[5] | ctmap->pal_or;
		if (pixels[6]) scrstart[6] = pixels[6] | ctmap->pal_or;
		if (pixels[7]) scrstart[7] = pixels[7] | ctmap->pal_or;
		mustcopy = true;
	}
}

//----------------------------------------------------Top-level screen render funcs

void drawnextscanline ()
{
	int x, on, mask;

	screen = vs + ((screen_scanline+8) << 8);

	if (*REG2100 & 0x80) // Screen off
		return;
	memset (mustcopybgline, 0, sizeof(mustcopybgline));
	memset (mustcopysprline,0, sizeof(mustcopysprline));

	if ((*REG2131 & 0x3F) == 0x00)
		on = 0;
	else // Get sub-screens on
		on = *REG212D & ~(*REG212C) & snesmode[*REG2105&7].onmask;
	for (x = 0; x < snesmode[*REG2105&7].bgs; x++) {
		mask = (1 << x);
		if ((*REG212C | *REG212D) & mask) {
			getbglineinfo (x);
			// Now, offset line-specific information...
			bg[x].scrolly += screen_scanline;
			// Generate scanlines for both priorities
			if (curgs->windowing && ((on & *REG212F & mask) || (*REG212C & *REG212E & mask)))
				// Sub screen || main screen window enabled (*212C==main screen, on==sub screen)
				generatebgscanline (x, true);
			else {
				generatebgscanline (x, false);
			}
		}
	}
	if (oamposchange)
		buildsprlinelist ();

	generatespritescanlines ();

	if ((*REG2105 & 15) == 8 + 1) {
		dobglinedrawsolid (3, on, 0);
		if (!(on&0x80)) dobglinedrawsolid (2, on, 0);
		else            dobglinedraw (2, on, 0);
		if (on&0x10) dospritelinedraw (0);
		dobglinedraw (3, on, 1);
		if (on&0x10) dospritelinedraw (1);
		dobglinedraw (1, on, 0); dobglinedraw (0, on, 0); dobglinedraw (1, on, 1);
		if (on&0x10) dospritelinedraw (2);
		dobglinedraw (0, on, 1);
		if (on&0x10) dospritelinedraw (3);
		dobglinedraw (2, on, 1);
	} else {
		dobglinedrawsolid (3, on, 0);
		if (!(on&0x80)) dobglinedrawsolid (2, on, 0);
		else            dobglinedraw (2, on, 0);
		if (on&0x10) dospritelinedraw (0);
		dobglinedraw (3, on, 1); dobglinedraw (2, on, 1);
		if (on&0x10) dospritelinedraw (1);
		dobglinedraw (1, on, 0); dobglinedraw (0, on, 0);
		if (on&0x10) dospritelinedraw (2);
		dobglinedraw (1, on, 1); dobglinedraw (0, on, 1);
		if (on&0x10) dospritelinedraw (3);
	}
	on = *REG212C & snesmode[*REG2105&7].onmask;
	if ((*REG2105 & 7) == 7) {
		if (on&0x10) dospritelinedraw (0);
		dobglinedraw (0, on, 0);
		if (on&0x10) dospritelinedraw (1);
		if (on&0x10) dospritelinedraw (2);
		if (on&0x10) dospritelinedraw (3);
	} else if ((*REG2105 & 15) == 8 + 1) {
		dobglinedraw (3, on, 0);
		dobglinedraw (2, on, 0);
		if (on&0x10) dospritelinedraw (0);
		dobglinedraw (3, on, 1);
		if (on&0x10) dospritelinedraw (1);
		dobglinedraw (1, on, 0);
		dobglinedraw (0, on, 0);
		dobglinedraw (1, on, 1);
		if (on&0x10) dospritelinedraw (2);
		dobglinedraw (0, on, 1);
		if (on&0x10) dospritelinedraw (3);
		dobglinedraw (2, on, 1);
	} else {
		dobglinedraw (3, on, 0);
		dobglinedraw (2, on, 0);
		if (on&0x10) dospritelinedraw (0);
		dobglinedraw (3, on, 1);
		dobglinedraw (2, on, 1);
		if (on&0x10) dospritelinedraw (1);
		dobglinedraw (1, on, 0);
		dobglinedraw (0, on, 0);
		if (on&0x10) dospritelinedraw (2);
		dobglinedraw (1, on, 1);
		dobglinedraw (0, on, 1);
		if (on&0x10) dospritelinedraw (3);
	}
}

void rendersnesscreen ()
{
	if (debugmode) {
		drawdebug (debugscreen);
	} else {
		doframedraw ();
	}
}

//---------------------------------------------------------Cached tile map updaters

void updatetilemap64_16x16 (byte *tilemap, struct cachetilemap *ctmap, int tcharbase, boolean secondrow)
{	// version for 16x16 tile maps.
	int x, tnum;

	if (secondrow) // only difference between 1st & 2nd row is +2 chars...
		tcharbase += (16 << curbg->tcharshift);
	for (x = 32; x > 0; x--) {
		tnum = tcharbase + ((*(word*)tilemap & 0x3FF) << curbg->tcharshift);
		ctmap[0].prio = (tilemap[1] >> 5) & 1;
		ctmap[0].tile = getcachetile (tnum, curbg->cdepth, tilemap[1] >> 6);
		ctmap[0].empty = cempty [tilemap[1]>>7][tnum];
		ctmap[0].solid = csolid [tilemap[1]>>7][tnum];
		ctmap[0].pal_or = ctmap[1].pal_or = curbg->cgoffs | ((tilemap[1] & 0x1C) << (curbg->cdepth<<1));
		tnum += 1 << curbg->tcharshift;
		ctmap[1].tile = getcachetile (tnum, curbg->cdepth, tilemap[1] >> 6);
		ctmap[1].empty = cempty [tilemap[1]>>7][tnum];
		ctmap[1].solid = csolid [tilemap[1]>>7][tnum];
		tilemap += 2;
		ctmap += 2;
	}
}

void updatetilemap32 (byte *tilemap, struct cachetilemap *ctmap, int tcharbase)
{
	int x, tnum;

	for (x = 32; x > 0; x--) {
		tnum = tcharbase + ((*(word*)tilemap & 0x3FF) << curbg->tcharshift);
		ctmap->prio = (tilemap[1] >> 5) & 1;
		ctmap->tile = getcachetile (tnum, curbg->cdepth, tilemap[1] >> 6);
		ctmap->empty = cempty [tilemap[1]>>7][tnum];
		ctmap->solid = csolid [tilemap[1]>>7][tnum];
		ctmap->pal_or = curbg->cgoffs | ((tilemap[1] & 0x1C) << (curbg->cdepth << 1));
		tilemap += 2;
		ctmap++;
	}
}

void updatetilemaprow (int row)
{	// uses curbg
	byte *tilemap = curbg->tilemap;
	struct cachetilemap *ctilemap = (struct cachetilemap *) ctmap[curbg->bgnum-1][row];

	if (row >= (32<<curbg->tile16x16)) {
		row -= (32<<curbg->tile16x16);
		tilemap += ((32*32*2) << curbg->width64);
	}
	if (!curbg->tile16x16) { // 8x8 tiles
		updatetilemap32 (tilemap + (row << 6), ctilemap, curbg->tcharbase);
		if (curbg->width64) { // 64 wide
			updatetilemap32 (tilemap + 32*32*2 + (row << 6), ctilemap + 32, curbg->tcharbase);
		} else {
			memcpy (ctilemap + 32, ctilemap, sizeof(cachetilemap)*32);
		}
		memcpy (ctilemap + 64, ctilemap, sizeof(cachetilemap)*64);
	} else { // 16x16 tiles
		updatetilemap64_16x16 (tilemap + ((row >> 1) << 6), ctilemap, curbg->tcharbase, row & 1);
		if (curbg->width64) { // 64 16x16 tiles wide
			updatetilemap64_16x16 (tilemap + 32*32*2 + ((row >> 1) << 6), ctilemap + 64, curbg->tcharbase, row & 1);
		} else {
			memcpy (ctilemap + 64, ctilemap, sizeof(cachetilemap)*64);
		}
	}
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -