MassBuilderSaveTool/src/Mass/Mass.cpp

294 lines
7.7 KiB
C++

// MassBuilderSaveTool
// Copyright (C) 2021 Guillaume Jacquemin
//
// This program 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, or
// (at your option) any later version.
//
// This program 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.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
#include <cstring>
#include <algorithm>
#include <Corrade/Containers/Array.h>
#include <Corrade/Utility/Directory.h>
#include "Locators.h"
#include "Mass.h"
std::string Mass::_lastError;
Mass::Mass(const std::string& path) {
_folder = Utility::Directory::path(path);
_filename = Utility::Directory::filename(path);
refreshValues();
}
auto Mass::lastError() -> std::string const& {
return _lastError;
}
auto Mass::getNameFromFile(const std::string& path) -> std::string {
if(!Utility::Directory::exists(path)) {
_lastError = path + " couldn't be found.";
return "";
}
std::string name;
auto mmap = Utility::Directory::mapRead(path);
auto iter = std::search(mmap.begin(), mmap.end(), &mass_name_locator[0], &mass_name_locator[56]);
if(iter != mmap.end()) {
name = std::string{iter + 70};
}
else {
_lastError = "The name couldn't be found in " + path;
}
return name;
}
void Mass::refreshValues() {
getName();
if(_state != State::Valid) {
return;
}
getFrameStyles();
getJointSliders();
}
auto Mass::filename() -> std::string const&{
return _filename;
}
auto Mass::name() -> std::string const&{
return _name;
}
auto Mass::state() -> State {
return _state;
}
auto Mass::jointSliders() -> Joints const& {
return _sliders;
}
auto Mass::frameStyles() -> Containers::StaticArrayView<4, Int> {
return _frameStyles;
}
auto Mass::setFrameStyle(Int index, Int style_id) -> bool {
if(index < 0 || index > 3) {
_lastError = "Index is out of range in Mass::setFrameStyle().";
return false;
}
std::string path = Utility::Directory::join(_folder, _filename);
if(!Utility::Directory::exists(path)) {
_lastError = path + " couldn't be found.";
_state = State::Empty;
return false;
}
auto mmap = Utility::Directory::map(path);
auto iter = std::search(mmap.begin(), mmap.end(), &frame_styles_locator[0], &frame_styles_locator[90]);
if(iter != mmap.end()) {
iter += 0x5A;
*(reinterpret_cast<Int*>(iter) + index) = style_id;
}
else {
_lastError = "Frame styles couldn't be found in " + path;
_state = State::Invalid;
return false;
}
return true;
}
auto Mass::updateSteamId(const std::string& steam_id) -> bool {
std::string path = Utility::Directory::join(_folder, _filename);
if(!Utility::Directory::exists(path)) {
_lastError = path + " couldn't be found.";
_state = State::Empty;
return false;
}
Utility::Directory::copy(path, path + ".tmp");
{
auto mmap = Utility::Directory::map(path + ".tmp");
auto iter = std::search(mmap.begin(), mmap.end(), &steamid_locator[0], &steamid_locator[23]);
if(iter == mmap.end()) {
_lastError = "The M.A.S.S. file at " + path + " seems to be corrupt.";
Utility::Directory::rm(path + ".tmp");
return false;
}
iter += 37;
if(std::strncmp(iter, steam_id.c_str(), steam_id.length()) != 0) {
for(int i = 0; i < 17; ++i) {
*(iter + i) = steam_id[i];
}
}
}
if(Utility::Directory::exists(path)) {
Utility::Directory::rm(path);
}
Utility::Directory::move(path + ".tmp", path);
return true;
}
void Mass::getName() {
std::string path = Utility::Directory::join(_folder, _filename);
if(!Utility::Directory::exists(path)) {
_lastError = path + " couldn't be found.";
_state = State::Empty;
return;
}
auto mmap = Utility::Directory::mapRead(path);
auto iter = std::search(mmap.begin(), mmap.end(), &mass_name_locator[0], &mass_name_locator[56]);
if(iter != mmap.end()) {
_name = std::string{iter + 70};
_state = State::Valid;
}
else {
_lastError = "The name couldn't be found in " + _filename;
_state = State::Invalid;
}
}
void Mass::getJointSliders() {
std::string path = Utility::Directory::join(_folder, _filename);
if(!Utility::Directory::exists(path)) {
_lastError = path + " couldn't be found.";
_state = State::Empty;
return;
}
auto mmap = Utility::Directory::mapRead(path);
auto iter = std::search(mmap.begin(), mmap.end(), &neck_slider_locator[0], &neck_slider_locator[63]);
if(iter != mmap.end()) {
_sliders.neck = *reinterpret_cast<const Float*>(iter + 0x49);
}
else {
_sliders.neck = 0.0f;
}
iter = std::search(mmap.begin(), mmap.end(), &body_slider_locator[0], &body_slider_locator[63]);
if(iter != mmap.end()) {
_sliders.body = *reinterpret_cast<const Float*>(iter + 0x49);
}
else {
_sliders.body = 0.0f;
}
iter = std::search(mmap.begin(), mmap.end(), &shoulders_slider_locator[0], &shoulders_slider_locator[67]);
if(iter != mmap.end()) {
_sliders.shoulders = *reinterpret_cast<const Float*>(iter + 0x4D);
}
else {
_sliders.shoulders = 0.0f;
}
iter = std::search(mmap.begin(), mmap.end(), &hips_slider_locator[0], &hips_slider_locator[63]);
if(iter != mmap.end()) {
_sliders.hips = *reinterpret_cast<const Float*>(iter + 0x49);
}
else {
_sliders.hips = 0.0f;
}
iter = std::search(mmap.begin(), mmap.end(), &uarms_slider_locator[0], &uarms_slider_locator[68]);
if(iter != mmap.end()) {
_sliders.upperArms = *reinterpret_cast<const Float*>(iter + 0x4E);
}
else {
_sliders.upperArms = 0.0f;
}
iter = std::search(mmap.begin(), mmap.end(), &larms_slider_locator[0], &larms_slider_locator[68]);
if(iter != mmap.end()) {
_sliders.lowerArms = *reinterpret_cast<const Float*>(iter + 0x4E);
}
else {
_sliders.lowerArms = 0.0f;
}
iter = std::search(mmap.begin(), mmap.end(), &ulegs_slider_locator[0], &ulegs_slider_locator[68]);
if(iter != mmap.end()) {
_sliders.upperLegs = *reinterpret_cast<const Float*>(iter + 0x4E);
}
else {
_sliders.upperLegs = 0.0f;
}
iter = std::search(mmap.begin(), mmap.end(), &llegs_slider_locator[0], &llegs_slider_locator[68]);
if(iter != mmap.end()) {
_sliders.lowerLegs = *reinterpret_cast<const Float*>(iter + 0x4E);
}
else {
_sliders.lowerLegs = 0.0f;
}
}
void Mass::getFrameStyles() {
std::string path = Utility::Directory::join(_folder, _filename);
if(!Utility::Directory::exists(path)) {
_lastError = path + " couldn't be found.";
_state = State::Empty;
return;
}
auto mmap = Utility::Directory::mapRead(path);
auto iter = std::search(mmap.begin(), mmap.end(), &frame_styles_locator[0], &frame_styles_locator[90]);
if(iter != mmap.end()) {
iter += 0x5A;
std::copy(reinterpret_cast<const Int*>(iter), reinterpret_cast<const Int*>(iter) + 4, _frameStyles.data());
}
else {
_lastError = "Frame styles couldn't be found in " + path;
_state = State::Invalid;
}
}