2 #include <snes/snes.hpp>
11 #define CUTOFF 2100000000
15 bool sdump_in_progress
;
23 class dummy_avsnoop
: public av_snooper
26 dummy_avsnoop() throw(std::bad_alloc
)
30 ~dummy_avsnoop() throw()
34 void frame(struct lcscreen
& _frame
, uint32_t fps_n
, uint32_t fps_d
) throw(std::bad_alloc
,
39 void sample(short l
, short r
) throw(std::bad_alloc
, std::runtime_error
)
43 void end() throw(std::bad_alloc
, std::runtime_error
)
48 sdump_in_progress
= false;
51 void gameinfo(const std::string
& gamename
, const std::list
<std::pair
<std::string
, std::string
>>&
52 authors
, double gametime
, const std::string
& rerecords
) throw(std::bad_alloc
, std::runtime_error
)
56 dummy_avsnoop
* snooper
;
58 function_ptr_command
<const std::string
&> jmd_dump("dump-sdmp", "Start sdmp capture",
59 "Syntax: dump-sdmp <prefix>\nStart SDMP capture to <prefix>\n",
60 [](const std::string
& prefix
) throw(std::bad_alloc
, std::runtime_error
) {
62 throw std::runtime_error("Expected filename");
63 sdump_open(prefix
, false);
64 messages
<< "Dumping to " << prefix
<< std::endl
;
67 function_ptr_command
<const std::string
&> jmd_dumpss("dump-sdmpss", "Start SS sdmp capture",
68 "Syntax: dump-sdmpss <file>\nStart SS SDMP capture to <file>\n",
69 [](const std::string
& prefix
) throw(std::bad_alloc
, std::runtime_error
) {
71 throw std::runtime_error("Expected filename");
72 sdump_open(prefix
, true);
73 messages
<< "Dumping to " << prefix
<< std::endl
;
76 function_ptr_command
<> end_avi("end-sdmp", "End SDMP capture",
77 "Syntax: end-sdmp\nEnd a SDMP capture.\n",
78 []() throw(std::bad_alloc
, std::runtime_error
) {
80 messages
<< "Dump finished" << std::endl
;
84 void sdump_open(const std::string
& prefix
, bool ss
)
87 throw std::runtime_error("Dump already in progress");
89 snooper
= new dummy_avsnoop
;
91 sdump_in_progress
= true;
99 if(!sdump_in_progress
)
100 throw std::runtime_error("No dump in progress");
103 sdump_in_progress
= false;
107 void sdump_frame(const uint32_t* buffer
, unsigned flags
)
110 unsigned char tbuffer
[2049];
111 if(!sdump_in_progress
)
113 if(!sdump_iopen
|| (ssize
> CUTOFF
&& !sdump_ss
)) {
114 std::cerr
<< "Starting new segment" << std::endl
;
117 std::ostringstream str
;
121 str
<< oprefix
<< "_" << std::setw(4) << std::setfill('0') << (next_seq
++) << ".sdmp";
122 std::string str2
= str
.str();
123 out
.open(str2
.c_str(), std::ios::out
| std::ios::binary
);
125 throw std::runtime_error("Failed to open '" + str2
+ "'");
131 uint32_t apufreq
= SNES::system
.apu_frequency();
132 uint32_t cpufreq
= SNES::system
.cpu_frequency();
133 tbuffer
[4] = cpufreq
>> 24;
134 tbuffer
[5] = cpufreq
>> 16;
135 tbuffer
[6] = cpufreq
>> 8;
136 tbuffer
[7] = cpufreq
;
137 tbuffer
[8] = apufreq
>> 24;
138 tbuffer
[9] = apufreq
>> 16;
139 tbuffer
[10] = apufreq
>> 8;
140 tbuffer
[11] = apufreq
;
141 out
.write(reinterpret_cast<char*>(tbuffer
), 12);
143 throw std::runtime_error("Failed to write header to '" + str2
+ "'");
147 for(unsigned i
= 0; i
< 512; i
++) {
148 for(unsigned j
= 0; j
< 512; j
++) {
149 tbuffer
[4 * j
+ 1] = buffer
[512 * i
+ j
] >> 24;
150 tbuffer
[4 * j
+ 2] = buffer
[512 * i
+ j
] >> 16;
151 tbuffer
[4 * j
+ 3] = buffer
[512 * i
+ j
] >> 8;
152 tbuffer
[4 * j
+ 4] = buffer
[512 * i
+ j
];
154 out
.write(reinterpret_cast<char*>(tbuffer
+ (i
? 1 : 0)), i
? 2048 : 2049);
157 throw std::runtime_error("Failed to write frame");
161 void sdump_sample(short left
, short right
)
163 if(!sdump_in_progress
|| !sdump_iopen
)
165 unsigned char pkt
[5];
167 pkt
[1] = static_cast<unsigned short>(left
) >> 8;
168 pkt
[2] = static_cast<unsigned short>(left
);
169 pkt
[3] = static_cast<unsigned short>(right
) >> 8;
170 pkt
[4] = static_cast<unsigned short>(right
);
171 out
.write(reinterpret_cast<char*>(pkt
), 5);
173 throw std::runtime_error("Failed to write sample");