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

📄 ppu.cpp

📁 著名SFC模拟器Snes9x的源代码。
💻 CPP
📖 第 1 页 / 共 5 页
字号:
/* * 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 "snes9x.h"#include "memmap.h"#include "ppu.h"#include "cpuexec.h"#include "missing.h"#include "apu.h"#include "dma.h"#include "gfx.h"#include "display.h"#include "sa1.h"#include "netplay.h"#include "sdd1.h"#include "srtc.h"#ifndef ZSNES_FX#include "fxemu.h"#include "fxinst.h"extern struct FxInit_s SuperFX;#elseEXTERN_C void S9xSuperFXWriteReg (uint8, uint32);EXTERN_C uint8 S9xSuperFXReadReg (uint32);#endifvoid S9xUpdateHTimer (){    if (PPU.HTimerEnabled)    {#ifdef DEBUGGER	missing.hirq_pos = PPU.IRQHBeamPos;#endif	PPU.HTimerPosition = PPU.IRQHBeamPos * Settings.H_Max / SNES_HCOUNTER_MAX;	if (PPU.HTimerPosition == Settings.H_Max ||	    PPU.HTimerPosition == Settings.HBlankStart)	{	    PPU.HTimerPosition--;	}	if (!PPU.VTimerEnabled || CPU.V_Counter == PPU.IRQVBeamPos)	{	    if (PPU.HTimerPosition <= CPU.Cycles)	    {		// Missed the IRQ on this line already		if (CPU.WhichEvent == HBLANK_END_EVENT ||		    CPU.WhichEvent == HTIMER_AFTER_EVENT)		{		    CPU.WhichEvent = HBLANK_END_EVENT;		    CPU.NextEvent = Settings.H_Max;		}		else		{		    CPU.WhichEvent = HBLANK_START_EVENT;		    CPU.NextEvent = Settings.HBlankStart;		}	    }	    else	    {		if (CPU.WhichEvent == HTIMER_BEFORE_EVENT ||		    CPU.WhichEvent == HBLANK_START_EVENT)		{		    if (PPU.HTimerPosition > Settings.HBlankStart)		    {			// HTimer was to trigger before h-blank start,			// now triggers after start of h-blank			CPU.NextEvent = Settings.HBlankStart;			CPU.WhichEvent = HBLANK_START_EVENT;		    }		    else		    {			CPU.NextEvent = PPU.HTimerPosition;			CPU.WhichEvent = HTIMER_BEFORE_EVENT;		    }		}		else		{		    CPU.WhichEvent = HTIMER_AFTER_EVENT;		    CPU.NextEvent = PPU.HTimerPosition;		}	    }	}    }}void S9xFixColourBrightness (){    IPPU.XB = mul_brightness [PPU.Brightness];    if (Settings.SixteenBit)    {	for (int i = 0; i < 256; i++)	{	    IPPU.Red [i] = IPPU.XB [PPU.CGDATA [i] & 0x1f];	    IPPU.Green [i] = IPPU.XB [(PPU.CGDATA [i] >> 5) & 0x1f];	    IPPU.Blue [i] = IPPU.XB [(PPU.CGDATA [i] >> 10) & 0x1f];	    IPPU.ScreenColors [i] = BUILD_PIXEL (IPPU.Red [i], IPPU.Green [i],						 IPPU.Blue [i]);	}    }}/**********************************************************************************************//* S9xSetPPU()                                                                                   *//* This function sets a PPU Register to a specific byte                                       *//**********************************************************************************************/void S9xSetPPU (uint8 Byte, uint16 Address){    if (Address <= 0x2183)    {    switch (Address)    {    case 0x2100:	// Brightness and screen blank bit	if (Byte != Memory.FillRAM [0x2100])	{	    FLUSH_REDRAW ();	    if (PPU.Brightness != (Byte & 0xF))	    {		IPPU.ColorsChanged = TRUE;		IPPU.DirectColourMapsNeedRebuild = TRUE;		PPU.Brightness = Byte & 0xF;		S9xFixColourBrightness ();		if (PPU.Brightness > IPPU.MaxBrightness)		    IPPU.MaxBrightness = PPU.Brightness;	    }	    if ((Memory.FillRAM[0x2100] & 0x80) != (Byte & 0x80))	    {		IPPU.ColorsChanged = TRUE;		PPU.ForcedBlanking = (Byte >> 7) & 1;	    }	}	break;    case 0x2101:	// Sprite (OBJ) tile address	if (Byte != Memory.FillRAM [0x2101])	{	    FLUSH_REDRAW ();	    PPU.OBJNameBase   = (Byte & 3) << 14;	    PPU.OBJNameSelect = ((Byte >> 3) & 3) << 13;	    PPU.OBJSizeSelect = (Byte >> 5) & 7;	    IPPU.OBJChanged = TRUE;	}	break;    case 0x2102:	// Sprite write address (low)	PPU.OAMAddr = Byte;	PPU.OAMFlip = 2;	PPU.OAMReadFlip = 0;	PPU.SavedOAMAddr = PPU.OAMAddr;	if (PPU.OAMPriorityRotation)	{	    PPU.FirstSprite = PPU.OAMAddr & 0x7f;#ifdef DEBUGGER	    missing.sprite_priority_rotation = 1;#endif	}	break;    case 0x2103:	// Sprite register write address (high), sprite priority rotation	// bit.	if ((PPU.OAMPriorityRotation = (Byte & 0x80) == 0 ? 0 : 1))	{	    PPU.FirstSprite = PPU.OAMAddr & 0x7f;#ifdef DEBUGGER	    missing.sprite_priority_rotation = 1;#endif	}	// Only update the sprite write address top bit if the low byte has	// been written to first.	if (PPU.OAMFlip & 2)	{	    PPU.OAMAddr &= 0x00FF;	    PPU.OAMAddr |= (Byte & 1) << 8;	}	PPU.OAMFlip = 0;	PPU.OAMReadFlip = 0;	PPU.SavedOAMAddr = PPU.OAMAddr;	break;    case 0x2104:	// Sprite register write	REGISTER_2104(Byte);	break;    case 0x2105:	// Screen mode (0 - 7), background tile sizes and background 3	// priority	if (Byte != Memory.FillRAM [0x2105])	{	    FLUSH_REDRAW ();	    PPU.BG3Priority  = (Byte >> 3) & 1;	    PPU.BG[0].BGSize = (Byte >> 4) & 1;	    PPU.BG[1].BGSize = (Byte >> 5) & 1;	    PPU.BG[2].BGSize = (Byte >> 6) & 1;	    PPU.BG[3].BGSize = (Byte >> 7) & 1;	    PPU.BGMode = Byte & 7;#ifdef DEBUGGER	    missing.modes[PPU.BGMode] = 1;#endif	}	break;    case 0x2106:	// Mosaic pixel size and enable	if (Byte != Memory.FillRAM [0x2106])	{	    FLUSH_REDRAW ();#ifdef DEBUGGER	    if ((Byte & 0xf0) && (Byte & 0x0f))		missing.mosaic = 1;#endif	    PPU.Mosaic = (Byte >> 4) + 1;	    PPU.BGMosaic [0] = (Byte & 1) && PPU.Mosaic > 1;	    PPU.BGMosaic [1] = (Byte & 2) && PPU.Mosaic > 1;	    PPU.BGMosaic [2] = (Byte & 4) && PPU.Mosaic > 1;	    PPU.BGMosaic [3] = (Byte & 8) && PPU.Mosaic > 1;	}	break;    case 0x2107:		// [BG0SC]	if (Byte != Memory.FillRAM [0x2107])	{	    FLUSH_REDRAW ();	    PPU.BG[0].SCSize = Byte & 3;	    PPU.BG[0].SCBase = (Byte & 0x7c) << 8;	}	break;    case 0x2108:		// [BG1SC]	if (Byte != Memory.FillRAM [0x2108])	{	    FLUSH_REDRAW ();	    PPU.BG[1].SCSize = Byte & 3;	    PPU.BG[1].SCBase = (Byte & 0x7c) << 8;	}	break;    case 0x2109:		// [BG2SC]	if (Byte != Memory.FillRAM [0x2109])	{	    FLUSH_REDRAW ();	    PPU.BG[2].SCSize = Byte & 3;	    PPU.BG[2].SCBase = (Byte & 0x7c) << 8;	}	break;    case 0x210A:		// [BG3SC]	if (Byte != Memory.FillRAM [0x210a])	{	    FLUSH_REDRAW ();	    PPU.BG[3].SCSize = Byte & 3;	    PPU.BG[3].SCBase = (Byte & 0x7c) << 8;	}	break;    case 0x210B:		// [BG01NBA]	if (Byte != Memory.FillRAM [0x210b])	{	    FLUSH_REDRAW ();	    PPU.BG[0].NameBase    = (Byte & 7) << 12;	    PPU.BG[1].NameBase    = ((Byte >> 4) & 7) << 12;	}	break;    case 0x210C:		// [BG23NBA]	if (Byte != Memory.FillRAM [0x210c])	{	    FLUSH_REDRAW ();	    PPU.BG[2].NameBase    = (Byte & 7) << 12;	    PPU.BG[3].NameBase    = ((Byte >> 4) & 7) << 12;	}	break;    case 0x210D:	PPU.BG[0].HOffset = ((PPU.BG[0].HOffset >> 8) & 0xff) |	    ((uint16) Byte << 8);	break;    case 0x210E:	PPU.BG[0].VOffset = ((PPU.BG[0].VOffset >> 8) & 0xff) |	    ((uint16) Byte << 8);	break;    case 0x210F:	PPU.BG[1].HOffset = ((PPU.BG[1].HOffset >> 8) & 0xff) |	    ((uint16) Byte << 8);	break;    case 0x2110:	PPU.BG[1].VOffset = ((PPU.BG[1].VOffset >> 8) & 0xff) |	    ((uint16) Byte << 8);	break;    case 0x2111:	PPU.BG[2].HOffset = ((PPU.BG[2].HOffset >> 8) & 0xff) |	    ((uint16) Byte << 8);	break;    case 0x2112:	PPU.BG[2].VOffset = ((PPU.BG[2].VOffset >> 8) & 0xff) |	    ((uint16) Byte << 8);	break;    case 0x2113:	PPU.BG[3].HOffset = ((PPU.BG[3].HOffset >> 8) & 0xff) |	    ((uint16) Byte << 8);	break;    case 0x2114:	PPU.BG[3].VOffset = ((PPU.BG[3].VOffset >> 8) & 0xff) |	    ((uint16) Byte << 8);	break;    case 0x2115:	// VRAM byte/word access flag and increment	PPU.VMA.High = (Byte & 0x80) == 0 ? FALSE : TRUE;	switch (Byte & 3)	{	case 0:	    PPU.VMA.Increment = 1;	    break;	case 1:	    PPU.VMA.Increment = 32;	    break;	case 2:	    PPU.VMA.Increment = 128;	    break;	case 3:	    PPU.VMA.Increment = 128;	    break;	}#ifdef DEBUGGER	if ((Byte & 3) != 0)	    missing.vram_inc = Byte & 3;#endif	if (Byte & 0x0c)	{	    static uint16 IncCount [4] = { 0, 32, 64, 128 };	    static uint16 Shift [4] = { 0, 5, 6, 7 };#ifdef DEBUGGER	    missing.vram_full_graphic_inc = (Byte & 0x0c) >> 2;#endif	    PPU.VMA.Increment = 1;	    uint8 i = (Byte & 0x0c) >> 2;	    PPU.VMA.FullGraphicCount = IncCount [i];	    PPU.VMA.Mask1 = IncCount [i] * 8 - 1;	    PPU.VMA.Shift = Shift [i];	}	else	    PPU.VMA.FullGraphicCount = 0;	break;    case 0x2116:	// VRAM read/write address (low)	PPU.VMA.Address &= 0xFF00;	PPU.VMA.Address |= Byte;	IPPU.FirstVRAMRead = TRUE;	break;    case 0x2117:	// VRAM read/write address (high)	PPU.VMA.Address &= 0x00FF;	PPU.VMA.Address |= Byte << 8;	IPPU.FirstVRAMRead = TRUE;	break;    case 0x2118:	// VRAM write data (low)	IPPU.FirstVRAMRead = TRUE;	REGISTER_2118(Byte);	break;    case 0x2119:	// VRAM write data (high)	IPPU.FirstVRAMRead = TRUE;	REGISTER_2119(Byte);	break;    case 0x211a:	// Mode 7 outside rotation area display mode and flipping	if (Byte != Memory.FillRAM [0x211a])	{	    FLUSH_REDRAW ();	    PPU.Mode7Repeat = Byte >> 6;	    PPU.Mode7VFlip = (Byte & 2) >> 1;	    PPU.Mode7HFlip = Byte & 1;	}	break;    case 0x211b:	// Mode 7 matrix A (low & high)	PPU.MatrixA = ((PPU.MatrixA >> 8) & 0xff) | (Byte << 8);	PPU.Need16x8Mulitply = TRUE;	break;    case 0x211c:	// Mode 7 matrix B (low & high)	PPU.MatrixB = ((PPU.MatrixB >> 8) & 0xff) | (Byte << 8);	PPU.Need16x8Mulitply = TRUE;	break;    case 0x211d:	// Mode 7 matrix C (low & high)	PPU.MatrixC = ((PPU.MatrixC >> 8) & 0xff) | (Byte << 8);	break;    case 0x211e:	// Mode 7 matrix D (low & high)	PPU.MatrixD = ((PPU.MatrixD >> 8) & 0xff) | (Byte << 8);	break;    case 0x211f:	// Mode 7 centre of rotation X (low & high)	PPU.CentreX = ((PPU.CentreX >> 8) & 0xff) | (Byte << 8);	break;    case 0x2120:	// Mode 7 centre of rotation Y (low & high)	PPU.CentreY = ((PPU.CentreY >> 8) & 0xff) | (Byte << 8);	break;    case 0x2121:	// CG-RAM address	PPU.CGFLIP = 0;	PPU.CGFLIPRead = 0;	PPU.CGADD = Byte;	break;    case 0x2122:	REGISTER_2122(Byte);	break;    case 0x2123:	// Window 1 and 2 enable for backgrounds 1 and 2	if (Byte != Memory.FillRAM [0x2123])	{	    FLUSH_REDRAW ();	    PPU.ClipWindow1Enable [0] = !!(Byte & 0x02);	    PPU.ClipWindow1Enable [1] = !!(Byte & 0x20);	    PPU.ClipWindow2Enable [0] = !!(Byte & 0x08);	    PPU.ClipWindow2Enable [1] = !!(Byte & 0x80);	    PPU.ClipWindow1Inside [0] = !(Byte & 0x01);	    PPU.ClipWindow1Inside [1] = !(Byte & 0x10);	    PPU.ClipWindow2Inside [0] = !(Byte & 0x04);	    PPU.ClipWindow2Inside [1] = !(Byte & 0x40);	    PPU.RecomputeClipWindows = TRUE;#ifdef DEBUGGER	    if (Byte & 0x80)		missing.window2[1] = 1;	    if (Byte & 0x20)		missing.window1[1] = 1;	    if (Byte & 0x08)		missing.window2[0] = 1;	    if (Byte & 0x02)		missing.window1[0] = 1;#endif	}	break;    case 0x2124:	// Window 1 and 2 enable for backgrounds 3 and 4	if (Byte != Memory.FillRAM [0x2124])	{	    FLUSH_REDRAW ();	    PPU.ClipWindow1Enable [2] = !!(Byte & 0x02);	    PPU.ClipWindow1Enable [3] = !!(Byte & 0x20);	    PPU.ClipWindow2Enable [2] = !!(Byte & 0x08);	    PPU.ClipWindow2Enable [3] = !!(Byte & 0x80);	    PPU.ClipWindow1Inside [2] = !(Byte & 0x01);	    PPU.ClipWindow1Inside [3] = !(Byte & 0x10);	    PPU.ClipWindow2Inside [2] = !(Byte & 0x04);	    PPU.ClipWindow2Inside [3] = !(Byte & 0x40);	    PPU.RecomputeClipWindows = TRUE;#ifdef DEBUGGER	    if (Byte & 0x80)		missing.window2[3] = 1;	    if (Byte & 0x20)		missing.window1[3] = 1;	    if (Byte & 0x08)		missing.window2[2] = 1;	    if (Byte & 0x02)		missing.window1[2] = 1;#endif

⌨️ 快捷键说明

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