📄 old screen.cpp
字号:
/* 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 + -