Ejemplo n.º 1
0
    /**
* Parse attribute AS_PATH data
*
* \param [in]   attr_len       Length of the attribute data
* \param [in]   data           Pointer to the attribute data
* \param [out]  parsed_update  Reference to parsed_update; will be updated with all parsed data
*/
void parseBgpLib::parseAttrDataAsPath(uint16_t attr_len, u_char *data, parsed_update &update) {
    int         path_len    = attr_len;
    u_char      seg_type;
    u_char      seg_len;
    uint32_t    seg_asn;
    uint32_t    origin_asn = -1;

    if (path_len < 4) // Nothing to parse if length doesn't include at least one asn
        return;

    update.attrs[LIB_ATTR_AS_PATH].official_type = ATTR_TYPE_AS_PATH;
    update.attrs[LIB_ATTR_AS_PATH].name = parse_bgp_lib::parse_bgp_lib_attr_names[LIB_ATTR_AS_PATH];

    /*
* Per draft-ietf-grow-bmp, UPDATES must be sent as 4-octet, but this requires the
*    UPDATE to be modified. In draft 14 a new peer header flag indicates size, but
*    not all implementations support this draft yet.
*
*    IOS XE/XR does not modify the UPDATE and therefore a peers
*    that is using 2-octet ASN's will not be parsed correctly.  Global instance var
*    four_octet_asn is used to check if the OPEN cap sent/recv 4-octet or not. A compliant
*    BMP implementation will still use 4-octet even if the peer is 2-octet, so a check is
*    needed to see if the as path is encoded using 4 or 2 octet. This check is only done
*    once.
*
*    This is temporary and can be removed after all implementations are complete with bmp draft 14 or greater.
*/
    if (p_info and not p_info->checked_asn_octet_length and not four_octet_asn)
    {
        /*
         * Loop through each path segment
         */
        u_char *d_ptr = data;
        while (path_len > 0) {
            d_ptr++; // seg_type
            seg_len = *d_ptr++;

            path_len -= 2 + (seg_len * 4);

            if (path_len >= 0)
                d_ptr += seg_len * 4;
        }

        if (path_len != 0) {
            LOG_INFO("%sUsing 2-octet ASN path parsing", debug_prepend_string.c_str());
            p_info->using_2_octet_asn = true;
        }
        p_info->checked_asn_octet_length = true;         // No more checking needed
        path_len = attr_len;                                // Put the path length back to starting value
    }

    // Define the octet size by known/detected size
    if (p_info)
        asn_octet_size = (p_info->using_2_octet_asn and not four_octet_asn) ? 2 : 4;

    /*
         * Loop through each path segment
         */
    while (path_len > 0) {

        seg_type = *data++;
        seg_len  = *data++;                  // Count of AS's, not bytes
        path_len -= 2;
        std::string decoded_path;

        if (seg_type == 1) {                 // If AS-SET open with a brace
            decoded_path.append(" {");
        }

        SELF_DEBUG("%sas_path seg_len = %d seg_type = %d, path_len = %d total_len = %d as_octet_size = %d", debug_prepend_string.c_str(),
                   seg_len, seg_type, path_len, attr_len, asn_octet_size);

        if ((seg_len * asn_octet_size) > path_len){

            LOG_NOTICE("%sCould not parse the AS PATH due to update message buffer being too short when using ASN octet size %d",
                       debug_prepend_string.c_str(), asn_octet_size);
            LOG_NOTICE("%sSwitching encoding size to 2-octet due to parsing failure", debug_prepend_string.c_str());

            asn_octet_size = 2;
        }

        // The rest of the data is the as path sequence, in blocks of 2 or 4 bytes
        for (; seg_len > 0; seg_len--) {
            seg_asn = 0;
            memcpy(&seg_asn, data, asn_octet_size);
            data += asn_octet_size;
            path_len -= asn_octet_size;                               // Adjust the path length for what was read

            parse_bgp_lib::SWAP_BYTES(&seg_asn, asn_octet_size);
            std::ostringstream numString;
            numString << seg_asn;
            if (seg_type == 2) {
                update.attrs[LIB_ATTR_AS_PATH].value.push_back(numString.str());
                origin_asn = seg_asn;
            } else if (seg_type == 1) {
                decoded_path.append(", ");
                decoded_path.append(numString.str());
            } else {
                std::cout << "Malformed AS path segment of type: " << static_cast<int>(seg_type) <<std::endl;
            }
        }

        if (seg_type == 1) {            // If AS-SET close with a brace
            decoded_path.append(" }");
            update.attrs[LIB_ATTR_AS_PATH].value.push_back(decoded_path);
        }
    }

        if (origin_asn >= 0) {
            update.attrs[LIB_ATTR_AS_ORIGIN].name = parse_bgp_lib::parse_bgp_lib_attr_names[LIB_ATTR_AS_ORIGIN];
            std::ostringstream numString;
            numString << origin_asn;
            update.attrs[LIB_ATTR_AS_ORIGIN].value.push_back(numString.str());
        }

    SELF_DEBUG("%sParsed AS_PATH count %d, origin as: %s", debug_prepend_string.c_str(), update.attrs[LIB_ATTR_AS_PATH].value.size(),
               update.attrs[LIB_ATTR_AS_PATH].value.size() > 0 ? update.attrs[LIB_ATTR_AS_PATH].value.front().c_str() : "NULL");
}
Ejemplo n.º 2
0
void Emulator::Load()
{
	Stop();

	try
	{
		Init();

		// Open SELF or ELF
		fs::file elf_file(m_path);

		if (!elf_file)
		{
			LOG_ERROR(LOADER, "Failed to open file: %s", m_path);
			return;
		}

		LOG_NOTICE(LOADER, "Path: %s", m_path);

		const std::string elf_dir = fs::get_parent_dir(m_path);
		const fs::file sfov(elf_dir + "/sce_sys/param.sfo");
		const fs::file sfo1(elf_dir + "/../PARAM.SFO");

		// Load PARAM.SFO (TODO)
		const auto _psf = psf::load_object(sfov ? sfov : sfo1);
		m_title = psf::get_string(_psf, "TITLE", m_path);
		m_title_id = psf::get_string(_psf, "TITLE_ID");

		LOG_NOTICE(LOADER, "Title: %s", GetTitle());
		LOG_NOTICE(LOADER, "Serial: %s", GetTitleID());

		// Initialize data/cache directory
		m_cache_path = fs::get_data_dir(m_title_id, m_path);
		LOG_NOTICE(LOADER, "Cache: %s", GetCachePath());

		// Load custom config-0
		if (fs::file cfg_file{m_cache_path + "/config.yml"})
		{
			LOG_NOTICE(LOADER, "Applying custom config: %s/config.yml", m_cache_path);
			g_cfg.from_string(cfg_file.to_string());
		}

		// Load custom config-1
		if (fs::file cfg_file{fs::get_config_dir() + "data/" + m_title_id + "/config.yml"})
		{
			LOG_NOTICE(LOADER, "Applying custom config: data/%s/config.yml", m_title_id);
			g_cfg.from_string(cfg_file.to_string());
		}

		// Load custom config-2
		if (fs::file cfg_file{m_path + ".yml"})
		{
			LOG_NOTICE(LOADER, "Applying custom config: %s.yml", m_path);
			g_cfg.from_string(cfg_file.to_string());
		}

		LOG_NOTICE(LOADER, "Used configuration:\n%s\n", g_cfg.to_string());

		// Load patches from different locations
		fxm::check_unlocked<patch_engine>()->append(fs::get_config_dir() + "data/" + m_title_id + "/patch.yml");
		fxm::check_unlocked<patch_engine>()->append(m_cache_path + "/patch.yml");

		// Mount all devices
		const std::string emu_dir_ = g_cfg.vfs.emulator_dir;
		const std::string emu_dir = emu_dir_.empty() ? fs::get_config_dir() : emu_dir_;
		const std::string home_dir = g_cfg.vfs.app_home;
		std::string bdvd_dir = g_cfg.vfs.dev_bdvd;

		vfs::mount("dev_hdd0", fmt::replace_all(g_cfg.vfs.dev_hdd0, "$(EmulatorDir)", emu_dir));
		vfs::mount("dev_hdd1", fmt::replace_all(g_cfg.vfs.dev_hdd1, "$(EmulatorDir)", emu_dir));
		vfs::mount("dev_flash", fmt::replace_all(g_cfg.vfs.dev_flash, "$(EmulatorDir)", emu_dir));
		vfs::mount("dev_usb", fmt::replace_all(g_cfg.vfs.dev_usb000, "$(EmulatorDir)", emu_dir));
		vfs::mount("dev_usb000", fmt::replace_all(g_cfg.vfs.dev_usb000, "$(EmulatorDir)", emu_dir));
		vfs::mount("app_home", home_dir.empty() ? elf_dir + '/' : fmt::replace_all(home_dir, "$(EmulatorDir)", emu_dir));

		// Mount /dev_bdvd/ if necessary
		if (bdvd_dir.empty()) 
		{
			size_t pos = elf_dir.rfind("PS3_GAME");
			std::string temp = elf_dir.substr(0, pos);
			if ((pos != std::string::npos) && fs::is_file(temp + "/PS3_DISC.SFB")) {
				bdvd_dir = temp;
			}
		}
		if (!bdvd_dir.empty() && fs::is_dir(bdvd_dir))
		{
			vfs::mount("dev_bdvd", fmt::replace_all(bdvd_dir, "$(EmulatorDir)", emu_dir));
			LOG_NOTICE(LOADER, "Disc: %s", vfs::get("/dev_bdvd"));
		}

		// Mount /host_root/ if necessary
		if (g_cfg.vfs.host_root)
		{
			vfs::mount("host_root", {});
		}

		// Check SELF header
		if (elf_file.size() >= 4 && elf_file.read<u32>() == "SCE\0"_u32)
		{
			const std::string decrypted_path = m_cache_path + "boot.elf";

			fs::stat_t encrypted_stat = elf_file.stat();
			fs::stat_t decrypted_stat;

			// Check modification time and try to load decrypted ELF
			if (fs::stat(decrypted_path, decrypted_stat) && decrypted_stat.mtime == encrypted_stat.mtime)
			{
				elf_file.open(decrypted_path);
			}
			else
			{
				// Decrypt SELF
				elf_file = decrypt_self(std::move(elf_file));

				if (fs::file elf_out{decrypted_path, fs::rewrite})
				{
					elf_out.write(elf_file.to_vector<u8>());
					elf_out.close();
					fs::utime(decrypted_path, encrypted_stat.atime, encrypted_stat.mtime);
				}
				else
				{
					LOG_ERROR(LOADER, "Failed to create boot.elf");
				}
			}
		}

		ppu_exec_object ppu_exec;
		ppu_prx_object ppu_prx;
		spu_exec_object spu_exec;
		arm_exec_object arm_exec;

		if (!elf_file)
		{
			LOG_ERROR(LOADER, "Failed to decrypt SELF: %s", m_path);
			return;
		}
		else if (ppu_exec.open(elf_file) == elf_error::ok)
		{
			// PS3 executable
			g_system = system_type::ps3;
			m_state = system_state::ready;
			GetCallbacks().on_ready();

			vm::ps3::init();

			if (m_elf_path.empty())
			{
				if (!bdvd_dir.empty() && fs::is_dir(bdvd_dir))
				{
					//Disc games are on /dev_bdvd/
					size_t pos = m_path.rfind("PS3_GAME");
					m_elf_path = "/dev_bdvd/" + m_path.substr(pos);
				}
				else if (m_path.find(vfs::get("/dev_hdd0/game/")) != -1)
				{
					m_elf_path = "/dev_hdd0/game/" + m_path.substr(vfs::get("/dev_hdd0/game/").size());
				}
				else
				{
					//For homebrew
					m_elf_path = "/host_root/" + m_path;
				}

				LOG_NOTICE(LOADER, "Elf path: %s", m_elf_path);
			}

			ppu_load_exec(ppu_exec);

			fxm::import<GSRender>(Emu.GetCallbacks().get_gs_render); // TODO: must be created in appropriate sys_rsx syscall
		}
		else if (ppu_prx.open(elf_file) == elf_error::ok)
		{
			// PPU PRX (experimental)
			g_system = system_type::ps3;
			m_state = system_state::ready;
			GetCallbacks().on_ready();
			vm::ps3::init();
			ppu_load_prx(ppu_prx, "");
		}
		else if (spu_exec.open(elf_file) == elf_error::ok)
		{
			// SPU executable (experimental)
			g_system = system_type::ps3;
			m_state = system_state::ready;
			GetCallbacks().on_ready();
			vm::ps3::init();
			spu_load_exec(spu_exec);
		}
		else if (arm_exec.open(elf_file) == elf_error::ok)
		{
			// ARMv7 executable
			g_system = system_type::psv;
			m_state = system_state::ready;
			GetCallbacks().on_ready();
			vm::psv::init();

			if (m_elf_path.empty())
			{
				m_elf_path = "host_root:" + m_path;
				LOG_NOTICE(LOADER, "Elf path: %s", m_elf_path);
			}

			arm_load_exec(arm_exec);
		}
		else
		{
			LOG_ERROR(LOADER, "Invalid or unsupported file format: %s", m_path);

			LOG_WARNING(LOADER, "** ppu_exec -> %s", ppu_exec.get_error());
			LOG_WARNING(LOADER, "** ppu_prx  -> %s", ppu_prx.get_error());
			LOG_WARNING(LOADER, "** spu_exec -> %s", spu_exec.get_error());
			LOG_WARNING(LOADER, "** arm_exec -> %s", arm_exec.get_error());
			return;
		}

		if (g_cfg.misc.autostart && IsReady())
		{
			Run();
		}
		else if (IsPaused())
		{
			m_state = system_state::ready;
			GetCallbacks().on_ready();
		}
	}
	catch (const std::exception& e)
	{
		LOG_FATAL(LOADER, "%s thrown: %s", typeid(e).name(), e.what());
		Stop();
	}
}
Ejemplo n.º 3
0
void Emulator::Load(bool add_only)
{
	Stop();

	try
	{
		Init();

		// Load game list (maps ABCD12345 IDs to /dev_bdvd/ locations) 
		YAML::Node games = YAML::Load(fs::file{fs::get_config_dir() + "/games.yml", fs::read + fs::create}.to_string());

		if (!games.IsMap())
		{
			games.reset();
		}

		LOG_NOTICE(LOADER, "Path: %s", m_path);

		const std::string elf_dir = fs::get_parent_dir(m_path);

		// Load PARAM.SFO (TODO)
		const auto _psf = psf::load_object([&]
		{
			if (fs::file sfov{elf_dir + "/sce_sys/param.sfo"})
			{
				return sfov;
			}
			else
			{
				return fs::file(elf_dir + "/../PARAM.SFO");
			}
		}());
		m_title = psf::get_string(_psf, "TITLE", m_path);
		m_title_id = psf::get_string(_psf, "TITLE_ID");
		const auto _cat = psf::get_string(_psf, "CATEGORY");

		LOG_NOTICE(LOADER, "Title: %s", GetTitle());
		LOG_NOTICE(LOADER, "Serial: %s", GetTitleID());

		// Initialize data/cache directory
		m_cache_path = fs::get_data_dir(m_title_id, m_path);
		LOG_NOTICE(LOADER, "Cache: %s", GetCachePath());

		// Load custom config-0
		if (fs::file cfg_file{m_cache_path + "/config.yml"})
		{
			LOG_NOTICE(LOADER, "Applying custom config: %s/config.yml", m_cache_path);
			g_cfg.from_string(cfg_file.to_string());
		}

		// Load custom config-1
		if (fs::file cfg_file{fs::get_config_dir() + "data/" + m_title_id + "/config.yml"})
		{
			LOG_NOTICE(LOADER, "Applying custom config: data/%s/config.yml", m_title_id);
			g_cfg.from_string(cfg_file.to_string());
		}

		// Load custom config-2
		if (fs::file cfg_file{m_path + ".yml"})
		{
			LOG_NOTICE(LOADER, "Applying custom config: %s.yml", m_path);
			g_cfg.from_string(cfg_file.to_string());
		}

		LOG_NOTICE(LOADER, "Used configuration:\n%s\n", g_cfg.to_string());

		// Load patches from different locations
		fxm::check_unlocked<patch_engine>()->append(fs::get_config_dir() + "data/" + m_title_id + "/patch.yml");
		fxm::check_unlocked<patch_engine>()->append(m_cache_path + "/patch.yml");

		// Mount all devices
		const std::string emu_dir_ = g_cfg.vfs.emulator_dir;
		const std::string emu_dir = emu_dir_.empty() ? fs::get_config_dir() : emu_dir_;
		const std::string home_dir = g_cfg.vfs.app_home;
		std::string bdvd_dir = g_cfg.vfs.dev_bdvd;

		vfs::mount("dev_hdd0", fmt::replace_all(g_cfg.vfs.dev_hdd0, "$(EmulatorDir)", emu_dir));
		vfs::mount("dev_hdd1", fmt::replace_all(g_cfg.vfs.dev_hdd1, "$(EmulatorDir)", emu_dir));
		vfs::mount("dev_flash", fmt::replace_all(g_cfg.vfs.dev_flash, "$(EmulatorDir)", emu_dir));
		vfs::mount("dev_usb", fmt::replace_all(g_cfg.vfs.dev_usb000, "$(EmulatorDir)", emu_dir));
		vfs::mount("dev_usb000", fmt::replace_all(g_cfg.vfs.dev_usb000, "$(EmulatorDir)", emu_dir));
		vfs::mount("app_home", home_dir.empty() ? elf_dir + '/' : fmt::replace_all(home_dir, "$(EmulatorDir)", emu_dir));

		// Detect boot location
		const std::string hdd0_game = vfs::get("/dev_hdd0/game/");
		const std::string hdd0_disc = vfs::get("/dev_hdd0/disc/");

		if (_cat == "DG" && m_path.find(hdd0_game + m_title_id + '/') != -1)
		{
			// Booting disc game from wrong location
			LOG_ERROR(LOADER, "Disc game found at invalid location: /dev_hdd0/game/%s/", m_title_id);

			// Move and retry from correct location
			if (fs::rename(hdd0_game + m_title_id, hdd0_disc + m_title_id))
			{
				LOG_SUCCESS(LOADER, "Disc game moved to special location: /dev_hdd0/disc/%s/", m_title_id);
				return SetPath(hdd0_disc + m_path.substr(hdd0_game.size())), Load();
			}
			else
			{
				LOG_ERROR(LOADER, "Failed to move disc game to /dev_hdd0/disc/%s/ (%s)", m_title_id, fs::g_tls_error);
				return;
			}
		}

		// Booting disc game
		if (_cat == "DG" && bdvd_dir.empty())
		{
			// Mount /dev_bdvd/ if necessary
			if (auto pos = elf_dir.rfind("/PS3_GAME") + 1)
			{
				bdvd_dir = elf_dir.substr(0, pos);
			}
		}

		// Booting patch data
		if (_cat == "GD" && bdvd_dir.empty())
		{
			// Load /dev_bdvd/ from game list if available
			if (auto node = games[m_title_id])
			{
				bdvd_dir = node.Scalar();
			}
			else
			{
				LOG_FATAL(LOADER, "Disc directory not found. Try to run the game from the actual game disc directory.");
			}
		}

		// Check /dev_bdvd/
		if (!bdvd_dir.empty() && fs::is_dir(bdvd_dir))
		{
			fs::file sfb_file;

			vfs::mount("dev_bdvd", bdvd_dir);
			LOG_NOTICE(LOADER, "Disc: %s", vfs::get("/dev_bdvd"));

			if (!sfb_file.open(vfs::get("/dev_bdvd/PS3_DISC.SFB")) || sfb_file.size() < 4 || sfb_file.read<u32>() != ".SFB"_u32)
			{
				LOG_ERROR(LOADER, "Invalid disc directory for the disc game %s", m_title_id);
				return;
			}

			const std::string bdvd_title_id = psf::get_string(psf::load_object(fs::file{vfs::get("/dev_bdvd/PS3_GAME/PARAM.SFO")}), "TITLE_ID");

			if (bdvd_title_id != m_title_id)
			{
				LOG_ERROR(LOADER, "Unexpected disc directory for the disc game %s (found %s)", m_title_id, bdvd_title_id);
				return;
			}

			// Store /dev_bdvd/ location
			games[m_title_id] = bdvd_dir;
			YAML::Emitter out;
			out << games;
			fs::file(fs::get_config_dir() + "/games.yml", fs::rewrite).write(out.c_str(), out.size());
		}
		else if (_cat == "DG" || _cat == "GD")
		{
			LOG_ERROR(LOADER, "Failed to mount disc directory for the disc game %s", m_title_id);
			return;
		}

		if (add_only)
		{
			LOG_NOTICE(LOADER, "Finished to add data to games.yml by boot for: %s", m_path);
			return;
		}

		// Check game updates
		const std::string hdd0_boot = hdd0_game + m_title_id + "/USRDIR/EBOOT.BIN";

		if (_cat == "DG" && fs::is_file(hdd0_boot))
		{
			// Booting game update
			LOG_SUCCESS(LOADER, "Updates found at /dev_hdd0/game/%s/!", m_title_id);
			return SetPath(hdd0_boot), Load();
		}

		// Mount /host_root/ if necessary
		if (g_cfg.vfs.host_root)
		{
			vfs::mount("host_root", {});
		}

		// Open SELF or ELF
		fs::file elf_file(m_path);

		if (!elf_file)
		{
			LOG_ERROR(LOADER, "Failed to open executable: %s", m_path);
			return;
		}

		// Check SELF header
		if (elf_file.size() >= 4 && elf_file.read<u32>() == "SCE\0"_u32)
		{
			const std::string decrypted_path = m_cache_path + "boot.elf";

			fs::stat_t encrypted_stat = elf_file.stat();
			fs::stat_t decrypted_stat;

			// Check modification time and try to load decrypted ELF
			if (fs::stat(decrypted_path, decrypted_stat) && decrypted_stat.mtime == encrypted_stat.mtime)
			{
				elf_file.open(decrypted_path);
			}
			else
			{
				// Decrypt SELF
				elf_file = decrypt_self(std::move(elf_file));

				if (fs::file elf_out{decrypted_path, fs::rewrite})
				{
					elf_out.write(elf_file.to_vector<u8>());
					elf_out.close();
					fs::utime(decrypted_path, encrypted_stat.atime, encrypted_stat.mtime);
				}
				else
				{
					LOG_ERROR(LOADER, "Failed to create boot.elf");
				}
			}
		}

		ppu_exec_object ppu_exec;
		ppu_prx_object ppu_prx;
		spu_exec_object spu_exec;
		arm_exec_object arm_exec;

		if (!elf_file)
		{
			LOG_ERROR(LOADER, "Failed to decrypt SELF: %s", m_path);
			return;
		}
		else if (ppu_exec.open(elf_file) == elf_error::ok)
		{
			// PS3 executable
			g_system = system_type::ps3;
			m_state = system_state::ready;
			GetCallbacks().on_ready();

			vm::ps3::init();

			if (m_elf_path.empty())
			{
				if (m_path.find(hdd0_game) != -1)
				{
					m_elf_path = "/dev_hdd0/game/" + m_path.substr(hdd0_game.size());
				}
				else if (!bdvd_dir.empty() && fs::is_dir(bdvd_dir))
				{
					//Disc games are on /dev_bdvd/
					size_t pos = m_path.rfind("PS3_GAME");
					m_elf_path = "/dev_bdvd/" + m_path.substr(pos);
				}
				else
				{
					//For homebrew
					m_elf_path = "/host_root/" + m_path;
				}

				LOG_NOTICE(LOADER, "Elf path: %s", m_elf_path);
			}

			ppu_load_exec(ppu_exec);

			fxm::import<GSRender>(Emu.GetCallbacks().get_gs_render); // TODO: must be created in appropriate sys_rsx syscall
		}
		else if (ppu_prx.open(elf_file) == elf_error::ok)
		{
			// PPU PRX (experimental)
			g_system = system_type::ps3;
			m_state = system_state::ready;
			GetCallbacks().on_ready();
			vm::ps3::init();
			ppu_load_prx(ppu_prx, m_path);
		}
		else if (spu_exec.open(elf_file) == elf_error::ok)
		{
			// SPU executable (experimental)
			g_system = system_type::ps3;
			m_state = system_state::ready;
			GetCallbacks().on_ready();
			vm::ps3::init();
			spu_load_exec(spu_exec);
		}
		else if (arm_exec.open(elf_file) == elf_error::ok)
		{
			// ARMv7 executable
			g_system = system_type::psv;
			m_state = system_state::ready;
			GetCallbacks().on_ready();
			vm::psv::init();

			if (m_elf_path.empty())
			{
				m_elf_path = "host_root:" + m_path;
				LOG_NOTICE(LOADER, "Elf path: %s", m_elf_path);
			}

			arm_load_exec(arm_exec);
		}
		else
		{
			LOG_ERROR(LOADER, "Invalid or unsupported file format: %s", m_path);

			LOG_WARNING(LOADER, "** ppu_exec -> %s", ppu_exec.get_error());
			LOG_WARNING(LOADER, "** ppu_prx  -> %s", ppu_prx.get_error());
			LOG_WARNING(LOADER, "** spu_exec -> %s", spu_exec.get_error());
			LOG_WARNING(LOADER, "** arm_exec -> %s", arm_exec.get_error());
			return;
		}

		if (g_cfg.misc.autostart && IsReady())
		{
			Run();
		}
		else if (IsPaused())
		{
			m_state = system_state::ready;
			GetCallbacks().on_ready();
		}
	}
	catch (const std::exception& e)
	{
		LOG_FATAL(LOADER, "%s thrown: %s", typeid(e).name(), e.what());
		Stop();
	}
}
Ejemplo n.º 4
0
void ControlInfo::Show()
{
	LOG_NOTICE(LOADER, "Type: 0x%08x", type);
	LOG_NOTICE(LOADER, "Size: 0x%08x", size);
	LOG_NOTICE(LOADER, "Next: 0x%llx", next);

	if (type == 1)
	{
		LOG_NOTICE(LOADER, "Control flag 1: 0x%08x", control_flags.ctrl_flag1);
		LOG_NOTICE(LOADER, "Unknown1: 0x%08x", control_flags.unknown1);
		LOG_NOTICE(LOADER, "Unknown2: 0x%08x", control_flags.unknown2);
		LOG_NOTICE(LOADER, "Unknown3: 0x%08x", control_flags.unknown3);
		LOG_NOTICE(LOADER, "Unknown4: 0x%08x", control_flags.unknown4);
		LOG_NOTICE(LOADER, "Unknown5: 0x%08x", control_flags.unknown5);
		LOG_NOTICE(LOADER, "Unknown6: 0x%08x", control_flags.unknown6);
		LOG_NOTICE(LOADER, "Unknown7: 0x%08x", control_flags.unknown7);
	}
	else if (type == 2)
	{
		if (size == 0x30)
		{
			std::string digest_str;
			for (int i = 0; i < 20; i++)
				digest_str += fmt::format("%02x", file_digest_30.digest[i]);

			LOG_NOTICE(LOADER, "Digest: %s", digest_str.c_str());
			LOG_NOTICE(LOADER, "Unknown: 0x%llx", file_digest_30.unknown);
		}
		else if (size == 0x40)
		{
			std::string digest_str1;
			std::string digest_str2;
			for (int i = 0; i < 20; i++)
			{
				digest_str1 += fmt::format("%02x", file_digest_40.digest1[i]);
				digest_str2 += fmt::format("%02x", file_digest_40.digest2[i]);
			}

			LOG_NOTICE(LOADER, "Digest1: %s", digest_str1.c_str());
			LOG_NOTICE(LOADER, "Digest2: %s", digest_str2.c_str());
			LOG_NOTICE(LOADER, "Unknown: 0x%llx", file_digest_40.unknown);
		}
	}
	else if (type == 3)
	{
		std::string contentid_str;
		std::string digest_str;
		std::string invdigest_str;
		std::string xordigest_str;
		for (int i = 0; i < 48; i++)
			contentid_str += fmt::format("%02x", npdrm.content_id[i]);
		for (int i = 0; i < 16; i++)
		{
			digest_str += fmt::format("%02x", npdrm.digest[i]);
			invdigest_str += fmt::format("%02x", npdrm.invdigest[i]);
			xordigest_str += fmt::format("%02x", npdrm.xordigest[i]);
		}

		LOG_NOTICE(LOADER, "Magic: 0x%08x", npdrm.magic);
		LOG_NOTICE(LOADER, "Unknown1: 0x%08x", npdrm.unknown1);
		LOG_NOTICE(LOADER, "License: 0x%08x", npdrm.license);
		LOG_NOTICE(LOADER, "Type: 0x%08x", npdrm.type);
		LOG_NOTICE(LOADER, "ContentID: %s", contentid_str.c_str());
		LOG_NOTICE(LOADER, "Digest: %s", digest_str.c_str());
		LOG_NOTICE(LOADER, "Inverse digest: %s", invdigest_str.c_str());
		LOG_NOTICE(LOADER, "XOR digest: %s", xordigest_str.c_str());
		LOG_NOTICE(LOADER, "Unknown2: 0x%llx", npdrm.unknown2);
		LOG_NOTICE(LOADER, "Unknown3: 0x%llx", npdrm.unknown3);
	}
}
Ejemplo n.º 5
0
void CPUThread::Task()
{
	if (Ini.HLELogging.GetValue()) LOG_NOTICE(PPU, "%s enter", CPUThread::GetFName().c_str());

	const std::vector<u64>& bp = Emu.GetBreakPoints();

	for (uint i = 0; i<bp.size(); ++i)
	{
		if (bp[i] == m_offset + PC)
		{
			Emu.Pause();
			break;
		}
	}

	std::vector<u64> trace;

#ifdef _WIN32
	_set_se_translator(_se_translator);
#else
	// TODO: linux version
#endif

	while (true)
	{
		int status = ThreadStatus();

		if (status == CPUThread_Stopped || status == CPUThread_Break)
		{
			break;
		}

		if (status == CPUThread_Sleeping)
		{
			std::this_thread::sleep_for(std::chrono::milliseconds(1));
			continue;
		}

		Step();
		//if (PC - 0x13ED4 < 0x288) trace.push_back(PC);
		NextPc(m_dec->DecodeMemory(PC + m_offset));

		if (status == CPUThread_Step)
		{
			m_is_step = false;
			break;
		}

		for (uint i = 0; i < bp.size(); ++i)
		{
			if (bp[i] == PC)
			{
				Emu.Pause();
				break;
			}
		}
	}

	for (auto& v : trace) LOG_NOTICE(PPU, "PC = 0x%llx", v);

	if (Ini.HLELogging.GetValue()) LOG_NOTICE(PPU, "%s leave", CPUThread::GetFName().c_str());
}
Ejemplo n.º 6
0
u8 edid_EventHandler(u16 baseAddr, int hpd, u8 state)
{
	LOG_TRACE2(hpd, state);
	if (edid_mStatus != EDID_READING)
	{
		return EDID_IDLE;
	}
	else if (!hpd)
	{ /* hot plug detected without cable disconnection */
		error_Set(ERR_HPD_LOST);
		LOG_WARNING("hpd");
		edid_mStatus = EDID_ERROR;
	}
	else if ((state & BIT(0)) != 0) /* error */
	{ 
		LOG_WARNING("error");
		edid_mStatus = EDID_ERROR;
	}
	else if ((state & BIT(1)) != 0) /* done */
	{ 
		if (edid_mCurrAddress >= sizeof(edid_mBuffer))
		{
			error_Set(ERR_OVERFLOW);
			LOG_WARNING("overflow");
			edid_mStatus = EDID_ERROR;
		}
		else
		{
			edid_mBuffer[edid_mCurrAddress] = halEdid_ReadData(baseAddr
					+ I2CM_BASE_ADDR);
			edid_mBlockSum += edid_mBuffer[edid_mCurrAddress++];
			if (edid_mCurrAddress >= sizeof(edid_mBuffer))
			{
				/*check if checksum is correct (CEA-861 D Spec p108) */
				if (edid_mBlockSum % 0x100 == 0)
				{
					LOG_NOTICE("block checksum correct");
					edid_ParseBlock(baseAddr, edid_mBuffer);
					edid_mCurrAddress = 0;
					edid_mCurrBlockNo++;
					edid_mBlockSum = 0;
					if (edid_mCurrBlockNo >= edid_mBlocksNo)
					{
						edid_mStatus = EDID_DONE; 
					}
				}
				else
				{
					error_Set(ERR_BLOCK_CHECKSUM_INVALID);
					LOG_WARNING("block checksum invalid");
					edid_mStatus = EDID_ERROR; 
				}
			}
		}
	}
	if (edid_mStatus == EDID_READING)
	{
		edid_ReadRequest(baseAddr, edid_mCurrAddress, edid_mCurrBlockNo);
	}
	else if (edid_mStatus == EDID_DONE)
	{
		edid_mBlocksNo = 1;
		edid_mCurrBlockNo = 0;
		edid_mCurrAddress = 0;
		edid_mBlockSum = 0;
	}
	return edid_mStatus;
}
Ejemplo n.º 7
0
s32 sys_ppu_thread_create(mem64_t thread_id, u32 entry, u64 arg, s32 prio, u32 stacksize, u64 flags, u32 threadname_addr)
{
	std::string threadname = "";
	if (Memory.IsGoodAddr(threadname_addr))
	{
		threadname = Memory.ReadString(threadname_addr);
		sysPrxForUser->Log("sys_ppu_thread_create(thread_id_addr=0x%x, entry=0x%x, arg=0x%llx, prio=%d, stacksize=0x%x, flags=0x%llx, threadname_addr=0x%x('%s'))",
			thread_id.GetAddr(), entry, arg, prio, stacksize, flags, threadname_addr, threadname.c_str());
	}
	else
	{
		sysPrxForUser->Log("sys_ppu_thread_create(thread_id_addr=0x%x, entry=0x%x, arg=0x%llx, prio=%d, stacksize=0x%x, flags=0x%llx, threadname_addr=0x%x)",
			thread_id.GetAddr(), entry, arg, prio, stacksize, flags, threadname_addr);
		if (threadname_addr != 0) return CELL_EFAULT;
	}

	if (!Memory.IsGoodAddr(entry) || !thread_id.IsGood())
	{
		return CELL_EFAULT;
	}

	bool is_joinable = false;
	bool is_interrupt = false;

	switch (flags)
	{
	case 0: break;
	case SYS_PPU_THREAD_CREATE_JOINABLE:
	{
		is_joinable = true;
		break;
	}
	case SYS_PPU_THREAD_CREATE_INTERRUPT:
	{
		is_interrupt = true;
		break;
	}
	default: sysPrxForUser->Error("sys_ppu_thread_create(): unknown flags value (0x%llx)", flags); return CELL_EPERM;
	}

	CPUThread& new_thread = Emu.GetCPU().AddThread(CPU_THREAD_PPU);

	thread_id = new_thread.GetId();
	new_thread.SetEntry(entry);
	new_thread.SetArg(0, arg);
	new_thread.SetPrio(prio);
	new_thread.SetStackSize(stacksize);
	//new_thread.flags = flags;
	new_thread.m_has_interrupt = false;
	new_thread.m_is_interrupt = is_interrupt;
	new_thread.SetName(threadname);

	LOG_NOTICE(PPU, "*** New PPU Thread [%s] (flags=0x%llx, entry=0x%x): id = %d", new_thread.GetName().c_str(), flags, entry, new_thread.GetId());

	if (!is_interrupt)
	{
		new_thread.Run();
		new_thread.Exec();
	}

	return CELL_OK;
}
Ejemplo n.º 8
0
bool extract_all_data(const fs::file* input, const fs::file* output, const char* input_file_name, unsigned char* devklic, unsigned char* rifkey, bool verbose)
{
	// Setup NPD and EDAT/SDAT structs.
	NPD_HEADER NPD;
	EDAT_HEADER EDAT;

	// Read in the NPD and EDAT/SDAT headers.
	read_npd_edat_header(input, NPD, EDAT);

	unsigned char npd_magic[4] = {0x4E, 0x50, 0x44, 0x00};  //NPD0
	if (memcmp(&NPD.magic, npd_magic, 4))
	{
		LOG_ERROR(LOADER, "EDAT: %s has invalid NPD header or already decrypted.", input_file_name);
		return 1;
	}

	if (verbose)
	{
		LOG_NOTICE(LOADER, "NPD HEADER");
		LOG_NOTICE(LOADER, "NPD version: %d", NPD.version);
		LOG_NOTICE(LOADER, "NPD license: %d", NPD.license);
		LOG_NOTICE(LOADER, "NPD type: %d", NPD.type);
	}

	// Set decryption key.
	u8 key[0x10] = { 0 };

	// Check EDAT/SDAT flag.
	if ((EDAT.flags & SDAT_FLAG) == SDAT_FLAG)
	{
		if (verbose)
		{
			LOG_NOTICE(LOADER, "SDAT HEADER");
			LOG_NOTICE(LOADER, "SDAT flags: 0x%08X", EDAT.flags);
			LOG_NOTICE(LOADER, "SDAT block size: 0x%08X", EDAT.block_size);
			LOG_NOTICE(LOADER, "SDAT file size: 0x%08X", (u64)EDAT.file_size);
		}

		// Generate SDAT key.
		xor_key(key, NPD.dev_hash, SDAT_KEY);
	}
	else
	{
		if (verbose)
		{
			LOG_NOTICE(LOADER, "EDAT HEADER");
			LOG_NOTICE(LOADER, "EDAT flags: 0x%08X", EDAT.flags);
			LOG_NOTICE(LOADER, "EDAT block size: 0x%08X", EDAT.block_size);
			LOG_NOTICE(LOADER, "EDAT file size: 0x%08X", (u64)EDAT.file_size);
		}

		// Perform header validation (EDAT only).
		char real_file_name[MAX_PATH];
		extract_file_name(input_file_name, real_file_name);
		if (!validate_npd_hashes(real_file_name, devklic, &NPD, verbose))
		{
			// Ignore header validation in DEBUG data.
			if ((EDAT.flags & EDAT_DEBUG_DATA_FLAG) != EDAT_DEBUG_DATA_FLAG)
			{
				LOG_ERROR(LOADER, "EDAT: NPD hash validation failed!");
				return 1;
			}
		}

		// Select EDAT key.
		if ((NPD.license & 0x3) == 0x3)           // Type 3: Use supplied devklic.
			memcpy(key, devklic, 0x10);
		else if ((NPD.license & 0x2) == 0x2)      // Type 2: Use key from RAP file (RIF key).
		{
			memcpy(key, rifkey, 0x10);

			// Make sure we don't have an empty RIF key.
			int i, test = 0;
			for (i = 0; i < 0x10; i++)
			{
				if (key[i] != 0)
				{
					test = 1;
					break;
				}
			}

			if (!test)
			{
				LOG_ERROR(LOADER, "EDAT: A valid RAP file is needed for this EDAT file!");
				return 1;
			}
		}
		else if ((NPD.license & 0x1) == 0x1)      // Type 1: Use network activation.
		{
			LOG_ERROR(LOADER, "EDAT: Network license not supported!");
			return 1;
		}

		if (verbose)
		{
			int i;
			LOG_NOTICE(LOADER, "DEVKLIC: ");
			for (i = 0; i < 0x10; i++)
				LOG_NOTICE(LOADER, "%02X", devklic[i]);

			LOG_NOTICE(LOADER, "RIF KEY: ");
			for (i = 0; i < 0x10; i++)
				LOG_NOTICE(LOADER, "%02X", rifkey[i]);
		}
	}

	if (verbose)
	{
		int i;
		LOG_NOTICE(LOADER, "DECRYPTION KEY: ");
		for (i = 0; i < 0x10; i++)
			LOG_NOTICE(LOADER, "%02X", key[i]);
	}

	input->seek(0);
	if (check_data(key, &EDAT, &NPD, input, verbose))
	{
		LOG_ERROR(LOADER, "EDAT: Data parsing failed!");
		return 1;
	}

	input->seek(0);
	if (decrypt_data(input, output, &EDAT, &NPD, key, verbose))
	{
		LOG_ERROR(LOADER, "EDAT: Data decryption failed!");
		return 1;
	}

	return 0;
}
Ejemplo n.º 9
0
int LsapiConn::processRespBuffed()
{
    int ret;
    int left;
    int len;
    m_pRespHeader = (char *)&m_respHeader;
    m_pRespHeaderBufEnd = &m_respBuf[1024];
    ret = read( m_pRespHeader, m_pRespHeaderBufEnd - m_pRespHeader );
    if ( ret <= 0 )
        return ret;
    if ( ret < (int)sizeof( lsapi_packet_header ) )
    {
        m_iPacketHeaderLeft = sizeof( lsapi_packet_header ) - ret;
        return ret;
    }
    m_pRespHeaderBufEnd     = m_pRespHeader + ret;
    m_iPacketLeft = verifyPacketHeader( &m_respHeader ) -
            LSAPI_PACKET_HEADER_LEN;
    if ( m_iPacketLeft < 0 )
	{
		errno = EIO;
        return -1;
    }
	if ( !m_iPacketLeft )
        m_iPacketHeaderLeft = LSAPI_PACKET_HEADER_LEN;
    else    
        m_iPacketHeaderLeft = 0;
    if ( ret < (int)(sizeof( lsapi_packet_header ) + sizeof( lsapi_resp_info )) )
    {
        m_pRespHeader += ret;
        switch( m_respHeader.m_type )
        {
        case LSAPI_RESP_END:
            m_respState = LSAPI_CONN_IDLE;
			incReqProcessed();
            setInProcess( 0 );
            getConnector()->endResponse( 0, 0 );
            return 0;
        case LSAPI_RESP_HEADER:
            m_iCurRespHeader    = 0;
            m_respState         = LSAPI_CONN_READ_RESP_INFO;
            m_pRespHeaderProcess = (char *)&m_respInfo;
            setRespBuf( m_pRespHeaderProcess );
            return ret;
        case LSAPI_REQ_RECEIVED:
            m_reqReceived       = 1;
            break;
        }
        m_pRespHeaderProcess    = (char *)&m_respInfo;
    }
    else
    {
        m_iCurRespHeader        = 0;
        m_respState             = LSAPI_CONN_READ_HEADER_LEN;
        m_pRespHeaderProcess    = m_respBuf;
    }
    while( (left = m_pRespHeaderBufEnd - m_pRespHeaderProcess) > 0  )
    {
        if ( m_iPacketHeaderLeft > 0 )
        {
            ret = processPacketHeader( m_pRespHeaderProcess, left );
            if ( ret <= 0 )
                return ret;
            m_pRespHeaderProcess += ret;
            left -= ret;
        }

        if ( m_iPacketLeft > 0 )
        {
            register HttpExtConnector * pHEC = getConnector();
            if ( !pHEC )
                return -1;
            int &respState = pHEC->getRespState();
            if ( m_iPacketLeft < left )
            {
                len = m_iPacketLeft;
                m_iPacketLeft = 0;
                m_iPacketHeaderLeft = LSAPI_PACKET_HEADER_LEN;
            }
            else
            {
                len = left;
                m_iPacketLeft -= left;
                left = 0;
            }
            switch( m_respHeader.m_type )
            {
            case LSAPI_RESP_HEADER:
                ret = processRespHeader(m_pRespHeaderBufEnd, respState);
                if ( ret < 0 )
                    return ret;
                break;
            case LSAPI_RESP_STREAM:
                if ( D_ENABLED( DL_MEDIUM ) )
                    LOG_D(( getLogger(), "[%s] process response stream %d bytes",
                        getLogId(), len ));
                ret = pHEC->processRespData( m_pRespHeaderProcess, len );
                if ( respState & 0xff )
                    m_respState = LSAPI_CONN_READ_RESP_BODY;
                if ( ret == -1 )
                    return ret;
                m_pRespHeaderProcess += len;
                break;
            case LSAPI_STDERR_STREAM:
                if ( D_ENABLED( DL_MEDIUM ) )
                    LOG_D(( getLogger(), "[%s] process STDERR stream %d bytes",
                        getLogId(), len ));
                ret = pHEC->processErrData( m_pRespHeaderProcess, len );
                m_pRespHeaderProcess += len;
                break;
            default:
                LOG_NOTICE(( getLogger(), "[%s] Unknown Packet Type %c, LSAPI protcol is broken.",
                    getLogId(), m_respHeader.m_type ));
                errno = EIO;
                return -1;
            }
        }
        else
            m_iPacketHeaderLeft = LSAPI_PACKET_HEADER_LEN;
        
        
    }
    return 1;
}
Ejemplo n.º 10
0
/**
* Parses the BGP attributes in the update
*
* \details
*     Parses all attributes.  Decoded values are updated in 'parsed_data'
*
* \param [in]   data       Pointer to the start of the prefixes to be parsed
* \param [in]   len        Length of the data in bytes to be read
* \param [out]  parsed_update  Reference to parsed_update; will be updated with all parsed data
*/
void parseBgpLib::parseBgpAttr(u_char *data, uint16_t len, parsed_update &update) {
    /*
     * Per RFC4271 Section 4.3, flag indicates if the length is 1 or 2 octets
     */
    u_char attr_flags;
    u_char attr_type;
    uint16_t attr_len;

    if (len == 0)
        return;

    else if (len < 3) {
        LOG_WARN("%sCannot parse the attributes due to the data being too short, error in update message. len=%d",
                 debug_prepend_string.c_str(), len);
        return;
    }

        // Generate the hash
        MD5 hash;

     /*
     * Iterate through all attributes and parse them
     */
    for (int read_size = 0; read_size < len; read_size += 2) {
        attr_flags = *data++;
        attr_type = *data++;

        // Check if the length field is 1 or two bytes
        if (ATTR_FLAG_EXTENDED(attr_flags)) {
            SELF_DEBUG("%sExtended length path attribute bit set for an entry", debug_prepend_string.c_str());
            memcpy(&attr_len, data, 2);
            data += 2;
            read_size += 2;
            parse_bgp_lib::SWAP_BYTES(&attr_len);
        } else
            attr_len = *data++;
        read_size++;

        // Get the attribute data, if we have any; making sure to not overrun buffer
        if (attr_len > 0 and (read_size + attr_len) <= len) {
            // Data pointer is currently at the data position of the attribute

            /*
             * Parse data based on attribute type
             */
            parseAttrData(attr_type, attr_len, data, update, hash);
            data += attr_len;
            read_size += attr_len;

            SELF_DEBUG("%sParsed attr Type=%d, size=%hu", debug_prepend_string.c_str(), attr_type, attr_len);
        } else if (attr_len) {
            LOG_NOTICE("%sAttribute data len of %hu is larger than available data in update message of %hu",
                       debug_prepend_string.c_str(), attr_len, (len - read_size));
            return;
        }
    }
        //Now save the generate hash
        hash.finalize();

        // Save the hash
        unsigned char *hash_raw = hash.raw_digest();
        update.attrs[LIB_ATTR_BASE_ATTR_HASH].name = parse_bgp_lib::parse_bgp_lib_attr_names[LIB_ATTR_BASE_ATTR_HASH];
        update.attrs[LIB_ATTR_BASE_ATTR_HASH].value.push_back(parse_bgp_lib::hash_toStr(hash_raw));
        delete[] hash_raw;

    }
Ejemplo n.º 11
0
void Emulator::Load()
{
	Stop();

	try
	{
		Init();

		if (!fs::is_file(m_path))
		{
			LOG_ERROR(LOADER, "File not found: %s", m_path);
			return;
		}

		const std::string& elf_dir = fs::get_parent_dir(m_path);

		if (IsSelf(m_path))
		{
			const std::size_t elf_ext_pos = m_path.find_last_of('.');
			const std::string& elf_ext = fmt::to_upper(m_path.substr(elf_ext_pos != -1 ? elf_ext_pos : m_path.size()));
			const std::string& elf_name = m_path.substr(elf_dir.size());

			if (elf_name.compare(elf_name.find_last_of("/\\", -1, 2) + 1, 9, "EBOOT.BIN", 9) == 0)
			{
				m_path.erase(m_path.size() - 9, 1); // change EBOOT.BIN to BOOT.BIN
			}
			else if (elf_ext == ".SELF" || elf_ext == ".SPRX")
			{
				m_path.erase(m_path.size() - 4, 1); // change *.self to *.elf, *.sprx to *.prx
			}
			else
			{
				m_path += ".decrypted.elf";
			}

			if (!DecryptSelf(m_path, elf_dir + elf_name))
			{
				LOG_ERROR(LOADER, "Failed to decrypt %s", elf_dir + elf_name);
				return;
			}
		}

		ResetInfo();

		LOG_NOTICE(LOADER, "Path: %s", m_path);

		// Load custom config
		if (fs::file cfg_file{ m_path + ".yml" })
		{
			LOG_NOTICE(LOADER, "Custom config: %s.yml", m_path);
			cfg::root.from_string(cfg_file.to_string());
		}

		const fs::file elf_file(m_path);
		ppu_exec_loader ppu_exec;
		ppu_prx_loader ppu_prx;
		spu_exec_loader spu_exec;
		arm_exec_loader arm_exec;

		if (!elf_file)
		{
			LOG_ERROR(LOADER, "Failed to open %s", m_path);
			return;
		}
		else if (ppu_exec.open(elf_file) == elf_error::ok)
		{
			// PS3 executable
			m_status = Ready;
			vm::ps3::init();

			if (m_elf_path.empty())
			{
				m_elf_path = "/host_root/" + m_path;
				LOG_NOTICE(LOADER, "Elf path: %s", m_elf_path);
			}

			// Load PARAM.SFO
			const auto _psf = psf::load_object(fs::file(elf_dir + "/../PARAM.SFO"));
			m_title = psf::get_string(_psf, "TITLE", m_path);
			m_title_id = psf::get_string(_psf, "TITLE_ID");

			LOG_NOTICE(LOADER, "Title: %s", GetTitle());
			LOG_NOTICE(LOADER, "Serial: %s", GetTitleID());
			LOG_NOTICE(LOADER, "");

			LOG_NOTICE(LOADER, "Used configuration:\n%s\n", cfg::root.to_string());

			// Mount /dev_bdvd/
			if (g_cfg_vfs_dev_bdvd.size() == 0 && fs::is_file(elf_dir + "/../../PS3_DISC.SFB"))
			{
				const auto dir_list = fmt::split(elf_dir, { "/", "\\" });

				// Check latest two directories
				if (dir_list.size() >= 2 && dir_list.back() == "USRDIR" && *(dir_list.end() - 2) == "PS3_GAME")
				{
					g_cfg_vfs_dev_bdvd = elf_dir.substr(0, elf_dir.length() - 15);
				}
				else
				{
					g_cfg_vfs_dev_bdvd = elf_dir + "/../../";
				}
			}

			// Mount /app_home/
			if (g_cfg_vfs_app_home.size() == 0)
			{
				g_cfg_vfs_app_home = elf_dir + '/';
			}

			vfs::dump();

			ppu_exec.load();

			Emu.GetCallbackManager().Init();
			fxm::import<GSRender>(PURE_EXPR(Emu.GetCallbacks().get_gs_render())); // TODO: must be created in appropriate sys_rsx syscall
		}
		else if (ppu_prx.open(elf_file) == elf_error::ok)
		{
			// PPU PRX (experimental)
			m_status = Ready;
			vm::ps3::init();
			ppu_prx.load();
			GetCallbackManager().Init();
		}
		else if (spu_exec.open(elf_file) == elf_error::ok)
		{
			// SPU executable (experimental)
			m_status = Ready;
			vm::ps3::init();
			spu_exec.load();
		}
		else if (arm_exec.open(elf_file) == elf_error::ok)
		{
			// ARMv7 executable
			m_status = Ready;
			vm::psv::init();
			arm_exec.load();
		}
		else
		{
			LOG_ERROR(LOADER, "Invalid or unsupported file format: %s", m_path);

			LOG_WARNING(LOADER, "** ppu_exec_loader -> %s", ppu_exec.get_error());
			LOG_WARNING(LOADER, "** ppu_prx_loader -> %s", ppu_prx.get_error());
			LOG_WARNING(LOADER, "** spu_exec_loader -> %s", spu_exec.get_error());
			LOG_WARNING(LOADER, "** arm_exec_loader -> %s", arm_exec.get_error());
			return;
		}

		debug::autopause::reload();
		SendDbgCommand(DID_READY_EMU);
		if (g_cfg_autostart) Run();
	}
	catch (const std::exception& e)
	{
		LOG_FATAL(LOADER, "%s thrown: %s", typeid(e).name(), e.what());
		Stop();
	}
}
Ejemplo n.º 12
0
    /**
* Parses the BGP prefixes (advertised and withdrawn) in the update
*
* \details
*     Parses all attributes.  Decoded values are updated in 'parsed_data'
*
* \param [in]   data       Pointer to the start of the prefixes to be parsed
* \param [in]   len        Length of the data in bytes to be read
* \param [in]   nlri_list Reference to parsed_update_data nlri list;
*/
void parseBgpLib::parseBgpNlri_v4(u_char *data, uint16_t len, std::list<parse_bgp_lib_nlri> &nlri_list) {
    u_char ipv4_raw[4];
    char ipv4_char[16];
    u_char addr_bytes;
    uint32_t path_id;
    u_char prefix_len;
    std::ostringstream numString;


    if (len <= 0 or data == NULL)
        return;

        // Loop through all prefixes
    for (size_t read_size = 0; read_size < len; read_size++) {
        parse_bgp_lib_nlri nlri;
        nlri.afi = parse_bgp_lib::BGP_AFI_IPV4;
        nlri.safi = parse_bgp_lib::BGP_SAFI_UNICAST;
        nlri.type = parse_bgp_lib::LIB_NLRI_TYPE_NONE;

        // Generate the hash
        MD5 hash;

        bzero(ipv4_raw, sizeof(ipv4_raw));

        // Parse add-paths if enabled
        bool peer_info_addpath = p_info and p_info->add_path_capability.isAddPathEnabled(bgp::BGP_AFI_IPV4, bgp::BGP_SAFI_UNICAST);

        if ((peer_info_addpath or addPathCap[BGP_AFI_IPV4_INTERNAL][BGP_SAFI_UNICAST_INTERNAL])
            and (len - read_size) >= 4) {
            memcpy(&path_id, data, 4);
            parse_bgp_lib::SWAP_BYTES(&path_id);
            data += 4;
            read_size += 4;
        } else
            path_id = 0;
        numString.str(std::string());
        numString << path_id;
        nlri.nlri[LIB_NLRI_PATH_ID].name = parse_bgp_lib::parse_bgp_lib_nlri_names[LIB_NLRI_PATH_ID];
        nlri.nlri[LIB_NLRI_PATH_ID].value.push_back(numString.str());

        if (path_id > 0)
            update_hash(&nlri.nlri[LIB_NLRI_PATH_ID].value, &hash);

        // set the address in bits length
        prefix_len = *data++;
        numString.str(std::string());
        numString << static_cast<unsigned>(prefix_len);

        nlri.nlri[LIB_NLRI_PREFIX_LENGTH].name = parse_bgp_lib::parse_bgp_lib_nlri_names[LIB_NLRI_PREFIX_LENGTH];
        nlri.nlri[LIB_NLRI_PREFIX_LENGTH].value.push_back(numString.str());
        update_hash(&nlri.nlri[LIB_NLRI_PREFIX_LENGTH].value, &hash);

        // Figure out how many bytes the bits requires
        addr_bytes = prefix_len / 8;
        if (prefix_len % 8)
            ++addr_bytes;

        SELF_DEBUG("%sReading NLRI data prefix bits=%d bytes=%d", debug_prepend_string.c_str(), prefix_len, addr_bytes);

        if (addr_bytes <= 4) {
            memcpy(ipv4_raw, data, addr_bytes);
            read_size += addr_bytes;
            data += addr_bytes;

            // Convert the IP to string printed format
            inet_ntop(AF_INET, ipv4_raw, ipv4_char, sizeof(ipv4_char));
            nlri.nlri[LIB_NLRI_PREFIX].name = parse_bgp_lib::parse_bgp_lib_nlri_names[LIB_NLRI_PREFIX];
            nlri.nlri[LIB_NLRI_PREFIX].value.push_back(ipv4_char);
            update_hash(&nlri.nlri[LIB_NLRI_PREFIX].value, &hash);
            SELF_DEBUG("%sAdding prefix %s len %d", debug_prepend_string.c_str(), ipv4_char, prefix_len);

            // set the raw/binary address
            nlri.nlri[LIB_NLRI_PREFIX_BIN].name = parse_bgp_lib::parse_bgp_lib_nlri_names[LIB_NLRI_PREFIX_BIN];
            nlri.nlri[LIB_NLRI_PREFIX_BIN].value.push_back(std::string(ipv4_raw, ipv4_raw + 4));

            //Update hash to include peer hash id
            if (p_info)
                hash.update((unsigned char *) p_info->peer_hash_str.c_str(), p_info->peer_hash_str.length());

            hash.finalize();

            // Save the hash
            unsigned char *hash_raw = hash.raw_digest();
            nlri.nlri[LIB_NLRI_HASH].name = parse_bgp_lib::parse_bgp_lib_nlri_names[LIB_NLRI_HASH];
            nlri.nlri[LIB_NLRI_HASH].value.push_back(parse_bgp_lib::hash_toStr(hash_raw));
            delete[] hash_raw;

            nlri.nlri[LIB_NLRI_IS_IPV4].name =parse_bgp_lib_nlri_names[LIB_NLRI_IS_IPV4];
            nlri.nlri[LIB_NLRI_IS_IPV4].value.push_back(string("1"));

            // Add tuple to prefix list
            nlri_list.push_back(nlri);
        } else if (addr_bytes > 4) {
            LOG_NOTICE("%sNRLI v4 address is larger than 4 bytes bytes=%d len=%d", debug_prepend_string.c_str(), addr_bytes, prefix_len);
        }
    }
}
Ejemplo n.º 13
0
    /**
     * Parses the BMP router Term message
     *
     * \details
     * Parse BMP Router Init message
     * \param [in]  bmp_data        Buffer containing the data
     * \param [in]  parsed_update   Reference to parsed_update; will be updated with all parsed data
     *
     */
    void parseBgpLib::parseBmpTermMsg(int sock, u_char *bmp_data, size_t bmp_data_len, parsed_update &update) {
        parse_bgp_lib_bmp_msg_v3 termMsg;
        char infoBuf[BMP_ROUTER_DATA_SIZE];
        int infoLen;

        u_char *bufPtr = bmp_data;

        /*
         * Create router timestamp
         */
        update.router[LIB_ROUTER_TIMESTAMP].name = parse_bgp_lib::parse_bgp_lib_router_names[LIB_ROUTER_TIMESTAMP];
        string ts;
        getTimestamp(0, 0, ts);
        update.router[LIB_ROUTER_TIMESTAMP].value.push_back(ts);

        /*
         * Loop through the term message (in buffer) to parse each TLV
         */
        for (int i=0; i < bmp_data_len; i += BMP_MSG_LEN) {
            memcpy(&termMsg, bufPtr, BMP_MSG_LEN);
            termMsg.info = NULL;
            bgp::SWAP_BYTES(&termMsg.len);
            bgp::SWAP_BYTES(&termMsg.type);

            bufPtr += BMP_MSG_LEN;                // Move pointer past the info header

            LOG_INFO("Term message type %hu and length %hu parsed", termMsg.type, termMsg.len);

            if (termMsg.len > 0) {
                infoLen = sizeof(infoBuf) < termMsg.len ? sizeof(infoBuf) : termMsg.len;
                bzero(infoBuf, sizeof(infoBuf));
                memcpy(infoBuf, bufPtr, infoLen);
                bufPtr += infoLen;                     // Move pointer past the info data
                i += infoLen;                       // Update the counter past the info data

                termMsg.info = infoBuf;

                LOG_INFO("Term message type %hu = %s", termMsg.type, termMsg.info);
            }

            /*
             * Save the data based on info type
             */
            switch (termMsg.type) {
                case TERM_TYPE_FREE_FORM_STRING :
                    update.router[LIB_ROUTER_TERM_DATA].name = parse_bgp_lib::parse_bgp_lib_router_names[LIB_ROUTER_TERM_DATA];
                    update.router[LIB_ROUTER_TERM_DATA].value.push_back(std::string(termMsg.info, infoLen));
                    break;

                case TERM_TYPE_REASON :
                {
                    // Get the term reason code from info data (first 2 bytes)
                    uint16_t term_reason;
                    memcpy(&term_reason, termMsg.info, 2);
                    bgp::SWAP_BYTES(&term_reason);
                    std::ostringstream numString;
                    numString << term_reason;
                    update.router[LIB_ROUTER_TERM_REASON_CODE].name = parse_bgp_lib::parse_bgp_lib_router_names[LIB_ROUTER_TERM_REASON_CODE];
                    update.router[LIB_ROUTER_TERM_REASON_CODE].value.push_back(numString.str());

                    string term_reason_text;
                    switch (term_reason) {
                        case TERM_REASON_ADMIN_CLOSE :
                            LOG_INFO("BMP session closed by remote administratively");
                            term_reason_text.assign("Remote session administratively closed");
                            break;

                        case TERM_REASON_OUT_OF_RESOURCES:
                            LOG_INFO("BMP session closed by remote due to out of resources");
                            term_reason_text.assign("Remote out of resources");
                            break;

                        case TERM_REASON_REDUNDANT_CONN:
                            LOG_INFO("BMP session closed by remote due to connection being redundant");
                            term_reason_text.assign("Remote considers connection redundant");
                            break;

                        case TERM_REASON_UNSPECIFIED:
                            LOG_INFO("BMP session closed by remote as unspecified");
                            term_reason_text.assign("Remote closed with unspecified reason");
                            break;

                        default:
                            LOG_INFO("closed with undefined reason code of %d", term_reason);
                            term_reason_text.assign("Unknown %d termination reason, which is not part of draft.", term_reason);
                    }
                    update.router[LIB_ROUTER_TERM_REASON_TEXT].name = parse_bgp_lib::parse_bgp_lib_router_names[LIB_ROUTER_TERM_REASON_TEXT];
                    update.router[LIB_ROUTER_TERM_REASON_TEXT].value.push_back(term_reason_text);

                    break;
                }

                default:
                    LOG_NOTICE("Term message type %hu is unexpected per draft", termMsg.type);
            }
        }
    }
Ejemplo n.º 14
0
    /**
     * Parses the BMP router init message
     *
     * \details
     * Parse BMP Router Init message
     * \param [in]  bmp_data        Buffer containing the data
     * \param [in]  parsed_update   Reference to parsed_update; will be updated with all parsed data
     *
     */
    void parseBgpLib::parseBmpInitMsg(int sock, u_char *bmp_data, size_t bmp_data_len, parsed_update &update) {
        parse_bgp_lib_bmp_msg_v3 initMsg;
        char infoBuf[BMP_ROUTER_DATA_SIZE];
        int infoLen;

        u_char *bufPtr = bmp_data;

        /*
         * Create router timestamp
         */
        update.router[LIB_ROUTER_TIMESTAMP].name = parse_bgp_lib::parse_bgp_lib_router_names[LIB_ROUTER_TIMESTAMP];
        string ts;
        getTimestamp(0, 0, ts);
        update.router[LIB_ROUTER_TIMESTAMP].value.push_back(ts);

        /*
         * Loop through the init message (in buffer) to parse each TLV
         */
        for (int i=0; i < bmp_data_len; i += BMP_MSG_LEN) {
            memcpy(&initMsg, bufPtr, BMP_MSG_LEN);
            initMsg.info = NULL;
            bgp::SWAP_BYTES(&initMsg.len);
            bgp::SWAP_BYTES(&initMsg.type);

            bufPtr += BMP_MSG_LEN;                // Move pointer past the info header

            // TODO: Change to SELF_DEBUG after IOS supports INIT messages correctly
            SELF_DEBUG("Init message type %hu and length %hu parsed", initMsg.type, initMsg.len);

            if (initMsg.len > 0) {
                infoLen = sizeof(infoBuf) < initMsg.len ? sizeof(infoBuf) : initMsg.len;
                bzero(infoBuf, sizeof(infoBuf));
                memcpy(infoBuf, bufPtr, infoLen);
                bufPtr += infoLen;                     // Move pointer past the info data
                i += infoLen;                          // Update the counter past the info data

                initMsg.info = infoBuf;

            }

            /*
             * Save the data based on info type
             */
            switch (initMsg.type) {
                case INIT_TYPE_FREE_FORM_STRING :
                    update.router[LIB_ROUTER_INITIATE_DATA].name = parse_bgp_lib::parse_bgp_lib_router_names[LIB_ROUTER_INITIATE_DATA];
                    update.router[LIB_ROUTER_INITIATE_DATA].value.push_back(std::string(initMsg.info, infoLen));

                    SELF_DEBUG("Init message type %hu = %s",
                               initMsg.type, update.router[LIB_ROUTER_INITIATE_DATA].value.front().c_str());

                    break;

                case INIT_TYPE_SYSNAME :
                    update.router[LIB_ROUTER_NAME].name = parse_bgp_lib::parse_bgp_lib_router_names[LIB_ROUTER_NAME];
                    update.router[LIB_ROUTER_NAME].value.push_back(std::string(initMsg.info, infoLen));

                    SELF_DEBUG("Init message type %hu = %s",
                               initMsg.type, update.router[LIB_ROUTER_NAME].value.front().c_str());

                    break;

                case INIT_TYPE_SYSDESCR :
                    update.router[LIB_ROUTER_DESCR].name = parse_bgp_lib::parse_bgp_lib_router_names[LIB_ROUTER_DESCR];
                    update.router[LIB_ROUTER_DESCR].value.push_back(std::string(initMsg.info, infoLen));

                    SELF_DEBUG("Init message type %hu = %s",
                               initMsg.type, update.router[LIB_ROUTER_DESCR].value.front().c_str());
                    break;

                case INIT_TYPE_ROUTER_BGP_ID:
                    if (initMsg.len != sizeof(in_addr_t)) {
                        LOG_NOTICE("Init message type BGP ID not of IPv4 addr length");
                        break;
                    }
                    char ipv4_char[16];
                    inet_ntop(AF_INET, initMsg.info, ipv4_char, sizeof(ipv4_char));

                    update.router[LIB_ROUTER_BGP_ID].name = parse_bgp_lib::parse_bgp_lib_router_names[LIB_ROUTER_BGP_ID];
                    update.router[LIB_ROUTER_BGP_ID].value.push_back(ipv4_char);

                    SELF_DEBUG("Init message type %hu = %s",
                               initMsg.type, update.router[LIB_ROUTER_BGP_ID].value.front().c_str());

                    break;

                default:
                    LOG_NOTICE("Init message type %hu is unexpected per rfc7854", initMsg.type);
            }
        }
    }
Ejemplo n.º 15
0
void SPUThread::WriteChannel(u32 ch, const u128& r)
{
	const u32 v = r._u32[3];

	switch (ch)
	{
	case SPU_WrOutIntrMbox:
	{
		if (!group) // if RawSPU
		{
			if (Ini.HLELogging.GetValue()) LOG_NOTICE(Log::SPU, "SPU_WrOutIntrMbox: interrupt(v=0x%x)", v);
			while (!SPU.Out_IntrMBox.Push(v))
			{
				std::this_thread::sleep_for(std::chrono::milliseconds(1));
				if (Emu.IsStopped())
				{
					LOG_WARNING(Log::SPU, "%s(%s) aborted", __FUNCTION__, spu_ch_name[ch]);
					return;
				}
			}
			m_intrtag[2].stat |= 1;
			if (CPUThread* t = Emu.GetCPU().GetThread(m_intrtag[2].thread))
			{
				if (t->GetType() == CPU_THREAD_PPU)
				{
					if (t->IsAlive())
					{
						LOG_ERROR(Log::SPU, "%s(%s): interrupt thread was alive", __FUNCTION__, spu_ch_name[ch]);
						Emu.Pause();
						return;
					}
					PPUThread& ppu = *(PPUThread*)t;
					ppu.GPR[3] = ppu.m_interrupt_arg;
					ppu.FastCall2(vm::read32(ppu.entry), vm::read32(ppu.entry + 4));
				}
			}
		}
		else
		{
			const u8 code = v >> 24;
			if (code < 64)
			{
				/* ===== sys_spu_thread_send_event (used by spu_printf) ===== */

				u8 spup = code & 63;

				u32 data;
				if (!SPU.Out_MBox.Pop(data))
				{
					LOG_ERROR(Log::SPU, "sys_spu_thread_send_event(v=0x%x, spup=%d): Out_MBox is empty", v, spup);
					return;
				}

				if (Ini.HLELogging.GetValue())
				{
					LOG_NOTICE(Log::SPU, "sys_spu_thread_send_event(spup=%d, data0=0x%x, data1=0x%x)", spup, v & 0x00ffffff, data);
				}

				EventPort& port = SPUPs[spup];

				std::lock_guard<std::mutex> lock(port.m_mutex);

				if (!port.eq)
				{
					LOG_WARNING(Log::SPU, "sys_spu_thread_send_event(spup=%d, data0=0x%x, data1=0x%x): event queue not connected", spup, (v & 0x00ffffff), data);
					SPU.In_MBox.PushUncond(CELL_ENOTCONN); // TODO: check error passing
					return;
				}

				if (!port.eq->events.push(SYS_SPU_THREAD_EVENT_USER_KEY, GetCurrentCPUThread()->GetId(), ((u64)spup << 32) | (v & 0x00ffffff), data))
				{
					SPU.In_MBox.PushUncond(CELL_EBUSY);
					return;
				}

				SPU.In_MBox.PushUncond(CELL_OK);
				return;
			}
			else if (code < 128)
			{
				/* ===== sys_spu_thread_throw_event ===== */

				const u8 spup = code & 63;

				u32 data;
				if (!SPU.Out_MBox.Pop(data))
				{
					LOG_ERROR(Log::SPU, "sys_spu_thread_throw_event(v=0x%x, spup=%d): Out_MBox is empty", v, spup);
					return;
				}

				//if (Ini.HLELogging.GetValue())
				{
					LOG_WARNING(Log::SPU, "sys_spu_thread_throw_event(spup=%d, data0=0x%x, data1=0x%x)", spup, v & 0x00ffffff, data);
				}

				EventPort& port = SPUPs[spup];

				std::lock_guard<std::mutex> lock(port.m_mutex);

				if (!port.eq)
				{
					LOG_WARNING(Log::SPU, "sys_spu_thread_throw_event(spup=%d, data0=0x%x, data1=0x%x): event queue not connected", spup, (v & 0x00ffffff), data);
					return;
				}

				// TODO: check passing spup value
				if (!port.eq->events.push(SYS_SPU_THREAD_EVENT_USER_KEY, GetCurrentCPUThread()->GetId(), ((u64)spup << 32) | (v & 0x00ffffff), data))
				{
					LOG_WARNING(Log::SPU, "sys_spu_thread_throw_event(spup=%d, data0=0x%x, data1=0x%x) failed (queue is full)", spup, (v & 0x00ffffff), data);
					return;
				}

				return;
			}
			else if (code == 128)
			{
				/* ===== sys_event_flag_set_bit ===== */
				u32 flag = v & 0xffffff;

				u32 data;
				if (!SPU.Out_MBox.Pop(data))
				{
					LOG_ERROR(Log::SPU, "sys_event_flag_set_bit(v=0x%x (flag=%d)): Out_MBox is empty", v, flag);
					return;
				}

				if (flag > 63)
				{
					LOG_ERROR(Log::SPU, "sys_event_flag_set_bit(id=%d, v=0x%x): flag > 63", data, v, flag);
					return;
				}

				//if (Ini.HLELogging.GetValue())
				{
					LOG_WARNING(Log::SPU, "sys_event_flag_set_bit(id=%d, v=0x%x (flag=%d))", data, v, flag);
				}

				EventFlag* ef;
				if (!Emu.GetIdManager().GetIDData(data, ef))
				{
					LOG_ERROR(Log::SPU, "sys_event_flag_set_bit(id=%d, v=0x%x (flag=%d)): EventFlag not found", data, v, flag);
					SPU.In_MBox.PushUncond(CELL_ESRCH);
					return;
				}

				u32 tid = GetCurrentCPUThread()->GetId();

				ef->m_mutex.lock(tid);
				ef->flags |= (u64)1 << flag;
				if (u32 target = ef->check())
				{
					// if signal, leave both mutexes locked...
					ef->signal.lock(target);
					ef->m_mutex.unlock(tid, target);
				}
				else
				{
					ef->m_mutex.unlock(tid);
				}

				SPU.In_MBox.PushUncond(CELL_OK);
				return;
			}
			else if (code == 192)
			{
				/* ===== sys_event_flag_set_bit_impatient ===== */
				u32 flag = v & 0xffffff;

				u32 data;
				if (!SPU.Out_MBox.Pop(data))
				{
					LOG_ERROR(Log::SPU, "sys_event_flag_set_bit_impatient(v=0x%x (flag=%d)): Out_MBox is empty", v, flag);
					return;
				}

				if (flag > 63)
				{
					LOG_ERROR(Log::SPU, "sys_event_flag_set_bit_impatient(id=%d, v=0x%x): flag > 63", data, v, flag);
					return;
				}

				//if (Ini.HLELogging.GetValue())
				{
					LOG_WARNING(Log::SPU, "sys_event_flag_set_bit_impatient(id=%d, v=0x%x (flag=%d))", data, v, flag);
				}

				EventFlag* ef;
				if (!Emu.GetIdManager().GetIDData(data, ef))
				{
					LOG_WARNING(Log::SPU, "sys_event_flag_set_bit_impatient(id=%d, v=0x%x (flag=%d)): EventFlag not found", data, v, flag);
					return;
				}

				u32 tid = GetCurrentCPUThread()->GetId();

				ef->m_mutex.lock(tid);
				ef->flags |= (u64)1 << flag;
				if (u32 target = ef->check())
				{
					// if signal, leave both mutexes locked...
					ef->signal.lock(target);
					ef->m_mutex.unlock(tid, target);
				}
				else
				{
					ef->m_mutex.unlock(tid);
				}

				return;
			}
			else
			{
				u32 data;
				if (SPU.Out_MBox.Pop(data))
				{
					LOG_ERROR(Log::SPU, "SPU_WrOutIntrMbox: unknown data (v=0x%x); Out_MBox = 0x%x", v, data);
				}
				else
				{
					LOG_ERROR(Log::SPU, "SPU_WrOutIntrMbox: unknown data (v=0x%x)", v);
				}
				SPU.In_MBox.PushUncond(CELL_EINVAL); // ???
				return;
			}
		}
		break;
	}

	case SPU_WrOutMbox:
	{
		while (!SPU.Out_MBox.Push(v) && !Emu.IsStopped()) std::this_thread::sleep_for(std::chrono::milliseconds(1));
		break;
	}

	case MFC_WrTagMask:
	{
		MFC1.QueryMask.SetValue(v);
		break;
	}

	case MFC_WrTagUpdate:
	{
		MFC1.TagStatus.PushUncond(MFC1.QueryMask.GetValue());
		break;
	}

	case MFC_LSA:
	{
		MFC1.LSA.SetValue(v);
		break;
	}

	case MFC_EAH:
	{
		MFC1.EAH.SetValue(v);
		break;
	}

	case MFC_EAL:
	{
		MFC1.EAL.SetValue(v);
		break;
	}

	case MFC_Size:
	{
		MFC1.Size_Tag.SetValue((MFC1.Size_Tag.GetValue() & 0xffff) | (v << 16));
		break;
	}

	case MFC_TagID:
	{
		MFC1.Size_Tag.SetValue((MFC1.Size_Tag.GetValue() & ~0xffff) | (v & 0xffff));
		break;
	}


	case MFC_Cmd:
	{
		MFC1.CMDStatus.SetValue(v);
		EnqMfcCmd(MFC1);
		break;
	}

	case MFC_WrListStallAck:
	{
		if (v >= 32)
		{
			LOG_ERROR(Log::SPU, "MFC_WrListStallAck error: invalid tag(%d)", v);
			return;
		}
		StalledList temp = StallList[v];
		if (!temp.MFCArgs)
		{
			LOG_ERROR(Log::SPU, "MFC_WrListStallAck error: empty tag(%d)", v);
			return;
		}
		StallList[v].MFCArgs = nullptr;
		ListCmd(temp.lsa, temp.ea, temp.tag, temp.size, temp.cmd, *temp.MFCArgs);
		break;
	}

	case SPU_WrDec:
	{
		m_dec_start = get_time();
		m_dec_value = v;
		break;
	}

	case SPU_WrEventMask:
	{
		m_event_mask = v;
		if (v & ~(SPU_EVENT_IMPLEMENTED)) LOG_ERROR(Log::SPU, "SPU_WrEventMask: unsupported event masked (0x%x)");
		break;
	}

	case SPU_WrEventAck:
	{
		m_events &= ~v;
		break;
	}

	default:
	{
		LOG_ERROR(Log::SPU, "%s error (v=0x%x): unknown/illegal channel (%d [%s]).", __FUNCTION__, v, ch, spu_ch_name[ch]);
		break;
	}
	}

	if (Emu.IsStopped()) LOG_WARNING(Log::SPU, "%s(%s) aborted", __FUNCTION__, spu_ch_name[ch]);
}
Ejemplo n.º 16
0
int LsapiConn::processResp()
{
    int ret;
    while( getState() == PROCESSING )
    {
        if ( m_iPacketHeaderLeft > 0 )
        {
            ret = read( ((char *)&m_respHeader) + sizeof( m_respHeader ) - m_iPacketHeaderLeft, 
                        m_iPacketHeaderLeft );
            if ( D_ENABLED( DL_MEDIUM ) )
                LOG_D(( getLogger(), "[%s] process packet header %d bytes",
                    getLogId(), ret ));
            if ( ret > 0 )
            {
                m_iPacketHeaderLeft -= ret;
                if ( m_iPacketHeaderLeft == 0 )
                {
                    m_iPacketLeft = verifyPacketHeader( &m_respHeader ) -
                            LSAPI_PACKET_HEADER_LEN;
                    if ( m_iPacketLeft < 0 )
                    {
                        const char * p = (const char *)&m_respHeader;
                        LOG_WARN(( "[%s] LSAPI Packet header is invalid,"
                                "('%c','%c','%c','%c','%c','%c','%c','%c')",
                                getLogId(), *p, *(p+1), *(p+2), *(p+3),
                                *(p+4), *(p+5), *(p+6), *(p+7) ));
						break;

                    }
//                     if ( m_iPacketLeft > LSAPI_MAX_HEADER_LEN )
//                     {
//                         LOG_WARN(( "[%s] LSAPI Packet is too large: %d",
//                                 getLogId(), m_iPacketLeft ));
// 						break;
//                     }
                    switch( m_respHeader.m_type )
                    {
                    case LSAPI_RESP_END:
                        m_respState = 0;
						incReqProcessed();
                        setInProcess( 0 );
                        getConnector()->endResponse( 0, 0 );
                        return 0;
                    case LSAPI_RESP_HEADER:
                        m_iCurRespHeader = 0;
                        m_respState = LSAPI_CONN_READ_RESP_INFO;
                        m_pRespHeaderProcess = (char *)&m_respInfo;
                        setRespBuf( m_pRespHeaderProcess );
                        break;
                    case LSAPI_REQ_RECEIVED:
                        m_reqReceived       = 1;
                        break;
                    }
                }
            }
            else
            {
                if (( m_respState == LSAPI_CONN_READ_RESP_BODY )&&
                    ( getConnector()))
                    getConnector()->flushResp();
                return ret;
            }
        }
        if ( m_iPacketLeft > 0 )
        {
            switch( m_respHeader.m_type )
            {
            case LSAPI_RESP_HEADER:
                ret = processRespHeader();
                if ( ret <= 0 )
                    return ret;
                break;
            case LSAPI_RESP_STREAM:
                ret = readRespBody();
                if ( ret <= 0 )
                {
                    if (( m_respState == LSAPI_CONN_READ_RESP_BODY )&&
                        ( getConnector()))
                        getConnector()->flushResp();
                    return ret;
                }
                break;
            case LSAPI_STDERR_STREAM:
                ret = readStderrStream();
                if ( ret <= 0 )
                    return ret;
                break;
            default:
                //error: protocol error
                LOG_NOTICE(( getLogger(), "[%s] Unknown Packet Type %c, LSAPI protcol is broken.",
                    getLogId(), m_respHeader.m_type ));
                errno = EIO;
                return -1;
            }
        }
        else
        {
            m_iPacketHeaderLeft = LSAPI_PACKET_HEADER_LEN;
        }
    }
	errno = EIO;    
    return -1;
}
Ejemplo n.º 17
0
void SPUThread::StopAndSignal(u32 code)
{
	SetExitStatus(code); // exit code (not status)
	// TODO: process interrupts for RawSPU

	switch (code)
	{
	case 0x110:
	{
		/* ===== sys_spu_thread_receive_event ===== */

		u32 spuq = 0;
		if (!SPU.Out_MBox.Pop(spuq))
		{
			LOG_ERROR(Log::SPU, "sys_spu_thread_receive_event: cannot read Out_MBox");
			SPU.In_MBox.PushUncond(CELL_EINVAL); // ???
			return;
		}

		if (SPU.In_MBox.GetCount())
		{
			LOG_ERROR(Log::SPU, "sys_spu_thread_receive_event(spuq=0x%x): In_MBox is not empty", spuq);
			SPU.In_MBox.PushUncond(CELL_EBUSY); // ???
			return;
		}

		if (Ini.HLELogging.GetValue())
		{
			LOG_NOTICE(Log::SPU, "sys_spu_thread_receive_event(spuq=0x%x)", spuq);
		}

		EventQueue* eq;
		if (!SPUQs.GetEventQueue(FIX_SPUQ(spuq), eq))
		{
			SPU.In_MBox.PushUncond(CELL_EINVAL); // TODO: check error value
			return;
		}

		u32 tid = GetId();

		eq->sq.push(tid); // add thread to sleep queue

		while (true)
		{
			switch (eq->owner.trylock(tid))
			{
			case SMR_OK:
				if (!eq->events.count())
				{
					eq->owner.unlock(tid);
					break;
				}
				else
				{
					u32 next = (eq->protocol == SYS_SYNC_FIFO) ? eq->sq.pop() : eq->sq.pop_prio();
					if (next != tid)
					{
						eq->owner.unlock(tid, next);
						break;
					}
				}
			case SMR_SIGNAL:
			{
				sys_event_data event;
				eq->events.pop(event);
				eq->owner.unlock(tid);
				SPU.In_MBox.PushUncond(CELL_OK);
				SPU.In_MBox.PushUncond((u32)event.data1);
				SPU.In_MBox.PushUncond((u32)event.data2);
				SPU.In_MBox.PushUncond((u32)event.data3);
				return;
			}
			case SMR_FAILED: break;
			default: eq->sq.invalidate(tid); SPU.In_MBox.PushUncond(CELL_ECANCELED); return;
			}

			std::this_thread::sleep_for(std::chrono::milliseconds(1));
			if (Emu.IsStopped())
			{
				LOG_WARNING(Log::SPU, "sys_spu_thread_receive_event(spuq=0x%x) aborted", spuq);
				eq->sq.invalidate(tid);
				return;
			}
		}
		break;
	}

	case 0x101:
	{
		/* ===== sys_spu_thread_group_exit ===== */

		if (!group)
		{
			LOG_ERROR(Log::SPU, "sys_spu_thread_group_exit(): group not set");
			break;
		}
		else if (!SPU.Out_MBox.GetCount())
		{
			LOG_ERROR(Log::SPU, "sys_spu_thread_group_exit(): Out_MBox is empty");
		}
		else if (Ini.HLELogging.GetValue())
		{
			LOG_NOTICE(Log::SPU, "sys_spu_thread_group_exit(status=0x%x)", SPU.Out_MBox.GetValue());
		}
		
		group->m_group_exit = true;
		group->m_exit_status = SPU.Out_MBox.GetValue();
		for (auto& v : group->list)
		{
			if (CPUThread* t = Emu.GetCPU().GetThread(v))
			{
				t->Stop();
			}
		}

		break;
	}

	case 0x102:
	{
		/* ===== sys_spu_thread_exit ===== */

		if (!SPU.Out_MBox.GetCount())
		{
			LOG_ERROR(Log::SPU, "sys_spu_thread_exit(): Out_MBox is empty");
		}
		else if (Ini.HLELogging.GetValue())
		{
			// the real exit status
			LOG_NOTICE(Log::SPU, "sys_spu_thread_exit(status=0x%x)", SPU.Out_MBox.GetValue());
		}
		SPU.Status.SetValue(SPU_STATUS_STOPPED_BY_STOP);
		Stop();
		break;
	}

	default:
	{
		if (!SPU.Out_MBox.GetCount())
		{
			LOG_ERROR(Log::SPU, "Unknown STOP code: 0x%x (no message)", code);
		}
		else
		{
			LOG_ERROR(Log::SPU, "Unknown STOP code: 0x%x (message=0x%x)", code, SPU.Out_MBox.GetValue());
		}
		Stop();
		break;
	}
	}
}
Ejemplo n.º 18
0
int LsapiConn::readStderrStream()
{
    register HttpExtConnector * pHEC = getConnector();
    int     ret;
    size_t  bufLen;
    char    achBuf[2049];
    
    while( m_iPacketLeft > 0 )
    {
        char * pBuf = achBuf;
        bufLen = sizeof( achBuf );
        int toRead = m_iPacketLeft + sizeof( m_respHeader );
        if ( toRead > (int)bufLen )
            toRead = bufLen ;
        ret = read( pBuf, toRead );
        if ( ret > 0 )
        {
            int len, packetLen;
            if ( D_ENABLED( DL_MEDIUM ) )
                LOG_D(( getLogger(), "[%s] process STDERR stream %d bytes, packet left: %d",
                    getLogId(), ret, m_iPacketLeft ));
            if ( ret >= m_iPacketLeft )
            {
                packetLen       = m_iPacketLeft;
                m_iPacketLeft   = 0;
            }
            else
            {
                packetLen       = ret;
                m_iPacketLeft  -= ret;
            }

            if (( packetLen == 8 )&& !m_iPacketLeft 
                && ( m_respHeader.m_packetLen.m_iLen == 16 ) 
                && ( memcmp( achBuf, "\0PID", 4 ) == 0 ) )
            {
                //ignore this packet for now.
            }
            else if ( pHEC )
                pHEC->processErrData( pBuf, packetLen );
            else
            {
                char ch = pBuf[packetLen];
                pBuf[ packetLen ] = 0;
                LOG_NOTICE(( getLogger(), "[%s] [LSAPI:STDERR]: %s", getLogId(), pBuf ));
                pBuf[ packetLen ] = ch;
            }

            if ( m_iPacketLeft <= 0 )
            {
                m_iPacketHeaderLeft = LSAPI_PACKET_HEADER_LEN;
                if ( ret > packetLen )
                {
                    if ( D_ENABLED( DL_MEDIUM ) )
                        LOG_D(( getLogger(), "[%s] process packet header %d bytes",
                            getLogId(), ret - packetLen ));
                    len = processPacketHeader( pBuf + packetLen, ret - packetLen );
                    if ( len <= 0 )
                        return len;
                    if (( m_respHeader.m_type != LSAPI_STDERR_STREAM )||
                        ( m_iPacketLeft <= 0 ))
                        return 1;
                }
                else
                    break;
            }
        }
        else
        {
            return ret;
        }
    }
    return 1;
}
Ejemplo n.º 19
0
u32 vdecOpen(VideoDecoder* data)
{
    VideoDecoder& vdec = *data;

    vdec.vdecCb = &Emu.GetCPU().AddThread(CPU_THREAD_PPU);

    u32 vdec_id = cellVdec->GetNewId(data);

    vdec.id = vdec_id;

    vdec.vdecCb->SetName("Video Decoder[" + std::to_string(vdec_id) + "] Callback");

    thread t("Video Decoder[" + std::to_string(vdec_id) + "] Thread", [&]()
    {
        LOG_NOTICE(HLE, "Video Decoder thread started");

        VdecTask& task = vdec.task;

        while (true)
        {
            if (Emu.IsStopped())
            {
                break;
            }

            if (vdec.job.IsEmpty() && vdec.is_running)
            {
                Sleep(1);
                continue;
            }

            if (vdec.frames.GetCount() >= 50)
            {
                Sleep(1);
                continue;
            }

            if (!vdec.job.Pop(task))
            {
                break;
            }

            switch (task.type)
            {
            case vdecStartSeq:
            {
                // TODO: reset data
                LOG_WARNING(HLE, "vdecStartSeq:");

                vdec.reader.addr = 0;
                vdec.reader.size = 0;
                vdec.is_running = true;
                vdec.just_started = true;
            }
            break;

            case vdecEndSeq:
            {
                // TODO: finalize
                LOG_WARNING(HLE, "vdecEndSeq:");

                vdec.vdecCb->ExecAsCallback(vdec.cbFunc, false, vdec.id, CELL_VDEC_MSG_TYPE_SEQDONE, CELL_OK, vdec.cbArg);
                /*Callback cb;
                cb.SetAddr(vdec.cbFunc);
                cb.Handle(vdec.id, CELL_VDEC_MSG_TYPE_SEQDONE, CELL_OK, vdec.cbArg);
                cb.Branch(true); // ???*/

                avcodec_close(vdec.ctx);
                avformat_close_input(&vdec.fmt);

                vdec.is_running = false;
            }
            break;

            case vdecDecodeAu:
            {
                int err;

                if (task.mode != CELL_VDEC_DEC_MODE_NORMAL)
                {
                    LOG_ERROR(HLE, "vdecDecodeAu: unsupported decoding mode(%d)", task.mode);
                    break;
                }

                vdec.reader.addr = task.addr;
                vdec.reader.size = task.size;
                //LOG_NOTICE(HLE, "Video AU: size = 0x%x, pts = 0x%llx, dts = 0x%llx", task.size, task.pts, task.dts);

                if (vdec.just_started)
                {
                    vdec.first_pts = task.pts;
                    vdec.last_pts = task.pts;
                    vdec.first_dts = task.dts;
                }

                struct AVPacketHolder : AVPacket
                {
                    AVPacketHolder(u32 size)
                    {
                        av_init_packet(this);

                        if (size)
                        {
                            data = (u8*)av_malloc(size + FF_INPUT_BUFFER_PADDING_SIZE);
                            memset(data + size, 0, FF_INPUT_BUFFER_PADDING_SIZE);
                            this->size = size + FF_INPUT_BUFFER_PADDING_SIZE;
                        }
                        else
                        {
                            data = NULL;
                            size = 0;
                        }
                    }

                    ~AVPacketHolder()
                    {
                        av_free(data);
                        //av_free_packet(this);
                    }

                } au(0);

                if (vdec.just_started) // deferred initialization
                {
                    err = avformat_open_input(&vdec.fmt, NULL, av_find_input_format("mpeg"), NULL);
                    if (err)
                    {
                        LOG_ERROR(HLE, "vdecDecodeAu: avformat_open_input() failed");
                        Emu.Pause();
                        break;
                    }
                    AVCodec* codec = avcodec_find_decoder(AV_CODEC_ID_H264); // ???
                    if (!codec)
                    {
                        LOG_ERROR(HLE, "vdecDecodeAu: avcodec_find_decoder() failed");
                        Emu.Pause();
                        break;
                    }
                    /*err = avformat_find_stream_info(vdec.fmt, NULL);
                    if (err)
                    {
                    	LOG_ERROR(HLE, "vdecDecodeAu: avformat_find_stream_info() failed");
                    	Emu.Pause();
                    	break;
                    }
                    if (!vdec.fmt->nb_streams)
                    {
                    	LOG_ERROR(HLE, "vdecDecodeAu: no stream found");
                    	Emu.Pause();
                    	break;
                    }*/
                    if (!avformat_new_stream(vdec.fmt, codec))
                    {
                        LOG_ERROR(HLE, "vdecDecodeAu: avformat_new_stream() failed");
                        Emu.Pause();
                        break;
                    }
                    vdec.ctx = vdec.fmt->streams[0]->codec; // TODO: check data

                    AVDictionary* opts = nullptr;
                    av_dict_set(&opts, "refcounted_frames", "1", 0);
                    {
                        std::lock_guard<std::mutex> lock(g_mutex_avcodec_open2);
                        // not multithread-safe
                        err = avcodec_open2(vdec.ctx, codec, &opts);
                    }
                    if (err)
                    {
                        LOG_ERROR(HLE, "vdecDecodeAu: avcodec_open2() failed");
                        Emu.Pause();
                        break;
                    }
                    //vdec.ctx->flags |= CODEC_FLAG_TRUNCATED;
                    //vdec.ctx->flags2 |= CODEC_FLAG2_CHUNKS;
                    vdec.just_started = false;
                }

                bool last_frame = false;

                while (true)
                {
                    if (Emu.IsStopped())
                    {
                        LOG_WARNING(HLE, "vdecDecodeAu: aborted");
                        return;
                    }

                    last_frame = av_read_frame(vdec.fmt, &au) < 0;
                    if (last_frame)
                    {
                        //break;
                        av_free(au.data);
                        au.data = NULL;
                        au.size = 0;
                    }

                    struct VdecFrameHolder : VdecFrame
                    {
                        VdecFrameHolder()
                        {
                            data = av_frame_alloc();
                        }

                        ~VdecFrameHolder()
                        {
                            if (data)
                            {
                                av_frame_unref(data);
                                av_frame_free(&data);
                            }
                        }

                    } frame;

                    if (!frame.data)
                    {
                        LOG_ERROR(HLE, "vdecDecodeAu: av_frame_alloc() failed");
                        Emu.Pause();
                        break;
                    }

                    int got_picture = 0;

                    int decode = avcodec_decode_video2(vdec.ctx, frame.data, &got_picture, &au);

                    if (decode <= 0)
                    {
                        if (!last_frame && decode < 0)
                        {
                            LOG_ERROR(HLE, "vdecDecodeAu: AU decoding error(0x%x)", decode);
                        }
                        if (!got_picture && vdec.reader.size == 0) break; // video end?
                    }

                    if (got_picture)
                    {
                        u64 ts = av_frame_get_best_effort_timestamp(frame.data);
                        if (ts != AV_NOPTS_VALUE)
                        {
                            frame.pts = ts/* - vdec.first_pts*/; // ???
                            vdec.last_pts = frame.pts;
                        }
                        else
                        {
                            vdec.last_pts += vdec.ctx->time_base.num * 90000 / (vdec.ctx->time_base.den / vdec.ctx->ticks_per_frame);
                            frame.pts = vdec.last_pts;
                        }
                        //frame.pts = vdec.last_pts;
                        //vdec.last_pts += 3754;
                        frame.dts = (frame.pts - vdec.first_pts) + vdec.first_dts;
                        frame.userdata = task.userData;

                        //LOG_NOTICE(HLE, "got picture (pts=0x%llx, dts=0x%llx)", frame.pts, frame.dts);

                        vdec.frames.Push(frame); // !!!!!!!!
                        frame.data = nullptr; // to prevent destruction

                        vdec.vdecCb->ExecAsCallback(vdec.cbFunc, false, vdec.id, CELL_VDEC_MSG_TYPE_PICOUT, CELL_OK, vdec.cbArg);
                        /*Callback cb;
                        cb.SetAddr(vdec.cbFunc);
                        cb.Handle(vdec.id, CELL_VDEC_MSG_TYPE_PICOUT, CELL_OK, vdec.cbArg);
                        cb.Branch(false);*/
                    }
                }

                vdec.vdecCb->ExecAsCallback(vdec.cbFunc, false, vdec.id, CELL_VDEC_MSG_TYPE_AUDONE, CELL_OK, vdec.cbArg);
                /*Callback cb;
                cb.SetAddr(vdec.cbFunc);
                cb.Handle(vdec.id, CELL_VDEC_MSG_TYPE_AUDONE, CELL_OK, vdec.cbArg);
                cb.Branch(false);*/
            }
            break;

            case vdecClose:
            {
                vdec.is_finished = true;
                LOG_NOTICE(HLE, "Video Decoder thread ended");
                return;
            }

            case vdecSetFrameRate:
            {
                LOG_ERROR(HLE, "TODO: vdecSetFrameRate(%d)", task.frc);
            }
            break;

            default:
                LOG_ERROR(HLE, "Video Decoder thread error: unknown task(%d)", task.type);
            }
        }

        vdec.is_finished = true;
        LOG_WARNING(HLE, "Video Decoder thread aborted");
    });

    t.detach();

    return vdec_id;
}
Ejemplo n.º 20
0
void GLGSRender::flip(int buffer)
{
	u32 buffer_width = gcm_buffers[buffer].width;
	u32 buffer_height = gcm_buffers[buffer].height;
	u32 buffer_pitch = gcm_buffers[buffer].pitch;

	glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
	glDisable(GL_SCISSOR_TEST);
	glDisable(GL_DEPTH_TEST);
	glDisable(GL_STENCIL_TEST);

	rsx::tiled_region buffer_region = get_tiled_address(gcm_buffers[buffer].offset, CELL_GCM_LOCATION_LOCAL);
	u32 absolute_address = buffer_region.address + buffer_region.base;

	if (0)
	{
		LOG_NOTICE(RSX, "flip(%d) -> 0x%x [0x%x]", buffer, absolute_address, rsx::get_address(gcm_buffers[1 - buffer].offset, CELL_GCM_LOCATION_LOCAL));
	}

	gl::texture *render_target_texture = m_rtts.get_texture_from_render_target_if_applicable(absolute_address);

	/**
	* Calling read_buffers will overwrite cached content
	*/

	__glcheck m_flip_fbo.recreate();
	m_flip_fbo.bind();

	auto *flip_fbo = &m_flip_fbo;

	if (render_target_texture)
	{
		__glcheck m_flip_fbo.color = *render_target_texture;
		__glcheck m_flip_fbo.read_buffer(m_flip_fbo.color);
	}
	else if (draw_fbo)
	{
		//HACK! it's here, because textures cache isn't implemented correctly!
		flip_fbo = &draw_fbo;
	}
	else
	{
		if (!m_flip_tex_color || m_flip_tex_color.size() != sizei{ (int)buffer_width, (int)buffer_height })
		{
			m_flip_tex_color.recreate(gl::texture::target::texture2D);

			__glcheck m_flip_tex_color.config()
				.size({ (int)buffer_width, (int)buffer_height })
				.type(gl::texture::type::uint_8_8_8_8)
				.format(gl::texture::format::bgra);

			m_flip_tex_color.pixel_unpack_settings().aligment(1).row_length(buffer_pitch / 4);
		}

		if (buffer_region.tile)
		{
			std::unique_ptr<u8[]> temp(new u8[buffer_height * buffer_pitch]);
			buffer_region.read(temp.get(), buffer_width, buffer_height, buffer_pitch);
			__glcheck m_flip_tex_color.copy_from(temp.get(), gl::texture::format::bgra, gl::texture::type::uint_8_8_8_8);
		}
		else
		{
			__glcheck m_flip_tex_color.copy_from(buffer_region.ptr, gl::texture::format::bgra, gl::texture::type::uint_8_8_8_8);
		}

		m_flip_fbo.color = m_flip_tex_color;
		__glcheck m_flip_fbo.read_buffer(m_flip_fbo.color);
	}

	areai screen_area = coordi({}, { (int)buffer_width, (int)buffer_height });

	coordi aspect_ratio;
	if (1) //enable aspect ratio
	{
		sizei csize(m_frame->client_width(), m_frame->client_height());
		sizei new_size = csize;

		const double aq = (double)buffer_width / buffer_height;
		const double rq = (double)new_size.width / new_size.height;
		const double q = aq / rq;

		if (q > 1.0)
		{
			new_size.height = int(new_size.height / q);
			aspect_ratio.y = (csize.height - new_size.height) / 2;
		}
		else if (q < 1.0)
		{
			new_size.width = int(new_size.width * q);
			aspect_ratio.x = (csize.width - new_size.width) / 2;
		}

		aspect_ratio.size = new_size;
	}
	else
	{
		aspect_ratio.size = { m_frame->client_width(), m_frame->client_height() };
	}

	gl::screen.clear(gl::buffers::color_depth_stencil);

	__glcheck flip_fbo->blit(gl::screen, screen_area, areai(aspect_ratio).flipped_vertical());

	if (g_cfg_rsx_overlay)
	{
		gl::screen.bind();
		glViewport(0, 0, m_frame->client_width(), m_frame->client_height());
		
		m_text_printer.print_text(0, 0, m_frame->client_width(), m_frame->client_height(), "draw calls: " + std::to_string(m_draw_calls));
		m_text_printer.print_text(0, 18, m_frame->client_width(), m_frame->client_height(), "draw call setup: " + std::to_string(m_begin_time) + "us");
		m_text_printer.print_text(0, 36, m_frame->client_width(), m_frame->client_height(), "vertex upload time: " + std::to_string(m_vertex_upload_time) + "us");
		m_text_printer.print_text(0, 54, m_frame->client_width(), m_frame->client_height(), "textures upload time: " + std::to_string(m_textures_upload_time) + "us");
		m_text_printer.print_text(0, 72, m_frame->client_width(), m_frame->client_height(), "draw call execution: " + std::to_string(m_draw_time) + "us");
	}

	m_frame->flip(m_context);

	m_draw_calls = 0;
	m_begin_time = 0;
	m_draw_time = 0;
	m_vertex_upload_time = 0;
	m_textures_upload_time = 0;

	for (auto &tex : m_rtts.invalidated_resources)
	{
		tex->remove();
	}

	m_rtts.invalidated_resources.clear();
}
Ejemplo n.º 21
0
void PE_Open() {
    LOG_NOTICE(TPE, "initialized ok");
    memset(PERegisters, 0, sizeof(PERegisters));
}
Ejemplo n.º 22
0
void VFS::SaveLoadDevices(std::vector<VFSManagerEntry>& res, bool is_load)
{
	int count = 0;
	if (is_load)
	{
		count = rpcs3::config.vfs.count.value();

		if (!count)
		{
			res.emplace_back(vfsDevice_LocalFile, "$(EmulatorDir)/dev_hdd0/",   "/dev_hdd0/");
			res.emplace_back(vfsDevice_LocalFile, "$(EmulatorDir)/dev_hdd1/",   "/dev_hdd1/");
			res.emplace_back(vfsDevice_LocalFile, "$(EmulatorDir)/dev_flash/",  "/dev_flash/");
			res.emplace_back(vfsDevice_LocalFile, "$(EmulatorDir)/dev_usb000/", "/dev_usb000/");
			res.emplace_back(vfsDevice_LocalFile, "$(EmulatorDir)/dev_usb000/", "/dev_usb/");
			res.emplace_back(vfsDevice_LocalFile, "",                           "/host_root/");

			return;
		}

		res.resize(count);
	}
	else
	{
		count = (int)res.size();
		rpcs3::config.vfs.count = count;
	}

	// Custom EmulationDir
	if (rpcs3::config.system.emulation_dir_path_enable.value())
	{
		std::string dir = rpcs3::config.system.emulation_dir_path.value();

		if (dir.empty())
		{
			rpcs3::config.system.emulation_dir_path = Emu.GetEmulatorPath();
		}

		if (!fs::is_dir(dir))
		{
			LOG_ERROR(GENERAL, "Custom EmulationDir: directory '%s' not found", dir);
		}
		else
		{
			LOG_NOTICE(GENERAL, "Custom EmulationDir: $(EmulatorDir) bound to '%s'", dir);
		}
	}

	for(int i=0; i<count; ++i)
	{
		rpcs3::config.vfs.add_entry(fmt::format("path[%d]", i), std::string{});
		rpcs3::config.vfs.add_entry(fmt::format("device_path[%d]", i), std::string{});
		rpcs3::config.vfs.add_entry(fmt::format("mount[%d]", i), std::string{});
		rpcs3::config.vfs.add_entry(fmt::format("device[%d]", i), 0);

		if (is_load)
		{
			res[i] = VFSManagerEntry();
			res[i].path = rpcs3::config.vfs.get_entry_value<std::string>(fmt::format("path[%d]", i), std::string{});
			res[i].device_path = rpcs3::config.vfs.get_entry_value<std::string>(fmt::format("device_path[%d]", i), std::string{});
			res[i].mount = rpcs3::config.vfs.get_entry_value<std::string>(fmt::format("mount[%d]", i), std::string{});
			res[i].device = (vfsDeviceType)rpcs3::config.vfs.get_entry_value<int>(fmt::format("device[%d]", i), 0);
		}
		else
		{
			rpcs3::config.vfs.set_entry_value(fmt::format("path[%d]", i), res[i].path);
			rpcs3::config.vfs.set_entry_value(fmt::format("device_path[%d]", i), res[i].device_path);
			rpcs3::config.vfs.set_entry_value(fmt::format("mount[%d]", i), res[i].mount);
			rpcs3::config.vfs.set_entry_value(fmt::format("device[%d]", i), (int)res[i].device);
		}
	}
}
Ejemplo n.º 23
0
void SELFDecrypter::ShowHeaders(bool isElf32)
{
	LOG_NOTICE(LOADER, "SCE header");
	LOG_NOTICE(LOADER, "----------------------------------------------------");
	sce_hdr.Show();
	LOG_NOTICE(LOADER, "----------------------------------------------------");
	LOG_NOTICE(LOADER, "SELF header");
	LOG_NOTICE(LOADER, "----------------------------------------------------");
	self_hdr.Show();
	LOG_NOTICE(LOADER, "----------------------------------------------------");
	LOG_NOTICE(LOADER, "APP INFO");
	LOG_NOTICE(LOADER, "----------------------------------------------------");
	app_info.Show();
	LOG_NOTICE(LOADER, "----------------------------------------------------");
	LOG_NOTICE(LOADER, "ELF header");
	LOG_NOTICE(LOADER, "----------------------------------------------------");
	isElf32 ? elf32_hdr.Show() : elf64_hdr.Show();
	LOG_NOTICE(LOADER, "----------------------------------------------------");
	LOG_NOTICE(LOADER, "ELF program headers");
	LOG_NOTICE(LOADER, "----------------------------------------------------");
	for(unsigned int i = 0; i < ((isElf32) ? phdr32_arr.size() : phdr64_arr.size()); i++)
		isElf32 ? phdr32_arr[i].Show() : phdr64_arr[i].Show();
	LOG_NOTICE(LOADER, "----------------------------------------------------");
	LOG_NOTICE(LOADER, "Section info");
	LOG_NOTICE(LOADER, "----------------------------------------------------");
	for(unsigned int i = 0; i < secinfo_arr.size(); i++)
		secinfo_arr[i].Show();
	LOG_NOTICE(LOADER, "----------------------------------------------------");
	LOG_NOTICE(LOADER, "SCE version info");
	LOG_NOTICE(LOADER, "----------------------------------------------------");
	scev_info.Show();
	LOG_NOTICE(LOADER, "----------------------------------------------------");
	LOG_NOTICE(LOADER, "Control info");
	LOG_NOTICE(LOADER, "----------------------------------------------------");
	for(unsigned int i = 0; i < ctrlinfo_arr.size(); i++)
		ctrlinfo_arr[i].Show();
	LOG_NOTICE(LOADER, "----------------------------------------------------");
	LOG_NOTICE(LOADER, "ELF section headers");
	LOG_NOTICE(LOADER, "----------------------------------------------------");
	for(unsigned int i = 0; i < ((isElf32) ? shdr32_arr.size() : shdr64_arr.size()); i++)
		isElf32 ? shdr32_arr[i].Show() : shdr64_arr[i].Show();
	LOG_NOTICE(LOADER, "----------------------------------------------------");
}
Ejemplo n.º 24
0
bool SELFDecrypter::DecryptNPDRM(u8 *metadata, u32 metadata_size)
{
	aes_context aes;
	ControlInfo *ctrl = NULL;
	u8 npdrm_key[0x10];
	u8 npdrm_iv[0x10];

	// Parse the control info structures to find the NPDRM control info.
	for(unsigned int i = 0; i < ctrlinfo_arr.size(); i++)
	{
		if (ctrlinfo_arr[i].type == 3)
		{
			ctrl = &ctrlinfo_arr[i];
			break;
		}
	}

	// Check if we have a valid NPDRM control info structure.
	// If not, the data has no NPDRM layer.
	if (!ctrl)
	{
		LOG_NOTICE(LOADER, "SELF: No NPDRM control info found!");
		return true;
	}

	if (ctrl->npdrm.license == 1)  // Network license.
	{
		LOG_ERROR(LOADER, "SELF: Can't decrypt network NPDRM!");
		return false;
	}
	else if (ctrl->npdrm.license == 2)  // Local license.
	{
		// Try to find a RAP file to get the key.
		if (!GetKeyFromRap(ctrl->npdrm.content_id, npdrm_key))
		{
			LOG_ERROR(LOADER, "SELF: Can't find RAP file for NPDRM decryption!");
			return false;
		}
	}
	else if (ctrl->npdrm.license == 3)  // Free license.
	{
		// Use klicensee if available.
		if (key_v.GetKlicenseeKey() != nullptr)
			memcpy(npdrm_key, key_v.GetKlicenseeKey(), 0x10);
		else 
			memcpy(npdrm_key, NP_KLIC_FREE, 0x10);
	}
	else
	{
		LOG_ERROR(LOADER, "SELF: Invalid NPDRM license type!");
		return false;
	}

	// Decrypt our key with NP_KLIC_KEY.
	aes_setkey_dec(&aes, NP_KLIC_KEY, 128);
	aes_crypt_ecb(&aes, AES_DECRYPT, npdrm_key, npdrm_key);

	// IV is empty.
	memset(npdrm_iv, 0, 0x10);

	// Use our final key to decrypt the NPDRM layer.
	aes_setkey_dec(&aes, npdrm_key, 128);
	aes_crypt_cbc(&aes, AES_DECRYPT, metadata_size, npdrm_iv, metadata, metadata);

	return true;
}
Ejemplo n.º 25
0
void CPUThread::Task()
{
	if (Ini.HLELogging.GetValue()) LOG_NOTICE(GENERAL, "%s enter", CPUThread::GetFName().c_str());

	const std::vector<u64>& bp = Emu.GetBreakPoints();

	for (uint i = 0; i<bp.size(); ++i)
	{
		if (bp[i] == m_offset + PC)
		{
			Emu.Pause();
			break;
		}
	}

	std::vector<u32> trace;

#ifdef _WIN32
	auto old_se_translator = _set_se_translator(_se_translator);
#else
	// TODO: linux version
#endif

	try
	{
		while (true)
		{
			int status = ThreadStatus();

			if (status == CPUThread_Stopped || status == CPUThread_Break)
			{
				break;
			}

			if (status == CPUThread_Sleeping)
			{
				std::this_thread::sleep_for(std::chrono::milliseconds(1)); // hack
				continue;
			}

			Step();
			//if (m_trace_enabled) trace.push_back(PC);
			NextPc(m_dec->DecodeMemory(PC + m_offset));

			if (status == CPUThread_Step)
			{
				m_is_step = false;
				break;
			}

			for (uint i = 0; i < bp.size(); ++i)
			{
				if (bp[i] == PC)
				{
					Emu.Pause();
					break;
				}
			}
		}
	}
	catch (const std::string& e)
	{
		LOG_ERROR(GENERAL, "Exception: %s", e.c_str());
		Emu.Pause();
	}
	catch (const char* e)
	{
		LOG_ERROR(GENERAL, "Exception: %s", e);
		Emu.Pause();
	}

#ifdef _WIN32
	_set_se_translator(old_se_translator);
#else
	// TODO: linux version
#endif

	if (trace.size())
	{
		LOG_NOTICE(GENERAL, "Trace begin (%d elements)", trace.size());

		u32 start = trace[0], prev = trace[0] - 4;

		for (auto& v : trace) //LOG_NOTICE(GENERAL, "PC = 0x%x", v);
		{
			if (v - prev != 4)
			{
				LOG_NOTICE(GENERAL, "Trace: 0x%08x .. 0x%08x", start, prev);
				start = v;
			}
			prev = v;
		}

		LOG_NOTICE(GENERAL, "Trace end: 0x%08x .. 0x%08x", start, prev);
	}


	if (Ini.HLELogging.GetValue()) LOG_NOTICE(GENERAL, "%s leave", CPUThread::GetFName().c_str());
}
Ejemplo n.º 26
0
void GLGSRender::on_init_thread()
{
	GSRender::on_init_thread();

	gl::init();

	//Enable adaptive vsync if vsync is requested
	gl::set_swapinterval(g_cfg.video.vsync ? -1 : 0);

	if (g_cfg.video.debug_output)
		gl::enable_debugging();

	LOG_NOTICE(RSX, "%s", (const char*)glGetString(GL_VERSION));
	LOG_NOTICE(RSX, "%s", (const char*)glGetString(GL_SHADING_LANGUAGE_VERSION));
	LOG_NOTICE(RSX, "%s", (const char*)glGetString(GL_VENDOR));

	auto& gl_caps = gl::get_driver_caps();

	if (!gl_caps.ARB_texture_buffer_supported)
	{
		fmt::throw_exception("Failed to initialize OpenGL renderer. ARB_texture_buffer_object is required but not supported by your GPU");
	}

	if (!gl_caps.ARB_dsa_supported && !gl_caps.EXT_dsa_supported)
	{
		fmt::throw_exception("Failed to initialize OpenGL renderer. ARB_direct_state_access or EXT_direct_state_access is required but not supported by your GPU");
	}

	if (!gl_caps.ARB_depth_buffer_float_supported && g_cfg.video.force_high_precision_z_buffer)
	{
		LOG_WARNING(RSX, "High precision Z buffer requested but your GPU does not support GL_ARB_depth_buffer_float. Option ignored.");
	}

	if (!gl_caps.ARB_texture_barrier_supported && !gl_caps.NV_texture_barrier_supported && !g_cfg.video.strict_rendering_mode)
	{
		LOG_WARNING(RSX, "Texture barriers are not supported by your GPU. Feedback loops will have undefined results.");
	}

	//Use industry standard resource alignment values as defaults
	m_uniform_buffer_offset_align = 256;
	m_min_texbuffer_alignment = 256;

	glEnable(GL_VERTEX_PROGRAM_POINT_SIZE);
	glGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, &m_uniform_buffer_offset_align);
	glGetIntegerv(GL_TEXTURE_BUFFER_OFFSET_ALIGNMENT, &m_min_texbuffer_alignment);
	m_vao.create();

	//Set min alignment to 16-bytes for SSE optimizations with aligned addresses to work
	m_min_texbuffer_alignment = std::max(m_min_texbuffer_alignment, 16);
	m_uniform_buffer_offset_align = std::max(m_uniform_buffer_offset_align, 16);

	const u32 texture_index_offset = rsx::limits::fragment_textures_count + rsx::limits::vertex_textures_count;

	//Array stream buffer
	{
		auto &tex = m_gl_persistent_stream_buffer;
		tex.create();
		tex.set_target(gl::texture::target::textureBuffer);
		glActiveTexture(GL_TEXTURE0 + texture_index_offset);
		tex.bind();
	}

	//Register stream buffer
	{
		auto &tex = m_gl_volatile_stream_buffer;
		tex.create();
		tex.set_target(gl::texture::target::textureBuffer);
		glActiveTexture(GL_TEXTURE0 + texture_index_offset + 1);
		tex.bind();
	}

	if (!gl_caps.ARB_buffer_storage_supported)
	{
		LOG_WARNING(RSX, "Forcing use of legacy OpenGL buffers because ARB_buffer_storage is not supported");
		// TODO: do not modify config options
		g_cfg.video.gl_legacy_buffers.from_string("true");
	}

	if (g_cfg.video.gl_legacy_buffers)
	{
		LOG_WARNING(RSX, "Using legacy openGL buffers.");
		manually_flush_ring_buffers = true;

		m_attrib_ring_buffer.reset(new gl::legacy_ring_buffer());
		m_transform_constants_buffer.reset(new gl::legacy_ring_buffer());
		m_fragment_constants_buffer.reset(new gl::legacy_ring_buffer());
		m_vertex_state_buffer.reset(new gl::legacy_ring_buffer());
		m_index_ring_buffer.reset(new gl::legacy_ring_buffer());
	}
	else
	{
		m_attrib_ring_buffer.reset(new gl::ring_buffer());
		m_transform_constants_buffer.reset(new gl::ring_buffer());
		m_fragment_constants_buffer.reset(new gl::ring_buffer());
		m_vertex_state_buffer.reset(new gl::ring_buffer());
		m_index_ring_buffer.reset(new gl::ring_buffer());
	}

	m_attrib_ring_buffer->create(gl::buffer::target::texture, 256 * 0x100000);
	m_index_ring_buffer->create(gl::buffer::target::element_array, 64 * 0x100000);
	m_transform_constants_buffer->create(gl::buffer::target::uniform, 16 * 0x100000);
	m_fragment_constants_buffer->create(gl::buffer::target::uniform, 16 * 0x100000);
	m_vertex_state_buffer->create(gl::buffer::target::uniform, 16 * 0x100000);

	m_vao.element_array_buffer = *m_index_ring_buffer;

	if (g_cfg.video.overlay)
	{
		if (gl_caps.ARB_shader_draw_parameters_supported)
		{
			m_text_printer.init();
			m_text_printer.set_enabled(true);
		}
	}

	for (int i = 0; i < rsx::limits::fragment_textures_count; ++i)
	{
		m_gl_sampler_states[i].create();
		m_gl_sampler_states[i].bind(i);
	}

	//Occlusion query
	for (u32 i = 0; i < occlusion_query_count; ++i)
	{
		auto &query = occlusion_query_data[i];
		glGenQueries(1, &query.handle);
		
		query.pending = false;
		query.active = false;
		query.result = 0;
	}

	//Clip planes are shader controlled; enable all planes driver-side
	glEnable(GL_CLIP_DISTANCE0 + 0);
	glEnable(GL_CLIP_DISTANCE0 + 1);
	glEnable(GL_CLIP_DISTANCE0 + 2);
	glEnable(GL_CLIP_DISTANCE0 + 3);
	glEnable(GL_CLIP_DISTANCE0 + 4);
	glEnable(GL_CLIP_DISTANCE0 + 5);

	m_gl_texture_cache.initialize(this);

	m_shaders_cache->load();
}
Ejemplo n.º 27
0
void Selector::threadMain()
{
	TRACE_BEGIN( LOG_LVL_INFO );
	bool gotEvent = false;
	struct pollfd	fds[ kMaxPollFds ];
	int				numFds = 0;
	
	fillPollFds( fds, numFds );
	
	// Event will be sent by EventThread on exit
	while( mRunning )
	{
		LOG( "%p on %d files", this, numFds );
		for ( int i = 1; i < numFds; i++ )
		{
			LOG( "%p fd %d", this, fds[ i ].fd );
		}
		
		// set errno to zero
		// this is being set to better monitor the behavior of poll on
		// the 7401 until poll gets fixed
		errno = 0;
		int res = 0;
		
		// test here to ensure that errno cannot be modified before it is tested.
		if ( ( res = poll( fds, numFds, -1 ) ) < 0 )
		{
			// for whatever reason, there are times when poll returns -1,
			// but doesn't set errno
			if (errno == 0)
				LOG_NOTICE( "Poll returned %d, but didn't set errno", res);
			else if (errno == EINTR)
				LOG_NOISE( "Poll was interrupted" );
			else
				LOG_ERR_PERROR( "Poll returned %d", res );
		}
		
		LOG( "%p woke up %d", this, res );
		
		if ( res > 0 )
		{
			LOG( "got %d from poll", res );
			
			for ( int i = 0; i < numFds; i++ )
			{
				if ( fds[ i ].fd == mPipe[ PIPE_READER ] )
				{
					LOG( "got %x on pipe %d", fds[ 0 ].revents, fds[ i ].fd );
					if ( fds[ i ].revents & POLLIN )
					{
						char buf[10];
						read( mPipe[ PIPE_READER ], &buf, 4 );
						
						// We need to handle events after we handle file
						// descriptor polls because one of the events
						// that we handle modifies the current list of
						// file descriptors for poll and we need to handle
						// any that occured before updating them.
						gotEvent = true;
					}			
					else if ( fds[ i ].revents & ( POLLHUP | POLLNVAL ) )
					{
						LOG_ERR_FATAL( "POLLHUP recieved on pipe" );
					}
				}
				else
				{
					LOG_NOISE( "got %x on fd %d", fds[ i ].revents, fds[ i ].fd );
					if ( fds[ i ].revents != 0 )
					{
						// if callListeners removes a listener we need to update 
						//  Fds.  However only set if callListeners returns true
						//  This should not be cleared since one of the listeners
						//  could have called removeListener and that call might 
						//  have set mUpdateFds
						if ( callListeners( fds[ i ].fd, fds[ i ].revents ) )
							mUpdateFds = true;
					}
				}
			}
		}

		// Now that file descriptors have been handled we can deal with
		// events if needed, including updating the poll file descriptor
		// list if it's been changed.
		if ( gotEvent )
		{
			Event *ev = mQueue.PollEvent();

			if ( ev == NULL )
			{
				LOG_WARN( "got NULL event" );
			}
			else if ( ev->getEventId() == Event::kSelectorUpdateEventId )
			{
				LOG( "got kSelectorUpdateEventId" );
				mUpdateFds = true;
				ev->Release();
			}
			else
			{
				LOG( "got event %d", ev->getEventId() );
				bool done = EventDispatcher::handleEvent( ev );
				if ( done )
					mRunning = false;
			}
			
			gotEvent = false;
		}
		
		if ( mUpdateFds )
		{
			fillPollFds( fds, numFds );
			mUpdateFds = false;
		}
		
		mCondition.Broadcast();
	}
	
	LOG_NOTICE( "Thread exiting" );
}
Ejemplo n.º 28
0
void SPUThread::EnqMfcCmd(MFCReg& MFCArgs)
{
	u32 cmd = MFCArgs.CMDStatus.GetValue();
	u16 op = cmd & MFC_MASK_CMD;

	u32 lsa = MFCArgs.LSA.GetValue();
	u64 ea = (u64)MFCArgs.EAL.GetValue() | ((u64)MFCArgs.EAH.GetValue() << 32);
	u32 size_tag = MFCArgs.Size_Tag.GetValue();
	u16 tag = (u16)size_tag;
	u16 size = size_tag >> 16;

	switch (op & ~(MFC_BARRIER_MASK | MFC_FENCE_MASK))
	{
	case MFC_PUT_CMD:
	case MFC_PUTR_CMD: // ???
	case MFC_GET_CMD:
	{
		if (Ini.HLELogging.GetValue()) LOG_NOTICE(Log::SPU, "DMA %s%s%s%s: lsa = 0x%x, ea = 0x%llx, tag = 0x%x, size = 0x%x, cmd = 0x%x",
			(op & MFC_PUT_CMD ? "PUT" : "GET"),
			(op & MFC_RESULT_MASK ? "R" : ""),
			(op & MFC_BARRIER_MASK ? "B" : ""),
			(op & MFC_FENCE_MASK ? "F" : ""),
			lsa, ea, tag, size, cmd);

		ProcessCmd(cmd, tag, lsa, ea, size);
		MFCArgs.CMDStatus.SetValue(MFC_PPU_DMA_CMD_ENQUEUE_SUCCESSFUL);
		break;
	}

	case MFC_PUTL_CMD:
	case MFC_PUTRL_CMD: // ???
	case MFC_GETL_CMD:
	{
		if (Ini.HLELogging.GetValue()) LOG_NOTICE(Log::SPU, "DMA %s%s%s%s: lsa = 0x%x, list = 0x%llx, tag = 0x%x, size = 0x%x, cmd = 0x%x",
			(op & MFC_PUT_CMD ? "PUT" : "GET"),
			(op & MFC_RESULT_MASK ? "RL" : "L"),
			(op & MFC_BARRIER_MASK ? "B" : ""),
			(op & MFC_FENCE_MASK ? "F" : ""),
			lsa, ea, tag, size, cmd);

		ListCmd(lsa, ea, tag, size, cmd, MFCArgs);
		break;
	}

	case MFC_GETLLAR_CMD:
	case MFC_PUTLLC_CMD:
	case MFC_PUTLLUC_CMD:
	case MFC_PUTQLLUC_CMD:
	{
		if (Ini.HLELogging.GetValue() || size != 128) LOG_NOTICE(Log::SPU, "DMA %s: lsa=0x%x, ea = 0x%llx, (tag) = 0x%x, (size) = 0x%x, cmd = 0x%x",
			(op == MFC_GETLLAR_CMD ? "GETLLAR" :
			op == MFC_PUTLLC_CMD ? "PUTLLC" :
			op == MFC_PUTLLUC_CMD ? "PUTLLUC" : "PUTQLLUC"),
			lsa, ea, tag, size, cmd);

		if (op == MFC_GETLLAR_CMD) // get reservation
		{
			if (R_ADDR)
			{
				m_events |= SPU_EVENT_LR;
			}

			R_ADDR = ea;
			for (u32 i = 0; i < 16; i++)
			{
				R_DATA[i] = vm::get_ptr<u64>(R_ADDR)[i];
				vm::get_ptr<u64>(dmac.ls_offset + lsa)[i] = R_DATA[i];
			}
			MFCArgs.AtomicStat.PushUncond(MFC_GETLLAR_SUCCESS);
		}
		else if (op == MFC_PUTLLC_CMD) // store conditional
		{
			MFCArgs.AtomicStat.PushUncond(MFC_PUTLLC_SUCCESS);

			if (R_ADDR == ea)
			{
				u32 changed = 0, mask = 0;
				u64 buf[16];
				for (u32 i = 0; i < 16; i++)
				{
					buf[i] = vm::get_ptr<u64>(dmac.ls_offset + lsa)[i];
					if (buf[i] != R_DATA[i])
					{
						changed++;
						mask |= (0x3 << (i * 2));
						if (vm::get_ptr<u64>(R_ADDR)[i] != R_DATA[i])
						{
							m_events |= SPU_EVENT_LR;
							MFCArgs.AtomicStat.PushUncond(MFC_PUTLLC_FAILURE);
							R_ADDR = 0;
							return;
						}
					}
				}

				for (u32 i = 0; i < 16; i++)
				{
					if (buf[i] != R_DATA[i])
					{
						if (InterlockedCompareExchange(&vm::get_ptr<volatile u64>(ea)[i], buf[i], R_DATA[i]) != R_DATA[i])
						{
							m_events |= SPU_EVENT_LR;
							MFCArgs.AtomicStat.PushUncond(MFC_PUTLLC_FAILURE);

							if (changed > 1)
							{
								LOG_ERROR(Log::SPU, "MFC_PUTLLC_CMD: Memory corrupted (~x%d (mask=0x%x)) (opcode=0x%x, cmd=0x%x, lsa = 0x%x, ea = 0x%llx, tag = 0x%x, size = 0x%x)",
									changed, mask, op, cmd, lsa, ea, tag, size);
								Emu.Pause();
							}
							
							break;
						}
					}
				}

				if (changed > 1)
				{
					LOG_WARNING(Log::SPU, "MFC_PUTLLC_CMD: Reservation impossibru (~x%d (mask=0x%x)) (opcode=0x%x, cmd=0x%x, lsa = 0x%x, ea = 0x%llx, tag = 0x%x, size = 0x%x)",
						changed, mask, op, cmd, lsa, ea, tag, size);

					SPUDisAsm dis_asm(CPUDisAsm_InterpreterMode);
					for (s32 i = (s32)PC; i < (s32)PC + 4 * 7; i += 4)
					{
						dis_asm.dump_pc = i;
						dis_asm.offset = vm::get_ptr<u8>(dmac.ls_offset);
						const u32 opcode = vm::read32(i + dmac.ls_offset);
						(*SPU_instr::rrr_list)(&dis_asm, opcode);
						if (i >= 0 && i < 0x40000)
						{
							LOG_NOTICE(Log::SPU, "*** %s", dis_asm.last_opcode.c_str());
						}
					}
				}
			}
			else
			{
				MFCArgs.AtomicStat.PushUncond(MFC_PUTLLC_FAILURE);
			}
			R_ADDR = 0;
		}
		else // store unconditional
		{
			if (R_ADDR)
			{
				m_events |= SPU_EVENT_LR;
			}

			ProcessCmd(MFC_PUT_CMD, tag, lsa, ea, 128);
			if (op == MFC_PUTLLUC_CMD)
			{
				MFCArgs.AtomicStat.PushUncond(MFC_PUTLLUC_SUCCESS);
			}
			R_ADDR = 0;
		}
		break;
	}

	default:
		LOG_ERROR(Log::SPU, "Unknown MFC cmd. (opcode=0x%x, cmd=0x%x, lsa = 0x%x, ea = 0x%llx, tag = 0x%x, size = 0x%x)",
			op, cmd, lsa, ea, tag, size);
		break;
	}
}
Ejemplo n.º 29
0
void Emulator::Stop()
{
	if (m_state.exchange(system_state::stopped) == system_state::stopped)
	{
		return;
	}

	LOG_NOTICE(GENERAL, "Stopping emulator...");

	GetCallbacks().on_stop();

#ifdef WITH_GDB_DEBUGGER
	//fxm for some reason doesn't call on_stop
	fxm::get<GDBDebugServer>()->on_stop();
	fxm::remove<GDBDebugServer>();
#endif

	auto e_stop = std::make_exception_ptr(cpu_flag::dbg_global_stop);

	auto on_select = [&](u32, cpu_thread& cpu)
	{
		cpu.state += cpu_flag::dbg_global_stop;
		cpu.get()->set_exception(e_stop);
	};

	idm::select<ppu_thread>(on_select);
	idm::select<ARMv7Thread>(on_select);
	idm::select<RawSPUThread>(on_select);
	idm::select<SPUThread>(on_select);

	if (auto mfc = fxm::check<mfc_thread>())
	{
		on_select(0, *mfc);
	}

	LOG_NOTICE(GENERAL, "All threads signaled...");

	while (g_thread_count)
	{
		m_cb.process_events();

		std::this_thread::sleep_for(10ms);
	}

	LOG_NOTICE(GENERAL, "All threads stopped...");

	lv2_obj::cleanup();
	idm::clear();
	fxm::clear();

	LOG_NOTICE(GENERAL, "Objects cleared...");

	RSXIOMem.Clear();
	vm::close();

	if (g_cfg.misc.autoexit)
	{
		GetCallbacks().exit();
	}
	else
	{
		Init();
	}

#ifdef LLVM_AVAILABLE
	extern void jit_finalize();
	jit_finalize();
#endif
}
Ejemplo n.º 30
0
	void thread::on_task()
	{
		on_init_thread();

		reset();

		last_flip_time = get_system_time() - 1000000;

		scope_thread_t vblank(PURE_EXPR("VBlank Thread"s), [this]()
		{
			const u64 start_time = get_system_time();

			vblank_count = 0;

			// TODO: exit condition
			while (!Emu.IsStopped())
			{
				if (get_system_time() - start_time > vblank_count * 1000000 / 60)
				{
					vblank_count++;

					if (vblank_handler)
					{
						Emu.GetCallbackManager().Async([func = vblank_handler](PPUThread& ppu)
						{
							func(ppu, 1);
						});
					}

					continue;
				}

				std::this_thread::sleep_for(1ms); // hack
			}
		});

		// TODO: exit condition
		while (true)
		{
			CHECK_EMU_STATUS;

			be_t<u32> get = ctrl->get;
			be_t<u32> put = ctrl->put;

			if (put == get || !Emu.IsRunning())
			{
				std::this_thread::sleep_for(std::chrono::milliseconds(1)); // hack
				continue;
			}

			const u32 cmd = ReadIO32(get);
			const u32 count = (cmd >> 18) & 0x7ff;

			if (cmd & CELL_GCM_METHOD_FLAG_JUMP)
			{
				u32 offs = cmd & 0x1fffffff;
				//LOG_WARNING(RSX, "rsx jump(0x%x) #addr=0x%x, cmd=0x%x, get=0x%x, put=0x%x", offs, m_ioAddress + get, cmd, get, put);
				ctrl->get = offs;
				continue;
			}
			if (cmd & CELL_GCM_METHOD_FLAG_CALL)
			{
				m_call_stack.push(get + 4);
				u32 offs = cmd & ~3;
				//LOG_WARNING(RSX, "rsx call(0x%x) #0x%x - 0x%x", offs, cmd, get);
				ctrl->get = offs;
				continue;
			}
			if (cmd == CELL_GCM_METHOD_FLAG_RETURN)
			{
				u32 get = m_call_stack.top();
				m_call_stack.pop();
				//LOG_WARNING(RSX, "rsx return(0x%x)", get);
				ctrl->get = get;
				continue;
			}

			if (cmd == 0) //nop
			{
				ctrl->get = get + 4;
				continue;
			}

			auto args = vm::ptr<u32>::make((u32)RSXIOMem.RealAddr(get + 4));

			u32 first_cmd = (cmd & 0xffff) >> 2;

			if (cmd & 0x3)
			{
				LOG_WARNING(RSX, "unaligned command: %s (0x%x from 0x%x)", get_method_name(first_cmd).c_str(), first_cmd, cmd & 0xffff);
			}

			for (u32 i = 0; i < count; i++)
			{
				u32 reg = cmd & CELL_GCM_METHOD_FLAG_NON_INCREMENT ? first_cmd : first_cmd + i;
				u32 value = args[i];

				if (rpcs3::config.misc.log.rsx_logging.value())
				{
					LOG_NOTICE(RSX, "%s(0x%x) = 0x%x", get_method_name(reg).c_str(), reg, value);
				}

				method_registers[reg] = value;
				if (capture_current_frame)
					frame_debug.command_queue.push_back(std::make_pair(reg, value));

				if (auto method = methods[reg])
					method(this, value);
			}

			ctrl->get = get + (count + 1) * 4;
		}
	}