Пример #1
0
int cellGcmInit(u32 context_addr, u32 cmdSize, u32 ioSize, u32 ioAddress)
{
	cellGcmSys.Warning("cellGcmInit(context_addr=0x%x,cmdSize=0x%x,ioSize=0x%x,ioAddress=0x%x)", context_addr, cmdSize, ioSize, ioAddress);

	if(!local_size && !local_addr)
	{
		local_size = 0xf900000; //TODO
		local_addr = Memory.RSXFBMem.GetStartAddr();
		Memory.RSXFBMem.Alloc(local_size);
	}

	cellGcmSys.Warning("*** local memory(addr=0x%x, size=0x%x)", local_addr, local_size);

	map_offset_addr = 0;
	map_offset_pos = 0;
	current_config.ioSize = re32(ioSize);
	current_config.ioAddress = re32(ioAddress);
	current_config.localSize = re32(local_size);
	current_config.localAddress = re32(local_addr);
	current_config.memoryFrequency = re32(650000000);
	current_config.coreFrequency = re32(500000000);

	InitOffsetTable();
	Memory.RSXCMDMem.Alloc(cmdSize);
	Memory.MemoryBlocks.push_back(Memory.RSXIOMem.SetRange(0xE0000000, 0x10000000/*256MB*/));//TODO: implement allocateAdressSpace in memoryBase
	cellGcmMapEaIoAddress(ioAddress, ioSize, 0);

	u32 ctx_begin = ioAddress/* + 0x1000*/;
	u32 ctx_size = 0x6ffc;
	current_context.begin = re(ctx_begin);
	current_context.end = re(ctx_begin + ctx_size);
	current_context.current = current_context.begin;
	current_context.callback = re32(Emu.GetRSXCallback() - 4);

	gcm_info.context_addr = Memory.MainMem.Alloc(0x1000);
	gcm_info.control_addr = gcm_info.context_addr + 0x40;

	Memory.WriteData(gcm_info.context_addr, current_context);
	Memory.Write32(context_addr, gcm_info.context_addr);

	CellGcmControl& ctrl = (CellGcmControl&)Memory[gcm_info.control_addr];
	ctrl.put = 0;
	ctrl.get = 0;
	ctrl.ref = -1;

	auto& render = Emu.GetGSManager().GetRender();
	render.m_ctxt_addr = context_addr;
	render.m_gcm_buffers_addr = Memory.Alloc(sizeof(gcmBuffer) * 8, sizeof(gcmBuffer));
	render.m_zculls_addr = Memory.Alloc(sizeof(CellGcmZcullInfo) * 8, sizeof(CellGcmZcullInfo));
	render.m_tiles_addr = Memory.Alloc(sizeof(CellGcmTileInfo) * 15, sizeof(CellGcmTileInfo));
	render.m_gcm_buffers_count = 0;
	render.m_gcm_current_buffer = 0;
	render.m_main_mem_info.Clear();
	render.m_main_mem_addr = 0;
	render.Init(ctx_begin, ctx_size, gcm_info.control_addr, local_addr);

	return CELL_OK;
}
Пример #2
0
void MemoryBase::WriteMMIO32(u32 addr, const u32 data)
{
	{
		std::lock_guard<std::recursive_mutex> lock(m_mutex);

		if (RawSPUMem[(addr - RAW_SPU_BASE_ADDR) / RAW_SPU_OFFSET] &&
			RawSPUMem[(addr - RAW_SPU_BASE_ADDR) / RAW_SPU_OFFSET]->Write32(addr, data))
		{
			return;
		}
	}

	*(u32*)((u8*)GetBaseAddr() + addr) = re32(data); // provoke error
}
Пример #3
0
void MemoryBase::WriteMMIO32(u32 addr, const u32 data)
{
	{
		LV2_LOCK(0);

		if (RawSPUMem[(addr - RAW_SPU_BASE_ADDR) / RAW_SPU_OFFSET] &&
			((RawSPUThread*)RawSPUMem[(addr - RAW_SPU_BASE_ADDR) / RAW_SPU_OFFSET])->Write32(addr, data))
		{
			return;
		}
	}

	*(u32*)((u8*)GetBaseAddr() + addr) = re32(data); // provoke error
}
Пример #4
0
u32 MemoryBase::ReadMMIO32(u32 addr)
{
	u32 res;
	{
		std::lock_guard<std::recursive_mutex> lock(m_mutex);

		if (RawSPUMem[(addr - RAW_SPU_BASE_ADDR) / RAW_SPU_OFFSET] &&
			RawSPUMem[(addr - RAW_SPU_BASE_ADDR) / RAW_SPU_OFFSET]->Read32(addr, &res))
		{
			return res;
		}
	}

	res = re32(*(u32*)((u8*)GetBaseAddr() + addr)); // provoke error
	return res;
}
Пример #5
0
int cellGcmInit(u32 context_addr, u32 cmdSize, u32 ioSize, u32 ioAddress)
{
	cellGcmSys.Log("cellGcmInit(context_addr=0x%x,cmdSize=0x%x,ioSize=0x%x,ioAddress=0x%x)", context_addr, cmdSize, ioSize, ioAddress);

	const u32 local_size = 0xf900000; //TODO
	const u32 local_addr = Memory.RSXFBMem.GetStartAddr();

	map_offset_addr = 0;
	map_offset_pos = 0;
	current_config.ioSize = re32(ioSize);
	current_config.ioAddress = re32(ioAddress);
	current_config.localSize = re32(local_size);
	current_config.localAddress = re32(local_addr);
	current_config.memoryFrequency = re32(650000000);
	current_config.coreFrequency = re32(500000000);

	Memory.RSXFBMem.Alloc(local_size);
	Memory.RSXCMDMem.Alloc(cmdSize);

	u32 ctx_begin = ioAddress/* + 0x1000*/;
	u32 ctx_size = 0x6ffc;
	current_context.begin = re(ctx_begin);
	current_context.end = re(ctx_begin + ctx_size);
	current_context.current = current_context.begin;
	current_context.callback = re32(Emu.GetRSXCallback() - 4);

	gcm_info.context_addr = Memory.MainMem.Alloc(0x1000);
	gcm_info.control_addr = gcm_info.context_addr + 0x40;

	Memory.WriteData(gcm_info.context_addr, current_context);
	Memory.Write32(context_addr, gcm_info.context_addr);

	CellGcmControl& ctrl = (CellGcmControl&)Memory[gcm_info.control_addr];
	ctrl.put = 0;
	ctrl.get = 0;
	ctrl.ref = -1;

	auto& render = Emu.GetGSManager().GetRender();
	render.m_ctxt_addr = context_addr;
	render.m_gcm_buffers_addr = Memory.Alloc(sizeof(gcmBuffer) * 8, sizeof(gcmBuffer));
	render.m_zculls_addr = Memory.Alloc(sizeof(CellGcmZcullInfo) * 8, sizeof(CellGcmZcullInfo));
	render.m_tiles_addr = Memory.Alloc(sizeof(CellGcmTileInfo) * 15, sizeof(CellGcmTileInfo));
	render.m_gcm_buffers_count = 0;
	render.m_gcm_current_buffer = 0;
	render.m_main_mem_info.Clear();
	render.m_main_mem_addr = 0;
	render.Init(ctx_begin, ctx_size, gcm_info.control_addr, local_addr);

	return CELL_OK;
}
Пример #6
0
u32 MemoryBase::ReadMMIO32(u32 addr)
{
	u32 res;
	{
		LV2_LOCK(0);

		if (RawSPUMem[(addr - RAW_SPU_BASE_ADDR) / RAW_SPU_OFFSET] &&
			((RawSPUThread*)RawSPUMem[(addr - RAW_SPU_BASE_ADDR) / RAW_SPU_OFFSET])->Read32(addr, &res))
		{
			return res;
		}
	}

	res = re32(*(u32*)((u8*)GetBaseAddr() + addr)); // provoke error
	return res;
}
Пример #7
0
u32 Memory::read32(u32 addr)
{
    return re32(*(u32*)((u64)m_base + addr));
}
Пример #8
0
void Memory::write32(u32 addr, u32 value)
{
    *(u32*)((u64)m_base + addr) = re32(value);
}
Пример #9
0
int sdata_unpack(const std::string& packed_file, const std::string& unpacked_file)
{
	std::shared_ptr<vfsFileBase> packed_stream(Emu.GetVFS().OpenFile(packed_file, vfsRead));
	std::shared_ptr<vfsFileBase> unpacked_stream(Emu.GetVFS().OpenFile(unpacked_file, vfsWrite));
	
	if(!packed_stream || !packed_stream->IsOpened())
	{
		sys_fs.Error("'%s' not found! flags: 0x%08x", packed_file.c_str(), vfsRead);
		return CELL_ENOENT;
	}

	if(!unpacked_stream || !unpacked_stream->IsOpened())
	{
		sys_fs.Error("'%s' couldn't be created! flags: 0x%08x", unpacked_file.c_str(), vfsWrite);
		return CELL_ENOENT;
	}

	char buffer [10200];
	packed_stream->Read(buffer, 256);
	u32 format = re32(*(u32*)&buffer[0]);
	if (format != 0x4E504400) // "NPD\x00"
	{
		sys_fs.Error("Illegal format. Expected 0x4E504400, but got 0x%08x", format);
		return CELL_EFSSPECIFIC;
	}

	u32 version	       = re32(*(u32*)&buffer[0x04]);
	u32 flags          = re32(*(u32*)&buffer[0x80]);
	u32 blockSize      = re32(*(u32*)&buffer[0x84]);
	u64 filesizeOutput = re64(*(u64*)&buffer[0x88]);
	u64 filesizeInput  = packed_stream->GetSize();
	u32 blockCount     = (filesizeOutput + blockSize-1) / blockSize;

	// SDATA file is compressed
	if (flags & 0x1)
	{
		sys_fs.Warning("cellFsSdataOpen: Compressed SDATA files are not supported yet.");
		return CELL_EFSSPECIFIC;
	}

	// SDATA file is NOT compressed
	else 
	{
		u32 t1 = (flags & 0x20) ? 0x20 : 0x10;
		u32 startOffset = (blockCount * t1) + 0x100;
		u64 filesizeTmp = (filesizeOutput+0xF)&0xFFFFFFF0 + startOffset;

		if (!sdata_check(version, flags, filesizeInput, filesizeTmp))
		{
			sys_fs.Error("cellFsSdataOpen: Wrong header information.");
			return CELL_EFSSPECIFIC;
		}
	
		if (flags & 0x20)
			packed_stream->Seek(0x100);
		else
			packed_stream->Seek(startOffset);

		for (u32 i = 0; i < blockCount; i++)
		{
			if (flags & 0x20)
				packed_stream->Seek(packed_stream->Tell() + t1);

			if (!(blockCount-i-1))
				blockSize = filesizeOutput-i*blockSize;

			packed_stream->Read(buffer+256, blockSize);
			unpacked_stream->Write(buffer+256, blockSize);
		}
	}

	return CELL_OK;
}
Пример #10
0
__forceinline void Write32(const fs::file& f, const u32 data)
{
	Write32LE(f, re32(data));
}
Пример #11
0
__forceinline void Write32(vfsStream& f, const u32 data)
{
	Write32LE(f, re32(data));
}
Пример #12
0
void StaticAnalyse(void* ptr, u32 size, u32 base)
{
	u32* data = (u32*)ptr; size /= 4;

	if(!Ini.HLEHookStFunc.GetValue())
		return;

	// TODO: optimize search
	for (u32 i = 0; i < size; i++)
	{
		for (u32 j = 0; j < g_static_funcs_list.GetCount(); j++)
		{
			if ((data[i] & g_static_funcs_list[j].ops[0].mask) == g_static_funcs_list[j].ops[0].crc)
			{
				bool found = true;
				u32 can_skip = 0;
				for (u32 k = i, x = 0; x + 1 <= g_static_funcs_list[j].ops.GetCount(); k++, x++)
				{
					if (k >= size)
					{
						found = false;
						break;
					}

					// skip NOP
					if (data[k] == se32(0x60000000)) 
					{
						x--;
						continue;
					}

					const u32 mask = g_static_funcs_list[j].ops[x].mask;
					const u32 crc = g_static_funcs_list[j].ops[x].crc;

					if (!mask)
					{
						// TODO: define syntax
						if (crc < 4) // skip various number of instructions that don't match next pattern entry
						{
							can_skip += crc;
							k--; // process this position again
						}
						else if (data[k] != crc) // skippable pattern ("optional" instruction), no mask allowed
						{
							k--;
							if (can_skip) // cannot define this behaviour properly
							{
								ConLog.Warning("StaticAnalyse(): can_skip = %d (unchanged)", can_skip);
							}
						}
						else
						{
							if (can_skip) // cannot define this behaviour properly
							{
								ConLog.Warning("StaticAnalyse(): can_skip = %d (set to 0)", can_skip);
								can_skip = 0;
							}
						}
					}
					else if ((data[k] & mask) != crc) // masked pattern
					{
						if (can_skip)
						{
							can_skip--;
						}
						else
						{
							found = false;
							break;
						}
					}
					else
					{
						can_skip = 0;
					}
				}
				if (found)
				{
					ConLog.Write("Function '%s' hooked (addr=0x%x)", g_static_funcs_list[j].name, i * 4 + base);
					g_static_funcs_list[j].found++;
					data[i+0] = re32(0x39600000 | j); // li r11, j
					data[i+1] = se32(0x44000003); // sc 3
					data[i+2] = se32(0x4e800020); // blr
					i += 2; // skip modified code
				}
			}
		}
	}

	// check function groups
	for (u32 i = 0; i < g_static_funcs_list.GetCount(); i++)
	{
		if (g_static_funcs_list[i].found) // start from some group
		{
			const u64 group = g_static_funcs_list[i].group;

			enum GroupSearchResult : u32
			{
				GSR_SUCCESS = 0, // every function from this group has been found once
				GSR_MISSING = 1, // (error) some function not found
				GSR_EXCESS = 2, // (error) some function found twice or more
			};
			u32 res = GSR_SUCCESS;

			// analyse
			for (u32 j = i; j < g_static_funcs_list.GetCount(); j++) if (g_static_funcs_list[j].group == group)
			{
				u32 count = g_static_funcs_list[j].found;

				if (count == 0) // not found
				{
					// check if this function has been found with different pattern
					for (u32 k = i; k < g_static_funcs_list.GetCount(); k++) if (g_static_funcs_list[k].group == group)
					{
						if (k != j && g_static_funcs_list[k].ptr == g_static_funcs_list[j].ptr)
						{
							count += g_static_funcs_list[k].found;
						}
					}
					if (count == 0)
					{
						res |= GSR_MISSING;
						ConLog.Error("Function '%s' not found", g_static_funcs_list[j].name);
					}
					else if (count > 1)
					{
						res |= GSR_EXCESS;
					}
				}
				else if (count == 1) // found
				{
					// ensure that this function has NOT been found with different pattern
					for (u32 k = i; k < g_static_funcs_list.GetCount(); k++) if (g_static_funcs_list[k].group == group)
					{
						if (k != j && g_static_funcs_list[k].ptr == g_static_funcs_list[j].ptr)
						{
							if (g_static_funcs_list[k].found)
							{
								res |= GSR_EXCESS;
								ConLog.Error("Function '%s' hooked twice", g_static_funcs_list[j].name);
							}
						}
					}
				}
				else
				{
					res |= GSR_EXCESS;
					ConLog.Error("Function '%s' hooked twice", g_static_funcs_list[j].name);
				}
			}

			// clear data
			for (u32 j = i; j < g_static_funcs_list.GetCount(); j++)
			{
				if (g_static_funcs_list[j].group == group) g_static_funcs_list[j].found = 0;
			}

			char name[9] = "????????";

			*(u64*)name = group;

			if (res == GSR_SUCCESS)
			{
				ConLog.Success("Function group [%s] successfully hooked", std::string(name, 9).c_str());
			}
			else
			{
				ConLog.Error("Function group [%s] failed:%s%s", std::string(name, 9).c_str(),
					(res & GSR_MISSING ? " missing;" : ""),
					(res & GSR_EXCESS ? " excess;" : ""));
			}
		}
	}
}