Fix most hotkeys to show up in configuration (were missing due to errant !)
[lsnes.git] / src / core / mbranch.cpp
blobc6afe5a9bf26db8a3f9f2b0122947be18a09a7c6
1 #include "core/command.hpp"
2 #include "core/controllerframe.hpp"
3 #include "core/dispatch.hpp"
4 #include "core/emustatus.hpp"
5 #include "core/mbranch.hpp"
6 #include "core/messages.hpp"
7 #include "core/movie.hpp"
8 #include "library/string.hpp"
10 movie_branches::movie_branches(movie_logic& _mlogic, emulator_dispatch& _dispatch, status_updater& _supdater)
11 : mlogic(_mlogic), edispatch(_dispatch), supdater(_supdater)
15 std::string movie_branches::name(const std::string& internal)
17 if(internal != "")
18 return internal;
19 return "(Default branch)";
22 std::set<std::string> movie_branches::enumerate()
24 std::set<std::string> r;
25 if(!mlogic)
26 return r;
27 for(auto& i : mlogic.get_mfile().branches)
28 r.insert(i.first);
29 return r;
32 std::string movie_branches::get()
34 if(!mlogic)
35 return "";
36 return mlogic.get_mfile().current_branch();
39 void movie_branches::set(const std::string& branch)
41 moviefile& mf = mlogic.get_mfile();
42 if(!mlogic.get_movie().readonly_mode())
43 (stringfmt() << "Branches are only switchable in readonly mode.").throwex();
44 if(!mf.branches.count(branch))
45 (stringfmt() << "Branch '" << name(branch) << "' does not exist.").throwex();
46 if(!mlogic.get_movie().compatible(mf.branches[branch]))
47 (stringfmt() << "Branch '" << name(branch) << "' differs in past.").throwex();
48 //Ok, execute the switch.
49 mf.input = &mf.branches[branch];
50 mlogic.get_movie().set_movie_data(mf.input);
51 edispatch.mbranch_change();
52 supdater.update();
53 messages << "Switched to branch '" << name(branch) << "'" << std::endl;
56 void movie_branches::_new(const std::string& branch, const std::string& from)
58 moviefile& mf = mlogic.get_mfile();
59 if(mf.branches.count(branch))
60 (stringfmt() << "Branch '" << name(branch) << "' already exists.").throwex();
61 mf.fork_branch(from, branch);
62 messages << "Created branch '" << name(branch) << "'" << std::endl;
63 edispatch.mbranch_change();
66 void movie_branches::rename(const std::string& oldn, const std::string& newn)
68 moviefile& mf = mlogic.get_mfile();
69 if(oldn == newn)
70 return;
71 if(!mf.branches.count(oldn))
72 (stringfmt() << "Branch '" << name(oldn) << "' does not exist.").throwex();
73 if(mf.branches.count(newn))
74 (stringfmt() << "Branch '" << name(newn) << "' already exists.").throwex();
75 mf.fork_branch(oldn, newn);
76 if(mlogic.get_mfile().current_branch() == oldn) {
77 mf.input = &mf.branches[newn];
78 mlogic.get_movie().set_movie_data(mf.input);
80 mf.branches.erase(oldn);
81 messages << "Renamed branch '" << name(oldn) << "' to '" << name(newn) << "'" << std::endl;
82 edispatch.mbranch_change();
83 supdater.update();
86 void movie_branches::_delete(const std::string& branch)
88 moviefile& mf = mlogic.get_mfile();
89 if(!mf.branches.count(branch))
90 (stringfmt() << "Branch '" << name(branch) << "' does not exist.").throwex();
91 if(mlogic.get_mfile().current_branch() == branch)
92 (stringfmt() << "Can't delete current branch '" << name(branch) << "'.").throwex();
93 mlogic.get_mfile().branches.erase(branch);
94 messages << "Deleted branch '" << name(branch) << "'" << std::endl;
95 edispatch.mbranch_change();
98 std::set<std::string> movie_branches::_movie_branches(const std::string& filename)
100 moviefile::branch_extractor e(filename);
101 return e.enumerate();
104 void movie_branches::import_branch(const std::string& filename, const std::string& ibranch,
105 const std::string& branchname, int mode)
107 auto& mv = mlogic.get_mfile();
108 if(mv.branches.count(branchname) && &mv.branches[branchname] == mv.input)
109 (stringfmt() << "Can't overwrite current branch.").throwex();
111 portctrl::frame_vector v(mv.input->get_types());
112 if(mode == MBRANCH_IMPORT_TEXT || mode == MBRANCH_IMPORT_BINARY) {
113 std::ifstream file(filename, (mode == MBRANCH_IMPORT_BINARY) ? std::ios_base::binary :
114 std::ios_base::in);
115 if(!file)
116 (stringfmt() << "Can't open '" << filename << "' for reading.").throwex();
117 portctrl::frame_vector::notify_freeze freeze(v);
118 if(mode == MBRANCH_IMPORT_BINARY) {
119 uint64_t stride = v.get_stride();
120 uint64_t pageframes = v.get_frames_per_page();
121 uint64_t vsize = 0;
122 size_t pagenum = 0;
123 size_t pagesize = stride * pageframes;
124 while(file) {
125 v.resize(vsize + pageframes);
126 unsigned char* contents = v.get_page_buffer(pagenum++);
127 file.read(reinterpret_cast<char*>(contents), pagesize);
128 vsize += (file.gcount() / stride);
130 v.resize(vsize);
131 } else {
132 std::string line;
133 portctrl::frame tmpl = v.blank_frame(false);
134 while(file) {
135 std::getline(file, line);
136 istrip_CR(line);
137 if(line.length() == 0)
138 continue;
139 tmpl.deserialize(line.c_str());
140 v.append(tmpl);
143 } else if(mode == MBRANCH_IMPORT_MOVIE) {
144 moviefile::branch_extractor e(filename);
145 e.read(ibranch, v);
147 bool created = !mv.branches.count(branchname);
148 try {
149 mv.branches[branchname] = v;
150 } catch(...) {
151 if(created)
152 mv.branches.erase(branchname);
156 void movie_branches::export_branch(const std::string& filename, const std::string& branchname, bool binary)
158 auto& mv = mlogic.get_mfile();
159 if(!mv.branches.count(branchname))
160 (stringfmt() << "Branch '" << branchname << "' does not exist.").throwex();
161 auto& v = mv.branches[branchname];
162 std::ofstream file(filename, binary ? std::ios_base::binary : std::ios_base::out);
163 if(!file)
164 (stringfmt() << "Can't open '" << filename << "' for writing.").throwex();
165 if(binary) {
166 uint64_t stride = v.get_stride();
167 uint64_t pageframes = v.get_frames_per_page();
168 uint64_t vsize = v.size();
169 size_t pagenum = 0;
170 while(vsize > 0) {
171 uint64_t count = (vsize > pageframes) ? pageframes : vsize;
172 size_t bytes = count * stride;
173 unsigned char* content = v.get_page_buffer(pagenum++);
174 file.write(reinterpret_cast<char*>(content), bytes);
175 vsize -= count;
177 } else {
178 char buf[MAX_SERIALIZED_SIZE];
179 for(uint64_t i = 0; i < v.size(); i++) {
180 v[i].serialize(buf);
181 file << buf << std::endl;
184 if(!file)
185 (stringfmt() << "Can't write to '" << filename << "'.").throwex();