mirror of
https://github.com/wheremyfoodat/Panda3DS.git
synced 2025-06-08 20:11:39 +12:00
Trongle
This commit is contained in:
parent
75070ca6ef
commit
be4fae5104
33 changed files with 341 additions and 70 deletions
|
@ -30,10 +30,6 @@ void GPU::reset() {
|
|||
// TODO: Reset blending, texturing, etc here
|
||||
}
|
||||
|
||||
void GPU::clearBuffer(u32 startAddress, u32 endAddress, u32 value, u32 control) {
|
||||
printf("GPU: Clear buffer\nStart: %08X End: %08X\nValue: %08X Control: %08X\n", startAddress, endAddress, value, control);
|
||||
}
|
||||
|
||||
void GPU::drawArrays(bool indexed) {
|
||||
if (indexed)
|
||||
drawArrays<true>();
|
||||
|
@ -48,13 +44,22 @@ void GPU::drawArrays() {
|
|||
const u32 vertexBase = ((regs[PICAInternalRegs::VertexAttribLoc] >> 1) & 0xfffffff) * 16;
|
||||
const u32 vertexCount = regs[PICAInternalRegs::VertexCountReg]; // Total # of vertices to transfer
|
||||
|
||||
// Configures the type of primitive and the number of vertex shader outputs
|
||||
const u32 primConfig = regs[PICAInternalRegs::PrimitiveConfig];
|
||||
const u32 primType = (primConfig >> 8) & 3;
|
||||
if (primType != 0) Helpers::panic("[PICA] Tried to draw non-triangle shape %d\n", primType);
|
||||
if (vertexCount % 3) Helpers::panic("[PICA] Vertex count not a multiple of 3");
|
||||
if (vertexCount > vertexBufferSize) Helpers::panic("[PICA] vertexCount > vertexBufferSize");
|
||||
|
||||
Vertex vertices[vertexBufferSize];
|
||||
|
||||
// Stuff the global attribute config registers in one u64 to make attr parsing easier
|
||||
// TODO: Cache this when the vertex attribute format registers are written to
|
||||
u64 vertexCfg = u64(regs[PICAInternalRegs::AttribFormatLow]) | (u64(regs[PICAInternalRegs::AttribFormatHigh]) << 32);
|
||||
|
||||
if constexpr (!indexed) {
|
||||
u32 offset = regs[PICAInternalRegs::VertexOffsetReg];
|
||||
printf("PICA::DrawArrays(vertex count = %d, vertexOffset = %d)\n", vertexCount, offset);
|
||||
log("PICA::DrawArrays(vertex count = %d, vertexOffset = %d)\n", vertexCount, offset);
|
||||
} else {
|
||||
Helpers::panic("[PICA] Indexed drawing");
|
||||
}
|
||||
|
@ -96,7 +101,6 @@ void GPU::drawArrays() {
|
|||
for (component = 0; component < componentCount; component++) {
|
||||
float val = *ptr++;
|
||||
attribute[component] = f24::fromFloat32(val);
|
||||
printf("Component %d: %f\n", component, (double)val);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -111,11 +115,13 @@ void GPU::drawArrays() {
|
|||
attribute[component] = (component == 3) ? f24::fromFloat32(1.0) : f24::fromFloat32(0.0);
|
||||
component++;
|
||||
}
|
||||
|
||||
printf("Attribute %d, type: %d, component count: %d\n", attrCount, attribType, componentCount);
|
||||
}
|
||||
}
|
||||
|
||||
shaderUnit.vs.run(); // Run vertex shader for vertex
|
||||
shaderUnit.vs.run();
|
||||
std::memcpy(&vertices[i].position, &shaderUnit.vs.outputs[0], sizeof(vec4f));
|
||||
std::memcpy(&vertices[i].colour, &shaderUnit.vs.outputs[1], sizeof(vec4f));
|
||||
}
|
||||
|
||||
drawVertices(OpenGL::Triangle, vertices, vertexCount);
|
||||
}
|
|
@ -4,7 +4,7 @@
|
|||
using namespace Floats;
|
||||
|
||||
u32 GPU::readReg(u32 address) {
|
||||
printf("Ignoring read from GPU register %08X\n", address);
|
||||
log("Ignoring read from GPU register %08X\n", address);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -13,13 +13,13 @@ void GPU::writeReg(u32 address, u32 value) {
|
|||
const u32 index = (address - 0x1EF01000) / sizeof(u32);
|
||||
writeInternalReg(index, value, 0xffffffff);
|
||||
} else {
|
||||
printf("Ignoring write to external GPU register %08X. Value: %08X\n", address, value);
|
||||
log("Ignoring write to external GPU register %08X. Value: %08X\n", address, value);
|
||||
}
|
||||
}
|
||||
|
||||
u32 GPU::readInternalReg(u32 index) {
|
||||
if (index > regNum) {
|
||||
printf("Tried to read invalid GPU register. Index: %X\n", index);
|
||||
Helpers::panic("Tried to read invalid GPU register. Index: %X\n", index);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -131,7 +131,7 @@ void GPU::writeInternalReg(u32 index, u32 value, u32 mask) {
|
|||
break;
|
||||
}
|
||||
} else {
|
||||
printf("GPU: Wrote to unimplemented internal reg: %X, value: %08X\n", index, newValue);
|
||||
log("GPU: Wrote to unimplemented internal reg: %X, value: %08X\n", index, newValue);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
160
src/core/PICA/renderer_opengl.cpp
Normal file
160
src/core/PICA/renderer_opengl.cpp
Normal file
|
@ -0,0 +1,160 @@
|
|||
#include "PICA/gpu.hpp"
|
||||
#include "opengl.hpp"
|
||||
|
||||
// This is all hacked up to display our first triangle
|
||||
|
||||
const char* vertexShader = R"(
|
||||
#version 420 core
|
||||
|
||||
layout (location = 0) in vec4 coords;
|
||||
layout (location = 1) in vec4 vertexColour;
|
||||
|
||||
out vec4 colour;
|
||||
|
||||
void main() {
|
||||
gl_Position = coords;
|
||||
colour = vertexColour;
|
||||
}
|
||||
)";
|
||||
|
||||
const char* fragmentShader = R"(
|
||||
#version 420 core
|
||||
|
||||
in vec4 colour;
|
||||
out vec4 fragColour;
|
||||
|
||||
void main() {
|
||||
fragColour = colour;
|
||||
}
|
||||
)";
|
||||
|
||||
const char* displayVertexShader = R"(
|
||||
#version 420 core
|
||||
out vec2 UV;
|
||||
|
||||
void main() {
|
||||
const vec4 positions[4] = vec4[](
|
||||
vec4(-1.0, 1.0, 1.0, 1.0), // Top-left
|
||||
vec4(1.0, 1.0, 1.0, 1.0), // Top-right
|
||||
vec4(-1.0, -1.0, 1.0, 1.0), // Bottom-left
|
||||
vec4(1.0, -1.0, 1.0, 1.0) // Bottom-right
|
||||
);
|
||||
|
||||
// The 3DS displays both screens' framebuffer rotated 90 deg counter clockwise
|
||||
// So we adjust our texcoords accordingly
|
||||
const vec2 texcoords[4] = vec2[](
|
||||
vec2(1.0, 1.0), // Top-right
|
||||
vec2(1.0, 0.0), // Bottom-right
|
||||
vec2(0.0, 1.0), // Top-left
|
||||
vec2(0.0, 0.0) // Bottom-left
|
||||
);
|
||||
|
||||
gl_Position = positions[gl_VertexID];
|
||||
UV = texcoords[gl_VertexID];
|
||||
}
|
||||
)";
|
||||
|
||||
const char* displayFragmentShader = R"(
|
||||
#version 420 core
|
||||
in vec2 UV;
|
||||
out vec4 FragColor;
|
||||
|
||||
uniform sampler2D u_texture; // TODO: Properly init this to 0 when I'm not lazy
|
||||
void main() {
|
||||
FragColor = texture(u_texture, UV);
|
||||
}
|
||||
)";
|
||||
|
||||
void GPU::initGraphicsContext() {
|
||||
// Set up texture for top screen
|
||||
fboTexture.create(400, 240, GL_RGBA8);
|
||||
fboTexture.bind();
|
||||
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
|
||||
fbo.createWithDrawTexture(fboTexture);
|
||||
fbo.bind(OpenGL::DrawFramebuffer);
|
||||
|
||||
OpenGL::setViewport(400, 240);
|
||||
OpenGL::setClearColor(0.0, 0.0, 0.0, 1.0);
|
||||
OpenGL::clearColor();
|
||||
|
||||
OpenGL::Shader vert(vertexShader, OpenGL::Vertex);
|
||||
OpenGL::Shader frag(fragmentShader, OpenGL::Fragment);
|
||||
triangleProgram.create({ vert, frag });
|
||||
|
||||
OpenGL::Shader vertDisplay(displayVertexShader, OpenGL::Vertex);
|
||||
OpenGL::Shader fragDisplay(displayFragmentShader, OpenGL::Fragment);
|
||||
displayProgram.create({ vertDisplay, fragDisplay });
|
||||
|
||||
vbo.createFixedSize(sizeof(Vertex) * vertexBufferSize, GL_STREAM_DRAW);
|
||||
vbo.bind();
|
||||
vao.create();
|
||||
vao.bind();
|
||||
|
||||
// Position (x, y, z, w) attributes
|
||||
vao.setAttributeFloat<float>(0, 4, sizeof(Vertex), offsetof(Vertex, position));
|
||||
vao.enableAttribute(0);
|
||||
// Colour attribute
|
||||
vao.setAttributeFloat<float>(1, 4, sizeof(Vertex), offsetof(Vertex, colour));
|
||||
vao.enableAttribute(1);
|
||||
|
||||
dummyVBO.create();
|
||||
dummyVAO.create();
|
||||
}
|
||||
|
||||
void GPU::getGraphicsContext() {
|
||||
OpenGL::disableDepth();
|
||||
OpenGL::disableScissor();
|
||||
OpenGL::setViewport(400, 240);
|
||||
fbo.bind(OpenGL::DrawAndReadFramebuffer);
|
||||
|
||||
vbo.bind();
|
||||
vao.bind();
|
||||
triangleProgram.use();
|
||||
}
|
||||
|
||||
void GPU::drawVertices(OpenGL::Primitives primType, Vertex* vertices, u32 count) {
|
||||
vbo.bufferVertsSub(vertices, count);
|
||||
OpenGL::draw(primType, count);
|
||||
}
|
||||
|
||||
constexpr u32 topScreenBuffer = 0x1f000000;
|
||||
constexpr u32 bottomScreenBuffer = 0x1f300000;
|
||||
|
||||
// Quick hack to display top screen for now
|
||||
void GPU::display() {
|
||||
OpenGL::disableScissor();
|
||||
OpenGL::bindScreenFramebuffer();
|
||||
fboTexture.bind();
|
||||
displayProgram.use();
|
||||
|
||||
dummyVBO.bind();
|
||||
dummyVAO.bind();
|
||||
OpenGL::setViewport(0, 240, 400, 240);
|
||||
|
||||
OpenGL::draw(OpenGL::TriangleStrip, 4);
|
||||
}
|
||||
|
||||
void GPU::clearBuffer(u32 startAddress, u32 endAddress, u32 value, u32 control) {
|
||||
log("GPU: Clear buffer\nStart: %08X End: %08X\nValue: %08X Control: %08X\n", startAddress, endAddress, value, control);
|
||||
|
||||
const float r = float((value >> 24) & 0xff) / 255.0;
|
||||
const float g = float((value >> 16) & 0xff) / 255.0;
|
||||
const float b = float((value >> 8) & 0xff) / 255.0;
|
||||
const float a = float(value & 0xff) / 255.0;
|
||||
|
||||
if (startAddress == topScreenBuffer) {
|
||||
log("GPU: Cleared top screen\n");
|
||||
} else if (startAddress == bottomScreenBuffer) {
|
||||
log("GPU: Tried to clear bottom screen\n");
|
||||
return;
|
||||
} else {
|
||||
log("GPU: Clearing some unknown buffer\n");
|
||||
}
|
||||
|
||||
OpenGL::setClearColor(r, g, b, a);
|
||||
OpenGL::clearColor();
|
||||
}
|
|
@ -37,7 +37,7 @@ void Kernel::arbitrateAddress() {
|
|||
const s32 value = s32(regs[3]);
|
||||
const s64 ns = s64(u64(regs[4]) | (u64(regs[5]) << 32));
|
||||
|
||||
printf("ArbitrateAddress(Handle = %X, address = %08X, type = %s, value = %d, ns = %lld)\n", handle, address,
|
||||
logSVC("ArbitrateAddress(Handle = %X, address = %08X, type = %s, value = %d, ns = %lld)\n", handle, address,
|
||||
arbitrationTypeToString(type), value, ns);
|
||||
|
||||
const auto arbiter = getObject(handle, KernelObjectType::AddressArbiter);
|
||||
|
@ -68,7 +68,7 @@ void Kernel::arbitrateAddress() {
|
|||
}
|
||||
|
||||
case ArbitrationType::Signal:
|
||||
printf("Broken ArbitrateAddress (type == SIGNAL)\n");
|
||||
logSVC("Broken ArbitrateAddress (type == SIGNAL)\n");
|
||||
switchThread(0);
|
||||
break;
|
||||
|
||||
|
|
|
@ -23,7 +23,7 @@ void Kernel::createEvent() {
|
|||
if (resetType > 2)
|
||||
Helpers::panic("Invalid reset type for event %d", resetType);
|
||||
|
||||
printf("CreateEvent(handle pointer = %08X, resetType = %s)\n", outPointer, resetTypeToString(resetType));
|
||||
logSVC("CreateEvent(handle pointer = %08X, resetType = %s)\n", outPointer, resetTypeToString(resetType));
|
||||
|
||||
regs[0] = SVCResult::Success;
|
||||
regs[1] = makeEvent(static_cast<ResetType>(resetType));
|
||||
|
@ -33,7 +33,7 @@ void Kernel::createEvent() {
|
|||
void Kernel::clearEvent() {
|
||||
const Handle handle = regs[0];
|
||||
const auto event = getObject(handle, KernelObjectType::Event);
|
||||
printf("ClearEvent(event handle = %d)\n", handle);
|
||||
logSVC("ClearEvent(event handle = %d)\n", handle);
|
||||
|
||||
if (event == nullptr) [[unlikely]] {
|
||||
regs[0] = SVCResult::BadHandle;
|
||||
|
@ -56,8 +56,6 @@ void Kernel::waitSynchronization1() {
|
|||
return;
|
||||
}
|
||||
|
||||
printf("WaitSynchronization1(handle = %X, ns = %lld) (STUBBED)\n", handle, ns);
|
||||
serviceManager.requestGPUInterrupt(GPUInterrupt::VBlank0);
|
||||
serviceManager.requestGPUInterrupt(GPUInterrupt::VBlank1);
|
||||
logSVC("WaitSynchronization1(handle = %X, ns = %lld) (STUBBED)\n", handle, ns);
|
||||
regs[0] = SVCResult::Success;
|
||||
}
|
|
@ -118,13 +118,13 @@ u32 Kernel::getTLSPointer() {
|
|||
|
||||
// Result CloseHandle(Handle handle)
|
||||
void Kernel::svcCloseHandle() {
|
||||
printf("CloseHandle(handle = %d) (Unimplemented)\n", regs[0]);
|
||||
logSVC("CloseHandle(handle = %d) (Unimplemented)\n", regs[0]);
|
||||
regs[0] = SVCResult::Success;
|
||||
}
|
||||
|
||||
// u64 GetSystemTick()
|
||||
void Kernel::getSystemTick() {
|
||||
printf("GetSystemTick()\n");
|
||||
logSVC("GetSystemTick()\n");
|
||||
|
||||
u64 ticks = cpu.getTicks();
|
||||
regs[0] = u32(ticks);
|
||||
|
@ -138,7 +138,7 @@ void Kernel::outputDebugString() {
|
|||
const u32 size = regs[1];
|
||||
|
||||
std::string message = mem.readString(pointer, size);
|
||||
printf("[OutputDebugString] %s\n", message.c_str());
|
||||
logSVC("[OutputDebugString] %s\n", message.c_str());
|
||||
regs[0] = SVCResult::Success;
|
||||
}
|
||||
|
||||
|
@ -147,7 +147,7 @@ void Kernel::getProcessInfo() {
|
|||
const auto pid = regs[1];
|
||||
const auto type = regs[2];
|
||||
const auto process = getProcessFromPID(pid);
|
||||
printf("GetProcessInfo(process: %s, type = %d)\n", getProcessName(pid).c_str(), type);
|
||||
logSVC("GetProcessInfo(process: %s, type = %d)\n", getProcessName(pid).c_str(), type);
|
||||
|
||||
if (process == nullptr) [[unlikely]] {
|
||||
regs[0] = SVCResult::BadHandle;
|
||||
|
@ -170,7 +170,7 @@ void Kernel::getProcessInfo() {
|
|||
// Result GetThreadId(u32* threadId, Handle thread)
|
||||
void Kernel::duplicateHandle() {
|
||||
Handle original = regs[1];
|
||||
printf("DuplicateHandle(handle = %X)\n", original);
|
||||
logSVC("DuplicateHandle(handle = %X)\n", original);
|
||||
|
||||
if (original == KernelHandles::CurrentThread) {
|
||||
printf("[Warning] Duplicated current thread. This might be horribly broken!\n");
|
||||
|
|
|
@ -49,7 +49,7 @@ void Kernel::controlMemory() {
|
|||
Helpers::panic("ControlMemory: Unaligned parameters\nAddr0: %08X\nAddr1: %08X\nSize: %08X", addr0, addr1, size);
|
||||
}
|
||||
|
||||
printf("ControlMemory(addr0 = %08X, addr1 = %08X, size = %08X, operation = %X (%c%c%c)%s\n",
|
||||
logSVC("ControlMemory(addr0 = %08X, addr1 = %08X, size = %08X, operation = %X (%c%c%c)%s\n",
|
||||
addr0, addr1, size, operation, r ? 'r' : '-', w ? 'w' : '-', x ? 'x' : '-', linear ? ", linear" : ""
|
||||
);
|
||||
|
||||
|
@ -75,7 +75,7 @@ void Kernel::queryMemory() {
|
|||
const u32 pageInfo = regs[1];
|
||||
const u32 addr = regs[2];
|
||||
|
||||
printf("QueryMemory(mem info pointer = %08X, page info pointer = %08X, addr = %08X)\n", memInfo, pageInfo, addr);
|
||||
logSVC("QueryMemory(mem info pointer = %08X, page info pointer = %08X, addr = %08X)\n", memInfo, pageInfo, addr);
|
||||
|
||||
const auto info = mem.queryMemory(addr);
|
||||
regs[0] = SVCResult::Success;
|
||||
|
@ -92,7 +92,7 @@ void Kernel::mapMemoryBlock() {
|
|||
const u32 addr = regs[1];
|
||||
const u32 myPerms = regs[2];
|
||||
const u32 otherPerms = regs[3];
|
||||
printf("MapMemoryBlock(block = %d, addr = %08X, myPerms = %X, otherPerms = %X\n", block, addr, myPerms, otherPerms);
|
||||
logSVC("MapMemoryBlock(block = %d, addr = %08X, myPerms = %X, otherPerms = %X\n", block, addr, myPerms, otherPerms);
|
||||
|
||||
if (!isAligned(addr)) [[unlikely]] {
|
||||
Helpers::panic("MapMemoryBlock: Unaligned address");
|
||||
|
|
|
@ -56,7 +56,7 @@ void Kernel::connectToPort() {
|
|||
}
|
||||
|
||||
Handle portHandle = optionalHandle.value();
|
||||
printf("ConnectToPort(handle pointer = %X, port = \"%s\")\n", handlePointer, port.c_str());
|
||||
logSVC("ConnectToPort(handle pointer = %X, port = \"%s\")\n", handlePointer, port.c_str());
|
||||
|
||||
const auto portData = objects[portHandle].getData<Port>();
|
||||
if (!portData->isPublic) {
|
||||
|
@ -76,7 +76,7 @@ void Kernel::sendSyncRequest() {
|
|||
const auto handle = regs[0];
|
||||
u32 messagePointer = getTLSPointer() + 0x80; // The message is stored starting at TLS+0x80
|
||||
|
||||
printf("SendSyncRequest(session handle = %X)\n", handle);
|
||||
logSVC("SendSyncRequest(session handle = %X)\n", handle);
|
||||
|
||||
// The sync request is being sent at a service rather than whatever port, so have the service manager intercept it
|
||||
if (KernelHandles::isServiceHandle(handle)) {
|
||||
|
|
|
@ -7,7 +7,7 @@ void Kernel::getResourceLimit() {
|
|||
const auto handlePointer = regs[0];
|
||||
const auto pid = regs[1];
|
||||
const auto process = getProcessFromPID(pid);
|
||||
printf("GetResourceLimit (handle pointer = %08X, process: %s)\n", handlePointer, getProcessName(pid).c_str());
|
||||
logSVC("GetResourceLimit (handle pointer = %08X, process: %s)\n", handlePointer, getProcessName(pid).c_str());
|
||||
|
||||
if (process == nullptr) [[unlikely]] {
|
||||
regs[0] = SVCResult::BadHandle;
|
||||
|
@ -33,7 +33,7 @@ void Kernel::getResourceLimitLimitValues() {
|
|||
return;
|
||||
}
|
||||
|
||||
printf("GetResourceLimitLimitValues(values = %08X, handle = %X, names = %08X, count = %d)\n", values, resourceLimit, names, count);
|
||||
logSVC("GetResourceLimitLimitValues(values = %08X, handle = %X, names = %08X, count = %d)\n", values, resourceLimit, names, count);
|
||||
// printf("[Warning] We do not currently support any resource maximum aside from the application ones");
|
||||
while (count != 0) {
|
||||
const u32 name = mem.read32(names);
|
||||
|
@ -62,7 +62,7 @@ void Kernel::getResourceLimitCurrentValues() {
|
|||
return;
|
||||
}
|
||||
|
||||
printf("GetResourceLimitCurrentValues(values = %08X, handle = %X, names = %08X, count = %d)\n", values, resourceLimit, names, count);
|
||||
logSVC("GetResourceLimitCurrentValues(values = %08X, handle = %X, names = %08X, count = %d)\n", values, resourceLimit, names, count);
|
||||
while (count != 0) {
|
||||
const u32 name = mem.read32(names);
|
||||
// TODO: Unsure if this is supposed to be s32 or u32. Shouldn't matter as the kernel can't create so many resources
|
||||
|
|
|
@ -75,7 +75,7 @@ void Kernel::createThread() {
|
|||
u32 initialSP = regs[3] & ~7; // SP is force-aligned to 8 bytes
|
||||
s32 id = static_cast<s32>(regs[4]);
|
||||
|
||||
printf("CreateThread(entry = %08X, stacktop = %08X, priority = %X, processor ID = %d)\n", entrypoint,
|
||||
logSVC("CreateThread(entry = %08X, stacktop = %08X, priority = %X, processor ID = %d)\n", entrypoint,
|
||||
initialSP, priority, id);
|
||||
|
||||
if (priority > 0x3F) [[unlikely]] {
|
||||
|
@ -99,7 +99,7 @@ void Kernel::sleepThreadOnArbiter(u32 waitingAddress) {
|
|||
|
||||
void Kernel::getThreadID() {
|
||||
Handle handle = regs[1];
|
||||
printf("GetThreadID(handle = %X)\n", handle);
|
||||
logSVC("GetThreadID(handle = %X)\n", handle);
|
||||
|
||||
if (handle == KernelHandles::CurrentThread) {
|
||||
regs[0] = SVCResult::Success;
|
||||
|
|
|
@ -24,7 +24,7 @@ void APTService::handleSyncRequest(u32 messagePointer) {
|
|||
}
|
||||
|
||||
void APTService::getLockHandle(u32 messagePointer) {
|
||||
printf("APT::GetLockHandle (Failure)\n");
|
||||
log("APT::GetLockHandle (Failure)\n");
|
||||
mem.write32(messagePointer + 4, Result::Failure); // Result code
|
||||
mem.write32(messagePointer + 16, 0); // Translation descriptor
|
||||
}
|
|
@ -26,11 +26,11 @@ void FSService::handleSyncRequest(u32 messagePointer) {
|
|||
}
|
||||
|
||||
void FSService::initialize(u32 messagePointer) {
|
||||
printf("FS::Initialize (failure)\n");
|
||||
log("FS::Initialize (failure)\n");
|
||||
mem.write32(messagePointer + 4, Result::Failure);
|
||||
}
|
||||
|
||||
void FSService::openArchive(u32 messagePointer) {
|
||||
printf("FS::OpenArchive (failure)\n");
|
||||
log("FS::OpenArchive (failure)\n");
|
||||
mem.write32(messagePointer + 4, Result::Failure);
|
||||
}
|
|
@ -14,10 +14,11 @@ namespace ServiceCommands {
|
|||
}
|
||||
|
||||
// Commands written to shared memory and processed by TriggerCmdReqQueue
|
||||
namespace GPUCommands {
|
||||
namespace GXCommands {
|
||||
enum : u32 {
|
||||
ProcessCommandList = 1,
|
||||
MemoryFill = 2
|
||||
MemoryFill = 2,
|
||||
TriggerDisplayTransfer = 3
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -50,7 +51,7 @@ void GPUService::handleSyncRequest(u32 messagePointer) {
|
|||
void GPUService::acquireRight(u32 messagePointer) {
|
||||
const u32 flag = mem.read32(messagePointer + 4);
|
||||
const u32 pid = mem.read32(messagePointer + 12);
|
||||
printf("GSP::GPU::AcquireRight (flag = %X, pid = %X)\n", flag, pid);
|
||||
log("GSP::GPU::AcquireRight (flag = %X, pid = %X)\n", flag, pid);
|
||||
|
||||
if (flag != 0) {
|
||||
Helpers::panic("GSP::GPU::acquireRight with flag != 0 needs to perform additional initialization");
|
||||
|
@ -76,7 +77,7 @@ void GPUService::registerInterruptRelayQueue(u32 messagePointer) {
|
|||
|
||||
const u32 flags = mem.read32(messagePointer + 4);
|
||||
const u32 eventHandle = mem.read32(messagePointer + 12);
|
||||
printf("GSP::GPU::RegisterInterruptRelayQueue (flags = %X, event handle = %X)\n", flags, eventHandle);
|
||||
log("GSP::GPU::RegisterInterruptRelayQueue (flags = %X, event handle = %X)\n", flags, eventHandle);
|
||||
|
||||
mem.write32(messagePointer + 4, Result::SuccessRegisterIRQ);
|
||||
mem.write32(messagePointer + 8, 0); // TODO: GSP module thread index
|
||||
|
@ -101,7 +102,7 @@ void GPUService::writeHwRegs(u32 messagePointer) {
|
|||
u32 ioAddr = mem.read32(messagePointer + 4); // GPU address based at 0x1EB00000, word aligned
|
||||
const u32 size = mem.read32(messagePointer + 8); // Size in bytes
|
||||
u32 dataPointer = mem.read32(messagePointer + 16);
|
||||
printf("GSP::GPU::writeHwRegs (GPU address = %08X, size = %X, data address = %08X)\n", ioAddr, size, dataPointer);
|
||||
log("GSP::GPU::writeHwRegs (GPU address = %08X, size = %X, data address = %08X)\n", ioAddr, size, dataPointer);
|
||||
|
||||
// Check for alignment
|
||||
if ((size & 3) || (ioAddr & 3) || (dataPointer & 3)) {
|
||||
|
@ -135,7 +136,7 @@ void GPUService::writeHwRegsWithMask(u32 messagePointer) {
|
|||
u32 dataPointer = mem.read32(messagePointer + 16); // Data pointer
|
||||
u32 maskPointer = mem.read32(messagePointer + 24); // Mask pointer
|
||||
|
||||
printf("GSP::GPU::writeHwRegsWithMask (GPU address = %08X, size = %X, data address = %08X, mask address = %08X)\n",
|
||||
log("GSP::GPU::writeHwRegsWithMask (GPU address = %08X, size = %X, data address = %08X, mask address = %08X)\n",
|
||||
ioAddr, size, dataPointer, maskPointer);
|
||||
|
||||
// Check for alignment
|
||||
|
@ -172,14 +173,14 @@ void GPUService::flushDataCache(u32 messagePointer) {
|
|||
u32 address = mem.read32(messagePointer + 4);
|
||||
u32 size = mem.read32(messagePointer + 8);
|
||||
u32 processHandle = handle = mem.read32(messagePointer + 16);
|
||||
printf("GSP::GPU::FlushDataCache(address = %08X, size = %X, process = %X\n", address, size, processHandle);
|
||||
log("GSP::GPU::FlushDataCache(address = %08X, size = %X, process = %X\n", address, size, processHandle);
|
||||
|
||||
mem.write32(messagePointer + 4, Result::Success);
|
||||
}
|
||||
|
||||
void GPUService::setLCDForceBlack(u32 messagePointer) {
|
||||
u32 flag = mem.read32(messagePointer + 4);
|
||||
printf("GSP::GPU::SetLCDForceBlank(flag = %d)\n", flag);
|
||||
log("GSP::GPU::SetLCDForceBlank(flag = %d)\n", flag);
|
||||
|
||||
if (flag != 0) {
|
||||
printf("Filled both LCDs with black\n");
|
||||
|
@ -193,9 +194,6 @@ void GPUService::triggerCmdReqQueue(u32 messagePointer) {
|
|||
mem.write32(messagePointer + 4, Result::Success);
|
||||
}
|
||||
|
||||
#include <chrono>
|
||||
#include <thread>
|
||||
using namespace std::chrono_literals;
|
||||
void GPUService::processCommandBuffer() {
|
||||
if (sharedMem == nullptr) [[unlikely]] { // Shared memory hasn't been set up yet
|
||||
return;
|
||||
|
@ -208,14 +206,14 @@ void GPUService::processCommandBuffer() {
|
|||
// Commands start at byte 0x20 of the command buffer, each being 0x20 bytes long
|
||||
u32* cmd = reinterpret_cast<u32*>(&cmdBuffer[0x20]);
|
||||
|
||||
printf("Processing %d GPU commands\n", commandsLeft);
|
||||
std::this_thread::sleep_for(1000ms);
|
||||
log("Processing %d GPU commands\n", commandsLeft);
|
||||
|
||||
while (commandsLeft != 0) {
|
||||
u32 cmdID = cmd[0] & 0xff;
|
||||
switch (cmdID) {
|
||||
case GPUCommands::ProcessCommandList: processCommandList(cmd); break;
|
||||
case GPUCommands::MemoryFill: memoryFill(cmd); break;
|
||||
case GXCommands::ProcessCommandList: processCommandList(cmd); break;
|
||||
case GXCommands::MemoryFill: memoryFill(cmd); break;
|
||||
case GXCommands::TriggerDisplayTransfer: triggerDisplayTransfer(cmd); break;
|
||||
default: Helpers::panic("GSP::GPU::ProcessCommands: Unknown cmd ID %d", cmdID);
|
||||
}
|
||||
|
||||
|
@ -249,6 +247,11 @@ void GPUService::memoryFill(u32* cmd) {
|
|||
}
|
||||
}
|
||||
|
||||
void GPUService::triggerDisplayTransfer(u32* cmd) {
|
||||
log("GSP::GPU::TriggerDisplayTransfer (Stubbed)\n");
|
||||
requestInterrupt(GPUInterrupt::PPF); // Send "Display transfer finished" interrupt
|
||||
}
|
||||
|
||||
// Actually send command list (aka display list) to GPU
|
||||
void GPUService::processCommandList(u32* cmd) {
|
||||
u32 address = cmd[1] & ~7; // Buffer address
|
||||
|
@ -305,5 +308,6 @@ void GPUService::processCommandList(u32* cmd) {
|
|||
}
|
||||
}
|
||||
|
||||
printf("GPU::GSP::processCommandList. Address: %08X, size in bytes: %08X\n", address, size);
|
||||
log("GPU::GSP::processCommandList. Address: %08X, size in bytes: %08X\n", address, size);
|
||||
requestInterrupt(GPUInterrupt::P3D); // Send an IRQ when command list processing is over
|
||||
}
|
|
@ -24,7 +24,7 @@ void HIDService::handleSyncRequest(u32 messagePointer) {
|
|||
}
|
||||
|
||||
void HIDService::getIPCHandles(u32 messagePointer) {
|
||||
printf("HID::GetIPCHandles (Failure)\n");
|
||||
log("HID::GetIPCHandles (Failure)\n");
|
||||
mem.write32(messagePointer + 4, Result::Failure); // Result code
|
||||
mem.write32(messagePointer + 8, 0x14000000); // Translation descriptor
|
||||
}
|
|
@ -25,11 +25,11 @@ void NDMService::handleSyncRequest(u32 messagePointer) {
|
|||
}
|
||||
|
||||
void NDMService::overrideDefaultDaemons(u32 messagePointer) {
|
||||
printf("NDM::OverrideDefaultDaemons(stubbed)\n");
|
||||
log("NDM::OverrideDefaultDaemons(stubbed)\n");
|
||||
mem.write32(messagePointer + 4, Result::Success);
|
||||
}
|
||||
|
||||
void NDMService::suspendDaemons(u32 messagePointer) {
|
||||
printf("NDM::SuspendDaemons(stubbed)\n");
|
||||
log("NDM::SuspendDaemons(stubbed)\n");
|
||||
mem.write32(messagePointer + 4, Result::Success);
|
||||
}
|
|
@ -54,7 +54,7 @@ void ServiceManager::handleSyncRequest(u32 messagePointer) {
|
|||
|
||||
// https://www.3dbrew.org/wiki/SRV:RegisterClient
|
||||
void ServiceManager::registerClient(u32 messagePointer) {
|
||||
printf("srv::registerClient (Stubbed)\n");
|
||||
log("srv::registerClient (Stubbed)\n");
|
||||
mem.write32(messagePointer + 4, Result::Success);
|
||||
}
|
||||
|
||||
|
@ -65,7 +65,7 @@ void ServiceManager::getServiceHandle(u32 messagePointer) {
|
|||
u32 handle = 0;
|
||||
|
||||
std::string service = mem.readString(messagePointer + 4, 8);
|
||||
printf("srv::getServiceHandle (Service: %s, nameLength: %d, flags: %d)\n", service.c_str(), nameLength, flags);
|
||||
log("srv::getServiceHandle (Service: %s, nameLength: %d, flags: %d)\n", service.c_str(), nameLength, flags);
|
||||
|
||||
if (service == "APT:S") {
|
||||
handle = KernelHandles::APT;
|
||||
|
@ -90,7 +90,7 @@ void ServiceManager::getServiceHandle(u32 messagePointer) {
|
|||
}
|
||||
|
||||
void ServiceManager::enableNotification(u32 messagePointer) {
|
||||
printf("srv::EnableNotification()\n");
|
||||
log("srv::EnableNotification()\n");
|
||||
|
||||
mem.write32(messagePointer + 4, Result::Success); // Result code
|
||||
mem.write32(messagePointer + 8, 0); // Translation descriptor
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue