void ShaderManagerVulkan::GetShaders(int prim, u32 vertType, VulkanVertexShader **vshader, VulkanFragmentShader **fshader, bool useHWTransform) { VShaderID VSID; if (gstate_c.IsDirty(DIRTY_VERTEXSHADER_STATE)) { gstate_c.Clean(DIRTY_VERTEXSHADER_STATE); ComputeVertexShaderID(&VSID, vertType, useHWTransform); } else { VSID = lastVSID_; } FShaderID FSID; if (gstate_c.IsDirty(DIRTY_FRAGMENTSHADER_STATE)) { gstate_c.Clean(DIRTY_FRAGMENTSHADER_STATE); ComputeFragmentShaderID(&FSID); } else { FSID = lastFSID_; } _dbg_assert_(G3D, FSID.Bit(FS_BIT_LMODE) == VSID.Bit(VS_BIT_LMODE)); _dbg_assert_(G3D, FSID.Bit(FS_BIT_DO_TEXTURE) == VSID.Bit(VS_BIT_DO_TEXTURE)); _dbg_assert_(G3D, FSID.Bit(FS_BIT_ENABLE_FOG) == VSID.Bit(VS_BIT_ENABLE_FOG)); _dbg_assert_(G3D, FSID.Bit(FS_BIT_FLATSHADE) == VSID.Bit(VS_BIT_FLATSHADE)); // Just update uniforms if this is the same shader as last time. if (lastVShader_ != nullptr && lastFShader_ != nullptr && VSID == lastVSID_ && FSID == lastFSID_) { *vshader = lastVShader_; *fshader = lastFShader_; _dbg_assert_msg_(G3D, (*vshader)->UseHWTransform() == useHWTransform, "Bad vshader was cached"); // Already all set, no need to look up in shader maps. return; } VulkanVertexShader *vs = vsCache_.Get(VSID); if (!vs) { // Vertex shader not in cache. Let's compile it. bool usesLighting; GenerateVulkanGLSLVertexShader(VSID, codeBuffer_, &usesLighting); vs = new VulkanVertexShader(vulkan_, VSID, codeBuffer_, vertType, useHWTransform, usesLighting); vsCache_.Insert(VSID, vs); } lastVSID_ = VSID; VulkanFragmentShader *fs = fsCache_.Get(FSID); if (!fs) { // Fragment shader not in cache. Let's compile it. GenerateVulkanGLSLFragmentShader(FSID, codeBuffer_); fs = new VulkanFragmentShader(vulkan_, FSID, codeBuffer_, useHWTransform); fsCache_.Insert(FSID, fs); } lastFSID_ = FSID; lastVShader_ = vs; lastFShader_ = fs; *vshader = vs; *fshader = fs; _dbg_assert_msg_(G3D, (*vshader)->UseHWTransform() == useHWTransform, "Bad vshader was computed"); }
void Jit::Comp_Mftv(u32 op) { CONDITIONAL_DISABLE; int imm = op & 0xFF; int rt = _RT; switch ((op >> 21) & 0x1f) { case 3: //mfv / mfvc // rt = 0, imm = 255 appears to be used as a CPU interlock by some games. if (rt != 0) { if (imm < 128) { //R(rt) = VI(imm); fpr.FlushV(imm); gpr.MapReg(rt, MAP_NOINIT | MAP_DIRTY); LDR(gpr.R(rt), CTXREG, fpr.GetMipsRegOffsetV(imm)); } else if (imm < 128 + VFPU_CTRL_MAX) { //mtvc DISABLE; // In case we have a saved prefix. //FlushPrefixV(); //gpr.BindToRegister(rt, false, true); //MOV(32, gpr.R(rt), M(¤tMIPS->vfpuCtrl[imm - 128])); } else { //ERROR - maybe need to make this value too an "interlock" value? _dbg_assert_msg_(CPU,0,"mfv - invalid register"); } } break; case 7: //mtv if (imm < 128) { gpr.FlushR(rt); fpr.MapRegV(imm, MAP_DIRTY | MAP_NOINIT); VLDR(fpr.V(imm), CTXREG, gpr.GetMipsRegOffset(rt)); } else if (imm < 128 + VFPU_CTRL_MAX) { //mtvc //currentMIPS->vfpuCtrl[imm - 128] = R(rt); DISABLE; //gpr.BindToRegister(rt, true, false); //MOV(32, M(¤tMIPS->vfpuCtrl[imm - 128]), gpr.R(rt)); // TODO: Optimization if rt is Imm? //if (imm - 128 == VFPU_CTRL_SPREFIX) { //js.prefixSFlag = JitState::PREFIX_UNKNOWN; //} else if (imm - 128 == VFPU_CTRL_TPREFIX) { // js.prefixTFlag = JitState::PREFIX_UNKNOWN; //} else if (imm - 128 == VFPU_CTRL_DPREFIX) { // js.prefixDFlag = JitState::PREFIX_UNKNOWN; //} } else { //ERROR _dbg_assert_msg_(CPU,0,"mtv - invalid register"); } break; default: DISABLE; } }
void Jit::EatInstruction(u32 op) { u32 info = MIPSGetInfo(op); _dbg_assert_msg_(JIT, !(info & DELAYSLOT), "Never eat a branch op."); _dbg_assert_msg_(JIT, !js.inDelaySlot, "Never eat an instruction inside a delayslot."); CheckJitBreakpoint(js.compilerPC + 4, 0); js.numInstructions++; js.compilerPC += 4; js.downcountAmount += MIPSGetInstructionCycleEstimate(op); }
void hleReSchedule(const char *reason) { _dbg_assert_msg_(HLE, reason != 0, "hleReSchedule: Expecting a valid reason."); _dbg_assert_msg_(HLE, reason != 0 && strlen(reason) < 256, "hleReSchedule: Not too long reason."); hleAfterSyscall |= HLE_AFTER_RESCHED; if (!reason) hleAfterSyscallReschedReason = "Invalid reason"; else hleAfterSyscallReschedReason = reason; }
void MIPSEmitter::SetJumpTarget(const FixupBranch &branch, const void *dst) { const intptr_t srcp = (intptr_t)branch.ptr; const intptr_t dstp = (intptr_t)dst; u32 *fixup = (u32 *)branch.ptr; _dbg_assert_msg_(JIT, (dstp & 3) == 0, "Destination should be aligned"); if (branch.type == BRANCH_16) { // The distance is encoded as words from the delay slot. ptrdiff_t distance = (dstp - srcp - 4) >> 2; _dbg_assert_msg_(JIT, BInRange(branch.ptr, dst), "Destination is too far away (%p -> %p)", branch.ptr, dst); *fixup = (*fixup & 0xffff0000) | (distance & 0x0000ffff); } else {
void FPURegCache::MapRegsVS(const u8 *r, VectorSize vsz, int flags) { const int n = GetNumVectorElements(vsz); _dbg_assert_msg_(JIT, jo_->enableVFPUSIMD, "Should not map simd regs when option is off."); if (!TryMapRegsVS(r, vsz, flags)) { // TODO: Could be more optimal. for (int i = 0; i < n; ++i) { StoreFromRegisterV(r[i]); } if (!TryMapRegsVS(r, vsz, flags)) { _dbg_assert_msg_(JIT, false, "MapRegsVS() failed on second try."); } } }
void ConsoleListener::LetterSpace(int Width, int Height) { _dbg_assert_msg_(COMMON, IsOpen(), "Don't call this before opening the console."); #if defined(_WIN32) && !defined(_XBOX) && !defined(__MINGW32__) // Get console info CONSOLE_SCREEN_BUFFER_INFO ConInfo; GetConsoleScreenBufferInfo(hConsole, &ConInfo); // int OldBufferWidth = ConInfo.dwSize.X; int OldBufferHeight = ConInfo.dwSize.Y; int OldScreenWidth = (ConInfo.srWindow.Right - ConInfo.srWindow.Left); int OldScreenHeight = (ConInfo.srWindow.Bottom - ConInfo.srWindow.Top); // int NewBufferWidth = Width; int NewBufferHeight = Height; int NewScreenWidth = NewBufferWidth - 1; int NewScreenHeight = OldScreenHeight; // Width BufferWidthHeight(NewBufferWidth, OldBufferHeight, NewScreenWidth, OldScreenHeight, (NewBufferWidth > OldScreenWidth-1)); // Height BufferWidthHeight(NewBufferWidth, NewBufferHeight, NewScreenWidth, NewScreenHeight, (NewBufferHeight > OldScreenHeight-1)); // Resize the window too //MoveWindow(GetConsoleWindow(), 200,200, (Width*8 + 50),(NewScreenHeight*12 + 200), true); #endif }
/* LetterSpace: SetConsoleScreenBufferSize and SetConsoleWindowInfo are dependent on each other, that's the reason for the additional checks. */ void ConsoleListener::BufferWidthHeight(int BufferWidth, int BufferHeight, int ScreenWidth, int ScreenHeight, bool BufferFirst) { _dbg_assert_msg_(COMMON, IsOpen(), "Don't call this before opening the console."); #if defined(_WIN32) && !defined(_XBOX) && !defined(__MINGW32__) BOOL SB, SW; if (BufferFirst) { // Change screen buffer size COORD Co = {BufferWidth, BufferHeight}; SB = SetConsoleScreenBufferSize(hConsole, Co); // Change the screen buffer window size SMALL_RECT coo = {0,0,ScreenWidth, ScreenHeight}; // top, left, right, bottom SW = SetConsoleWindowInfo(hConsole, TRUE, &coo); } else { // Change the screen buffer window size SMALL_RECT coo = {0,0, ScreenWidth, ScreenHeight}; // top, left, right, bottom SW = SetConsoleWindowInfo(hConsole, TRUE, &coo); // Change screen buffer size COORD Co = {BufferWidth, BufferHeight}; SB = SetConsoleScreenBufferSize(hConsole, Co); } #endif }
void Int_SVQ(u32 op) { int imm = (signed short)(op&0xFFFC); int rs = _RS; int vt = (((op >> 16) & 0x1f)) | ((op&1) << 5); u32 addr = R(rs) + imm; switch (op >> 26) { case 53: //lvl.q/lvr.q if (addr & 0x3) { _dbg_assert_msg_(CPU, 0, "Misaligned lvX.q"); } if ((op&2) == 0) { // It's an LVL float d[4]; ReadVector(d, V_Quad, vt); int offset = (addr >> 2) & 3; for (int i = 0; i < offset + 1; i++) { d[3 - i] = Memory::Read_Float(addr - i * 4); } WriteVector(d, V_Quad, vt); } else {
void __UmdBeginCallback(SceUID threadID, SceUID prevCallbackId) { SceUID pauseKey = prevCallbackId == 0 ? threadID : prevCallbackId; if (HLEKernel::VerifyWait(threadID, WAITTYPE_UMD, 1)) { // This means two callbacks in a row. PSP crashes if the same callback runs inside itself. // TODO: Handle this better? if (umdPausedWaits.find(pauseKey) != umdPausedWaits.end()) return; _dbg_assert_msg_(SCEIO, umdStatTimeoutEvent != -1, "Must have a umd timer"); s64 cyclesLeft = CoreTiming::UnscheduleEvent(umdStatTimeoutEvent, threadID); if (cyclesLeft != 0) umdPausedWaits[pauseKey] = CoreTiming::GetTicks() + cyclesLeft; else umdPausedWaits[pauseKey] = 0; HLEKernel::RemoveWaitingThread(umdWaitingThreads, threadID); DEBUG_LOG(SCEIO, "sceUmdWaitDriveStatCB: Suspending lock wait for callback"); } else WARN_LOG_REPORT(SCEIO, "sceUmdWaitDriveStatCB: beginning callback with bad wait id?"); }
std::function<void(u32, T)> InvalidWriteLambda() const { return [](u32, T) { _dbg_assert_msg_(MEMMAP, 0, "Called the write lambda on a read " "complex handler."); }; }
void Jit::Comp_Generic(MIPSOpcode op) { FlushAll(); MIPSInterpretFunc func = MIPSGetInterpretFunc(op); _dbg_assert_msg_(JIT, (MIPSGetInfo(op) & DELAYSLOT) == 0, "Cannot use interpreter for branch ops."); if (func) { MOV(32, M(&mips_->pc), Imm32(js.compilerPC)); if (USE_JIT_MISSMAP) ABI_CallFunctionC(&JitLogMiss, op.encoding); else ABI_CallFunctionC(func, op.encoding); } else ERROR_LOG_REPORT(JIT, "Trying to compile instruction %08x that can't be interpreted", op.encoding); const MIPSInfo info = MIPSGetInfo(op); if ((info & IS_VFPU) != 0 && (info & VFPU_NO_PREFIX) == 0) { // If it does eat them, it'll happen in MIPSCompileOp(). if ((info & OUT_EAT_PREFIX) == 0) js.PrefixUnknown(); } }
void Jit::FlushPrefixV() { if ((js.prefixSFlag & JitState::PREFIX_DIRTY) != 0) { MOV(32, M((void *)&mips_->vfpuCtrl[VFPU_CTRL_SPREFIX]), Imm32(js.prefixS)); js.prefixSFlag = (JitState::PrefixState) (js.prefixSFlag & ~JitState::PREFIX_DIRTY); } if ((js.prefixTFlag & JitState::PREFIX_DIRTY) != 0) { MOV(32, M((void *)&mips_->vfpuCtrl[VFPU_CTRL_TPREFIX]), Imm32(js.prefixT)); js.prefixTFlag = (JitState::PrefixState) (js.prefixTFlag & ~JitState::PREFIX_DIRTY); } if ((js.prefixDFlag & JitState::PREFIX_DIRTY) != 0) { MOV(32, M((void *)&mips_->vfpuCtrl[VFPU_CTRL_DPREFIX]), Imm32(js.prefixD)); _dbg_assert_msg_(JIT, sizeof(bool) <= 4, "Bools shouldn't be that big?"); const size_t bool_stride = 4 / sizeof(bool); for (size_t i = 0; i < ARRAY_SIZE(mips_->vfpuWriteMask); i += bool_stride) MOV(32, M((void *)&mips_->vfpuWriteMask[i]), Imm32(*(u32 *)&js.writeMask[i])); js.prefixDFlag = (JitState::PrefixState) (js.prefixDFlag & ~JitState::PREFIX_DIRTY); } }
void Reschedule(const char *reason) { #ifdef _DEBUG _dbg_assert_msg_(HLE, reason != 0 && strlen(reason) < 256, "Reschedule: Invalid or too long reason."); #endif Core::g_app_core->PrepareReschedule(); g_reschedule = true; }
void __UmdBeginCallback(SceUID threadID, SceUID prevCallbackId) { SceUID pauseKey = prevCallbackId == 0 ? threadID : prevCallbackId; u32 error; SceUID waitID = __KernelGetWaitID(threadID, WAITTYPE_UMD, error); if (waitID == 1) { // This means two callbacks in a row. PSP crashes if the same callback runs inside itself. // TODO: Handle this better? if (umdPausedWaitTimeouts.find(pauseKey) != umdPausedWaitTimeouts.end()) return; _dbg_assert_msg_(HLE, umdStatTimeoutEvent != -1, "Must have a umd timer"); s64 cyclesLeft = CoreTiming::UnscheduleEvent(umdStatTimeoutEvent, threadID); if (cyclesLeft != 0) umdPausedWaitTimeouts[pauseKey] = CoreTiming::GetTicks() + cyclesLeft; else umdPausedWaitTimeouts[pauseKey] = 0; for (auto it = umdWaitingThreads.begin(); it < umdWaitingThreads.end(); ++it) { if (threadID == threadID) umdWaitingThreads.erase(it--); } DEBUG_LOG(HLE, "sceUmdWaitDriveStatCB: Suspending lock wait for callback"); } else WARN_LOG_REPORT(HLE, "sceUmdWaitDriveStatCB: beginning callback with bad wait id?"); }
bool Get(IniFile::Section *section) { switch (type_) { case TYPE_BOOL: if (cb_.b) { default_.b = cb_.b(); } return section->Get(ini_, ptr_.b, default_.b); case TYPE_INT: if (cb_.i) { default_.i = cb_.i(); } return section->Get(ini_, ptr_.i, default_.i); case TYPE_FLOAT: if (cb_.f) { default_.f = cb_.f(); } return section->Get(ini_, ptr_.f, default_.f); case TYPE_STRING: if (cb_.s) { default_.s = cb_.s(); } return section->Get(ini_, ptr_.s, default_.s); default: _dbg_assert_msg_(LOADER, false, "Unexpected ini setting type"); return false; } }
USBHost::USBHost(Kernel& ios, const std::string& device_name) : Device(ios, device_name) { #ifdef __LIBUSB__ const int ret = libusb_init(&m_libusb_context); _dbg_assert_msg_(IOS_USB, ret == 0, "Failed to init libusb for USB passthrough."); #endif }
FixupBranch MIPSEmitter::BGTZ(MIPSReg rs, std::function<void ()> delaySlot) { // 000111 sssss xxxxx iiiiiiiiiiiiiii (fix up) _dbg_assert_msg_(JIT, rs < F_BASE, "Bad emitter arguments"); FixupBranch b = MakeFixupBranch(BRANCH_16); Write32Fields(26, 0x07, 21, rs); ApplyDelaySlot(delaySlot); return b; }
static inline FrameBufferUpdate* GetFrameBufferInfo(u32 thread_id, u32 screen_index) { _dbg_assert_msg_(GSP, screen_index < 2, "Invalid screen index"); // For each thread there are two FrameBufferUpdate fields u32 offset = 0x200 + (2 * thread_id + screen_index) * sizeof(FrameBufferUpdate); ResultVal<u8*> ptr = Kernel::GetSharedMemoryPointer(g_shared_memory, offset); return reinterpret_cast<FrameBufferUpdate*>(ptr.ValueOr(nullptr)); }
void Jit::Comp_Generic(u32 op) { FlushAll(); MIPSInterpretFunc func = MIPSGetInterpretFunc(op); _dbg_assert_msg_(JIT, (MIPSGetInfo(op) & DELAYSLOT) == 0, "Cannot use interpreter for branch ops."); if (func) { MOV(32, M(&mips_->pc), Imm32(js.compilerPC)); if (USE_JIT_MISSMAP) ABI_CallFunctionC((void *)&JitLogMiss, op); else ABI_CallFunctionC((void *)func, op); } else _dbg_assert_msg_(JIT, 0, "Trying to compile instruction that can't be interpreted"); }
FixupBranch MIPSEmitter::BNE(MIPSReg rs, MIPSReg rt, std::function<void ()> delaySlot) { // 000101 sssss ttttt iiiiiiiiiiiiiii (fix up) _dbg_assert_msg_(JIT, rs < F_BASE && rt < F_BASE, "Bad emitter arguments"); FixupBranch b = MakeFixupBranch(BRANCH_16); Write32Fields(26, 0x05, 21, rs, 16, rt); ApplyDelaySlot(delaySlot); return b; }
void __CtrlTimerUpdate(u64 userdata, int cyclesLate) { // This only runs in timer mode (ctrlCycle > 0.) _dbg_assert_msg_(SCECTRL, ctrlCycle > 0, "Ctrl: sampling cycle should be > 0"); __CtrlDoSample(); CoreTiming::ScheduleEvent(usToCycles(ctrlCycle), ctrlTimer, 0); }
std::function<T(u32)> InvalidReadLambda() const { return [](u32) { _dbg_assert_msg_(MEMMAP, 0, "Called the read lambda on a write " "complex handler."); return 0; }; }
void Jit::Comp_FPULS(MIPSOpcode op) { CONDITIONAL_DISABLE; s32 offset = _IMM16; int ft = _FT; MIPSGPReg rs = _RS; switch(op >> 26) { case 49: //FI(ft) = Memory::Read_U32(addr); break; //lwc1 { gpr.Lock(rs); fpr.SpillLock(ft); fpr.MapReg(ft, false, true); JitSafeMem safe(this, rs, offset); OpArg src; if (safe.PrepareRead(src, 4)) MOVSS(fpr.RX(ft), src); if (safe.PrepareSlowRead(&Memory::Read_U32)) { MOV(32, M(&ssLoadStoreTemp), R(EAX)); MOVSS(fpr.RX(ft), M(&ssLoadStoreTemp)); } safe.Finish(); gpr.UnlockAll(); fpr.ReleaseSpillLocks(); } break; case 57: //Memory::Write_U32(FI(ft), addr); break; //swc1 { gpr.Lock(rs); fpr.SpillLock(ft); fpr.MapReg(ft, true, false); JitSafeMem safe(this, rs, offset); OpArg dest; if (safe.PrepareWrite(dest, 4)) MOVSS(dest, fpr.RX(ft)); if (safe.PrepareSlowWrite()) { MOVSS(M(&ssLoadStoreTemp), fpr.RX(ft)); safe.DoSlowWrite(&Memory::Write_U32, M(&ssLoadStoreTemp)); } safe.Finish(); gpr.UnlockAll(); fpr.ReleaseSpillLocks(); } break; default: _dbg_assert_msg_(CPU,0,"Trying to interpret FPULS instruction that can't be interpreted"); break; } }
s32 GCMemcardDirectory::Read(u32 address, s32 length, u8 *destaddress) { s32 block = address / BLOCK_SIZE; u32 offset = address % BLOCK_SIZE; s32 extra = 0; // used for read calls that are across multiple blocks if (offset + length > BLOCK_SIZE) { extra = length + offset - BLOCK_SIZE; length -= extra; // verify that we haven't calculated a length beyond BLOCK_SIZE _dbg_assert_msg_(EXPANSIONINTERFACE, (address + length) % BLOCK_SIZE == 0, "Memcard directory Read Logic Error"); } if (m_LastBlock != block) { switch (block) { case 0: m_LastBlock = block; m_LastBlockAddress = (u8 *)&m_hdr; break; case 1: m_LastBlock = -1; m_LastBlockAddress = (u8 *)&m_dir1; break; case 2: m_LastBlock = -1; m_LastBlockAddress = (u8 *)&m_dir2; break; case 3: m_LastBlock = block; m_LastBlockAddress = (u8 *)&m_bat1; break; case 4: m_LastBlock = block; m_LastBlockAddress = (u8 *)&m_bat2; break; default: m_LastBlock = SaveAreaRW(block); if (m_LastBlock == -1) { memset(destaddress, 0xFF, length); return 0; } } } memcpy(destaddress, m_LastBlockAddress + offset, length); if (extra) extra = Read(address + length, extra, destaddress + length); return length + extra; }
void OpenGL_CreateAttributelessVAO() { glGenVertexArrays(1, &attributelessVAO); _dbg_assert_msg_(VIDEO, attributelessVAO != 0, "Attributeless VAO should have been created successfully.") // In a compatibility context, we require a valid, bound array buffer. glGenBuffers(1, &attributelessVBO); _dbg_assert_msg_(VIDEO, attributelessVBO != 0, "Attributeless VBO should have been created successfully.") // Initialize the buffer with nothing. 16 floats is an arbitrary size that may work around driver issues. glBindBuffer(GL_ARRAY_BUFFER, attributelessVBO); glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * 16, nullptr, GL_STATIC_DRAW); // We must also define vertex attribute 0. glBindVertexArray(attributelessVAO); glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, nullptr); glEnableVertexAttribArray(0); }
IPCCommandResult CWII_IPC_HLE_Device_di::IOCtlV(u32 _CommandAddress) { SIOCtlVBuffer CommandBuffer(_CommandAddress); // Prepare the out buffer(s) with zeros as a safety precaution // to avoid returning bad values for (u32 i = 0; i < CommandBuffer.NumberPayloadBuffer; i++) { Memory::Memset(CommandBuffer.PayloadBuffer[i].m_Address, 0, CommandBuffer.PayloadBuffer[i].m_Size); } u32 ReturnValue = 0; switch (CommandBuffer.Parameter) { case DVDInterface::DVDLowOpenPartition: { _dbg_assert_msg_(WII_IPC_DVD, CommandBuffer.InBuffer[1].m_Address == 0, "DVDLowOpenPartition with ticket"); _dbg_assert_msg_(WII_IPC_DVD, CommandBuffer.InBuffer[2].m_Address == 0, "DVDLowOpenPartition with cert chain"); u64 const partition_offset = ((u64)Memory::Read_U32(CommandBuffer.InBuffer[0].m_Address + 4) << 2); DVDInterface::ChangePartition(partition_offset); INFO_LOG(WII_IPC_DVD, "DVDLowOpenPartition: partition_offset 0x%016" PRIx64, partition_offset); // Read TMD to the buffer u32 tmd_size; std::unique_ptr<u8[]> tmd_buf = DVDInterface::GetVolume().GetTMD(&tmd_size); Memory::CopyToEmu(CommandBuffer.PayloadBuffer[0].m_Address, tmd_buf.get(), tmd_size); WII_IPC_HLE_Interface::ES_DIVerify(tmd_buf.get(), tmd_size); ReturnValue = 1; } break; default: ERROR_LOG(WII_IPC_DVD, "IOCtlV: %i", CommandBuffer.Parameter); _dbg_assert_msg_(WII_IPC_DVD, 0, "IOCtlV: %i", CommandBuffer.Parameter); break; } Memory::Write_U32(ReturnValue, _CommandAddress + 4); return GetDefaultReply(); }
void SimpleGLWindow::Draw(u8 *data, int w, int h, bool flipped, Format fmt) { wglMakeCurrent(hDC_, hGLRC_); GLint components = GL_RGBA; GLenum glfmt; if (fmt == FORMAT_8888) { glPixelStorei(GL_UNPACK_ALIGNMENT, 4); glfmt = GL_UNSIGNED_BYTE; } else if (fmt == FORMAT_FLOAT) { glfmt = GL_FLOAT; components = GL_RED; } else { glPixelStorei(GL_UNPACK_ALIGNMENT, 2); if (fmt == FORMAT_4444) { glfmt = GL_UNSIGNED_SHORT_4_4_4_4; } else if (fmt == FORMAT_5551) { glfmt = GL_UNSIGNED_SHORT_5_5_5_1; } else if (fmt == FORMAT_565) { glfmt = GL_UNSIGNED_SHORT_5_6_5; components = GL_RGB; } else if (fmt == FORMAT_4444_REV) { glfmt = GL_UNSIGNED_SHORT_4_4_4_4_REV; } else if (fmt == FORMAT_5551_REV) { glfmt = GL_UNSIGNED_SHORT_1_5_5_5_REV; } else if (fmt == FORMAT_565_REV) { glfmt = GL_UNSIGNED_SHORT_5_6_5_REV; components = GL_RGB; } else if (fmt == FORMAT_16BIT) { glfmt = GL_UNSIGNED_SHORT; components = GL_RED; } else if (fmt == FORMAT_8BIT) { glfmt = GL_UNSIGNED_BYTE; components = GL_RED; } else { _dbg_assert_msg_(COMMON, false, "Invalid SimpleGLWindow format."); } } glBindTexture(GL_TEXTURE_2D, tex_); glTexImage2D(GL_TEXTURE_2D, 0, components, w, h, 0, components, glfmt, data); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); // Reset offset when the texture size changes. if (tw_ != w || th_ != h) { tw_ = w; th_ = h; offsetX_ = 0; offsetY_ = 0; } tflipped_ = flipped; Redraw(); }
// TODO(yuriks): This might be what the fs:REG service is for. See the Register/Unregister calls in // http://3dbrew.org/wiki/Filesystem_services#ProgramRegistry_service_.22fs:REG.22 ResultCode CreateArchive(std::unique_ptr<FileSys::ArchiveBackend>&& backend, ArchiveIdCode id_code) { auto result = id_code_map.emplace(id_code, Common::make_unique<Archive>(std::move(backend), id_code)); bool inserted = result.second; _dbg_assert_msg_(Service_FS, inserted, "Tried to register more than one archive with same id code"); auto& archive = result.first->second; LOG_DEBUG(Service_FS, "Registered archive %s with id code 0x%08X", archive->GetName().c_str(), id_code); return RESULT_SUCCESS; }
std::vector<MbxWaitingThread>::iterator __KernelMbxFindPriority(std::vector<MbxWaitingThread> &waiting) { _dbg_assert_msg_(HLE, !waiting.empty(), "__KernelMutexFindPriority: Trying to find best of no threads."); std::vector<MbxWaitingThread>::iterator iter, end, best = waiting.end(); u32 best_prio = 0xFFFFFFFF; for (iter = waiting.begin(), end = waiting.end(); iter != end; ++iter) { u32 iter_prio = __KernelGetThreadPrio(iter->first); if (iter_prio < best_prio) { best = iter; best_prio = iter_prio; } } _dbg_assert_msg_(HLE, best != waiting.end(), "__KernelMutexFindPriority: Returning invalid best thread."); return best; }