diff --git a/include/services/cam.hpp b/include/services/cam.hpp index 7cd851b9..7f4065ab 100644 --- a/include/services/cam.hpp +++ b/include/services/cam.hpp @@ -11,6 +11,7 @@ class CAMService { // Service commands void driverInitialize(u32 messagePointer); + void getMaxLines(u32 messagePointer); public: CAMService(Memory& mem) : mem(mem) {} diff --git a/src/core/services/cam.cpp b/src/core/services/cam.cpp index 0ce013f3..fc6b27a1 100644 --- a/src/core/services/cam.cpp +++ b/src/core/services/cam.cpp @@ -2,7 +2,8 @@ namespace CAMCommands { enum : u32 { - DriverInitialize = 0x00390000 + DriverInitialize = 0x00390000, + GetMaxLines = 0x000A0080 }; } @@ -18,6 +19,7 @@ void CAMService::handleSyncRequest(u32 messagePointer) { const u32 command = mem.read32(messagePointer); switch (command) { case CAMCommands::DriverInitialize: driverInitialize(messagePointer); break; + case CAMCommands::GetMaxLines: getMaxLines(messagePointer); break; default: Helpers::panic("CAM service requested. Command: %08X\n", command); } } @@ -25,4 +27,35 @@ void CAMService::handleSyncRequest(u32 messagePointer) { void CAMService::driverInitialize(u32 messagePointer) { log("CAM::DriverInitialize\n"); mem.write32(messagePointer + 4, Result::Success); +} + +// Algorithm taken from Citra +// https://github.com/citra-emu/citra/blob/master/src/core/hle/service/cam/cam.cpp#L465 +void CAMService::getMaxLines(u32 messagePointer) { + const u16 width = mem.read16(messagePointer + 4); + const u16 height = mem.read16(messagePointer + 8); + log("CAM::GetMaxLines (width = %d, height = %d)\n", width, height); + + constexpr u32 MIN_TRANSFER_UNIT = 256; + constexpr u32 MAX_BUFFER_SIZE = 2560; + if (width * height * 2 % MIN_TRANSFER_UNIT != 0) { + Helpers::panic("CAM::GetMaxLines out of range"); + } else { + u32 lines = MAX_BUFFER_SIZE / width; + if (lines > height) { + lines = height; + } + + u32 result = Result::Success; + while (height % lines != 0 || (lines * width * 2 % MIN_TRANSFER_UNIT != 0)) { + --lines; + if (lines == 0) { + Helpers::panic("CAM::GetMaxLines out of range"); + break; + } + } + + mem.write32(messagePointer + 4, result); + mem.write16(messagePointer + 8, lines); + } } \ No newline at end of file