Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

FS: Stub card SPI and some other things #675

Merged
merged 2 commits into from
Dec 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -338,7 +338,7 @@ set(LOADER_SOURCE_FILES src/core/loader/elf.cpp src/core/loader/ncsd.cpp src/cor
set(FS_SOURCE_FILES src/core/fs/archive_self_ncch.cpp src/core/fs/archive_save_data.cpp src/core/fs/archive_sdmc.cpp
src/core/fs/archive_ext_save_data.cpp src/core/fs/archive_ncch.cpp src/core/fs/romfs.cpp
src/core/fs/ivfc.cpp src/core/fs/archive_user_save_data.cpp src/core/fs/archive_system_save_data.cpp
src/core/fs/archive_twl_photo.cpp src/core/fs/archive_twl_sound.cpp
src/core/fs/archive_twl_photo.cpp src/core/fs/archive_twl_sound.cpp src/core/fs/archive_card_spi.cpp
)

set(APPLET_SOURCE_FILES src/core/applets/applet.cpp src/core/applets/mii_selector.cpp src/core/applets/software_keyboard.cpp src/core/applets/applet_manager.cpp
Expand Down Expand Up @@ -389,7 +389,7 @@ set(HEADER_FILES include/emulator.hpp include/helpers.hpp include/termcolor.hpp
include/align.hpp include/audio/aac_decoder.hpp include/PICA/pica_simd.hpp include/services/fonts.hpp
include/audio/audio_interpolation.hpp include/audio/hle_mixer.hpp include/audio/dsp_simd.hpp
include/services/dsp_firmware_db.hpp include/frontend_settings.hpp include/fs/archive_twl_photo.hpp
include/fs/archive_twl_sound.hpp
include/fs/archive_twl_sound.hpp include/fs/archive_card_spi.hpp
)

cmrc_add_resource_library(
Expand Down
1 change: 1 addition & 0 deletions include/fs/archive_base.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ namespace ArchiveID {
SDMC = 9,
SDMCWriteOnly = 0xA,

CardSPI = 0x12345679,
SavedataAndNcch = 0x2345678A,
// 3DBrew: This is the same as the regular SaveData archive, except with this the savedata ID and mediatype is loaded from the input archive
// lowpath.
Expand Down
30 changes: 30 additions & 0 deletions include/fs/archive_card_spi.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
#pragma once
#include "archive_base.hpp"
#include "result/result.hpp"

using Result::HorizonResult;

class CardSPIArchive : public ArchiveBase {
public:
CardSPIArchive(Memory& mem) : ArchiveBase(mem) {}
std::string name() override { return "Card SPI"; }

u64 getFreeBytes() override {
Helpers::warn("Unimplemented GetFreeBytes for Card SPI archive");
return 0_MB;
}

HorizonResult createDirectory(const FSPath& path) override;
HorizonResult createFile(const FSPath& path, u64 size) override;
HorizonResult deleteFile(const FSPath& path) override;

Rust::Result<ArchiveBase*, HorizonResult> openArchive(const FSPath& path) override;
Rust::Result<DirectorySession, HorizonResult> openDirectory(const FSPath& path) override;

FileDescriptor openFile(const FSPath& path, const FilePerms& perms) override;

std::optional<u32> readFile(FileSession* file, u64 offset, u32 size, u32 dataPointer) override {
Helpers::panic("Unimplemented ReadFile for Card SPI archive");
return {};
};
};
3 changes: 3 additions & 0 deletions include/services/dsp.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,12 @@ class DSPService {
size_t totalEventCount;
std::vector<u8> loadedComponent;

bool headphonesInserted = true;

// Service functions
void convertProcessAddressFromDspDram(u32 messagePointer); // Nice function name
void flushDataCache(u32 messagePointer);
void forceHeadphoneOut(u32 messagePointer);
void getHeadphoneStatus(u32 messagePointer);
void getSemaphoreEventHandle(u32 messagePointer);
void invalidateDCache(u32 messagePointer);
Expand Down
5 changes: 4 additions & 1 deletion include/services/fs.hpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#pragma once
#include "config.hpp"
#include "fs/archive_card_spi.hpp"
#include "fs/archive_ext_save_data.hpp"
#include "fs/archive_ncch.hpp"
#include "fs/archive_save_data.hpp"
Expand Down Expand Up @@ -43,6 +44,7 @@ class FSService {

TWLPhotoArchive twlPhoto;
TWLSoundArchive twlSound;
CardSPIArchive cardSpi;

ArchiveBase* getArchiveFromID(u32 id, const FSPath& archivePath);
Rust::Result<Handle, HorizonResult> openArchiveHandle(u32 archiveID, const FSPath& path);
Expand Down Expand Up @@ -92,7 +94,8 @@ class FSService {
FSService(Memory& mem, Kernel& kernel, const EmulatorConfig& config)
: mem(mem), saveData(mem), sharedExtSaveData_nand(mem, "../SharedFiles/NAND", true), extSaveData_sdmc(mem, "SDMC"), sdmc(mem),
sdmcWriteOnly(mem, true), selfNcch(mem), ncch(mem), userSaveData1(mem, ArchiveID::UserSaveData1),
userSaveData2(mem, ArchiveID::UserSaveData2), systemSaveData(mem), twlPhoto(mem), twlSound(mem), kernel(kernel), config(config) {}
userSaveData2(mem, ArchiveID::UserSaveData2), systemSaveData(mem), twlPhoto(mem), twlSound(mem), cardSpi(mem), kernel(kernel),
config(config) {}

void reset();
void handleSyncRequest(u32 messagePointer);
Expand Down
29 changes: 15 additions & 14 deletions include/services/gsp_gpu.hpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#pragma once
#include <cstring>
#include <optional>

#include "PICA/gpu.hpp"
#include "helpers.hpp"
#include "kernel_types.hpp"
Expand All @@ -9,12 +10,12 @@
#include "result/result.hpp"

enum class GPUInterrupt : u8 {
PSC0 = 0, // Memory fill completed
PSC1 = 1, // ?
VBlank0 = 2, // ?
VBlank1 = 3, // ?
PPF = 4, // Display transfer finished
P3D = 5, // Command list processing finished
PSC0 = 0, // Memory fill completed
PSC1 = 1, // ?
VBlank0 = 2, // ?
VBlank1 = 3, // ?
PPF = 4, // Display transfer finished
P3D = 5, // Command list processing finished
DMA = 6
};

Expand All @@ -28,8 +29,8 @@ class GPUService {
Memory& mem;
GPU& gpu;
Kernel& kernel;
u32& currentPID; // Process ID of the current process
u8* sharedMem; // Pointer to GSP shared memory
u32& currentPID; // Process ID of the current process
u8* sharedMem; // Pointer to GSP shared memory

// At any point in time only 1 process has privileges to use rendering functions
// This is the PID of that process
Expand Down Expand Up @@ -64,8 +65,8 @@ class GPUService {

// Used for saving and restoring GPU state via ImportDisplayCaptureInfo
struct CaptureInfo {
u32 leftFramebuffer; // Left framebuffer VA
u32 rightFramebuffer; // Right framebuffer VA (Top screen only)
u32 leftFramebuffer; // Left framebuffer VA
u32 rightFramebuffer; // Right framebuffer VA (Top screen only)
u32 format;
u32 stride;
};
Expand All @@ -74,6 +75,7 @@ class GPUService {
// Service commands
void acquireRight(u32 messagePointer);
void flushDataCache(u32 messagePointer);
void invalidateDataCache(u32 messagePointer);
void importDisplayCaptureInfo(u32 messagePointer);
void readHwRegs(u32 messagePointer);
void registerInterruptRelayQueue(u32 messagePointer);
Expand Down Expand Up @@ -108,15 +110,14 @@ class GPUService {
FramebufferUpdate* getTopFramebufferInfo() { return getFramebufferInfo(0); }
FramebufferUpdate* getBottomFramebufferInfo() { return getFramebufferInfo(1); }

public:
GPUService(Memory& mem, GPU& gpu, Kernel& kernel, u32& currentPID) : mem(mem), gpu(gpu),
kernel(kernel), currentPID(currentPID) {}
public:
GPUService(Memory& mem, GPU& gpu, Kernel& kernel, u32& currentPID) : mem(mem), gpu(gpu), kernel(kernel), currentPID(currentPID) {}
void reset();
void handleSyncRequest(u32 messagePointer);
void requestInterrupt(GPUInterrupt type);
void setSharedMem(u8* ptr) {
sharedMem = ptr;
if (ptr != nullptr) { // Zero-fill shared memory in case the process tries to read stale service data or vice versa
if (ptr != nullptr) { // Zero-fill shared memory in case the process tries to read stale service data or vice versa
std::memset(ptr, 0, 0x1000);
}
}
Expand Down
1 change: 1 addition & 0 deletions include/services/mcu/mcu_hwc.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ namespace MCU {

// Service commands
void getBatteryLevel(u32 messagePointer);
void setInfoLEDPattern(u32 messagePointer);

public:
HWCService(Memory& mem, const EmulatorConfig& config) : mem(mem), config(config) {}
Expand Down
40 changes: 40 additions & 0 deletions src/core/fs/archive_card_spi.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
#include <algorithm>
#include <memory>

#include "fs/archive_card_spi.hpp"

namespace fs = std::filesystem;

HorizonResult CardSPIArchive::createFile(const FSPath& path, u64 size) {
Helpers::panic("[Card SPI] CreateFile not yet supported");
return Result::Success;
}

HorizonResult CardSPIArchive::deleteFile(const FSPath& path) {
Helpers::panic("[Card SPI] Unimplemented DeleteFile");
return Result::Success;
}

HorizonResult CardSPIArchive::createDirectory(const FSPath& path) {
Helpers::panic("[Card SPI] CreateDirectory not yet supported");
return Result::Success;
}

FileDescriptor CardSPIArchive::openFile(const FSPath& path, const FilePerms& perms) {
Helpers::panic("[Card SPI] OpenFile not yet supported");
return FileError;
}

Rust::Result<ArchiveBase*, HorizonResult> CardSPIArchive::openArchive(const FSPath& path) {
if (path.type != PathType::Empty) {
Helpers::panic("Unimplemented path type for CardSPIArchive::OpenArchive");
}

Helpers::warn("Unimplemented: Card SPI archive");
return Err(Result::FailurePlaceholder);
}

Rust::Result<DirectorySession, HorizonResult> CardSPIArchive::openDirectory(const FSPath& path) {
Helpers::panic("[Card SPI] OpenDirectory not yet supported");
return Err(Result::FailurePlaceholder);
}
16 changes: 14 additions & 2 deletions src/core/services/dsp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,8 @@ namespace DSPCommands {
RegisterInterruptEvents = 0x00150082,
GetSemaphoreEventHandle = 0x00160000,
SetSemaphoreMask = 0x00170040,
GetHeadphoneStatus = 0x001F0000
GetHeadphoneStatus = 0x001F0000,
ForceHeadphoneOut = 0x00200040,
};
}

Expand All @@ -42,6 +43,7 @@ namespace Result {
void DSPService::reset() {
totalEventCount = 0;
semaphoreMask = 0;
headphonesInserted = true;

semaphoreEvent = std::nullopt;
interrupt0 = std::nullopt;
Expand All @@ -60,6 +62,7 @@ void DSPService::handleSyncRequest(u32 messagePointer) {
case DSPCommands::ConvertProcessAddressFromDspDram: convertProcessAddressFromDspDram(messagePointer); break;
case DSPCommands::FlushDataCache: flushDataCache(messagePointer); break;
case DSPCommands::InvalidateDataCache: invalidateDCache(messagePointer); break;
case DSPCommands::ForceHeadphoneOut: forceHeadphoneOut(messagePointer); break;
case DSPCommands::GetHeadphoneStatus: getHeadphoneStatus(messagePointer); break;
case DSPCommands::GetSemaphoreEventHandle: getSemaphoreEventHandle(messagePointer); break;
case DSPCommands::LoadComponent: loadComponent(messagePointer); break;
Expand Down Expand Up @@ -210,7 +213,8 @@ void DSPService::getHeadphoneStatus(u32 messagePointer) {

mem.write32(messagePointer, IPC::responseHeader(0x1F, 2, 0));
mem.write32(messagePointer + 4, Result::Success);
mem.write32(messagePointer + 8, Result::HeadphonesInserted); // This should be toggleable for shits and giggles
// This should be toggleable for shits and giggles
mem.write32(messagePointer + 8, headphonesInserted ? Result::HeadphonesInserted : Result::HeadphonesNotInserted);
}

void DSPService::getSemaphoreEventHandle(u32 messagePointer) {
Expand Down Expand Up @@ -278,6 +282,14 @@ void DSPService::invalidateDCache(u32 messagePointer) {
mem.write32(messagePointer + 4, Result::Success);
}

void DSPService::forceHeadphoneOut(u32 messagePointer) {
headphonesInserted = mem.read8(messagePointer + 4) != 0;

log("DSP::ForceHeadphoneOut\n");
mem.write32(messagePointer, IPC::responseHeader(0x20, 1, 0));
mem.write32(messagePointer + 4, Result::Success);
}

DSPService::ComponentDumpResult DSPService::dumpComponent(const std::filesystem::path& path) {
if (loadedComponent.empty()) {
return ComponentDumpResult::NotLoaded;
Expand Down
1 change: 1 addition & 0 deletions src/core/services/fs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ ArchiveBase* FSService::getArchiveFromID(u32 id, const FSPath& archivePath) {

case ArchiveID::TwlPhoto: return &twlPhoto;
case ArchiveID::TwlSound: return &twlSound;
case ArchiveID::CardSPI: return &cardSpi;

default:
Helpers::panic("Unknown archive. ID: %d\n", id);
Expand Down
14 changes: 13 additions & 1 deletion src/core/services/gsp_gpu.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,15 @@ namespace ServiceCommands {
WriteHwRegsWithMask = 0x00020084,
SetBufferSwap = 0x00050200,
FlushDataCache = 0x00080082,
InvalidateDataCache = 0x00090082,
SetLCDForceBlack = 0x000B0040,
TriggerCmdReqQueue = 0x000C0000,
ReleaseRight = 0x00170000,
ImportDisplayCaptureInfo = 0x00180000,
SaveVramSysArea = 0x00190000,
RestoreVramSysArea = 0x001A0000,
SetInternalPriorities = 0x001E0080,
StoreDataCache = 0x001F0082
StoreDataCache = 0x001F0082,
};
}

Expand Down Expand Up @@ -63,6 +64,7 @@ void GPUService::handleSyncRequest(u32 messagePointer) {
case ServiceCommands::ReadHwRegs: readHwRegs(messagePointer); break;
case ServiceCommands::WriteHwRegs: writeHwRegs(messagePointer); break;
case ServiceCommands::WriteHwRegsWithMask: writeHwRegsWithMask(messagePointer); break;
case ServiceCommands::InvalidateDataCache: invalidateDataCache(messagePointer); break;
default: Helpers::panic("GPU service requested. Command: %08X\n", command);
}
}
Expand Down Expand Up @@ -278,6 +280,16 @@ void GPUService::flushDataCache(u32 messagePointer) {
mem.write32(messagePointer + 4, Result::Success);
}

void GPUService::invalidateDataCache(u32 messagePointer) {
u32 address = mem.read32(messagePointer + 4);
u32 size = mem.read32(messagePointer + 8);
u32 processHandle = handle = mem.read32(messagePointer + 16);
log("GSP::GPU::InvalidateDataCache(address = %08X, size = %X, process = %X)\n", address, size, processHandle);

mem.write32(messagePointer, IPC::responseHeader(0x9, 1, 0));
mem.write32(messagePointer + 4, Result::Success);
}

void GPUService::storeDataCache(u32 messagePointer) {
u32 address = mem.read32(messagePointer + 4);
u32 size = mem.read32(messagePointer + 8);
Expand Down
13 changes: 12 additions & 1 deletion src/core/services/mcu/mcu_hwc.cpp
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
#include "services/mcu/mcu_hwc.hpp"

#include "ipc.hpp"
#include "result/result.hpp"
#include "services/mcu/mcu_hwc.hpp"

namespace MCU::HWCCommands {
enum : u32 {
GetBatteryLevel = 0x00050000,
SetInfoLedPattern = 0x000A0640,
};
}

Expand All @@ -14,6 +16,7 @@ void MCU::HWCService::handleSyncRequest(u32 messagePointer) {
const u32 command = mem.read32(messagePointer);
switch (command) {
case HWCCommands::GetBatteryLevel: getBatteryLevel(messagePointer); break;
case HWCCommands::SetInfoLedPattern: setInfoLEDPattern(messagePointer); break;
default: Helpers::panic("MCU::HWC service requested. Command: %08X\n", command);
}
}
Expand All @@ -24,4 +27,12 @@ void MCU::HWCService::getBatteryLevel(u32 messagePointer) {
mem.write32(messagePointer, IPC::responseHeader(0x5, 2, 0));
mem.write32(messagePointer + 4, Result::Success);
mem.write8(messagePointer + 8, config.batteryPercentage);
}

void MCU::HWCService::setInfoLEDPattern(u32 messagePointer) {
log("MCU::HWC::SetInfoLedPattern\n");

// 25 parameters to make some notification LEDs blink...
mem.write32(messagePointer, IPC::responseHeader(0xA, 1, 0));
mem.write32(messagePointer + 4, Result::Success);
}
Loading