示例#1
0
		public static MemoryBlock ReadStream(Stream stream, int length)
		{
			MemoryBlock memoryBlock;

			// Initialize variables
			memoryBlock = null;

			try
			{
				// Create the memory block once the file has been successfully opened
				memoryBlock = new MemoryBlock((int)length);

				// Read the file using the extension method defined below
				stream.Read(memoryBlock, 0, memoryBlock.Length);
			}
			catch
			{
				// Dispose the memory if needed
				if (memoryBlock != null)
					memoryBlock.Dispose();

				throw;
			}
			finally
			{
				// Close the file
				stream.Close();
			}

			return memoryBlock;
		}
示例#2
0
		/// <summary>Initializes a new instance of the <see cref="GameBoyMemoryBus"/> class, preloaded with an external ROM.</summary>
		/// <param name="externalRom">The external ROM to load.</param>
		public GameBoyMemoryBus(MemoryBlock externalRom)
		{
			try
			{
				Initialize();
				LoadRom(externalRom);
			}
			catch { Dispose(); }
		}
示例#3
0
		public unsafe VideoStatusSnapshot(GameBoyMemoryBus bus)
		{
			this.bus = bus;
			this.videoMemoryBlock = new MemoryBlock(bus.VideoRam.Length);
			this.VideoMemory = (byte*)this.videoMemoryBlock.Pointer;
			this.objectAttributeMemoryBlock = new MemoryBlock(0xA0); // Do not allocate more bytes than needed… GameBoyMemoryBus allocates 0x100 because of the segmented memory.
			this.ObjectAttributeMemory = (byte*)this.objectAttributeMemoryBlock.Pointer;
			this.paletteMemoryBlock = new MemoryBlock(bus.PaletteMemory.Length);
			this.PaletteMemory = (byte*)this.paletteMemoryBlock.Pointer;
		}
示例#4
0
		public CodeMap(MemoryBlock rom)
		{
			if (rom == null)
				throw new ArgumentNullException("rom");
			if (rom.Length < 32768) // Refuse to analyze a ROM smaller than 32 KB
				throw new InvalidOperationException();

			this.rom = rom;
			labelDictionary = new Dictionary<int, Label>();
			instructionList = new List<Instruction>();
			analyzeThread = new Thread(Analyze);
			asyncResult = new AsyncResult();
		}
示例#5
0
		private void LoadRom(string fileName)
		{
			FileInfo fileInfo = new FileInfo(fileName);

			// Open only existing rom files
			if (!fileInfo.Exists)
				throw new FileNotFoundException();
			// Limit the rom size to 4 Mb
			if (fileInfo.Length > 4 * 1024 * 1024)
				throw new FileTooLongException();
			rom = MemoryUtility.ReadFile(fileInfo);
			memory = new FlexibleGameBoyMemory(rom);
			disassemblyView.Memory = memory;
			codeMap = new CodeMap(rom);
		}
		partial void InitializeMemory()
		{
			// Use a RNG for uninitialized RAM simulation
			random = new Random();

			unsafe
			{
				segmentWriteHandlerArray = new MemoryWriteHandler[256];

				segmentMemoryBlock = new MemoryBlock(256 * sizeof(byte*)); // Allocate a memory segment table (256 segments)
				segmentArray = (byte**)segmentMemoryBlock.Pointer;

				externalRamBlock = new MemoryBlock(131072); // 128Kb maximum

				videoMemoryBlock = new MemoryBlock(16384); // 8Kb banks (only in CGB mode)
				videoMemory = (byte*)videoMemoryBlock.Pointer;

				workMemoryBlock = new MemoryBlock(32768); // 4Kb banks (switchable in CGB mode)
				workMemory = (byte*)workMemoryBlock.Pointer;

				objectAttributeMemoryBlock = new MemoryBlock(256); // 256 bytes of OAM
				objectAttributeMemory = (byte*)objectAttributeMemoryBlock.Pointer;

				portMemoryBlock = new MemoryBlock(256); // 256 bytes of High RAM
				portMemory = (byte*)portMemoryBlock.Pointer;

				paletteMemoryBlock = new MemoryBlock(16 * 4 * sizeof(ushort)); // 128 bytes of palette ram (only for CGB)
				paletteMemory = (byte*)paletteMemoryBlock.Pointer;

				generalMemoryBlock = new MemoryBlock(512); // 256 bytes of register memory and 256 bytes of 'trash' memory
				externalPortMemory = (byte*)generalMemoryBlock.Pointer;
				trashMemory = (byte*)generalMemoryBlock.Pointer + 256;

				dmgBootMemoryBlock = new MemoryBlock(0x100);
				dmgBootMemory = (byte*)dmgBootMemoryBlock.Pointer;
				sgbBootMemoryBlock = new MemoryBlock(0x100);
				sgbBootMemory = (byte*)sgbBootMemoryBlock.Pointer;
				cgbBootMemoryBlock = new MemoryBlock(0x800);
				cgbBootMemory = (byte*)cgbBootMemoryBlock.Pointer;
			}

			ResetSegments();
			ResetWriteHandlers();
		}
示例#7
0
		public static unsafe int Read(this Stream stream, MemoryBlock memoryBlock, int offset, int length)
		{
			byte* pMemory;
			int bytesRead, bytesToRead, totalBytesRead;
			byte[] buffer;

			if (memoryBlock == null)
				throw new ArgumentNullException();
			if (offset >= memoryBlock.Length && length != 0)
				throw new ArgumentOutOfRangeException("offset");
			if (length < 0 || offset + length > memoryBlock.Length)
				throw new ArgumentOutOfRangeException("length");

			// Get a pointer to the memory block
			pMemory = (byte*)memoryBlock.Pointer + offset;

			// Obtain a reference to the buffer (lazy allocation)
			buffer = Buffer;

			totalBytesRead = 0;
			bytesToRead = Math.Min(bufferLength, length);

			// Read the file in chunks
			fixed (byte* pBuffer = buffer)
			{
				while ((bytesRead = stream.Read(buffer, 0, bytesToRead)) > 0)
				{
					MemoryBlock.Copy(pMemory, pBuffer, bytesRead);
					totalBytesRead += bytesRead;
					pMemory += bytesRead;
					length -= bytesRead;
					if (length < bytesToRead)
						bytesToRead = length;
				}
			}

			return totalBytesRead;
		}
示例#8
0
		public static void Set(MemoryBlock destination, int destinationOffset, byte value, int length)
		{
			if (destination.memoryPointer == null)
				throw new InvalidOperationException();
			if (destinationOffset < 0)
				throw new ArgumentOutOfRangeException("destinationOffset");
			if (length < 0)
				throw new ArgumentOutOfRangeException("length");

			Memory.Set((byte*)destination.memoryPointer + destinationOffset, value, (uint)length);
		}
示例#9
0
		public static void Copy(MemoryBlock destination, int destinationOffset, MemoryBlock source, int sourceOffset, int length)
		{
			if (destination.memoryPointer == null || source.memoryPointer == null)
				throw new InvalidOperationException();
			if (destinationOffset < 0)
				throw new ArgumentOutOfRangeException("destinationOffset");
			if (sourceOffset < 0)
				throw new ArgumentOutOfRangeException("sourceOffset");
			if (length < 0)
				throw new ArgumentOutOfRangeException("length");

			Memory.Copy((byte*)destination.memoryPointer + destinationOffset, (byte*)source.memoryPointer + sourceOffset, length);
		}
示例#10
0
		public FlexibleGameBoyMemory(MemoryBlock externalRom)
		{
			this.externalRom = externalRom;
			this.externalRomBank = 1;
		}
示例#11
0
		public unsafe AudioStatusSnapshot(GameBoyMemoryBus bus)
		{
			this.bus = bus;
			this.wavePatternMemoryBlock = new MemoryBlock(16);
			this.WavePatternMemory = (byte*)this.wavePatternMemoryBlock.Pointer;
		}
示例#12
0
		public static unsafe void Write(this BinaryWriter writer, MemoryBlock memoryBlock, int offset, int length)
		{
			byte* pMemory;
			int bytesLeft,
				bytesToWrite;
			byte[] buffer;

			if (memoryBlock == null)
				throw new ArgumentNullException("memoryBlock");
			if (offset >= memoryBlock.Length && length != 0)
				throw new ArgumentOutOfRangeException("offset");
			if (length < 0 || offset + length > memoryBlock.Length)
				throw new ArgumentOutOfRangeException("length");

			// Initialize variables
			bytesLeft = length;
			bytesToWrite = bufferLength;

			// Get a pointer to the memory block
			pMemory = (byte*)memoryBlock.Pointer + offset;

			// Obtain a reference to the buffer (lazy allocation)
			buffer = Buffer;

			// Write the file in chunks
			fixed (byte* pBuffer = buffer)
			{
				while (bytesLeft > 0)
				{
					if (bytesLeft < bytesToWrite)
						bytesToWrite = bytesLeft;
					Memory.Copy(pBuffer, pMemory, (uint)bytesToWrite);
					writer.Write(buffer, 0, bytesToWrite);
					pMemory += bytesToWrite;
					bytesLeft -= bytesToWrite;
				}
			}
		}
示例#13
0
		public static unsafe void WriteFile(FileInfo fileInfo, MemoryBlock memoryBlock)
		{
			FileStream fileStream;

			if (fileInfo == null)
				throw new ArgumentNullException("fileInfo");
			if (memoryBlock == null)
				throw new ArgumentNullException("memoryBlock");

			// Open the file in exclusive mode
			using (fileStream = fileInfo.Open(FileMode.Open, FileAccess.Write, FileShare.Read))
				fileStream.Write(memoryBlock, 0, memoryBlock.Length);
		}
		partial void ResetMemory()
		{
			// Reallocate the RAM block if the Mapper request more memory than currently allocated
			if (mapper != null && mapper.RamSize > externalRamBlock.Length)
			{
				externalRamBlock.Dispose();
				externalRamBlock = new MemoryBlock(mapper.RamSize);
			}
			
			// Fill various RAM areas with random data at “boot” time
			// This allows for erasing the previous game residual information.
			unsafe
			{
				// Fill the video RAM.
				RandomFill(videoMemory, videoMemoryBlock.Length);
				// Fill the OAM.
				RandomFill(objectAttributeMemory, objectAttributeMemoryBlock.Length);
				// Fill the “trash” memory. (Invalid memory)
				RandomFill(trashMemory, 256);
			}

			videoRamBank = 0;
			workRamBank = 1;
			internalRomMapped = false;

			ResetSegments();
			ResetWriteHandlers();
		}
示例#15
0
		public void LoadRom(MemoryBlock externalRom)
		{
			RomInformation romInformation;

			if (externalRom == null) throw new ArgumentNullException("externalRom");

			if ((externalRom.Length & 0x3FFF) != 0
				|| (externalRom.Length >> 14) > 256)
				throw new InvalidOperationException();

			romInformation = new RomInformation(externalRom);

			if (romInformation.RomSize != externalRom.Length) throw new InvalidOperationException();

			Mapper mapper;

			switch (romInformation.RomType)
			{
				case RomType.RomOnly:
				case RomType.RomRam:
				case RomType.RomRamBattery:
					mapper = new Mappers.RomController(this);
					break;
				case RomType.RomMbc1:
				case RomType.RomMbc1Ram:
				case RomType.RomMbc1RamBattery:
					mapper = new Mappers.MemoryBankController1(this);
					break;
				case RomType.RomMbc2:
				case RomType.RomMbc2Battery:
					mapper = new Mappers.MemoryBankController2(this);
					break;
				case RomType.RomMbc3:
				case RomType.RomMbc3Ram:
				case RomType.RomMbc3RamBattery:
				case RomType.RomMbc3TimerBattery:
				case RomType.RomMbc3TimerRamBattery:
					mapper = new Mappers.MemoryBankController3(this);
					break;
				case RomType.RomMbc5:
				case RomType.RomMbc5Ram:
				case RomType.RomMbc5RamBattery:
				case RomType.RomMbc5Rumble:
				case RomType.RomMbc5RumbleRam:
				case RomType.RomMbc5RumbleRamBattery:
					mapper = new Mappers.MemoryBankController5(this);
					break;
				default:
					throw new NotSupportedException("Unsupported Cartidge Type");
			}

#if WITH_THREADING
			SuspendEmulation();
#endif

			this.romInformation = romInformation;
			this.externalRomBlock = externalRom;
			this.mapper = mapper;
			this.colorMode = ColorHardware & romInformation.ColorGameBoySupport;

#if WITH_DEBUGGING
			ClearBreakpoints();
#endif
			Reset(); // Will call “ResumeEmulation”…

			// Fills the external RAM with random data.
			// It can be loaded with real data later.
			unsafe { RandomFill((byte*)externalRamBlock.Pointer, externalRamBlock.Length); }

			romLoaded = true;
		}
示例#16
0
		public void LoadRom(MemoryBlock rom)
		{
			emulationStatus = EmulationStatus.Stopped;
			bus.LoadRom(rom);
			emulationStatus = EmulationStatus.Paused;
			OnRomChanged(EventArgs.Empty);
		}