Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

FF8: Vibration feature #415

Merged
merged 3 commits into from
Mar 19, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ set(RELEASE_NAME "FFNx")
if(_DLL_VERSION STREQUAL "devel" OR _DLL_VERSION MATCHES "-")
set(_DLL_RCVERSION "0,0,0,0")
set(_DLL_RCSTRVERSION "0.0.0.0")
set(PATCH_COLLECT_DUPLICATES 1)
else()
string(REPLACE "." "," _DLL_RCVERSION ${_DLL_VERSION})
set(_DLL_RCSTRVERSION ${_DLL_VERSION})
Expand Down Expand Up @@ -142,6 +143,11 @@ target_compile_options(
PRIVATE /Zc:strictStrings-
PRIVATE /Qpar
)
if(PATCH_COLLECT_DUPLICATES)
target_compile_definitions(${RELEASE_NAME}
PRIVATE PATCH_COLLECT_DUPLICATES
)
endif()
target_compile_features(${RELEASE_NAME}
PRIVATE cxx_std_20
)
Expand Down
2 changes: 2 additions & 0 deletions src/common.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@
#include "achievement.h"

#include "ff8/vram.h"
#include "ff8/vibration.h"

bool proxyWndProc = false;

Expand Down Expand Up @@ -677,6 +678,7 @@ int common_create_window(HINSTANCE hInstance, struct game_obj* game_object)
if (ff8)
{
vram_init();
vibration_init();
}

// enable verbose logging for FFMpeg
Expand Down
32 changes: 30 additions & 2 deletions src/crashdump.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,17 +33,45 @@
class FFNxStackWalker : public StackWalker
{
public:
FFNxStackWalker() : StackWalker() {}
FFNxStackWalker(bool muted = false) : StackWalker(), _baseAddress(0), _size(0), _muted(muted) {}
DWORD64 getBaseAddress() const {
return _baseAddress;
}
DWORD getSize() const {
return _size;
}
protected:
virtual void OnLoadModule(LPCSTR img, LPCSTR mod, DWORD64 baseAddr,
DWORD size, DWORD result, LPCSTR symType, LPCSTR pdbName,
ULONGLONG fileVersion
)
{
if (_baseAddress == 0 && _size == 0)
{
_baseAddress = baseAddr;
_size = size;
}
StackWalker::OnLoadModule(
img, mod, baseAddr, size, result, symType, pdbName, fileVersion
);
}

virtual void OnDbgHelpErr(LPCSTR szFuncName, DWORD gle, DWORD64 addr)
{
// Silence is golden.
}

virtual void OnOutput(LPCSTR szText)
{
ffnx_trace(szText);
if (! _muted)
{
ffnx_trace(szText);
}
}
private:
DWORD64 _baseAddress;
DWORD _size;
bool _muted;
};

LONG WINAPI ExceptionHandler(EXCEPTION_POINTERS *ep);
64 changes: 58 additions & 6 deletions src/ff8.h
Original file line number Diff line number Diff line change
Expand Up @@ -563,6 +563,55 @@ struct ff8_win_obj
uint32_t callback2;
};

struct ff8_gamepad_vibration_state_entry {
int8_t field_0[20];
};

struct ff8_gamepad_vibration_state {
uint8_t field_0;
uint8_t field_1;
uint8_t field_2;
uint8_t field_3;
uint16_t field_4;
uint8_t right_motor_speed;
uint8_t left_motor_speed;
uint8_t field_8;
uint8_t field_9;
uint8_t vibration_active;
uint8_t vibration_capable;
uint32_t field_C;
uint32_t field_10;
uint32_t field_14;
uint8_t field_18;
uint8_t field_19;
uint8_t field_1A;
uint8_t vibrate_option_enabled;
ff8_gamepad_vibration_state_entry entries[8];
uint32_t field_BC;
uint32_t field_C0;
};

struct ff8_vibrate_motor_struc
{
uint8_t *data_start;
uint8_t *data_end;
int16_t counter;
uint16_t data_size;
uint8_t enabled;
uint8_t padding_D;
uint8_t padding_E;
uint8_t padding_F;
};

struct ff8_vibrate_struc
{
ff8_vibrate_motor_struc sub_struc_left;
ff8_vibrate_motor_struc sub_struc_right;
uint16_t field_20;
uint8_t intensity;
uint8_t field_23;
};

struct ff8_game_obj
{
uint32_t do_quit;
Expand Down Expand Up @@ -839,7 +888,6 @@ struct ff8_externals
uint32_t nvidia_hack2;
struct sprite_viewport *menu_viewport;
uint32_t main_loop;
uint32_t cardgame_mainloop;
uint32_t sub_47CCB0;
uint32_t sub_534640;
uint32_t sub_4972A0;
Expand Down Expand Up @@ -872,7 +920,6 @@ struct ff8_externals
uint32_t sub_468BD0;
uint32_t pubintro_main_loop;
uint32_t credits_main_loop;
uint32_t sub_52F300;
DWORD* credits_loop_state;
DWORD* credits_counter;
uint32_t sub_470520;
Expand Down Expand Up @@ -929,7 +976,6 @@ struct ff8_externals
DWORD* engine_mapped_buttons;
uint32_t pubintro_enter_main;
uint32_t draw_movie_frame;
uint32_t sub_529FF0;
struct ff8_movie_obj *movie_object;
uint32_t initialize_sound;
int (*sub_5304B0)();
Expand Down Expand Up @@ -982,9 +1028,6 @@ struct ff8_externals
uint32_t sub_46DDC0;
uint32_t start;
uint32_t battle_main_loop;
uint32_t is_window_active;
uint32_t is_window_active_sub1;
uint32_t is_window_active_sub2;
void (*show_vram_window)();
void (*refresh_vram_window)();
char* music_path;
Expand Down Expand Up @@ -1054,6 +1097,15 @@ struct ff8_externals
uint32_t sub_4A0880;
uint32_t sub_4A0C00;
char(*show_dialog)(int32_t, uint32_t, int16_t);
int(*pause_menu_with_vibration)(int);
int(*pause_menu)(int);
uint32_t init_pause_menu;
uint32_t get_vibration_capability;
uint32_t vibration_apply;
int(*get_keyon)(int, int);
uint32_t set_vibration;
ff8_gamepad_vibration_state *gamepad_vibration_states;
ff8_vibrate_struc *vibration_objects;
};

void ff8gl_field_78(struct ff8_polygon_set *polygon_set, struct ff8_game_obj *game_object);
Expand Down
97 changes: 97 additions & 0 deletions src/ff8/vibration.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
/****************************************************************************/
// Copyright (C) 2009 Aali132 //
// Copyright (C) 2018 quantumpencil //
// Copyright (C) 2018 Maxime Bacoux //
// Copyright (C) 2020 Chris Rizzitello //
// Copyright (C) 2020 John Pritchard //
// Copyright (C) 2022 myst6re //
// Copyright (C) 2022 Julian Xhokaxhiu //
// Copyright (C) 2022 Tang-Tang Zhou //
// //
// This file is part of FFNx //
// //
// FFNx is free software: you can redistribute it and/or modify //
// it under the terms of the GNU General Public License as published by //
// the Free Software Foundation, either version 3 of the License //
// //
// FFNx is distributed in the hope that it will be useful, //
// but WITHOUT ANY WARRANTY; without even the implied warranty of //
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
// GNU General Public License for more details. //
/****************************************************************************/
#include "vibration.h"
#include "../ff8.h"
#include "../log.h"
#include "../gamepad.h"
#include "../patch.h"

int previous_left = 0;
int previous_right = 0;

int ff8_vibrate_capability(int port)
{
if (trace_all) ffnx_trace("%s port=%d\n", __func__, port);

return xinput_connected && gamepad.GetPort() > 0;
}

int ff8_game_is_paused(int callback)
{
if (trace_all) ffnx_trace("%s callback=%p\n", __func__, callback);

if (ff8_vibrate_capability(0))
{
// Reroute to the vibrate pause menu
int ret = ff8_externals.pause_menu_with_vibration(callback);

int keyon = ff8_externals.get_keyon(0, 0);
// Press pause again
if ((keyon & 0x800) != 0) {
return 1;
}

return ret;
}

return ff8_externals.pause_menu(callback);
}

void apply_vibrate_calc(char port, int left, int right)
{
ff8_gamepad_vibration_state *gamepad_state = ff8_externals.gamepad_vibration_states;
ff8_vibrate_struc *vibration_objects = ff8_externals.vibration_objects;
XINPUT_VIBRATION vibration = XINPUT_VIBRATION();

int enabled = gamepad_state[port].vibrate_option_enabled;

if (left >= 0)
{
gamepad_state[port & 1].left_motor_speed = left;
vibration.wLeftMotorSpeed = left * 65535 / 255;
}
if (right >= 0)
{
gamepad_state[port & 1].right_motor_speed = right;
vibration.wRightMotorSpeed = right * 65535 / 255;
}
gamepad_state[port & 1].vibration_active = 1;

if (enabled == 255 && (previous_left != left || previous_right != right))
{
if (xinput_connected)
{
gamepad.SetState(vibration);
gamepad.Send();
}
}

previous_left = left;
previous_right = right;
}

void vibration_init()
{
replace_call(uint32_t(ff8_externals.check_game_is_paused) + 0x88, ff8_game_is_paused);
replace_function(ff8_externals.get_vibration_capability, ff8_vibrate_capability);
replace_function(ff8_externals.vibration_apply, apply_vibrate_calc);
}
25 changes: 25 additions & 0 deletions src/ff8/vibration.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/****************************************************************************/
// Copyright (C) 2009 Aali132 //
// Copyright (C) 2018 quantumpencil //
// Copyright (C) 2018 Maxime Bacoux //
// Copyright (C) 2020 Chris Rizzitello //
// Copyright (C) 2020 John Pritchard //
// Copyright (C) 2022 myst6re //
// Copyright (C) 2022 Julian Xhokaxhiu //
// Copyright (C) 2022 Tang-Tang Zhou //
// //
// This file is part of FFNx //
// //
// FFNx is free software: you can redistribute it and/or modify //
// it under the terms of the GNU General Public License as published by //
// the Free Software Foundation, either version 3 of the License //
// //
// FFNx is distributed in the hope that it will be useful, //
// but WITHOUT ANY WARRANTY; without even the implied warranty of //
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
// GNU General Public License for more details. //
/****************************************************************************/

#pragma once

void vibration_init();
Loading