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

📄 dma.cpp

📁 SFC游戏模拟器 snes9x 1.43 的原代码
💻 CPP
📖 第 1 页 / 共 3 页
字号:
							*(p +  0) = (*(p +  0) << 1) | ((r >> 4) & 1);							*(p +  1) = (*(p +  1) << 1) | ((r >> 5) & 1);							*(p + 16) = (*(p + 16) << 1) | ((r >> 6) & 1);							*(p + 17) = (*(p + 17) << 1) | ((r >> 7) & 1);						}						p += 2;					}					p += 32 - 16;				}			}			break;		case 8:			for (i = 0; i < count; i += inc, base += char_line_bytes, 				inc = char_line_bytes, char_count = num_chars)			{				uint8 *line = base + (num_chars - char_count) * 8;				for (uint32 j = 0; j < char_count && p - buffer < count; 				j++, line += 8)				{					uint8 *q = line;					for (int l = 0; l < 8; l++, q += bytes_per_line)					{						for (int b = 0; b < 8; b++)						{							uint8 r = *(q + b);							*(p +  0) = (*(p +  0) << 1) | ((r >> 0) & 1);							*(p +  1) = (*(p +  1) << 1) | ((r >> 1) & 1);							*(p + 16) = (*(p + 16) << 1) | ((r >> 2) & 1);							*(p + 17) = (*(p + 17) << 1) | ((r >> 3) & 1);							*(p + 32) = (*(p + 32) << 1) | ((r >> 4) & 1);							*(p + 33) = (*(p + 33) << 1) | ((r >> 5) & 1);							*(p + 48) = (*(p + 48) << 1) | ((r >> 6) & 1);							*(p + 49) = (*(p + 49) << 1) | ((r >> 7) & 1);						}						p += 2;					}					p += 64 - 16;				}			}			break;		}    }	#ifdef DEBUGGER    if (Settings.TraceDMA)    {		sprintf (String, "DMA[%d]: %s Mode: %d 0x%02X%04X->0x21%02X Bytes: %d (%s) V-Line:%ld",			Channel, d->TransferDirection ? "read" : "write",			d->TransferMode, d->ABank, d->AAddress,			d->BAddress, d->TransferBytes,			d->AAddressFixed ? "fixed" :		(d->AAddressDecrement ? "dec" : "inc"),			CPU.V_Counter);		if (d->BAddress == 0x18 || d->BAddress == 0x19 || d->BAddress == 0x39 || d->BAddress == 0x3a)			sprintf (String, "%s VRAM: %04X (%d,%d) %s", String,				PPU.VMA.Address,				PPU.VMA.Increment, PPU.VMA.FullGraphicCount,				PPU.VMA.High ? "word" : "byte");		else			if (d->BAddress == 0x22 || d->BAddress == 0x3b)							sprintf (String, "%s CGRAM: %02X (%x)", String, PPU.CGADD,					PPU.CGFLIP);						else				if (d->BAddress == 0x04 || d->BAddress == 0x38)					sprintf (String, "%s OBJADDR: %04X", String, PPU.OAMAddr);				S9xMessage (S9X_TRACE, S9X_DMA_TRACE, String);    }#endif	    if (!d->TransferDirection)    {		/* XXX: DMA is potentially broken here for cases where we DMA across		 * XXX: memmap boundries. A possible solution would be to re-call		 * XXX: GetBasePointer whenever we cross a boundry, and when		 * XXX: GetBasePointer returns (0) to take the 'slow path' and use		 * XXX: S9xGetByte instead of *base. GetBasePointer() would want to		 * XXX: return (0) for MAP_PPU and whatever else is a register range		 * XXX: rather than a RAM/ROM block, and we'd want to detect MAP_PPU		 * XXX: (or specifically, Address Bus B addresses $2100-$21FF in		 * XXX: banks $00-$3F) specially and treat it as MAP_NONE (since		 * XXX: PPU->PPU transfers don't work).		 */		//reflects extra cycle used by DMA		CPU.Cycles += SLOW_ONE_CYCLE * (count+1);		S9xUpdateAPUTimer();		uint8 *base = GetBasePointer ((d->ABank << 16) + d->AAddress);		uint16 p = d->AAddress;				if (!base)			base = Memory.ROM;				if (in_sa1_dma)		{			base = &Memory.ROM [CMemory::MAX_ROM_SIZE - 0x10000];			p = 0;		}				if (in_sdd1_dma)		{			base = in_sdd1_dma;			p = 0;		}		if(spc7110_dma)		{			base=spc7110_dma;			p = 0;		}		if (inc > 0)			d->AAddress += count;		else			if (inc < 0)				d->AAddress -= count;						if (d->TransferMode == 0 || d->TransferMode == 2 || d->TransferMode == 6)			{				switch (d->BAddress)				{				case 0x04:					do					{						Work = *(base + p);						REGISTER_2104(Work);						p += inc;						CHECK_SOUND();					} while (--count > 0);					break;				case 0x18:#ifndef CORRECT_VRAM_READS					IPPU.FirstVRAMRead = TRUE;#endif					if (!PPU.VMA.FullGraphicCount)					{						do						{							Work = *(base + p);							REGISTER_2118_linear(Work);							p += inc;							CHECK_SOUND();						} while (--count > 0);					}					else					{						do						{							Work = *(base + p);							REGISTER_2118_tile(Work);							p += inc;							CHECK_SOUND();						} while (--count > 0);					}					break;				case 0x19:#ifndef CORRECT_VRAM_READS					IPPU.FirstVRAMRead = TRUE;#endif					if (!PPU.VMA.FullGraphicCount)					{						do						{							Work = *(base + p);							REGISTER_2119_linear(Work);							p += inc;							CHECK_SOUND();						} while (--count > 0);					}					else					{						do						{							Work = *(base + p);							REGISTER_2119_tile(Work);							p += inc;							CHECK_SOUND();						} while (--count > 0);					}					break;				case 0x22:					do					{						Work = *(base + p);						REGISTER_2122(Work);						p += inc;						CHECK_SOUND();					} while (--count > 0);					break;				case 0x80:					do					{						Work = *(base + p);						REGISTER_2180(Work);						p += inc;						CHECK_SOUND();					} while (--count > 0);					break;				default:					do					{						Work = *(base + p);						S9xSetPPU (Work, 0x2100 + d->BAddress);						p += inc;						CHECK_SOUND();					} while (--count > 0);					break;				}			}			else				if (d->TransferMode == 1 || d->TransferMode == 5)				{					if (d->BAddress == 0x18)					{						// Write to V-RAM#ifndef CORRECT_VRAM_READS						IPPU.FirstVRAMRead = TRUE;#endif						if (!PPU.VMA.FullGraphicCount)						{							while (count > 1)							{								Work = *(base + p);								REGISTER_2118_linear(Work);								p += inc;																Work = *(base + p);								REGISTER_2119_linear(Work);								p += inc;								CHECK_SOUND();								count -= 2;							}							if (count == 1)							{								Work = *(base + p);								REGISTER_2118_linear(Work);								p += inc;							}						}						else						{							while (count > 1)							{								Work = *(base + p);								REGISTER_2118_tile(Work);								p += inc;																Work = *(base + p);								REGISTER_2119_tile(Work);								p += inc;								CHECK_SOUND();								count -= 2;							}							if (count == 1)							{								Work = *(base + p);								REGISTER_2118_tile(Work);								p += inc;							}						}					}					else					{						// DMA mode 1 general case						while (count > 1)						{							Work = *(base + p);							S9xSetPPU (Work, 0x2100 + d->BAddress);							p += inc;														Work = *(base + p);							S9xSetPPU (Work, 0x2101 + d->BAddress);							p += inc;							CHECK_SOUND();							count -= 2;						}						if (count == 1)						{							Work = *(base + p);							S9xSetPPU (Work, 0x2100 + d->BAddress);							p += inc;						}					}				}				else					if (d->TransferMode == 3 || d->TransferMode == 7)					{						do						{							Work = *(base + p);							S9xSetPPU (Work, 0x2100 + d->BAddress);							p += inc;							if (count <= 1)								break;														Work = *(base + p);							S9xSetPPU (Work, 0x2100 + d->BAddress);							p += inc;							if (count <= 2)								break;														Work = *(base + p);							S9xSetPPU (Work, 0x2101 + d->BAddress);							p += inc;							if (count <= 3)								break;														Work = *(base + p);							S9xSetPPU (Work, 0x2101 + d->BAddress);							p += inc;							CHECK_SOUND();							count -= 4;						} while (count > 0);					}					else						if (d->TransferMode == 4)						{							do							{								Work = *(base + p);								S9xSetPPU (Work, 0x2100 + d->BAddress);								p += inc;								if (count <= 1)									break;																Work = *(base + p);								S9xSetPPU (Work, 0x2101 + d->BAddress);								p += inc;								if (count <= 2)									break;																Work = *(base + p);								S9xSetPPU (Work, 0x2102 + d->BAddress);								p += inc;								if (count <= 3)									break;																Work = *(base + p);								S9xSetPPU (Work, 0x2103 + d->BAddress);								p += inc;								CHECK_SOUND();								count -= 4;							} while (count > 0);						}						else						{#ifdef DEBUGGER							//	    if (Settings.TraceDMA)							{								sprintf (String, "Unknown DMA transfer mode: %d on channel %d\n",									d->TransferMode, Channel);								S9xMessage (S9X_TRACE, S9X_DMA_TRACE, String);							}#endif						}    }    else    {		/* XXX: DMA is potentially broken here for cases where the dest is		 * XXX: in the Address Bus B range. Note that this bad dest may not		 * XXX: cover the whole range of the DMA though, if we transfer		 * XXX: 65536 bytes only 256 of them may be Address Bus B.		 */		do		{			switch (d->TransferMode)			{			case 0:			case 2:			case 6:				Work = S9xGetPPU (0x2100 + d->BAddress);				S9xSetByte (Work, (d->ABank << 16) + d->AAddress);				d->AAddress += inc;				--count;				break;							case 1:			case 5:				Work = S9xGetPPU (0x2100 + d->BAddress);				S9xSetByte (Work, (d->ABank << 16) + d->AAddress);				d->AAddress += inc;				if (!--count)					break;								Work = S9xGetPPU (0x2101 + d->BAddress);				S9xSetByte (Work, (d->ABank << 16) + d->AAddress);				d->AAddress += inc;				count--;				break;							case 3:			case 7:				Work = S9xGetPPU (0x2100 + d->BAddress);				S9xSetByte (Work, (d->ABank << 16) + d->AAddress);				d->AAddress += inc;				if (!--count)					break;				

⌨️ 快捷键说明

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