diff --git a/include/text_strings.h.in b/include/text_strings.h.in index 711d4562..f1c83171 100644 --- a/include/text_strings.h.in +++ b/include/text_strings.h.in @@ -93,6 +93,12 @@ #define TEXT_HUD_WIDE_INFO _("PLEASE CONFIGURE YOUR DISPLAY OR YOUR EMULATOR TO\nSTRETCH THE IMAGE TO 16:9") #endif +#define TEXT_CAM_INFO_SLOWEST _("CAM SPEED: SLOWEST") +#define TEXT_CAM_INFO_SLOW _("CAM SPEED: SLOW") +#define TEXT_CAM_INFO_MEDIUM _("CAM SPEED: MEDIUM") +#define TEXT_CAM_INFO_FAST _("CAM SPEED: FAST") +#define TEXT_CAM_INFO_FASTEST _("CAM SPEED: FASTEST") + #if defined(VERSION_JP) || defined(VERSION_SH) /** diff --git a/src/game/camera.c b/src/game/camera.c index 25b27983..2ff11930 100644 --- a/src/game/camera.c +++ b/src/game/camera.c @@ -98,6 +98,7 @@ Vec3f sPlayer2FocusOffset; * The pitch used for the credits easter egg. */ s16 sCreditsPlayer2Pitch; +s16 rButtonCounter2; /** * The yaw used for the credits easter egg. */ @@ -107,6 +108,7 @@ s16 sCreditsPlayer2Yaw; */ u8 sFramesPaused; + extern struct CameraFOVStatus sFOVState; extern struct TransitionInfo sModeTransition; extern struct PlayerGeometry sMarioGeometry; @@ -259,6 +261,7 @@ s16 sCameraSoundFlags; * Stores what C-Buttons are pressed this frame. */ u16 sCButtonsPressed; +u16 rButtonCounter; /** * A copy of gDialogID, the dialog displayed during the cutscene. */ @@ -437,6 +440,7 @@ u8 sFramesSinceCutsceneEnded = 0; * 3 = Dialog doesn't have a response */ u8 sCutsceneDialogResponse = DIALOG_RESPONSE_NONE; +u8 stickReset = 1; struct PlayerCameraState *sMarioCamState = &gPlayerCameraState[0]; struct PlayerCameraState *sLuigiCamState = &gPlayerCameraState[1]; u32 unused8032D008 = 0; @@ -755,6 +759,7 @@ void set_camera_height(struct Camera *c, f32 goalHeight) { UNUSED s16 action = sMarioCamState->action; f32 baseOff = 125.f; f32 camCeilHeight = find_ceil(c->pos[0], gLakituState.goalPos[1] - 50.f, c->pos[2], &surface); + f32 approachRate = 20.0f; if (sMarioCamState->action & ACT_FLAG_HANGING) { marioCeilHeight = sMarioGeometry.currCeilHeight; @@ -790,7 +795,8 @@ void set_camera_height(struct Camera *c, f32 goalHeight) { c->pos[1] = goalHeight; } } - approach_camera_height(c, goalHeight, 20.f); + approachRate += ABS(c->pos[1] - goalHeight) / 20; + approach_camera_height(c, goalHeight, approachRate); if (camCeilHeight != CELL_HEIGHT_LIMIT) { camCeilHeight -= baseOff; if ((c->pos[1] > camCeilHeight && sMarioGeometry.currFloorHeight + baseOff < camCeilHeight) @@ -934,9 +940,25 @@ s32 update_8_directions_camera(struct Camera *c, Vec3f focus, Vec3f pos) { UNUSED f32 unused1; UNUSED f32 unused2; UNUSED f32 unused3; - f32 yOff = 125.f; + f32 yOff; f32 baseDist = 1000.f; + if (gMarioState->action & ACT_FLAG_SWIMMING) { + yOff = -125.f; + } else { + yOff = 125.f; + } + + if ((gPlayer1Controller->buttonDown & R_TRIG) && (gPlayer1Controller->buttonDown & U_CBUTTONS)) { + gKeepCliffCam = 1; + pitch = DEGREES(60); + } else if (((gPlayer1Controller->buttonDown & U_CBUTTONS) || (gPlayer1Controller->buttonDown & R_TRIG)) && gKeepCliffCam) { + pitch = DEGREES(60); + } else { + gKeepCliffCam = 0; + } + + sAreaYaw = camYaw; calc_y_to_curr_floor(&posY, 1.f, 200.f, &focusY, 0.9f, 200.f); focus_on_mario(focus, pos, posY + yOff, focusY + yOff, sLakituDist + baseDist, pitch, camYaw); @@ -1170,6 +1192,28 @@ void mode_radial_camera(struct Camera *c) { pan_ahead_of_player(c); } +// Returns the camera speed based on the user's camera speed setting +f32 set_camera_speed(void) { + switch(gCameraSpeed) { + case 0: + return 0.5f; + break; + case 1: + return 1; + break; + case 2: + return 1.5; + break; + case 3: + return 2; + break; + case 4: + return 3.5; + break; + } + return 0; +} + /** * A mode that only has 8 camera angles, 45 degrees apart */ @@ -1177,42 +1221,59 @@ void mode_8_directions_camera(struct Camera *c) { Vec3f pos; UNUSED u8 unused[8]; s16 oldAreaYaw = sAreaYaw; + // Get the camera speed based on the user's setting + f32 cameraSpeed = set_camera_speed(); radial_camera_input(c, 0.f); - if (gPlayer1Controller->buttonPressed & R_CBUTTONS) { - s8DirModeYawOffset += DEGREES(45); - play_sound_cbutton_side(); - } - if (gPlayer1Controller->buttonPressed & L_CBUTTONS) { - s8DirModeYawOffset -= DEGREES(45); - play_sound_cbutton_side(); + if ((gPlayer1Controller->buttonPressed & L_CBUTTONS) && !(gPlayer1Controller->buttonDown & R_TRIG)) { + s8DirModeBaseYaw -= DEGREES(45); + } else if ((gPlayer1Controller->buttonPressed & R_CBUTTONS) && !(gPlayer1Controller->buttonDown & R_TRIG)) { + s8DirModeBaseYaw += DEGREES(45); + } else if (gPlayer2Controller->rawStickX) { + s8DirModeBaseYaw += DEGREES(gPlayer2Controller->rawStickX * 4 / 64); // Analog camera support (Use the "Dual Analog" input mode in Parallel Launcher) } -#ifdef PARALLEL_LAKITU_CAM - // extra functionality - else if (gPlayer1Controller->buttonPressed & U_JPAD) { - s8DirModeYawOffset = 0; - s8DirModeYawOffset = gMarioState->faceAngle[1]-0x8000; - } - else if (gPlayer1Controller->buttonDown & L_JPAD) { - s8DirModeYawOffset -= DEGREES(2); - } - else if (gPlayer1Controller->buttonDown & R_JPAD) { - s8DirModeYawOffset += DEGREES(2); + + if (gPlayer1Controller->buttonDown & R_TRIG) { + if (gPlayer1Controller->buttonDown & L_CBUTTONS) { + s8DirModeBaseYaw -= DEGREES(cameraSpeed); + } else if (gPlayer1Controller->buttonDown & R_CBUTTONS) { + s8DirModeBaseYaw += DEGREES(cameraSpeed); + } + rButtonCounter++; // This increses whenever R is held. + } else { + if (rButtonCounter > 0 && rButtonCounter <= 5 && !((gPlayer1Controller->buttonDown & L_CBUTTONS) || (gPlayer1Controller->buttonDown & R_CBUTTONS) || (gMarioState->action & ACT_FLAG_SWIMMING_OR_FLYING))) { + // This centers the camera behind mario. It triggers when you let go of R in less than 5 frames. + s8DirModeYawOffset = 0; + s8DirModeBaseYaw = gMarioState->faceAngle[1]-0x8000; + gMarioState->area->camera->yaw = s8DirModeBaseYaw; + play_sound_rbutton_changed(); + } + rButtonCounter = 0; + } + if (gPlayer1Controller->buttonPressed & R_TRIG) { + if (rButtonCounter2 <= 5) { + set_cam_angle(CAM_ANGLE_MARIO); // Enter mario cam if R is pressed 2 times in less than 5 frames + rButtonCounter2 = 6; + } else { + rButtonCounter2 = 0; + } + } else { + rButtonCounter2++; } - else if (gPlayer1Controller->buttonPressed & D_JPAD) { - s8DirModeYawOffset = s8DirModeYawOffset&0xE000; + if (gPlayer1Controller->buttonPressed & D_JPAD) { + s8DirModeBaseYaw = (s8DirModeBaseYaw + 0x1000) & 0xE000; // Lock the camera to the nearest 45deg axis } -#endif lakitu_zoom(400.f, 0x900); c->nextYaw = update_8_directions_camera(c, c->focus, pos); + set_camera_height(c, pos[1]); c->pos[0] = pos[0]; c->pos[2] = pos[2]; sAreaYawChange = sAreaYaw - oldAreaYaw; - set_camera_height(c, pos[1]); } + /** * Updates the camera in outward radial mode. * sModeOffsetYaw is calculated in radial_camera_move, which calls offset_yaw_outward_radial @@ -2116,7 +2177,7 @@ s16 update_default_camera(struct Camera *c) { gLakituState.goalPos[1], gLakituState.goalPos[2], &ceil); s16 yawDir; - + handle_c_button_movement(c); vec3f_get_dist_and_angle(sMarioCamState->pos, c->pos, &dist, &pitch, &yaw); @@ -3036,6 +3097,8 @@ void update_lakitu(struct Camera *c) { void update_camera(struct Camera *c) { UNUSED u8 unused[24]; + extern s16 s8DirModeBaseYaw; + gCamera = c; update_camera_hud_status(c); if (c->cutscene == 0 && @@ -3046,14 +3109,13 @@ void update_camera(struct Camera *c) { // Only process R_TRIG if 'fixed' is not selected in the menu if (cam_select_alt_mode(0) == CAM_SELECTION_MARIO) { if (gPlayer1Controller->buttonPressed & R_TRIG) { - if (set_cam_angle(0) == CAM_ANGLE_LAKITU) { - set_cam_angle(CAM_ANGLE_MARIO); - } else { + if (set_cam_angle(0) == CAM_ANGLE_MARIO) { + s8DirModeBaseYaw = ((gMarioState->faceAngle[1]-0x8000) + 0x1000) & 0xE000; set_cam_angle(CAM_ANGLE_LAKITU); } } } - play_sound_if_cam_switched_to_lakitu_or_mario(); + //play_sound_if_cam_switched_to_lakitu_or_mario(); } // Initialize the camera @@ -3356,7 +3418,6 @@ void init_camera(struct Camera *c) { struct Surface *floor = 0; Vec3f marioOffset; s32 i; - sCreditsPlayer2Pitch = 0; sCreditsPlayer2Yaw = 0; gPrevLevel = gCurrLevelArea / 16; @@ -4901,15 +4962,15 @@ void play_camera_buzz_if_c_sideways(void) { } void play_sound_cbutton_up(void) { - play_sound(SOUND_MENU_CAMERA_ZOOM_IN, gGlobalSoundSource); + //play_sound(SOUND_MENU_CAMERA_ZOOM_OUT, gGlobalSoundSource); } void play_sound_cbutton_down(void) { - play_sound(SOUND_MENU_CAMERA_ZOOM_OUT, gGlobalSoundSource); + //play_sound(SOUND_MENU_CAMERA_ZOOM_OUT, gGlobalSoundSource); } void play_sound_cbutton_side(void) { - play_sound(SOUND_MENU_CAMERA_TURN, gGlobalSoundSource); + //play_sound(SOUND_MENU_CAMERA_TURN, gGlobalSoundSource); } void play_sound_button_change_blocked(void) { @@ -5013,7 +5074,7 @@ s32 radial_camera_input(struct Camera *c, UNUSED f32 unused) { } // Zoom in / enter C-Up - if (gPlayer1Controller->buttonPressed & U_CBUTTONS) { + if (((gPlayer1Controller->buttonPressed & U_CBUTTONS) || (gPlayer2Controller->rawStickY > 40)) && (stickReset) && !(gPlayer1Controller->buttonDown & R_TRIG)) { if (gCameraMovementFlags & CAM_MOVE_ZOOMED_OUT) { gCameraMovementFlags &= ~CAM_MOVE_ZOOMED_OUT; play_sound_cbutton_up(); @@ -5023,7 +5084,7 @@ s32 radial_camera_input(struct Camera *c, UNUSED f32 unused) { } // Zoom out - if (gPlayer1Controller->buttonPressed & D_CBUTTONS) { + if ((gPlayer1Controller->buttonPressed & D_CBUTTONS) || (gPlayer2Controller->rawStickY < -40)) { if (gCameraMovementFlags & CAM_MOVE_ZOOMED_OUT) { gCameraMovementFlags |= CAM_MOVE_ALREADY_ZOOMED_OUT; #ifndef VERSION_JP @@ -5035,6 +5096,12 @@ s32 radial_camera_input(struct Camera *c, UNUSED f32 unused) { } } + if ((gPlayer2Controller->rawStickY > 40) || (gPlayer2Controller->rawStickY < -40)) { + stickReset = 0; + } else { + stickReset = 1; + } + //! returning uninitialized variable return dummy; } @@ -5600,7 +5667,7 @@ void set_camera_mode_8_directions(struct Camera *c) { if (c->mode != CAMERA_MODE_8_DIRECTIONS) { c->mode = CAMERA_MODE_8_DIRECTIONS; sStatusFlags &= ~CAM_FLAG_SMOOTH_MOVEMENT; - s8DirModeBaseYaw = 0; + s8DirModeBaseYaw = ((gMarioState->faceAngle[1]-0x8000) + 0x1000) & 0xE000; s8DirModeYawOffset = 0; } } diff --git a/src/game/game_init.c b/src/game/game_init.c index 317e33bf..6687016d 100644 --- a/src/game/game_init.c +++ b/src/game/game_init.c @@ -51,6 +51,11 @@ u8 gBorderHeight; #ifdef CUSTOM_DEBUG u8 gCustomDebugMode; #endif +u8 gCameraSpeed = 2; +u8 gWaterCamOverride; +u8 gFlyingCamOverride; +u8 gKeepCliffCam; +s32 gCliffTimer; #ifdef EEP s8 gEepromProbe; #endif @@ -739,6 +744,7 @@ void thread5_game_loop(UNUSED void *arg) { play_music(SEQ_PLAYER_SFX, SEQUENCE_ARGS(0, SEQ_SOUND_PLAYER), 0); set_sound_mode(save_file_get_sound_mode()); + gCameraSpeed = (save_file_get_camera_speed()); #ifdef WIDE gWidescreen = save_file_get_widescreen_mode(); #endif diff --git a/src/game/game_init.h b/src/game/game_init.h index 84a31755..817c58df 100644 --- a/src/game/game_init.h +++ b/src/game/game_init.h @@ -45,6 +45,10 @@ extern u8 gIsConsole; #ifdef WIDE extern s16 gWidescreen; #endif +extern u8 gCameraSpeed; +extern u8 gWaterCamOverride; +extern u8 gFlyingCamOverride; +extern u8 gKeepCliffCam; extern u8 gBorderHeight; #ifdef CUSTOM_DEBUG extern u8 gCustomDebugMode; diff --git a/src/game/ingame_menu.c b/src/game/ingame_menu.c index 6cbfd8e1..01dd4de8 100644 --- a/src/game/ingame_menu.c +++ b/src/game/ingame_menu.c @@ -59,6 +59,12 @@ void *languageTable[][3] = #endif }; +u8 textCamInfoSlowest[] = { TEXT_CAM_INFO_SLOWEST }; +u8 textCamInfoSlow[] = { TEXT_CAM_INFO_SLOW }; +u8 textCamInfoMedium[] = { TEXT_CAM_INFO_MEDIUM }; +u8 textCamInfoFast[] = { TEXT_CAM_INFO_FAST}; +u8 textCamInfoFastest[] = { TEXT_CAM_INFO_FASTEST }; + extern u8 gLastCompletedCourseNum; extern u8 gLastCompletedStarNum; @@ -1504,6 +1510,45 @@ void reset_red_coins_collected(void) { gRedCoinsCollected = 0; } +void render_camera_speed_setting(void) { + gSPDisplayList(gDisplayListHead++, dl_ia_text_begin); + gDPSetEnvColor(gDisplayListHead++, 255, 255, 255, gDialogTextAlpha); + switch (gCameraSpeed) { + case 0: + print_generic_string(190, 20, textCamInfoSlowest); + break; + case 1: + print_generic_string(190, 20, textCamInfoSlow); + break; + case 2: + print_generic_string(190, 20, textCamInfoMedium); + break; + case 3: + print_generic_string(190, 20, textCamInfoFast); + break; + case 4: + print_generic_string(190, 20, textCamInfoFastest); + break; + } + gSPDisplayList(gDisplayListHead++, dl_ia_text_end); + + if (gPlayer1Controller->buttonPressed & R_JPAD) { + if (gCameraSpeed < 4) { + gCameraSpeed += 1; + } else { + gCameraSpeed = 0; + } + save_file_set_camera_speed(gCameraSpeed); + } else if (gPlayer1Controller->buttonPressed & L_JPAD) { + if (gCameraSpeed > 0) { + gCameraSpeed -= 1; + } else { + gCameraSpeed = 4; + } + save_file_set_camera_speed(gCameraSpeed); + } +} + void change_dialog_camera_angle(void) { if (cam_select_alt_mode(0) == CAM_SELECTION_MARIO) { gDialogCameraAngleIndex = CAM_SELECTION_MARIO; @@ -1942,6 +1987,11 @@ s16 render_pause_courses_and_castle(void) { } #if defined(WIDE) && !defined(PUPPYCAM) render_widescreen_setting(); + render_camera_speed_setting(); + if (gPlayer1Controller->buttonPressed & L_TRIG){ + gWidescreen ^= 1; + save_file_set_widescreen_mode(gWidescreen); + } #endif if (gDialogTextAlpha < 250) { gDialogTextAlpha += 25; diff --git a/src/game/mario.c b/src/game/mario.c index 31e97bce..29b5e9c4 100644 --- a/src/game/mario.c +++ b/src/game/mario.c @@ -1468,32 +1468,39 @@ void update_mario_inputs(struct MarioState *m) { void set_submerged_cam_preset_and_spawn_bubbles(struct MarioState *m) { f32 heightBelowWater; s16 camPreset; + extern s16 s8DirModeBaseYaw; + if (!gWaterCamOverride) { + if ((m->action & ACT_GROUP_MASK) == ACT_GROUP_SUBMERGED) { + heightBelowWater = (f32)(m->waterLevel - 80) - m->pos[1]; + camPreset = m->area->camera->mode; + if (m->action & ACT_FLAG_METAL_WATER) { + if (camPreset != CAMERA_MODE_CLOSE) { + set_camera_mode(m->area->camera, CAMERA_MODE_CLOSE, 1); + } + } else { + if ((heightBelowWater > 800.0f) && (camPreset != CAMERA_MODE_BEHIND_MARIO)) { + set_camera_mode(m->area->camera, CAMERA_MODE_BEHIND_MARIO, 1); + } - if ((m->action & ACT_GROUP_MASK) == ACT_GROUP_SUBMERGED) { - heightBelowWater = (f32)(m->waterLevel - 80) - m->pos[1]; - camPreset = m->area->camera->mode; - - if (m->action & ACT_FLAG_METAL_WATER) { - if (camPreset != CAMERA_MODE_CLOSE) { - set_camera_mode(m->area->camera, CAMERA_MODE_CLOSE, 1); - } - } else { - if ((heightBelowWater > 800.0f) && (camPreset != CAMERA_MODE_BEHIND_MARIO)) { - set_camera_mode(m->area->camera, CAMERA_MODE_BEHIND_MARIO, 1); - } - - if ((heightBelowWater < 400.0f) && (camPreset != CAMERA_MODE_WATER_SURFACE)) { - set_camera_mode(m->area->camera, CAMERA_MODE_WATER_SURFACE, 1); - } + if ((heightBelowWater < 400.0f) && (camPreset != CAMERA_MODE_WATER_SURFACE)) { + set_camera_mode(m->area->camera, CAMERA_MODE_WATER_SURFACE, 1); + } - // As long as Mario isn't drowning or at the top - // of the water with his head out, spawn bubbles. - if (!(m->action & ACT_FLAG_INTANGIBLE)) { - if ((m->pos[1] < (f32)(m->waterLevel - 160)) || (m->faceAngle[0] < -0x800)) { - m->particleFlags |= PARTICLE_BUBBLE; + // As long as Mario isn't drowning or at the top + // of the water with his head out, spawn bubbles. + if (!(m->action & ACT_FLAG_INTANGIBLE)) { + if ((m->pos[1] < (f32)(m->waterLevel - 160)) || (m->faceAngle[0] < -0x800)) { + m->particleFlags |= PARTICLE_BUBBLE; + } } } } + } else { + set_camera_mode(m->area->camera, CAMERA_MODE_8_DIRECTIONS, 1); + } + if ((gPlayer1Controller->buttonPressed & R_TRIG) && (m->action & ACT_FLAG_SWIMMING)) { + s8DirModeBaseYaw = ((gMarioState->faceAngle[1]-0x8000) + 0x1000) & 0xE000; + gWaterCamOverride ^= 1; } } diff --git a/src/game/mario_actions_airborne.c b/src/game/mario_actions_airborne.c index ce6467ef..c7e998c1 100644 --- a/src/game/mario_actions_airborne.c +++ b/src/game/mario_actions_airborne.c @@ -1736,6 +1736,10 @@ s32 act_shot_from_cannon(struct MarioState *m) { s32 act_flying(struct MarioState *m) { s16 startPitch = m->faceAngle[0]; + if (gPlayer1Controller->buttonPressed & R_TRIG) { + gFlyingCamOverride ^= 1; + } + if (m->input & INPUT_Z_PRESSED) { if (m->area->camera->mode == CAMERA_MODE_BEHIND_MARIO) { set_camera_mode(m->area->camera, m->area->camera->defMode, 1); @@ -1750,8 +1754,10 @@ s32 act_flying(struct MarioState *m) { return set_mario_action(m, ACT_FREEFALL, 0); } - if (m->area->camera->mode != CAMERA_MODE_BEHIND_MARIO) { + if (!gFlyingCamOverride) { set_camera_mode(m->area->camera, CAMERA_MODE_BEHIND_MARIO, 1); + } else { + set_camera_mode(m->area->camera, CAMERA_MODE_8_DIRECTIONS, 1); } if (m->actionState == 0) { @@ -1933,7 +1939,7 @@ s32 act_flying_triple_jump(struct MarioState *m) { } if (m->vel[1] < 4.0f) { - if (m->area->camera->mode != CAMERA_MODE_BEHIND_MARIO) { + if ((m->area->camera->mode != CAMERA_MODE_BEHIND_MARIO) && (!gFlyingCamOverride)) { set_camera_mode(m->area->camera, CAMERA_MODE_BEHIND_MARIO, 1); } @@ -1944,7 +1950,7 @@ s32 act_flying_triple_jump(struct MarioState *m) { set_mario_action(m, ACT_FLYING, 1); } - if (m->actionTimer++ == 10 && m->area->camera->mode != CAMERA_MODE_BEHIND_MARIO) { + if (m->actionTimer++ == 10 && m->area->camera->mode != CAMERA_MODE_BEHIND_MARIO && (!gFlyingCamOverride)) { set_camera_mode(m->area->camera, CAMERA_MODE_BEHIND_MARIO, 1); } diff --git a/src/game/save_file.c b/src/game/save_file.c index bcdcdbaf..3f0b8ca1 100644 --- a/src/game/save_file.c +++ b/src/game/save_file.c @@ -673,6 +673,12 @@ u8 save_file_get_widescreen_mode(void) { return gSaveBuffer.menuData[0].wideMode; } +void save_file_set_camera_speed(u8 speed) { + gSaveBuffer.menuData[0].cameraSpeedSetting = speed; + gMainMenuDataModified = TRUE; + save_main_menu_data(); +} + void save_file_set_widescreen_mode(u8 mode) { gSaveBuffer.menuData[0].wideMode = mode; @@ -685,6 +691,10 @@ u16 save_file_get_sound_mode(void) { return gSaveBuffer.menuData[0].soundMode; } +u8 save_file_get_camera_speed(void) { + return gSaveBuffer.menuData[0].cameraSpeedSetting; +} + void save_file_move_cap_to_default_location(void) { if (save_file_get_flags() & SAVE_FLAG_CAP_ON_GROUND) { switch (gSaveBuffer.files[gCurrSaveFileNum - 1][0].capLevel) { diff --git a/src/game/save_file.h b/src/game/save_file.h index 64cf0c63..085ec1d9 100644 --- a/src/game/save_file.h +++ b/src/game/save_file.h @@ -63,6 +63,7 @@ struct MainMenuSaveData #ifdef WIDE u8 wideMode: 1; #endif + u8 cameraSpeedSetting: 3; #ifdef VERSION_EU u8 language: 2; @@ -178,6 +179,8 @@ u16 save_file_get_sound_mode(void); u8 save_file_get_widescreen_mode(void); void save_file_set_widescreen_mode(u8 mode); #endif +u8 save_file_get_camera_speed(void); +void save_file_set_camera_speed(u8 speed); void save_file_move_cap_to_default_location(void); void disable_warp_checkpoint(void);