1 #if defined(BSNES_V084) || defined(BSNES_V085) || defined(BSNES_V086) || defined(BSNES_V087)
3 #include <core/emucore.hpp>
4 #include "core/advdumper.hpp"
5 #include "core/dispatch.hpp"
6 #include "core/emucore.hpp"
7 #include "core/moviedata.hpp"
8 #include "library/serialization.hpp"
9 #include "video/tcp.hpp"
20 #define CUTOFF 2100000000
21 #define SDUMP_FLAG_HIRES 1
22 #define SDUMP_FLAG_INTERLACED 2
23 #define SDUMP_FLAG_OVERSCAN 4
24 #define SDUMP_FLAG_PAL 8
28 void deleter_fn(void* f
)
30 delete reinterpret_cast<std::ofstream
*>(f
);
33 class sdmp_avsnoop
: public information_dispatch
36 sdmp_avsnoop(const std::string
& prefix
, const std::string
& mode
) throw(std::bad_alloc
,
38 : information_dispatch("dump-sdmp")
42 sdump_ss
= (mode
!= "ms");
47 out
= &(socket_address(prefix
).connect());
48 deleter
= socket_address::deleter();
55 ~sdmp_avsnoop() throw()
64 void on_raw_frame(const uint32_t* raw
, bool hires
, bool interlaced
, bool overscan
, unsigned region
)
67 flags
|= (hires
? SDUMP_FLAG_HIRES
: 0);
68 flags
|= (interlaced
? SDUMP_FLAG_INTERLACED
: 0);
69 flags
|= (overscan
? SDUMP_FLAG_OVERSCAN
: 0);
70 flags
|= (region
== VIDEO_REGION_PAL
? SDUMP_FLAG_PAL
: 0);
71 unsigned char tbuffer
[2049];
72 if(!out
|| (ssize
> CUTOFF
&& !sdump_ss
)) {
73 std::cerr
<< "Starting new segment" << std::endl
;
76 std::ostringstream str
;
80 str
<< oprefix
<< "_" << std::setw(4) << std::setfill('0') << (next_seq
++)
82 std::string str2
= str
.str();
83 out
= new std::ofstream(str2
.c_str(), std::ios::out
| std::ios::binary
);
85 throw std::runtime_error("Failed to open '" + str2
+ "'");
86 write32ube(tbuffer
, 0x53444D50U
);
87 auto rates
= our_rom
->rtype
->get_snes_rate();
88 write32ube(tbuffer
+ 4, rates
.first
);
89 write32ube(tbuffer
+ 8, rates
.second
);
90 out
->write(reinterpret_cast<char*>(tbuffer
), 12);
92 throw std::runtime_error("Failed to write header to '" + str2
+ "'");
97 for(unsigned i
= 0; i
< 512; i
++) {
98 for(unsigned j
= 0; j
< 512; j
++)
99 write32ube(tbuffer
+ (4 * j
+ 1), raw
[512 * i
+ j
]);
100 out
->write(reinterpret_cast<char*>(tbuffer
+ (i
? 1 : 0)), i
? 2048 : 2049);
103 throw std::runtime_error("Failed to write frame");
107 void on_sample(short l
, short r
)
109 if(!out
|| !dumped_pic
)
111 unsigned char pkt
[5];
113 write16sbe(pkt
+ 1, l
);
114 write16sbe(pkt
+ 3, r
);
115 out
->write(reinterpret_cast<char*>(pkt
), 5);
117 throw std::runtime_error("Failed to write sample");
127 bool get_dumper_flag() throw()
137 void (*deleter
)(void* f
);
141 sdmp_avsnoop
* vid_dumper
;
143 class adv_sdmp_dumper
: public adv_dumper
146 adv_sdmp_dumper() : adv_dumper("INTERNAL-SDMP") { information_dispatch::do_dumper_update(); }
147 ~adv_sdmp_dumper() throw();
148 std::set
<std::string
> list_submodes() throw(std::bad_alloc
)
150 std::set
<std::string
> x
;
157 unsigned mode_details(const std::string
& mode
) throw()
160 return target_type_file
;
162 return target_type_prefix
;
164 return target_type_special
;
165 return target_type_mask
;
168 std::string
mode_extension(const std::string
& mode
) throw()
170 return "sdmp"; //Ignored anyway in non-ss mode.
173 std::string
name() throw(std::bad_alloc
)
178 std::string
modename(const std::string
& mode
) throw(std::bad_alloc
)
181 return "Single-Segment";
183 return "Multi-Segment";
185 return "over TCP/IP";
191 return (vid_dumper
!= NULL
);
194 void start(const std::string
& mode
, const std::string
& prefix
) throw(std::bad_alloc
,
198 throw std::runtime_error("Expected target");
200 throw std::runtime_error("SDMP Dump already in progress");
202 vid_dumper
= new sdmp_avsnoop(prefix
, mode
);
203 } catch(std::bad_alloc
& e
) {
205 } catch(std::exception
& e
) {
206 std::ostringstream x
;
207 x
<< "Error starting SDMP dump: " << e
.what();
208 throw std::runtime_error(x
.str());
210 messages
<< "Dumping SDMP (" << mode
<< ") to " << prefix
<< std::endl
;
211 information_dispatch::do_dumper_update();
217 throw std::runtime_error("No SDMP video dump in progress");
219 vid_dumper
->on_dump_end();
220 messages
<< "SDMP Dump finished" << std::endl
;
221 } catch(std::bad_alloc
& e
) {
223 } catch(std::exception
& e
) {
224 messages
<< "Error ending SDMP dump: " << e
.what() << std::endl
;
228 information_dispatch::do_dumper_update();
232 adv_sdmp_dumper::~adv_sdmp_dumper() throw()