Remove partial exception specifiers
[lsnes.git] / src / core / moviefile-text-save.cpp
blob0052144fe11574e34821ef3b9ead87f3ac9f65b1
1 #include "core/messages.hpp"
2 #include "core/moviefile-common.hpp"
3 #include "core/moviefile.hpp"
4 #include "library/binarystream.hpp"
5 #include "library/minmax.hpp"
6 #include "library/serialization.hpp"
7 #include "library/string.hpp"
8 #include "library/zip.hpp"
10 #include <fcntl.h>
11 #include <unistd.h>
12 #include <iostream>
13 #include <algorithm>
14 #include <sstream>
15 #if defined(_WIN32) || defined(_WIN64) || defined(TEST_WIN32_CODE)
16 #include <windows.h>
17 #endif
19 namespace
21 void write_active_macros(zip::writer& w, const std::string& member, const std::map<std::string, uint64_t>& ma)
23 if(ma.empty())
24 return;
25 std::ostream& m = w.create_file(member);
26 try {
27 for(auto i : ma)
28 m << i.second << " " << i.first << std::endl;
29 if(!m)
30 throw std::runtime_error("Can't write ZIP file member");
31 w.close_file();
32 } catch(...) {
33 w.close_file();
34 throw;
38 template<typename T> std::string pick_a_name(const std::map<std::string, T>& map, bool prefer_unnamed)
40 if(prefer_unnamed && !map.count(""))
41 return "";
42 size_t count = 1;
43 while(true) {
44 std::string c = (stringfmt() << "(unnamed branch #" << count++ << ")").str();
45 if(!map.count(c))
46 return c;
50 void write_rrdata(zip::writer& w, rrdata_set& rrd)
52 uint64_t count;
53 std::vector<char> out;
54 count = rrd.write(out);
55 w.write_raw_file("rrdata", out);
56 std::ostream& m2 = w.create_file("rerecords");
57 try {
58 m2 << count << std::endl;
59 if(!m2)
60 throw std::runtime_error("Can't write ZIP file member");
61 w.close_file();
62 } catch(...) {
63 w.close_file();
64 throw;
68 void write_authors_file(zip::writer& w, std::vector<std::pair<std::string, std::string>>& authors)
70 std::ostream& m = w.create_file("authors");
71 try {
72 for(auto i : authors)
73 if(i.second == "")
74 m << i.first << std::endl;
75 else
76 m << i.first << "|" << i.second << std::endl;
77 if(!m)
78 throw std::runtime_error("Can't write ZIP file member");
79 w.close_file();
80 } catch(...) {
81 w.close_file();
82 throw;
86 void write_input(zip::writer& w, const std::string& mname, portctrl::frame_vector& input)
88 std::ostream& m = w.create_file(mname);
89 try {
90 char buffer[MAX_SERIALIZED_SIZE];
91 for(size_t i = 0; i < input.size(); i++) {
92 input[i].serialize(buffer);
93 m << buffer << std::endl;
95 if(!m)
96 throw std::runtime_error("Can't write ZIP file member");
97 w.close_file();
98 } catch(...) {
99 w.close_file();
100 throw;
104 void write_subtitles(zip::writer& w, const std::string& file, std::map<moviefile_subtiming, std::string>& x)
106 std::ostream& m = w.create_file(file);
107 try {
108 for(auto i : x)
109 m << i.first.get_frame() << " " << i.first.get_length() << " "
110 << subtitle_commentary::s_escape(i.second) << std::endl;
111 if(!m)
112 throw std::runtime_error("Can't write ZIP file member");
113 w.close_file();
114 } catch(...) {
115 w.close_file();
116 throw;
120 void write_pollcounters(zip::writer& w, const std::string& file, const std::vector<uint32_t>& pctr)
122 std::ostream& m = w.create_file(file);
123 try {
124 for(auto i : pctr) {
125 int32_t x = i & 0x7FFFFFFFUL;
126 if((i & 0x80000000UL) == 0)
127 x = -x - 1;
128 m << x << std::endl;
130 if(!m)
131 throw std::runtime_error("Can't write ZIP file member");
132 w.close_file();
133 } catch(...) {
134 w.close_file();
135 throw;
140 void moviefile::save(zip::writer& w, rrdata_set& rrd, bool as_state)
142 w.write_linefile("gametype", gametype->get_name());
143 moviefile_write_settings<zip::writer>(w, settings, gametype->get_type().get_settings(), [](zip::writer& w,
144 const std::string& name, const std::string& value) -> void {
145 if(regex_match("port[0-9]+", name))
146 w.write_linefile(name, value);
147 else
148 w.write_linefile("setting." + name, value);
150 w.write_linefile("gamename", gamename, true);
151 w.write_linefile("systemid", "lsnes-rr1");
152 w.write_linefile("controlsversion", "0");
153 coreversion = gametype->get_type().get_core_identifier();
154 w.write_linefile("coreversion", coreversion);
155 w.write_linefile("projectid", projectid);
156 write_rrdata(w, rrd);
157 w.write_linefile("rom.sha256", romimg_sha256[0], true);
158 w.write_linefile("romxml.sha256", romxml_sha256[0], true);
159 w.write_linefile("rom.hint", namehint[0], true);
160 for(size_t i = 1; i < ROM_SLOT_COUNT; i++) {
161 w.write_linefile((stringfmt() << "slot" << (char)(96 + i) << ".sha256").str(), romimg_sha256[i],
162 true);
163 w.write_linefile((stringfmt() << "slot" << (char)(96 + i) << "xml.sha256").str(), romxml_sha256[i],
164 true);
165 w.write_linefile((stringfmt() << "slot" << (char)(96 + i) << ".hint").str(), namehint[i],
166 true);
168 write_subtitles(w, "subtitles", subtitles);
169 for(auto i : movie_sram)
170 w.write_raw_file("moviesram." + i.first, i.second);
171 w.write_numeric_file("starttime.second", movie_rtc_second);
172 w.write_numeric_file("starttime.subsecond", movie_rtc_subsecond);
173 if(!anchor_savestate.empty())
174 w.write_raw_file("savestate.anchor", anchor_savestate);
175 if(as_state) {
176 w.write_numeric_file("saveframe", dyn.save_frame);
177 w.write_numeric_file("lagcounter", dyn.lagged_frames);
178 write_pollcounters(w, "pollcounters", dyn.pollcounters);
179 w.write_raw_file("hostmemory", dyn.host_memory);
180 w.write_raw_file("savestate", dyn.savestate);
181 w.write_raw_file("screenshot", dyn.screenshot);
182 for(auto i : dyn.sram)
183 w.write_raw_file("sram." + i.first, i.second);
184 w.write_numeric_file("savetime.second", dyn.rtc_second);
185 w.write_numeric_file("savetime.subsecond", dyn.rtc_subsecond);
186 w.write_numeric_file("pollflag", dyn.poll_flag);
187 write_active_macros(w, "macros", dyn.active_macros);
189 for(auto i : ramcontent)
190 w.write_raw_file("initram." + i.first, i.second);
191 write_authors_file(w, authors);
193 std::map<std::string, uint64_t> branch_table;
194 uint64_t next_branch = 1;
195 for(auto& i : branches) {
196 uint64_t id;
197 if(&i.second == input)
198 id = 0;
199 else
200 id = next_branch++;
201 branch_table[i.first] = id;
202 w.write_linefile((stringfmt() << "branchname." << id).str(), i.first);
203 if(id)
204 write_input(w, (stringfmt() << "input." << id).str(), i.second);
205 else
206 write_input(w, "input", i.second);
209 w.commit();