mirror of
https://github.com/wheremyfoodat/Panda3DS.git
synced 2025-04-22 05:15:51 +12:00
Merge remote-tracking branch 'upstream/master' into CRO
This commit is contained in:
commit
d50c94cbdc
48 changed files with 4278 additions and 3203 deletions
|
@ -17,7 +17,10 @@ void ACTService::handleSyncRequest(u32 messagePointer) {
|
|||
case ACTCommands::GenerateUUID: generateUUID(messagePointer); break;
|
||||
case ACTCommands::GetAccountDataBlock: getAccountDataBlock(messagePointer); break;
|
||||
case ACTCommands::Initialize: initialize(messagePointer); break;
|
||||
default: Helpers::panic("ACT service requested. Command: %08X\n", command);
|
||||
default:
|
||||
Helpers::warn("Undocumented ACT service requested. Command: %08X", command);
|
||||
mem.write32(messagePointer + 4, Result::Success);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -6,7 +6,10 @@ namespace CAMCommands {
|
|||
enum : u32 {
|
||||
GetBufferErrorInterruptEvent = 0x00060040,
|
||||
DriverInitialize = 0x00390000,
|
||||
SetTransferLines = 0x00090100,
|
||||
GetMaxLines = 0x000A0080,
|
||||
SetFrameRate = 0x00200080,
|
||||
SetContrast = 0x00230080,
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -18,7 +21,12 @@ void CAMService::handleSyncRequest(u32 messagePointer) {
|
|||
case CAMCommands::DriverInitialize: driverInitialize(messagePointer); break;
|
||||
case CAMCommands::GetBufferErrorInterruptEvent: getBufferErrorInterruptEvent(messagePointer); break;
|
||||
case CAMCommands::GetMaxLines: getMaxLines(messagePointer); break;
|
||||
default: Helpers::panic("CAM service requested. Command: %08X\n", command);
|
||||
case CAMCommands::SetContrast: setContrast(messagePointer); break;
|
||||
case CAMCommands::SetFrameRate: setFrameRate(messagePointer); break;
|
||||
case CAMCommands::SetTransferLines: setTransferLines(messagePointer); break;
|
||||
default:
|
||||
Helpers::panic("Unimplemented CAM service requested. Command: %08X\n", command);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -28,6 +36,38 @@ void CAMService::driverInitialize(u32 messagePointer) {
|
|||
mem.write32(messagePointer + 4, Result::Success);
|
||||
}
|
||||
|
||||
void CAMService::setContrast(u32 messagePointer) {
|
||||
const u32 cameraSelect = mem.read32(messagePointer + 4);
|
||||
const u32 contrast = mem.read32(messagePointer + 8);
|
||||
|
||||
log("CAM::SetPhotoMode (camera select = %d, contrast = %d)\n", cameraSelect, contrast);
|
||||
|
||||
mem.write32(messagePointer, IPC::responseHeader(0x23, 1, 0));
|
||||
mem.write32(messagePointer + 4, Result::Success);
|
||||
}
|
||||
|
||||
void CAMService::setTransferLines(u32 messagePointer) {
|
||||
const u32 port = mem.read32(messagePointer + 4);
|
||||
const s16 lines = mem.read16(messagePointer + 8);
|
||||
const s16 width = mem.read16(messagePointer + 12);
|
||||
const s16 height = mem.read16(messagePointer + 16);
|
||||
|
||||
log("CAM::SetTransferLines (port = %d, lines = %d, width = %d, height = %d)\n", port, lines, width, height);
|
||||
|
||||
mem.write32(messagePointer, IPC::responseHeader(0x9, 1, 0));
|
||||
mem.write32(messagePointer + 4, Result::Success);
|
||||
}
|
||||
|
||||
void CAMService::setFrameRate(u32 messagePointer) {
|
||||
const u32 cameraSelect = mem.read32(messagePointer + 4);
|
||||
const u32 framerate = mem.read32(messagePointer + 8);
|
||||
|
||||
log("CAM::SetPhotoMode (camera select = %d, framerate = %d)\n", cameraSelect, framerate);
|
||||
|
||||
mem.write32(messagePointer, IPC::responseHeader(0x20, 1, 0));
|
||||
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) {
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
#include "kernel/kernel.hpp"
|
||||
#include "io_file.hpp"
|
||||
#include "ipc.hpp"
|
||||
#include "result/result.hpp"
|
||||
|
||||
#ifdef CreateFile // windows.h defines CreateFile & DeleteFile because of course it does.
|
||||
#undef CreateDirectory
|
||||
|
@ -25,13 +26,17 @@ namespace FSCommands {
|
|||
GetFreeBytes = 0x08120080,
|
||||
IsSdmcDetected = 0x08170000,
|
||||
IsSdmcWritable = 0x08180000,
|
||||
AbnegateAccessRight = 0x08400040,
|
||||
GetFormatInfo = 0x084500C2,
|
||||
GetArchiveResource = 0x08490040,
|
||||
FormatSaveData = 0x084C0242,
|
||||
CreateExtSaveData = 0x08510242,
|
||||
DeleteExtSaveData = 0x08520100,
|
||||
SetArchivePriority = 0x085A00C0,
|
||||
InitializeWithSdkVersion = 0x08610042,
|
||||
SetPriority = 0x08620040,
|
||||
GetPriority = 0x08630000,
|
||||
SetThisSaveDataSecureValue = 0x086E00C0,
|
||||
GetThisSaveDataSecureValue = 0x086F0040,
|
||||
TheGameboyVCFunction = 0x08750180,
|
||||
};
|
||||
|
@ -158,6 +163,7 @@ void FSService::handleSyncRequest(u32 messagePointer) {
|
|||
case FSCommands::DeleteFile: deleteFile(messagePointer); break;
|
||||
case FSCommands::FormatSaveData: formatSaveData(messagePointer); break;
|
||||
case FSCommands::FormatThisUserSaveData: formatThisUserSaveData(messagePointer); break;
|
||||
case FSCommands::GetArchiveResource: getArchiveResource(messagePointer); break;
|
||||
case FSCommands::GetFreeBytes: getFreeBytes(messagePointer); break;
|
||||
case FSCommands::GetFormatInfo: getFormatInfo(messagePointer); break;
|
||||
case FSCommands::GetPriority: getPriority(messagePointer); break;
|
||||
|
@ -170,7 +176,10 @@ void FSService::handleSyncRequest(u32 messagePointer) {
|
|||
case FSCommands::OpenDirectory: openDirectory(messagePointer); break;
|
||||
case FSCommands::OpenFile: [[likely]] openFile(messagePointer); break;
|
||||
case FSCommands::OpenFileDirectly: [[likely]] openFileDirectly(messagePointer); break;
|
||||
case FSCommands::SetArchivePriority: setArchivePriority(messagePointer); break;
|
||||
case FSCommands::SetPriority: setPriority(messagePointer); break;
|
||||
case FSCommands::SetThisSaveDataSecureValue: setThisSaveDataSecureValue(messagePointer); break;
|
||||
case FSCommands::AbnegateAccessRight: abnegateAccessRight(messagePointer); break;
|
||||
case FSCommands::TheGameboyVCFunction: theGameboyVCFunction(messagePointer); break;
|
||||
default: Helpers::panic("FS service requested. Command: %08X\n", command);
|
||||
}
|
||||
|
@ -344,7 +353,8 @@ void FSService::openFileDirectly(u32 messagePointer) {
|
|||
std::optional<Handle> handle = openFileHandle(archive, filePath, archivePath, perms);
|
||||
mem.write32(messagePointer, IPC::responseHeader(0x803, 1, 2));
|
||||
if (!handle.has_value()) {
|
||||
Helpers::panic("OpenFileDirectly: Failed to open file with given path");
|
||||
printf("OpenFileDirectly failed\n");
|
||||
mem.write32(messagePointer + 4, Result::FS::FileNotFound);
|
||||
} else {
|
||||
mem.write32(messagePointer + 4, Result::Success);
|
||||
mem.write32(messagePointer + 12, handle.value());
|
||||
|
@ -579,6 +589,36 @@ void FSService::getPriority(u32 messagePointer) {
|
|||
mem.write32(messagePointer + 8, priority);
|
||||
}
|
||||
|
||||
void FSService::getArchiveResource(u32 messagePointer) {
|
||||
const u32 mediaType = mem.read32(messagePointer + 4);
|
||||
log("FS::GetArchiveResource (media type = %d) (stubbed)\n");
|
||||
|
||||
// For the time being, return the same stubbed archive resource for every media type
|
||||
static constexpr ArchiveResource resource = {
|
||||
.sectorSize = 512,
|
||||
.clusterSize = 16_KB,
|
||||
.partitionCapacityInClusters = 0x80000, // 0x80000 * 16 KB = 8GB
|
||||
.freeSpaceInClusters = 0x80000, // Same here
|
||||
};
|
||||
|
||||
mem.write32(messagePointer, IPC::responseHeader(0x849, 5, 0));
|
||||
mem.write32(messagePointer + 4, Result::Success);
|
||||
|
||||
mem.write32(messagePointer + 8, resource.sectorSize);
|
||||
mem.write32(messagePointer + 12, resource.clusterSize);
|
||||
mem.write32(messagePointer + 16, resource.partitionCapacityInClusters);
|
||||
mem.write32(messagePointer + 20, resource.freeSpaceInClusters);
|
||||
}
|
||||
|
||||
void FSService::setArchivePriority(u32 messagePointer) {
|
||||
Handle archive = mem.read64(messagePointer + 4);
|
||||
const u32 value = mem.read32(messagePointer + 12);
|
||||
log("FS::SetArchivePriority (priority = %d, archive handle = %X)\n", value, handle);
|
||||
|
||||
mem.write32(messagePointer, IPC::responseHeader(0x85A, 1, 0));
|
||||
mem.write32(messagePointer + 4, Result::Success);
|
||||
}
|
||||
|
||||
void FSService::setPriority(u32 messagePointer) {
|
||||
const u32 value = mem.read32(messagePointer + 4);
|
||||
log("FS::SetPriority (priority = %d)\n", value);
|
||||
|
@ -588,6 +628,18 @@ void FSService::setPriority(u32 messagePointer) {
|
|||
priority = value;
|
||||
}
|
||||
|
||||
void FSService::abnegateAccessRight(u32 messagePointer) {
|
||||
const u32 right = mem.read32(messagePointer + 4);
|
||||
log("FS::AbnegateAccessRight (right = %d)\n", right);
|
||||
|
||||
if (right >= 0x38) {
|
||||
Helpers::warn("FS::AbnegateAccessRight: Invalid access right");
|
||||
}
|
||||
|
||||
mem.write32(messagePointer, IPC::responseHeader(0x840, 1, 0));
|
||||
mem.write32(messagePointer + 4, Result::Success);
|
||||
}
|
||||
|
||||
void FSService::getThisSaveDataSecureValue(u32 messagePointer) {
|
||||
Helpers::warn("Unimplemented FS::GetThisSaveDataSecureValue");
|
||||
|
||||
|
@ -595,6 +647,19 @@ void FSService::getThisSaveDataSecureValue(u32 messagePointer) {
|
|||
mem.write32(messagePointer + 4, Result::Success);
|
||||
}
|
||||
|
||||
void FSService::setThisSaveDataSecureValue(u32 messagePointer) {
|
||||
const u64 value = mem.read32(messagePointer + 4);
|
||||
const u32 slot = mem.read32(messagePointer + 12);
|
||||
const u32 id = mem.read32(messagePointer + 16);
|
||||
const u8 variation = mem.read8(messagePointer + 20);
|
||||
|
||||
// TODO: Actually do something with this.
|
||||
Helpers::warn("Unimplemented FS::SetThisSaveDataSecureValue");
|
||||
|
||||
mem.write32(messagePointer, IPC::responseHeader(0x86E, 1, 0));
|
||||
mem.write32(messagePointer + 4, Result::Success);
|
||||
}
|
||||
|
||||
void FSService::theGameboyVCFunction(u32 messagePointer) {
|
||||
Helpers::warn("Unimplemented FS: function: 0x08750180");
|
||||
|
||||
|
@ -602,21 +667,21 @@ void FSService::theGameboyVCFunction(u32 messagePointer) {
|
|||
mem.write32(messagePointer + 4, Result::Success);
|
||||
}
|
||||
|
||||
// Shows whether an SD card is inserted. At the moment stubbed to no
|
||||
constexpr bool sdInserted = false;
|
||||
|
||||
void FSService::isSdmcDetected(u32 messagePointer) {
|
||||
log("FS::IsSdmcDetected\n");
|
||||
|
||||
mem.write32(messagePointer, IPC::responseHeader(0x817, 2, 0));
|
||||
mem.write32(messagePointer + 4, Result::Success);
|
||||
mem.write8(messagePointer + 8, sdInserted ? 1 : 0);
|
||||
mem.write8(messagePointer + 8, config.sdCardInserted ? 1 : 0);
|
||||
}
|
||||
|
||||
// We consider our SD card to always be writable if oen is inserted for now
|
||||
// So isSdmcWritable returns 1 if an SD card is inserted (because it's always writable) and 0 if not.
|
||||
// We consider our SD card to always be writable if one is inserted for now
|
||||
// However we do make sure to respect the configs and properly return the correct value here
|
||||
void FSService::isSdmcWritable(u32 messagePointer) {
|
||||
log("FS::isSdmcWritable\n");
|
||||
const bool writeProtected = (!config.sdCardInserted) || (config.sdCardInserted && config.sdWriteProtected);
|
||||
|
||||
mem.write32(messagePointer, IPC::responseHeader(0x818, 2, 0));
|
||||
mem.write32(messagePointer + 4, Result::Success);
|
||||
mem.write8(messagePointer + 8, sdInserted ? 1 : 0);
|
||||
mem.write8(messagePointer + 8, writeProtected ? 0 : 1);
|
||||
}
|
|
@ -6,6 +6,8 @@
|
|||
namespace HTTPCommands {
|
||||
enum : u32 {
|
||||
Initialize = 0x00010044,
|
||||
CreateRootCertChain = 0x002D0000,
|
||||
RootCertChainAddDefaultCert = 0x00300080,
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -14,7 +16,9 @@ void HTTPService::reset() { initialized = false; }
|
|||
void HTTPService::handleSyncRequest(u32 messagePointer) {
|
||||
const u32 command = mem.read32(messagePointer);
|
||||
switch (command) {
|
||||
case HTTPCommands::CreateRootCertChain: createRootCertChain(messagePointer); break;
|
||||
case HTTPCommands::Initialize: initialize(messagePointer); break;
|
||||
case HTTPCommands::RootCertChainAddDefaultCert: rootCertChainAddDefaultCert(messagePointer); break;
|
||||
default: Helpers::panic("HTTP service requested. Command: %08X\n", command);
|
||||
}
|
||||
}
|
||||
|
@ -39,4 +43,28 @@ void HTTPService::initialize(u32 messagePointer) {
|
|||
initialized = true;
|
||||
// We currently don't emulate HTTP properly. TODO: Prepare POST buffer here
|
||||
mem.write32(messagePointer + 4, Result::Success);
|
||||
}
|
||||
|
||||
void HTTPService::createRootCertChain(u32 messagePointer) {
|
||||
log("HTTP::CreateRootCertChain (Unimplemented)\n");
|
||||
|
||||
// TODO: Verify response header
|
||||
mem.write32(messagePointer, IPC::responseHeader(0x2D, 2, 0));
|
||||
mem.write32(messagePointer + 4, Result::Success);
|
||||
|
||||
// RootCertChain context handle. No need to emulate this yet
|
||||
mem.write32(messagePointer + 8, 0x66666666);
|
||||
}
|
||||
|
||||
void HTTPService::rootCertChainAddDefaultCert(u32 messagePointer) {
|
||||
log("HTTP::RootCertChainAddDefaultCert (Unimplemented)\n");
|
||||
const u32 contextHandle = mem.read32(messagePointer + 4);
|
||||
const u32 certID = mem.read32(messagePointer + 8);
|
||||
|
||||
// TODO: Verify response header
|
||||
mem.write32(messagePointer, IPC::responseHeader(0x30, 2, 0));
|
||||
mem.write32(messagePointer + 4, Result::Success);
|
||||
|
||||
// Cert context handle. No need to emulate this yet
|
||||
mem.write32(messagePointer + 8, 0x66666666);
|
||||
}
|
|
@ -13,6 +13,7 @@ namespace MICCommands {
|
|||
SetGain = 0x00080040,
|
||||
GetGain = 0x00090000,
|
||||
SetPower = 0x000A0040,
|
||||
GetPower = 0x000B0000,
|
||||
SetIirFilter = 0x000C0042,
|
||||
SetClamp = 0x000D0040,
|
||||
CaptainToadFunction = 0x00100040,
|
||||
|
@ -33,6 +34,7 @@ void MICService::handleSyncRequest(u32 messagePointer) {
|
|||
switch (command) {
|
||||
case MICCommands::GetEventHandle: getEventHandle(messagePointer); break;
|
||||
case MICCommands::GetGain: getGain(messagePointer); break;
|
||||
case MICCommands::GetPower: getPower(messagePointer); break;
|
||||
case MICCommands::IsSampling: isSampling(messagePointer); break;
|
||||
case MICCommands::MapSharedMem: mapSharedMem(messagePointer); break;
|
||||
case MICCommands::SetClamp: setClamp(messagePointer); break;
|
||||
|
@ -101,6 +103,14 @@ void MICService::setPower(u32 messagePointer) {
|
|||
mem.write32(messagePointer + 4, Result::Success);
|
||||
}
|
||||
|
||||
void MICService::getPower(u32 messagePointer) {
|
||||
log("MIC::GetPower\n");
|
||||
|
||||
mem.write32(messagePointer, IPC::responseHeader(0xB, 2, 0));
|
||||
mem.write32(messagePointer + 4, Result::Success);
|
||||
mem.write8(messagePointer + 8, micEnabled ? 1 : 0);
|
||||
}
|
||||
|
||||
void MICService::setClamp(u32 messagePointer) {
|
||||
u8 val = mem.read8(messagePointer + 4);
|
||||
log("MIC::SetClamp (value = %d)\n", val);
|
||||
|
|
|
@ -5,6 +5,7 @@ namespace PTMCommands {
|
|||
enum : u32 {
|
||||
GetAdapterState = 0x00050000,
|
||||
GetBatteryLevel = 0x00070000,
|
||||
GetBatteryChargeState = 0x00080000,
|
||||
GetStepHistory = 0x000B00C2,
|
||||
GetTotalStepCount = 0x000C0000,
|
||||
ConfigureNew3DSCPU = 0x08180040,
|
||||
|
@ -18,6 +19,7 @@ void PTMService::handleSyncRequest(u32 messagePointer) {
|
|||
switch (command) {
|
||||
case PTMCommands::ConfigureNew3DSCPU: configureNew3DSCPU(messagePointer); break;
|
||||
case PTMCommands::GetAdapterState: getAdapterState(messagePointer); break;
|
||||
case PTMCommands::GetBatteryChargeState: getBatteryChargeState(messagePointer); break;
|
||||
case PTMCommands::GetBatteryLevel: getBatteryLevel(messagePointer); break;
|
||||
case PTMCommands::GetStepHistory: getStepHistory(messagePointer); break;
|
||||
case PTMCommands::GetTotalStepCount: getTotalStepCount(messagePointer); break;
|
||||
|
@ -33,6 +35,16 @@ void PTMService::getAdapterState(u32 messagePointer) {
|
|||
mem.write8(messagePointer + 8, config.chargerPlugged ? 1 : 0);
|
||||
}
|
||||
|
||||
void PTMService::getBatteryChargeState(u32 messagePointer) {
|
||||
log("PTM::GetBatteryChargeState");
|
||||
// We're only charging if the battery is not already full
|
||||
const bool charging = config.chargerPlugged && (config.batteryPercentage < 100);
|
||||
|
||||
mem.write32(messagePointer, IPC::responseHeader(0x7, 2, 0));
|
||||
mem.write32(messagePointer + 4, Result::Success);
|
||||
mem.write8(messagePointer + 8, charging ? 1 : 0);
|
||||
}
|
||||
|
||||
void PTMService::getBatteryLevel(u32 messagePointer) {
|
||||
log("PTM::GetBatteryLevel");
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
|
||||
ServiceManager::ServiceManager(std::span<u32, 16> regs, Memory& mem, GPU& gpu, u32& currentPID, Kernel& kernel, const EmulatorConfig& config)
|
||||
: regs(regs), mem(mem), kernel(kernel), ac(mem), am(mem), boss(mem), act(mem), apt(mem, kernel), cam(mem, kernel), cecd(mem, kernel), cfg(mem),
|
||||
dlp_srvr(mem), dsp(mem, kernel), hid(mem, kernel), http(mem), ir_user(mem, kernel), frd(mem), fs(mem, kernel),
|
||||
dlp_srvr(mem), dsp(mem, kernel), hid(mem, kernel), http(mem), ir_user(mem, kernel), frd(mem), fs(mem, kernel, config),
|
||||
gsp_gpu(mem, gpu, kernel, currentPID), gsp_lcd(mem), ldr(mem), mcu_hwc(mem, config), mic(mem, kernel), nfc(mem, kernel), nim(mem), ndm(mem),
|
||||
news_u(mem), ptm(mem, config), soc(mem), ssl(mem), y2r(mem, kernel) {}
|
||||
|
||||
|
@ -79,6 +79,7 @@ void ServiceManager::handleSyncRequest(u32 messagePointer) {
|
|||
case Commands::RegisterClient: registerClient(messagePointer); break;
|
||||
case Commands::GetServiceHandle: getServiceHandle(messagePointer); break;
|
||||
case Commands::Subscribe: subscribe(messagePointer); break;
|
||||
case Commands::Unsubscribe: unsubscribe(messagePointer); break;
|
||||
default: Helpers::panic("Unknown \"srv:\" command: %08X", header);
|
||||
}
|
||||
}
|
||||
|
@ -178,6 +179,14 @@ void ServiceManager::subscribe(u32 messagePointer) {
|
|||
mem.write32(messagePointer + 4, Result::Success);
|
||||
}
|
||||
|
||||
void ServiceManager::unsubscribe(u32 messagePointer) {
|
||||
u32 id = mem.read32(messagePointer + 4);
|
||||
log("srv::Unsubscribe (id = %d) (stubbed)\n", id);
|
||||
|
||||
mem.write32(messagePointer, IPC::responseHeader(0xA, 1, 0));
|
||||
mem.write32(messagePointer + 4, Result::Success);
|
||||
}
|
||||
|
||||
void ServiceManager::sendCommandToService(u32 messagePointer, Handle handle) {
|
||||
switch (handle) {
|
||||
// Breaking alphabetical order a bit to place the ones I think are most common at the top
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
#include "services/y2r.hpp"
|
||||
|
||||
#include "ipc.hpp"
|
||||
#include "kernel.hpp"
|
||||
|
||||
|
@ -6,8 +7,10 @@ namespace Y2RCommands {
|
|||
enum : u32 {
|
||||
SetInputFormat = 0x00010040,
|
||||
SetOutputFormat = 0x00030040,
|
||||
GetOutputFormat = 0x00040000,
|
||||
SetRotation = 0x00050040,
|
||||
SetBlockAlignment = 0x00070040,
|
||||
GetBlockAlignment = 0x00080000,
|
||||
SetSpacialDithering = 0x00090040,
|
||||
SetTemporalDithering = 0x000B0040,
|
||||
SetTransferEndInterrupt = 0x000D0040,
|
||||
|
@ -17,7 +20,9 @@ namespace Y2RCommands {
|
|||
SetSendingV = 0x00120102,
|
||||
SetReceiving = 0x00180102,
|
||||
SetInputLineWidth = 0x001A0040,
|
||||
GetInputLineWidth = 0x001B0000,
|
||||
SetInputLines = 0x001C0040,
|
||||
GetInputLines = 0x001D0000,
|
||||
SetStandardCoeff = 0x00200040,
|
||||
SetAlpha = 0x00220040,
|
||||
StartConversion = 0x00260000,
|
||||
|
@ -26,7 +31,7 @@ namespace Y2RCommands {
|
|||
SetPackageParameter = 0x002901C0,
|
||||
PingProcess = 0x002A0000,
|
||||
DriverInitialize = 0x002B0000,
|
||||
DriverFinalize = 0x002C0000
|
||||
DriverFinalize = 0x002C0000,
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -52,6 +57,10 @@ void Y2RService::handleSyncRequest(u32 messagePointer) {
|
|||
switch (command) {
|
||||
case Y2RCommands::DriverInitialize: driverInitialize(messagePointer); break;
|
||||
case Y2RCommands::DriverFinalize: driverFinalize(messagePointer); break;
|
||||
case Y2RCommands::GetBlockAlignment: getBlockAlignment(messagePointer); break;
|
||||
case Y2RCommands::GetInputLines: getInputLines(messagePointer); break;
|
||||
case Y2RCommands::GetInputLineWidth: getInputLineWidth(messagePointer); break;
|
||||
case Y2RCommands::GetOutputFormat: getOutputFormat(messagePointer); break;
|
||||
case Y2RCommands::GetTransferEndEvent: getTransferEndEvent(messagePointer); break;
|
||||
case Y2RCommands::IsBusyConversion: isBusyConversion(messagePointer); break;
|
||||
case Y2RCommands::PingProcess: pingProcess(messagePointer); break;
|
||||
|
@ -81,7 +90,7 @@ void Y2RService::pingProcess(u32 messagePointer) {
|
|||
log("Y2R::PingProcess\n");
|
||||
mem.write32(messagePointer, IPC::responseHeader(0x2A, 2, 0));
|
||||
mem.write32(messagePointer + 4, Result::Success);
|
||||
mem.write32(messagePointer + 8, 0); // Connected number
|
||||
mem.write32(messagePointer + 8, 0); // Connected number
|
||||
}
|
||||
|
||||
void Y2RService::driverInitialize(u32 messagePointer) {
|
||||
|
@ -98,8 +107,9 @@ void Y2RService::driverFinalize(u32 messagePointer) {
|
|||
|
||||
void Y2RService::getTransferEndEvent(u32 messagePointer) {
|
||||
log("Y2R::GetTransferEndEvent\n");
|
||||
if (!transferEndEvent.has_value())
|
||||
if (!transferEndEvent.has_value()) {
|
||||
transferEndEvent = kernel.makeEvent(ResetType::OneShot);
|
||||
}
|
||||
|
||||
mem.write32(messagePointer, IPC::responseHeader(0xF, 1, 2));
|
||||
mem.write32(messagePointer + 4, Result::Success);
|
||||
|
@ -150,6 +160,14 @@ void Y2RService::setBlockAlignment(u32 messagePointer) {
|
|||
mem.write32(messagePointer + 4, Result::Success);
|
||||
}
|
||||
|
||||
void Y2RService::getBlockAlignment(u32 messagePointer) {
|
||||
log("Y2R::GetBlockAlignment\n");
|
||||
|
||||
mem.write32(messagePointer, IPC::responseHeader(0x8, 2, 0));
|
||||
mem.write32(messagePointer + 4, Result::Success);
|
||||
mem.write32(messagePointer + 8, static_cast<u32>(alignment));
|
||||
}
|
||||
|
||||
void Y2RService::setInputFormat(u32 messagePointer) {
|
||||
const u32 format = mem.read32(messagePointer + 4);
|
||||
log("Y2R::SetInputFormat (format = %d)\n", format);
|
||||
|
@ -178,6 +196,14 @@ void Y2RService::setOutputFormat(u32 messagePointer) {
|
|||
mem.write32(messagePointer + 4, Result::Success);
|
||||
}
|
||||
|
||||
void Y2RService::getOutputFormat(u32 messagePointer) {
|
||||
log("Y2R::GetOutputFormat\n");
|
||||
|
||||
mem.write32(messagePointer, IPC::responseHeader(0x4, 2, 0));
|
||||
mem.write32(messagePointer + 4, Result::Success);
|
||||
mem.write32(messagePointer + 8, static_cast<u32>(outputFmt));
|
||||
}
|
||||
|
||||
void Y2RService::setPackageParameter(u32 messagePointer) {
|
||||
// Package parameter is 3 words
|
||||
const u32 word1 = mem.read32(messagePointer + 4);
|
||||
|
@ -243,6 +269,13 @@ void Y2RService::setInputLineWidth(u32 messagePointer) {
|
|||
}
|
||||
}
|
||||
|
||||
void Y2RService::getInputLineWidth(u32 messagePointer) {
|
||||
log("Y2R::GetInputLineWidth\n");
|
||||
|
||||
mem.write32(messagePointer, IPC::responseHeader(0x1B, 2, 0));
|
||||
mem.write32(messagePointer + 4, Result::Success);
|
||||
mem.write32(messagePointer + 8, inputLineWidth);
|
||||
}
|
||||
void Y2RService::setInputLines(u32 messagePointer) {
|
||||
const u16 lines = mem.read16(messagePointer + 4);
|
||||
log("Y2R::SetInputLines (lines = %d)\n", lines);
|
||||
|
@ -253,19 +286,30 @@ void Y2RService::setInputLines(u32 messagePointer) {
|
|||
Helpers::panic("Y2R: Invalid input line count");
|
||||
} else {
|
||||
// According to Citra, the Y2R module seems to accidentally skip setting the line # if it's 1024
|
||||
if (lines != 1024)
|
||||
if (lines != 1024) {
|
||||
inputLines = lines;
|
||||
}
|
||||
mem.write32(messagePointer + 4, Result::Success);
|
||||
}
|
||||
}
|
||||
|
||||
void Y2RService::getInputLines(u32 messagePointer) {
|
||||
log("Y2R::GetInputLines\n");
|
||||
|
||||
mem.write32(messagePointer, IPC::responseHeader(0x1D, 2, 0));
|
||||
mem.write32(messagePointer + 4, Result::Success);
|
||||
mem.write32(messagePointer + 8, inputLines);
|
||||
}
|
||||
|
||||
void Y2RService::setStandardCoeff(u32 messagePointer) {
|
||||
const u32 coeff = mem.read32(messagePointer + 4);
|
||||
log("Y2R::SetStandardCoeff (coefficient = %d)\n", coeff);
|
||||
mem.write32(messagePointer, IPC::responseHeader(0x20, 1, 0));
|
||||
|
||||
if (coeff > 3)
|
||||
Helpers::panic("Y2R: Invalid standard coefficient");
|
||||
if (coeff > 3) {
|
||||
Helpers::panic("Y2R: Invalid standard coefficient (coefficient = %d)\n", coeff);
|
||||
}
|
||||
|
||||
else {
|
||||
Helpers::warn("Unimplemented: Y2R standard coefficient");
|
||||
mem.write32(messagePointer + 4, Result::Success);
|
||||
|
@ -316,4 +360,4 @@ void Y2RService::startConversion(u32 messagePointer) {
|
|||
if (transferEndEvent.has_value()) {
|
||||
kernel.signalEvent(transferEndEvent.value());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue