Example #1
0
static bool LoadRom(const std::string& fname, int size_in_words, u16 *rom)
{
	File::IOFile pFile(fname, "rb");
	const size_t size_in_bytes = size_in_words * sizeof(u16);
	if (pFile)
	{
		pFile.ReadArray(rom, size_in_words);
		pFile.Close();

		// Byteswap the rom.
		for (int i = 0; i < size_in_words; i++)
			rom[i] = Common::swap16(rom[i]);

		// Always keep ROMs write protected.
		WriteProtectMemory(rom, size_in_bytes, false);
		return true;
	}

	PanicAlertT(
		"Failed to load DSP ROM:\t%s\n"
		"\n"
		"This file is required to use DSP LLE.\n"
		"It is not included with Dolphin as it contains copyrighted data.\n"
		"Use DSPSpy to dump the file from your physical console.\n"
		"\n"
		"You may use the DSP HLE engine which does not require ROM dumps.\n"
		"(Choose it from the \"Audio\" tab of the configuration dialog.)", fname.c_str());
	return false;
}
Example #2
0
TEST(PageFault, PageFault)
{
  EMM::InstallExceptionHandler();
  void* data = AllocateMemoryPages(PAGE_GRAN);
  EXPECT_NE(data, nullptr);
  WriteProtectMemory(data, PAGE_GRAN, false);

  PageFaultFakeJit pfjit;
  jit = &pfjit;
  pfjit.m_data = data;

  auto start = std::chrono::high_resolution_clock::now();
  *(volatile int*)data = 5;
  auto end = std::chrono::high_resolution_clock::now();

#define AS_NS(diff)                                                                                \
  ((unsigned long long)std::chrono::duration_cast<std::chrono::nanoseconds>(diff).count())

  EMM::UninstallExceptionHandler();
  jit = nullptr;

  printf("page fault timing:\n");
  printf("start->HandleFault     %llu ns\n", AS_NS(pfjit.m_pre_unprotect_time - start));
  printf("UnWriteProtectMemory   %llu ns\n",
         AS_NS(pfjit.m_post_unprotect_time - pfjit.m_pre_unprotect_time));
  printf("HandleFault->end       %llu ns\n", AS_NS(end - pfjit.m_post_unprotect_time));
  printf("total                  %llu ns\n", AS_NS(end - start));
}
Example #3
0
void DSPLLE::DoState(PointerWrap &p)
{
	bool isHLE = false;
	p.Do(isHLE);
	if (isHLE != false && p.GetMode() == PointerWrap::MODE_READ)
	{
		Core::DisplayMessage("State is incompatible with current DSP engine. Aborting load state.", 3000);
		p.SetMode(PointerWrap::MODE_VERIFY);
		return;
	}
	p.Do(g_dsp.r);
	p.Do(g_dsp.pc);
#if PROFILE
	p.Do(g_dsp.err_pc);
#endif
	p.Do(g_dsp.cr);
	p.Do(g_dsp.reg_stack_ptr);
	p.Do(g_dsp.exceptions);
	p.Do(g_dsp.external_interrupt_waiting);

	for (int i = 0; i < 4; i++)
	{
		p.Do(g_dsp.reg_stack[i]);
	}

	p.Do(g_dsp.step_counter);
	p.Do(g_dsp.ifx_regs);
	p.Do(g_dsp.mbox[0]);
	p.Do(g_dsp.mbox[1]);
	UnWriteProtectMemory(g_dsp.iram, DSP_IRAM_BYTE_SIZE, false);
	p.DoArray(g_dsp.iram, DSP_IRAM_SIZE);
	WriteProtectMemory(g_dsp.iram, DSP_IRAM_BYTE_SIZE, false);
	if (p.GetMode() == PointerWrap::MODE_READ)
		DSPHost::CodeLoaded((const u8*)g_dsp.iram, DSP_IRAM_BYTE_SIZE);
	p.DoArray(g_dsp.dram, DSP_DRAM_SIZE);
	p.Do(cyclesLeft);
	p.Do(init_hax);
	p.Do(m_cycle_count);

	bool prevInitMixer = m_InitMixer;
	p.Do(m_InitMixer);
	if (prevInitMixer != m_InitMixer && p.GetMode() == PointerWrap::MODE_READ)
	{
		if (m_InitMixer)
		{
			InitMixer();
			AudioCommon::PauseAndLock(true);
		}
		else
		{
			AudioCommon::PauseAndLock(false);
			soundStream->Stop();
			delete soundStream;
			soundStream = nullptr;
		}
	}
}
Example #4
0
bool DSPCore_Init(const DSPInitOptions& opts)
{
  g_dsp.step_counter = 0;
  g_cycles_left = 0;
  g_init_hax = false;

  g_dsp.irom = (u16*)AllocateMemoryPages(DSP_IROM_BYTE_SIZE);
  g_dsp.iram = (u16*)AllocateMemoryPages(DSP_IRAM_BYTE_SIZE);
  g_dsp.dram = (u16*)AllocateMemoryPages(DSP_DRAM_BYTE_SIZE);
  g_dsp.coef = (u16*)AllocateMemoryPages(DSP_COEF_BYTE_SIZE);

  memcpy(g_dsp.irom, opts.irom_contents.data(), DSP_IROM_BYTE_SIZE);
  memcpy(g_dsp.coef, opts.coef_contents.data(), DSP_COEF_BYTE_SIZE);

  // Try to load real ROM contents.
  if (!VerifyRoms())
  {
    DSPCore_FreeMemoryPages();
    return false;
  }

  memset(&g_dsp.r, 0, sizeof(g_dsp.r));

  std::fill(std::begin(g_dsp.reg_stack_ptr), std::end(g_dsp.reg_stack_ptr), 0);

  for (size_t i = 0; i < ArraySize(g_dsp.reg_stack); i++)
    std::fill(std::begin(g_dsp.reg_stack[i]), std::end(g_dsp.reg_stack[i]), 0);

  // Fill IRAM with HALT opcodes.
  std::fill(g_dsp.iram, g_dsp.iram + DSP_IRAM_SIZE, 0x0021);

  // Just zero out DRAM.
  std::fill(g_dsp.dram, g_dsp.dram + DSP_DRAM_SIZE, 0);

  // Copied from a real console after the custom UCode has been loaded.
  // These are the indexing wrapping registers.
  std::fill(std::begin(g_dsp.r.wr), std::end(g_dsp.r.wr), 0xffff);

  g_dsp.r.sr |= SR_INT_ENABLE;
  g_dsp.r.sr |= SR_EXT_INT_ENABLE;

  g_dsp.cr = 0x804;
  gdsp_ifx_init();
  // Mostly keep IRAM write protected. We unprotect only when DMA-ing
  // in new ucodes.
  WriteProtectMemory(g_dsp.iram, DSP_IRAM_BYTE_SIZE, false);

  // Initialize JIT, if necessary
  if (opts.core_type == DSPInitOptions::CORE_JIT)
    g_dsp_jit = std::make_unique<DSPEmitter>();

  g_dsp_cap.reset(opts.capture_logger);

  core_state = DSPCORE_RUNNING;
  return true;
}
Example #5
0
PVOID ProbeInvokeCreateProcessAddress()
{
    PVOID               Shell32, Shell32CreateProcessW, CreateProcessW;
    PLDR_MODULE         Shell32Module, MainModule;
    SHELLEXECUTEINFOW   ExecuteInfo;
    PIMAGE_NT_HEADERS   NtHeaders;

    Shell32 = Ldr::LoadDll(L"Shell32.dll");

    Shell32CreateProcessW = PtrAdd(Shell32, IATLookupRoutineRVAByHashNoFix(Shell32, KERNEL32_CreateProcessW));

    MainModule = FindLdrModuleByHandle(nullptr);

    RtlDuplicateUnicodeString(RTL_DUPSTR_ADD_NULL, &MainModule->FullDllName, &ProbeApplicationName);
    RtlInitUnicodeString(&ProbeCommandLine, L"ML_PROBE_APPLICATION_COMMAMD_LINE");

    ZeroMemory(&ExecuteInfo, sizeof(ExecuteInfo));

    ExecuteInfo.cbSize          = sizeof(ExecuteInfo);
    ExecuteInfo.fMask           = SEE_MASK_NOASYNC | SEE_MASK_FLAG_NO_UI;
    ExecuteInfo.lpVerb          = L"open";
    ExecuteInfo.lpFile          = ProbeApplicationName.Buffer;
    ExecuteInfo.lpParameters    = ProbeCommandLine.Buffer;
    ExecuteInfo.lpDirectory     = ProbeApplicationName.Buffer;
    ExecuteInfo.nShow           = SW_SHOW;

    *(PVOID *)&Shell32CreateProcessWIAT = Shell32CreateProcessW;
    *(PVOID *)&Shell32CreateProcessWPtr = *(PVOID *)Shell32CreateProcessWIAT;

    CreateProcessW = ProbeInvokeCreateProcessW;
    WriteProtectMemory(CurrentProcess, Shell32CreateProcessW, &CreateProcessW, sizeof(CreateProcessW));
    ShellExecuteExW(&ExecuteInfo);
    WriteProtectMemory(CurrentProcess, Shell32CreateProcessW, &Shell32CreateProcessWPtr, sizeof(Shell32CreateProcessWPtr));

    RtlFreeUnicodeString(&ProbeApplicationName);

    NtHeaders = RtlImageNtHeader(Shell32);

    if (InvokeReturnAddress < Shell32 || InvokeReturnAddress > PtrAdd(Shell32, NtHeaders->OptionalHeader.SizeOfImage))
        return nullptr;

    return InvokeReturnAddress;
}
Example #6
0
static const u8* gdsp_idma_in(u16 dsp_addr, u32 addr, u32 size)
{
	UnWriteProtectMemory(g_dsp.iram, DSP_IRAM_BYTE_SIZE, false);

	u8* dst = ((u8*)g_dsp.iram);
	for (u32 i = 0; i < size; i += 2)
	{
		*(u16*)&dst[dsp_addr + i] = Common::swap16(*(const u16*)&g_dsp.cpu_ram[(addr + i) & 0x0fffffff]);
	}
	WriteProtectMemory(g_dsp.iram, DSP_IRAM_BYTE_SIZE, false);

	DSPHost::CodeLoaded((const u8*)g_dsp.iram + dsp_addr, size);

	NOTICE_LOG(DSPLLE, "*** Copy new UCode from 0x%08x to 0x%04x (crc: %8x)", addr, dsp_addr, g_dsp.iram_crc);

	return dst + dsp_addr;
}
Example #7
0
static void gdsp_idma_in(u16 dsp_addr, u32 addr, u32 size)
{
	UnWriteProtectMemory(g_dsp.iram, DSP_IRAM_BYTE_SIZE, false);

	u8* dst = ((u8*)g_dsp.iram);
	for (u32 i = 0; i < size; i += 2)
	{ 
		*(u16*)&dst[dsp_addr + i] = Common::swap16(*(const u16*)&g_dsp.cpu_ram[(addr + i) & 0x0fffffff]);
	}
	WriteProtectMemory(g_dsp.iram, DSP_IRAM_BYTE_SIZE, false);

	g_dsp.iram_crc = DSPHost_CodeLoaded(g_dsp.cpu_ram + (addr & 0x0fffffff), size);
	
	NOTICE_LOG(DSPLLE, "*** Copy new UCode from 0x%08x to 0x%04x (crc: %8x)", addr, dsp_addr, g_dsp.iram_crc);

	if (dspjit)
		dspjit->ClearIRAM();
	
	DSPAnalyzer::Analyze();
}
Example #8
0
void DSPLLE::DoState(PointerWrap &p)
{
	bool is_hle = false;
	p.Do(is_hle);
	if (is_hle && p.GetMode() == PointerWrap::MODE_READ)
	{
		Core::DisplayMessage("State is incompatible with current DSP engine. Aborting load state.", 3000);
		p.SetMode(PointerWrap::MODE_VERIFY);
		return;
	}
	p.Do(g_dsp.r);
	p.Do(g_dsp.pc);
#if PROFILE
	p.Do(g_dsp.err_pc);
#endif
	p.Do(g_dsp.cr);
	p.Do(g_dsp.reg_stack_ptr);
	p.Do(g_dsp.exceptions);
	p.Do(g_dsp.external_interrupt_waiting);

	for (int i = 0; i < 4; i++)
	{
		p.Do(g_dsp.reg_stack[i]);
	}

	p.Do(g_dsp.step_counter);
	p.DoArray(g_dsp.ifx_regs);
	p.Do(g_dsp.mbox[0]);
	p.Do(g_dsp.mbox[1]);
	UnWriteProtectMemory(g_dsp.iram, DSP_IRAM_BYTE_SIZE, false);
	p.DoArray(g_dsp.iram, DSP_IRAM_SIZE);
	WriteProtectMemory(g_dsp.iram, DSP_IRAM_BYTE_SIZE, false);
	if (p.GetMode() == PointerWrap::MODE_READ)
		DSPHost::CodeLoaded((const u8*)g_dsp.iram, DSP_IRAM_BYTE_SIZE);
	p.DoArray(g_dsp.dram, DSP_DRAM_SIZE);
	p.Do(g_cycles_left);
	p.Do(g_init_hax);
	p.Do(m_cycle_count);
}
Example #9
0
bool DSPCore_Init(const std::string& irom_filename, const std::string& coef_filename, bool bUsingJIT)
{
	g_dsp.step_counter = 0;
	cyclesLeft = 0;
	init_hax = false;
	dspjit = nullptr;

	g_dsp.irom = (u16*)AllocateMemoryPages(DSP_IROM_BYTE_SIZE);
	g_dsp.iram = (u16*)AllocateMemoryPages(DSP_IRAM_BYTE_SIZE);
	g_dsp.dram = (u16*)AllocateMemoryPages(DSP_DRAM_BYTE_SIZE);
	g_dsp.coef = (u16*)AllocateMemoryPages(DSP_COEF_BYTE_SIZE);

	// Fill roms with zeros.
	memset(g_dsp.irom, 0, DSP_IROM_BYTE_SIZE);
	memset(g_dsp.coef, 0, DSP_COEF_BYTE_SIZE);

	// Try to load real ROM contents.
	if (!LoadRom(irom_filename, DSP_IROM_SIZE, g_dsp.irom) ||
	    !LoadRom(coef_filename, DSP_COEF_SIZE, g_dsp.coef) ||
	    !VerifyRoms(irom_filename, coef_filename))
	{
		DSPCore_FreeMemoryPages();
		return false;
	}

	memset(&g_dsp.r,0,sizeof(g_dsp.r));

	for (int i = 0; i < 4; i++)
	{
		g_dsp.reg_stack_ptr[i] = 0;
		for (int j = 0; j < DSP_STACK_DEPTH; j++)
		{
			g_dsp.reg_stack[i][j] = 0;
		}
	}

	// Fill IRAM with HALT opcodes.
	for (int i = 0; i < DSP_IRAM_SIZE; i++)
	{
		g_dsp.iram[i] = 0x0021; // HALT opcode
	}

	// Just zero out DRAM.
	for (int i = 0; i < DSP_DRAM_SIZE; i++)
	{
		g_dsp.dram[i] = 0;
	}

	// Copied from a real console after the custom UCode has been loaded.
	// These are the indexing wrapping registers.
	g_dsp.r.wr[0] = 0xffff;
	g_dsp.r.wr[1] = 0xffff;
	g_dsp.r.wr[2] = 0xffff;
	g_dsp.r.wr[3] = 0xffff;

	g_dsp.r.sr |= SR_INT_ENABLE;
	g_dsp.r.sr |= SR_EXT_INT_ENABLE;

	g_dsp.cr = 0x804;
	gdsp_ifx_init();
	// Mostly keep IRAM write protected. We unprotect only when DMA-ing
	// in new ucodes.
	WriteProtectMemory(g_dsp.iram, DSP_IRAM_BYTE_SIZE, false);

	// Initialize JIT, if necessary
	if (bUsingJIT)
		dspjit = new DSPEmitter();

	core_state = DSPCORE_RUNNING;
	return true;
}
Example #10
0
BOOL HookCallCreateProcessFast(PVOID InvokeReturnAddress)
{
    PBYTE               InvokeBuffer;
    PVOID               *JumpAddressBegin, *JumpAddressEnd, HookRoutine;
    PIMAGE_NT_HEADERS   NtHeaders;
    PLDR_MODULE         Shell32;

    InvokeBuffer = (PBYTE)InvokeReturnAddress;
    LOOP_ONCE
    {
        if (*(PUSHORT)&InvokeBuffer[-6] != 0x15FF)
            continue;

#if ML_X86

        if (*(PULONG)&InvokeBuffer[-4] != (ULONG)Shell32CreateProcessWIAT)
            break;

#elif ML_AMD64

        if ((PVOID)PtrAdd(InvokeBuffer, *(PULONG)&InvokeBuffer[-4]) != Shell32CreateProcessWIAT)
            break;

#endif // arch

        Shell32 = FindLdrModuleByName(&WCS2US(L"SHELL32.dll"));
        NtHeaders = RtlImageNtHeader(Shell32->DllBase);
        if (NtHeaders == nullptr)
            break;

        JumpAddressEnd = (PVOID *)PtrAdd(Shell32->DllBase, ROUND_UP(NtHeaders->OptionalHeader.SizeOfHeaders, NtHeaders->OptionalHeader.SectionAlignment));
        JumpAddressBegin = (PVOID *)(IMAGE_FIRST_SECTION(NtHeaders) + NtHeaders->FileHeader.NumberOfSections);

        JumpAddressBegin = (PVOID *)ROUND_UP((ULONG_PTR)JumpAddressBegin, 16);

        while (JumpAddressBegin < JumpAddressEnd)
        {

#if ML_X86

            if (
                JumpAddressBegin[0] == nullptr &&
                JumpAddressBegin[1] == nullptr &&
                JumpAddressBegin[2] == nullptr &&
                JumpAddressBegin[3] == nullptr
               )
            {
                break;
            }

            JumpAddressBegin += 4;

#else
            if (
                JumpAddressBegin[0] == nullptr &&
                JumpAddressBegin[1] == nullptr
               )
            {
                break;
            }

            JumpAddressBegin += 2;

#endif

        }

        if (JumpAddressBegin >= JumpAddressEnd)
            break;

        HookRoutine = SpeedUpCreateProcessW;
        WriteProtectMemory(CurrentProcess, JumpAddressBegin, &HookRoutine, sizeof(HookRoutine));

#if ML_X86

        WriteProtectMemory(CurrentProcess, &InvokeBuffer[-4], &JumpAddressBegin, sizeof(JumpAddressBegin));

#elif ML_AMD64

        LONG64 RelateOffset;

        RelateOffset = (TYPE_OF(RelateOffset))PtrSub(JumpAddressBegin, InvokeBuffer);

        WriteProtectMemory(CurrentProcess, &InvokeBuffer[-4], &RelateOffset, sizeof(LONG));

#endif

        return TRUE;
    }

    return FALSE;
}