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