Unattended dumping support
This commit is contained in:
parent
83e2d655ed
commit
66fcf13980
10 changed files with 389 additions and 28 deletions
50
Makefile
50
Makefile
|
@ -3,12 +3,15 @@ CC := g++-4.5
|
|||
HOSTCC = $(CC)
|
||||
OBJECTS = $(patsubst %.cpp,%.o,$(wildcard generic/*.cpp)) $(patsubst %.cpp,%.o,$(wildcard avidump/*.cpp)) fonts/font.o
|
||||
GENERIC_LIBS = -ldl -lboost_iostreams -lboost_filesystem -lboost_system -lz
|
||||
|
||||
PROGRAMS = lsnes.exe movieinfo.exe
|
||||
|
||||
CFLAGS = $(USER_CFLAGS)
|
||||
HOSTCCFLAGS = $(USER_HOSTCCFLAGS)
|
||||
LDFLAGS = $(GENERIC_LIBS) $(USER_LDFLAGS)
|
||||
PLATFORM = SDL
|
||||
PLATFORM_CFLAGS = $(CFLAGS)
|
||||
PLATFORM_LDFLAGS = $(LDFLAGS)
|
||||
|
||||
PROGRAMS = lsnes.exe movieinfo.exe lsnes-dumpavi.exe
|
||||
|
||||
|
||||
#Lua.
|
||||
ifdef NO_LUA
|
||||
|
@ -19,26 +22,47 @@ CFLAGS += $(shell pkg-config lua5.1 --cflags)
|
|||
LDFLAGS += $(shell pkg-config lua5.1 --libs)
|
||||
endif
|
||||
|
||||
#Platform stuff (SDL).
|
||||
OBJECTS += $(patsubst %.cpp,%.o,$(wildcard SDL/*.cpp))
|
||||
CFLAGS += $(shell sdl-config --cflags)
|
||||
LDFLAGS += $(shell sdl-config --libs)
|
||||
|
||||
|
||||
#Some misc defines.
|
||||
ifdef NO_THREADS
|
||||
CFLAGS += -DNO_THREADS
|
||||
endif
|
||||
|
||||
ifdef USE_THREADS
|
||||
CFLAGS += -DUSE_THREADS
|
||||
endif
|
||||
ifdef TEST_WIN32
|
||||
CFLAGS += -DTEST_WIN32_CODE
|
||||
endif
|
||||
ifdef BSNES_IS_COMPAT
|
||||
CFLAGS += -DBSNES_IS_COMPAT
|
||||
endif
|
||||
|
||||
|
||||
all: $(PROGRAMS)
|
||||
|
||||
.PRECIOUS: %.exe %.o
|
||||
|
||||
%.exe: %.o $(OBJECTS)
|
||||
|
||||
#Platform stuff.
|
||||
ifeq ($(PLATFORM), SDL)
|
||||
LSNES_MAIN = lsnes.o
|
||||
PLATFORM_OBJECTS += $(patsubst %.cpp,%.o,$(wildcard SDL/*.cpp))
|
||||
PLATFORM_CFLAGS += $(shell sdl-config --cflags)
|
||||
PLATFORM_LDFLAGS += $(shell sdl-config --libs)
|
||||
ifdef TEST_WIN32
|
||||
PLATFORM_LDFLAGS += -lSDLmain
|
||||
endif
|
||||
SDL/%.o: SDL/%.cpp
|
||||
$(CC) -I. -Igeneric -g -std=c++0x -I$(BSNES_PATH) -c -o $@ $< $(CFLAGS) $(PLATFORM_CFLAGS)
|
||||
lsnes.o: lsnes.cpp
|
||||
$(CC) -I. -Igeneric -g -std=c++0x -I$(BSNES_PATH) -c -o $@ $< $(CFLAGS) $(PLATFORM_CFLAGS)
|
||||
lsnes.exe: lsnes.o $(OBJECTS) $(PLATFORM_OBJECTS)
|
||||
$(CC) -o $@ $^ $(BSNES_PATH)/out/libsnes.a $(LDFLAGS) $(PLATFORM_LDFLAGS)
|
||||
else
|
||||
lsnes.o:
|
||||
echo "Unsupported platform" $(PLATFORM)
|
||||
false
|
||||
endif
|
||||
|
||||
|
||||
%.exe: %.o $(OBJECTS) dummy/window-dummy.o
|
||||
$(CC) -o $@ $^ $(BSNES_PATH)/out/libsnes.a $(LDFLAGS)
|
||||
|
||||
%.o: %.cpp
|
||||
|
|
|
@ -8,8 +8,16 @@
|
|||
#include <list>
|
||||
#include <stdexcept>
|
||||
|
||||
|
||||
#ifdef USE_THREADS
|
||||
#define REALLY_USE_THREADS 1
|
||||
#endif
|
||||
#ifndef NO_THREADS
|
||||
#ifdef __linux__
|
||||
#define REALLY_USE_THREADS 1
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef REALLY_USE_THREADS
|
||||
#include <thread>
|
||||
#include <condition_variable>
|
||||
#include <mutex>
|
||||
|
|
51
dummy/window-dummy.cpp
Normal file
51
dummy/window-dummy.cpp
Normal file
|
@ -0,0 +1,51 @@
|
|||
#include "window.hpp"
|
||||
#include <cstdlib>
|
||||
#include <iostream>
|
||||
|
||||
namespace
|
||||
{
|
||||
std::map<std::string, std::string> status;
|
||||
}
|
||||
|
||||
void window::init() {}
|
||||
void window::quit() {}
|
||||
void window::poll_inputs() throw(std::bad_alloc) {}
|
||||
void window::notify_screen_update(bool full) throw() {}
|
||||
void window::set_main_surface(screen& scr) throw() {}
|
||||
void window::paused(bool enable) throw() {}
|
||||
void window::wait_msec(uint64_t msec) throw(std::bad_alloc) {}
|
||||
void window::cancel_wait() throw() {}
|
||||
void window::sound_enable(bool enable) throw() {}
|
||||
void window::play_audio_sample(uint16_t left, uint16_t right) throw() {}
|
||||
void window::set_window_compensation(uint32_t xoffset, uint32_t yoffset, uint32_t hscl, uint32_t vscl) {}
|
||||
|
||||
bool window::modal_message(const std::string& msg, bool confirm) throw(std::bad_alloc)
|
||||
{
|
||||
std::cerr << "Modal message: " << msg << std::endl;
|
||||
return confirm;
|
||||
}
|
||||
|
||||
void window::fatal_error() throw()
|
||||
{
|
||||
std::cerr << "Exiting on fatal error." << std::endl;
|
||||
exit(1);
|
||||
}
|
||||
|
||||
void window::message(const std::string& msg) throw(std::bad_alloc)
|
||||
{
|
||||
if(msg[msg.length() - 1] == '\n')
|
||||
std::cout << msg;
|
||||
else
|
||||
std::cout << msg << std::endl;
|
||||
}
|
||||
|
||||
std::map<std::string, std::string>& window::get_emustatus() throw()
|
||||
{
|
||||
return status;
|
||||
}
|
||||
|
||||
uint64_t get_ticks_msec() throw()
|
||||
{
|
||||
static uint64_t c = 0;
|
||||
return c++;
|
||||
}
|
|
@ -976,7 +976,7 @@ namespace
|
|||
}
|
||||
}
|
||||
|
||||
void main_loop(struct loaded_rom& rom, struct moviefile& initial) throw(std::bad_alloc,
|
||||
void main_loop(struct loaded_rom& rom, struct moviefile& initial, bool load_has_to_succeed) throw(std::bad_alloc,
|
||||
std::runtime_error)
|
||||
{
|
||||
//Basic initialization.
|
||||
|
@ -1001,6 +1001,10 @@ void main_loop(struct loaded_rom& rom, struct moviefile& initial) throw(std::bad
|
|||
OOM_panic();
|
||||
} catch(std::exception& e) {
|
||||
messages << "ERROR: Can't load initial state: " << e.what() << std::endl;
|
||||
if(load_has_to_succeed) {
|
||||
messages << "FATAL: Can't load movie" << std::endl;
|
||||
window::fatal_error();
|
||||
}
|
||||
system_corrupt = true;
|
||||
update_movie_state();
|
||||
framebuffer = screen_corrupt;
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
/**
|
||||
* \brief Emulator main loop.
|
||||
*/
|
||||
void main_loop(struct loaded_rom& rom, struct moviefile& settings) throw(std::bad_alloc,
|
||||
std::runtime_error);
|
||||
void main_loop(struct loaded_rom& rom, struct moviefile& settings, bool load_has_to_succeed = false)
|
||||
throw(std::bad_alloc, std::runtime_error);
|
||||
|
||||
#endif
|
|
@ -1,7 +1,6 @@
|
|||
#ifndef _window__hpp__included__
|
||||
#define _window__hpp__included__
|
||||
|
||||
#include "SDL.h"
|
||||
#include "render.hpp"
|
||||
#include <string>
|
||||
#include <map>
|
||||
|
|
|
@ -439,7 +439,7 @@ void zip_writer::commit() throw(std::bad_alloc, std::logic_error, std::runtime_e
|
|||
throw std::runtime_error("Failed to write central directory end marker to output file");
|
||||
zipstream.close();
|
||||
std::string backup = zipfile_path + ".backup";
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
#if defined(_WIN32) || defined(_WIN64) || defined(TEST_WIN32_CODE)
|
||||
//Grumble, Windows seemingly can't do this atomically.
|
||||
remove(backup.c_str());
|
||||
#endif
|
||||
|
@ -513,7 +513,7 @@ void zip_writer::close_file() throw(std::bad_alloc, std::logic_error, std::runti
|
|||
|
||||
namespace
|
||||
{
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
#if defined(_WIN32) || defined(_WIN64) || defined(TEST_WIN32_CODE)
|
||||
const char* path_splitters = "\\/";
|
||||
bool drives_allowed = true;
|
||||
#else
|
||||
|
|
213
lsnes-dumpavi.cpp
Normal file
213
lsnes-dumpavi.cpp
Normal file
|
@ -0,0 +1,213 @@
|
|||
#include <sstream>
|
||||
#include "mainloop.hpp"
|
||||
#include "command.hpp"
|
||||
#include "lua.hpp"
|
||||
#include "moviedata.hpp"
|
||||
#include "rrdata.hpp"
|
||||
#include "lsnes.hpp"
|
||||
#include "rom.hpp"
|
||||
#include "keymapper.hpp"
|
||||
#include "misc.hpp"
|
||||
#include "window.hpp"
|
||||
#include <sys/time.h>
|
||||
#include <snes/snes.hpp>
|
||||
#include <ui-libsnes/libsnes.hpp>
|
||||
#include "framerate.hpp"
|
||||
#include "avsnoop.hpp"
|
||||
|
||||
namespace
|
||||
{
|
||||
class myavsnoop : public av_snooper
|
||||
{
|
||||
public:
|
||||
myavsnoop(uint64_t frames_to_dump)
|
||||
{
|
||||
frames_dumped = 0;
|
||||
total = frames_to_dump;
|
||||
}
|
||||
|
||||
~myavsnoop()
|
||||
{
|
||||
}
|
||||
|
||||
void frame(struct lcscreen& _frame, uint32_t fps_n, uint32_t fps_d) throw(std::bad_alloc,
|
||||
std::runtime_error)
|
||||
{
|
||||
frames_dumped++;
|
||||
if(frames_dumped % 100 == 0) {
|
||||
std::cout << "Dumping frame " << frames_dumped << "/" << total << " ("
|
||||
<< (100 * frames_dumped / total) << "%)" << std::endl;
|
||||
}
|
||||
if(frames_dumped == total) {
|
||||
//Rough way to end it.
|
||||
av_snooper::end(true);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
void sample(short l, short r) throw(std::bad_alloc, std::runtime_error)
|
||||
{
|
||||
}
|
||||
|
||||
void end() throw(std::bad_alloc, std::runtime_error)
|
||||
{
|
||||
std::cout << "Finished!" << std::endl;
|
||||
}
|
||||
|
||||
void gameinfo(const std::string& gamename, const std::list<std::pair<std::string, std::string>>&
|
||||
authors, double gametime, const std::string& rerecords) throw(std::bad_alloc,
|
||||
std::runtime_error)
|
||||
{
|
||||
}
|
||||
private:
|
||||
uint64_t frames_dumped;
|
||||
uint64_t total;
|
||||
};
|
||||
|
||||
void dumper_startup(const std::vector<std::string>& cmdline)
|
||||
{
|
||||
unsigned level = 7;
|
||||
std::string prefix = "avidump";
|
||||
uint64_t length = 0;
|
||||
for(auto i = cmdline.begin(); i != cmdline.end(); i++) {
|
||||
std::string a = *i;
|
||||
if(a.length() > 9 && a.substr(0, 9) == "--prefix=")
|
||||
prefix = a.substr(9);
|
||||
if(a.length() > 8 && a.substr(0, 8) == "--level=")
|
||||
try {
|
||||
level = boost::lexical_cast<unsigned>(a.substr(8));
|
||||
if(level < 0 || level > 18)
|
||||
throw std::runtime_error("Level out of range (0-18)");
|
||||
} catch(std::exception& e) {
|
||||
std::cerr << "Bad --level: " << e.what() << std::endl;
|
||||
exit(1);
|
||||
}
|
||||
if(a.length() > 9 && a.substr(0, 9) == "--length=")
|
||||
try {
|
||||
length = boost::lexical_cast<uint64_t>(a.substr(9));
|
||||
if(!length)
|
||||
throw std::runtime_error("Length out of range (1-)");
|
||||
} catch(std::exception& e) {
|
||||
std::cerr << "Bad --length: " << e.what() << std::endl;
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
if(!length) {
|
||||
std::cerr << "--length=<frames> has to be specified" << std::endl;
|
||||
exit(1);
|
||||
}
|
||||
std::cout << "Invoking dumper" << std::endl;
|
||||
std::ostringstream cmd;
|
||||
cmd << "dump-avi " << level << " " << prefix;
|
||||
command::invokeC(cmd.str());
|
||||
if(av_snooper::dump_in_progress()) {
|
||||
std::cout << "Dumper attach confirmed" << std::endl;
|
||||
} else {
|
||||
std::cout << "Can't start dumper!" << std::endl;
|
||||
exit(1);
|
||||
}
|
||||
myavsnoop* s = new myavsnoop(length);
|
||||
}
|
||||
|
||||
void startup_lua_scripts(const std::vector<std::string>& cmdline)
|
||||
{
|
||||
for(auto i = cmdline.begin(); i != cmdline.end(); i++) {
|
||||
std::string a = *i;
|
||||
if(a.length() > 6 && a.substr(0, 6) == "--lua=") {
|
||||
command::invokeC("run-lua " + a.substr(6));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class my_interfaced : public SNES::Interface
|
||||
{
|
||||
string path(SNES::Cartridge::Slot slot, const string &hint)
|
||||
{
|
||||
return "./";
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
std::vector<std::string> cmdline;
|
||||
for(int i = 1; i < argc; i++)
|
||||
cmdline.push_back(argv[i]);
|
||||
my_interfaced intrf;
|
||||
SNES::system.interface = &intrf;
|
||||
|
||||
set_random_seed();
|
||||
|
||||
{
|
||||
std::ostringstream x;
|
||||
x << snes_library_id() << " (" << SNES::Info::Profile << " core)";
|
||||
bsnes_core_version = x.str();
|
||||
}
|
||||
init_lua();
|
||||
|
||||
messages << "BSNES version: " << bsnes_core_version << std::endl;
|
||||
messages << "lsnes version: lsnes rr" << lsnes_version << std::endl;
|
||||
messages << "Command line is: ";
|
||||
for(auto k = cmdline.begin(); k != cmdline.end(); k++)
|
||||
messages << "\"" << *k << "\" ";
|
||||
messages << std::endl;
|
||||
|
||||
std::string cfgpath = get_config_path();
|
||||
|
||||
messages << "--- Loading ROM ---" << std::endl;
|
||||
struct loaded_rom r;
|
||||
try {
|
||||
r = load_rom_from_commandline(cmdline);
|
||||
r.load();
|
||||
} catch(std::bad_alloc& e) {
|
||||
OOM_panic();
|
||||
} catch(std::exception& e) {
|
||||
messages << "FATAL: Can't load ROM: " << e.what() << std::endl;
|
||||
fatal_error();
|
||||
exit(1);
|
||||
}
|
||||
messages << "Detected region: " << gtype::tostring(r.rtype, r.region) << std::endl;
|
||||
if(r.region == REGION_PAL)
|
||||
set_nominal_framerate(322445.0/6448.0);
|
||||
else if(r.region == REGION_NTSC)
|
||||
set_nominal_framerate(10738636.0/178683.0);
|
||||
|
||||
messages << "--- Internal memory mappings ---" << std::endl;
|
||||
dump_region_map();
|
||||
messages << "--- End of Startup --- " << std::endl;
|
||||
|
||||
dumper_startup(cmdline);
|
||||
startup_lua_scripts(cmdline);
|
||||
|
||||
moviefile movie;
|
||||
try {
|
||||
bool tried = false;
|
||||
bool loaded = false;
|
||||
for(auto i = cmdline.begin(); i != cmdline.end(); i++)
|
||||
if(i->length() > 0 && (*i)[0] != '-') {
|
||||
try {
|
||||
tried = true;
|
||||
movie = moviefile(*i);
|
||||
loaded = true;
|
||||
} catch(std::bad_alloc& e) {
|
||||
OOM_panic();
|
||||
} catch(std::exception& e) {
|
||||
messages << "Error loading '" << *i << "': " << e.what() << std::endl;
|
||||
}
|
||||
}
|
||||
if(!tried)
|
||||
throw std::runtime_error("Specifying movie is required");
|
||||
if(!loaded)
|
||||
throw std::runtime_error("Can't load any of the movies specified");
|
||||
main_loop(r, movie, true);
|
||||
} catch(std::bad_alloc& e) {
|
||||
OOM_panic();
|
||||
} catch(std::exception& e) {
|
||||
messages << "FATAL: " << e.what() << std::endl;
|
||||
fatal_error();
|
||||
return 1;
|
||||
}
|
||||
rrdata::close();
|
||||
return 0;
|
||||
}
|
|
@ -1,4 +1,3 @@
|
|||
#ifndef PLATFORM_STARTUP
|
||||
#include <sstream>
|
||||
#include "mainloop.hpp"
|
||||
#include "command.hpp"
|
||||
|
@ -14,7 +13,7 @@
|
|||
#include <snes/snes.hpp>
|
||||
#include <ui-libsnes/libsnes.hpp>
|
||||
#include "framerate.hpp"
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
#if defined(_WIN32) || defined(_WIN64) || defined(TEST_WIN32_CODE)
|
||||
#include "SDL_main.h"
|
||||
#endif
|
||||
|
||||
|
@ -74,11 +73,7 @@ namespace
|
|||
}
|
||||
}
|
||||
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
int SDL_main(int argc, char** argv)
|
||||
#else
|
||||
int main(int argc, char** argv)
|
||||
#endif
|
||||
{
|
||||
std::vector<std::string> cmdline;
|
||||
for(int i = 1; i < argc; i++)
|
||||
|
@ -164,4 +159,3 @@ int main(int argc, char** argv)
|
|||
window::quit();
|
||||
return 0;
|
||||
}
|
||||
#endif
|
70
manual.lyx
70
manual.lyx
|
@ -158,7 +158,7 @@ Force ROM to be considered NTSC-only (default for everything except SNES
|
|||
\end_layout
|
||||
|
||||
\begin_layout Subsection
|
||||
New session options
|
||||
New session options (not for lsnes-avidump.exe)
|
||||
\end_layout
|
||||
|
||||
\begin_layout Standard
|
||||
|
@ -227,6 +227,70 @@ If filename is specified on command line, it is loaded as initial state
|
|||
(instead of constructing one).
|
||||
\end_layout
|
||||
|
||||
\begin_layout Standard
|
||||
Mandatory for lsnes-avidump.exe
|
||||
\end_layout
|
||||
|
||||
\begin_layout Subsection
|
||||
lsnes-avidump.exe options
|
||||
\end_layout
|
||||
|
||||
\begin_layout Subsubsection
|
||||
--prefix=<prefix>
|
||||
\end_layout
|
||||
|
||||
\begin_layout Standard
|
||||
Set dump prefix.
|
||||
Default is
|
||||
\begin_inset Quotes eld
|
||||
\end_inset
|
||||
|
||||
avidump
|
||||
\begin_inset Quotes erd
|
||||
\end_inset
|
||||
|
||||
.
|
||||
\end_layout
|
||||
|
||||
\begin_layout Subsubsection
|
||||
--level=<level>
|
||||
\end_layout
|
||||
|
||||
\begin_layout Standard
|
||||
Set compression level (0-18).
|
||||
Default is 7.
|
||||
\end_layout
|
||||
|
||||
\begin_layout Subsubsection
|
||||
--length=<length>
|
||||
\end_layout
|
||||
|
||||
\begin_layout Standard
|
||||
Set number of frames to dump.
|
||||
Mandatory.
|
||||
\end_layout
|
||||
|
||||
\begin_layout Subsubsection
|
||||
--lua=<script>
|
||||
\end_layout
|
||||
|
||||
\begin_layout Standard
|
||||
Run specified lua script.
|
||||
\end_layout
|
||||
|
||||
\begin_layout Section
|
||||
Movieinfo.exe
|
||||
\end_layout
|
||||
|
||||
\begin_layout Itemize
|
||||
Syntax: Movieinfo.exe <file>
|
||||
\end_layout
|
||||
|
||||
\begin_layout Standard
|
||||
Opens <file> and parses it as a movie, giving all sorts of information about
|
||||
it.
|
||||
\end_layout
|
||||
|
||||
\begin_layout Section
|
||||
Startup file lsnes.rc
|
||||
\end_layout
|
||||
|
@ -2968,7 +3032,11 @@ Fix rerecord counting
|
|||
\end_layout
|
||||
|
||||
\begin_layout Itemize
|
||||
Add movieinfo program
|
||||
\end_layout
|
||||
|
||||
\begin_layout Itemize
|
||||
Fix loading movies starting from SRAM.
|
||||
\end_layout
|
||||
|
||||
\end_body
|
||||
|
|
Loading…
Add table
Reference in a new issue