Skip to content

Commit

Permalink
FS: Stub card SPI and some other things
Browse files Browse the repository at this point in the history
  • Loading branch information
wheremyfoodat committed Dec 9, 2024
1 parent 055dbc7 commit cc669d7
Show file tree
Hide file tree
Showing 12 changed files with 139 additions and 21 deletions.
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);
}
19 changes: 17 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,17 @@ void DSPService::invalidateDCache(u32 messagePointer) {
mem.write32(messagePointer + 4, Result::Success);
}

void DSPService::forceHeadphoneOut(u32 messagePointer) {
const bool force = mem.read8(messagePointer + 4) != 0;
if (force) {
headphonesInserted = false;
}

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

0 comments on commit cc669d7

Please sign in to comment.