namespace NWM { // 802.11 broadcast MAC address constexpr MacAddress BroadcastMac = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; constexpr u64 DefaultNetworkUptime = 900000000; // 15 minutes in microseconds. // Note: These values were taken from a packet capture of an o3DS XL // broadcasting a Super Smash Bros. 4 lobby. constexpr u16 DefaultExtraCapabilities = 0x0431; // Size of the SSID broadcast by an UDS beacon frame. constexpr u8 UDSBeaconSSIDSize = 8; // The maximum size of the data stored in the EncryptedData0 tag (24). constexpr u32 EncryptedDataSizeCutoff = 0xFA; /** * NWM Beacon data encryption key, taken from the NWM module code. * We stub this with an all-zeros key as that is enough for Citra's purpose. * The real key can be used here to generate beacons that will be accepted by * a real 3ds. */ constexpr std::array<u8, CryptoPP::AES::BLOCKSIZE> nwm_beacon_key = {}; /** * Generates a buffer with the fixed parameters of an 802.11 Beacon frame * using dummy values. * @returns A buffer with the fixed parameters of the beacon frame. */ std::vector<u8> GenerateFixedParameters() { std::vector<u8> buffer(sizeof(BeaconFrameHeader)); BeaconFrameHeader header{}; // Use a fixed default time for now. // TODO(Subv): Perhaps use the difference between now and the time the network was started? header.timestamp = DefaultNetworkUptime; header.beacon_interval = DefaultBeaconInterval; header.capabilities = DefaultExtraCapabilities; std::memcpy(buffer.data(), &header, sizeof(header)); return buffer; } /** * Generates an SSID tag of an 802.11 Beacon frame with an 8-byte all-zero SSID value. * @returns A buffer with the SSID tag. */ std::vector<u8> GenerateSSIDTag() { std::vector<u8> buffer(sizeof(TagHeader) + UDSBeaconSSIDSize); TagHeader tag_header{}; tag_header.tag_id = static_cast<u8>(TagId::SSID); tag_header.length = UDSBeaconSSIDSize; std::memcpy(buffer.data(), &tag_header, sizeof(TagHeader)); // The rest of the buffer is already filled with zeros. return buffer; } /** * Generates a buffer with the basic tagged parameters of an 802.11 Beacon frame * such as SSID, Rate Information, Country Information, etc. * @returns A buffer with the tagged parameters of the beacon frame. */ std::vector<u8> GenerateBasicTaggedParameters() { // Append the SSID tag std::vector<u8> buffer = GenerateSSIDTag(); // TODO(Subv): Add the SupportedRates tag. // TODO(Subv): Add the DSParameterSet tag. // TODO(Subv): Add the TrafficIndicationMap tag. // TODO(Subv): Add the CountryInformation tag. // TODO(Subv): Add the ERPInformation tag. return buffer; } /** * Generates a buffer with the Dummy Nintendo tag. * It is currently unknown what this tag does. * TODO(Subv): Figure out if this is needed and what it does. * @returns A buffer with the Nintendo tagged parameters of the beacon frame. */ std::vector<u8> GenerateNintendoDummyTag() { // Note: These values were taken from a packet capture of an o3DS XL // broadcasting a Super Smash Bros. 4 lobby. constexpr std::array<u8, 3> dummy_data = {0x0A, 0x00, 0x00}; DummyTag tag{}; tag.header.tag_id = static_cast<u8>(TagId::VendorSpecific); tag.header.length = sizeof(DummyTag) - sizeof(TagHeader); tag.oui_type = static_cast<u8>(NintendoTagId::Dummy); tag.oui = NintendoOUI; tag.data = dummy_data; std::vector<u8> buffer(sizeof(DummyTag)); std::memcpy(buffer.data(), &tag, sizeof(DummyTag)); return buffer; } /** * Generates a buffer with the Network Info Nintendo tag. * This tag contains the network information of the network that is being broadcast. * It also contains the application data provided by the application that opened the network. * @returns A buffer with the Nintendo network info parameter of the beacon frame. */ std::vector<u8> GenerateNintendoNetworkInfoTag(const NetworkInfo& network_info) { NetworkInfoTag tag{}; tag.header.tag_id = static_cast<u8>(TagId::VendorSpecific); tag.header.length = sizeof(NetworkInfoTag) - sizeof(TagHeader) + network_info.application_data_size; tag.appdata_size = network_info.application_data_size; // Set the hash to zero initially, it will be updated once we calculate it. tag.sha_hash = {}; // Ensure the network structure has the correct OUI and OUI type. ASSERT(network_info.oui_type == static_cast<u8>(NintendoTagId::NetworkInfo)); ASSERT(network_info.oui_value == NintendoOUI); // Ensure the application data size is less than the maximum value. ASSERT_MSG(network_info.application_data_size <= ApplicationDataSize, "Data size is too big."); // This tag contains the network info structure starting at the OUI. std::memcpy(tag.network_info.data(), &network_info.oui_value, tag.network_info.size()); // Copy the tag and the data so we can calculate the SHA1 over it. std::vector<u8> buffer(sizeof(tag) + network_info.application_data_size); std::memcpy(buffer.data(), &tag, sizeof(tag)); std::memcpy(buffer.data() + sizeof(tag), network_info.application_data.data(), network_info.application_data_size); // Calculate the SHA1 of the contents of the tag. std::array<u8, CryptoPP::SHA1::DIGESTSIZE> hash; CryptoPP::SHA1().CalculateDigest(hash.data(), buffer.data() + offsetof(NetworkInfoTag, network_info), buffer.size() - sizeof(TagHeader)); // Copy it directly into the buffer, overwriting the zeros that we had previously placed there. std::memcpy(buffer.data() + offsetof(NetworkInfoTag, sha_hash), hash.data(), hash.size()); return buffer; } /* * Calculates the CTR used for the AES-CTR encryption of the data stored in the * EncryptedDataTags. * @returns The CTR used for beacon crypto. */ std::array<u8, CryptoPP::AES::BLOCKSIZE> GetBeaconCryptoCTR(const NetworkInfo& network_info) { BeaconDataCryptoCTR data{}; data.host_mac = network_info.host_mac_address; data.wlan_comm_id = network_info.wlan_comm_id; data.id = network_info.id; data.network_id = network_info.network_id; std::array<u8, CryptoPP::AES::BLOCKSIZE> hash; std::memcpy(hash.data(), &data, sizeof(data)); return hash; } /* * Serializes the node information into the format needed for network transfer, * and then encrypts it with the NWM key. * @returns The serialized and encrypted node information. */ std::vector<u8> GeneratedEncryptedData(const NetworkInfo& network_info, const NodeList& nodes) { std::vector<u8> buffer(sizeof(BeaconData)); BeaconData data{}; std::memcpy(buffer.data(), &data, sizeof(BeaconData)); for (const NodeInfo& node : nodes) { // Serialize each node and convert the data from // host byte-order to Big Endian. BeaconNodeInfo info{}; info.friend_code_seed = node.friend_code_seed; info.network_node_id = node.network_node_id; for (int i = 0; i < info.username.size(); ++i) info.username[i] = node.username[i]; buffer.insert(buffer.end(), reinterpret_cast<u8*>(&info), reinterpret_cast<u8*>(&info) + sizeof(info)); } // Calculate the MD5 hash of the data in the buffer, not including the hash field. std::array<u8, CryptoPP::Weak::MD5::DIGESTSIZE> hash; CryptoPP::Weak::MD5().CalculateDigest(hash.data(), buffer.data() + offsetof(BeaconData, bitmask), buffer.size() - sizeof(data.md5_hash)); // Copy the hash into the buffer. std::memcpy(buffer.data(), hash.data(), hash.size()); // Encrypt the data using AES-CTR and the NWM beacon key. using CryptoPP::AES; std::array<u8, AES::BLOCKSIZE> counter = GetBeaconCryptoCTR(network_info); CryptoPP::CTR_Mode<AES>::Encryption aes; aes.SetKeyWithIV(nwm_beacon_key.data(), AES::BLOCKSIZE, counter.data()); aes.ProcessData(buffer.data(), buffer.data(), buffer.size()); return buffer; } void DecryptBeaconData(const NetworkInfo& network_info, std::vector<u8>& buffer) { // Decrypt the data using AES-CTR and the NWM beacon key. using CryptoPP::AES; std::array<u8, AES::BLOCKSIZE> counter = GetBeaconCryptoCTR(network_info); CryptoPP::CTR_Mode<AES>::Decryption aes; aes.SetKeyWithIV(nwm_beacon_key.data(), AES::BLOCKSIZE, counter.data()); aes.ProcessData(buffer.data(), buffer.data(), buffer.size()); } /** * Generates a buffer with the Network Info Nintendo tag. * This tag contains the first portion of the encrypted payload in the 802.11 beacon frame. * The encrypted payload contains information about the nodes currently connected to the network. * @returns A buffer with the first Nintendo encrypted data parameters of the beacon frame. */ std::vector<u8> GenerateNintendoFirstEncryptedDataTag(const NetworkInfo& network_info, const NodeList& nodes) { const size_t payload_size = std::min<size_t>(EncryptedDataSizeCutoff, nodes.size() * sizeof(NodeInfo)); EncryptedDataTag tag{}; tag.header.tag_id = static_cast<u8>(TagId::VendorSpecific); tag.header.length = static_cast<u8>(sizeof(tag) - sizeof(TagHeader) + payload_size); tag.oui_type = static_cast<u8>(NintendoTagId::EncryptedData0); tag.oui = NintendoOUI; std::vector<u8> buffer(sizeof(tag) + payload_size); std::memcpy(buffer.data(), &tag, sizeof(tag)); std::vector<u8> encrypted_data = GeneratedEncryptedData(network_info, nodes); std::memcpy(buffer.data() + sizeof(tag), encrypted_data.data(), payload_size); return buffer; } /** * Generates a buffer with the Network Info Nintendo tag. * This tag contains the second portion of the encrypted payload in the 802.11 beacon frame. * The encrypted payload contains information about the nodes currently connected to the network. * This tag is only present if the payload size is greater than EncryptedDataSizeCutoff (0xFA) * bytes. * @returns A buffer with the second Nintendo encrypted data parameters of the beacon frame. */ std::vector<u8> GenerateNintendoSecondEncryptedDataTag(const NetworkInfo& network_info, const NodeList& nodes) { // This tag is only present if the payload is larger than EncryptedDataSizeCutoff (0xFA). if (nodes.size() * sizeof(NodeInfo) <= EncryptedDataSizeCutoff) return {}; const size_t payload_size = nodes.size() * sizeof(NodeInfo) - EncryptedDataSizeCutoff; const size_t tag_length = sizeof(EncryptedDataTag) - sizeof(TagHeader) + payload_size; // TODO(Subv): What does the 3DS do when a game has too much data to fit into the tag? ASSERT_MSG(tag_length <= 255, "Data is too big."); EncryptedDataTag tag{}; tag.header.tag_id = static_cast<u8>(TagId::VendorSpecific); tag.header.length = static_cast<u8>(tag_length); tag.oui_type = static_cast<u8>(NintendoTagId::EncryptedData1); tag.oui = NintendoOUI; std::vector<u8> buffer(sizeof(tag) + payload_size); std::memcpy(buffer.data(), &tag, sizeof(tag)); std::vector<u8> encrypted_data = GeneratedEncryptedData(network_info, nodes); std::memcpy(buffer.data() + sizeof(tag), encrypted_data.data() + EncryptedDataSizeCutoff, payload_size); return buffer; } /** * Generates a buffer with the Nintendo tagged parameters of an 802.11 Beacon frame * for UDS communication. * @returns A buffer with the Nintendo tagged parameters of the beacon frame. */ std::vector<u8> GenerateNintendoTaggedParameters(const NetworkInfo& network_info, const NodeList& nodes) { ASSERT_MSG(network_info.max_nodes == nodes.size(), "Inconsistent network state."); std::vector<u8> buffer = GenerateNintendoDummyTag(); std::vector<u8> network_info_tag = GenerateNintendoNetworkInfoTag(network_info); std::vector<u8> first_data_tag = GenerateNintendoFirstEncryptedDataTag(network_info, nodes); std::vector<u8> second_data_tag = GenerateNintendoSecondEncryptedDataTag(network_info, nodes); buffer.insert(buffer.end(), network_info_tag.begin(), network_info_tag.end()); buffer.insert(buffer.end(), first_data_tag.begin(), first_data_tag.end()); buffer.insert(buffer.end(), second_data_tag.begin(), second_data_tag.end()); return buffer; } std::vector<u8> GenerateBeaconFrame(const NetworkInfo& network_info, const NodeList& nodes) { std::vector<u8> buffer = GenerateFixedParameters(); std::vector<u8> basic_tags = GenerateBasicTaggedParameters(); std::vector<u8> nintendo_tags = GenerateNintendoTaggedParameters(network_info, nodes); buffer.insert(buffer.end(), basic_tags.begin(), basic_tags.end()); buffer.insert(buffer.end(), nintendo_tags.begin(), nintendo_tags.end()); return buffer; } } // namespace NWM
LRESULT COption::ExtractProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp) { static CFolderDialog FolderDlg; static SOption* pOption = &m_option_tmp; // Extraction Settings static constexpr std::array<LPCTSTR, 3> ExtractCheckText{{ _T("Extract each folder"), _T("Fix the CRC of OGG files upon extraction"), _T("Enable simple decoding") }}; static const std::array<BOOL*, 4> ExtractCheckFlag{{ &pOption->bCreateFolder, &pOption->bFixOgg, &pOption->bEasyDecrypt, &pOption->bRenameScriptExt }}; static std::array<CCheckBox, ExtractCheckText.size()> ExtractCheck; static CCheckBox ExtractCheckAlpha; static CLabel ExtractLabelPng, ExtractLabelAlpha, ExtractLabelBuf, ExtractLabelTmp; static CRadioBtn ExtractRadioImage, ExtractRadioSave; static CUpDown ExtractUpDownPng; static CEditBox ExtractEditPng, ExtractEditAlpha, ExtractEditSave, ExtractEditBuf, ExtractEditTmp; static CButton ExtractBtnSave, ExtractBtnTmp; static CGroupBox ExtractGroupImage, ExtractGroupSave; switch (msg) { case WM_INITDIALOG: { UINT ID = 10000; const int x = 10; const int xx = 15; int y = 0; // Extraction Settings for (size_t i = 0; i < ExtractCheckText.size(); i++) { ExtractCheck[i].Create(hWnd, ExtractCheckText[i], ID++, x, y += 20, 230, 20); ExtractCheck[i].SetCheck(*ExtractCheckFlag[i]); } // int y_image = y; ExtractGroupImage.Create(hWnd, _T("Output image format"), ID++, x, y_image += 34, 240, 110); ExtractRadioImage.Close(); ExtractRadioImage.Create(hWnd, _T("BMP"), ID++, x + xx, y_image += 18, 50, 20); ExtractRadioImage.Create(hWnd, _T("PNG"), ID++, x + xx, y_image += 20, 50, 20); ExtractRadioImage.SetCheck(0, pOption->bDstBMP); ExtractRadioImage.SetCheck(1, pOption->bDstPNG); ExtractLabelPng.Create(hWnd, _T("Compression Level"), ID++, x + xx + 50, y_image + 3, 100, 20); ExtractEditPng.Create(hWnd, _T(""), ID++, x + xx + 150, y_image, 40, 22); ExtractEditPng.SetLimit(1); ExtractUpDownPng.Create(hWnd, ExtractEditPng.GetCtrlHandle(), pOption->CmplvPng, ID++, 9, 0); // ExtractCheckAlpha.Create(hWnd, _T("Enable alpha blending"), ID++, x + xx, y_image += 22, 140, 20); ExtractCheckAlpha.SetCheck(pOption->bAlphaBlend); ExtractLabelAlpha.Create(hWnd, _T("Background color"), ID++, x + xx * 2 + 4, y_image += 24, 100, 20); ExtractEditAlpha.Create(hWnd, pOption->szBgRGB, ID++, x + xx * 2 + 100, y_image - 4, 100, 22); ExtractEditAlpha.SetLimit(6); ExtractEditAlpha.Enable(pOption->bAlphaBlend); // const int x_save = x + 200; int y_save = y; ExtractGroupSave.Create(hWnd, _T("Destination"), ID++, x_save + 50, y_save += 34, 290, 110); ExtractRadioSave.Close(); ExtractRadioSave.Create(hWnd, _T("Specify each time"), ID++, x_save + xx + 50, y_save += 18, 220, 20); ExtractRadioSave.Create(hWnd, _T("Same folder as input source"), ID++, x_save + xx + 50, y_save += 20, 200, 20); ExtractRadioSave.Create(hWnd, _T("The following folder"), ID++, x_save + xx + 50, y_save += 20, 200, 20); ExtractRadioSave.SetCheck(0, pOption->bSaveSel); ExtractRadioSave.SetCheck(1, pOption->bSaveSrc); ExtractRadioSave.SetCheck(2, pOption->bSaveDir); ExtractEditSave.Create(hWnd, pOption->SaveDir, ID++, x_save + xx * 2 + 40, y_save += 20, 200, 22); ExtractEditSave.Enable(pOption->bSaveDir); ExtractBtnSave.Create(hWnd, _T("Browse"), ID++, x_save + xx * 2 + 250, y_save + 1, 50, 20); ExtractBtnSave.Enable(pOption->bSaveDir); // y = (y_image > y_save) ? y_image : y_save; ExtractLabelBuf.Create(hWnd, _T("Buffer Size(KB)"), ID++, x, y += 44, 100, 20); ExtractEditBuf.Create(hWnd, pOption->BufSize, ID++, x + 100, y - 4, 110, 22); // ExtractLabelTmp.Create(hWnd, _T("Temporary Folder"), ID++, x, y += 24, 100, 20); ExtractEditTmp.Create(hWnd, pOption->TmpDir, ID++, x + 100, y - 4, 200, 22); ExtractBtnTmp.Create(hWnd, _T("Browse"), ID++, x + 310, y - 3, 50, 20); break; } case WM_COMMAND: // Checkbox if (LOWORD(wp) >= ExtractCheck.front().GetID() && LOWORD(wp) <= ExtractCheck.back().GetID()) { PropSheet_Changed(::GetParent(hWnd), hWnd); break; } // Alpha blend check box if (LOWORD(wp) == ExtractCheckAlpha.GetID()) { ExtractEditAlpha.Enable(ExtractCheckAlpha.GetCheck()); PropSheet_Changed(::GetParent(hWnd), hWnd); break; } //Output image format radio button if (LOWORD(wp) >= ExtractRadioImage.GetID(0) && LOWORD(wp) <= ExtractRadioImage.GetID(1)) { PropSheet_Changed(::GetParent(hWnd), hWnd); break; } // Destination radio button if (LOWORD(wp) >= ExtractRadioSave.GetID(0) && LOWORD(wp) <= ExtractRadioSave.GetID(2)) { ExtractEditSave.Enable(ExtractRadioSave.GetCheck(2)); ExtractBtnSave.Enable(ExtractRadioSave.GetCheck(2)); PropSheet_Changed(::GetParent(hWnd), hWnd); break; } // Output folder browse if (LOWORD(wp) == ExtractBtnSave.GetID()) { TCHAR szSaveDir[_MAX_DIR]; ExtractEditSave.GetText(szSaveDir, sizeof(szSaveDir)); if (FolderDlg.DoModal(hWnd, _T("Select the output folder"), szSaveDir)) ExtractEditSave.SetText(szSaveDir); break; } // Temporary folder browse if (LOWORD(wp) == ExtractBtnTmp.GetID()) { TCHAR szTmpDir[_MAX_DIR]; ExtractEditTmp.GetText(szTmpDir, sizeof(szTmpDir)); if (FolderDlg.DoModal(hWnd, _T("Select a temporary folder"), szTmpDir)) ExtractEditTmp.SetText(szTmpDir); break; } // Contents of the edit box have been changed if (HIWORD(wp) == EN_CHANGE) { PropSheet_Changed(::GetParent(hWnd), hWnd); break; } break; case WM_NOTIFY: { const auto* const hdr = reinterpret_cast<LPNMHDR>(lp); switch (hdr->code) { // OK/Apply, Tabbing case PSN_APPLY: case PSN_KILLACTIVE: // Extraction Settings for (size_t i = 0; i < ExtractCheck.size(); i++) *ExtractCheckFlag[i] = ExtractCheck[i].GetCheck(); // pOption->bDstBMP = ExtractRadioImage.GetCheck(0); pOption->bDstPNG = ExtractRadioImage.GetCheck(1); ExtractEditPng.GetText(&pOption->CmplvPng, FALSE); // pOption->bAlphaBlend = ExtractCheckAlpha.GetCheck(); ExtractEditAlpha.GetText(&pOption->BgRGB, TRUE); _stprintf(pOption->szBgRGB, _T("%06x"), pOption->BgRGB); // pOption->bSaveSel = ExtractRadioSave.GetCheck(0); pOption->bSaveSrc = ExtractRadioSave.GetCheck(1); pOption->bSaveDir = ExtractRadioSave.GetCheck(2); ExtractEditSave.GetText(pOption->SaveDir); // ExtractEditBuf.GetText(&pOption->BufSize, FALSE); // ExtractEditTmp.GetText(pOption->TmpDir); // OK/Apply if (hdr->code == PSN_APPLY) Apply(); return TRUE; } break; } } return FALSE; }
[[nodiscard]] std::array<char16, 2>::const_iterator begin() const noexcept { return m_buffer.begin(); }
int nbDims(std::array<T, N> const& p) { return p.size(); }
namespace coreinit { be_wfunc_ptr<void*, uint32_t>* pMEMAllocFromDefaultHeap; be_wfunc_ptr<void*, uint32_t, int>* pMEMAllocFromDefaultHeapEx; be_wfunc_ptr<void, void*>* pMEMFreeToDefaultHeap; static std::array<CommonHeap *, MEMBaseHeapType::Max> sMemArenas; static ExpandedHeap * sSystemHeap = nullptr; static MemoryList * sForegroundMemlist = nullptr; static MemoryList * sMEM1Memlist = nullptr; static MemoryList * sMEM2Memlist = nullptr; static MemoryList * findListContainingHeap(CommonHeap *heap) { be_val<uint32_t> start, size, end; OSGetForegroundBucket(&start, &size); end = start + size; if (heap->dataStart >= start && heap->dataEnd <= end) { return sForegroundMemlist; } else { OSGetMemBound(OSMemoryType::MEM1, &start, &size); end = start + size; if (heap->dataStart >= start && heap->dataEnd <= end) { return sMEM1Memlist; } else { return sMEM2Memlist; } } } static MemoryList * findListContainingBlock(void *block) { be_val<uint32_t> start, size, end; uint32_t addr = memory_untranslate(block); OSGetForegroundBucket(&start, &size); end = start + size; if (addr >= start && addr <= end) { return sForegroundMemlist; } else { OSGetMemBound(OSMemoryType::MEM1, &start, &size); end = start + size; if (addr >= start && addr <= end) { return sMEM1Memlist; } else { return sMEM2Memlist; } } } static CommonHeap * findHeapContainingBlock(MemoryList *list, void *block) { CommonHeap *heap = nullptr; uint32_t addr = memory_untranslate(block); while ((heap = reinterpret_cast<CommonHeap*>(MEMGetNextListObject(list, heap)))) { if (addr >= heap->dataStart && addr < heap->dataEnd) { auto child = findHeapContainingBlock(&heap->list, block); return child ? child : heap; } } return nullptr; } void MEMiInitHeapHead(CommonHeap *heap, MEMiHeapTag tag, uint32_t dataStart, uint32_t dataEnd) { heap->tag = tag; MEMInitList(&heap->list, offsetof(CommonHeap, link)); heap->dataStart = dataStart; heap->dataEnd = dataEnd; OSInitSpinLock(&heap->lock); heap->flags = 0; if (auto list = findListContainingHeap(heap)) { MEMAppendListObject(list, heap); } } void MEMiFinaliseHeap(CommonHeap *heap) { if (auto list = findListContainingHeap(heap)) { MEMRemoveListObject(list, heap); } } void MEMDumpHeap(CommonHeap *heap) { switch (heap->tag) { case MEMiHeapTag::ExpandedHeap: MEMiDumpExpHeap(reinterpret_cast<ExpandedHeap*>(heap)); break; case MEMiHeapTag::UnitHeap: MEMiDumpUnitHeap(reinterpret_cast<UnitHeap*>(heap)); break; case MEMiHeapTag::FrameHeap: case MEMiHeapTag::UserHeap: case MEMiHeapTag::BlockHeap: gLog->info("Unimplemented MEMDumpHeap type"); } } CommonHeap * MEMFindContainHeap(void *block) { if (auto list = findListContainingBlock(block)) { return findHeapContainingBlock(list, block); } return nullptr; } MEMBaseHeapType MEMGetArena(CommonHeap *heap) { for (auto i = 0u; i < sMemArenas.size(); ++i) { if (sMemArenas[i] == heap) { return static_cast<MEMBaseHeapType>(i); } } return MEMBaseHeapType::Invalid; } CommonHeap * MEMGetBaseHeapHandle(MEMBaseHeapType type) { if (type < sMemArenas.size()) { return sMemArenas[type]; } else { return nullptr; } } CommonHeap * MEMSetBaseHeapHandle(MEMBaseHeapType type, CommonHeap *heap) { if (type < sMemArenas.size()) { auto previous = sMemArenas[type]; sMemArenas[type] = heap; return previous; } else { return nullptr; } } // TODO: Move to coreinit::internal void CoreInitDefaultHeap() { be_val<uint32_t> addr, size; // Create expanding heap for MEM2 OSGetMemBound(OSMemoryType::MEM2, &addr, &size); auto mem2 = MEMCreateExpHeap(make_virtual_ptr<ExpandedHeap>(addr), size); MEMSetBaseHeapHandle(MEMBaseHeapType::MEM2, reinterpret_cast<CommonHeap*>(mem2)); // Create frame heap for MEM1 OSGetMemBound(OSMemoryType::MEM1, &addr, &size); auto mem1 = MEMCreateFrmHeap(make_virtual_ptr<FrameHeap>(addr), size); MEMSetBaseHeapHandle(MEMBaseHeapType::MEM1, reinterpret_cast<CommonHeap*>(mem1)); // Create frame heap for Foreground OSGetForegroundBucketFreeArea(&addr, &size); auto fg = MEMCreateFrmHeap(make_virtual_ptr<FrameHeap>(addr), size); MEMSetBaseHeapHandle(MEMBaseHeapType::FG, reinterpret_cast<CommonHeap*>(fg)); } // TODO: Move to coreinit::internal void CoreFreeDefaultHeap() { // Delete all base heaps for (auto i = 0u; i < MEMBaseHeapType::Max; ++i) { if (sMemArenas[i]) { auto heap = reinterpret_cast<CommonHeap*>(sMemArenas[i]); switch (heap->tag) { case MEMiHeapTag::ExpandedHeap: MEMDestroyExpHeap(reinterpret_cast<ExpandedHeap*>(heap)); break; case MEMiHeapTag::FrameHeap: MEMDestroyFrmHeap(reinterpret_cast<FrameHeap*>(heap)); break; case MEMiHeapTag::UnitHeap: case MEMiHeapTag::UserHeap: case MEMiHeapTag::BlockHeap: default: assert(false); } sMemArenas[i] = nullptr; } } // Delete system heap MEMDestroyExpHeap(sSystemHeap); sSystemHeap = nullptr; // Free function pointers if (pMEMAllocFromDefaultHeap) { coreinit::internal::sysFree(pMEMAllocFromDefaultHeap); pMEMAllocFromDefaultHeap = nullptr; } if (pMEMAllocFromDefaultHeapEx) { coreinit::internal::sysFree(pMEMAllocFromDefaultHeap); pMEMAllocFromDefaultHeap = nullptr; } if (pMEMFreeToDefaultHeap) { coreinit::internal::sysFree(pMEMAllocFromDefaultHeap); pMEMAllocFromDefaultHeap = nullptr; } } void Module::registerMembaseFunctions() { sMemArenas.fill(nullptr); RegisterKernelFunction(MEMGetBaseHeapHandle); RegisterKernelFunction(MEMSetBaseHeapHandle); RegisterKernelFunction(MEMGetArena); RegisterKernelDataName("MEMAllocFromDefaultHeap", pMEMAllocFromDefaultHeap); RegisterKernelDataName("MEMAllocFromDefaultHeapEx", pMEMAllocFromDefaultHeapEx); RegisterKernelDataName("MEMFreeToDefaultHeap", pMEMFreeToDefaultHeap); RegisterKernelFunction(MEMiInitHeapHead); RegisterKernelFunction(MEMiFinaliseHeap); RegisterKernelFunction(MEMFindContainHeap); RegisterKernelFunction(MEMDumpHeap); // These are default implementations for function pointers, register as exports // so we will have function thunks generated RegisterKernelFunctionName("internal_defaultAlloc", coreinit::internal::defaultAllocFromDefaultHeap); RegisterKernelFunctionName("internal_defaultAllocEx", coreinit::internal::defaultAllocFromDefaultHeapEx); RegisterKernelFunctionName("internal_defaultFree", coreinit::internal::defaultFreeToDefaultHeap); } void Module::initialiseMembase() { sSystemHeap = nullptr; sMemArenas.fill(nullptr); sForegroundMemlist = coreinit::internal::sysAlloc<MemoryList>(); MEMInitList(sForegroundMemlist, offsetof(CommonHeap, link)); sMEM1Memlist = coreinit::internal::sysAlloc<MemoryList>(); MEMInitList(sMEM1Memlist, offsetof(CommonHeap, link)); sMEM2Memlist = coreinit::internal::sysAlloc<MemoryList>(); MEMInitList(sMEM2Memlist, offsetof(CommonHeap, link)); CoreInitDefaultHeap(); *pMEMAllocFromDefaultHeap = findExportAddress("internal_defaultAlloc"); *pMEMAllocFromDefaultHeapEx = findExportAddress("internal_defaultAllocEx"); *pMEMFreeToDefaultHeap = findExportAddress("internal_defaultFree"); } namespace internal { void * sysAlloc(size_t size, int alignment) { auto systemHeap = gSystem.getSystemHeap(); return systemHeap->alloc(size, alignment); } void sysFree(void *addr) { auto systemHeap = gSystem.getSystemHeap(); return systemHeap->free(addr); } char * sysStrDup(const std::string &src) { auto buffer = reinterpret_cast<char *>(coreinit::internal::sysAlloc(src.size() + 1, 4)); std::memcpy(buffer, src.data(), src.size()); buffer[src.size()] = 0; return buffer; } void * defaultAllocFromDefaultHeap(uint32_t size) { auto heap = MEMGetBaseHeapHandle(MEMBaseHeapType::MEM2); return MEMAllocFromExpHeap(reinterpret_cast<ExpandedHeap*>(heap), size); } void * defaultAllocFromDefaultHeapEx(uint32_t size, int alignment) { auto heap = MEMGetBaseHeapHandle(MEMBaseHeapType::MEM2); return MEMAllocFromExpHeapEx(reinterpret_cast<ExpandedHeap*>(heap), size, alignment); } void defaultFreeToDefaultHeap(void *block) { auto heap = MEMGetBaseHeapHandle(MEMBaseHeapType::MEM2); return MEMFreeToExpHeap(reinterpret_cast<ExpandedHeap*>(heap), reinterpret_cast<uint8_t *>(block)); } } // namespace internal } // namespace coreinit
const char* PatchTypeAsString(PatchType type) { return s_patch_type_strings.at(static_cast<int>(type)); }
static void Serialize(const std::array<T, N>& x, Archive& ar) { for (typename std::array<T, N>::const_iterator it = x.begin(); it != x.end(); ++it) Serialization<Archive, T>::Serialize(*it, ar); }
static inline bool IsNo31Month(const int Month) { static const std::array<int, 5> No31Month = { 2, 4, 6, 9, 11 }; return std::any_of(No31Month.begin(), No31Month.end(), [Month](const int i) { return Month == i; }); }
bool cMap::UpdatePixel(unsigned int a_X, unsigned int a_Z) { int BlockX = m_CenterX + static_cast<int>((a_X - m_Width / 2) * GetPixelWidth()); int BlockZ = m_CenterZ + static_cast<int>((a_Z - m_Height / 2) * GetPixelWidth()); int ChunkX, ChunkZ; cChunkDef::BlockToChunk(BlockX, BlockZ, ChunkX, ChunkZ); int RelX = BlockX - (ChunkX * cChunkDef::Width); int RelZ = BlockZ - (ChunkZ * cChunkDef::Width); ASSERT(m_World != nullptr); ColorID PixelData; m_World->DoWithChunk(ChunkX, ChunkZ, [&](cChunk & a_Chunk) { if (!a_Chunk.IsValid()) { return false; } if (GetDimension() == dimNether) { // TODO 2014-02-22 xdot: Nether maps return false; } static const std::array<unsigned char, 4> BrightnessID = { { 3, 0, 1, 2 } }; // Darkest to lightest BLOCKTYPE TargetBlock; NIBBLETYPE TargetMeta; auto Height = a_Chunk.GetHeight(RelX, RelZ); auto ChunkHeight = cChunkDef::Height; a_Chunk.GetBlockTypeMeta(RelX, Height, RelZ, TargetBlock, TargetMeta); auto ColourID = BlockHandler(TargetBlock)->GetMapBaseColourID(TargetMeta); if (IsBlockWater(TargetBlock)) { ChunkHeight /= 4; while (((--Height) != -1) && IsBlockWater(a_Chunk.GetBlock(RelX, Height, RelZ))) { continue; } } else if (ColourID == 0) { while (((--Height) != -1) && ((ColourID = BlockHandler(a_Chunk.GetBlock(RelX, Height, RelZ))->GetMapBaseColourID(a_Chunk.GetMeta(RelX, Height, RelZ))) == 0)) { continue; } } // Multiply base color ID by 4 and add brightness ID const int BrightnessIDSize = static_cast<int>(BrightnessID.size()); PixelData = ColourID * 4 + BrightnessID[static_cast<size_t>(Clamp<int>((BrightnessIDSize * Height) / ChunkHeight, 0, BrightnessIDSize - 1))]; return false; } ); SetPixel(a_X, a_Z, PixelData); return true; }
std::shared_ptr<AVStream> open_encoder( const AVCodec& codec, std::map<std::string, std::string>& options) { auto st = avformat_new_stream( oc_.get(), &codec); if (!st) BOOST_THROW_EXCEPTION(caspar_exception() << msg_info("Could not allocate video-stream.") << boost::errinfo_api_function("av_new_stream")); auto enc = st->codec; CASPAR_VERIFY(enc); switch(enc->codec_type) { case AVMEDIA_TYPE_VIDEO: { enc->time_base = video_graph_out_->inputs[0]->time_base; enc->pix_fmt = static_cast<AVPixelFormat>(video_graph_out_->inputs[0]->format); enc->sample_aspect_ratio = st->sample_aspect_ratio = video_graph_out_->inputs[0]->sample_aspect_ratio; enc->width = video_graph_out_->inputs[0]->w; enc->height = video_graph_out_->inputs[0]->h; break; } case AVMEDIA_TYPE_AUDIO: { enc->time_base = audio_graph_out_->inputs[0]->time_base; enc->sample_fmt = static_cast<AVSampleFormat>(audio_graph_out_->inputs[0]->format); enc->sample_rate = audio_graph_out_->inputs[0]->sample_rate; enc->channel_layout = audio_graph_out_->inputs[0]->channel_layout; enc->channels = audio_graph_out_->inputs[0]->channels; break; } } if(oc_->oformat->flags & AVFMT_GLOBALHEADER) enc->flags |= CODEC_FLAG_GLOBAL_HEADER; static const std::array<std::string, 4> char_id_map = {{"v", "a", "d", "s"}}; const auto char_id = char_id_map.at(enc->codec_type); const auto codec_opts = remove_options( options, boost::regex("^(" + char_id + "?[^:]+):" + char_id + "$")); AVDictionary* av_codec_opts = nullptr; to_dict( &av_codec_opts, options); to_dict( &av_codec_opts, codec_opts); options.clear(); FF(avcodec_open2( enc, &codec, av_codec_opts ? &av_codec_opts : nullptr)); if(av_codec_opts) { auto t = av_dict_get( av_codec_opts, "", nullptr, AV_DICT_IGNORE_SUFFIX); while(t) { options[t->key + (codec_opts.find(t->key) != codec_opts.end() ? ":" + char_id : "")] = t->value; t = av_dict_get( av_codec_opts, "", t, AV_DICT_IGNORE_SUFFIX); } av_dict_free(&av_codec_opts); } if(enc->codec_type == AVMEDIA_TYPE_AUDIO && !(codec.capabilities & CODEC_CAP_VARIABLE_FRAME_SIZE)) { CASPAR_ASSERT(enc->frame_size > 0); av_buffersink_set_frame_size(audio_graph_out_, enc->frame_size); } return std::shared_ptr<AVStream>(st, [this](AVStream* st) { avcodec_close(st->codec); }); }
#include <Nazara/Core/Serialization.hpp> #include <Nazara/Core/Color.hpp> #include <Nazara/Core/MemoryView.hpp> #include <Nazara/Math/BoundingVolume.hpp> #include <Nazara/Math/Frustum.hpp> #include <Nazara/Math/Ray.hpp> #include <array> #include <Catch/catch.hpp> SCENARIO("Serialization", "[CORE][SERIALIZATION]") { GIVEN("A context of serialization") { std::array<char, 256> datas; // The array must be bigger than any of the serializable classes Nz::MemoryView stream(datas.data(), datas.size()); Nz::SerializationContext context; context.stream = &stream; WHEN("We serialize basic types") { THEN("Arithmetical types") { context.stream->SetCursorPos(0); REQUIRE(Serialize(context, 3)); int value = 0; context.stream->SetCursorPos(0); REQUIRE(Unserialize(context, &value)); REQUIRE(value == 3);
#include <kernel/session/win32_session.h> #include <thread> #include <future> #pragma warning(disable:4996) namespace kernel { ::std::shared_ptr<win32_session> win32_session::handshake(life_stream raw_stream, session_id_t sid) throw(...) { ::std::array<unsigned char, 512> pipe_name; pipe_name.fill(0); sprintf((char*)(pipe_name.data()), "opennui_pipe_%d", sid); auto stream_pair = _message_stream_connection(raw_stream, (char*)pipe_name.data()); win32_message_stream& cts_stream = stream_pair.first; win32_message_stream& stc_stream = stream_pair.second; ::std::shared_ptr<win32_session> session = ::std::make_shared<win32_session>(); session->_life_stream = std::move(raw_stream); session->_cts_stream = std::move(cts_stream); session->_stc_stream = std::move(stc_stream); session->_session_id = sid; return session; } win32_session::session_id_t win32_session::get_id() const { return _session_id; } win32_session::life_stream win32_session::get_life_stream() {
TrieNode() : nearest_leaf{nullptr}, nearest_leaf_distance{INFu}, ids{nullptr} { children.fill(nullptr); }
int APIENTRY WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { int argc = __argc; char **argv = __argv; #else int main(int argc, char *argv[]) { #endif int seed = time(NULL); bool verifyexit = false; bool check_mods = false; std::string dump; dump_mode dmode = dump_mode::TSV; std::vector<std::string> opts; std::string world; /** if set try to load first save in this world on startup */ // Set default file paths #ifdef PREFIX #define Q(STR) #STR #define QUOTE(STR) Q(STR) PATH_INFO::init_base_path(std::string(QUOTE(PREFIX))); #else PATH_INFO::init_base_path(""); #endif #if (defined USE_HOME_DIR || defined USE_XDG_DIR) PATH_INFO::init_user_dir(); #else PATH_INFO::init_user_dir("./"); #endif PATH_INFO::set_standard_filenames(); MAP_SHARING::setDefaults(); { const char *section_default = nullptr; const char *section_map_sharing = "Map sharing"; const char *section_user_directory = "User directories"; const std::array<arg_handler, 12> first_pass_arguments = {{ { "--seed", "<string of letters and or numbers>", "Sets the random number generator's seed value", section_default, [&seed](int num_args, const char **params) -> int { if (num_args < 1) return -1; const unsigned char *hash_input = (const unsigned char *) params[0]; seed = djb2_hash(hash_input); return 1; } }, { "--jsonverify", nullptr, "Checks the cdda json files", section_default, [&verifyexit](int, const char **) -> int { verifyexit = true; return 0; } }, { "--check-mods", "[mods...]", "Checks the json files belonging to cdda mods", section_default, [&check_mods,&opts]( int n, const char *params[] ) -> int { check_mods = true; test_mode = true; for( int i = 0; i < n; ++i ) { opts.emplace_back( params[ i ] ); } return 0; } }, { "--dump-stats", "<what> [mode = TSV] [opts...]", "Dumps item stats", section_default, [&dump,&dmode,&opts](int n, const char *params[]) -> int { if( n < 1 ) { return -1; } test_mode = true; dump = params[ 0 ]; for( int i = 2; i < n; ++i ) { opts.emplace_back( params[ i ] ); } if( n >= 2 ) { if( !strcmp( params[ 1 ], "TSV" ) ) { dmode = dump_mode::TSV; return 0; } else if( !strcmp( params[ 1 ], "HTML" ) ) { dmode = dump_mode::HTML; return 0; } else { return -1; } } return 0; } }, { "--world", "<name>", "Load world", section_default, [&world](int n, const char *params[]) -> int { if( n < 1 ) { return -1; } world = params[0]; return 1; } }, { "--basepath", "<path>", "Base path for all game data subdirectories", section_default, [](int num_args, const char **params) { if (num_args < 1) return -1; PATH_INFO::init_base_path(params[0]); PATH_INFO::set_standard_filenames(); return 1; } }, { "--shared", nullptr, "Activates the map-sharing mode", section_map_sharing, [](int, const char **) -> int { MAP_SHARING::setSharing(true); MAP_SHARING::setCompetitive(true); MAP_SHARING::setWorldmenu(false); return 0; } }, { "--username", "<name>", "Instructs map-sharing code to use this name for your character.", section_map_sharing, [](int num_args, const char **params) -> int { if (num_args < 1) return -1; MAP_SHARING::setUsername(params[0]); return 1; } }, { "--addadmin", "<username>", "Instructs map-sharing code to use this name for your character and give you " "access to the cheat functions.", section_map_sharing, [](int num_args, const char **params) -> int { if (num_args < 1) return -1; MAP_SHARING::addAdmin(params[0]); return 1; } }, { "--adddebugger", "<username>", "Informs map-sharing code that you're running inside a debugger", section_map_sharing, [](int num_args, const char **params) -> int { if (num_args < 1) return -1; MAP_SHARING::addDebugger(params[0]); return 1; } }, { "--competitive", nullptr, "Instructs map-sharing code to disable access to the in-game cheat functions", section_map_sharing, [](int, const char **) -> int { MAP_SHARING::setCompetitive(true); return 0; } }, { "--userdir", "<path>", "Base path for user-overrides to files from the ./data directory and named below", section_user_directory, [](int num_args, const char **params) -> int { if (num_args < 1) return -1; PATH_INFO::init_user_dir(params[0]); PATH_INFO::set_standard_filenames(); return 1; } } }}; // The following arguments are dependent on one or more of the previous flags and are run // in a second pass. const std::array<arg_handler, 9> second_pass_arguments = {{ { "--worldmenu", nullptr, "Enables the world menu in the map-sharing code", section_map_sharing, [](int, const char **) -> int { MAP_SHARING::setWorldmenu(true); return true; } }, { "--datadir", "<directory name>", "Sub directory from which game data is loaded", nullptr, [](int num_args, const char **params) -> int { if (num_args < 1) return -1; PATH_INFO::update_pathname("datadir", params[0]); PATH_INFO::update_datadir(); return 1; } }, { "--savedir", "<directory name>", "Subdirectory for game saves", section_user_directory, [](int num_args, const char **params) -> int { if (num_args < 1) return -1; PATH_INFO::update_pathname("savedir", params[0]); return 1; } }, { "--configdir", "<directory name>", "Subdirectory for game configuration", section_user_directory, [](int num_args, const char **params) -> int { if (num_args < 1) return -1; PATH_INFO::update_pathname("config_dir", params[0]); PATH_INFO::update_config_dir(); return 1; } }, { "--memorialdir", "<directory name>", "Subdirectory for memorials", section_user_directory, [](int num_args, const char **params) -> int { if (num_args < 1) return -1; PATH_INFO::update_pathname("memorialdir", params[0]); return 1; } }, { "--optionfile", "<filename>", "Name of the options file within the configdir", section_user_directory, [](int num_args, const char **params) -> int { if (num_args < 1) return -1; PATH_INFO::update_pathname("options", params[0]); return 1; } }, { "--keymapfile", "<filename>", "Name of the keymap file within the configdir", section_user_directory, [](int num_args, const char **params) -> int { if (num_args < 1) return -1; PATH_INFO::update_pathname("keymap", params[0]); return 1; } }, { "--autopickupfile", "<filename>", "Name of the autopickup options file within the configdir", nullptr, [](int num_args, const char **params) -> int { if (num_args < 1) return -1; PATH_INFO::update_pathname("autopickup", params[0]); return 1; } }, { "--motdfile", "<filename>", "Name of the message of the day file within the motd directory", nullptr, [](int num_args, const char **params) -> int { if (num_args < 1) return -1; PATH_INFO::update_pathname("motd", params[0]); return 1; } }, }}; // Process CLI arguments. const size_t num_first_pass_arguments = sizeof(first_pass_arguments) / sizeof(first_pass_arguments[0]); const size_t num_second_pass_arguments = sizeof(second_pass_arguments) / sizeof(second_pass_arguments[0]); int saved_argc = --argc; // skip program name const char **saved_argv = (const char **)++argv; while (argc) { if(!strcmp(argv[0], "--help")) { printHelpMessage(first_pass_arguments.data(), num_first_pass_arguments, second_pass_arguments.data(), num_second_pass_arguments); return 0; } else { bool arg_handled = false; for (size_t i = 0; i < num_first_pass_arguments; ++i) { auto &arg_handler = first_pass_arguments[i]; if (!strcmp(argv[0], arg_handler.flag)) { argc--; argv++; int args_consumed = arg_handler.handler(argc, (const char **)argv); if (args_consumed < 0) { printf("Failed parsing parameter '%s'\n", *(argv - 1)); exit(1); } argc -= args_consumed; argv += args_consumed; arg_handled = true; break; } } // Skip other options. if (!arg_handled) { --argc; ++argv; } } } while (saved_argc) { bool arg_handled = false; for (size_t i = 0; i < num_second_pass_arguments; ++i) { auto &arg_handler = second_pass_arguments[i]; if (!strcmp(saved_argv[0], arg_handler.flag)) { --saved_argc; ++saved_argv; int args_consumed = arg_handler.handler(saved_argc, saved_argv); if (args_consumed < 0) { printf("Failed parsing parameter '%s'\n", *(argv - 1)); exit(1); } saved_argc -= args_consumed; saved_argv += args_consumed; arg_handled = true; break; } } // Ingore unknown options. if (!arg_handled) { --saved_argc; ++saved_argv; } } } if (!assure_dir_exist(FILENAMES["user_dir"].c_str())) { printf("Can't open or create %s. Check permissions.\n", FILENAMES["user_dir"].c_str()); exit(1); } setupDebug(); if (setlocale(LC_ALL, "") == NULL) { DebugLog(D_WARNING, D_MAIN) << "Error while setlocale(LC_ALL, '')."; } else { try { std::locale::global( std::locale( "" ) ); } catch( const std::exception& ) { // if user default locale retrieval isn't implemented by system try{ // default to basic C locale std::locale::global( std::locale::classic() ); } catch( const std::exception &err ) { debugmsg( "%s", err.what() ); exit_handler(-999); } } } get_options().init(); get_options().load(); set_language(); // in test mode don't initialize curses to avoid escape sequences being inserted into output stream if( !test_mode ) { if( initscr() == nullptr ) { // Initialize ncurses DebugLog( D_ERROR, DC_ALL ) << "initscr failed!"; return 1; } init_interface(); noecho(); // Don't echo keypresses cbreak(); // C-style breaks (e.g. ^C to SIGINT) keypad(stdscr, true); // Numpad is numbers } #if !(defined TILES || defined _WIN32 || defined WINDOWS) // For tiles or windows, this is handled already in initscr(). init_colors(); #endif // curs_set(0); // Invisible cursor set_escdelay(10); // Make escape actually responsive srand(seed); g = new game; // First load and initialize everything that does not // depend on the mods. try { g->load_static_data(); if (verifyexit) { exit_handler(0); } if( !dump.empty() ) { init_colors(); exit( g->dump_stats( dump, dmode, opts ) ? 0 : 1 ); } if( check_mods ) { init_colors(); loading_ui ui( false ); exit( g->check_mod_data( opts, ui ) && !test_dirty ? 0 : 1 ); } } catch( const std::exception &err ) { debugmsg( "%s", err.what() ); exit_handler(-999); } // Now we do the actual game. g->init_ui(); curs_set(0); // Invisible cursor here, because MAPBUFFER.load() is crash-prone #if (!(defined _WIN32 || defined WINDOWS)) struct sigaction sigIntHandler; sigIntHandler.sa_handler = exit_handler; sigemptyset(&sigIntHandler.sa_mask); sigIntHandler.sa_flags = 0; sigaction(SIGINT, &sigIntHandler, NULL); #endif while( true ) { if( !world.empty() ) { if( !g->load( world ) ) { break; } world.clear(); // ensure quit returns to opening screen } else { main_menu menu; if( !menu.opening_screen() ) { break; } } while( !g->do_turn() ); }; exit_handler(-999); return 0; }
void EUTelGeometryTelescopeGeoDescription::master2LocalVec( int sensorID, std::array<double,3> const & globalVec, std::array<double,3>& localVec) { this->master2LocalVec(sensorID, globalVec.data(), localVec.data()); }
#include <Nazara/Audio/Algorithm.hpp> #include <Catch/catch.hpp> #include <array> TEST_CASE("MixToMono", "[AUDIO][ALGORITHM]") { SECTION("Mix two channels together") { std::array<int, 4> input{ 1, 3, 5, 3 }; std::array<int, 2> output{ 0, 0 }; // Two channels and two frames ! Nz::MixToMono(input.data(), output.data(), 2, 2); std::array<int, 2> theoric{ 2, 4 }; // It's the mean of the two channels REQUIRE(output == theoric); } }
namespace PatchEngine { constexpr std::array<const char*, 3> s_patch_type_strings{{ "byte", "word", "dword", }}; static std::vector<Patch> s_on_frame; static std::map<u32, int> s_speed_hacks; const char* PatchTypeAsString(PatchType type) { return s_patch_type_strings.at(static_cast<int>(type)); } void LoadPatchSection(const std::string& section, std::vector<Patch>& patches, IniFile& globalIni, IniFile& localIni) { // Load the name of all enabled patches std::string enabledSectionName = section + "_Enabled"; std::vector<std::string> enabledLines; std::set<std::string> enabledNames; localIni.GetLines(enabledSectionName, &enabledLines); for (const std::string& line : enabledLines) { if (!line.empty() && line[0] == '$') { std::string name = line.substr(1, line.size() - 1); enabledNames.insert(name); } } const IniFile* inis[2] = {&globalIni, &localIni}; for (const IniFile* ini : inis) { std::vector<std::string> lines; Patch currentPatch; ini->GetLines(section, &lines); for (std::string& line : lines) { if (line.empty()) continue; if (line[0] == '$') { // Take care of the previous code if (!currentPatch.name.empty()) { patches.push_back(currentPatch); } currentPatch.entries.clear(); // Set active and name currentPatch.name = line.substr(1, line.size() - 1); currentPatch.active = enabledNames.find(currentPatch.name) != enabledNames.end(); currentPatch.user_defined = (ini == &localIni); } else { std::string::size_type loc = line.find('='); if (loc != std::string::npos) { line[loc] = ':'; } const std::vector<std::string> items = SplitString(line, ':'); if (items.size() >= 3) { PatchEntry pE; bool success = true; success &= TryParse(items[0], &pE.address); success &= TryParse(items[2], &pE.value); const auto iter = std::find(s_patch_type_strings.begin(), s_patch_type_strings.end(), items[1]); pE.type = PatchType(std::distance(s_patch_type_strings.begin(), iter)); success &= (pE.type != (PatchType)3); if (success) { currentPatch.entries.push_back(pE); } } } } if (!currentPatch.name.empty() && !currentPatch.entries.empty()) { patches.push_back(currentPatch); } } } static void LoadSpeedhacks(const std::string& section, IniFile& ini) { std::vector<std::string> keys; ini.GetKeys(section, &keys); for (const std::string& key : keys) { std::string value; ini.GetOrCreateSection(section)->Get(key, &value, "BOGUS"); if (value != "BOGUS") { u32 address; u32 cycles; bool success = true; success &= TryParse(key, &address); success &= TryParse(value, &cycles); if (success) { s_speed_hacks[address] = static_cast<int>(cycles); } } } } int GetSpeedhackCycles(const u32 addr) { const auto iter = s_speed_hacks.find(addr); if (iter == s_speed_hacks.end()) return 0; return iter->second; } void LoadPatches() { IniFile merged = SConfig::GetInstance().LoadGameIni(); IniFile globalIni = SConfig::GetInstance().LoadDefaultGameIni(); IniFile localIni = SConfig::GetInstance().LoadLocalGameIni(); LoadPatchSection("OnFrame", s_on_frame, globalIni, localIni); // Check if I'm syncing Codes if (Config::Get(Config::MAIN_CODE_SYNC_OVERRIDE)) { Gecko::SetSyncedCodesAsActive(); ActionReplay::SetSyncedCodesAsActive(); } else { Gecko::SetActiveCodes(Gecko::LoadCodes(globalIni, localIni)); ActionReplay::LoadAndApplyCodes(globalIni, localIni); } LoadSpeedhacks("Speedhacks", merged); } static void ApplyPatches(const std::vector<Patch>& patches) { for (const Patch& patch : patches) { if (patch.active) { for (const PatchEntry& entry : patch.entries) { u32 addr = entry.address; u32 value = entry.value; switch (entry.type) { case PatchType::Patch8Bit: PowerPC::HostWrite_U8(static_cast<u8>(value), addr); break; case PatchType::Patch16Bit: PowerPC::HostWrite_U16(static_cast<u16>(value), addr); break; case PatchType::Patch32Bit: PowerPC::HostWrite_U32(value, addr); break; default: // unknown patchtype break; } } } } } // Requires MSR.DR, MSR.IR // There's no perfect way to do this, it's just a heuristic. // We require at least 2 stack frames, if the stack is shallower than that then it won't work. static bool IsStackSane() { DEBUG_ASSERT(MSR.DR && MSR.IR); // Check the stack pointer u32 SP = GPR(1); if (!PowerPC::HostIsRAMAddress(SP)) return false; // Read the frame pointer from the stack (find 2nd frame from top), assert that it makes sense u32 next_SP = PowerPC::HostRead_U32(SP); if (next_SP <= SP || !PowerPC::HostIsRAMAddress(next_SP) || !PowerPC::HostIsRAMAddress(next_SP + 4)) return false; // Check the link register makes sense (that it points to a valid IBAT address) const u32 address = PowerPC::HostRead_U32(next_SP + 4); return PowerPC::HostIsInstructionRAMAddress(address) && 0 != PowerPC::HostRead_U32(address); } bool ApplyFramePatches() { // Because we're using the VI Interrupt to time this instead of patching the game with a // callback hook we can end up catching the game in an exception vector. // We deal with this by returning false so that SystemTimers will reschedule us in a few cycles // where we can try again after the CPU hopefully returns back to the normal instruction flow. if (!MSR.DR || !MSR.IR || !IsStackSane()) { DEBUG_LOG( ACTIONREPLAY, "Need to retry later. CPU configuration is currently incorrect. PC = 0x%08X, MSR = 0x%08X", PC, MSR.Hex); return false; } ApplyPatches(s_on_frame); // Run the Gecko code handler Gecko::RunCodeHandler(); ActionReplay::RunAllActive(); return true; } void Shutdown() { s_on_frame.clear(); s_speed_hacks.clear(); ActionReplay::ApplyCodes({}); Gecko::Shutdown(); } void Reload() { Shutdown(); LoadPatches(); } } // namespace
/*! * \brief By default all elements are set to zero. */ Matrix(){ d.fill( T(0.0) ); }
void LoadPatchSection(const std::string& section, std::vector<Patch>& patches, IniFile& globalIni, IniFile& localIni) { // Load the name of all enabled patches std::string enabledSectionName = section + "_Enabled"; std::vector<std::string> enabledLines; std::set<std::string> enabledNames; localIni.GetLines(enabledSectionName, &enabledLines); for (const std::string& line : enabledLines) { if (!line.empty() && line[0] == '$') { std::string name = line.substr(1, line.size() - 1); enabledNames.insert(name); } } const IniFile* inis[2] = {&globalIni, &localIni}; for (const IniFile* ini : inis) { std::vector<std::string> lines; Patch currentPatch; ini->GetLines(section, &lines); for (std::string& line : lines) { if (line.empty()) continue; if (line[0] == '$') { // Take care of the previous code if (!currentPatch.name.empty()) { patches.push_back(currentPatch); } currentPatch.entries.clear(); // Set active and name currentPatch.name = line.substr(1, line.size() - 1); currentPatch.active = enabledNames.find(currentPatch.name) != enabledNames.end(); currentPatch.user_defined = (ini == &localIni); } else { std::string::size_type loc = line.find('='); if (loc != std::string::npos) { line[loc] = ':'; } const std::vector<std::string> items = SplitString(line, ':'); if (items.size() >= 3) { PatchEntry pE; bool success = true; success &= TryParse(items[0], &pE.address); success &= TryParse(items[2], &pE.value); const auto iter = std::find(s_patch_type_strings.begin(), s_patch_type_strings.end(), items[1]); pE.type = PatchType(std::distance(s_patch_type_strings.begin(), iter)); success &= (pE.type != (PatchType)3); if (success) { currentPatch.entries.push_back(pE); } } } } if (!currentPatch.name.empty() && !currentPatch.entries.empty()) { patches.push_back(currentPatch); } } }
/*! * \brief Constructor using a user defined default value to fill the container. * \param value default value */ Matrix(const T& value){ d.fill(value); }
T get(std::array<T,N> const& p, int i) { return i < p.size() ? p[i] : 0; }
/*! * \brief Return a pointer to the first element of the data container. * \return A pointer to the first element of the data container. */ T* data(){ return d.data(); }
vector<T> vec(const std::array<T, n>& arr) { return vector<T>(arr.begin(), arr.end()); }
/*! * \brief Return a const pointer to the first element of the data container. * \return A const pointer to the first element of the data container. */ const T* data() const { return d.data(); }
void PageRecord::StartOutput() { assert(m_page_started); if(m_output_started) return; if(m_simple_synth != NULL) { m_simple_synth->PlaySequence(SEQUENCE_RECORD_START.data(), SEQUENCE_RECORD_START.size()); usleep(200000); } try { Logger::LogInfo("[PageRecord::StartOutput] " + tr("Starting output ...")); if(m_output_manager == NULL) { // set the file name if(m_separate_files) m_output_settings.file = GetNewSegmentFile(m_file_base); // for OpenGL recording, detect the application size if(m_video_area == PageInput::VIDEO_AREA_GLINJECT && !m_video_scaling) { if(m_gl_inject_input == NULL) { Logger::LogError("[PageRecord::StartOutput] " + tr("Error: Could not get the size of the OpenGL application because the GLInject input has not been created.")); throw GLInjectException(); } m_gl_inject_input->GetCurrentSize(&m_video_in_width, &m_video_in_height); if(m_video_in_width == 0 && m_video_in_height == 0) { Logger::LogError("[PageRecord::StartOutput] " + tr("Error: Could not get the size of the OpenGL application. Either the " "application wasn't started correctly, or the application hasn't created an OpenGL window yet. If " "you want to start recording before starting the application, you have to enable scaling and enter " "the video size manually.")); throw GLInjectException(); } } // calculate the output width and height if(m_video_scaling) { // Only even width and height is allowed because the final images are encoded as YUV. m_output_settings.video_width = m_video_scaled_width / 2 * 2; m_output_settings.video_height = m_video_scaled_height / 2 * 2; } else if(m_video_area == PageInput::VIDEO_AREA_GLINJECT) { // The input size is the size of the OpenGL application and can't be changed. The output size is set to the current size of the application. m_output_settings.video_width = m_video_in_width / 2 * 2; m_output_settings.video_height = m_video_in_height / 2 * 2; } else { // If the user did not explicitly select scaling, then don't force scaling just because the recording area is one pixel too large. // One missing row/column of pixels is probably better than a blurry video (and scaling is SLOW). m_video_in_width = m_video_in_width / 2 * 2; m_video_in_height = m_video_in_height / 2 * 2; m_output_settings.video_width = m_video_in_width; m_output_settings.video_height = m_video_in_height; } // start the output m_output_manager.reset(new OutputManager(m_output_settings)); } else { // start a new segment m_output_manager->GetSynchronizer()->NewSegment(); } Logger::LogInfo("[PageRecord::StartOutput] " + tr("Started output.")); m_output_started = true; m_recorded_something = true; UpdateSysTray(); UpdateRecordPauseButton(); UpdateInput(); } catch(...) { Logger::LogError("[PageRecord::StartOutput] " + tr("Error: Something went wrong during initialization.")); } }
void operator()(msgpack::object& o, const std::array<unsigned char, N>& v) const { uint32_t size = checked_get_container_size(v.size()); o.type = msgpack::type::BIN; o.via.bin.ptr = reinterpret_cast<char const*>(v.data()); o.via.bin.size = size; }
// protected bool IPAddressV6::inBinarySubnet(const std::array<uint8_t, 2> addr, size_t numBits) const { const unsigned char* subbytes = mask(numBits).bytes(); return (std::memcmp(addr.data(), subbytes, 2) == 0); }
void EUTelGeometryTelescopeGeoDescription::local2Master( int sensorID, std::array<double,3> const & localPos, std::array<double,3>& globalPos) { this->local2Master(sensorID, localPos.data(), globalPos.data()); }
std::string LibusbSoundplaneDriver::getSerialNumberString() const { const std::array<unsigned char, 64> serialNumber = mSerialNumber.load(); return std::string(reinterpret_cast<const char *>(serialNumber.data())); }
void Module::initialiseExceptions() { sExceptionCallbacks.fill(nullptr); }