[CAM] Implement GetMaxLines

This commit is contained in:
wheremyfoodat 2023-03-13 02:08:31 +02:00
parent 5b9648e0a8
commit fd284e5bfd
2 changed files with 35 additions and 1 deletions

View file

@ -11,6 +11,7 @@ class CAMService {
// Service commands
void driverInitialize(u32 messagePointer);
void getMaxLines(u32 messagePointer);
public:
CAMService(Memory& mem) : mem(mem) {}

View file

@ -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);
}
}