From 54f07324b0c145a9f7a020183800c89d6263333c Mon Sep 17 00:00:00 2001 From: Andreas Eversberg Date: Thu, 26 Apr 2018 19:22:51 +0200 Subject: [PATCH] OVR: Move player with controller to the direction it points to --- src/libovr/ovr.c | 10 ++++-- src/libovr/ovr.h | 2 +- src/mercenary/main.c | 84 +++++++++++++++++++++++++++++++++++----------- src/mercenary/mercenary.h | 10 ++++++ src/mercenary/mercenary2.c | 30 +++++++++++++++++ src/mercenary/mercenary3.c | 31 +++++++++++++++++ 6 files changed, 145 insertions(+), 22 deletions(-) diff --git a/src/libovr/ovr.c b/src/libovr/ovr.c index 9083471..204f10b 100755 --- a/src/libovr/ovr.c +++ b/src/libovr/ovr.c @@ -100,6 +100,7 @@ static int mirror_width; static int mirror_height; static ovrEyeRenderDesc eyeRenderDesc[2]; static ovrPosef hmdToEyeViewPose[2]; +static ovrPosef headPose; static ovrPosef handPoses[2]; static ovrInputState inputState; static ovrLayerEyeFov layer; @@ -239,7 +240,7 @@ error: return -EINVAL; } -void get_poses_ovr(int *button_a, int *button_b, int *button_x, int *button_y, int *button_menu, int *button_trigger, int *button_left_thumb, int *button_right_thumb, double *hand_right_x, double *hand_right_y, double *hand_right_z, double *hand_right_yaw, double *hand_right_pitch, double *hand_right_roll, double *stick_left_x, double *stick_left_y, double *stick_right_x, double *stick_right_y) +void get_poses_ovr(int *button_a, int *button_b, int *button_x, int *button_y, int *button_menu, int *button_trigger, int *button_left_thumb, int *button_right_thumb, double *hand_right_x, double *hand_right_y, double *hand_right_z, double *hand_right_yaw, double *hand_right_pitch, double *hand_right_roll, double *stick_left_x, double *stick_left_y, double *stick_right_x, double *stick_right_y, double *head_yaw, double *head_pitch, double *head_roll) { ovrResult result; float yaw, pitch, roll; @@ -249,7 +250,8 @@ void get_poses_ovr(int *button_a, int *button_b, int *button_x, int *button_y, i double displayMidpointSeconds = ovr_GetPredictedDisplayTime(session, frameIndex); ovrTrackingState hmdState = ovr_GetTrackingState(session, displayMidpointSeconds, ovrTrue); ovr_CalcEyePoses(hmdState.HeadPose.ThePose, hmdToEyeViewPose, layer.RenderPose); - /* Grab hand poses useful for rendering hand or controller representation */ + /* Grab hand poses useful for rendering head/hand or controller representation */ + headPose = hmdState.HeadPose.ThePose; handPoses[ovrHand_Left] = hmdState.HandPoses[ovrHand_Left].ThePose; handPoses[ovrHand_Right] = hmdState.HandPoses[ovrHand_Right].ThePose; x = handPoses[ovrHand_Right].Position.x; @@ -261,6 +263,10 @@ void get_poses_ovr(int *button_a, int *button_b, int *button_x, int *button_y, i *hand_right_x = x / 0.0254; *hand_right_y = y / 0.0254; *hand_right_z = z / 0.0254; + ovrOrientation2yawpitchroll(headPose.Orientation, &yaw, &pitch, &roll); + *head_yaw = yaw; + *head_pitch = pitch; + *head_roll = roll; ovrOrientation2yawpitchroll(handPoses[ovrHand_Right].Orientation, &yaw, &pitch, &roll); *hand_right_yaw = yaw; *hand_right_pitch = pitch; diff --git a/src/libovr/ovr.h b/src/libovr/ovr.h index 9cd9aa5..18e8c8f 100755 --- a/src/libovr/ovr.h +++ b/src/libovr/ovr.h @@ -1,7 +1,7 @@ int init_ovr(int multisampling); void exit_ovr(void); -void get_poses_ovr(int *button_a, int *button_b, int *button_x, int *button_y, int *button_menu, int *button_trigger, int *button_left_thumb, int *button_right_thumb, double *hand_right_x, double *hand_right_y, double *hand_right_z, double *hand_right_yaw, double *hand_right_pitch, double *hand_right_roll, double *stick_left_x, double *stick_left_y, double *stick_right_x, double *stick_right_y); +void get_poses_ovr(int *button_a, int *button_b, int *button_x, int *button_y, int *button_menu, int *button_trigger, int *button_left_thumb, int *button_right_thumb, double *hand_right_x, double *hand_right_y, double *hand_right_z, double *hand_right_yaw, double *hand_right_pitch, double *hand_right_roll, double *stick_left_x, double *stick_left_y, double *stick_right_x, double *stick_right_y, double *head_yaw, double *head_pitch, double *head_roll); void begin_render_ovr(void); void begin_render_ovr_eye(int eye, double *camera_x, double *camera_y, double *camera_z); void end_render_ovr_eye(int eye); diff --git a/src/mercenary/main.c b/src/mercenary/main.c index bd0fca6..2f7d314 100644 --- a/src/mercenary/main.c +++ b/src/mercenary/main.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include "../../include/keycodes.h" @@ -48,6 +49,10 @@ #define FOV_JOLLY 80.0 #define FOV_MAX 170.0 +#define STICK_WALK_THRESHOLD 0.2 /* move the stick until the player moves */ +#define STICK_ROTATE_THRESHOLD 0.2 /* move the stick until the player rotates */ +#define STICK_THRUST_THRESHOLD 0.2 /* move the stick until the craft moves */ + static int config_ctrl_c = 0; static int config_amiga_speed = 0; /* fast speed */ static double config_fps = 16.0; @@ -311,10 +316,11 @@ static void handle_vr_poses(void) int button_a = 0, button_b = 0, button_x = 0, button_y = 0, button_menu = 0, button_trigger = 0, button_left_thumb = 0, button_right_thumb = 0; double hand_right_x = 0.0, hand_right_y = 0.0, hand_right_z = 0.0; double hand_right_yaw = 0.0, hand_right_pitch = 0.0, hand_right_roll = 0.0; + double head_yaw = 0.0, head_pitch = 0.0, head_roll = 0.0; double stick_left_x = 0.0, stick_left_y = 0.0, stick_right_x = 0.0, stick_right_y = 0.0; int thrust = KEYCODE_SPACE; - get_poses_ovr(&button_a, &button_b, &button_x, &button_y, &button_menu, &button_trigger, &button_left_thumb, &button_right_thumb, &hand_right_x, &hand_right_y, &hand_right_z, &hand_right_yaw, &hand_right_pitch, &hand_right_roll, &stick_left_x, &stick_left_y, &stick_right_x, &stick_right_y); + get_poses_ovr(&button_a, &button_b, &button_x, &button_y, &button_menu, &button_trigger, &button_left_thumb, &button_right_thumb, &hand_right_x, &hand_right_y, &hand_right_z, &hand_right_yaw, &hand_right_pitch, &hand_right_roll, &stick_left_x, &stick_left_y, &stick_right_x, &stick_right_y, &head_yaw, &head_pitch, &head_roll); if (button_menu && !button_menu_last) { /* menu toggle */ if (help_view == help_views) @@ -364,11 +370,6 @@ static void handle_vr_poses(void) set_amiga_key(KEYCODE_SPACE, 1); set_amiga_key(KEYCODE_SPACE, 0); } - if (button_right_thumb && !button_right_thumb_last) { - /* 'running' pressed */ - set_amiga_key(KEYCODE_r, 1); - set_amiga_key(KEYCODE_r, 0); - } if (button_trigger && !button_trigger_last) { /* trigger pressed */ if (!keyboard_on) { @@ -387,28 +388,28 @@ static void handle_vr_poses(void) } } /* joystick */ - if (stick_right_x > 0.5) + if (stick_right_x > STICK_ROTATE_THRESHOLD) set_joystick(0, 1, -1, -1, -1); else - if (stick_right_x < -0.5) + if (stick_right_x < -STICK_ROTATE_THRESHOLD) set_joystick(1, 0, -1, -1, -1); else - if (stick_right_x_last > 0.5 || stick_right_x_last < -0.5) + if (stick_right_x_last > STICK_ROTATE_THRESHOLD || stick_right_x_last < -STICK_ROTATE_THRESHOLD) set_joystick(0, 0, -1, -1, -1); - if (stick_right_y > 0.5) + if (stick_right_y > STICK_WALK_THRESHOLD) set_joystick(-1, -1, 1, 0, -1); else - if (stick_right_y < -0.5) + if (stick_right_y < -STICK_WALK_THRESHOLD) set_joystick(-1, -1, 0, 1, -1); else - if (stick_right_y_last > 0.5 || stick_right_y_last < -0.5) + if (stick_right_y_last > STICK_WALK_THRESHOLD || stick_right_y_last < -STICK_WALK_THRESHOLD) set_joystick(-1, -1, 0, 0, -1); /* thrust */ - if (stick_left_y > 0.3) - thrust = (stick_left_y - 0.3) / 0.6 * 11.0; + if (stick_left_y > STICK_THRUST_THRESHOLD) + thrust = (stick_left_y - STICK_THRUST_THRESHOLD) / (1.0 - STICK_THRUST_THRESHOLD) * 10.5; else - if (stick_left_y < -0.3) - thrust = (stick_left_y + 0.3) / 0.6 * 11.0; + if (stick_left_y < -STICK_THRUST_THRESHOLD) + thrust = (stick_left_y - -STICK_THRUST_THRESHOLD) / (1.0 - -STICK_THRUST_THRESHOLD) * 10.5; else thrust = 0; if (thrust >= 10) @@ -448,6 +449,42 @@ static void handle_vr_poses(void) vr_key = 0; if (keyboard_on) handle_vr_keyboard(keyboard_on - 1, hand_right_x, hand_right_y, hand_right_z, hand_right_yaw, hand_right_pitch, &vr_key); + + if (stick_right_y > STICK_WALK_THRESHOLD || stick_right_y < -STICK_WALK_THRESHOLD) { + double roll, pitch, yaw; + double dist, east, north; + int32_t move_east[4], move_north[4]; + + mercenary_get_orientation(&roll, &pitch, &yaw); + /* we use a maximum move of 40 for all 4 steps (this is 10 for each step - equal to 'running') */ + if (stick_right_y > 0.0) + dist = (stick_right_y - STICK_WALK_THRESHOLD) / (1.0 - STICK_WALK_THRESHOLD) * 40.0; + else + dist = (stick_right_y + STICK_WALK_THRESHOLD) / (1.0 - STICK_WALK_THRESHOLD) * 40.0; + east = sin(hand_right_yaw + yaw + M_PI) * dist; + north = -cos(hand_right_yaw + yaw + M_PI) * dist; + /* calculatate the integer positions of 4 steps */ + move_east[0] = (int32_t)((east * 0.25) + 0.5); + move_north[0] = (int32_t)((north * 0.25) + 0.5); + move_east[1] = (int32_t)((east * 0.5) + 0.5); + move_north[1] = (int32_t)((north * 0.5) + 0.5); + move_east[2] = (int32_t)((east * 0.75) + 0.5); + move_north[2] = (int32_t)((north * 0.75) + 0.5); + move_east[3] = (int32_t)(east + 0.5); + move_north[3] = (int32_t)(north + 0.5); + /* calculate the delta between each of the 4 step */ + move_east[3] -= move_east[2]; + move_north[3] -= move_north[2]; + move_east[2] -= move_east[1]; + move_north[2] -= move_north[1]; + move_east[1] -= move_east[0]; + move_north[1] -= move_north[0]; + /* the game takes 4 steps to move the player */ + mercenary_vr_move(1, move_east, move_north); + } else { + /* don't change what the game actually does when moving joystick in y-direction */ + mercenary_vr_move(0, NULL, NULL); + } } #endif @@ -485,6 +522,14 @@ static void skip_intro(void) static void special_event(int event) { +#ifdef HAVE_OVR + /* handle VR events */ + if (event == STOP_AT_PATCH_VR) { + mercenary_patch_vr(); + return; + } +#endif + /* handle events to improve rendering */ if (render_improved) render_capture_event(event); } @@ -508,6 +553,10 @@ static void main_loop(void) /* render result on window */ while (!quit) { +#ifdef HAVE_OVR + /* get vr poses */ + handle_vr_poses(); +#endif /* if we are in interstellar fligt, we use 50 Hz */ /* if we are approaching to Eris Space Port, we use 10 Hz */ /* else we use whatever frame rate the user wants */ @@ -571,8 +620,6 @@ static void main_loop(void) /* STEP 2: transfer legacy image (or just benson) in memory to OpenGL texture */ #ifdef HAVE_OVR - handle_vr_poses(); - begin_render_ovr(); for (eye = 0; eye < 2; eye++) { @@ -1210,7 +1257,6 @@ int main(int argc, char *argv[]) "\n" "Walking / Driving / Flying using Controller:\n" " Use thumb stick on right controller, to move player / craft.\n" - " Press thumb stick on tright controller to toggle running/walking speed.\n" " Press `X' button to board, `Y' button to leave.\n" " Move thumb stick on left controller to drive/fly forward or backward.\n" " Press and hold thumb stick on left controller for escape sequence.\n" diff --git a/src/mercenary/mercenary.h b/src/mercenary/mercenary.h index c8bd3d3..bcabc3f 100644 --- a/src/mercenary/mercenary.h +++ b/src/mercenary/mercenary.h @@ -3,6 +3,7 @@ enum { STOP_AT_END = 0, STOP_AT_PATCH_RENDER, + STOP_AT_PATCH_VR, STOP_AT_WAIT_VBL, STOP_AT_WAIT_INPUT, STOP_AT_CLEAR_SCREEN1, @@ -64,10 +65,18 @@ enum { STOP_AT_EXPLOSION, }; +struct vr_move { + int override; + int index; + int32_t east[4]; + int32_t north[4]; +}; + extern const struct cpu_stop mercenary_stop_at[]; void mercenary_load(void); void mercenary_patch(void); void mercenary_patch_render(void); +void mercenary_patch_vr(void); uint32_t mercenary_palette_view(void); uint32_t mercenary_palette_render(void); uint32_t mercenary_palette_predefined(void); @@ -85,6 +94,7 @@ uint16_t mercenary_poly_tags_color(void); int mercenary_background_index(void); uint32_t mercenary_planet_scale_index(void); uint32_t mercenary_star_table(void); +void mercenary_vr_move(int override, int32_t *east, int32_t *north); extern const char *mercenary_name; extern const char *mercenary_gamesavesuffix; diff --git a/src/mercenary/mercenary2.c b/src/mercenary/mercenary2.c index 55449d2..74d9c29 100644 --- a/src/mercenary/mercenary2.c +++ b/src/mercenary/mercenary2.c @@ -18,6 +18,7 @@ */ #include +#include #include #include #include @@ -30,6 +31,9 @@ #define INITIAL_STACK 0x7fffa #define RESET_VECTOR 0x59484 +/* VR heading to alter direction we walk to */ +static struct vr_move vr_move; + /* interrupt CPU execution at special break points and tell emulation what to do */ const struct cpu_stop mercenary_stop_at[] = { { 0x59a4e, STOP_AT_WAIT_VBL }, /* done with rendering, waiting for VBL */ @@ -108,6 +112,7 @@ const struct cpu_stop mercenary_stop_at[] = { { 0x528C4, STOP_AT_PATCH_RENDER }, /* patch away planet check (behind observer) */ { 0x45806, STOP_AT_PATCH_RENDER }, /* patch away planet rendering (would crash without check above) */ { 0x53276, STOP_AT_PATCH_RENDER }, /* patch away beacon check (not visible on screen) */ + { 0x58EA8, STOP_AT_PATCH_VR }, /* step that moves player */ { 0x0, STOP_AT_END }, /* end */ }; @@ -118,6 +123,8 @@ void mercenary_load(void) { int i; + memset(&vr_move, 0, sizeof(vr_move)); + /* load game binary from constant to volatile memory */ for (i = 0; i < mercenary2_hex_size; i += 4) { m68k_write_memory_32(i, mercenary2_hex[i / 4]); @@ -183,6 +190,20 @@ void mercenary_patch_render(void) } } +/* patch execution for VR improvement */ +void mercenary_patch_vr(void) +{ + switch (REG_PC) { + case 0x58EA8: /* at this point we process one step of the player walking on the ground */ + if (vr_move.override && vr_move.index < 4) { + REG_D[2] = vr_move.east[vr_move.index]; + REG_D[3] = vr_move.north[vr_move.index]; + vr_move.index++; + } + break; + } +} + uint32_t mercenary_palette_view(void) { return m68k_read_memory_32(0x007c14); @@ -303,6 +324,15 @@ uint32_t mercenary_star_table(void) return 0x005D8C0; } +void mercenary_vr_move(int override, int32_t *east, int32_t *north) +{ + vr_move.override = override; + if (east) + memcpy(vr_move.east, east, sizeof(vr_move.east)); + if (north) + memcpy(vr_move.north, north, sizeof(vr_move.north)); + vr_move.index = 0; +} const char *mercenary_name = "Mercenary II - Damocles"; const char *mercenary_gamesavesuffix = ".m2save"; diff --git a/src/mercenary/mercenary3.c b/src/mercenary/mercenary3.c index 0a5a76d..9afd60b 100644 --- a/src/mercenary/mercenary3.c +++ b/src/mercenary/mercenary3.c @@ -18,6 +18,7 @@ */ #include +#include #include #include #include @@ -36,6 +37,9 @@ #define RESET_VECTOR 0x5a16c // #define RESET_VECTOR 0x5a1a4 /* strange reset vector that causes the player to fly around */ +/* VR heading to alter direction we walk to */ +static struct vr_move vr_move; + /* interrupt CPU execution at special break points and tell emulation what to do */ const struct cpu_stop mercenary_stop_at[] = { { 0x5a826, STOP_AT_WAIT_VBL }, /* done with rendering, waiting for VBL */ @@ -114,6 +118,7 @@ const struct cpu_stop mercenary_stop_at[] = { { 0x537B0, STOP_AT_PATCH_RENDER }, /* patch away planet check (behind observer) */ { 0x45806, STOP_AT_PATCH_RENDER }, /* patch away planet rendering (would crash without check above) */ { 0x5406E, STOP_AT_PATCH_RENDER }, /* patch away beacon check (not visible on screen) */ + { 0x59A00, STOP_AT_PATCH_VR }, /* step that moves player */ { 0x0, STOP_AT_END }, /* end */ }; @@ -124,6 +129,8 @@ void mercenary_load(void) { int i; + memset(&vr_move, 0, sizeof(vr_move)); + /* load game binary from constant to volatile memory */ for (i = 0; i < mercenary3_hex_size; i += 4) { m68k_write_memory_32(i, mercenary3_hex[i / 4]); @@ -219,6 +226,20 @@ void mercenary_patch_render(void) } } +/* patch execution for VR improvement */ +void mercenary_patch_vr(void) +{ + switch (REG_PC) { + case 0x59A00: /* at this point we process one step of the player walking on the ground */ + if (vr_move.override && vr_move.index < 4) { + REG_D[2] = vr_move.east[vr_move.index]; + REG_D[3] = vr_move.north[vr_move.index]; + vr_move.index++; + } + break; + } +} + uint32_t mercenary_palette_view(void) { return m68k_read_memory_32(0x0072b0); @@ -342,6 +363,16 @@ uint32_t mercenary_star_table(void) return DS_84+0x6A; } +void mercenary_vr_move(int override, int32_t *east, int32_t *north) +{ + vr_move.override = override; + if (east) + memcpy(vr_move.east, east, sizeof(vr_move.east)); + if (north) + memcpy(vr_move.north, north, sizeof(vr_move.north)); + vr_move.index = 0; +} + const char *mercenary_name = "Mercenary III - The Dion Crisis"; const char *mercenary_gamesavesuffix = ".m3save"; -- 2.13.6