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;
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;
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;
*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;
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);
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
+#include <math.h>
#include <sys/stat.h>
#include <sys/types.h>
#include "../../include/keycodes.h"
#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;
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)
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) {
}
}
/* 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)
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
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);
}
/* 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 */
/* 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++) {
"\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"
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,
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);
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;
*/
#include <stdio.h>
+#include <string.h>
#include <stdint.h>
#include <stdlib.h>
#include <math.h>
#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 */
{ 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 */
};
{
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]);
}
}
+/* 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);
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";
*/
#include <stdio.h>
+#include <string.h>
#include <stdint.h>
#include <stdlib.h>
#include <math.h>
#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 */
{ 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 */
};
{
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]);
}
}
+/* 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);
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";