From e120a3dc0f42b204a24b54a6704418d75b780681 Mon Sep 17 00:00:00 2001 From: "Nicolas \"Pixel\" Noble" Date: Wed, 23 Oct 2024 20:28:16 -0700 Subject: [PATCH] VSCode extension work - Adding psyqo cube example - Adding darwin arm support for pcsx-redux --- tools/vscode-extension/README.md | 4 +- tools/vscode-extension/pcsx-redux.js | 10 +- tools/vscode-extension/templates.js | 27 +++ .../templates/psyqo/cube/Makefile | 7 + .../templates/psyqo/cube/compile_flags.txt | 7 + .../templates/psyqo/cube/main.cpp | 197 ++++++++++++++++++ 6 files changed, 249 insertions(+), 3 deletions(-) create mode 100644 tools/vscode-extension/templates/psyqo/cube/Makefile create mode 100644 tools/vscode-extension/templates/psyqo/cube/compile_flags.txt create mode 100644 tools/vscode-extension/templates/psyqo/cube/main.cpp diff --git a/tools/vscode-extension/README.md b/tools/vscode-extension/README.md index 643f20173..242b1b72c 100644 --- a/tools/vscode-extension/README.md +++ b/tools/vscode-extension/README.md @@ -13,7 +13,6 @@ The panel will have the ability to install the tools on the most popular platfor - The extension is currently only targeting Windows, Linux Ubuntu, Arch Linux, and MacOS. It may work on more platforms, but it's not guaranteed, and won't be as automated as it is on the supported platforms. - Only Windows and Linux Ubuntu have been thoroughly tested for now. - The extension will not work from the browser as it requires running external tools. It may work in a remote SSH session, but it's not been tested. -- The PCSX-Redux dependency is currently only available on x86_64 platforms, and may possibly work on M1/M2 Macs. - Linux requires libfuse2 to be installed, for AppImages like the PCSX-Redux dependency to work. - The PCSX-Redux workflow won't check for system-wide installations, and will always install the dependency locally. @@ -21,6 +20,9 @@ The panel will have the ability to install the tools on the most popular platfor - 0.3.8 - Added automatic setup of Python virtual environments in order to reflect the changes in ps1-bare-metal. + - Fixed compile_flags.txt in template file. + - Added psyqo cube example. + - Added download support for Darwin ARM64 (M1/M2/etc) for PCSX-Redux. - 0.3.7 - Bumping gcc to 14.2.0 - Bumping binutils to 2.43 diff --git a/tools/vscode-extension/pcsx-redux.js b/tools/vscode-extension/pcsx-redux.js index 318ebd09f..5018713da 100644 --- a/tools/vscode-extension/pcsx-redux.js +++ b/tools/vscode-extension/pcsx-redux.js @@ -27,9 +27,13 @@ const updateInfo = { infoBase: 'https://distrib.app/storage/manifests/pcsx-redux/dev-linux-x64/', fileType: 'zip' }, - darwin: { + darwin_Intel: { infoBase: 'https://distrib.app/storage/manifests/pcsx-redux/dev-macos-x64/', fileType: 'dmg' + }, + darwin_Arm: { + infoBase: 'https://distrib.app/storage/manifests/pcsx-redux/dev-macos-arm/', + fileType: 'dmg' } } @@ -101,7 +105,9 @@ exports.install = async () => { } } - const updateInfoForPlatform = updateInfo[process.platform] + const darwinArch = process.arch === 'arm64' ? 'Arm' : 'Intel' + const platform = process.platform === 'darwin' ? 'darwin_' + darwinArch : process.platform + const updateInfoForPlatform = updateInfo[platform] const outputDir = process.platform === 'win32' ? vscode.Uri.joinPath(globalStorageUri, 'pcsx-redux').fsPath diff --git a/tools/vscode-extension/templates.js b/tools/vscode-extension/templates.js index fd505e085..f9e6436d6 100644 --- a/tools/vscode-extension/templates.js +++ b/tools/vscode-extension/templates.js @@ -767,6 +767,33 @@ const templates = { ) } }, + psyqo_cube: { + name: 'PSYQo Cube', + category: 'PSYQo SDK', + description: 'A project featuring a rotating cube using the PSYQo SDK.', + url: 'https://github.com/pcsx-redux/nugget/tree/main/psyqo#how', + examples: + 'https://github.com/grumpycoders/pcsx-redux/tree/main/src/mips/psyqo/examples', + requiredTools: ['git', 'make', 'toolchain'], + recommendedTools: ['gdb', 'debugger', 'redux'], + create: async function (fullPath, name, progressReporter) { + const git = await createGitRepository( + fullPath, + psyqoTemplate, + progressReporter + ) + await copyTemplateDirectory( + git, + fullPath, + name, + [ + path.join(extensionUri.fsPath, 'templates', 'common'), + path.join(extensionUri.fsPath, 'templates', 'psyqo', 'cube') + ], + { projectName: name, isCMake: false } + ) + } + }, psyq_netyaroze: { name: 'Net Yaroze Sprite', category: 'Psy-Q SDK', diff --git a/tools/vscode-extension/templates/psyqo/cube/Makefile b/tools/vscode-extension/templates/psyqo/cube/Makefile new file mode 100644 index 000000000..7936fcd0c --- /dev/null +++ b/tools/vscode-extension/templates/psyqo/cube/Makefile @@ -0,0 +1,7 @@ +TARGET = {{projectName}} +TYPE = ps-exe + +SRCS = \ +main.cpp + +include third_party/nugget/psyqo/psyqo.mk diff --git a/tools/vscode-extension/templates/psyqo/cube/compile_flags.txt b/tools/vscode-extension/templates/psyqo/cube/compile_flags.txt new file mode 100644 index 000000000..a0d792fec --- /dev/null +++ b/tools/vscode-extension/templates/psyqo/cube/compile_flags.txt @@ -0,0 +1,7 @@ +-m32 +-std=c++20 +-fcoroutines-ts +-I. +-Ithird_party/nugget +-Ithird_party/nugget/third_party/EASTL/include +-Ithird_party/nugget/third_party/EABase/include/Common diff --git a/tools/vscode-extension/templates/psyqo/cube/main.cpp b/tools/vscode-extension/templates/psyqo/cube/main.cpp new file mode 100644 index 000000000..2a439c2f4 --- /dev/null +++ b/tools/vscode-extension/templates/psyqo/cube/main.cpp @@ -0,0 +1,197 @@ +{{=<% %>=}}#include "psyqo/application.hh" +#include "psyqo/fixed-point.hh" +#include "psyqo/fragments.hh" +#include "psyqo/gpu.hh" +#include "psyqo/gte-kernels.hh" +#include "psyqo/gte-registers.hh" +#include "psyqo/primitives/common.hh" +#include "psyqo/primitives/quads.hh" +#include "psyqo/scene.hh" +#include "psyqo/soft-math.hh" +#include "psyqo/trigonometry.hh" +#include "psyqo/vector.hh" + +using namespace psyqo::fixed_point_literals; +using namespace psyqo::trig_literals; + +static constexpr unsigned NUM_CUBE_VERTICES = 8; +static constexpr unsigned NUM_CUBE_FACES = 6; +static constexpr unsigned ORDERING_TABLE_SIZE = 240; + +typedef struct { + uint8_t vertices[4]; + psyqo::Color color; +} Face; + +static constexpr psyqo::Matrix33 identity = {{ + {1.0_fp, 0.0_fp, 0.0_fp}, + {0.0_fp, 1.0_fp, 0.0_fp}, + {0.0_fp, 0.0_fp, 1.0_fp}, +}}; + +class Cube final : public psyqo::Application { + void prepare() override; + void createScene() override; + + public: + psyqo::Trig<> m_trig; +}; + +class CubeScene final : public psyqo::Scene { + void start(StartReason reason) override; + void frame() override; + + psyqo::Angle m_rot = 0; + + // We need to create 2 OrderingTable objects since we can't reuse a single one for both + // framebuffers, as the previous one may not finish transfering in time. + psyqo::OrderingTable m_ots[2]; + + // Since we're using an ordering table, we need to sort fill commands as well, + // otherwise they'll draw over our beautiful cube. + psyqo::Fragments::SimpleFragment m_clear[2]; + + eastl::array, 6> m_quads; + + static constexpr psyqo::Color c_bg = {.r = 63, .g = 63, .b = 63}; + + static constexpr psyqo::Vec3 c_cubeVertices[NUM_CUBE_VERTICES] = { + {.x = -0.05, .y = -0.05, .z = -0.05}, {.x = 0.05, .y = -0.05, .z = -0.05}, {.x = -0.05, .y = 0.05, .z = -0.05}, + {.x = 0.05, .y = 0.05, .z = -0.05}, {.x = -0.05, .y = -0.05, .z = 0.05}, {.x = 0.05, .y = -0.05, .z = 0.05}, + {.x = -0.05, .y = 0.05, .z = 0.05}, {.x = 0.05, .y = 0.05, .z = 0.05}}; + + static constexpr Face c_cubeFaces[NUM_CUBE_FACES] = { + {.vertices = {0, 1, 2, 3}, .color = {0, 0, 255}}, {.vertices = {6, 7, 4, 5}, .color = {0, 255, 0}}, + {.vertices = {4, 5, 0, 1}, .color = {0, 255, 255}}, {.vertices = {7, 6, 3, 2}, .color = {255, 0, 0}}, + {.vertices = {6, 4, 2, 0}, .color = {255, 0, 255}}, {.vertices = {5, 7, 1, 3}, .color = {255, 255, 0}}}; +}; + +static Cube cube; +static CubeScene cubeScene; + +void Cube::prepare() { + psyqo::GPU::Configuration config; + config.set(psyqo::GPU::Resolution::W320) + .set(psyqo::GPU::VideoMode::AUTO) + .set(psyqo::GPU::ColorMode::C15BITS) + .set(psyqo::GPU::Interlace::PROGRESSIVE); + + gpu().initialize(config); +} + +void Cube::createScene() { pushScene(&cubeScene); } + +void CubeScene::start(StartReason reason) { + // Clear the translation registers + psyqo::GTE::clear(); + psyqo::GTE::clear(); + psyqo::GTE::clear(); + + // Set the screen offset in the GTE. (this is half the X and Y resolutions as standard) + psyqo::GTE::write(psyqo::FixedPoint<16>(160.0).raw()); + psyqo::GTE::write(psyqo::FixedPoint<16>(120.0).raw()); + + // Write the projection plane distance. + psyqo::GTE::write(120); + + // Set the scaling for Z averaging. + psyqo::GTE::write(ORDERING_TABLE_SIZE / 3); + psyqo::GTE::write(ORDERING_TABLE_SIZE / 4); +} + +void CubeScene::frame() { + eastl::array projected; + + // Get which frame we're currently drawing + int parity = gpu().getParity(); + + // Get our current ordering table and fill command + auto& ot = m_ots[parity]; + auto& clear = m_clear[parity]; + + // Chain the fill command accordingly to clear the buffer + gpu().getNextClear(clear.primitive, c_bg); + gpu().chain(clear); + + // We want the cube to appear slightly further away, so we translate it by 512 on the Z-axis. + psyqo::GTE::write(512); + + // Here we're setting up the rotation for the spinning cube + // First, generate a rotation matrix for the X-axis and Y-axis + auto transform = psyqo::SoftMath::generateRotationMatrix33(m_rot, psyqo::SoftMath::Axis::X, cube.m_trig); + auto rot = psyqo::SoftMath::generateRotationMatrix33(m_rot, psyqo::SoftMath::Axis::Y, cube.m_trig); + + // Multiply the X and Y rotation matrices together + psyqo::SoftMath::multiplyMatrix33(transform, rot, &transform); + + // Generate a Z-axis rotation matrix (Empty, but it's here for your use) + psyqo::SoftMath::generateRotationMatrix33(0, 0, psyqo::SoftMath::Axis::Z, cube.m_trig); + + // Apply the combined rotation and write it to the pseudo register for the cube's rotation + psyqo::SoftMath::multiplyMatrix33(transform, rot, &transform); + psyqo::GTE::writeUnsafe(transform); + + int faceNum = 0; + + for (auto face : c_cubeFaces) { + // We load the first 3 vertices into the GTE. We can't do all 4 at once because the GTE + // handles only 3 at a time... + psyqo::GTE::writeUnsafe(c_cubeVertices[face.vertices[0]]); + psyqo::GTE::writeUnsafe(c_cubeVertices[face.vertices[1]]); + psyqo::GTE::writeUnsafe(c_cubeVertices[face.vertices[2]]); + + // We perform rtpt (Perspective transformation) to the three verticies. + psyqo::GTE::Kernels::rtpt(); + + // Nclip determines the winding of the vertices, used to check which direction the face is pointing. + // Clockwise winding means the face is oriented towards us. + psyqo::GTE::Kernels::nclip(); + + // Read the result of nclip and skip rendering this face if it's not facing us + int32_t mac0 = 0; + psyqo::GTE::read(reinterpret_cast(&mac0)); + if (mac0 <= 0) continue; + + // Since the GTE can only handle 3 vertices at a time, we need to store our first vertex + // so we can write our last one. + psyqo::GTE::read(&projected[0].packed); + + // Write the last vertex + psyqo::GTE::writeSafe(c_cubeVertices[face.vertices[3]]); + + // Perform rtps (Perspective transformation) to the last vertice (rtpS - single, rtpT - triple). + psyqo::GTE::Kernels::rtps(); + + // Calculate the average Z for the z-Index to be put in the ordering table + psyqo::GTE::Kernels::avsz4(); + int32_t zIndex = 0; + psyqo::GTE::read(reinterpret_cast(&zIndex)); + + // If the Z-index is out of bounds for our ordering table, we skip rendering this face. + if (zIndex < 0 || zIndex >= ORDERING_TABLE_SIZE) continue; + + // Read the 3 remaining vertices from the GTE + psyqo::GTE::read(&projected[1].packed); + psyqo::GTE::read(&projected[2].packed); + psyqo::GTE::read(&projected[3].packed); + + // Take a Quad fragment from our array, set its vertices, color and make it opaque + auto& quad = m_quads[faceNum]; + quad.primitive.setPointA(projected[0]); + quad.primitive.setPointB(projected[1]); + quad.primitive.setPointC(projected[2]); + quad.primitive.setPointD(projected[3]); + quad.primitive.setColor(face.color); + quad.primitive.setOpaque(); + + // Insert the Quad fragment into the ordering table at the calculated Z-index. + ot.insert(quad, zIndex); + faceNum++; + } + + // Send the entire ordering table as a DMA chain to the GPU. + gpu().chain(ot); + m_rot += 0.005_pi; +} + +int main() { return cube.run(); }