2 #include "core/command.hpp"
3 #include "core/controller.hpp"
4 #include "core/dispatch.hpp"
5 #include "core/keymapper.hpp"
6 #include "core/instance.hpp"
7 #include "core/moviedata.hpp"
8 #include "core/multitrack.hpp"
9 #include "lua/internal.hpp"
11 void update_movie_state();
13 multitrack_edit::multitrack_edit(movie_logic
& _mlogic
, controller_state
& _controls
)
14 : mlogic(_mlogic
), controls(_controls
)
18 bool multitrack_edit::is_enabled()
23 void multitrack_edit::enable(bool state
)
26 threads::alock
h(mlock
);
28 controllerstate
.clear();
33 void multitrack_edit::set(unsigned port
, unsigned controller
, state s
)
36 threads::alock
h(mlock
);
37 controllerstate
[std::make_pair(port
, controller
)] = s
;
42 void multitrack_edit::set_and_notify(unsigned port
, unsigned controller
, state s
)
44 if(!mlogic
|| !mlogic
.get_movie().readonly_mode())
46 set(port
, controller
, s
);
47 notify_multitrack_change(port
, controller
, (int)s
);
50 void multitrack_edit::rotate(bool forward
)
52 if(!mlogic
|| !mlogic
.get_movie().readonly_mode())
54 std::vector
<std::pair
<unsigned, unsigned>> x
;
55 for(unsigned i
= 0;; i
++) {
56 auto pcid
= controls
.lcid_to_pcid(i
);
59 x
.push_back(std::make_pair(pcid
.first
, pcid
.second
));
61 auto old_controllerstate
= controllerstate
;
62 for(unsigned i
= 0; i
< x
.size(); i
++) {
63 state s
= MT_PRESERVE
;
64 if(old_controllerstate
.count(x
[i
]))
65 s
= old_controllerstate
[x
[i
]];
76 controllerstate
[x
[i2
]] = s
;
77 notify_multitrack_change(x
[i2
].first
, x
[i2
].second
, s
);
82 multitrack_edit::state
multitrack_edit::get(unsigned port
, unsigned controller
)
84 threads::alock
h(mlock
);
85 auto key
= std::make_pair(port
, controller
);
86 if(controllerstate
.count(key
))
87 return controllerstate
[key
];
91 void multitrack_edit::config_altered()
93 threads::alock
h(mlock
);
94 controllerstate
.clear();
97 void multitrack_edit::process_frame(controller_frame
& input
)
99 if(!mlogic
|| !mlogic
.get_movie().readonly_mode())
101 threads::alock
h(mlock
);
102 bool any_need
= false;
105 for(auto i
: controllerstate
)
106 any_need
= any_need
|| (i
.second
!= MT_PRESERVE
);
108 return; //No need to twiddle.
109 unsigned indices
= input
.get_index_count();
110 const port_type_set
& portset
= input
.porttypes();
111 pollcounter_vector
& p
= mlogic
.get_movie().get_pollcounters();
112 for(unsigned i
= 0; i
< indices
; i
++) {
113 port_index_triple t
= portset
.index_to_triple(i
);
116 auto key
= std::make_pair(t
.port
, t
.controller
);
117 uint32_t pc
= p
.get_polls(i
);
118 if(!controllerstate
.count(key
) || controllerstate
[key
] == MT_PRESERVE
|| (!t
.port
&& !t
.controller
)) {
119 int16_t v
= mlogic
.get_movie().read_subframe_at_index(pc
, t
.port
, t
.controller
,
121 input
.axis3(t
.port
, t
.controller
, t
.control
, v
);
123 int16_t v
= mlogic
.get_movie().read_subframe_at_index(pc
, t
.port
, t
.controller
,
125 controllerstate
[key
];
126 const port_type
& pt
= portset
.port_type(t
.port
);
127 auto pci
= pt
.controller_info
->get(t
.controller
);
128 auto pb
= pci
? pci
->get(t
.control
) : NULL
;
129 bool is_axis
= (pb
&& pb
->is_analog());
130 switch(controllerstate
[key
]) {
133 int16_t v2
= input
.axis3(t
.port
, t
.controller
, t
.control
);
137 v
|= input
.axis3(t
.port
, t
.controller
, t
.control
);
140 v
= input
.axis3(t
.port
, t
.controller
, t
.control
);
147 int16_t v2
= input
.axis3(t
.port
, t
.controller
, t
.control
);
151 v
^= input
.axis3(t
.port
, t
.controller
, t
.control
);
154 mlogic
.get_movie().write_subframe_at_index(pc
, t
.port
, t
.controller
, t
.control
,
156 v
= mlogic
.get_movie().read_subframe_at_index(pc
, t
.port
, t
.controller
,
158 input
.axis3(t
.port
, t
.controller
, t
.control
, v
);
163 bool multitrack_edit::any_records()
165 if(!mlogic
|| !mlogic
.get_movie().readonly_mode())
167 threads::alock
h(mlock
);
168 bool any_need
= false;
169 for(auto i
: controllerstate
)
170 any_need
= any_need
|| (i
.second
!= MT_PRESERVE
);
176 command::fnptr
<> rotate_forward(lsnes_cmds
, "rotate-multitrack", "Rotate multitrack",
177 "Syntax: rotate-multitrack\nRotate multitrack\n",
178 []() throw(std::bad_alloc
, std::runtime_error
) {
179 CORE().mteditor
.rotate(true);
180 update_movie_state();
183 command::fnptr
<> rotate_backward(lsnes_cmds
, "rotate-multitrack-backwards", "Rotate multitrack backwards",
184 "Syntax: rotate-multitrack-backwards\nRotate multitrack backwards\n",
185 []() throw(std::bad_alloc
, std::runtime_error
) {
186 CORE().mteditor
.rotate(false);
187 update_movie_state();
190 command::fnptr
<const std::string
&> set_mt(lsnes_cmds
, "set-multitrack", "Set multitrack mode",
191 "Syntax: set-multitrack <controller> <mode>\nSet multitrack mode\n",
192 [](const std::string
& args
) throw(std::bad_alloc
, std::runtime_error
) {
193 regex_results r
= regex("(.*)[ \t]+(.*)", args
);
195 throw std::runtime_error("Bad arguments");
196 auto c
= controller_by_name(r
[1]);
198 throw std::runtime_error("No such controller");
200 CORE().mteditor
.set_and_notify(c
.first
, c
.second
, multitrack_edit::MT_PRESERVE
);
201 else if(r
[2] == "rewrite")
202 CORE().mteditor
.set_and_notify(c
.first
, c
.second
, multitrack_edit::MT_OVERWRITE
);
203 else if(r
[2] == "or")
204 CORE().mteditor
.set_and_notify(c
.first
, c
.second
, multitrack_edit::MT_OR
);
205 else if(r
[2] == "xor")
206 CORE().mteditor
.set_and_notify(c
.first
, c
.second
, multitrack_edit::MT_XOR
);
208 throw std::runtime_error("Invalid mode (keep, rewrite, or, xor)");
209 update_movie_state();
212 keyboard::invbind_info
_mtback(lsnes_invbinds
, "rotate-multitrack-backwards",
213 "Multitrack‣Rotate backwards");
214 keyboard::invbind_info
_mtfwd(lsnes_invbinds
, "rotate-multitrack", "Multitrack‣Rotate forward");
216 int multitrack_state(lua::state
& L
, lua::parameters
& P
)
218 unsigned port
, controller
;
222 auto s
= CORE().mteditor
.get(port
, controller
);
224 case multitrack_edit::MT_OR
:
227 case multitrack_edit::MT_OVERWRITE
:
228 L
.pushstring("rewrite");
230 case multitrack_edit::MT_PRESERVE
:
231 L
.pushstring("keep");
233 case multitrack_edit::MT_XOR
:
241 lua::functions
mtfn(lua_func_misc
, "input", {
242 {"multitrack_state", multitrack_state
},