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

📄 old screen.cpp

📁 SNES game emulator. C and asm files.
💻 CPP
📖 第 1 页 / 共 3 页
字号:
/*  SCREEN.CPP - SNES Screen Renderer
	Color depths (cdepth): 0=4 colors 1=16 colors 3=256 colors.
*/

#include "Common.hpp"
#include "GrEngine.hpp"
#include "CPU.hpp"
#include "FileMan.hpp"
#include "GUI.hpp"
#include "SPC700.hpp"
#include "Screen.hpp"
#include <ASSERT.H>

int debugscreen;

int memdumpoffset = 0, vramdumpoffset = 0, oamdumpoffset = 0, cgramdumpoffset = 0;
int vramblitoffset = 0, vramblitcdepth = 0;
int debug_sprmin = 0, debug_sprmax = 127;

char vramcmpfn[40] = "";
byte debug_vram[65536];

union cachetile ctile [4][4096]; // 1MB!
byte cstatus [4096];
byte csolid [2][4096], cempty [2][4096];  // 8 bits, 1 for each scanline of the tile.
	// Two sets 0=no vertical flip, 1=vertical flip

struct cachetilemap ctmap [4][128][128][2], sprmap [128][8][8];
	// 1MB! + 64K
	// here's the deal with the ctmap (cached tile map): 4 BGs*128 max height*
	// 128 max width*2 priorities*8 bytes=1MB.  This stores a more useful version of the
	// tile maps.  The unused priority entry has it's "empty" byte set to 0xFF, so nothing
	// is drawn.  Every scanline, one line of this cached tile map is built from the tile
	// map data in VRAM (except that the same line will not be built two scanlines in a row,
	// so it may be up to 8 lines between line copies.)
	// Now, if the BG isn't large enough horizontally to fill 128 elements, it is copied so
	// that it does.  For example if it's 32 tiles wide, those 32 built tiles are copied
	// 4 times to fill 128 elements.

byte spr8x8size [128]; // Set to 0 when cache entry is invalidated.

struct bginfo bg[4], *curbg;

union cachetile *translatetile (int taddress, byte cdepth, int flip)
{
	byte *tile = (byte*) &(ctile[flip][taddress]), *o_tile = tile;
	byte *addr = vram + (taddress << 4), *o_addr = addr, temp;
	signed char x, y, incaddr;
	boolean issolid = true, vflip = flip >> 1;
	byte *solidflags = &csolid[vflip][taddress], *emptyflags = &cempty[vflip][taddress];

	taddress &= 4095;
	if (flip & 2) {
		incaddr = -2;
		addr += 14;
	} else
		incaddr = 2;
	//debug0 ("  Caching tile; cstatus=%X cdepth=%d address=%d taddress=%d", cstatus[taddress], cdepth, taddress << 4, taddress);
	*solidflags = 0;
	*emptyflags = 0;
	switch (cdepth) {
	case 0:
		for (y = 0; y < 8; y++, tile += 8, addr += incaddr) {
			x = 7;
			do {
				tile[7-x] = ((addr[0] & (1<<x)) ?1:0) | (addr[1] & (1<<x) ?2:0);
				x--;
			} while (x >= 0);
			if ((addr[0] | addr[1]) == 0xFF) *solidflags |= (1 << y);
			else if ((addr[0] | addr[1]) == 0) *emptyflags |= (1 << y);
		}
		break;
	case 1:
		for (y = 0; y < 8; y++, tile += 8, addr += incaddr) {
			x = 7;
			do {
				tile[7-x] = (addr[0] & (1<<x) ?1:0) | (addr[1] & (1<<x) ?2:0) | (addr[16] & (1<<x) ?4:0) | (addr[17] & (1<<x) ?8:0);
				x--;
			} while (x >= 0);
			temp = addr[0] | addr[1] | addr[16] | addr[17];
			if (temp == 0xFF) *solidflags |= (1 << y);
			else if (temp == 0) *emptyflags |= (1 << y);
		}
		break;
	case 3:
		for (y = 0; y < 8; y++, tile += 8, addr += incaddr) {
			x = 7;
			do {
				tile[7-x] = (addr[0] & (1<<x) ?1:0) | (addr[1] & (1<<x) ?2:0) | (addr[16] & (1<<x) ?4:0) | (addr[17] & (1<<x) ?8:0) \
						  | (addr[32]& (1<<x)?16:0) | (addr[33]& (1<<x)?32:0) | (addr[48] & (1<<x)?64:0) | (addr[49] &(1<<x)?128:0);
				x--;
			} while (x >= 0);
			temp = addr[0] | addr[1] | addr[16] | addr[17] | addr[32] | addr[33] | addr[48] | addr[49];
			if (temp == 0xFF) *solidflags |= (1 << y);
			else if (temp == 0) *emptyflags |= (1 << y);
		}
		break;
	}
	cstatus [taddress] = cdepth | (cstatus [taddress] & 0xF0) | (16 << flip);
	tile = o_tile;
	if (flip & 1) {
		for (y = 0; y < 8; y++) {
			temp = tile[7]; tile[7] = tile[0]; tile[0] = temp;
			temp = tile[6]; tile[6] = tile[1]; tile[1] = temp;
			temp = tile[5]; tile[5] = tile[2]; tile[2] = temp;
			temp = tile[4]; tile[4] = tile[3]; tile[3] = temp;
			tile += 8;
		}
	}
	/*
	if ((taddress<<4) >= 0xC000 && (taddress<<4) < 0xC200) { // second row first ball
		for (y=0;y<8;y++) {
			debug0 ("    %d %02X %02X %02X %02X %02X %02X %02X %02X   P0:%04X", y,
			ctile[taddress].pixel[y*8], ctile[taddress].pixel[y*8+1],
			ctile[taddress].pixel[y*8+2], ctile[taddress].pixel[y*8+3],
			ctile[taddress].pixel[y*8+4], ctile[taddress].pixel[y*8+5],
			ctile[taddress].pixel[y*8+6], ctile[taddress].pixel[y*8+7],
			*((word*)&o_addr[y*2]));
		}
	}
	*/
	return &ctile [flip][taddress];
}

inline union cachetile *getcachetile (int taddress, byte cdepth, int flip)
{ // COLOR DEPTH: 0=2 bit 1=4 bit 3=8 bit
	if ((cstatus[taddress] & (16 << flip)) && (cstatus[taddress] & 0x3) == cdepth) {
		return &ctile [flip][taddress];
	} else {
		return translatetile (taddress, cdepth, flip);
	}
}

byte *screen, scanlines;
	// screen points to current scanline; scanlines = 224 or 239.

struct snesscreenmode {
	int bgs;
	byte cdepth[4];
} snesmode [8] = {
	{ 4, 0, 0, 0, 0 },
	{ 3, 1, 1, 0 },
	{ 2, 1, 1 },
	{ 2, 3, 1 },
	{ 2, 3, 0 },
	{ 2, 1, 0 },
	{ 1, 1 },
	{ 0 }
};

void resetscreenframe ()
{       // To be called at scanline 0...
	int x;

	screen = vs + 256*8;
	for (x = 0; x < 4; x++) {
		getbgframeinfo (x);
		bg[x].lastbgrow = -1;
	}
	for (x = 0; x < 256; x++) {
		setsnespalette (x, ((word*)cgram) [x], (*REG2100 & 0xF));
	}
	if ((*REG212C | *REG212D | curgs->bgs) & 0x10) {
		buildspritetable ();
		oamposchange = true;
	}
}

void getbgframeinfo (int plane)
{
	bg[plane].bgnum = plane + 1;
}

void getbglineinfo (int plane)
{
	bg[plane].cdepth = snesmode[*REG2105 & 7].cdepth[plane];
	bg[plane].tcharshift = (bg[plane].cdepth == 3 ? 2 : bg[plane].cdepth);
	if (*REG2105 & (16 << plane)) { // 16x16 tiles
		bg[plane].tile16x16 = true;
	} else {
		bg[plane].tile16x16 = false;
	}
	if (*REG2107(plane) & 2) { // SC Height
		bg[plane].height64 = true;
		//bg[plane].pixheight = (512 << bg[plane].tile16x16);
		//bg[plane].pixheightand = (bg[plane].tile16x16 ? 0x3FF : 0x1FF);
		bg[plane].height8x8 = (64 << bg[plane].tile16x16);
	} else {
		bg[plane].height64 = false;
		//bg[plane].pixheight = (256 << bg[plane].tile16x16);
		//bg[plane].pixheightand = (bg[plane].tile16x16 ? 0x1FF : 0xFF);
		bg[plane].height8x8 = (32 << bg[plane].tile16x16);
	}
	if (*(REG2107(plane)) & 1) { // SC Width
		bg[plane].width64 = true;
		//bg[plane].pixwidth = (512 << bg[plane].tile16x16);
		//bg[plane].pixwidthand = (bg[plane].tile16x16 ? 0x3FF : 0x1FF);
		//bg[plane].pixwidthshift = (9 + bg[plane].tile16x16);
		bg[plane].width8x8 = (64 << bg[plane].tile16x16);
	} else {
		bg[plane].width64 = false;
		//bg[plane].pixwidth = (256 << bg[plane].tile16x16);
		//bg[plane].pixwidthand = (bg[plane].tile16x16 ? 0x1FF : 0xFF);
		//bg[plane].pixwidthshift = (8 + bg[plane].tile16x16);
		bg[plane].width8x8 = (32 << bg[plane].tile16x16);
	}
	bg[plane].width8x8and = bg[plane].width8x8 - 1;
	bg[plane].height8x8and = bg[plane].height8x8 - 1;
	bg[plane].tilemap = vram + ((*REG2107(plane) & 0x7C) << 9); // Correct in demos
	bg[plane].tcharbase = ((*REG210B >> (plane << 2)) & 7) << 9; // Correct in demos
	bg[plane].scrollx = (state.scrollreg[plane << 1].scroll   & 0x7FF);
	bg[plane].scrolly = (state.scrollreg[(plane<<1)+1].scroll & 0x7FF);// & bg[plane].pixelheightmask);
	if ((*REG2105 & 7) == 0) // Mode 0
		bg[plane].cgoffs = (plane << 5);
	else
		bg[plane].cgoffs = 0;
}

void dobglinedraw (int plane, int on, boolean priority)
{
	int row, offsy;

	if (snesmode[*REG2105&7].bgs > plane && (on & (1 << plane)) && (curgs->bgs & (1 << plane))) {
		curbg = &bg[plane];
		row = ((curbg->scrolly >> 3) & curbg->height8x8and);
		offsy = curbg->scrolly & 7;
		if (row != curbg->lastbgrow) {
			updatetilemaprow (row); // uses curbg
			curbg->lastbgrow = row;
		}
		blitbgline (row, offsy, (curbg->scrollx + 7) >> 3, screen + ((8 - curbg->scrollx) & 7), priority);
		// row, offsy, col, scrstart, priority
	}
	if ((*REG2105&7) == 7) {
		blitmode7line ();
	}
}

void blitmode7line (void)
{
	/*int pixx, x, y;

	for (pixx = 0; pixx < 256; pixx++) {
		x = pixx << 8;
		y = screen_scanline << 8;
	}*/
}

void drawnextscanline ()
{
	int x, on;

	screen = vs + (screen_scanline+8) * 256;

	if (*REG2100 & 0x80) // Screen off
		return;
	debug0 ("scanline %d", screen_scanline);
	for (x = 0; x < snesmode[*REG2105&7].bgs; x++) {
		getbglineinfo (x);
		// Now, offset line-specific information...
		bg[x].scrolly += screen_scanline;
		debug0 ("getbginfo %d",x);
	}
	if (oamposchange) {
		debug0 ("Build sprlinelist");
		buildsprlinelist ();
	}

	on = *REG212D & ~(*REG212C); // Draw sub screens
	debug0 ("subscreen on %X",on);
	if ((*REG2105 & 15) == 8 + 1) {
		dobglinedraw (3, on, 0); dobglinedraw (2, on, 0);
		dobglinedraw (3, on, 1); dobglinedraw (1, on, 0);
		dobglinedraw (0, on, 0); dobglinedraw (1, on, 1);
		dobglinedraw (0, on, 1); dobglinedraw (2, on, 1);
	} else {
		dobglinedraw (3, on, 0); dobglinedraw (2, on, 0);
		dobglinedraw (3, on, 1); dobglinedraw (2, on, 1);
		dobglinedraw (1, on, 0); dobglinedraw (0, on, 0);
		dobglinedraw (1, on, 1); dobglinedraw (0, on, 1);
	}
	on = *REG212C;
	debug0 ("mainscreen on %X",on);
	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);

⌨️ 快捷键说明

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