Port XboxHandsVC

Based on https://github.com/gennariarmando/gtavc-xbox-hands
This commit is contained in:
Dima353
2026-07-28 00:09:29 +03:00
parent f21b7bd3ff
commit 00ce78eaa1
12 changed files with 3321 additions and 4 deletions
+1 -1
View File
@@ -18,7 +18,7 @@ CXX = $(PREFIX)-g++
ARCH := -mtune=cortex-a9 -march=armv7-a -mfpu=neon
CFLAGS := -g -Wl,-q,--no-enum-size-warning -fno-short-enums -fno-optimize-sibling-calls -O2 -ftree-vectorize -mfloat-abi=hard -fno-builtin-memcpy $(ARCH) $(DEFINES)
CFLAGS += $(INCLUDE) -DPSP2 -DMASTER -DLIBRW -DRW_GL3 -DAUDIO_OAL -DLIBRW_GLAD
CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions
CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions -std=gnu++17
ASFLAGS := -g $(ARCH)
LDFLAGS = -g $(ARCH) -Wl,-Map,$(notdir $*.map)
LIBS := -lrw -lopenal -lSDL2 -lvita2d -lvitaGL -lSceAppMgr_stub -lSceDisplay_stub -lSceCommonDialog_stub -lSceLibKernel_stub \
+5
View File
@@ -22,6 +22,7 @@
#include "ColStore.h"
#include "Radar.h"
#include "Pools.h"
#include "CutsceneHands.h"
const struct {
const char *szTrackName;
@@ -204,6 +205,10 @@ CCutsceneMgr::LoadCutsceneData(const char *szCutsceneName)
strcpy(ms_cutsceneName, szCutsceneName);
#ifdef CUTSCENE_HANDS
CutsceneHands::InitXML();
#endif
RwStream *stream;
stream = RwStreamOpen(rwSTREAMFILENAME, rwSTREAMREAD, "ANIM\\CUTS.IMG");
assert(stream);
+5
View File
@@ -18,6 +18,7 @@
#include "Cranes.h"
#include "Credits.h"
#include "CutsceneMgr.h"
#include "CutsceneHands.h"
#include "DMAudio.h"
#include "Darkel.h"
#include "Debug.h"
@@ -585,6 +586,10 @@ bool CGame::Initialise(const char* datFile)
DMAudio.SetStartingTrackPositions(TRUE);
DMAudio.ChangeMusicMode(MUSICMODE_GAME);
#ifdef CUTSCENE_HANDS
CutsceneHands::Initialise();
#endif
return true;
}
+13 -1
View File
@@ -25,6 +25,7 @@
#include "Population.h"
#include "Gangs.h"
#include "CutsceneMgr.h"
#include "CutsceneHands.h"
#include "CdStream.h"
#include "Streaming.h"
#include "Replay.h"
@@ -1055,17 +1056,28 @@ void
CStreaming::RequestSpecialChar(int32 charId, const char *modelName, int32 flags)
{
RequestSpecialModel(charId + MI_SPECIAL01, modelName, flags);
#ifdef CUTSCENE_HANDS
CutsceneHands::RequestSpecialChar(charId, modelName);
#endif
}
bool
CStreaming::HasSpecialCharLoaded(int32 id)
{
return HasModelLoaded(id + MI_SPECIAL01);
bool loaded = HasModelLoaded(id + MI_SPECIAL01);
#ifdef CUTSCENE_HANDS
if(loaded)
CutsceneHands::SpecialCharLoaded(id);
#endif
return loaded;
}
void
CStreaming::SetMissionDoesntRequireSpecialChar(int32 id)
{
#ifdef CUTSCENE_HANDS
CutsceneHands::UnloadSpecialChar(id);
#endif
return SetMissionDoesntRequireModel(id + MI_SPECIAL01);
}
+3
View File
@@ -355,6 +355,9 @@ enum Config {
#define EXTENDED_PIPELINES // custom render pipelines (includes Neo)
#define SCREEN_DROPLETS // neo water droplets
#define NEW_RENDERER // leeds-like world rendering, needs librw
#ifdef RT
#define CUTSCENE_HANDS // Xbox HD cutscene hands (ported from XboxHandsVC.asi); RT-only (10thAE/Vanilla mod builds), needs assets, self-disables if absent
#endif
#endif
#define FIX_SPRITES // fix sprites aspect ratio(moon, coronas, particle etc)
File diff suppressed because it is too large Load Diff
+44
View File
@@ -0,0 +1,44 @@
#pragma once
#include "config.h"
#ifdef CUTSCENE_HANDS
// HD cutscene hands, backported from the Xbox version of GTA:VC.
// Ported from the "XboxHandsVC" plugin-sdk mod (XboxHandsVC.asi) into native
// re3/reVC source: the plugin's address hooks become direct calls from
// CCutsceneObject / CCutsceneMgr / CStreaming, and its RenderWare skin/HAnim
// calls are mapped onto librw.
//
// SAFETY: the feature is fully opt-in on the assets. Initialise() only flips
// ms_enabled to true when EVERY required asset loads (anim/CSHands.txd,
// anim/CSHands.dff, the four anim/*.anm files, data/CutsceneHands.xml). If any
// is missing or fails to parse, ms_enabled stays false, a note is logged, and
// every entry point below becomes a no-op. The game then runs exactly as stock
// -- the original mod called exit(1) on a missing model; we never do that.
class CObject;
class CutsceneHands
{
public:
static bool ms_enabled; // true only after all assets loaded successfully
// Lifecycle (call once RenderWare + streaming/TxdStore are up, and at shutdown)
static void Initialise(void); // loads txd/dff/anm/xml; sets ms_enabled
static void Shutdown(void);
// CCutsceneMgr::LoadCutsceneData -> (re)parse the per-cutscene config
static void InitXML(void);
// Special-character streaming (CStreaming request/loaded/remove for cutscene actors)
static void RequestSpecialChar(int slot, const char *name);
static void SpecialCharLoaded(int id);
static void UnloadSpecialChar(int id);
// CCutsceneObject render hooks
static void PreRender(CObject *obj); // attach + pose the HD hands, atrophy stock hand bones
static void Render(CObject *obj); // draw the HD hand atomics for this actor
};
#endif // CUTSCENE_HANDS
+56
View File
@@ -0,0 +1,56 @@
#pragma once
#include "config.h"
#ifdef CUTSCENE_HANDS
// Small RenderWare helpers for the cutscene-hands port. The original mod's Utils.h
// reimplemented these with hardcoded retail-VC addresses and RW-SDK struct field
// names; none of that exists here, so everything is redone on top of librw (via the
// fakerw layer, which already provides the native RpHAnim*/RpClump*/RwStream* API).
#include "rwcore.h"
#include "rpworld.h"
#include "rphanim.h"
#include "rpskin.h"
// Load a .dff clump from a loose file. Returns nil on any failure (caller decides).
static RpClump *CutsceneHands_LoadClump(const char *name)
{
RwStream *stream = RwStreamOpen(rwSTREAMFILENAME, rwSTREAMREAD, name);
if(stream == nil)
return nil;
RpClump *out = nil;
if(RwStreamFindChunk(stream, rwID_CLUMP, nil, nil))
out = RpClumpStreamRead(stream);
RwStreamClose(stream, nil);
return out;
}
// Load a RenderWare .anm (HAnim animation) from a loose file. nil on failure.
static RpHAnimAnimation *CutsceneHands_LoadAnm(const char *name)
{
RwStream *stream = RwStreamOpen(rwSTREAMFILENAME, rwSTREAMREAD, name);
if(stream == nil)
return nil;
RpHAnimAnimation *out = nil;
if(RwStreamFindChunk(stream, rwID_HANIMANIMATION, nil, nil))
out = RpHAnimAnimationStreamRead(stream);
RwStreamClose(stream, nil);
return out;
}
static RpAtomic *CutsceneHands_GetHierCB(RpAtomic *atomic, void *data)
{
*(RpHAnimHierarchy**)data = RpSkinAtomicGetHAnimHierarchy(atomic);
return nil;
}
// First skinned atomic's HAnim hierarchy in a clump.
static RpHAnimHierarchy *CutsceneHands_GetHierarchy(RpClump *clump)
{
RpHAnimHierarchy *hier = nil;
RpClumpForAllAtomics(clump, CutsceneHands_GetHierCB, &hier);
return hier;
}
#endif // CUTSCENE_HANDS
File diff suppressed because it is too large Load Diff
+230
View File
@@ -0,0 +1,230 @@
//base code from unknown
//psksvp@ccs.neu.edu has added/modified this code.
#ifndef __XML_LIBRARY__
#define __XML_LIBRARY__
#include "config.h"
#ifdef CUTSCENE_HANDS // only built for the Xbox cutscene-hands feature (handhelds)
#include <memory>
#include <vector>
#include <string>
#include <istream>
namespace XmlLibrary
{
class Attribute;
class Element;
class Null;
typedef std::vector<Attribute*> AttributeVector;
typedef std::vector<Element*> ElementVector;
class Attribute
{
std::string m_strName;
std::string m_strValue;
public:
Attribute(const std::string& strName, const std::string& strValue);
const std::string& Name(void) const;
const std::string& Value(void) const;
};
class Value
{
std::string m_strValue;
public:
Value(void);
void Add(const std::string& strText);
void Add(char c);
operator const std::string&(void) const;
operator const char*(void) const;
operator bool(void) const;
operator char(void) const;
operator unsigned char(void) const;
operator short(void) const;
operator unsigned short(void) const;
operator int(void) const;
operator unsigned int(void) const;
operator long(void) const;
operator unsigned long(void) const;
operator float(void) const;
operator double(void) const;
};
class Element
{
private:
const std::string m_strName;
Value m_value;
public:
static Null& null;
public:
Element(void);
Element(const std::string& strName);
virtual ~Element(void);
void AddValue(const std::string& strText);
void AddValue(char c);
const std::string& GetName(void) const;
const Value& GetValue(void) const;
const Element& operator()(const char* szName, int nIndex = 0) const;
public:
virtual bool IsNull(void) const;
virtual bool Add(Element* pChild) = 0;
virtual const ElementVector* GetChilds(void) const = 0;
virtual const Element& GetChild(const char* szName, int nIndex = 0) const = 0;
virtual const AttributeVector* GetAttributes(void) const = 0;
};
class Tag :public Element
{
private:
AttributeVector m_attributes;
ElementVector m_childs;
public:
Tag(const std::string& strName);
~Tag(void);
void Add(Attribute* pAttribute);
virtual bool Add(Element* pChild);
virtual const ElementVector* GetChilds(void) const;
virtual const Element& GetChild(const char* szName, int nIndex = 0) const;
virtual const AttributeVector* GetAttributes(void) const;
private:
bool FindChild(const char* szName, ElementVector::const_iterator& it) const;
};
class Simple :public Element
{
public:
Simple(const std::string& strName);
virtual bool Add(Element* pChild);
virtual const ElementVector* GetChilds(void) const;
virtual const Element& GetChild(const char* szName, int nIndex = 0) const;
virtual const AttributeVector* GetAttributes(void) const;
};
class Comment :public Simple
{
public:
Comment(const std::string& strComment);
};
class Null :public Simple
{
public:
Null(void);
private:
virtual bool IsNull(void) const;
};
class SyntaxError
{
private:
int m_nLine;
int m_nColumn;
public:
SyntaxError(int nLine, int nColumn);
int GetLine(void) const;
int GetColumn(void) const;
};
class Parser;
class Bookmark
{
private:
Parser& m_reader;
const char* m_szSourceCurrent;
//std::istream::pos_type m_CurPos;
int m_nLine;
int m_nColumn;
public:
Bookmark(Parser& reader);
void Restore(void);
void GetSubString(std::string& strString, int nNumEndSkip = 0);
void Reset(void);
};
class Parser
{
friend class Bookmark;
private:
const char* m_szSource;
const char* m_szSourceCurrent;
const char* m_szSourceEnd;
//std::istream* m_pInputStream;
int m_nLine;
int m_nColumn;
std::string m_strXmlVersion;
std::unique_ptr<Element> m_pRootElem;
bool m_hasError; // set instead of throwing under -fno-exceptions
public:
bool HadError(void) const { return m_hasError; }
Parser(void);
virtual ~Parser(void);
//Element& Parse(std::istream* pInputStream);
Element& Parse(const char* szXmlSource, unsigned int nSourceSize);
private:
char NextChar(void);
void PreviousChar(void);
bool ParseSpaces(void);
bool ParseString(const char* pString);
bool ParseStringNoCase(const char* pString);
bool ParseNumber(int& nNum);
bool ParseHexNumber(int& nNum);
bool ParseChar(char c);
bool ParseName(std::string& strName);
bool ParseDeclBegining(const char* szString);
bool ParseXMLDecl(void);
bool ParseEq(void);
bool ParseVersionInfo(std::string& strVersion);
bool ParseVersionNum(std::string& strVersion);
bool ParseEncodingDecl(void);
bool ParseEncName(void);
void ParseMiscs(void);
bool ParseReference(char& c);
bool ParseAttValue(std::string& strValue);
bool ParseAttribute(Tag* pElem);
bool ParseETag(Element& element);
void ParseContentETag(Tag& element);
bool ParseMarkup(Element& element);
bool ParseCDATA(Element& element);
Comment* ParseComment(void);
Tag* ParseTagBegining(void);
Tag* ParseElement(void);
Element* ParseDocument(void);
bool MapReferenceName(const std::string& strName, char& c);
void RaiseSyntaxError(void);
};
}
#endif // CUTSCENE_HANDS
#endif
+9 -2
View File
@@ -47,7 +47,8 @@ RwReal RwV3dDotProduct(const RwV3d * ina, const RwV3d * inb) { return dot(*ina,
//void RwV3dCrossProduct(RwV3d * out, const RwV3d * ina, const RwV3d * inb);
RwV3d *RwV3dTransformPoints(RwV3d * pointsOut, const RwV3d * pointsIn, RwInt32 numPoints, const RwMatrix * matrix)
{ V3d::transformPoints(pointsOut, pointsIn, numPoints, matrix); return pointsOut; }
//RwV3d *RwV3dTransformVectors(RwV3d * vectorsOut, const RwV3d * vectorsIn, RwInt32 numPoints, const RwMatrix * matrix);
RwV3d *RwV3dTransformVectors(RwV3d * vectorsOut, const RwV3d * vectorsIn, RwInt32 numPoints, const RwMatrix * matrix)
{ V3d::transformVectors(vectorsOut, vectorsIn, numPoints, matrix); return vectorsOut; }
@@ -92,7 +93,7 @@ RwFrame *RwFrameTransform(RwFrame * frame, const RwMatrix * m, RwOpCombineType c
RwFrame *RwFrameOrthoNormalize(RwFrame * frame) { return frame; }
RwFrame *RwFrameSetIdentity(RwFrame * frame) { frame->matrix.setIdentity(); frame->updateObjects(); return frame; }
//RwFrame *RwFrameCloneHierarchy(RwFrame * root);
//RwBool RwFrameDestroyHierarchy(RwFrame * frame);
RwBool RwFrameDestroyHierarchy(RwFrame * frame) { frame->destroyHierarchy(); return true; }
RwFrame *RwFrameForAllChildren(RwFrame * frame, RwFrameCallBack callBack, void *data)
{ return frame->forAllChildren(callBack, data); }
RwFrame *RwFrameRemoveChild(RwFrame * child) { child->removeChild(); return child; }
@@ -897,6 +898,12 @@ RpHAnimHierarchy *RpHAnimHierarchySetFlags(RpHAnimHierarchy *hierarchy, RpHAnimH
RwBool RpHAnimHierarchySetCurrentAnim(RpHAnimHierarchy *hierarchy, RpHAnimAnimation *anim) { hierarchy->interpolator->setCurrentAnim(anim); return true; }
RwBool RpHAnimHierarchyAddAnimTime(RpHAnimHierarchy *hierarchy, RwReal time) { hierarchy->interpolator->addTime(time); return true; }
RwBool RpHAnimHierarchySetCurrentAnimTime(RpHAnimHierarchy *hierarchy, RwReal time) {
// librw has no absolute-time setter; reset to t=0 then advance.
rw::AnimInterpolator *interp = hierarchy->interpolator;
if(interp->currentAnim){ interp->setCurrentAnim(interp->currentAnim); interp->addTime(time); }
return true;
}
RwMatrix *RpHAnimHierarchyGetMatrixArray(RpHAnimHierarchy *hierarchy) { return hierarchy->matrices; }
RwBool RpHAnimHierarchyUpdateMatrices(RpHAnimHierarchy *hierarchy) { hierarchy->updateMatrices(); return true; }
+8
View File
@@ -12,6 +12,7 @@
#include "Shadows.h"
#include "Timecycle.h"
#include "CutsceneShadow.h"
#include "CutsceneHands.h"
#include "CutsceneObject.h"
#include "ModelIndices.h"
#include "RpAnimBlend.h"
@@ -145,6 +146,10 @@ CCutsceneObject::PreRender(void)
RpGeometrySetFlags(geometry, RpGeometryGetFlags(geometry) | rpGEOMETRYMODULATEMATERIALCOLOR);
RpGeometryForAllMaterials(geometry, MaterialSetAlpha, (void*)255);
}
#ifdef CUTSCENE_HANDS
CutsceneHands::PreRender(this);
#endif
}
void
@@ -152,6 +157,9 @@ CCutsceneObject::Render(void)
{
SetCullMode(rwCULLMODECULLNONE);
CObject::Render();
#ifdef CUTSCENE_HANDS
CutsceneHands::Render(this);
#endif
SetCullMode(rwCULLMODECULLBACK);
}