diff --git a/include/services/nfc.hpp b/include/services/nfc.hpp index 59e8f362..cc13f826 100644 --- a/include/services/nfc.hpp +++ b/include/services/nfc.hpp @@ -14,13 +14,35 @@ class NFCService { Kernel& kernel; MAKE_LOG_FUNCTION(log, nfcLogger) + enum class Old3DSAdapterStatus : u32 { + Idle = 0, + AttemptingToInitialize = 1, + InitializationComplete = 2, + Active = 3, + }; + + enum class TagStatus : u8 { + NotInitialized = 0, + Initialized = 1, + Scanning = 2, + InRange = 3, + OutOfRange = 4, + Loaded = 5, + }; + // Kernel events signaled when an NFC tag goes in and out of range respectively std::optional tagInRangeEvent, tagOutOfRangeEvent; + Old3DSAdapterStatus adapterStatus; + TagStatus tagStatus; + // Service commands + void communicationGetStatus(u32 messagePointer); void initialize(u32 messagePointer); void getTagInRangeEvent(u32 messagePointer); void getTagOutOfRangeEvent(u32 messagePointer); + void getTagState(u32 messagePointer); + void stopCommunication(u32 messagePointer); public: NFCService(Memory& mem, Kernel& kernel) : mem(mem), kernel(kernel) {} diff --git a/src/core/memory.cpp b/src/core/memory.cpp index d359d637..39c8520d 100644 --- a/src/core/memory.cpp +++ b/src/core/memory.cpp @@ -152,8 +152,13 @@ u32 Memory::read32(u32 vaddr) { default: if (vaddr >= VirtualAddrs::VramStart && vaddr < VirtualAddrs::VramStart + VirtualAddrs::VramSize) { - Helpers::warn("VRAM read!\n"); - return 0; + static int shutUpCounter = 0; + if (shutUpCounter < 5) { // Stop spamming about VRAM reads after the first 5 + Helpers::warn("VRAM read!\n"); + } + + // TODO: Properly handle framebuffer readbacks and the like + return *(u32*)&vram[vaddr - VirtualAddrs::VramStart]; } Helpers::panic("Unimplemented 32-bit read, addr: %08X", vaddr); diff --git a/src/core/services/nfc.cpp b/src/core/services/nfc.cpp index c6ed363d..4281c0e4 100644 --- a/src/core/services/nfc.cpp +++ b/src/core/services/nfc.cpp @@ -5,22 +5,31 @@ namespace NFCCommands { enum : u32 { Initialize = 0x00010040, + StopCommunication = 0x00040000, GetTagInRangeEvent = 0x000B0000, - GetTagOutOfRangeEvent = 0x000C0000 + GetTagOutOfRangeEvent = 0x000C0000, + GetTagState = 0x000D0000, + CommunicationGetStatus = 0x000F0000, }; } void NFCService::reset() { tagInRangeEvent = std::nullopt; tagOutOfRangeEvent = std::nullopt; + + adapterStatus = Old3DSAdapterStatus::Idle; + tagStatus = TagStatus::NotInitialized; } void NFCService::handleSyncRequest(u32 messagePointer) { const u32 command = mem.read32(messagePointer); switch (command) { + case NFCCommands::CommunicationGetStatus: communicationGetStatus(messagePointer); break; case NFCCommands::Initialize: initialize(messagePointer); break; case NFCCommands::GetTagInRangeEvent: getTagInRangeEvent(messagePointer); break; case NFCCommands::GetTagOutOfRangeEvent: getTagOutOfRangeEvent(messagePointer); break; + case NFCCommands::GetTagState: getTagState(messagePointer); break; + case NFCCommands::StopCommunication: stopCommunication(messagePointer); break; default: Helpers::panic("NFC service requested. Command: %08X\n", command); } } @@ -29,6 +38,8 @@ void NFCService::initialize(u32 messagePointer) { const u8 type = mem.read8(messagePointer + 4); log("NFC::Initialize (type = %d)\n", type); + adapterStatus = Old3DSAdapterStatus::InitializationComplete; + tagStatus = TagStatus::Initialized; // TODO: This should error if already initialized. Also sanitize type. mem.write32(messagePointer, IPC::responseHeader(0x1, 1, 0)); mem.write32(messagePointer + 4, Result::Success); @@ -67,4 +78,32 @@ void NFCService::getTagOutOfRangeEvent(u32 messagePointer) { mem.write32(messagePointer + 4, Result::Success); // TODO: Translation descriptor here mem.write32(messagePointer + 12, tagOutOfRangeEvent.value()); +} + +void NFCService::getTagState(u32 messagePointer) { + log("NFC::GetTagState"); + + mem.write32(messagePointer, IPC::responseHeader(0xD, 2, 0)); + mem.write32(messagePointer + 4, Result::Success); + mem.write8(messagePointer + 8, static_cast(tagStatus)); +} + +void NFCService::communicationGetStatus(u32 messagePointer) { + log("NFC::CommunicationGetStatus"); + + if (adapterStatus != Old3DSAdapterStatus::InitializationComplete) { + Helpers::warn("NFC::CommunicationGetStatus: Old 3DS NFC Adapter not initialized\n"); + } + + mem.write32(messagePointer, IPC::responseHeader(0xF, 2, 0)); + mem.write32(messagePointer + 4, Result::Success); + mem.write8(messagePointer + 8, static_cast(adapterStatus)); +} + +void NFCService::stopCommunication(u32 messagePointer) { + log("NFC::StopCommunication\n"); + // TODO: Actually stop communication when we emulate amiibo + + mem.write32(messagePointer, IPC::responseHeader(0x4, 1, 0)); + mem.write32(messagePointer + 4, Result::Success); } \ No newline at end of file