Beispiel #1
0
	void DoState(PointerWrap &p) {
		auto s = p.Section("MpegContext", 1);
		if (!s)
			return;

		p.DoArray(mpegheader, 2048);
		p.Do(defaultFrameWidth);
		p.Do(videoFrameCount);
		p.Do(audioFrameCount);
		p.Do(endOfAudioReached);
		p.Do(endOfVideoReached);
		p.Do(videoPixelMode);
		p.Do(mpegMagic);
		p.Do(mpegVersion);
		p.Do(mpegRawVersion);
		p.Do(mpegOffset);
		p.Do(mpegStreamSize);
		p.Do(mpegFirstTimestamp);
		p.Do(mpegLastTimestamp);
		p.Do(mpegFirstDate);
		p.Do(mpegLastDate);
		p.Do(mpegRingbufferAddr);
		p.DoArray(esBuffers, NUM_ES_BUFFERS);
		p.Do(avc);
		p.Do(avcRegistered);
		p.Do(atracRegistered);
		p.Do(pcmRegistered);
		p.Do(dataRegistered);
		p.Do(ignoreAtrac);
		p.Do(ignorePcm);
		p.Do(ignoreAvc);
		p.Do(isAnalyzed);
		p.Do<u32, StreamInfo>(streamMap);
		p.DoClass(mediaengine);
	}
Beispiel #2
0
void DoState(PointerWrap &p)
{
	auto s = p.Section("Memory", 1, 2);
	if (!s)
		return;

	if (s < 2) {
		if (!g_RemasterMode)
			g_MemorySize = RAM_NORMAL_SIZE;
		g_PSPModel = PSP_MODEL_FAT;
	} else {
		u32 oldMemorySize = g_MemorySize;
		p.Do(g_PSPModel);
		p.DoMarker("PSPModel");
		if (!g_RemasterMode) {
			g_MemorySize = g_PSPModel == PSP_MODEL_FAT ? RAM_NORMAL_SIZE : RAM_DOUBLE_SIZE;
			if (oldMemorySize < g_MemorySize) {
				Shutdown();
				Init();
			}
		}
	}

	p.DoArray(GetPointer(PSP_GetKernelMemoryBase()), g_MemorySize);
	p.DoMarker("RAM");

	p.DoArray(m_pVRAM, VRAM_SIZE);
	p.DoMarker("VRAM");
	p.DoArray(m_pScratchPad, SCRATCHPAD_SIZE);
	p.DoMarker("ScratchPad");
}
Beispiel #3
0
void SavedataParam::DoState(PointerWrap &p)
{
	auto s = p.Section("SavedataParam", 1);
	if (!s)
		return;

	// pspParam is handled in PSPSaveDialog.
	p.Do(selectedSave);
	p.Do(saveDataListCount);
	p.Do(saveNameListDataCount);
	if (p.mode == p.MODE_READ)
	{
		if (saveDataList != NULL)
			delete [] saveDataList;
		if (saveDataListCount != 0)
		{
			saveDataList = new SaveFileInfo[saveDataListCount];
			p.DoArray(saveDataList, saveDataListCount);
		}
		else
			saveDataList = NULL;
	}
	else
		p.DoArray(saveDataList, saveDataListCount);
}
Beispiel #4
0
void DoState(PointerWrap &p)
{
	p.DoArray(m_pRAM, RAM_SIZE);
	p.DoMarker("RAM");
	p.DoArray(m_pVRAM, VRAM_SIZE);
	p.DoMarker("VRAM");
	p.DoArray(m_pScratchPad, SCRATCHPAD_SIZE);
	p.DoMarker("ScratchPad");
}
Beispiel #5
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;
		}
	}
}
Beispiel #6
0
void PixelShaderManager::DoState(PointerWrap &p)
{
	p.DoArray(s_tev_color);
	p.DoArray(s_tev_konst_color);

	if (p.GetMode() == PointerWrap::MODE_READ)
	{
		// Reload current state from global GPU state
		// NOTE: This requires that all GPU memory has been loaded already.
		Dirty();
	}
}
Beispiel #7
0
void SWVertexLoader::DoState(PointerWrap &p)
{
	p.DoArray(m_AttributeLoaders, sizeof m_AttributeLoaders);
	p.Do(m_VertexSize);
	p.Do(*m_CurrentVat);
	p.Do(m_positionLoader);
	p.Do(m_normalLoader);
	p.DoArray(m_colorLoader, sizeof m_colorLoader);
	p.Do(m_NumAttributeLoaders);
	m_SetupUnit->DoState(p);
	p.Do(m_TexGenSpecialCase);
}
Beispiel #8
0
void DoState(PointerWrap &p)
{
	auto s = p.Section("Memory", 1);
	if (!s)
		return;

	p.DoArray(m_pRAM, g_MemorySize);
	p.DoMarker("RAM");
	p.DoArray(m_pVRAM, VRAM_SIZE);
	p.DoMarker("VRAM");
	p.DoArray(m_pScratchPad, SCRATCHPAD_SIZE);
	p.DoMarker("ScratchPad");
}
Beispiel #9
0
void DoState(PointerWrap &p)
{
    bool wii = SConfig::GetInstance().m_LocalCoreStartupParameter.bWii;
    p.DoArray(m_pRAM, RAM_SIZE);
    p.DoArray(m_pL1Cache, L1_CACHE_SIZE);
    p.DoMarker("Memory RAM");
    if (bFakeVMEM)
        p.DoArray(m_pFakeVMEM, FAKEVMEM_SIZE);
    p.DoMarker("Memory FakeVMEM");
    if (wii)
        p.DoArray(m_pEXRAM, EXRAM_SIZE);
    p.DoMarker("Memory EXRAM");
}
Beispiel #10
0
void DoCPState(PointerWrap& p)
{
    p.DoArray(g_main_cp_state.array_bases);
    p.DoArray(g_main_cp_state.array_strides);
    p.Do(g_main_cp_state.matrix_index_a);
    p.Do(g_main_cp_state.matrix_index_b);
    p.Do(g_main_cp_state.vtx_desc.Hex);
    p.DoArray(g_main_cp_state.vtx_attr);
    p.DoMarker("CP Memory");
    if (p.mode == PointerWrap::MODE_READ)
    {
        g_main_cp_state.bases_dirty = true;
    }
}
Beispiel #11
0
void DoState(PointerWrap &p)
{
    p.DoArray(m_pRAM, g_MemorySize);
    p.DoMarker("RAM");
    p.DoArray(m_pVRAM, VRAM_SIZE);
    p.DoMarker("VRAM");
    p.DoArray(m_pScratchPad, SCRATCHPAD_SIZE);
    p.DoMarker("ScratchPad");
    p.Do(g_RemasterMode); // TODO: Need to test more if this and MemoryMask need to be saved in the state
    p.DoMarker("RemasterMode");
    p.Do(g_MemoryMask);
    p.DoMarker("MemoryMask");
    p.Do(g_DoubleTextureCoordinates); // TODO: Is there a more appropriate place for this?
    p.DoMarker("DoubleTextureCoordinates");
}
Beispiel #12
0
void MediaEngine::DoState(PointerWrap &p){
	auto s = p.Section("MediaEngine", 1);
	if (!s)
		return;

	p.Do(m_videoStream);
	p.Do(m_audioStream);

	p.DoArray(m_mpegheader, sizeof(m_mpegheader));

	p.Do(m_ringbuffersize);

	u32 hasloadStream = m_pdata != NULL;
	p.Do(hasloadStream);
	if (hasloadStream && p.mode == p.MODE_READ)
		loadStream(m_mpegheader, 2048, m_ringbuffersize);
#ifdef USE_FFMPEG
	u32 hasopencontext = m_pFormatCtx != NULL;
#else
	u32 hasopencontext = false;
#endif
	p.Do(hasopencontext);
	if (hasopencontext && p.mode == p.MODE_READ)
		openContext();
	if (m_pdata)
		m_pdata->DoState(p);
	if (m_demux)
		m_demux->DoState(p);

	p.Do(m_videopts);
	p.Do(m_audiopts);

	p.Do(m_isVideoEnd);
	p.Do(m_noAudioData);
}
Beispiel #13
0
void MediaEngine::DoState(PointerWrap &p) {
    p.Do(m_videoStream);
    p.Do(m_audioStream);

    p.DoArray(m_mpegheader, sizeof(m_mpegheader));

    p.Do(m_ringbuffersize);

    u32 hasloadStream = m_pdata != NULL;
    p.Do(hasloadStream);
    if (hasloadStream && p.mode == p.MODE_READ)
        loadStream(m_mpegheader, 2048, m_ringbuffersize);
    u32 hasopencontext = m_pFormatCtx != NULL;
    p.Do(hasopencontext);
    if (hasopencontext && p.mode == p.MODE_READ)
        openContext();
    if (m_pdata)
        m_pdata->DoState(p);
    if (m_demux)
        m_demux->DoState(p);

    p.Do(m_videopts);
    p.Do(m_audiopts);

    p.Do(m_isVideoEnd);
    p.Do(m_noAudioData);
    p.DoMarker("MediaEngine");
}
Beispiel #14
0
void Fifo_DoState(PointerWrap &p)
{
	p.DoArray(videoBuffer, FIFO_SIZE);
	p.Do(size);
	p.DoPointer(g_pVideoData, videoBuffer);
	p.Do(g_bSkipCurrentFrame);
}
Beispiel #15
0
void __sceAudiocodecDoState(PointerWrap &p){
	auto s = p.Section("AudioList", 0, 2);
	if (!s) {
		oldStateLoaded = true;
		return;
	}

	int count = (int)audioList.size();
	p.Do(count);

	if (count > 0) {
		if (p.mode == PointerWrap::MODE_READ) {
			clearDecoders();

			// loadstate if audioList is nonempty
			auto codec_ = new int[count];
			auto ctxPtr_ = new u32[count];
			p.DoArray(codec_, s >= 2 ? count : (int)ARRAY_SIZE(codec_));
			p.DoArray(ctxPtr_, s >= 2 ? count : (int)ARRAY_SIZE(ctxPtr_));
			for (int i = 0; i < count; i++) {
				auto decoder = new SimpleAudio(codec_[i]);
				decoder->SetCtxPtr(ctxPtr_[i]);
				audioList[ctxPtr_[i]] = decoder;
			}
			delete[] codec_;
			delete[] ctxPtr_;
		}
		else
		{
			// savestate if audioList is nonempty
			// Some of this is only necessary in Write but won't really hurt Measure.
			auto codec_ = new int[count];
			auto ctxPtr_ = new u32[count];
			int i = 0;
			for (auto it = audioList.begin(), end = audioList.end(); it != end; it++) {
				const SimpleAudio *decoder = it->second;
				codec_[i] = decoder->GetAudioType();
				ctxPtr_[i] = decoder->GetCtxPtr();
				i++;
			}
			p.DoArray(codec_, count);
			p.DoArray(ctxPtr_, count);
			delete[] codec_;
			delete[] ctxPtr_;
		}
	}
}
Beispiel #16
0
void DoCPState(PointerWrap& p)
{
	// We don't save g_preprocess_cp_state separately because the GPU should be
	// synced around state save/load.
	p.DoArray(g_main_cp_state.array_bases);
	p.DoArray(g_main_cp_state.array_strides);
	p.Do(g_main_cp_state.matrix_index_a);
	p.Do(g_main_cp_state.matrix_index_b);
	p.Do(g_main_cp_state.vtx_desc.Hex);
	p.DoArray(g_main_cp_state.vtx_attr);
	p.DoMarker("CP Memory");
	if (p.mode == PointerWrap::MODE_READ)
	{
		CopyPreprocessCPStateFromMain();
		g_main_cp_state.bases_dirty = true;
	}
}
Beispiel #17
0
static void DoState(PointerWrap &p)
{
	// BP Memory
	p.Do(bpmem);
	p.DoMarker("BP Memory");

	// CP Memory
	p.DoArray(arraybases, 16);
	p.DoArray(arraystrides, 16);
	p.Do(MatrixIndexA);
	p.Do(MatrixIndexB);
	p.Do(g_VtxDesc.Hex);
	p.DoArray(g_VtxAttr, 8);
	p.DoMarker("CP Memory");

	// XF Memory
	p.Do(xfregs);
	p.DoArray(xfmem, XFMEM_SIZE);
	p.DoMarker("XF Memory");

	// Texture decoder
	p.DoArray(texMem, TMEM_SIZE);
	p.DoMarker("texMem");

	// FIFO
	Fifo_DoState(p);
	p.DoMarker("Fifo");

	CommandProcessor::DoState(p);
	p.DoMarker("CommandProcessor");

	PixelEngine::DoState(p);
	p.DoMarker("PixelEngine");

	// the old way of replaying current bpmem as writes to push side effects to pixel shader manager doesn't really work.
	PixelShaderManager::DoState(p);
	p.DoMarker("PixelShaderManager");

	VertexShaderManager::DoState(p);
	p.DoMarker("VertexShaderManager");

	VertexManager::DoState(p);
	p.DoMarker("VertexManager");

	// TODO: search for more data that should be saved and add it here
}
Beispiel #18
0
void BlockAllocator::Block::DoState(PointerWrap &p)
{
	p.Do(start);
	p.Do(size);
	p.Do(taken);
	p.DoArray(tag, sizeof(tag));
	p.DoMarker("Block");
}
Beispiel #19
0
void __PowerDoState(PointerWrap &p) {
	auto s = p.Section("scePower", 1);
	if (!s)
		return;

	p.DoArray(powerCbSlots, ARRAY_SIZE(powerCbSlots));
	p.Do(volatileMemLocked);
	p.Do(volatileWaitingThreads);
}
Beispiel #20
0
	virtual void DoState(PointerWrap &p)
	{
		p.Do(nf);
		if (p.mode == p.MODE_READ)
			blocks = new bool[nf.numBlocks];
		p.DoArray(blocks, nf.numBlocks);
		p.Do(address);
		p.DoMarker("FPL");
	}
Beispiel #21
0
void PSPMsgDialog::DoState(PointerWrap &p)
{
	PSPDialog::DoState(p);
	p.Do(flag);
	p.Do(messageDialog);
	p.Do(messageDialogAddr);
	p.DoArray(msgText, sizeof(msgText));
	p.Do(yesnoChoice);
	p.DoMarker("PSPMsgDialog");
}
Beispiel #22
0
void MIPSState::DoState(PointerWrap &p) {
	auto s = p.Section("MIPSState", 1, 3);
	if (!s)
		return;

	// Reset the jit if we're loading.
	if (p.mode == p.MODE_READ)
		Reset();
	if (MIPSComp::jit)
		MIPSComp::jit->DoState(p);
	else
		MIPSComp::jit->DoDummyState(p);

	p.DoArray(r, sizeof(r) / sizeof(r[0]));
	p.DoArray(f, sizeof(f) / sizeof(f[0]));
	if (s <= 2) {
		float vtemp[128];
		p.DoArray(vtemp, sizeof(v) / sizeof(v[0]));
		for (int i = 0; i < 128; i++) {
			v[voffset[i]] = vtemp[i];
		}
	} else {
		p.DoArray(v, sizeof(v) / sizeof(v[0]));
	}
	p.DoArray(vfpuCtrl, sizeof(vfpuCtrl) / sizeof(vfpuCtrl[0]));
	p.Do(pc);
	p.Do(nextPC);
	p.Do(downcount);
	// Reversed, but we can just leave it that way.
	p.Do(hi);
	p.Do(lo);
	p.Do(fpcond);
	if (s <= 1) {
		u32 fcr0_unused = 0;
		p.Do(fcr0_unused);
	}
	p.Do(fcr31);
	p.Do(rng.m_w);
	p.Do(rng.m_z);
	p.Do(inDelaySlot);
	p.Do(llBit);
	p.Do(debugCount);
}
Beispiel #23
0
void DoState(PointerWrap& p)
{
  // some of this code has been disabled, because
  // it changes registers even in MODE_MEASURE (which is suspicious and seems like it could cause
  // desyncs)
  // and because the values it's changing have been added to CoreTiming::DoState, so it might
  // conflict to mess with them here.

  // rSPR(SPR_DEC) = SystemTimers::GetFakeDecrementer();
  // *((u64 *)&TL) = SystemTimers::GetFakeTimeBase(); //works since we are little endian and TL
  // comes first :)

  p.DoArray(ppcState.gpr);
  p.Do(ppcState.pc);
  p.Do(ppcState.npc);
  p.DoArray(ppcState.cr_val);
  p.Do(ppcState.msr);
  p.Do(ppcState.fpscr);
  p.Do(ppcState.Exceptions);
  p.Do(ppcState.downcount);
  p.Do(ppcState.xer_ca);
  p.Do(ppcState.xer_so_ov);
  p.Do(ppcState.xer_stringctrl);
  p.DoArray(ppcState.ps);
  p.DoArray(ppcState.sr);
  p.DoArray(ppcState.spr);
  p.DoArray(ppcState.tlb);
  p.Do(ppcState.pagetable_base);
  p.Do(ppcState.pagetable_hashmask);

  ppcState.iCache.DoState(p);

  if (p.GetMode() == PointerWrap::MODE_READ)
  {
    IBATUpdated();
    DBATUpdated();
  }

  // SystemTimers::DecrementerSet();
  // SystemTimers::TimeBaseSet();

  JitInterface::DoState(p);
}
Beispiel #24
0
void DoState(PointerWrap &p) {
	auto s = p.Section("Memory", 1, 3);
	if (!s)
		return;

	if (s < 2) {
		if (!g_RemasterMode)
			g_MemorySize = RAM_NORMAL_SIZE;
		g_PSPModel = PSP_MODEL_FAT;
	} else if (s == 2) {
		// In version 2, we determine memory size based on PSP model.
		u32 oldMemorySize = g_MemorySize;
		p.Do(g_PSPModel);
		p.DoMarker("PSPModel");
		if (!g_RemasterMode) {
			g_MemorySize = g_PSPModel == PSP_MODEL_FAT ? RAM_NORMAL_SIZE : RAM_DOUBLE_SIZE;
			if (oldMemorySize < g_MemorySize) {
				Shutdown();
				Init();
			}
		}
	} else {
		// In version 3, we started just saving the memory size directly.
		// It's no longer based strictly on the PSP model.
		u32 oldMemorySize = g_MemorySize;
		p.Do(g_PSPModel);
		p.DoMarker("PSPModel");
		p.Do(g_MemorySize);
		if (oldMemorySize != g_MemorySize) {
			Shutdown();
			Init();
		}
	}

	p.DoArray(GetPointer(PSP_GetKernelMemoryBase()), g_MemorySize);
	p.DoMarker("RAM");

	p.DoArray(m_pPhysicalVRAM1, VRAM_SIZE);
	p.DoMarker("VRAM");
	p.DoArray(m_pPhysicalScratchPad, SCRATCHPAD_SIZE);
	p.DoMarker("ScratchPad");
}
Beispiel #25
0
void BlockAllocator::Block::DoState(PointerWrap &p)
{
	auto s = p.Section("Block", 1);
	if (!s)
		return;

	p.Do(start);
	p.Do(size);
	p.Do(taken);
	p.DoArray(tag, sizeof(tag));
}
Beispiel #26
0
void SaveFileInfo::DoState(PointerWrap &p)
{
	auto s = p.Section("SaveFileInfo", 1, 2);
	if (!s)
		return;

	p.Do(size);
	p.Do(saveName);
	p.Do(idx);

	p.DoArray(title, sizeof(title));
	p.DoArray(saveTitle, sizeof(saveTitle));
	p.DoArray(saveDetail, sizeof(saveDetail));

	p.Do(modif_time);

	if (s <= 1) {
		u32 textureData;
		int textureWidth;
		int textureHeight;
		p.Do(textureData);
		p.Do(textureWidth);
		p.Do(textureHeight);

		if (textureData != 0) {
			// Must be MODE_READ.
			texture = new PPGeImage("");
			texture->CompatLoad(textureData, textureWidth, textureHeight);
		}
	} else {
		bool hasTexture = texture != NULL;
		p.Do(hasTexture);
		if (hasTexture) {
			if (p.mode == p.MODE_READ) {
				texture = new PPGeImage("");
			}
			texture->DoState(p);
		}
	}
}
Beispiel #27
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);
}
Beispiel #28
0
void MpegDemux::DoState(PointerWrap &p) {
	auto s = p.Section("MpegDemux", 1);
	if (!s)
		return;

	p.Do(m_index);
	p.Do(m_len);
	p.Do(m_audioChannel);
	p.Do(m_readSize);
	if (m_buf)
		p.DoArray(m_buf, m_len);
	p.DoClass(m_audioStream);
}
Beispiel #29
0
void __KernelMemoryDoState(PointerWrap &p)
{
	kernelMemory.DoState(p);
	userMemory.DoState(p);

	p.Do(vplWaitTimer);
	CoreTiming::RestoreRegisterEvent(vplWaitTimer, "VplTimeout", __KernelVplTimeout);
	p.Do(flags_);
	p.Do(sdkVersion_);
	p.Do(compilerVersion_);
	p.DoArray(tlsUsedIndexes, ARRAY_SIZE(tlsUsedIndexes));
	p.DoMarker("sceKernelMemory");
}
Beispiel #30
0
void KernelObjectPool::DoState(PointerWrap &p)
{
	auto s = p.Section("KernelObjectPool", 1);
	if (!s)
		return;

	int _maxCount = maxCount;
	p.Do(_maxCount);

	if (_maxCount != maxCount)
	{
		p.SetError(p.ERROR_FAILURE);
		ERROR_LOG(SCEKERNEL, "Unable to load state: different kernel object storage.");
		return;
	}

	if (p.mode == p.MODE_READ)
	{
		hleCurrentThreadName = NULL;
		kernelObjects.Clear();
	}

	p.Do(nextID);
	p.DoArray(occupied, maxCount);
	for (int i = 0; i < maxCount; ++i)
	{
		if (!occupied[i])
			continue;

		int type;
		if (p.mode == p.MODE_READ)
		{
			p.Do(type);
			pool[i] = CreateByIDType(type);

			// Already logged an error.
			if (pool[i] == NULL)
				return;

			pool[i]->uid = i + handleOffset;
		}
		else
		{
			type = pool[i]->GetIDType();
			p.Do(type);
		}
		pool[i]->DoState(p);
		if (p.error >= p.ERROR_FAILURE)
			break;
	}
}