int sceDisplayAdjustAccumulatedHcount(int value) { if (value < 0) { ERROR_LOG_REPORT(SCEDISPLAY, "sceDisplayAdjustAccumulatedHcount(%d): invalid value", value); return SCE_KERNEL_ERROR_INVALID_VALUE; } // Since it includes the current hCount, find the difference to apply to the base. u32 accumHCount = __DisplayGetAccumulatedHcount(); int diff = value - accumHCount; hCountBase += diff; DEBUG_LOG(SCEDISPLAY, "sceDisplayAdjustAccumulatedHcount(%d)", value); return 0; }
void GPUCommon::ProcessEvent(GPUEvent ev) { switch (ev.type) { case GPU_EVENT_PROCESS_QUEUE: ProcessDLQueueInternal(); break; case GPU_EVENT_REAPPLY_GFX_STATE: ReapplyGfxStateInternal(); break; default: ERROR_LOG_REPORT(G3D, "Unexpected GPU event type: %d", (int)ev); } }
MpegContext *getMpegCtx(u32 mpegAddr) { u32 mpeg = Memory::Read_U32(mpegAddr); // TODO: Remove. if (mpegMap.find(mpeg) == mpegMap.end()) { ERROR_LOG_REPORT(HLE, "Bad mpeg handle %08x - using last one (%08x) instead", mpeg, lastMpegHandle); mpeg = lastMpegHandle; } if (mpegMap.find(mpeg) == mpegMap.end()) return NULL; return mpegMap[mpeg]; }
void __KernelEventFlagBeginCallback(SceUID threadID, SceUID prevCallbackId) { SceUID pauseKey = prevCallbackId == 0 ? threadID : prevCallbackId; u32 error; SceUID flagID = __KernelGetWaitID(threadID, WAITTYPE_EVENTFLAG, error); u32 timeoutPtr = __KernelGetWaitTimeoutPtr(threadID, error); EventFlag *flag = flagID == 0 ? NULL : kernelObjects.Get<EventFlag>(flagID, error); if (flag) { // This means two callbacks in a row. PSP crashes if the same callback runs inside itself. // TODO: Handle this better? if (flag->pausedWaits.find(pauseKey) != flag->pausedWaits.end()) return; EventFlagTh waitData = {0}; for (size_t i = 0; i < flag->waitingThreads.size(); i++) { EventFlagTh *t = &flag->waitingThreads[i]; if (t->tid == threadID) { waitData = *t; // TODO: Hmm, what about priority/fifo order? Does it lose its place in line? flag->waitingThreads.erase(flag->waitingThreads.begin() + i); break; } } if (waitData.tid != threadID) { ERROR_LOG_REPORT(HLE, "sceKernelWaitEventFlagCB: wait not found to pause for callback"); return; } if (timeoutPtr != 0 && eventFlagWaitTimer != -1) { s64 cyclesLeft = CoreTiming::UnscheduleEvent(eventFlagWaitTimer, threadID); waitData.pausedTimeout = CoreTiming::GetTicks() + cyclesLeft; } else waitData.pausedTimeout = 0; flag->pausedWaits[pauseKey] = waitData; DEBUG_LOG(HLE, "sceKernelWaitEventFlagCB: Suspending lock wait for callback"); } else WARN_LOG_REPORT(HLE, "sceKernelWaitEventFlagCB: beginning callback with bad wait id?"); }
int sceKernelVolatileMemUnlock(int type) { if (type != 0) { ERROR_LOG_REPORT(HLE, "sceKernelVolatileMemUnlock(%i) - invalid mode", type); return SCE_KERNEL_ERROR_INVALID_MODE; } if (volatileMemLocked) { volatileMemLocked = false; // Wake someone, always fifo. bool wokeThreads = false; u32 error; while (!volatileWaitingThreads.empty() && !volatileMemLocked) { VolatileWaitingThread waitInfo = volatileWaitingThreads.front(); volatileWaitingThreads.erase(volatileWaitingThreads.begin()); int waitID = __KernelGetWaitID(waitInfo.threadID, WAITTYPE_VMEM, error); // If they were force-released, just skip. if (waitID == 1 && __KernelVolatileMemLock(0, waitInfo.addrPtr, waitInfo.sizePtr) == 0) { __KernelResumeThreadFromWait(waitInfo.threadID, 0); wokeThreads = true; } } if (wokeThreads) { INFO_LOG(HLE, "sceKernelVolatileMemUnlock(%i) handed over to another thread", type); hleReSchedule("volatile mem unlocked"); } else { DEBUG_LOG(HLE, "sceKernelVolatileMemUnlock(%i)", type); } } else { ERROR_LOG_REPORT(HLE, "sceKernelVolatileMemUnlock(%i) FAILED - not locked", type); // I guess it must use a sema. return SCE_KERNEL_ERROR_SEMA_OVF; } return 0; }
int sceAudiocodecInit(u32 ctxPtr, int codec) { if (isValidCodec(codec)) { // Create audio decoder for given audio codec and push it into AudioList if (removeDecoder(ctxPtr)) { WARN_LOG_REPORT(HLE, "sceAudiocodecInit(%08x, %d): replacing existing context", ctxPtr, codec); } auto decoder = new SimpleAudio(ctxPtr, codec); audioList[ctxPtr] = decoder; INFO_LOG(ME, "sceAudiocodecInit(%08x, %i (%s))", ctxPtr, codec, GetCodecName(codec)); DEBUG_LOG(ME, "Number of playing sceAudioCodec audios : %d", (int)audioList.size()); return 0; } ERROR_LOG_REPORT(ME, "sceAudiocodecInit(%08x, %i (%s)): Unknown audio codec %i", ctxPtr, codec, GetCodecName(codec), codec); return 0; }
size_t DirectoryFileSystem::ReadFile(u32 handle, u8 *pointer, s64 size, int &usec) { EntryMap::iterator iter = entries.find(handle); if (iter != entries.end()) { if (size < 0) { ERROR_LOG_REPORT(FILESYS, "Invalid read for %lld bytes from disk %s", size, iter->second.guestFilename.c_str()); return 0; } size_t bytesRead = iter->second.hFile.Read(pointer,size); return bytesRead; } else { //This shouldn't happen... ERROR_LOG(FILESYS,"Cannot read file that hasn't been opened: %08x", handle); return 0; } }
void ApplyPrefixST(float *v, u32 data, VectorSize size) { // Possible optimization shortcut: if (data == 0xe4) return; int n = GetNumVectorElements(size); float origV[4]; static const float constantArray[8] = {0.f, 1.f, 2.f, 0.5f, 3.f, 1.f/3.f, 0.25f, 1.f/6.f}; for (int i = 0; i < n; i++) { origV[i] = v[i]; } for (int i = 0; i < n; i++) { int regnum = (data >> (i*2)) & 3; int abs = (data >> (8+i)) & 1; int negate = (data >> (16+i)) & 1; int constants = (data >> (12+i)) & 1; if (!constants) { // Prefix may say "z, z, z, z" but if this is a pair, we force to x. // TODO: But some ops seem to use const 0 instead? if (regnum >= n) { ERROR_LOG_REPORT(CPU, "Invalid VFPU swizzle: %08x: %i / %d at PC = %08x (%s)", data, regnum, n, currentMIPS->pc, currentMIPS->DisasmAt(currentMIPS->pc)); //for (int i = 0; i < 12; i++) { // ERROR_LOG(CPU, " vfpuCtrl[%i] = %08x", i, currentMIPS->vfpuCtrl[i]); //} regnum = 0; } v[i] = origV[regnum]; if (abs) v[i] = fabs(v[i]); } else { v[i] = constantArray[regnum + (abs<<2)]; } if (negate) v[i] = -v[i]; } }
int sceKernelAllocateTls(SceUID uid) { // TODO: Allocate downward if PSP_TLS_ATTR_HIGHMEM? DEBUG_LOG(HLE, "sceKernelAllocateTls(%08x)", uid); u32 error; TLS *tls = kernelObjects.Get<TLS>(uid, error); if (tls) { SceUID threadID = __KernelGetCurThread(); int allocBlock = -1; // If the thread already has one, return it. for (size_t i = 0; i < tls->ntls.totalBlocks && allocBlock == -1; ++i) { if (tls->usage[i] == threadID) allocBlock = (int) i; } if (allocBlock == -1) { for (size_t i = 0; i < tls->ntls.totalBlocks && allocBlock == -1; ++i) { // The PSP doesn't give the same block out twice in a row, even if freed. if (tls->usage[tls->next] == 0) allocBlock = tls->next; tls->next = (tls->next + 1) % tls->ntls.blockSize; } if (allocBlock != -1) { tls->usage[allocBlock] = threadID; --tls->ntls.freeBlocks; } } if (allocBlock == -1) { // TODO: Wait here, wake when one is free. ERROR_LOG_REPORT(HLE, "sceKernelAllocateTls: should wait"); return -1; } return tls->address + allocBlock * tls->ntls.blockSize; } else return error; }
int sceFontGetCharGlyphImage_Clip(u32 fontHandle, u32 charCode, u32 glyphImagePtr, int clipXPos, int clipYPos, int clipWidth, int clipHeight) { if (!Memory::IsValidAddress(glyphImagePtr)) { ERROR_LOG(HLE, "sceFontGetCharGlyphImage_Clip(%08x, %i, %08x, %i, %i, %i, %i): bad glyphImage pointer", fontHandle, charCode, glyphImagePtr, clipXPos, clipYPos, clipWidth, clipHeight); return ERROR_FONT_INVALID_PARAMETER; } LoadedFont *font = GetLoadedFont(fontHandle, false); if (!font) { ERROR_LOG_REPORT(HLE, "sceFontGetCharGlyphImage_Clip(%08x, %i, %08x, %i, %i, %i, %i): bad font", fontHandle, charCode, glyphImagePtr, clipXPos, clipYPos, clipWidth, clipHeight); return ERROR_FONT_INVALID_PARAMETER; } INFO_LOG(HLE, "sceFontGetCharGlyphImage_Clip(%08x, %i, %08x, %i, %i, %i, %i)", fontHandle, charCode, glyphImagePtr, clipXPos, clipYPos, clipWidth, clipHeight); auto glyph = Memory::GetStruct<const GlyphImage>(glyphImagePtr); int altCharCode = font->GetFontLib()->GetAltCharCode(); font->GetPGF()->DrawCharacter(glyph, clipXPos, clipYPos, clipXPos + clipWidth, clipYPos + clipHeight, charCode, altCharCode, FONT_PGF_CHARGLYPH); return 0; }
u32 sceUtilityLoadModule(u32 module) { // TODO: Not all modules between 0x100 and 0x601 are valid. if (module < 0x100 || module > 0x601) { ERROR_LOG_REPORT(HLE, "sceUtilityLoadModule(%i): invalid module id", module); return SCE_ERROR_MODULE_BAD_ID; } DEBUG_LOG(HLE, "sceUtilityLoadModule(%i)", module); // TODO: Each module has its own timing, technically, but this is a low-end. // Note: Some modules have dependencies, but they still resched. if (module == 0x3FF) return hleDelayResult(0, "utility module loaded", 130); else return hleDelayResult(0, "utility module loaded", 25000); }
u32 sceUtilityUnloadModule(u32 module) { // TODO: Not all modules between 0x100 and 0x601 are valid. if (module < 0x100 || module > 0x601) { ERROR_LOG_REPORT(HLE, "sceUtilityUnloadModule(%i): invalid module id", module); return SCE_ERROR_MODULE_BAD_ID; } DEBUG_LOG(HLE, "sceUtilityUnloadModule(%i)", module); // TODO: Each module has its own timing, technically, but this is a low-end. // Note: If not loaded, it should not reschedule actually... if (module == 0x3FF) return hleDelayResult(0, "utility module unloaded", 110); else return hleDelayResult(0, "utility module unloaded", 400); }
int sceFontGetCharGlyphImage(u32 fontHandle, u32 charCode, u32 glyphImagePtr) { if (!Memory::IsValidAddress(glyphImagePtr)) { ERROR_LOG(HLE, "sceFontGetCharGlyphImage(%x, %x, %x): bad glyphImage pointer", fontHandle, charCode, glyphImagePtr); return ERROR_FONT_INVALID_PARAMETER; } LoadedFont *font = GetLoadedFont(fontHandle, false); if (!font) { ERROR_LOG_REPORT(HLE, "sceFontGetCharGlyphImage(%x, %x, %x): bad font", fontHandle, charCode, glyphImagePtr); return ERROR_FONT_INVALID_PARAMETER; } DEBUG_LOG(HLE, "sceFontGetCharGlyphImage(%x, %x, %x)", fontHandle, charCode, glyphImagePtr); auto glyph = Memory::GetStruct<const GlyphImage>(glyphImagePtr); int altCharCode = font->GetFontLib()->GetAltCharCode(); font->GetPGF()->DrawCharacter(glyph, 0, 0, 8192, 8192, charCode, altCharCode, FONT_PGF_CHARGLYPH); return 0; }
int MediaEngine::getAudioSamples(u32 bufferPtr) { if (!Memory::IsValidAddress(bufferPtr)) { ERROR_LOG_REPORT(ME, "Ignoring bad audio decode address %08x during video playback", bufferPtr); } u8 *buffer = Memory::GetPointer(bufferPtr); if (!m_demux) { return 0; } // When m_demux , increment pts m_audiopts += 4180; // Demux now (rather than on add data) so that we select the right stream. m_demux->demux(m_audioStream); u8 *audioFrame = 0; int headerCode1, headerCode2; int frameSize = m_demux->getNextaudioFrame(&audioFrame, &headerCode1, &headerCode2); if (frameSize == 0) { m_noAudioData = true; return 0; } int outbytes = 0; if (m_audioContext != NULL) { if (!AudioDecode(m_audioContext, audioFrame, frameSize, &outbytes, buffer)) { ERROR_LOG(ME, "Audio (%s) decode failed during video playback", GetCodecName(m_audioType)); } } if (headerCode1 == 0x24) { // it a mono atrac3plus, convert it to stereo s16 *outbuf = (s16*)buffer; s16 *inbuf = (s16*)buffer; for (int i = 0x800 - 1; i >= 0; i--) { s16 sample = inbuf[i]; outbuf[i * 2] = sample; outbuf[i * 2 + 1] = sample; } } m_noAudioData = false; return 0x2000; }
int sceFontGetFontInfo(u32 fontHandle, u32 fontInfoPtr) { if (!Memory::IsValidAddress(fontInfoPtr)) { ERROR_LOG(HLE, "sceFontGetFontInfo(%x, %x): bad fontInfo pointer", fontHandle, fontInfoPtr); return ERROR_FONT_INVALID_PARAMETER; } LoadedFont *font = GetLoadedFont(fontHandle, true); if (!font) { ERROR_LOG_REPORT(HLE, "sceFontGetFontInfo(%x, %x): bad font", fontHandle, fontInfoPtr); return ERROR_FONT_INVALID_PARAMETER; } DEBUG_LOG(HLE, "sceFontGetFontInfo(%x, %x)", fontHandle, fontInfoPtr); auto fi = Memory::GetStruct<PGFFontInfo>(fontInfoPtr); font->GetPGF()->GetFontInfo(fi); fi->fontStyle = font->GetFont()->GetFontStyle(); return 0; }
SceUID KernelObjectPool::Create(KernelObject *obj, int rangeBottom, int rangeTop) { if (rangeTop > maxCount) rangeTop = maxCount; if (nextID >= rangeBottom && nextID < rangeTop) rangeBottom = nextID++; for (int i = rangeBottom; i < rangeTop; i++) { if (!occupied[i]) { occupied[i] = true; pool[i] = obj; pool[i]->uid = i + handleOffset; return i + handleOffset; } } ERROR_LOG_REPORT(SCEKERNEL, "Unable to allocate kernel object, too many objects slots in use."); return 0; }
int sceFontGetCharInfo(u32 fontHandle, u32 charCode, u32 charInfoPtr) { if (!Memory::IsValidAddress(charInfoPtr)) { ERROR_LOG(HLE, "sceFontGetCharInfo(%08x, %i, %08x): bad charInfo pointer", fontHandle, charCode, charInfoPtr); return ERROR_FONT_INVALID_PARAMETER; } LoadedFont *font = GetLoadedFont(fontHandle, false); if (!font) { // The PSP crashes, but we assume it'd work like sceFontGetFontInfo(), and not touch charInfo. ERROR_LOG_REPORT(HLE, "sceFontGetCharInfo(%08x, %i, %08x): bad font", fontHandle, charCode, charInfoPtr); return ERROR_FONT_INVALID_PARAMETER; } DEBUG_LOG(HLE, "sceFontGetCharInfo(%08x, %i, %08x)", fontHandle, charCode, charInfoPtr); auto charInfo = Memory::GetStruct<PGFCharInfo>(charInfoPtr); font->GetPGF()->GetCharInfo(charCode, charInfo); return 0; }
int sceKernelVolatileMemTryLock(int type, u32 paddr, u32 psize) { u32 error = __KernelVolatileMemLock(type, paddr, psize); switch (error) { case 0: DEBUG_LOG(HLE, "sceKernelVolatileMemTryLock(%i, %08x, %08x) - success", type, paddr, psize); break; case ERROR_POWER_VMEM_IN_USE: ERROR_LOG(HLE, "sceKernelVolatileMemTryLock(%i, %08x, %08x) - already locked!", type, paddr, psize); break; default: ERROR_LOG_REPORT(HLE, "%08x=sceKernelVolatileMemTryLock(%i, %08x, %08x) - error", type, paddr, psize, error); break; } return error; }
void D3D9_Resize(HWND window) { // This should only be called from the emu thread. int xres, yres; GetRes(xres, yres); bool w_changed = pp.BackBufferWidth != xres; bool h_changed = pp.BackBufferHeight != yres; if (device && (w_changed || h_changed)) { DX9::fbo_shutdown(); pp.BackBufferWidth = xres; pp.BackBufferHeight = yres; HRESULT hr = device->Reset(&pp); if (FAILED(hr)) { ERROR_LOG_REPORT(G3D, "Unable to reset device: %s", DXGetErrorStringA(hr)); PanicAlert("Unable to reset D3D9 device: %s", DXGetErrorStringA(hr)); } DX9::fbo_init(d3d); } }
int MediaEngine::getAudioSamples(u32 bufferPtr) { if (!Memory::IsValidAddress(bufferPtr)) { ERROR_LOG_REPORT(ME, "Ignoring bad audio decode address %08x during video playback", bufferPtr); } u8 *buffer = Memory::GetPointer(bufferPtr); if (!m_demux) { return 0; } u8 *audioFrame = 0; int headerCode1, headerCode2; int frameSize = getNextAudioFrame(&audioFrame, &headerCode1, &headerCode2); if (frameSize == 0) { return 0; } int outbytes = 0; if (m_audioContext != NULL) { if (!m_audioContext->Decode(audioFrame, frameSize, buffer, &outbytes)) { ERROR_LOG(ME, "Audio (%s) decode failed during video playback", GetCodecName(m_audioType)); } #ifndef MOBILE_DEVICE CBreakPoints::ExecMemCheck(bufferPtr, true, outbytes, currentMIPS->pc); #endif } if (headerCode1 == 0x24) { // it a mono atrac3plus, convert it to stereo s16 *outbuf = (s16*)buffer; s16 *inbuf = (s16*)buffer; for (int i = 0x800 - 1; i >= 0; i--) { s16 sample = inbuf[i]; outbuf[i * 2] = sample; outbuf[i * 2 + 1] = sample; } } return 0x2000; }
void D3D9Context::Resize() { // This should only be called from the emu thread. int xres, yres; GetRes(hWnd, xres, yres); bool w_changed = pp.BackBufferWidth != xres; bool h_changed = pp.BackBufferHeight != yres; if (device && (w_changed || h_changed)) { DX9::fbo_shutdown(); pp.BackBufferWidth = xres; pp.BackBufferHeight = yres; HRESULT hr = device->Reset(&pp); if (FAILED(hr)) { // Had to remove DXGetErrorStringA calls here because dxerr.lib is deprecated and will not link with VS 2015. ERROR_LOG_REPORT(G3D, "Unable to reset D3D device"); PanicAlert("Unable to reset D3D9 device"); } DX9::fbo_init(d3d); } }
bool WriteSyscall(const char *moduleName, u32 nib, u32 address) { if (nib == 0) { WARN_LOG_REPORT(HLE, "Wrote patched out nid=0 syscall (%s)", moduleName); Memory::Write_U32(MIPS_MAKE_JR_RA(), address); //patched out? Memory::Write_U32(MIPS_MAKE_NOP(), address+4); //patched out? return true; } int modindex = GetModuleIndex(moduleName); if (modindex != -1) { Memory::Write_U32(MIPS_MAKE_JR_RA(), address); // jr ra Memory::Write_U32(GetSyscallOp(moduleName, nib), address + 4); return true; } else { ERROR_LOG_REPORT(HLE, "Unable to write unknown syscall: %s/%08x", moduleName, nib); return false; } }
void Jit::WriteExit(u32 destination, int exit_num) { _dbg_assert_msg_(JIT, exit_num < MAX_JIT_BLOCK_EXITS, "Expected a valid exit_num"); if (!Memory::IsValidAddress(destination)) { ERROR_LOG_REPORT(JIT, "Trying to write block exit to illegal destination %08x: pc = %08x", destination, currentMIPS->pc); } // If we need to verify coreState and rewind, we may not jump yet. if (js.afterOp & (JitState::AFTER_CORE_STATE | JitState::AFTER_REWIND_PC_BAD_STATE)) { // CORE_RUNNING is <= CORE_NEXTFRAME. CMP(32, M((void*)&coreState), Imm32(CORE_NEXTFRAME)); FixupBranch skipCheck = J_CC(CC_LE); MOV(32, M(&mips_->pc), Imm32(js.compilerPC)); WriteSyscallExit(); SetJumpTarget(skipCheck); js.afterOp = JitState::AFTER_NONE; } WriteDowncount(); //If nobody has taken care of this yet (this can be removed when all branches are done) JitBlock *b = js.curBlock; b->exitAddress[exit_num] = destination; b->exitPtrs[exit_num] = GetWritableCodePtr(); // Link opportunity! int block = blocks.GetBlockNumberFromStartAddress(destination); if (block >= 0 && jo.enableBlocklink) { // It exists! Joy of joy! JMP(blocks.GetBlock(block)->checkedEntry, true); b->linkStatus[exit_num] = true; } else { // No blocklinking. MOV(32, M(&mips_->pc), Imm32(destination)); JMP(asm_.dispatcher, true); } }
u32 scePsmfPlayerConfigPlayer(u32 psmfPlayer, int configMode, int configAttr) { PsmfPlayer *psmfplayer = getPsmfPlayer(psmfPlayer); if (!psmfplayer) { ERROR_LOG(HLE, "scePsmfPlayerConfigPlayer(%08x, %i, %i): invalid psmf player", psmfPlayer, configMode, configAttr); return ERROR_PSMF_NOT_FOUND; } if (configMode == PSMF_PLAYER_CONFIG_MODE_LOOP) { INFO_LOG(HLE, "scePsmfPlayerConfigPlayer(%08x, loop, %i)", psmfPlayer, configAttr); videoLoopStatus = configAttr; } else if (configMode == PSMF_PLAYER_CONFIG_MODE_PIXEL_TYPE) { INFO_LOG(HLE, "scePsmfPlayerConfigPlayer(%08x, pixelType, %i)", psmfPlayer, configAttr); // Does -1 mean default or something? if (configAttr != -1) { videoPixelMode = configAttr; } } else { ERROR_LOG_REPORT(HLE, "scePsmfPlayerConfigPlayer(%08x, %i, %i): unknown parameter", psmfPlayer, configMode, configAttr); } return 0; }
int MediaEngine::getAudioSamples(u32 bufferPtr) { if (!Memory::IsValidAddress(bufferPtr)) { ERROR_LOG_REPORT(ME, "Ignoring bad audio decode address %08x during video playback", bufferPtr); } u8 *buffer = Memory::GetPointer(bufferPtr); if (!m_demux) { return 0; } u8 *audioFrame = 0; int headerCode1, headerCode2; int frameSize = m_demux->getNextaudioFrame(&audioFrame, &headerCode1, &headerCode2); if (frameSize == 0) { m_noAudioData = true; return 0; } int outbytes = 0; if (m_audioContext != NULL) { if (!AT3Decode(m_audioContext, audioFrame, frameSize, &outbytes, buffer)) { ERROR_LOG(ME, "AT3 decode failed during video playback"); } } if (headerCode1 == 0x24) { // it a mono atrac3plus, convert it to stereo s16 *outbuf = (s16*)buffer; s16 *inbuf = (s16*)buffer; for (int i = 0x800 - 1; i >= 0; i--) { s16 sample = inbuf[i]; outbuf[i * 2] = sample; outbuf[i * 2 + 1] = sample; } } m_audiopts += 4180; m_noAudioData = false; return 0x2000; }
static u32 sceUtilityUnloadModule(u32 module) { const ModuleLoadInfo *info = __UtilityModuleInfo(module); if (!info) { ERROR_LOG_REPORT(SCEUTILITY, "sceUtilityUnloadModule(%i): invalid module id", module); return SCE_ERROR_MODULE_BAD_ID; } if (currentlyLoadedModules.find(module) == currentlyLoadedModules.end()) { WARN_LOG(SCEUTILITY, "sceUtilityUnloadModule(%i): not yet loaded", module); return SCE_ERROR_MODULE_NOT_LOADED; } if (currentlyLoadedModules[module] != 0) { userMemory.Free(currentlyLoadedModules[module]); } currentlyLoadedModules.erase(module); INFO_LOG(SCEUTILITY, "sceUtilityUnloadModule(%i)", module); // TODO: Each module has its own timing, technically, but this is a low-end. if (module == 0x3FF) return hleDelayResult(0, "utility module unloaded", 110); else return hleDelayResult(0, "utility module unloaded", 400); }
virtual void handleResult(PendingInterrupt& pend) { GeInterruptData intrdata = ge_pending_cb.front(); ge_pending_cb.pop_front(); DisplayList* dl = gpu->getList(intrdata.listid); if (!dl->interruptsEnabled) { ERROR_LOG_REPORT(SCEGE, "Unable to finish GE interrupt: list has interrupts disabled, should not happen"); return; } switch (dl->signal) { case PSP_GE_SIGNAL_HANDLER_SUSPEND: if (sceKernelGetCompiledSdkVersion() <= 0x02000010) { // uofw says dl->state = endCmd & 0xFF; DisplayListState newState = static_cast<DisplayListState>(Memory::ReadUnchecked_U32(intrdata.pc - 4) & 0xFF); //dl->status = static_cast<DisplayListStatus>(Memory::ReadUnchecked_U32(intrdata.pc) & 0xFF); //if(dl->status < 0 || dl->status > PSP_GE_LIST_PAUSED) // ERROR_LOG(SCEGE, "Weird DL status after signal suspend %x", dl->status); if (newState != PSP_GE_DL_STATE_RUNNING) DEBUG_LOG_REPORT(SCEGE, "GE Interrupt: newState might be %d", newState); if (dl->state != PSP_GE_DL_STATE_NONE && dl->state != PSP_GE_DL_STATE_COMPLETED) { dl->state = PSP_GE_DL_STATE_QUEUED; } } break; default: break; } gpu->InterruptEnd(intrdata.listid); }
u32 sceUtilityUnloadModule(u32 module) { // TODO: Not all modules between 0x100 and 0x601 are valid. if (module < 0x100 || module > 0x601) { ERROR_LOG_REPORT(SCEUTILITY, "sceUtilityUnloadModule(%i): invalid module id", module); return SCE_ERROR_MODULE_BAD_ID; } if (currentlyLoadedModules.find(module) == currentlyLoadedModules.end()) { WARN_LOG(SCEUTILITY, "sceUtilityUnloadModule(%i): not yet loaded", module); return SCE_ERROR_MODULE_NOT_LOADED; } currentlyLoadedModules.erase(module); INFO_LOG(SCEUTILITY, "sceUtilityUnloadModule(%i)", module); // TODO: Each module has its own timing, technically, but this is a low-end. // Note: If not loaded, it should not reschedule actually... if (module == 0x3FF) return hleDelayResult(0, "utility module unloaded", 110); else return hleDelayResult(0, "utility module unloaded", 400); }
static int sceKernelVolatileMemTryLock(int type, u32 paddr, u32 psize) { u32 error = __KernelVolatileMemLock(type, paddr, psize); switch (error) { case 0: // HACK: This fixes Crash Tag Team Racing. // Should only wait 1200 cycles though according to Unknown's testing, // and with that it's still broken. So it's not this, unfortunately. // Leaving it in for the 0.9.8 release anyway. hleEatCycles(500000); DEBUG_LOG(HLE, "sceKernelVolatileMemTryLock(%i, %08x, %08x) - success", type, paddr, psize); break; case SCE_KERNEL_ERROR_POWER_VMEM_IN_USE: ERROR_LOG(HLE, "sceKernelVolatileMemTryLock(%i, %08x, %08x) - already locked!", type, paddr, psize); break; default: ERROR_LOG_REPORT(HLE, "%08x=sceKernelVolatileMemTryLock(%i, %08x, %08x) - error", type, paddr, psize, error); break; } return error; }
static u32 sceUtilityLoadModule(u32 module) { const ModuleLoadInfo *info = __UtilityModuleInfo(module); if (!info) { ERROR_LOG_REPORT(SCEUTILITY, "sceUtilityLoadModule(%i): invalid module id", module); return SCE_ERROR_MODULE_BAD_ID; } if (currentlyLoadedModules.find(module) != currentlyLoadedModules.end()) { ERROR_LOG(SCEUTILITY, "sceUtilityLoadModule(%i): already loaded", module); return SCE_ERROR_MODULE_ALREADY_LOADED; } // Some games, like Kamen Rider Climax Heroes OOO, require an error if dependencies aren't loaded yet. for (const int *dep = info->dependencies; dep && *dep == 0; ++dep) { if (currentlyLoadedModules.find(*dep) == currentlyLoadedModules.end()) { ERROR_LOG(SCEUTILITY, "sceUtilityLoadModule(%i): dependent module %i not loaded", module, *dep); return hleDelayResult(SCE_KERNEL_ERROR_LIBRARY_NOTFOUND, "utility module load attempt", 25000); } } INFO_LOG(SCEUTILITY, "sceUtilityLoadModule(%i)", module); u32 allocSize = info->size; char name[64]; snprintf(name, sizeof(name), "UtilityModule/%x", module); if (allocSize != 0) { currentlyLoadedModules[module] = userMemory.Alloc(allocSize, false, name); } else { currentlyLoadedModules[module] = 0; } // TODO: Each module has its own timing, technically, but this is a low-end. if (module == 0x3FF) return hleDelayResult(0, "utility module loaded", 130); else return hleDelayResult(0, "utility module loaded", 25000); }