From fd16c379ff4880bdf7677b742a9375ca7014c07e Mon Sep 17 00:00:00 2001 From: squidbus <175574877+squidbus@users.noreply.github.com> Date: Tue, 25 Mar 2025 09:22:48 -0700 Subject: [PATCH 1/2] Use Application Support directory on macOS. (#553) --- README.md | 1 + include/zelda_support.h | 2 ++ src/game/config.cpp | 7 +++++++ src/main/support_apple.mm | 9 +++++++++ 4 files changed, 19 insertions(+) diff --git a/README.md b/README.md index 95f9aa3..77868c8 100644 --- a/README.md +++ b/README.md @@ -122,6 +122,7 @@ You'll probably also want to change the default behavior so that you don't need #### Where is the savefile stored? - Windows: `%LOCALAPPDATA%\Zelda64Recompiled\saves` - Linux: `~/.config/Zelda64Recompiled/saves` +- macOS: `~/Library/Application Support/Zelda64Recompiled/saves` #### How do I choose a different ROM? **You don't.** This project is **only** a port of Majora's Mask (and Ocarina of Time in the future), and it will only accept one specific ROM: the US version of the N64 release of Majora's Mask. ROMs in formats other than .z64 will be automatically converted, as long as it is the correct ROM. **It is not an emulator and it cannot run any arbitrary ROM.** diff --git a/include/zelda_support.h b/include/zelda_support.h index 9751e9a..70dfe6f 100644 --- a/include/zelda_support.h +++ b/include/zelda_support.h @@ -3,6 +3,7 @@ #include #include +#include namespace zelda64 { std::filesystem::path get_asset_path(const char* asset); @@ -12,6 +13,7 @@ namespace zelda64 { // Apple specific methods that usually require Objective-C. Implemented in support_apple.mm. #ifdef __APPLE__ void dispatch_on_ui_thread(std::function func); + std::optional get_application_support_directory(); std::filesystem::path get_bundle_resource_directory(); std::filesystem::path get_bundle_directory(); #endif diff --git a/src/game/config.cpp b/src/game/config.cpp index 7f6c614..17ff9e4 100644 --- a/src/game/config.cpp +++ b/src/game/config.cpp @@ -162,6 +162,13 @@ std::filesystem::path zelda64::get_app_folder_path() { return std::filesystem::path{getenv("APP_FOLDER_PATH")}; } +#if defined(__APPLE__) + const auto supportdir = zelda64::get_application_support_directory(); + if (supportdir) { + return *supportdir / zelda64::program_id; + } +#endif + const char *homedir; if ((homedir = getenv("HOME")) == nullptr) { diff --git a/src/main/support_apple.mm b/src/main/support_apple.mm index 604a998..60a851e 100644 --- a/src/main/support_apple.mm +++ b/src/main/support_apple.mm @@ -12,6 +12,15 @@ namespace zelda64 { }); } + std::optional get_application_support_directory() { + NSArray *dirs = NSSearchPathForDirectoriesInDomains(NSApplicationSupportDirectory, NSUserDomainMask, YES); + if ([dirs count] > 0) { + NSString *dir = [dirs firstObject]; + return std::filesystem::path([dir UTF8String]); + } + return std::nullopt; + } + std::filesystem::path get_bundle_resource_directory() { NSString *bundlePath = [[NSBundle mainBundle] resourcePath]; return std::filesystem::path([bundlePath UTF8String]); From 0e96cc3dc968bcacaa156ea2c2db6032fc573f62 Mon Sep 17 00:00:00 2001 From: danielryb <59661841+danielryb@users.noreply.github.com> Date: Wed, 9 Apr 2025 22:48:34 +0200 Subject: [PATCH 2/2] Add exports for stars' display lists (#563) --- patches/sky_transform_tagging.c | 62 +++++++++++++++++++++++---------- 1 file changed, 43 insertions(+), 19 deletions(-) diff --git a/patches/sky_transform_tagging.c b/patches/sky_transform_tagging.c index dff8ca8..5ae3c40 100644 --- a/patches/sky_transform_tagging.c +++ b/patches/sky_transform_tagging.c @@ -3,6 +3,42 @@ #include "transform_ids.h" #include "libc64/qrand.h" +Gfx default_star_setup_dl[] = { + gsDPSetCombineLERP(PRIMITIVE, 0, ENVIRONMENT, 0, PRIMITIVE, 0, ENVIRONMENT, 0, PRIMITIVE, 0, ENVIRONMENT, 0, + PRIMITIVE, 0, ENVIRONMENT, 0), + gsDPSetOtherMode( + G_AD_DISABLE | G_CD_DISABLE | G_CK_NONE | G_TC_FILT | G_TF_POINT | G_TT_NONE | G_TL_TILE | + G_TD_CLAMP | G_TP_NONE | G_CYC_1CYCLE | G_PM_NPRIMITIVE, + G_AC_NONE | G_ZS_PRIM | G_RM_AA_XLU_LINE | G_RM_AA_XLU_LINE2), + gsSPLoadGeometryMode(0), + gsSPEndDisplayList(), +}; + +Gfx* star_setup_dl = default_star_setup_dl; + +RECOMP_EXPORT void recomp_set_star_setup_dl(Gfx* g) { + star_setup_dl = g; +} + +static Vtx star_verts[] = { + {{{ -1, -1, 0 }, 0, { 0 << 6, 0 << 6 }, { 0, 0, 0, 0xFF }}}, + {{{ 1, -1, 0 }, 0, { 64 << 6, 0 << 6 }, { 0, 0, 0, 0xFF }}}, + {{{ -1, 1, 0 }, 0, { 0 << 6, 64 << 6 }, { 0, 0, 0, 0xFF }}}, + {{{ 1, 1, 0 }, 0, { 64 << 6, 64 << 6 }, { 0, 0, 0, 0xFF }}} +}; + +Gfx default_star_draw_dl[] = { + gsSPVertex(star_verts, ARRAY_COUNT(star_verts), 0), + gsSP2Triangles(0, 1, 2, 0x0, 1, 3, 2, 0x0), + gsSPEndDisplayList(), +}; + +Gfx* star_draw_dl = default_star_draw_dl; + +RECOMP_EXPORT void recomp_set_star_draw_dl(Gfx* g) { + star_draw_dl = g; +} + extern Mtx* sSkyboxDrawMatrix; RECOMP_PATCH void Skybox_Draw(SkyboxContext* skyboxCtx, GraphicsContext* gfxCtx, s16 skyboxId, s16 blend, f32 x, f32 y, f32 z) { @@ -29,7 +65,7 @@ RECOMP_PATCH void Skybox_Draw(SkyboxContext* skyboxCtx, GraphicsContext* gfxCtx, Matrix_ToMtx(sSkyboxDrawMatrix); gSPMatrix(POLY_OPA_DISP++, sSkyboxDrawMatrix, G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); - + // @recomp Tag the skybox's matrix, skipping interpolation if the camera's interpolation was also skipped. if (camera_was_skipped()) { gEXMatrixGroupDecomposedSkipAll(POLY_OPA_DISP++, SKYBOX_TRANSFORM_ID_START, G_EX_PUSH, G_MTX_MODELVIEW, G_EX_EDIT_NONE); @@ -37,7 +73,7 @@ RECOMP_PATCH void Skybox_Draw(SkyboxContext* skyboxCtx, GraphicsContext* gfxCtx, else { gEXMatrixGroupDecomposedNormal(POLY_OPA_DISP++, SKYBOX_TRANSFORM_ID_START, G_EX_PUSH, G_MTX_MODELVIEW, G_EX_EDIT_NONE); } - + gDPSetColorDither(POLY_OPA_DISP++, G_CD_MAGICSQ); gDPSetTextureFilter(POLY_OPA_DISP++, G_TF_BILERP); gDPLoadTLUT_pal256(POLY_OPA_DISP++, skyboxCtx->paletteStaticSegment); @@ -66,14 +102,8 @@ RECOMP_PATCH void Skybox_Draw(SkyboxContext* skyboxCtx, GraphicsContext* gfxCtx, CLOSE_DISPS(gfxCtx); } -// @recomp Draw stars with billboarding to allow for interpolation instead of rects. +// @recomp Draw stars with billboarding to allow for interpolation instead of rects. void Environment_DrawSkyboxStarBillboard(GraphicsContext* gfxCtx, MtxF* billboard_mtx, Gfx** gfxp, f32 x, f32 y, f32 z, s32 width, s32 height) { - static Vtx star_verts[] = { - {{{ -1, -1, 0 }, 0, { 0, 0 }, { 0, 0, 0, 0xFF }}}, - {{{ 1, -1, 0 }, 0, { 0, 0 }, { 0, 0, 0, 0xFF }}}, - {{{ -1, 1, 0 }, 0, { 0, 0 }, { 0, 0, 0, 0xFF }}}, - {{{ 1, 1, 0 }, 0, { 0, 0 }, { 0, 0, 0, 0xFF }}} - }; Gfx* gfx = *gfxp; MtxF scale_matrix; @@ -83,7 +113,6 @@ void Environment_DrawSkyboxStarBillboard(GraphicsContext* gfxCtx, MtxF* billboar // Scales down the stars to roughly match what their original rect size was. SkinMatrix_SetScale(&scale_matrix, width * 25.0f / 4.0f, height * 25.0f / 4.0f, 1.0f); SkinMatrix_MtxFMtxFMult(billboard_mtx, &scale_matrix, &mv_matrix); - mv_matrix.mf[3][0] = x; mv_matrix.mf[3][1] = y; mv_matrix.mf[3][2] = z; @@ -91,8 +120,9 @@ void Environment_DrawSkyboxStarBillboard(GraphicsContext* gfxCtx, MtxF* billboar MtxConv_F2L(m, &mv_matrix); gSPMatrix(gfx++, m, G_MTX_MODELVIEW | G_MTX_LOAD | G_MTX_PUSH); - gSPVertex(gfx++, star_verts, ARRAY_COUNT(star_verts), 0); - gSP2Triangles(gfx++, 0, 1, 2, 0x0, 1, 3, 2, 0x0); + + gSPDisplayList(gfx++, star_draw_dl); + gSPPopMatrix(gfx++, G_MTX_MODELVIEW); *gfxp = gfx; @@ -168,14 +198,8 @@ RECOMP_PATCH void Environment_DrawSkyboxStarsImpl(PlayState* play, Gfx** gfxP) { gDPPipeSync(gfx++); gDPSetEnvColor(gfx++, 255, 255, 255, 255.0f * D_801F4F28); - gDPSetCombineLERP(gfx++, PRIMITIVE, 0, ENVIRONMENT, 0, PRIMITIVE, 0, ENVIRONMENT, 0, PRIMITIVE, 0, ENVIRONMENT, 0, - PRIMITIVE, 0, ENVIRONMENT, 0); - gDPSetOtherMode(gfx++, - G_AD_DISABLE | G_CD_DISABLE | G_CK_NONE | G_TC_FILT | G_TF_POINT | G_TT_NONE | G_TL_TILE | - G_TD_CLAMP | G_TP_NONE | G_CYC_1CYCLE | G_PM_NPRIMITIVE, - G_AC_NONE | G_ZS_PRIM | G_RM_AA_XLU_LINE | G_RM_AA_XLU_LINE2); - gSPLoadGeometryMode(gfx++, 0); + gSPDisplayList(gfx++, star_setup_dl); randInt = ((u32)gSaveContext.save.saveInfo.playerData.playerName[0] << 0x18) ^ ((u32)gSaveContext.save.saveInfo.playerData.playerName[1] << 0x14) ^