Example #1
0
void PPUThread::AddArgv(const std::string& arg)
{
	m_stack_point -= arg.length() + 1;
	m_stack_point = AlignAddr(m_stack_point, 0x10) - 0x10;
	m_argv_addr.push_back(m_stack_point);
	memcpy(vm::get_ptr<char>(m_stack_point), arg.c_str(), arg.size() + 1);
}
Example #2
0
void PPUThread::InitRegs()
{
	const u32 pc = entry ? vm::read32(entry) : 0;
	const u32 rtoc = entry ? vm::read32(entry + 4) : 0;

	//ConLog.Write("entry = 0x%x", entry);
	//ConLog.Write("rtoc = 0x%x", rtoc);

	SetPc(pc);

	/*
	const s32 thread_num = Emu.GetCPU().GetThreadNumById(GetType(), GetId());

	if(thread_num < 0)
	{
		LOG_ERROR(PPU, "GetThreadNumById failed.");
		Emu.Pause();
		return;
	}
	*/

	/*
	const s32 tls_size = Emu.GetTLSFilesz() * thread_num;

	if(tls_size >= Emu.GetTLSMemsz())
	{
		LOG_ERROR(PPU, "Out of TLS memory.");
		Emu.Pause();
		return;
	}
	*/

	GPR[1] = AlignAddr(m_stack_addr + m_stack_size, 0x200) - 0x200;
	GPR[2] = rtoc;
	GPR[13] = Memory.PRXMem.GetStartAddr() + 0x7060;

	LR = Emu.GetPPUThreadExit();
	CTR = PC;
	CR.CR = 0x22000082;
	VSCR.NJ = 1;
	TB = 0;
}
Example #3
0
static void BinWriteMem (BinDesc* D, MemoryArea* M)
/* Write the segments of one memory area to a file */
{
    unsigned I;

    /* Get the start address of this memory area */
    unsigned long Addr = M->Start;

    /* Debugging: Check that the file offset is correct */
    if (ftell (D->F) != (long)M->FileOffs) {
        Internal ("Invalid file offset for memory area %s: %ld/%lu",
                  GetString (M->Name), ftell (D->F), M->FileOffs);
    }

    /* Walk over all segments in this memory area */
    for (I = 0; I < CollCount (&M->SegList); ++I) {

        int DoWrite;

        /* Get the segment */
        SegDesc* S = CollAtUnchecked (&M->SegList, I);

        /* Keep the user happy */
        Print (stdout, 1, "    Writing `%s'\n", GetString (S->Name));

        /* Writes do only occur in the load area and not for BSS segments */
        DoWrite = (S->Flags & SF_BSS) == 0      &&      /* No BSS segment */
                   S->Load == M                 &&      /* LOAD segment */
                   S->Seg->Dumped == 0;                 /* Not already written */

        /* Output debugging stuff */
        PrintBoolVal ("bss", S->Flags & SF_BSS);
        PrintBoolVal ("LoadArea", S->Load == M);
        PrintBoolVal ("Dumped", S->Seg->Dumped);
        PrintBoolVal ("DoWrite", DoWrite);
        PrintNumVal  ("Address", Addr);
        PrintNumVal  ("FileOffs", (unsigned long) ftell (D->F));

        /* Check if the alignment for the segment from the linker config is
         * a multiple for that of the segment.
         */
        if ((S->RunAlignment % S->Seg->Alignment) != 0) {
            /* Segment requires another alignment than configured
             * in the linker.
             */
            Warning ("Segment `%s' is not aligned properly. Resulting "
                     "executable may not be functional.",
                     GetString (S->Name));
        }

        /* If this is the run memory area, we must apply run alignment. If
         * this is not the run memory area but the load memory area (which
         * means that both are different), we must apply load alignment.
         * Beware: DoWrite may be true even if this is the run memory area,
         * because it may be also the load memory area.
         */
        if (S->Run == M) {

            /* Handle ALIGN and OFFSET/START */
            if (S->Flags & SF_ALIGN) {
                /* Align the address */
                unsigned long NewAddr = AlignAddr (Addr, S->RunAlignment);
                if (DoWrite || (M->Flags & MF_FILL) != 0) {
                    WriteMult (D->F, M->FillVal, NewAddr - Addr);
                    PrintNumVal ("SF_ALIGN", NewAddr - Addr);
                }
                Addr = NewAddr;
            } else if (S->Flags & (SF_OFFSET | SF_START)) {
                unsigned long NewAddr = S->Addr;
                if (S->Flags & SF_OFFSET) {
                    /* It's an offset, not a fixed address, make an address */
                    NewAddr += M->Start;
                }
                if (DoWrite || (M->Flags & MF_FILL) != 0) {
                    WriteMult (D->F, M->FillVal, NewAddr-Addr);
                    PrintNumVal ("SF_OFFSET", NewAddr - Addr);
                }
                Addr = NewAddr;
            }

        } else if (S->Load == M) {

            /* Handle ALIGN_LOAD */
            if (S->Flags & SF_ALIGN_LOAD) {
                /* Align the address */
                unsigned long NewAddr = AlignAddr (Addr, S->LoadAlignment);
                if (DoWrite || (M->Flags & MF_FILL) != 0) {
                    WriteMult (D->F, M->FillVal, NewAddr - Addr);
                    PrintNumVal ("SF_ALIGN_LOAD", NewAddr - Addr);
                }
                Addr = NewAddr;
            }

        }

        /* Now write the segment to disk if it is not a BSS type segment and
         * if the memory area is the load area.
         */
        if (DoWrite) {
            unsigned long P = ftell (D->F);
            SegWrite (D->Filename, D->F, S->Seg, BinWriteExpr, D);
            PrintNumVal ("Wrote", (unsigned long) (ftell (D->F) - P));
        } else if (M->Flags & MF_FILL) {
            WriteMult (D->F, S->Seg->FillVal, S->Seg->Size);
            PrintNumVal ("Filled", (unsigned long) S->Seg->Size);
        }

        /* If this was the load memory area, mark the segment as dumped */
        if (S->Load == M) {
            S->Seg->Dumped = 1;
        }

        /* Calculate the new address */
        Addr += S->Seg->Size;
    }

    /* If a fill was requested, fill the remaining space */
    if ((M->Flags & MF_FILL) != 0 && M->FillLevel < M->Size) {
        unsigned long ToFill = M->Size - M->FillLevel;
        Print (stdout, 2, "    Filling 0x%lx bytes with 0x%02x\n",
               ToFill, M->FillVal);
        WriteMult (D->F, M->FillVal, ToFill);
        M->FillLevel = M->Size;
    }
}
Example #4
0
void PPUThread::InitRegs()
{
	const u32 pc = Memory.Read32(entry);
	const u32 rtoc = Memory.Read32(entry + 4);

	//ConLog.Write("entry = 0x%x", entry);
	//ConLog.Write("rtoc = 0x%x", rtoc);

	SetPc(pc);

	/*
	const s32 thread_num = Emu.GetCPU().GetThreadNumById(GetType(), GetId());

	if(thread_num < 0)
	{
		LOG_ERROR(PPU, "GetThreadNumById failed.");
		Emu.Pause();
		return;
	}
	*/

	/*
	const s32 tls_size = Emu.GetTLSFilesz() * thread_num;

	if(tls_size >= Emu.GetTLSMemsz())
	{
		LOG_ERROR(PPU, "Out of TLS memory.");
		Emu.Pause();
		return;
	}
	*/

	m_stack_point = AlignAddr(m_stack_point, 0x200) - 0x200;

	GPR[1] = m_stack_point;
	GPR[2] = rtoc;
	/*
	for(int i=4; i<32; ++i)
	{
		if(i != 6)
			GPR[i] = (i+1) * 0x10000;
	}
	*/
	if(m_argv_addr.size())
	{
		u64 argc = m_argv_addr.size();
		m_stack_point -= 0xc + 4 * argc;
		u64 argv = m_stack_point;

		auto argv_list = vm::ptr<be_t<u64>>::make((u32)argv);
		for(int i=0; i<argc; ++i) argv_list[i] = m_argv_addr[i];

		GPR[3] = argc;
		GPR[4] = argv;
		GPR[5] = argv ? argv + 0xc + 4 * argc : 0; //unk
	}
	else
	{
		GPR[3] = m_args[0];
		GPR[4] = m_args[1];
		GPR[5] = m_args[2];
		GPR[6] = m_args[3];
	}

	GPR[0] = pc;
	GPR[8] = entry;
	GPR[11] = 0x80;
	GPR[12] = Emu.GetMallocPageSize();
	GPR[13] = Memory.PRXMem.GetStartAddr() + 0x7060;
	GPR[28] = GPR[4];
	GPR[29] = GPR[3];
	GPR[31] = GPR[5];

	LR = Emu.GetPPUThreadExit();
	CTR = PC;
	CR.CR = 0x22000082;
	VSCR.NJ = 1;
	TB = 0;
}