summaryrefslogtreecommitdiffstats
path: root/src/emu/ioport.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/emu/ioport.cpp')
-rw-r--r--src/emu/ioport.cpp132
1 files changed, 122 insertions, 10 deletions
diff --git a/src/emu/ioport.cpp b/src/emu/ioport.cpp
index 28bfe54e040..5999a75abe5 100644
--- a/src/emu/ioport.cpp
+++ b/src/emu/ioport.cpp
@@ -93,6 +93,7 @@
#include "emu.h"
#include "emuopts.h"
#include "config.h"
+#include "fileio.h"
#include "xmlfile.h"
#include "profiler.h"
#include "ui/uimain.h"
@@ -339,6 +340,117 @@ std::string substitute_player(std::string_view name, u8 player)
return result;
}
+
+
+// ======================> inp_header
+
+// header at the front of INP files
+class inp_header
+{
+public:
+ // parameters
+ static constexpr unsigned MAJVERSION = 3;
+ static constexpr unsigned MINVERSION = 0;
+
+ bool read(emu_file &f)
+ {
+ return f.read(m_data, sizeof(m_data)) == sizeof(m_data);
+ }
+ bool write(emu_file &f) const
+ {
+ return f.write(m_data, sizeof(m_data)) == sizeof(m_data);
+ }
+
+ bool check_magic() const
+ {
+ return 0 == std::memcmp(MAGIC, m_data + OFFS_MAGIC, OFFS_BASETIME - OFFS_MAGIC);
+ }
+ u64 get_basetime() const
+ {
+ return
+ (u64(m_data[OFFS_BASETIME + 0]) << (0 * 8)) |
+ (u64(m_data[OFFS_BASETIME + 1]) << (1 * 8)) |
+ (u64(m_data[OFFS_BASETIME + 2]) << (2 * 8)) |
+ (u64(m_data[OFFS_BASETIME + 3]) << (3 * 8)) |
+ (u64(m_data[OFFS_BASETIME + 4]) << (4 * 8)) |
+ (u64(m_data[OFFS_BASETIME + 5]) << (5 * 8)) |
+ (u64(m_data[OFFS_BASETIME + 6]) << (6 * 8)) |
+ (u64(m_data[OFFS_BASETIME + 7]) << (7 * 8));
+ }
+ unsigned get_majversion() const
+ {
+ return m_data[OFFS_MAJVERSION];
+ }
+ unsigned get_minversion() const
+ {
+ return m_data[OFFS_MINVERSION];
+ }
+ std::string get_sysname() const
+ {
+ return get_string<OFFS_SYSNAME, OFFS_APPDESC>();
+ }
+ std::string get_appdesc() const
+ {
+ return get_string<OFFS_APPDESC, OFFS_END>();
+ }
+
+ void set_magic()
+ {
+ std::memcpy(m_data + OFFS_MAGIC, MAGIC, OFFS_BASETIME - OFFS_MAGIC);
+ }
+ void set_basetime(u64 time)
+ {
+ m_data[OFFS_BASETIME + 0] = u8((time >> (0 * 8)) & 0x00ff);
+ m_data[OFFS_BASETIME + 1] = u8((time >> (1 * 8)) & 0x00ff);
+ m_data[OFFS_BASETIME + 2] = u8((time >> (2 * 8)) & 0x00ff);
+ m_data[OFFS_BASETIME + 3] = u8((time >> (3 * 8)) & 0x00ff);
+ m_data[OFFS_BASETIME + 4] = u8((time >> (4 * 8)) & 0x00ff);
+ m_data[OFFS_BASETIME + 5] = u8((time >> (5 * 8)) & 0x00ff);
+ m_data[OFFS_BASETIME + 6] = u8((time >> (6 * 8)) & 0x00ff);
+ m_data[OFFS_BASETIME + 7] = u8((time >> (7 * 8)) & 0x00ff);
+ }
+ void set_version()
+ {
+ m_data[OFFS_MAJVERSION] = MAJVERSION;
+ m_data[OFFS_MINVERSION] = MINVERSION;
+ }
+ void set_sysname(std::string const &name)
+ {
+ set_string<OFFS_SYSNAME, OFFS_APPDESC>(name);
+ }
+ void set_appdesc(std::string const &desc)
+ {
+ set_string<OFFS_APPDESC, OFFS_END>(desc);
+ }
+
+private:
+ template <std::size_t BEGIN, std::size_t END> void set_string(std::string const &str)
+ {
+ std::size_t const used = (std::min<std::size_t>)(str.size() + 1, END - BEGIN);
+ std::memcpy(m_data + BEGIN, str.c_str(), used);
+ if ((END - BEGIN) > used)
+ std::memset(m_data + BEGIN + used, 0, (END - BEGIN) - used);
+ }
+ template <std::size_t BEGIN, std::size_t END> std::string get_string() const
+ {
+ char const *const begin = reinterpret_cast<char const *>(m_data + BEGIN);
+ return std::string(begin, std::find(begin, reinterpret_cast<char const *>(m_data + END), '\0'));
+ }
+
+ static constexpr std::size_t OFFS_MAGIC = 0x00; // 0x08 bytes
+ static constexpr std::size_t OFFS_BASETIME = 0x08; // 0x08 bytes (little-endian binary integer)
+ static constexpr std::size_t OFFS_MAJVERSION = 0x10; // 0x01 bytes (binary integer)
+ static constexpr std::size_t OFFS_MINVERSION = 0x11; // 0x01 bytes (binary integer)
+ // 0x02 bytes reserved
+ static constexpr std::size_t OFFS_SYSNAME = 0x14; // 0x0c bytes (ASCII)
+ static constexpr std::size_t OFFS_APPDESC = 0x20; // 0x20 bytes (ASCII)
+ static constexpr std::size_t OFFS_END = 0x40;
+
+ static u8 const MAGIC[OFFS_BASETIME - OFFS_MAGIC];
+
+ u8 m_data[OFFS_END];
+};
+
} // anonymous namespace
@@ -1734,8 +1846,6 @@ ioport_manager::ioport_manager(running_machine &machine)
, m_safe_to_read(false)
, m_last_frame_time(attotime::zero)
, m_last_delta_nsec(0)
- , m_record_file(machine.options().input_directory(), OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS)
- , m_playback_file(machine.options().input_directory(), OPEN_FLAG_READ)
, m_playback_accumulated_speed(0)
, m_playback_accumulated_frames(0)
, m_deselected_card_config()
@@ -2811,7 +2921,8 @@ time_t ioport_manager::playback_init()
return 0;
// open the playback file
- std::error_condition const filerr = m_playback_file.open(filename);
+ m_playback_file = std::make_unique<emu_file>(machine().options().input_directory(), OPEN_FLAG_READ);
+ std::error_condition const filerr = m_playback_file->open(filename);
// return an explicit error if file isn't found in given path
if (filerr == std::errc::no_such_file_or_directory)
@@ -2823,7 +2934,7 @@ time_t ioport_manager::playback_init()
// read the header and verify that it is a modern version; if not, print an error
inp_header header;
- if (!header.read(m_playback_file))
+ if (!header.read(*m_playback_file))
fatalerror("Input file is corrupt or invalid (missing header)\n");
if (!header.check_magic())
fatalerror("Input file invalid or in an older, unsupported format\n");
@@ -2843,7 +2954,7 @@ time_t ioport_manager::playback_init()
osd_printf_info("Input file is for machine '%s', not for current machine '%s'\n", sysname, machine().system().name);
// enable compression
- m_playback_stream = util::zlib_read(m_playback_file, 16386);
+ m_playback_stream = util::zlib_read(*m_playback_file, 16386);
return basetime;
}
@@ -2859,7 +2970,7 @@ void ioport_manager::playback_end(const char *message)
{
// close the file
m_playback_stream.reset();
- m_playback_file.close();
+ m_playback_file.reset();
// pop a message
if (message != nullptr)
@@ -2981,7 +3092,8 @@ void ioport_manager::record_init()
return;
// open the record file
- std::error_condition const filerr = m_record_file.open(filename);
+ m_record_file = std::make_unique<emu_file>(machine().options().input_directory(), OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS);
+ std::error_condition const filerr = m_record_file->open(filename);
if (filerr)
throw emu_fatalerror("ioport_manager::record_init: Failed to open file for recording (%s:%d %s)", filerr.category().name(), filerr.value(), filerr.message());
@@ -2998,10 +3110,10 @@ void ioport_manager::record_init()
header.set_appdesc(util::string_format("%s %s", emulator_info::get_appname(), emulator_info::get_build_version()));
// write it
- header.write(m_record_file);
+ header.write(*m_record_file);
// enable compression
- m_record_stream = util::zlib_write(m_record_file, 6, 16384);
+ m_record_stream = util::zlib_write(*m_record_file, 6, 16384);
}
@@ -3016,7 +3128,7 @@ void ioport_manager::record_end(const char *message)
{
// close the file
m_record_stream.reset(); // TODO: check for errors flushing the last compressed block before doing this
- m_record_file.close();
+ m_record_file.reset();
// pop a message
if (message != nullptr)