void CWII_IPC_HLE_WiiMote::ReceiveConnectionResponse(u8 _Ident, u8* _pData, u32 _Size) { l2cap_con_rsp_cp* rsp = (l2cap_con_rsp_cp*)_pData; _dbg_assert_(WII_IPC_WIIMOTE, _Size == sizeof(l2cap_con_rsp_cp)); INFO_LOG(WII_IPC_WIIMOTE, "[L2CAP] ReceiveConnectionResponse"); DEBUG_LOG(WII_IPC_WIIMOTE, " DCID: 0x%04x", rsp->dcid); DEBUG_LOG(WII_IPC_WIIMOTE, " SCID: 0x%04x", rsp->scid); DEBUG_LOG(WII_IPC_WIIMOTE, " Result: 0x%04x", rsp->result); DEBUG_LOG(WII_IPC_WIIMOTE, " Status: 0x%04x", rsp->status); _dbg_assert_(WII_IPC_WIIMOTE, rsp->result == L2CAP_SUCCESS); _dbg_assert_(WII_IPC_WIIMOTE, rsp->status == L2CAP_NO_INFO); _dbg_assert_(WII_IPC_WIIMOTE, DoesChannelExist(rsp->scid)); SChannel& rChannel = m_Channel[rsp->scid]; rChannel.DCID = rsp->dcid; // update state machine if (rChannel.PSM == L2CAP_PSM_HID_CNTL) m_HIDControlChannel_Connected = true; else if (rChannel.PSM == L2CAP_PSM_HID_INTR) m_HIDInterruptChannel_Connected = true; }
void CWII_IPC_HLE_WiiMote::SDPSendServiceSearchResponse(u16 cid, u16 TransactionID, u8* pServiceSearchPattern, u16 MaximumServiceRecordCount) { // verify block... we handle search pattern for HID service only { CBigEndianBuffer buffer(pServiceSearchPattern); _dbg_assert_(WII_IPC_WIIMOTE, buffer.Read8(0) == SDP_SEQ8); // data sequence _dbg_assert_(WII_IPC_WIIMOTE, buffer.Read8(1) == 0x03); // sequence size // HIDClassID _dbg_assert_(WII_IPC_WIIMOTE, buffer.Read8(2) == 0x19); _dbg_assert_(WII_IPC_WIIMOTE, buffer.Read16(3) == 0x1124); } u8 DataFrame[1000]; CBigEndianBuffer buffer(DataFrame); int Offset = 0; l2cap_hdr_t* pHeader = (l2cap_hdr_t*)&DataFrame[Offset]; Offset += sizeof(l2cap_hdr_t); pHeader->dcid = cid; buffer.Write8 (Offset, 0x03); Offset++; buffer.Write16(Offset, TransactionID); Offset += 2; // Transaction ID buffer.Write16(Offset, 0x0009); Offset += 2; // Param length buffer.Write16(Offset, 0x0001); Offset += 2; // TotalServiceRecordCount buffer.Write16(Offset, 0x0001); Offset += 2; // CurrentServiceRecordCount buffer.Write32(Offset, 0x10000); Offset += 4; // ServiceRecordHandleList[4] buffer.Write8(Offset, 0x00); Offset++; // No continuation state; pHeader->length = (u16)(Offset - sizeof(l2cap_hdr_t)); m_pHost->SendACLPacket(GetConnectionHandle(), DataFrame, pHeader->length + sizeof(l2cap_hdr_t)); }
bool DirectoryBlobReader::ReadInternal(u64 offset, u64 length, u8* buffer, const std::set<DiscContent>& contents) { if (contents.empty()) return true; // Determine which DiscContent the offset refers to std::set<DiscContent>::const_iterator it = contents.lower_bound(DiscContent(offset)); if (it->GetOffset() > offset && it != contents.begin()) --it; // zero fill to start of file data PadToAddress(it->GetOffset(), &offset, &length, &buffer); while (it != contents.end() && length > 0) { _dbg_assert_(DISCIO, it->GetOffset() <= offset); if (!it->Read(&offset, &length, &buffer)) return false; ++it; if (it != contents.end()) { _dbg_assert_(DISCIO, it->GetOffset() >= offset); PadToAddress(it->GetOffset(), &offset, &length, &buffer); } } return true; }
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 EmuWindow_GLFW::OnClientAreaResizeEvent(GLFWwindow* win, int width, int height) { _dbg_assert_(GUI, width > 0); _dbg_assert_(GUI, height > 0); // NOTE: GLFW provides no proper way to set a minimal window size. // Hence, we just ignore the corresponding EmuWindow hint. GetEmuWindow(win)->NotifyClientAreaSizeChanged(std::pair<unsigned,unsigned>(width, height)); }
void CEXIChannel::AddDevice(IEXIDevice* pDevice, const int device_num, bool notifyPresenceChanged) { _dbg_assert_(EXPANSIONINTERFACE, device_num < NUM_DEVICES); // delete the old device if (m_pDevices[device_num] != NULL) { delete m_pDevices[device_num]; m_pDevices[device_num] = NULL; } // replace it with the new one m_pDevices[device_num] = pDevice; if(notifyPresenceChanged) { // This means "device presence changed", software has to check // m_Status.EXT to see if it is now present or not if (m_ChannelId != 2) { m_Status.EXTINT = 1; UpdateInterrupts(); } } }
void CWII_IPC_HLE_WiiMote::ReceiveL2capData(u16 scid, const void* _pData, u32 _Size) { // Allocate DataFrame u8 DataFrame[1024]; u32 Offset = 0; l2cap_hdr_t* pHeader = (l2cap_hdr_t*)DataFrame; Offset += sizeof(l2cap_hdr_t); // Check if we are already reporting on this channel _dbg_assert_(WII_IPC_WIIMOTE, DoesChannelExist(scid)); SChannel& rChannel = m_Channel[scid]; // Add an additional 4 byte header to the Wiimote report pHeader->dcid = rChannel.DCID; pHeader->length = _Size; // Copy the Wiimote report to DataFrame memcpy(DataFrame + Offset, _pData, _Size); // Update Offset to the final size of the report Offset += _Size; // Update the status bar Host_SetWiiMoteConnectionState(2); // Send the report m_pHost->SendACLPacket(GetConnectionHandle(), DataFrame, Offset); }
ResultVal<Handle> HandleTable::Create(SharedPtr<Object> obj) { _dbg_assert_(Kernel, obj != nullptr); u16 slot = next_free_slot; if (slot >= generations.size()) { LOG_ERROR(Kernel, "Unable to allocate Handle, too many slots in use."); return ERR_OUT_OF_HANDLES; } next_free_slot = generations[slot]; u16 generation = next_generation++; // Overflow count so it fits in the 15 bits dedicated to the generation in the handle. // CTR-OS doesn't use generation 0, so skip straight to 1. if (next_generation >= (1 << 15)) next_generation = 1; Handle handle = generation | (slot << 15); if (obj->handle == INVALID_HANDLE) obj->handle = handle; generations[slot] = generation; objects[slot] = std::move(obj); return MakeResult<Handle>(handle); }
const u8* GetAttribPacket(u32 serviceHandle, u32 cont, u32& _size) { if (serviceHandle == 0x10000) { if (cont == 0) { _size = sizeof(packet1); return packet1; } else if (cont == 0x76) { _size = sizeof(packet2); return packet2; } else if (cont == 0xec) { _size = sizeof(packet3); return packet3; } else if (cont == 0x162) { _size = sizeof(packet4); return packet4; } } if (serviceHandle == 0x10001) { _dbg_assert_(WII_IPC_WIIMOTE, cont == 0x00); _size = sizeof(packet4_0x10001); return packet4_0x10001; } return nullptr; }
int ParseAttribList(u8* pAttribIDList, u16& _startID, u16& _endID) { u32 attribOffset = 0; CBigEndianBuffer attribList(pAttribIDList); u8 sequence = attribList.Read8(attribOffset); attribOffset++; u8 seqSize = attribList.Read8(attribOffset); attribOffset++; u8 typeID = attribList.Read8(attribOffset); attribOffset++; #if MAX_LOGLEVEL >= DEBUG_LEVEL _dbg_assert_(WII_IPC_WIIMOTE, sequence == SDP_SEQ8); (void)seqSize; #else (void)sequence, (void)seqSize; #endif if (typeID == SDP_UINT32) { _startID = attribList.Read16(attribOffset); attribOffset += 2; _endID = attribList.Read16(attribOffset); attribOffset += 2; } else { _startID = attribList.Read16(attribOffset); attribOffset += 2; _endID = _startID; DEBUG_LOG(WII_IPC_WIIMOTE, "Read just a single attrib - not tested"); PanicAlert("Read just a single attrib - not tested"); } return attribOffset; }
IVolume::ECountry CVolumeDirectory::GetCountry() const { _dbg_assert_(DVDINTERFACE, m_diskHeader); u8 CountryCode = m_diskHeader[3]; return CountrySwitch(CountryCode); }
bool RunBuffer() { // fifo is read 32 bytes at a time // read fifo data to internal buffer if (cpreg.ctrl.GPReadEnable) ReadFifo(); SetStatus(); _dbg_assert_(COMMANDPROCESSOR, writePos >= readPos); g_pVideoData = &commandBuffer[readPos]; u32 availableBytes = writePos - readPos; while (OpcodeDecoder::CommandRunnable(availableBytes)) { cpreg.status.CommandIdle = 0; OpcodeDecoder::Run(availableBytes); // if data was read by the opcode decoder then the video data pointer changed readPos = (u32)(g_pVideoData - &commandBuffer[0]); _dbg_assert_(VIDEO, writePos >= readPos); availableBytes = writePos - readPos; } cpreg.status.CommandIdle = 1; bool ranDecoder = false; // move data remaining in the command buffer if (readPos > 0) { memmove(&commandBuffer[0], &commandBuffer[readPos], availableBytes); writePos -= readPos; readPos = 0; ranDecoder = true; } return ranDecoder; }
void CVolumeDirectory::SetUniqueID(std::string _ID) { _dbg_assert_(DVDINTERFACE, m_diskHeader); u32 length = (u32)_ID.length(); if(length > 6) length = 6; memcpy(m_diskHeader, _ID.c_str(), length); }
std::string CVolumeDirectory::GetUniqueID() const { _dbg_assert_(DVDINTERFACE, m_diskHeader); char buffer[7]; memcpy(buffer, m_diskHeader, 6); buffer[6] = 0; std::string id = buffer; return id; }
void CWII_IPC_HLE_WiiMote::HandleSDP(u16 cid, u8* _pData, u32 _Size) { // Debugger::PrintDataBuffer(LogTypes::WIIMOTE, _pData, _Size, "HandleSDP: "); CBigEndianBuffer buffer(_pData); switch (buffer.Read8(0)) { // SDP_ServiceSearchRequest case 0x02: { WARN_LOG(WII_IPC_WIIMOTE, "!!! SDP_ServiceSearchRequest !!!"); _dbg_assert_(WII_IPC_WIIMOTE, _Size == 13); u16 TransactionID = buffer.Read16(1); u8* pServiceSearchPattern = buffer.GetPointer(5); u16 MaximumServiceRecordCount = buffer.Read16(10); SDPSendServiceSearchResponse(cid, TransactionID, pServiceSearchPattern, MaximumServiceRecordCount); } break; // SDP_ServiceAttributeRequest case 0x04: { WARN_LOG(WII_IPC_WIIMOTE, "!!! SDP_ServiceAttributeRequest !!!"); u16 startAttrID, endAttrID; u32 offset = 1; u16 TransactionID = buffer.Read16(offset); offset += 2; // u16 ParameterLength = buffer.Read16(offset); offset += 2; u32 ServiceHandle = buffer.Read32(offset); offset += 4; u16 MaximumAttributeByteCount = buffer.Read16(offset); offset += 2; offset += ParseAttribList(buffer.GetPointer(offset), startAttrID, endAttrID); u8* pContinuationState = buffer.GetPointer(offset); SDPSendServiceAttributeResponse(cid, TransactionID, ServiceHandle, startAttrID, endAttrID, MaximumAttributeByteCount, pContinuationState); } break; default: ERROR_LOG(WII_IPC_WIIMOTE, "WIIMOTE: Unknown SDP command %x", _pData[0]); PanicAlert("WIIMOTE: Unknown SDP command %x", _pData[0]); break; } }
int WiimoteHidapi::IOWrite(const u8* buf, size_t len) { _dbg_assert_(WIIMOTE, buf[0] == (WR_SET_REPORT | BT_OUTPUT)); int result = hid_write(m_handle, buf + 1, len - 1); if (result == -1) { ERROR_LOG(WIIMOTE, "Failed to write to %s.", m_device_path.c_str()); return 0; } return (result == 0) ? 1 : result; }
void EmuWindow_GLFW::OnMinimalClientAreaChangeRequest(const std::pair<unsigned,unsigned>& minimal_size) { std::pair<int,int> current_size; glfwGetWindowSize(m_render_window, ¤t_size.first, ¤t_size.second); _dbg_assert_(GUI, (int)minimal_size.first > 0 && (int)minimal_size.second > 0); int new_width = std::max(current_size.first, (int)minimal_size.first); int new_height = std::max(current_size.second, (int)minimal_size.second); if (current_size != std::make_pair(new_width, new_height)) glfwSetWindowSize(m_render_window, new_width, new_height); }
void CVolumeDirectory::SetName(std::string _Name) { _dbg_assert_(DVDINTERFACE, m_diskHeader); u32 length = (u32)_Name.length(); if(length > MAX_NAME_LENGTH) length = MAX_NAME_LENGTH; memcpy(m_diskHeader + 0x20, _Name.c_str(), length); m_diskHeader[length + 0x20] = 0; }
void CVolumeDirectory::SetDiskTypeWii() { _dbg_assert_(DVDINTERFACE, m_diskHeader); m_diskHeader[0x18] = 0x5d; m_diskHeader[0x19] = 0x1c; m_diskHeader[0x1a] = 0x9e; m_diskHeader[0x1b] = 0xa3; memset(m_diskHeader + 0x1c, 0, 4); m_addressShift = 2; }
void CVolumeDirectory::SetDiskTypeGC() { _dbg_assert_(DVDINTERFACE, m_diskHeader); memset(m_diskHeader + 0x18, 0, 4); m_diskHeader[0x1c] = 0xc2; m_diskHeader[0x1d] = 0x33; m_diskHeader[0x1e] = 0x9f; m_diskHeader[0x1f] = 0x3d; m_addressShift = 0; }
void CEXIAD16::TransferByte(u8& _byte) { if (m_uPosition == 0) { m_uCommand = _byte; } else { switch (m_uCommand) { case init: { m_uAD16Register.U32 = 0x04120000; switch (m_uPosition) { case 1: _dbg_assert_(EXPANSIONINTERFACE, (_byte == 0x00)); break; // just skip case 2: _byte = m_uAD16Register.U8[0]; break; case 3: _byte = m_uAD16Register.U8[1]; break; case 4: _byte = m_uAD16Register.U8[2]; break; case 5: _byte = m_uAD16Register.U8[3]; break; } } break; case write: { switch (m_uPosition) { case 1: m_uAD16Register.U8[0] = _byte; break; case 2: m_uAD16Register.U8[1] = _byte; break; case 3: m_uAD16Register.U8[2] = _byte; break; case 4: m_uAD16Register.U8[3] = _byte; break; } } break; case read: { switch (m_uPosition) { case 1: _byte = m_uAD16Register.U8[0]; break; case 2: _byte = m_uAD16Register.U8[1]; break; case 3: _byte = m_uAD16Register.U8[2]; break; case 4: _byte = m_uAD16Register.U8[3]; break; } } break; } } m_uPosition++; }
void VulkanPushBuffer::Unmap() { _dbg_assert_(G3D, writePtr_ != 0); /* // Should not need this since we use coherent memory. VkMappedMemoryRange range{ VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE }; range.offset = 0; range.size = offset_; range.memory = buffers_[buf_].deviceMemory; vkFlushMappedMemoryRanges(device_, 1, &range); */ vkUnmapMemory(device_, buffers_[buf_].deviceMemory); writePtr_ = nullptr; }
void RegisterMMIO(MMIO::Mapping* mmio, u32 base) { for (int i = 0; i < MAX_EXI_CHANNELS; ++i) { _dbg_assert_(EXPANSIONINTERFACE, g_Channels[i] != nullptr); // Each channel has 5 32 bit registers assigned to it. We offset the // base that we give to each channel for registration. // // Be careful: this means the base is no longer aligned on a page // boundary and using "base | FOO" is not valid! g_Channels[i]->RegisterMMIO(mmio, base + 5 * 4 * i); } }
void CWII_IPC_HLE_WiiMote::SendConfigurationRequest(u16 scid, u16 MTU, u16 FlushTimeOut) { _dbg_assert_(WII_IPC_WIIMOTE, DoesChannelExist(scid)); SChannel& rChannel = m_Channel[scid]; u8 Buffer[1024]; int Offset = 0; l2cap_cfg_req_cp* cr = (l2cap_cfg_req_cp*)&Buffer[Offset]; cr->dcid = rChannel.DCID; cr->flags = 0; Offset += sizeof(l2cap_cfg_req_cp); DEBUG_LOG(WII_IPC_WIIMOTE, "[L2CAP] SendConfigurationRequest"); DEBUG_LOG(WII_IPC_WIIMOTE, " Dcid: 0x%04x", cr->dcid); DEBUG_LOG(WII_IPC_WIIMOTE, " Flags: 0x%04x", cr->flags); l2cap_cfg_opt_t* pOptions; // (shuffle2) currently we end up not appending options. this is because we don't // negotiate after trying to set MTU = 0 fails (stack will respond with // "configuration failed" msg...). This is still fine, we'll just use whatever the // Bluetooth stack defaults to. if (MTU || rChannel.MTU) { if (MTU == 0) MTU = rChannel.MTU; pOptions = (l2cap_cfg_opt_t*)&Buffer[Offset]; Offset += sizeof(l2cap_cfg_opt_t); pOptions->type = L2CAP_OPT_MTU; pOptions->length = L2CAP_OPT_MTU_SIZE; *(u16*)&Buffer[Offset] = MTU; Offset += L2CAP_OPT_MTU_SIZE; DEBUG_LOG(WII_IPC_WIIMOTE, " MTU: 0x%04x", MTU); } if (FlushTimeOut || rChannel.FlushTimeOut) { if (FlushTimeOut == 0) FlushTimeOut = rChannel.FlushTimeOut; pOptions = (l2cap_cfg_opt_t*)&Buffer[Offset]; Offset += sizeof(l2cap_cfg_opt_t); pOptions->type = L2CAP_OPT_FLUSH_TIMO; pOptions->length = L2CAP_OPT_FLUSH_TIMO_SIZE; *(u16*)&Buffer[Offset] = FlushTimeOut; Offset += L2CAP_OPT_FLUSH_TIMO_SIZE; DEBUG_LOG(WII_IPC_WIIMOTE, " FlushTimeOut: 0x%04x", FlushTimeOut); } SendCommandToACL(L2CAP_CONFIG_REQ, L2CAP_CONFIG_REQ, Offset, Buffer); }
/** * Loads framebuffer from emulated memory into the active OpenGL texture. */ void RendererOpenGL::LoadFBToActiveGLTexture(const GPU::Regs::FramebufferConfig& framebuffer, const TextureInfo& texture) { const VAddr framebuffer_vaddr = Memory::PhysicalToVirtualAddress( framebuffer.active_fb == 1 ? framebuffer.address_left2 : framebuffer.address_left1); LOG_TRACE(Render_OpenGL, "0x%08x bytes from 0x%08x(%dx%d), fmt %x", framebuffer.stride * framebuffer.height, framebuffer_vaddr, (int)framebuffer.width, (int)framebuffer.height, (int)framebuffer.format); const u8* framebuffer_data = Memory::GetPointer(framebuffer_vaddr); // TODO: Handle other pixel formats _dbg_assert_msg_(Render_OpenGL, framebuffer.color_format == GPU::Regs::PixelFormat::RGB8, "Unsupported 3DS pixel format."); size_t pixel_stride = framebuffer.stride / 3; // OpenGL only supports specifying a stride in units of pixels, not bytes, unfortunately _dbg_assert_(Render_OpenGL, pixel_stride * 3 == framebuffer.stride); // Ensure no bad interactions with GL_UNPACK_ALIGNMENT, which by default // only allows rows to have a memory alignement of 4. _dbg_assert_(Render_OpenGL, pixel_stride % 4 == 0); glBindTexture(GL_TEXTURE_2D, texture.handle); glPixelStorei(GL_UNPACK_ROW_LENGTH, (GLint)pixel_stride); // Update existing texture // TODO: Test what happens on hardware when you change the framebuffer dimensions so that they // differ from the LCD resolution. // TODO: Applications could theoretically crash Citra here by specifying too large // framebuffer sizes. We should make sure that this cannot happen. glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, framebuffer.width, framebuffer.height, GL_BGR, GL_UNSIGNED_BYTE, framebuffer_data); glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); glBindTexture(GL_TEXTURE_2D, 0); }
SceUID KernelObjectPool::Create(KernelObject *obj) { for (int i=0; i<maxCount; i++) { if (!occupied[i]) { occupied[i]=true; pool[i] = obj; pool[i]->uid = i + handleOffset; return i + handleOffset; } } _dbg_assert_(HLE, 0); return 0; }
SceUID KernelObjectPool::Create(KernelObject *obj, int rangeBottom, int rangeTop) { if (rangeTop > maxCount) rangeTop = maxCount; for (int i = rangeBottom; i < rangeTop; i++) { if (!occupied[i]) { occupied[i] = true; pool[i] = obj; pool[i]->uid = i + handleOffset; return i + handleOffset; } } _dbg_assert_(HLE, 0); return 0; }
void Fifo_PauseAndLock(bool doLock, bool unpauseOnUnlock) { if (doLock) { EmulatorState(false); if (!Core::IsGPUThread()) m_csHWVidOccupied.lock(); _dbg_assert_(COMMON, !CommandProcessor::fifo.isGpuReadingData); } else { if (unpauseOnUnlock) EmulatorState(true); if (!Core::IsGPUThread()) m_csHWVidOccupied.unlock(); } }
void CEXIChannel::Read32(u32& _uReturnValue, const u32 _iRegister) { switch (_iRegister) { case EXI_STATUS: { // check if external device is present // pretty sure it is memcard only, not entirely sure if (m_ChannelId == 2) { m_Status.EXT = 0; } else { m_Status.EXT = GetDevice(1)->IsPresent() ? 1 : 0; } _uReturnValue = m_Status.Hex; break; } case EXI_DMAADDR: _uReturnValue = m_DMAMemoryAddress; break; case EXI_DMALENGTH: _uReturnValue = m_DMALength; break; case EXI_DMACONTROL: _uReturnValue = m_Control.Hex; break; case EXI_IMMDATA: _uReturnValue = m_ImmData; break; default: _dbg_assert_(EXPANSIONINTERFACE, 0); _uReturnValue = 0xDEADBEEF; } DEBUG_LOG(EXPANSIONINTERFACE, "(r32) 0x%08x channel: %i register: %s", _uReturnValue, m_ChannelId, Debug_GetRegisterName(_iRegister)); }
void CEXIChannel::AddDevice(IEXIDevice* pDevice, const int device_num, bool notifyPresenceChanged) { _dbg_assert_(EXPANSIONINTERFACE, device_num < NUM_DEVICES); // replace it with the new one m_pDevices[device_num].reset(pDevice); if(notifyPresenceChanged) { // This means "device presence changed", software has to check // m_Status.EXT to see if it is now present or not if (m_ChannelId != 2) { m_Status.EXTINT = 1; CoreTiming::ScheduleEvent_Threadsafe_Immediate(updateInterrupts, 0); } } }