mirror of
https://github.com/zeldaret/botw.git
synced 2024-11-23 05:10:01 +00:00
Switch to subrepos
git subrepo clone https://github.com/open-ead/sead lib/sead subrepo: subdir: "lib/sead" merged: "1b66e825d" upstream: origin: "https://github.com/open-ead/sead" branch: "master" commit: "1b66e825d" git-subrepo: version: "0.4.3" origin: "https://github.com/ingydotnet/git-subrepo" commit: "2f68596" git subrepo clone (merge) https://github.com/open-ead/nnheaders lib/NintendoSDK subrepo: subdir: "lib/NintendoSDK" merged: "9ee21399f" upstream: origin: "https://github.com/open-ead/nnheaders" branch: "master" commit: "9ee21399f" git-subrepo: version: "0.4.3" origin: "ssh://git@github.com/ingydotnet/git-subrepo" commit: "2f68596" git subrepo clone https://github.com/open-ead/agl lib/agl subrepo: subdir: "lib/agl" merged: "7c063271b" upstream: origin: "https://github.com/open-ead/agl" branch: "master" commit: "7c063271b" git-subrepo: version: "0.4.3" origin: "ssh://git@github.com/ingydotnet/git-subrepo" commit: "2f68596" git subrepo clone https://github.com/open-ead/EventFlow lib/EventFlow subrepo: subdir: "lib/EventFlow" merged: "c35d21b34" upstream: origin: "https://github.com/open-ead/EventFlow" branch: "master" commit: "c35d21b34" git-subrepo: version: "0.4.3" origin: "ssh://git@github.com/ingydotnet/git-subrepo" commit: "2f68596"
This commit is contained in:
parent
ffcc7f659e
commit
18c60323a9
12
.gitmodules
vendored
12
.gitmodules
vendored
@ -1,15 +1,3 @@
|
||||
[submodule "lib/sead"]
|
||||
path = lib/sead
|
||||
url = https://github.com/open-ead/sead
|
||||
[submodule "lib/NintendoSDK"]
|
||||
path = lib/NintendoSDK
|
||||
url = https://github.com/open-ead/nnheaders
|
||||
[submodule "lib/agl"]
|
||||
path = lib/agl
|
||||
url = https://github.com/open-ead/agl
|
||||
[submodule "lib/EventFlow"]
|
||||
path = lib/EventFlow
|
||||
url = https://github.com/open-ead/EventFlow
|
||||
[submodule "tools/common"]
|
||||
path = tools/common
|
||||
url = https://github.com/open-ead/nx-decomp-tools
|
||||
|
@ -220,6 +220,41 @@ This project sometimes uses small hacks to force particular code to be generated
|
||||
|
||||
* `MATCHING_HACK_NX_CLANG`: Hacks for Switch, when compiling with Clang.
|
||||
|
||||
## Modifying library code
|
||||
|
||||
Changes to the following libraries must be PR'd/submitted to their own repository:
|
||||
|
||||
* sead: https://github.com/open-ead/sead
|
||||
* NintendoSDK: https://github.com/open-ead/nnheaders
|
||||
* agl: https://github.com/open-ead/agl
|
||||
* EventFlow: https://github.com/open-ead/EventFlow
|
||||
|
||||
The recommended workflow is to commit your changes as usual in the BotW repo, and then do a "subrepo push" to
|
||||
your fork of the library repo once you are ready to open a pull request.
|
||||
|
||||
Example:
|
||||
|
||||
```
|
||||
echo test > lib/sead/test_file
|
||||
git add -A
|
||||
git commit -m "test"
|
||||
git subrepo push lib/sead -r <your fork> -b <new branch name in your fork>
|
||||
```
|
||||
|
||||
You can then open one PR in the BotW repo and another one in the library repo.
|
||||
|
||||
Once the library repo PR has been merged, a maintainer will let you know what you should do
|
||||
to update the library subrepo in the BotW repo.
|
||||
|
||||
Follow the [instructions here](https://github.com/ingydotnet/git-subrepo#installation) to install the git-subrepo command
|
||||
if you do not already have it.
|
||||
|
||||
### Updating the library repos
|
||||
|
||||
Library subrepos can be updated with e.g. `git subrepo pull lib/sead`. This will pull the latest changes from the
|
||||
library repository and git-subrepo will automatically create a commit in the BotW repo to reflect the changes.
|
||||
Do not attempt to amend the commit message -- doing so could break the subrepo.
|
||||
|
||||
## Project tools
|
||||
|
||||
* Check all decompiled functions for issues: `tools/check`
|
||||
|
@ -1 +0,0 @@
|
||||
Subproject commit c35d21b34397bec6dd3c67a649fc66b68839341e
|
75
lib/EventFlow/.clang-format
Normal file
75
lib/EventFlow/.clang-format
Normal file
@ -0,0 +1,75 @@
|
||||
---
|
||||
Language: Cpp
|
||||
AccessModifierOffset: -4
|
||||
AlignAfterOpenBracket: Align
|
||||
AlignConsecutiveAssignments: false
|
||||
AlignConsecutiveDeclarations: false
|
||||
AlignOperands: true
|
||||
AlignTrailingComments: true
|
||||
AllowAllParametersOfDeclarationOnNextLine: true
|
||||
AllowShortBlocksOnASingleLine: Never
|
||||
AllowShortCaseLabelsOnASingleLine: false
|
||||
AllowShortFunctionsOnASingleLine: Inline
|
||||
AllowShortIfStatementsOnASingleLine: Never
|
||||
AllowShortLoopsOnASingleLine: false
|
||||
AlwaysBreakAfterDefinitionReturnType: None
|
||||
AlwaysBreakAfterReturnType: None
|
||||
AlwaysBreakBeforeMultilineStrings: false
|
||||
AlwaysBreakTemplateDeclarations: Yes
|
||||
BinPackArguments: true
|
||||
BinPackParameters: true
|
||||
BreakBeforeBinaryOperators: None
|
||||
BreakBeforeBraces: Attach
|
||||
BreakBeforeTernaryOperators: false
|
||||
BreakConstructorInitializersBeforeComma: false
|
||||
ColumnLimit: 100
|
||||
CommentPragmas: '^ (IWYU pragma:|NOLINT)'
|
||||
ConstructorInitializerAllOnOneLineOrOnePerLine: false
|
||||
ConstructorInitializerIndentWidth: 4
|
||||
ContinuationIndentWidth: 4
|
||||
Cpp11BracedListStyle: true
|
||||
DerivePointerAlignment: false
|
||||
DisableFormat: false
|
||||
ForEachMacros: []
|
||||
IncludeCategories:
|
||||
- Regex: '^<[Ww]indows\.h>$'
|
||||
Priority: 1
|
||||
- Regex: '^<'
|
||||
Priority: 2
|
||||
- Regex: '^"'
|
||||
Priority: 3
|
||||
IndentCaseLabels: false
|
||||
IndentWidth: 4
|
||||
IndentWrappedFunctionNames: false
|
||||
KeepEmptyLinesAtTheStartOfBlocks: false
|
||||
MacroBlockBegin: ''
|
||||
MacroBlockEnd: ''
|
||||
MaxEmptyLinesToKeep: 1
|
||||
NamespaceIndentation: None
|
||||
ObjCBlockIndentWidth: 4
|
||||
ObjCSpaceAfterProperty: false
|
||||
ObjCSpaceBeforeProtocolList: true
|
||||
PenaltyBreakBeforeFirstCallParameter: 19
|
||||
PenaltyBreakComment: 300
|
||||
PenaltyBreakFirstLessLess: 120
|
||||
PenaltyBreakString: 1000
|
||||
PenaltyExcessCharacter: 1000000
|
||||
PenaltyReturnTypeOnItsOwnLine: 60
|
||||
PointerAlignment: Left
|
||||
ReflowComments: true
|
||||
SortIncludes: true
|
||||
SpaceAfterCStyleCast: false
|
||||
SpaceBeforeAssignmentOperators: true
|
||||
SpaceBeforeParens: ControlStatements
|
||||
SpaceInEmptyParentheses: false
|
||||
SpacesBeforeTrailingComments: 2
|
||||
SpacesInAngles: false
|
||||
SpacesInContainerLiterals: true
|
||||
SpacesInCStyleCastParentheses: false
|
||||
SpacesInParentheses: false
|
||||
SpacesInSquareBrackets: false
|
||||
Standard: c++17
|
||||
TabWidth: 4
|
||||
UseTab: Never
|
||||
WhitespaceSensitiveMacros: ["ORE_ENUM"]
|
||||
...
|
31
lib/EventFlow/.gitignore
vendored
Normal file
31
lib/EventFlow/.gitignore
vendored
Normal file
@ -0,0 +1,31 @@
|
||||
__pycache__/
|
||||
*.pyc
|
||||
*.egg-info/
|
||||
*.dist-info/
|
||||
*.so
|
||||
*.dll
|
||||
dist/
|
||||
build/
|
||||
bin/
|
||||
.mypy_cache/
|
||||
.benchmarks/
|
||||
|
||||
.idea/
|
||||
.vscode/
|
||||
|
||||
*.id0
|
||||
*.id1
|
||||
*.id2
|
||||
*.idb
|
||||
*.i64
|
||||
*.nam
|
||||
*.til
|
||||
|
||||
main.elf
|
||||
|
||||
perf.mData
|
||||
perf.mData.old
|
||||
.gdb_history
|
||||
|
||||
.DS_Store
|
||||
tools/aarch64-none-elf-objdump
|
12
lib/EventFlow/.gitrepo
Normal file
12
lib/EventFlow/.gitrepo
Normal file
@ -0,0 +1,12 @@
|
||||
; DO NOT EDIT (unless you know what you are doing)
|
||||
;
|
||||
; This subdirectory is a git "subrepo", and this file is maintained by the
|
||||
; git-subrepo command. See https://github.com/git-commands/git-subrepo#readme
|
||||
;
|
||||
[subrepo]
|
||||
remote = https://github.com/open-ead/EventFlow
|
||||
branch = master
|
||||
commit = c35d21b34397bec6dd3c67a649fc66b68839341e
|
||||
parent = ffcc7f659ebc9bc9d149e52bec553b906bb47369
|
||||
method = merge
|
||||
cmdver = 0.4.3
|
56
lib/EventFlow/CMakeLists.txt
Normal file
56
lib/EventFlow/CMakeLists.txt
Normal file
@ -0,0 +1,56 @@
|
||||
project(EventFlow CXX ASM)
|
||||
|
||||
option(EVFL_VER_LABO "Build Labo's version of this library" OFF)
|
||||
|
||||
add_library(evfl OBJECT
|
||||
include/evfl/Action.h
|
||||
include/evfl/EvflAllocator.h
|
||||
include/evfl/Flowchart.h
|
||||
include/evfl/Param.h
|
||||
include/evfl/Query.h
|
||||
include/evfl/ResActor.h
|
||||
include/evfl/ResEventFlowFile.h
|
||||
include/evfl/ResFlowchart.h
|
||||
include/evfl/ResTimeline.h
|
||||
include/evfl/TimelineObj.h
|
||||
include/ore/Allocator.h
|
||||
include/ore/Array.h
|
||||
include/ore/BinaryFile.h
|
||||
include/ore/BitUtils.h
|
||||
include/ore/Buffer.h
|
||||
include/ore/EnumUtil.h
|
||||
include/ore/IntrusiveList.h
|
||||
include/ore/IterRange.h
|
||||
include/ore/RelocationTable.h
|
||||
include/ore/ResDic.h
|
||||
include/ore/ResEndian.h
|
||||
include/ore/ResMetaData.h
|
||||
include/ore/StringPool.h
|
||||
include/ore/StringView.h
|
||||
include/ore/Types.h
|
||||
src/evfl/Action.cpp
|
||||
src/evfl/Param.cpp
|
||||
src/evfl/Flowchart.cpp
|
||||
src/evfl/FlowchartObj.cpp
|
||||
src/evfl/TimelineObj.cpp
|
||||
src/evfl/ResEventFlowFile.cpp
|
||||
src/evfl/ResTimeline.cpp
|
||||
src/evfl/ResActor.cpp
|
||||
src/evfl/ResFlowchart.cpp
|
||||
src/ore/BitUtils.cpp
|
||||
src/ore/EnumUtil.cpp
|
||||
src/ore/BinaryFile.cpp
|
||||
src/ore/RelocationTable.cpp
|
||||
src/ore/StringPool.cpp
|
||||
src/ore/ResDic.cpp
|
||||
src/ore/ResMetaData.cpp
|
||||
)
|
||||
|
||||
target_compile_options(evfl PRIVATE -fno-exceptions)
|
||||
target_compile_options(evfl PRIVATE -fno-strict-aliasing)
|
||||
target_compile_options(evfl PRIVATE -Wno-invalid-offsetof)
|
||||
target_include_directories(evfl PUBLIC include/)
|
||||
|
||||
if(EVFL_VER_LABO)
|
||||
target_compile_definitions(evfl PUBLIC EVFL_VER_LABO=1)
|
||||
endif()
|
125
lib/EventFlow/include/evfl/Action.h
Normal file
125
lib/EventFlow/include/evfl/Action.h
Normal file
@ -0,0 +1,125 @@
|
||||
#pragma once
|
||||
|
||||
#include <evfl/Param.h>
|
||||
#include <ore/EnumUtil.h>
|
||||
#include <ore/IntrusiveList.h>
|
||||
#include <utility>
|
||||
|
||||
namespace evfl {
|
||||
|
||||
class FlowchartContext;
|
||||
class FlowchartContextNode;
|
||||
class FlowchartObj;
|
||||
struct ResClip;
|
||||
struct ResEvent;
|
||||
struct ResOneshot;
|
||||
class TimelineObj;
|
||||
class VariablePack;
|
||||
|
||||
ORE_VALUED_ENUM(TriggerType, kFlowchart = 0, kClipEnter = 1, kClipLeave = 2, kOneshot = 3,
|
||||
kNormal = 0, kEnter = 1, kLeave = 2)
|
||||
|
||||
class ActionDoneHandler {
|
||||
public:
|
||||
ActionDoneHandler() = default;
|
||||
ActionDoneHandler(FlowchartObj* obj, FlowchartContext* context, int node_idx);
|
||||
explicit ActionDoneHandler(TimelineObj* obj) : m_is_flowchart(false) { m_timeline_obj = obj; }
|
||||
~ActionDoneHandler() { m_list_node.Erase(); }
|
||||
|
||||
ActionDoneHandler(const ActionDoneHandler&) = delete;
|
||||
auto operator=(const ActionDoneHandler&) = delete;
|
||||
|
||||
ActionDoneHandler(ActionDoneHandler&& other) noexcept { *this = std::move(other); }
|
||||
|
||||
ActionDoneHandler& operator=(ActionDoneHandler&& other) noexcept {
|
||||
m_context = other.m_context;
|
||||
m_node_idx = other.m_node_idx;
|
||||
m_obj = other.m_obj;
|
||||
m_node_counter = other.m_node_counter;
|
||||
m_handled = other.m_handled;
|
||||
m_is_flowchart = other.m_is_flowchart;
|
||||
m_list_node = std::move(other.m_list_node);
|
||||
|
||||
other.m_context = nullptr;
|
||||
other.m_node_idx = -1;
|
||||
other.m_node_counter = -1;
|
||||
other.m_obj = nullptr;
|
||||
other.m_handled = false;
|
||||
other.m_is_flowchart = true;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
FlowchartContextNode* GetContextNode();
|
||||
void InvokeFromFlowchartImpl();
|
||||
void InvokeFromTimelineImpl();
|
||||
bool IsWaitingJoin();
|
||||
bool CancelWaiting();
|
||||
|
||||
void Reset() {
|
||||
m_context = nullptr;
|
||||
m_obj = nullptr;
|
||||
m_node_idx = -1;
|
||||
m_node_counter = -1;
|
||||
m_handled = false;
|
||||
m_is_flowchart = true;
|
||||
}
|
||||
|
||||
static constexpr size_t GetListNodeOffset() { return offsetof(ActionDoneHandler, m_list_node); }
|
||||
|
||||
private:
|
||||
friend class FlowchartContext;
|
||||
|
||||
ore::IntrusiveListNode m_list_node;
|
||||
FlowchartContext* m_context = nullptr;
|
||||
int m_node_idx = -1;
|
||||
int m_node_counter = -1;
|
||||
union {
|
||||
FlowchartObj* m_obj = nullptr;
|
||||
TimelineObj* m_timeline_obj;
|
||||
};
|
||||
bool m_handled = false;
|
||||
bool m_is_flowchart = true;
|
||||
};
|
||||
|
||||
struct ActionArg {
|
||||
ActionArg(FlowchartContext* context, int node_idx, void* actor_user_data_,
|
||||
void* action_user_data_, VariablePack* variable_pack_, const ResEvent* event_)
|
||||
: param_accessor(context, node_idx), actor_user_data(actor_user_data_),
|
||||
action_user_data(action_user_data_), flowchart_ctx(context),
|
||||
variable_pack(variable_pack_), res(event_), timeline_time_delta(0.0),
|
||||
trigger_type(TriggerType::kFlowchart) {}
|
||||
|
||||
ActionArg(const ResClip* clip, void* actor_user_data_, void* action_user_data_,
|
||||
float timeline_time_delta_, TriggerType::Type type, const ore::ResMetaData* params)
|
||||
: param_accessor(params), actor_user_data(actor_user_data_),
|
||||
action_user_data(action_user_data_), res(clip), timeline_time_delta(timeline_time_delta_),
|
||||
trigger_type(type) {}
|
||||
|
||||
ActionArg(const ResOneshot* oneshot, void* actor_user_data_, void* action_user_data_,
|
||||
float timeline_time_delta_, const ore::ResMetaData* params)
|
||||
: param_accessor(params), actor_user_data(actor_user_data_),
|
||||
action_user_data(action_user_data_), res(oneshot),
|
||||
timeline_time_delta(timeline_time_delta_), trigger_type(TriggerType::kOneshot) {
|
||||
res.oneshot = oneshot;
|
||||
}
|
||||
|
||||
ParamAccessor param_accessor;
|
||||
void* actor_user_data = nullptr;
|
||||
void* action_user_data = nullptr;
|
||||
FlowchartContext* flowchart_ctx = nullptr;
|
||||
VariablePack* variable_pack = nullptr;
|
||||
union Res {
|
||||
explicit Res(const ResEvent* e) : event(e) {}
|
||||
explicit Res(const ResClip* c) : clip(c) {}
|
||||
explicit Res(const ResOneshot* o) : oneshot(o) {}
|
||||
|
||||
const ResEvent* event;
|
||||
const ResClip* clip;
|
||||
const ResOneshot* oneshot;
|
||||
} res;
|
||||
float timeline_time_delta{};
|
||||
TriggerType::Type trigger_type{};
|
||||
};
|
||||
|
||||
} // namespace evfl
|
31
lib/EventFlow/include/evfl/EvflAllocator.h
Normal file
31
lib/EventFlow/include/evfl/EvflAllocator.h
Normal file
@ -0,0 +1,31 @@
|
||||
#pragma once
|
||||
|
||||
#include <ore/Allocator.h>
|
||||
|
||||
namespace evfl {
|
||||
|
||||
struct AllocateArg {
|
||||
void* (*alloc)(size_t size, size_t alignment, void* userdata);
|
||||
void (*free)(void* ptr, void* userdata);
|
||||
void* alloc_userdata;
|
||||
void* free_userdata;
|
||||
};
|
||||
|
||||
class EvflAllocator : public ore::Allocator {
|
||||
public:
|
||||
EvflAllocator() = default;
|
||||
explicit EvflAllocator(AllocateArg arg) : m_arg(arg) {}
|
||||
|
||||
void* AllocImpl(size_t size, size_t alignment) override {
|
||||
return m_arg.alloc(size, alignment, m_arg.alloc_userdata);
|
||||
}
|
||||
|
||||
void FreeImpl(void* ptr) override { m_arg.free(ptr, m_arg.free_userdata); }
|
||||
|
||||
AllocateArg GetArg() const { return m_arg; }
|
||||
|
||||
private:
|
||||
AllocateArg m_arg;
|
||||
};
|
||||
|
||||
} // namespace evfl
|
208
lib/EventFlow/include/evfl/Flowchart.h
Normal file
208
lib/EventFlow/include/evfl/Flowchart.h
Normal file
@ -0,0 +1,208 @@
|
||||
#pragma once
|
||||
|
||||
#include <evfl/EvflAllocator.h>
|
||||
#include <evfl/ResActor.h>
|
||||
#include <ore/Array.h>
|
||||
#include <ore/Buffer.h>
|
||||
#include <ore/EnumUtil.h>
|
||||
#include <ore/IntrusiveList.h>
|
||||
#include <ore/IterRange.h>
|
||||
#include <ore/StringView.h>
|
||||
#include <ore/Types.h>
|
||||
|
||||
namespace ore {
|
||||
class Allocator;
|
||||
class BitArray;
|
||||
} // namespace ore
|
||||
|
||||
namespace evfl {
|
||||
|
||||
class MetaDataPack;
|
||||
struct ResEntryPoint;
|
||||
struct ResEvent;
|
||||
struct ResFlowchart;
|
||||
class VariablePack;
|
||||
|
||||
ORE_ENUM(SubFlowCallbackType, kEnter, kLeave)
|
||||
|
||||
class FlowchartObj {
|
||||
public:
|
||||
class Builder {
|
||||
public:
|
||||
Builder(const ResFlowchart* flowchart, ore::BitArray* visited_entry_points)
|
||||
: m_flowchart(flowchart), m_entry_points_mask(visited_entry_points) {}
|
||||
|
||||
bool Build(FlowchartObj* obj, ore::Allocator* allocator,
|
||||
ore::IterRange<const ResFlowchart* const*> flowcharts);
|
||||
|
||||
private:
|
||||
const ResFlowchart* m_flowchart{};
|
||||
ore::BitArray* m_entry_points_mask{};
|
||||
ActBinder::Builder m_act_binder_builder{};
|
||||
};
|
||||
|
||||
#ifdef MATCHING_HACK_NX_CLANG
|
||||
[[gnu::always_inline]]
|
||||
#endif
|
||||
~FlowchartObj() = default;
|
||||
|
||||
const ResFlowchart* GetFlowchart() const { return m_flowchart; }
|
||||
const ActBinder& GetActBinder() const { return m_act_binder; }
|
||||
ActBinder& GetActBinder() { return m_act_binder; }
|
||||
|
||||
private:
|
||||
const ResFlowchart* m_flowchart{};
|
||||
ActBinder m_act_binder;
|
||||
};
|
||||
|
||||
class FlowchartContextNode {
|
||||
public:
|
||||
ORE_ENUM(State, kInvalid, kFree, kNotInvoked, kInvoked, kDone, kWaiting)
|
||||
|
||||
FlowchartContextNode() { Reset(); }
|
||||
|
||||
bool IsInvalidOrFree() const { return m_state == State::kInvalid || m_state == State::kFree; }
|
||||
FlowchartObj* GetObj() const { return m_obj; }
|
||||
VariablePack* GetVariablePack() const { return m_variable_pack; }
|
||||
int GetNodeCounter() const { return m_node_counter; }
|
||||
u16 GetEventIdx() const { return m_event_idx; }
|
||||
u16 GetNextNodeIdx() const { return m_next_node_idx; }
|
||||
State::Type GetState() const { return m_state; }
|
||||
|
||||
void Reset() {
|
||||
m_node_counter = -1;
|
||||
m_obj = nullptr;
|
||||
m_event_idx = -1;
|
||||
m_next_node_idx = -1;
|
||||
m_idx = -1;
|
||||
m_state = State::kInvalid;
|
||||
m_variable_pack = nullptr;
|
||||
m_owns_variable_pack = false;
|
||||
}
|
||||
|
||||
private:
|
||||
friend class ActionDoneHandler;
|
||||
friend class FlowchartContext;
|
||||
|
||||
FlowchartObj* m_obj;
|
||||
VariablePack* m_variable_pack;
|
||||
int m_node_counter;
|
||||
u16 m_event_idx;
|
||||
u16 m_next_node_idx;
|
||||
u16 m_idx;
|
||||
ore::SizedEnum<State::Type, u8> m_state;
|
||||
bool m_owns_variable_pack;
|
||||
};
|
||||
|
||||
class FlowchartContext {
|
||||
public:
|
||||
class Builder {
|
||||
public:
|
||||
using FlowchartRange = ore::IterRange<const ResFlowchart* const*>;
|
||||
ORE_ENUM(BuildResultType, kSuccess, kInvalidOperation, kResFlowchartNotFound, kEntryPointNotFound)
|
||||
|
||||
struct BuildResult {
|
||||
BuildResultType::Type result;
|
||||
/// Indicates which flowchart was required yet couldn't be found.
|
||||
ore::StringView missing_flowchart_name{};
|
||||
/// Indicates which entry point was required yet couldn't be found.
|
||||
ore::StringView missing_entry_point_name{};
|
||||
};
|
||||
|
||||
Builder() = default;
|
||||
explicit Builder(FlowchartRange flowcharts, int flowchart_idx = 0)
|
||||
: m_flowcharts(flowcharts), m_flowchart_idx(flowchart_idx) {}
|
||||
|
||||
bool SetEntryPoint(const ore::StringView& flowchart_name,
|
||||
const ore::StringView& entry_point_name);
|
||||
bool SetEntryPoint(BuildResult* result, const ore::StringView& flowchart_name,
|
||||
const ore::StringView& entry_point_name);
|
||||
|
||||
bool Build(FlowchartContext* context, AllocateArg allocate_arg);
|
||||
bool Build(BuildResult* result, FlowchartContext* context, AllocateArg allocate_arg);
|
||||
|
||||
private:
|
||||
bool BuildImpl(BuildResult* result, FlowchartRange flowcharts, FlowchartContext* context,
|
||||
AllocateArg allocate_arg, ore::Buffer flowchart_obj_buffer);
|
||||
|
||||
FlowchartRange m_flowcharts{};
|
||||
int m_flowchart_idx = 0;
|
||||
int m_entry_point_idx = -1;
|
||||
};
|
||||
|
||||
FlowchartContext();
|
||||
~FlowchartContext() {
|
||||
Dispose();
|
||||
m_objs.DestructElements();
|
||||
}
|
||||
|
||||
FlowchartContext(const FlowchartContext&) = delete;
|
||||
auto operator=(const FlowchartContext&) = delete;
|
||||
|
||||
void Start(MetaDataPack* pack);
|
||||
int AllocNode();
|
||||
void AllocVariablePack(FlowchartContextNode& node, const ResEntryPoint& entry_point);
|
||||
void ProcessContext();
|
||||
FlowchartObj* FindFlowchartObj(ore::StringView name);
|
||||
const FlowchartObj* FindFlowchartObj(ore::StringView name) const;
|
||||
void UnbindAll();
|
||||
void Clear();
|
||||
void FreeVariablePack(FlowchartContextNode& node);
|
||||
void CopyVariablePack(FlowchartContextNode& src, FlowchartContextNode& dst);
|
||||
bool ProcessContextNode(int node_idx);
|
||||
ActorBinding* TrackBackArgumentActor(int node_idx, const ore::StringView& name);
|
||||
bool IsUsing(const ResFlowchart* flowchart) const;
|
||||
bool IsPlaying(const ResFlowchart* flowchart) const;
|
||||
const ore::Array<ActorBinding>* GetUsedResActors(ore::StringView flowchart_name) const;
|
||||
|
||||
FlowchartContextNode& GetNode(int idx) { return m_nodes[idx]; }
|
||||
const FlowchartContextNode& GetNode(int idx) const { return m_nodes[idx]; }
|
||||
MetaDataPack* GetMetaDataPack() const { return m_metadata_pack; }
|
||||
ore::Array<FlowchartObj>& GetObjs() { return m_objs; }
|
||||
const ore::Array<FlowchartObj>& GetObjs() const { return m_objs; }
|
||||
|
||||
private:
|
||||
void Dispose() {
|
||||
m_obj_idx = -1;
|
||||
m_active_entry_point_idx = -1;
|
||||
m_metadata_pack = nullptr;
|
||||
m_objs.Clear(&m_allocator);
|
||||
for (auto& node : m_nodes)
|
||||
FreeVariablePack(node);
|
||||
m_nodes.Reset();
|
||||
}
|
||||
|
||||
void UpdateNodeCounter(int node_idx) {
|
||||
auto& node = GetNode(node_idx);
|
||||
node.m_node_counter = ++s_GlobalCounter;
|
||||
}
|
||||
|
||||
void CallSubFlowCallback(const ResFlowchart* flowchart, const ResEvent* event,
|
||||
SubFlowCallbackType::Type type) {
|
||||
#ifdef EVFL_VER_LABO
|
||||
if (m_on_sub_flow_callback)
|
||||
m_on_sub_flow_callback(this, flowchart, event, type);
|
||||
#endif
|
||||
}
|
||||
|
||||
static int s_GlobalCounter;
|
||||
|
||||
EvflAllocator m_allocator;
|
||||
ore::Array<FlowchartObj> m_objs;
|
||||
ore::DynArrayList<FlowchartContextNode> m_nodes;
|
||||
ore::IntrusiveList<ActionDoneHandler> m_handlers;
|
||||
#ifdef EVFL_VER_LABO
|
||||
void (*m_on_sub_flow_callback)(FlowchartContext* context, const ResFlowchart* flowchart,
|
||||
const ResEvent* event, SubFlowCallbackType::Type type) = nullptr;
|
||||
#endif
|
||||
MetaDataPack* m_metadata_pack = nullptr;
|
||||
void* _78 = nullptr;
|
||||
int m_next_node_idx = 0;
|
||||
int m_num_allocated_nodes = 0;
|
||||
int m_obj_idx = -1;
|
||||
int m_active_entry_point_idx = -1;
|
||||
bool m_is_processing = false;
|
||||
u8 _91 = 0;
|
||||
};
|
||||
|
||||
} // namespace evfl
|
208
lib/EventFlow/include/evfl/Param.h
Normal file
208
lib/EventFlow/include/evfl/Param.h
Normal file
@ -0,0 +1,208 @@
|
||||
#pragma once
|
||||
|
||||
#include <evfl/EvflAllocator.h>
|
||||
#include <ore/Array.h>
|
||||
#include <ore/BinaryFile.h>
|
||||
#include <ore/Buffer.h>
|
||||
#include <ore/EnumUtil.h>
|
||||
#include <ore/IterRange.h>
|
||||
#include <ore/ResMetaData.h>
|
||||
#include <ore/StringView.h>
|
||||
#include <ore/Types.h>
|
||||
|
||||
namespace ore {
|
||||
struct ResDic;
|
||||
struct ResMetaData;
|
||||
} // namespace ore
|
||||
|
||||
namespace evfl {
|
||||
|
||||
class FlowchartContext;
|
||||
class FlowchartObj;
|
||||
struct ResEntryPoint;
|
||||
|
||||
class MetaDataPack {
|
||||
public:
|
||||
ORE_ENUM(DataType, kInt, kBool, kFloat, kString, kWString)
|
||||
|
||||
struct Entry {
|
||||
union Value {
|
||||
bool b;
|
||||
int i;
|
||||
float f;
|
||||
const char* str;
|
||||
const wchar_t* wstr;
|
||||
};
|
||||
|
||||
bool IsKey(const ore::StringView& other) const { return ore::StringView(key) == other; }
|
||||
|
||||
const char* key;
|
||||
Value value;
|
||||
DataType::Type type;
|
||||
};
|
||||
|
||||
class Builder {
|
||||
public:
|
||||
void CalcMemSize();
|
||||
bool Build(MetaDataPack* pack, ore::Buffer buffer);
|
||||
void SetNumEntries(int num) { m_num_entries = num; }
|
||||
int GetRequiredSize() const { return m_required_size; }
|
||||
|
||||
private:
|
||||
int m_num_entries = 16;
|
||||
int m_required_size = 0;
|
||||
int m_alignment_real = 16;
|
||||
int m_entries_byte_size = 0;
|
||||
int m_alignment = 16;
|
||||
int _14 = 0;
|
||||
int m_buffer_offset = -1;
|
||||
};
|
||||
|
||||
void AddInt(const char* key, int value);
|
||||
void AddBool(const char* key, bool value);
|
||||
void AddFloat(const char* key, float value);
|
||||
void AddStringPtr(const char* key, const char* value);
|
||||
void AddWStringPtr(const char* key, const wchar_t* value);
|
||||
|
||||
bool FindInt(int* value, const ore::StringView& key) const;
|
||||
bool FindBool(bool* value, const ore::StringView& key) const;
|
||||
bool FindFloat(float* value, const ore::StringView& key) const;
|
||||
bool FindString(ore::StringView* value, const ore::StringView& key) const;
|
||||
bool FindWString(ore::WStringView* value, const ore::StringView& key) const;
|
||||
|
||||
ore::ResMetaData::DataType::Type GetType(const ore::StringView& key) const;
|
||||
|
||||
private:
|
||||
Entry* Find(const ore::StringView& key) const;
|
||||
Entry& AddEntry() { return m_entries[m_entries_num++]; }
|
||||
|
||||
ore::Array<Entry> GetEntries() const { return {m_entries, m_entries_num}; }
|
||||
|
||||
ore::Buffer m_buffer{};
|
||||
Entry* m_entries{};
|
||||
int m_entries_num{};
|
||||
int m_entries_capacity{};
|
||||
};
|
||||
|
||||
class VariablePack {
|
||||
public:
|
||||
using VariableType = ore::ResMetaData::DataType::Type;
|
||||
|
||||
struct Entry {
|
||||
union Value {
|
||||
void* dummy;
|
||||
int i;
|
||||
float f;
|
||||
ore::DynArrayList<int>* int_array;
|
||||
ore::DynArrayList<float>* float_array;
|
||||
};
|
||||
|
||||
Value value;
|
||||
VariableType type;
|
||||
};
|
||||
|
||||
VariablePack();
|
||||
~VariablePack();
|
||||
VariablePack(const VariablePack&) = delete;
|
||||
auto operator=(const VariablePack&) = delete;
|
||||
|
||||
void Init(AllocateArg arg, const ResEntryPoint* entry_point);
|
||||
|
||||
Entry* GetVariableEntry(const ore::StringView& name);
|
||||
const Entry* GetVariableEntry(const ore::StringView& name) const;
|
||||
VariableType GetVariableType(const ore::StringView& name) const;
|
||||
ore::StringView GetVariableName(int idx) const;
|
||||
int GetVariableCount() const;
|
||||
|
||||
bool Contains(const ore::StringView& name) const;
|
||||
|
||||
bool FindInt(int* value, const ore::StringView& name) const;
|
||||
bool FindBool(bool* value, const ore::StringView& name) const;
|
||||
bool FindFloat(float* value, const ore::StringView& name) const;
|
||||
bool FindIntList(ore::DynArrayList<int>** value, const ore::StringView& name) const;
|
||||
bool FindFloatList(ore::DynArrayList<float>** value, const ore::StringView& name) const;
|
||||
|
||||
int GetInt(const ore::StringView& name) const;
|
||||
bool GetBool(const ore::StringView& name) const;
|
||||
float GetFloat(const ore::StringView& name) const;
|
||||
ore::DynArrayList<int>* GetIntList(const ore::StringView& name) const;
|
||||
ore::DynArrayList<float>* GetFloatList(const ore::StringView& name) const;
|
||||
|
||||
void SetInt(const ore::StringView& name, int value);
|
||||
void SetFloat(const ore::StringView& name, float value);
|
||||
void SetBool(const ore::StringView& name, bool value);
|
||||
|
||||
private:
|
||||
void Dispose();
|
||||
ore::Allocator* GetAllocator() { return &m_allocator; }
|
||||
|
||||
const ore::ResDic* m_names = nullptr;
|
||||
ore::Array<Entry> m_variables;
|
||||
EvflAllocator m_allocator;
|
||||
};
|
||||
|
||||
class ParamAccessor {
|
||||
public:
|
||||
using Type = ore::ResMetaData::DataType::Type;
|
||||
using IntRange = ore::IterRange<const int*>;
|
||||
using FloatRange = ore::IterRange<const float*>;
|
||||
using StringRange = ore::IterRange<const ore::BinTPtr<ore::BinString>*>;
|
||||
using WStringRange = ore::IterRange<const ore::BinTPtr<ore::BinWString>*>;
|
||||
|
||||
explicit ParamAccessor(const ore::ResMetaData* metadata);
|
||||
explicit ParamAccessor(const FlowchartContext* context, int node_idx);
|
||||
|
||||
const ore::ResMetaData* GetFrontResMetaData() const;
|
||||
int GetParamCount() const;
|
||||
ore::StringView GetParamName(int idx) const;
|
||||
Type GetParamType(int idx) const;
|
||||
|
||||
/// @param out_metadata Must be nonnull.
|
||||
/// @param out_metadata_pack Must be nonnull.
|
||||
/// @param out_variable_pack Must be nonnull.
|
||||
/// @param out_obj May be null.
|
||||
/// @param argument Name of the argument to search for.
|
||||
ore::StringView TrackBackArgument(const ore::ResMetaData** out_metadata,
|
||||
const MetaDataPack** out_metadata_pack,
|
||||
const VariablePack** out_variable_pack,
|
||||
FlowchartObj** out_obj,
|
||||
const ore::StringView& argument) const;
|
||||
|
||||
int GetInt(int idx) const;
|
||||
bool FindInt(int* value, const ore::StringView& name) const;
|
||||
|
||||
bool GetBool(int idx) const;
|
||||
bool FindBool(bool* value, const ore::StringView& name) const;
|
||||
|
||||
float GetFloat(int idx) const;
|
||||
bool FindFloat(float* value, const ore::StringView& name) const;
|
||||
|
||||
ore::StringView GetString(int idx) const;
|
||||
bool FindString(ore::StringView* value, const ore::StringView& name) const;
|
||||
|
||||
ore::WStringView GetWString(int idx) const;
|
||||
bool FindWString(ore::WStringView* value, const ore::StringView& name) const;
|
||||
|
||||
IntRange GetIntArray(int idx) const;
|
||||
bool FindIntArray(IntRange* value, const ore::StringView& name) const;
|
||||
|
||||
FloatRange GetFloatArray(int idx) const;
|
||||
bool FindFloatArray(FloatRange* value, const ore::StringView& name) const;
|
||||
|
||||
StringRange GetStringArray(int idx) const;
|
||||
bool FindStringArray(StringRange* value, const ore::StringView& name) const;
|
||||
|
||||
WStringRange GetWStringArray(int idx) const;
|
||||
bool FindWStringArray(WStringRange* value, const ore::StringView& name) const;
|
||||
|
||||
bool FindActorIdentifier(ore::StringView* actor_name, ore::StringView* actor_sub_name,
|
||||
const ore::StringView& name) const;
|
||||
|
||||
private:
|
||||
const ore::ResMetaData* m_metadata = nullptr;
|
||||
const FlowchartContext* m_context = nullptr;
|
||||
int m_node_idx = -1;
|
||||
u32 m_node_counter = -1;
|
||||
};
|
||||
|
||||
} // namespace evfl
|
29
lib/EventFlow/include/evfl/Query.h
Normal file
29
lib/EventFlow/include/evfl/Query.h
Normal file
@ -0,0 +1,29 @@
|
||||
#pragma once
|
||||
|
||||
#include <evfl/Param.h>
|
||||
#include <ore/EnumUtil.h>
|
||||
|
||||
namespace evfl {
|
||||
|
||||
class FlowchartContext;
|
||||
struct ResEvent;
|
||||
class VariablePack;
|
||||
|
||||
ORE_ENUM(QueryValueType, kBool, kInt, kFloat, kString, kConst)
|
||||
|
||||
struct QueryArg {
|
||||
QueryArg(FlowchartContext* context, int node_idx, void* actor_user_data_,
|
||||
void* query_user_data_, const ResEvent* event_, VariablePack* variable_pack_)
|
||||
: actor_user_data(actor_user_data_), query_user_data(query_user_data_), main_event(event_),
|
||||
flowchart_ctx(context), variable_pack(variable_pack_), param_accessor(context, node_idx) {
|
||||
}
|
||||
|
||||
void* actor_user_data;
|
||||
void* query_user_data;
|
||||
const ResEvent* main_event;
|
||||
FlowchartContext* flowchart_ctx;
|
||||
VariablePack* variable_pack;
|
||||
ParamAccessor param_accessor;
|
||||
};
|
||||
|
||||
} // namespace evfl
|
187
lib/EventFlow/include/evfl/ResActor.h
Normal file
187
lib/EventFlow/include/evfl/ResActor.h
Normal file
@ -0,0 +1,187 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstddef>
|
||||
#include <ore/Array.h>
|
||||
#include <ore/BinaryFile.h>
|
||||
#include <ore/IterRange.h>
|
||||
#include <utility>
|
||||
|
||||
namespace ore {
|
||||
struct ResEndian;
|
||||
struct ResMetaData;
|
||||
} // namespace ore
|
||||
|
||||
namespace evfl {
|
||||
|
||||
struct ActionArg;
|
||||
class ActionDoneHandler;
|
||||
class FlowchartContext;
|
||||
class FlowchartContextNode;
|
||||
class FlowchartObj;
|
||||
struct QueryArg;
|
||||
|
||||
struct ResAction {
|
||||
ore::BinTPtr<ore::BinString> name;
|
||||
};
|
||||
|
||||
struct ResQuery {
|
||||
ore::BinTPtr<ore::BinString> name;
|
||||
};
|
||||
|
||||
struct ResActor {
|
||||
bool HasArgumentName() const { return !argument_name.Get()->empty(); }
|
||||
|
||||
ore::BinTPtr<ore::BinString> name;
|
||||
ore::BinTPtr<ore::BinString> secondary_name;
|
||||
ore::BinTPtr<ore::BinString> argument_name;
|
||||
ore::BinTPtr<ResAction> actions;
|
||||
ore::BinTPtr<ResQuery> queries;
|
||||
ore::BinTPtr<ore::ResMetaData> params;
|
||||
u16 num_actions;
|
||||
u16 num_queries;
|
||||
/// Entry point index for assicated entry point (0xffff if none)
|
||||
u16 entry_point_idx;
|
||||
// TODO: Cut number? This is set to 1 for flowcharts but other values have been seen
|
||||
// for timeline actors.
|
||||
u8 cut_number;
|
||||
};
|
||||
|
||||
using ActionHandler = void (*)(const ActionArg& arg, ActionDoneHandler done_handler);
|
||||
using QueryHandler = int (*)(const QueryArg& arg);
|
||||
|
||||
class ActorBinding {
|
||||
public:
|
||||
struct Action {
|
||||
ActionHandler handler{};
|
||||
void* user_data{};
|
||||
const ResAction* res_action{};
|
||||
};
|
||||
|
||||
struct Query {
|
||||
QueryHandler handler{};
|
||||
void* user_data{};
|
||||
const ResQuery* res_query{};
|
||||
};
|
||||
|
||||
ActorBinding() = default;
|
||||
|
||||
void Register(const ResAction* action);
|
||||
void Register(const ResQuery* query);
|
||||
|
||||
// Similar to std::find_if. Returns m_actions.end() if the specified action is not found.
|
||||
Action* GetAction(const ore::StringView& name);
|
||||
const Action* GetAction(const ore::StringView& name) const;
|
||||
Query* GetQuery(const ore::StringView& name);
|
||||
const Query* GetQuery(const ore::StringView& name) const;
|
||||
|
||||
ore::DynArrayList<Action>& GetActions() { return m_actions; }
|
||||
ore::DynArrayList<Query>& GetQueries() { return m_queries; }
|
||||
const ore::DynArrayList<Action>& GetActions() const { return m_actions; }
|
||||
const ore::DynArrayList<Query>& GetQueries() const { return m_queries; }
|
||||
auto ActionsEnd() const { return m_actions.end(); }
|
||||
auto QueriesEnd() const { return m_queries.end(); }
|
||||
|
||||
auto GetActor() const { return m_actor; }
|
||||
|
||||
void* GetUserData() const { return m_user_data; }
|
||||
void SetUserData(void* user_data) { m_user_data = user_data; }
|
||||
|
||||
bool IsInitialized() const { return m_initialized; }
|
||||
bool IsUsed() const { return m_is_used; }
|
||||
void SetInitialized(bool initialized) { m_initialized = initialized; }
|
||||
void SetIsUsed(bool used) { m_is_used = used; }
|
||||
|
||||
void UnbindAll() {
|
||||
m_user_data = nullptr;
|
||||
m_initialized = false;
|
||||
for (auto it = m_actions.begin(); it != m_actions.end(); ++it) {
|
||||
it->handler = nullptr;
|
||||
it->user_data = nullptr;
|
||||
}
|
||||
for (auto it = m_queries.begin(); it != m_queries.end(); ++it) {
|
||||
it->handler = nullptr;
|
||||
it->user_data = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
friend class ActBinder;
|
||||
|
||||
ore::DynArrayList<Action> m_actions{};
|
||||
ore::DynArrayList<Query> m_queries{};
|
||||
void* m_user_data{};
|
||||
const ResActor* m_actor{};
|
||||
bool m_initialized{};
|
||||
bool m_is_used{};
|
||||
};
|
||||
|
||||
class ActBinder {
|
||||
public:
|
||||
class Builder {
|
||||
public:
|
||||
bool Build(evfl::ActBinder* binder, ore::Allocator* allocator,
|
||||
ore::IterRange<const ResActor*> actors);
|
||||
};
|
||||
|
||||
ActBinder() = default;
|
||||
ActBinder(const ActBinder&) = delete;
|
||||
auto operator=(const ActBinder&) = delete;
|
||||
|
||||
#ifdef MATCHING_HACK_NX_CLANG
|
||||
[[gnu::always_inline]]
|
||||
#endif
|
||||
~ActBinder() {
|
||||
Reset();
|
||||
}
|
||||
|
||||
u32 GetEventUsedActorCount() const { return m_event_used_actor_count; }
|
||||
const ore::Array<ActorBinding>* GetUsedResActors() const;
|
||||
|
||||
ore::Array<ActorBinding>& GetBindings() { return m_bindings; }
|
||||
const ore::Array<ActorBinding>& GetBindings() const { return m_bindings; }
|
||||
void IncrementNumActors() { ++m_event_used_actor_count; }
|
||||
void SetIsUsed() { m_is_used = true; }
|
||||
bool IsUsed() const { return m_is_used; }
|
||||
|
||||
void RegisterAction(int actor_idx, const evfl::ResAction* action) {
|
||||
auto& binding = GetBindings()[actor_idx];
|
||||
if (!binding.IsUsed() && binding.GetActor()->argument_name.Get()->empty()) {
|
||||
IncrementNumActors();
|
||||
binding.SetIsUsed(true);
|
||||
}
|
||||
binding.Register(action);
|
||||
}
|
||||
|
||||
void RegisterQuery(int actor_idx, const evfl::ResQuery* query) {
|
||||
auto& binding = GetBindings()[actor_idx];
|
||||
if (!binding.IsUsed() && binding.GetActor()->argument_name.Get()->empty()) {
|
||||
IncrementNumActors();
|
||||
binding.SetIsUsed(true);
|
||||
}
|
||||
binding.Register(query);
|
||||
}
|
||||
|
||||
void UnbindAll() {
|
||||
for (auto it = m_bindings.begin(); it != m_bindings.end(); ++it)
|
||||
it->UnbindAll();
|
||||
}
|
||||
|
||||
void Reset() {
|
||||
m_event_used_actor_count = 0;
|
||||
if (auto* data = m_bindings.data()) {
|
||||
m_bindings.ClearWithoutFreeing();
|
||||
m_allocator->Free(data);
|
||||
}
|
||||
m_allocator = nullptr;
|
||||
}
|
||||
|
||||
private:
|
||||
u32 m_event_used_actor_count{};
|
||||
ore::Allocator* m_allocator{};
|
||||
ore::SelfDestructingArray<ActorBinding> m_bindings{};
|
||||
bool m_is_used{};
|
||||
};
|
||||
|
||||
void SwapEndian(ore::ResEndian* endian, ResActor* actor);
|
||||
|
||||
} // namespace evfl
|
36
lib/EventFlow/include/evfl/ResEventFlowFile.h
Normal file
36
lib/EventFlow/include/evfl/ResEventFlowFile.h
Normal file
@ -0,0 +1,36 @@
|
||||
#pragma once
|
||||
|
||||
#include <ore/BinaryFile.h>
|
||||
#include <ore/Types.h>
|
||||
|
||||
namespace ore {
|
||||
struct ResDic;
|
||||
struct ResEndian;
|
||||
} // namespace ore
|
||||
|
||||
namespace evfl {
|
||||
|
||||
struct ResFlowchart;
|
||||
struct ResTimeline;
|
||||
|
||||
struct ResEventFlowFile {
|
||||
/// data must be a pointer to a buffer of size >= 0x20.
|
||||
static bool IsValid(void* data);
|
||||
/// data must be a valid ResEventFlowFile.
|
||||
static ResEventFlowFile* ResCast(void* data);
|
||||
|
||||
void Relocate();
|
||||
void Unrelocate();
|
||||
|
||||
ore::BinaryFileHeader header;
|
||||
u16 num_flowcharts;
|
||||
u16 num_timelines;
|
||||
ore::BinTPtr<ore::BinTPtr<ResFlowchart>> flowcharts;
|
||||
ore::BinTPtr<ore::ResDic> flowchart_names;
|
||||
ore::BinTPtr<ore::BinTPtr<ResTimeline>> timelines;
|
||||
ore::BinTPtr<ore::ResDic> timeline_names;
|
||||
};
|
||||
|
||||
void SwapEndian(ore::ResEndian* endian, ResEventFlowFile* file);
|
||||
|
||||
} // namespace evfl
|
136
lib/EventFlow/include/evfl/ResFlowchart.h
Normal file
136
lib/EventFlow/include/evfl/ResFlowchart.h
Normal file
@ -0,0 +1,136 @@
|
||||
#pragma once
|
||||
|
||||
#include <ore/BinaryFile.h>
|
||||
#include <ore/EnumUtil.h>
|
||||
#include <ore/ResDic.h>
|
||||
#include <ore/ResMetaData.h>
|
||||
#include <ore/StringView.h>
|
||||
|
||||
namespace ore {
|
||||
struct ResEndian;
|
||||
}
|
||||
|
||||
namespace evfl {
|
||||
|
||||
struct ResActor;
|
||||
|
||||
struct ResCase {
|
||||
u32 value;
|
||||
u16 event_idx;
|
||||
};
|
||||
|
||||
struct ResEvent {
|
||||
ORE_ENUM(EventType, kAction, kSwitch, kFork, kJoin, kSubFlow)
|
||||
|
||||
ore::BinTPtr<ore::BinString> name;
|
||||
ore::SizedEnum<EventType::Type, u8> type;
|
||||
|
||||
union {
|
||||
// Action, Join, Sub flow
|
||||
u16 next_event_idx;
|
||||
// Switch
|
||||
u16 num_cases;
|
||||
// Fork
|
||||
u16 num_forks;
|
||||
};
|
||||
|
||||
union {
|
||||
// Action, Switch
|
||||
u16 actor_idx;
|
||||
// Fork
|
||||
u16 join_event_idx;
|
||||
};
|
||||
|
||||
union {
|
||||
// Action
|
||||
u16 actor_action_idx;
|
||||
// Switch
|
||||
u16 actor_query_idx;
|
||||
};
|
||||
|
||||
union {
|
||||
// Action, Switch, Sub flow
|
||||
ore::BinTPtr<ore::ResMetaData> params;
|
||||
// Fork
|
||||
ore::BinTPtr<u16> fork_event_indices;
|
||||
};
|
||||
|
||||
union {
|
||||
// Switch
|
||||
ore::BinTPtr<ResCase> cases;
|
||||
// Sub flow
|
||||
ore::BinTPtr<ore::BinString> sub_flow_flowchart;
|
||||
};
|
||||
|
||||
union {
|
||||
// Sub flow
|
||||
ore::BinTPtr<ore::BinString> sub_flow_entry_point;
|
||||
};
|
||||
};
|
||||
|
||||
struct ResVariableDef {
|
||||
union Value {
|
||||
// Also used for booleans. Anything that is != 0 is treated as true.
|
||||
int i;
|
||||
float f;
|
||||
ore::BinTPtr<int> int_array;
|
||||
ore::BinTPtr<float> float_array;
|
||||
};
|
||||
|
||||
Value value;
|
||||
u16 num;
|
||||
ore::SizedEnum<ore::ResMetaData::DataType::Type, u8> type;
|
||||
};
|
||||
|
||||
struct ResEntryPoint {
|
||||
ore::BinTPtr<u16> sub_flow_event_indices;
|
||||
ore::BinTPtr<ore::ResDic> variable_defs_names;
|
||||
ore::BinTPtr<ResVariableDef> variable_defs;
|
||||
u16 num_sub_flow_event_indices;
|
||||
u16 num_variable_defs;
|
||||
u16 main_event_idx;
|
||||
};
|
||||
|
||||
struct ResFlowchart {
|
||||
int CountEvent(ResEvent::EventType::Type type) const;
|
||||
|
||||
const ResEntryPoint* GetEntryPoint(const ore::StringView& entry_point_name) const {
|
||||
const int idx = entry_point_names.Get()->FindIndex(entry_point_name);
|
||||
if (idx == -1)
|
||||
return nullptr;
|
||||
|
||||
return entry_points.Get() + idx;
|
||||
}
|
||||
|
||||
ore::StringView GetEntryPointName(int idx) const {
|
||||
return entry_point_names.Get()->GetEntries()[1 + idx].GetKey();
|
||||
}
|
||||
|
||||
/// 'EVFL'
|
||||
u32 magic;
|
||||
/// String pool offset (relative to this structure)
|
||||
u32 string_pool_offset;
|
||||
u32 reserved_8;
|
||||
u32 reserved_c;
|
||||
u16 num_actors;
|
||||
u16 num_actions;
|
||||
u16 num_queries;
|
||||
u16 num_events;
|
||||
u16 num_entry_points;
|
||||
u16 reserved_1a;
|
||||
u16 reserved_1c;
|
||||
u16 reserved_1e;
|
||||
ore::BinTPtr<ore::BinString> name;
|
||||
ore::BinTPtr<ResActor> actors;
|
||||
ore::BinTPtr<ResEvent> events;
|
||||
ore::BinTPtr<ore::ResDic> entry_point_names;
|
||||
ore::BinTPtr<ResEntryPoint> entry_points;
|
||||
};
|
||||
|
||||
void SwapEndian(ore::ResEndian* endian, ResCase* case_);
|
||||
void SwapEndian(ore::ResEndian* endian, ResEvent* event);
|
||||
void SwapEndian(ore::ResEndian* endian, ResEntryPoint* entry);
|
||||
void SwapEndian(ore::ResEndian* endian, ResVariableDef* def);
|
||||
void SwapEndian(ore::ResEndian* endian, ResFlowchart* flowchart);
|
||||
|
||||
} // namespace evfl
|
80
lib/EventFlow/include/evfl/ResTimeline.h
Normal file
80
lib/EventFlow/include/evfl/ResTimeline.h
Normal file
@ -0,0 +1,80 @@
|
||||
#pragma once
|
||||
|
||||
#include <ore/BinaryFile.h>
|
||||
#include <ore/EnumUtil.h>
|
||||
#include <ore/Types.h>
|
||||
|
||||
namespace ore {
|
||||
struct ResEndian;
|
||||
struct ResMetaData;
|
||||
} // namespace ore
|
||||
|
||||
namespace evfl {
|
||||
|
||||
struct ResActor;
|
||||
|
||||
struct ResTrigger {
|
||||
u16 clip_index;
|
||||
u8 trigger_type;
|
||||
};
|
||||
|
||||
struct ResCut {
|
||||
float start_time;
|
||||
ore::BinTPtr<ore::BinString> name;
|
||||
ore::BinTPtr<ore::ResMetaData> params;
|
||||
};
|
||||
|
||||
struct ResClip {
|
||||
float start_time;
|
||||
float duration;
|
||||
u16 actor_index;
|
||||
u16 actor_action_index;
|
||||
u8 _c;
|
||||
ore::BinTPtr<ore::ResMetaData> params;
|
||||
};
|
||||
|
||||
struct ResOneshot {
|
||||
float time;
|
||||
u16 actor_index;
|
||||
u16 actor_action_index;
|
||||
u32 _8;
|
||||
u32 _c;
|
||||
ore::BinTPtr<ore::ResMetaData> params;
|
||||
};
|
||||
|
||||
struct ResSubtimeline {
|
||||
ore::BinTPtr<ore::BinString> name;
|
||||
};
|
||||
|
||||
struct ResTimeline {
|
||||
/// 'TLIN'
|
||||
u32 magic;
|
||||
/// String pool offset (relative to this structure)
|
||||
int string_pool_offset;
|
||||
u32 reserved_8;
|
||||
u32 reserved_c;
|
||||
float duration;
|
||||
u16 num_actors;
|
||||
u16 num_actions;
|
||||
u16 num_clips;
|
||||
u16 num_oneshots;
|
||||
u16 num_subtimelines;
|
||||
u16 num_cuts;
|
||||
ore::BinTPtr<ore::BinString> name;
|
||||
ore::BinTPtr<ResActor> actors;
|
||||
ore::BinTPtr<ResClip> clips;
|
||||
ore::BinTPtr<ResOneshot> oneshots;
|
||||
ore::BinTPtr<ResTrigger> triggers;
|
||||
ore::BinTPtr<ResSubtimeline> subtimelines;
|
||||
ore::BinTPtr<ResCut> cuts;
|
||||
ore::BinTPtr<ore::ResMetaData> params;
|
||||
};
|
||||
|
||||
void SwapEndian(ore::ResEndian* endian, ResTrigger* trigger);
|
||||
void SwapEndian(ore::ResEndian* endian, ResCut* cut);
|
||||
void SwapEndian(ore::ResEndian* endian, ResClip* clip);
|
||||
void SwapEndian(ore::ResEndian* endian, ResOneshot* oneshot);
|
||||
void SwapEndian(ore::ResEndian* endian, ResSubtimeline* subtimeline);
|
||||
void SwapEndian(ore::ResEndian* endian, ResTimeline* timeline);
|
||||
|
||||
} // namespace evfl
|
78
lib/EventFlow/include/evfl/TimelineObj.h
Normal file
78
lib/EventFlow/include/evfl/TimelineObj.h
Normal file
@ -0,0 +1,78 @@
|
||||
#pragma once
|
||||
|
||||
#include <evfl/EvflAllocator.h>
|
||||
#include <evfl/ResActor.h>
|
||||
#include <ore/Array.h>
|
||||
#include <ore/EnumUtil.h>
|
||||
#include <ore/Types.h>
|
||||
|
||||
namespace evfl {
|
||||
|
||||
struct ResTimeline;
|
||||
|
||||
ORE_ENUM(TimelineState, kNotStarted, kPlaying, kStop, kPause)
|
||||
|
||||
class TimelineObj {
|
||||
public:
|
||||
class Builder {
|
||||
public:
|
||||
explicit Builder(const ResTimeline* timeline) : m_timeline(timeline) {}
|
||||
|
||||
bool Build(TimelineObj* obj, AllocateArg allocate_arg);
|
||||
|
||||
private:
|
||||
const ResTimeline* m_timeline = nullptr;
|
||||
ActBinder::Builder m_act_binder_builder;
|
||||
};
|
||||
|
||||
TimelineObj();
|
||||
|
||||
void Calc();
|
||||
void Reset();
|
||||
void SetState(TimelineState::Type state);
|
||||
void Start(float start_time);
|
||||
void JumpTimeTo(float time);
|
||||
void AdvanceTimeTo(float time);
|
||||
bool RegisterSubtimeline(TimelineObj* obj);
|
||||
|
||||
ActBinder& GetActBinder() { return m_act_binder; }
|
||||
const ActBinder& GetActBinder() const { return m_act_binder; }
|
||||
const ore::Array<TimelineObj*>& GetSubTimelines() const { return m_sub_timelines; }
|
||||
const ResTimeline* GetTimeline() const { return m_timeline; }
|
||||
float GetTime() const { return m_time; }
|
||||
float GetNewTime() const { return m_new_time; }
|
||||
int GetLastTriggerIdx() const { return m_last_trigger_idx; }
|
||||
int GetLastOneshotIdx() const { return m_last_oneshot_idx; }
|
||||
int GetPlayCounter() const { return m_play_counter; }
|
||||
bool IsStarted() const { return m_started; }
|
||||
bool IsJumpedTime() const { return m_jumped_time; }
|
||||
TimelineState::Type GetState() const { return m_state; }
|
||||
|
||||
private:
|
||||
void CalcImpl();
|
||||
void JumpTimeToImpl(float time);
|
||||
void AdvanceTimeToImpl(float time);
|
||||
|
||||
static int s_GlobalPlayCounter;
|
||||
|
||||
void Finalize() {
|
||||
m_timeline = nullptr;
|
||||
m_act_binder.Reset();
|
||||
m_sub_timelines.Clear(&m_allocator);
|
||||
}
|
||||
|
||||
EvflAllocator m_allocator;
|
||||
ore::Array<TimelineObj*> m_sub_timelines;
|
||||
const ResTimeline* m_timeline{};
|
||||
ActBinder m_act_binder{};
|
||||
float m_time{};
|
||||
float m_new_time{};
|
||||
int m_last_trigger_idx = -1;
|
||||
int m_last_oneshot_idx = -1;
|
||||
int m_play_counter = 0;
|
||||
bool m_started = false;
|
||||
bool m_jumped_time = false;
|
||||
ore::SizedEnum<TimelineState::Type, u8> m_state = TimelineState::kNotStarted;
|
||||
};
|
||||
|
||||
} // namespace evfl
|
45
lib/EventFlow/include/ore/Allocator.h
Normal file
45
lib/EventFlow/include/ore/Allocator.h
Normal file
@ -0,0 +1,45 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstddef>
|
||||
#include <memory>
|
||||
#include <ore/Types.h>
|
||||
|
||||
namespace ore {
|
||||
|
||||
class Allocator {
|
||||
public:
|
||||
Allocator() = default;
|
||||
virtual ~Allocator() = default;
|
||||
|
||||
void* New(size_t size, size_t alignment = alignof(std::max_align_t)) {
|
||||
return AllocImpl(size, alignment);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T* New(size_t alignment = alignof(std::max_align_t)) {
|
||||
auto* buffer = AllocImpl(sizeof(T), alignment);
|
||||
if (buffer)
|
||||
return new (buffer) T;
|
||||
return static_cast<T*>(buffer);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void Delete(T* ptr) {
|
||||
std::destroy_at(ptr);
|
||||
Free(ptr);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void DeleteAndNull(T*& ptr) {
|
||||
std::destroy_at(ptr);
|
||||
Free(ptr);
|
||||
ptr = nullptr;
|
||||
}
|
||||
|
||||
void Free(void* ptr) { FreeImpl(ptr); }
|
||||
|
||||
virtual void* AllocImpl(size_t size, size_t alignment) = 0;
|
||||
virtual void FreeImpl(void* ptr) = 0;
|
||||
};
|
||||
|
||||
} // namespace ore
|
287
lib/EventFlow/include/ore/Array.h
Normal file
287
lib/EventFlow/include/ore/Array.h
Normal file
@ -0,0 +1,287 @@
|
||||
#pragma once
|
||||
|
||||
#include <algorithm>
|
||||
#include <iterator>
|
||||
#include <memory>
|
||||
#include <ore/Allocator.h>
|
||||
#include <ore/Buffer.h>
|
||||
#include <ore/IterRange.h>
|
||||
#include <type_traits>
|
||||
|
||||
namespace ore {
|
||||
|
||||
// This is like a std::span, not a fixed-size array like std::array.
|
||||
// Elements will NOT be automatically freed.
|
||||
template <typename T>
|
||||
class Array {
|
||||
public:
|
||||
Array() = default;
|
||||
Array(T* data, int size) : m_data(data), m_size(size) {}
|
||||
|
||||
T* data() const { return m_data; }
|
||||
int size() const { return m_size; }
|
||||
|
||||
auto begin() const { return data(); }
|
||||
auto end() const { return data() + size(); }
|
||||
|
||||
T& operator[](int idx) { return m_data[idx]; }
|
||||
const T& operator[](int idx) const { return m_data[idx]; }
|
||||
|
||||
T& front() { return m_data[0]; }
|
||||
const T& front() const { return m_data[0]; }
|
||||
|
||||
T& back() { return m_data[m_size - 1]; }
|
||||
const T& back() const { return m_data[m_size - 1]; }
|
||||
|
||||
void SetBuffer(void* new_buffer, int num) {
|
||||
DestructElements();
|
||||
m_data = static_cast<T*>(new_buffer);
|
||||
m_size = num;
|
||||
}
|
||||
|
||||
void SetBuffer(int num, Allocator* allocator) {
|
||||
auto* new_buffer = allocator->AllocImpl(num * int(sizeof(T)), alignof(std::max_align_t));
|
||||
SetBuffer(new_buffer, num);
|
||||
}
|
||||
|
||||
void ConstructElements(int num, Allocator* allocator) {
|
||||
SetBuffer(num, allocator);
|
||||
DefaultConstructElements();
|
||||
}
|
||||
|
||||
void ConstructElements(void* new_buffer, int num) {
|
||||
SetBuffer(new_buffer, num);
|
||||
DefaultConstructElements();
|
||||
}
|
||||
|
||||
void ConstructElements(Buffer buffer) {
|
||||
DestructElements();
|
||||
m_data = reinterpret_cast<T*>(buffer.data);
|
||||
m_size = buffer.size / int(sizeof(T));
|
||||
DefaultConstructElements();
|
||||
}
|
||||
|
||||
void DestructElements() { std::destroy(begin(), end()); }
|
||||
|
||||
void ClearWithoutFreeing() {
|
||||
DestructElements();
|
||||
m_data = nullptr;
|
||||
m_size = 0;
|
||||
}
|
||||
|
||||
void Clear(Allocator* allocator) {
|
||||
if (!m_data)
|
||||
return;
|
||||
auto* data = m_data;
|
||||
ClearWithoutFreeing();
|
||||
allocator->Free(data);
|
||||
}
|
||||
|
||||
void DefaultConstructElements() {
|
||||
for (auto it = begin(), e = end(); it != e;)
|
||||
new (it++) T;
|
||||
}
|
||||
|
||||
void UninitializedDefaultConstructElements() {
|
||||
std::uninitialized_default_construct(begin(), end());
|
||||
}
|
||||
|
||||
private:
|
||||
T* m_data{};
|
||||
int m_size{};
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
class SelfDestructingArray : public Array<T> {
|
||||
public:
|
||||
~SelfDestructingArray() { this->DestructElements(); }
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
class ArrayListBase {
|
||||
public:
|
||||
ArrayListBase() : m_data(), m_size(), m_capacity() {}
|
||||
ArrayListBase(T* data, int capacity) {
|
||||
m_size = 0;
|
||||
m_data = data;
|
||||
m_capacity = capacity;
|
||||
}
|
||||
~ArrayListBase() { clear(); }
|
||||
|
||||
ArrayListBase(const ArrayListBase&) = delete;
|
||||
auto operator=(const ArrayListBase&) = delete;
|
||||
|
||||
T* begin() { return m_data; }
|
||||
const T* begin() const { return m_data; }
|
||||
|
||||
T* end() { return m_data + m_size; }
|
||||
const T* end() const { return m_data + m_size; }
|
||||
|
||||
T* data() { return m_data; }
|
||||
const T* data() const { return m_data; }
|
||||
|
||||
int size() const { return m_size; }
|
||||
int capacity() const { return m_capacity; }
|
||||
|
||||
T& operator[](int idx) { return m_data[idx]; }
|
||||
const T& operator[](int idx) const { return m_data[idx]; }
|
||||
|
||||
T& front() { return m_data[0]; }
|
||||
const T& front() const { return m_data[0]; }
|
||||
|
||||
T& back() { return m_data[m_size - 1]; }
|
||||
const T& back() const { return m_data[m_size - 1]; }
|
||||
|
||||
template <typename... Args>
|
||||
T& emplace_back(Args&&... args) {
|
||||
auto* item = new (&m_data[m_size++]) T(std::forward<Args>(args)...);
|
||||
return *item;
|
||||
}
|
||||
|
||||
void push_back(const T& item) { new (&m_data[m_size++]) T(item); }
|
||||
|
||||
void pop_back() {
|
||||
std::destroy_at(&back());
|
||||
--m_size;
|
||||
}
|
||||
|
||||
void clear() {
|
||||
std::destroy(begin(), end());
|
||||
m_size = 0;
|
||||
}
|
||||
|
||||
T* m_data;
|
||||
int m_size;
|
||||
int m_capacity;
|
||||
};
|
||||
|
||||
template <typename T, int N>
|
||||
class FixedArrayList : public ArrayListBase<T> {
|
||||
public:
|
||||
FixedArrayList() : ArrayListBase<T>(reinterpret_cast<T*>(m_storage), N) {}
|
||||
|
||||
private:
|
||||
std::aligned_storage_t<sizeof(T), alignof(T)> m_storage[N];
|
||||
};
|
||||
|
||||
// This is like a std::vector.
|
||||
template <typename T>
|
||||
class DynArrayList : public ArrayListBase<T> {
|
||||
public:
|
||||
DynArrayList() = default;
|
||||
explicit DynArrayList(Allocator* allocator) : m_allocator(allocator) {}
|
||||
|
||||
~DynArrayList() {
|
||||
clear();
|
||||
m_allocator = nullptr;
|
||||
this->m_size = 0;
|
||||
}
|
||||
|
||||
void Reset() {
|
||||
clear();
|
||||
m_allocator = nullptr;
|
||||
}
|
||||
|
||||
DynArrayList(const DynArrayList&) = delete;
|
||||
auto operator=(const DynArrayList&) = delete;
|
||||
|
||||
void Init(Allocator* allocator, int initial_capacity = 1) {
|
||||
clear();
|
||||
m_allocator = allocator;
|
||||
Reallocate(initial_capacity);
|
||||
}
|
||||
|
||||
template <typename... Args>
|
||||
T& emplace_back(Args&&... args) {
|
||||
GrowIfNeeded();
|
||||
return ArrayListBase<T>::emplace_back(std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
void push_back(const T& item) {
|
||||
GrowIfNeeded();
|
||||
return ArrayListBase<T>::push_back(item);
|
||||
}
|
||||
|
||||
void clear() {
|
||||
std::destroy(this->begin(), this->end());
|
||||
auto* data = this->m_data;
|
||||
this->m_data = nullptr;
|
||||
this->m_size = 0;
|
||||
this->m_capacity = 0;
|
||||
Free(data);
|
||||
}
|
||||
|
||||
template <typename InputIterator>
|
||||
void OverwriteWith(InputIterator src_begin, InputIterator src_end) {
|
||||
const int src_size = std::distance(src_begin, src_end);
|
||||
if (src_size > this->m_capacity) {
|
||||
this->m_size = 0;
|
||||
Reallocate(2 * src_size);
|
||||
}
|
||||
this->m_size = src_size;
|
||||
std::uninitialized_copy(src_begin, src_end, this->begin());
|
||||
}
|
||||
|
||||
/// Quadratic complexity; only use this for small copies.
|
||||
template <typename Range>
|
||||
void DeduplicateCopy(const Range& range) {
|
||||
for (auto it = range.begin(), end = range.end(); it != end; ++it) {
|
||||
auto value = *it;
|
||||
if (std::find_if(range.begin(), it, [&](const auto& v) { return value == v; }) == it)
|
||||
this->emplace_back(value);
|
||||
}
|
||||
}
|
||||
|
||||
/// Resize the array so that it contains `new_size` elements.
|
||||
///
|
||||
/// - If the new size is greater than the current size, new elements are added and
|
||||
/// default initialized. Iterators may be invalidated.
|
||||
/// - If the new size is less than the current size, excess elements are destroyed.
|
||||
///
|
||||
/// @param new_size The new size of the array.
|
||||
void Resize(int new_size) {
|
||||
if (this->m_capacity < new_size)
|
||||
Reallocate(new_size);
|
||||
|
||||
if (this->m_size < new_size) {
|
||||
std::uninitialized_default_construct(this->m_data + this->m_size,
|
||||
this->m_data + new_size);
|
||||
} else {
|
||||
std::destroy(this->m_data + new_size, this->m_data + this->m_size);
|
||||
}
|
||||
|
||||
this->m_size = new_size;
|
||||
}
|
||||
|
||||
private:
|
||||
void GrowIfNeeded() {
|
||||
if (this->m_size < this->m_capacity)
|
||||
return;
|
||||
Reallocate(2 * this->m_size + 2);
|
||||
}
|
||||
|
||||
void Reallocate(int new_capacity) {
|
||||
const int num_bytes = sizeof(T) * new_capacity;
|
||||
auto* new_buffer =
|
||||
static_cast<T*>(m_allocator->AllocImpl(num_bytes, alignof(std::max_align_t)));
|
||||
auto* old_buffer = this->m_data;
|
||||
auto* capacity = &this->m_capacity;
|
||||
UninitializedCopyTo(new_buffer);
|
||||
this->m_data = new_buffer;
|
||||
*capacity = new_capacity;
|
||||
Free(old_buffer);
|
||||
}
|
||||
|
||||
void UninitializedCopyTo(T* destination) const {
|
||||
std::uninitialized_copy(this->begin(), this->end(), destination);
|
||||
}
|
||||
|
||||
void Free(void* ptr) {
|
||||
if (ptr)
|
||||
m_allocator->Free(ptr);
|
||||
}
|
||||
|
||||
Allocator* m_allocator{};
|
||||
};
|
||||
|
||||
} // namespace ore
|
153
lib/EventFlow/include/ore/BinaryFile.h
Normal file
153
lib/EventFlow/include/ore/BinaryFile.h
Normal file
@ -0,0 +1,153 @@
|
||||
#pragma once
|
||||
|
||||
#include <ore/StringView.h>
|
||||
#include <ore/Types.h>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
namespace ore {
|
||||
|
||||
template <typename T>
|
||||
constexpr T AlignUpToPowerOf2(T val, int base) {
|
||||
return val + base - 1 & static_cast<unsigned int>(-base);
|
||||
}
|
||||
|
||||
struct RelocationTable;
|
||||
|
||||
struct BinaryBlockHeader {
|
||||
BinaryBlockHeader* FindNextBlock(int type);
|
||||
const BinaryBlockHeader* FindNextBlock(int type) const;
|
||||
BinaryBlockHeader* GetNextBlock();
|
||||
const BinaryBlockHeader* GetNextBlock() const;
|
||||
void SetNextBlock(BinaryBlockHeader* block);
|
||||
|
||||
u32 magic;
|
||||
int next_block_offset;
|
||||
};
|
||||
|
||||
struct BinaryFileHeader {
|
||||
bool IsValid(s64 magic_, int ver_major_, int ver_minor_, int ver_patch_, int ver_sub_) const;
|
||||
bool IsSignatureValid(s64 magic_) const;
|
||||
bool IsVersionValid(int major, int minor, int patch, int sub) const;
|
||||
bool IsEndianReverse() const;
|
||||
bool IsEndianValid() const;
|
||||
|
||||
bool IsAlignmentValid() const;
|
||||
int GetAlignment() const;
|
||||
void SetAlignment(int alignment_);
|
||||
|
||||
bool IsRelocated() const;
|
||||
void SetRelocated(bool relocated);
|
||||
|
||||
void SetByteOrderMark();
|
||||
|
||||
int GetFileSize() const;
|
||||
void SetFileSize(int size);
|
||||
|
||||
StringView GetFileName() const;
|
||||
void SetFileName(const StringView& name);
|
||||
|
||||
RelocationTable* GetRelocationTable();
|
||||
void SetRelocationTable(RelocationTable* table);
|
||||
|
||||
BinaryBlockHeader* GetFirstBlock();
|
||||
const BinaryBlockHeader* GetFirstBlock() const;
|
||||
void SetFirstBlock(BinaryBlockHeader* block);
|
||||
|
||||
BinaryBlockHeader* FindFirstBlock(int type);
|
||||
const BinaryBlockHeader* FindFirstBlock(int type) const;
|
||||
|
||||
u64 magic;
|
||||
u8 ver_major;
|
||||
u8 ver_minor;
|
||||
u8 ver_patch;
|
||||
u8 ver_sub;
|
||||
s16 bom;
|
||||
u8 alignment;
|
||||
u8 _f;
|
||||
int file_name_offset;
|
||||
u16 relocation_flags;
|
||||
u16 first_block_offset;
|
||||
int relocation_table_offset;
|
||||
int file_size;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct BinTString {
|
||||
// Make it impossible to accidentally construct a (partial, broken) copy.
|
||||
BinTString(const BinTString&) = delete;
|
||||
auto operator=(const BinTString&) = delete;
|
||||
|
||||
T* data() { return chars; }
|
||||
const T* data() const { return chars; }
|
||||
|
||||
T& operator[](size_t idx) { return data()[idx]; }
|
||||
const T& operator[](size_t idx) const { return data()[idx]; }
|
||||
|
||||
auto begin() { return data(); }
|
||||
auto begin() const { return data(); }
|
||||
|
||||
auto end() { return data() + length; }
|
||||
auto end() const { return data() + length; }
|
||||
|
||||
bool empty() const { return length == 0; }
|
||||
|
||||
// NOLINTNEXTLINE(google-explicit-constructor)
|
||||
operator TStringView<T>() const { return {data(), length}; }
|
||||
|
||||
BinTString* NextString() { return const_cast<BinTString*>(std::as_const(*this).NextString()); }
|
||||
|
||||
const BinTString* NextString() const {
|
||||
// XXX: this shouldn't have to be a separate case.
|
||||
if constexpr (std::is_same_v<T, wchar_t>) {
|
||||
const auto offset = ((2 + (4 * (length + 1) - 1)) & -4) + 2;
|
||||
return reinterpret_cast<const BinTString*>(reinterpret_cast<const char*>(this) +
|
||||
offset);
|
||||
|
||||
} else {
|
||||
// + 1 for the null terminator
|
||||
const auto offset = offsetof(BinTString, chars) + sizeof(T) * (length + 1);
|
||||
return reinterpret_cast<const BinTString*>(
|
||||
reinterpret_cast<const char*>(this) +
|
||||
AlignUpToPowerOf2(offset, alignof(BinTString)));
|
||||
}
|
||||
}
|
||||
|
||||
u16 length;
|
||||
T chars[1];
|
||||
};
|
||||
|
||||
using BinString = BinTString<char>;
|
||||
using BinWString = BinTString<wchar_t>;
|
||||
|
||||
template <typename T>
|
||||
struct BinTPtr {
|
||||
void Clear() { offset_or_ptr = 0; }
|
||||
void Set(T* ptr) { offset_or_ptr = reinterpret_cast<u64>(ptr); }
|
||||
|
||||
// Only use this after relocation.
|
||||
T* Get() { return reinterpret_cast<T*>(offset_or_ptr); }
|
||||
const T* Get() const { return reinterpret_cast<const T*>(offset_or_ptr); }
|
||||
|
||||
void SetOffset(void* base, void* ptr) {
|
||||
offset_or_ptr = static_cast<int>(ptr ? uintptr_t(ptr) - uintptr_t(base) : 0);
|
||||
}
|
||||
|
||||
u64 GetOffset() const { return offset_or_ptr; }
|
||||
|
||||
T* ToPtr(void* base) const {
|
||||
const auto offset = static_cast<int>(offset_or_ptr);
|
||||
if (offset == 0)
|
||||
return nullptr;
|
||||
return reinterpret_cast<T*>(reinterpret_cast<char*>(base) + offset);
|
||||
}
|
||||
|
||||
void Relocate(void* base) { Set(ToPtr(base)); }
|
||||
void Unrelocate(void* base) { SetOffset(base, Get()); }
|
||||
|
||||
u64 offset_or_ptr;
|
||||
};
|
||||
|
||||
static_assert(sizeof(u64) >= sizeof(void*));
|
||||
|
||||
} // namespace ore
|
149
lib/EventFlow/include/ore/BitUtils.h
Normal file
149
lib/EventFlow/include/ore/BitUtils.h
Normal file
@ -0,0 +1,149 @@
|
||||
#pragma once
|
||||
|
||||
#include <ore/Allocator.h>
|
||||
#include <ore/Types.h>
|
||||
|
||||
namespace ore {
|
||||
|
||||
constexpr int PopCount(u32 x) {
|
||||
x = x - ((x >> 1) & 0x55555555);
|
||||
x = (x & 0x33333333) + ((x >> 2) & 0x33333333);
|
||||
x = (x + (x >> 4)) & 0x0F0F0F0F;
|
||||
x += (x >> 8);
|
||||
x += (x >> 16);
|
||||
return int(x & 0x3f);
|
||||
}
|
||||
|
||||
constexpr int PopCount(u64 x) {
|
||||
x = x - ((x >> 1) & 0x5555555555555555);
|
||||
x = (x & 0x3333333333333333) + ((x >> 2) & 0x3333333333333333);
|
||||
x = (x + (x >> 4)) & 0x0F0F0F0F0F0F0F0F;
|
||||
x += (x >> 8);
|
||||
x += (x >> 16);
|
||||
x += (x >> 32);
|
||||
return int(x & 0x7f);
|
||||
}
|
||||
|
||||
constexpr int CountTrailingZeros(u32 x) {
|
||||
return PopCount((x & -x) - 1);
|
||||
}
|
||||
|
||||
constexpr int CountTrailingZeros(u64 x) {
|
||||
return PopCount((x & -x) - 1);
|
||||
}
|
||||
|
||||
namespace detail {
|
||||
template <typename T>
|
||||
constexpr T AlignUpToPowerOf2(T val, int base) {
|
||||
return val + base - 1 & static_cast<unsigned int>(-base);
|
||||
}
|
||||
} // namespace detail
|
||||
|
||||
class BitArray {
|
||||
public:
|
||||
using Word = size_t;
|
||||
static constexpr int NumBitsPerWord = sizeof(Word) * 8;
|
||||
static constexpr int ClearMask = ~(NumBitsPerWord - 1);
|
||||
static constexpr int ShiftAmount = CountTrailingZeros(u32(NumBitsPerWord));
|
||||
|
||||
class TestIter {
|
||||
public:
|
||||
TestIter(const Word* start, const Word* end);
|
||||
TestIter& operator++();
|
||||
|
||||
int operator*() const { return m_bit; }
|
||||
bool operator==(const TestIter& other) const { return m_bit == other.m_bit; }
|
||||
bool operator!=(const TestIter& other) const { return !operator==(other); }
|
||||
|
||||
private:
|
||||
void SetInvalid() {
|
||||
m_bit = -1;
|
||||
m_current_word = nullptr;
|
||||
m_last_word = nullptr;
|
||||
m_next = 0;
|
||||
}
|
||||
|
||||
int m_bit;
|
||||
const Word* m_current_word;
|
||||
const Word* m_last_word;
|
||||
Word m_next;
|
||||
};
|
||||
|
||||
/// Same as TestIter but clears bits after iterating over them.
|
||||
class TestClearIter {
|
||||
public:
|
||||
TestClearIter(Word* start, Word* end);
|
||||
TestClearIter& operator++();
|
||||
int operator*() const { return m_bit; }
|
||||
bool operator==(const TestClearIter& other) const { return m_bit == other.m_bit; }
|
||||
bool operator!=(const TestClearIter& other) const { return !operator==(other); }
|
||||
|
||||
private:
|
||||
void SetInvalid() {
|
||||
m_bit = -1;
|
||||
m_current_word = nullptr;
|
||||
m_last_word = nullptr;
|
||||
m_next = 0;
|
||||
}
|
||||
|
||||
int m_bit;
|
||||
Word* m_current_word;
|
||||
Word* m_last_word;
|
||||
Word m_next;
|
||||
};
|
||||
|
||||
constexpr BitArray() = default;
|
||||
constexpr BitArray(void* buffer, int num_bits) { SetData(buffer, num_bits); }
|
||||
constexpr BitArray(ore::Allocator* allocator, int num_bits) {
|
||||
AllocateBuffer(allocator, num_bits);
|
||||
}
|
||||
|
||||
void SetData(void* buffer, int num_bits) {
|
||||
m_words = reinterpret_cast<Word*>(buffer);
|
||||
m_num_bits = num_bits;
|
||||
}
|
||||
|
||||
void AllocateBuffer(ore::Allocator* allocator, int num_bits) {
|
||||
SetData(allocator->New(GetRequiredBufferSize(num_bits)), num_bits);
|
||||
SetAllOff();
|
||||
}
|
||||
|
||||
void FreeBufferIfNeeded(ore::Allocator* allocator) {
|
||||
if (m_words)
|
||||
allocator->Delete(m_words);
|
||||
}
|
||||
|
||||
void FreeBuffer(ore::Allocator* allocator) { allocator->Delete(m_words); }
|
||||
|
||||
bool Test(int bit) const {
|
||||
return (GetWord(bit) & (Word(1) << (Word(bit) % NumBitsPerWord))) != 0;
|
||||
}
|
||||
void Set(int bit) { GetWord(bit) |= Word(1) << (Word(bit) % NumBitsPerWord); }
|
||||
void Clear(int bit) { GetWord(bit) &= ~(Word(1) << (Word(bit) % NumBitsPerWord)); }
|
||||
|
||||
void SetAllOn();
|
||||
void SetAllOff();
|
||||
TestIter BeginTest() const;
|
||||
TestIter EndTest() const;
|
||||
TestClearIter BeginTestClear();
|
||||
TestClearIter EndTestClear();
|
||||
|
||||
static int GetRequiredBufferSize(int num_bits) {
|
||||
return sizeof(Word) * (detail::AlignUpToPowerOf2(num_bits, NumBitsPerWord) >> ShiftAmount);
|
||||
}
|
||||
|
||||
private:
|
||||
Word& GetWord(int bit) const { return m_words[bit >> ShiftAmount]; }
|
||||
int GetNumWords() const { return int((m_num_bits + NumBitsPerWord - 1) >> ShiftAmount); }
|
||||
|
||||
void Fill(int num, Word value) {
|
||||
auto* it = m_words;
|
||||
for (int i = num - 1; i >= 0; --i)
|
||||
*it++ = value;
|
||||
}
|
||||
|
||||
Word* m_words{};
|
||||
int m_num_bits{};
|
||||
};
|
||||
|
||||
} // namespace ore
|
25
lib/EventFlow/include/ore/Buffer.h
Normal file
25
lib/EventFlow/include/ore/Buffer.h
Normal file
@ -0,0 +1,25 @@
|
||||
#pragma once
|
||||
|
||||
#include <ore/Allocator.h>
|
||||
#include <ore/Types.h>
|
||||
|
||||
namespace ore {
|
||||
|
||||
struct Buffer {
|
||||
template <typename T>
|
||||
void Allocate(Allocator* allocator, int num) {
|
||||
size = sizeof(T) * num;
|
||||
data = static_cast<char*>(allocator->New(size));
|
||||
}
|
||||
|
||||
void Free(Allocator* allocator) {
|
||||
allocator->Free(data);
|
||||
data = nullptr;
|
||||
size = 0;
|
||||
}
|
||||
|
||||
char* data;
|
||||
int size;
|
||||
};
|
||||
|
||||
} // namespace ore
|
115
lib/EventFlow/include/ore/EnumUtil.h
Normal file
115
lib/EventFlow/include/ore/EnumUtil.h
Normal file
@ -0,0 +1,115 @@
|
||||
#pragma once
|
||||
|
||||
#include <iterator>
|
||||
#include <ore/IterRange.h>
|
||||
#include <ore/StringView.h>
|
||||
#include <type_traits>
|
||||
|
||||
namespace ore {
|
||||
|
||||
namespace detail::EnumUtil {
|
||||
|
||||
int FindIndex(int value, const IterRange<const int*>& values);
|
||||
void Parse(const IterRange<StringView*>& out, StringView definition);
|
||||
|
||||
constexpr int CountValues(const char* text_all, size_t text_all_len) {
|
||||
int count = 1;
|
||||
for (size_t i = 0; i < text_all_len; ++i) {
|
||||
if (text_all[i] == ',')
|
||||
++count;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
} // namespace detail::EnumUtil
|
||||
|
||||
template <class T>
|
||||
struct Enum {
|
||||
public:
|
||||
Enum() { T::Init(); }
|
||||
|
||||
static Enum<T>& Info() { return s_Info; }
|
||||
|
||||
StringView name{};
|
||||
IterRange<StringView*> members{};
|
||||
|
||||
private:
|
||||
static inline Enum<T> s_Info{};
|
||||
};
|
||||
|
||||
#define ORE_ENUM(NAME, ...) \
|
||||
class NAME { \
|
||||
public: \
|
||||
enum Type { __VA_ARGS__ }; \
|
||||
\
|
||||
static void Init() { \
|
||||
static ore::StringView names[cCount]; \
|
||||
ore::detail::EnumUtil::Parse(ore::IterRange<ore::StringView*>(names), cTextAll); \
|
||||
ore::Enum<NAME>::Info().name = #NAME; \
|
||||
ore::Enum<NAME>::Info().members = ore::IterRange<ore::StringView*>(names); \
|
||||
} \
|
||||
\
|
||||
static constexpr int Size() { return cCount; } \
|
||||
static constexpr Type Invalid() { return Type(Size()); } \
|
||||
\
|
||||
private: \
|
||||
static constexpr const char* cTextAll = #__VA_ARGS__; \
|
||||
static constexpr size_t cTextAllLen = sizeof(#__VA_ARGS__); \
|
||||
static constexpr int cCount = ore::detail::EnumUtil::CountValues(cTextAll, cTextAllLen); \
|
||||
};
|
||||
|
||||
// FIXME
|
||||
template <class T>
|
||||
class ValuedEnum {
|
||||
public:
|
||||
ValuedEnum() { T::Init(); }
|
||||
|
||||
static Enum<T>& Info() { return s_Info; }
|
||||
|
||||
StringView name{};
|
||||
IterRange<StringView*> members{};
|
||||
|
||||
private:
|
||||
static inline Enum<T> s_Info{};
|
||||
};
|
||||
|
||||
#define ORE_VALUED_ENUM(NAME, ...) \
|
||||
class NAME { \
|
||||
public: \
|
||||
enum Type { __VA_ARGS__ }; \
|
||||
\
|
||||
static void Init() { \
|
||||
static ore::StringView names[cCount]; \
|
||||
ore::detail::EnumUtil::Parse(ore::IterRange<ore::StringView*>(names), cTextAll); \
|
||||
ore::ValuedEnum<NAME>::Info().name = #NAME; \
|
||||
ore::ValuedEnum<NAME>::Info().members = ore::IterRange<ore::StringView*>(names); \
|
||||
} \
|
||||
\
|
||||
static constexpr int Size() { return cCount; } \
|
||||
static constexpr Type Invalid() { return Type(Size()); } \
|
||||
\
|
||||
private: \
|
||||
static constexpr const char* cTextAll = #__VA_ARGS__; \
|
||||
static constexpr size_t cTextAllLen = sizeof(#__VA_ARGS__); \
|
||||
static constexpr int cCount = ore::detail::EnumUtil::CountValues(cTextAll, cTextAllLen); \
|
||||
};
|
||||
|
||||
/// For storing an enum with a particular storage size when specifying the underlying type of the
|
||||
/// enum is not an option.
|
||||
template <typename Enum, typename Storage>
|
||||
struct SizedEnum {
|
||||
static_assert(std::is_enum<Enum>());
|
||||
static_assert(!std::is_enum<Storage>());
|
||||
|
||||
constexpr SizedEnum() = default;
|
||||
constexpr SizedEnum(Enum value) { *this = value; }
|
||||
constexpr operator Enum() const { return static_cast<Enum>(mValue); }
|
||||
constexpr SizedEnum& operator=(Enum value) {
|
||||
mValue = static_cast<Storage>(value);
|
||||
return *this;
|
||||
}
|
||||
|
||||
Storage mValue;
|
||||
};
|
||||
|
||||
} // namespace ore
|
100
lib/EventFlow/include/ore/IntrusiveList.h
Normal file
100
lib/EventFlow/include/ore/IntrusiveList.h
Normal file
@ -0,0 +1,100 @@
|
||||
#pragma once
|
||||
|
||||
#include <utility>
|
||||
|
||||
namespace ore {
|
||||
|
||||
class IntrusiveListNode {
|
||||
public:
|
||||
constexpr explicit IntrusiveListNode() { m_prev = m_next = this; }
|
||||
|
||||
IntrusiveListNode(const IntrusiveListNode&) = delete;
|
||||
auto operator=(const IntrusiveListNode&) = delete;
|
||||
|
||||
IntrusiveListNode(IntrusiveListNode&& other) noexcept { *this = std::move(other); }
|
||||
IntrusiveListNode& operator=(IntrusiveListNode&& other) noexcept {
|
||||
auto* prev = other.m_prev;
|
||||
other.m_prev = this;
|
||||
prev->m_next = this;
|
||||
m_prev = prev;
|
||||
m_next = &other;
|
||||
other.Erase();
|
||||
return *this;
|
||||
}
|
||||
|
||||
IntrusiveListNode* Prev() const { return m_prev; }
|
||||
IntrusiveListNode* Next() const { return m_next; }
|
||||
bool IsLinked() const { return Prev() || Next(); }
|
||||
|
||||
void Erase() {
|
||||
auto* next = m_next;
|
||||
auto* next_prev = next->m_prev;
|
||||
m_prev->m_next = next;
|
||||
next->m_prev = m_prev;
|
||||
// This is a circular list.
|
||||
next_prev->m_next = this;
|
||||
m_prev = next_prev;
|
||||
}
|
||||
|
||||
void InsertFront(IntrusiveListNode* node) {
|
||||
auto* prev = node->m_prev;
|
||||
node->m_prev = m_prev;
|
||||
prev->m_next = this;
|
||||
m_prev->m_next = node;
|
||||
m_prev = prev;
|
||||
}
|
||||
|
||||
private:
|
||||
template <typename T>
|
||||
friend class IntrusiveList;
|
||||
|
||||
IntrusiveListNode* m_prev{};
|
||||
IntrusiveListNode* m_next{};
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
class IntrusiveList {
|
||||
public:
|
||||
void SetOffset(int offset) { m_offset = offset; }
|
||||
|
||||
bool Empty() const { return m_node.m_next == &m_node; }
|
||||
T* Front() { return NodeToItemWithNullCheck(m_node.m_next); }
|
||||
T* Back() { return NodeToItemWithNullCheck(m_node.m_prev); }
|
||||
const T* Front() const { return NodeToItemWithNullCheck(m_node.m_next); }
|
||||
const T* Back() const { return NodeToItemWithNullCheck(m_node.m_prev); }
|
||||
|
||||
void Erase(T* item) { ItemToNode(item)->Erase(); }
|
||||
|
||||
void InsertFront(T* item) { m_node.InsertFront(ItemToNode(item)); }
|
||||
|
||||
private:
|
||||
IntrusiveListNode* ItemToNode(T* item) const {
|
||||
return reinterpret_cast<IntrusiveListNode*>(reinterpret_cast<char*>(item) + m_offset);
|
||||
}
|
||||
|
||||
const IntrusiveListNode* ItemToNode(const T* item) const {
|
||||
return reinterpret_cast<const IntrusiveListNode*>(reinterpret_cast<const char*>(item) +
|
||||
m_offset);
|
||||
}
|
||||
|
||||
T* NodeToItem(IntrusiveListNode* node) const {
|
||||
return reinterpret_cast<T*>(reinterpret_cast<char*>(node) - m_offset);
|
||||
}
|
||||
|
||||
const T* NodeToItem(const IntrusiveListNode* node) const {
|
||||
return reinterpret_cast<const T*>(reinterpret_cast<const char*>(node) - m_offset);
|
||||
}
|
||||
|
||||
T* NodeToItemWithNullCheck(IntrusiveListNode* node) const {
|
||||
return node == &m_node ? nullptr : NodeToItem(node);
|
||||
}
|
||||
|
||||
const T* NodeToItemWithNullCheck(const IntrusiveListNode* node) const {
|
||||
return node == &m_node ? nullptr : NodeToItem(node);
|
||||
}
|
||||
|
||||
IntrusiveListNode m_node;
|
||||
int m_offset = -1;
|
||||
};
|
||||
|
||||
} // namespace ore
|
28
lib/EventFlow/include/ore/IterRange.h
Normal file
28
lib/EventFlow/include/ore/IterRange.h
Normal file
@ -0,0 +1,28 @@
|
||||
#pragma once
|
||||
|
||||
#include <iterator>
|
||||
|
||||
namespace ore {
|
||||
|
||||
template <typename T>
|
||||
class IterRange {
|
||||
public:
|
||||
constexpr IterRange() = default;
|
||||
constexpr IterRange(const T& begin_, const T& end_) : m_begin(begin_), m_end(end_) {}
|
||||
template <typename Other>
|
||||
// NOLINTNEXTLINE(google-explicit-constructor)
|
||||
constexpr IterRange(Other& x) : IterRange(std::begin(x), std::end(x)) {}
|
||||
|
||||
constexpr IterRange(const T& begin, int size) : m_begin(begin), m_end(begin + size) {}
|
||||
|
||||
const auto& begin() const { return m_begin; }
|
||||
const auto& end() const { return m_end; }
|
||||
|
||||
int size() const { return end() - begin(); }
|
||||
|
||||
private:
|
||||
T m_begin{};
|
||||
T m_end{};
|
||||
};
|
||||
|
||||
} // namespace ore
|
50
lib/EventFlow/include/ore/RelocationTable.h
Normal file
50
lib/EventFlow/include/ore/RelocationTable.h
Normal file
@ -0,0 +1,50 @@
|
||||
#pragma once
|
||||
|
||||
#include <ore/Types.h>
|
||||
|
||||
namespace ore {
|
||||
|
||||
struct RelocationTable {
|
||||
struct Section {
|
||||
struct Entry {
|
||||
/// Offset to pointers to relocate
|
||||
int pointers_offset;
|
||||
/// Bit field that determines which pointers need to be relocated
|
||||
/// (next to 32 contiguous pointers starting from the listed offset)
|
||||
u32 mask;
|
||||
};
|
||||
|
||||
void SetPtr(void* ptr_);
|
||||
void* GetPtr() const;
|
||||
void* GetPtrInFile(void* base) const;
|
||||
void* GetBasePtr(void* base) const;
|
||||
u32 GetSize() const;
|
||||
|
||||
u64 ptr;
|
||||
int offset;
|
||||
int size;
|
||||
int first_entry_idx;
|
||||
int num_entries;
|
||||
};
|
||||
|
||||
u32 magic;
|
||||
int table_start_offset;
|
||||
int num_sections;
|
||||
Section sections[1];
|
||||
|
||||
Section* GetSections() { return sections; }
|
||||
const Section* GetSections() const { return sections; }
|
||||
|
||||
Section::Entry* GetEntries() {
|
||||
return reinterpret_cast<Section::Entry*>(GetSections() + num_sections);
|
||||
}
|
||||
const Section::Entry* GetEntries() const {
|
||||
return reinterpret_cast<const Section::Entry*>(GetSections() + num_sections);
|
||||
}
|
||||
|
||||
void Relocate();
|
||||
void Unrelocate();
|
||||
static int CalcSize(int num_sections, int num_entries);
|
||||
};
|
||||
|
||||
} // namespace ore
|
62
lib/EventFlow/include/ore/ResDic.h
Normal file
62
lib/EventFlow/include/ore/ResDic.h
Normal file
@ -0,0 +1,62 @@
|
||||
#pragma once
|
||||
|
||||
#include <ore/BinaryFile.h>
|
||||
#include <ore/StringView.h>
|
||||
#include <ore/Types.h>
|
||||
|
||||
namespace ore {
|
||||
|
||||
struct ResEndian;
|
||||
|
||||
struct ResDicEntry {
|
||||
StringView GetKey() const { return *name.Get(); }
|
||||
|
||||
// Bits 3-7: index of the byte that should be checked
|
||||
// Bits 0-2: index of the bit in that byte
|
||||
int compact_bit_idx;
|
||||
u16 next_indices[2];
|
||||
BinTPtr<BinString> name;
|
||||
};
|
||||
|
||||
struct ResDic {
|
||||
static int FindRefBit(const StringView& str1, const StringView& str2);
|
||||
|
||||
const ResDicEntry* FindEntry(const StringView& key) const {
|
||||
auto* prev = &entries[0];
|
||||
auto* entry = &entries[prev->next_indices[0]];
|
||||
while (prev->compact_bit_idx < entry->compact_bit_idx) {
|
||||
const int bit_idx = entry->compact_bit_idx;
|
||||
long bit = 0;
|
||||
if (u32(key.length()) > u32(bit_idx >> 3))
|
||||
bit = ((key[key.length() + -((bit_idx >> 3) + 1)] >> (bit_idx & 7))) & 1;
|
||||
|
||||
prev = entry;
|
||||
entry = &entries[prev->next_indices[bit]];
|
||||
}
|
||||
return entry;
|
||||
}
|
||||
|
||||
/// Returns the index for the specified key or -1 if it cannot be found.
|
||||
int FindIndex(const StringView& key) const {
|
||||
const auto* entry = FindEntry(key);
|
||||
const auto entry_name = entry->GetKey();
|
||||
bool ok = [&] { return StringView(key.data(), key.length()) == entry_name; }();
|
||||
if (!ok)
|
||||
return -1;
|
||||
return static_cast<int>(entry - &GetEntries()[1]);
|
||||
}
|
||||
|
||||
/// Entry 0 is the root entry.
|
||||
ResDicEntry* GetEntries() { return entries; }
|
||||
/// Entry 0 is the root entry.
|
||||
const ResDicEntry* GetEntries() const { return entries; }
|
||||
|
||||
u32 magic;
|
||||
int num_entries;
|
||||
ResDicEntry entries[1];
|
||||
// Followed by ResDicEntry[num_entries].
|
||||
};
|
||||
|
||||
void SwapEndian(ResEndian* endian, ResDic* dic);
|
||||
|
||||
} // namespace ore
|
75
lib/EventFlow/include/ore/ResEndian.h
Normal file
75
lib/EventFlow/include/ore/ResEndian.h
Normal file
@ -0,0 +1,75 @@
|
||||
#pragma once
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
|
||||
#include <cstring>
|
||||
#include <ore/Types.h>
|
||||
|
||||
namespace ore {
|
||||
|
||||
[[nodiscard]] inline u8 SwapEndian(u8 x) {
|
||||
return x;
|
||||
}
|
||||
|
||||
[[nodiscard]] inline u16 SwapEndian(u16 x) {
|
||||
#ifdef _MSC_VER
|
||||
return _byteswap_ushort(x);
|
||||
#else
|
||||
return __builtin_bswap16(x);
|
||||
#endif
|
||||
}
|
||||
|
||||
[[nodiscard]] inline u32 SwapEndian(u32 x) {
|
||||
#ifdef _MSC_VER
|
||||
return _byteswap_ulong(x);
|
||||
#else
|
||||
return __builtin_bswap32(x);
|
||||
#endif
|
||||
}
|
||||
|
||||
[[nodiscard]] inline u64 SwapEndian(u64 x) {
|
||||
#ifdef _MSC_VER
|
||||
return _byteswap_uint64(x);
|
||||
#else
|
||||
return __builtin_bswap64(x);
|
||||
#endif
|
||||
}
|
||||
|
||||
[[nodiscard]] inline s8 SwapEndian(s8 x) {
|
||||
return SwapEndian(u8(x));
|
||||
}
|
||||
|
||||
[[nodiscard]] inline s16 SwapEndian(s16 x) {
|
||||
return SwapEndian(u16(x));
|
||||
}
|
||||
|
||||
[[nodiscard]] inline s32 SwapEndian(s32 x) {
|
||||
return SwapEndian(u32(x));
|
||||
}
|
||||
|
||||
[[nodiscard]] inline s64 SwapEndian(s64 x) {
|
||||
return SwapEndian(u64(x));
|
||||
}
|
||||
|
||||
[[nodiscard]] inline f32 SwapEndian(f32 x) {
|
||||
static_assert(sizeof(u32) == sizeof(f32));
|
||||
u32 i;
|
||||
std::memcpy(&i, &x, sizeof(i));
|
||||
i = SwapEndian(i);
|
||||
std::memcpy(&x, &i, sizeof(i));
|
||||
return x;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline void SwapEndian(T* value) {
|
||||
*value = SwapEndian(*value);
|
||||
}
|
||||
|
||||
struct ResEndian {
|
||||
char* base;
|
||||
bool is_serializing;
|
||||
};
|
||||
|
||||
} // namespace ore
|
58
lib/EventFlow/include/ore/ResMetaData.h
Normal file
58
lib/EventFlow/include/ore/ResMetaData.h
Normal file
@ -0,0 +1,58 @@
|
||||
#pragma once
|
||||
|
||||
#include <ore/BinaryFile.h>
|
||||
#include <ore/EnumUtil.h>
|
||||
#include <ore/ResDic.h>
|
||||
#include <ore/StringView.h>
|
||||
#include <ore/Types.h>
|
||||
|
||||
namespace ore {
|
||||
|
||||
struct ResDic;
|
||||
struct ResEndian;
|
||||
|
||||
struct ResMetaData {
|
||||
struct ActorIdentifier {
|
||||
BinTPtr<BinString> name;
|
||||
BinTPtr<BinString> sub_name;
|
||||
};
|
||||
|
||||
union Value {
|
||||
BinTPtr<ResMetaData> container;
|
||||
// Also used for booleans. Anything that is != 0 is treated as true.
|
||||
int i;
|
||||
float f;
|
||||
BinTPtr<BinString> str;
|
||||
BinTPtr<BinWString> wstr;
|
||||
ActorIdentifier actor;
|
||||
};
|
||||
|
||||
ORE_ENUM(DataType, kArgument, kContainer, kInt, kBool, kFloat, kString, kWString, kIntArray, kBoolArray, kFloatArray, kStringArray, kWStringArray, kActorIdentifier)
|
||||
|
||||
/// @warning Only usable if type == kContainer.
|
||||
const ResMetaData* Get(const StringView& key, DataType::Type expected_type) const {
|
||||
const int idx = dictionary.Get()->FindIndex(key);
|
||||
if (idx == -1)
|
||||
return nullptr;
|
||||
|
||||
const auto* meta = (&value.container + idx)->Get();
|
||||
if (meta->type != expected_type)
|
||||
return nullptr;
|
||||
|
||||
return meta;
|
||||
}
|
||||
|
||||
SizedEnum<DataType::Type, u8> type;
|
||||
u16 num_items;
|
||||
BinTPtr<ResDic> dictionary;
|
||||
Value value;
|
||||
};
|
||||
|
||||
// XXX: is this unused?
|
||||
struct ResUserData {
|
||||
ORE_ENUM(DataType, kInt, kFloat, kString, kWString, kStream)
|
||||
};
|
||||
|
||||
void SwapEndian(ResEndian* endian, ResMetaData* res);
|
||||
|
||||
} // namespace ore
|
20
lib/EventFlow/include/ore/StringPool.h
Normal file
20
lib/EventFlow/include/ore/StringPool.h
Normal file
@ -0,0 +1,20 @@
|
||||
#pragma once
|
||||
|
||||
#include <ore/BinaryFile.h>
|
||||
#include <ore/Types.h>
|
||||
|
||||
namespace ore {
|
||||
|
||||
struct StringPool : BinaryBlockHeader {
|
||||
int GetLength() const;
|
||||
void SetLength(int len);
|
||||
|
||||
BinString* GetFirstString() { return dummy_string.NextString(); }
|
||||
|
||||
u32 reserved_8;
|
||||
u32 reserved_c;
|
||||
int length;
|
||||
BinString dummy_string;
|
||||
};
|
||||
|
||||
} // namespace ore
|
79
lib/EventFlow/include/ore/StringView.h
Normal file
79
lib/EventFlow/include/ore/StringView.h
Normal file
@ -0,0 +1,79 @@
|
||||
#pragma once
|
||||
|
||||
#include <algorithm>
|
||||
#include <ore/Types.h>
|
||||
#include <string>
|
||||
|
||||
namespace ore {
|
||||
|
||||
template <typename T>
|
||||
constexpr size_t StringLength(const T* str) {
|
||||
if (str == nullptr || str[0] == 0)
|
||||
return 0;
|
||||
|
||||
size_t len = 0;
|
||||
while (*str++ != 0)
|
||||
++len;
|
||||
|
||||
#ifdef MATCHING_HACK_NX_CLANG
|
||||
__builtin_assume(len <= 0xffffffff);
|
||||
#endif
|
||||
return len;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
class TStringView {
|
||||
public:
|
||||
// Annoyingly enough, this cannot be defaulted (otherwise Clang will not dynamically
|
||||
// initialize static StringView variables).
|
||||
TStringView() {}
|
||||
|
||||
constexpr TStringView(const T* data, size_t len) : m_data(data), m_len(len) {}
|
||||
|
||||
/// @param data A null-terminated string. Must not be nullptr.
|
||||
// NOLINTNEXTLINE(google-explicit-constructor)
|
||||
TStringView(const T* data) : m_data(data), m_len(StringLength(data)) {}
|
||||
|
||||
constexpr const T* data() const { return m_data; }
|
||||
constexpr int size() const { return m_len; }
|
||||
constexpr int length() const { return m_len; }
|
||||
constexpr bool empty() const { return size() == 0; }
|
||||
|
||||
constexpr auto begin() const { return m_data; }
|
||||
constexpr auto cbegin() const { return m_data; }
|
||||
constexpr auto end() const { return m_data + m_len; }
|
||||
constexpr auto cend() const { return m_data + m_len; }
|
||||
|
||||
const T& operator[](size_t idx) const { return m_data[idx]; }
|
||||
|
||||
static int Compare(TStringView lhs, TStringView rhs) {
|
||||
const T* s1 = lhs.data();
|
||||
const T* s2 = rhs.data();
|
||||
int len = std::min(lhs.size(), rhs.size());
|
||||
if (len < 1)
|
||||
return lhs.size() - rhs.size();
|
||||
while (len-- > 0) {
|
||||
if (*s1 == 0 || *s1 != *s2)
|
||||
return *s1 - *s2;
|
||||
++s1, ++s2;
|
||||
}
|
||||
return lhs.size() - rhs.size();
|
||||
}
|
||||
|
||||
int Compare(TStringView rhs) const { return Compare(*this, rhs); }
|
||||
|
||||
friend bool operator==(TStringView lhs, TStringView rhs) {
|
||||
return lhs.size() == rhs.size() && Compare(lhs, rhs) == 0;
|
||||
}
|
||||
|
||||
friend bool operator!=(TStringView lhs, TStringView rhs) { return !operator==(lhs, rhs); }
|
||||
|
||||
private:
|
||||
const T* m_data{};
|
||||
u32 m_len{};
|
||||
};
|
||||
|
||||
using StringView = TStringView<char>;
|
||||
using WStringView = TStringView<wchar_t>;
|
||||
|
||||
} // namespace ore
|
20
lib/EventFlow/include/ore/Types.h
Normal file
20
lib/EventFlow/include/ore/Types.h
Normal file
@ -0,0 +1,20 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
|
||||
using u8 = std::uint8_t;
|
||||
using u16 = std::uint16_t;
|
||||
using u32 = std::uint32_t;
|
||||
using u64 = std::uint64_t;
|
||||
|
||||
using s8 = std::int8_t;
|
||||
using s16 = std::int16_t;
|
||||
using s32 = std::int32_t;
|
||||
using s64 = std::int64_t;
|
||||
|
||||
using f32 = float;
|
||||
using f64 = double;
|
||||
|
||||
using char16 = char16_t;
|
||||
using size_t = std::size_t;
|
56
lib/EventFlow/src/evfl/Action.cpp
Normal file
56
lib/EventFlow/src/evfl/Action.cpp
Normal file
@ -0,0 +1,56 @@
|
||||
#include <evfl/Action.h>
|
||||
#include <evfl/Flowchart.h>
|
||||
|
||||
namespace evfl {
|
||||
|
||||
ActionDoneHandler::ActionDoneHandler(FlowchartObj* obj, FlowchartContext* context, int node_idx)
|
||||
: m_context(context) {
|
||||
m_node_idx = node_idx;
|
||||
m_obj = obj;
|
||||
m_node_counter = context->GetNode(node_idx).GetNodeCounter();
|
||||
}
|
||||
|
||||
FlowchartContextNode* ActionDoneHandler::GetContextNode() {
|
||||
if (!m_context)
|
||||
return nullptr;
|
||||
|
||||
auto& node = m_context->GetNode(m_node_idx);
|
||||
if (node.GetNodeCounter() != m_node_counter)
|
||||
return nullptr;
|
||||
|
||||
return &node;
|
||||
}
|
||||
|
||||
void ActionDoneHandler::InvokeFromFlowchartImpl() {
|
||||
auto* node = GetContextNode();
|
||||
if (!node)
|
||||
return;
|
||||
|
||||
node->m_state = FlowchartContextNode::State::kDone;
|
||||
m_context->ProcessContext();
|
||||
}
|
||||
|
||||
void ActionDoneHandler::InvokeFromTimelineImpl() {}
|
||||
|
||||
bool ActionDoneHandler::IsWaitingJoin() {
|
||||
if (!m_context)
|
||||
return false;
|
||||
|
||||
const auto& node = m_context->GetNode(m_node_idx);
|
||||
if (node.GetNodeCounter() != m_node_counter)
|
||||
return false;
|
||||
|
||||
return node.GetState() == FlowchartContextNode::State::kWaiting;
|
||||
}
|
||||
|
||||
bool ActionDoneHandler::CancelWaiting() {
|
||||
auto* node = GetContextNode();
|
||||
if (!node)
|
||||
return false;
|
||||
|
||||
node->m_state = FlowchartContextNode::State::kInvoked;
|
||||
m_handled = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace evfl
|
694
lib/EventFlow/src/evfl/Flowchart.cpp
Normal file
694
lib/EventFlow/src/evfl/Flowchart.cpp
Normal file
@ -0,0 +1,694 @@
|
||||
#include <algorithm>
|
||||
#include <evfl/Action.h>
|
||||
#include <evfl/Flowchart.h>
|
||||
#include <evfl/Param.h>
|
||||
#include <evfl/Query.h>
|
||||
#include <evfl/ResFlowchart.h>
|
||||
#include <iterator>
|
||||
#include <ore/Array.h>
|
||||
#include <ore/BitUtils.h>
|
||||
#include <ore/IterRange.h>
|
||||
#include <ore/ResDic.h>
|
||||
#include <ore/StringView.h>
|
||||
|
||||
namespace evfl {
|
||||
|
||||
int FlowchartContext::s_GlobalCounter{};
|
||||
|
||||
FlowchartContext::FlowchartContext() {
|
||||
m_handlers.SetOffset(ActionDoneHandler::GetListNodeOffset());
|
||||
}
|
||||
|
||||
void FlowchartContext::Start(MetaDataPack* pack) {
|
||||
auto& obj = m_objs[m_obj_idx];
|
||||
const auto& entry_point = obj.GetFlowchart()->entry_points.Get()[m_active_entry_point_idx];
|
||||
|
||||
const auto main_event_idx = entry_point.main_event_idx;
|
||||
if (main_event_idx == 0xffff)
|
||||
return;
|
||||
|
||||
m_metadata_pack = pack;
|
||||
|
||||
const int node_idx = AllocNode();
|
||||
auto& node = m_nodes[node_idx];
|
||||
node.m_obj = &obj;
|
||||
node.m_event_idx = main_event_idx;
|
||||
node.m_next_node_idx = -1;
|
||||
node.m_idx = node_idx;
|
||||
node.m_state = FlowchartContextNode::State::kNotInvoked;
|
||||
AllocVariablePack(node, entry_point);
|
||||
|
||||
ProcessContext();
|
||||
}
|
||||
|
||||
int FlowchartContext::AllocNode() {
|
||||
int idx = m_next_node_idx;
|
||||
|
||||
if (idx == 0xffff) {
|
||||
idx = m_nodes.size();
|
||||
m_nodes.Resize(2 * m_nodes.size());
|
||||
for (int i = idx, n = m_nodes.size(); i < n - 1; ++i) {
|
||||
m_nodes[i].m_next_node_idx = i + 1;
|
||||
m_nodes[i].m_state = FlowchartContextNode::State::kFree;
|
||||
}
|
||||
}
|
||||
|
||||
auto& node = m_nodes[idx];
|
||||
m_next_node_idx = node.m_next_node_idx;
|
||||
node.m_event_idx = -1;
|
||||
node.m_next_node_idx = -1;
|
||||
node.m_idx = -1;
|
||||
node.m_owns_variable_pack = false;
|
||||
node.m_obj = nullptr;
|
||||
node.m_variable_pack = nullptr;
|
||||
node.m_node_counter = ++s_GlobalCounter;
|
||||
node.m_state = FlowchartContextNode::State::kInvalid;
|
||||
++m_num_allocated_nodes;
|
||||
return idx;
|
||||
}
|
||||
|
||||
void FlowchartContext::AllocVariablePack(FlowchartContextNode& node,
|
||||
const ResEntryPoint& entry_point) {
|
||||
FreeVariablePack(node);
|
||||
|
||||
if (entry_point.num_variable_defs != 0) {
|
||||
auto* pack = m_allocator.New<VariablePack>();
|
||||
pack->Init(m_allocator.GetArg(), &entry_point);
|
||||
node.m_variable_pack = pack;
|
||||
node.m_owns_variable_pack = true;
|
||||
}
|
||||
}
|
||||
|
||||
void FlowchartContext::ProcessContext() {
|
||||
if (m_is_processing) {
|
||||
_91 = 1;
|
||||
} else {
|
||||
m_is_processing = true;
|
||||
do {
|
||||
_91 = 0;
|
||||
for (int i = 0, n = m_nodes.size(); i < n; ++i) {
|
||||
if (!m_nodes[i].IsInvalidOrFree())
|
||||
_91 = (ProcessContextNode(i) | (_91 != 0)) & 1;
|
||||
}
|
||||
} while (_91);
|
||||
m_is_processing = false;
|
||||
}
|
||||
}
|
||||
|
||||
FlowchartObj* FlowchartContext::FindFlowchartObj(ore::StringView name) {
|
||||
auto it = std::find_if(m_objs.begin(), m_objs.end(), [&](const FlowchartObj& obj) {
|
||||
return name == *obj.GetFlowchart()->name.Get();
|
||||
});
|
||||
return it == m_objs.end() ? nullptr : it;
|
||||
}
|
||||
|
||||
const FlowchartObj* FlowchartContext::FindFlowchartObj(ore::StringView name) const {
|
||||
auto it = std::find_if(m_objs.begin(), m_objs.end(), [&](const FlowchartObj& obj) {
|
||||
return name == *obj.GetFlowchart()->name.Get();
|
||||
});
|
||||
return it == m_objs.end() ? nullptr : it;
|
||||
}
|
||||
|
||||
void FlowchartContext::UnbindAll() {
|
||||
Clear();
|
||||
for (auto it = m_objs.begin(); it != m_objs.end(); ++it)
|
||||
it->GetActBinder().UnbindAll();
|
||||
}
|
||||
|
||||
void FlowchartContext::Clear() {
|
||||
for (int i = 0, n = m_nodes.size(); i < n; ++i) {
|
||||
FreeVariablePack(m_nodes[i]);
|
||||
m_nodes[i].Reset();
|
||||
if (i < n - 1) {
|
||||
m_nodes[i].m_next_node_idx = i + 1;
|
||||
m_nodes[i].m_state = FlowchartContextNode::State::kFree;
|
||||
}
|
||||
}
|
||||
|
||||
m_next_node_idx = 0;
|
||||
m_num_allocated_nodes = 0;
|
||||
m_metadata_pack = nullptr;
|
||||
|
||||
while (!m_handlers.Empty()) {
|
||||
auto* handler = m_handlers.Front();
|
||||
handler->m_list_node.Erase();
|
||||
handler->Reset();
|
||||
}
|
||||
}
|
||||
|
||||
void FlowchartContext::FreeVariablePack(FlowchartContextNode& node) {
|
||||
if (node.m_variable_pack && node.m_owns_variable_pack)
|
||||
m_allocator.DeleteAndNull(node.m_variable_pack);
|
||||
|
||||
node.m_variable_pack = nullptr;
|
||||
node.m_owns_variable_pack = false;
|
||||
}
|
||||
|
||||
void FlowchartContext::CopyVariablePack(FlowchartContextNode& src, FlowchartContextNode& dst) {
|
||||
FreeVariablePack(dst);
|
||||
dst.m_variable_pack = src.m_variable_pack;
|
||||
dst.m_owns_variable_pack = false;
|
||||
}
|
||||
|
||||
bool FlowchartContext::ProcessContextNode(int node_idx) {
|
||||
using State = FlowchartContextNode::State;
|
||||
auto& node = GetNode(node_idx);
|
||||
while (true) {
|
||||
auto* obj = node.m_obj;
|
||||
const auto* flowchart = obj->GetFlowchart();
|
||||
const auto& event = flowchart->events.Get()[node.m_event_idx];
|
||||
|
||||
int next_event_idx = -1;
|
||||
|
||||
switch (event.type) {
|
||||
case ResEvent::EventType::kAction: {
|
||||
switch (node.m_state) {
|
||||
case State::kNotInvoked: {
|
||||
node.m_state = State::kInvoked;
|
||||
|
||||
const auto actor_idx = event.actor_idx;
|
||||
#ifdef EVFL_VER_LABO
|
||||
const auto& actor = flowchart->actors.Get()[actor_idx];
|
||||
#else
|
||||
const auto& actor = obj->GetFlowchart()->actors.Get()[actor_idx];
|
||||
#endif
|
||||
const auto* actions = actor.actions.Get();
|
||||
const auto* arg_name = actor.argument_name.Get();
|
||||
const auto action_idx = event.actor_action_idx;
|
||||
|
||||
const auto* binding = &obj->GetActBinder().GetBindings()[actor_idx];
|
||||
if (!arg_name->empty()) {
|
||||
binding = TrackBackArgumentActor(node_idx, *arg_name);
|
||||
if (!binding)
|
||||
return false;
|
||||
}
|
||||
|
||||
const auto* action = binding->GetAction(*actions[action_idx].name.Get());
|
||||
const ActionArg arg(this, node_idx, binding->GetUserData(), action->user_data,
|
||||
node.m_variable_pack, &event);
|
||||
ActionDoneHandler done_handler(obj, this, node_idx);
|
||||
m_handlers.InsertFront(&done_handler);
|
||||
action->handler(arg, std::move(done_handler));
|
||||
return false;
|
||||
} // action case State::kNotInvoked
|
||||
case State::kDone:
|
||||
next_event_idx = event.next_event_idx;
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
} // case ResEvent::EventType::kAction
|
||||
|
||||
case ResEvent::EventType::kSwitch: {
|
||||
if (node.m_state != State::kNotInvoked)
|
||||
return false;
|
||||
|
||||
const auto actor_idx = event.actor_idx;
|
||||
const auto& actor = flowchart->actors.Get()[actor_idx];
|
||||
const auto* queries = actor.queries.Get();
|
||||
const auto* arg_name = actor.argument_name.Get();
|
||||
const auto query_idx = event.actor_query_idx;
|
||||
|
||||
const auto* binding = &obj->GetActBinder().GetBindings()[actor_idx];
|
||||
if (!arg_name->empty()) {
|
||||
binding = TrackBackArgumentActor(node_idx, *arg_name);
|
||||
if (!binding)
|
||||
return false;
|
||||
}
|
||||
|
||||
const auto* query = binding->GetQuery(*queries[query_idx].name.Get());
|
||||
const QueryArg arg(this, node_idx, binding->GetUserData(), query->user_data, &event,
|
||||
node.m_variable_pack);
|
||||
const int result = query->handler(arg);
|
||||
|
||||
next_event_idx = 0xffff;
|
||||
ore::Array<const ResCase> cases{event.cases.Get(), event.num_cases};
|
||||
for (const auto& case_ : cases) {
|
||||
if (case_.value == result) {
|
||||
next_event_idx = case_.event_idx;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
} // case ResEvent::EventType::kSwitch
|
||||
|
||||
case ResEvent::EventType::kFork: {
|
||||
if (node.m_state != State::kNotInvoked)
|
||||
return false;
|
||||
|
||||
node.m_event_idx = event.join_event_idx;
|
||||
node.m_state = State::kInvoked;
|
||||
UpdateNodeCounter(node_idx);
|
||||
|
||||
int prev_fork_node_idx = -1;
|
||||
int first_fork_node_idx = -1;
|
||||
int last_fork_node_idx = -1;
|
||||
|
||||
const ore::Array<const u16> forks{event.fork_event_indices.Get(), event.num_forks};
|
||||
for (const auto& fork : forks) {
|
||||
last_fork_node_idx = AllocNode();
|
||||
auto& fork_node = GetNode(last_fork_node_idx);
|
||||
fork_node.m_obj = obj;
|
||||
fork_node.m_event_idx = fork;
|
||||
fork_node.m_next_node_idx = node_idx;
|
||||
fork_node.m_idx = prev_fork_node_idx;
|
||||
fork_node.m_state = State::kNotInvoked;
|
||||
if (first_fork_node_idx == -1)
|
||||
first_fork_node_idx = last_fork_node_idx;
|
||||
CopyVariablePack(node, fork_node);
|
||||
prev_fork_node_idx = last_fork_node_idx;
|
||||
}
|
||||
|
||||
GetNode(first_fork_node_idx).m_idx = u16(last_fork_node_idx);
|
||||
return true;
|
||||
} // case ResEvent::EventType::kFork
|
||||
|
||||
case ResEvent::EventType::kJoin: {
|
||||
if (node.m_state != State::kDone)
|
||||
return false;
|
||||
next_event_idx = event.next_event_idx;
|
||||
break;
|
||||
} // case ResEvent::EventType::kJoin
|
||||
|
||||
case ResEvent::EventType::kSubFlow: {
|
||||
bool called;
|
||||
bool valid_parameters;
|
||||
bool tried_invoking = false;
|
||||
switch (node.m_state) {
|
||||
case State::kNotInvoked: {
|
||||
tried_invoking = true;
|
||||
node.m_state = State::kInvoked;
|
||||
|
||||
const ore::StringView sub_flow_flowchart = *event.sub_flow_flowchart.Get();
|
||||
if (!sub_flow_flowchart.empty()) {
|
||||
obj = FindFlowchartObj(sub_flow_flowchart);
|
||||
if (obj == nullptr) {
|
||||
called = false;
|
||||
valid_parameters = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
const int entry_point_idx = obj->GetFlowchart()->entry_point_names.Get()->FindIndex(
|
||||
*event.sub_flow_entry_point.Get());
|
||||
if (entry_point_idx == -1) {
|
||||
called = false;
|
||||
valid_parameters = false;
|
||||
break;
|
||||
}
|
||||
|
||||
const auto& entry_point = obj->GetFlowchart()->entry_points.Get()[entry_point_idx];
|
||||
|
||||
const u16 main_event_idx = entry_point.main_event_idx;
|
||||
if (main_event_idx == 0xffff) {
|
||||
node.m_state = State::kDone;
|
||||
called = false;
|
||||
valid_parameters = true;
|
||||
break;
|
||||
}
|
||||
|
||||
// Optimization: if this is a tail call, we don't need to allocate a new node.
|
||||
if (event.next_event_idx == 0xffff && event.params.Get() == nullptr) {
|
||||
node.m_obj = obj;
|
||||
node.m_event_idx = main_event_idx;
|
||||
node.m_state = State::kNotInvoked;
|
||||
AllocVariablePack(node, entry_point);
|
||||
UpdateNodeCounter(node_idx);
|
||||
} else {
|
||||
const auto sub_flow_node_idx = AllocNode();
|
||||
auto& sub_flow_node = GetNode(sub_flow_node_idx);
|
||||
sub_flow_node.m_obj = obj;
|
||||
sub_flow_node.m_event_idx = main_event_idx;
|
||||
sub_flow_node.m_next_node_idx = node_idx;
|
||||
sub_flow_node.m_idx = sub_flow_node_idx;
|
||||
sub_flow_node.m_state = State::kNotInvoked;
|
||||
AllocVariablePack(sub_flow_node, entry_point);
|
||||
}
|
||||
CallSubFlowCallback(flowchart, &event, SubFlowCallbackType::kEnter);
|
||||
called = true;
|
||||
/// @bug valid_parameters should have been initialized to true here.
|
||||
/// This bug causes LLVM to generate dumb code like
|
||||
/// mov w8, wzr; mov w9, wzr; orr w8, w8, w9 (for the failure cases above)
|
||||
/// or more worryingly:
|
||||
/// mov w8, #1; orr w8, w8, w9
|
||||
/// where w9 is actually undefined!
|
||||
#ifdef AVOID_UB
|
||||
valid_parameters = true;
|
||||
#endif
|
||||
break;
|
||||
} // subflow case State::kNotInvoked
|
||||
case State::kInvoked:
|
||||
return false;
|
||||
case State::kDone:
|
||||
next_event_idx = event.next_event_idx;
|
||||
CallSubFlowCallback(flowchart, &event, SubFlowCallbackType::kLeave);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (tried_invoking)
|
||||
return valid_parameters || called;
|
||||
break;
|
||||
} // case ResEvent::EventType::kSubFlow
|
||||
}
|
||||
|
||||
// We are checking for 0xffff (a 0xffff that comes from the ResEvent data), *not* -1.
|
||||
if (next_event_idx == 0xffff) {
|
||||
bool ready = false;
|
||||
auto* node_2 = &node;
|
||||
if (node.m_idx != node_idx) {
|
||||
do {
|
||||
node_2 = &GetNode(node_2->m_idx);
|
||||
ready |= node_2->m_state != State::kWaiting;
|
||||
} while (node_2->m_idx != node_idx);
|
||||
}
|
||||
|
||||
if (!ready) {
|
||||
if (node.m_next_node_idx != 0xffff)
|
||||
GetNode(node.m_next_node_idx).m_state = State::kDone;
|
||||
|
||||
int next_node_idx = node_idx;
|
||||
int next;
|
||||
do {
|
||||
auto& node_to_free = GetNode(next_node_idx);
|
||||
next = node_to_free.m_idx;
|
||||
FreeVariablePack(node_to_free);
|
||||
node_to_free.Reset();
|
||||
node_to_free.m_next_node_idx = m_next_node_idx;
|
||||
node_to_free.m_state = State::kFree;
|
||||
m_next_node_idx = next_node_idx;
|
||||
--m_num_allocated_nodes;
|
||||
next_node_idx = next;
|
||||
} while (next != node_idx);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (event.type == ResEvent::EventType::kAction) {
|
||||
node.m_state = State::kWaiting;
|
||||
return true;
|
||||
}
|
||||
|
||||
node_2->m_idx = node.m_idx;
|
||||
auto& node_to_free = GetNode(node_idx);
|
||||
FreeVariablePack(node_to_free);
|
||||
node_to_free.Reset();
|
||||
node_to_free.m_next_node_idx = m_next_node_idx;
|
||||
node_to_free.m_state = State::kFree;
|
||||
m_next_node_idx = node_idx;
|
||||
--m_num_allocated_nodes;
|
||||
return true;
|
||||
}
|
||||
|
||||
node.m_event_idx = next_event_idx;
|
||||
node.m_state = State::kNotInvoked;
|
||||
UpdateNodeCounter(node_idx);
|
||||
}
|
||||
}
|
||||
|
||||
ActorBinding* FlowchartContext::TrackBackArgumentActor(int node_idx, const ore::StringView& name) {
|
||||
if (node_idx == -1)
|
||||
return nullptr;
|
||||
|
||||
const ore::ResMetaData* metadata;
|
||||
const MetaDataPack* metadata_pack;
|
||||
const VariablePack* variable_pack;
|
||||
FlowchartObj* obj;
|
||||
const ParamAccessor accessor{this, GetNode(node_idx).GetNextNodeIdx()};
|
||||
const auto real_name =
|
||||
accessor.TrackBackArgument(&metadata, &metadata_pack, &variable_pack, &obj, name);
|
||||
|
||||
if (real_name.empty() || !metadata || !obj)
|
||||
return nullptr;
|
||||
|
||||
const auto* param = metadata->Get(real_name, ore::ResMetaData::DataType::kActorIdentifier);
|
||||
if (!param)
|
||||
return nullptr;
|
||||
|
||||
const ore::StringView actor_name = *param->value.actor.name.Get();
|
||||
const ore::StringView actor_sub_name = *param->value.actor.sub_name.Get();
|
||||
|
||||
auto actor = obj->GetFlowchart()->actors.Get();
|
||||
for (int i = 0; i < int(obj->GetFlowchart()->num_actors); ++i, ++actor) {
|
||||
if (*actor->name.Get() == actor_name && *actor->secondary_name.Get() == actor_sub_name) {
|
||||
if (!actor->argument_name.Get()->empty())
|
||||
return nullptr;
|
||||
return &obj->GetActBinder().GetBindings()[i];
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool FlowchartContext::IsUsing(const ResFlowchart* flowchart) const {
|
||||
auto* obj = FindFlowchartObj(*flowchart->name.Get());
|
||||
return obj && obj->GetActBinder().IsUsed();
|
||||
}
|
||||
|
||||
// NON_MATCHING: if (((state | 4) & 7) != 4) -- extremely weird check
|
||||
bool FlowchartContext::IsPlaying(const ResFlowchart* flowchart) const {
|
||||
int state = 2;
|
||||
for (int i = 0, n = m_nodes.size(); i < n; ++i) {
|
||||
if (m_nodes[i].IsInvalidOrFree()) {
|
||||
state = 4;
|
||||
} else {
|
||||
const auto flowchart_name = ore::StringView(*flowchart->name.Get());
|
||||
const auto node_flowchart_name =
|
||||
ore::StringView(*m_nodes[i].m_obj->GetFlowchart()->name.Get());
|
||||
if (node_flowchart_name == flowchart_name) {
|
||||
state = 1;
|
||||
} else {
|
||||
state = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (((state | 4) & 7) != 4)
|
||||
break;
|
||||
}
|
||||
return state != 2;
|
||||
}
|
||||
|
||||
const ore::Array<ActorBinding>*
|
||||
FlowchartContext::GetUsedResActors(ore::StringView flowchart_name) const {
|
||||
auto* obj = FindFlowchartObj(flowchart_name);
|
||||
if (!obj)
|
||||
return nullptr;
|
||||
return obj->GetActBinder().GetUsedResActors();
|
||||
}
|
||||
|
||||
/// Recursively checks subflow calls in the specified entry point for missing flowcharts
|
||||
/// or entry points.
|
||||
/// @param result Optional.
|
||||
/// @param visited Visited entry points (one BitArray per flowchart)
|
||||
/// @param flowchart_idx Index of the flowchart to which the entry point belongs.
|
||||
/// @param entry_point_idx Index of the entry point to be checked.
|
||||
/// @returns true on success, false on failure
|
||||
bool CheckSubFlowCalls(FlowchartContext::Builder::BuildResult* result,
|
||||
const ore::IterRange<const ResFlowchart* const*>& flowcharts,
|
||||
ore::Array<ore::BitArray>& visited, int flowchart_idx, int entry_point_idx) {
|
||||
if (visited[flowchart_idx].Test(entry_point_idx))
|
||||
return true;
|
||||
visited[flowchart_idx].Set(entry_point_idx);
|
||||
|
||||
const auto* flowchart = *std::next(flowcharts.begin(), flowchart_idx);
|
||||
const auto entry_point_name =
|
||||
flowchart->entry_point_names.Get()->GetEntries()[1 + entry_point_idx].GetKey();
|
||||
const auto* entry_point = flowchart->GetEntryPoint(entry_point_name);
|
||||
|
||||
for (u16 i = 0; i != entry_point->num_sub_flow_event_indices; ++i) {
|
||||
const auto& event = flowchart->events.Get()[entry_point->sub_flow_event_indices.Get()[i]];
|
||||
ore::StringView sub_flow_flowchart = *event.sub_flow_flowchart.Get();
|
||||
const ore::StringView sub_flow_entry_point = *event.sub_flow_entry_point.Get();
|
||||
|
||||
auto sub_flowchart_idx = flowchart_idx;
|
||||
auto* sub_flowchart_res = flowchart;
|
||||
|
||||
if (!sub_flow_flowchart.empty()) {
|
||||
const auto it =
|
||||
std::find_if(flowcharts.begin(), flowcharts.end(), [=](const ResFlowchart* f) {
|
||||
return sub_flow_flowchart == *f->name.Get();
|
||||
});
|
||||
|
||||
if (it == flowcharts.end()) {
|
||||
if (result) {
|
||||
result->result =
|
||||
FlowchartContext::Builder::BuildResultType::kResFlowchartNotFound;
|
||||
result->missing_flowchart_name = sub_flow_flowchart;
|
||||
result->missing_entry_point_name = {};
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
sub_flowchart_idx = std::distance(flowcharts.begin(), it);
|
||||
sub_flowchart_res = *it;
|
||||
|
||||
} else {
|
||||
sub_flow_flowchart = *flowchart->name.Get();
|
||||
}
|
||||
|
||||
const int sub_entry_point_idx =
|
||||
sub_flowchart_res->entry_point_names.Get()->FindIndex(sub_flow_entry_point);
|
||||
|
||||
if (sub_entry_point_idx == -1) {
|
||||
if (result) {
|
||||
result->result = FlowchartContext::Builder::BuildResultType::kEntryPointNotFound;
|
||||
result->missing_flowchart_name = sub_flow_flowchart;
|
||||
result->missing_entry_point_name = sub_flow_entry_point;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!CheckSubFlowCalls(result, flowcharts, visited, sub_flowchart_idx, sub_entry_point_idx))
|
||||
return false;
|
||||
}
|
||||
|
||||
if (result) {
|
||||
result->result = FlowchartContext::Builder::BuildResultType::kSuccess;
|
||||
result->missing_flowchart_name = {};
|
||||
result->missing_entry_point_name = {};
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool FlowchartContext::Builder::SetEntryPoint(const ore::StringView& flowchart_name,
|
||||
const ore::StringView& entry_point_name) {
|
||||
return SetEntryPoint(nullptr, flowchart_name, entry_point_name);
|
||||
}
|
||||
|
||||
bool FlowchartContext::Builder::SetEntryPoint(BuildResult* result,
|
||||
const ore::StringView& flowchart_name,
|
||||
const ore::StringView& entry_point_name) {
|
||||
const auto* flowchart_it =
|
||||
std::find_if(m_flowcharts.begin(), m_flowcharts.end(), [=](const ResFlowchart* flowchart) {
|
||||
return flowchart_name == *flowchart->name.Get();
|
||||
});
|
||||
|
||||
if (flowchart_it == m_flowcharts.end()) {
|
||||
if (result) {
|
||||
result->result = BuildResultType::kResFlowchartNotFound;
|
||||
result->missing_flowchart_name = flowchart_name;
|
||||
result->missing_entry_point_name = {};
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
const auto entry_point_idx =
|
||||
(*flowchart_it)->entry_point_names.Get()->FindIndex(entry_point_name);
|
||||
|
||||
if (entry_point_idx == -1) {
|
||||
if (result) {
|
||||
result->result = BuildResultType::kEntryPointNotFound;
|
||||
result->missing_flowchart_name = flowchart_name;
|
||||
result->missing_entry_point_name = entry_point_name;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
m_flowchart_idx = std::distance(m_flowcharts.begin(), flowchart_it);
|
||||
m_entry_point_idx = entry_point_idx;
|
||||
if (result) {
|
||||
result->result = BuildResultType::kSuccess;
|
||||
result->missing_flowchart_name = {};
|
||||
result->missing_entry_point_name = {};
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool FlowchartContext::Builder::BuildImpl(BuildResult* result, FlowchartRange flowcharts,
|
||||
FlowchartContext* context, AllocateArg allocate_arg,
|
||||
ore::Buffer flowchart_obj_buffer) {
|
||||
context->m_nodes.Reset();
|
||||
EvflAllocator allocator{allocate_arg};
|
||||
context->m_allocator = allocator;
|
||||
|
||||
const int num_flowcharts = flowcharts.size();
|
||||
|
||||
ore::Array<ore::BitArray> visited_entry_points;
|
||||
visited_entry_points.SetBuffer(num_flowcharts, &allocator);
|
||||
visited_entry_points.UninitializedDefaultConstructElements();
|
||||
|
||||
const auto clean_up_visited_entry_points = [&] {
|
||||
if (auto* data = visited_entry_points.data()) {
|
||||
for (auto it = data; it != data + visited_entry_points.size(); ++it)
|
||||
it->FreeBufferIfNeeded(&allocator);
|
||||
|
||||
visited_entry_points.DestructElements();
|
||||
allocator.Free(data);
|
||||
}
|
||||
};
|
||||
|
||||
for (int i = 0; i < num_flowcharts; ++i) {
|
||||
visited_entry_points[i].AllocateBuffer(&allocator,
|
||||
(flowcharts.begin()[i])->num_entry_points);
|
||||
}
|
||||
|
||||
if (!CheckSubFlowCalls(result, flowcharts, visited_entry_points, m_flowchart_idx,
|
||||
m_entry_point_idx)) {
|
||||
clean_up_visited_entry_points();
|
||||
return false;
|
||||
}
|
||||
|
||||
context->m_objs.ConstructElements(flowchart_obj_buffer);
|
||||
|
||||
for (int i = 0; i < num_flowcharts; ++i) {
|
||||
auto* obj = &context->m_objs[i];
|
||||
FlowchartObj::Builder obj_builder{flowcharts.begin()[i], &visited_entry_points[i]};
|
||||
|
||||
if (!obj_builder.Build(obj, &context->m_allocator, flowcharts)) {
|
||||
clean_up_visited_entry_points();
|
||||
context->m_objs.ClearWithoutFreeing();
|
||||
|
||||
if (result) {
|
||||
const auto* flowchart = flowcharts.begin()[m_flowchart_idx];
|
||||
const ore::StringView name = *flowchart->name.Get();
|
||||
const ore::StringView ep_name = flowchart->GetEntryPointName(m_entry_point_idx);
|
||||
result->result = BuildResultType::kInvalidOperation;
|
||||
result->missing_flowchart_name = name;
|
||||
result->missing_entry_point_name = ep_name;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
context->m_obj_idx = m_flowchart_idx;
|
||||
context->m_active_entry_point_idx = m_entry_point_idx;
|
||||
context->m_nodes.Init(&context->m_allocator, 16);
|
||||
context->m_nodes.Resize(16);
|
||||
context->Clear();
|
||||
clean_up_visited_entry_points();
|
||||
|
||||
if (result) {
|
||||
result->result = BuildResultType::kSuccess;
|
||||
result->missing_flowchart_name = {};
|
||||
result->missing_entry_point_name = {};
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool FlowchartContext::Builder::Build(FlowchartContext* context, AllocateArg allocate_arg) {
|
||||
return Build(nullptr, context, allocate_arg);
|
||||
}
|
||||
|
||||
bool FlowchartContext::Builder::Build(BuildResult* result, FlowchartContext* context,
|
||||
AllocateArg allocate_arg) {
|
||||
context->Dispose();
|
||||
|
||||
EvflAllocator allocator{allocate_arg};
|
||||
|
||||
ore::DynArrayList<const ResFlowchart*> flowcharts{&allocator};
|
||||
flowcharts.Init(&allocator);
|
||||
flowcharts.DeduplicateCopy(m_flowcharts);
|
||||
|
||||
FlowchartRange range{flowcharts};
|
||||
ore::Buffer obj_buffer{};
|
||||
obj_buffer.Allocate<FlowchartObj>(&allocator, flowcharts.size());
|
||||
|
||||
if (!BuildImpl(result, range, context, allocate_arg, obj_buffer)) {
|
||||
obj_buffer.Free(&allocator);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace evfl
|
243
lib/EventFlow/src/evfl/FlowchartObj.cpp
Normal file
243
lib/EventFlow/src/evfl/FlowchartObj.cpp
Normal file
@ -0,0 +1,243 @@
|
||||
#include <algorithm>
|
||||
#include <evfl/Flowchart.h>
|
||||
#include <evfl/ResActor.h>
|
||||
#include <evfl/ResFlowchart.h>
|
||||
#include <ore/Allocator.h>
|
||||
#include <ore/Array.h>
|
||||
#include <ore/BitUtils.h>
|
||||
#include <ore/IterRange.h>
|
||||
#include <ore/ResMetaData.h>
|
||||
#include <ore/Types.h>
|
||||
|
||||
namespace evfl {
|
||||
|
||||
namespace {
|
||||
|
||||
void RegisterBindings(FlowchartObj* obj, ore::BitArray* visited_events, int event_idx) {
|
||||
const ResActor* actors = obj->GetFlowchart()->actors.Get();
|
||||
const ResEvent* events = obj->GetFlowchart()->events.Get();
|
||||
|
||||
while (event_idx != 0xffff && !visited_events->Test(event_idx)) {
|
||||
visited_events->Set(event_idx);
|
||||
const ResEvent& event = events[event_idx];
|
||||
const auto event_type = event.type;
|
||||
|
||||
switch (event_type.mValue) {
|
||||
case ResEvent::EventType::kAction:
|
||||
if (actors[event.actor_idx].argument_name.Get()->empty()) {
|
||||
auto* action = actors[event.actor_idx].actions.Get() + event.actor_action_idx;
|
||||
obj->GetActBinder().RegisterAction(event.actor_idx, action);
|
||||
}
|
||||
break;
|
||||
case ResEvent::EventType::kSwitch:
|
||||
if (actors[event.actor_idx].argument_name.Get()->empty()) {
|
||||
auto* query = actors[event.actor_idx].queries.Get() + event.actor_query_idx;
|
||||
obj->GetActBinder().RegisterQuery(event.actor_idx, query);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// Process the next event.
|
||||
|
||||
switch (event_type) {
|
||||
case ResEvent::EventType::kAction:
|
||||
case ResEvent::EventType::kJoin:
|
||||
case ResEvent::EventType::kSubFlow:
|
||||
event_idx = event.next_event_idx;
|
||||
break;
|
||||
case ResEvent::EventType::kSwitch: {
|
||||
ore::Array<const ResCase> cases{event.cases.Get(), event.num_cases};
|
||||
std::for_each(cases.begin(), cases.end(), [&](const ResCase& case_) {
|
||||
RegisterBindings(obj, visited_events, case_.event_idx);
|
||||
});
|
||||
return;
|
||||
}
|
||||
case ResEvent::EventType::kFork: {
|
||||
ore::Array<const u16> forks{event.fork_event_indices.Get(), event.num_forks};
|
||||
std::for_each(forks.begin(), forks.end(),
|
||||
[&](u16 fork) { RegisterBindings(obj, visited_events, fork); });
|
||||
event_idx = event.join_event_idx;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct ActorArgumentInfo {
|
||||
bool operator==(const ActorArgumentInfo& rhs) const {
|
||||
return entry_point_idx == rhs.entry_point_idx && flowchart == rhs.flowchart &&
|
||||
rhs.GetActorArgumentName() == GetActorArgumentName();
|
||||
}
|
||||
bool operator!=(const ActorArgumentInfo& rhs) const { return !(*this == rhs); }
|
||||
|
||||
ore::StringView GetActorArgumentName() const {
|
||||
return ore::StringView(actor_argument_name, actor_argument_name_len);
|
||||
}
|
||||
|
||||
const ResFlowchart* flowchart;
|
||||
int entry_point_idx;
|
||||
const char* actor_argument_name;
|
||||
size_t actor_argument_name_len;
|
||||
};
|
||||
|
||||
// NON_MATCHING: the if checks are reordered to hell for some reason
|
||||
const ResActor* FindActor(const ActorArgumentInfo& entry) {
|
||||
ore::Array<const ResActor> actors{entry.flowchart->actors.Get(), entry.flowchart->num_actors};
|
||||
for (const auto& actor : actors) {
|
||||
if (actor.entry_point_idx != entry.entry_point_idx)
|
||||
continue;
|
||||
if (actor.argument_name.Get()->empty())
|
||||
continue;
|
||||
if (*actor.argument_name.Get() != entry.GetActorArgumentName())
|
||||
continue;
|
||||
return &actor;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void RegisterBindingsForArguments(ActBinder& binder, int actor_idx,
|
||||
const ore::IterRange<const ResFlowchart* const*>& flowcharts,
|
||||
ore::ArrayListBase<ActorArgumentInfo>& processed,
|
||||
const ActorArgumentInfo& entry) {
|
||||
if (std::find(processed.begin(), processed.end(), entry) != processed.end())
|
||||
return;
|
||||
|
||||
processed.emplace_back(entry);
|
||||
|
||||
if (auto* actor = FindActor(entry)) {
|
||||
ore::Array<const ResAction> actions{actor->actions.Get(), actor->num_actions};
|
||||
for (const auto& action : actions)
|
||||
binder.RegisterAction(actor_idx, &action);
|
||||
|
||||
ore::Array<const ResQuery> queries{actor->queries.Get(), actor->num_queries};
|
||||
for (const auto& query : queries)
|
||||
binder.RegisterQuery(actor_idx, &query);
|
||||
}
|
||||
|
||||
const auto& entry_point = entry.flowchart->entry_points.Get()[entry.entry_point_idx];
|
||||
ore::Array<const u16> sub_flow_event_indices{entry_point.sub_flow_event_indices.Get(),
|
||||
entry_point.num_sub_flow_event_indices};
|
||||
for (auto sub_flow_event_idx : sub_flow_event_indices) {
|
||||
const auto& event = entry.flowchart->events.Get()[sub_flow_event_idx];
|
||||
const ore::StringView sub_flow_flowchart = *event.sub_flow_flowchart.Get();
|
||||
const ore::StringView sub_flow_entry_point = *event.sub_flow_entry_point.Get();
|
||||
|
||||
auto* params = event.params.Get();
|
||||
if (!params)
|
||||
continue;
|
||||
|
||||
for (int i = 0; i < params->num_items; ++i) {
|
||||
auto* param = (¶ms->value.container + i)->Get();
|
||||
if (param->type != ore::ResMetaData::DataType::kArgument)
|
||||
continue;
|
||||
if (entry.GetActorArgumentName() != *param->value.str.Get())
|
||||
continue;
|
||||
|
||||
const ResFlowchart* flowchart = entry.flowchart;
|
||||
if (!sub_flow_flowchart.empty()) {
|
||||
flowchart =
|
||||
*std::find_if(flowcharts.begin(), flowcharts.end(), [=](const ResFlowchart* f) {
|
||||
return sub_flow_flowchart == *f->name.Get();
|
||||
});
|
||||
}
|
||||
|
||||
const auto entry_point_idx =
|
||||
flowchart->entry_point_names.Get()->FindIndex(sub_flow_entry_point);
|
||||
const auto actor_argument_name = params->dictionary.Get()->GetEntries()[1 + i].GetKey();
|
||||
|
||||
ActorArgumentInfo arg;
|
||||
arg.flowchart = flowchart;
|
||||
arg.entry_point_idx = entry_point_idx;
|
||||
arg.actor_argument_name = actor_argument_name.data();
|
||||
arg.actor_argument_name_len = actor_argument_name.size();
|
||||
RegisterBindingsForArguments(binder, actor_idx, flowcharts, processed, arg);
|
||||
}
|
||||
}
|
||||
|
||||
processed.pop_back();
|
||||
}
|
||||
|
||||
void RegisterBindingsForActorIdentifiers(FlowchartObj* obj,
|
||||
ore::IterRange<const ResFlowchart* const*> flowcharts,
|
||||
int entry_point_idx) {
|
||||
auto* flowchart = obj->GetFlowchart();
|
||||
const auto& entry_point = flowchart->entry_points.Get()[entry_point_idx];
|
||||
|
||||
ore::IterRange<const u16*> sub_flow_event_indices{entry_point.sub_flow_event_indices.Get(),
|
||||
entry_point.num_sub_flow_event_indices};
|
||||
const ResEvent* events = flowchart->events.Get();
|
||||
ore::IterRange<const ResActor*> actors{flowchart->actors.Get(), flowchart->num_actors};
|
||||
|
||||
for (auto sub_flow_event_idx : sub_flow_event_indices) {
|
||||
const auto& event = events[sub_flow_event_idx];
|
||||
|
||||
auto* params = event.params.Get();
|
||||
if (!params)
|
||||
continue;
|
||||
|
||||
const ore::StringView sub_flow_flowchart = *event.sub_flow_flowchart.Get();
|
||||
const ore::StringView sub_flow_entry_point = *event.sub_flow_entry_point.Get();
|
||||
const ResFlowchart* arg_flowchart = flowchart;
|
||||
if (!sub_flow_flowchart.empty()) {
|
||||
arg_flowchart =
|
||||
*std::find_if(flowcharts.begin(), flowcharts.end(), [=](const ResFlowchart* f) {
|
||||
return sub_flow_flowchart == *f->name.Get();
|
||||
});
|
||||
}
|
||||
|
||||
for (int i = 0; i < params->num_items; ++i) {
|
||||
auto* param = (¶ms->value.container + i)->Get();
|
||||
if (param->type != ore::ResMetaData::DataType::kActorIdentifier)
|
||||
continue;
|
||||
|
||||
const ore::StringView param_name =
|
||||
params->dictionary.Get()->GetEntries()[1 + i].GetKey();
|
||||
const ore::StringView name = *param->value.actor.name.Get();
|
||||
const ore::StringView sub_name = *param->value.actor.sub_name.Get();
|
||||
auto* actor = std::find_if(actors.begin(), actors.end(), [&](const ResActor& a) {
|
||||
return name == *a.name.Get() && sub_name == *a.secondary_name.Get();
|
||||
});
|
||||
const int actor_idx = std::distance(actors.begin(), actor);
|
||||
const int arg_entry_point_idx =
|
||||
arg_flowchart->entry_point_names.Get()->FindIndex(sub_flow_entry_point);
|
||||
|
||||
ore::FixedArrayList<ActorArgumentInfo, 64> processed;
|
||||
ActorArgumentInfo arg;
|
||||
arg.flowchart = arg_flowchart;
|
||||
arg.entry_point_idx = arg_entry_point_idx;
|
||||
arg.actor_argument_name = param_name.data();
|
||||
arg.actor_argument_name_len = param_name.size();
|
||||
RegisterBindingsForArguments(obj->GetActBinder(), actor_idx, flowcharts, processed,
|
||||
arg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
bool FlowchartObj::Builder::Build(FlowchartObj* obj, ore::Allocator* allocator,
|
||||
ore::IterRange<const ResFlowchart* const*> flowcharts) {
|
||||
obj->m_flowchart = m_flowchart;
|
||||
m_act_binder_builder.Build(&obj->GetActBinder(), allocator,
|
||||
{m_flowchart->actors.Get(), m_flowchart->num_actors});
|
||||
|
||||
const int num_events = m_flowchart->num_events;
|
||||
ore::BitArray visited_events{allocator, num_events};
|
||||
|
||||
auto* entry_points = obj->m_flowchart->entry_points.Get();
|
||||
auto entry_point_it = m_entry_points_mask->BeginTest();
|
||||
const auto entry_point_end = m_entry_points_mask->EndTest();
|
||||
while (entry_point_it != entry_point_end) {
|
||||
RegisterBindings(obj, &visited_events, entry_points[*entry_point_it].main_event_idx);
|
||||
RegisterBindingsForActorIdentifiers(obj, flowcharts, *entry_point_it);
|
||||
obj->GetActBinder().SetIsUsed();
|
||||
++entry_point_it;
|
||||
}
|
||||
|
||||
visited_events.FreeBuffer(allocator);
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace evfl
|
714
lib/EventFlow/src/evfl/Param.cpp
Normal file
714
lib/EventFlow/src/evfl/Param.cpp
Normal file
@ -0,0 +1,714 @@
|
||||
#include <algorithm>
|
||||
#include <evfl/Flowchart.h>
|
||||
#include <evfl/Param.h>
|
||||
#include <evfl/ResFlowchart.h>
|
||||
#include <ore/BinaryFile.h>
|
||||
#include <ore/ResDic.h>
|
||||
|
||||
namespace evfl {
|
||||
|
||||
namespace {
|
||||
|
||||
constexpr ore::ResMetaData::DataType::Type
|
||||
ConvertMetaDataPackTypeToMDType(MetaDataPack::DataType::Type type) {
|
||||
if (u32(type) < u32(MetaDataPack::DataType::Invalid()))
|
||||
return ore::ResMetaData::DataType::Type(ore::ResMetaData::DataType::kInt + type);
|
||||
|
||||
#ifdef MATCHING_HACK_NX_CLANG
|
||||
// Force a branch to be generated (instead of CSEL)
|
||||
__builtin_assume(type >= 0);
|
||||
#endif
|
||||
return ore::ResMetaData::DataType::Invalid();
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
void MetaDataPack::AddInt(const char* key, int value) {
|
||||
auto& entry = AddEntry();
|
||||
entry.key = key;
|
||||
entry.value.i = value;
|
||||
entry.type = DataType::kInt;
|
||||
}
|
||||
|
||||
// NON_MATCHING: ???
|
||||
void MetaDataPack::AddBool(const char* key, bool value) {
|
||||
auto& entry = AddEntry();
|
||||
entry.key = key;
|
||||
entry.value.i = value;
|
||||
entry.type = DataType::kBool;
|
||||
}
|
||||
|
||||
void MetaDataPack::AddFloat(const char* key, float value) {
|
||||
auto& entry = AddEntry();
|
||||
entry.key = key;
|
||||
entry.value.f = value;
|
||||
entry.type = DataType::kFloat;
|
||||
}
|
||||
|
||||
void MetaDataPack::AddStringPtr(const char* key, const char* value) {
|
||||
auto& entry = AddEntry();
|
||||
entry.key = key;
|
||||
entry.value.str = value;
|
||||
entry.type = DataType::kString;
|
||||
}
|
||||
|
||||
void MetaDataPack::AddWStringPtr(const char* key, const wchar_t* value) {
|
||||
auto& entry = AddEntry();
|
||||
entry.key = key;
|
||||
entry.value.wstr = value;
|
||||
entry.type = DataType::kWString;
|
||||
}
|
||||
|
||||
MetaDataPack::Entry* MetaDataPack::Find(const ore::StringView& key) const {
|
||||
for (auto& entry : GetEntries()) {
|
||||
if (entry.IsKey(key))
|
||||
return &entry;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool MetaDataPack::FindInt(int* value, const ore::StringView& key) const {
|
||||
auto* entry = Find(key);
|
||||
if (!entry || entry->type != DataType::kInt)
|
||||
return false;
|
||||
*value = entry->value.i;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MetaDataPack::FindBool(bool* value, const ore::StringView& key) const {
|
||||
auto* entry = Find(key);
|
||||
if (!entry || entry->type != DataType::kBool)
|
||||
return false;
|
||||
*value = entry->value.i == 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MetaDataPack::FindFloat(float* value, const ore::StringView& key) const {
|
||||
auto* entry = Find(key);
|
||||
if (!entry || entry->type != DataType::kFloat)
|
||||
return false;
|
||||
*value = entry->value.f;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MetaDataPack::FindString(ore::StringView* value, const ore::StringView& key) const {
|
||||
auto* entry = Find(key);
|
||||
if (!entry || entry->type != DataType::kString)
|
||||
return false;
|
||||
*value = entry->value.str;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MetaDataPack::FindWString(ore::WStringView* value, const ore::StringView& key) const {
|
||||
auto* entry = Find(key);
|
||||
if (!entry || entry->type != DataType::kWString)
|
||||
return false;
|
||||
*value = entry->value.wstr;
|
||||
return true;
|
||||
}
|
||||
|
||||
ore::ResMetaData::DataType::Type MetaDataPack::GetType(const ore::StringView& key) const {
|
||||
auto* entry = Find(key);
|
||||
return ConvertMetaDataPackTypeToMDType(entry ? entry->type : DataType::Invalid());
|
||||
}
|
||||
|
||||
// NON_MATCHING: two add operands swapped
|
||||
void MetaDataPack::Builder::CalcMemSize() {
|
||||
m_entries_byte_size = sizeof(Entry) * m_num_entries;
|
||||
m_required_size = 0;
|
||||
m_alignment_real = 16;
|
||||
if (m_num_entries != 0) {
|
||||
m_alignment_real = std::max(16, m_alignment);
|
||||
m_buffer_offset = ore::AlignUpToPowerOf2(_14, m_alignment) - _14;
|
||||
m_required_size = m_buffer_offset + m_entries_byte_size;
|
||||
}
|
||||
}
|
||||
|
||||
bool MetaDataPack::Builder::Build(MetaDataPack* pack, ore::Buffer buffer) {
|
||||
if (m_alignment_real <= 0)
|
||||
return false;
|
||||
if (m_required_size > buffer.size)
|
||||
return false;
|
||||
pack->m_buffer.data = buffer.data;
|
||||
pack->m_buffer.size = buffer.size;
|
||||
const int byte_size = m_entries_byte_size;
|
||||
pack->m_entries = reinterpret_cast<Entry*>(buffer.data + m_buffer_offset);
|
||||
pack->m_entries_capacity = byte_size / int(sizeof(Entry));
|
||||
pack->m_entries_num = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
ParamAccessor::ParamAccessor(const ore::ResMetaData* metadata) : m_metadata(metadata) {}
|
||||
|
||||
ParamAccessor::ParamAccessor(const FlowchartContext* context, int node_idx)
|
||||
: m_context(context), m_node_idx(node_idx) {
|
||||
m_node_counter = context->GetNode(node_idx).GetNodeCounter();
|
||||
}
|
||||
|
||||
const ore::ResMetaData* ParamAccessor::GetFrontResMetaData() const {
|
||||
if (m_node_idx == -1)
|
||||
return m_metadata;
|
||||
|
||||
const auto& node = m_context->GetNode(m_node_idx);
|
||||
const auto& event = node.GetObj()->GetFlowchart()->events.Get()[node.GetEventIdx()];
|
||||
return event.params.Get();
|
||||
}
|
||||
|
||||
int ParamAccessor::GetParamCount() const {
|
||||
auto* meta = GetFrontResMetaData();
|
||||
return meta ? meta->num_items : 0;
|
||||
}
|
||||
|
||||
ore::StringView ParamAccessor::GetParamName(int idx) const {
|
||||
auto* meta = GetFrontResMetaData();
|
||||
return meta->dictionary.Get()->GetEntries()[1 + idx].GetKey();
|
||||
}
|
||||
|
||||
ParamAccessor::Type ParamAccessor::GetParamType(int idx) const {
|
||||
Type type = ore::ResMetaData::DataType::Invalid();
|
||||
|
||||
const ore::ResMetaData* metadata;
|
||||
const MetaDataPack* metadata_pack;
|
||||
const VariablePack* variable_pack;
|
||||
const auto param_name = GetParamName(idx);
|
||||
const auto real_name =
|
||||
TrackBackArgument(&metadata, &metadata_pack, &variable_pack, nullptr, param_name);
|
||||
|
||||
if (metadata) {
|
||||
const int entry_idx = metadata->dictionary.Get()->FindIndex(real_name);
|
||||
if (entry_idx == -1)
|
||||
return ore::ResMetaData::DataType::Invalid();
|
||||
type = (&metadata->value.container + entry_idx)->Get()->type;
|
||||
} else if (variable_pack) {
|
||||
type = variable_pack->GetVariableType(real_name);
|
||||
} else if (metadata_pack) {
|
||||
type = metadata_pack->GetType(real_name);
|
||||
}
|
||||
|
||||
if (type == ore::ResMetaData::DataType::Invalid())
|
||||
return ore::ResMetaData::DataType::Invalid();
|
||||
|
||||
return type;
|
||||
}
|
||||
|
||||
ore::StringView ParamAccessor::TrackBackArgument(const ore::ResMetaData** out_metadata,
|
||||
const MetaDataPack** out_metadata_pack,
|
||||
const VariablePack** out_variable_pack,
|
||||
FlowchartObj** out_obj,
|
||||
const ore::StringView& argument) const {
|
||||
*out_metadata = nullptr;
|
||||
*out_metadata_pack = nullptr;
|
||||
*out_variable_pack = nullptr;
|
||||
if (out_obj)
|
||||
*out_obj = nullptr;
|
||||
|
||||
if (m_node_idx == -1) {
|
||||
*out_metadata = m_metadata;
|
||||
return argument;
|
||||
}
|
||||
|
||||
auto ret = argument;
|
||||
|
||||
for (int i = m_node_idx; i != 0xffff; i = m_context->GetNode(i).GetNextNodeIdx()) {
|
||||
const auto& node = m_context->GetNode(i);
|
||||
const auto* variable_pack = node.GetVariablePack();
|
||||
const auto* events = node.GetObj()->GetFlowchart()->events.Get();
|
||||
const auto& event = events[node.GetEventIdx()];
|
||||
|
||||
if (!((event.type == ResEvent::EventType::kAction && i == m_node_idx) ||
|
||||
(event.type == ResEvent::EventType::kSwitch && i == m_node_idx) ||
|
||||
event.type == ResEvent::EventType::kSubFlow)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const auto* params = event.params.Get();
|
||||
if (!params)
|
||||
return {};
|
||||
|
||||
const auto* param = params->Get(ret, Type::kArgument);
|
||||
if (param) {
|
||||
ret = *param->value.str.Get();
|
||||
if (variable_pack && variable_pack->Contains(ret)) {
|
||||
*out_variable_pack = variable_pack;
|
||||
return ret;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
*out_metadata = params;
|
||||
if (out_obj)
|
||||
*out_obj = node.GetObj();
|
||||
return ret;
|
||||
}
|
||||
|
||||
*out_metadata_pack = m_context->GetMetaDataPack();
|
||||
if (*out_metadata_pack == nullptr)
|
||||
return {};
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ParamAccessor::GetInt(int idx) const {
|
||||
int value;
|
||||
FindInt(&value, GetParamName(idx));
|
||||
return value;
|
||||
}
|
||||
|
||||
bool ParamAccessor::FindInt(int* value, const ore::StringView& name) const {
|
||||
const ore::ResMetaData* metadata;
|
||||
const MetaDataPack* metadata_pack;
|
||||
const VariablePack* variable_pack;
|
||||
const auto real_name =
|
||||
TrackBackArgument(&metadata, &metadata_pack, &variable_pack, nullptr, name);
|
||||
|
||||
if (metadata) {
|
||||
const auto* entry = metadata->Get(real_name, Type::kInt);
|
||||
if (entry != nullptr) {
|
||||
*value = entry->value.i;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (variable_pack && variable_pack->FindInt(value, real_name))
|
||||
return true;
|
||||
|
||||
if (metadata_pack && metadata_pack->FindInt(value, real_name))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ParamAccessor::GetBool(int idx) const {
|
||||
bool value;
|
||||
FindBool(&value, GetParamName(idx));
|
||||
return value;
|
||||
}
|
||||
|
||||
bool ParamAccessor::FindBool(bool* value, const ore::StringView& name) const {
|
||||
const ore::ResMetaData* metadata;
|
||||
const MetaDataPack* metadata_pack;
|
||||
const VariablePack* variable_pack;
|
||||
const auto real_name =
|
||||
TrackBackArgument(&metadata, &metadata_pack, &variable_pack, nullptr, name);
|
||||
|
||||
if (metadata) {
|
||||
const auto* entry = metadata->Get(real_name, Type::kBool);
|
||||
if (entry != nullptr) {
|
||||
*value = entry->value.i != 0;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (variable_pack && variable_pack->FindBool(value, real_name))
|
||||
return true;
|
||||
|
||||
if (metadata_pack && metadata_pack->FindBool(value, real_name))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
float ParamAccessor::GetFloat(int idx) const {
|
||||
float value;
|
||||
FindFloat(&value, GetParamName(idx));
|
||||
return value;
|
||||
}
|
||||
|
||||
bool ParamAccessor::FindFloat(float* value, const ore::StringView& name) const {
|
||||
const ore::ResMetaData* metadata;
|
||||
const MetaDataPack* metadata_pack;
|
||||
const VariablePack* variable_pack;
|
||||
const auto real_name =
|
||||
TrackBackArgument(&metadata, &metadata_pack, &variable_pack, nullptr, name);
|
||||
|
||||
if (metadata) {
|
||||
const auto* entry = metadata->Get(real_name, Type::kFloat);
|
||||
if (entry != nullptr) {
|
||||
*value = entry->value.f;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (variable_pack && variable_pack->FindFloat(value, real_name))
|
||||
return true;
|
||||
|
||||
if (metadata_pack && metadata_pack->FindFloat(value, real_name))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
ore::StringView ParamAccessor::GetString(int idx) const {
|
||||
ore::StringView value;
|
||||
FindString(&value, GetParamName(idx));
|
||||
return value;
|
||||
}
|
||||
|
||||
bool ParamAccessor::FindString(ore::StringView* value, const ore::StringView& name) const {
|
||||
const ore::ResMetaData* metadata;
|
||||
const MetaDataPack* metadata_pack;
|
||||
const VariablePack* variable_pack;
|
||||
const auto real_name =
|
||||
TrackBackArgument(&metadata, &metadata_pack, &variable_pack, nullptr, name);
|
||||
|
||||
if (metadata) {
|
||||
const auto* entry = metadata->Get(real_name, Type::kString);
|
||||
if (entry) {
|
||||
*value = *entry->value.str.Get();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
if (metadata_pack)
|
||||
return metadata_pack->FindString(value, real_name);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
ore::WStringView ParamAccessor::GetWString(int idx) const {
|
||||
ore::WStringView value;
|
||||
FindWString(&value, GetParamName(idx));
|
||||
return value;
|
||||
}
|
||||
|
||||
bool ParamAccessor::FindWString(ore::WStringView* value, const ore::StringView& name) const {
|
||||
const ore::ResMetaData* metadata;
|
||||
const MetaDataPack* metadata_pack;
|
||||
const VariablePack* variable_pack;
|
||||
const auto real_name =
|
||||
TrackBackArgument(&metadata, &metadata_pack, &variable_pack, nullptr, name);
|
||||
|
||||
if (metadata) {
|
||||
const auto* entry = metadata->Get(real_name, Type::kWString);
|
||||
if (entry) {
|
||||
*value = *entry->value.wstr.Get();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
if (metadata_pack)
|
||||
return metadata_pack->FindWString(value, real_name);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
ParamAccessor::IntRange ParamAccessor::GetIntArray(int idx) const {
|
||||
IntRange value;
|
||||
FindIntArray(&value, GetParamName(idx));
|
||||
return value;
|
||||
}
|
||||
|
||||
bool ParamAccessor::FindIntArray(ParamAccessor::IntRange* value,
|
||||
const ore::StringView& name) const {
|
||||
const ore::ResMetaData* metadata;
|
||||
const MetaDataPack* metadata_pack;
|
||||
const VariablePack* variable_pack;
|
||||
const auto real_name =
|
||||
TrackBackArgument(&metadata, &metadata_pack, &variable_pack, nullptr, name);
|
||||
|
||||
if (metadata) {
|
||||
const auto* entry = metadata->Get(real_name, Type::kIntArray);
|
||||
if (entry) {
|
||||
*value = IntRange{&entry->value.i, entry->num_items};
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (variable_pack) {
|
||||
ore::DynArrayList<int>* list;
|
||||
if (variable_pack->FindIntList(&list, real_name)) {
|
||||
*value = IntRange{*list};
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
ParamAccessor::FloatRange ParamAccessor::GetFloatArray(int idx) const {
|
||||
FloatRange value;
|
||||
FindFloatArray(&value, GetParamName(idx));
|
||||
return value;
|
||||
}
|
||||
|
||||
bool ParamAccessor::FindFloatArray(ParamAccessor::FloatRange* value,
|
||||
const ore::StringView& name) const {
|
||||
const ore::ResMetaData* metadata;
|
||||
const MetaDataPack* metadata_pack;
|
||||
const VariablePack* variable_pack;
|
||||
const auto real_name =
|
||||
TrackBackArgument(&metadata, &metadata_pack, &variable_pack, nullptr, name);
|
||||
|
||||
if (metadata) {
|
||||
const auto* entry = metadata->Get(real_name, Type::kFloatArray);
|
||||
if (entry) {
|
||||
*value = FloatRange{&entry->value.f, entry->num_items};
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (variable_pack) {
|
||||
ore::DynArrayList<float>* list;
|
||||
if (variable_pack->FindFloatList(&list, real_name)) {
|
||||
*value = FloatRange{*list};
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
ParamAccessor::StringRange ParamAccessor::GetStringArray(int idx) const {
|
||||
StringRange value;
|
||||
FindStringArray(&value, GetParamName(idx));
|
||||
return value;
|
||||
}
|
||||
|
||||
bool ParamAccessor::FindStringArray(ParamAccessor::StringRange* value,
|
||||
const ore::StringView& name) const {
|
||||
const ore::ResMetaData* metadata;
|
||||
const MetaDataPack* metadata_pack;
|
||||
const VariablePack* variable_pack;
|
||||
const auto real_name =
|
||||
TrackBackArgument(&metadata, &metadata_pack, &variable_pack, nullptr, name);
|
||||
|
||||
if (metadata) {
|
||||
const auto* entry = metadata->Get(real_name, Type::kStringArray);
|
||||
if (entry) {
|
||||
*value = StringRange{&entry->value.str, entry->num_items};
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
ParamAccessor::WStringRange ParamAccessor::GetWStringArray(int idx) const {
|
||||
WStringRange value;
|
||||
FindWStringArray(&value, GetParamName(idx));
|
||||
return value;
|
||||
}
|
||||
|
||||
bool ParamAccessor::FindWStringArray(ParamAccessor::WStringRange* value,
|
||||
const ore::StringView& name) const {
|
||||
const ore::ResMetaData* metadata;
|
||||
const MetaDataPack* metadata_pack;
|
||||
const VariablePack* variable_pack;
|
||||
const auto real_name =
|
||||
TrackBackArgument(&metadata, &metadata_pack, &variable_pack, nullptr, name);
|
||||
|
||||
if (metadata) {
|
||||
const auto* entry = metadata->Get(real_name, Type::kWStringArray);
|
||||
if (entry) {
|
||||
*value = WStringRange{&entry->value.wstr, entry->num_items};
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
VariablePack::VariableType VariablePack::GetVariableType(const ore::StringView& name) const {
|
||||
if (!Contains(name))
|
||||
return ore::ResMetaData::DataType::Invalid();
|
||||
return GetVariableEntry(name)->type;
|
||||
}
|
||||
|
||||
bool VariablePack::FindInt(int* value, const ore::StringView& name) const {
|
||||
if (GetVariableType(name) != ore::ResMetaData::DataType::kInt)
|
||||
return false;
|
||||
*value = GetVariableEntry(name)->value.i;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool VariablePack::FindBool(bool* value, const ore::StringView& name) const {
|
||||
if (GetVariableType(name) != ore::ResMetaData::DataType::kBool)
|
||||
return false;
|
||||
*value = GetVariableEntry(name)->value.i;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool VariablePack::FindFloat(float* value, const ore::StringView& name) const {
|
||||
if (GetVariableType(name) != ore::ResMetaData::DataType::kFloat)
|
||||
return false;
|
||||
*value = GetVariableEntry(name)->value.f;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool VariablePack::FindIntList(ore::DynArrayList<int>** value, const ore::StringView& name) const {
|
||||
if (GetVariableType(name) != ore::ResMetaData::DataType::kIntArray)
|
||||
return false;
|
||||
*value = GetVariableEntry(name)->value.int_array;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool VariablePack::FindFloatList(ore::DynArrayList<float>** value,
|
||||
const ore::StringView& name) const {
|
||||
if (GetVariableType(name) != ore::ResMetaData::DataType::kFloatArray)
|
||||
return false;
|
||||
*value = GetVariableEntry(name)->value.float_array;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ParamAccessor::FindActorIdentifier(ore::StringView* actor_name,
|
||||
ore::StringView* actor_sub_name,
|
||||
const ore::StringView& name) const {
|
||||
const ore::ResMetaData* metadata;
|
||||
const MetaDataPack* metadata_pack;
|
||||
const VariablePack* variable_pack;
|
||||
const auto real_name =
|
||||
TrackBackArgument(&metadata, &metadata_pack, &variable_pack, nullptr, name);
|
||||
|
||||
if (metadata) {
|
||||
const auto* entry = metadata->Get(real_name, Type::kActorIdentifier);
|
||||
if (entry) {
|
||||
*actor_name = *entry->value.actor.name.Get();
|
||||
*actor_sub_name = *entry->value.actor.sub_name.Get();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool VariablePack::Contains(const ore::StringView& name) const {
|
||||
return m_names->FindIndex(name) != -1;
|
||||
}
|
||||
|
||||
VariablePack::VariablePack() = default;
|
||||
|
||||
VariablePack::~VariablePack() {
|
||||
Dispose();
|
||||
}
|
||||
|
||||
void VariablePack::Dispose() {
|
||||
auto* variables = m_variables.data();
|
||||
if (!variables)
|
||||
return;
|
||||
|
||||
for (auto& variable : m_variables) {
|
||||
switch (variable.type) {
|
||||
case ore::ResMetaData::DataType::kIntArray:
|
||||
if (variable.value.int_array)
|
||||
GetAllocator()->DeleteAndNull(variable.value.int_array);
|
||||
break;
|
||||
case ore::ResMetaData::DataType::kFloatArray:
|
||||
if (variable.value.float_array)
|
||||
GetAllocator()->DeleteAndNull(variable.value.float_array);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
GetAllocator()->FreeImpl(variables);
|
||||
}
|
||||
|
||||
void VariablePack::Init(AllocateArg arg, const ResEntryPoint* entry_point) {
|
||||
Dispose();
|
||||
m_names = entry_point->variable_defs_names.Get();
|
||||
m_allocator = evfl::EvflAllocator{arg};
|
||||
m_variables.ConstructElements(m_names->num_entries, GetAllocator());
|
||||
|
||||
const ResVariableDef* def = entry_point->variable_defs.Get();
|
||||
for (auto& variable : m_variables) {
|
||||
variable.type = def->type;
|
||||
variable.value = {};
|
||||
switch (variable.type) {
|
||||
case ore::ResMetaData::DataType::kArgument:
|
||||
case ore::ResMetaData::DataType::kContainer:
|
||||
break;
|
||||
case ore::ResMetaData::DataType::kInt:
|
||||
case ore::ResMetaData::DataType::kBool:
|
||||
variable.value.i = def->value.i;
|
||||
break;
|
||||
case ore::ResMetaData::DataType::kFloat:
|
||||
variable.value.f = def->value.f;
|
||||
break;
|
||||
case ore::ResMetaData::DataType::kString:
|
||||
case ore::ResMetaData::DataType::kWString:
|
||||
break;
|
||||
case ore::ResMetaData::DataType::kIntArray: {
|
||||
variable.value.int_array = GetAllocator()->New<ore::DynArrayList<int>>();
|
||||
variable.value.int_array->Init(GetAllocator(), 2);
|
||||
ore::Array<const int> values{def->value.int_array.Get(), def->num};
|
||||
variable.value.int_array->OverwriteWith(values.begin(), values.end());
|
||||
break;
|
||||
}
|
||||
case ore::ResMetaData::DataType::kBoolArray:
|
||||
break;
|
||||
case ore::ResMetaData::DataType::kFloatArray: {
|
||||
variable.value.float_array = GetAllocator()->New<ore::DynArrayList<float>>();
|
||||
variable.value.float_array->Init(GetAllocator(), 2);
|
||||
ore::Array<const float> values{def->value.float_array.Get(), def->num};
|
||||
variable.value.float_array->OverwriteWith(values.begin(), values.end());
|
||||
break;
|
||||
}
|
||||
case ore::ResMetaData::DataType::kStringArray:
|
||||
case ore::ResMetaData::DataType::kWStringArray:
|
||||
case ore::ResMetaData::DataType::kActorIdentifier:
|
||||
break;
|
||||
}
|
||||
++def;
|
||||
}
|
||||
}
|
||||
|
||||
const VariablePack::Entry* VariablePack::GetVariableEntry(const ore::StringView& name) const {
|
||||
return &m_variables[m_names->FindIndex(name)];
|
||||
}
|
||||
|
||||
ore::StringView VariablePack::GetVariableName(int idx) const {
|
||||
return *m_names->GetEntries()[1 + idx].name.Get();
|
||||
}
|
||||
|
||||
int VariablePack::GetVariableCount() const {
|
||||
return m_names->num_entries;
|
||||
}
|
||||
|
||||
VariablePack::Entry* VariablePack::GetVariableEntry(const ore::StringView& name) {
|
||||
return &m_variables[m_names->FindIndex(name)];
|
||||
}
|
||||
|
||||
void VariablePack::SetInt(const ore::StringView& name, int value) {
|
||||
m_variables[m_names->FindIndex(name)].value.i = value;
|
||||
}
|
||||
|
||||
void VariablePack::SetFloat(const ore::StringView& name, float value) {
|
||||
m_variables[m_names->FindIndex(name)].value.f = value;
|
||||
}
|
||||
|
||||
void VariablePack::SetBool(const ore::StringView& name, bool value) {
|
||||
m_variables[m_names->FindIndex(name)].value.i = value;
|
||||
}
|
||||
|
||||
int VariablePack::GetInt(const ore::StringView& name) const {
|
||||
int value;
|
||||
FindInt(&value, name);
|
||||
return value;
|
||||
}
|
||||
|
||||
bool VariablePack::GetBool(const ore::StringView& name) const {
|
||||
bool value;
|
||||
FindBool(&value, name);
|
||||
return value;
|
||||
}
|
||||
|
||||
float VariablePack::GetFloat(const ore::StringView& name) const {
|
||||
float value;
|
||||
FindFloat(&value, name);
|
||||
return value;
|
||||
}
|
||||
|
||||
ore::DynArrayList<int>* VariablePack::GetIntList(const ore::StringView& name) const {
|
||||
ore::DynArrayList<int>* value;
|
||||
FindIntList(&value, name);
|
||||
return value;
|
||||
}
|
||||
|
||||
ore::DynArrayList<float>* VariablePack::GetFloatList(const ore::StringView& name) const {
|
||||
ore::DynArrayList<float>* value;
|
||||
FindFloatList(&value, name);
|
||||
return value;
|
||||
}
|
||||
|
||||
} // namespace evfl
|
89
lib/EventFlow/src/evfl/ResActor.cpp
Normal file
89
lib/EventFlow/src/evfl/ResActor.cpp
Normal file
@ -0,0 +1,89 @@
|
||||
#include <algorithm>
|
||||
#include <evfl/ResActor.h>
|
||||
#include <ore/ResEndian.h>
|
||||
#include <ore/ResMetaData.h>
|
||||
|
||||
namespace evfl {
|
||||
|
||||
void ActorBinding::Register(const ResAction* action) {
|
||||
if (GetAction(*action->name.Get()) != m_actions.end())
|
||||
return;
|
||||
|
||||
Action entry;
|
||||
entry.res_action = action;
|
||||
m_actions.emplace_back(entry);
|
||||
}
|
||||
|
||||
void ActorBinding::Register(const ResQuery* query) {
|
||||
if (GetQuery(*query->name.Get()) != m_queries.end())
|
||||
return;
|
||||
|
||||
Query entry;
|
||||
entry.res_query = query;
|
||||
m_queries.emplace_back(entry);
|
||||
}
|
||||
|
||||
ActorBinding::Action* ActorBinding::GetAction(const ore::StringView& name) {
|
||||
return std::find_if(m_actions.begin(), m_actions.end(), [name](const Action& action) {
|
||||
return name == *action.res_action->name.Get();
|
||||
});
|
||||
}
|
||||
|
||||
const ActorBinding::Action* ActorBinding::GetAction(const ore::StringView& name) const {
|
||||
return std::find_if(m_actions.begin(), m_actions.end(), [name](const Action& action) {
|
||||
return name == *action.res_action->name.Get();
|
||||
});
|
||||
}
|
||||
|
||||
ActorBinding::Query* ActorBinding::GetQuery(const ore::StringView& name) {
|
||||
return std::find_if(m_queries.begin(), m_queries.end(), [name](const Query& query) {
|
||||
return name == *query.res_query->name.Get();
|
||||
});
|
||||
}
|
||||
|
||||
const ActorBinding::Query* ActorBinding::GetQuery(const ore::StringView& name) const {
|
||||
return std::find_if(m_queries.begin(), m_queries.end(), [name](const Query& query) {
|
||||
return name == *query.res_query->name.Get();
|
||||
});
|
||||
}
|
||||
|
||||
bool ActBinder::Builder::Build(evfl::ActBinder* binder, ore::Allocator* allocator,
|
||||
ore::IterRange<const ResActor*> actors) {
|
||||
binder->m_event_used_actor_count = 0;
|
||||
binder->m_allocator = allocator;
|
||||
binder->m_bindings.ConstructElements(actors.size(), allocator);
|
||||
|
||||
auto it = actors.begin();
|
||||
for (int i = 0; i < actors.size(); ++i) {
|
||||
auto& binding = binder->m_bindings[i];
|
||||
binding.m_actor = it;
|
||||
binding.m_actions.Init(binder->m_allocator);
|
||||
binding.m_queries.Init(binder->m_allocator);
|
||||
++it;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
const ore::Array<ActorBinding>* ActBinder::GetUsedResActors() const {
|
||||
return &m_bindings;
|
||||
}
|
||||
|
||||
void SwapEndian(ore::ResEndian* endian, ResActor* actor) {
|
||||
using ore::SwapEndian;
|
||||
if (endian->is_serializing) {
|
||||
if (auto* params = actor->params.ToPtr(endian->base))
|
||||
SwapEndian(endian, params);
|
||||
SwapEndian(&actor->num_actions);
|
||||
SwapEndian(&actor->num_queries);
|
||||
SwapEndian(&actor->entry_point_idx);
|
||||
} else {
|
||||
SwapEndian(&actor->num_actions);
|
||||
SwapEndian(&actor->num_queries);
|
||||
SwapEndian(&actor->entry_point_idx);
|
||||
if (auto* params = actor->params.ToPtr(endian->base))
|
||||
SwapEndian(endian, params);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace evfl
|
112
lib/EventFlow/src/evfl/ResEventFlowFile.cpp
Normal file
112
lib/EventFlow/src/evfl/ResEventFlowFile.cpp
Normal file
@ -0,0 +1,112 @@
|
||||
#include <evfl/ResEventFlowFile.h>
|
||||
#include <evfl/ResFlowchart.h>
|
||||
#include <evfl/ResTimeline.h>
|
||||
#include <ore/Array.h>
|
||||
#include <ore/RelocationTable.h>
|
||||
#include <ore/ResDic.h>
|
||||
#include <ore/ResEndian.h>
|
||||
#include <ore/StringPool.h>
|
||||
#include <string_view>
|
||||
|
||||
namespace evfl {
|
||||
|
||||
using ore::SwapEndian;
|
||||
|
||||
template <typename T>
|
||||
constexpr T MakeMagic(std::string_view magic) {
|
||||
T result = 0;
|
||||
for (size_t i = 0; i < magic.length(); ++i)
|
||||
result |= T(magic[i]) << (8 * i);
|
||||
return result;
|
||||
}
|
||||
|
||||
bool ResEventFlowFile::IsValid(void* data) {
|
||||
return static_cast<ore::BinaryFileHeader*>(data)->IsValid(MakeMagic<u64>("BFEVFL"), 0, 3, 0, 0);
|
||||
}
|
||||
|
||||
ResEventFlowFile* ResEventFlowFile::ResCast(void* data) {
|
||||
auto* file = static_cast<ResEventFlowFile*>(data);
|
||||
file->Relocate();
|
||||
return file;
|
||||
}
|
||||
|
||||
void ResEventFlowFile::Relocate() {
|
||||
if (header.IsRelocated())
|
||||
return;
|
||||
|
||||
auto* table = header.GetRelocationTable();
|
||||
table->Relocate();
|
||||
header.SetRelocated(true);
|
||||
}
|
||||
|
||||
void ResEventFlowFile::Unrelocate() {
|
||||
if (!header.IsRelocated())
|
||||
return;
|
||||
|
||||
auto* table = header.GetRelocationTable();
|
||||
table->Unrelocate();
|
||||
header.SetRelocated(false);
|
||||
}
|
||||
|
||||
static void SwapEndian(ore::ResEndian* endian, ore::StringPool* pool) {
|
||||
ore::BinString* str = pool->GetFirstString();
|
||||
const int num_strings = pool->GetLength();
|
||||
if (endian->is_serializing) {
|
||||
for (int i = 0; i < num_strings; ++i) {
|
||||
auto* next = str->NextString();
|
||||
SwapEndian(&str->length);
|
||||
str = next;
|
||||
}
|
||||
} else {
|
||||
for (int i = 0; i < num_strings; ++i) {
|
||||
SwapEndian(&str->length);
|
||||
str = str->NextString();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static void SwapEndian(ore::ResEndian* endian, ore::BinTPtr<T>* ptr) {
|
||||
if (auto* value = ptr->ToPtr(endian->base))
|
||||
SwapEndian(endian, value);
|
||||
}
|
||||
|
||||
static void SwapEndianForFileData(ore::ResEndian* endian, ResEventFlowFile* file) {
|
||||
ore::Array<ore::BinTPtr<ResFlowchart>> flowcharts{file->flowcharts.ToPtr(endian->base),
|
||||
file->num_flowcharts};
|
||||
for (auto& flowchart : flowcharts)
|
||||
SwapEndian(endian, &flowchart);
|
||||
|
||||
if (auto* flowchart_names = file->flowchart_names.ToPtr(endian->base))
|
||||
SwapEndian(endian, flowchart_names);
|
||||
|
||||
ore::Array<ore::BinTPtr<ResTimeline>> timelines{file->timelines.ToPtr(endian->base),
|
||||
file->num_timelines};
|
||||
for (auto& timeline : timelines)
|
||||
SwapEndian(endian, &timeline);
|
||||
|
||||
if (auto* timeline_names = file->timeline_names.ToPtr(endian->base))
|
||||
SwapEndian(endian, timeline_names);
|
||||
|
||||
auto* string_pool =
|
||||
static_cast<ore::StringPool*>(file->header.FindFirstBlock(MakeMagic<u32>("STR ")));
|
||||
SwapEndian(endian, string_pool);
|
||||
}
|
||||
|
||||
void SwapEndian(ore::ResEndian* endian, ResEventFlowFile* file) {
|
||||
const auto swap_fields = [&] {
|
||||
SwapEndian(&file->header.bom);
|
||||
SwapEndian(&file->num_flowcharts);
|
||||
SwapEndian(&file->num_timelines);
|
||||
};
|
||||
|
||||
if (endian->is_serializing) {
|
||||
SwapEndianForFileData(endian, file);
|
||||
swap_fields();
|
||||
} else {
|
||||
swap_fields();
|
||||
SwapEndianForFileData(endian, file);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace evfl
|
191
lib/EventFlow/src/evfl/ResFlowchart.cpp
Normal file
191
lib/EventFlow/src/evfl/ResFlowchart.cpp
Normal file
@ -0,0 +1,191 @@
|
||||
#include <algorithm>
|
||||
#include <evfl/ResActor.h>
|
||||
#include <evfl/ResFlowchart.h>
|
||||
#include <ore/Array.h>
|
||||
#include <ore/ResDic.h>
|
||||
#include <ore/ResEndian.h>
|
||||
|
||||
namespace evfl {
|
||||
|
||||
using ore::SwapEndian;
|
||||
|
||||
static void SwapEndianForFlowchartData(ore::ResEndian* endian, ResFlowchart* flowchart) {
|
||||
ore::Array<ResActor> actors{flowchart->actors.ToPtr(endian->base), flowchart->num_actors};
|
||||
for (auto& actor : actors)
|
||||
SwapEndian(endian, &actor);
|
||||
|
||||
ore::Array<ResEvent> events{flowchart->events.ToPtr(endian->base), flowchart->num_events};
|
||||
for (auto& event : events)
|
||||
SwapEndian(endian, &event);
|
||||
|
||||
if (auto* names = flowchart->entry_point_names.ToPtr(endian->base))
|
||||
SwapEndian(endian, names);
|
||||
|
||||
ore::Array<ResEntryPoint> entry_points{flowchart->entry_points.ToPtr(endian->base),
|
||||
flowchart->num_entry_points};
|
||||
for (auto& entry : entry_points)
|
||||
SwapEndian(endian, &entry);
|
||||
}
|
||||
|
||||
static void SwapEndianForFlowchartFields(ore::ResEndian* endian, ResFlowchart* flowchart) {
|
||||
SwapEndian(&flowchart->num_actors);
|
||||
SwapEndian(&flowchart->num_actions);
|
||||
SwapEndian(&flowchart->num_queries);
|
||||
SwapEndian(&flowchart->num_events);
|
||||
SwapEndian(&flowchart->num_entry_points);
|
||||
}
|
||||
|
||||
void SwapEndian(ore::ResEndian* endian, ResFlowchart* flowchart) {
|
||||
if (endian->is_serializing) {
|
||||
SwapEndianForFlowchartData(endian, flowchart);
|
||||
SwapEndianForFlowchartFields(endian, flowchart);
|
||||
} else {
|
||||
SwapEndianForFlowchartFields(endian, flowchart);
|
||||
SwapEndianForFlowchartData(endian, flowchart);
|
||||
}
|
||||
}
|
||||
|
||||
int ResFlowchart::CountEvent(ResEvent::EventType::Type type) const {
|
||||
ore::Array<const ResEvent> array{events.Get(), num_events};
|
||||
return std::count_if(array.begin(), array.end(),
|
||||
[type](const ResEvent& event) { return event.type == type; });
|
||||
}
|
||||
|
||||
void SwapEndian(ore::ResEndian* endian, ResCase* case_) {
|
||||
SwapEndian(&case_->event_idx);
|
||||
SwapEndian(&case_->value);
|
||||
}
|
||||
|
||||
static void SwapEndianForEventData(ore::ResEndian* endian, ResEvent* event) {
|
||||
switch (event->type) {
|
||||
case ResEvent::EventType::kAction:
|
||||
if (auto* params = event->params.ToPtr(endian->base))
|
||||
SwapEndian(endian, params);
|
||||
break;
|
||||
case ResEvent::EventType::kSwitch: {
|
||||
ore::Array<ResCase> cases{event->cases.ToPtr(endian->base), event->num_cases};
|
||||
for (auto& case_ : cases)
|
||||
SwapEndian(endian, &case_);
|
||||
if (auto* params = event->params.ToPtr(endian->base))
|
||||
SwapEndian(endian, params);
|
||||
break;
|
||||
}
|
||||
case ResEvent::EventType::kFork: {
|
||||
ore::Array<u16> forks{event->fork_event_indices.ToPtr(endian->base), event->num_forks};
|
||||
for (auto& fork : forks)
|
||||
SwapEndian(&fork);
|
||||
break;
|
||||
}
|
||||
case ResEvent::EventType::kJoin:
|
||||
break;
|
||||
case ResEvent::EventType::kSubFlow:
|
||||
if (auto* params = event->params.ToPtr(endian->base))
|
||||
SwapEndian(endian, params);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void SwapEndianForEventFields(ore::ResEndian* endian, ResEvent* event) {
|
||||
switch (event->type) {
|
||||
case ResEvent::EventType::kAction:
|
||||
SwapEndian(&event->next_event_idx);
|
||||
SwapEndian(&event->actor_idx);
|
||||
SwapEndian(&event->actor_action_idx);
|
||||
break;
|
||||
case ResEvent::EventType::kSwitch:
|
||||
SwapEndian(&event->next_event_idx);
|
||||
SwapEndian(&event->actor_idx);
|
||||
SwapEndian(&event->actor_query_idx);
|
||||
break;
|
||||
case ResEvent::EventType::kFork:
|
||||
SwapEndian(&event->num_forks);
|
||||
SwapEndian(&event->join_event_idx);
|
||||
break;
|
||||
case ResEvent::EventType::kJoin:
|
||||
case ResEvent::EventType::kSubFlow:
|
||||
SwapEndian(&event->next_event_idx);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void SwapEndian(ore::ResEndian* endian, ResEvent* event) {
|
||||
if (endian->is_serializing) {
|
||||
SwapEndianForEventData(endian, event);
|
||||
SwapEndianForEventFields(endian, event);
|
||||
} else {
|
||||
SwapEndianForEventFields(endian, event);
|
||||
SwapEndianForEventData(endian, event);
|
||||
}
|
||||
}
|
||||
|
||||
static void SwapEndianImpl(ore::ResEndian* endian, ResEntryPoint* entry) {
|
||||
ore::Array<u16> sub_flow_event_indices{entry->sub_flow_event_indices.ToPtr(endian->base),
|
||||
entry->num_sub_flow_event_indices};
|
||||
for (auto& x : sub_flow_event_indices)
|
||||
SwapEndian(&x);
|
||||
|
||||
auto* variable_def_names = entry->variable_defs_names.ToPtr(endian->base);
|
||||
if (variable_def_names)
|
||||
SwapEndian(endian, variable_def_names);
|
||||
|
||||
ore::Array<ResVariableDef> variable_defs{entry->variable_defs.ToPtr(endian->base),
|
||||
entry->num_variable_defs};
|
||||
for (auto& def : variable_defs)
|
||||
SwapEndian(endian, &def);
|
||||
}
|
||||
|
||||
void SwapEndian(ore::ResEndian* endian, ResEntryPoint* entry) {
|
||||
if (endian->is_serializing) {
|
||||
SwapEndianImpl(endian, entry);
|
||||
SwapEndian(&entry->main_event_idx);
|
||||
SwapEndian(&entry->num_sub_flow_event_indices);
|
||||
SwapEndian(&entry->num_variable_defs);
|
||||
} else {
|
||||
SwapEndian(&entry->main_event_idx);
|
||||
SwapEndian(&entry->num_sub_flow_event_indices);
|
||||
SwapEndian(&entry->num_variable_defs);
|
||||
SwapEndianImpl(endian, entry);
|
||||
}
|
||||
}
|
||||
|
||||
static void SwapEndianImpl(ore::ResEndian* endian, ResVariableDef* def) {
|
||||
switch (def->type) {
|
||||
case ore::ResMetaData::DataType::kIntArray: {
|
||||
const auto num = def->num;
|
||||
ore::Array<int> array{def->value.int_array.ToPtr(endian->base), num};
|
||||
for (auto& x : array)
|
||||
SwapEndian(&x);
|
||||
break;
|
||||
}
|
||||
case ore::ResMetaData::DataType::kFloatArray: {
|
||||
const auto num = def->num;
|
||||
ore::Array<float> array{def->value.float_array.ToPtr(endian->base), num};
|
||||
for (auto& x : array)
|
||||
SwapEndian(reinterpret_cast<u32*>(&x));
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static bool IsScalarVariableDef(ResVariableDef* def) {
|
||||
using Type = ore::ResMetaData::DataType::Type;
|
||||
return def->type == Type::kInt || def->type == Type::kBool || def->type == Type::kFloat;
|
||||
}
|
||||
|
||||
void SwapEndian(ore::ResEndian* endian, ResVariableDef* def) {
|
||||
if (endian->is_serializing) {
|
||||
SwapEndianImpl(endian, def);
|
||||
SwapEndian(&def->num);
|
||||
if (IsScalarVariableDef(def))
|
||||
SwapEndian(&def->value.i);
|
||||
} else {
|
||||
SwapEndian(&def->num);
|
||||
if (IsScalarVariableDef(def))
|
||||
SwapEndian(&def->value.i);
|
||||
SwapEndianImpl(endian, def);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace evfl
|
118
lib/EventFlow/src/evfl/ResTimeline.cpp
Normal file
118
lib/EventFlow/src/evfl/ResTimeline.cpp
Normal file
@ -0,0 +1,118 @@
|
||||
#include <evfl/ResActor.h>
|
||||
#include <evfl/ResTimeline.h>
|
||||
#include <ore/Array.h>
|
||||
#include <ore/ResEndian.h>
|
||||
#include <ore/ResMetaData.h>
|
||||
|
||||
namespace evfl {
|
||||
|
||||
using ore::SwapEndian;
|
||||
|
||||
void SwapEndian(ore::ResEndian* endian, ResTrigger* trigger) {
|
||||
SwapEndian(&trigger->clip_index);
|
||||
}
|
||||
|
||||
void SwapEndian(ore::ResEndian* endian, ResCut* cut) {
|
||||
if (endian->is_serializing) {
|
||||
if (auto* params = cut->params.ToPtr(endian->base))
|
||||
SwapEndian(endian, params);
|
||||
SwapEndian(&cut->start_time);
|
||||
} else {
|
||||
SwapEndian(&cut->start_time);
|
||||
if (auto* params = cut->params.ToPtr(endian->base))
|
||||
SwapEndian(endian, params);
|
||||
}
|
||||
}
|
||||
|
||||
void SwapEndian(ore::ResEndian* endian, ResClip* clip) {
|
||||
const auto swap_fields = [&] {
|
||||
SwapEndian(&clip->start_time);
|
||||
SwapEndian(&clip->duration);
|
||||
SwapEndian(&clip->actor_index);
|
||||
SwapEndian(&clip->actor_action_index);
|
||||
};
|
||||
|
||||
const auto swap_params = [&] {
|
||||
if (auto* params = clip->params.ToPtr(endian->base))
|
||||
SwapEndian(endian, params);
|
||||
};
|
||||
|
||||
if (endian->is_serializing) {
|
||||
swap_params();
|
||||
swap_fields();
|
||||
} else {
|
||||
swap_fields();
|
||||
swap_params();
|
||||
}
|
||||
}
|
||||
|
||||
void SwapEndian(ore::ResEndian* endian, ResOneshot* oneshot) {
|
||||
const auto swap_fields = [&] {
|
||||
SwapEndian(&oneshot->time);
|
||||
SwapEndian(&oneshot->actor_index);
|
||||
SwapEndian(&oneshot->actor_action_index);
|
||||
};
|
||||
|
||||
const auto swap_params = [&] {
|
||||
if (auto* params = oneshot->params.ToPtr(endian->base))
|
||||
SwapEndian(endian, params);
|
||||
};
|
||||
|
||||
if (endian->is_serializing) {
|
||||
swap_params();
|
||||
swap_fields();
|
||||
} else {
|
||||
swap_fields();
|
||||
swap_params();
|
||||
}
|
||||
}
|
||||
|
||||
void SwapEndian(ore::ResEndian* endian, ResSubtimeline* subtimeline) {}
|
||||
|
||||
static void SwapEndianForTimelineData(ore::ResEndian* endian, ResTimeline* timeline) {
|
||||
ore::Array<ResClip> clips{timeline->clips.ToPtr(endian->base), timeline->num_clips};
|
||||
for (auto& clip : clips)
|
||||
SwapEndian(endian, &clip);
|
||||
|
||||
ore::Array<ResOneshot> oneshots{timeline->oneshots.ToPtr(endian->base), timeline->num_oneshots};
|
||||
for (auto& oneshot : oneshots)
|
||||
SwapEndian(endian, &oneshot);
|
||||
|
||||
ore::Array<ResActor> actors{timeline->actors.ToPtr(endian->base), timeline->num_actors};
|
||||
for (auto& actor : actors)
|
||||
SwapEndian(endian, &actor);
|
||||
|
||||
const int num_triggers = timeline->num_clips * 2;
|
||||
ore::Array<ResTrigger> triggers{timeline->triggers.ToPtr(endian->base), num_triggers};
|
||||
for (auto& trigger : triggers)
|
||||
SwapEndian(endian, &trigger);
|
||||
|
||||
ore::Array<ResCut> cuts{timeline->cuts.ToPtr(endian->base), timeline->num_cuts};
|
||||
for (auto& cut : cuts)
|
||||
SwapEndian(endian, &cut);
|
||||
|
||||
if (auto* params = timeline->params.ToPtr(endian->base))
|
||||
SwapEndian(endian, params);
|
||||
}
|
||||
|
||||
void SwapEndian(ore::ResEndian* endian, ResTimeline* timeline) {
|
||||
const auto swap_fields = [&] {
|
||||
SwapEndian(&timeline->duration);
|
||||
SwapEndian(&timeline->num_actors);
|
||||
SwapEndian(&timeline->num_actions);
|
||||
SwapEndian(&timeline->num_clips);
|
||||
SwapEndian(&timeline->num_oneshots);
|
||||
SwapEndian(&timeline->num_subtimelines);
|
||||
SwapEndian(&timeline->num_cuts);
|
||||
};
|
||||
|
||||
if (endian->is_serializing) {
|
||||
SwapEndianForTimelineData(endian, timeline);
|
||||
swap_fields();
|
||||
} else {
|
||||
swap_fields();
|
||||
SwapEndianForTimelineData(endian, timeline);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace evfl
|
235
lib/EventFlow/src/evfl/TimelineObj.cpp
Normal file
235
lib/EventFlow/src/evfl/TimelineObj.cpp
Normal file
@ -0,0 +1,235 @@
|
||||
#include <evfl/Action.h>
|
||||
#include <evfl/ResActor.h>
|
||||
#include <evfl/ResTimeline.h>
|
||||
#include <evfl/TimelineObj.h>
|
||||
#include <utility>
|
||||
|
||||
namespace evfl {
|
||||
|
||||
int TimelineObj::s_GlobalPlayCounter{};
|
||||
|
||||
// NON_MATCHING: didn't bother matching, clearly equivalent
|
||||
TimelineObj::TimelineObj() = default;
|
||||
|
||||
void TimelineObj::Calc() {
|
||||
CalcImpl();
|
||||
for (auto* timeline : m_sub_timelines) {
|
||||
if (timeline)
|
||||
timeline->Calc();
|
||||
}
|
||||
}
|
||||
|
||||
void TimelineObj::Reset() {
|
||||
m_play_counter = ++s_GlobalPlayCounter;
|
||||
m_started = false;
|
||||
m_state = TimelineState::kNotStarted;
|
||||
for (auto* timeline : m_sub_timelines) {
|
||||
if (timeline)
|
||||
timeline->Reset();
|
||||
}
|
||||
}
|
||||
|
||||
void TimelineObj::SetState(TimelineState::Type state) {
|
||||
m_state = state;
|
||||
}
|
||||
|
||||
void TimelineObj::Start(float start_time) {
|
||||
if (m_started)
|
||||
return;
|
||||
|
||||
m_started = true;
|
||||
m_state = TimelineState::kPlaying;
|
||||
m_time = -1.0;
|
||||
m_last_trigger_idx = -1;
|
||||
m_last_oneshot_idx = -1;
|
||||
JumpTimeTo(start_time);
|
||||
Calc();
|
||||
|
||||
for (auto* timeline : m_sub_timelines) {
|
||||
if (timeline && !timeline->m_started)
|
||||
timeline->Start(start_time);
|
||||
}
|
||||
}
|
||||
|
||||
void TimelineObj::JumpTimeTo(float time) {
|
||||
JumpTimeToImpl(time);
|
||||
}
|
||||
|
||||
void TimelineObj::AdvanceTimeTo(float time) {
|
||||
AdvanceTimeToImpl(time);
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
TriggerType::Type ReverseTriggerType(TriggerType::Type clip_trigger_type) {
|
||||
switch (clip_trigger_type) {
|
||||
case TriggerType::kClipEnter:
|
||||
return TriggerType::kClipLeave;
|
||||
case TriggerType::kClipLeave:
|
||||
return TriggerType::kClipEnter;
|
||||
case TriggerType::kOneshot:
|
||||
return TriggerType::kOneshot;
|
||||
default:
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
float GetTriggerTime(TriggerType::Type type, const ResClip& clip) {
|
||||
switch (type) {
|
||||
case TriggerType::kEnter:
|
||||
return clip.start_time;
|
||||
case TriggerType::kLeave:
|
||||
return clip.start_time + clip.duration;
|
||||
default:
|
||||
return 0.0;
|
||||
}
|
||||
}
|
||||
|
||||
float GetTriggerTimeReverse(TriggerType::Type type, const ResClip& clip) {
|
||||
switch (type) {
|
||||
case TriggerType::kEnter:
|
||||
return clip.start_time + clip.duration;
|
||||
case TriggerType::kLeave:
|
||||
return clip.start_time;
|
||||
default:
|
||||
return 0.0;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
// NON_MATCHING: reorderings for the action binding stuff
|
||||
void TimelineObj::CalcImpl() {
|
||||
if (m_time == m_new_time)
|
||||
return;
|
||||
|
||||
const int direction = m_time < m_new_time ? 1 : -1;
|
||||
const auto time_max = m_time < m_new_time ? m_new_time : m_time;
|
||||
const auto time_min = m_time < m_new_time ? m_time : m_new_time;
|
||||
|
||||
ore::Array<const ResTrigger> triggers{m_timeline->triggers.Get(), 2 * m_timeline->num_clips};
|
||||
ore::Array<const ResClip> clips{m_timeline->clips.Get(), m_timeline->num_clips};
|
||||
|
||||
for (int trigger_idx = (m_time < m_new_time) + m_last_trigger_idx;
|
||||
u32(trigger_idx) < u32(triggers.size()); trigger_idx += direction) {
|
||||
const auto& trigger = triggers[trigger_idx];
|
||||
const auto& clip = clips[trigger.clip_index];
|
||||
const auto trigger_type = TriggerType::Type(trigger.trigger_type);
|
||||
|
||||
const float trigger_time = GetTriggerTime(trigger_type, clip);
|
||||
if (trigger_time <= time_min || time_max < trigger_time)
|
||||
break;
|
||||
|
||||
m_last_trigger_idx = trigger_idx;
|
||||
|
||||
if (m_jumped_time) {
|
||||
const float rev_trigger_time = GetTriggerTimeReverse(trigger_type, clip);
|
||||
if (time_min < rev_trigger_time && rev_trigger_time <= time_max)
|
||||
continue;
|
||||
}
|
||||
|
||||
const auto actor_idx = clip.actor_index;
|
||||
const auto& bindings = m_act_binder.GetBindings();
|
||||
const auto* actions = m_timeline->actors.Get()[actor_idx].actions.Get();
|
||||
const auto& binding = bindings[actor_idx];
|
||||
const ore::StringView name = *actions[clip.actor_action_index].name.Get();
|
||||
const auto* action = binding.GetAction(name);
|
||||
|
||||
auto real_trigger_type = trigger_type;
|
||||
if (m_jumped_time && direction < 0)
|
||||
real_trigger_type = ReverseTriggerType(real_trigger_type);
|
||||
|
||||
const ActionArg arg(&clip, binding.GetUserData(), action->user_data,
|
||||
m_new_time - trigger_time, real_trigger_type, clip.params.Get());
|
||||
ActionDoneHandler handler{this};
|
||||
action->handler(arg, std::move(handler));
|
||||
}
|
||||
|
||||
ore::Array<const ResOneshot> oneshots{m_timeline->oneshots.Get(), m_timeline->num_oneshots};
|
||||
for (int oneshot_idx = (m_time < m_new_time) + m_last_oneshot_idx;
|
||||
u32(oneshot_idx) < u32(oneshots.size()); oneshot_idx += direction) {
|
||||
const auto& oneshot = oneshots[oneshot_idx];
|
||||
const auto trigger_time = oneshot.time;
|
||||
if (trigger_time < time_min || time_max < trigger_time)
|
||||
break;
|
||||
|
||||
m_last_oneshot_idx = oneshot_idx;
|
||||
|
||||
if (m_jumped_time && trigger_time != m_new_time)
|
||||
continue;
|
||||
|
||||
const auto actor_idx = oneshot.actor_index;
|
||||
const auto& bindings = m_act_binder.GetBindings();
|
||||
const auto& binding = bindings[actor_idx];
|
||||
const auto* actions = m_timeline->actors.Get()[actor_idx].actions.Get();
|
||||
const ore::StringView name = *actions[oneshot.actor_action_index].name.Get();
|
||||
const auto* action = binding.GetAction(name);
|
||||
|
||||
const ActionArg arg(&oneshot, binding.GetUserData(), action->user_data,
|
||||
m_new_time - trigger_time, oneshot.params.Get());
|
||||
ActionDoneHandler handler{this};
|
||||
action->handler(arg, std::move(handler));
|
||||
}
|
||||
|
||||
m_time = m_new_time;
|
||||
}
|
||||
|
||||
void TimelineObj::AdvanceTimeToImpl(float time) {
|
||||
m_new_time = time;
|
||||
m_jumped_time = false;
|
||||
for (auto* timeline : m_sub_timelines) {
|
||||
if (timeline)
|
||||
timeline->AdvanceTimeToImpl(time);
|
||||
}
|
||||
}
|
||||
|
||||
void TimelineObj::JumpTimeToImpl(float time) {
|
||||
m_new_time = time;
|
||||
m_jumped_time = true;
|
||||
for (auto* timeline : m_sub_timelines) {
|
||||
if (timeline)
|
||||
timeline->JumpTimeToImpl(time);
|
||||
}
|
||||
}
|
||||
|
||||
bool TimelineObj::RegisterSubtimeline(TimelineObj* obj) {
|
||||
ore::Array<const ResSubtimeline> subtimelines{m_timeline->subtimelines.Get(),
|
||||
m_timeline->num_subtimelines};
|
||||
for (int i = 0; i < subtimelines.size(); ++i) {
|
||||
if (ore::StringView(*obj->m_timeline->name.Get()) == *subtimelines[i].name.Get()) {
|
||||
m_sub_timelines[i] = obj;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// NON_MATCHING: std::fill using obj->m_sub_timelines.size() rather than the byte size
|
||||
bool TimelineObj::Builder::Build(TimelineObj* obj, AllocateArg allocate_arg) {
|
||||
if (!obj)
|
||||
return false;
|
||||
|
||||
if (!allocate_arg.alloc || !allocate_arg.free)
|
||||
return false;
|
||||
|
||||
obj->Finalize();
|
||||
|
||||
EvflAllocator allocator{allocate_arg};
|
||||
obj->m_allocator = allocator;
|
||||
|
||||
m_act_binder_builder.Build(&obj->m_act_binder, &obj->m_allocator,
|
||||
{m_timeline->actors.Get(), m_timeline->num_actors});
|
||||
|
||||
auto& bindings = obj->m_act_binder.GetBindings();
|
||||
for (auto it = bindings.begin(); it != bindings.end(); ++it)
|
||||
it->SetIsUsed(true);
|
||||
|
||||
obj->m_timeline = m_timeline;
|
||||
obj->m_allocator = allocator;
|
||||
obj->m_sub_timelines.ConstructElements(m_timeline->num_subtimelines, &allocator);
|
||||
std::fill(obj->m_sub_timelines.begin(), obj->m_sub_timelines.end(), nullptr);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace evfl
|
182
lib/EventFlow/src/ore/BinaryFile.cpp
Normal file
182
lib/EventFlow/src/ore/BinaryFile.cpp
Normal file
@ -0,0 +1,182 @@
|
||||
#include <cstdint>
|
||||
#include <ore/BinaryFile.h>
|
||||
#include <ore/BitUtils.h>
|
||||
|
||||
namespace ore {
|
||||
|
||||
bool BinaryFileHeader::IsValid(s64 magic_, int ver_major_, int ver_minor_, int ver_patch_,
|
||||
int ver_sub_) const {
|
||||
bool valid = true;
|
||||
valid &= int(ver_major) == ver_major_ && int(ver_minor) == ver_minor_ &&
|
||||
magic == magic_ & int(ver_patch) <= ver_patch_;
|
||||
valid &= IsEndianReverse() || IsEndianValid();
|
||||
valid &= IsAlignmentValid();
|
||||
return valid;
|
||||
}
|
||||
|
||||
bool BinaryFileHeader::IsSignatureValid(s64 magic_) const {
|
||||
return magic == magic_;
|
||||
}
|
||||
|
||||
bool BinaryFileHeader::IsVersionValid(int major, int minor, int patch, int sub) const {
|
||||
if (int(ver_major) != major)
|
||||
return false;
|
||||
if (int(ver_minor) != minor)
|
||||
return false;
|
||||
if (int(ver_patch) > patch)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool BinaryFileHeader::IsEndianReverse() const {
|
||||
return bom == s16(0xFFFE);
|
||||
}
|
||||
|
||||
bool BinaryFileHeader::IsEndianValid() const {
|
||||
return bom == s16(0xFEFF);
|
||||
}
|
||||
|
||||
bool BinaryFileHeader::IsAlignmentValid() const {
|
||||
return (std::uintptr_t(this) & (GetAlignment() - 1)) == 0;
|
||||
}
|
||||
|
||||
int BinaryFileHeader::GetAlignment() const {
|
||||
return 1 << alignment;
|
||||
}
|
||||
|
||||
static constexpr u32 FlagRelocated = 1 << 0;
|
||||
|
||||
bool BinaryFileHeader::IsRelocated() const {
|
||||
return relocation_flags & FlagRelocated;
|
||||
}
|
||||
|
||||
void BinaryFileHeader::SetRelocated(bool relocated) {
|
||||
if (relocated)
|
||||
relocation_flags |= FlagRelocated;
|
||||
else
|
||||
relocation_flags &= ~FlagRelocated;
|
||||
}
|
||||
|
||||
void BinaryFileHeader::SetByteOrderMark() {
|
||||
bom = s16(0xFEFF);
|
||||
}
|
||||
|
||||
int BinaryFileHeader::GetFileSize() const {
|
||||
return file_size;
|
||||
}
|
||||
|
||||
void BinaryFileHeader::SetFileSize(int size) {
|
||||
file_size = size;
|
||||
}
|
||||
|
||||
void BinaryFileHeader::SetAlignment(int alignment_) {
|
||||
alignment = CountTrailingZeros(u32(alignment_));
|
||||
}
|
||||
|
||||
StringView BinaryFileHeader::GetFileName() const {
|
||||
StringView name;
|
||||
if (file_name_offset != 0)
|
||||
name = reinterpret_cast<const char*>(this) + file_name_offset;
|
||||
return name;
|
||||
}
|
||||
|
||||
void BinaryFileHeader::SetFileName(const StringView& name) {
|
||||
if (name.empty()) {
|
||||
file_name_offset = 0;
|
||||
} else {
|
||||
file_name_offset = int(intptr_t(name.data()) - intptr_t(this));
|
||||
#ifdef MATCHING_HACK_NX_CLANG
|
||||
asm("");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
RelocationTable* BinaryFileHeader::GetRelocationTable() {
|
||||
if (relocation_table_offset == 0)
|
||||
return nullptr;
|
||||
return reinterpret_cast<RelocationTable*>(reinterpret_cast<char*>(this) +
|
||||
relocation_table_offset);
|
||||
}
|
||||
|
||||
void BinaryFileHeader::SetRelocationTable(RelocationTable* table) {
|
||||
if (table == nullptr) {
|
||||
relocation_table_offset = 0;
|
||||
} else {
|
||||
relocation_table_offset = int(intptr_t(table) - intptr_t(this));
|
||||
#ifdef MATCHING_HACK_NX_CLANG
|
||||
asm("");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
BinaryBlockHeader* BinaryFileHeader::GetFirstBlock() {
|
||||
if (first_block_offset == 0)
|
||||
return nullptr;
|
||||
return reinterpret_cast<BinaryBlockHeader*>(reinterpret_cast<char*>(this) + first_block_offset);
|
||||
}
|
||||
|
||||
const BinaryBlockHeader* BinaryFileHeader::GetFirstBlock() const {
|
||||
if (first_block_offset == 0)
|
||||
return nullptr;
|
||||
return reinterpret_cast<const BinaryBlockHeader*>(reinterpret_cast<const char*>(this) +
|
||||
first_block_offset);
|
||||
}
|
||||
|
||||
BinaryBlockHeader* BinaryFileHeader::FindFirstBlock(int type) {
|
||||
auto* block = GetFirstBlock();
|
||||
if (!block || block->magic == type)
|
||||
return block;
|
||||
return block->FindNextBlock(type);
|
||||
}
|
||||
|
||||
const BinaryBlockHeader* BinaryFileHeader::FindFirstBlock(int type) const {
|
||||
auto* block = GetFirstBlock();
|
||||
if (!block || block->magic == type)
|
||||
return block;
|
||||
return block->FindNextBlock(type);
|
||||
}
|
||||
|
||||
void BinaryFileHeader::SetFirstBlock(BinaryBlockHeader* block) {
|
||||
if (block == nullptr)
|
||||
first_block_offset = 0;
|
||||
else
|
||||
first_block_offset = int(intptr_t(block) - intptr_t(this));
|
||||
}
|
||||
|
||||
BinaryBlockHeader* BinaryBlockHeader::FindNextBlock(int type) {
|
||||
auto* block = this;
|
||||
do
|
||||
block = block->GetNextBlock();
|
||||
while (block && block->magic != type);
|
||||
return block;
|
||||
}
|
||||
|
||||
const BinaryBlockHeader* BinaryBlockHeader::FindNextBlock(int type) const {
|
||||
auto* block = this;
|
||||
do
|
||||
block = block->GetNextBlock();
|
||||
while (block && block->magic != type);
|
||||
return block;
|
||||
}
|
||||
|
||||
BinaryBlockHeader* BinaryBlockHeader::GetNextBlock() {
|
||||
if (next_block_offset == 0)
|
||||
return nullptr;
|
||||
return reinterpret_cast<BinaryBlockHeader*>(reinterpret_cast<char*>(this) + next_block_offset);
|
||||
}
|
||||
|
||||
const BinaryBlockHeader* BinaryBlockHeader::GetNextBlock() const {
|
||||
if (next_block_offset == 0)
|
||||
return nullptr;
|
||||
return reinterpret_cast<const BinaryBlockHeader*>(reinterpret_cast<const char*>(this) +
|
||||
next_block_offset);
|
||||
}
|
||||
|
||||
void BinaryBlockHeader::SetNextBlock(BinaryBlockHeader* block) {
|
||||
if (block == nullptr)
|
||||
next_block_offset = 0;
|
||||
else
|
||||
next_block_offset = int(intptr_t(block) - intptr_t(this));
|
||||
}
|
||||
|
||||
} // namespace ore
|
115
lib/EventFlow/src/ore/BitUtils.cpp
Normal file
115
lib/EventFlow/src/ore/BitUtils.cpp
Normal file
@ -0,0 +1,115 @@
|
||||
#include <ore/BitUtils.h>
|
||||
|
||||
namespace ore {
|
||||
|
||||
void BitArray::SetAllOn() {
|
||||
const int num = m_num_bits >> ShiftAmount;
|
||||
Fill(num, Word(-1));
|
||||
|
||||
u32 remainder = u32(m_num_bits) % NumBitsPerWord;
|
||||
if (remainder != 0)
|
||||
m_words[num] = (1ul << remainder) - 1;
|
||||
}
|
||||
|
||||
void BitArray::SetAllOff() {
|
||||
Fill(GetNumWords(), Word(0));
|
||||
}
|
||||
|
||||
BitArray::TestIter BitArray::BeginTest() const {
|
||||
return TestIter(m_words, m_words + GetNumWords());
|
||||
}
|
||||
|
||||
BitArray::TestIter BitArray::EndTest() const {
|
||||
return TestIter(nullptr, nullptr);
|
||||
}
|
||||
|
||||
BitArray::TestClearIter BitArray::BeginTestClear() {
|
||||
return TestClearIter(m_words, m_words + GetNumWords());
|
||||
}
|
||||
|
||||
BitArray::TestClearIter BitArray::EndTestClear() {
|
||||
return TestClearIter(nullptr, nullptr);
|
||||
}
|
||||
|
||||
BitArray::TestIter::TestIter(const BitArray::Word* start, const BitArray::Word* end) {
|
||||
for (auto* it = start; it != end; ++it) {
|
||||
if (*it != 0) {
|
||||
auto idx = CountTrailingZeros(*it);
|
||||
idx += 8 * int(intptr_t(it) - intptr_t(start)) & ClearMask;
|
||||
m_bit = idx;
|
||||
m_current_word = it;
|
||||
m_last_word = end;
|
||||
m_next = *it & (*it - 1);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
SetInvalid();
|
||||
}
|
||||
|
||||
BitArray::TestIter& BitArray::TestIter::operator++() {
|
||||
m_bit &= ClearMask;
|
||||
|
||||
// Fast path: we still have bits in the current word
|
||||
if (m_next != 0) {
|
||||
m_bit += CountTrailingZeros(m_next);
|
||||
m_next &= m_next - 1;
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Find the next nonzero word and the first set bit in it
|
||||
++m_current_word;
|
||||
for (; m_current_word != m_last_word; ++m_current_word) {
|
||||
m_bit += NumBitsPerWord;
|
||||
if (*m_current_word == 0)
|
||||
continue;
|
||||
m_bit += CountTrailingZeros(*m_current_word);
|
||||
m_next = *m_current_word & (*m_current_word - 1);
|
||||
return *this;
|
||||
}
|
||||
|
||||
SetInvalid();
|
||||
return *this;
|
||||
}
|
||||
|
||||
BitArray::TestClearIter::TestClearIter(BitArray::Word* start, BitArray::Word* end) {
|
||||
for (auto* it = start; it != end; ++it) {
|
||||
if (*it != 0) {
|
||||
auto idx = CountTrailingZeros(*it);
|
||||
idx += 8 * int(intptr_t(it) - intptr_t(start)) & ClearMask;
|
||||
m_bit = idx;
|
||||
m_current_word = it;
|
||||
m_last_word = end;
|
||||
m_next = *it & (*it - 1);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
SetInvalid();
|
||||
}
|
||||
|
||||
BitArray::TestClearIter& BitArray::TestClearIter::operator++() {
|
||||
m_bit &= ClearMask;
|
||||
|
||||
if (m_next != 0) {
|
||||
m_bit += CountTrailingZeros(m_next);
|
||||
m_next &= m_next - 1;
|
||||
return *this;
|
||||
}
|
||||
|
||||
*m_current_word = 0;
|
||||
++m_current_word;
|
||||
for (; m_current_word != m_last_word; *m_current_word = 0, ++m_current_word) {
|
||||
m_bit += NumBitsPerWord;
|
||||
if (*m_current_word == 0)
|
||||
continue;
|
||||
m_bit += CountTrailingZeros(*m_current_word);
|
||||
m_next = *m_current_word & (*m_current_word - 1);
|
||||
return *this;
|
||||
}
|
||||
|
||||
SetInvalid();
|
||||
return *this;
|
||||
}
|
||||
|
||||
} // namespace ore
|
13
lib/EventFlow/src/ore/EnumUtil.cpp
Normal file
13
lib/EventFlow/src/ore/EnumUtil.cpp
Normal file
@ -0,0 +1,13 @@
|
||||
#include <algorithm>
|
||||
#include <ore/EnumUtil.h>
|
||||
|
||||
namespace ore {
|
||||
|
||||
int detail::EnumUtil::FindIndex(int value, const IterRange<const int*>& values) {
|
||||
auto it = std::find_if(values.begin(), values.end(), [value](int x) { return value == x; });
|
||||
if (it == values.end())
|
||||
return -1;
|
||||
return static_cast<int>(it - values.begin());
|
||||
}
|
||||
|
||||
} // namespace ore
|
106
lib/EventFlow/src/ore/RelocationTable.cpp
Normal file
106
lib/EventFlow/src/ore/RelocationTable.cpp
Normal file
@ -0,0 +1,106 @@
|
||||
#include <cstring>
|
||||
#include <ore/RelocationTable.h>
|
||||
|
||||
namespace ore {
|
||||
|
||||
namespace {
|
||||
|
||||
struct BitFlag32 {
|
||||
explicit BitFlag32(u32 flags) : m_flags(flags) {}
|
||||
bool operator[](int idx) const { return m_flags & (1 << idx); }
|
||||
|
||||
u32 m_flags{};
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
void RelocationTable::Section::SetPtr(void* ptr_) {
|
||||
ptr = reinterpret_cast<u64>(ptr_);
|
||||
}
|
||||
|
||||
void* RelocationTable::Section::GetPtr() const {
|
||||
return reinterpret_cast<void*>(ptr);
|
||||
}
|
||||
|
||||
void* RelocationTable::Section::GetPtrInFile(void* base) const {
|
||||
return static_cast<char*>(base) + offset;
|
||||
}
|
||||
|
||||
void* RelocationTable::Section::GetBasePtr(void* base) const {
|
||||
if (ptr)
|
||||
base = reinterpret_cast<void*>(ptr - offset);
|
||||
return base;
|
||||
}
|
||||
|
||||
u32 RelocationTable::Section::GetSize() const {
|
||||
return size;
|
||||
}
|
||||
|
||||
void RelocationTable::Relocate() {
|
||||
char* const table_base = reinterpret_cast<char*>(this) - table_start_offset;
|
||||
const auto* entries = GetEntries();
|
||||
const int num = num_sections;
|
||||
|
||||
for (int section_idx = 0; section_idx < num; ++section_idx) {
|
||||
const auto& section = GetSections()[section_idx];
|
||||
|
||||
auto* base = static_cast<char*>(section.GetBasePtr(table_base));
|
||||
const int idx0 = section.first_entry_idx;
|
||||
const int end = idx0 + section.num_entries;
|
||||
|
||||
for (int idx = idx0; idx < end; ++idx) {
|
||||
const auto& entry = entries[idx];
|
||||
const auto pointers_offset = entry.pointers_offset;
|
||||
const BitFlag32 mask{entry.mask};
|
||||
|
||||
auto* pointer_ptr = reinterpret_cast<u64*>(table_base + pointers_offset);
|
||||
for (int i = 0; i < 32; ++i, ++pointer_ptr) {
|
||||
if (!mask[i])
|
||||
continue;
|
||||
const auto offset = static_cast<int>(*pointer_ptr);
|
||||
void* ptr = offset == 0 ? nullptr : reinterpret_cast<void*>(base + offset);
|
||||
std::memcpy(pointer_ptr, &ptr, sizeof(ptr));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RelocationTable::Unrelocate() {
|
||||
char* const table_base = reinterpret_cast<char*>(this) - table_start_offset;
|
||||
const auto* entries = GetEntries();
|
||||
const int num = num_sections;
|
||||
|
||||
for (int section_idx = 0; section_idx < num; ++section_idx) {
|
||||
auto& section = GetSections()[section_idx];
|
||||
|
||||
auto* base = static_cast<char*>(section.GetBasePtr(table_base));
|
||||
section.SetPtr(nullptr);
|
||||
const int idx0 = section.first_entry_idx;
|
||||
const int end = idx0 + section.num_entries;
|
||||
|
||||
for (int idx = idx0; idx < end; ++idx) {
|
||||
const auto& entry = entries[idx];
|
||||
const auto pointers_offset = entry.pointers_offset;
|
||||
const BitFlag32 mask{entry.mask};
|
||||
|
||||
auto* pointer_ptr = reinterpret_cast<void**>(table_base + pointers_offset);
|
||||
for (int i = 0; i < 32; ++i, ++pointer_ptr) {
|
||||
if (!mask[i])
|
||||
continue;
|
||||
void* ptr = *pointer_ptr;
|
||||
u64 offset = static_cast<int>(ptr == nullptr ? 0 : intptr_t(ptr) - intptr_t(base));
|
||||
std::memcpy(pointer_ptr, &offset, sizeof(offset));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int RelocationTable::CalcSize(int num_sections, int num_entries) {
|
||||
int size = 0;
|
||||
size += offsetof(RelocationTable, sections);
|
||||
size += sizeof(Section) * num_sections;
|
||||
size += sizeof(Section::Entry) * num_entries;
|
||||
return size;
|
||||
}
|
||||
|
||||
} // namespace ore
|
50
lib/EventFlow/src/ore/ResDic.cpp
Normal file
50
lib/EventFlow/src/ore/ResDic.cpp
Normal file
@ -0,0 +1,50 @@
|
||||
#include <algorithm>
|
||||
#include <ore/ResDic.h>
|
||||
#include <ore/ResEndian.h>
|
||||
|
||||
namespace ore {
|
||||
|
||||
int ResDic::FindRefBit(const StringView& str1, const StringView& str2) {
|
||||
const auto len1 = str1.size();
|
||||
const auto len2 = str2.size();
|
||||
const auto len = std::max(len1, len2);
|
||||
|
||||
for (int bit_idx = 0; bit_idx < 8 * len; ++bit_idx) {
|
||||
const int idx = bit_idx >> 3;
|
||||
|
||||
int bit1 = 0;
|
||||
if (len1 > idx)
|
||||
bit1 = str1[len1 + -(idx + 1)] >> (bit_idx % 8) & 1;
|
||||
|
||||
int bit2 = 0;
|
||||
if (len2 > idx)
|
||||
bit2 = str2[len2 + -(idx + 1)] >> (bit_idx % 8) & 1;
|
||||
|
||||
if (bit1 != bit2)
|
||||
return bit_idx;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
void SwapEndian(ResEndian* endian, ResDic* dic) {
|
||||
const auto swap_entries = [&] {
|
||||
const int num_entries = dic->num_entries + 1;
|
||||
for (int i = 0; i < num_entries; ++i) {
|
||||
ResDicEntry& entry = dic->GetEntries()[i];
|
||||
SwapEndian(&entry.compact_bit_idx);
|
||||
SwapEndian(&entry.next_indices[0]);
|
||||
SwapEndian(&entry.next_indices[1]);
|
||||
}
|
||||
};
|
||||
|
||||
if (endian->is_serializing) {
|
||||
swap_entries();
|
||||
SwapEndian(&dic->num_entries);
|
||||
} else {
|
||||
SwapEndian(&dic->num_entries);
|
||||
swap_entries();
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace ore
|
89
lib/EventFlow/src/ore/ResMetaData.cpp
Normal file
89
lib/EventFlow/src/ore/ResMetaData.cpp
Normal file
@ -0,0 +1,89 @@
|
||||
#include <ore/ResDic.h>
|
||||
#include <ore/ResEndian.h>
|
||||
#include <ore/ResMetaData.h>
|
||||
|
||||
namespace ore {
|
||||
|
||||
static void SwapEndianImpl(ResEndian* endian, ResMetaData* res) {
|
||||
auto* dictionary = res->dictionary.ToPtr(endian->base);
|
||||
if (dictionary)
|
||||
SwapEndian(endian, dictionary);
|
||||
|
||||
switch (res->type) {
|
||||
case ResMetaData::DataType::kArgument:
|
||||
case ResMetaData::DataType::kString:
|
||||
case ResMetaData::DataType::kStringArray:
|
||||
case ResMetaData::DataType::kActorIdentifier: {
|
||||
if (res->num_items == 0)
|
||||
break;
|
||||
BinString* str = res->value.str.ToPtr(endian->base);
|
||||
if (endian->is_serializing) {
|
||||
for (int i = 0, n = res->num_items; i < n; ++i) {
|
||||
auto* next = str->NextString();
|
||||
SwapEndian(&str->length);
|
||||
str = next;
|
||||
}
|
||||
} else {
|
||||
for (int i = 0, n = res->num_items; i < n; ++i) {
|
||||
SwapEndian(&str->length);
|
||||
str = str->NextString();
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ResMetaData::DataType::kContainer: {
|
||||
for (int i = 0, n = res->num_items; i < n; ++i) {
|
||||
ResMetaData* ptr = (&res->value.container + i)->ToPtr(endian->base);
|
||||
if (ptr)
|
||||
SwapEndian(endian, ptr);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ResMetaData::DataType::kInt:
|
||||
case ResMetaData::DataType::kBool:
|
||||
case ResMetaData::DataType::kFloat:
|
||||
case ResMetaData::DataType::kIntArray:
|
||||
case ResMetaData::DataType::kFloatArray:
|
||||
for (int i = 0, n = res->num_items; i < n; ++i) {
|
||||
SwapEndian(&res->value.i + i);
|
||||
}
|
||||
break;
|
||||
case ResMetaData::DataType::kWString:
|
||||
case ResMetaData::DataType::kWStringArray: {
|
||||
if (res->num_items == 0)
|
||||
break;
|
||||
BinWString* str = res->value.wstr.ToPtr(endian->base);
|
||||
if (endian->is_serializing) {
|
||||
for (int i = 0, n = res->num_items; i < n; ++i) {
|
||||
for (auto& c : *str)
|
||||
c = static_cast<wchar_t>(SwapEndian(static_cast<u32>(c)));
|
||||
auto* next = str->NextString();
|
||||
SwapEndian(&str->length);
|
||||
str = next;
|
||||
}
|
||||
} else {
|
||||
for (int i = 0, n = res->num_items; i < n; ++i) {
|
||||
SwapEndian(&str->length);
|
||||
for (auto& c : *str)
|
||||
c = static_cast<wchar_t>(SwapEndian(static_cast<u32>(c)));
|
||||
str = str->NextString();
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ResMetaData::DataType::kBoolArray:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void SwapEndian(ResEndian* endian, ResMetaData* res) {
|
||||
if (endian->is_serializing) {
|
||||
SwapEndianImpl(endian, res);
|
||||
SwapEndian(&res->num_items);
|
||||
} else {
|
||||
SwapEndian(&res->num_items);
|
||||
SwapEndianImpl(endian, res);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace ore
|
13
lib/EventFlow/src/ore/StringPool.cpp
Normal file
13
lib/EventFlow/src/ore/StringPool.cpp
Normal file
@ -0,0 +1,13 @@
|
||||
#include <ore/StringPool.h>
|
||||
|
||||
namespace ore {
|
||||
|
||||
int StringPool::GetLength() const {
|
||||
return length;
|
||||
}
|
||||
|
||||
void StringPool::SetLength(int len) {
|
||||
length = len;
|
||||
}
|
||||
|
||||
} // namespace ore
|
@ -1 +0,0 @@
|
||||
Subproject commit dea2e24df14973b3c80901c34766b87f89f708b0
|
74
lib/NintendoSDK/.clang-format
Normal file
74
lib/NintendoSDK/.clang-format
Normal file
@ -0,0 +1,74 @@
|
||||
---
|
||||
Language: Cpp
|
||||
AccessModifierOffset: -4
|
||||
AlignAfterOpenBracket: Align
|
||||
AlignConsecutiveAssignments: false
|
||||
AlignConsecutiveDeclarations: false
|
||||
AlignOperands: true
|
||||
AlignTrailingComments: true
|
||||
AllowAllParametersOfDeclarationOnNextLine: true
|
||||
AllowShortBlocksOnASingleLine: Never
|
||||
AllowShortCaseLabelsOnASingleLine: false
|
||||
AllowShortFunctionsOnASingleLine: Inline
|
||||
AllowShortIfStatementsOnASingleLine: Never
|
||||
AllowShortLoopsOnASingleLine: false
|
||||
AlwaysBreakAfterDefinitionReturnType: None
|
||||
AlwaysBreakAfterReturnType: None
|
||||
AlwaysBreakBeforeMultilineStrings: false
|
||||
AlwaysBreakTemplateDeclarations: Yes
|
||||
BinPackArguments: true
|
||||
BinPackParameters: true
|
||||
BreakBeforeBinaryOperators: None
|
||||
BreakBeforeBraces: Attach
|
||||
BreakBeforeTernaryOperators: false
|
||||
BreakConstructorInitializersBeforeComma: false
|
||||
ColumnLimit: 100
|
||||
CommentPragmas: '^ (IWYU pragma:|NOLINT)'
|
||||
ConstructorInitializerAllOnOneLineOrOnePerLine: false
|
||||
ConstructorInitializerIndentWidth: 4
|
||||
ContinuationIndentWidth: 4
|
||||
Cpp11BracedListStyle: true
|
||||
DerivePointerAlignment: false
|
||||
DisableFormat: false
|
||||
ForEachMacros: []
|
||||
IncludeCategories:
|
||||
- Regex: '^<[Ww]indows\.h>$'
|
||||
Priority: 1
|
||||
- Regex: '^<'
|
||||
Priority: 2
|
||||
- Regex: '^"'
|
||||
Priority: 3
|
||||
IndentCaseLabels: false
|
||||
IndentWidth: 4
|
||||
IndentWrappedFunctionNames: false
|
||||
KeepEmptyLinesAtTheStartOfBlocks: false
|
||||
MacroBlockBegin: ''
|
||||
MacroBlockEnd: ''
|
||||
MaxEmptyLinesToKeep: 1
|
||||
NamespaceIndentation: None
|
||||
ObjCBlockIndentWidth: 4
|
||||
ObjCSpaceAfterProperty: false
|
||||
ObjCSpaceBeforeProtocolList: true
|
||||
PenaltyBreakBeforeFirstCallParameter: 19
|
||||
PenaltyBreakComment: 300
|
||||
PenaltyBreakFirstLessLess: 120
|
||||
PenaltyBreakString: 1000
|
||||
PenaltyExcessCharacter: 1000000
|
||||
PenaltyReturnTypeOnItsOwnLine: 60
|
||||
PointerAlignment: Left
|
||||
ReflowComments: true
|
||||
SortIncludes: true
|
||||
SpaceAfterCStyleCast: false
|
||||
SpaceBeforeAssignmentOperators: true
|
||||
SpaceBeforeParens: ControlStatements
|
||||
SpaceInEmptyParentheses: false
|
||||
SpacesBeforeTrailingComments: 2
|
||||
SpacesInAngles: false
|
||||
SpacesInContainerLiterals: true
|
||||
SpacesInCStyleCastParentheses: false
|
||||
SpacesInParentheses: false
|
||||
SpacesInSquareBrackets: false
|
||||
Standard: c++17
|
||||
TabWidth: 4
|
||||
UseTab: Never
|
||||
...
|
12
lib/NintendoSDK/.gitrepo
Normal file
12
lib/NintendoSDK/.gitrepo
Normal file
@ -0,0 +1,12 @@
|
||||
; DO NOT EDIT (unless you know what you are doing)
|
||||
;
|
||||
; This subdirectory is a git "subrepo", and this file is maintained by the
|
||||
; git-subrepo command. See https://github.com/git-commands/git-subrepo#readme
|
||||
;
|
||||
[subrepo]
|
||||
remote = https://github.com/open-ead/nnheaders
|
||||
branch = master
|
||||
commit = 9ee21399ff05176c98b0651be3851fba3f70ceda
|
||||
parent = ffcc7f659ebc9bc9d149e52bec553b906bb47369
|
||||
method = merge
|
||||
cmdver = 0.4.3
|
129
lib/NintendoSDK/CMakeLists.txt
Normal file
129
lib/NintendoSDK/CMakeLists.txt
Normal file
@ -0,0 +1,129 @@
|
||||
project(NintendoSDK CXX ASM)
|
||||
|
||||
add_library(NintendoSDK OBJECT
|
||||
include/nvn/nvn_types.h
|
||||
include/nvn/nvn.h
|
||||
include/nvn/nvn_api.h
|
||||
include/nn/types.h
|
||||
include/nn/os.h
|
||||
include/nn/nifm.h
|
||||
include/nn/prepo.h
|
||||
include/nn/vfx/Config.h
|
||||
include/nn/vfx/System.h
|
||||
include/nn/vfx/Heap.h
|
||||
include/nn/socket.h
|
||||
include/nn/aoc.h
|
||||
include/nn/fs.h
|
||||
include/nn/ro.h
|
||||
include/nn/oe.h
|
||||
include/nn/util.h
|
||||
include/nn/image.h
|
||||
include/nn/util/Float2.h
|
||||
include/nn/ui2d/detail/TexCoordArray.h
|
||||
include/nn/ui2d/Layout.h
|
||||
include/nn/ui2d/Parts.h
|
||||
include/nn/ui2d/Pane.h
|
||||
include/nn/ui2d/Material.h
|
||||
include/nn/g3d/ResMaterialAnim.h
|
||||
include/nn/g3d/ResShapeAnim.h
|
||||
include/nn/g3d/ResLightAnim.h
|
||||
include/nn/g3d/ResSkeletalAnim.h
|
||||
include/nn/g3d/ResSceneAnim.h
|
||||
include/nn/g3d/BindFuncTable.h
|
||||
include/nn/g3d/ResFile.h
|
||||
include/nn/g3d/ResMaterial.h
|
||||
include/nn/g3d/ResFogAnim.h
|
||||
include/nn/g3d/ResModel.h
|
||||
include/nn/nn.h
|
||||
include/nn/settings.h
|
||||
include/nn/hid.h
|
||||
include/nn/atk/detail/StreamSoundRuntime.h
|
||||
include/nn/atk/detail/BasicSound.h
|
||||
include/nn/atk/detail/WaveSoundRuntime.h
|
||||
include/nn/atk/detail/SequenceSoundRuntime.h
|
||||
include/nn/atk/detail/SoundArchiveManager.h
|
||||
include/nn/atk/detail/AdvancedWaveSoundRuntime.h
|
||||
include/nn/atk/SoundArchivePlayer.h
|
||||
include/nn/atk/SoundPlayer.h
|
||||
include/nn/atk/SoundDataManager.h
|
||||
include/nn/nex/client.h
|
||||
include/nn/nex/RootObject.h
|
||||
include/nn/nex/socket.h
|
||||
include/nn/nex/key.h
|
||||
include/nn/nex/checksum.h
|
||||
include/nn/nex/reference.h
|
||||
include/nn/nex/pseudo.h
|
||||
include/nn/nex/string.h
|
||||
include/nn/nex/instance.h
|
||||
include/nn/nex/ddl.h
|
||||
include/nn/nex/encryption.h
|
||||
include/nn/nex/cache.h
|
||||
include/nn/nex/time.h
|
||||
include/nn/nex/plugin.h
|
||||
include/nn/nex/dynamic.h
|
||||
include/nn/nex/data.h
|
||||
include/nn/nex/auth.h
|
||||
include/nn/nex/buffer.h
|
||||
include/nn/nex/system.h
|
||||
include/nn/nex/hash.h
|
||||
include/nn/time.h
|
||||
include/nn/diag.h
|
||||
include/nn/init.h
|
||||
include/nn/crypto.h
|
||||
include/nn/ssl.h
|
||||
include/nn/gfx/detail/pool.h
|
||||
include/nn/gfx/detail/deviceimpl.h
|
||||
include/nn/gfx/detail/bufferimpl.h
|
||||
include/nn/gfx/device.h
|
||||
include/nn/gfx/memory.h
|
||||
include/nn/gfx/buffer.h
|
||||
include/nn/gfx/api.h
|
||||
include/nn/vi.h
|
||||
include/nn/account.h
|
||||
include/nn/audio.h
|
||||
include/nn/friends.h
|
||||
include/nn/mem.h
|
||||
include/nv.h
|
||||
include/vapours/results.hpp
|
||||
include/vapours/results/sf_results.hpp
|
||||
include/vapours/results/capsrv_results.hpp
|
||||
include/vapours/results/pgl_results.hpp
|
||||
include/vapours/results/lr_results.hpp
|
||||
include/vapours/results/spl_results.hpp
|
||||
include/vapours/results/pm_results.hpp
|
||||
include/vapours/results/settings_results.hpp
|
||||
include/vapours/results/debug_results.hpp
|
||||
include/vapours/results/cal_results.hpp
|
||||
include/vapours/results/i2c_results.hpp
|
||||
include/vapours/results/results_common.hpp
|
||||
include/vapours/results/time_results.hpp
|
||||
include/vapours/results/vi_results.hpp
|
||||
include/vapours/results/ns_results.hpp
|
||||
include/vapours/results/fs_results.hpp
|
||||
include/vapours/results/hipc_results.hpp
|
||||
include/vapours/results/os_results.hpp
|
||||
include/vapours/results/ro_results.hpp
|
||||
include/vapours/results/loader_results.hpp
|
||||
include/vapours/results/err_results.hpp
|
||||
include/vapours/results/ncm_results.hpp
|
||||
include/vapours/results/svc_results.hpp
|
||||
include/vapours/results/nim_results.hpp
|
||||
include/vapours/results/exosphere_results.hpp
|
||||
include/vapours/results/creport_results.hpp
|
||||
include/vapours/results/erpt_results.hpp
|
||||
include/vapours/results/kvdb_results.hpp
|
||||
include/vapours/results/dmnt_results.hpp
|
||||
include/vapours/results/updater_results.hpp
|
||||
include/vapours/results/fatal_results.hpp
|
||||
include/vapours/results/sm_results.hpp
|
||||
include/vapours/results/psc_results.hpp
|
||||
|
||||
modules/nvn/nvnInit.cpp
|
||||
)
|
||||
|
||||
target_include_directories(NintendoSDK PUBLIC include/)
|
||||
target_compile_options(NintendoSDK PRIVATE -fno-strict-aliasing)
|
||||
target_compile_options(NintendoSDK PRIVATE -Wall -Wextra)
|
||||
target_compile_options(NintendoSDK PRIVATE -Wno-invalid-offsetof)
|
||||
|
||||
target_link_libraries(NintendoSDK PUBLIC)
|
10
lib/NintendoSDK/README.md
Normal file
10
lib/NintendoSDK/README.md
Normal file
@ -0,0 +1,10 @@
|
||||
# nnheaders
|
||||
Repository of user created nnsdk headers.
|
||||
|
||||
The header files contained herewithin are entirely user created via Reverse Engineering or publicly available sources (non stripped binaries containing symbols).
|
||||
|
||||
Do not ask for or PR any copyrighted material to this repo. You will be ignored.
|
||||
|
||||
# Credits
|
||||
- [Shadow](https://github.com/shadowninja108/) - For [Skyline](https://github.com/shadowninja108/Skyline), which was the primary inspiration and use case for this repo.
|
||||
- [Shibbo](https://github.com/shibbo) - For [OdysseyReversed](https://github.com/shibbo/OdysseyReversed/), which most of these headers came from.
|
57
lib/NintendoSDK/include/nn/account.h
Normal file
57
lib/NintendoSDK/include/nn/account.h
Normal file
@ -0,0 +1,57 @@
|
||||
/**
|
||||
* @file account.h
|
||||
* @brief Account service implementation.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <nn/os.h>
|
||||
#include <nn/types.h>
|
||||
|
||||
namespace nn {
|
||||
namespace account {
|
||||
typedef char Nickname[0x21];
|
||||
typedef u64 NetworkServiceAccountId;
|
||||
|
||||
class AsyncContext;
|
||||
|
||||
class Uid {
|
||||
public:
|
||||
bool IsValid() const { return m_Storage[0] != 0 || m_Storage[1] != 0; }
|
||||
|
||||
u64 m_Storage[2];
|
||||
};
|
||||
|
||||
class UserHandle {
|
||||
public:
|
||||
Uid m_Uid;
|
||||
void* m_Handle;
|
||||
};
|
||||
|
||||
void Initialize();
|
||||
Result ListAllUsers(s32*, Uid*, s32 numUsers);
|
||||
Result OpenUser(UserHandle*, Uid const&);
|
||||
Result IsNetworkServiceAccountAvailable(bool* out, UserHandle const&);
|
||||
void CloseUser(UserHandle const&);
|
||||
|
||||
Result EnsureNetworkServiceAccountAvailable(UserHandle const& userHandle);
|
||||
Result EnsureNetworkServiceAccountIdTokenCacheAsync(AsyncContext*, UserHandle const&);
|
||||
Result LoadNetworkServiceAccountIdTokenCache(u64*, char*, u64, UserHandle const&);
|
||||
|
||||
Result GetLastOpenedUser(Uid*);
|
||||
Result GetNickname(Nickname* nickname, Uid const& userID);
|
||||
|
||||
Result GetUserId(Uid* uid, const UserHandle& handle);
|
||||
Result OpenPreselectedUser(UserHandle* handle);
|
||||
|
||||
class AsyncContext {
|
||||
public:
|
||||
AsyncContext();
|
||||
|
||||
Result HasDone(bool*);
|
||||
Result GetResult();
|
||||
Result Cancel();
|
||||
Result GetSystemEvent(nn::os::SystemEvent*);
|
||||
};
|
||||
}; // namespace account
|
||||
}; // namespace nn
|
9
lib/NintendoSDK/include/nn/aoc.h
Normal file
9
lib/NintendoSDK/include/nn/aoc.h
Normal file
@ -0,0 +1,9 @@
|
||||
#pragma once
|
||||
|
||||
#include <nn/types.h>
|
||||
|
||||
namespace nn::aoc {
|
||||
|
||||
int ListAddOnContent(int*, int, int);
|
||||
|
||||
} // namespace nn::aoc
|
37
lib/NintendoSDK/include/nn/atk/SoundArchivePlayer.h
Normal file
37
lib/NintendoSDK/include/nn/atk/SoundArchivePlayer.h
Normal file
@ -0,0 +1,37 @@
|
||||
/**
|
||||
* @file SoundArchivePlayer.h
|
||||
* @brief Basic sound player from a sound archive.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <nn/atk/detail/AdvancedWaveSoundRuntime.h>
|
||||
#include <nn/atk/detail/SequenceSoundRuntime.h>
|
||||
#include <nn/atk/detail/SoundArchiveManager.h>
|
||||
#include <nn/atk/detail/StreamSoundRuntime.h>
|
||||
#include <nn/atk/detail/WaveSoundRuntime.h>
|
||||
|
||||
namespace nn {
|
||||
namespace atk {
|
||||
class SoundArchivePlayer {
|
||||
public:
|
||||
SoundArchivePlayer();
|
||||
|
||||
virtual ~SoundArchivePlayer();
|
||||
|
||||
bool IsAvailable() const;
|
||||
void Finalize();
|
||||
void StopAllSound(s32, bool);
|
||||
void DisposeInstances();
|
||||
|
||||
nn::atk::detail::SoundArchiveManager mArchiveManager; // _8
|
||||
nn::atk::detail::SequenceSoundRuntime mSeqSoundRuntime; // _50
|
||||
nn::atk::detail::WaveSoundRuntime mWaveSoundRuntime; // _130
|
||||
nn::atk::detail::AdvancedWaveSoundRuntime mAdvancedWaveSound; // _1B0
|
||||
nn::atk::detail::StreamSoundRuntime mStreamSoundRuntime; // _1E0
|
||||
u64 _290;
|
||||
u32 _298;
|
||||
u8 _29C[0x2E8 - 0x29C];
|
||||
};
|
||||
}; // namespace atk
|
||||
}; // namespace nn
|
25
lib/NintendoSDK/include/nn/atk/SoundDataManager.h
Normal file
25
lib/NintendoSDK/include/nn/atk/SoundDataManager.h
Normal file
@ -0,0 +1,25 @@
|
||||
/**
|
||||
* @file SoundDataManager.h
|
||||
* @brief Sound data management implementation.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <nn/types.h>
|
||||
|
||||
namespace nn {
|
||||
namespace atk {
|
||||
class SoundDataManager {
|
||||
public:
|
||||
SoundDataManager();
|
||||
virtual ~SoundDataManager();
|
||||
|
||||
virtual void InvalidateData(void const*, void const*);
|
||||
virtual void SetFileAddressToTable(u32, void const*);
|
||||
virtual u64 GetFileAddressFromTable(u32) const;
|
||||
virtual u32 GetFileAddressImpl(u32) const;
|
||||
|
||||
u8 _0[0x240];
|
||||
};
|
||||
}; // namespace atk
|
||||
}; // namespace nn
|
56
lib/NintendoSDK/include/nn/atk/SoundPlayer.h
Normal file
56
lib/NintendoSDK/include/nn/atk/SoundPlayer.h
Normal file
@ -0,0 +1,56 @@
|
||||
/**
|
||||
* @file SoundPlayer.h
|
||||
* @brief Sound player.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <nn/types.h>
|
||||
|
||||
namespace nn {
|
||||
namespace atk {
|
||||
enum PauseMode {
|
||||
|
||||
};
|
||||
|
||||
class SoundPlayer {
|
||||
public:
|
||||
SoundPlayer();
|
||||
~SoundPlayer();
|
||||
|
||||
void StopAllSound(s32);
|
||||
void Update();
|
||||
void DoFreePlayerHeap();
|
||||
void detail_SortPriorityList(bool);
|
||||
void PauseAllSound(s32, bool);
|
||||
void PauseAllSound(bool, s32, nn::atk::PauseMode);
|
||||
void SetVolume(f32 vol);
|
||||
void SetLowPassFilterFrequency(f32 filterFreq);
|
||||
void SetBiquadFilter(s32 filterType, f32 baseFreq);
|
||||
void SetDefaultOutputLine(u32 line);
|
||||
|
||||
void detail_SetPlayableSoundLimit(s32 limit);
|
||||
bool CanPlaySound(s32);
|
||||
|
||||
u64 _0;
|
||||
u64 _8;
|
||||
u64 _10;
|
||||
u64 _18;
|
||||
u64 _20;
|
||||
u64 _28;
|
||||
u64 _30;
|
||||
u64 _38;
|
||||
s32 _40;
|
||||
s32 mPlayableSoundCount; // _44
|
||||
s32 _48;
|
||||
f32 mVolume; // _4C
|
||||
f32 mLowPassFreq; // _50
|
||||
s32 mFilterType; // _54
|
||||
f32 mBaseFreq; // _58
|
||||
u32 mDefaultOutputLine; // _5C
|
||||
f32 mOutputVolume; // _60
|
||||
u64 _64;
|
||||
u64 _6C;
|
||||
};
|
||||
}; // namespace atk
|
||||
}; // namespace nn
|
@ -0,0 +1,28 @@
|
||||
/**
|
||||
* @file AdvancedWaveSoundRuntime.h
|
||||
* @brief Runtime wave sound api.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <nn/types.h>
|
||||
|
||||
namespace nn {
|
||||
namespace atk {
|
||||
namespace detail {
|
||||
class AdvancedWaveSoundRuntime {
|
||||
public:
|
||||
AdvancedWaveSoundRuntime();
|
||||
~AdvancedWaveSoundRuntime();
|
||||
|
||||
void Initialize(s32, void**, void const*);
|
||||
void Finalize();
|
||||
s32 GetActiveCount() const;
|
||||
void SetupUserParam(void**, u64);
|
||||
void Update();
|
||||
|
||||
u8 _0[0x30];
|
||||
};
|
||||
}; // namespace detail
|
||||
}; // namespace atk
|
||||
}; // namespace nn
|
137
lib/NintendoSDK/include/nn/atk/detail/BasicSound.h
Normal file
137
lib/NintendoSDK/include/nn/atk/detail/BasicSound.h
Normal file
@ -0,0 +1,137 @@
|
||||
/**
|
||||
* @file BasicSound.h
|
||||
* @brief A basic sound.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <nn/types.h>
|
||||
|
||||
namespace nn {
|
||||
namespace atk {
|
||||
class SoundActor;
|
||||
|
||||
enum MixMode {
|
||||
|
||||
};
|
||||
|
||||
namespace detail {
|
||||
class PlayerHeap;
|
||||
class ExternalSoundPlayer;
|
||||
|
||||
class BasicSound {
|
||||
public:
|
||||
BasicSound();
|
||||
virtual ~BasicSound();
|
||||
|
||||
virtual void Initialize();
|
||||
virtual void Finalize();
|
||||
virtual bool IsPrepared() const = 0;
|
||||
virtual bool IsAttachedTempSpecialHandle() = 0;
|
||||
virtual void DetachTempSpecialHandle() = 0;
|
||||
virtual void OnUpdatePlayerPriority();
|
||||
virtual void UpdateMoveValue();
|
||||
virtual void OnUpdateParam();
|
||||
|
||||
void SetPriority(s32, s32);
|
||||
void GetPriority(s32*, s32*) const;
|
||||
void ClearIsFinalizedForCannotAllocatedResourceFlag();
|
||||
void SetId(u32 newID);
|
||||
bool IsAttachedGeneralHandle();
|
||||
void DetachGeneralHandle();
|
||||
bool IsAttachedTempGeneralHandle();
|
||||
void DetachTempGeneralHandle();
|
||||
void StartPrepared();
|
||||
void Stop(s32);
|
||||
void SetPlayerPriority(s32);
|
||||
void ForceStop();
|
||||
void Pause(bool, s32);
|
||||
void Mute(bool, s32);
|
||||
void SetAutoStopCounter(s32);
|
||||
void FadeIn(s32);
|
||||
bool IsPause() const;
|
||||
bool IsMute() const;
|
||||
void Update();
|
||||
void UpdateParam();
|
||||
void UpdateMoveValue();
|
||||
void CalculateVolume() const;
|
||||
f32 CalculatePitch() const;
|
||||
f32 CalculateLpfFrequency() const;
|
||||
u32 CalculateOutLineFlag() const;
|
||||
void CalculateBiquadFilter(s32*, f32*) const;
|
||||
void AttachPlayerHeap(nn::atk::detail::PlayerHeap*);
|
||||
void DetachPlayerHeap(nn::atk::detail::PlayerHeap*);
|
||||
void AttachSoundPlayer(nn::atk::SoundPlayer*);
|
||||
void DetachSoundPlayer(nn::atk::SoundPlayer*);
|
||||
void AttachSoundActor(nn::atk::SoundActor*);
|
||||
void DetachSoundActor(nn::atk::SoundActor*);
|
||||
void AttachExternalSoundPlayer(nn::atk::detail::ExternalSoundPlayer*);
|
||||
void DetachExternalSoundPlayer(nn::atk::detail::ExternalSoundPlayer*);
|
||||
u32 GetRemainingFadeFrames() const;
|
||||
u32 GetRemainingPauseFadeFrames() const;
|
||||
u32 GetRemainingMuteFadeFrames() const;
|
||||
void SetInitialVolume(f32 vol);
|
||||
f32 GetInitialVolume() const;
|
||||
void SetVolume(f32, s32);
|
||||
s32 GetVolume() const;
|
||||
void SetPitch(f32);
|
||||
f32 GetPitch() const;
|
||||
void SetLpfFreq(f32);
|
||||
f32 GetLpfFreq() const;
|
||||
void SetBiquadFilter(s32, f32);
|
||||
void GetBiquadFilter(s32*, f32*) const;
|
||||
void SetOutputLine(u32);
|
||||
u32 GetOutputLine() const;
|
||||
void ResetOutputLine();
|
||||
void SetMixMode(nn::atk::MixMode);
|
||||
nn::atk::MixMode GetMixMode();
|
||||
void SetPan(f32);
|
||||
f32 GetPan() const;
|
||||
void SetSurroundPan(f32);
|
||||
f32 GetSurroundPan() const;
|
||||
void SetMainSend(f32);
|
||||
f32 GetMainSend() const;
|
||||
|
||||
u64* _8; // nn::atk::detail::PlayerHeap*
|
||||
u64* _10; // nn::atk::SoundHandle*
|
||||
u64* _18; // nn::atk::SoundHandle*
|
||||
nn::atk::SoundPlayer* mSoundPlayer; // _20
|
||||
u64* _28; // nn::atk::SoundActor*
|
||||
u64* _30; // nn::atk::detail::ExternalSoundPlayer*
|
||||
u64* _38; // nn::atk::SoundArchive*
|
||||
u8 _40[0xF0 - 0x40];
|
||||
s32 mPriority; // _F0
|
||||
u32 _F4;
|
||||
u32 _F8;
|
||||
s32 mAutoStopCounter; // _FC
|
||||
u64 _100;
|
||||
u32 mID; // _108
|
||||
u32 _10C;
|
||||
u32 _110;
|
||||
u32 _114;
|
||||
f32 mInitialVolume; // _118
|
||||
f32 mPitch; // _11C
|
||||
f32 mLpfFreq; // _120
|
||||
f32 _124;
|
||||
u32 mOutputLine; // _128
|
||||
f32 _12C;
|
||||
f32 mVolume; // _130
|
||||
u32 _134;
|
||||
u32 _138;
|
||||
nn::atk::MixMode mMixMode; // _13C
|
||||
f32 mPan; // _140
|
||||
f32 mSurroundPan; // _144
|
||||
f32 mMainSend; // _148
|
||||
u8 _14C[0x158 - 0x14C];
|
||||
f32 mOutputVol; // _158
|
||||
u8 _15C[0x190 - 0x15C];
|
||||
f32 mOutputPan; // _190
|
||||
f32 mOutputSurroundPan; // _194
|
||||
f32 mOutputMainSend; // _198
|
||||
f32 mOutputFxSend; // _19C
|
||||
|
||||
static u64 g_LastInstanceId;
|
||||
};
|
||||
}; // namespace detail
|
||||
}; // namespace atk
|
||||
}; // namespace nn
|
37
lib/NintendoSDK/include/nn/atk/detail/SequenceSoundRuntime.h
Normal file
37
lib/NintendoSDK/include/nn/atk/detail/SequenceSoundRuntime.h
Normal file
@ -0,0 +1,37 @@
|
||||
/**
|
||||
* @file SequenceSoundRuntime.h
|
||||
* @brief Sequenced Sound Runtime Info
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <nn/types.h>
|
||||
|
||||
namespace nn {
|
||||
namespace atk {
|
||||
namespace detail {
|
||||
class SoundArchiveManager;
|
||||
|
||||
class SequenceSoundRuntime {
|
||||
public:
|
||||
SequenceSoundRuntime();
|
||||
~SequenceSoundRuntime();
|
||||
|
||||
void Initialize(s32, void**, void const*);
|
||||
void Finalize();
|
||||
void SetupSequenceTrack(s32, void**, void const*);
|
||||
void SetupUserParam(void**, u64);
|
||||
bool IsSoundArchiveAvailable() const;
|
||||
s32 GetActiveCount() const;
|
||||
s32 GetFreeCount() const;
|
||||
void SetSequenceSkipIntervalTick(s32 tick);
|
||||
s32 GetSequenceSkipIntervalTick();
|
||||
void Update();
|
||||
|
||||
u8 _0[0xD0];
|
||||
nn::atk::detail::SoundArchiveManager* mArchiveManager; // _D0
|
||||
u64 _D8;
|
||||
};
|
||||
}; // namespace detail
|
||||
}; // namespace atk
|
||||
}; // namespace nn
|
42
lib/NintendoSDK/include/nn/atk/detail/SoundArchiveManager.h
Normal file
42
lib/NintendoSDK/include/nn/atk/detail/SoundArchiveManager.h
Normal file
@ -0,0 +1,42 @@
|
||||
/**
|
||||
* @file SoundArchiveManager.h
|
||||
* @brief Sound archive manager implementation.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <nn/types.h>
|
||||
|
||||
namespace nn {
|
||||
namespace atk {
|
||||
class SoundHandle;
|
||||
class SoundArchive;
|
||||
class SoundDataManager;
|
||||
|
||||
namespace detail {
|
||||
class AddonSoundArchiveContainer;
|
||||
|
||||
class SoundArchiveManager {
|
||||
public:
|
||||
SoundArchiveManager();
|
||||
|
||||
virtual ~SoundArchiveManager();
|
||||
|
||||
void Initialize(nn::atk::SoundArchive const*, nn::atk::SoundDataManager const*);
|
||||
void ChangeTargetArchive(char const*);
|
||||
void Finalize();
|
||||
bool IsAvailable() const;
|
||||
nn::atk::detail::AddonSoundArchiveContainer* GetAddonSoundArchive(char const*) const;
|
||||
|
||||
u64 _8;
|
||||
u64* _10;
|
||||
nn::atk::detail::AddonSoundArchiveContainer* _18;
|
||||
u64* _20;
|
||||
nn::atk::SoundArchive* mSoundArchive; // _28
|
||||
u64 _30;
|
||||
u64 _38;
|
||||
u64 _40;
|
||||
};
|
||||
}; // namespace detail
|
||||
}; // namespace atk
|
||||
}; // namespace nn
|
22
lib/NintendoSDK/include/nn/atk/detail/StreamSoundRuntime.h
Normal file
22
lib/NintendoSDK/include/nn/atk/detail/StreamSoundRuntime.h
Normal file
@ -0,0 +1,22 @@
|
||||
/**
|
||||
* @file StreamSoundRuntime.h
|
||||
* @brief Stream sound runtime information.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <nn/types.h>
|
||||
|
||||
namespace nn {
|
||||
namespace atk {
|
||||
namespace detail {
|
||||
class StreamSoundRuntime {
|
||||
public:
|
||||
StreamSoundRuntime();
|
||||
~StreamSoundRuntime();
|
||||
|
||||
u8 _0[0xB0];
|
||||
};
|
||||
}; // namespace detail
|
||||
}; // namespace atk
|
||||
}; // namespace nn
|
29
lib/NintendoSDK/include/nn/atk/detail/WaveSoundRuntime.h
Normal file
29
lib/NintendoSDK/include/nn/atk/detail/WaveSoundRuntime.h
Normal file
@ -0,0 +1,29 @@
|
||||
/**
|
||||
* @file WaveSoundRuntime.h
|
||||
* @brief Wave sound runtime info.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <nn/types.h>
|
||||
|
||||
namespace nn {
|
||||
namespace atk {
|
||||
namespace detail {
|
||||
class WaveSoundRuntime {
|
||||
public:
|
||||
WaveSoundRuntime();
|
||||
~WaveSoundRuntime();
|
||||
|
||||
void Initialize(s32, void**, void const*);
|
||||
void Finalize();
|
||||
s32 GetActiveCount() const;
|
||||
s32 GetFreeWaveSoundCount() const;
|
||||
void SetupUserParam(void**, u64);
|
||||
void Update();
|
||||
|
||||
u8 _0[0x80];
|
||||
};
|
||||
}; // namespace detail
|
||||
}; // namespace atk
|
||||
}; // namespace nn
|
344
lib/NintendoSDK/include/nn/audio.h
Normal file
344
lib/NintendoSDK/include/nn/audio.h
Normal file
@ -0,0 +1,344 @@
|
||||
/**
|
||||
* @file audio.h
|
||||
* @brief Audio implementation.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <nn/os.h>
|
||||
#include <nn/types.h>
|
||||
|
||||
namespace nn {
|
||||
namespace audio {
|
||||
// Common audio
|
||||
struct AudioDeviceName {
|
||||
char raw_name[0x100];
|
||||
};
|
||||
|
||||
static_assert(sizeof(AudioDeviceName) == 0x100);
|
||||
|
||||
void AcquireAudioDeviceSwitchNotification(nn::os::SystemEvent* event);
|
||||
s32 ListAudioDeviceName(nn::audio::AudioDeviceName* buffer, s32 bufferCount);
|
||||
Result SetAudioDeviceOutputVolume(nn::audio::AudioDeviceName const* device, float volume);
|
||||
u32 GetActiveChannelCount();
|
||||
|
||||
struct AudioRendererConfig {
|
||||
u64* _0;
|
||||
u64* _8;
|
||||
u64* _10;
|
||||
u64* _18;
|
||||
u64* _20;
|
||||
u64* _28;
|
||||
u64* _30;
|
||||
u64* _38;
|
||||
u64* _40;
|
||||
u64* _48;
|
||||
u64* _50;
|
||||
};
|
||||
|
||||
enum AudioRendererRenderingDevice : u32 {
|
||||
AudioRendererRenderingDevice_Cpu,
|
||||
AudioRendererRenderingDevice_Dsp
|
||||
};
|
||||
|
||||
enum AudioRendererExecutionMode : u32 {
|
||||
AudioRendererExecutionMode_Manual,
|
||||
AudioRendererExecutionMode_Auto,
|
||||
};
|
||||
|
||||
enum SampleFormat : u32 {
|
||||
SampleFormat_Invalid,
|
||||
SampleFormat_PcmInt8,
|
||||
SampleFormat_PcmInt16,
|
||||
SampleFormat_PcmInt24,
|
||||
SampleFormat_PcmInt32,
|
||||
SampleFormat_PcmFloat,
|
||||
SampleFormat_Adpcm,
|
||||
};
|
||||
|
||||
enum MemoryPoolState : u32 {
|
||||
MemoryPoolState_Invalid,
|
||||
MemoryPoolState_New,
|
||||
MemoryPoolState_RequestDetach,
|
||||
MemoryPoolState_Detached,
|
||||
MemoryPoolState_RequestAttach,
|
||||
MemoryPoolState_Attached,
|
||||
MemoryPoolState_Released,
|
||||
};
|
||||
|
||||
struct AudioRendererParameter {
|
||||
u32 sampleRate;
|
||||
u32 sampleCount;
|
||||
u32 mixBufferCount;
|
||||
u32 subMixCount;
|
||||
u32 voiceCount;
|
||||
u32 sinkCount;
|
||||
u32 effectCount;
|
||||
u32 performanceFrameCount;
|
||||
bool isVoiceDropEnabled;
|
||||
u32 splitterCount;
|
||||
u32 splitterSendChannelCount;
|
||||
AudioRendererRenderingDevice renderingDevice;
|
||||
AudioRendererExecutionMode executionMode;
|
||||
u32 _34;
|
||||
u32 revision;
|
||||
};
|
||||
|
||||
static_assert(sizeof(AudioRendererParameter) == 0x3C);
|
||||
|
||||
struct BiquadFilterParameter {
|
||||
bool enabled;
|
||||
s16 numerator[3];
|
||||
s16 denominator[2];
|
||||
};
|
||||
|
||||
static_assert(sizeof(BiquadFilterParameter) == 0xC);
|
||||
|
||||
struct WaveBuffer {
|
||||
void* buffer;
|
||||
size_t bufferSize;
|
||||
s32 startSampleOffset;
|
||||
s32 endSampleOffset;
|
||||
bool shouldLoop;
|
||||
bool isEndOfStream;
|
||||
void* context;
|
||||
size_t contextSize;
|
||||
};
|
||||
|
||||
static_assert(sizeof(WaveBuffer) == 0x30);
|
||||
|
||||
struct AudioRendererHandle {
|
||||
u64* _0;
|
||||
u64* _8;
|
||||
};
|
||||
|
||||
struct MemoryPoolType {
|
||||
u64* _0;
|
||||
};
|
||||
|
||||
struct CircularBufferSinkType {
|
||||
u64* _0;
|
||||
};
|
||||
|
||||
struct AuxType {
|
||||
u64* _0;
|
||||
};
|
||||
|
||||
struct DelayType {
|
||||
u64* _0;
|
||||
};
|
||||
|
||||
struct FinalMixType {
|
||||
u64* _0;
|
||||
};
|
||||
|
||||
struct SubMixType {
|
||||
u64* _0;
|
||||
};
|
||||
|
||||
struct VoiceType {
|
||||
u64* _0;
|
||||
|
||||
enum PlayState : u32 {
|
||||
PlayState_Start,
|
||||
PlayState_Stop,
|
||||
PlayState_Pause,
|
||||
};
|
||||
};
|
||||
|
||||
struct DeviceSinkType {
|
||||
u64* _0;
|
||||
};
|
||||
|
||||
// Audio Renderer base APIs
|
||||
void InitializeAudioRendererParameter(nn::audio::AudioRendererParameter* inParameter);
|
||||
bool IsValidAudioRendererParameter(nn::audio::AudioRendererParameter const& inParameter);
|
||||
size_t GetAudioRendererWorkBufferSize(nn::audio::AudioRendererParameter const& inParameter);
|
||||
size_t GetAudioRendererConfigWorkBufferSize(nn::audio::AudioRendererParameter const& inParameter);
|
||||
Result InitializeAudioRendererConfig(nn::audio::AudioRendererConfig* outConfig,
|
||||
nn::audio::AudioRendererParameter const& inParameter,
|
||||
void* buffer, size_t bufferSize);
|
||||
Result OpenAudioRenderer(nn::audio::AudioRendererHandle* outHandle,
|
||||
nn::audio::AudioRendererParameter const& inParameter, void* workBuffer,
|
||||
size_t workBufferSize);
|
||||
void CloseAudioRenderer(nn::audio::AudioRendererHandle handle);
|
||||
Result StartAudioRenderer(nn::audio::AudioRendererHandle handle);
|
||||
Result StopAudioRenderer(nn::audio::AudioRendererHandle handle);
|
||||
Result RequestUpdateAudioRenderer(nn::audio::AudioRendererHandle handle,
|
||||
nn::audio::AudioRendererConfig const* config);
|
||||
|
||||
// Audio Renderer MemoryPool APIs
|
||||
bool IsMemoryPoolAttached(nn::audio::MemoryPoolType const* pool);
|
||||
bool RequestAttachMemoryPool(nn::audio::MemoryPoolType* pool);
|
||||
bool RequestDetachMemoryPool(nn::audio::MemoryPoolType* pool);
|
||||
bool AcquireMemoryPool(nn::audio::AudioRendererConfig* config, nn::audio::MemoryPoolType* outPool,
|
||||
void* address, size_t size);
|
||||
void ReleaseMemoryPool(nn::audio::AudioRendererConfig* config, nn::audio::MemoryPoolType* pool);
|
||||
void* GetMemoryPoolAddress(nn::audio::MemoryPoolType const* pool);
|
||||
size_t GetMemoryPoolSize(nn::audio::MemoryPoolType const* pool);
|
||||
MemoryPoolState GetMemoryPoolState(nn::audio::MemoryPoolType const* pool);
|
||||
|
||||
// Audio Renderer Effect APIs
|
||||
void SetDelayInputOutput(nn::audio::DelayType* delay, s8 const* input, s8 const* output, s32 count);
|
||||
void* RemoveDelay(nn::audio::AudioRendererConfig* config, nn::audio::DelayType* delay,
|
||||
nn::audio::FinalMixType* mix);
|
||||
void* RemoveDelay(nn::audio::AudioRendererConfig* config, nn::audio::DelayType* delay,
|
||||
nn::audio::SubMixType* mix);
|
||||
bool IsDelayRemovable(nn::audio::DelayType* delay);
|
||||
|
||||
size_t GetRequiredBufferSizeForAuxSendReturnBuffer(nn::audio::AudioRendererParameter const* config,
|
||||
s32 mixBufferFrameCount, s32 channelCount);
|
||||
Result AddAux(nn::audio::AudioRendererConfig* config, nn::audio::AuxType* aux,
|
||||
nn::audio::FinalMixType* mix, void* sendBuffer, void* returnBuffer,
|
||||
size_t bufferSize);
|
||||
Result AddAux(nn::audio::AudioRendererConfig* config, nn::audio::AuxType* aux,
|
||||
nn::audio::SubMixType* mix, void* sendBuffer, void* returnBuffer, size_t bufferSize);
|
||||
void RemoveAux(nn::audio::AudioRendererConfig* config, nn::audio::AuxType* aux,
|
||||
nn::audio::FinalMixType* mix);
|
||||
void RemoveAux(nn::audio::AudioRendererConfig* config, nn::audio::AuxType* aux,
|
||||
nn::audio::SubMixType* mix);
|
||||
void SetAuxEnabled(nn::audio::AuxType* aux, bool enable);
|
||||
void SetAuxInputOutput(nn::audio::AuxType* aux, s8 const* input, s8 const* output, s32 count);
|
||||
bool IsAuxRemovable(nn::audio::AuxType* aux);
|
||||
s32 GetAuxSampleCount(nn::audio::AuxType const* aux);
|
||||
s32 GetAuxSampleRate(nn::audio::AuxType const* aux);
|
||||
s32 ReadAuxSendBuffer(nn::audio::AuxType* aux, s32* buffer, s32 count);
|
||||
s32 WriteAuxReturnBuffer(nn::audio::AuxType* aux, s32 const* buffer, s32 count);
|
||||
|
||||
// Audio Renderer Performance APIs
|
||||
size_t
|
||||
GetRequiredBufferSizeForPerformanceFrames(nn::audio::AudioRendererParameter const& inParameter);
|
||||
void* SetPerformanceFrameBuffer(nn::audio::AudioRendererConfig* config, void* buffer,
|
||||
size_t bufferSize);
|
||||
|
||||
enum PerformanceEntryType : u8 {
|
||||
PerformanceEntryType_Invalid,
|
||||
PerformanceEntryType_Voice,
|
||||
PerformanceEntryType_SubMix,
|
||||
PerformanceEntryType_FinalMix,
|
||||
PerformanceEntryType_Sink
|
||||
};
|
||||
|
||||
struct PerformanceEntry {
|
||||
s32 nodeId;
|
||||
s32 startTime;
|
||||
s32 processingTime;
|
||||
PerformanceEntryType entryType;
|
||||
};
|
||||
|
||||
static_assert(sizeof(PerformanceEntry) == 0x10);
|
||||
|
||||
enum PerformanceDetailType : u8 {
|
||||
PerformanceDetailType_Unknown,
|
||||
PerformanceDetailType_PcmInt16,
|
||||
PerformanceDetailType_Adpcm,
|
||||
PerformanceDetailType_VolumeRamp,
|
||||
PerformanceDetailType_BiquadFilter,
|
||||
PerformanceDetailType_Mix,
|
||||
PerformanceDetailType_Delay,
|
||||
PerformanceDetailType_Aux,
|
||||
PerformanceDetailType_Reverb,
|
||||
PerformanceDetailType_Reverb3d,
|
||||
PerformanceDetailType_PcmFloat
|
||||
};
|
||||
|
||||
struct PerformanceDetail {
|
||||
s32 nodeId;
|
||||
s32 startTime;
|
||||
s32 processingTime;
|
||||
PerformanceDetailType detailType;
|
||||
PerformanceEntryType entryType;
|
||||
};
|
||||
|
||||
static_assert(sizeof(PerformanceDetail) == 0x10);
|
||||
|
||||
class PerformanceInfo {
|
||||
public:
|
||||
PerformanceInfo();
|
||||
~PerformanceInfo();
|
||||
|
||||
bool SetBuffer(void const* buffer, size_t bufferSize);
|
||||
bool MoveToNextFrame();
|
||||
s32 GetTotalProcessingTime();
|
||||
PerformanceEntry GetEntries(s32* count);
|
||||
PerformanceDetail GetDetails(s32* count);
|
||||
|
||||
private:
|
||||
void* buffer;
|
||||
size_t bufferSize;
|
||||
void* header;
|
||||
PerformanceEntry* entries;
|
||||
PerformanceDetail* details;
|
||||
};
|
||||
|
||||
static_assert(sizeof(PerformanceInfo) == 0x28);
|
||||
|
||||
// Audio Renderer Sink APIs
|
||||
Result AddDeviceSink(nn::audio::AudioRendererConfig* config, nn::audio::DeviceSinkType* sink,
|
||||
nn::audio::FinalMixType* mix, s8 const* input, s32 inputCount,
|
||||
char const* deviceName);
|
||||
void RemoveDeviceSink(nn::audio::AudioRendererConfig* config, nn::audio::DeviceSinkType* sink,
|
||||
nn::audio::FinalMixType* mix);
|
||||
u32 GetSinkNodeId(nn::audio::DeviceSinkType const* sink);
|
||||
|
||||
Result AddCircularBufferSink(nn::audio::AudioRendererConfig* config,
|
||||
nn::audio::CircularBufferSinkType* sink, nn::audio::FinalMixType* mix,
|
||||
s8 const* input, s32 inputCount, void* buffer, size_t bufferSize,
|
||||
nn::audio::SampleFormat sampleFormat);
|
||||
void RemoveCircularBufferSink(nn::audio::AudioRendererConfig* config,
|
||||
nn::audio::CircularBufferSinkType* sink,
|
||||
nn::audio::FinalMixType* mix);
|
||||
size_t ReadCircularBufferSink(nn::audio::CircularBufferSinkType* sink, void* buffer,
|
||||
size_t buffer_size);
|
||||
u32 GetSinkNodeId(nn::audio::CircularBufferSinkType const* sink);
|
||||
size_t
|
||||
GetRequiredBufferSizeForCircularBufferSink(nn::audio::AudioRendererParameter const* inParameter,
|
||||
s32 inputCount, s32 frameCount,
|
||||
nn::audio::SampleFormat sampleFormat);
|
||||
|
||||
// Audio Renderer Mix APIs
|
||||
bool AcquireFinalMix(nn::audio::AudioRendererConfig* config, nn::audio::FinalMixType* mix,
|
||||
s32 bufferCount);
|
||||
bool AcquireSubMix(nn::audio::AudioRendererConfig* config, nn::audio::SubMixType* mix,
|
||||
s32 sampleRate, s32 bufferCount);
|
||||
void ReleaseSubMix(nn::audio::AudioRendererConfig* config, nn::audio::SubMixType* mix);
|
||||
void SetSubMixDestination(nn::audio::AudioRendererConfig* config, nn::audio::SubMixType* source,
|
||||
nn::audio::FinalMixType* destination);
|
||||
void SetSubMixDestination(nn::audio::AudioRendererConfig* config, nn::audio::SubMixType* source,
|
||||
nn::audio::SubMixType* destination);
|
||||
void SetSubMixMixVolume(nn::audio::SubMixType* source, nn::audio::FinalMixType* destination,
|
||||
float volume, s32 sourceIndex, s32 destinationIndex);
|
||||
void SetSubMixMixVolume(nn::audio::SubMixType* source, nn::audio::SubMixType* destination,
|
||||
float volume, s32 sourceIndex, s32 destinationIndex);
|
||||
u32 GetSubMixNodeId(nn::audio::SubMixType const* mix);
|
||||
|
||||
// Audio Renderer Voice APIs
|
||||
Result AcquireVoiceSlot(nn::audio::AudioRendererConfig* config, nn::audio::VoiceType* voice,
|
||||
s32 sampleRate, s32 channelCount, nn::audio::SampleFormat sampleFormat,
|
||||
s32 priority, void const* buffer, size_t bufferSize);
|
||||
void ReleaseVoiceSlot(nn::audio::AudioRendererConfig* config, nn::audio::VoiceType* voice);
|
||||
bool IsVoiceValid(nn::audio::VoiceType const* voice);
|
||||
bool IsVoiceDroppedFlagOn(nn::audio::VoiceType const* voice);
|
||||
void ResetVoiceDroppedFlag(nn::audio::VoiceType* voice);
|
||||
void SetVoiceDestination(nn::audio::AudioRendererConfig* config, nn::audio::VoiceType* voice,
|
||||
nn::audio::FinalMixType* mix);
|
||||
void SetVoiceDestination(nn::audio::AudioRendererConfig* config, nn::audio::VoiceType* voice,
|
||||
nn::audio::SubMixType* mix);
|
||||
void SetVoiceVolume(nn::audio::VoiceType* config, float volume);
|
||||
void SetVoicePitch(nn::audio::VoiceType* config, float pitch);
|
||||
void SetVoicePlayState(nn::audio::VoiceType* voice, nn::audio::VoiceType::PlayState state);
|
||||
void SetVoicePriority(nn::audio::VoiceType* voice, s32 priority);
|
||||
void SetVoiceBiquadFilterParameter(nn::audio::VoiceType* voice, s32 index,
|
||||
nn::audio::BiquadFilterParameter const& biquadFilterParameter);
|
||||
void SetVoiceMixVolume(nn::audio::VoiceType* voice, nn::audio::FinalMixType* mix, float volume,
|
||||
int sourceIndex, int destinationIndex);
|
||||
void SetVoiceMixVolume(nn::audio::VoiceType* voice, nn::audio::SubMixType* mix, float volume,
|
||||
int sourceIndex, int destinationIndex);
|
||||
nn::audio::VoiceType::PlayState GetVoicePlayState(nn::audio::VoiceType const* voice);
|
||||
s32 GetVoicePriority(nn::audio::VoiceType const* voice);
|
||||
u64 GetVoicePlayedSampleCount(nn::audio::VoiceType const* voice);
|
||||
u32 GetVoiceNodeId(nn::audio::VoiceType const* voice);
|
||||
bool AppendWaveBuffer(nn::audio::VoiceType* voice, nn::audio::WaveBuffer const* waveBuffer);
|
||||
nn::audio::WaveBuffer* GetReleasedWaveBuffer(nn::audio::VoiceType* voice);
|
||||
}; // namespace audio
|
||||
}; // namespace nn
|
112
lib/NintendoSDK/include/nn/bcat.h
Normal file
112
lib/NintendoSDK/include/nn/bcat.h
Normal file
@ -0,0 +1,112 @@
|
||||
/**
|
||||
* @file bcat.h
|
||||
* @brief BCAT service implementation.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <nn/os.h>
|
||||
#include <nn/types.h>
|
||||
|
||||
namespace nn {
|
||||
|
||||
namespace bcat {
|
||||
|
||||
struct DirectoryName {
|
||||
void isValid();
|
||||
};
|
||||
|
||||
struct FileName {
|
||||
void isValid();
|
||||
};
|
||||
|
||||
class DeliveryCacheDirectory {
|
||||
public:
|
||||
DeliveryCacheDirectory();
|
||||
~DeliveryCacheDirectory();
|
||||
Result Open(nn::bcat::DirectoryName const&);
|
||||
Result GetCount();
|
||||
Result Close();
|
||||
};
|
||||
|
||||
class DeliveryCacheFile {
|
||||
public:
|
||||
DeliveryCacheFile();
|
||||
~DeliveryCacheFile();
|
||||
Result Open(nn::bcat::DirectoryName const&, nn::bcat::FileName const&);
|
||||
Result Read(size_t file1, s64, void*, size_t file2);
|
||||
Result GetSize();
|
||||
Result GetDigest();
|
||||
Result Close();
|
||||
};
|
||||
|
||||
class DeliveryCacheProgress {
|
||||
public:
|
||||
DeliveryCacheProgress();
|
||||
~DeliveryCacheProgress();
|
||||
Result Detach();
|
||||
Result Update();
|
||||
Result GetStatus();
|
||||
Result GetCurrentDirectoryName();
|
||||
Result GetCurrentFileName();
|
||||
Result GetCurrentDownloaded();
|
||||
Result GetCurrentTotale();
|
||||
Result GetWholeDownloaded();
|
||||
Result GetWholeTotal();
|
||||
Result GetResult();
|
||||
// void Attach(nn::bcat::detail::ipc::IDeliveryCacheProgressService*);
|
||||
};
|
||||
|
||||
namespace detail {
|
||||
|
||||
namespace DeliveryCacheProgressImpl {
|
||||
Result Clear();
|
||||
Result NotifyStartConnect();
|
||||
Result NotifyStartProcessList();
|
||||
Result SetWholeDownloadSize(s64);
|
||||
Result SetDownloadProgress(s64, nn::bcat::DirectoryName const&, nn::bcat::FileName const&, s64);
|
||||
Result NotifyStartDownloadFile(nn::bcat::DirectoryName const&, nn::bcat::FileName const&, s64);
|
||||
Result UpdateDownloadFileProgress(s64);
|
||||
Result NotifyStartCommitDirectory(nn::bcat::DirectoryName const&);
|
||||
Result NotifyDone(nn::Result);
|
||||
|
||||
} // namespace DeliveryCacheProgressImpl
|
||||
class ShimLibraryGlobal {
|
||||
public:
|
||||
ShimLibraryGlobal();
|
||||
~ShimLibraryGlobal();
|
||||
Result Initialize();
|
||||
Result GetSession();
|
||||
Result MountDeliveryCacheStorage();
|
||||
Result IsDeliveryCacheStorageMounted();
|
||||
Result UnmountDeliveryCacheStorage();
|
||||
// void CreateFileService(nn::bcat::detail::ipc::IDeliveryCacheFileService**);
|
||||
// void CreateDirectoryService(nn::bcat::detail::ipc::IDeliveryCacheDirectoryService**)
|
||||
Result IncrementDeliveryCacheFileCount();
|
||||
Result DecrementDeliveryCacheFileCount();
|
||||
Result IncrementDeliveryCacheDirectoryCount();
|
||||
Result DecrementDeliveryCacheFileCount();
|
||||
Result EnumerateDeliveryCacheDirectory(int*, nn::bcat::DirectoryName*, int);
|
||||
};
|
||||
|
||||
namespace ipc {
|
||||
Result Initialize();
|
||||
// void CreateBcatService(nn::bcat::detail::ipc::IBcatService**);
|
||||
Result Finalize();
|
||||
// void CreateBcatService(nn::bcat::detail::ipc::IBcatService**);
|
||||
// void CreateDeliveryCacheStorageService(nn::bcat::detail::ipc::IDeliveryCacheStorageService**);
|
||||
// void CreateDeliveryCacheStorageService(nn::bcat::detail::ipc::IDeliveryCacheStorageService**,
|
||||
// nn::ApplicationId);
|
||||
|
||||
} // namespace ipc
|
||||
} // namespace detail
|
||||
|
||||
Result Initialize();
|
||||
Result MountDeliveryCacheStorage();
|
||||
Result UnmountDeliveryCacheStorage();
|
||||
Result EnumerateDeliveryCacheDirectory(int*, nn::bcat::DirectoryName*, int);
|
||||
Result RequestSyncDeliveryCache(nn::bcat::DeliveryCacheProgress*);
|
||||
Result EnumerateDeliveryCacheDirectory(int*, nn::bcat::DirectoryName*, int);
|
||||
|
||||
} // namespace bcat
|
||||
} // namespace nn
|
86
lib/NintendoSDK/include/nn/crypto.h
Normal file
86
lib/NintendoSDK/include/nn/crypto.h
Normal file
@ -0,0 +1,86 @@
|
||||
/**
|
||||
* @file crypto.h
|
||||
* @brief Crypto service implementation.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <nn/types.h>
|
||||
|
||||
namespace nn {
|
||||
namespace crypto {
|
||||
void GenerateSha256Hash(void*, ulong, void const*, ulong);
|
||||
|
||||
class Sha256Context;
|
||||
|
||||
void DecryptAes128Cbc(void*, u64, void const*, u64, void const*, u64, void const*, u64);
|
||||
void EncryptAes128Cbc(void*, u64, void const*, u64, void const*, u64, void const*, u64);
|
||||
void DecryptAes128Ccm(void*, u64, void*, u64, void const*, u64, void const*, u64, void const*, u64,
|
||||
void const*, u64, u64);
|
||||
|
||||
namespace detail {
|
||||
class Md5Impl {
|
||||
public:
|
||||
void Initialize();
|
||||
void Update(void const*, u64 dataSize);
|
||||
void ProcessBlock();
|
||||
void GetHash(void*, u64 hashSize);
|
||||
void ProcessLastBlock();
|
||||
|
||||
u32 _x0;
|
||||
u32 _x4;
|
||||
u32 _x8;
|
||||
u32 _xC;
|
||||
u8 _x10[0x50 - 0x10];
|
||||
u64 _x50;
|
||||
u32 _x58;
|
||||
};
|
||||
|
||||
class Sha1Impl {
|
||||
public:
|
||||
void Initialize();
|
||||
void Update(void const*, u64);
|
||||
void ProcessBlock(void const*);
|
||||
void GetHash(void* destHash, u64);
|
||||
void ProcessLastBlock();
|
||||
|
||||
u64 _x0;
|
||||
u64 _x8;
|
||||
u32 _x10;
|
||||
u128 _x14;
|
||||
u128 _x24;
|
||||
u128 _x34;
|
||||
u32 _x44;
|
||||
u64 _x48;
|
||||
u64 _x50;
|
||||
u64 _x58;
|
||||
u64 _x60;
|
||||
};
|
||||
|
||||
class Sha256Impl {
|
||||
public:
|
||||
void Initialize();
|
||||
void Update(void const*, u64);
|
||||
void ProcessBlocks(u8 const*, u64);
|
||||
void GetHash(void* destHash, u64);
|
||||
void ProcessLastBlock();
|
||||
void InitializeWithContext(nn::crypto::Sha256Context const*);
|
||||
void GetContext(nn::crypto::Sha256Context*) const;
|
||||
|
||||
u64 _x0;
|
||||
u64 _x8;
|
||||
u32 _x10;
|
||||
u128 _x14;
|
||||
u128 _x24;
|
||||
u128 _x34;
|
||||
u32 _x44;
|
||||
u64 _x48;
|
||||
u64 _x50;
|
||||
u64 _x58;
|
||||
u64 _x60;
|
||||
u64 _x68;
|
||||
u32 _x70;
|
||||
};
|
||||
}; // namespace detail
|
||||
}; // namespace crypto
|
||||
}; // namespace nn
|
33
lib/NintendoSDK/include/nn/diag.h
Normal file
33
lib/NintendoSDK/include/nn/diag.h
Normal file
@ -0,0 +1,33 @@
|
||||
/**
|
||||
* @file diag.h
|
||||
* @brief Module, logging, and symbol operations.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <nn/types.h>
|
||||
|
||||
namespace nn {
|
||||
namespace diag {
|
||||
struct LogMetaData;
|
||||
|
||||
struct ModuleInfo {
|
||||
char* mPath;
|
||||
u64 mBaseAddr;
|
||||
u64 mSize;
|
||||
};
|
||||
|
||||
namespace detail {
|
||||
// LOG
|
||||
void LogImpl(nn::diag::LogMetaData const&, char const*, ...);
|
||||
void AbortImpl(char const*, char const*, char const*, s32);
|
||||
void AbortImpl(char const*, char const*, char const*, int, Result);
|
||||
}; // namespace detail
|
||||
|
||||
// MODULE / SYMBOL
|
||||
u32* GetSymbolName(char* name, u64 nameSize, u64 addr);
|
||||
u64 GetRequiredBufferSizeForGetAllModuleInfo();
|
||||
s32 GetAllModuleInfo(nn::diag::ModuleInfo** out, void* buffer, u64 bufferSize);
|
||||
u64 GetSymbolSize(u64 addr);
|
||||
}; // namespace diag
|
||||
}; // namespace nn
|
31
lib/NintendoSDK/include/nn/err.h
Normal file
31
lib/NintendoSDK/include/nn/err.h
Normal file
@ -0,0 +1,31 @@
|
||||
#pragma once
|
||||
|
||||
#include <nn/settings.h>
|
||||
|
||||
namespace nn {
|
||||
namespace err {
|
||||
enum ErrorCodeCategoryType : u32 {
|
||||
unk1,
|
||||
unk2,
|
||||
};
|
||||
|
||||
class ApplicationErrorArg {
|
||||
public:
|
||||
ApplicationErrorArg();
|
||||
ApplicationErrorArg(u32 error_code, const char* dialog_message, const char* fullscreen_message,
|
||||
const nn::settings::LanguageCode& languageCode);
|
||||
void SetApplicationErrorCodeNumber(u32 error_code);
|
||||
void SetDialogMessage(const char* message);
|
||||
void SetFullScreenMessage(const char* message);
|
||||
|
||||
u64 unk;
|
||||
u32 error_code;
|
||||
nn::settings::LanguageCode language_code;
|
||||
char dialog_message[2048];
|
||||
char fullscreen_message[2048];
|
||||
};
|
||||
|
||||
u32 MakeErrorCode(ErrorCodeCategoryType err_category_type, u32 errorCodeNumber);
|
||||
void ShowApplicationError(const ApplicationErrorArg& arg);
|
||||
} // namespace err
|
||||
} // namespace nn
|
42
lib/NintendoSDK/include/nn/friends.h
Normal file
42
lib/NintendoSDK/include/nn/friends.h
Normal file
@ -0,0 +1,42 @@
|
||||
/**
|
||||
* @file friends.h
|
||||
* @brief Friend implementation.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <nn/account.h>
|
||||
#include <nn/os.h>
|
||||
|
||||
namespace nn {
|
||||
namespace friends {
|
||||
typedef char Url[0xA0];
|
||||
|
||||
class AsyncContext;
|
||||
class Profile;
|
||||
|
||||
void Initialize();
|
||||
Result GetProfileList(nn::friends::AsyncContext* context, nn::friends::Profile* profiles,
|
||||
nn::account::Uid const& userID,
|
||||
nn::account::NetworkServiceAccountId const* accountIDs, s32 numAccounts);
|
||||
|
||||
class Profile {
|
||||
public:
|
||||
Profile();
|
||||
|
||||
nn::account::NetworkServiceAccountId GetAccountId() const;
|
||||
nn::account::Nickname& GetNickname() const;
|
||||
bool IsValid() const;
|
||||
Result GetProfileImageUrl(nn::friends::Url*, s32);
|
||||
};
|
||||
|
||||
class AsyncContext {
|
||||
public:
|
||||
AsyncContext();
|
||||
~AsyncContext();
|
||||
|
||||
Result GetSystemEvent(nn::os::SystemEvent*);
|
||||
Result GetResult() const;
|
||||
};
|
||||
}; // namespace friends
|
||||
}; // namespace nn
|
132
lib/NintendoSDK/include/nn/fs.h
Normal file
132
lib/NintendoSDK/include/nn/fs.h
Normal file
@ -0,0 +1,132 @@
|
||||
/**
|
||||
* @file fs.h
|
||||
* @brief Filesystem implementation.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <nn/account.h>
|
||||
#include <nn/types.h>
|
||||
|
||||
namespace nn {
|
||||
typedef u64 ApplicationId;
|
||||
|
||||
namespace fs {
|
||||
using namespace ams::fs;
|
||||
|
||||
typedef u64 UserId;
|
||||
|
||||
struct DirectoryEntry {
|
||||
char name[0x300 + 1];
|
||||
char _x302[3];
|
||||
u8 type;
|
||||
char _x304;
|
||||
s64 fileSize;
|
||||
};
|
||||
|
||||
struct FileHandle {
|
||||
void* handle;
|
||||
};
|
||||
|
||||
struct DirectoryHandle {
|
||||
void* handle;
|
||||
};
|
||||
|
||||
enum DirectoryEntryType { DirectoryEntryType_Directory, DirectoryEntryType_File };
|
||||
|
||||
enum OpenMode {
|
||||
OpenMode_Read = 1 << 0,
|
||||
OpenMode_Write = 1 << 1,
|
||||
OpenMode_Append = 1 << 2,
|
||||
|
||||
OpenMode_ReadWrite = OpenMode_Read | OpenMode_Write
|
||||
};
|
||||
|
||||
enum OpenDirectoryMode {
|
||||
OpenDirectoryMode_Directory = 1 << 0,
|
||||
OpenDirectoryMode_File = 1 << 1,
|
||||
OpenDirectoryMode_All = OpenDirectoryMode_Directory | OpenDirectoryMode_File,
|
||||
};
|
||||
|
||||
struct ReadOption {
|
||||
u32 value;
|
||||
|
||||
static const ReadOption None;
|
||||
};
|
||||
inline constexpr const ReadOption ReadOption::None = {0};
|
||||
|
||||
enum WriteOptionFlag {
|
||||
WriteOptionFlag_Flush = 1 << 0,
|
||||
};
|
||||
|
||||
struct WriteOption {
|
||||
int flags;
|
||||
|
||||
static WriteOption CreateOption(int flags) {
|
||||
WriteOption op;
|
||||
op.flags = flags;
|
||||
return op;
|
||||
}
|
||||
};
|
||||
|
||||
// ROM
|
||||
Result QueryMountRomCacheSize(size_t* size);
|
||||
Result QueryMountRomCacheSize(size_t* size, nn::ApplicationId);
|
||||
Result QueryMountAddOnContentCacheSize(size_t* size, int id);
|
||||
Result MountRom(char const* name, void* cache, size_t cache_size);
|
||||
Result MountAddOnContent(char const* name, int id, void* cache, size_t cache_size);
|
||||
bool CanMountRomForDebug();
|
||||
Result CanMountRom(nn::ApplicationId);
|
||||
Result QueryMountRomOnFileCacheSize(u64*, nn::fs::FileHandle);
|
||||
Result MountRomOnFile(char const*, nn::fs::FileHandle, void*, u64);
|
||||
|
||||
// SAVE
|
||||
Result EnsureSaveData(nn::account::Uid const&);
|
||||
Result MountSaveData(char const*, nn::fs::UserId);
|
||||
Result MountSaveDataForDebug(char const*);
|
||||
Result CommitSaveData(const char* path);
|
||||
|
||||
// FILE
|
||||
Result GetEntryType(nn::fs::DirectoryEntryType* type, char const* path);
|
||||
Result CreateFile(char const* filepath, s64 size);
|
||||
Result OpenFile(nn::fs::FileHandle*, char const* path, s32);
|
||||
Result SetFileSize(FileHandle fileHandle, s64 filesize);
|
||||
void CloseFile(FileHandle fileHandle);
|
||||
Result FlushFile(FileHandle fileHandle);
|
||||
Result DeleteFile(char const* filepath);
|
||||
Result ReadFile(u64* outSize, nn::fs::FileHandle handle, s64 offset, void* buffer, u64 bufferSize,
|
||||
const ReadOption& option);
|
||||
Result ReadFile(u64* outSize, nn::fs::FileHandle handle, s64 offset, void* buffer, u64 bufferSize);
|
||||
Result ReadFile(nn::fs::FileHandle handle, s64 offset, void* buffer, u64 bufferSize);
|
||||
Result WriteFile(FileHandle handle, s64 fileOffset, void const* buff, u64 size,
|
||||
WriteOption const& option);
|
||||
Result GetFileSize(s64* size, FileHandle fileHandle);
|
||||
|
||||
// DIRECTORY
|
||||
// there are three open modes; dir, file, all
|
||||
Result OpenDirectory(DirectoryHandle* handle, char const* path, s32 openMode);
|
||||
void CloseDirectory(DirectoryHandle directoryHandle);
|
||||
Result ReadDirectory(s64*, DirectoryEntry*, DirectoryHandle directoryHandle, s64);
|
||||
Result CreateDirectory(char const* directorypath);
|
||||
Result GetDirectoryEntryCount(s64*, DirectoryHandle);
|
||||
|
||||
// SD
|
||||
Result MountSdCard(char const*);
|
||||
Result MountSdCardForDebug(char const*);
|
||||
bool IsSdCardInserted();
|
||||
Result FormatSdCard();
|
||||
Result FormatSdCardDryRun();
|
||||
bool IsExFatSupported();
|
||||
|
||||
Result MountHost(char const* mount, char const* path);
|
||||
Result MountHostRoot();
|
||||
Result UnmountHostRoot();
|
||||
|
||||
Result Unmount(char const* mount);
|
||||
|
||||
// BCAT
|
||||
Result MountBcatSaveData(char const*, ApplicationId);
|
||||
Result CreateBcatSaveData(ApplicationId, s64);
|
||||
|
||||
}; // namespace fs
|
||||
}; // namespace nn
|
31
lib/NintendoSDK/include/nn/g3d/BindFuncTable.h
Normal file
31
lib/NintendoSDK/include/nn/g3d/BindFuncTable.h
Normal file
@ -0,0 +1,31 @@
|
||||
#pragma once
|
||||
|
||||
#include <nn/types.h>
|
||||
|
||||
namespace nn {
|
||||
namespace g3d {
|
||||
struct DDLDeclarations {
|
||||
u64 _0;
|
||||
u32 _8;
|
||||
u32 DDLDeclarations_xC;
|
||||
u64 _10;
|
||||
u64 _18;
|
||||
};
|
||||
|
||||
class BindFuncTable {
|
||||
struct StringLength {
|
||||
size_t length;
|
||||
const char* content;
|
||||
};
|
||||
struct EntryPointer {
|
||||
void* something_0;
|
||||
nn::g3d::BindFuncTable::StringLength* string;
|
||||
};
|
||||
|
||||
private:
|
||||
int lengths[4];
|
||||
nn::g3d::BindFuncTable::EntryPointer strings[4];
|
||||
};
|
||||
|
||||
}; // namespace g3d
|
||||
}; // namespace nn
|
75
lib/NintendoSDK/include/nn/g3d/ResFile.h
Normal file
75
lib/NintendoSDK/include/nn/g3d/ResFile.h
Normal file
@ -0,0 +1,75 @@
|
||||
/**
|
||||
* @file ResFile.h
|
||||
* @brief Resource file for models.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <nn/gfx/api.h>
|
||||
#include <nn/gfx/memory.h>
|
||||
#include <nn/types.h>
|
||||
#include <nn/util.h>
|
||||
|
||||
namespace nn {
|
||||
|
||||
namespace gfx {
|
||||
template <typename T>
|
||||
class TDevice;
|
||||
}
|
||||
|
||||
namespace g3d {
|
||||
class ResModel;
|
||||
class ResMaterialAnim;
|
||||
class ResShapeAnim;
|
||||
class ResSceneAnim;
|
||||
typedef void* TextureRef;
|
||||
|
||||
class ResFile : public nn::util::BinaryFileHeader {
|
||||
public:
|
||||
static bool IsValid(void const* modelSrc);
|
||||
void Relocate();
|
||||
void Unrelocate();
|
||||
static nn::g3d::ResFile* ResCast(void*);
|
||||
s32 BindTexture(nn::g3d::TextureRef (*ref)(char const*, void*), void*);
|
||||
void ReleaseTexture();
|
||||
void
|
||||
Setup(nn::gfx::TDevice<nn::gfx::ApiVariation<nn::gfx::ApiType<4>, nn::gfx::ApiVersion<8>>>*);
|
||||
void
|
||||
Setup(nn::gfx::TDevice<nn::gfx::ApiVariation<nn::gfx::ApiType<4>, nn::gfx::ApiVersion<8>>>*,
|
||||
nn::gfx::TMemoryPool<nn::gfx::ApiVariation<nn::gfx::ApiType<4>, nn::gfx::ApiVersion<8>>>*,
|
||||
s64, u64);
|
||||
void
|
||||
Cleanup(nn::gfx::TDevice<nn::gfx::ApiVariation<nn::gfx::ApiType<4>, nn::gfx::ApiVersion<8>>>*);
|
||||
void Reset();
|
||||
|
||||
u64 mFileNameLength; // _20
|
||||
nn::g3d::ResModel* mModels; // _28
|
||||
u64 mModelDictOffset; // _30
|
||||
u64 mSkeleAnimOffset; // _38
|
||||
u64 mSkeleAnimDictOffset; // _40
|
||||
nn::g3d::ResMaterialAnim* mMatAnims; // _48
|
||||
u64 mMatAnimsDictOffset; // _50
|
||||
u64 mBoneVisiOffset; // _58
|
||||
u64 mBoneVisiDictOffset; // _60
|
||||
nn::g3d::ResShapeAnim* mShapeAnims; // _68
|
||||
u64 mShapeAnimDictOffset; // _70
|
||||
nn::g3d::ResSceneAnim* mSceneAnims; // _78
|
||||
u64 mSceneAnimDictOffset; // _80
|
||||
u64 mMemoryPool; // _88
|
||||
u64 mBufferSection; // _90
|
||||
u64 mEmbeddedFilesOffset; // _98
|
||||
u64 mEmbeddedFilesDictOffset; // _A0
|
||||
u64 mPadding; // _A8
|
||||
u64 mStrTableOffset; // _B0
|
||||
u32 mStrTableSize; // _B8
|
||||
u16 mModelCount; // _BC
|
||||
u16 mSkeleAnimCount; // _BE
|
||||
u16 mMatAnimCount; // _C0
|
||||
u16 mBoneAnimCount; // _C2
|
||||
u16 mShapeAnimCount; // _C4
|
||||
u16 mSceneAnimCount; // _C6
|
||||
u16 mExternalFileCount; // _C8
|
||||
u8 mPad[0x6]; // _CA
|
||||
};
|
||||
}; // namespace g3d
|
||||
}; // namespace nn
|
21
lib/NintendoSDK/include/nn/g3d/ResFogAnim.h
Normal file
21
lib/NintendoSDK/include/nn/g3d/ResFogAnim.h
Normal file
@ -0,0 +1,21 @@
|
||||
#pragma once
|
||||
|
||||
#include <nn/types.h>
|
||||
|
||||
namespace nn {
|
||||
namespace g3d {
|
||||
class ResFogAnim {
|
||||
public:
|
||||
char mMagic[4]; // _0
|
||||
u16 mFlags; // _4
|
||||
u16 mPad; // _6
|
||||
s32 mNumFrames; // _8
|
||||
u8 mNumCurves; // _C
|
||||
u8 mIdxDistanceAttnFunc; // _D
|
||||
u16 mNumUserData; // _E
|
||||
u32 mSizeBaked; // _10
|
||||
u64 mNameOffset; // _14
|
||||
u64 mFuncNameOffset; // _1C
|
||||
};
|
||||
}; // namespace g3d
|
||||
}; // namespace nn
|
12
lib/NintendoSDK/include/nn/g3d/ResLightAnim.h
Normal file
12
lib/NintendoSDK/include/nn/g3d/ResLightAnim.h
Normal file
@ -0,0 +1,12 @@
|
||||
#pragma once
|
||||
|
||||
#include <nn/types.h>
|
||||
|
||||
namespace nn {
|
||||
namespace g3d {
|
||||
class ResLightAnim {
|
||||
public:
|
||||
s32 Bind(nn::g3d::BindFuncTable const&);
|
||||
};
|
||||
}; // namespace g3d
|
||||
}; // namespace nn
|
29
lib/NintendoSDK/include/nn/g3d/ResMaterial.h
Normal file
29
lib/NintendoSDK/include/nn/g3d/ResMaterial.h
Normal file
@ -0,0 +1,29 @@
|
||||
/**
|
||||
* @file ResMaterial.h
|
||||
* @brief Resource material for models.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <nn/types.h>
|
||||
|
||||
namespace nn {
|
||||
namespace g3d {
|
||||
typedef void* TextureRef;
|
||||
|
||||
class ResMaterial {
|
||||
public:
|
||||
u64 BindTexture(nn::g3d::TextureRef (*)(char const*, void*), void*);
|
||||
void ForceBindTexture(nn::g3d::TextureRef const&, char const*);
|
||||
void ReleaseTexture();
|
||||
void
|
||||
Setup(nn::gfx::TDevice<nn::gfx::ApiVariation<nn::gfx::ApiType<4>, nn::gfx::ApiVersion<4>>>*);
|
||||
void
|
||||
Cleanup(nn::gfx::TDevice<nn::gfx::ApiVariation<nn::gfx::ApiType<8>, nn::gfx::ApiVersion<8>>>*);
|
||||
void Reset();
|
||||
void Reset(u32);
|
||||
|
||||
u8 _0[0xB4];
|
||||
};
|
||||
}; // namespace g3d
|
||||
}; // namespace nn
|
19
lib/NintendoSDK/include/nn/g3d/ResMaterialAnim.h
Normal file
19
lib/NintendoSDK/include/nn/g3d/ResMaterialAnim.h
Normal file
@ -0,0 +1,19 @@
|
||||
/**
|
||||
* @file ResMaterialAnim.h
|
||||
* @brief Resource file for material animations.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace nn {
|
||||
namespace g3d {
|
||||
typedef void* TextureRef;
|
||||
|
||||
class ResMaterialAnim {
|
||||
public:
|
||||
void ReleaseTexture();
|
||||
s32 BindTexture(nn::g3d::TextureRef (*)(char const*, void*), void*);
|
||||
void Reset();
|
||||
};
|
||||
}; // namespace g3d
|
||||
}; // namespace nn
|
32
lib/NintendoSDK/include/nn/g3d/ResModel.h
Normal file
32
lib/NintendoSDK/include/nn/g3d/ResModel.h
Normal file
@ -0,0 +1,32 @@
|
||||
/**
|
||||
* @file ResModel.h
|
||||
* @brief Resource model.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <nn/types.h>
|
||||
|
||||
namespace nn {
|
||||
namespace g3d {
|
||||
class ResMaterial;
|
||||
|
||||
typedef void* TextureRef;
|
||||
|
||||
class ResModel {
|
||||
public:
|
||||
u64 BindTexture(nn::g3d::TextureRef (*)(char const*, void*), void*);
|
||||
void ForceBindTexture(nn::g3d::TextureRef const&, char const*);
|
||||
void ReleaseTexture();
|
||||
void
|
||||
Setup(nn::gfx::TDevice<nn::gfx::ApiVariation<nn::gfx::ApiType<4>, nn::gfx::ApiVersion<8>>>*);
|
||||
void
|
||||
Cleanup(nn::gfx::TDevice<nn::gfx::ApiVariation<nn::gfx::ApiType<4>, nn::gfx::ApiVersion<8>>>*);
|
||||
void Reset();
|
||||
void Reset(u32);
|
||||
nn::g3d::ResMaterial* FindMaterial(char const* materialName) const;
|
||||
|
||||
u8 _0[0x70];
|
||||
};
|
||||
}; // namespace g3d
|
||||
}; // namespace nn
|
41
lib/NintendoSDK/include/nn/g3d/ResSceneAnim.h
Normal file
41
lib/NintendoSDK/include/nn/g3d/ResSceneAnim.h
Normal file
@ -0,0 +1,41 @@
|
||||
/**
|
||||
* @file ResSceneAnim.h
|
||||
* @brief Resource file for scene animations.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <nn/types.h>
|
||||
|
||||
namespace nn {
|
||||
namespace g3d {
|
||||
class ResLightAnim;
|
||||
class ResFogAnim;
|
||||
struct BindFuncTable;
|
||||
|
||||
class ResSceneAnim {
|
||||
public:
|
||||
s32 Bind(nn::g3d::BindFuncTable const&);
|
||||
void Release();
|
||||
void Reset();
|
||||
|
||||
char mMagic[4]; // _0
|
||||
s32 mBlockOffset; // _4
|
||||
u64 mBlockSize; // _8
|
||||
u64 mNameOffset; // _10
|
||||
u64 mPathOffset; // _18
|
||||
u64 mCameraAnimOffset; // _20
|
||||
u64 mCameraAnimDictOffset; // _28
|
||||
nn::g3d::ResLightAnim* mLightAnims; // _30
|
||||
u64 mLightAnimDictOffset; // _38
|
||||
nn::g3d::ResFogAnim* mFogAnims; // _40
|
||||
u64 mFogAnimDictOffset; // _48
|
||||
u64 mUserDataOffset; // _50
|
||||
u64 mUserDataDictOffset; // _58
|
||||
u16 mUserDataCount; // _60
|
||||
u16 mCameraAnimCount; // _62
|
||||
u16 mLightAnimCount; // _64
|
||||
u16 mFogAnimCount; // _66
|
||||
};
|
||||
}; // namespace g3d
|
||||
}; // namespace nn
|
15
lib/NintendoSDK/include/nn/g3d/ResShapeAnim.h
Normal file
15
lib/NintendoSDK/include/nn/g3d/ResShapeAnim.h
Normal file
@ -0,0 +1,15 @@
|
||||
/**
|
||||
* @file ResShapeAnim.h
|
||||
* @brief Resource file for shape animations.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace nn {
|
||||
namespace g3d {
|
||||
class ResShapeAnim {
|
||||
public:
|
||||
void Reset();
|
||||
};
|
||||
}; // namespace g3d
|
||||
}; // namespace nn
|
15
lib/NintendoSDK/include/nn/g3d/ResSkeletalAnim.h
Normal file
15
lib/NintendoSDK/include/nn/g3d/ResSkeletalAnim.h
Normal file
@ -0,0 +1,15 @@
|
||||
/**
|
||||
* @file ResSkeletalAnim.h
|
||||
* @brief Resource file for skeletal animations.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace nn {
|
||||
namespace g3d {
|
||||
class ResSkeletalAnim {
|
||||
public:
|
||||
void Reset();
|
||||
};
|
||||
}; // namespace g3d
|
||||
}; // namespace nn
|
22
lib/NintendoSDK/include/nn/gfx/api.h
Normal file
22
lib/NintendoSDK/include/nn/gfx/api.h
Normal file
@ -0,0 +1,22 @@
|
||||
/**
|
||||
* @file api.h
|
||||
* @brief GFX API version and typing.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace nn {
|
||||
namespace gfx {
|
||||
// passes both ApiType<4> and ApiVersion<8>
|
||||
template <typename T, typename T2>
|
||||
class ApiVariation {};
|
||||
|
||||
// usually passed as just a 4
|
||||
template <int T>
|
||||
class ApiType {};
|
||||
|
||||
// usually passed as just a 8
|
||||
template <int T>
|
||||
class ApiVersion {};
|
||||
}; // namespace gfx
|
||||
}; // namespace nn
|
28
lib/NintendoSDK/include/nn/gfx/buffer.h
Normal file
28
lib/NintendoSDK/include/nn/gfx/buffer.h
Normal file
@ -0,0 +1,28 @@
|
||||
/**
|
||||
* @file buffer.h
|
||||
* @brief GFX Buffers.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <nn/types.h>
|
||||
|
||||
namespace nn {
|
||||
namespace gfx {
|
||||
class BufferInfo {
|
||||
public:
|
||||
void SetDefault();
|
||||
|
||||
u64 mInfo; // _0
|
||||
};
|
||||
|
||||
class BufferTextureViewInfo {
|
||||
public:
|
||||
void SetDefault();
|
||||
|
||||
u64 _0;
|
||||
u64 _8;
|
||||
u64 _10;
|
||||
};
|
||||
}; // namespace gfx
|
||||
}; // namespace nn
|
55
lib/NintendoSDK/include/nn/gfx/detail/bufferimpl.h
Normal file
55
lib/NintendoSDK/include/nn/gfx/detail/bufferimpl.h
Normal file
@ -0,0 +1,55 @@
|
||||
/**
|
||||
* @file bufferimpl.h
|
||||
* @brief Buffer implementation for GFX.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace nn {
|
||||
namespace gfx {
|
||||
class GpuAddress;
|
||||
class BufferInfo;
|
||||
|
||||
namespace detail {
|
||||
template <typename T>
|
||||
class MemoryPoolImpl;
|
||||
template <typename T>
|
||||
class DeviceImpl;
|
||||
|
||||
template <typename T>
|
||||
class BufferImpl {
|
||||
public:
|
||||
BufferImpl();
|
||||
~BufferImpl();
|
||||
|
||||
void Initialize(nn::gfx::detail::DeviceImpl<
|
||||
nn::gfx::ApiVariation<nn::gfx::ApiType<4>, nn::gfx::ApiVersion<8>>>*,
|
||||
nn::gfx::BufferInfo const&,
|
||||
nn::gfx::detail::MemoryPoolImpl<
|
||||
nn::gfx::ApiVariation<nn::gfx::ApiType<4>, nn::gfx::ApiVersion<8>>>*,
|
||||
s64, u64);
|
||||
void Finalize(nn::gfx::detail::DeviceImpl<
|
||||
nn::gfx::ApiVariation<nn::gfx::ApiType<4>, nn::gfx::ApiVersion<8>>>*);
|
||||
void* Map() const;
|
||||
void Unmap() const;
|
||||
void FlushMappedRange(s64, u64) const;
|
||||
void InvalidateMappedRange(s64, u64) const;
|
||||
void GetGpuAddress(nn::gfx::GpuAddress*) const;
|
||||
|
||||
T* mBuff; // _0
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
class CommandBufferImpl {
|
||||
public:
|
||||
CommandBufferImpl();
|
||||
~CommandBufferImpl();
|
||||
|
||||
void Reset();
|
||||
void Begin();
|
||||
void End();
|
||||
void Dispatch(s32, s32, s32);
|
||||
};
|
||||
}; // namespace detail
|
||||
}; // namespace gfx
|
||||
}; // namespace nn
|
24
lib/NintendoSDK/include/nn/gfx/detail/deviceimpl.h
Normal file
24
lib/NintendoSDK/include/nn/gfx/detail/deviceimpl.h
Normal file
@ -0,0 +1,24 @@
|
||||
/**
|
||||
* @file deviceimpl.h
|
||||
* @brief Device implementation for GFX.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace nn {
|
||||
namespace gfx {
|
||||
class DeviceInfo;
|
||||
|
||||
namespace detail {
|
||||
template <typename T>
|
||||
class DeviceImpl {
|
||||
public:
|
||||
DeviceImpl();
|
||||
~DeviceImpl();
|
||||
|
||||
void Initialize(nn::gfx::DeviceInfo const& deviceInfo);
|
||||
void Finalize();
|
||||
};
|
||||
}; // namespace detail
|
||||
}; // namespace gfx
|
||||
}; // namespace nn
|
41
lib/NintendoSDK/include/nn/gfx/detail/pool.h
Normal file
41
lib/NintendoSDK/include/nn/gfx/detail/pool.h
Normal file
@ -0,0 +1,41 @@
|
||||
#pragma once
|
||||
|
||||
#include <nn/types.h>
|
||||
|
||||
namespace nn {
|
||||
namespace gfx {
|
||||
struct MemoryPoolInfo;
|
||||
template <typename T>
|
||||
struct DeviceImpl;
|
||||
|
||||
namespace detail {
|
||||
class MemoryPoolData {
|
||||
public:
|
||||
void SetDefault();
|
||||
|
||||
s32 _0; // set to 0x88
|
||||
s32 _4;
|
||||
u64 _8;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
class MemoryPoolImpl {
|
||||
public:
|
||||
MemoryPoolImpl();
|
||||
~MemoryPoolImpl();
|
||||
|
||||
void Initialize(nn::gfx::detail::DeviceImpl<
|
||||
nn::gfx::ApiVariation<nn::gfx::ApiType<4>, nn::gfx::ApiVersion<8>>>*,
|
||||
nn::gfx::MemoryPoolInfo const&);
|
||||
void Finalize(nn::gfx::detail::DeviceImpl<
|
||||
nn::gfx::ApiVariation<nn::gfx::ApiType<4>, nn::gfx::ApiVersion<8>>>*);
|
||||
void* Map() const;
|
||||
void Unmap() const;
|
||||
void FlushMappedRange(s64, u64) const;
|
||||
void InvalidateMappedRange(s64, u64) const;
|
||||
|
||||
u8 _0[0x120]; // pool data
|
||||
};
|
||||
}; // namespace detail
|
||||
}; // namespace gfx
|
||||
}; // namespace nn
|
20
lib/NintendoSDK/include/nn/gfx/device.h
Normal file
20
lib/NintendoSDK/include/nn/gfx/device.h
Normal file
@ -0,0 +1,20 @@
|
||||
/**
|
||||
* @file device.h
|
||||
* @brief Device implementation for GFX.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <nn/types.h>
|
||||
|
||||
namespace nn {
|
||||
namespace gfx {
|
||||
class DeviceInfo {
|
||||
public:
|
||||
u64 mInfo; // _0
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
class TDevice {};
|
||||
}; // namespace gfx
|
||||
}; // namespace nn
|
14
lib/NintendoSDK/include/nn/gfx/memory.h
Normal file
14
lib/NintendoSDK/include/nn/gfx/memory.h
Normal file
@ -0,0 +1,14 @@
|
||||
/**
|
||||
* @file memory.h
|
||||
* @brief GFX Memory Pool.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace nn {
|
||||
namespace gfx {
|
||||
// todo: finish me!
|
||||
template <typename T>
|
||||
class TMemoryPool {};
|
||||
}; // namespace gfx
|
||||
}; // namespace nn
|
43
lib/NintendoSDK/include/nn/hid.h
Normal file
43
lib/NintendoSDK/include/nn/hid.h
Normal file
@ -0,0 +1,43 @@
|
||||
/**
|
||||
* @file hid.h
|
||||
* @brief Functions that help process gamepad inputs.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <nn/types.h>
|
||||
#include <nn/util.h>
|
||||
|
||||
namespace nn {
|
||||
namespace hid {
|
||||
struct NpadHandheldState;
|
||||
struct NpadStyleTag;
|
||||
|
||||
struct ControllerSupportArg {
|
||||
u8 mMinPlayerCount;
|
||||
u8 mMaxPlayerCount;
|
||||
u8 mTakeOverConnection;
|
||||
bool mLeftJustify;
|
||||
bool mPermitJoyconDual;
|
||||
bool mSingleMode;
|
||||
bool mUseColors;
|
||||
sead::Color4u8 mColors[4];
|
||||
u8 mUsingControllerNames;
|
||||
char mControllerNames[4][0x81];
|
||||
};
|
||||
|
||||
struct ControllerSupportResultInfo {
|
||||
int mPlayerCount;
|
||||
int mSelectedId;
|
||||
};
|
||||
|
||||
void InitializeNpad();
|
||||
void SetSupportedNpadIdType(u32 const*, u64);
|
||||
void SetSupportedNpadStyleSet(nn::util::BitFlagSet<32, nn::hid::NpadStyleTag>);
|
||||
void GetNpadStyleSet(u32 const&);
|
||||
void GetNpadStates(nn::hid::NpadHandheldState*, s32, u32 const&);
|
||||
static int ShowControllerSupport(nn::hid::ControllerSupportResultInfo*,
|
||||
ControllerSupportArg const&);
|
||||
|
||||
}; // namespace hid
|
||||
}; // namespace nn
|
50
lib/NintendoSDK/include/nn/image.h
Normal file
50
lib/NintendoSDK/include/nn/image.h
Normal file
@ -0,0 +1,50 @@
|
||||
/**
|
||||
* @file image.h
|
||||
* @brief JPEG decoding library.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <nn/types.h>
|
||||
|
||||
namespace nn {
|
||||
namespace image {
|
||||
// there's probably more
|
||||
enum JpegStatus {
|
||||
OK = 0,
|
||||
INVALID_FORMAT = -32,
|
||||
UNSUPPORTED_FORMAT = -33,
|
||||
OUT_OF_MEMORY = -64,
|
||||
};
|
||||
|
||||
enum PixelFormat { RGBA32, RGB24 };
|
||||
|
||||
enum ProcessStage { UNREGISTERED = 0, REGISTERED = 1, ANALYZED = 2 };
|
||||
|
||||
struct Dimension {
|
||||
f32 width;
|
||||
f32 height;
|
||||
};
|
||||
|
||||
class JpegDecoder {
|
||||
public:
|
||||
JpegDecoder();
|
||||
virtual ~JpegDecoder();
|
||||
|
||||
void SetImageData(void const* source, u64 size);
|
||||
nn::image::JpegStatus Analyze();
|
||||
nn::image::Dimension GetAnalyzedDimension() const;
|
||||
s64 GetAnalyzedWorkBufferSize() const;
|
||||
JpegStatus Decode(void* out, s64, s32 alignment, void*, s64);
|
||||
|
||||
nn::image::ProcessStage mProcessStage; // _8
|
||||
void* mData; // _C
|
||||
s64 mSize; // _14
|
||||
s32 _18;
|
||||
nn::image::PixelFormat mFormat; // _1C
|
||||
Dimension mImgDimensions; // _20
|
||||
s64 _28;
|
||||
// rest is related to EXIF processing
|
||||
};
|
||||
}; // namespace image
|
||||
}; // namespace nn
|
21
lib/NintendoSDK/include/nn/init.h
Normal file
21
lib/NintendoSDK/include/nn/init.h
Normal file
@ -0,0 +1,21 @@
|
||||
/**
|
||||
* @file init.h
|
||||
* @brief Initialization functions for OS related functions.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <nn/mem.h>
|
||||
#include <nn/types.h>
|
||||
|
||||
namespace nn {
|
||||
namespace init {
|
||||
void InitializeAllocator(void* addr, u64 size);
|
||||
nn::mem::StandardAllocator* GetAllocator();
|
||||
|
||||
namespace detail {
|
||||
void* DefaultAllocatorForThreadLocal(u64, u64);
|
||||
void* DefaultDeallocatorForThreadLocal(void*, u64);
|
||||
}; // namespace detail
|
||||
} // namespace init
|
||||
}; // namespace nn
|
30
lib/NintendoSDK/include/nn/mem.h
Normal file
30
lib/NintendoSDK/include/nn/mem.h
Normal file
@ -0,0 +1,30 @@
|
||||
/**
|
||||
* @file mem.h
|
||||
* @brief Memory allocation functions.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <nn/os.h>
|
||||
#include <nn/types.h>
|
||||
|
||||
namespace nn {
|
||||
namespace mem {
|
||||
class StandardAllocator {
|
||||
public:
|
||||
StandardAllocator();
|
||||
|
||||
void Initialize(void* address, u64 size);
|
||||
void Finalize();
|
||||
void* Reallocate(void* address, u64 newSize);
|
||||
void* Allocate(u64 size);
|
||||
void Free(void* address);
|
||||
void Dump();
|
||||
|
||||
bool mIsInitialized; // _0
|
||||
bool mIsEnabledThreadCache; // _1
|
||||
u16 _2;
|
||||
u64* mAllocAddr; // _4
|
||||
};
|
||||
}; // namespace mem
|
||||
}; // namespace nn
|
30
lib/NintendoSDK/include/nn/nex/RootObject.h
Normal file
30
lib/NintendoSDK/include/nn/nex/RootObject.h
Normal file
@ -0,0 +1,30 @@
|
||||
/**
|
||||
* @file RootObject.h
|
||||
* @brief RootObject for NEX.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <nn/types.h>
|
||||
|
||||
namespace nn {
|
||||
namespace nex {
|
||||
class RootObject {
|
||||
public:
|
||||
enum TargetPool {};
|
||||
|
||||
virtual ~RootObject();
|
||||
|
||||
void* operator new(u64);
|
||||
void operator delete(void*);
|
||||
void* operator new(u64, char const*, u32);
|
||||
void* operator new[](u64);
|
||||
void* operator new[](u64, char const*, u32);
|
||||
void operator delete[](void*);
|
||||
void operator delete(void*, char const*, u32);
|
||||
void operator delete[](void*, char const*, u32);
|
||||
void* operator new(u64, nn::nex::RootObject::TargetPool);
|
||||
void* operator new(u64, nn::nex::RootObject::TargetPool, char const*, u32);
|
||||
};
|
||||
}; // namespace nex
|
||||
}; // namespace nn
|
20
lib/NintendoSDK/include/nn/nex/auth.h
Normal file
20
lib/NintendoSDK/include/nn/nex/auth.h
Normal file
@ -0,0 +1,20 @@
|
||||
/**
|
||||
* @file auth.h
|
||||
* @brief Authorization for DDL.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <nn/nex/ddl.h>
|
||||
|
||||
namespace nn {
|
||||
namespace nex {
|
||||
class NintendoAuthenticationDDLDeclarations : public nn::nex::DDLDeclarations {
|
||||
public:
|
||||
virtual ~NintendoAuthenticationDDLDeclarations();
|
||||
virtual void Init();
|
||||
|
||||
void Register();
|
||||
};
|
||||
}; // namespace nex
|
||||
}; // namespace nn
|
25
lib/NintendoSDK/include/nn/nex/buffer.h
Normal file
25
lib/NintendoSDK/include/nn/nex/buffer.h
Normal file
@ -0,0 +1,25 @@
|
||||
/**
|
||||
* @file buffer.h
|
||||
* @brief NEX buffer implementation.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <nn/types.h>
|
||||
|
||||
namespace nn {
|
||||
namespace nex {
|
||||
class String;
|
||||
// todo
|
||||
class Buffer {
|
||||
public:
|
||||
Buffer(nn::nex::Buffer const&);
|
||||
Buffer(nn::nex::Buffer&&);
|
||||
Buffer(nn::nex::String const&);
|
||||
|
||||
void FreeDataBuffer(u8*, u64);
|
||||
|
||||
virtual ~Buffer();
|
||||
};
|
||||
}; // namespace nex
|
||||
}; // namespace nn
|
33
lib/NintendoSDK/include/nn/nex/cache.h
Normal file
33
lib/NintendoSDK/include/nn/nex/cache.h
Normal file
@ -0,0 +1,33 @@
|
||||
/**
|
||||
* @file cache.h
|
||||
* @brief NEX Cache Mangement.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <nn/types.h>
|
||||
|
||||
namespace nn {
|
||||
namespace nex {
|
||||
class String;
|
||||
class BasicCache;
|
||||
|
||||
class CacheManager {
|
||||
public:
|
||||
CacheManager();
|
||||
~CacheManager();
|
||||
|
||||
nn::nex::BasicCache* GetCache(nn::nex::String const&);
|
||||
};
|
||||
|
||||
class BasicCache {
|
||||
public:
|
||||
BasicCache(nn::nex::String const&);
|
||||
|
||||
virtual ~BasicCache();
|
||||
|
||||
u64 _8;
|
||||
u8 _10;
|
||||
};
|
||||
}; // namespace nex
|
||||
}; // namespace nn
|
61
lib/NintendoSDK/include/nn/nex/checksum.h
Normal file
61
lib/NintendoSDK/include/nn/nex/checksum.h
Normal file
@ -0,0 +1,61 @@
|
||||
/**
|
||||
* @file checksum.h
|
||||
* @brief NEX Checksum Implementation.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <nn/nex/RootObject.h>
|
||||
|
||||
namespace nn {
|
||||
namespace nex {
|
||||
class Buffer;
|
||||
|
||||
class ChecksumAlgorithm : public nn::nex::RootObject {
|
||||
public:
|
||||
ChecksumAlgorithm();
|
||||
|
||||
virtual ~ChecksumAlgorithm();
|
||||
|
||||
virtual bool ComputeChecksum(nn::nex::Buffer const&, nn::nex::Buffer*) = 0;
|
||||
// virtual bool ComputeChecksum(u8 const **, u64 const *, u64, nn::nex::SignatureBytes &) = 0;
|
||||
virtual bool IsReady() const;
|
||||
virtual void ComputeChecksumForTransport(u8 const*, u64);
|
||||
virtual u32 ComputeChecksumForTransportArray(u8 const**, u64 const*, u64) = 0;
|
||||
virtual u32 GetChecksumLength() = 0;
|
||||
|
||||
u64 _8;
|
||||
u8 _10;
|
||||
};
|
||||
|
||||
class MD5Checksum : public nn::nex::ChecksumAlgorithm {
|
||||
public:
|
||||
MD5Checksum();
|
||||
|
||||
virtual ~MD5Checksum();
|
||||
|
||||
virtual bool ComputeChecksum(nn::nex::Buffer const&, nn::nex::Buffer*);
|
||||
virtual u32 ComputeChecksumForTransportArray(u8 const**, u64 const*, u64);
|
||||
virtual u32 GetChecksumLength();
|
||||
};
|
||||
|
||||
class CRC16Checksum : public nn::nex::ChecksumAlgorithm {
|
||||
public:
|
||||
CRC16Checksum();
|
||||
|
||||
virtual ~CRC16Checksum();
|
||||
|
||||
virtual bool ComputeChecksum(nn::nex::Buffer const&, nn::nex::Buffer*);
|
||||
virtual u32 ComputeChecksumForTransportArray(u8 const**, u64 const*, u64);
|
||||
virtual u32 GetChecksumLength();
|
||||
};
|
||||
|
||||
/*
|
||||
this actually inherits some sort of KeyedChecksum thing. whatever
|
||||
class HMACChecksum : public nn::nex::ChecksumAlgorithm
|
||||
{
|
||||
|
||||
};
|
||||
*/
|
||||
}; // namespace nex
|
||||
}; // namespace nn
|
111
lib/NintendoSDK/include/nn/nex/client.h
Normal file
111
lib/NintendoSDK/include/nn/nex/client.h
Normal file
@ -0,0 +1,111 @@
|
||||
/**
|
||||
* @file client.h
|
||||
* @brief Client implementations for NEX.
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <nn/nex/system.h>
|
||||
|
||||
namespace nn {
|
||||
namespace nex {
|
||||
class Credentials;
|
||||
class EndPoint;
|
||||
class Message;
|
||||
class ProtocolCallContext;
|
||||
class ProtocolRequestBrokerInterface;
|
||||
|
||||
class Protocol : public nn::nex::SystemComponent {
|
||||
public:
|
||||
enum _Command { Response, Request };
|
||||
|
||||
enum _Type {
|
||||
Client, // implemented in nn::nex::ClientProtocol
|
||||
Server // implemented in nn::nex::ServerProtocol
|
||||
};
|
||||
|
||||
Protocol(u32);
|
||||
|
||||
virtual ~Protocol();
|
||||
|
||||
virtual char* GetType() const;
|
||||
virtual bool IsAKindOf(char const*) const;
|
||||
virtual void EnforceDeclareSysComponentMacro();
|
||||
|
||||
virtual bool BeginInitialization();
|
||||
virtual bool BeginTermination();
|
||||
|
||||
virtual nn::nex::Protocol::_Type GetProtocolType() const = 0;
|
||||
virtual void EndPointDisconnected(nn::nex::EndPoint*);
|
||||
virtual void FaultDetected(nn::nex::EndPoint*, u32);
|
||||
virtual nn::nex::Protocol* Clone() const;
|
||||
virtual bool Reload();
|
||||
|
||||
nn::nex::EndPoint* GetOutgoingConnection() const;
|
||||
void SetIncomingConnection(nn::nex::EndPoint*);
|
||||
void SetProtocolID(u16);
|
||||
void AddMethodID(nn::nex::Message*, u32);
|
||||
void CopyMembers(nn::nex::Protocol const*);
|
||||
void AssociateProtocolRequestBroker(nn::nex::ProtocolRequestBrokerInterface*);
|
||||
void ClearFlag(u32 newFlag);
|
||||
|
||||
static void ExtractProtocolKey(nn::nex::Message*, nn::nex::Protocol::_Command&, u16&);
|
||||
static bool IsOldRVDDLVersion(nn::nex::EndPoint*);
|
||||
|
||||
u16 mProtocolID; // _48
|
||||
u16 _4A;
|
||||
u32 _4C;
|
||||
nn::nex::EndPoint* mOutgoingConnection; // _50
|
||||
nn::nex::ProtocolRequestBrokerInterface* mBrokerInterface; // _58
|
||||
u32 mFlags; // _60
|
||||
u32 _64;
|
||||
nn::nex::EndPoint* mIncomingConnection; // _68
|
||||
u32 mUseLoopback; // _70 (boolean)
|
||||
u32 _74;
|
||||
u64 _78;
|
||||
u32 _80;
|
||||
u32 _84;
|
||||
};
|
||||
|
||||
class ClientProtocol : public nn::nex::Protocol {
|
||||
public:
|
||||
ClientProtocol(u32);
|
||||
|
||||
virtual ~ClientProtocol();
|
||||
|
||||
virtual char* GetType() const;
|
||||
virtual bool IsAKindOf(char const*) const;
|
||||
virtual void EnforceDeclareSysComponentMacro();
|
||||
|
||||
virtual nn::nex::Protocol::_Type GetProtocolType() const = 0;
|
||||
|
||||
virtual void ExtractCallSpecificResults(nn::nex::Message*, nn::nex::ProtocolCallContext*) = 0;
|
||||
virtual nn::nex::ClientProtocol* CreateResponder() const = 0;
|
||||
virtual void SetDefaultCredentials(nn::nex::Credentials*);
|
||||
|
||||
bool SendOverLocalLoopback(nn::nex::ProtocolCallContext*, nn::nex::Message*);
|
||||
bool SendRMCMessage(nn::nex::ProtocolCallContext*, nn::nex::Message*);
|
||||
void ProcessResponse(nn::nex::Message*, nn::nex::EndPoint*);
|
||||
|
||||
nn::nex::Credentials* mCredentials; // _88
|
||||
};
|
||||
|
||||
class ServerProtocol : public nn::nex::Protocol {
|
||||
public:
|
||||
ServerProtocol(u32);
|
||||
|
||||
virtual ~ServerProtocol();
|
||||
|
||||
virtual char* GetType() const;
|
||||
virtual bool IsAKindOf(char const*) const;
|
||||
virtual void EnforceDeclareSysComponentMacro();
|
||||
|
||||
virtual nn::nex::Protocol::_Type GetProtocolType() const = 0;
|
||||
|
||||
virtual void DispatchProtocolMessage(nn::nex::Message*, nn::nex::Message*, bool*,
|
||||
nn::nex::EndPoint*) = 0;
|
||||
virtual void DispatchProtocolMessageWithAttemptCount(u64, nn::nex::Message*, nn::nex::Message*,
|
||||
bool*, int*, nn::nex::EndPoint*);
|
||||
virtual bool UseAttemptCountMethod();
|
||||
};
|
||||
}; // namespace nex
|
||||
}; // namespace nn
|
21
lib/NintendoSDK/include/nn/nex/data.h
Normal file
21
lib/NintendoSDK/include/nn/nex/data.h
Normal file
@ -0,0 +1,21 @@
|
||||
/**
|
||||
* @file data.h
|
||||
* @brief NEX Data.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <nn/nex/RootObject.h>
|
||||
|
||||
namespace nn {
|
||||
namespace nex {
|
||||
class Data : public nn::nex::RootObject {
|
||||
public:
|
||||
Data();
|
||||
|
||||
virtual ~Data();
|
||||
|
||||
u8 _8;
|
||||
};
|
||||
}; // namespace nex
|
||||
}; // namespace nn
|
40
lib/NintendoSDK/include/nn/nex/ddl.h
Normal file
40
lib/NintendoSDK/include/nn/nex/ddl.h
Normal file
@ -0,0 +1,40 @@
|
||||
/**
|
||||
* @file ddl.h
|
||||
* @brief DDL Declaration Implementation.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <nn/nex/RootObject.h>
|
||||
|
||||
namespace nn {
|
||||
namespace nex {
|
||||
class DDLDeclarations : public nn::nex::RootObject {
|
||||
public:
|
||||
DDLDeclarations(bool);
|
||||
|
||||
virtual ~DDLDeclarations();
|
||||
|
||||
virtual void Init() = 0;
|
||||
|
||||
void RegisterIfRequired();
|
||||
void Unregister();
|
||||
static void UnregisterAll();
|
||||
void LoadAll();
|
||||
void Load();
|
||||
void UnloadAll();
|
||||
void Unload();
|
||||
void ResetDOClassIDs();
|
||||
|
||||
u32 mNumDecsLoaded; // _8
|
||||
u8 DDLDeclarations_xC;
|
||||
u8 _D; // padding
|
||||
u8 _E; // ^^
|
||||
u8 _F; // ^^
|
||||
u64 _10;
|
||||
bool _18;
|
||||
|
||||
static nn::nex::DDLDeclarations* s_pFirstDDLDecl;
|
||||
};
|
||||
}; // namespace nex
|
||||
}; // namespace nn
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user