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

📄 clip.cpp

📁 著名SFC模拟器Snes9x的源代码。
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/* * Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. * * (c) Copyright 1996 - 2001 Gary Henderson (gary@daniver.demon.co.uk) and *                           Jerremy Koot (jkoot@snes9x.com) * * Super FX C emulator code  * (c) Copyright 1997 - 1999 Ivar (Ivar@snes9x.com) and *                           Gary Henderson. * Super FX assembler emulator code (c) Copyright 1998 zsKnight and _Demo_. * * DSP1 emulator code (c) Copyright 1998 Ivar, _Demo_ and Gary Henderson. * C4 asm and some C emulation code (c) Copyright 2000 zsKnight and _Demo_. * C4 C code (c) Copyright 2001 Gary Henderson (gary@daniver.demon.co.uk). * * DOS port code contains the works of other authors. See headers in * individual files. * * Snes9x homepage: www.snes9x.com * * Permission to use, copy, modify and distribute Snes9x in both binary and * source form, for non-commercial purposes, is hereby granted without fee, * providing that this license information and copyright notice appear with * all copies and any derived work. * * This software is provided 'as-is', without any express or implied * warranty. In no event shall the authors be held liable for any damages * arising from the use of this software. * * Snes9x is freeware for PERSONAL USE only. Commercial users should * seek permission of the copyright holders first. Commercial use includes * charging money for Snes9x or software derived from Snes9x. * * The copyright holders request that bug fixes and improvements to the code * should be forwarded to them so everyone can benefit from the modifications * in future versions. * * Super NES and Super Nintendo Entertainment System are trademarks of * Nintendo Co., Limited and its subsidiary companies. */#include <stdlib.h>#include "snes9x.h"#include "memmap.h"#include "ppu.h"struct Band{    uint32 Left;    uint32 Right;};#undef MIN#undef MAX#define MIN(A,B) ((A) < (B) ? (A) : (B))#define MAX(A,B) ((A) > (B) ? (A) : (B))#define BAND_EMPTY(B) (B.Left >= B.Right)#define BANDS_INTERSECT(A,B) ((A.Left >= B.Left && A.Left < B.Right) || \			      (A.Right > B.Left && A.Right <= B.Right))#define OR_BANDS(R,A,B) {\    R.Left = MIN(A.Left, B.Left); \    R.Right = MAX(A.Right, B.Right);}    #define AND_BANDS(R,A,B) {\    R.Left = MAX(A.Left, B.Left); \    R.Right = MIN(A.Right, B.Right);}static int IntCompare (const void *d1, const void *d2){    if (*(uint32 *) d1 > *(uint32 *) d2)	return (1);    else    if (*(uint32 *) d1 < *(uint32 *) d2)	return (-1);    return (0);}static int BandCompare (const void *d1, const void *d2){    if (((struct Band *) d1)->Left > ((struct Band *) d2)->Left)	return (1);    else    if (((struct Band *) d1)->Left < ((struct Band *) d2)->Left)	return (-1);    return (0);}void ComputeClipWindows (){    struct ClipData *pClip = &IPPU.Clip [0];    // Loop around the main screen then the sub-screen.    for (int c = 0; c < 2; c++, pClip++)    {        // Loop around the colour window then a clip window for each of the        // background layers.	for (int w = 5; w >= 0; w--)	{	    pClip->Count[w] = 0;	    if (w == 5) // The colour window...	    {		if (c == 0) // ... on the main screen		{		    if ((Memory.FillRAM [0x2130] & 0xc0) == 0xc0)		    {			// The whole of the main screen is switched off,			// completely clip everything.			for (int i = 0; i < 6; i++)			{			    IPPU.Clip [c].Count [i] = 1;			    IPPU.Clip [c].Left [0][i] = 1;			    IPPU.Clip [c].Right [0][i] = 0;			}			continue;		    }		    else		    if ((Memory.FillRAM [0x2130] & 0xc0) == 0x00)			continue;		}		else		{		    // .. colour window on the sub-screen.		    if ((Memory.FillRAM [0x2130] & 0x30) == 0x30)		    {			// The sub-screen is switched off, completely			// clip everything.			for (int i = 0; i < 6; i++)			{			    IPPU.Clip [1].Count [i] = 1;			    IPPU.Clip [1].Left [0][i] = 1;			    IPPU.Clip [1].Right [0][i] = 0;			}			return;		    }		    else		    if ((Memory.FillRAM [0x2130] & 0x30) == 0x00)			continue;		}	    }	    if (!Settings.DisableGraphicWindows)	    {		if (w == 5 || pClip->Count [5] ||		    (Memory.FillRAM [0x212c + c] & 		     Memory.FillRAM [0x212e + c] & (1 << w)))		{		    struct Band Win1[3];		    struct Band Win2[3];		    uint32 Window1Enabled = 0;		    uint32 Window2Enabled = 0;		    bool8 invert = (w == 5 && 				    ((c == 1 && (Memory.FillRAM [0x2130] & 0x30) == 0x10) ||				     (c == 0 && (Memory.FillRAM [0x2130] & 0xc0) == 0x40)));		    if (w == 5 ||			(Memory.FillRAM [0x212c + c] & Memory.FillRAM [0x212e + c] & (1 << w)))		    {			if (PPU.ClipWindow1Enable [w])			{			    if (!PPU.ClipWindow1Inside [w])			    {				Win1[Window1Enabled].Left = PPU.Window1Left;				Win1[Window1Enabled++].Right = PPU.Window1Right + 1;			    }			    else			    {				if (PPU.Window1Left <= PPU.Window1Right)				{				    if (PPU.Window1Left > 0)				    {					Win1[Window1Enabled].Left = 0;					Win1[Window1Enabled++].Right = PPU.Window1Left;				    }				    if (PPU.Window1Right < 255)				    {					Win1[Window1Enabled].Left = PPU.Window1Right + 1;					Win1[Window1Enabled++].Right = 256;				    }				    if (Window1Enabled == 0)				    {					Win1[Window1Enabled].Left = 1;					Win1[Window1Enabled++].Right = 0;				    }				}				else				{				    // 'outside' a window with no range - 				    // appears to be the whole screen.				    Win1[Window1Enabled].Left = 0;				    Win1[Window1Enabled++].Right = 256;				}			    }			}			if (PPU.ClipWindow2Enable [w])			{			    if (!PPU.ClipWindow2Inside [w])			    {				Win2[Window2Enabled].Left = PPU.Window2Left;				Win2[Window2Enabled++].Right = PPU.Window2Right + 1;			    }			    else			    {				if (PPU.Window2Left <= PPU.Window2Right)				{				    if (PPU.Window2Left > 0)				    {					Win2[Window2Enabled].Left = 0;					Win2[Window2Enabled++].Right = PPU.Window2Left;				    }				    if (PPU.Window2Right < 255)				    {					Win2[Window2Enabled].Left = PPU.Window2Right + 1;					Win2[Window2Enabled++].Right = 256;				    }				    if (Window2Enabled == 0)				    {					Win2[Window2Enabled].Left = 1;					Win2[Window2Enabled++].Right = 0;				    }				}				else				{				    Win2[Window2Enabled].Left = 0;				    Win2[Window2Enabled++].Right = 256;				}			    }			}		    }		    if (Window1Enabled && Window2Enabled)		    {			// Overlap logic			//			// Each window will be in one of three states:			// 1. <no range> (Left > Right. One band)			// 2. |    ----------------             | (Left >= 0, Right <= 255, Left <= Right. One band)			// 3. |------------           ----------| (Left1 == 0, Right1 < Left2; Left2 > Right1, Right2 == 255. Two bands)						struct Band Bands [6];			int B = 0;			switch (PPU.ClipWindowOverlapLogic [w] ^ 1)			{			case CLIP_OR:			    if (Window1Enabled == 1)			    {				if (BAND_EMPTY(Win1[0]))				{				    B = Window2Enabled;				    memmove (Bands, Win2,					     sizeof(Win2[0]) * Window2Enabled);				}				else				{				    if (Window2Enabled == 1)				    {					if (BAND_EMPTY (Win2[0]))					    Bands[B++] = Win1[0];					else					{					    if (BANDS_INTERSECT (Win1[0], Win2[0]))					    {						OR_BANDS(Bands[0],Win1[0], Win2[0])						B = 1;					    }					    else					    {						Bands[B++] = Win1[0];						Bands[B++] = Win2[0];					    }					}				    }				    else				    {					if (BANDS_INTERSECT(Win1[0], Win2[0]))					{					    OR_BANDS(Bands[0], Win1[0], Win2[0])					    if (BANDS_INTERSECT(Win1[0], Win2[1]))						OR_BANDS(Bands[1], Win1[0], Win2[1])					    else						Bands[1] = Win2[1];					    B = 1;					    if (BANDS_INTERSECT(Bands[0], Bands[1]))						OR_BANDS(Bands[0], Bands[0], Bands[1])					    else						B = 2;					}					else					if (BANDS_INTERSECT(Win1[0], Win2[1]))					{					    Bands[B++] = Win2[0];					    OR_BANDS(Bands[B], Win1[0], Win2[1]);					    B++;					}					else					{					    Bands[0] = Win2[0];					    Bands[1] = Win1[0];					    Bands[2] = Win2[1];					    B = 3;					}				    }				}			    }			    else			    if (Window2Enabled == 1)			    {				if (BAND_EMPTY(Win2[0]))				{				    // Window 2 defines an empty range - just				    // use window 1 as the clipping (which				    // could also be empty).				    B = Window1Enabled;				    memmove (Bands, Win1,					     sizeof(Win1[0]) * Window1Enabled);				}				else				{				    // Window 1 has two bands and Window 2 has one.				    // Neither is an empty region.				    if (BANDS_INTERSECT(Win2[0], Win1[0]))				    {					OR_BANDS(Bands[0], Win2[0], Win1[0])					if (BANDS_INTERSECT(Win2[0], Win1[1]))					    OR_BANDS(Bands[1], Win2[0], Win1[1])					else					    Bands[1] = Win1[1];					B = 1;					if (BANDS_INTERSECT(Bands[0], Bands[1]))					    OR_BANDS(Bands[0], Bands[0], Bands[1])					else					    B = 2;				    }				    else				    if (BANDS_INTERSECT(Win2[0], Win1[1]))				    {					Bands[B++] = Win1[0];					OR_BANDS(Bands[B], Win2[0], Win1[1]);					B++;				    }				    else				    {					Bands[0] = Win1[0];					Bands[1] = Win2[0];					Bands[2] = Win1[1];					B = 3;				    }				}			    }			    else			    {				// Both windows have two bands				OR_BANDS(Bands[0], Win1[0], Win2[0]);				OR_BANDS(Bands[1], Win1[1], Win2[1]);				B = 1;				if (BANDS_INTERSECT(Bands[0], Bands[1]))				    OR_BANDS(Bands[0], Bands[0], Bands[1])				else				    B = 2;			    }			    break;			case CLIP_AND:			    if (Window1Enabled == 1)

⌨️ 快捷键说明

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