Beispiel #1
0
CPU::State FifoPlayer::AdvanceFrame()
{
  if (m_CurrentFrame >= m_FrameRangeEnd)
  {
    if (!m_Loop)
      return CPU::State::PowerDown;
    // If there are zero frames in the range then sleep instead of busy spinning
    if (m_FrameRangeStart >= m_FrameRangeEnd)
      return CPU::State::Stepping;

    // When looping, reload the contents of all the BP/CP/CF registers.
    // This ensures that each time the first frame is played back, the state of the
    // GPU is the same for each playback loop.
    m_CurrentFrame = m_FrameRangeStart;
    LoadRegisters();
    LoadTextureMemory();
    FlushWGP();
  }

  if (m_FrameWrittenCb)
    m_FrameWrittenCb();

  if (m_EarlyMemoryUpdates && m_CurrentFrame == m_FrameRangeStart)
    WriteAllMemoryUpdates();

  WriteFrame(m_File->GetFrame(m_CurrentFrame), m_FrameInfo[m_CurrentFrame]);

  ++m_CurrentFrame;
  return CPU::State::Running;
}
Beispiel #2
0
void FifoPlayer::WriteFrame(const FifoFrameInfo &frame, const AnalyzedFrameInfo &info)
{
	// Core timing information
	m_CyclesPerFrame = SystemTimers::GetTicksPerSecond() / 60;
	m_ElapsedCycles = 0;
	m_FrameFifoSize = frame.fifoDataSize;

	// Determine start and end objects
	u32 numObjects = (u32)(info.objectStarts.size());
	u32 drawStart = std::min(numObjects, m_ObjectRangeStart);
	u32 drawEnd = std::min(numObjects - 1, m_ObjectRangeEnd);

	u32 position = 0;
	u32 memoryUpdate = 0;

	// Skip memory updates during frame if true
	if (m_EarlyMemoryUpdates)
	{
		memoryUpdate = (u32)(frame.memoryUpdates.size());
	}

	if (numObjects > 0)
	{
		u32 objectNum = 0;

		// Write fifo data skipping objects before the draw range
		while (objectNum < drawStart)
		{
			WriteFramePart(position, info.objectStarts[objectNum], memoryUpdate, frame, info);

			position = info.objectEnds[objectNum];
			++objectNum;
		}

		// Write objects in draw range
		if (objectNum < numObjects && drawStart <= drawEnd)
		{
			objectNum = drawEnd;
			WriteFramePart(position, info.objectEnds[objectNum], memoryUpdate, frame, info);
			position = info.objectEnds[objectNum];
			++objectNum;
		}

		// Write fifo data skipping objects after the draw range
		while (objectNum < numObjects)
		{
			WriteFramePart(position, info.objectStarts[objectNum], memoryUpdate, frame, info);

			position = info.objectEnds[objectNum];
			++objectNum;
		}
	}

	// Write data after the last object
	WriteFramePart(position, frame.fifoDataSize, memoryUpdate, frame, info);

	FlushWGP();
}
Beispiel #3
0
void FifoPlayer::LoadMemory()
{
	UReg_MSR newMSR;
	newMSR.DR = 1;
	newMSR.IR = 1;
	MSR = newMSR.Hex;
	PowerPC::ppcState.spr[SPR_IBAT0U] = 0x80001fff;
	PowerPC::ppcState.spr[SPR_IBAT0L] = 0x00000002;
	PowerPC::ppcState.spr[SPR_DBAT0U] = 0x80001fff;
	PowerPC::ppcState.spr[SPR_DBAT0L] = 0x00000002;
	PowerPC::ppcState.spr[SPR_DBAT1U] = 0xc0001fff;
	PowerPC::ppcState.spr[SPR_DBAT1L] = 0x0000002a;

	Memory::Clear();

	SetupFifo();

	u32 *regs = m_File->GetBPMem();
	for (int i = 0; i < FifoDataFile::BP_MEM_SIZE; ++i)
	{
		if (ShouldLoadBP(i))
			LoadBPReg(i, regs[i]);
	}

	regs = m_File->GetCPMem();
	LoadCPReg(0x30, regs[0x30]);
	LoadCPReg(0x40, regs[0x40]);
	LoadCPReg(0x50, regs[0x50]);
	LoadCPReg(0x60, regs[0x60]);

	for (int i = 0; i < 8; ++i)
	{
		LoadCPReg(0x70 + i, regs[0x70 + i]);
		LoadCPReg(0x80 + i, regs[0x80 + i]);
		LoadCPReg(0x90 + i, regs[0x90 + i]);
	}

	for (int i = 0; i < 16; ++i)
	{
		LoadCPReg(0xa0 + i, regs[0xa0 + i]);
		LoadCPReg(0xb0 + i, regs[0xb0 + i]);
	}

	regs = m_File->GetXFMem();
	for (int i = 0; i < FifoDataFile::XF_MEM_SIZE; i += 16)
		LoadXFMem16(i, &regs[i]);

	regs = m_File->GetXFRegs();
	for (int i = 0; i < FifoDataFile::XF_REGS_SIZE; ++i)
		LoadXFReg(i, regs[i]);

	FlushWGP();
}
Beispiel #4
0
void FifoPlayer::LoadMemory()
{
	Memory::Clear();

	SetupFifo();

	u32 *regs = m_File->GetBPMem();
	for (int i = 0; i < FifoDataFile::BP_MEM_SIZE; ++i)
	{
		if (ShouldLoadBP(i))
			LoadBPReg(i, regs[i]);
	}

	regs = m_File->GetCPMem();
	LoadCPReg(0x30, regs[0x30]);
	LoadCPReg(0x40, regs[0x40]);
	LoadCPReg(0x50, regs[0x50]);
	LoadCPReg(0x60, regs[0x60]);

	for (int i = 0; i < 8; ++i)
	{
		LoadCPReg(0x70 + i, regs[0x70 + i]);
		LoadCPReg(0x80 + i, regs[0x80 + i]);
		LoadCPReg(0x90 + i, regs[0x90 + i]);
	}

	for (int i = 0; i < 16; ++i)
	{
		LoadCPReg(0xa0 + i, regs[0xa0 + i]);
		LoadCPReg(0xb0 + i, regs[0xb0 + i]);
	}

	regs = m_File->GetXFMem();
	for (int i = 0; i < FifoDataFile::XF_MEM_SIZE; i += 16)
		LoadXFMem16(i, &regs[i]);

	regs = m_File->GetXFRegs();
	for (int i = 0; i < FifoDataFile::XF_REGS_SIZE; ++i)
		LoadXFReg(i, regs[i]);

	FlushWGP();
}
Beispiel #5
0
void FifoPlayer::LoadMemory()
{
  UReg_MSR newMSR;
  newMSR.DR = 1;
  newMSR.IR = 1;
  MSR = newMSR.Hex;
  PowerPC::ppcState.spr[SPR_IBAT0U] = 0x80001fff;
  PowerPC::ppcState.spr[SPR_IBAT0L] = 0x00000002;
  PowerPC::ppcState.spr[SPR_DBAT0U] = 0x80001fff;
  PowerPC::ppcState.spr[SPR_DBAT0L] = 0x00000002;
  PowerPC::ppcState.spr[SPR_DBAT1U] = 0xc0001fff;
  PowerPC::ppcState.spr[SPR_DBAT1L] = 0x0000002a;
  PowerPC::DBATUpdated();
  PowerPC::IBATUpdated();

  SetupFifo();
  LoadRegisters();
  LoadTextureMemory();
  FlushWGP();
}
Beispiel #6
0
void FifoPlayer::SetupFifo()
{
	WriteCP(0x02, 0); // disable read, BP, interrupts
	WriteCP(0x04, 7); // clear overflow, underflow, metrics

	const FifoFrameInfo& frame = m_File->GetFrame(m_CurrentFrame);

	// Set fifo bounds
	WriteCP(0x20, frame.fifoStart);
	WriteCP(0x22, frame.fifoStart >> 16);
	WriteCP(0x24, frame.fifoEnd);
	WriteCP(0x26, frame.fifoEnd >> 16);

	// Set watermarks
	u32 fifoSize = frame.fifoEnd - frame.fifoStart;
	WriteCP(0x28, fifoSize);
	WriteCP(0x2a, fifoSize >> 16);
	WriteCP(0x2c, 0);
	WriteCP(0x2e, 0);

	// Set R/W pointers to fifo start
	WriteCP(0x30, 0);
	WriteCP(0x32, 0);
	WriteCP(0x34, frame.fifoStart);
	WriteCP(0x36, frame.fifoStart >> 16);
	WriteCP(0x38, frame.fifoStart);
	WriteCP(0x3a, frame.fifoStart >> 16);

	// Set fifo bounds
	WritePI(12, frame.fifoStart);
	WritePI(16, frame.fifoEnd);

	// Set write pointer
	WritePI(20, frame.fifoStart);
	FlushWGP();
	WritePI(20, frame.fifoStart);

	WriteCP(0x02, 17); // enable read & GP link
}
Beispiel #7
0
void FifoPlayer::SetupFifo()
{
  WriteCP(CommandProcessor::CTRL_REGISTER, 0);   // disable read, BP, interrupts
  WriteCP(CommandProcessor::CLEAR_REGISTER, 7);  // clear overflow, underflow, metrics

  const FifoFrameInfo& frame = m_File->GetFrame(m_CurrentFrame);

  // Set fifo bounds
  WriteCP(CommandProcessor::FIFO_BASE_LO, frame.fifoStart);
  WriteCP(CommandProcessor::FIFO_BASE_HI, frame.fifoStart >> 16);
  WriteCP(CommandProcessor::FIFO_END_LO, frame.fifoEnd);
  WriteCP(CommandProcessor::FIFO_END_HI, frame.fifoEnd >> 16);

  // Set watermarks, high at 75%, low at 0%
  u32 hi_watermark = (frame.fifoEnd - frame.fifoStart) * 3 / 4;
  WriteCP(CommandProcessor::FIFO_HI_WATERMARK_LO, hi_watermark);
  WriteCP(CommandProcessor::FIFO_HI_WATERMARK_HI, hi_watermark >> 16);
  WriteCP(CommandProcessor::FIFO_LO_WATERMARK_LO, 0);
  WriteCP(CommandProcessor::FIFO_LO_WATERMARK_HI, 0);

  // Set R/W pointers to fifo start
  WriteCP(CommandProcessor::FIFO_RW_DISTANCE_LO, 0);
  WriteCP(CommandProcessor::FIFO_RW_DISTANCE_HI, 0);
  WriteCP(CommandProcessor::FIFO_WRITE_POINTER_LO, frame.fifoStart);
  WriteCP(CommandProcessor::FIFO_WRITE_POINTER_HI, frame.fifoStart >> 16);
  WriteCP(CommandProcessor::FIFO_READ_POINTER_LO, frame.fifoStart);
  WriteCP(CommandProcessor::FIFO_READ_POINTER_HI, frame.fifoStart >> 16);

  // Set fifo bounds
  WritePI(ProcessorInterface::PI_FIFO_BASE, frame.fifoStart);
  WritePI(ProcessorInterface::PI_FIFO_END, frame.fifoEnd);

  // Set write pointer
  WritePI(ProcessorInterface::PI_FIFO_WPTR, frame.fifoStart);
  FlushWGP();
  WritePI(ProcessorInterface::PI_FIFO_WPTR, frame.fifoStart);

  WriteCP(CommandProcessor::CTRL_REGISTER, 17);  // enable read & GP link
}