summaryrefslogtreecommitdiff
path: root/soh/src/code
diff options
context:
space:
mode:
Diffstat (limited to 'soh/src/code')
-rw-r--r--soh/src/code/audio_synthesis.c6
-rw-r--r--soh/src/code/z_camera.c3
-rw-r--r--soh/src/code/z_lib.c4
-rw-r--r--soh/src/code/z_map_exp.c103
-rw-r--r--soh/src/code/z_map_mark.c28
-rw-r--r--soh/src/code/z_parameter.c6
-rw-r--r--soh/src/code/z_play.c17
-rw-r--r--soh/src/code/z_player_lib.c4
-rw-r--r--soh/src/code/z_room.c2
-rw-r--r--soh/src/code/z_view.c28
10 files changed, 153 insertions, 48 deletions
diff --git a/soh/src/code/audio_synthesis.c b/soh/src/code/audio_synthesis.c
index e1b42185a..f2c526630 100644
--- a/soh/src/code/audio_synthesis.c
+++ b/soh/src/code/audio_synthesis.c
@@ -653,7 +653,11 @@ Acmd* AudioSynth_DoOneAudioUpdate(s16* aiBuf, s32 aiBufLen, Acmd* cmd, s32 updat
}
updateIndex = aiBufLen * 2;
- aInterleave(cmd++, DMEM_TEMP, DMEM_LEFT_CH, DMEM_RIGHT_CH, updateIndex);
+ if (CVarGetInteger("gMirroredWorld", 0)) {
+ aInterleave(cmd++, DMEM_TEMP, DMEM_RIGHT_CH, DMEM_LEFT_CH, updateIndex);
+ } else {
+ aInterleave(cmd++, DMEM_TEMP, DMEM_LEFT_CH, DMEM_RIGHT_CH, updateIndex);
+ }
aSaveBuffer(cmd++, DMEM_TEMP, aiBuf, updateIndex * 2);
return cmd;
diff --git a/soh/src/code/z_camera.c b/soh/src/code/z_camera.c
index b1fe9987d..e0d827107 100644
--- a/soh/src/code/z_camera.c
+++ b/soh/src/code/z_camera.c
@@ -1487,8 +1487,9 @@ s32 Camera_Free(Camera* camera) {
f32 newCamX = -D_8015BD7C->state.input[0].cur.right_stick_x * 10.0f * (CVarGetFloat("gThirdPersonCameraSensitivityX", 1.0f));
f32 newCamY = D_8015BD7C->state.input[0].cur.right_stick_y * 10.0f * (CVarGetFloat("gThirdPersonCameraSensitivityY", 1.0f));
+ bool invertXAxis = (CVarGetInteger("gInvertXAxis", 0) && !CVarGetInteger("gMirroredWorld", 0)) || (!CVarGetInteger("gInvertXAxis", 0) && CVarGetInteger("gMirroredWorld", 0));
- camera->play->camX += newCamX * (CVarGetInteger("gInvertXAxis", 0) ? -1 : 1);
+ camera->play->camX += newCamX * (invertXAxis ? -1 : 1);
camera->play->camY += newCamY * (CVarGetInteger("gInvertYAxis", 1) ? 1 : -1);
if (camera->play->camY > 0x32A4) {
diff --git a/soh/src/code/z_lib.c b/soh/src/code/z_lib.c
index 3508fceb7..820256cbb 100644
--- a/soh/src/code/z_lib.c
+++ b/soh/src/code/z_lib.c
@@ -201,6 +201,10 @@ void func_80077D10(f32* arg0, s16* arg1, Input* input) {
f32 relX = input->rel.stick_x;
f32 relY = input->rel.stick_y;
+ if (CVarGetInteger("gMirroredWorld", 0)) {
+ relX = -input->rel.stick_x;
+ }
+
*arg0 = sqrtf(SQ(relX) + SQ(relY));
*arg0 = (60.0f < *arg0) ? 60.0f : *arg0;
diff --git a/soh/src/code/z_map_exp.c b/soh/src/code/z_map_exp.c
index 990f1b695..3a758d92a 100644
--- a/soh/src/code/z_map_exp.c
+++ b/soh/src/code/z_map_exp.c
@@ -635,32 +635,49 @@ void Minimap_DrawCompassIcons(PlayState* play) {
gDPSetEnvColor(OVERLAY_DISP++, 0, 0, 0, 255);
gDPSetCombineMode(OVERLAY_DISP++, G_CC_PRIMITIVE, G_CC_PRIMITIVE);
+ s16 mapWidth = 0;
+ s16 mapStartPosX = 0;
+ if (play->sceneNum >= SCENE_SPOT00 && play->sceneNum <= SCENE_GANON_TOU) { // Overworld
+ mapStartPosX = R_OW_MINIMAP_X;
+ mapWidth = gMapData->owMinimapWidth[R_MAP_INDEX];
+ } else if (play->sceneNum >= SCENE_YDAN && play->sceneNum <= SCENE_ICE_DOUKUTO) { // Dungeons
+ mapStartPosX = R_DGN_MINIMAP_X;
+ mapWidth = 96;
+ }
+
+ // The compass offset value is a factor of 10 compared to N64 screen pixels and originates in the center of the screen
+ // Compute the additional mirror offset value by normalizing the original offset position
+ // and taking it's distance to the center of the map, duplicating that result and casting back to a factor of 10
+ s16 mirrorOffset = ((mapWidth / 2) - ((R_COMPASS_OFFSET_X / 10) - (mapStartPosX - SCREEN_WIDTH / 2))) * 2 * 10;
+
tempX = player->actor.world.pos.x;
tempZ = player->actor.world.pos.z;
- tempX /= R_COMPASS_SCALE_X;
+ tempX /= R_COMPASS_SCALE_X * (CVarGetInteger("gMirroredWorld", 0) ? -1 : 1);
tempZ /= R_COMPASS_SCALE_Y;
+
+ s16 tempXOffset = R_COMPASS_OFFSET_X + (CVarGetInteger("gMirroredWorld", 0) ? mirrorOffset : 0);
if (CVarGetInteger("gMinimapPosType", 0) != 0) {
if (CVarGetInteger("gMinimapPosType", 0) == 1) {//Anchor Left
if (CVarGetInteger("gMinimapUseMargins", 0) != 0) {X_Margins_Minimap = Left_MM_Margin;};
- Matrix_Translate(
- OTRGetDimensionFromLeftEdge((R_COMPASS_OFFSET_X + (X_Margins_Minimap*10) + tempX + (CVarGetInteger("gMinimapPosX", 0)*10)) / 10.0f),
- (R_COMPASS_OFFSET_Y + ((Y_Margins_Minimap*10)*-1) - tempZ + ((CVarGetInteger("gMinimapPosY", 0)*10)*-1)) / 10.0f, 0.0f, MTXMODE_NEW);
+ Matrix_Translate(
+ OTRGetDimensionFromLeftEdge((tempXOffset + (X_Margins_Minimap*10) + tempX + (CVarGetInteger("gMinimapPosX", 0)*10)) / 10.0f),
+ (R_COMPASS_OFFSET_Y + ((Y_Margins_Minimap*10)*-1) - tempZ + ((CVarGetInteger("gMinimapPosY", 0)*10)*-1)) / 10.0f, 0.0f, MTXMODE_NEW);
} else if (CVarGetInteger("gMinimapPosType", 0) == 2) {//Anchor Right
if (CVarGetInteger("gMinimapUseMargins", 0) != 0) {X_Margins_Minimap = Right_MM_Margin;};
Matrix_Translate(
- OTRGetDimensionFromRightEdge((R_COMPASS_OFFSET_X + (X_Margins_Minimap*10) + tempX + (CVarGetInteger("gMinimapPosX", 0)*10)) / 10.0f),
+ OTRGetDimensionFromRightEdge((tempXOffset + (X_Margins_Minimap*10) + tempX + (CVarGetInteger("gMinimapPosX", 0)*10)) / 10.0f),
(R_COMPASS_OFFSET_Y +((Y_Margins_Minimap*10)*-1) - tempZ + ((CVarGetInteger("gMinimapPosY", 0)*10)*-1)) / 10.0f, 0.0f, MTXMODE_NEW);
} else if (CVarGetInteger("gMinimapPosType", 0) == 3) {//Anchor None
Matrix_Translate(
- (R_COMPASS_OFFSET_X + tempX + (CVarGetInteger("gMinimapPosX", 0)*10) / 10.0f),
+ (tempXOffset + tempX + (CVarGetInteger("gMinimapPosX", 0)*10) / 10.0f),
(R_COMPASS_OFFSET_Y + ((Y_Margins_Minimap*10)*-1) - tempZ + ((CVarGetInteger("gMinimapPosY", 0)*10)*-1)) / 10.0f, 0.0f, MTXMODE_NEW);
}
} else {
- Matrix_Translate(OTRGetDimensionFromRightEdge((R_COMPASS_OFFSET_X+(X_Margins_Minimap*10) + tempX) / 10.0f), (R_COMPASS_OFFSET_Y+((Y_Margins_Minimap*10)*-1) - tempZ) / 10.0f, 0.0f, MTXMODE_NEW);
+ Matrix_Translate(OTRGetDimensionFromRightEdge((tempXOffset+(X_Margins_Minimap*10) + tempX) / 10.0f), (R_COMPASS_OFFSET_Y+((Y_Margins_Minimap*10)*-1) - tempZ) / 10.0f, 0.0f, MTXMODE_NEW);
}
Matrix_Scale(0.4f, 0.4f, 0.4f, MTXMODE_APPLY);
Matrix_RotateX(-1.6f, MTXMODE_APPLY);
- tempX = (0x7FFF - player->actor.shape.rot.y) / 0x400;
+ tempX = ((0x7FFF - player->actor.shape.rot.y) / 0x400) * (CVarGetInteger("gMirroredWorld", 0) ? -1 : 1);
Matrix_RotateY(tempX / 10.0f, MTXMODE_APPLY);
gSPMatrix(OVERLAY_DISP++, MATRIX_NEWMTX(play->state.gfxCtx),
G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
@@ -669,32 +686,32 @@ void Minimap_DrawCompassIcons(PlayState* play) {
gSPDisplayList(OVERLAY_DISP++, gCompassArrowDL);
//Player map entry (red arrow)
- tempX = sPlayerInitialPosX+X_Margins_Minimap;
- tempZ = sPlayerInitialPosZ+Y_Margins_Minimap;
- tempX /= R_COMPASS_SCALE_X;
+ tempX = sPlayerInitialPosX;
+ tempZ = sPlayerInitialPosZ;
+ tempX /= R_COMPASS_SCALE_X * (CVarGetInteger("gMirroredWorld", 0) ? -1 : 1);
tempZ /= R_COMPASS_SCALE_Y;
if (CVarGetInteger("gMinimapPosType", 0) != 0) {
if (CVarGetInteger("gMinimapPosType", 0) == 1) {//Anchor Left
if (CVarGetInteger("gMinimapUseMargins", 0) != 0) {X_Margins_Minimap = Left_MM_Margin;};
- Matrix_Translate(
- OTRGetDimensionFromLeftEdge((R_COMPASS_OFFSET_X + (X_Margins_Minimap*10) + tempX + (CVarGetInteger("gMinimapPosX", 0)*10)) / 10.0f),
- (R_COMPASS_OFFSET_Y + ((Y_Margins_Minimap*10)*-1) - tempZ + ((CVarGetInteger("gMinimapPosY", 0)*10)*-1)) / 10.0f, 0.0f, MTXMODE_NEW);
+ Matrix_Translate(
+ OTRGetDimensionFromLeftEdge((tempXOffset + (X_Margins_Minimap*10) + tempX + (CVarGetInteger("gMinimapPosX", 0)*10)) / 10.0f),
+ (R_COMPASS_OFFSET_Y + ((Y_Margins_Minimap*10)*-1) - tempZ + ((CVarGetInteger("gMinimapPosY", 0)*10)*-1)) / 10.0f, 0.0f, MTXMODE_NEW);
} else if (CVarGetInteger("gMinimapPosType", 0) == 2) {//Anchor Right
if (CVarGetInteger("gMinimapUseMargins", 0) != 0) {X_Margins_Minimap = Right_MM_Margin;};
Matrix_Translate(
- OTRGetDimensionFromRightEdge((R_COMPASS_OFFSET_X + (X_Margins_Minimap*10) + tempX + (CVarGetInteger("gMinimapPosX", 0)*10)) / 10.0f),
+ OTRGetDimensionFromRightEdge((tempXOffset + (X_Margins_Minimap*10) + tempX + (CVarGetInteger("gMinimapPosX", 0)*10)) / 10.0f),
(R_COMPASS_OFFSET_Y +((Y_Margins_Minimap*10)*-1) - tempZ + ((CVarGetInteger("gMinimapPosY", 0)*10)*-1)) / 10.0f, 0.0f, MTXMODE_NEW);
} else if (CVarGetInteger("gMinimapPosType", 0) == 3) {//Anchor None
Matrix_Translate(
- (R_COMPASS_OFFSET_X + tempX + (CVarGetInteger("gMinimapPosX", 0)*10) / 10.0f),
+ (tempXOffset + tempX + (CVarGetInteger("gMinimapPosX", 0)*10) / 10.0f),
(R_COMPASS_OFFSET_Y - tempZ + ((CVarGetInteger("gMinimapPosY", 0)*10)*-1)) / 10.0f, 0.0f, MTXMODE_NEW);
}
} else {
- Matrix_Translate(OTRGetDimensionFromRightEdge((R_COMPASS_OFFSET_X+(X_Margins_Minimap*10) + tempX) / 10.0f), (R_COMPASS_OFFSET_Y+((Y_Margins_Minimap*10)*-1) - tempZ) / 10.0f, 0.0f, MTXMODE_NEW);
+ Matrix_Translate(OTRGetDimensionFromRightEdge((tempXOffset+(X_Margins_Minimap*10) + tempX) / 10.0f), (R_COMPASS_OFFSET_Y+((Y_Margins_Minimap*10)*-1) - tempZ) / 10.0f, 0.0f, MTXMODE_NEW);
}
Matrix_Scale(VREG(9) / 100.0f, VREG(9) / 100.0f, VREG(9) / 100.0f, MTXMODE_APPLY);
Matrix_RotateX(VREG(52) / 10.0f, MTXMODE_APPLY);
- Matrix_RotateY(sPlayerInitialDirection / 10.0f, MTXMODE_APPLY);
+ Matrix_RotateY((sPlayerInitialDirection * (CVarGetInteger("gMirroredWorld", 0) ? -1 : 1)) / 10.0f, MTXMODE_APPLY);
gSPMatrix(OVERLAY_DISP++, MATRIX_NEWMTX(play->state.gfxCtx),
G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
@@ -752,8 +769,9 @@ void Minimap_Draw(PlayState* play) {
if (CHECK_DUNGEON_ITEM(DUNGEON_MAP, mapIndex)) {
gDPSetPrimColor(OVERLAY_DISP++, 0, 0, minimapColor.r, minimapColor.g, minimapColor.b, interfaceCtx->minimapAlpha);
+ u8 mirrorMode = CVarGetInteger("gMirroredWorld", 0) ? G_TX_MIRROR : G_TX_NOMIRROR;
gDPLoadTextureBlock_4b(OVERLAY_DISP++, interfaceCtx->mapSegmentName[0], G_IM_FMT_I, 96, 85, 0,
- G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK,
+ mirrorMode | G_TX_WRAP, G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK,
G_TX_NOMASK, G_TX_NOLOD, G_TX_NOLOD);
s16 dgnMiniMapX = OTRGetRectDimensionFromRightEdge(R_DGN_MINIMAP_X + X_Margins_Minimap);
@@ -770,9 +788,16 @@ void Minimap_Draw(PlayState* play) {
dgnMiniMapX = CVarGetInteger("gMinimapPosX", 0);
}
}
+
+ s32 sValue = 0;
+ if (CVarGetInteger("gMirroredWorld", 0)) {
+ // Flip the minimap on the x-axis (s-axis) by setting s to the textures mirror boundary
+ sValue = 96 << 5;
+ }
+
gSPWideTextureRectangle(OVERLAY_DISP++, dgnMiniMapX << 2, dgnMiniMapY << 2,
(dgnMiniMapX + 96) << 2, (dgnMiniMapY + 85) << 2, G_TX_RENDERTILE,
- 0, 0, 1 << 10, 1 << 10);
+ sValue, 0, 1 << 10, 1 << 10);
}
if (CHECK_DUNGEON_ITEM(DUNGEON_COMPASS, mapIndex)) {
@@ -820,9 +845,10 @@ void Minimap_Draw(PlayState* play) {
gDPSetCombineMode(OVERLAY_DISP++, G_CC_MODULATEIA_PRIM, G_CC_MODULATEIA_PRIM);
gDPSetPrimColor(OVERLAY_DISP++, 0, 0, minimapColor.r, minimapColor.g, minimapColor.b, interfaceCtx->minimapAlpha);
+ u8 mirrorMode = CVarGetInteger("gMirroredWorld", 0) ? G_TX_MIRROR : G_TX_NOMIRROR;
gDPLoadTextureBlock_4b(OVERLAY_DISP++, interfaceCtx->mapSegmentName[0], G_IM_FMT_IA,
gMapData->owMinimapWidth[mapIndex], gMapData->owMinimapHeight[mapIndex], 0,
- G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK,
+ mirrorMode | G_TX_WRAP, G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK,
G_TX_NOMASK, G_TX_NOLOD, G_TX_NOLOD);
s16 oWMiniMapX = OTRGetRectDimensionFromRightEdge(R_OW_MINIMAP_X + X_Margins_Minimap);
@@ -839,9 +865,16 @@ void Minimap_Draw(PlayState* play) {
oWMiniMapX = CVarGetInteger("gMinimapPosX", 0);
}
}
+
+ s32 sValue = 0;
+ if (CVarGetInteger("gMirroredWorld", 0)) {
+ // Flip the minimap on the x-axis (s-axis) by setting s to the textures mirror boundary
+ sValue = gMapData->owMinimapWidth[mapIndex] << 5;
+ }
+
gSPWideTextureRectangle(OVERLAY_DISP++, oWMiniMapX << 2, oWMiniMapY << 2,
(oWMiniMapX + gMapData->owMinimapWidth[mapIndex]) << 2,
- (oWMiniMapY + gMapData->owMinimapHeight[mapIndex]) << 2, G_TX_RENDERTILE, 0,
+ (oWMiniMapY + gMapData->owMinimapHeight[mapIndex]) << 2, G_TX_RENDERTILE, sValue,
0, 1 << 10, 1 << 10);
gDPSetPrimColor(OVERLAY_DISP++, 0, 0, minimapColor.r, minimapColor.g, minimapColor.b, interfaceCtx->minimapAlpha);
@@ -851,26 +884,33 @@ void Minimap_Draw(PlayState* play) {
if (((play->sceneNum != SCENE_SPOT01) && (play->sceneNum != SCENE_SPOT04) &&
(play->sceneNum != SCENE_SPOT08)) ||
(LINK_AGE_IN_YEARS != YEARS_ADULT)) {
+ s16 origX = gMapData->owEntranceIconPosX[sEntranceIconMapIndex];
+
+ // Compute the distance of the center of the original texture location to the center of the map
+ // Then duplicate that and right-align the texture (extra 2 pixels are due to the texture being a 6px left-aligned in a 8px tex)
+ s16 distFromCenter = (R_OW_MINIMAP_X + (gMapData->owMinimapWidth[mapIndex] / 2)) - (origX + (iconSize / 2));
+ s16 mirrorOffset = distFromCenter * 2 + (iconSize / 2) - 2;
+ s16 newX = origX + (CVarGetInteger("gMirroredWorld", 0) ? mirrorOffset : 0);
+
// The game authentically uses larger negative values for the entrance icon Y pos value. Normally only the first 12 bits
// would be read when the final value is passed into `gSPTextureRectangle`, but our cosmetic hud placements requires using
// `gSPWideTextureRectangle` which reads the first 24 bits instead. This caused the icon to be placed off screen.
// To address this, we take only the first 10 bits (which are later left-shifted by 2 to get our final 12 bits)
// to fix the entrance icon position when used with `gSPWideTextureRectangle`
s16 newY = gMapData->owEntranceIconPosY[sEntranceIconMapIndex] & 0x3FF;
- s16 PosX = gMapData->owEntranceIconPosX[sEntranceIconMapIndex] + X_Margins_Minimap;
- s16 entranceX = OTRGetRectDimensionFromRightEdge(PosX);
+ s16 entranceX = OTRGetRectDimensionFromRightEdge(newX + X_Margins_Minimap);
s16 entranceY = newY + Y_Margins_Minimap;
if (CVarGetInteger("gMinimapPosType", 0) != 0) {
entranceY = newY + CVarGetInteger("gMinimapPosY", 0) + Y_Margins_Minimap;
if (CVarGetInteger("gMinimapPosType", 0) == 1) { // Anchor Left
if (CVarGetInteger("gMinimapUseMargins", 0) != 0) {X_Margins_Minimap = Left_MM_Margin;};
- entranceX = OTRGetRectDimensionFromLeftEdge(PosX + CVarGetInteger("gMinimapPosX", 0));
+ entranceX = OTRGetRectDimensionFromLeftEdge(newX + X_Margins_Minimap + CVarGetInteger("gMinimapPosX", 0));
} else if (CVarGetInteger("gMinimapPosType", 0) == 2) { // Anchor Right
if (CVarGetInteger("gMinimapUseMargins", 0) != 0) {X_Margins_Minimap = Right_MM_Margin;};
- entranceX = OTRGetRectDimensionFromRightEdge(PosX + CVarGetInteger("gMinimapPosX", 0));
+ entranceX = OTRGetRectDimensionFromRightEdge(newX + X_Margins_Minimap + CVarGetInteger("gMinimapPosX", 0));
} else if (CVarGetInteger("gMinimapPosType", 0) == 3) { // Anchor None
- entranceX = PosX + CVarGetInteger("gMinimapPosX", 0);
+ entranceX = newX + X_Margins_Minimap + CVarGetInteger("gMinimapPosX", 0);
}
}
@@ -894,18 +934,19 @@ void Minimap_Draw(PlayState* play) {
}
}
- s16 entranceX = OTRGetRectDimensionFromRightEdge(270 + X_Margins_Minimap);
+ s16 origX = CVarGetInteger("gMirroredWorld", 0) ? 256 : 270;
+ s16 entranceX = OTRGetRectDimensionFromRightEdge(origX + X_Margins_Minimap);
s16 entranceY = 154 + Y_Margins_Minimap;
if (CVarGetInteger("gMinimapPosType", 0) != 0) {
entranceY = 154 + Y_Margins_Minimap + CVarGetInteger("gMinimapPosY", 0);
if (CVarGetInteger("gMinimapPosType", 0) == 1) {//Anchor Left
if (CVarGetInteger("gMinimapUseMargins", 0) != 0) {X_Margins_Minimap = Left_MM_Margin;};
- entranceX = OTRGetRectDimensionFromLeftEdge(270 + X_Margins_Minimap + CVarGetInteger("gMinimapPosX", 0));
+ entranceX = OTRGetRectDimensionFromLeftEdge(origX + X_Margins_Minimap + CVarGetInteger("gMinimapPosX", 0));
} else if (CVarGetInteger("gMinimapPosType", 0) == 2) {//Anchor Right
if (CVarGetInteger("gMinimapUseMargins", 0) != 0) {X_Margins_Minimap = Right_MM_Margin;};
- entranceX = OTRGetRectDimensionFromRightEdge(270 + X_Margins_Minimap + CVarGetInteger("gMinimapPosX", 0));
+ entranceX = OTRGetRectDimensionFromRightEdge(origX + X_Margins_Minimap + CVarGetInteger("gMinimapPosX", 0));
} else if (CVarGetInteger("gMinimapPosType", 0) == 3) {//Anchor None
- entranceX = 270 + X_Margins_Minimap + CVarGetInteger("gMinimapPosX", 0);
+ entranceX = origX + X_Margins_Minimap + CVarGetInteger("gMinimapPosX", 0);
}
}
diff --git a/soh/src/code/z_map_mark.c b/soh/src/code/z_map_mark.c
index 8d9f025a0..f40ead1b8 100644
--- a/soh/src/code/z_map_mark.c
+++ b/soh/src/code/z_map_mark.c
@@ -132,8 +132,19 @@ void MapMark_DrawForDungeon(PlayState* play) {
//Place each chest / boss room icon
for (i = 0; i < mapMarkIconData->count; i++) {
if ((mapMarkIconData->markType != MAP_MARK_CHEST) || !Flags_GetTreasure(play, markPoint->chestFlag)) {
+ markInfo = &sMapMarkInfoTable[mapMarkIconData->markType];
+ int height = markInfo->textureHeight * 1.0f; //Adjust Height with scale
+ int width = markInfo->textureWidth * 1.0f; //Adjust Width with scale
+ int height_factor = (1 << 10) * markInfo->textureHeight / height;
+ int width_factor = (1 << 10) * markInfo->textureWidth / width;
+
+ // The original mark point X originates from the left edge of the map
+ // For mirror mode, we compute the new mark point X by subtracting it from the right side of the
+ // dungeon map and the textures width
+ s16 markPointX = CVarGetInteger("gMirroredWorld", 0) ? 96 - markPoint->x - width : markPoint->x;
+
//Minimap chest / boss icon
- const s32 PosX_Minimap_ori = GREG(94) + OTRGetRectDimensionFromRightEdge(markPoint->x+X_Margins_Minimap_ic) + 204;
+ const s32 PosX_Minimap_ori = GREG(94) + OTRGetRectDimensionFromRightEdge(markPointX+X_Margins_Minimap_ic) + 204;
const s32 PosY_Minimap_ori = GREG(95) + markPoint->y + Y_Margins_Minimap_ic + 140;
if (CVarGetInteger("gMinimapPosType", 0) != 0) {
rectTop = (markPoint->y + Y_Margins_Minimap_ic + 140 + CVarGetInteger("gMinimapPosY", 0));
@@ -143,15 +154,15 @@ void MapMark_DrawForDungeon(PlayState* play) {
play->sceneNum == SCENE_BMORI1 || play->sceneNum == SCENE_HIDAN || play->sceneNum == SCENE_MIZUSIN ||
play->sceneNum == SCENE_JYASINZOU || play->sceneNum == SCENE_HAKADAN || play->sceneNum == SCENE_HAKADANCH ||
play->sceneNum == SCENE_ICE_DOUKUTO) {
- rectLeft = OTRGetRectDimensionFromLeftEdge(markPoint->x+CVarGetInteger("gMinimapPosX", 0)+204+X_Margins_Minimap_ic);
+ rectLeft = OTRGetRectDimensionFromLeftEdge(markPointX+CVarGetInteger("gMinimapPosX", 0)+204+X_Margins_Minimap_ic);
} else {
- rectLeft = OTRGetRectDimensionFromLeftEdge(markPoint->x+CVarGetInteger("gMinimapPosX", 0)+204+X_Margins_Minimap_ic);
+ rectLeft = OTRGetRectDimensionFromLeftEdge(markPointX+CVarGetInteger("gMinimapPosX", 0)+204+X_Margins_Minimap_ic);
}
} else if (CVarGetInteger("gMinimapPosType", 0) == 2) {//Anchor Right
if (CVarGetInteger("gMinimapUseMargins", 0) != 0) {X_Margins_Minimap_ic = Right_MC_Margin;};
- rectLeft = OTRGetRectDimensionFromRightEdge(markPoint->x+CVarGetInteger("gMinimapPosX", 0)+204+X_Margins_Minimap_ic);
+ rectLeft = OTRGetRectDimensionFromRightEdge(markPointX+CVarGetInteger("gMinimapPosX", 0)+204+X_Margins_Minimap_ic);
} else if (CVarGetInteger("gMinimapPosType", 0) == 3) {//Anchor None
- rectLeft = markPoint->x+CVarGetInteger("gMinimapPosX", 0)+204+X_Margins_Minimap_ic;
+ rectLeft = markPointX+CVarGetInteger("gMinimapPosX", 0)+204+X_Margins_Minimap_ic;
} else if (CVarGetInteger("gMinimapPosType", 0) == 4) {//Hidden
rectLeft = -9999;
}
@@ -160,13 +171,6 @@ void MapMark_DrawForDungeon(PlayState* play) {
rectTop = PosY_Minimap_ori;
}
- int height = 8 * 1.0f; //Adjust Height with scale
- int width = 8 * 1.0f; //Adjust Width with scale
- int height_factor = (1 << 10) * 8 / height;
- int width_factor = (1 << 10) * 8 / width;
-
- markInfo = &sMapMarkInfoTable[mapMarkIconData->markType];
-
gDPPipeSync(OVERLAY_DISP++);
gDPLoadTextureBlock(OVERLAY_DISP++, markInfo->texture, markInfo->imageFormat, G_IM_SIZ_MARK,
diff --git a/soh/src/code/z_parameter.c b/soh/src/code/z_parameter.c
index 756e445e9..43be8b854 100644
--- a/soh/src/code/z_parameter.c
+++ b/soh/src/code/z_parameter.c
@@ -5090,7 +5090,13 @@ void Interface_Draw(PlayState* play) {
Minimap_Draw(play);
if ((R_PAUSE_MENU_MODE != 2) && (R_PAUSE_MENU_MODE != 3)) {
+ if (CVarGetInteger("gMirroredWorld", 0)) {
+ gSPMatrix(OVERLAY_DISP++, interfaceCtx->view.projectionFlippedPtr, G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_PROJECTION);
+ }
func_8002C124(&play->actorCtx.targetCtx, play); // Draw Z-Target
+ if (CVarGetInteger("gMirroredWorld", 0)) {
+ gSPMatrix(OVERLAY_DISP++, interfaceCtx->view.projectionPtr, G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_PROJECTION);
+ }
}
Gfx_SetupDL_39Overlay(play->state.gfxCtx);
diff --git a/soh/src/code/z_play.c b/soh/src/code/z_play.c
index 59257ad9f..24cef9426 100644
--- a/soh/src/code/z_play.c
+++ b/soh/src/code/z_play.c
@@ -1473,6 +1473,17 @@ void Play_Draw(PlayState* play) {
func_800AA460(&play->view, play->view.fovy, play->view.zNear, play->lightCtx.fogFar);
func_800AAA50(&play->view, 15);
+ // Flip the projections and invert culling for the OPA and XLU display buffers
+ // These manage the world and effects
+ if (CVarGetInteger("gMirroredWorld", 0)) {
+ gSPSetExtraGeometryMode(POLY_OPA_DISP++, G_EX_INVERT_CULLING);
+ gSPSetExtraGeometryMode(POLY_XLU_DISP++, G_EX_INVERT_CULLING);
+ gSPMatrix(POLY_OPA_DISP++, play->view.projectionFlippedPtr, G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_PROJECTION);
+ gSPMatrix(POLY_XLU_DISP++, play->view.projectionFlippedPtr, G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_PROJECTION);
+ gSPMatrix(POLY_OPA_DISP++, play->view.viewingPtr, G_MTX_NOPUSH | G_MTX_MUL | G_MTX_PROJECTION);
+ gSPMatrix(POLY_XLU_DISP++, play->view.viewingPtr, G_MTX_NOPUSH | G_MTX_MUL | G_MTX_PROJECTION);
+ }
+
// The billboard matrix temporarily stores the viewing matrix
Matrix_MtxToMtxF(&play->view.viewing, &play->billboardMtxF);
Matrix_MtxToMtxF(&play->view.projection, &play->viewProjectionMtxF);
@@ -1694,6 +1705,12 @@ void Play_Draw(PlayState* play) {
}
}
}
+
+ // Reset the inverted culling
+ if (CVarGetInteger("gMirroredWorld", 0)) {
+ gSPClearExtraGeometryMode(POLY_OPA_DISP++, G_EX_INVERT_CULLING);
+ gSPClearExtraGeometryMode(POLY_XLU_DISP++, G_EX_INVERT_CULLING);
+ }
}
if (play->view.unk_124 != 0) {
diff --git a/soh/src/code/z_player_lib.c b/soh/src/code/z_player_lib.c
index cb856b870..8048a6097 100644
--- a/soh/src/code/z_player_lib.c
+++ b/soh/src/code/z_player_lib.c
@@ -1776,7 +1776,7 @@ void func_80091A24(PlayState* play, void* seg04, void* seg06, SkelAnime* skelAni
Matrix_SetTranslateRotateYXZ(pos->x - ((CVarGetInteger("gPauseLiveLink", 0) && LINK_AGE_IN_YEARS == YEARS_ADULT) ? 25 : 0),
pos->y - (CVarGetInteger("gPauseTriforce", 0) ? 16 : 0), pos->z, rot);
- Matrix_Scale(scale, scale, scale, MTXMODE_APPLY);
+ Matrix_Scale(scale * (CVarGetInteger("gMirroredWorld", 0) ? -1 : 1), scale, scale, MTXMODE_APPLY);
gSPSegment(POLY_OPA_DISP++, 0x04, seg04);
gSPSegment(POLY_OPA_DISP++, 0x06, seg06);
@@ -1798,7 +1798,7 @@ void func_80091A24(PlayState* play, void* seg04, void* seg06, SkelAnime* skelAni
Matrix_SetTranslateRotateYXZ(pos->x - (LINK_AGE_IN_YEARS == YEARS_ADULT ? 25 : 0),
pos->y + 280 + (LINK_AGE_IN_YEARS == YEARS_ADULT ? 48 : 0), pos->z, rot);
- Matrix_Scale(scale * 1, scale * 1, scale * 1, MTXMODE_APPLY);
+ Matrix_Scale(scale * (CVarGetInteger("gMirroredWorld", 0) ? -1 : 1), scale * 1, scale * 1, MTXMODE_APPLY);
Gfx* ohNo = POLY_XLU_DISP;
POLY_XLU_DISP = POLY_OPA_DISP;
diff --git a/soh/src/code/z_room.c b/soh/src/code/z_room.c
index 1d4b610c5..17b2feb82 100644
--- a/soh/src/code/z_room.c
+++ b/soh/src/code/z_room.c
@@ -270,7 +270,7 @@ void func_8009638C(Gfx** displayList, void* source, void* tlut, u16 width, u16 h
bg->b.imageFmt = fmt;
bg->b.imageSiz = siz;
bg->b.imagePal = 0;
- bg->b.imageFlip = 0;
+ bg->b.imageFlip = CVarGetInteger("gMirroredWorld", 0) ? G_BG_FLAG_FLIPS : 0;
if (ResourceMgr_ResourceIsBackground((char*) source)) {
char* blob = (char*) ResourceGetDataByName((char *) source);
diff --git a/soh/src/code/z_view.c b/soh/src/code/z_view.c
index c84634a6b..6ea62941c 100644
--- a/soh/src/code/z_view.c
+++ b/soh/src/code/z_view.c
@@ -296,6 +296,7 @@ s32 func_800AAA9C(View* view) {
s32 height;
Vp* vp;
Mtx* projection;
+ Mtx* projectionFlipped;
Mtx* viewing;
GraphicsContext* gfxCtx = view->gfxCtx;
@@ -313,8 +314,11 @@ s32 func_800AAA9C(View* view) {
gSPViewport(POLY_KAL_DISP++, vp);
projection = Graph_Alloc(gfxCtx, sizeof(Mtx));
+ projectionFlipped = Graph_Alloc(gfxCtx, sizeof(Mtx));
LOG_CHECK_NULL_POINTER("projection", projection);
+ LOG_CHECK_NULL_POINTER("projectionFlipped", projectionFlipped);
view->projectionPtr = projection;
+ view->projectionFlippedPtr = projectionFlipped;
width = view->viewport.rightX - view->viewport.leftX;
height = view->viewport.bottomY - view->viewport.topY;
@@ -427,6 +431,15 @@ s32 func_800AAA9C(View* view) {
}
osSyncPrintf("\n");
}
+ if (CVarGetInteger("gMirroredWorld", 0)) {
+ MtxF flipF;
+ SkinMatrix_Clear(&flipF);
+ flipF.xx = -1.0;
+ MtxF projectionF;
+ Matrix_MtxToMtxF(projection, &projectionF);
+ SkinMatrix_MtxFMtxFMult(&projectionF, &flipF, &projectionF);
+ Matrix_MtxFToMtx(&projectionF, projectionFlipped);
+ }
view->projection = *projection;
@@ -511,6 +524,7 @@ s32 func_800AB0A8(View* view) {
s32 func_800AB2C4(View* view) {
Vp* vp;
Mtx* projection;
+ Mtx* projectionFlipped;
GraphicsContext* gfxCtx;
gfxCtx = view->gfxCtx;
@@ -528,12 +542,26 @@ s32 func_800AB2C4(View* view) {
gSPViewport(OVERLAY_DISP++, vp);
projection = Graph_Alloc(gfxCtx, sizeof(Mtx));
+ projectionFlipped = Graph_Alloc(gfxCtx, sizeof(Mtx));
LOG_CHECK_NULL_POINTER("projection", projection);
+ LOG_CHECK_NULL_POINTER("projectionFlipped", projectionFlipped);
view->projectionPtr = projection;
+ view->projectionFlippedPtr = projectionFlipped;
guOrtho(projection, -(f32)gScreenWidth * 0.5f, (f32)gScreenWidth * 0.5f, -(f32)gScreenHeight * 0.5f,
(f32)gScreenHeight * 0.5f, -30, view->zFar, view->scale);
+ // This is for z-targeting
+ if (CVarGetInteger("gMirroredWorld", 0)) {
+ MtxF flipF;
+ SkinMatrix_Clear(&flipF);
+ flipF.xx = -1.0;
+ MtxF projectionF;
+ Matrix_MtxToMtxF(projection, &projectionF);
+ SkinMatrix_MtxFMtxFMult(&projectionF, &flipF, &projectionF);
+ Matrix_MtxFToMtx(&projectionF, projectionFlipped);
+ }
+
view->projection = *projection;
gSPMatrix(OVERLAY_DISP++, projection, G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_PROJECTION);