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

📄 dma.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 "snes9x.h"#include "memmap.h"#include "ppu.h"#include "cpuexec.h"#include "missing.h"#include "dma.h"#include "apu.h"#include "gfx.h"#include "sa1.h"extern int HDMA_ModeByteCounts [8];extern uint8 *HDMAMemPointers [8];extern uint8 *HDMABasePointers [8];/**********************************************************************************************//* S9xDoDMA()                                                                                   *//* This function preforms the general dma transfer                                            *//**********************************************************************************************/void S9xDoDMA (uint8 Channel){    uint8 Work;    if (Channel > 7 || CPU.InDMA)	return;    CPU.InDMA = TRUE;    bool8 in_sa1_dma = FALSE;    SDMA *d = &DMA[Channel];    int count = d->TransferBytes;    if (count == 0)	count = 0x10000;    int inc = d->AAddressFixed ? 0 : (!d->AAddressDecrement ? 1 : -1);    switch (d->BAddress)    {    case 0x18:    case 0x19:	if (IPPU.RenderThisFrame)	    FLUSH_REDRAW ();    if (Settings.SDD1 && d->AAddressFixed && 	Memory.BlockIsROM [((d->ABank << 16) + d->AAddress) >> 12])    {	inc = !d->AAddressDecrement ? 1 : -1;//    if (d->BAddress == 0x18 && Settings.SDD1 && d->AAddressFixed)//    {//	printf ("%02x%04x, count: %d\n", d->ABank, d->AAddress, d->TransferBytes);#if 0	uint8 *base = GetBasePointer ((d->ABank << 16) + d->AAddress) + d->AAddress;	for (int i = 0; i < 16; i++)	    printf ("%02x ", *base++);	printf ("\n");#endif    }	break;    }    if (d->BAddress == 0x18 && SA1.in_char_dma && (d->ABank & 0xf0) == 0x40)    {	// Perform packed bitmap to PPU character format conversion on the	// data before transmitting it to V-RAM via-DMA.	int num_chars = 1 << ((Memory.FillRAM [0x2231] >> 2) & 7);	int depth = (Memory.FillRAM [0x2231] & 3) == 0 ? 8 :		    (Memory.FillRAM [0x2231] & 3) == 1 ? 4 : 2;	int bytes_per_char = 8 * depth;	int bytes_per_line = depth * num_chars;	int char_line_bytes = bytes_per_char * num_chars;	uint32 addr = (d->AAddress / char_line_bytes) * char_line_bytes;	uint8 *base = GetBasePointer ((d->ABank << 16) + addr) + addr;	uint8 *buffer = &Memory.ROM [CMemory::MAX_ROM_SIZE - 0x10000];	uint8 *p = buffer;	uint32 inc = char_line_bytes - (d->AAddress % char_line_bytes);	uint32 char_count = inc / bytes_per_char;	in_sa1_dma = TRUE;	//printf ("%08x,", base); fflush (stdout);//printf ("depth = %d, count = %d, bytes_per_char = %d, bytes_per_line = %d, num_chars = %d, char_line_bytes = %d\n",//depth, count, bytes_per_char, bytes_per_line, num_chars, char_line_bytes);	int i;	switch (depth)	{	case 2:	    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) * 2;		for (uint32 j = 0; j < char_count && p - buffer < count; 		     j++, line += 2)		{		    uint8 *q = line;		    for (int l = 0; l < 8; l++, q += bytes_per_line)		    {			for (int b = 0; b < 2; b++)			{			    uint8 r = *(q + b);			    *(p + 0) = (*(p + 0) << 1) | ((r >> 0) & 1);			    *(p + 1) = (*(p + 1) << 1) | ((r >> 1) & 1);			    *(p + 0) = (*(p + 0) << 1) | ((r >> 2) & 1);			    *(p + 1) = (*(p + 1) << 1) | ((r >> 3) & 1);			    *(p + 0) = (*(p + 0) << 1) | ((r >> 4) & 1);			    *(p + 1) = (*(p + 1) << 1) | ((r >> 5) & 1);			    *(p + 0) = (*(p + 0) << 1) | ((r >> 6) & 1);			    *(p + 1) = (*(p + 1) << 1) | ((r >> 7) & 1);			}			p += 2;		    }		}	    }	    break;	case 4:	    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) * 4;		for (uint32 j = 0; j < char_count && p - buffer < count; 		     j++, line += 4)		{		    uint8 *q = line;		    for (int l = 0; l < 8; l++, q += bytes_per_line)		    {			for (int b = 0; b < 4; 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 +  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)	    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)	    sprintf (String, "%s CGRAM: %02X (%x)", String, PPU.CGADD,		     PPU.CGFLIP);	else	if (d->BAddress == 0x04)	    sprintf (String, "%s OBJADDR: %04X", String, PPU.OAMAddr);	S9xMessage (S9X_TRACE, S9X_DMA_TRACE, String);    }#endif    if (!d->TransferDirection)    {#ifdef VAR_CYCLES	CPU.Cycles += 8 * count;#else	CPU.Cycles += count + (count >> 2);#endif	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 (inc > 0)	    d->AAddress += count;	else	if (inc < 0)	    d->AAddress -= count;	if (d->TransferMode == 0 || d->TransferMode == 2)	{	    switch (d->BAddress)	    {	    case 0x04:		do		{		    Work = *(base + p);		    REGISTER_2104(Work);		    p += inc;		    CHECK_SOUND();		} while (--count > 0);		break;	    case 0x18:		IPPU.FirstVRAMRead = TRUE;		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:		IPPU.FirstVRAMRead = TRUE;		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		IPPU.FirstVRAMRead = TRUE;		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;

⌨️ 快捷键说明

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