-
Notifications
You must be signed in to change notification settings - Fork 0
/
flowchart.bt
90 lines (80 loc) · 2.99 KB
/
flowchart.bt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
struct VariableDef {
uint64 ptr_x0;
uint16 x8;
uchar xa;
uchar xb[5] <hidden=true>; // padding
};
// 'Entry point' structure. References events.
typedef struct (string name_) {
local string name <hidden=true> = name_;
uint64 sub_flow_event_indexes_offset <hidden=true>; // Indexes in the flowchart->x30 array.
// Variable defs are read and parsed, but unused by BotW flowcharts as of 1.5.0.
POINTER<Dic> variable_def_names;
Assert(variable_def_names_offset == 0);
POINTER<VariableDef> variable_defs;
Assert(variable_defs_offset == 0);
uint16 num_sub_flow_event_indexes <hidden=true>;
uint16 num_variable_defs;
Assert(num_variable_defs == 0);
EventIndex main_event_idx;
uint16 x1e <hidden=true>; // padding
Assert(x1e == 0);
if (num_sub_flow_event_indexes > 0) {
const local uint64 pos <hidden=true> = FTell();
FSeek(sub_flow_event_indexes_offset);
EventIndex sub_flow_event_indexes[num_sub_flow_event_indexes];
FSeek(pos);
}
} EntryPoint <read=EntryPointToString>;
string EntryPointToString(const EntryPoint& s) { return s.name; }
// 'Resource flowchart'. Root structure for non-timeline event flows.
// It seems that at one point Nintendo had support for multi-flowchart files,
// as is evident from the fact that the header has a flowchart DIC.
// However the final version of the game only looks at the first flowchart and ignores the DIC.
struct Flowchart {
const uint64 start <hidden=true> = FTell();
char type[4];
uint32 string_table_offset <format=hex>; // Relative.
uint32 x8 <hidden=true>; // padding
uint32 xc <hidden=true>; // padding
Assert(x8 == 0);
Assert(xc == 0);
uint16 num_actors;
uint16 num_actions;
uint16 num_queries;
uint16 num_events;
uint16 num_entry_points;
uint16 x1a <hidden=true>; // padding
Assert(x1a == 0);
uint16 x1c <hidden=true>; // padding
Assert(x1c == 0);
uint16 x1e <hidden=true>; // padding
Assert(x1e == 0);
POINTER<PascalString> name;
struct Actors { POINTER<Actor[num_actors]> actors <bgcolor=0x957000, optimize=false>; } actors;
struct Events { POINTER<Event[num_events]> events <bgcolor=0xa56300, optimize=false>; } events;
struct EntryPoints {
POINTER<Dic> dic <bgcolor=0x854020>;
Assert(dic.num_nodes == num_entry_points);
uint64 offset <hidden=true>;
const local uint64 pos <hidden=true> = FTell();
FSeek(offset);
local uint node_idx <hidden=true> = 0;
for (node_idx = 0; node_idx < dic.num_nodes; ++node_idx) {
EntryPoint entry_points(PascalStringToString(dic.nodes[node_idx].name))
<bgcolor=0x65001f>;
}
FSeek(pos);
} entry_points;
FSeek(start + string_table_offset);
// Check action and query counts.
local uint i <hidden=true> = 0;
local uint action_count <hidden=true> = 0;
local uint query_count <hidden=true> = 0;
for (i = 0; i < num_actors; ++i) {
action_count += actors.actors[i].num_actions;
query_count += actors.actors[i].num_queries;
}
Assert(action_count == num_actions);
Assert(query_count == num_queries);
};