summaryrefslogtreecommitdiffstatshomepage
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/devices/bus/coco/coco_dwsock.cpp33
-rw-r--r--src/devices/bus/coco/coco_dwsock.h2
-rw-r--r--src/devices/bus/iq151/minigraf.cpp4
-rw-r--r--src/devices/bus/iq151/ms151a.cpp4
-rw-r--r--src/devices/bus/nubus/nubus_image.cpp26
-rw-r--r--src/devices/bus/nubus/nubus_image.h2
-rw-r--r--src/devices/bus/ti99x/gromport.cpp48
-rw-r--r--src/devices/bus/ti99x/gromport.h4
-rw-r--r--src/devices/imagedev/diablo.cpp6
-rw-r--r--src/devices/imagedev/floppy.cpp14
-rw-r--r--src/devices/imagedev/harddriv.cpp6
-rw-r--r--src/devices/sound/samples.cpp12
-rw-r--r--src/emu/audit.cpp10
-rw-r--r--src/emu/cheat.cpp8
-rw-r--r--src/emu/clifront.cpp85
-rw-r--r--src/emu/config.cpp16
-rw-r--r--src/emu/debug/debugcmd.cpp4
-rw-r--r--src/emu/debug/debugcpu.cpp8
-rw-r--r--src/emu/diimage.cpp60
-rw-r--r--src/emu/dipty.cpp56
-rw-r--r--src/emu/dipty.h32
-rw-r--r--src/emu/emuopts.cpp4
-rw-r--r--src/emu/fileio.cpp150
-rw-r--r--src/emu/fileio.h54
-rw-r--r--src/emu/hashfile.cpp4
-rw-r--r--src/emu/image.cpp4
-rw-r--r--src/emu/ioport.cpp12
-rw-r--r--src/emu/language.cpp2
-rw-r--r--src/emu/luaengine.cpp6
-rw-r--r--src/emu/machine.cpp14
-rw-r--r--src/emu/mame.cpp4
-rw-r--r--src/emu/render.cpp4
-rw-r--r--src/emu/rendfont.cpp14
-rw-r--r--src/emu/rendutil.cpp4
-rw-r--r--src/emu/romload.cpp48
-rw-r--r--src/emu/romload.h8
-rw-r--r--src/emu/screen.cpp4
-rw-r--r--src/emu/softlist.cpp4
-rw-r--r--src/emu/ui/auditmenu.cpp2
-rw-r--r--src/emu/ui/cmdrender.h2
-rw-r--r--src/emu/ui/custmenu.cpp4
-rw-r--r--src/emu/ui/datfile.cpp2
-rw-r--r--src/emu/ui/dirmenu.cpp76
-rw-r--r--src/emu/ui/filesel.cpp8
-rw-r--r--src/emu/ui/icorender.h4
-rw-r--r--src/emu/ui/imgcntrl.cpp6
-rw-r--r--src/emu/ui/inifile.cpp6
-rw-r--r--src/emu/ui/miscmenu.cpp22
-rw-r--r--src/emu/ui/optsmenu.cpp7
-rw-r--r--src/emu/ui/selgame.cpp64
-rw-r--r--src/emu/ui/selsoft.cpp33
-rw-r--r--src/emu/ui/ui.cpp2
-rw-r--r--src/emu/ui/utils.h4
-rw-r--r--src/emu/video.cpp55
-rw-r--r--src/emu/video.h16
-rw-r--r--src/lib/util/aviio.cpp3369
-rw-r--r--src/lib/util/aviio.h188
-rw-r--r--src/lib/util/cdrom.cpp4
-rw-r--r--src/lib/util/chd.cpp16
-rw-r--r--src/lib/util/chdcd.cpp55
-rw-r--r--src/lib/util/corefile.cpp168
-rw-r--r--src/lib/util/corefile.h25
-rw-r--r--src/lib/util/un7z.cpp693
-rw-r--r--src/lib/util/un7z.h152
-rw-r--r--src/lib/util/unzip.cpp794
-rw-r--r--src/lib/util/unzip.h187
-rw-r--r--src/lib/util/zippath.cpp175
-rw-r--r--src/lib/util/zippath.h4
-rw-r--r--src/mame/drivers/jaguar.cpp4
-rw-r--r--src/mame/etc/jrcrypt.cpp4
-rw-r--r--src/mame/machine/fddebug.cpp16
-rw-r--r--src/osd/modules/file/posixfile.cpp482
-rw-r--r--src/osd/modules/file/posixfile.h28
-rw-r--r--src/osd/modules/file/posixptty.cpp184
-rw-r--r--src/osd/modules/file/posixsocket.cpp236
-rw-r--r--src/osd/modules/file/stdfile.cpp251
-rw-r--r--src/osd/modules/file/winfile.cpp513
-rw-r--r--src/osd/modules/file/winfile.h34
-rw-r--r--src/osd/modules/file/winptty.cpp111
-rw-r--r--src/osd/modules/file/winsocket.cpp277
-rw-r--r--src/osd/modules/render/d3d/d3dhlsl.cpp36
-rw-r--r--src/osd/modules/render/d3d/d3dhlsl.h34
-rw-r--r--src/osd/osdcore.h270
-rw-r--r--src/osd/osdmini/minidir.cpp11
-rw-r--r--src/osd/osdmini/minifile.cpp238
-rw-r--r--src/osd/osdmini/minimisc.cpp6
-rw-r--r--src/osd/sdl/sdldir.cpp79
-rw-r--r--src/osd/sdl/sdlfile.cpp630
-rw-r--r--src/osd/sdl/sdlfile.h51
-rw-r--r--src/osd/sdl/sdlptty_unix.cpp161
-rw-r--r--src/osd/sdl/sdlptty_win32.cpp12
-rw-r--r--src/osd/sdl/sdlsocket.cpp193
-rw-r--r--src/osd/windows/windir.cpp17
-rw-r--r--src/osd/windows/winfile.cpp571
-rw-r--r--src/osd/windows/winfile.h56
-rw-r--r--src/osd/windows/winptty.cpp70
-rw-r--r--src/osd/windows/winsocket.cpp204
-rw-r--r--src/osd/windows/winutil.cpp41
-rw-r--r--src/osd/windows/winutil.h9
-rw-r--r--src/tools/chdman.cpp121
-rw-r--r--src/tools/imgtool/stream.cpp28
-rw-r--r--src/tools/ldverify.cpp42
-rw-r--r--src/tools/pngcmp.cpp16
-rw-r--r--src/tools/regrep.cpp18
-rw-r--r--src/tools/romcmp.cpp36
-rw-r--r--src/tools/split.cpp18
-rw-r--r--src/tools/src2html.cpp8
-rw-r--r--src/tools/unidasm.cpp4
108 files changed, 5860 insertions, 6183 deletions
diff --git a/src/devices/bus/coco/coco_dwsock.cpp b/src/devices/bus/coco/coco_dwsock.cpp
index 2750f266998..fb2e18a23fb 100644
--- a/src/devices/bus/coco/coco_dwsock.cpp
+++ b/src/devices/bus/coco/coco_dwsock.cpp
@@ -68,14 +68,13 @@ beckerport_device::beckerport_device(const machine_config &mconfig, const char *
: device_t(mconfig, COCO_DWSOCK, "Virtual Becker Port", tag, owner, clock, "coco_dwsock", __FILE__), m_hostname(nullptr),
m_dwconfigport(*this, DRIVEWIRE_PORT_TAG), m_dwtcpport(0)
{
- m_pSocket = nullptr;
m_head = 0;
m_rx_pending = 0;
}
beckerport_device::~beckerport_device()
{
- if (m_pSocket != nullptr)
+ if (m_pSocket)
beckerport_device::device_stop();
}
@@ -93,8 +92,8 @@ void beckerport_device::device_start(void)
osd_printf_verbose("Connecting to Drivewire server on %s:%d... ", m_hostname, m_dwtcpport);
UINT64 filesize; // unused
- file_error filerr = osd_open(chAddress, 0, &m_pSocket, &filesize);
- if (filerr != FILERR_NONE)
+ osd_file::error filerr = osd_file::open(chAddress, 0, m_pSocket, filesize);
+ if (filerr != osd_file::error::NONE)
{
osd_printf_verbose("Error: osd_open returned error %i!\n", (int) filerr);
return;
@@ -109,11 +108,10 @@ void beckerport_device::device_start(void)
void beckerport_device::device_stop(void)
{
- if (m_pSocket != nullptr)
+ if (m_pSocket)
{
printf("Closing connection to Drivewire server\n");
- osd_close(m_pSocket);
- m_pSocket = nullptr;
+ m_pSocket.reset();
}
}
@@ -135,7 +133,7 @@ READ8_MEMBER(beckerport_device::read)
{
unsigned char data = 0x5a;
- if (m_pSocket == nullptr)
+ if (!m_pSocket)
return data;
switch (offset)
@@ -144,9 +142,9 @@ READ8_MEMBER(beckerport_device::read)
if (!m_rx_pending)
{
/* Try to read from dws */
- file_error filerr = osd_read(m_pSocket, m_buf, 0, sizeof(m_buf), &m_rx_pending);
- if (filerr != FILERR_NONE && filerr != FILERR_FAILURE) // FILERR_FAILURE means no data available, so don't throw error message
- fprintf(stderr, "coco_dwsock.c: beckerport_device::read() socket read operation failed with file_error %i\n", filerr);
+ osd_file::error filerr = m_pSocket->read(m_buf, 0, sizeof(m_buf), m_rx_pending);
+ if (filerr != osd_file::error::NONE && filerr != osd_file::error::FAILURE) // osd_file::error::FAILURE means no data available, so don't throw error message
+ fprintf(stderr, "coco_dwsock.c: beckerport_device::read() socket read operation failed with osd_file::error %i\n", int(filerr));
else
m_head = 0;
}
@@ -175,10 +173,11 @@ READ8_MEMBER(beckerport_device::read)
WRITE8_MEMBER(beckerport_device::write)
{
- char d = (char)data;
- file_error filerr;
+ char d = char(data);
+ osd_file::error filerr;
+ std::uint32_t written;
- if (m_pSocket == nullptr)
+ if (!m_pSocket)
return;
switch (offset)
@@ -187,9 +186,9 @@ WRITE8_MEMBER(beckerport_device::write)
//printf("beckerport_write: error: write (0x%02x) to status register\n", d);
break;
case DWS_DATA:
- filerr = osd_write(m_pSocket, &d, 0, 1, nullptr);
- if (filerr != FILERR_NONE)
- fprintf(stderr, "coco_dwsock.c: beckerport_device::write() socket write operation failed with file_error %i\n", filerr);
+ filerr = m_pSocket->write(&d, 0, 1, written);
+ if (filerr != osd_file::error::NONE)
+ fprintf(stderr, "coco_dwsock.c: beckerport_device::write() socket write operation failed with osd_file::error %i\n", int(filerr));
//printf("beckerport_write: data write one byte (0x%02x)\n", d & 0xff);
break;
default:
diff --git a/src/devices/bus/coco/coco_dwsock.h b/src/devices/bus/coco/coco_dwsock.h
index 1d1fe71c3d3..d3af3fbb525 100644
--- a/src/devices/bus/coco/coco_dwsock.h
+++ b/src/devices/bus/coco/coco_dwsock.h
@@ -57,7 +57,7 @@ private:
required_ioport m_dwconfigport;
int m_dwtcpport;
- osd_file *m_pSocket;
+ osd_file::ptr m_pSocket;
unsigned int m_rx_pending;
unsigned int m_head;
diff --git a/src/devices/bus/iq151/minigraf.cpp b/src/devices/bus/iq151/minigraf.cpp
index 1a8e9d182a0..14cd9515cf7 100644
--- a/src/devices/bus/iq151/minigraf.cpp
+++ b/src/devices/bus/iq151/minigraf.cpp
@@ -78,9 +78,9 @@ void iq151_minigraf_device::device_stop()
{
#if DUMP_PAPER_INTO_PNG
emu_file file(machine().options().snapshot_directory(), OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS);
- file_error filerr = file.open("iq151_minigraf.png");
+ auto const filerr = file.open("iq151_minigraf.png");
- if (filerr == FILERR_NONE)
+ if (filerr == osd_file::error::NONE)
{
static const rgb_t png_palette[] = { rgb_t::white, rgb_t::black };
diff --git a/src/devices/bus/iq151/ms151a.cpp b/src/devices/bus/iq151/ms151a.cpp
index 99da92c6d61..c3aedf5f07d 100644
--- a/src/devices/bus/iq151/ms151a.cpp
+++ b/src/devices/bus/iq151/ms151a.cpp
@@ -77,9 +77,9 @@ void iq151_ms151a_device::device_stop()
{
#if DUMP_PAPER_INTO_PNG
emu_file file(machine().options().snapshot_directory(), OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS);
- file_error filerr = file.open("iq151_ms151a.png");
+ osd_file::error filerr = file.open("iq151_ms151a.png");
- if (filerr == FILERR_NONE)
+ if (filerr == osd_file::error::NONE)
{
static const rgb_t png_palette[] = { rgb_t::white, rgb_t::black };
diff --git a/src/devices/bus/nubus/nubus_image.cpp b/src/devices/bus/nubus/nubus_image.cpp
index 412925fc351..d7752e3babc 100644
--- a/src/devices/bus/nubus/nubus_image.cpp
+++ b/src/devices/bus/nubus/nubus_image.cpp
@@ -310,7 +310,7 @@ WRITE32_MEMBER( nubus_image_device::file_cmd_w )
strcpy(fullpath, (const char *)filectx.curdir);
strcat(fullpath, "/");
strcat(fullpath, (const char*)filectx.filename);
- if(osd_open((const char*)fullpath, OPEN_FLAG_READ, &filectx.fd, &filectx.filelen) != FILERR_NONE) printf("Error opening %s\n", fullpath);
+ if(osd_file::open(std::string(fullpath), OPEN_FLAG_READ, filectx.fd, filectx.filelen) != osd_file::error::NONE) printf("Error opening %s\n", fullpath);
filectx.bytecount = 0;
break;
case kFileCmdPutFile:
@@ -318,7 +318,7 @@ WRITE32_MEMBER( nubus_image_device::file_cmd_w )
strcpy(fullpath, (const char *)filectx.curdir);
strcat(fullpath, "/");
strcat(fullpath, (const char*)filectx.filename);
- if(osd_open((const char*)fullpath, OPEN_FLAG_WRITE|OPEN_FLAG_CREATE, &filectx.fd, &filesize) != FILERR_NONE) printf("Error opening %s\n", fullpath);
+ if(osd_file::open(std::string(fullpath), OPEN_FLAG_WRITE|OPEN_FLAG_CREATE, filectx.fd, filesize) != osd_file::error::NONE) printf("Error opening %s\n", fullpath);
filectx.bytecount = 0;
break;
}
@@ -331,33 +331,31 @@ READ32_MEMBER( nubus_image_device::file_cmd_r )
WRITE32_MEMBER( nubus_image_device::file_data_w )
{
- UINT32 count = 4;
- UINT32 actualcount = 0;
+ std::uint32_t count = 4;
+ std::uint32_t actualcount = 0;
data = ((data & 0xff) << 24) | ((data & 0xff00) << 8) | ((data & 0xff0000) >> 8) | ((data & 0xff000000) >> 24);
- if(filectx.fd != nullptr) {
+ if(filectx.fd) {
//data = ni_ntohl(data);
if((filectx.bytecount + count) > filectx.filelen) count = filectx.filelen - filectx.bytecount;
- osd_write(filectx.fd, &data, filectx.bytecount, count, &actualcount);
+ filectx.fd->write(&data, filectx.bytecount, count, actualcount);
filectx.bytecount += actualcount;
if(filectx.bytecount >= filectx.filelen) {
- osd_close(filectx.fd);
- filectx.fd = nullptr;
+ filectx.fd.reset();
}
}
}
READ32_MEMBER( nubus_image_device::file_data_r )
{
- if(filectx.fd != nullptr) {
- UINT32 ret;
- UINT32 actual = 0;
- osd_read(filectx.fd, &ret, filectx.bytecount, sizeof(ret), &actual);
+ if(filectx.fd) {
+ std::uint32_t ret;
+ std::uint32_t actual = 0;
+ filectx.fd->read(&ret, filectx.bytecount, sizeof(ret), actual);
filectx.bytecount += actual;
if(actual < sizeof(ret)) {
- osd_close(filectx.fd);
- filectx.fd = nullptr;
+ filectx.fd.reset();
}
return ni_htonl(ret);
}
diff --git a/src/devices/bus/nubus/nubus_image.h b/src/devices/bus/nubus/nubus_image.h
index d850b3f7735..dda6e55fc02 100644
--- a/src/devices/bus/nubus/nubus_image.h
+++ b/src/devices/bus/nubus/nubus_image.h
@@ -19,7 +19,7 @@ struct nbfilectx {
UINT8 filename[128];
UINT8 curdir[1024];
osd_directory *dirp;
- osd_file *fd;
+ osd_file::ptr fd;
UINT64 filelen;
UINT32 bytecount;
};
diff --git a/src/devices/bus/ti99x/gromport.cpp b/src/devices/bus/ti99x/gromport.cpp
index 9e1533cb9a8..2b9a66d028a 100644
--- a/src/devices/bus/ti99x/gromport.cpp
+++ b/src/devices/bus/ti99x/gromport.cpp
@@ -148,7 +148,7 @@
static void image_battery_load_by_name(emu_options &options, const char *filename, void *buffer, int length, int fill)
{
- file_error filerr;
+ osd_file::error filerr;
int bytes_read = 0;
assert_always(buffer && (length > 0), "Must specify sensical buffer/length");
@@ -156,7 +156,7 @@ static void image_battery_load_by_name(emu_options &options, const char *filenam
/* try to open the battery file and read it in, if possible */
emu_file file(options.nvram_directory(), OPEN_FLAG_READ);
filerr = file.open(filename);
- if (filerr == FILERR_NONE)
+ if (filerr == osd_file::error::NONE)
bytes_read = file.read(buffer, length);
/* fill remaining bytes (if necessary) */
@@ -174,8 +174,8 @@ static void image_battery_save_by_name(emu_options &options, const char *filenam
/* try to open the battery file and write it out, if possible */
emu_file file(options.nvram_directory(), OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS);
- file_error filerr = file.open(filename);
- if (filerr == FILERR_NONE)
+ osd_file::error filerr = file.open(filename);
+ if (filerr == osd_file::error::NONE)
file.write(buffer, length);
}
@@ -2245,10 +2245,10 @@ rpk_socket::rpk_socket(const char* id, int length, UINT8* contents)
/*
Locate a file in the ZIP container
*/
-const zip_file_header* rpk_reader::find_file(zip_file *zip, const char *filename, UINT32 crc)
+const zip_file::file_header* rpk_reader::find_file(zip_file &zip, const char *filename, UINT32 crc)
{
- const zip_file_header *header;
- for (header = zip_file_first_file(zip); header != nullptr; header = zip_file_next_file(zip))
+ const zip_file::file_header *header;
+ for (header = zip.first_file(); header != nullptr; header = zip.next_file())
{
// We don't check for CRC == 0.
if (crc != 0)
@@ -2272,16 +2272,16 @@ const zip_file_header* rpk_reader::find_file(zip_file *zip, const char *filename
/*
Load a rom resource and put it in a pcb socket instance.
*/
-rpk_socket* rpk_reader::load_rom_resource(zip_file* zip, xml_data_node* rom_resource_node, const char* socketname)
+rpk_socket* rpk_reader::load_rom_resource(zip_file &zip, xml_data_node* rom_resource_node, const char* socketname)
{
const char* file;
const char* crcstr;
const char* sha1;
- zip_error ziperr;
+ zip_file::error ziperr;
UINT32 crc;
int length;
UINT8* contents;
- const zip_file_header *header;
+ const zip_file::file_header *header;
// find the file attribute (required)
file = xml_get_attribute_string(rom_resource_node, "file", nullptr);
@@ -2310,10 +2310,10 @@ rpk_socket* rpk_reader::load_rom_resource(zip_file* zip, xml_data_node* rom_reso
if (contents==nullptr) throw rpk_exception(RPK_OUT_OF_MEMORY);
// and unzip file from the zip file
- ziperr = zip_file_decompress(zip, contents, length);
- if (ziperr != ZIPERR_NONE)
+ ziperr = zip.decompress(contents, length);
+ if (ziperr != zip_file::error::NONE)
{
- if (ziperr == ZIPERR_UNSUPPORTED) throw rpk_exception(RPK_ZIP_UNSUPPORTED);
+ if (ziperr == zip_file::error::UNSUPPORTED) throw rpk_exception(RPK_ZIP_UNSUPPORTED);
else throw rpk_exception(RPK_ZIP_ERROR);
}
@@ -2414,15 +2414,15 @@ rpk_socket* rpk_reader::load_ram_resource(emu_options &options, xml_data_node* r
rpk* rpk_reader::open(emu_options &options, const char *filename, const char *system_name)
{
- zip_error ziperr;
+ zip_file::error ziperr;
- const zip_file_header *header;
+ const zip_file::file_header *header;
const char *pcb_type;
const char *id;
const char *uses_name;
const char *resource_name;
- zip_file* zipfile;
+ zip_file::ptr zipfile;
std::vector<char> layout_text;
xml_data_node *layout_xml = nullptr;
@@ -2442,21 +2442,21 @@ rpk* rpk_reader::open(emu_options &options, const char *filename, const char *sy
try
{
/* open the ZIP file */
- ziperr = zip_file_open(filename, &zipfile);
- if (ziperr != ZIPERR_NONE) throw rpk_exception(RPK_NOT_ZIP_FORMAT);
+ ziperr = zip_file::open(filename, zipfile);
+ if (ziperr != zip_file::error::NONE) throw rpk_exception(RPK_NOT_ZIP_FORMAT);
/* find the layout.xml file */
- header = find_file(zipfile, "layout.xml", 0);
+ header = find_file(*zipfile, "layout.xml", 0);
if (header == nullptr) throw rpk_exception(RPK_MISSING_LAYOUT);
/* reserve space for the layout file contents (+1 for the termination) */
layout_text.resize(header->uncompressed_length + 1);
/* uncompress the layout text */
- ziperr = zip_file_decompress(zipfile, &layout_text[0], header->uncompressed_length);
- if (ziperr != ZIPERR_NONE)
+ ziperr = zipfile->decompress(&layout_text[0], header->uncompressed_length);
+ if (ziperr != zip_file::error::NONE)
{
- if (ziperr == ZIPERR_UNSUPPORTED) throw rpk_exception(RPK_ZIP_UNSUPPORTED);
+ if (ziperr == zip_file::error::UNSUPPORTED) throw rpk_exception(RPK_ZIP_UNSUPPORTED);
else throw rpk_exception(RPK_ZIP_ERROR);
}
@@ -2523,7 +2523,7 @@ rpk* rpk_reader::open(emu_options &options, const char *filename, const char *sy
// found it
if (strcmp(resource_node->name, "rom")==0)
{
- newsock = load_rom_resource(zipfile, resource_node, id);
+ newsock = load_rom_resource(*zipfile, resource_node, id);
newrpk->add_socket(id, newsock);
}
else
@@ -2545,14 +2545,12 @@ rpk* rpk_reader::open(emu_options &options, const char *filename, const char *sy
{
newrpk->close();
if (layout_xml != nullptr) xml_file_free(layout_xml);
- if (zipfile != nullptr) zip_file_close(zipfile);
// rethrow the exception
throw;
}
if (layout_xml != nullptr) xml_file_free(layout_xml);
- if (zipfile != nullptr) zip_file_close(zipfile);
return newrpk;
}
diff --git a/src/devices/bus/ti99x/gromport.h b/src/devices/bus/ti99x/gromport.h
index 7655173b10d..9b60425aa06 100644
--- a/src/devices/bus/ti99x/gromport.h
+++ b/src/devices/bus/ti99x/gromport.h
@@ -454,8 +454,8 @@ public:
rpk *open(emu_options &options, const char *filename, const char *system_name);
private:
- const zip_file_header* find_file(zip_file *zip, const char *filename, UINT32 crc);
- rpk_socket* load_rom_resource(zip_file* zip, xml_data_node* rom_resource_node, const char* socketname);
+ const zip_file::file_header* find_file(zip_file &zip, const char *filename, UINT32 crc);
+ rpk_socket* load_rom_resource(zip_file &zip, xml_data_node* rom_resource_node, const char* socketname);
rpk_socket* load_ram_resource(emu_options &options, xml_data_node* ram_resource_node, const char* socketname, const char* system_name);
const pcb_type* m_types;
};
diff --git a/src/devices/imagedev/diablo.cpp b/src/devices/imagedev/diablo.cpp
index 6ba6aad5cf2..ba43f09efee 100644
--- a/src/devices/imagedev/diablo.cpp
+++ b/src/devices/imagedev/diablo.cpp
@@ -171,8 +171,8 @@ static chd_error open_disk_diff(emu_options &options, const char *name, chd_file
/* try to open the diff */
//printf("Opening differencing image file: %s\n", fname.c_str());
emu_file diff_file(options.diff_directory(), OPEN_FLAG_READ | OPEN_FLAG_WRITE);
- file_error filerr = diff_file.open(fname.c_str());
- if (filerr == FILERR_NONE)
+ osd_file::error filerr = diff_file.open(fname.c_str());
+ if (filerr == osd_file::error::NONE)
{
std::string fullpath(diff_file.fullpath());
diff_file.close();
@@ -185,7 +185,7 @@ static chd_error open_disk_diff(emu_options &options, const char *name, chd_file
//printf("Creating differencing image: %s\n", fname.c_str());
diff_file.set_openflags(OPEN_FLAG_READ | OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS);
filerr = diff_file.open(fname.c_str());
- if (filerr == FILERR_NONE)
+ if (filerr == osd_file::error::NONE)
{
std::string fullpath(diff_file.fullpath());
diff_file.close();
diff --git a/src/devices/imagedev/floppy.cpp b/src/devices/imagedev/floppy.cpp
index c4269c944ef..38e0a5ff9d8 100644
--- a/src/devices/imagedev/floppy.cpp
+++ b/src/devices/imagedev/floppy.cpp
@@ -295,9 +295,9 @@ void floppy_image_device::commit_image()
io.procs = &image_ioprocs;
io.filler = 0xff;
- file_error err = image_core_file().truncate(0);
- if (err != 0)
- popmessage("Error, unable to truncate image: %d", err);
+ osd_file::error err = image_core_file().truncate(0);
+ if (err != osd_file::error::NONE)
+ popmessage("Error, unable to truncate image: %d", int(err));
output_format->save(&io, image);
}
@@ -365,8 +365,8 @@ floppy_image_format_t *floppy_image_device::identify(std::string filename)
util::core_file::ptr fd;
std::string revised_path;
- file_error err = zippath_fopen(filename.c_str(), OPEN_FLAG_READ, fd, revised_path);
- if(err) {
+ osd_file::error err = zippath_fopen(filename.c_str(), OPEN_FLAG_READ, fd, revised_path);
+ if(err != osd_file::error::NONE) {
seterror(IMAGE_ERROR_INVALIDIMAGE, "Unable to open the image file");
return nullptr;
}
@@ -1000,12 +1000,12 @@ void ui_menu_control_floppy_image::hook_load(std::string filename, bool softlist
bool can_in_place = input_format->supports_save();
if(can_in_place) {
- file_error filerr;
+ osd_file::error filerr;
std::string tmp_path;
util::core_file::ptr tmp_file;
/* attempt to open the file for writing but *without* create */
filerr = zippath_fopen(filename.c_str(), OPEN_FLAG_READ | OPEN_FLAG_WRITE, tmp_file, tmp_path);
- if(!filerr)
+ if(filerr == osd_file::error::NONE)
tmp_file.reset();
else
can_in_place = false;
diff --git a/src/devices/imagedev/harddriv.cpp b/src/devices/imagedev/harddriv.cpp
index d07852e166f..ff058f837f7 100644
--- a/src/devices/imagedev/harddriv.cpp
+++ b/src/devices/imagedev/harddriv.cpp
@@ -195,8 +195,8 @@ static chd_error open_disk_diff(emu_options &options, const char *name, chd_file
/* try to open the diff */
//printf("Opening differencing image file: %s\n", fname.c_str());
emu_file diff_file(options.diff_directory(), OPEN_FLAG_READ | OPEN_FLAG_WRITE);
- file_error filerr = diff_file.open(fname.c_str());
- if (filerr == FILERR_NONE)
+ osd_file::error filerr = diff_file.open(fname.c_str());
+ if (filerr == osd_file::error::NONE)
{
std::string fullpath(diff_file.fullpath());
diff_file.close();
@@ -209,7 +209,7 @@ static chd_error open_disk_diff(emu_options &options, const char *name, chd_file
//printf("Creating differencing image: %s\n", fname.c_str());
diff_file.set_openflags(OPEN_FLAG_READ | OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS);
filerr = diff_file.open(fname.c_str());
- if (filerr == FILERR_NONE)
+ if (filerr == osd_file::error::NONE)
{
std::string fullpath(diff_file.fullpath());
diff_file.close();
diff --git a/src/devices/sound/samples.cpp b/src/devices/sound/samples.cpp
index 62bd8e02657..0b92b51202d 100644
--- a/src/devices/sound/samples.cpp
+++ b/src/devices/sound/samples.cpp
@@ -618,20 +618,20 @@ bool samples_device::load_samples()
{
// attempt to open as FLAC first
emu_file file(machine().options().sample_path(), OPEN_FLAG_READ);
- file_error filerr = file.open(basename, PATH_SEPARATOR, samplename, ".flac");
- if (filerr != FILERR_NONE && altbasename != nullptr)
+ osd_file::error filerr = file.open(basename, PATH_SEPARATOR, samplename, ".flac");
+ if (filerr != osd_file::error::NONE && altbasename != nullptr)
filerr = file.open(altbasename, PATH_SEPARATOR, samplename, ".flac");
// if not, try as WAV
- if (filerr != FILERR_NONE)
+ if (filerr != osd_file::error::NONE)
filerr = file.open(basename, PATH_SEPARATOR, samplename, ".wav");
- if (filerr != FILERR_NONE && altbasename != nullptr)
+ if (filerr != osd_file::error::NONE && altbasename != nullptr)
filerr = file.open(altbasename, PATH_SEPARATOR, samplename, ".wav");
// if opened, read it
- if (filerr == FILERR_NONE)
+ if (filerr == osd_file::error::NONE)
read_sample(file, m_sample[index]);
- else if (filerr == FILERR_NOT_FOUND)
+ else if (filerr == osd_file::error::NOT_FOUND)
{
logerror("%s: Sample '%s' NOT FOUND\n", tag(), samplename);
ok = false;
diff --git a/src/emu/audit.cpp b/src/emu/audit.cpp
index 7f371ee56c8..e9e4dee63f2 100644
--- a/src/emu/audit.cpp
+++ b/src/emu/audit.cpp
@@ -296,11 +296,11 @@ media_auditor::summary media_auditor::audit_samples()
while (path.next(curpath, samplename))
{
// attempt to access the file (.flac) or (.wav)
- file_error filerr = file.open(curpath.c_str(), ".flac");
- if (filerr != FILERR_NONE)
+ osd_file::error filerr = file.open(curpath.c_str(), ".flac");
+ if (filerr != osd_file::error::NONE)
filerr = file.open(curpath.c_str(), ".wav");
- if (filerr == FILERR_NONE)
+ if (filerr == osd_file::error::NONE)
{
record.set_status(audit_record::STATUS_GOOD, audit_record::SUBSTATUS_GOOD);
found++;
@@ -433,14 +433,14 @@ audit_record *media_auditor::audit_one_rom(const rom_entry *rom)
while (path.next(curpath, record.name()))
{
// open the file if we can
- file_error filerr;
+ osd_file::error filerr;
if (has_crc)
filerr = file.open(curpath.c_str(), crc);
else
filerr = file.open(curpath.c_str());
// if it worked, get the actual length and hashes, then stop
- if (filerr == FILERR_NONE)
+ if (filerr == osd_file::error::NONE)
{
record.set_actual(file.hashes(m_validation), file.size());
break;
diff --git a/src/emu/cheat.cpp b/src/emu/cheat.cpp
index 0a799ca6f13..f9fe6499d61 100644
--- a/src/emu/cheat.cpp
+++ b/src/emu/cheat.cpp
@@ -1171,10 +1171,10 @@ bool cheat_manager::save_all(const char *filename)
{
// open the file with the proper name
emu_file cheatfile(machine().options().cheat_path(), OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS);
- file_error filerr = cheatfile.open(filename, ".xml");
+ osd_file::error filerr = cheatfile.open(filename, ".xml");
// if that failed, return nothing
- if (filerr != FILERR_NONE)
+ if (filerr != osd_file::error::NONE)
return false;
// wrap the rest of catch errors
@@ -1372,10 +1372,10 @@ void cheat_manager::load_cheats(const char *filename)
try
{
// open the file with the proper name
- file_error filerr = cheatfile.open(filename, ".xml");
+ osd_file::error filerr = cheatfile.open(filename, ".xml");
// loop over all instrances of the files found in our search paths
- while (filerr == FILERR_NONE)
+ while (filerr == osd_file::error::NONE)
{
osd_printf_verbose("Loading cheats file from %s\n", cheatfile.fullpath());
diff --git a/src/emu/clifront.cpp b/src/emu/clifront.cpp
index 7c6c974cce7..79b53e943c7 100644
--- a/src/emu/clifront.cpp
+++ b/src/emu/clifront.cpp
@@ -266,7 +266,7 @@ int cli_frontend::execute(int argc, char **argv)
m_result = MAMERR_FATALERROR;
}
- _7z_file_cache_clear();
+ _7z_file::cache_clear();
global_free(manager);
return m_result;
@@ -1000,7 +1000,7 @@ void cli_frontend::verifyroms(const char *gamename)
}
// clear out any cached files
- zip_file_cache_clear();
+ zip_file::cache_clear();
// return an error if none found
if (matched == 0)
@@ -1092,7 +1092,7 @@ void cli_frontend::verifysamples(const char *gamename)
}
// clear out any cached files
- zip_file_cache_clear();
+ zip_file::cache_clear();
// return an error if none found
if (matched == 0)
@@ -1407,7 +1407,7 @@ void cli_frontend::verifysoftware(const char *gamename)
}
// clear out any cached files
- zip_file_cache_clear();
+ zip_file::cache_clear();
// return an error if none found
if (matched == 0)
@@ -1529,7 +1529,7 @@ void cli_frontend::verifysoftlist(const char *gamename)
}
// clear out any cached files
- zip_file_cache_clear();
+ zip_file::cache_clear();
// return an error if none found
if (matched == 0)
@@ -1618,7 +1618,7 @@ void cli_frontend::execute_commands(const char *exename)
{
// attempt to open the output file
emu_file file(OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS);
- if (file.open(emulator_info::get_configname(), ".ini") != FILERR_NONE)
+ if (file.open(emulator_info::get_configname(), ".ini") != osd_file::error::NONE)
throw emu_fatalerror("Unable to create file %s.ini\n",emulator_info::get_configname());
// generate the updated INI
@@ -1626,7 +1626,7 @@ void cli_frontend::execute_commands(const char *exename)
ui_options ui_opts;
emu_file file_ui(OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS);
- if (file_ui.open("ui.ini") != FILERR_NONE)
+ if (file_ui.open("ui.ini") != osd_file::error::NONE)
throw emu_fatalerror("Unable to create file ui.ini\n");
// generate the updated INI
@@ -1761,68 +1761,61 @@ void media_identifier::identify(const char *filename)
if (core_filename_ends_with(filename, ".7z"))
{
// first attempt to examine it as a valid _7Z file
- _7z_file *_7z = nullptr;
- _7z_error _7zerr = _7z_file_open(filename, &_7z);
- if (_7zerr == _7ZERR_NONE && _7z != nullptr)
+ _7z_file::ptr _7z;
+ _7z_file::error _7zerr = _7z_file::open(filename, _7z);
+ if (_7zerr == _7z_file::error::NONE && _7z != nullptr)
{
+ std::vector<std::uint8_t> data;
+
// loop over entries in the .7z, skipping empty files and directories
- for (int i = 0; i < _7z->db.db.NumFiles; i++)
+ for (int i = _7z->first_file(); i >= 0; i = _7z->next_file())
{
- const CSzFileItem *f = _7z->db.db.Files + i;
- _7z->curr_file_idx = i;
- int namelen = SzArEx_GetFileNameUtf16(&_7z->db, i, nullptr);
- std::vector<UINT16> temp(namelen);
- dynamic_buffer temp2(namelen+1);
- UINT8* temp3 = &temp2[0];
- memset(temp3, 0x00, namelen);
- SzArEx_GetFileNameUtf16(&_7z->db, i, &temp[0]);
- // crude, need real UTF16->UTF8 conversion ideally
- for (int j=0;j<namelen;j++)
- {
- temp3[j] = (UINT8)temp[j];
- }
-
- if (!(f->IsDir) && (f->Size != 0))
+ const std::uint64_t length(_7z->current_uncompressed_length());
+ if ((length != 0) && (std::uint32_t(length) == length))
{
// decompress data into RAM and identify it
- dynamic_buffer data(f->Size);
- _7zerr = _7z_file_decompress(_7z, &data[0], f->Size);
- if (_7zerr == _7ZERR_NONE)
- identify_data((const char*)&temp2[0], &data[0], f->Size);
+ try
+ {
+ data.resize(std::size_t(length));
+ _7zerr = _7z->decompress(&data[0], std::uint32_t(length));
+ if (_7zerr == _7z_file::error::NONE)
+ identify_data(_7z->current_name().c_str(), &data[0], length);
+ }
+ catch (...)
+ {
+ // resizing the buffer could cause a bad_alloc if archive contains large files
+ }
+ data.clear();
}
}
-
- // close up
- _7z_file_close(_7z);
}
// clear out any cached files
- _7z_file_cache_clear();
+ _7z.reset();
+ _7z_file::cache_clear();
}
else if (core_filename_ends_with(filename, ".zip"))
{
// first attempt to examine it as a valid ZIP file
- zip_file *zip = nullptr;
- zip_error ziperr = zip_file_open(filename, &zip);
- if (ziperr == ZIPERR_NONE && zip != nullptr)
+ zip_file::ptr zip = nullptr;
+ zip_file::error ziperr = zip_file::open(filename, zip);
+ if (ziperr == zip_file::error::NONE && zip != nullptr)
{
// loop over entries in the ZIP, skipping empty files and directories
- for (const zip_file_header *entry = zip_file_first_file(zip); entry != nullptr; entry = zip_file_next_file(zip))
+ for (const zip_file::file_header *entry = zip->first_file(); entry != nullptr; entry = zip->next_file())
if (entry->uncompressed_length != 0)
{
// decompress data into RAM and identify it
dynamic_buffer data(entry->uncompressed_length);
- ziperr = zip_file_decompress(zip, &data[0], entry->uncompressed_length);
- if (ziperr == ZIPERR_NONE)
+ ziperr = zip->decompress(&data[0], entry->uncompressed_length);
+ if (ziperr == zip_file::error::NONE)
identify_data(entry->filename, &data[0], entry->uncompressed_length);
}
-
- // close up
- zip_file_close(zip);
}
// clear out any cached files
- zip_file_cache_clear();
+ zip.reset();
+ zip_file::cache_clear();
}
// otherwise, identify as a raw file
@@ -1880,8 +1873,8 @@ void media_identifier::identify_file(const char *name)
// load the file and process if it opens and has a valid length
UINT32 length;
void *data;
- const file_error filerr = util::core_file::load(name, &data, length);
- if (filerr == FILERR_NONE && length > 0)
+ const osd_file::error filerr = util::core_file::load(name, &data, length);
+ if (filerr == osd_file::error::NONE && length > 0)
{
identify_data(name, reinterpret_cast<UINT8 *>(data), length);
osd_free(data);
diff --git a/src/emu/config.cpp b/src/emu/config.cpp
index 691012a4a41..7402341ad32 100644
--- a/src/emu/config.cpp
+++ b/src/emu/config.cpp
@@ -68,9 +68,9 @@ int configuration_manager::load_settings()
{
/* open the config file */
emu_file file(machine().options().ctrlr_path(), OPEN_FLAG_READ);
- file_error filerr = file.open(controller, ".cfg");
+ osd_file::error filerr = file.open(controller, ".cfg");
- if (filerr != FILERR_NONE)
+ if (filerr != osd_file::error::NONE)
throw emu_fatalerror("Could not load controller file %s.cfg", controller);
/* load the XML */
@@ -80,13 +80,13 @@ int configuration_manager::load_settings()
/* next load the defaults file */
emu_file file(machine().options().cfg_directory(), OPEN_FLAG_READ);
- file_error filerr = file.open("default.cfg");
- if (filerr == FILERR_NONE)
+ osd_file::error filerr = file.open("default.cfg");
+ if (filerr == osd_file::error::NONE)
load_xml(file, config_type::CONFIG_TYPE_DEFAULT);
/* finally, load the game-specific file */
filerr = file.open(machine().basename(), ".cfg");
- if (filerr == FILERR_NONE)
+ if (filerr == osd_file::error::NONE)
loaded = load_xml(file, config_type::CONFIG_TYPE_GAME);
/* loop over all registrants and call their final function */
@@ -107,13 +107,13 @@ void configuration_manager::save_settings()
/* save the defaults file */
emu_file file(machine().options().cfg_directory(), OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS);
- file_error filerr = file.open("default.cfg");
- if (filerr == FILERR_NONE)
+ osd_file::error filerr = file.open("default.cfg");
+ if (filerr == osd_file::error::NONE)
save_xml(file, config_type::CONFIG_TYPE_DEFAULT);
/* finally, save the game-specific file */
filerr = file.open(machine().basename(), ".cfg");
- if (filerr == FILERR_NONE)
+ if (filerr == osd_file::error::NONE)
save_xml(file, config_type::CONFIG_TYPE_GAME);
/* loop over all registrants and call their final function */
diff --git a/src/emu/debug/debugcmd.cpp b/src/emu/debug/debugcmd.cpp
index 21ed7860a30..b8a7ebc4874 100644
--- a/src/emu/debug/debugcmd.cpp
+++ b/src/emu/debug/debugcmd.cpp
@@ -2856,9 +2856,9 @@ static void execute_snap(running_machine &machine, int ref, int params, const ch
if (fname.find(".png") == -1)
fname.append(".png");
emu_file file(machine.options().snapshot_directory(), OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS);
- file_error filerr = file.open(fname.c_str());
+ osd_file::error filerr = file.open(fname.c_str());
- if (filerr != FILERR_NONE)
+ if (filerr != osd_file::error::NONE)
{
debug_console_printf(machine, "Error creating file '%s'\n", filename);
return;
diff --git a/src/emu/debug/debugcpu.cpp b/src/emu/debug/debugcpu.cpp
index 2b8595b3c30..4e59ed8a652 100644
--- a/src/emu/debug/debugcpu.cpp
+++ b/src/emu/debug/debugcpu.cpp
@@ -332,8 +332,8 @@ bool debug_comment_save(running_machine &machine)
if (found_comments)
{
emu_file file(machine.options().comment_directory(), OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS);
- file_error filerr = file.open(machine.basename(), ".cmt");
- if (filerr == FILERR_NONE)
+ osd_file::error filerr = file.open(machine.basename(), ".cmt");
+ if (filerr == osd_file::error::NONE)
{
xml_file_write(root, file);
comments_saved = true;
@@ -361,10 +361,10 @@ bool debug_comment_load(running_machine &machine)
{
// open the file
emu_file file(machine.options().comment_directory(), OPEN_FLAG_READ);
- file_error filerr = file.open(machine.basename(), ".cmt");
+ osd_file::error filerr = file.open(machine.basename(), ".cmt");
// if an error, just return false
- if (filerr != FILERR_NONE)
+ if (filerr != osd_file::error::NONE)
return false;
// wrap in a try/catch to handle errors
diff --git a/src/emu/diimage.cpp b/src/emu/diimage.cpp
index 704f7d987e8..216b1af1fca 100644
--- a/src/emu/diimage.cpp
+++ b/src/emu/diimage.cpp
@@ -330,11 +330,8 @@ bool device_image_interface::try_change_working_directory(const char *subdir)
void device_image_interface::setup_working_directory()
{
- char *dst = nullptr;
-
- osd_get_full_path(&dst,".");
/* first set up the working directory to be the starting directory */
- m_working_directory = dst;
+ osd_get_full_path(m_working_directory, ".");
/* now try browsing down to "software" */
if (try_change_working_directory("software"))
@@ -346,7 +343,6 @@ void device_image_interface::setup_working_directory()
gamedrv = driver_list::compatible_with(gamedrv);
}
}
- osd_free(dst);
}
//-------------------------------------------------
@@ -512,14 +508,14 @@ void device_image_interface::battery_load(void *buffer, int length, int fill)
{
assert_always(buffer && (length > 0), "Must specify sensical buffer/length");
- file_error filerr;
+ osd_file::error filerr;
int bytes_read = 0;
std::string fname = std::string(device().machine().system().name).append(PATH_SEPARATOR).append(m_basename_noext.c_str()).append(".nv");
/* try to open the battery file and read it in, if possible */
emu_file file(device().machine().options().nvram_directory(), OPEN_FLAG_READ);
filerr = file.open(fname.c_str());
- if (filerr == FILERR_NONE)
+ if (filerr == osd_file::error::NONE)
bytes_read = file.read(buffer, length);
/* fill remaining bytes (if necessary) */
@@ -530,14 +526,14 @@ void device_image_interface::battery_load(void *buffer, int length, void *def_bu
{
assert_always(buffer && (length > 0), "Must specify sensical buffer/length");
- file_error filerr;
+ osd_file::error filerr;
int bytes_read = 0;
std::string fname = std::string(device().machine().system().name).append(PATH_SEPARATOR).append(m_basename_noext.c_str()).append(".nv");
/* try to open the battery file and read it in, if possible */
emu_file file(device().machine().options().nvram_directory(), OPEN_FLAG_READ);
filerr = file.open(fname.c_str());
- if (filerr == FILERR_NONE)
+ if (filerr == osd_file::error::NONE)
bytes_read = file.read(buffer, length);
/* if no file was present, copy the default battery */
@@ -558,8 +554,8 @@ void device_image_interface::battery_save(const void *buffer, int length)
/* try to open the battery file and write it out, if possible */
emu_file file(device().machine().options().nvram_directory(), OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS);
- file_error filerr = file.open(fname.c_str());
- if (filerr == FILERR_NONE)
+ osd_file::error filerr = file.open(fname.c_str());
+ if (filerr == osd_file::error::NONE)
file.write(buffer, length);
}
@@ -620,32 +616,32 @@ image_error_t device_image_interface::load_image_by_path(UINT32 open_flags, cons
/* did the open succeed? */
switch(filerr)
{
- case FILERR_NONE:
+ case osd_file::error::NONE:
/* success! */
m_readonly = (open_flags & OPEN_FLAG_WRITE) ? 0 : 1;
m_created = (open_flags & OPEN_FLAG_CREATE) ? 1 : 0;
err = IMAGE_ERROR_SUCCESS;
break;
- case FILERR_NOT_FOUND:
- case FILERR_ACCESS_DENIED:
+ case osd_file::error::NOT_FOUND:
+ case osd_file::error::ACCESS_DENIED:
/* file not found (or otherwise cannot open); continue */
err = IMAGE_ERROR_FILENOTFOUND;
break;
- case FILERR_OUT_OF_MEMORY:
+ case osd_file::error::OUT_OF_MEMORY:
/* out of memory */
err = IMAGE_ERROR_OUTOFMEMORY;
break;
- case FILERR_ALREADY_OPEN:
+ case osd_file::error::ALREADY_OPEN:
/* this shouldn't happen */
err = IMAGE_ERROR_ALREADYOPEN;
break;
- case FILERR_FAILURE:
- case FILERR_TOO_MANY_FILES:
- case FILERR_INVALID_DATA:
+ case osd_file::error::FAILURE:
+ case osd_file::error::TOO_MANY_FILES:
+ case osd_file::error::INVALID_DATA:
default:
/* other errors */
err = IMAGE_ERROR_INTERNAL;
@@ -653,7 +649,7 @@ image_error_t device_image_interface::load_image_by_path(UINT32 open_flags, cons
}
/* if successful, set the file name */
- if (filerr == FILERR_NONE)
+ if (filerr == osd_file::error::NONE)
set_image_filename(revised_path.c_str());
return err;
@@ -672,32 +668,32 @@ int device_image_interface::reopen_for_write(const char *path)
/* did the open succeed? */
switch(filerr)
{
- case FILERR_NONE:
+ case osd_file::error::NONE:
/* success! */
m_readonly = 0;
m_created = 1;
err = IMAGE_ERROR_SUCCESS;
break;
- case FILERR_NOT_FOUND:
- case FILERR_ACCESS_DENIED:
+ case osd_file::error::NOT_FOUND:
+ case osd_file::error::ACCESS_DENIED:
/* file not found (or otherwise cannot open); continue */
err = IMAGE_ERROR_FILENOTFOUND;
break;
- case FILERR_OUT_OF_MEMORY:
+ case osd_file::error::OUT_OF_MEMORY:
/* out of memory */
err = IMAGE_ERROR_OUTOFMEMORY;
break;
- case FILERR_ALREADY_OPEN:
+ case osd_file::error::ALREADY_OPEN:
/* this shouldn't happen */
err = IMAGE_ERROR_ALREADYOPEN;
break;
- case FILERR_FAILURE:
- case FILERR_TOO_MANY_FILES:
- case FILERR_INVALID_DATA:
+ case osd_file::error::FAILURE:
+ case osd_file::error::TOO_MANY_FILES:
+ case osd_file::error::INVALID_DATA:
default:
/* other errors */
err = IMAGE_ERROR_INTERNAL;
@@ -705,7 +701,7 @@ int device_image_interface::reopen_for_write(const char *path)
}
/* if successful, set the file name */
- if (filerr == FILERR_NONE)
+ if (filerr == osd_file::error::NONE)
set_image_filename(revised_path.c_str());
return err;
@@ -803,7 +799,7 @@ bool device_image_interface::load_software(software_list_device &swlist, const c
/* handle files */
if (ROMENTRY_ISFILE(romp))
{
- file_error filerr = FILERR_NOT_FOUND;
+ osd_file::error filerr = osd_file::error::NOT_FOUND;
UINT32 crc = 0;
bool has_crc = hash_collection(ROM_GETHASHDATA(romp)).crc(crc);
@@ -872,9 +868,9 @@ bool device_image_interface::load_software(software_list_device &swlist, const c
warningcount += verify_length_and_hash(m_mame_file.get(),ROM_GETNAME(romp),ROM_GETLENGTH(romp),hash_collection(ROM_GETHASHDATA(romp)));
- if (filerr == FILERR_NONE)
+ if (filerr == osd_file::error::NONE)
filerr = util::core_file::open_proxy(*m_mame_file, m_file);
- if (filerr == FILERR_NONE)
+ if (filerr == osd_file::error::NONE)
retVal = TRUE;
break; // load first item for start
diff --git a/src/emu/dipty.cpp b/src/emu/dipty.cpp
index bd1a166322f..a2ada675307 100644
--- a/src/emu/dipty.cpp
+++ b/src/emu/dipty.cpp
@@ -12,10 +12,10 @@
#include "osdcore.h"
device_pty_interface::device_pty_interface(const machine_config &mconfig, device_t &device)
- : device_interface(device, "pty"),
- m_pty_master(nullptr),
- m_slave_name(),
- m_opened(false)
+ : device_interface(device, "pty")
+ , m_pty_master()
+ , m_slave_name()
+ , m_opened(false)
{
}
@@ -23,63 +23,57 @@ device_pty_interface::~device_pty_interface()
{
}
-bool device_pty_interface::open(void)
+bool device_pty_interface::open()
{
- if (!m_opened) {
- char buffer[ 128 ];
-
- if (osd_openpty(&m_pty_master , buffer , sizeof(buffer)) == FILERR_NONE) {
+ if (!m_opened)
+ {
+ if (osd_file::openpty(m_pty_master, m_slave_name) == osd_file::error::NONE)
+ {
m_opened = true;
- m_slave_name.assign(buffer);
- } else {
+ }
+ else
+ {
m_opened = false;
- m_pty_master = nullptr;
+ m_pty_master.reset();
}
}
-
return m_opened;
}
-void device_pty_interface::close(void)
+void device_pty_interface::close()
{
- if (m_opened) {
- osd_close(m_pty_master);
- m_opened = false;
- }
+ m_pty_master.reset();
+ m_opened = false;
}
-bool device_pty_interface::is_open(void) const
+bool device_pty_interface::is_open() const
{
return m_opened;
}
ssize_t device_pty_interface::read(UINT8 *rx_chars , size_t count) const
{
- UINT32 actual_bytes;
-
- if (m_opened && osd_read(m_pty_master, rx_chars, 0, count, &actual_bytes) == FILERR_NONE) {
+ std::uint32_t actual_bytes;
+ if (m_opened && m_pty_master->read(rx_chars, 0, count, actual_bytes) == osd_file::error::NONE)
return actual_bytes;
- } else {
+ else
return -1;
- }
}
void device_pty_interface::write(UINT8 tx_char) const
{
- UINT32 actual_bytes;
-
- if (m_opened) {
- osd_write(m_pty_master, &tx_char, 0, 1, &actual_bytes);
- }
+ std::uint32_t actual_bytes;
+ if (m_opened)
+ m_pty_master->write(&tx_char, 0, 1, actual_bytes);
}
-bool device_pty_interface::is_slave_connected(void) const
+bool device_pty_interface::is_slave_connected() const
{
// TODO: really check for slave status
return m_opened;
}
-const char *device_pty_interface::slave_name(void) const
+const char *device_pty_interface::slave_name() const
{
return m_slave_name.c_str();
}
diff --git a/src/emu/dipty.h b/src/emu/dipty.h
index 4efa39fa702..10549e52ccb 100644
--- a/src/emu/dipty.h
+++ b/src/emu/dipty.h
@@ -14,35 +14,35 @@
#error Dont include this file directly; include emu.h instead.
#endif
-#ifndef __DIPTY_H__
-#define __DIPTY_H__
+#ifndef MAME_EMU_DIPTY_H
+#define MAME_EMU_DIPTY_H
class device_pty_interface : public device_interface
{
public:
- // construction/destruction
- device_pty_interface(const machine_config &mconfig, device_t &device);
- virtual ~device_pty_interface();
+ // construction/destruction
+ device_pty_interface(const machine_config &mconfig, device_t &device);
+ virtual ~device_pty_interface();
- bool open(void);
- void close(void);
+ bool open();
+ void close();
- bool is_open(void) const;
+ bool is_open() const;
- ssize_t read(UINT8 *rx_chars , size_t count) const;
- void write(UINT8 tx_char) const;
+ ssize_t read(UINT8 *rx_chars , size_t count) const;
+ void write(UINT8 tx_char) const;
- bool is_slave_connected(void) const;
+ bool is_slave_connected() const;
- const char *slave_name(void) const;
+ const char *slave_name() const;
protected:
- osd_file *m_pty_master;
- std::string m_slave_name;
- bool m_opened;
+ osd_file::ptr m_pty_master;
+ std::string m_slave_name;
+ bool m_opened;
};
// iterator
typedef device_interface_iterator<device_pty_interface> pty_interface_iterator;
-#endif /* __DIPTY_H__ */
+#endif /* MAME_EMU_DIPTY_H */
diff --git a/src/emu/emuopts.cpp b/src/emu/emuopts.cpp
index 332c9c2d787..f8127e28dbb 100644
--- a/src/emu/emuopts.cpp
+++ b/src/emu/emuopts.cpp
@@ -568,8 +568,8 @@ bool emu_options::parse_one_ini(const char *basename, int priority, std::string
// open the file; if we fail, that's ok
emu_file file(ini_path(), OPEN_FLAG_READ);
- file_error filerr = file.open(basename, ".ini");
- if (filerr != FILERR_NONE)
+ osd_file::error filerr = file.open(basename, ".ini");
+ if (filerr != osd_file::error::NONE)
return false;
// parse the file
diff --git a/src/emu/fileio.cpp b/src/emu/fileio.cpp
index 79bf746fbfa..b8e0c433575 100644
--- a/src/emu/fileio.cpp
+++ b/src/emu/fileio.cpp
@@ -146,7 +146,7 @@ emu_file::emu_file(UINT32 openflags)
m_openflags(openflags),
m_zipfile(nullptr),
m_ziplength(0),
- m__7zfile(nullptr),
+ m__7zfile(),
m__7zlength(0),
m_remove_on_close(false),
m_restrict_to_mediapath(false)
@@ -164,7 +164,7 @@ emu_file::emu_file(const char *searchpath, UINT32 openflags)
m_openflags(openflags),
m_zipfile(nullptr),
m_ziplength(0),
- m__7zfile(nullptr),
+ m__7zfile(),
m__7zlength(0),
m_remove_on_close(false),
m_restrict_to_mediapath(false)
@@ -255,7 +255,7 @@ hash_collection &emu_file::hashes(const char *types)
// open - open a file by searching paths
//-------------------------------------------------
-file_error emu_file::open(const char *name)
+osd_file::error emu_file::open(const char *name)
{
// remember the filename and CRC info
m_filename = name;
@@ -267,28 +267,28 @@ file_error emu_file::open(const char *name)
return open_next();
}
-file_error emu_file::open(const char *name1, const char *name2)
+osd_file::error emu_file::open(const char *name1, const char *name2)
{
// concatenate the strings and do a standard open
std::string name = std::string(name1).append(name2);
return open(name.c_str());
}
-file_error emu_file::open(const char *name1, const char *name2, const char *name3)
+osd_file::error emu_file::open(const char *name1, const char *name2, const char *name3)
{
// concatenate the strings and do a standard open
std::string name = std::string(name1).append(name2).append(name3);
return open(name.c_str());
}
-file_error emu_file::open(const char *name1, const char *name2, const char *name3, const char *name4)
+osd_file::error emu_file::open(const char *name1, const char *name2, const char *name3, const char *name4)
{
// concatenate the strings and do a standard open
std::string name = std::string(name1).append(name2).append(name3).append(name4);
return open(name.c_str());
}
-file_error emu_file::open(const char *name, UINT32 crc)
+osd_file::error emu_file::open(const char *name, UINT32 crc)
{
// remember the filename and CRC info
m_filename = name;
@@ -300,21 +300,21 @@ file_error emu_file::open(const char *name, UINT32 crc)
return open_next();
}
-file_error emu_file::open(const char *name1, const char *name2, UINT32 crc)
+osd_file::error emu_file::open(const char *name1, const char *name2, UINT32 crc)
{
// concatenate the strings and do a standard open
std::string name = std::string(name1).append(name2);
return open(name.c_str(), crc);
}
-file_error emu_file::open(const char *name1, const char *name2, const char *name3, UINT32 crc)
+osd_file::error emu_file::open(const char *name1, const char *name2, const char *name3, UINT32 crc)
{
// concatenate the strings and do a standard open
std::string name = std::string(name1).append(name2).append(name3);
return open(name.c_str(), crc);
}
-file_error emu_file::open(const char *name1, const char *name2, const char *name3, const char *name4, UINT32 crc)
+osd_file::error emu_file::open(const char *name1, const char *name2, const char *name3, const char *name4, UINT32 crc)
{
// concatenate the strings and do a standard open
std::string name = std::string(name1).append(name2).append(name3).append(name4);
@@ -327,19 +327,19 @@ file_error emu_file::open(const char *name1, const char *name2, const char *name
// the filename by iterating over paths
//-------------------------------------------------
-file_error emu_file::open_next()
+osd_file::error emu_file::open_next()
{
// if we're open from a previous attempt, close up now
if (m_file != nullptr)
close();
// loop over paths
- file_error filerr = FILERR_NOT_FOUND;
+ osd_file::error filerr = osd_file::error::NOT_FOUND;
while (m_iterator.next(m_fullpath, m_filename.c_str()))
{
// attempt to open the file directly
filerr = util::core_file::open(m_fullpath.c_str(), m_openflags, m_file);
- if (filerr == FILERR_NONE)
+ if (filerr == osd_file::error::NONE)
break;
// if we're opening for read-only we have other options
@@ -348,13 +348,13 @@ file_error emu_file::open_next()
std::string tempfullpath = m_fullpath;
filerr = attempt_zipped();
- if (filerr == FILERR_NONE)
+ if (filerr == osd_file::error::NONE)
break;
m_fullpath = tempfullpath;
filerr = attempt__7zped();
- if (filerr == FILERR_NONE)
+ if (filerr == osd_file::error::NONE)
break;
}
}
@@ -367,7 +367,7 @@ file_error emu_file::open_next()
// just an array of data in RAM
//-------------------------------------------------
-file_error emu_file::open_ram(const void *data, UINT32 length)
+osd_file::error emu_file::open_ram(const void *data, UINT32 length)
{
// set a fake filename and CRC
m_filename = "RAM";
@@ -386,21 +386,15 @@ file_error emu_file::open_ram(const void *data, UINT32 length)
void emu_file::close()
{
// close files and free memory
- if (m__7zfile != nullptr)
- _7z_file_close(m__7zfile);
- m__7zfile = nullptr;
-
- if (m_zipfile != nullptr)
- zip_file_close(m_zipfile);
- m_zipfile = nullptr;
-
+ m__7zfile.reset();
+ m_zipfile.reset();
m_file.reset();
m__7zdata.clear();
m_zipdata.clear();
if (m_remove_on_close)
- osd_rmfile(m_fullpath.c_str());
+ osd_file::remove(m_fullpath);
m_remove_on_close = false;
// reset our hashes and path as well
@@ -415,7 +409,7 @@ void emu_file::close()
// compression, or up to 9 for max compression
//-------------------------------------------------
-file_error emu_file::compress(int level)
+osd_file::error emu_file::compress(int level)
{
return m_file->compress(level);
}
@@ -429,10 +423,10 @@ file_error emu_file::compress(int level)
bool emu_file::compressed_file_ready(void)
{
// load the ZIP file now if we haven't yet
- if (m__7zfile != nullptr && load__7zped_file() != FILERR_NONE)
+ if (m__7zfile != nullptr && load__7zped_file() != osd_file::error::NONE)
return true;
- if (m_zipfile != nullptr && load_zipped_file() != FILERR_NONE)
+ if (m_zipfile != nullptr && load_zipped_file() != osd_file::error::NONE)
return true;
return false;
@@ -657,7 +651,7 @@ bool emu_file::part_of_mediapath(std::string path)
// attempt_zipped - attempt to open a ZIPped file
//-------------------------------------------------
-file_error emu_file::attempt_zipped()
+osd_file::error emu_file::attempt_zipped()
{
std::string filename;
@@ -667,11 +661,11 @@ file_error emu_file::attempt_zipped()
// find the final path separator
int dirsep = m_fullpath.find_last_of(PATH_SEPARATOR[0]);
if (dirsep == -1)
- return FILERR_NOT_FOUND;
+ return osd_file::error::NOT_FOUND;
if (restrict_to_mediapath())
if ( !part_of_mediapath(m_fullpath) )
- return FILERR_NOT_FOUND;
+ return osd_file::error::NOT_FOUND;
// insert the part from the right of the separator into the head of the filename
if (filename.length() > 0)
@@ -682,49 +676,49 @@ file_error emu_file::attempt_zipped()
m_fullpath = m_fullpath.substr(0, dirsep).append(".zip");
// attempt to open the ZIP file
- zip_file *zip;
- zip_error ziperr = zip_file_open(m_fullpath.c_str(), &zip);
+ zip_file::ptr zip;
+ zip_file::error ziperr = zip_file::open(m_fullpath, zip);
// chop the .zip back off the filename before continuing
m_fullpath = m_fullpath.substr(0, dirsep);
// if we failed to open this file, continue scanning
- if (ziperr != ZIPERR_NONE)
+ if (ziperr != zip_file::error::NONE)
continue;
// see if we can find a file with the right name and (if available) crc
- const zip_file_header *header;
- for (header = zip_file_first_file(zip); header != nullptr; header = zip_file_next_file(zip))
+ const zip_file::file_header *header;
+ for (header = zip->first_file(); header != nullptr; header = zip->next_file())
if (zip_filename_match(*header, filename) && (!(m_openflags & OPEN_FLAG_HAS_CRC) || header->crc == m_crc))
break;
// if that failed, look for a file with the right crc, but the wrong filename
if (header == nullptr && (m_openflags & OPEN_FLAG_HAS_CRC))
- for (header = zip_file_first_file(zip); header != nullptr; header = zip_file_next_file(zip))
+ for (header = zip->first_file(); header != nullptr; header = zip->next_file())
if (header->crc == m_crc && !zip_header_is_path(*header))
break;
// if that failed, look for a file with the right name; reporting a bad checksum
// is more helpful and less confusing than reporting "rom not found"
if (header == nullptr)
- for (header = zip_file_first_file(zip); header != nullptr; header = zip_file_next_file(zip))
+ for (header = zip->first_file(); header != nullptr; header = zip->next_file())
if (zip_filename_match(*header, filename))
break;
// if we got it, read the data
if (header != nullptr)
{
- m_zipfile = zip;
+ m_zipfile = std::move(zip);
m_ziplength = header->uncompressed_length;
// build a hash with just the CRC
m_hashes.reset();
m_hashes.add_crc(header->crc);
- return (m_openflags & OPEN_FLAG_NO_PRELOAD) ? FILERR_NONE : load_zipped_file();
+ return (m_openflags & OPEN_FLAG_NO_PRELOAD) ? osd_file::error::NONE : load_zipped_file();
}
// close up the ZIP file and try the next level
- zip_file_close(zip);
+ zip.reset();
}
}
@@ -733,7 +727,7 @@ file_error emu_file::attempt_zipped()
// load_zipped_file - load a ZIPped file
//-------------------------------------------------
-file_error emu_file::load_zipped_file()
+osd_file::error emu_file::load_zipped_file()
{
assert(m_file == nullptr);
assert(m_zipdata.empty());
@@ -743,25 +737,24 @@ file_error emu_file::load_zipped_file()
m_zipdata.resize(m_ziplength);
// read the data into our buffer and return
- zip_error ziperr = zip_file_decompress(m_zipfile, &m_zipdata[0], m_zipdata.size());
- if (ziperr != ZIPERR_NONE)
+ zip_file::error ziperr = m_zipfile->decompress(&m_zipdata[0], m_zipdata.size());
+ if (ziperr != zip_file::error::NONE)
{
m_zipdata.clear();
- return FILERR_FAILURE;
+ return osd_file::error::FAILURE;
}
// convert to RAM file
- file_error filerr = util::core_file::open_ram(&m_zipdata[0], m_zipdata.size(), m_openflags, m_file);
- if (filerr != FILERR_NONE)
+ osd_file::error filerr = util::core_file::open_ram(&m_zipdata[0], m_zipdata.size(), m_openflags, m_file);
+ if (filerr != osd_file::error::NONE)
{
m_zipdata.clear();
- return FILERR_FAILURE;
+ return osd_file::error::FAILURE;
}
// close out the ZIP file
- zip_file_close(m_zipfile);
- m_zipfile = nullptr;
- return FILERR_NONE;
+ m_zipfile.reset();
+ return osd_file::error::NONE;
}
@@ -770,7 +763,7 @@ file_error emu_file::load_zipped_file()
// to expected filename, ignoring any directory
//-------------------------------------------------
-bool emu_file::zip_filename_match(const zip_file_header &header, const std::string &filename)
+bool emu_file::zip_filename_match(const zip_file::file_header &header, const std::string &filename)
{
const char *zipfile = header.filename + header.filename_length - filename.length();
return (zipfile >= header.filename && core_stricmp(filename.c_str(),zipfile) == 0 && (zipfile == header.filename || zipfile[-1] == '/'));
@@ -782,7 +775,7 @@ bool emu_file::zip_filename_match(const zip_file_header &header, const std::stri
// in header is a path
//-------------------------------------------------
-bool emu_file::zip_header_is_path(const zip_file_header &header)
+bool emu_file::zip_header_is_path(const zip_file::file_header &header)
{
const char *zipfile = header.filename + header.filename_length - 1;
return (zipfile >= header.filename && zipfile[0] == '/');
@@ -792,7 +785,7 @@ bool emu_file::zip_header_is_path(const zip_file_header &header)
// attempt__7zped - attempt to open a .7z file
//-------------------------------------------------
-file_error emu_file::attempt__7zped()
+osd_file::error emu_file::attempt__7zped()
{
std::string filename;
@@ -802,11 +795,11 @@ file_error emu_file::attempt__7zped()
// find the final path separator
int dirsep = m_fullpath.find_last_of(PATH_SEPARATOR[0]);
if (dirsep == -1)
- return FILERR_NOT_FOUND;
+ return osd_file::error::NOT_FOUND;
if (restrict_to_mediapath())
if ( !part_of_mediapath(m_fullpath) )
- return FILERR_NOT_FOUND;
+ return osd_file::error::NOT_FOUND;
// insert the part from the right of the separator into the head of the filename
if (filename.length() > 0)
@@ -817,43 +810,41 @@ file_error emu_file::attempt__7zped()
m_fullpath = m_fullpath.substr(0, dirsep).append(".7z");
// attempt to open the _7Z file
- _7z_file *_7z;
- _7z_error _7zerr = _7z_file_open(m_fullpath.c_str(), &_7z);
+ _7z_file::ptr _7z;
+ _7z_file::error _7zerr = _7z_file::open(m_fullpath, _7z);
// chop the ._7z back off the filename before continuing
m_fullpath = m_fullpath.substr(0, dirsep);
// if we failed to open this file, continue scanning
- if (_7zerr != _7ZERR_NONE)
+ if (_7zerr != _7z_file::error::NONE)
continue;
int fileno = -1;
// see if we can find a file with the right name and (if available) crc
- if (m_openflags & OPEN_FLAG_HAS_CRC) fileno = _7z_search_crc_match(_7z, m_crc, filename.c_str(), filename.length(), true, true);
+ if (m_openflags & OPEN_FLAG_HAS_CRC) fileno = _7z->search(m_crc, filename);
// if that failed, look for a file with the right crc, but the wrong filename
- if (fileno==-1)
- if (m_openflags & OPEN_FLAG_HAS_CRC) fileno = _7z_search_crc_match(_7z, m_crc, filename.c_str(), filename.length(), true, false);
+ if ((fileno == -1) && (m_openflags & OPEN_FLAG_HAS_CRC)) fileno = _7z->search(m_crc);
// if that failed, look for a file with the right name; reporting a bad checksum
// is more helpful and less confusing than reporting "rom not found"
- if (fileno==-1)
- fileno = _7z_search_crc_match(_7z, m_crc, filename.c_str(), filename.length(), false, true);
+ if (fileno == -1) fileno = _7z->search(filename);
if (fileno != -1)
{
- m__7zfile = _7z;
- m__7zlength = _7z->uncompressed_length;
+ m__7zfile = std::move(_7z);
+ m__7zlength = _7z->current_uncompressed_length();
// build a hash with just the CRC
m_hashes.reset();
- m_hashes.add_crc(_7z->crc);
- return (m_openflags & OPEN_FLAG_NO_PRELOAD) ? FILERR_NONE : load__7zped_file();
+ m_hashes.add_crc(_7z->current_crc());
+ return (m_openflags & OPEN_FLAG_NO_PRELOAD) ? osd_file::error::NONE : load__7zped_file();
}
// close up the _7Z file and try the next level
- _7z_file_close(_7z);
+ _7z.reset();
}
}
@@ -862,33 +853,32 @@ file_error emu_file::attempt__7zped()
// load__7zped_file - load a _7Zped file
//-------------------------------------------------
-file_error emu_file::load__7zped_file()
+osd_file::error emu_file::load__7zped_file()
{
assert(m_file == nullptr);
assert(m__7zdata.empty());
- assert(m__7zfile != nullptr);
+ assert(m__7zfile);
// allocate some memory
m__7zdata.resize(m__7zlength);
// read the data into our buffer and return
- _7z_error _7zerr = _7z_file_decompress(m__7zfile, &m__7zdata[0], m__7zdata.size());
- if (_7zerr != _7ZERR_NONE)
+ _7z_file::error _7zerr = m__7zfile->decompress(&m__7zdata[0], m__7zdata.size());
+ if (_7zerr != _7z_file::error::NONE)
{
m__7zdata.clear();
- return FILERR_FAILURE;
+ return osd_file::error::FAILURE;
}
// convert to RAM file
- file_error filerr = util::core_file::open_ram(&m__7zdata[0], m__7zdata.size(), m_openflags, m_file);
- if (filerr != FILERR_NONE)
+ osd_file::error filerr = util::core_file::open_ram(&m__7zdata[0], m__7zdata.size(), m_openflags, m_file);
+ if (filerr != osd_file::error::NONE)
{
m__7zdata.clear();
- return FILERR_FAILURE;
+ return osd_file::error::FAILURE;
}
// close out the _7Z file
- _7z_file_close(m__7zfile);
- m__7zfile = nullptr;
- return FILERR_NONE;
+ m__7zfile.reset();
+ return osd_file::error::NONE;
}
diff --git a/src/emu/fileio.h b/src/emu/fileio.h
index 22f36f5362e..c54c740d686 100644
--- a/src/emu/fileio.h
+++ b/src/emu/fileio.h
@@ -10,11 +10,12 @@
#pragma once
-#ifndef __FILEIO_H__
-#define __FILEIO_H__
+#ifndef MAME_EMU_FILEIO_H
+#define MAME_EMU_FILEIO_H
#include "corefile.h"
#include "hash.h"
+#include "unzip.h"
// some systems use macros for getc/putc rather than functions
#ifdef getc
@@ -26,11 +27,7 @@
//**************************************************************************
// forward declarations
-struct zip_file_header;
-struct zip_file;
-
-struct _7z_file_header;
-struct _7z_file;
+class _7z_file;
// ======================> path_iterator
@@ -105,20 +102,20 @@ public:
void set_restrict_to_mediapath(bool rtmp = true) { m_restrict_to_mediapath = rtmp; }
// open/close
- file_error open(const char *name);
- file_error open(const char *name1, const char *name2);
- file_error open(const char *name1, const char *name2, const char *name3);
- file_error open(const char *name1, const char *name2, const char *name3, const char *name4);
- file_error open(const char *name, UINT32 crc);
- file_error open(const char *name1, const char *name2, UINT32 crc);
- file_error open(const char *name1, const char *name2, const char *name3, UINT32 crc);
- file_error open(const char *name1, const char *name2, const char *name3, const char *name4, UINT32 crc);
- file_error open_next();
- file_error open_ram(const void *data, UINT32 length);
+ osd_file::error open(const char *name);
+ osd_file::error open(const char *name1, const char *name2);
+ osd_file::error open(const char *name1, const char *name2, const char *name3);
+ osd_file::error open(const char *name1, const char *name2, const char *name3, const char *name4);
+ osd_file::error open(const char *name, UINT32 crc);
+ osd_file::error open(const char *name1, const char *name2, UINT32 crc);
+ osd_file::error open(const char *name1, const char *name2, const char *name3, UINT32 crc);
+ osd_file::error open(const char *name1, const char *name2, const char *name3, const char *name4, UINT32 crc);
+ osd_file::error open_next();
+ osd_file::error open_ram(const void *data, UINT32 length);
void close();
// control
- file_error compress(int compress);
+ osd_file::error compress(int compress);
// position
int seek(INT64 offset, int whence);
@@ -148,13 +145,13 @@ private:
bool compressed_file_ready(void);
// internal helpers
- file_error attempt_zipped();
- file_error load_zipped_file();
- bool zip_filename_match(const zip_file_header &header, const std::string &filename);
- bool zip_header_is_path(const zip_file_header &header);
+ osd_file::error attempt_zipped();
+ osd_file::error load_zipped_file();
+ bool zip_filename_match(const zip_file::file_header &header, const std::string &filename);
+ bool zip_header_is_path(const zip_file::file_header &header);
- file_error attempt__7zped();
- file_error load__7zped_file();
+ osd_file::error attempt__7zped();
+ osd_file::error load__7zped_file();
// internal state
std::string m_filename; // original filename provided
@@ -166,17 +163,16 @@ private:
UINT32 m_openflags; // flags we used for the open
hash_collection m_hashes; // collection of hashes
- zip_file * m_zipfile; // ZIP file pointer
+ zip_file::ptr m_zipfile; // ZIP file pointer
dynamic_buffer m_zipdata; // ZIP file data
UINT64 m_ziplength; // ZIP file length
- _7z_file * m__7zfile; // 7Z file pointer
+ std::unique_ptr<_7z_file> m__7zfile; // 7Z file pointer
dynamic_buffer m__7zdata; // 7Z file data
UINT64 m__7zlength; // 7Z file length
bool m_remove_on_close; // flag: remove the file when closing
- bool m_restrict_to_mediapath; // flag: restrict to paths inside the media-path
+ bool m_restrict_to_mediapath; // flag: restrict to paths inside the media-path
};
-
-#endif /* __FILEIO_H__ */
+#endif // MAME_EMU_FILEIO_H
diff --git a/src/emu/hashfile.cpp b/src/emu/hashfile.cpp
index 557d9c28d5f..ca668e1dfae 100644
--- a/src/emu/hashfile.cpp
+++ b/src/emu/hashfile.cpp
@@ -430,7 +430,7 @@ hash_file *hashfile_open(emu_options &options, const char *sysname, int is_prelo
{
hash_file *hashfile = nullptr;
object_pool *pool = nullptr;
- file_error filerr;
+ osd_file::error filerr;
/* create a pool for this hash file */
pool = pool_alloc_lib(error_proc);
@@ -450,7 +450,7 @@ hash_file *hashfile_open(emu_options &options, const char *sysname, int is_prelo
/* open a file */
hashfile->file = global_alloc(emu_file(options.hash_path(), OPEN_FLAG_READ));
filerr = hashfile->file->open(sysname, ".hsi");
- if (filerr != FILERR_NONE)
+ if (filerr != osd_file::error::NONE)
{
global_free(hashfile->file);
hashfile->file = nullptr;
diff --git a/src/emu/image.cpp b/src/emu/image.cpp
index 76de04714fb..f9f6111a292 100644
--- a/src/emu/image.cpp
+++ b/src/emu/image.cpp
@@ -155,8 +155,8 @@ int image_manager::write_config(emu_options &options, const char *filename, cons
}
emu_file file(options.ini_path(), OPEN_FLAG_WRITE | OPEN_FLAG_CREATE);
- file_error filerr = file.open(filename);
- if (filerr == FILERR_NONE)
+ osd_file::error filerr = file.open(filename);
+ if (filerr == osd_file::error::NONE)
{
std::string inistring = options.output_ini();
file.puts(inistring.c_str());
diff --git a/src/emu/ioport.cpp b/src/emu/ioport.cpp
index 2b00cabb94b..1ca4d477575 100644
--- a/src/emu/ioport.cpp
+++ b/src/emu/ioport.cpp
@@ -3407,8 +3407,8 @@ time_t ioport_manager::playback_init()
return 0;
// open the playback file
- file_error filerr = m_playback_file.open(filename);
- assert_always(filerr == FILERR_NONE, "Failed to open file for playback");
+ osd_file::error filerr = m_playback_file.open(filename);
+ assert_always(filerr == osd_file::error::NONE, "Failed to open file for playback");
// read the header and verify that it is a modern version; if not, print an error
inp_header header;
@@ -3582,8 +3582,8 @@ void ioport_manager::record_init()
return;
// open the record file
- file_error filerr = m_record_file.open(filename);
- assert_always(filerr == FILERR_NONE, "Failed to open file for recording");
+ osd_file::error filerr = m_record_file.open(filename);
+ assert_always(filerr == osd_file::error::NONE, "Failed to open file for recording");
// get the base time
system_time systime;
@@ -3625,8 +3625,8 @@ void ioport_manager::timecode_init() {
filename.append(record_filename).append(".timecode");
osd_printf_info("Record input timecode file: %s\n", record_filename);
- file_error filerr = m_timecode_file.open(filename.c_str());
- assert_always(filerr == FILERR_NONE, "Failed to open file for input timecode recording");
+ osd_file::error filerr = m_timecode_file.open(filename.c_str());
+ assert_always(filerr == osd_file::error::NONE, "Failed to open file for input timecode recording");
m_timecode_file.puts(std::string("# ==========================================\n").c_str());
m_timecode_file.puts(std::string("# TIMECODE FILE FOR VIDEO PREVIEW GENERATION\n").c_str());
diff --git a/src/emu/language.cpp b/src/emu/language.cpp
index b47605f50c8..8d4618c7be3 100644
--- a/src/emu/language.cpp
+++ b/src/emu/language.cpp
@@ -41,7 +41,7 @@ void load_translation(emu_options &m_options)
strreplace(name, " ", "_");
strreplace(name, "(", "");
strreplace(name, ")", "");
- if (file.open(name.c_str(), PATH_SEPARATOR "strings.mo") == FILERR_NONE)
+ if (file.open(name.c_str(), PATH_SEPARATOR "strings.mo") == osd_file::error::NONE)
{
UINT64 size = file.size();
UINT32 *buffer = global_alloc_array(UINT32, size / 4 + 1);
diff --git a/src/emu/luaengine.cpp b/src/emu/luaengine.cpp
index 4ffee509693..5ef7b935b0e 100644
--- a/src/emu/luaengine.cpp
+++ b/src/emu/luaengine.cpp
@@ -870,7 +870,7 @@ int lua_engine::lua_screen::l_snapshot(lua_State *L)
luaL_argcheck(L, lua_isstring(L, 2) || lua_isnone(L, 2), 2, "optional argument: filename, string expected");
emu_file file(sc->machine().options().snapshot_directory(), OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS);
- file_error filerr;
+ osd_file::error filerr;
if (!lua_isnone(L, 2)) {
const char *filename = lua_tostring(L, 2);
@@ -884,9 +884,9 @@ int lua_engine::lua_screen::l_snapshot(lua_State *L)
filerr = sc->machine().video().open_next(file, "png");
}
- if (filerr != FILERR_NONE)
+ if (filerr != osd_file::error::NONE)
{
- luaL_error(L, "file_error=%d", filerr);
+ luaL_error(L, "osd_file::error=%d", filerr);
return 0;
}
diff --git a/src/emu/machine.cpp b/src/emu/machine.cpp
index b3ac263473e..00db05b59c3 100644
--- a/src/emu/machine.cpp
+++ b/src/emu/machine.cpp
@@ -333,8 +333,8 @@ int running_machine::run(bool firstrun)
if (options().log() && &system() != &GAME_NAME(___empty))
{
m_logfile = std::make_unique<emu_file>(OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS);
- file_error filerr = m_logfile->open("error.log");
- assert_always(filerr == FILERR_NONE, "unable to open log file");
+ osd_file::error filerr = m_logfile->open("error.log");
+ assert_always(filerr == osd_file::error::NONE, "unable to open log file");
add_logerror_callback(logfile_callback);
}
@@ -440,7 +440,7 @@ int running_machine::run(bool firstrun)
// call all exit callbacks registered
call_notifiers(MACHINE_NOTIFY_EXIT);
- zip_file_cache_clear();
+ zip_file::cache_clear();
// close the logfile
m_logfile.reset();
@@ -824,7 +824,7 @@ void running_machine::handle_saveload()
UINT32 openflags = (m_saveload_schedule == SLS_LOAD) ? OPEN_FLAG_READ : (OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS);
const char *opnamed = (m_saveload_schedule == SLS_LOAD) ? "loaded" : "saved";
const char *opname = (m_saveload_schedule == SLS_LOAD) ? "load" : "save";
- file_error filerr = FILERR_NONE;
+ osd_file::error filerr = osd_file::error::NONE;
// if no name, bail
emu_file file(m_saveload_searchpath, openflags);
@@ -846,7 +846,7 @@ void running_machine::handle_saveload()
// open the file
filerr = file.open(m_saveload_pending_file.c_str());
- if (filerr == FILERR_NONE)
+ if (filerr == osd_file::error::NONE)
{
// read/write the save state
save_error saverr = (m_saveload_schedule == SLS_LOAD) ? m_save.read_file(file) : m_save.write_file(file);
@@ -1171,7 +1171,7 @@ void running_machine::nvram_load()
for (device_nvram_interface *nvram = iter.first(); nvram != nullptr; nvram = iter.next())
{
emu_file file(options().nvram_directory(), OPEN_FLAG_READ);
- if (file.open(nvram_filename(nvram->device()).c_str()) == FILERR_NONE)
+ if (file.open(nvram_filename(nvram->device()).c_str()) == osd_file::error::NONE)
{
nvram->nvram_load(file);
file.close();
@@ -1192,7 +1192,7 @@ void running_machine::nvram_save()
for (device_nvram_interface *nvram = iter.first(); nvram != nullptr; nvram = iter.next())
{
emu_file file(options().nvram_directory(), OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS);
- if (file.open(nvram_filename(nvram->device()).c_str()) == FILERR_NONE)
+ if (file.open(nvram_filename(nvram->device()).c_str()) == osd_file::error::NONE)
{
nvram->nvram_save(file);
file.close();
diff --git a/src/emu/mame.cpp b/src/emu/mame.cpp
index 5e93623498d..2f313dceabb 100644
--- a/src/emu/mame.cpp
+++ b/src/emu/mame.cpp
@@ -158,8 +158,8 @@ void machine_manager::start_luaengine()
m_lua->initialize();
{
emu_file file(options().plugins_path(), OPEN_FLAG_READ);
- file_error filerr = file.open("boot.lua");
- if (filerr == FILERR_NONE)
+ osd_file::error filerr = file.open("boot.lua");
+ if (filerr == osd_file::error::NONE)
{
m_lua->load_script(file.fullpath());
}
diff --git a/src/emu/render.cpp b/src/emu/render.cpp
index 3de791eab52..4d4d1344db5 100644
--- a/src/emu/render.cpp
+++ b/src/emu/render.cpp
@@ -1588,8 +1588,8 @@ bool render_target::load_layout_file(const char *dirname, const char *filename)
// attempt to open the file; bail if we can't
emu_file layoutfile(manager().machine().options().art_path(), OPEN_FLAG_READ);
- file_error filerr = layoutfile.open(fname.c_str());
- if (filerr != FILERR_NONE)
+ osd_file::error filerr = layoutfile.open(fname.c_str());
+ if (filerr != osd_file::error::NONE)
return false;
// read the file
diff --git a/src/emu/rendfont.cpp b/src/emu/rendfont.cpp
index 89c174c31bf..27a14bb0d55 100644
--- a/src/emu/rendfont.cpp
+++ b/src/emu/rendfont.cpp
@@ -164,8 +164,8 @@ render_font::render_font(render_manager &manager, const char *filename)
// load the raw data instead
emu_file ramfile(OPEN_FLAG_READ);
- file_error filerr = ramfile.open_ram(font_uismall, sizeof(font_uismall));
- if (filerr == FILERR_NONE)
+ osd_file::error filerr = ramfile.open_ram(font_uismall, sizeof(font_uismall));
+ if (filerr == osd_file::error::NONE)
load_cached(ramfile, 0);
render_font_command_glyph();
}
@@ -470,8 +470,8 @@ bool render_font::load_cached_bdf(const char *filename)
{
// first try to open the BDF itself
emu_file file(manager().machine().options().font_path(), OPEN_FLAG_READ);
- file_error filerr = file.open(filename);
- if (filerr != FILERR_NONE)
+ osd_file::error filerr = file.open(filename);
+ if (filerr != osd_file::error::NONE)
return false;
// determine the file size and allocate memory
@@ -494,7 +494,7 @@ bool render_font::load_cached_bdf(const char *filename)
{
emu_file cachefile(manager().machine().options().font_path(), OPEN_FLAG_READ);
filerr = cachefile.open(cachedname.c_str());
- if (filerr == FILERR_NONE)
+ if (filerr == osd_file::error::NONE)
{
// if we have a cached version, load it
bool result = load_cached(cachefile, hash);
@@ -730,8 +730,8 @@ bool render_font::save_cached(const char *filename, UINT32 hash)
// attempt to open the file
emu_file file(manager().machine().options().font_path(), OPEN_FLAG_WRITE | OPEN_FLAG_CREATE);
- file_error filerr = file.open(filename);
- if (filerr != FILERR_NONE)
+ osd_file::error filerr = file.open(filename);
+ if (filerr != osd_file::error::NONE)
return false;
// determine the number of characters
diff --git a/src/emu/rendutil.cpp b/src/emu/rendutil.cpp
index 6d0bde63adb..4c49c6c8a62 100644
--- a/src/emu/rendutil.cpp
+++ b/src/emu/rendutil.cpp
@@ -540,8 +540,8 @@ bool render_load_png(bitmap_argb32 &bitmap, emu_file &file, const char *dirname,
fname.assign(filename);
else
fname.assign(dirname).append(PATH_SEPARATOR).append(filename);
- file_error filerr = file.open(fname.c_str());
- if (filerr != FILERR_NONE)
+ osd_file::error filerr = file.open(fname.c_str());
+ if (filerr != osd_file::error::NONE)
return false;
// read the PNG data
diff --git a/src/emu/romload.cpp b/src/emu/romload.cpp
index f5f15551ab5..45cbeecbea4 100644
--- a/src/emu/romload.cpp
+++ b/src/emu/romload.cpp
@@ -28,9 +28,9 @@
HELPERS (also used by diimage.cpp)
***************************************************************************/
-static file_error common_process_file(emu_options &options, const char *location, const char *ext, const rom_entry *romp, emu_file &image_file)
+static osd_file::error common_process_file(emu_options &options, const char *location, const char *ext, const rom_entry *romp, emu_file &image_file)
{
- file_error filerr;
+ osd_file::error filerr;
if (location != nullptr && strcmp(location, "") != 0)
filerr = image_file.open(location, PATH_SEPARATOR, ROM_GETNAME(romp), ext);
@@ -40,7 +40,7 @@ static file_error common_process_file(emu_options &options, const char *location
return filerr;
}
-std::unique_ptr<emu_file> common_process_file(emu_options &options, const char *location, bool has_crc, UINT32 crc, const rom_entry *romp, file_error &filerr)
+std::unique_ptr<emu_file> common_process_file(emu_options &options, const char *location, bool has_crc, UINT32 crc, const rom_entry *romp, osd_file::error &filerr)
{
auto image_file = std::make_unique<emu_file>(options.media_path(), OPEN_FLAG_READ);
@@ -49,7 +49,7 @@ std::unique_ptr<emu_file> common_process_file(emu_options &options, const char *
else
filerr = image_file->open(location, PATH_SEPARATOR, ROM_GETNAME(romp));
- if (filerr != FILERR_NONE)
+ if (filerr != osd_file::error::NONE)
{
image_file = nullptr;
}
@@ -549,7 +549,7 @@ void rom_load_manager::region_post_process(const char *rgntag, bool invert)
int rom_load_manager::open_rom_file(const char *regiontag, const rom_entry *romp, std::string &tried_file_names, bool from_list)
{
- file_error filerr = FILERR_NOT_FOUND;
+ osd_file::error filerr = osd_file::error::NOT_FOUND;
UINT32 romsize = rom_file_size(romp);
tried_file_names = "";
@@ -656,7 +656,7 @@ int rom_load_manager::open_rom_file(const char *regiontag, const rom_entry *romp
m_romsloadedsize += romsize;
/* return the result */
- return (filerr == FILERR_NONE);
+ return (filerr == osd_file::error::NONE);
}
@@ -959,19 +959,19 @@ int open_disk_image(emu_options &options, const game_driver *gamedrv, const rom_
{
emu_file image_file(options.media_path(), OPEN_FLAG_READ);
const rom_entry *region, *rom;
- file_error filerr;
+ osd_file::error filerr;
chd_error err;
/* attempt to open the properly named file, scanning up through parent directories */
- filerr = FILERR_NOT_FOUND;
- for (int searchdrv = driver_list::find(*gamedrv); searchdrv != -1 && filerr != FILERR_NONE; searchdrv = driver_list::clone(searchdrv))
+ filerr = osd_file::error::NOT_FOUND;
+ for (int searchdrv = driver_list::find(*gamedrv); searchdrv != -1 && filerr != osd_file::error::NONE; searchdrv = driver_list::clone(searchdrv))
filerr = common_process_file(options, driver_list::driver(searchdrv).name, ".chd", romp, image_file);
- if (filerr != FILERR_NONE)
+ if (filerr != osd_file::error::NONE)
filerr = common_process_file(options, nullptr, ".chd", romp, image_file);
/* look for the disk in the locationtag too */
- if (filerr != FILERR_NONE && locationtag != nullptr)
+ if (filerr != osd_file::error::NONE && locationtag != nullptr)
{
// check if we are dealing with softwarelists. if so, locationtag
// is actually a concatenation of: listname + setname + parentname
@@ -1022,19 +1022,19 @@ int open_disk_image(emu_options &options, const game_driver *gamedrv, const rom_
else
{
// try to load from list/setname
- if ((filerr != FILERR_NONE) && (tag2.c_str() != nullptr))
+ if ((filerr != osd_file::error::NONE) && (tag2.c_str() != nullptr))
filerr = common_process_file(options, tag2.c_str(), ".chd", romp, image_file);
// try to load from list/parentname (if any)
- if ((filerr != FILERR_NONE) && has_parent && (tag3.c_str() != nullptr))
+ if ((filerr != osd_file::error::NONE) && has_parent && (tag3.c_str() != nullptr))
filerr = common_process_file(options, tag3.c_str(), ".chd", romp, image_file);
// try to load from setname
- if ((filerr != FILERR_NONE) && (tag4.c_str() != nullptr))
+ if ((filerr != osd_file::error::NONE) && (tag4.c_str() != nullptr))
filerr = common_process_file(options, tag4.c_str(), ".chd", romp, image_file);
// try to load from parentname (if any)
- if ((filerr != FILERR_NONE) && has_parent && (tag5.c_str() != nullptr))
+ if ((filerr != osd_file::error::NONE) && has_parent && (tag5.c_str() != nullptr))
filerr = common_process_file(options, tag5.c_str(), ".chd", romp, image_file);
// only for CHD we also try to load from list/
- if ((filerr != FILERR_NONE) && (tag1.c_str() != nullptr))
+ if ((filerr != osd_file::error::NONE) && (tag1.c_str() != nullptr))
{
tag1.erase(tag1.length() - 1, 1); // remove the PATH_SEPARATOR
filerr = common_process_file(options, tag1.c_str(), ".chd", romp, image_file);
@@ -1043,7 +1043,7 @@ int open_disk_image(emu_options &options, const game_driver *gamedrv, const rom_
}
/* did the file open succeed? */
- if (filerr == FILERR_NONE)
+ if (filerr == osd_file::error::NONE)
{
std::string fullpath(image_file.fullpath());
image_file.close();
@@ -1073,15 +1073,15 @@ int open_disk_image(emu_options &options, const game_driver *gamedrv, const rom_
romphashes == hash_collection(ROM_GETHASHDATA(rom)))
{
/* attempt to open the properly named file, scanning up through parent directories */
- filerr = FILERR_NOT_FOUND;
- for (int searchdrv = drv; searchdrv != -1 && filerr != FILERR_NONE; searchdrv = driver_list::clone(searchdrv))
+ filerr = osd_file::error::NOT_FOUND;
+ for (int searchdrv = drv; searchdrv != -1 && filerr != osd_file::error::NONE; searchdrv = driver_list::clone(searchdrv))
filerr = common_process_file(options, driver_list::driver(searchdrv).name, ".chd", rom, image_file);
- if (filerr != FILERR_NONE)
+ if (filerr != osd_file::error::NONE)
filerr = common_process_file(options, nullptr, ".chd", rom, image_file);
/* did the file open succeed? */
- if (filerr == FILERR_NONE)
+ if (filerr == osd_file::error::NONE)
{
std::string fullpath(image_file.fullpath());
image_file.close();
@@ -1108,8 +1108,8 @@ chd_error rom_load_manager::open_disk_diff(emu_options &options, const rom_entry
/* try to open the diff */
LOG(("Opening differencing image file: %s\n", fname.c_str()));
emu_file diff_file(options.diff_directory(), OPEN_FLAG_READ | OPEN_FLAG_WRITE);
- file_error filerr = diff_file.open(fname.c_str());
- if (filerr == FILERR_NONE)
+ osd_file::error filerr = diff_file.open(fname.c_str());
+ if (filerr == osd_file::error::NONE)
{
std::string fullpath(diff_file.fullpath());
diff_file.close();
@@ -1122,7 +1122,7 @@ chd_error rom_load_manager::open_disk_diff(emu_options &options, const rom_entry
LOG(("Creating differencing image: %s\n", fname.c_str()));
diff_file.set_openflags(OPEN_FLAG_READ | OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS);
filerr = diff_file.open(fname.c_str());
- if (filerr == FILERR_NONE)
+ if (filerr == osd_file::error::NONE)
{
std::string fullpath(diff_file.fullpath());
diff_file.close();
diff --git a/src/emu/romload.h b/src/emu/romload.h
index c7c10e49325..fe35bfc3fe2 100644
--- a/src/emu/romload.h
+++ b/src/emu/romload.h
@@ -13,8 +13,8 @@
#error Dont include this file directly; include emu.h instead.
#endif
-#ifndef __ROMLOAD_H__
-#define __ROMLOAD_H__
+#ifndef MAME_EMU_ROMLOAD_H
+#define MAME_EMU_ROMLOAD_H
#include "chd.h"
@@ -350,7 +350,7 @@ private:
/* ----- Helpers ----- */
-std::unique_ptr<emu_file> common_process_file(emu_options &options, const char *location, bool has_crc, UINT32 crc, const rom_entry *romp, file_error &filerr);
+std::unique_ptr<emu_file> common_process_file(emu_options &options, const char *location, bool has_crc, UINT32 crc, const rom_entry *romp, osd_file::error &filerr);
/* return pointer to the first ROM region within a source */
const rom_entry *rom_first_region(const device_t &device);
@@ -386,4 +386,4 @@ std::string rom_parameter_value(const rom_entry *romp);
/* open a disk image, searching up the parent and loading by checksum */
int open_disk_image(emu_options &options, const game_driver *gamedrv, const rom_entry *romp, chd_file &image_chd, const char *locationtag);
-#endif /* __ROMLOAD_H__ */
+#endif // MAME_EMU_ROMLOAD_H
diff --git a/src/emu/screen.cpp b/src/emu/screen.cpp
index c286788ea37..111a1b3232a 100644
--- a/src/emu/screen.cpp
+++ b/src/emu/screen.cpp
@@ -1153,8 +1153,8 @@ void screen_device::finalize_burnin()
// compute the name and create the file
emu_file file(machine().options().snapshot_directory(), OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS);
- file_error filerr = file.open(machine().basename(), PATH_SEPARATOR "burnin-", this->tag()+1, ".png") ;
- if (filerr == FILERR_NONE)
+ osd_file::error filerr = file.open(machine().basename(), PATH_SEPARATOR "burnin-", this->tag()+1, ".png") ;
+ if (filerr == osd_file::error::NONE)
{
png_info pnginfo = { nullptr };
// png_error pngerr;
diff --git a/src/emu/softlist.cpp b/src/emu/softlist.cpp
index 05e9c761719..d554b394c21 100644
--- a/src/emu/softlist.cpp
+++ b/src/emu/softlist.cpp
@@ -478,8 +478,8 @@ void software_list_device::parse()
m_errors.clear();
// attempt to open the file
- file_error filerr = m_file.open(m_list_name.c_str(), ".xml");
- if (filerr == FILERR_NONE)
+ osd_file::error filerr = m_file.open(m_list_name.c_str(), ".xml");
+ if (filerr == osd_file::error::NONE)
{
// parse if no error
std::ostringstream errs;
diff --git a/src/emu/ui/auditmenu.cpp b/src/emu/ui/auditmenu.cpp
index 68b3c2d285b..c30619be3a9 100644
--- a/src/emu/ui/auditmenu.cpp
+++ b/src/emu/ui/auditmenu.cpp
@@ -174,7 +174,7 @@ void ui_menu_audit::save_available_machines()
{
// attempt to open the output file
emu_file file(machine().ui().options().ui_path(), OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS);
- if (file.open(emulator_info::get_configname(), "_avail.ini") == FILERR_NONE)
+ if (file.open(emulator_info::get_configname(), "_avail.ini") == osd_file::error::NONE)
{
// generate header
std::ostringstream buffer;
diff --git a/src/emu/ui/cmdrender.h b/src/emu/ui/cmdrender.h
index d9bf466f1e9..01cc169816d 100644
--- a/src/emu/ui/cmdrender.h
+++ b/src/emu/ui/cmdrender.h
@@ -87,7 +87,7 @@ void render_font::render_font_command_glyph()
{
emu_file ramfile(OPEN_FLAG_READ);
- if (ramfile.open_ram(font_uicmd14, sizeof(font_uicmd14)) == FILERR_NONE)
+ if (ramfile.open_ram(font_uicmd14, sizeof(font_uicmd14)) == osd_file::error::NONE)
load_cached_cmd(ramfile, 0);
}
diff --git a/src/emu/ui/custmenu.cpp b/src/emu/ui/custmenu.cpp
index 2d6083536db..85df4afcd8a 100644
--- a/src/emu/ui/custmenu.cpp
+++ b/src/emu/ui/custmenu.cpp
@@ -239,7 +239,7 @@ void ui_menu_custom_filter::save_custom_filters()
{
// attempt to open the output file
emu_file file(machine().ui().options().ui_path(), OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS);
- if (file.open("custom_", emulator_info::get_configname(), "_filter.ini") == FILERR_NONE)
+ if (file.open("custom_", emulator_info::get_configname(), "_filter.ini") == osd_file::error::NONE)
{
// generate custom filters info
std::ostringstream cinfo;
@@ -552,7 +552,7 @@ void ui_menu_swcustom_filter::save_sw_custom_filters()
{
// attempt to open the output file
emu_file file(machine().ui().options().ui_path(), OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS);
- if (file.open("custom_", m_driver->name, "_filter.ini") == FILERR_NONE)
+ if (file.open("custom_", m_driver->name, "_filter.ini") == osd_file::error::NONE)
{
// generate custom filters info
std::ostringstream cinfo;
diff --git a/src/emu/ui/datfile.cpp b/src/emu/ui/datfile.cpp
index 7a5ebb57e6f..35dfde7249d 100644
--- a/src/emu/ui/datfile.cpp
+++ b/src/emu/ui/datfile.cpp
@@ -548,7 +548,7 @@ bool datfile_manager::parseopen(const char *filename)
// so it's better and faster use standard C fileio functions.
emu_file file(machine().ui().options().history_path(), OPEN_FLAG_READ);
- if (file.open(filename) != FILERR_NONE)
+ if (file.open(filename) != osd_file::error::NONE)
return false;
m_fullpath = file.fullpath();
diff --git a/src/emu/ui/dirmenu.cpp b/src/emu/ui/dirmenu.cpp
index 8ae0372af30..03260a337d9 100644
--- a/src/emu/ui/dirmenu.cpp
+++ b/src/emu/ui/dirmenu.cpp
@@ -28,33 +28,33 @@ struct folders_entry
static const folders_entry s_folders[] =
{
- { __("ROMs"), OPTION_MEDIAPATH, ADDING },
- { __("UI"), OPTION_UI_PATH, CHANGE },
- { __("Language"), OPTION_LANGUAGEPATH, CHANGE },
- { __("Samples"), OPTION_SAMPLEPATH, ADDING },
- { __("DATs"), OPTION_HISTORY_PATH, ADDING },
- { __("INIs"), OPTION_INIPATH, ADDING },
- { __("Extra INIs"), OPTION_EXTRAINI_PATH, CHANGE },
- { __("Icons"), OPTION_ICONS_PATH, ADDING },
- { __("Cheats"), OPTION_CHEATPATH, ADDING },
- { __("Snapshots"), OPTION_SNAPSHOT_DIRECTORY, ADDING },
- { __("Cabinets"), OPTION_CABINETS_PATH, ADDING },
- { __("Flyers"), OPTION_FLYERS_PATH, ADDING },
- { __("Titles"), OPTION_TITLES_PATH, ADDING },
- { __("Ends"), OPTION_ENDS_PATH, ADDING },
- { __("PCBs"), OPTION_PCBS_PATH, ADDING },
- { __("Marquees"), OPTION_MARQUEES_PATH, ADDING },
- { __("Controls Panels"), OPTION_CPANELS_PATH, ADDING },
- { __("Crosshairs"), OPTION_CROSSHAIRPATH, ADDING },
- { __("Artworks"), OPTION_ARTPATH, ADDING },
- { __("Bosses"), OPTION_BOSSES_PATH, ADDING },
- { __("Artworks Preview"), OPTION_ARTPREV_PATH, ADDING },
- { __("Select"), OPTION_SELECT_PATH, ADDING },
- { __("GameOver"), OPTION_GAMEOVER_PATH, ADDING },
- { __("HowTo"), OPTION_HOWTO_PATH, ADDING },
- { __("Logos"), OPTION_LOGOS_PATH, ADDING },
- { __("Scores"), OPTION_SCORES_PATH, ADDING },
- { __("Versus"), OPTION_VERSUS_PATH, ADDING },
+ { __("ROMs"), OPTION_MEDIAPATH, ADDING },
+ { __("UI"), OPTION_UI_PATH, CHANGE },
+ { __("Language"), OPTION_LANGUAGEPATH, CHANGE },
+ { __("Samples"), OPTION_SAMPLEPATH, ADDING },
+ { __("DATs"), OPTION_HISTORY_PATH, ADDING },
+ { __("INIs"), OPTION_INIPATH, ADDING },
+ { __("Extra INIs"), OPTION_EXTRAINI_PATH, CHANGE },
+ { __("Icons"), OPTION_ICONS_PATH, ADDING },
+ { __("Cheats"), OPTION_CHEATPATH, ADDING },
+ { __("Snapshots"), OPTION_SNAPSHOT_DIRECTORY, ADDING },
+ { __("Cabinets"), OPTION_CABINETS_PATH, ADDING },
+ { __("Flyers"), OPTION_FLYERS_PATH, ADDING },
+ { __("Titles"), OPTION_TITLES_PATH, ADDING },
+ { __("Ends"), OPTION_ENDS_PATH, ADDING },
+ { __("PCBs"), OPTION_PCBS_PATH, ADDING },
+ { __("Marquees"), OPTION_MARQUEES_PATH, ADDING },
+ { __("Controls Panels"), OPTION_CPANELS_PATH, ADDING },
+ { __("Crosshairs"), OPTION_CROSSHAIRPATH, ADDING },
+ { __("Artworks"), OPTION_ARTPATH, ADDING },
+ { __("Bosses"), OPTION_BOSSES_PATH, ADDING },
+ { __("Artworks Preview"), OPTION_ARTPREV_PATH, ADDING },
+ { __("Select"), OPTION_SELECT_PATH, ADDING },
+ { __("GameOver"), OPTION_GAMEOVER_PATH, ADDING },
+ { __("HowTo"), OPTION_HOWTO_PATH, ADDING },
+ { __("Logos"), OPTION_LOGOS_PATH, ADDING },
+ { __("Scores"), OPTION_SCORES_PATH, ADDING },
+ { __("Versus"), OPTION_VERSUS_PATH, ADDING },
};
@@ -95,7 +95,6 @@ void ui_menu_directory::handle()
void ui_menu_directory::populate()
{
-
for (auto & elem : s_folders)
item_append(_(elem.name), nullptr, 0, (void *)(FPTR)elem.action);
@@ -144,7 +143,7 @@ void ui_menu_directory::custom_render(void *selectedref, float top, float bottom
// ctor / dtor
//-------------------------------------------------
-ui_menu_display_actual::ui_menu_display_actual(running_machine &machine, render_container *container, int ref)
+ui_menu_display_actual::ui_menu_display_actual(running_machine &machine, render_container *container, int ref)
: ui_menu(machine, container), m_ref(ref)
{
}
@@ -181,9 +180,9 @@ void ui_menu_display_actual::handle()
void ui_menu_display_actual::populate()
{
m_tempbuf = string_format(_("Current %1$s Folders"), _(s_folders[m_ref].name));
- if (machine().ui().options().exists(s_folders[m_ref].option))
+ if (machine().ui().options().exists(s_folders[m_ref].option))
m_searchpath.assign(machine().ui().options().value(s_folders[m_ref].option));
- else
+ else
m_searchpath.assign(machine().options().value(s_folders[m_ref].option));
path_iterator path(m_searchpath.c_str());
@@ -238,7 +237,7 @@ void ui_menu_display_actual::custom_render(void *selectedref, float top, float b
y1 += UI_BOX_TB_BORDER;
// draw the text within it
- mui.draw_text_full(container, m_tempbuf.c_str(), x1, y1, x2 - x1, JUSTIFY_CENTER, WRAP_TRUNCATE,
+ mui.draw_text_full(container, m_tempbuf.c_str(), x1, y1, x2 - x1, JUSTIFY_CENTER, WRAP_TRUNCATE,
DRAW_NORMAL, UI_TEXT_COLOR, UI_TEXT_BG_COLOR, nullptr, nullptr);
// compute our bounds
@@ -279,10 +278,7 @@ ui_menu_add_change_folder::ui_menu_add_change_folder(running_machine &machine, r
m_search[0] = '\0';
// configure the starting path
- char *dst = nullptr;
- osd_get_full_path(&dst, ".");
- m_current_path = dst;
- osd_free(dst);
+ osd_get_full_path(m_current_path, ".");
std::string searchpath;
if (machine.ui().options().exists(s_folders[m_ref].option))
@@ -571,9 +567,9 @@ void ui_menu_add_change_folder::custom_render(void *selectedref, float top, floa
ui_menu_remove_folder::ui_menu_remove_folder(running_machine &machine, render_container *container, int ref) : ui_menu(machine, container)
{
m_ref = ref;
- if (machine.ui().options().exists(s_folders[m_ref].option))
+ if (machine.ui().options().exists(s_folders[m_ref].option))
m_searchpath.assign(machine.ui().options().value(s_folders[m_ref].option));
- else
+ else
m_searchpath.assign(machine.options().value(s_folders[m_ref].option));
path_iterator path(m_searchpath.c_str());
@@ -609,7 +605,7 @@ void ui_menu_remove_folder::handle()
machine().ui().options().set_value(s_folders[m_ref].option, tmppath.c_str(), OPTION_PRIORITY_CMDLINE, error_string);
else if (strcmp(machine().options().value(s_folders[m_ref].option),tmppath.c_str())!=0)
{
- machine().options().set_value(s_folders[m_ref].option, tmppath.c_str(), OPTION_PRIORITY_CMDLINE, error_string);
+ machine().options().set_value(s_folders[m_ref].option, tmppath.c_str(), OPTION_PRIORITY_CMDLINE, error_string);
machine().options().mark_changed(s_folders[m_ref].option);
}
@@ -662,6 +658,6 @@ void ui_menu_remove_folder::custom_render(void *selectedref, float top, float bo
y1 += UI_BOX_TB_BORDER;
// draw the text within it
- mui.draw_text_full(container, tempbuf.c_str(), x1, y1, x2 - x1, JUSTIFY_CENTER, WRAP_NEVER, DRAW_NORMAL,
+ mui.draw_text_full(container, tempbuf.c_str(), x1, y1, x2 - x1, JUSTIFY_CENTER, WRAP_NEVER, DRAW_NORMAL,
UI_TEXT_COLOR, UI_TEXT_BG_COLOR, nullptr, nullptr);
}
diff --git a/src/emu/ui/filesel.cpp b/src/emu/ui/filesel.cpp
index ec8d4c2ea22..89658407279 100644
--- a/src/emu/ui/filesel.cpp
+++ b/src/emu/ui/filesel.cpp
@@ -536,7 +536,7 @@ void ui_menu_file_selector::append_entry_menu_item(const file_selector_entry *en
void ui_menu_file_selector::populate()
{
zippath_directory *directory = nullptr;
- file_error err;
+ osd_file::error err;
const osd_directory_entry *dirent;
const file_selector_entry *entry;
const file_selector_entry *selected_entry = nullptr;
@@ -579,7 +579,7 @@ void ui_menu_file_selector::populate()
}
// build the menu for each item
- if (err == FILERR_NONE)
+ if (err == osd_file::error::NONE)
{
while((dirent = zippath_readdir(directory)) != nullptr)
{
@@ -621,7 +621,7 @@ void ui_menu_file_selector::populate()
void ui_menu_file_selector::handle()
{
- file_error err;
+ osd_file::error err;
const file_selector_entry *entry;
const file_selector_entry *selected_entry = nullptr;
int bestmatch = 0;
@@ -657,7 +657,7 @@ void ui_menu_file_selector::handle()
case SELECTOR_ENTRY_TYPE_DIRECTORY:
// drive/directory - first check the path
err = zippath_opendir(entry->fullpath, nullptr);
- if (err != FILERR_NONE)
+ if (err != osd_file::error::NONE)
{
// this path is problematic; present the user with an error and bail
machine().ui().popup_time(1, "Error accessing %s", entry->fullpath);
diff --git a/src/emu/ui/icorender.h b/src/emu/ui/icorender.h
index eec52b7e3ed..79452bd9fca 100644
--- a/src/emu/ui/icorender.h
+++ b/src/emu/ui/icorender.h
@@ -80,9 +80,9 @@ void render_load_ico(bitmap_argb32 &bitmap, emu_file &file, const char *dirname,
else
fname.assign(dirname).append(PATH_SEPARATOR).append(filename);
- file_error filerr = file.open(fname.c_str());
+ osd_file::error filerr = file.open(fname.c_str());
- if (filerr != FILERR_NONE)
+ if (filerr != osd_file::error::NONE)
return;
// allocates a buffer for the image
diff --git a/src/emu/ui/imgcntrl.cpp b/src/emu/ui/imgcntrl.cpp
index 3b96f63971e..f0b6f3da5b4 100644
--- a/src/emu/ui/imgcntrl.cpp
+++ b/src/emu/ui/imgcntrl.cpp
@@ -64,7 +64,7 @@ ui_menu_control_device_image::ui_menu_control_device_image(running_machine &mach
current_directory.assign(image->working_directory());
/* check to see if the path exists; if not clear it */
- if (zippath_opendir(current_directory.c_str(), nullptr) != FILERR_NONE)
+ if (zippath_opendir(current_directory.c_str(), nullptr) != osd_file::error::NONE)
current_directory.clear();
}
}
@@ -184,8 +184,8 @@ void ui_menu_control_device_image::handle()
bool can_create = false;
if(image->is_creatable()) {
zippath_directory *directory = nullptr;
- file_error err = zippath_opendir(current_directory.c_str(), &directory);
- can_create = err == FILERR_NONE && !zippath_is_zip(directory);
+ osd_file::error err = zippath_opendir(current_directory.c_str(), &directory);
+ can_create = err == osd_file::error::NONE && !zippath_is_zip(directory);
if(directory)
zippath_closedir(directory);
}
diff --git a/src/emu/ui/inifile.cpp b/src/emu/ui/inifile.cpp
index 8958fe4cd3b..ac669e03d40 100644
--- a/src/emu/ui/inifile.cpp
+++ b/src/emu/ui/inifile.cpp
@@ -151,7 +151,7 @@ bool inifile_manager::parseopen(const char *filename)
// so it's better and faster use standard C fileio functions.
emu_file file(machine().ui().options().extraini_path(), OPEN_FLAG_READ);
- if (file.open(filename) != FILERR_NONE)
+ if (file.open(filename) != osd_file::error::NONE)
return false;
m_fullpath = file.fullpath();
@@ -359,7 +359,7 @@ bool favorite_manager::isgame_favorite(ui_software_info &swinfo)
void favorite_manager::parse_favorite()
{
emu_file file(machine().ui().options().ui_path(), OPEN_FLAG_READ);
- if (file.open(favorite_filename) == FILERR_NONE)
+ if (file.open(favorite_filename) == osd_file::error::NONE)
{
char readbuf[1024];
file.gets(readbuf, 1024);
@@ -418,7 +418,7 @@ void favorite_manager::save_favorite_games()
{
// attempt to open the output file
emu_file file(machine().ui().options().ui_path(), OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS);
- if (file.open(favorite_filename) == FILERR_NONE)
+ if (file.open(favorite_filename) == osd_file::error::NONE)
{
if (m_list.empty())
{
diff --git a/src/emu/ui/miscmenu.cpp b/src/emu/ui/miscmenu.cpp
index 2145069bfab..e11a416e01d 100644
--- a/src/emu/ui/miscmenu.cpp
+++ b/src/emu/ui/miscmenu.cpp
@@ -588,7 +588,7 @@ ui_menu_misc_options::~ui_menu_misc_options()
{
machine().ui().options().set_value(m_options[d].option, m_options[d].status, OPTION_PRIORITY_CMDLINE, error_string);
}
- else
+ else
{
if (machine().options().bool_value(m_options[d].option) != m_options[d].status)
{
@@ -677,7 +677,7 @@ void ui_menu_misc_options::custom_render(void *selectedref, float top, float bot
// ctor / dtor
//-------------------------------------------------
-ui_menu_export::ui_menu_export(running_machine &machine, render_container *container, std::vector<const game_driver *> drvlist)
+ui_menu_export::ui_menu_export(running_machine &machine, render_container *container, std::vector<const game_driver *> drvlist)
: ui_menu(machine, container), m_list(drvlist)
{
}
@@ -705,11 +705,11 @@ void ui_menu_export::handle()
{
std::string filename("exported");
emu_file infile(machine().ui().options().ui_path(), OPEN_FLAG_READ);
- if (infile.open(filename.c_str(), ".xml") == FILERR_NONE)
+ if (infile.open(filename.c_str(), ".xml") == osd_file::error::NONE)
for (int seq = 0; ; ++seq)
{
std::string seqtext = string_format("%s_%04d", filename, seq);
- if (infile.open(seqtext.c_str(), ".xml") != FILERR_NONE)
+ if (infile.open(seqtext.c_str(), ".xml") != osd_file::error::NONE)
{
filename = seqtext;
break;
@@ -718,7 +718,7 @@ void ui_menu_export::handle()
// attempt to open the output file
emu_file file(machine().ui().options().ui_path(), OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS);
- if (file.open(filename.c_str(), ".xml") == FILERR_NONE)
+ if (file.open(filename.c_str(), ".xml") == osd_file::error::NONE)
{
FILE *pfile;
std::string fullpath(file.fullpath());
@@ -745,11 +745,11 @@ void ui_menu_export::handle()
{
std::string filename("exported");
emu_file infile(machine().ui().options().ui_path(), OPEN_FLAG_READ);
- if (infile.open(filename.c_str(), ".txt") == FILERR_NONE)
+ if (infile.open(filename.c_str(), ".txt") == osd_file::error::NONE)
for (int seq = 0; ; ++seq)
{
std::string seqtext = string_format("%s_%04d", filename, seq);
- if (infile.open(seqtext.c_str(), ".txt") != FILERR_NONE)
+ if (infile.open(seqtext.c_str(), ".txt") != osd_file::error::NONE)
{
filename = seqtext;
break;
@@ -758,7 +758,7 @@ void ui_menu_export::handle()
// attempt to open the output file
emu_file file(machine().ui().options().ui_path(), OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS);
- if (file.open(filename.c_str(), ".txt") == FILERR_NONE)
+ if (file.open(filename.c_str(), ".txt") == osd_file::error::NONE)
{
// print the header
std::ostringstream buffer;
@@ -829,8 +829,8 @@ void ui_menu_machine_configure::handle()
{
std::string filename(m_drv->name);
emu_file file(machine().options().ini_path(), OPEN_FLAG_WRITE | OPEN_FLAG_CREATE);
- file_error filerr = file.open(filename.c_str(), ".ini");
- if (filerr == FILERR_NONE)
+ osd_file::error filerr = file.open(filename.c_str(), ".ini");
+ if (filerr == osd_file::error::NONE)
{
std::string inistring = machine().options().output_ini();
file.puts(inistring.c_str());
@@ -889,4 +889,4 @@ void ui_menu_machine_configure::custom_render(void *selectedref, float top, floa
// draw the text within it
mui.draw_text_full(container, m_drv->description, x1, y1, x2 - x1, JUSTIFY_CENTER, WRAP_TRUNCATE,
DRAW_NORMAL, UI_TEXT_COLOR, UI_TEXT_BG_COLOR, nullptr, nullptr);
-} \ No newline at end of file
+}
diff --git a/src/emu/ui/optsmenu.cpp b/src/emu/ui/optsmenu.cpp
index f93bdbf4652..c80ad0ad00e 100644
--- a/src/emu/ui/optsmenu.cpp
+++ b/src/emu/ui/optsmenu.cpp
@@ -314,7 +314,7 @@ void save_ui_options(running_machine &machine)
{
// attempt to open the output file
emu_file file(machine.options().ini_path(), OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS);
- if (file.open("ui.ini") == FILERR_NONE)
+ if (file.open("ui.ini") == osd_file::error::NONE)
{
// generate the updated INI
std::string initext = machine.ui().options().output_ini();
@@ -339,7 +339,7 @@ void save_main_option(running_machine &machine)
// attempt to open the main ini file
{
emu_file file(machine.options().ini_path(), OPEN_FLAG_READ);
- if (file.open(emulator_info::get_configname(), ".ini") == FILERR_NONE)
+ if (file.open(emulator_info::get_configname(), ".ini") == osd_file::error::NONE)
{
bool result = options.parse_ini_file((util::core_file&)file, OPTION_PRIORITY_MAME_INI, OPTION_PRIORITY_DRIVER_INI, error);
if (!result)
@@ -361,7 +361,7 @@ void save_main_option(running_machine &machine)
// attempt to open the output file
{
emu_file file(machine.options().ini_path(), OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS);
- if (file.open(emulator_info::get_configname(), ".ini") == FILERR_NONE)
+ if (file.open(emulator_info::get_configname(), ".ini") == osd_file::error::NONE)
{
// generate the updated INI
std::string initext = options.output_ini();
@@ -375,4 +375,3 @@ void save_main_option(running_machine &machine)
}
machine.ui().popup_time(3, "%s", _("\n Configuration saved \n\n"));
}
-
diff --git a/src/emu/ui/selgame.cpp b/src/emu/ui/selgame.cpp
index d0beab50bcc..023ca72b470 100644
--- a/src/emu/ui/selgame.cpp
+++ b/src/emu/ui/selgame.cpp
@@ -34,13 +34,13 @@
extern const char UI_VERSION_TAG[];
static bool first_start = true;
-static const char *dats_info[] = {
- __("General Info"),
- __("History"),
- __("Mameinfo"),
- __("Sysinfo"),
- __("Messinfo"),
- __("Command"),
+static const char *dats_info[] = {
+ __("General Info"),
+ __("History"),
+ __("Mameinfo"),
+ __("Sysinfo"),
+ __("Messinfo"),
+ __("Command"),
__("Mamescore") };
std::vector<const game_driver *> ui_menu_select_game::m_sortedlist;
@@ -505,7 +505,7 @@ void ui_menu_select_game::handle()
// if we're in an error state, overlay an error message
if (ui_error)
- machine().ui().draw_text_box(container, _("The selected machine is missing one or more required ROM or CHD images. "
+ machine().ui().draw_text_box(container, _("The selected machine is missing one or more required ROM or CHD images. "
"Please select a different machine.\n\nPress any key (except ESC) to continue."), JUSTIFY_CENTER, 0.5f, 0.5f, UI_RED_COLOR);
// handle filters selection from key shortcuts
@@ -839,7 +839,7 @@ void ui_menu_select_game::custom_render(void *selectedref, float top, float bott
for (int line = 0; line < 2; ++line)
{
mui.draw_text_full(container, tempbuf[line].c_str(), 0.0f, 0.0f, 1.0f, JUSTIFY_CENTER, WRAP_NEVER,
- DRAW_NONE, ARGB_WHITE, ARGB_BLACK, &width, nullptr);
+ DRAW_NONE, ARGB_WHITE, ARGB_BLACK, &width, nullptr);
width += 2 * UI_BOX_LR_BORDER;
maxwidth = MAX(width, maxwidth);
}
@@ -861,7 +861,7 @@ void ui_menu_select_game::custom_render(void *selectedref, float top, float bott
// draw the text within it
for (int line = 0; line < 2; ++line)
{
- mui.draw_text_full(container, tempbuf[line].c_str(), x1, y1, x2 - x1, JUSTIFY_CENTER, WRAP_NEVER,
+ mui.draw_text_full(container, tempbuf[line].c_str(), x1, y1, x2 - x1, JUSTIFY_CENTER, WRAP_NEVER,
DRAW_NORMAL, UI_TEXT_COLOR, UI_TEXT_BG_COLOR, nullptr, nullptr);
y1 += mui.get_line_height();
}
@@ -918,7 +918,7 @@ void ui_menu_select_game::custom_render(void *selectedref, float top, float bott
color = UI_GREEN_COLOR;
if ((driver->flags & (MACHINE_IMPERFECT_GRAPHICS | MACHINE_WRONG_COLORS | MACHINE_IMPERFECT_COLORS
- | MACHINE_NO_SOUND | MACHINE_IMPERFECT_SOUND)) != 0)
+ | MACHINE_NO_SOUND | MACHINE_IMPERFECT_SOUND)) != 0)
color = UI_YELLOW_COLOR;
if ((driver->flags & (MACHINE_NOT_WORKING | MACHINE_UNEMULATED_PROTECTION)) != 0)
@@ -986,7 +986,7 @@ void ui_menu_select_game::custom_render(void *selectedref, float top, float bott
for (auto & elem : tempbuf)
{
- mui.draw_text_full(container, elem.c_str(), 0.0f, 0.0f, 1.0f, JUSTIFY_CENTER, WRAP_NEVER,
+ mui.draw_text_full(container, elem.c_str(), 0.0f, 0.0f, 1.0f, JUSTIFY_CENTER, WRAP_NEVER,
DRAW_NONE, ARGB_WHITE, ARGB_BLACK, &width, nullptr);
width += 2 * UI_BOX_LR_BORDER;
maxwidth = MAX(maxwidth, width);
@@ -1549,7 +1549,7 @@ void ui_menu_select_game::populate_search()
if (cx != -1 && ((driver_list::driver(cx).flags & MACHINE_IS_BIOS_ROOT) != 0))
cloneof = false;
}
- item_append(m_searchlist[curitem]->description, nullptr, (!cloneof) ? flags_ui : (MENU_FLAG_INVERT | flags_ui),
+ item_append(m_searchlist[curitem]->description, nullptr, (!cloneof) ? flags_ui : (MENU_FLAG_INVERT | flags_ui),
(void *)m_searchlist[curitem]);
}
}
@@ -1694,7 +1694,7 @@ bool ui_menu_select_game::load_available_machines()
{
// try to load available drivers from file
emu_file file(machine().ui().options().ui_path(), OPEN_FLAG_READ);
- if (file.open(emulator_info::get_configname(), "_avail.ini") != FILERR_NONE)
+ if (file.open(emulator_info::get_configname(), "_avail.ini") != osd_file::error::NONE)
return false;
std::string readbuf;
@@ -1746,7 +1746,7 @@ void ui_menu_select_game::load_custom_filters()
{
// attempt to open the output file
emu_file file(machine().ui().options().ui_path(), OPEN_FLAG_READ);
- if (file.open("custom_", emulator_info::get_configname(), "_filter.ini") == FILERR_NONE)
+ if (file.open("custom_", emulator_info::get_configname(), "_filter.ini") == osd_file::error::NONE)
{
char buffer[MAX_CHAR_INFO];
@@ -1902,7 +1902,7 @@ float ui_menu_select_game::draw_left_panel(float x1, float y1, float x2, float y
convert_command_glyph(str);
}
- mui.draw_text_full(container, str.c_str(), x1t, y1, x2 - x1, JUSTIFY_LEFT, WRAP_NEVER,
+ mui.draw_text_full(container, str.c_str(), x1t, y1, x2 - x1, JUSTIFY_LEFT, WRAP_NEVER,
DRAW_NORMAL, fgcolor, bgcolor, nullptr, nullptr, text_size);
y1 += line_height_max;
}
@@ -2006,14 +2006,14 @@ void ui_menu_select_game::infos_render(void *selectedref, float origx1, float or
// apply title to right panel
float title_size = 0.0f;
- float txt_lenght = 0.0f;
+ float txt_length = 0.0f;
for (int x = UI_FIRST_LOAD; x < UI_LAST_LOAD; ++x)
{
mui.draw_text_full(container, _(dats_info[x]), origx1, origy1, origx2 - origx1, JUSTIFY_CENTER,
- WRAP_NEVER, DRAW_NONE, UI_TEXT_COLOR, UI_TEXT_BG_COLOR, &txt_lenght, nullptr);
- txt_lenght += 0.01f;
- title_size = MAX(txt_lenght, title_size);
+ WRAP_NEVER, DRAW_NONE, UI_TEXT_COLOR, UI_TEXT_BG_COLOR, &txt_length, nullptr);
+ txt_length += 0.01f;
+ title_size = (std::max)(txt_length, title_size);
}
rgb_t fgcolor = UI_TEXT_COLOR;
@@ -2072,7 +2072,7 @@ void ui_menu_select_game::infos_render(void *selectedref, float origx1, float or
if (buffer.empty())
{
- mui.draw_text_full(container, _("No Infos Available"), origx1, (origy2 + origy1) * 0.5f, origx2 - origx1, JUSTIFY_CENTER,
+ mui.draw_text_full(container, _("No Infos Available"), origx1, (origy2 + origy1) * 0.5f, origx2 - origx1, JUSTIFY_CENTER,
WRAP_WORD, DRAW_NORMAL, UI_TEXT_COLOR, UI_TEXT_BG_COLOR, nullptr, nullptr);
return;
}
@@ -2126,7 +2126,7 @@ void ui_menu_select_game::infos_render(void *selectedref, float origx1, float or
JUSTIFY_LEFT, WRAP_TRUNCATE, DRAW_NORMAL, UI_TEXT_COLOR, UI_TEXT_BG_COLOR, &item_width, nullptr, tmp_size);
mui.draw_text_full(container, last_part.c_str(), effective_left + item_width, oy1,
- origx2 - origx1 - 2.0f * gutter_width - item_width, JUSTIFY_RIGHT, WRAP_TRUNCATE,
+ origx2 - origx1 - 2.0f * gutter_width - item_width, JUSTIFY_RIGHT, WRAP_TRUNCATE,
DRAW_NORMAL, UI_TEXT_COLOR, UI_TEXT_BG_COLOR, nullptr, nullptr, tmp_size);
}
}
@@ -2146,18 +2146,18 @@ void ui_menu_select_game::infos_render(void *selectedref, float origx1, float or
std::string first_part(tempbuf.substr(0, first_dspace));
std::string last_part(tempbuf.substr(first_dspace + 1));
strtrimspace(last_part);
- mui.draw_text_full(container, first_part.c_str(), effective_left, oy1, effective_width, JUSTIFY_LEFT,
+ mui.draw_text_full(container, first_part.c_str(), effective_left, oy1, effective_width, JUSTIFY_LEFT,
WRAP_TRUNCATE, DRAW_NORMAL, UI_TEXT_COLOR, UI_TEXT_BG_COLOR, nullptr, nullptr, tmp_size);
- mui.draw_text_full(container, last_part.c_str(), effective_left, oy1, origx2 - origx1 - 2.0f * gutter_width,
+ mui.draw_text_full(container, last_part.c_str(), effective_left, oy1, origx2 - origx1 - 2.0f * gutter_width,
JUSTIFY_RIGHT, WRAP_TRUNCATE, DRAW_NORMAL, UI_TEXT_COLOR, UI_TEXT_BG_COLOR, nullptr, nullptr, tmp_size);
}
else
- mui.draw_text_full(container, tempbuf.c_str(), origx1 + gutter_width, oy1, origx2 - origx1, JUSTIFY_LEFT,
+ mui.draw_text_full(container, tempbuf.c_str(), origx1 + gutter_width, oy1, origx2 - origx1, JUSTIFY_LEFT,
WRAP_TRUNCATE, DRAW_NORMAL, UI_TEXT_COLOR, UI_TEXT_BG_COLOR, nullptr, nullptr, tmp_size);
}
else
- mui.draw_text_full(container, tempbuf.c_str(), origx1 + gutter_width, oy1, origx2 - origx1, JUSTIFY_LEFT,
+ mui.draw_text_full(container, tempbuf.c_str(), origx1 + gutter_width, oy1, origx2 - origx1, JUSTIFY_LEFT,
WRAP_TRUNCATE, DRAW_NORMAL, UI_TEXT_COLOR, UI_TEXT_BG_COLOR, nullptr, nullptr, text_size);
oy1 += (line_height * text_size);
@@ -2182,17 +2182,17 @@ void ui_menu_select_game::infos_render(void *selectedref, float origx1, float or
else
{
float title_size = 0.0f;
- float txt_lenght = 0.0f;
+ float txt_length = 0.0f;
std::string t_text[2];
t_text[0] = _("History");
t_text[1] = _("Usage");
for (auto & elem: t_text)
{
- mui.draw_text_full(container, elem.c_str(), origx1, origy1, origx2 - origx1, JUSTIFY_CENTER, WRAP_TRUNCATE,
- DRAW_NONE, UI_TEXT_COLOR, UI_TEXT_BG_COLOR, &txt_lenght, nullptr);
- txt_lenght += 0.01f;
- title_size = MAX(txt_lenght, title_size);
+ mui.draw_text_full(container, elem.c_str(), origx1, origy1, origx2 - origx1, JUSTIFY_CENTER, WRAP_TRUNCATE,
+ DRAW_NONE, UI_TEXT_COLOR, UI_TEXT_BG_COLOR, &txt_length, nullptr);
+ txt_length += 0.01f;
+ title_size = (std::max)(txt_length, title_size);
}
rgb_t fgcolor = UI_TEXT_COLOR;
@@ -2260,7 +2260,7 @@ void ui_menu_select_game::infos_render(void *selectedref, float origx1, float or
else if (r == r_visible_lines - 1 && itemline != totallines - 1)
info_arrow(1, origx1, origx2, oy1, line_height, text_size, ud_arrow_width);
else
- mui.draw_text_full(container, tempbuf.c_str(), origx1 + gutter_width, oy1, origx2 - origx1, JUSTIFY_LEFT,
+ mui.draw_text_full(container, tempbuf.c_str(), origx1 + gutter_width, oy1, origx2 - origx1, JUSTIFY_LEFT,
WRAP_TRUNCATE, DRAW_NORMAL, UI_TEXT_COLOR, UI_TEXT_BG_COLOR, nullptr, nullptr, text_size);
oy1 += (line_height * text_size);
}
diff --git a/src/emu/ui/selsoft.cpp b/src/emu/ui/selsoft.cpp
index 19a24dc8c20..0b8078b5f2f 100644
--- a/src/emu/ui/selsoft.cpp
+++ b/src/emu/ui/selsoft.cpp
@@ -29,9 +29,9 @@ std::string reselect_last::software;
std::string reselect_last::swlist;
bool reselect_last::m_reselect = false;
static const char *region_lists[] = { "arab", "arg", "asia", "aus", "aut", "bel", "blr", "bra", "can", "chi", "chn", "cze", "den",
- "ecu", "esp", "euro", "fin", "fra", "gbr", "ger", "gre", "hkg", "hun", "irl", "isr",
- "isv", "ita", "jpn", "kaz", "kor", "lat", "lux", "mex", "ned", "nld", "nor", "nzl",
- "pol", "rus", "slo", "spa", "sui", "swe", "tha", "tpe", "tw", "uk", "ukr", "usa" };
+ "ecu", "esp", "euro", "fin", "fra", "gbr", "ger", "gre", "hkg", "hun", "irl", "isr",
+ "isv", "ita", "jpn", "kaz", "kor", "lat", "lux", "mex", "ned", "nld", "nor", "nzl",
+ "pol", "rus", "slo", "spa", "sui", "swe", "tha", "tpe", "tw", "uk", "ukr", "usa" };
//-------------------------------------------------
// compares two items in the software list and
@@ -303,7 +303,6 @@ void ui_menu_select_software::handle()
if (m_event != nullptr && m_event->itemref == nullptr)
{
-
if (m_event->iptkey == IPT_UI_CONFIGURE)
inkey_configure(m_event);
@@ -488,7 +487,7 @@ void ui_menu_select_software::populate()
old_software = m_has_empty_start ? curitem + 1 : curitem;
item_append(m_displaylist[curitem]->longname.c_str(), m_displaylist[curitem]->devicetype.c_str(),
- m_displaylist[curitem]->parentname.empty() ? flags_ui : (MENU_FLAG_INVERT | flags_ui), (void *)m_displaylist[curitem]);
+ m_displaylist[curitem]->parentname.empty() ? flags_ui : (MENU_FLAG_INVERT | flags_ui), (void *)m_displaylist[curitem]);
}
}
@@ -498,8 +497,8 @@ void ui_menu_select_software::populate()
for (int curitem = 0; m_searchlist[curitem] != nullptr; ++curitem)
item_append(m_searchlist[curitem]->longname.c_str(), m_searchlist[curitem]->devicetype.c_str(),
- m_searchlist[curitem]->parentname.empty() ? flags_ui : (MENU_FLAG_INVERT | flags_ui),
- (void *)m_searchlist[curitem]);
+ m_searchlist[curitem]->parentname.empty() ? flags_ui : (MENU_FLAG_INVERT | flags_ui),
+ (void *)m_searchlist[curitem]);
}
item_append(MENU_SEPARATOR_ITEM, nullptr, flags_ui, nullptr);
@@ -700,7 +699,7 @@ void ui_menu_select_software::custom_render(void *selectedref, float top, float
for (int line = 0; line < 3; ++line)
{
mui.draw_text_full(container, tempbuf[line].c_str(), 0.0f, 0.0f, 1.0f, JUSTIFY_CENTER, WRAP_NEVER,
- DRAW_NONE, ARGB_WHITE, ARGB_BLACK, &width, nullptr);
+ DRAW_NONE, ARGB_WHITE, ARGB_BLACK, &width, nullptr);
width += 2 * UI_BOX_LR_BORDER;
maxwidth = MAX(width, maxwidth);
}
@@ -723,7 +722,7 @@ void ui_menu_select_software::custom_render(void *selectedref, float top, float
for (int line = 0; line < 3; ++line)
{
mui.draw_text_full(container, tempbuf[line].c_str(), x1, y1, x2 - x1, JUSTIFY_CENTER, WRAP_NEVER,
- DRAW_NORMAL, UI_TEXT_COLOR, UI_TEXT_BG_COLOR, nullptr, nullptr);
+ DRAW_NORMAL, UI_TEXT_COLOR, UI_TEXT_BG_COLOR, nullptr, nullptr);
y1 += mui.get_line_height();
}
@@ -845,7 +844,7 @@ void ui_menu_select_software::custom_render(void *selectedref, float top, float
for (auto & elem : tempbuf)
{
mui.draw_text_full(container, elem.c_str(), 0.0f, 0.0f, 1.0f, JUSTIFY_CENTER, WRAP_NEVER,
- DRAW_NONE, ARGB_WHITE, ARGB_BLACK, &width, nullptr);
+ DRAW_NONE, ARGB_WHITE, ARGB_BLACK, &width, nullptr);
width += 2 * UI_BOX_LR_BORDER;
maxwidth = MAX(maxwidth, width);
}
@@ -872,7 +871,7 @@ void ui_menu_select_software::custom_render(void *selectedref, float top, float
for (auto & elem : tempbuf)
{
mui.draw_text_full(container, elem.c_str(), x1, y1, x2 - x1, JUSTIFY_CENTER, WRAP_NEVER,
- DRAW_NORMAL, UI_TEXT_COLOR, UI_TEXT_BG_COLOR, nullptr, nullptr);
+ DRAW_NORMAL, UI_TEXT_COLOR, UI_TEXT_BG_COLOR, nullptr, nullptr);
y1 += machine().ui().get_line_height();
}
}
@@ -1049,7 +1048,7 @@ void ui_menu_select_software::load_sw_custom_filters()
{
// attempt to open the output file
emu_file file(machine().ui().options().ui_path(), OPEN_FLAG_READ);
- if (file.open("custom_", m_driver->name, "_filter.ini") == FILERR_NONE)
+ if (file.open("custom_", m_driver->name, "_filter.ini") == osd_file::error::NONE)
{
char buffer[MAX_CHAR_INFO];
@@ -1479,7 +1478,7 @@ float ui_menu_select_software::draw_left_panel(float x1, float y1, float x2, flo
}
mui.draw_text_full(container, str.c_str(), x1t, y1, x2 - x1, JUSTIFY_LEFT, WRAP_NEVER,
- DRAW_NORMAL, fgcolor, bgcolor, nullptr, nullptr, text_size);
+ DRAW_NORMAL, fgcolor, bgcolor, nullptr, nullptr, text_size);
y1 += line_height;
}
@@ -1979,7 +1978,7 @@ void ui_software_parts::custom_render(void *selectedref, float top, float bottom
float width;
ui_manager &mui = machine().ui();
mui.draw_text_full(container, _("Software part selection:"), 0.0f, 0.0f, 1.0f, JUSTIFY_CENTER, WRAP_TRUNCATE,
- DRAW_NONE, ARGB_WHITE, ARGB_BLACK, &width, nullptr);
+ DRAW_NONE, ARGB_WHITE, ARGB_BLACK, &width, nullptr);
width += 2 * UI_BOX_LR_BORDER;
float maxwidth = MAX(origx2 - origx1, width);
@@ -1999,7 +1998,7 @@ void ui_software_parts::custom_render(void *selectedref, float top, float bottom
// draw the text within it
mui.draw_text_full(container, _("Software part selection:"), x1, y1, x2 - x1, JUSTIFY_CENTER, WRAP_TRUNCATE,
- DRAW_NORMAL, UI_TEXT_COLOR, UI_TEXT_BG_COLOR, nullptr, nullptr);
+ DRAW_NORMAL, UI_TEXT_COLOR, UI_TEXT_BG_COLOR, nullptr, nullptr);
}
//-------------------------------------------------
@@ -2117,7 +2116,7 @@ void ui_bios_selection::custom_render(void *selectedref, float top, float bottom
float width;
ui_manager &mui = machine().ui();
mui.draw_text_full(container, _("Bios selection:"), 0.0f, 0.0f, 1.0f, JUSTIFY_CENTER, WRAP_TRUNCATE,
- DRAW_NONE, ARGB_WHITE, ARGB_BLACK, &width, nullptr);
+ DRAW_NONE, ARGB_WHITE, ARGB_BLACK, &width, nullptr);
width += 2 * UI_BOX_LR_BORDER;
float maxwidth = MAX(origx2 - origx1, width);
@@ -2137,5 +2136,5 @@ void ui_bios_selection::custom_render(void *selectedref, float top, float bottom
// draw the text within it
mui.draw_text_full(container, _("Bios selection:"), x1, y1, x2 - x1, JUSTIFY_CENTER, WRAP_TRUNCATE,
- DRAW_NORMAL, UI_TEXT_COLOR, UI_TEXT_BG_COLOR, nullptr, nullptr);
+ DRAW_NORMAL, UI_TEXT_COLOR, UI_TEXT_BG_COLOR, nullptr, nullptr);
}
diff --git a/src/emu/ui/ui.cpp b/src/emu/ui/ui.cpp
index 839e7c2d7a2..a265e74c7b1 100644
--- a/src/emu/ui/ui.cpp
+++ b/src/emu/ui/ui.cpp
@@ -169,7 +169,7 @@ static void load_ui_options(running_machine &machine)
std::string error;
// attempt to open the output file
emu_file file(machine.options().ini_path(), OPEN_FLAG_READ);
- if (file.open("ui.ini") == FILERR_NONE)
+ if (file.open("ui.ini") == osd_file::error::NONE)
{
bool result = machine.ui().options().parse_ini_file((util::core_file&)file, OPTION_PRIORITY_MAME_INI, OPTION_PRIORITY_DRIVER_INI, error);
if (!result)
diff --git a/src/emu/ui/utils.h b/src/emu/ui/utils.h
index a2f24a20479..5c1485e102b 100644
--- a/src/emu/ui/utils.h
+++ b/src/emu/ui/utils.h
@@ -271,9 +271,9 @@ void render_load_jpeg(_T &bitmap, emu_file &file, const char *dirname, const cha
else
fname.assign(dirname).append(PATH_SEPARATOR).append(filename);
- file_error filerr = file.open(fname.c_str());
+ osd_file::error filerr = file.open(fname.c_str());
- if (filerr != FILERR_NONE)
+ if (filerr != osd_file::error::NONE)
return;
// define standard JPEG structures
diff --git a/src/emu/video.cpp b/src/emu/video.cpp
index 229553a92b8..c3090bc6096 100644
--- a/src/emu/video.cpp
+++ b/src/emu/video.cpp
@@ -350,8 +350,8 @@ void video_manager::save_active_screen_snapshots()
if (machine().render().is_live(*screen))
{
emu_file file(machine().options().snapshot_directory(), OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS);
- file_error filerr = open_next(file, "png");
- if (filerr == FILERR_NONE)
+ osd_file::error filerr = open_next(file, "png");
+ if (filerr == osd_file::error::NONE)
save_snapshot(screen, file);
}
}
@@ -360,8 +360,8 @@ void video_manager::save_active_screen_snapshots()
else
{
emu_file file(machine().options().snapshot_directory(), OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS);
- file_error filerr = open_next(file, "png");
- if (filerr == FILERR_NONE)
+ osd_file::error filerr = open_next(file, "png");
+ if (filerr == osd_file::error::NONE)
save_snapshot(nullptr, file);
}
}
@@ -428,7 +428,7 @@ void video_manager::begin_recording(const char *name, movie_format format)
// build up information about this new movie
screen_device *screen = machine().first_screen();
- avi_movie_info info;
+ avi_file::movie_info info;
info.video_format = 0;
info.video_timescale = 1000 * ((screen != nullptr) ? ATTOSECONDS_TO_HZ(screen->frame_period().attoseconds()) : screen_device::DEFAULT_FRAME_RATE);
info.video_sampletime = 1000;
@@ -446,7 +446,7 @@ void video_manager::begin_recording(const char *name, movie_format format)
info.audio_samplerate = machine().sample_rate();
// create a new temporary movie file
- file_error filerr;
+ osd_file::error filerr;
std::string fullpath;
{
emu_file tempfile(machine().options().snapshot_directory(), OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS);
@@ -456,20 +456,20 @@ void video_manager::begin_recording(const char *name, movie_format format)
filerr = open_next(tempfile, "avi");
// if we succeeded, make a copy of the name and create the real file over top
- if (filerr == FILERR_NONE)
+ if (filerr == osd_file::error::NONE)
fullpath = tempfile.fullpath();
}
- if (filerr == FILERR_NONE)
+ if (filerr == osd_file::error::NONE)
{
// compute the frame time
m_avi_frame_period = attotime::from_seconds(1000) / info.video_timescale;
// create the file and free the string
- avi_error avierr = avi_create(fullpath.c_str(), &info, &m_avi_file);
- if (avierr != AVIERR_NONE)
+ avi_file::error avierr = avi_file::create(fullpath, info, m_avi_file);
+ if (avierr != avi_file::error::NONE)
{
- osd_printf_error("Error creating AVI: %s\n", avi_error_string(avierr));
+ osd_printf_error("Error creating AVI: %s\n", avi_file::error_string(avierr));
return end_recording(format);
}
}
@@ -487,13 +487,13 @@ void video_manager::begin_recording(const char *name, movie_format format)
// create a new movie file and start recording
m_mng_file = std::make_unique<emu_file>(machine().options().snapshot_directory(), OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS);
- file_error filerr;
+ osd_file::error filerr;
if (name != nullptr)
filerr = m_mng_file->open(name);
else
filerr = open_next(*m_mng_file, "mng");
- if (filerr == FILERR_NONE)
+ if (filerr == osd_file::error::NONE)
{
// start the capture
screen_device *screen = machine().first_screen();
@@ -510,7 +510,7 @@ void video_manager::begin_recording(const char *name, movie_format format)
}
else
{
- osd_printf_error("Error creating MNG, file_error=%d\n", filerr);
+ osd_printf_error("Error creating MNG, osd_file::error=%d\n", int(filerr));
m_mng_file.reset();
}
}
@@ -526,10 +526,9 @@ void video_manager::end_recording(movie_format format)
if (format == MF_AVI)
{
// close the file if it exists
- if (m_avi_file != nullptr)
+ if (m_avi_file)
{
- avi_close(m_avi_file);
- m_avi_file = nullptr;
+ m_avi_file.reset();
// reset the state
m_avi_frame = 0;
@@ -563,10 +562,10 @@ void video_manager::add_sound_to_recording(const INT16 *sound, int numsamples)
g_profiler.start(PROFILER_MOVIE_REC);
// write the next frame
- avi_error avierr = avi_append_sound_samples(m_avi_file, 0, sound + 0, numsamples, 1);
- if (avierr == AVIERR_NONE)
- avierr = avi_append_sound_samples(m_avi_file, 1, sound + 1, numsamples, 1);
- if (avierr != AVIERR_NONE)
+ avi_file::error avierr = m_avi_file->append_sound_samples(0, sound + 0, numsamples, 1);
+ if (avierr == avi_file::error::NONE)
+ avierr = m_avi_file->append_sound_samples(1, sound + 1, numsamples, 1);
+ if (avierr != avi_file::error::NONE)
end_recording(MF_AVI);
g_profiler.stop();
@@ -1091,8 +1090,8 @@ void video_manager::recompute_speed(const attotime &emutime)
{
// create a final screenshot
emu_file file(machine().options().snapshot_directory(), OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS);
- file_error filerr = file.open(machine().basename(), PATH_SEPARATOR "final.png");
- if (filerr == FILERR_NONE)
+ osd_file::error filerr = file.open(machine().basename(), PATH_SEPARATOR "final.png");
+ if (filerr == osd_file::error::NONE)
save_snapshot(screen, file);
}
//printf("Scheduled exit at %f\n", emutime.as_double());
@@ -1150,7 +1149,7 @@ void video_manager::create_snapshot_bitmap(screen_device *screen)
// scheme
//-------------------------------------------------
-file_error video_manager::open_next(emu_file &file, const char *extension)
+osd_file::error video_manager::open_next(emu_file &file, const char *extension)
{
UINT32 origflags = file.openflags();
@@ -1260,8 +1259,8 @@ file_error video_manager::open_next(emu_file &file, const char *extension)
strreplace(fname, "%i", string_format("%04d", seq).c_str());
// try to open the file; stop when we fail
- file_error filerr = file.open(fname.c_str());
- if (filerr != FILERR_NONE)
+ osd_file::error filerr = file.open(fname.c_str());
+ if (filerr != osd_file::error::NONE)
break;
}
}
@@ -1296,8 +1295,8 @@ void video_manager::record_frame()
while (m_avi_next_frame_time <= curtime)
{
// write the next frame
- avi_error avierr = avi_append_video_frame(m_avi_file, m_snap_bitmap);
- if (avierr != AVIERR_NONE)
+ avi_file::error avierr = m_avi_file->append_video_frame(m_snap_bitmap);
+ if (avierr != avi_file::error::NONE)
{
g_profiler.stop();
end_recording(MF_AVI);
diff --git a/src/emu/video.h b/src/emu/video.h
index 67939d47eaa..019b2b0a472 100644
--- a/src/emu/video.h
+++ b/src/emu/video.h
@@ -14,8 +14,10 @@
#error Dont include this file directly; include emu.h instead.
#endif
-#ifndef __VIDEO_H__
-#define __VIDEO_H__
+#ifndef MAME_EMU_VIDEO_H
+#define MAME_EMU_VIDEO_H
+
+#include "aviio.h"
//**************************************************************************
@@ -35,7 +37,7 @@ const int MAX_FRAMESKIP = FRAMESKIP_LEVELS - 2;
// forward references
class render_target;
class screen_device;
-struct avi_file;
+class avi_file;
@@ -64,7 +66,7 @@ public:
bool throttled() const { return m_throttled; }
float throttle_rate() const { return m_throttle_rate; }
bool fastforward() const { return m_fastforward; }
- bool is_recording() const { return (m_mng_file != nullptr || m_avi_file != nullptr); }
+ bool is_recording() const { return (m_mng_file || m_avi_file); }
// setters
void set_frameskip(int frameskip);
@@ -76,7 +78,7 @@ public:
// misc
void toggle_throttle();
void toggle_record_movie();
- file_error open_next(emu_file &file, const char *extension);
+ osd_file::error open_next(emu_file &file, const char *extension);
// render a frame
void frame_update(bool debug = false);
@@ -184,7 +186,7 @@ private:
UINT32 m_mng_frame; // current movie frame number
// movie recording - AVI
- avi_file * m_avi_file; // handle to the open movie file
+ avi_file::ptr m_avi_file; // handle to the open movie file
attotime m_avi_frame_period; // period of a single movie frame
attotime m_avi_next_frame_time; // time of next frame
UINT32 m_avi_frame; // current movie frame number
@@ -205,4 +207,4 @@ private:
};
-#endif /* __VIDEO_H__ */
+#endif // MAME_EMU_VIDEO_H
diff --git a/src/lib/util/aviio.cpp b/src/lib/util/aviio.cpp
index a448128070b..8483adb24f6 100644
--- a/src/lib/util/aviio.cpp
+++ b/src/lib/util/aviio.cpp
@@ -1,5 +1,5 @@
// license:BSD-3-Clause
-// copyright-holders:Aaron Giles
+// copyright-holders:Aaron Giles, Vas Crabb
/***************************************************************************
aviio.c
@@ -8,8 +8,10 @@
***************************************************************************/
-#include <stdlib.h>
-#include <assert.h>
+#include <array>
+#include <cassert>
+#include <cstdlib>
+#include <cstring>
#include "aviio.h"
@@ -45,7 +47,7 @@
* @brief A macro that defines four gigabytes.
*/
-#define FOUR_GB ((UINT64)1 << 32)
+#define FOUR_GB (std::uint64_t(1) << 32)
/**
* @def MAX_SOUND_CHANNELS
@@ -222,7 +224,7 @@
#define HUFFYUV_PREDICT_DECORR 0x40
-
+namespace {
/***************************************************************************
TYPE DEFINITIONS
***************************************************************************/
@@ -235,14 +237,12 @@
struct avi_chunk
{
- /** @brief The offset. */
- UINT64 offset; /* file offset of chunk header */
- /** @brief The size. */
- UINT64 size; /* size of this chunk */
- /** @brief The type. */
- UINT32 type; /* type of this chunk */
- /** @brief The listtype. */
- UINT32 listtype; /* type of this list (if we are a list) */
+ avi_chunk() : offset(0), size(0), type(0), listtype(0) { }
+
+ std::uint64_t offset; /* file offset of chunk header */
+ std::uint64_t size; /* size of this chunk */
+ std::uint32_t type; /* type of this chunk */
+ std::uint32_t listtype; /* type of this list (if we are a list) */
};
/**
@@ -253,211 +253,297 @@ struct avi_chunk
struct avi_chunk_list
{
- /** @brief The offset. */
- UINT64 offset; /* offset in the file of header */
- /** @brief The length. */
- UINT32 length; /* length of the chunk including header */
+ std::uint64_t offset; /* offset in the file of header */
+ std::uint32_t length; /* length of the chunk including header */
};
/**
- * @struct huffyuv_table
+ * @struct avi_stream
*
- * @brief A huffyuv table.
+ * @brief An avi stream.
*/
-struct huffyuv_table
-{
- /** @brief The shift[ 256]. */
- UINT8 shift[256]; /* bit shift amounts */
- /** @brief The bits[ 256]. */
- UINT32 bits[256]; /* bit match values */
- /** @brief The mask[ 256]. */
- UINT32 mask[256]; /* bit mask values */
- /** @brief The baselookup[ 65536]. */
- UINT16 baselookup[65536]; /* base lookup table */
- /** @brief The extralookup. */
- UINT16 * extralookup; /* extra lookup tables */
-};
+class avi_stream
+{
+public:
+ avi_stream()
+ : m_type(0)
+ , m_format(0)
+ , m_rate(0)
+ , m_scale(0)
+ , m_samples(0)
+ , m_chunks()
+ , m_width(0)
+ , m_height(0)
+ , m_depth(0)
+ , m_interlace(0)
+ , m_huffyuv()
+ , m_channels(0)
+ , m_samplebits(0)
+ , m_samplerate(0)
+ , m_saved_strh_offset(0)
+ , m_saved_indx_offset(0)
+ {
+ }
-/**
- * @struct huffyuv_data
- *
- * @brief A huffyuv data.
- */
+ void initialize_video(avi_file::movie_info const &info)
+ {
+ m_type = STREAMTYPE_VIDS;
+ m_format = info.video_format;
+ m_rate = info.video_timescale;
+ m_scale = info.video_sampletime;
+ m_width = info.video_width;
+ m_height = info.video_height;
+ m_depth = info.video_depth;
+ }
-struct huffyuv_data
-{
- /** @brief The predictor. */
- UINT8 predictor; /* predictor */
- /** @brief The table[ 3]. */
- huffyuv_table table[3]; /* array of tables */
-};
+ void initialize_audio(avi_file::movie_info const &info)
+ {
+ m_type = STREAMTYPE_AUDS;
+ m_format = info.audio_format;
+ m_rate = info.audio_timescale;
+ m_scale = info.audio_sampletime;
+ m_channels = info.audio_channels;
+ m_samplebits = info.audio_samplebits;
+ m_samplerate = info.audio_samplerate;
+ }
-/**
- * @struct avi_stream
- *
- * @brief An avi stream.
- */
+ std::uint32_t type() const { return m_type; }
+ std::uint32_t format() const { return m_format; }
+
+ std::uint32_t rate() const { return m_rate; }
+ std::uint32_t scale() const { return m_scale; }
+ std::uint32_t samples() const { return m_samples; }
+ void set_samples(std::uint32_t value) { m_samples = value; }
+ std::uint32_t add_samples(std::uint32_t value) { return m_samples += value; }
+
+ std::uint32_t chunks() const { return m_chunks.size(); }
+ avi_chunk_list const &chunk(std::uint32_t index) const { assert(index < m_chunks.size()); return m_chunks[index]; }
+ avi_chunk_list &chunk(std::uint32_t index) { assert(index < m_chunks.size()); return m_chunks[index]; }
+ avi_file::error set_chunk_info(std::uint32_t index, std::uint64_t offset, std::uint32_t length);
+ void set_chunks(std::uint32_t count) { assert(count <= m_chunks.size()); m_chunks.resize(count); }
+
+ std::uint32_t width() const { return m_width; }
+ std::uint32_t height() const { return m_height; }
+ std::uint32_t depth() const { return m_depth; }
+
+ std::uint16_t channels() const { return m_channels; }
+ std::uint16_t samplebits() const { return m_samplebits; }
+ std::uint32_t samplerate() const { return m_samplerate; }
+ std::uint32_t bytes_per_sample() const { return (m_samplebits / 8) * m_channels; }
+
+ avi_file::error set_strh_data(std::uint8_t const *data, std::uint32_t size);
+ avi_file::error set_strf_data(std::uint8_t const *data, std::uint32_t size);
+
+ std::uint64_t &saved_strh_offset() { return m_saved_strh_offset; }
+ std::uint64_t &saved_indx_offset() { return m_saved_indx_offset; }
+
+ // RGB helpers
+ avi_file::error rgb32_compress_to_rgb(const bitmap_rgb32 &bitmap, std::uint8_t *data, std::uint32_t numbytes) const;
+
+ // YUY helpers
+ avi_file::error yuv_decompress_to_yuy16(const std::uint8_t *data, std::uint32_t numbytes, bitmap_yuy16 &bitmap) const;
+ avi_file::error yuy16_compress_to_yuy(const bitmap_yuy16 &bitmap, std::uint8_t *data, std::uint32_t numbytes) const;
+
+ // HuffYUV helpers
+ avi_file::error huffyuv_decompress_to_yuy16(const std::uint8_t *data, std::uint32_t numbytes, bitmap_yuy16 &bitmap) const;
+
+private:
+ struct huffyuv_table
+ {
+ std::uint8_t shift[256]; /* bit shift amounts */
+ std::uint32_t bits[256]; /* bit match values */
+ std::uint32_t mask[256]; /* bit mask values */
+ std::uint16_t baselookup[65536]; /* base lookup table */
+ std::vector<std::uint16_t> extralookup; /* extra lookup tables */
+ };
+
+ struct huffyuv_data
+ {
+ std::uint8_t predictor; /* predictor */
+ huffyuv_table table[3]; /* array of tables */
+ };
-struct avi_stream
-{
- /** @brief The type. */
- UINT32 type; /* subtype of stream */
- /** @brief Describes the format to use. */
- UINT32 format; /* format of stream data */
-
- /** @brief The rate. */
- UINT32 rate; /* timescale for stream */
- /** @brief The scale. */
- UINT32 scale; /* duration of one sample in the stream */
- /** @brief The samples. */
- UINT32 samples; /* number of samples */
-
- /** @brief The chunk. */
- avi_chunk_list * chunk; /* list of chunks */
- /** @brief The chunks. */
- UINT32 chunks; /* chunks currently known */
- /** @brief The chunksalloc. */
- UINT32 chunksalloc; /* number of chunks allocated */
-
- /** @brief The width. */
- UINT32 width; /* width of video */
- /** @brief The height. */
- UINT32 height; /* height of video */
- /** @brief The depth. */
- UINT32 depth; /* depth of video */
- /** @brief The interlace. */
- UINT8 interlace; /* interlace parameters */
- /** @brief The huffyuv. */
- huffyuv_data * huffyuv; /* huffyuv decompression data */
-
- /** @brief The channels. */
- UINT16 channels; /* audio channels */
- /** @brief The samplebits. */
- UINT16 samplebits; /* audio bits per sample */
- /** @brief The samplerate. */
- UINT32 samplerate; /* audio sample rate */
+ avi_file::error huffyuv_extract_tables(const std::uint8_t *chunkdata, std::uint32_t size);
+
+ std::uint32_t m_type; /* subtype of stream */
+ std::uint32_t m_format; /* format of stream data */
+
+ std::uint32_t m_rate; /* timescale for stream */
+ std::uint32_t m_scale; /* duration of one sample in the stream */
+ std::uint32_t m_samples; /* number of samples */
+
+ std::vector<avi_chunk_list> m_chunks; /* list of chunks */
+
+ std::uint32_t m_width; /* width of video */
+ std::uint32_t m_height; /* height of video */
+ std::uint32_t m_depth; /* depth of video */
+ std::uint8_t m_interlace; /* interlace parameters */
+ std::unique_ptr<huffyuv_data const> m_huffyuv; /* huffyuv decompression data */
+
+ std::uint16_t m_channels; /* audio channels */
+ std::uint16_t m_samplebits; /* audio bits per sample */
+ std::uint32_t m_samplerate; /* audio sample rate */
/* only used when creating */
- /** @brief The saved strh offset. */
- UINT64 saved_strh_offset; /* writeoffset of strh chunk */
- /** @brief The saved indx offset. */
- UINT64 saved_indx_offset; /* writeoffset of indx chunk */
+ std::uint64_t m_saved_strh_offset; /* writeoffset of strh chunk */
+ std::uint64_t m_saved_indx_offset; /* writeoffset of indx chunk */
};
/**
- * @struct avi_file
+ * @class avi_file_impl
*
* @brief An avi file.
*/
-struct avi_file
+class avi_file_impl : public avi_file
{
- /* shared data */
- /** @brief The file. */
- osd_file * file; /* pointer to open file */
- /** @brief The type. */
- int type; /* type of access (read/create) */
- /** @brief The information. */
- avi_movie_info info; /* movie info structure */
- /** @brief The tempbuffer. */
- UINT8 * tempbuffer; /* temporary buffer */
- /** @brief The tempbuffersize. */
- UINT32 tempbuffersize; /* size of the temporary buffer */
-
- /* only used when reading */
- /** @brief The streams. */
- int streams; /* number of streams */
- /** @brief The stream. */
- avi_stream * stream; /* allocated array of stream information */
- /** @brief The rootchunk. */
- avi_chunk rootchunk; /* dummy root chunk that wraps the whole file */
-
- /* only used when creating */
- /** @brief The writeoffs. */
- UINT64 writeoffs; /* current file write offset */
- /** @brief The riffbase. */
- UINT64 riffbase; /* base of the current RIFF */
-
- /** @brief The chunkstack[ 8]. */
- avi_chunk chunkstack[8]; /* stack of chunks we are writing */
- /** @brief The chunksp. */
- int chunksp; /* stack pointer for the current chunk */
-
- /** @brief The saved movi offset. */
- UINT64 saved_movi_offset; /* writeoffset of movi list */
- /** @brief The saved avih offset. */
- UINT64 saved_avih_offset; /* writeoffset of avih chunk */
-
- /** @brief The soundbuf. */
- INT16 * soundbuf; /* buffer for sound data */
- /** @brief The soundbuf samples. */
- UINT32 soundbuf_samples; /* length of sound buffer in samples */
- /** @brief The soundbuf chansamples[ maximum sound channels]. */
- UINT32 soundbuf_chansamples[MAX_SOUND_CHANNELS]; /* samples in buffer for each channel */
- /** @brief The soundbuf chunks. */
- UINT32 soundbuf_chunks; /* number of chunks completed so far */
- /** @brief The soundbuf frames. */
- UINT32 soundbuf_frames; /* number of frames ahead of the video */
-};
-
+public:
+ avi_file_impl(osd_file::ptr &&file, std::uint64_t length) : avi_file_impl()
+ {
+ m_file = std::move(file);
+ m_type = FILETYPE_READ;
+
+ // make a root atom
+ m_rootchunk.offset = 0;
+ m_rootchunk.size = length;
+ m_rootchunk.type = 0;
+ m_rootchunk.listtype = 0;
+ }
+ avi_file_impl(osd_file::ptr &&file, movie_info const &info) : avi_file_impl()
+ {
+ m_file = std::move(file);
+ m_type = FILETYPE_CREATE;
-/***************************************************************************
- PROTOTYPES
-***************************************************************************/
+ // copy the movie info
+ m_info = info;
+ m_info.video_numsamples = 0;
+ m_info.audio_numsamples = 0;
-/* stream helpers */
+ // initialize the video track
+ m_streams.emplace_back();
+ m_streams.back().initialize_video(m_info);
-/* core chunk read routines */
-static avi_error get_first_chunk(avi_file *file, const avi_chunk *parent, avi_chunk *newchunk);
-static avi_error get_next_chunk(avi_file *file, const avi_chunk *parent, avi_chunk *newchunk);
-static avi_error find_first_chunk(avi_file *file, UINT32 findme, const avi_chunk *container, avi_chunk *result);
-static avi_error find_next_chunk(avi_file *file, UINT32 findme, const avi_chunk *container, avi_chunk *result);
-static avi_error get_next_chunk_internal(avi_file *file, const avi_chunk *parent, avi_chunk *newchunk, UINT64 offset);
-static avi_error read_chunk_data(avi_file *file, const avi_chunk *chunk, UINT8 **buffer);
+ // initialize the audio track
+ if (m_info.audio_channels > 0)
+ {
+ m_streams.emplace_back();
+ m_streams.back().initialize_audio(m_info);
+ }
+ }
-/* chunk read helpers */
-static avi_error read_movie_data(avi_file *file);
-static avi_error extract_movie_info(avi_file *file);
-static avi_error parse_avih_chunk(avi_file *file, avi_chunk *avih);
-static avi_error parse_strh_chunk(avi_file *file, avi_stream *stream, avi_chunk *strh);
-static avi_error parse_strf_chunk(avi_file *file, avi_stream *stream, avi_chunk *strf);
-static avi_error parse_indx_chunk(avi_file *file, avi_stream *stream, avi_chunk *strf);
-static avi_error parse_idx1_chunk(avi_file *file, UINT64 baseoffset, avi_chunk *idx1);
+ virtual ~avi_file_impl() override;
+
+ virtual void printf_chunks() override;
+
+ virtual movie_info const &get_movie_info() const override;
+ virtual std::uint32_t first_sample_in_frame(std::uint32_t framenum) const override;
+
+ virtual error read_video_frame(std::uint32_t framenum, bitmap_yuy16 &bitmap) override;
+ virtual error read_sound_samples(int channel, std::uint32_t firstsample, std::uint32_t numsamples, std::int16_t *output) override;
+
+ virtual error append_video_frame(bitmap_yuy16 &bitmap) override;
+ virtual error append_video_frame(bitmap_rgb32 &bitmap) override;
+ virtual error append_sound_samples(int channel, std::int16_t const *samples, std::uint32_t numsamples, std::uint32_t sampleskip) override;
+
+ error read_movie_data();
+ error write_initial_headers();
+ error soundbuf_initialize();
+
+private:
+ avi_file_impl()
+ : m_file()
+ , m_type(0)
+ , m_info({ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 })
+ , m_tempbuffer()
+ , m_streams()
+ , m_rootchunk()
+ , m_writeoffs(0)
+ , m_riffbase(0)
+ , m_chunkstack()
+ , m_chunksp(0)
+ , m_saved_movi_offset(0)
+ , m_saved_avih_offset(0)
+ , m_soundbuf()
+ , m_soundbuf_samples(0)
+ , m_soundbuf_chansamples{ 0 }
+ , m_soundbuf_chunks(0)
+ , m_soundbuf_frames(0)
+ {
+ }
-/* core chunk write routines */
-static avi_error chunk_open(avi_file *file, UINT32 type, UINT32 listtype, UINT32 estlength);
-static avi_error chunk_close(avi_file *file);
-static avi_error chunk_write(avi_file *file, UINT32 type, const void *data, UINT32 length);
-static avi_error chunk_overwrite(avi_file *file, UINT32 type, const void *data, UINT32 length, UINT64 *offset, int initial_write);
+ avi_stream *get_video_stream();
+ avi_stream *get_audio_stream(int channel, int &offset);
+ std::uint32_t compute_idx1_size() const;
+ std::uint32_t get_chunkid_for_stream(const avi_stream *stream) const;
+ std::uint32_t framenum_to_samplenum(std::uint32_t framenum) const;
+ error expand_tempbuffer(std::uint32_t length);
+
+ // core chunk read routines
+ error get_first_chunk(avi_chunk const *parent, avi_chunk &newchunk);
+ error get_next_chunk(avi_chunk const *parent, avi_chunk &newchunk);
+ error find_first_chunk(std::uint32_t findme, avi_chunk const *container, avi_chunk &result);
+ error find_next_chunk(std::uint32_t findme, avi_chunk const *container, avi_chunk &result);
+ error find_first_list(std::uint32_t findme, avi_chunk const *container, avi_chunk &result);
+ error find_next_list(std::uint32_t findme, avi_chunk const *container, avi_chunk &result);
+ error get_next_chunk_internal(avi_chunk const *parent, avi_chunk &newchunk, std::uint64_t offset);
+ error read_chunk_data(avi_chunk const &chunk, std::unique_ptr<std::uint8_t []> &buffer);
+
+ // chunk read helpers
+ error extract_movie_info();
+ error parse_avih_chunk(avi_chunk const &avih);
+ error parse_strh_chunk(avi_stream &stream, avi_chunk const &strh);
+ error parse_strf_chunk(avi_stream &stream, avi_chunk const &strf);
+ error parse_indx_chunk(avi_stream &stream, avi_chunk const &strf);
+ error parse_idx1_chunk(std::uint64_t baseoffset, avi_chunk const &idx1);
+
+ // core chunk write routines
+ error chunk_open(std::uint32_t type, std::uint32_t listtype, std::uint32_t estlength);
+ error chunk_close();
+ error chunk_write(std::uint32_t type, const void *data, std::uint32_t length);
+ error chunk_overwrite(std::uint32_t type, const void *data, std::uint32_t length, std::uint64_t &offset, bool initial_write);
+
+ // chunk write helpers
+ error write_avih_chunk(bool initial_write);
+ error write_strh_chunk(avi_stream &stream, bool initial_write);
+ error write_strf_chunk(avi_stream const &stream);
+ error write_indx_chunk(avi_stream &stream, bool initial_write);
+ error write_idx1_chunk();
+
+ // sound buffering helpers
+ error soundbuf_write_chunk(std::uint32_t framenum);
+ error soundbuf_flush(bool only_flush_full);
+
+ // debugging
+ void printf_chunk_recursive(avi_chunk const *chunk, int indent);
-/* chunk write helpers */
-static avi_error write_initial_headers(avi_file *file);
-static avi_error write_avih_chunk(avi_file *file, int initial_write);
-static avi_error write_strh_chunk(avi_file *file, avi_stream *stream, int initial_write);
-static avi_error write_strf_chunk(avi_file *file, avi_stream *stream);
-static avi_error write_indx_chunk(avi_file *file, avi_stream *stream, int initial_write);
-static avi_error write_idx1_chunk(avi_file *file);
+ /* shared data */
+ osd_file::ptr m_file; /* pointer to open file */
+ int m_type; /* type of access (read/create) */
+ movie_info m_info; /* movie info structure */
+ std::vector<std::uint8_t> m_tempbuffer; /* temporary buffer */
-/* sound buffering helpers */
-static avi_error soundbuf_initialize(avi_file *file);
-static avi_error soundbuf_write_chunk(avi_file *file, UINT32 framenum);
-static avi_error soundbuf_flush(avi_file *file, int only_flush_full);
+ /* only used when reading */
+ std::vector<avi_stream> m_streams; /* allocated array of stream information */
+ avi_chunk m_rootchunk; /* dummy root chunk that wraps the whole file */
-/* RGB helpers */
-static avi_error rgb32_compress_to_rgb(avi_stream *stream, const bitmap_rgb32 &bitmap, UINT8 *data, UINT32 numbytes);
+ /* only used when creating */
+ std::uint64_t m_writeoffs; /* current file write offset */
+ std::uint64_t m_riffbase; /* base of the current RIFF */
-/* YUY helpers */
-static avi_error yuv_decompress_to_yuy16(avi_stream *stream, const UINT8 *data, UINT32 numbytes, bitmap_yuy16 &bitmap);
-static avi_error yuy16_compress_to_yuy(avi_stream *stream, const bitmap_yuy16 &bitmap, UINT8 *data, UINT32 numbytes);
+ std::array<avi_chunk, 8> m_chunkstack; /* stack of chunks we are writing */
+ int m_chunksp; /* stack pointer for the current chunk */
-/* HuffYUV helpers */
-static avi_error huffyuv_extract_tables(avi_stream *stream, const UINT8 *chunkdata, UINT32 size);
-static avi_error huffyuv_decompress_to_yuy16(avi_stream *stream, const UINT8 *data, UINT32 numbytes, bitmap_yuy16 &bitmap);
+ std::uint64_t m_saved_movi_offset; /* writeoffset of movi list */
+ std::uint64_t m_saved_avih_offset; /* writeoffset of avih chunk */
-/* debugging */
-static void printf_chunk_recursive(avi_file *file, avi_chunk *chunk, int indent);
+ std::vector<std::int16_t> m_soundbuf; /* buffer for sound data */
+ std::uint32_t m_soundbuf_samples; /* length of sound buffer in samples */
+ std::uint32_t m_soundbuf_chansamples[MAX_SOUND_CHANNELS]; /* samples in buffer for each channel */
+ std::uint32_t m_soundbuf_chunks; /* number of chunks completed so far */
+ std::uint32_t m_soundbuf_frames; /* number of frames ahead of the video */
+};
@@ -471,7 +557,7 @@ static void printf_chunk_recursive(avi_file *file, avi_chunk *chunk, int indent)
-------------------------------------------------*/
/**
- * @fn static inline UINT16 fetch_16bits(const UINT8 *data)
+ * @fn static inline std::uint16_t fetch_16bits(const std::uint8_t *data)
*
* @brief Fetches the 16bits.
*
@@ -480,7 +566,7 @@ static void printf_chunk_recursive(avi_file *file, avi_chunk *chunk, int indent)
* @return The 16bits.
*/
-static inline UINT16 fetch_16bits(const UINT8 *data)
+inline std::uint16_t fetch_16bits(const std::uint8_t *data)
{
return data[0] | (data[1] << 8);
}
@@ -492,7 +578,7 @@ static inline UINT16 fetch_16bits(const UINT8 *data)
-------------------------------------------------*/
/**
- * @fn static inline UINT32 fetch_32bits(const UINT8 *data)
+ * @fn static inline std::uint32_t fetch_32bits(const std::uint8_t *data)
*
* @brief Fetches the 32bits.
*
@@ -501,7 +587,7 @@ static inline UINT16 fetch_16bits(const UINT8 *data)
* @return The 32bits.
*/
-static inline UINT32 fetch_32bits(const UINT8 *data)
+inline std::uint32_t fetch_32bits(const std::uint8_t *data)
{
return data[0] | (data[1] << 8) | (data[2] << 16) | (data[3] << 24);
}
@@ -513,7 +599,7 @@ static inline UINT32 fetch_32bits(const UINT8 *data)
-------------------------------------------------*/
/**
- * @fn static inline UINT64 fetch_64bits(const UINT8 *data)
+ * @fn static inline std::uint64_t fetch_64bits(const std::uint8_t *data)
*
* @brief Fetches the 64bits.
*
@@ -522,12 +608,12 @@ static inline UINT32 fetch_32bits(const UINT8 *data)
* @return The 64bits.
*/
-static inline UINT64 fetch_64bits(const UINT8 *data)
+inline std::uint64_t fetch_64bits(const std::uint8_t *data)
{
- return (UINT64)data[0] | ((UINT64)data[1] << 8) |
- ((UINT64)data[2] << 16) | ((UINT64)data[3] << 24) |
- ((UINT64)data[4] << 32) | ((UINT64)data[5] << 40) |
- ((UINT64)data[6] << 48) | ((UINT64)data[7] << 56);
+ return std::uint64_t(data[0]) | (std::uint64_t(data[1]) << 8) |
+ (std::uint64_t(data[2]) << 16) | (std::uint64_t(data[3]) << 24) |
+ (std::uint64_t(data[4]) << 32) | (std::uint64_t(data[5]) << 40) |
+ (std::uint64_t(data[6]) << 48) | (std::uint64_t(data[7]) << 56);
}
@@ -537,7 +623,7 @@ static inline UINT64 fetch_64bits(const UINT8 *data)
-------------------------------------------------*/
/**
- * @fn static inline void put_16bits(UINT8 *data, UINT16 value)
+ * @fn static inline void put_16bits(std::uint8_t *data, std::uint16_t value)
*
* @brief Puts the 16bits.
*
@@ -545,7 +631,7 @@ static inline UINT64 fetch_64bits(const UINT8 *data)
* @param value The value.
*/
-static inline void put_16bits(UINT8 *data, UINT16 value)
+inline void put_16bits(std::uint8_t *data, std::uint16_t value)
{
data[0] = value >> 0;
data[1] = value >> 8;
@@ -558,7 +644,7 @@ static inline void put_16bits(UINT8 *data, UINT16 value)
-------------------------------------------------*/
/**
- * @fn static inline void put_32bits(UINT8 *data, UINT32 value)
+ * @fn static inline void put_32bits(std::uint8_t *data, std::uint32_t value)
*
* @brief Puts the 32bits.
*
@@ -566,7 +652,7 @@ static inline void put_16bits(UINT8 *data, UINT16 value)
* @param value The value.
*/
-static inline void put_32bits(UINT8 *data, UINT32 value)
+inline void put_32bits(std::uint8_t *data, std::uint32_t value)
{
data[0] = value >> 0;
data[1] = value >> 8;
@@ -581,7 +667,7 @@ static inline void put_32bits(UINT8 *data, UINT32 value)
-------------------------------------------------*/
/**
- * @fn static inline void put_64bits(UINT8 *data, UINT64 value)
+ * @fn static inline void put_64bits(std::uint8_t *data, std::uint64_t value)
*
* @brief Puts the 64bits.
*
@@ -589,7 +675,7 @@ static inline void put_32bits(UINT8 *data, UINT32 value)
* @param value The value.
*/
-static inline void put_64bits(UINT8 *data, UINT64 value)
+inline void put_64bits(std::uint8_t *data, std::uint64_t value)
{
data[0] = value >> 0;
data[1] = value >> 8;
@@ -602,29 +688,120 @@ static inline void put_64bits(UINT8 *data, UINT64 value)
}
+/**
+ * @fn static void u64toa(std::uint64_t val, char *output)
+ *
+ * @brief 64toas.
+ *
+ * @param val The value.
+ * @param [in,out] output If non-null, the output.
+ */
+
+inline void u64toa(std::uint64_t val, char *output)
+{
+ std::uint32_t lo = std::uint32_t(val & 0xffffffff);
+ std::uint32_t hi = std::uint32_t(val >> 32);
+ if (hi != 0)
+ sprintf(output, "%X%08X", hi, lo);
+ else
+ sprintf(output, "%X", lo);
+}
+
+
+/*-------------------------------------------------
+ set_stream_chunk_info - set the chunk info
+ for a given chunk within a stream
+-------------------------------------------------*/
+
+/**
+ * @fn static inline avi_error set_stream_chunk_info(avi_stream *stream, std::uint32_t index, std::uint64_t offset, std::uint32_t length)
+ *
+ * @brief Sets stream chunk information.
+ *
+ * @param [in,out] stream If non-null, the stream.
+ * @param index Zero-based index of the.
+ * @param offset The offset.
+ * @param length The length.
+ *
+ * @return An avi_error.
+ */
+
+inline avi_file::error avi_stream::set_chunk_info(std::uint32_t index, std::uint64_t offset, std::uint32_t length)
+{
+ /* if we need to allocate more, allocate more */
+ if (index >= m_chunks.capacity())
+ {
+ try { m_chunks.reserve((std::max<std::size_t>)(index, m_chunks.capacity() + 1000)); }
+ catch (...) { return avi_file::error::NO_MEMORY; }
+ }
+
+ /* update the number of chunks */
+ m_chunks.resize((std::max<std::size_t>)(m_chunks.size(), index + 1));
+
+ /* set the data */
+ m_chunks[index].offset = offset;
+ m_chunks[index].length = length;
+
+ return avi_file::error::NONE;
+}
+
+
+inline avi_file::error avi_stream::set_strh_data(std::uint8_t const *data, std::uint32_t size)
+{
+ m_type = fetch_32bits(&data[0]);
+ m_scale = fetch_32bits(&data[20]);
+ m_rate = fetch_32bits(&data[24]);
+ m_samples = fetch_32bits(&data[32]);
+ return avi_file::error::NONE;
+}
+
+
+inline avi_file::error avi_stream::set_strf_data(std::uint8_t const *data, std::uint32_t size)
+{
+ /* audio and video streams have differing headers */
+ if (m_type == STREAMTYPE_VIDS)
+ {
+ m_width = fetch_32bits(&data[4]);
+ m_height = fetch_32bits(&data[8]);
+ m_depth = fetch_16bits(&data[14]);
+ m_format = fetch_32bits(&data[16]);
+
+ /* extra extraction for HuffYUV data */
+ if ((m_format == FORMAT_HFYU) && (size >= 56))
+ {
+ avi_file::error const avierr = huffyuv_extract_tables(data, size);
+ if (avierr != avi_file::error::NONE)
+ return avierr;
+ }
+ }
+ else if (m_type == STREAMTYPE_AUDS)
+ {
+ m_channels = fetch_16bits(&data[2]);
+ m_samplebits = fetch_16bits(&data[14]);
+ m_samplerate = fetch_32bits(&data[4]);
+ }
+ return avi_file::error::NONE;
+}
+
+
/*-------------------------------------------------
get_video_stream - return a pointer to the
video stream
-------------------------------------------------*/
/**
- * @fn static inline avi_stream *get_video_stream(avi_file *file)
+ * @fn static inline avi_stream *get_video_stream()
*
* @brief Gets video stream.
*
- * @param [in,out] file If non-null, the file.
- *
* @return null if it fails, else the video stream.
*/
-static inline avi_stream *get_video_stream(avi_file *file)
+inline avi_stream *avi_file_impl::get_video_stream()
{
- int streamnum;
-
- /* find the video stream */
- for (streamnum = 0; streamnum < file->streams; streamnum++)
- if (file->stream[streamnum].type == STREAMTYPE_VIDS)
- return &file->stream[streamnum];
+ for (int streamnum = 0; streamnum < m_streams.size(); streamnum++)
+ if (m_streams[streamnum].type() == STREAMTYPE_VIDS)
+ return &m_streams[streamnum];
return nullptr;
}
@@ -647,21 +824,18 @@ static inline avi_stream *get_video_stream(avi_file *file)
* @return null if it fails, else the audio stream.
*/
-static inline avi_stream *get_audio_stream(avi_file *file, int channel, int *offset)
+inline avi_stream *avi_file_impl::get_audio_stream(int channel, int &offset)
{
- int streamnum;
-
/* find the audios stream */
- for (streamnum = 0; streamnum < file->streams; streamnum++)
- if (file->stream[streamnum].type == STREAMTYPE_AUDS)
+ for (int streamnum = 0; streamnum < m_streams.size(); streamnum++)
+ if (m_streams[streamnum].type() == STREAMTYPE_AUDS)
{
- if (channel < file->stream[streamnum].channels)
+ if (channel < m_streams[streamnum].channels())
{
- if (offset != nullptr)
- *offset = channel;
- return &file->stream[streamnum];
+ offset = channel;
+ return &m_streams[streamnum];
}
- channel -= file->stream[streamnum].channels;
+ channel -= m_streams[streamnum].channels();
}
return nullptr;
@@ -669,58 +843,12 @@ static inline avi_stream *get_audio_stream(avi_file *file, int channel, int *off
/*-------------------------------------------------
- set_stream_chunk_info - set the chunk info
- for a given chunk within a stream
--------------------------------------------------*/
-
-/**
- * @fn static inline avi_error set_stream_chunk_info(avi_stream *stream, UINT32 index, UINT64 offset, UINT32 length)
- *
- * @brief Sets stream chunk information.
- *
- * @param [in,out] stream If non-null, the stream.
- * @param index Zero-based index of the.
- * @param offset The offset.
- * @param length The length.
- *
- * @return An avi_error.
- */
-
-static inline avi_error set_stream_chunk_info(avi_stream *stream, UINT32 index, UINT64 offset, UINT32 length)
-{
- /* if we need to allocate more, allocate more */
- if (index >= stream->chunksalloc)
- {
- UINT32 newcount = MAX(index, stream->chunksalloc + 1000);
- avi_chunk_list *newchunks = (avi_chunk_list *)malloc(newcount * sizeof(stream->chunk[0]));
- if (newchunks == nullptr)
- return AVIERR_NO_MEMORY;
- if (stream->chunk != nullptr)
- {
- memcpy(newchunks, stream->chunk, stream->chunksalloc * sizeof(stream->chunk[0]));
- free(stream->chunk);
- }
- stream->chunk = newchunks;
- stream->chunksalloc = newcount;
- }
-
- /* set the data */
- stream->chunk[index].offset = offset;
- stream->chunk[index].length = length;
-
- /* update the number of chunks */
- stream->chunks = MAX(stream->chunks, index + 1);
- return AVIERR_NONE;
-}
-
-
-/*-------------------------------------------------
compute_idx1_size - compute the size of the
idx1 chunk
-------------------------------------------------*/
/**
- * @fn static inline UINT32 compute_idx1_size(avi_file *file)
+ * @fn static inline std::uint32_t compute_idx1_size(avi_file *file)
*
* @brief Calculates the index 1 size.
*
@@ -729,14 +857,13 @@ static inline avi_error set_stream_chunk_info(avi_stream *stream, UINT32 index,
* @return The calculated index 1 size.
*/
-static inline UINT32 compute_idx1_size(avi_file *file)
+inline std::uint32_t avi_file_impl::compute_idx1_size() const
{
int chunks = 0;
- int strnum;
/* count chunks in streams */
- for (strnum = 0; strnum < file->streams; strnum++)
- chunks += file->stream[strnum].chunks;
+ for (int strnum = 0; strnum < m_streams.size(); strnum++)
+ chunks += m_streams[strnum].chunks();
return chunks * 16 + 8;
}
@@ -748,7 +875,7 @@ static inline UINT32 compute_idx1_size(avi_file *file)
-------------------------------------------------*/
/**
- * @fn static inline UINT32 get_chunkid_for_stream(avi_file *file, avi_stream *stream)
+ * @fn static inline std::uint32_t get_chunkid_for_stream(avi_file *file, avi_stream *stream)
*
* @brief Gets chunkid for stream.
*
@@ -758,14 +885,14 @@ static inline UINT32 compute_idx1_size(avi_file *file)
* @return The chunkid for stream.
*/
-static inline UINT32 get_chunkid_for_stream(avi_file *file, avi_stream *stream)
+inline std::uint32_t avi_file_impl::get_chunkid_for_stream(const avi_stream *stream) const
{
- UINT32 chunkid;
+ std::uint32_t chunkid;
- chunkid = AVI_FOURCC('0' + (stream - file->stream) / 10, '0' + (stream - file->stream) % 10, 0, 0);
- if (stream->type == STREAMTYPE_VIDS)
- chunkid |= (stream->format == 0) ? CHUNKTYPE_XXDB : CHUNKTYPE_XXDC;
- else if (stream->type == STREAMTYPE_AUDS)
+ chunkid = AVI_FOURCC('0' + (stream - &m_streams[0]) / 10, '0' + (stream - &m_streams[0]) % 10, 0, 0);
+ if (stream->type() == STREAMTYPE_VIDS)
+ chunkid |= (stream->format() == 0) ? CHUNKTYPE_XXDB : CHUNKTYPE_XXDC;
+ else if (stream->type() == STREAMTYPE_AUDS)
chunkid |= CHUNKTYPE_XXWB;
return chunkid;
@@ -778,19 +905,19 @@ static inline UINT32 get_chunkid_for_stream(avi_file *file, avi_stream *stream)
-------------------------------------------------*/
/**
- * @fn static inline UINT32 framenum_to_samplenum(avi_file *file, UINT32 framenum)
+ * @fn static inline std::uint32_t framenum_to_samplenum(avi_file *file, std::uint32_t framenum)
*
* @brief Framenum to samplenum.
*
* @param [in,out] file If non-null, the file.
* @param framenum The framenum.
*
- * @return An UINT32.
+ * @return An std::uint32_t.
*/
-static inline UINT32 framenum_to_samplenum(avi_file *file, UINT32 framenum)
+inline std::uint32_t avi_file_impl::framenum_to_samplenum(std::uint32_t framenum) const
{
- return ((UINT64)file->info.audio_samplerate * (UINT64)framenum * (UINT64)file->info.video_sampletime + file->info.video_timescale - 1) / (UINT64)file->info.video_timescale;
+ return (std::uint64_t(m_info.audio_samplerate) * std::uint64_t(framenum) * std::uint64_t(m_info.video_sampletime) + m_info.video_timescale - 1) / std::uint64_t(m_info.video_timescale);
}
@@ -801,7 +928,7 @@ static inline UINT32 framenum_to_samplenum(avi_file *file, UINT32 framenum)
-------------------------------------------------*/
/**
- * @fn static inline avi_error expand_tempbuffer(avi_file *file, UINT32 length)
+ * @fn static inline avi_error expand_tempbuffer(avi_file *file, std::uint32_t length)
*
* @brief Expand tempbuffer.
*
@@ -811,207 +938,532 @@ static inline UINT32 framenum_to_samplenum(avi_file *file, UINT32 framenum)
* @return An avi_error.
*/
-static inline avi_error expand_tempbuffer(avi_file *file, UINT32 length)
+inline avi_file::error avi_file_impl::expand_tempbuffer(std::uint32_t length)
{
/* expand the tempbuffer to hold the data if necessary */
- if (length > file->tempbuffersize)
+ if (length > m_tempbuffer.size())
{
- file->tempbuffersize = 2 * length;
- UINT8 *newbuffer = (UINT8 *)malloc(file->tempbuffersize);
- if (newbuffer == nullptr)
- return AVIERR_NO_MEMORY;
- if (file->tempbuffer != nullptr)
- free(file->tempbuffer);
- file->tempbuffer = newbuffer;
+ try { m_tempbuffer.resize(2 * length); }
+ catch (...) { return error::NO_MEMORY; }
}
- return AVIERR_NONE;
+ return error::NONE;
}
+/*-------------------------------------------------
+ rgb32_compress_to_rgb - "compress" an RGB32
+ bitmap to an RGB encoded frame
+-------------------------------------------------*/
+
+/**
+ * @fn static avi_error rgb32_compress_to_rgb(avi_stream *stream, const bitmap_rgb32 &bitmap, std::uint8_t *data, std::uint32_t numbytes)
+ *
+ * @brief RGB 32 compress to RGB.
+ *
+ * @param [in,out] stream If non-null, the stream.
+ * @param bitmap The bitmap.
+ * @param [in,out] data If non-null, the data.
+ * @param numbytes The numbytes.
+ *
+ * @return An avi_error.
+ */
+
+avi_file::error avi_stream::rgb32_compress_to_rgb(const bitmap_rgb32 &bitmap, std::uint8_t *data, std::uint32_t numbytes) const
+{
+ int const height = (std::min<int>)(m_height, bitmap.height());
+ int const width = (std::min<int>)(m_width, bitmap.width());
+ std::uint8_t *const dataend = data + numbytes;
+ int x, y;
+
+ /* compressed video */
+ for (y = 0; y < height; y++)
+ {
+ const std::uint32_t *source = &bitmap.pix32(y);
+ std::uint8_t *dest = data + (m_height - 1 - y) * m_width * 3;
+
+ for (x = 0; x < width && dest < dataend; x++)
+ {
+ rgb_t pix = *source++;
+ *dest++ = pix.b();
+ *dest++ = pix.g();
+ *dest++ = pix.r();
+ }
+
+ /* fill in any blank space on the right */
+ for ( ; x < m_width && dest < dataend; x++)
+ {
+ *dest++ = 0;
+ *dest++ = 0;
+ *dest++ = 0;
+ }
+ }
+
+ /* fill in any blank space on the bottom */
+ for ( ; y < m_height; y++)
+ {
+ std::uint8_t *dest = data + (m_height - 1 - y) * m_width * 3;
+ for (x = 0; x < m_width && dest < dataend; x++)
+ {
+ *dest++ = 0;
+ *dest++ = 0;
+ *dest++ = 0;
+ }
+ }
+
+ return avi_file::error::NONE;
+}
-/***************************************************************************
- IMPLEMENTATION
-***************************************************************************/
/*-------------------------------------------------
- avi_open - open an AVI movie file for read
+ yuv_decompress_to_yuy16 - decompress a YUV
+ encoded frame to a YUY16 bitmap
-------------------------------------------------*/
/**
- * @fn avi_error avi_open(const char *filename, avi_file **file)
+ * @fn static avi_error yuv_decompress_to_yuy16(avi_stream *stream, const std::uint8_t *data, std::uint32_t numbytes, bitmap_yuy16 &bitmap)
*
- * @brief Queries if a given avi open.
+ * @brief Yuv decompress to yuy 16.
*
- * @param filename Filename of the file.
- * @param [in,out] file If non-null, the file.
+ * @param [in,out] stream If non-null, the stream.
+ * @param data The data.
+ * @param numbytes The numbytes.
+ * @param [in,out] bitmap The bitmap.
*
* @return An avi_error.
*/
-avi_error avi_open(const char *filename, avi_file **file)
+avi_file::error avi_stream::yuv_decompress_to_yuy16(const std::uint8_t *data, std::uint32_t numbytes, bitmap_yuy16 &bitmap) const
{
- avi_file *newfile = nullptr;
- file_error filerr;
- avi_error avierr;
- UINT64 length;
-
- /* allocate the file */
- newfile = (avi_file *)malloc(sizeof(*newfile));
- if (newfile == nullptr)
- return AVIERR_NO_MEMORY;
- memset(newfile, 0, sizeof(*newfile));
- newfile->type = FILETYPE_READ;
+ std::uint16_t const *const dataend = reinterpret_cast<const std::uint16_t *>(data + numbytes);
+ int x, y;
- /* open the file */
- filerr = osd_open(filename, OPEN_FLAG_READ, &newfile->file, &length);
- if (filerr != FILERR_NONE)
+ /* compressed video */
+ for (y = 0; y < m_height; y++)
{
- avierr = AVIERR_CANT_OPEN_FILE;
- goto error;
+ const std::uint16_t *source = reinterpret_cast<const std::uint16_t *>(data) + y * m_width;
+ std::uint16_t *dest = &bitmap.pix16(y);
+
+ /* switch off the compression */
+ switch (m_format)
+ {
+ case FORMAT_UYVY:
+ for (x = 0; x < m_width && source < dataend; x++)
+ *dest++ = *source++;
+ break;
+
+ case FORMAT_VYUY:
+ case FORMAT_YUY2:
+ for (x = 0; x < m_width && source < dataend; x++)
+ {
+ std::uint16_t pix = *source++;
+ *dest++ = (pix >> 8) | (pix << 8);
+ }
+ break;
+ }
}
- /* make a root atom */
- newfile->rootchunk.offset = 0;
- newfile->rootchunk.size = length;
- newfile->rootchunk.type = 0;
- newfile->rootchunk.listtype = 0;
+ return avi_file::error::NONE;
+}
- /* parse the data */
- avierr = read_movie_data(newfile);
- if (avierr != AVIERR_NONE)
- goto error;
- *file = newfile;
- return AVIERR_NONE;
+/*-------------------------------------------------
+ yuy16_compress_to_yuy - "compress" a YUY16
+ bitmap to a YUV encoded frame
+-------------------------------------------------*/
-error:
- /* clean up after an error */
- if (newfile != nullptr)
+/**
+ * @fn static avi_error yuy16_compress_to_yuy(avi_stream *stream, const bitmap_yuy16 &bitmap, std::uint8_t *data, std::uint32_t numbytes)
+ *
+ * @brief Yuy 16 compress to yuy.
+ *
+ * @param [in,out] stream If non-null, the stream.
+ * @param bitmap The bitmap.
+ * @param [in,out] data If non-null, the data.
+ * @param numbytes The numbytes.
+ *
+ * @return An avi_error.
+ */
+
+avi_file::error avi_stream::yuy16_compress_to_yuy(const bitmap_yuy16 &bitmap, std::uint8_t *data, std::uint32_t numbytes) const
+{
+ std::uint16_t *const dataend = reinterpret_cast<std::uint16_t *>(data + numbytes);
+ int x, y;
+
+ /* compressed video */
+ for (y = 0; y < m_height; y++)
{
- if (newfile->file != nullptr)
- osd_close(newfile->file);
- free(newfile);
+ const std::uint16_t *source = &bitmap.pix16(y);
+ std::uint16_t *dest = reinterpret_cast<std::uint16_t *>(data) + y * m_width;
+
+ /* switch off the compression */
+ switch (m_format)
+ {
+ case FORMAT_UYVY:
+ for (x = 0; x < m_width && dest < dataend; x++)
+ *dest++ = *source++;
+ break;
+
+ case FORMAT_VYUY:
+ case FORMAT_YUY2:
+ for (x = 0; x < m_width && dest < dataend; x++)
+ {
+ std::uint16_t pix = *source++;
+ *dest++ = (pix >> 8) | (pix << 8);
+ }
+ break;
+ }
}
- return avierr;
+
+ return avi_file::error::NONE;
}
/*-------------------------------------------------
- avi_create - create a new AVI movie file
+ huffyuv_extract_tables - extract HuffYUV
+ tables
-------------------------------------------------*/
/**
- * @fn avi_error avi_create(const char *filename, const avi_movie_info *info, avi_file **file)
+ * @fn static avi_error huffyuv_extract_tables(avi_stream *stream, const std::uint8_t *chunkdata, std::uint32_t size)
*
- * @brief Avi create.
+ * @brief Huffyuv extract tables.
*
- * @param filename Filename of the file.
- * @param info The information.
- * @param [in,out] file If non-null, the file.
+ * @param [in,out] stream If non-null, the stream.
+ * @param chunkdata The chunkdata.
+ * @param size The size.
*
* @return An avi_error.
*/
-avi_error avi_create(const char *filename, const avi_movie_info *info, avi_file **file)
+avi_file::error avi_stream::huffyuv_extract_tables(const std::uint8_t *chunkdata, std::uint32_t size)
{
- avi_file *newfile = nullptr;
- file_error filerr;
- avi_stream *stream;
- avi_error avierr;
- UINT64 length;
+ const std::uint8_t *const chunkend = chunkdata + size;
- /* validate video info */
- if ((info->video_format != 0 && info->video_format != FORMAT_UYVY && info->video_format != FORMAT_VYUY && info->video_format != FORMAT_YUY2) ||
- info->video_width == 0 ||
- info->video_height == 0 ||
- info->video_depth == 0 || info->video_depth % 8 != 0)
- return AVIERR_UNSUPPORTED_VIDEO_FORMAT;
+ /* allocate memory for the data */
+ std::unique_ptr<huffyuv_data> huffyuv;
+ try { huffyuv = std::make_unique<huffyuv_data>(); }
+ catch (...) { return avi_file::error::NO_MEMORY; }
- /* validate audio info */
- if (info->audio_format != 0 ||
- info->audio_channels > MAX_SOUND_CHANNELS ||
- info->audio_samplebits != 16)
- return AVIERR_UNSUPPORTED_AUDIO_FORMAT;
+ /* extract predictor information */
+ if (&chunkdata[40] >= chunkend)
+ return avi_file::error::INVALID_DATA;
+ huffyuv->predictor = chunkdata[40];
- /* allocate the file */
- newfile = (avi_file *)malloc(sizeof(*newfile));
- if (newfile == nullptr)
- return AVIERR_NO_MEMORY;
- memset(newfile, 0, sizeof(*newfile));
- newfile->type = FILETYPE_CREATE;
+ /* make sure it's the left predictor */
+ if ((huffyuv->predictor & ~HUFFYUV_PREDICT_DECORR) != HUFFYUV_PREDICT_LEFT)
+ return avi_file::error::UNSUPPORTED_VIDEO_FORMAT;
- /* open the file */
- filerr = osd_open(filename, OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS, &newfile->file, &length);
- if (filerr != FILERR_NONE)
+ /* make sure it's 16bpp YUV data */
+ if (chunkdata[41] != 16)
+ return avi_file::error::UNSUPPORTED_VIDEO_FORMAT;
+ chunkdata += 44;
+
+ /* loop over tables */
+ for (int tabnum = 0; tabnum < 3; tabnum++)
{
- avierr = AVIERR_CANT_OPEN_FILE;
- goto error;
+ huffyuv_table &table = huffyuv->table[tabnum];
+ std::uint32_t curbits, bitadd;
+ std::uint16_t bitsat16 = 0;
+ int offset = 0, bits;
+
+ /* loop until we populate the whole table */
+ while (offset < 256)
+ {
+ int data, shift, count, i;
+
+ /* extract the next run */
+ if (chunkdata >= chunkend)
+ return avi_file::error::INVALID_DATA;
+ data = *chunkdata++;
+ shift = data & 0x1f;
+ count = data >> 5;
+
+ /* zero count means next whole byte is a count */
+ if (count == 0)
+ {
+ if (chunkdata >= chunkend)
+ return avi_file::error::INVALID_DATA;
+ count = *chunkdata++;
+ }
+ for (i = 0; i < count; i++)
+ table.shift[offset++] = shift;
+ }
+
+ /* now determine bit patterns and masks */
+ curbits = 0;
+ for (bits = 31; bits >= 0; bits--)
+ {
+ bitadd = 1 << (32 - bits);
+
+ /* make sure we've cleared out all the bits below */
+ if ((curbits & (bitadd - 1)) != 0)
+ return avi_file::error::INVALID_DATA;
+
+ /* find all entries with this shift count and assign them */
+ for (offset = 0; offset < 256; offset++)
+ if (table.shift[offset] == bits)
+ {
+ table.bits[offset] = curbits;
+ table.mask[offset] = ~(bitadd - 1);
+ curbits += bitadd;
+ }
+
+ /* remember the bit pattern when we complete all the 17-bit codes */
+ if (bits == 17)
+ bitsat16 = curbits >> 16;
+ }
+
+ /* allocate the number of extra lookup tables we need */
+ if (bitsat16 > 0)
+ {
+ try { table.extralookup.resize(bitsat16 * 65536); }
+ catch (...) { return avi_file::error::NO_MEMORY; }
+ for (offset = 0; offset < bitsat16; offset++)
+ table.baselookup[offset] = (offset << 8) | 0;
+ }
+
+ /* then create lookup tables */
+ for (offset = 0; offset < 256; offset++)
+ if (table.shift[offset] > 16)
+ {
+ std::uint16_t *tablebase = &table.extralookup[(table.bits[offset] >> 16) * 65536];
+ std::uint32_t start = table.bits[offset] & 0xffff;
+ std::uint32_t end = start + ((1 << (32 - table.shift[offset])) - 1);
+ while (start <= end)
+ tablebase[start++] = (offset << 8) | (table.shift[offset] - 16);
+ }
+ else if (table.shift[offset] > 0)
+ {
+ std::uint32_t start = table.bits[offset] >> 16;
+ std::uint32_t end = start + ((1 << (16 - table.shift[offset])) - 1);
+ while (start <= end)
+ table.baselookup[start++] = (offset << 8) | table.shift[offset];
+ }
}
- /* copy the movie info */
- newfile->info = *info;
- newfile->info.video_numsamples = 0;
- newfile->info.audio_numsamples = 0;
+ m_huffyuv = std::move(huffyuv);
+ return avi_file::error::NONE;
+}
+
- /* allocate two streams */
- newfile->stream = (avi_stream *)malloc(2 * sizeof(newfile->stream[0]));
- if (newfile->stream == nullptr)
+/*-------------------------------------------------
+ huffyuv_decompress_to_yuy16 - decompress a
+ HuffYUV-encoded frame to a YUY16 bitmap
+-------------------------------------------------*/
+
+/**
+ * @fn static avi_error huffyuv_decompress_to_yuy16(avi_stream *stream, const std::uint8_t *data, std::uint32_t numbytes, bitmap_yuy16 &bitmap)
+ *
+ * @brief Huffyuv decompress to yuy 16.
+ *
+ * @param [in,out] stream If non-null, the stream.
+ * @param data The data.
+ * @param numbytes The numbytes.
+ * @param [in,out] bitmap The bitmap.
+ *
+ * @return An avi_error.
+ */
+
+avi_file::error avi_stream::huffyuv_decompress_to_yuy16(const std::uint8_t *data, std::uint32_t numbytes, bitmap_yuy16 &bitmap) const
+{
+ int prevlines = (m_height > 288) ? 2 : 1;
+ std::uint8_t lastprevy = 0, lastprevcb = 0, lastprevcr = 0;
+ std::uint8_t lasty = 0, lastcb = 0, lastcr = 0;
+ std::uint8_t bitsinbuffer = 0;
+ std::uint32_t bitbuffer = 0;
+ std::uint32_t dataoffs = 0;
+ int x, y;
+
+ /* compressed video */
+ for (y = 0; y < m_height; y++)
{
- avierr = AVIERR_NO_MEMORY;
- goto error;
+ std::uint16_t *dest = &bitmap.pix16(y);
+
+ /* handle the first four bytes independently */
+ x = 0;
+ if (y == 0)
+ {
+ /* first DWORD is stored as YUY2 */
+ lasty = data[dataoffs++];
+ lastcb = data[dataoffs++];
+ *dest++ = (lasty << 8) | lastcb;
+ lasty = data[dataoffs++];
+ lastcr = data[dataoffs++];
+ *dest++ = (lasty << 8) | lastcr;
+ x = 2;
+ }
+
+ /* loop over pixels */
+ for ( ; x < m_width; x++)
+ {
+ huffyuv_table const &ytable = m_huffyuv->table[0];
+ huffyuv_table const &ctable = m_huffyuv->table[1 + (x & 1)];
+ std::uint16_t huffdata;
+ int shift;
+
+ /* fill up the buffer; they store little-endian DWORDs, so we XOR with 3 */
+ while (bitsinbuffer <= 24 && dataoffs < numbytes)
+ {
+ bitbuffer |= data[dataoffs++ ^ 3] << (24 - bitsinbuffer);
+ bitsinbuffer += 8;
+ }
+
+ /* look up the Y component */
+ huffdata = ytable.baselookup[bitbuffer >> 16];
+ shift = huffdata & 0xff;
+ if (shift == 0)
+ {
+ bitsinbuffer -= 16;
+ bitbuffer <<= 16;
+
+ /* fill up the buffer; they store little-endian DWORDs, so we XOR with 3 */
+ while (bitsinbuffer <= 24 && dataoffs < numbytes)
+ {
+ bitbuffer |= data[dataoffs++ ^ 3] << (24 - bitsinbuffer);
+ bitsinbuffer += 8;
+ }
+
+ huffdata = ytable.extralookup[(huffdata >> 8) * 65536 + (bitbuffer >> 16)];
+ shift = huffdata & 0xff;
+ }
+ bitsinbuffer -= shift;
+ bitbuffer <<= shift;
+ std::uint16_t const pixel = huffdata & 0xff00;
+
+ /* fill up the buffer; they store little-endian DWORDs, so we XOR with 3 */
+ while (bitsinbuffer <= 24 && dataoffs < numbytes)
+ {
+ bitbuffer |= data[dataoffs++ ^ 3] << (24 - bitsinbuffer);
+ bitsinbuffer += 8;
+ }
+
+ /* look up the Cb/Cr component */
+ huffdata = ctable.baselookup[bitbuffer >> 16];
+ shift = huffdata & 0xff;
+ if (shift == 0)
+ {
+ bitsinbuffer -= 16;
+ bitbuffer <<= 16;
+
+ /* fill up the buffer; they store little-endian DWORDs, so we XOR with 3 */
+ while (bitsinbuffer <= 24 && dataoffs < numbytes)
+ {
+ bitbuffer |= data[dataoffs++ ^ 3] << (24 - bitsinbuffer);
+ bitsinbuffer += 8;
+ }
+
+ huffdata = ctable.extralookup[(huffdata >> 8) * 65536 + (bitbuffer >> 16)];
+ shift = huffdata & 0xff;
+ }
+ bitsinbuffer -= shift;
+ bitbuffer <<= shift;
+ *dest++ = pixel | (huffdata >> 8);
+ }
}
- memset(newfile->stream, 0, 2 * sizeof(newfile->stream[0]));
-
- /* initialize the video track */
- stream = &newfile->stream[newfile->streams++];
- stream->type = STREAMTYPE_VIDS;
- stream->format = newfile->info.video_format;
- stream->rate = newfile->info.video_timescale;
- stream->scale = newfile->info.video_sampletime;
- stream->width = newfile->info.video_width;
- stream->height = newfile->info.video_height;
- stream->depth = newfile->info.video_depth;
-
- /* initialize the audio track */
- if (newfile->info.audio_channels > 0)
+
+ /* apply deltas */
+ lastprevy = lastprevcb = lastprevcr = 0;
+ for (y = 0; y < m_height; y++)
{
- stream = &newfile->stream[newfile->streams++];
- stream->type = STREAMTYPE_AUDS;
- stream->format = newfile->info.audio_format;
- stream->rate = newfile->info.audio_timescale;
- stream->scale = newfile->info.audio_sampletime;
- stream->channels = newfile->info.audio_channels;
- stream->samplebits = newfile->info.audio_samplebits;
- stream->samplerate = newfile->info.audio_samplerate;
-
- /* initialize the sound buffering */
- avierr = soundbuf_initialize(newfile);
- if (avierr != AVIERR_NONE)
- goto error;
- }
+ std::uint16_t *prevrow = &bitmap.pix16(y - prevlines);
+ std::uint16_t *dest = &bitmap.pix16(y);
- /* write the initial headers */
- avierr = write_initial_headers(newfile);
- if (avierr != AVIERR_NONE)
- goto error;
+ /* handle the first four bytes independently */
+ x = 0;
+ if (y == 0)
+ {
+ /* lasty, lastcr, lastcb are set up previously */
+ x = 2;
+ }
- *file = newfile;
- return AVIERR_NONE;
+ /* left predict or gradient predict */
+ if ((m_huffyuv->predictor & ~HUFFYUV_PREDICT_DECORR) == HUFFYUV_PREDICT_LEFT ||
+ ((m_huffyuv->predictor & ~HUFFYUV_PREDICT_DECORR) == HUFFYUV_PREDICT_GRADIENT))
+ {
+ /* first do left deltas */
+ for ( ; x < m_width; x += 2)
+ {
+ std::uint16_t pixel0 = dest[x + 0];
+ std::uint16_t pixel1 = dest[x + 1];
-error:
- /* clean up after an error */
- if (newfile != nullptr)
- {
- if (newfile->stream != nullptr)
- free(newfile->stream);
- if (newfile->file != nullptr)
+ lasty += pixel0 >> 8;
+ lastcb += pixel0;
+ dest[x + 0] = (lasty << 8) | lastcb;
+
+ lasty += pixel1 >> 8;
+ lastcr += pixel1;
+ dest[x + 1] = (lasty << 8) | lastcr;
+ }
+
+ /* for gradient, we then add in the previous row */
+ if ((m_huffyuv->predictor & ~HUFFYUV_PREDICT_DECORR) == HUFFYUV_PREDICT_GRADIENT && y >= prevlines)
+ for (x = 0; x < m_width; x++)
+ {
+ std::uint16_t curpix = dest[x];
+ std::uint16_t prevpix = prevrow[x];
+ std::uint8_t ysum = (curpix >> 8) + (prevpix >> 8);
+ std::uint8_t csum = curpix + prevpix;
+ dest[x] = (ysum << 8) | csum;
+ }
+ }
+
+ /* median predict on rows > 0 */
+ else if ((m_huffyuv->predictor & ~HUFFYUV_PREDICT_DECORR) == HUFFYUV_PREDICT_MEDIAN && y >= prevlines)
{
- osd_close(newfile->file);
- osd_rmfile(filename);
+ for ( ; x < m_width; x += 2)
+ {
+ std::uint16_t prevpixel0 = prevrow[x + 0];
+ std::uint16_t prevpixel1 = prevrow[x + 1];
+ std::uint16_t pixel0 = dest[x + 0];
+ std::uint16_t pixel1 = dest[x + 1];
+ std::uint8_t a, b, c;
+
+ /* compute previous, above, and (prev + above - above-left) */
+ a = lasty;
+ b = prevpixel0 >> 8;
+ c = lastprevy;
+ lastprevy = b;
+ if (a > b) { std::uint8_t tmp = a; a = b; b = tmp; }
+ if (a > c) { std::uint8_t tmp = a; a = c; c = tmp; }
+ if (b > c) { std::uint8_t tmp = b; b = c; c = tmp; }
+ lasty = (pixel0 >> 8) + b;
+
+ /* compute previous, above, and (prev + above - above-left) */
+ a = lastcb;
+ b = prevpixel0 & 0xff;
+ c = lastprevcb;
+ lastprevcb = b;
+ if (a > b) { std::uint8_t tmp = a; a = b; b = tmp; }
+ if (a > c) { std::uint8_t tmp = a; a = c; c = tmp; }
+ if (b > c) { std::uint8_t tmp = b; b = c; c = tmp; }
+ lastcb = (pixel0 & 0xff) + b;
+ dest[x + 0] = (lasty << 8) | lastcb;
+
+ /* compute previous, above, and (prev + above - above-left) */
+ a = lasty;
+ b = prevpixel1 >> 8;
+ c = lastprevy;
+ lastprevy = b;
+ if (a > b) { std::uint8_t tmp = a; a = b; b = tmp; }
+ if (a > c) { std::uint8_t tmp = a; a = c; c = tmp; }
+ if (b > c) { std::uint8_t tmp = b; b = c; c = tmp; }
+ lasty = (pixel1 >> 8) + b;
+
+ /* compute previous, above, and (prev + above - above-left) */
+ a = lastcr;
+ b = prevpixel1 & 0xff;
+ c = lastprevcr;
+ lastprevcr = b;
+ if (a > b) { std::uint8_t tmp = a; a = b; b = tmp; }
+ if (a > c) { std::uint8_t tmp = a; a = c; c = tmp; }
+ if (b > c) { std::uint8_t tmp = b; b = c; c = tmp; }
+ lastcr = (pixel1 & 0xff) + b;
+ dest[x + 1] = (lasty << 8) | lastcr;
+ }
}
- free(newfile);
}
- return avierr;
+
+ return avi_file::error::NONE;
}
@@ -1029,73 +1481,46 @@ error:
* @return An avi_error.
*/
-avi_error avi_close(avi_file *file)
+avi_file_impl::~avi_file_impl()
{
- avi_error avierr = AVIERR_NONE;
- int strnum;
+ error avierr = error::NONE;
/* if we're creating a new file, finalize it by writing out the non-media chunks */
- if (file->type == FILETYPE_CREATE)
+ if (m_type == FILETYPE_CREATE)
{
/* flush any pending sound data */
- avierr = soundbuf_flush(file, FALSE);
+ avierr = soundbuf_flush(false);
/* close the movi chunk */
- if (avierr == AVIERR_NONE)
- avierr = chunk_close(file);
+ if (avierr == error::NONE)
+ avierr = chunk_close();
/* if this is the first RIFF chunk, write an idx1 */
- if (avierr == AVIERR_NONE && file->riffbase == 0)
- avierr = write_idx1_chunk(file);
+ if (avierr == error::NONE && m_riffbase == 0)
+ avierr = write_idx1_chunk();
/* update the strh and indx chunks for each stream */
- for (strnum = 0; strnum < file->streams; strnum++)
+ for (int strnum = 0; strnum < m_streams.size(); strnum++)
{
- if (avierr == AVIERR_NONE)
- avierr = write_strh_chunk(file, &file->stream[strnum], FALSE);
- if (avierr == AVIERR_NONE)
- avierr = write_indx_chunk(file, &file->stream[strnum], FALSE);
+ if (avierr == error::NONE)
+ avierr = write_strh_chunk(m_streams[strnum], false);
+ if (avierr == error::NONE)
+ avierr = write_indx_chunk(m_streams[strnum], false);
}
/* update the avih chunk */
- if (avierr == AVIERR_NONE)
- avierr = write_avih_chunk(file, FALSE);
+ if (avierr == error::NONE)
+ avierr = write_avih_chunk(false);
/* close the RIFF chunk */
- if (avierr == AVIERR_NONE)
- avierr = chunk_close(file);
+ if (avierr == error::NONE)
+ avierr = chunk_close();
}
/* close the file */
- osd_close(file->file);
-
- /* free the stream-specific data */
- for (strnum = 0; strnum < file->streams; strnum++)
- {
- avi_stream *stream = &file->stream[strnum];
- if (stream->huffyuv != nullptr)
- {
- huffyuv_data *huffyuv = stream->huffyuv;
- int table;
+ m_file.reset();
- for (table = 0; table < ARRAY_LENGTH(huffyuv->table); table++)
- if (huffyuv->table[table].extralookup != nullptr)
- free(huffyuv->table[table].extralookup);
- free(huffyuv);
- }
- if (stream->chunk != nullptr)
- free(stream->chunk);
- }
-
- /* free the file itself */
- if (file->soundbuf != nullptr)
- free(file->soundbuf);
- if (file->stream != nullptr)
- free(file->stream);
- if (file->tempbuffer != nullptr)
- free(file->tempbuffer);
- free(file);
- return avierr;
+ //return avierr;
}
@@ -1111,55 +1536,14 @@ avi_error avi_close(avi_file *file)
* @param [in,out] file If non-null, the file.
*/
-void avi_printf_chunks(avi_file *file)
-{
- printf_chunk_recursive(file, &file->rootchunk, 0);
-}
-
-
-/*-------------------------------------------------
- avi_error_string - get the error string for
- an avi_error
--------------------------------------------------*/
-
-/**
- * @fn const char *avi_error_string(avi_error err)
- *
- * @brief Avi error string.
- *
- * @param err The error.
- *
- * @return null if it fails, else a char*.
- */
-
-const char *avi_error_string(avi_error err)
+void avi_file_impl::printf_chunks()
{
- switch (err)
- {
- case AVIERR_NONE: return "success";
- case AVIERR_END: return "hit end of file";
- case AVIERR_INVALID_DATA: return "invalid data";
- case AVIERR_NO_MEMORY: return "out of memory";
- case AVIERR_READ_ERROR: return "read error";
- case AVIERR_WRITE_ERROR: return "write error";
- case AVIERR_STACK_TOO_DEEP: return "stack overflow";
- case AVIERR_UNSUPPORTED_FEATURE: return "unsupported feature";
- case AVIERR_CANT_OPEN_FILE: return "unable to open file";
- case AVIERR_INCOMPATIBLE_AUDIO_STREAMS: return "found incompatible audio streams";
- case AVIERR_INVALID_SAMPLERATE: return "found invalid sample rate";
- case AVIERR_INVALID_STREAM: return "invalid stream";
- case AVIERR_INVALID_FRAME: return "invalid frame index";
- case AVIERR_INVALID_BITMAP: return "invalid bitmap";
- case AVIERR_UNSUPPORTED_VIDEO_FORMAT: return "unsupported video format";
- case AVIERR_UNSUPPORTED_AUDIO_FORMAT: return "unsupported audio format";
- case AVIERR_EXCEEDED_SOUND_BUFFER: return "sound buffer overflow";
- default: return "undocumented error";
- }
+ printf_chunk_recursive(&m_rootchunk, 0);
}
/*-------------------------------------------------
- avi_get_movie_info - return a pointer to the
+ get_movie_info - return a pointer to the
movie info
-------------------------------------------------*/
@@ -1173,9 +1557,9 @@ const char *avi_error_string(avi_error err)
* @return null if it fails, else an avi_movie_info*.
*/
-const avi_movie_info *avi_get_movie_info(avi_file *file)
+avi_file::movie_info const &avi_file_impl::get_movie_info() const
{
- return &file->info;
+ return m_info;
}
@@ -1185,19 +1569,19 @@ const avi_movie_info *avi_get_movie_info(avi_file *file)
-------------------------------------------------*/
/**
- * @fn UINT32 avi_first_sample_in_frame(avi_file *file, UINT32 framenum)
+ * @fn std::uint32_t avi_first_sample_in_frame(avi_file *file, std::uint32_t framenum)
*
* @brief Avi first sample in frame.
*
* @param [in,out] file If non-null, the file.
* @param framenum The framenum.
*
- * @return An UINT32.
+ * @return An std::uint32_t.
*/
-UINT32 avi_first_sample_in_frame(avi_file *file, UINT32 framenum)
+std::uint32_t avi_file_impl::first_sample_in_frame(std::uint32_t framenum) const
{
- return framenum_to_samplenum(file, framenum);
+ return framenum_to_samplenum(framenum);
}
@@ -1208,7 +1592,7 @@ UINT32 avi_first_sample_in_frame(avi_file *file, UINT32 framenum)
-------------------------------------------------*/
/**
- * @fn avi_error avi_read_video_frame(avi_file *file, UINT32 framenum, bitmap_yuy16 &bitmap)
+ * @fn avi_error avi_read_video_frame(avi_file *file, std::uint32_t framenum, bitmap_yuy16 &bitmap)
*
* @brief Avi read video frame.
*
@@ -1219,54 +1603,51 @@ UINT32 avi_first_sample_in_frame(avi_file *file, UINT32 framenum)
* @return An avi_error.
*/
-avi_error avi_read_video_frame(avi_file *file, UINT32 framenum, bitmap_yuy16 &bitmap)
+avi_file::error avi_file_impl::read_video_frame(std::uint32_t framenum, bitmap_yuy16 &bitmap)
{
- avi_error avierr = AVIERR_NONE;
- UINT32 bytes_read, chunkid;
- file_error filerr;
- avi_stream *stream;
-
/* get the video stream */
- stream = get_video_stream(file);
- if (stream == nullptr)
- return AVIERR_INVALID_STREAM;
+ avi_stream *const stream = get_video_stream();
+ if (!stream)
+ return error::INVALID_STREAM;
/* validate our ability to handle the data */
- if (stream->format != FORMAT_UYVY && stream->format != FORMAT_VYUY && stream->format != FORMAT_YUY2 && stream->format != FORMAT_HFYU)
- return AVIERR_UNSUPPORTED_VIDEO_FORMAT;
+ if (stream->format() != FORMAT_UYVY && stream->format() != FORMAT_VYUY && stream->format() != FORMAT_YUY2 && stream->format() != FORMAT_HFYU)
+ return error::UNSUPPORTED_VIDEO_FORMAT;
/* assume one chunk == one frame */
- if (framenum >= stream->chunks)
- return AVIERR_INVALID_FRAME;
+ if (framenum >= stream->chunks())
+ return error::INVALID_FRAME;
/* we only support YUY-style bitmaps (16bpp) */
- if (bitmap.width() < stream->width || bitmap.height() < stream->height)
- return AVIERR_INVALID_BITMAP;
+ if (bitmap.width() < stream->width() || bitmap.height() < stream->height())
+ return error::INVALID_BITMAP;
/* expand the tempbuffer to hold the data if necessary */
- avierr = expand_tempbuffer(file, stream->chunk[framenum].length);
- if (avierr != AVIERR_NONE)
+ error avierr = error::NONE;
+ avierr = expand_tempbuffer(stream->chunk(framenum).length);
+ if (avierr != error::NONE)
return avierr;
/* read in the data */
- filerr = osd_read(file->file, file->tempbuffer, stream->chunk[framenum].offset, stream->chunk[framenum].length, &bytes_read);
- if (filerr != FILERR_NONE || bytes_read != stream->chunk[framenum].length)
- return AVIERR_READ_ERROR;
+ std::uint32_t bytes_read;
+ osd_file::error const filerr = m_file->read(&m_tempbuffer[0], stream->chunk(framenum).offset, stream->chunk(framenum).length, bytes_read);
+ if (filerr != osd_file::error::NONE || bytes_read != stream->chunk(framenum).length)
+ return error::READ_ERROR;
/* validate this is good data */
- chunkid = fetch_32bits(&file->tempbuffer[0]);
- if (chunkid == get_chunkid_for_stream(file, stream))
+ std::uint32_t const chunkid = fetch_32bits(&m_tempbuffer[0]);
+ if (chunkid == get_chunkid_for_stream(stream))
{
/* HuffYUV-compressed */
- if (stream->format == FORMAT_HFYU)
- avierr = huffyuv_decompress_to_yuy16(stream, file->tempbuffer + 8, stream->chunk[framenum].length - 8, bitmap);
+ if (stream->format() == FORMAT_HFYU)
+ avierr = stream->huffyuv_decompress_to_yuy16(&m_tempbuffer[8], stream->chunk(framenum).length - 8, bitmap);
/* other YUV-compressed */
else
- avierr = yuv_decompress_to_yuy16(stream, file->tempbuffer + 8, stream->chunk[framenum].length - 8, bitmap);
+ avierr = stream->yuv_decompress_to_yuy16(&m_tempbuffer[8], stream->chunk(framenum).length - 8, bitmap);
}
else
- avierr = AVIERR_INVALID_DATA;
+ avierr = error::INVALID_DATA;
return avierr;
}
@@ -1278,7 +1659,7 @@ avi_error avi_read_video_frame(avi_file *file, UINT32 framenum, bitmap_yuy16 &bi
-------------------------------------------------*/
/**
- * @fn avi_error avi_read_sound_samples(avi_file *file, int channel, UINT32 firstsample, UINT32 numsamples, INT16 *output)
+ * @fn avi_error avi_read_sound_samples(avi_file *file, int channel, std::uint32_t firstsample, std::uint32_t numsamples, std::int16_t *output)
*
* @brief Avi read sound samples.
*
@@ -1291,95 +1672,90 @@ avi_error avi_read_video_frame(avi_file *file, UINT32 framenum, bitmap_yuy16 &bi
* @return An avi_error.
*/
-avi_error avi_read_sound_samples(avi_file *file, int channel, UINT32 firstsample, UINT32 numsamples, INT16 *output)
+avi_file::error avi_file_impl::read_sound_samples(int channel, std::uint32_t firstsample, std::uint32_t numsamples, std::int16_t *output)
{
- avi_error avierr = AVIERR_NONE;
- UINT32 bytes_per_sample;
- file_error filerr;
- avi_stream *stream;
- int offset = 0;
-
/* get the audio stream */
- stream = get_audio_stream(file, channel, &offset);
- if (stream == nullptr)
- return AVIERR_INVALID_STREAM;
+ int offset = 0;
+ avi_stream *const stream = get_audio_stream(channel, offset);
+ if (!stream)
+ return error::INVALID_STREAM;
/* validate our ability to handle the data */
- if (stream->format != 0 || (stream->samplebits != 8 && stream->samplebits != 16))
- return AVIERR_UNSUPPORTED_AUDIO_FORMAT;
+ if (stream->format() != 0 || (stream->samplebits() != 8 && stream->samplebits() != 16))
+ return error::UNSUPPORTED_AUDIO_FORMAT;
/* verify we are in range */
- if (firstsample >= stream->samples)
- return AVIERR_INVALID_FRAME;
- if (firstsample + numsamples > stream->samples)
- numsamples = stream->samples - firstsample;
+ if (firstsample >= stream->samples())
+ return error::INVALID_FRAME;
+ if (firstsample + numsamples > stream->samples())
+ numsamples = stream->samples() - firstsample;
/* determine bytes per sample */
- bytes_per_sample = (stream->samplebits / 8) * stream->channels;
+ std::uint32_t const bytes_per_sample = stream->bytes_per_sample();
/* loop until all samples have been extracted */
while (numsamples > 0)
{
- UINT32 chunkbase = 0, chunkend = 0, chunkid;
- UINT32 bytes_read, samples_this_chunk;
+ std::uint32_t chunkbase = 0, chunkend = 0, chunkid;
+ std::uint32_t bytes_read, samples_this_chunk;
int chunknum, sampnum;
/* locate the chunk with the first sample */
- for (chunknum = 0; chunknum < stream->chunks; chunknum++)
+ for (chunknum = 0; chunknum < stream->chunks(); chunknum++)
{
- chunkend = chunkbase + (stream->chunk[chunknum].length - 8) / bytes_per_sample;
+ chunkend = chunkbase + (stream->chunk(chunknum).length - 8) / bytes_per_sample;
if (firstsample < chunkend)
break;
chunkbase = chunkend;
}
/* if we hit the end, fill the rest with silence */
- if (chunknum == stream->chunks)
+ if (chunknum == stream->chunks())
{
- memset(output, 0, numsamples * 2);
+ std::memset(output, 0, numsamples * 2);
break;
}
/* expand the tempbuffer to hold the data if necessary */
- avierr = expand_tempbuffer(file, stream->chunk[chunknum].length);
- if (avierr != AVIERR_NONE)
+ error avierr = expand_tempbuffer(stream->chunk(chunknum).length);
+ if (avierr != error::NONE)
return avierr;
/* read in the data */
- filerr = osd_read(file->file, file->tempbuffer, stream->chunk[chunknum].offset, stream->chunk[chunknum].length, &bytes_read);
- if (filerr != FILERR_NONE || bytes_read != stream->chunk[chunknum].length)
- return AVIERR_READ_ERROR;
+ auto const filerr = m_file->read(&m_tempbuffer[0], stream->chunk(chunknum).offset, stream->chunk(chunknum).length, bytes_read);
+ if (filerr != osd_file::error::NONE || bytes_read != stream->chunk(chunknum).length)
+ return error::READ_ERROR;
/* validate this is good data */
- chunkid = fetch_32bits(&file->tempbuffer[0]);
- if (chunkid != get_chunkid_for_stream(file, stream))
- return AVIERR_INVALID_DATA;
+ chunkid = fetch_32bits(&m_tempbuffer[0]);
+ if (chunkid != get_chunkid_for_stream(stream))
+ return error::INVALID_DATA;
/* determine how many samples to copy */
samples_this_chunk = chunkend - firstsample;
- samples_this_chunk = MIN(samples_this_chunk, numsamples);
+ samples_this_chunk = (std::min)(samples_this_chunk, numsamples);
/* extract 16-bit samples from the chunk */
- if (stream->samplebits == 16)
+ if (stream->samplebits() == 16)
{
- const INT16 *base = (const INT16 *)(file->tempbuffer + 8);
- base += stream->channels * (firstsample - chunkbase) + offset;
+ const std::int16_t *base = reinterpret_cast<const std::int16_t *>(&m_tempbuffer[8]);
+ base += stream->channels() * (firstsample - chunkbase) + offset;
for (sampnum = 0; sampnum < samples_this_chunk; sampnum++)
{
*output++ = LITTLE_ENDIANIZE_INT16(*base);
- base += stream->channels;
+ base += stream->channels();
}
}
/* extract 8-bit samples from the chunk */
- else if (stream->samplebits == 8)
+ else if (stream->samplebits() == 8)
{
- const UINT8 *base = (const UINT8 *)(file->tempbuffer + 8);
- base += stream->channels * (firstsample - chunkbase) + offset;
+ const std::uint8_t *base = &m_tempbuffer[8];
+ base += stream->channels() * (firstsample - chunkbase) + offset;
for (sampnum = 0; sampnum < samples_this_chunk; sampnum++)
{
*output++ = (*base << 8) - 0x8000;
- base += stream->channels;
+ base += stream->channels();
}
}
@@ -1388,7 +1764,7 @@ avi_error avi_read_sound_samples(avi_file *file, int channel, UINT32 firstsample
numsamples -= samples_this_chunk;
}
- return avierr;
+ return error::NONE;
}
@@ -1408,45 +1784,45 @@ avi_error avi_read_sound_samples(avi_file *file, int channel, UINT32 firstsample
* @return An avi_error.
*/
-avi_error avi_append_video_frame(avi_file *file, bitmap_yuy16 &bitmap)
+avi_file::error avi_file_impl::append_video_frame(bitmap_yuy16 &bitmap)
{
- avi_stream *stream = get_video_stream(file);
- avi_error avierr;
- UINT32 maxlength;
+ avi_stream *const stream = get_video_stream();
+ error avierr;
+ std::uint32_t maxlength;
/* validate our ability to handle the data */
- if (stream->format != FORMAT_UYVY && stream->format != FORMAT_VYUY && stream->format != FORMAT_YUY2 && stream->format != FORMAT_HFYU)
- return AVIERR_UNSUPPORTED_VIDEO_FORMAT;
+ if (stream->format() != FORMAT_UYVY && stream->format() != FORMAT_VYUY && stream->format() != FORMAT_YUY2 && stream->format() != FORMAT_HFYU)
+ return error::UNSUPPORTED_VIDEO_FORMAT;
/* write out any sound data first */
- avierr = soundbuf_write_chunk(file, stream->chunks);
- if (avierr != AVIERR_NONE)
+ avierr = soundbuf_write_chunk(stream->chunks());
+ if (avierr != error::NONE)
return avierr;
/* make sure we have enough room */
- maxlength = 2 * stream->width * stream->height;
- avierr = expand_tempbuffer(file, maxlength);
- if (avierr != AVIERR_NONE)
+ maxlength = 2 * stream->width() * stream->height();
+ avierr = expand_tempbuffer(maxlength);
+ if (avierr != error::NONE)
return avierr;
/* now compress the data */
- avierr = yuy16_compress_to_yuy(stream, bitmap, file->tempbuffer, maxlength);
- if (avierr != AVIERR_NONE)
+ avierr = stream->yuy16_compress_to_yuy(bitmap, &m_tempbuffer[0], maxlength);
+ if (avierr != error::NONE)
return avierr;
/* write the data */
- avierr = chunk_write(file, get_chunkid_for_stream(file, stream), file->tempbuffer, maxlength);
- if (avierr != AVIERR_NONE)
+ avierr = chunk_write(get_chunkid_for_stream(stream), &m_tempbuffer[0], maxlength);
+ if (avierr != error::NONE)
return avierr;
/* set the info for this new chunk */
- avierr = set_stream_chunk_info(stream, stream->chunks, file->writeoffs - maxlength - 8, maxlength + 8);
- if (avierr != AVIERR_NONE)
+ avierr = stream->set_chunk_info(stream->chunks(), m_writeoffs - maxlength - 8, maxlength + 8);
+ if (avierr != error::NONE)
return avierr;
- stream->samples = file->info.video_numsamples = stream->chunks;
+ stream->set_samples(m_info.video_numsamples = stream->chunks());
- return AVIERR_NONE;
+ return error::NONE;
}
@@ -1466,49 +1842,49 @@ avi_error avi_append_video_frame(avi_file *file, bitmap_yuy16 &bitmap)
* @return An avi_error.
*/
-avi_error avi_append_video_frame(avi_file *file, bitmap_rgb32 &bitmap)
+avi_file::error avi_file_impl::append_video_frame(bitmap_rgb32 &bitmap)
{
- avi_stream *stream = get_video_stream(file);
- avi_error avierr;
- UINT32 maxlength;
+ avi_stream *const stream = get_video_stream();
+ error avierr;
+ std::uint32_t maxlength;
/* validate our ability to handle the data */
- if (stream->format != 0)
- return AVIERR_UNSUPPORTED_VIDEO_FORMAT;
+ if (stream->format() != 0)
+ return error::UNSUPPORTED_VIDEO_FORMAT;
/* depth must be 24 */
- if (stream->depth != 24)
- return AVIERR_UNSUPPORTED_VIDEO_FORMAT;
+ if (stream->depth() != 24)
+ return error::UNSUPPORTED_VIDEO_FORMAT;
/* write out any sound data first */
- avierr = soundbuf_write_chunk(file, stream->chunks);
- if (avierr != AVIERR_NONE)
+ avierr = soundbuf_write_chunk(stream->chunks());
+ if (avierr != error::NONE)
return avierr;
/* make sure we have enough room */
- maxlength = 3 * stream->width * stream->height;
- avierr = expand_tempbuffer(file, maxlength);
- if (avierr != AVIERR_NONE)
+ maxlength = 3 * stream->width() * stream->height();
+ avierr = expand_tempbuffer(maxlength);
+ if (avierr != error::NONE)
return avierr;
/* copy the RGB data to the destination */
- avierr = rgb32_compress_to_rgb(stream, bitmap, file->tempbuffer, maxlength);
- if (avierr != AVIERR_NONE)
+ avierr = stream->rgb32_compress_to_rgb(bitmap, &m_tempbuffer[0], maxlength);
+ if (avierr != error::NONE)
return avierr;
/* write the data */
- avierr = chunk_write(file, get_chunkid_for_stream(file, stream), file->tempbuffer, maxlength);
- if (avierr != AVIERR_NONE)
+ avierr = chunk_write(get_chunkid_for_stream(stream), &m_tempbuffer[0], maxlength);
+ if (avierr != error::NONE)
return avierr;
/* set the info for this new chunk */
- avierr = set_stream_chunk_info(stream, stream->chunks, file->writeoffs - maxlength - 8, maxlength + 8);
- if (avierr != AVIERR_NONE)
+ avierr = stream->set_chunk_info(stream->chunks(), m_writeoffs - maxlength - 8, maxlength + 8);
+ if (avierr != error::NONE)
return avierr;
- stream->samples = file->info.video_numsamples = stream->chunks;
+ stream->set_samples(m_info.video_numsamples = stream->chunks());
- return AVIERR_NONE;
+ return error::NONE;
}
@@ -1518,7 +1894,7 @@ avi_error avi_append_video_frame(avi_file *file, bitmap_rgb32 &bitmap)
-------------------------------------------------*/
/**
- * @fn avi_error avi_append_sound_samples(avi_file *file, int channel, const INT16 *samples, UINT32 numsamples, UINT32 sampleskip)
+ * @fn avi_error avi_append_sound_samples(avi_file *file, int channel, const std::int16_t *samples, std::uint32_t numsamples, std::uint32_t sampleskip)
*
* @brief Avi append sound samples.
*
@@ -1531,27 +1907,27 @@ avi_error avi_append_video_frame(avi_file *file, bitmap_rgb32 &bitmap)
* @return An avi_error.
*/
-avi_error avi_append_sound_samples(avi_file *file, int channel, const INT16 *samples, UINT32 numsamples, UINT32 sampleskip)
+avi_file::error avi_file_impl::append_sound_samples(int channel, const std::int16_t *samples, std::uint32_t numsamples, std::uint32_t sampleskip)
{
- UINT32 sampoffset = file->soundbuf_chansamples[channel];
- UINT32 sampnum;
+ std::uint32_t sampoffset = m_soundbuf_chansamples[channel];
+ std::uint32_t sampnum;
/* see if we have enough room in the buffer */
- if (sampoffset + numsamples > file->soundbuf_samples)
- return AVIERR_EXCEEDED_SOUND_BUFFER;
+ if (sampoffset + numsamples > m_soundbuf_samples)
+ return error::EXCEEDED_SOUND_BUFFER;
/* append samples to the buffer in little-endian format */
for (sampnum = 0; sampnum < numsamples; sampnum++)
{
- INT16 data = *samples++;
+ std::int16_t data = *samples++;
samples += sampleskip;
data = LITTLE_ENDIANIZE_INT16(data);
- file->soundbuf[sampoffset++ * file->info.audio_channels + channel] = data;
+ m_soundbuf[sampoffset++ * m_info.audio_channels + channel] = data;
}
- file->soundbuf_chansamples[channel] = sampoffset;
+ m_soundbuf_chansamples[channel] = sampoffset;
/* flush any full sound chunks to disk */
- return soundbuf_flush(file, TRUE);
+ return soundbuf_flush(TRUE);
}
@@ -1561,7 +1937,7 @@ avi_error avi_append_sound_samples(avi_file *file, int channel, const INT16 *sam
-------------------------------------------------*/
/**
- * @fn static avi_error read_chunk_data(avi_file *file, const avi_chunk *chunk, UINT8 **buffer)
+ * @fn static avi_error read_chunk_data(avi_file *file, const avi_chunk *chunk, std::uint8_t **buffer)
*
* @brief Reads chunk data.
*
@@ -1572,26 +1948,22 @@ avi_error avi_append_sound_samples(avi_file *file, int channel, const INT16 *sam
* @return The chunk data.
*/
-static avi_error read_chunk_data(avi_file *file, const avi_chunk *chunk, UINT8 **buffer)
+avi_file::error avi_file_impl::read_chunk_data(avi_chunk const &chunk, std::unique_ptr<std::uint8_t []> &buffer)
{
- file_error filerr;
- UINT32 bytes_read;
-
/* allocate memory for the data */
- *buffer = (UINT8 *)malloc(chunk->size);
- if (*buffer == nullptr)
- return AVIERR_NO_MEMORY;
+ try { buffer.reset(new std::uint8_t[chunk.size]); }
+ catch (...) { return error::NO_MEMORY; }
/* read from the file */
- filerr = osd_read(file->file, *buffer, chunk->offset + 8, chunk->size, &bytes_read);
- if (filerr != FILERR_NONE || bytes_read != chunk->size)
+ std::uint32_t bytes_read;
+ osd_file::error const filerr = m_file->read(&buffer[0], chunk.offset + 8, chunk.size, bytes_read);
+ if (filerr != osd_file::error::NONE || bytes_read != chunk.size)
{
- free(*buffer);
- *buffer = nullptr;
- return AVIERR_READ_ERROR;
+ buffer.reset();
+ return error::READ_ERROR;
}
- return AVIERR_NONE;
+ return error::NONE;
}
@@ -1612,12 +1984,12 @@ static avi_error read_chunk_data(avi_file *file, const avi_chunk *chunk, UINT8 *
* @return The first chunk.
*/
-static avi_error get_first_chunk(avi_file *file, const avi_chunk *parent, avi_chunk *newchunk)
+avi_file::error avi_file_impl::get_first_chunk(avi_chunk const *parent, avi_chunk &newchunk)
{
- UINT64 startoffset = (parent != nullptr && parent->type != 0) ? parent->offset + 12 : 0;
+ std::uint64_t startoffset = (parent != nullptr && parent->type != 0) ? parent->offset + 12 : 0;
if (parent != nullptr && parent->type != CHUNKTYPE_LIST && parent->type != CHUNKTYPE_RIFF && parent->type != 0)
- return AVIERR_INVALID_DATA;
- return get_next_chunk_internal(file, parent, newchunk, startoffset);
+ return error::INVALID_DATA;
+ return get_next_chunk_internal(parent, newchunk, startoffset);
}
@@ -1638,10 +2010,10 @@ static avi_error get_first_chunk(avi_file *file, const avi_chunk *parent, avi_ch
* @return The next chunk.
*/
-static avi_error get_next_chunk(avi_file *file, const avi_chunk *parent, avi_chunk *newchunk)
+avi_file::error avi_file_impl::get_next_chunk(avi_chunk const *parent, avi_chunk &newchunk)
{
- UINT64 nextoffset = newchunk->offset + 8 + newchunk->size + (newchunk->size & 1);
- return get_next_chunk_internal(file, parent, newchunk, nextoffset);
+ std::uint64_t nextoffset = newchunk.offset + 8 + newchunk.size + (newchunk.size & 1);
+ return get_next_chunk_internal(parent, newchunk, nextoffset);
}
@@ -1651,7 +2023,7 @@ static avi_error get_next_chunk(avi_file *file, const avi_chunk *parent, avi_chu
-------------------------------------------------*/
/**
- * @fn static avi_error find_first_chunk(avi_file *file, UINT32 findme, const avi_chunk *container, avi_chunk *result)
+ * @fn static avi_error find_first_chunk(avi_file *file, std::uint32_t findme, const avi_chunk *container, avi_chunk *result)
*
* @brief Searches for the first chunk.
*
@@ -1663,13 +2035,13 @@ static avi_error get_next_chunk(avi_file *file, const avi_chunk *parent, avi_chu
* @return The found chunk.
*/
-static avi_error find_first_chunk(avi_file *file, UINT32 findme, const avi_chunk *container, avi_chunk *result)
+avi_file::error avi_file_impl::find_first_chunk(std::uint32_t findme, const avi_chunk *container, avi_chunk &result)
{
- avi_error avierr;
+ error avierr;
- for (avierr = get_first_chunk(file, container, result); avierr == AVIERR_NONE; avierr = get_next_chunk(file, container, result))
- if (result->type == findme)
- return AVIERR_NONE;
+ for (avierr = get_first_chunk(container, result); avierr == error::NONE; avierr = get_next_chunk(container, result))
+ if (result.type == findme)
+ return error::NONE;
return avierr;
}
@@ -1681,7 +2053,7 @@ static avi_error find_first_chunk(avi_file *file, UINT32 findme, const avi_chunk
-------------------------------------------------*/
/**
- * @fn static avi_error find_next_chunk(avi_file *file, UINT32 findme, const avi_chunk *container, avi_chunk *result)
+ * @fn static avi_error find_next_chunk(avi_file *file, std::uint32_t findme, const avi_chunk *container, avi_chunk *result)
*
* @brief Searches for the next chunk.
*
@@ -1693,13 +2065,13 @@ static avi_error find_first_chunk(avi_file *file, UINT32 findme, const avi_chunk
* @return The found chunk.
*/
-static avi_error find_next_chunk(avi_file *file, UINT32 findme, const avi_chunk *container, avi_chunk *result)
+avi_file::error avi_file_impl::find_next_chunk(std::uint32_t findme, const avi_chunk *container, avi_chunk &result)
{
- avi_error avierr;
+ error avierr;
- for (avierr = get_next_chunk(file, container, result); avierr == AVIERR_NONE; avierr = get_next_chunk(file, container, result))
- if (result->type == findme)
- return AVIERR_NONE;
+ for (avierr = get_next_chunk(container, result); avierr == error::NONE; avierr = get_next_chunk(container, result))
+ if (result.type == findme)
+ return error::NONE;
return avierr;
}
@@ -1711,7 +2083,7 @@ static avi_error find_next_chunk(avi_file *file, UINT32 findme, const avi_chunk
-------------------------------------------------*/
/**
- * @fn static avi_error find_first_list(avi_file *file, UINT32 findme, const avi_chunk *container, avi_chunk *result)
+ * @fn static avi_error find_first_list(avi_file *file, std::uint32_t findme, const avi_chunk *container, avi_chunk *result)
*
* @brief Searches for the first list.
*
@@ -1723,13 +2095,13 @@ static avi_error find_next_chunk(avi_file *file, UINT32 findme, const avi_chunk
* @return The found list.
*/
-static avi_error find_first_list(avi_file *file, UINT32 findme, const avi_chunk *container, avi_chunk *result)
+avi_file::error avi_file_impl::find_first_list(std::uint32_t findme, const avi_chunk *container, avi_chunk &result)
{
- avi_error avierr;
+ error avierr;
- for (avierr = find_first_chunk(file, CHUNKTYPE_LIST, container, result); avierr == AVIERR_NONE; avierr = find_next_chunk(file, CHUNKTYPE_LIST, container, result))
- if (result->listtype == findme)
- return AVIERR_NONE;
+ for (avierr = find_first_chunk(CHUNKTYPE_LIST, container, result); avierr == error::NONE; avierr = find_next_chunk(CHUNKTYPE_LIST, container, result))
+ if (result.listtype == findme)
+ return error::NONE;
return avierr;
}
@@ -1741,7 +2113,7 @@ static avi_error find_first_list(avi_file *file, UINT32 findme, const avi_chunk
-------------------------------------------------*/
/**
- * @fn static avi_error find_next_list(avi_file *file, UINT32 findme, const avi_chunk *container, avi_chunk *result)
+ * @fn static avi_error find_next_list(avi_file *file, std::uint32_t findme, const avi_chunk *container, avi_chunk *result)
*
* @brief Searches for the next list.
*
@@ -1753,13 +2125,13 @@ static avi_error find_first_list(avi_file *file, UINT32 findme, const avi_chunk
* @return The found list.
*/
-static avi_error find_next_list(avi_file *file, UINT32 findme, const avi_chunk *container, avi_chunk *result)
+avi_file::error avi_file_impl::find_next_list(std::uint32_t findme, const avi_chunk *container, avi_chunk &result)
{
- avi_error avierr;
+ error avierr;
- for (avierr = find_next_chunk(file, CHUNKTYPE_LIST, container, result); avierr == AVIERR_NONE; avierr = find_next_chunk(file, CHUNKTYPE_LIST, container, result))
- if (result->listtype == findme)
- return AVIERR_NONE;
+ for (avierr = find_next_chunk(CHUNKTYPE_LIST, container, result); avierr == error::NONE; avierr = find_next_chunk(CHUNKTYPE_LIST, container, result))
+ if (result.listtype == findme)
+ return error::NONE;
return avierr;
}
@@ -1771,7 +2143,7 @@ static avi_error find_next_list(avi_file *file, UINT32 findme, const avi_chunk *
-------------------------------------------------*/
/**
- * @fn static avi_error get_next_chunk_internal(avi_file *file, const avi_chunk *parent, avi_chunk *newchunk, UINT64 offset)
+ * @fn static avi_error get_next_chunk_internal(avi_file *file, const avi_chunk *parent, avi_chunk *newchunk, std::uint64_t offset)
*
* @brief Gets the next chunk internal.
*
@@ -1783,42 +2155,42 @@ static avi_error find_next_list(avi_file *file, UINT32 findme, const avi_chunk *
* @return The next chunk internal.
*/
-static avi_error get_next_chunk_internal(avi_file *file, const avi_chunk *parent, avi_chunk *newchunk, UINT64 offset)
+avi_file::error avi_file_impl::get_next_chunk_internal(const avi_chunk *parent, avi_chunk &newchunk, std::uint64_t offset)
{
- file_error filerr;
- UINT8 buffer[12];
- UINT32 bytesread;
+ osd_file::error filerr;
+ std::uint8_t buffer[12];
+ std::uint32_t bytesread;
/* NULL parent implies the root */
if (parent == nullptr)
- parent = &file->rootchunk;
+ parent = &m_rootchunk;
/* start at the current offset */
- newchunk->offset = offset;
+ newchunk.offset = offset;
/* if we're past the bounds of the parent, bail */
- if (newchunk->offset + 8 >= parent->offset + 8 + parent->size)
- return AVIERR_END;
+ if (newchunk.offset + 8 >= parent->offset + 8 + parent->size)
+ return error::END;
/* read the header */
- filerr = osd_read(file->file, buffer, newchunk->offset, 8, &bytesread);
- if (filerr != FILERR_NONE || bytesread != 8)
- return AVIERR_INVALID_DATA;
+ filerr = m_file->read(buffer, newchunk.offset, 8, bytesread);
+ if (filerr != osd_file::error::NONE || bytesread != 8)
+ return error::INVALID_DATA;
/* fill in the new chunk */
- newchunk->type = fetch_32bits(&buffer[0]);
- newchunk->size = fetch_32bits(&buffer[4]);
+ newchunk.type = fetch_32bits(&buffer[0]);
+ newchunk.size = fetch_32bits(&buffer[4]);
/* if we are a list, fetch the list type */
- if (newchunk->type == CHUNKTYPE_LIST || newchunk->type == CHUNKTYPE_RIFF)
+ if (newchunk.type == CHUNKTYPE_LIST || newchunk.type == CHUNKTYPE_RIFF)
{
- filerr = osd_read(file->file, &buffer[8], newchunk->offset + 8, 4, &bytesread);
- if (filerr != FILERR_NONE || bytesread != 4)
- return AVIERR_INVALID_DATA;
- newchunk->listtype = fetch_32bits(&buffer[8]);
+ filerr = m_file->read(&buffer[8], newchunk.offset + 8, 4, bytesread);
+ if (filerr != osd_file::error::NONE || bytesread != 4)
+ return error::INVALID_DATA;
+ newchunk.listtype = fetch_32bits(&buffer[8]);
}
- return AVIERR_NONE;
+ return error::NONE;
}
@@ -1836,98 +2208,95 @@ static avi_error get_next_chunk_internal(avi_file *file, const avi_chunk *parent
* @return The movie data.
*/
-static avi_error read_movie_data(avi_file *file)
+avi_file::error avi_file_impl::read_movie_data()
{
avi_chunk riff, hdrl, avih, strl, strh, strf, indx, movi, idx1;
- avi_error avierr;
- int strindex;
+ error avierr;
/* find the RIFF chunk */
- avierr = find_first_chunk(file, CHUNKTYPE_RIFF, nullptr, &riff);
- if (avierr != AVIERR_NONE)
- goto error;
+ avierr = find_first_chunk(CHUNKTYPE_RIFF, nullptr, riff);
+ if (avierr != error::NONE)
+ return avierr;
/* verify that the RIFF type is AVI */
if (riff.listtype != LISTTYPE_AVI)
{
- avierr = AVIERR_INVALID_DATA;
- goto error;
+ avierr = error::INVALID_DATA;
+ return avierr;
}
/* find the hdrl LIST chunk within the RIFF */
- avierr = find_first_list(file, LISTTYPE_HDRL, &riff, &hdrl);
- if (avierr != AVIERR_NONE)
- goto error;
+ avierr = find_first_list(LISTTYPE_HDRL, &riff, hdrl);
+ if (avierr != error::NONE)
+ return avierr;
/* find the avih chunk */
- avierr = find_first_chunk(file, CHUNKTYPE_AVIH, &hdrl, &avih);
- if (avierr != AVIERR_NONE)
- goto error;
+ avierr = find_first_chunk(CHUNKTYPE_AVIH, &hdrl, avih);
+ if (avierr != error::NONE)
+ return avierr;
/* parse the avih chunk */
- avierr = parse_avih_chunk(file, &avih);
- if (avierr != AVIERR_NONE)
- goto error;
+ avierr = parse_avih_chunk(avih);
+ if (avierr != error::NONE)
+ return avierr;
/* loop over strl LIST chunks */
- strindex = 0;
- for (avierr = find_first_list(file, LISTTYPE_STRL, &hdrl, &strl); avierr == AVIERR_NONE; avierr = find_next_list(file, LISTTYPE_STRL, &hdrl, &strl))
+ int strindex = 0;
+ for (avierr = find_first_list(LISTTYPE_STRL, &hdrl, strl); avierr == error::NONE; avierr = find_next_list(LISTTYPE_STRL, &hdrl, strl))
{
/* if we have too many, it's a bad file */
- if (strindex >= file->streams)
- goto error;
+ if (strindex >= m_streams.size())
+ return avierr;
/* find the strh chunk */
- avierr = find_first_chunk(file, CHUNKTYPE_STRH, &strl, &strh);
- if (avierr != AVIERR_NONE)
- goto error;
+ avierr = find_first_chunk(CHUNKTYPE_STRH, &strl, strh);
+ if (avierr != error::NONE)
+ return avierr;
/* parse the data */
- avierr = parse_strh_chunk(file, &file->stream[strindex], &strh);
- if (avierr != AVIERR_NONE)
- goto error;
+ avierr = parse_strh_chunk(m_streams[strindex], strh);
+ if (avierr != error::NONE)
+ return avierr;
/* find the strf chunk */
- avierr = find_first_chunk(file, CHUNKTYPE_STRF, &strl, &strf);
- if (avierr != AVIERR_NONE)
- goto error;
+ avierr = find_first_chunk(CHUNKTYPE_STRF, &strl, strf);
+ if (avierr != error::NONE)
+ return avierr;
/* parse the data */
- avierr = parse_strf_chunk(file, &file->stream[strindex], &strf);
- if (avierr != AVIERR_NONE)
- goto error;
+ avierr = parse_strf_chunk(m_streams[strindex], strf);
+ if (avierr != error::NONE)
+ return avierr;
/* find the indx chunk, if present */
- avierr = find_first_chunk(file, CHUNKTYPE_INDX, &strl, &indx);
- if (avierr == AVIERR_NONE)
- avierr = parse_indx_chunk(file, &file->stream[strindex], &indx);
+ avierr = find_first_chunk(CHUNKTYPE_INDX, &strl, indx);
+ if (avierr == error::NONE)
+ avierr = parse_indx_chunk(m_streams[strindex], indx);
/* next stream */
strindex++;
}
/* normalize the error after parsing the stream headers */
- if (avierr == AVIERR_END)
- avierr = AVIERR_NONE;
- if (avierr != AVIERR_NONE)
- goto error;
+ if (avierr == error::END)
+ avierr = error::NONE;
+ if (avierr != error::NONE)
+ return avierr;
/* find the base of the movi data */
- avierr = find_first_list(file, LISTTYPE_MOVI, &riff, &movi);
- if (avierr != AVIERR_NONE)
- goto error;
+ avierr = find_first_list(LISTTYPE_MOVI, &riff, movi);
+ if (avierr != error::NONE)
+ return avierr;
/* find and parse the idx1 chunk within the RIFF (if present) */
- avierr = find_first_chunk(file, CHUNKTYPE_IDX1, &riff, &idx1);
- if (avierr == AVIERR_NONE)
- avierr = parse_idx1_chunk(file, movi.offset + 8, &idx1);
- if (avierr != AVIERR_NONE)
- goto error;
+ avierr = find_first_chunk(CHUNKTYPE_IDX1, &riff, idx1);
+ if (avierr == error::NONE)
+ avierr = parse_idx1_chunk(movi.offset + 8, idx1);
+ if (avierr != error::NONE)
+ return avierr;
/* now extract the movie info */
- avierr = extract_movie_info(file);
-
-error:
+ avierr = extract_movie_info();
return avierr;
}
@@ -1947,59 +2316,55 @@ error:
* @return The extracted movie information.
*/
-static avi_error extract_movie_info(avi_file *file)
+avi_file::error avi_file_impl::extract_movie_info()
{
- //avi_stream *audiostream;
avi_stream *stream;
+ int offset;
/* get the video stream */
- stream = get_video_stream(file);
+ stream = get_video_stream();
if (stream != nullptr)
{
/* fill in the info */
- file->info.video_format = stream->format;
- file->info.video_timescale = stream->rate;
- file->info.video_sampletime = stream->scale;
- file->info.video_numsamples = stream->samples;
- file->info.video_width = stream->width;
- file->info.video_height = stream->height;
+ m_info.video_format = stream->format();
+ m_info.video_timescale = stream->rate();
+ m_info.video_sampletime = stream->scale();
+ m_info.video_numsamples = stream->samples();
+ m_info.video_width = stream->width();
+ m_info.video_height = stream->height();
}
/* get the first audio stream */
- stream = get_audio_stream(file, 0, nullptr);
+ stream = get_audio_stream(0, offset);
if (stream != nullptr)
{
/* fill in the info */
- file->info.audio_format = stream->format;
- file->info.audio_timescale = stream->rate;
- file->info.audio_sampletime = stream->scale;
- file->info.audio_numsamples = stream->samples;
- file->info.audio_channels = 1;
- file->info.audio_samplebits = stream->samplebits;
- file->info.audio_samplerate = stream->samplerate;
+ m_info.audio_format = stream->format();
+ m_info.audio_timescale = stream->rate();
+ m_info.audio_sampletime = stream->scale();
+ m_info.audio_numsamples = stream->samples();
+ m_info.audio_channels = 1;
+ m_info.audio_samplebits = stream->samplebits();
+ m_info.audio_samplerate = stream->samplerate();
}
/* now make sure all other audio streams are valid */
- //audiostream = stream;
- while (1)
+ while (nullptr != (stream = get_audio_stream(m_info.audio_channels, offset)))
{
/* get the stream info */
- stream = get_audio_stream(file, file->info.audio_channels, nullptr);
- if (stream == nullptr)
- break;
- file->info.audio_channels++;
+ m_info.audio_channels++;
/* verify compatibility */
- if (file->info.audio_format != stream->format ||
- file->info.audio_timescale != stream->rate ||
- file->info.audio_sampletime != stream->scale ||
- file->info.audio_numsamples != stream->samples ||
- file->info.audio_samplebits != stream->samplebits ||
- file->info.audio_samplerate != stream->samplerate)
- return AVIERR_INCOMPATIBLE_AUDIO_STREAMS;
+ if (m_info.audio_format != stream->format() ||
+ m_info.audio_timescale != stream->rate() ||
+ m_info.audio_sampletime != stream->scale() ||
+ m_info.audio_numsamples != stream->samples() ||
+ m_info.audio_samplebits != stream->samplebits() ||
+ m_info.audio_samplerate != stream->samplerate())
+ return error::INCOMPATIBLE_AUDIO_STREAMS;
}
- return AVIERR_NONE;
+ return error::NONE;
}
@@ -2019,28 +2384,21 @@ static avi_error extract_movie_info(avi_file *file)
* @return An avi_error.
*/
-static avi_error parse_avih_chunk(avi_file *file, avi_chunk *avih)
+avi_file::error avi_file_impl::parse_avih_chunk(avi_chunk const &avih)
{
- UINT8 *chunkdata = nullptr;
- avi_error avierr;
-
/* read the data */
- avierr = read_chunk_data(file, avih, &chunkdata);
- if (avierr != AVIERR_NONE)
- goto error;
+ std::unique_ptr<std::uint8_t []> chunkdata;
+ error avierr = read_chunk_data(avih, chunkdata);
+ if (avierr != error::NONE)
+ return avierr;
/* extract the data */
- file->streams = fetch_32bits(&chunkdata[24]);
+ std::uint32_t const streams = fetch_32bits(&chunkdata[24]);
/* allocate memory for the streams */
- file->stream = (avi_stream *)malloc(sizeof(*file->stream) * file->streams);
- if (file->stream == nullptr)
- goto error;
- memset(file->stream, 0, sizeof(*file->stream) * file->streams);
+ m_streams.clear();
+ m_streams.resize(streams);
-error:
- if (chunkdata != nullptr)
- free(chunkdata);
return avierr;
}
@@ -2062,26 +2420,16 @@ error:
* @return An avi_error.
*/
-static avi_error parse_strh_chunk(avi_file *file, avi_stream *stream, avi_chunk *strh)
+avi_file::error avi_file_impl::parse_strh_chunk(avi_stream &stream, avi_chunk const &strh)
{
- UINT8 *chunkdata = nullptr;
- avi_error avierr;
-
/* read the data */
- avierr = read_chunk_data(file, strh, &chunkdata);
- if (avierr != AVIERR_NONE)
- goto error;
+ std::unique_ptr<std::uint8_t []> chunkdata;
+ error const avierr = read_chunk_data(strh, chunkdata);
+ if (avierr != error::NONE)
+ return avierr;
/* extract the data */
- stream->type = fetch_32bits(&chunkdata[0]);
- stream->scale = fetch_32bits(&chunkdata[20]);
- stream->rate = fetch_32bits(&chunkdata[24]);
- stream->samples = fetch_32bits(&chunkdata[32]);
-
-error:
- if (chunkdata != nullptr)
- free(chunkdata);
- return avierr;
+ return stream.set_strh_data(&chunkdata[0], strh.size);
}
@@ -2102,43 +2450,17 @@ error:
* @return An avi_error.
*/
-static avi_error parse_strf_chunk(avi_file *file, avi_stream *stream, avi_chunk *strf)
+avi_file::error avi_file_impl::parse_strf_chunk(avi_stream &stream, avi_chunk const &strf)
{
- UINT8 *chunkdata = nullptr;
- avi_error avierr;
+ error avierr;
/* read the data */
- avierr = read_chunk_data(file, strf, &chunkdata);
- if (avierr != AVIERR_NONE)
- goto error;
-
- /* audio and video streams have differing headers */
- if (stream->type == STREAMTYPE_VIDS)
- {
- stream->width = fetch_32bits(&chunkdata[4]);
- stream->height = fetch_32bits(&chunkdata[8]);
- stream->depth = fetch_16bits(&chunkdata[14]);
- stream->format = fetch_32bits(&chunkdata[16]);
-
- /* extra extraction for HuffYUV data */
- if (stream->format == FORMAT_HFYU && strf->size >= 56)
- {
- avierr = huffyuv_extract_tables(stream, chunkdata, strf->size);
- if (avierr != AVIERR_NONE)
- goto error;
- }
- }
- else if (stream->type == STREAMTYPE_AUDS)
- {
- stream->channels = fetch_16bits(&chunkdata[2]);
- stream->samplebits = fetch_16bits(&chunkdata[14]);
- stream->samplerate = fetch_32bits(&chunkdata[4]);
- }
+ std::unique_ptr<std::uint8_t []> chunkdata;
+ avierr = read_chunk_data(strf, chunkdata);
+ if (avierr != error::NONE)
+ return avierr;
-error:
- if (chunkdata != nullptr)
- free(chunkdata);
- return avierr;
+ return stream.set_strf_data(&chunkdata[0], strf.size);
}
@@ -2158,50 +2480,46 @@ error:
* @return An avi_error.
*/
-static avi_error parse_indx_chunk(avi_file *file, avi_stream *stream, avi_chunk *strf)
+avi_file::error avi_file_impl::parse_indx_chunk(avi_stream &stream, avi_chunk const &strf)
{
- UINT32 entries, entry;
- UINT8 *chunkdata = nullptr;
- UINT16 longs_per_entry;
- UINT8 type;
- UINT64 baseoffset;
- avi_error avierr;
+ error avierr;
/* read the data */
- avierr = read_chunk_data(file, strf, &chunkdata);
- if (avierr != AVIERR_NONE)
- goto error;
+ std::unique_ptr<std::uint8_t []> chunkdata;
+ avierr = read_chunk_data(strf, chunkdata);
+ if (avierr != error::NONE)
+ return avierr;
/* extract the data */
- longs_per_entry = fetch_16bits(&chunkdata[0]);
+ std::uint16_t const longs_per_entry = fetch_16bits(&chunkdata[0]);
//subtype = chunkdata[2];
- type = chunkdata[3];
- entries = fetch_32bits(&chunkdata[4]);
+ std::uint8_t const type = chunkdata[3];
+ std::uint32_t const entries = fetch_32bits(&chunkdata[4]);
//id = fetch_32bits(&chunkdata[8]);
- baseoffset = fetch_64bits(&chunkdata[12]);
+ std::uint64_t const baseoffset = fetch_64bits(&chunkdata[12]);
/* if this is a superindex, loop over entries and call ourselves recursively */
if (type == AVI_INDEX_OF_INDEXES)
{
/* validate the size of each entry */
if (longs_per_entry != 4)
- return AVIERR_INVALID_DATA;
+ return error::INVALID_DATA;
/* loop over entries and create subchunks for each */
- for (entry = 0; entry < entries; entry++)
+ for (std::uint32_t entry = 0; entry < entries; entry++)
{
- const UINT8 *base = &chunkdata[24 + entry * 16];
- file_error filerr;
+ const std::uint8_t *base = &chunkdata[24 + entry * 16];
+ osd_file::error filerr;
avi_chunk subchunk;
- UINT32 bytes_read;
- UINT8 buffer[8];
+ std::uint32_t bytes_read;
+ std::uint8_t buffer[8];
/* go read the subchunk */
subchunk.offset = fetch_64bits(&base[0]);
- filerr = osd_read(file->file, buffer, subchunk.offset, sizeof(buffer), &bytes_read);
- if (filerr != FILERR_NONE || bytes_read != sizeof(buffer))
+ filerr = m_file->read(buffer, subchunk.offset, sizeof(buffer), bytes_read);
+ if (filerr != osd_file::error::NONE || bytes_read != sizeof(buffer))
{
- avierr = AVIERR_READ_ERROR;
+ avierr = error::READ_ERROR;
break;
}
@@ -2210,8 +2528,8 @@ static avi_error parse_indx_chunk(avi_file *file, avi_stream *stream, avi_chunk
subchunk.size = fetch_32bits(&buffer[4]);
/* recursively parse each referenced chunk; stop if we hit an error */
- avierr = parse_indx_chunk(file, stream, &subchunk);
- if (avierr != AVIERR_NONE)
+ avierr = parse_indx_chunk(stream, subchunk);
+ if (avierr != error::NONE)
break;
}
}
@@ -2221,25 +2539,22 @@ static avi_error parse_indx_chunk(avi_file *file, avi_stream *stream, avi_chunk
{
/* validate the size of each entry */
if (longs_per_entry != 2 && longs_per_entry != 3)
- return AVIERR_INVALID_DATA;
+ return error::INVALID_DATA;
/* loop over entries and parse out the data */
- for (entry = 0; entry < entries; entry++)
+ for (std::uint32_t entry = 0; entry < entries; entry++)
{
- const UINT8 *base = &chunkdata[24 + entry * 4 * longs_per_entry];
- UINT32 offset = fetch_32bits(&base[0]);
- UINT32 size = fetch_32bits(&base[4]) & 0x7fffffff; // bit 31 == NOT a keyframe
+ const std::uint8_t *base = &chunkdata[24 + entry * 4 * longs_per_entry];
+ std::uint32_t offset = fetch_32bits(&base[0]);
+ std::uint32_t size = fetch_32bits(&base[4]) & 0x7fffffff; // bit 31 == NOT a keyframe
/* set the info for this chunk and advance */
- avierr = set_stream_chunk_info(stream, stream->chunks++, baseoffset + offset - 8, size + 8);
- if (avierr != AVIERR_NONE)
+ avierr = stream.set_chunk_info(stream.chunks(), baseoffset + offset - 8, size + 8);
+ if (avierr != error::NONE)
break;
}
}
-error:
- if (chunkdata != nullptr)
- free(chunkdata);
return avierr;
}
@@ -2249,7 +2564,7 @@ error:
-------------------------------------------------*/
/**
- * @fn static avi_error parse_idx1_chunk(avi_file *file, UINT64 baseoffset, avi_chunk *idx1)
+ * @fn static avi_error parse_idx1_chunk(avi_file *file, std::uint64_t baseoffset, avi_chunk *idx1)
*
* @brief Parse index 1 chunk.
*
@@ -2260,48 +2575,39 @@ error:
* @return An avi_error.
*/
-static avi_error parse_idx1_chunk(avi_file *file, UINT64 baseoffset, avi_chunk *idx1)
+avi_file::error avi_file_impl::parse_idx1_chunk(std::uint64_t baseoffset, avi_chunk const &idx1)
{
- UINT8 *chunkdata = nullptr;
- avi_error avierr;
- UINT32 entries;
- UINT32 entry;
+ error avierr;
/* read the data */
- avierr = read_chunk_data(file, idx1, &chunkdata);
- if (avierr != AVIERR_NONE)
- goto error;
+ std::unique_ptr<std::uint8_t []> chunkdata;
+ avierr = read_chunk_data(idx1, chunkdata);
+ if (avierr != error::NONE)
+ return avierr;
/* loop over entries */
- entries = idx1->size / 16;
- for (entry = 0; entry < entries; entry++)
+ std::uint32_t const entries = idx1.size / 16;
+ for (std::uint32_t entry = 0; entry < entries; entry++)
{
- const UINT8 *base = &chunkdata[entry * 16];
- UINT32 chunkid = fetch_32bits(&base[0]);
- UINT32 offset = fetch_32bits(&base[8]);
- UINT32 size = fetch_32bits(&base[12]);
- avi_stream *stream;
+ std::uint8_t const *const base = &chunkdata[entry * 16];
+ std::uint32_t const chunkid = fetch_32bits(&base[0]);
+ std::uint32_t const offset = fetch_32bits(&base[8]);
+ std::uint32_t const size = fetch_32bits(&base[12]);
int streamnum;
/* determine the stream index */
streamnum = ((chunkid >> 8) & 0xff) - '0';
streamnum += 10 * ((chunkid & 0xff) - '0');
- if (streamnum >= file->streams)
- {
- avierr = AVIERR_INVALID_DATA;
- goto error;
- }
- stream = &file->stream[streamnum];
+ if (streamnum >= m_streams.size())
+ return error::INVALID_DATA;
+ avi_stream &stream = m_streams[streamnum];
/* set the appropriate entry */
- avierr = set_stream_chunk_info(stream, stream->chunks++, baseoffset + offset, size + 8);
- if (avierr != AVIERR_NONE)
- goto error;
+ avierr = stream.set_chunk_info(stream.chunks(), baseoffset + offset, size + 8);
+ if (avierr != error::NONE)
+ return avierr;
}
-error:
- if (chunkdata != nullptr)
- free(chunkdata);
return avierr;
}
@@ -2311,7 +2617,7 @@ error:
-------------------------------------------------*/
/**
- * @fn static avi_error chunk_open(avi_file *file, UINT32 type, UINT32 listtype, UINT32 estlength)
+ * @fn static avi_error chunk_open(avi_file *file, std::uint32_t type, std::uint32_t listtype, std::uint32_t estlength)
*
* @brief Queries if a given chunk open.
*
@@ -2323,57 +2629,55 @@ error:
* @return An avi_error.
*/
-static avi_error chunk_open(avi_file *file, UINT32 type, UINT32 listtype, UINT32 estlength)
+avi_file::error avi_file_impl::chunk_open(std::uint32_t type, std::uint32_t listtype, std::uint32_t estlength)
{
- file_error filerr;
- avi_chunk *chunk;
- UINT32 written;
-
/* if we're out of stack entries, bail */
- if (file->chunksp >= ARRAY_LENGTH(file->chunkstack))
- return AVIERR_STACK_TOO_DEEP;
- chunk = &file->chunkstack[file->chunksp++];
+ if (m_chunksp >= m_chunkstack.size())
+ return error::STACK_TOO_DEEP;
+ avi_chunk &chunk = m_chunkstack[m_chunksp++];
/* set up the chunk information */
- chunk->offset = file->writeoffs;
- chunk->size = estlength;
- chunk->type = type;
- chunk->listtype = listtype;
+ chunk.offset = m_writeoffs;
+ chunk.size = estlength;
+ chunk.type = type;
+ chunk.listtype = listtype;
/* non-list types */
if (type != CHUNKTYPE_RIFF && type != CHUNKTYPE_LIST)
{
- UINT8 buffer[8];
+ std::uint8_t buffer[8];
/* populate the header */
- put_32bits(&buffer[0], chunk->type);
- put_32bits(&buffer[4], chunk->size);
+ put_32bits(&buffer[0], chunk.type);
+ put_32bits(&buffer[4], chunk.size);
/* write the header */
- filerr = osd_write(file->file, buffer, file->writeoffs, sizeof(buffer), &written);
- if (filerr != FILERR_NONE || written != sizeof(buffer))
- return AVIERR_WRITE_ERROR;
- file->writeoffs += written;
+ std::uint32_t written;
+ osd_file::error const filerr = m_file->write(buffer, m_writeoffs, sizeof(buffer), written);
+ if (filerr != osd_file::error::NONE || written != sizeof(buffer))
+ return error::WRITE_ERROR;
+ m_writeoffs += written;
}
/* list types */
else
{
- UINT8 buffer[12];
+ std::uint8_t buffer[12];
/* populate the header */
- put_32bits(&buffer[0], chunk->type);
- put_32bits(&buffer[4], chunk->size);
- put_32bits(&buffer[8], chunk->listtype);
+ put_32bits(&buffer[0], chunk.type);
+ put_32bits(&buffer[4], chunk.size);
+ put_32bits(&buffer[8], chunk.listtype);
/* write the header */
- filerr = osd_write(file->file, buffer, file->writeoffs, sizeof(buffer), &written);
- if (filerr != FILERR_NONE || written != sizeof(buffer))
- return AVIERR_WRITE_ERROR;
- file->writeoffs += written;
+ std::uint32_t written;
+ osd_file::error const filerr = m_file->write(buffer, m_writeoffs, sizeof(buffer), written);
+ if (filerr != osd_file::error::NONE || written != sizeof(buffer))
+ return error::WRITE_ERROR;
+ m_writeoffs += written;
}
- return AVIERR_NONE;
+ return error::NONE;
}
@@ -2391,32 +2695,31 @@ static avi_error chunk_open(avi_file *file, UINT32 type, UINT32 listtype, UINT32
* @return An avi_error.
*/
-static avi_error chunk_close(avi_file *file)
+avi_file::error avi_file_impl::chunk_close()
{
- avi_chunk *chunk = &file->chunkstack[--file->chunksp];
- UINT64 chunksize = file->writeoffs - (chunk->offset + 8);
- UINT32 written;
+ avi_chunk const &chunk = m_chunkstack[--m_chunksp];
+ std::uint64_t const chunksize = m_writeoffs - (chunk.offset + 8);
/* error if we don't fit into 32 bits */
- if (chunksize != (UINT32)chunksize)
- return AVIERR_INVALID_DATA;
+ if (chunksize != std::uint32_t(chunksize))
+ return error::INVALID_DATA;
/* write the final size if it is different from the guess */
- if (chunk->size != chunksize)
+ if (chunk.size != chunksize)
{
- file_error filerr;
- UINT8 buffer[4];
+ std::uint8_t buffer[4];
- put_32bits(&buffer[0], (UINT32)chunksize);
- filerr = osd_write(file->file, buffer, chunk->offset + 4, sizeof(buffer), &written);
- if (filerr != FILERR_NONE || written != sizeof(buffer))
- return AVIERR_WRITE_ERROR;
+ put_32bits(&buffer[0], std::uint32_t(chunksize));
+ std::uint32_t written;
+ osd_file::error const filerr = m_file->write(buffer, chunk.offset + 4, sizeof(buffer), written);
+ if (filerr != osd_file::error::NONE || written != sizeof(buffer))
+ return error::WRITE_ERROR;
}
/* round up to the next word */
- file->writeoffs += chunksize & 1;
+ m_writeoffs += chunksize & 1;
- return AVIERR_NONE;
+ return error::NONE;
}
@@ -2425,7 +2728,7 @@ static avi_error chunk_close(avi_file *file)
-------------------------------------------------*/
/**
- * @fn static avi_error chunk_write(avi_file *file, UINT32 type, const void *data, UINT32 length)
+ * @fn static avi_error chunk_write(avi_file *file, std::uint32_t type, const void *data, std::uint32_t length)
*
* @brief Chunk write.
*
@@ -2437,67 +2740,63 @@ static avi_error chunk_close(avi_file *file)
* @return An avi_error.
*/
-static avi_error chunk_write(avi_file *file, UINT32 type, const void *data, UINT32 length)
+avi_file::error avi_file_impl::chunk_write(std::uint32_t type, const void *data, std::uint32_t length)
{
- file_error filerr;
- avi_error avierr;
- UINT32 idxreserve;
- UINT32 written;
+ error avierr;
/* if we are the first RIFF, we must reserve enough space for the IDX chunk */
- idxreserve = 0;
- if (file->riffbase == 0 && type != CHUNKTYPE_IDX1)
- idxreserve = compute_idx1_size(file);
+ std::uint32_t const idxreserve = (m_riffbase == 0 && type != CHUNKTYPE_IDX1) ? compute_idx1_size() : 0;
/* if we are getting too big, split the RIFF */
/* note that we ignore writes before the current RIFF base, as those are assumed to be
overwrites of a chunk from the previous RIFF */
- if (file->writeoffs >= file->riffbase && file->writeoffs + length + idxreserve - file->riffbase >= MAX_RIFF_SIZE)
+ if ((m_writeoffs >= m_riffbase) && ((m_writeoffs + length + idxreserve - m_riffbase) >= MAX_RIFF_SIZE))
{
/* close the movi list */
- avierr = chunk_close(file);
- if (avierr != AVIERR_NONE)
+ avierr = chunk_close();
+ if (avierr != error::NONE)
return avierr;
/* write the idx1 chunk if this is the first */
- if (file->riffbase == 0)
+ if (m_riffbase == 0)
{
- avierr = write_idx1_chunk(file);
- if (avierr != AVIERR_NONE)
+ avierr = write_idx1_chunk();
+ if (avierr != error::NONE)
return avierr;
}
/* close the RIFF */
- avierr = chunk_close(file);
- if (avierr != AVIERR_NONE)
+ avierr = chunk_close();
+ if (avierr != error::NONE)
return avierr;
/* open a new RIFF */
- file->riffbase = file->writeoffs;
- avierr = chunk_open(file, CHUNKTYPE_RIFF, LISTTYPE_AVIX, 0);
- if (avierr != AVIERR_NONE)
+ m_riffbase = m_writeoffs;
+ avierr = chunk_open(CHUNKTYPE_RIFF, LISTTYPE_AVIX, 0);
+ if (avierr != error::NONE)
return avierr;
/* open a nested movi list */
- file->saved_movi_offset = file->writeoffs;
- avierr = chunk_open(file, CHUNKTYPE_LIST, LISTTYPE_MOVI, 0);
- if (avierr != AVIERR_NONE)
+ m_saved_movi_offset = m_writeoffs;
+ avierr = chunk_open(CHUNKTYPE_LIST, LISTTYPE_MOVI, 0);
+ if (avierr != error::NONE)
return avierr;
}
/* open the chunk */
- avierr = chunk_open(file, type, 0, length);
- if (avierr != AVIERR_NONE)
+ avierr = chunk_open(type, 0, length);
+ if (avierr != error::NONE)
return avierr;
/* write the data */
- filerr = osd_write(file->file, data, file->writeoffs, length, &written);
- if (filerr != FILERR_NONE || written != length)
- return AVIERR_WRITE_ERROR;
- file->writeoffs += written;
+ std::uint32_t written;
+ osd_file::error const filerr = m_file->write(data, m_writeoffs, length, written);
+ if (filerr != osd_file::error::NONE || written != length)
+ return error::WRITE_ERROR;
+ m_writeoffs += written;
/* close the chunk */
- return chunk_close(file);
+ return chunk_close();
}
@@ -2509,7 +2808,7 @@ static avi_error chunk_write(avi_file *file, UINT32 type, const void *data, UINT
-------------------------------------------------*/
/**
- * @fn static avi_error chunk_overwrite(avi_file *file, UINT32 type, const void *data, UINT32 length, UINT64 *offset, int initial_write)
+ * @fn static avi_error chunk_overwrite(avi_file *file, std::uint32_t type, const void *data, std::uint32_t length, std::uint64_t *offset, int initial_write)
*
* @brief Chunk overwrite.
*
@@ -2523,28 +2822,27 @@ static avi_error chunk_write(avi_file *file, UINT32 type, const void *data, UINT
* @return An avi_error.
*/
-static avi_error chunk_overwrite(avi_file *file, UINT32 type, const void *data, UINT32 length, UINT64 *offset, int initial_write)
+avi_file::error avi_file_impl::chunk_overwrite(std::uint32_t type, const void *data, std::uint32_t length, std::uint64_t &offset, bool initial_write)
{
- UINT64 savedoffset = 0;
- avi_error avierr;
+ std::uint64_t savedoffset = 0;
/* if this is our initial write, save the offset */
if (initial_write)
- *offset = file->writeoffs;
+ offset = m_writeoffs;
/* otherwise, remember the current write offset and replace it with the original */
else
{
- savedoffset = file->writeoffs;
- file->writeoffs = *offset;
+ savedoffset = m_writeoffs;
+ m_writeoffs = offset;
}
/* write the chunk */
- avierr = chunk_write(file, type, data, length);
+ error const avierr = chunk_write(type, data, length);
/* if this isn't the initial write, restore the previous offset */
if (!initial_write)
- file->writeoffs = savedoffset;
+ m_writeoffs = savedoffset;
return avierr;
}
@@ -2565,67 +2863,66 @@ static avi_error chunk_overwrite(avi_file *file, UINT32 type, const void *data,
* @return An avi_error.
*/
-static avi_error write_initial_headers(avi_file *file)
+avi_file::error avi_file_impl::write_initial_headers()
{
- avi_error avierr;
- int strnum;
+ error avierr;
/* reset the write pointer */
- file->writeoffs = 0;
+ m_writeoffs = 0;
/* open a RIFF chunk */
- avierr = chunk_open(file, CHUNKTYPE_RIFF, LISTTYPE_AVI, 0);
- if (avierr != AVIERR_NONE)
+ avierr = chunk_open(CHUNKTYPE_RIFF, LISTTYPE_AVI, 0);
+ if (avierr != error::NONE)
return avierr;
/* open a hdlr LIST */
- avierr = chunk_open(file, CHUNKTYPE_LIST, LISTTYPE_HDRL, 0);
- if (avierr != AVIERR_NONE)
+ avierr = chunk_open(CHUNKTYPE_LIST, LISTTYPE_HDRL, 0);
+ if (avierr != error::NONE)
return avierr;
/* write an avih chunk */
- avierr = write_avih_chunk(file, TRUE);
- if (avierr != AVIERR_NONE)
+ avierr = write_avih_chunk(true);
+ if (avierr != error::NONE)
return avierr;
/* for each stream, write a strl LIST */
- for (strnum = 0; strnum < file->streams; strnum++)
+ for (int strnum = 0; strnum < m_streams.size(); strnum++)
{
/* open a strl LIST */
- avierr = chunk_open(file, CHUNKTYPE_LIST, LISTTYPE_STRL, 0);
- if (avierr != AVIERR_NONE)
+ avierr = chunk_open(CHUNKTYPE_LIST, LISTTYPE_STRL, 0);
+ if (avierr != error::NONE)
return avierr;
/* write the strh chunk */
- avierr = write_strh_chunk(file, &file->stream[strnum], TRUE);
- if (avierr != AVIERR_NONE)
+ avierr = write_strh_chunk(m_streams[strnum], true);
+ if (avierr != error::NONE)
return avierr;
/* write the strf chunk */
- avierr = write_strf_chunk(file, &file->stream[strnum]);
- if (avierr != AVIERR_NONE)
+ avierr = write_strf_chunk(m_streams[strnum]);
+ if (avierr != error::NONE)
return avierr;
/* write the indx chunk */
- avierr = write_indx_chunk(file, &file->stream[strnum], TRUE);
- if (avierr != AVIERR_NONE)
+ avierr = write_indx_chunk(m_streams[strnum], true);
+ if (avierr != error::NONE)
return avierr;
/* close the strl LIST */
- avierr = chunk_close(file);
- if (avierr != AVIERR_NONE)
+ avierr = chunk_close();
+ if (avierr != error::NONE)
return avierr;
}
/* close the hdlr LIST */
- avierr = chunk_close(file);
- if (avierr != AVIERR_NONE)
+ avierr = chunk_close();
+ if (avierr != error::NONE)
return avierr;
/* open a movi LIST */
- file->saved_movi_offset = file->writeoffs;
- avierr = chunk_open(file, CHUNKTYPE_LIST, LISTTYPE_MOVI, 0);
- if (avierr != AVIERR_NONE)
+ m_saved_movi_offset = m_writeoffs;
+ avierr = chunk_open(CHUNKTYPE_LIST, LISTTYPE_MOVI, 0);
+ if (avierr != error::NONE)
return avierr;
return avierr;
@@ -2648,23 +2945,23 @@ static avi_error write_initial_headers(avi_file *file)
* @return An avi_error.
*/
-static avi_error write_avih_chunk(avi_file *file, int initial_write)
+avi_file::error avi_file_impl::write_avih_chunk(bool initial_write)
{
- avi_stream *video = get_video_stream(file);
- UINT8 buffer[56];
+ avi_stream *video = get_video_stream();
+ std::uint8_t buffer[56];
/* reset the buffer */
- memset(buffer, 0, sizeof(buffer));
+ std::memset(buffer, 0, sizeof(buffer));
- put_32bits(&buffer[0], 1000000 * (INT64)video->scale / video->rate); /* dwMicroSecPerFrame */
+ put_32bits(&buffer[0], 1000000 * std::int64_t(video->scale()) / video->rate()); /* dwMicroSecPerFrame */
put_32bits(&buffer[12], AVIF_HASINDEX | AVIF_ISINTERLEAVED); /* dwFlags */
- put_32bits(&buffer[16], video->samples); /* dwTotalFrames */
- put_32bits(&buffer[24], file->streams); /* dwStreams */
- put_32bits(&buffer[32], video->width); /* dwWidth */
- put_32bits(&buffer[36], video->height); /* dwHeight */
+ put_32bits(&buffer[16], video->samples()); /* dwTotalFrames */
+ put_32bits(&buffer[24], m_streams.size()); /* dwStreams */
+ put_32bits(&buffer[32], video->width()); /* dwWidth */
+ put_32bits(&buffer[36], video->height()); /* dwHeight */
/* (over)write the chunk */
- return chunk_overwrite(file, CHUNKTYPE_AVIH, buffer, sizeof(buffer), &file->saved_avih_offset, initial_write);
+ return chunk_overwrite(CHUNKTYPE_AVIH, buffer, sizeof(buffer), m_saved_avih_offset, initial_write);
}
@@ -2685,41 +2982,41 @@ static avi_error write_avih_chunk(avi_file *file, int initial_write)
* @return An avi_error.
*/
-static avi_error write_strh_chunk(avi_file *file, avi_stream *stream, int initial_write)
+avi_file::error avi_file_impl::write_strh_chunk(avi_stream &stream, bool initial_write)
{
- UINT8 buffer[56];
+ std::uint8_t buffer[56];
/* reset the buffer */
- memset(buffer, 0, sizeof(buffer));
+ std::memset(buffer, 0, sizeof(buffer));
- put_32bits(&buffer[0], stream->type); /* fccType */
- put_32bits(&buffer[20], stream->scale); /* dwScale */
- put_32bits(&buffer[24], stream->rate); /* dwRate */
- put_32bits(&buffer[32], stream->samples); /* dwLength */
+ put_32bits(&buffer[0], stream.type()); /* fccType */
+ put_32bits(&buffer[20], stream.scale()); /* dwScale */
+ put_32bits(&buffer[24], stream.rate()); /* dwRate */
+ put_32bits(&buffer[32], stream.samples()); /* dwLength */
put_32bits(&buffer[40], 10000); /* dwQuality */
/* video-stream specific data */
- if (stream->type == STREAMTYPE_VIDS)
+ if (stream.type() == STREAMTYPE_VIDS)
{
put_32bits(&buffer[4], /* fccHandler */
- (stream->format == FORMAT_HFYU) ? HANDLER_HFYU : HANDLER_DIB);
+ (stream.format() == FORMAT_HFYU) ? HANDLER_HFYU : HANDLER_DIB);
put_32bits(&buffer[36], /* dwSuggestedBufferSize */
- stream->width * stream->height * 4);
- put_16bits(&buffer[52], stream->width); /* rcFrame.right */
- put_16bits(&buffer[54], stream->height); /* rcFrame.bottom */
+ stream.width() * stream.height() * 4);
+ put_16bits(&buffer[52], stream.width()); /* rcFrame.right */
+ put_16bits(&buffer[54], stream.height()); /* rcFrame.bottom */
}
/* audio-stream specific data */
- if (stream->type == STREAMTYPE_AUDS)
+ if (stream.type() == STREAMTYPE_AUDS)
{
put_32bits(&buffer[36], /* dwSuggestedBufferSize */
- stream->samplerate * stream->channels * (stream->samplebits / 8));
+ stream.samplerate() * stream.bytes_per_sample());
put_32bits(&buffer[44], /* dwSampleSize */
- stream->channels * (stream->samplebits / 8));
+ stream.bytes_per_sample());
}
/* write the chunk */
- return chunk_overwrite(file, CHUNKTYPE_STRH, buffer, sizeof(buffer), &stream->saved_strh_offset, initial_write);
+ return chunk_overwrite(CHUNKTYPE_STRH, buffer, sizeof(buffer), stream.saved_strh_offset(), initial_write);
}
@@ -2739,51 +3036,51 @@ static avi_error write_strh_chunk(avi_file *file, avi_stream *stream, int initia
* @return An avi_error.
*/
-static avi_error write_strf_chunk(avi_file *file, avi_stream *stream)
+avi_file::error avi_file_impl::write_strf_chunk(avi_stream const &stream)
{
/* video stream */
- if (stream->type == STREAMTYPE_VIDS)
+ if (stream.type() == STREAMTYPE_VIDS)
{
- UINT8 buffer[40];
+ std::uint8_t buffer[40];
/* reset the buffer */
- memset(buffer, 0, sizeof(buffer));
+ std::memset(buffer, 0, sizeof(buffer));
put_32bits(&buffer[0], sizeof(buffer)); /* biSize */
- put_32bits(&buffer[4], stream->width); /* biWidth */
- put_32bits(&buffer[8], stream->height); /* biHeight */
+ put_32bits(&buffer[4], stream.width()); /* biWidth */
+ put_32bits(&buffer[8], stream.height()); /* biHeight */
put_16bits(&buffer[12], 1); /* biPlanes */
- put_16bits(&buffer[14], stream->depth); /* biBitCount */
- put_32bits(&buffer[16], stream->format); /* biCompression */
+ put_16bits(&buffer[14], stream.depth()); /* biBitCount */
+ put_32bits(&buffer[16], stream.format()); /* biCompression */
put_32bits(&buffer[20], /* biSizeImage */
- stream->width * stream->height * (stream->depth + 7) / 8);
+ stream.width() * stream.height() * (stream.depth() + 7) / 8);
/* write the chunk */
- return chunk_write(file, CHUNKTYPE_STRF, buffer, sizeof(buffer));
+ return chunk_write(CHUNKTYPE_STRF, buffer, sizeof(buffer));
}
/* audio stream */
- if (stream->type == STREAMTYPE_AUDS)
+ if (stream.type() == STREAMTYPE_AUDS)
{
- UINT8 buffer[16];
+ std::uint8_t buffer[16];
/* reset the buffer */
- memset(buffer, 0, sizeof(buffer));
+ std::memset(buffer, 0, sizeof(buffer));
put_16bits(&buffer[0], 1); /* wFormatTag */
- put_16bits(&buffer[2], stream->channels); /* nChannels */
- put_32bits(&buffer[4], stream->samplerate); /* nSamplesPerSec */
+ put_16bits(&buffer[2], stream.channels()); /* nChannels */
+ put_32bits(&buffer[4], stream.samplerate()); /* nSamplesPerSec */
put_32bits(&buffer[8], /* nAvgBytesPerSec */
- stream->samplerate * stream->channels * (stream->samplebits / 8));
+ stream.samplerate() * stream.bytes_per_sample());
put_16bits(&buffer[12], /* nBlockAlign */
- stream->channels * (stream->samplebits / 8));
- put_16bits(&buffer[14], stream->samplebits); /* wBitsPerSample */
+ stream.bytes_per_sample());
+ put_16bits(&buffer[14], stream.samplebits()); /* wBitsPerSample */
/* write the chunk */
- return chunk_write(file, CHUNKTYPE_STRF, buffer, sizeof(buffer));
+ return chunk_write(CHUNKTYPE_STRF, buffer, sizeof(buffer));
}
- return AVIERR_INVALID_DATA;
+ return error::INVALID_DATA;
}
@@ -2804,35 +3101,30 @@ static avi_error write_strf_chunk(avi_file *file, avi_stream *stream)
* @return An avi_error.
*/
-static avi_error write_indx_chunk(avi_file *file, avi_stream *stream, int initial_write)
+avi_file::error avi_file_impl::write_indx_chunk(avi_stream &stream, bool initial_write)
{
- UINT8 buffer[24 + 16 * MAX_AVI_SIZE_IN_GB / 4];
- UINT32 chunkid, indexchunkid;
- UINT32 master_entries = 0;
+ std::uint8_t buffer[24 + 16 * MAX_AVI_SIZE_IN_GB / 4];
+ std::uint32_t master_entries = 0;
/* reset the buffer */
- memset(buffer, 0, sizeof(buffer));
+ std::memset(buffer, 0, sizeof(buffer));
/* construct the chunk ID and index chunk ID */
- chunkid = get_chunkid_for_stream(file, stream);
- indexchunkid = AVI_FOURCC('i', 'x', '0' + (stream - file->stream) / 10, '0' + (stream - file->stream) % 10);
+ std::uint32_t const chunkid = get_chunkid_for_stream(&stream);
+ std::uint32_t const indexchunkid = AVI_FOURCC('i', 'x', '0' + (&stream - &m_streams[0]) / 10, '0' + (&stream - &m_streams[0]) % 10);
/* loop over chunks of 4GB and write out indexes for them first */
- if (!initial_write && file->riffbase != 0)
+ if (!initial_write && m_riffbase != 0)
{
- UINT64 currentbase;
- for (currentbase = 0; currentbase < file->writeoffs; currentbase += FOUR_GB)
+ for (std::uint64_t currentbase = 0; currentbase < m_writeoffs; currentbase += FOUR_GB)
{
- UINT64 currentend = currentbase + FOUR_GB;
- UINT32 chunks_this_index = 0;
- UINT32 bytes_this_index = 0;
- avi_error avierr;
- UINT32 chunknum;
- UINT8 *tempbuf;
+ std::uint64_t const currentend = currentbase + FOUR_GB;
+ std::uint32_t chunks_this_index = 0;
+ std::uint32_t bytes_this_index = 0;
/* count chunks that are in this region */
- for (chunknum = 0; chunknum < stream->chunks; chunknum++)
- if (stream->chunk[chunknum].offset >= currentbase && stream->chunk[chunknum].offset < currentend)
+ for (std::uint32_t chunknum = 0; chunknum < stream.chunks(); chunknum++)
+ if (stream.chunk(chunknum).offset >= currentbase && stream.chunk(chunknum).offset < currentend)
chunks_this_index++;
/* if no chunks, skip */
@@ -2840,10 +3132,10 @@ static avi_error write_indx_chunk(avi_file *file, avi_stream *stream, int initia
continue;
/* allocate memory */
- tempbuf = (UINT8 *)malloc(24 + 8 * chunks_this_index);
- if (tempbuf == nullptr)
- return AVIERR_NO_MEMORY;
- memset(tempbuf, 0, 24 + 8 * chunks_this_index);
+ std::unique_ptr<std::uint8_t []> tempbuf;
+ try { tempbuf.reset(new std::uint8_t[24 + 8 * chunks_this_index]); }
+ catch (...) { return error::NO_MEMORY; }
+ std::memset(&tempbuf[0], 0, 24 + 8 * chunks_this_index);
/* make a regular index */
put_16bits(&tempbuf[0], 2); /* wLongsPerEntry */
@@ -2855,28 +3147,27 @@ static avi_error write_indx_chunk(avi_file *file, avi_stream *stream, int initia
/* now fill in the indexes */
chunks_this_index = 0;
- for (chunknum = 0; chunknum < stream->chunks; chunknum++)
- if (stream->chunk[chunknum].offset >= currentbase && stream->chunk[chunknum].offset < currentend)
+ for (std::uint32_t chunknum = 0; chunknum < stream.chunks(); chunknum++)
+ if (stream.chunk(chunknum).offset >= currentbase && stream.chunk(chunknum).offset < currentend)
{
- put_32bits(&tempbuf[24 + 8 * chunks_this_index + 0], stream->chunk[chunknum].offset + 8 - currentbase);
- put_32bits(&tempbuf[24 + 8 * chunks_this_index + 4], stream->chunk[chunknum].length - 8);
- bytes_this_index += stream->chunk[chunknum].length;
+ put_32bits(&tempbuf[24 + 8 * chunks_this_index + 0], stream.chunk(chunknum).offset + 8 - currentbase);
+ put_32bits(&tempbuf[24 + 8 * chunks_this_index + 4], stream.chunk(chunknum).length - 8);
+ bytes_this_index += stream.chunk(chunknum).length;
chunks_this_index++;
}
/* write the offset of this index to the master table */
- put_64bits(&buffer[24 + 16 * master_entries + 0], file->writeoffs);
+ put_64bits(&buffer[24 + 16 * master_entries + 0], m_writeoffs);
put_32bits(&buffer[24 + 16 * master_entries + 8], 24 + 8 * chunks_this_index + 8);
- if (stream->type == STREAMTYPE_VIDS)
+ if (stream.type() == STREAMTYPE_VIDS)
put_32bits(&buffer[24 + 16 * master_entries + 12], chunks_this_index);
- else if (stream->type == STREAMTYPE_AUDS)
- put_32bits(&buffer[24 + 16 * master_entries + 12], bytes_this_index / ((stream->samplebits / 8) * stream->channels));
+ else if (stream.type() == STREAMTYPE_AUDS)
+ put_32bits(&buffer[24 + 16 * master_entries + 12], bytes_this_index / stream.bytes_per_sample());
master_entries++;
/* write the index */
- avierr = chunk_write(file, indexchunkid, tempbuf, 24 + 8 * chunks_this_index);
- free(tempbuf);
- if (avierr != AVIERR_NONE)
+ error const avierr = chunk_write(indexchunkid, &tempbuf[0], 24 + 8 * chunks_this_index);
+ if (avierr != error::NONE)
return avierr;
}
}
@@ -2892,7 +3183,7 @@ static avi_error write_indx_chunk(avi_file *file, avi_stream *stream, int initia
}
/* (over)write the chunk */
- return chunk_overwrite(file, (master_entries == 0) ? CHUNKTYPE_JUNK : CHUNKTYPE_INDX, buffer, sizeof(buffer), &stream->saved_indx_offset, initial_write);
+ return chunk_overwrite((master_entries == 0) ? CHUNKTYPE_JUNK : CHUNKTYPE_INDX, buffer, sizeof(buffer), stream.saved_indx_offset(), initial_write);
}
@@ -2910,47 +3201,42 @@ static avi_error write_indx_chunk(avi_file *file, avi_stream *stream, int initia
* @return An avi_error.
*/
-static avi_error write_idx1_chunk(avi_file *file)
+avi_file::error avi_file_impl::write_idx1_chunk()
{
- UINT32 tempbuflength = compute_idx1_size(file) - 8;
- UINT32 curchunk[2] = { 0 };
- UINT32 curoffset;
- avi_error avierr;
- UINT8 *tempbuf;
+ std::uint32_t const tempbuflength = compute_idx1_size() - 8;
+ std::uint32_t curchunk[2] = { 0 };
/* allocate a temporary buffer */
- tempbuf = (UINT8 *)malloc(tempbuflength);
- if (tempbuf == nullptr)
- return AVIERR_NO_MEMORY;
+ std::unique_ptr<std::uint8_t []> tempbuf;
+ try { tempbuf.reset(new std::uint8_t[tempbuflength]); }
+ catch (...) { return error::NO_MEMORY; }
/* fill it in */
- for (curoffset = 0; curoffset < tempbuflength; curoffset += 16)
+ for (std::uint32_t curoffset = 0; curoffset < tempbuflength; curoffset += 16)
{
- UINT64 minoffset = ~(UINT64)0;
- int strnum, minstr = 0;
+ std::uint64_t minoffset = ~std::uint64_t(0);
+ int minstr = 0;
/* determine which stream has the next chunk */
- for (strnum = 0; strnum < file->streams; strnum++)
- if (curchunk[strnum] < file->stream[strnum].chunks && file->stream[strnum].chunk[curchunk[strnum]].offset < minoffset)
+ for (int strnum = 0; strnum < m_streams.size(); strnum++)
+ if (curchunk[strnum] < m_streams[strnum].chunks() && m_streams[strnum].chunk(curchunk[strnum]).offset < minoffset)
{
- minoffset = file->stream[strnum].chunk[curchunk[strnum]].offset;
+ minoffset = m_streams[strnum].chunk(curchunk[strnum]).offset;
minstr = strnum;
}
/* make an entry for this index */
- put_32bits(&tempbuf[curoffset + 0], get_chunkid_for_stream(file, &file->stream[minstr]));
+ put_32bits(&tempbuf[curoffset + 0], get_chunkid_for_stream(&m_streams[minstr]));
put_32bits(&tempbuf[curoffset + 4], 0x0010 /* AVIIF_KEYFRAME */);
- put_32bits(&tempbuf[curoffset + 8], minoffset - (file->saved_movi_offset + 8));
- put_32bits(&tempbuf[curoffset + 12], file->stream[minstr].chunk[curchunk[minstr]].length - 8);
+ put_32bits(&tempbuf[curoffset + 8], minoffset - (m_saved_movi_offset + 8));
+ put_32bits(&tempbuf[curoffset + 12], m_streams[minstr].chunk(curchunk[minstr]).length - 8);
/* advance the chunk counter for this stream */
curchunk[minstr]++;
}
/* write the chunk */
- avierr = chunk_write(file, CHUNKTYPE_IDX1, tempbuf, tempbuflength);
- free(tempbuf);
- return avierr;
+ return chunk_write(CHUNKTYPE_IDX1, &tempbuf[0], tempbuflength);
}
@@ -2969,31 +3255,31 @@ static avi_error write_idx1_chunk(avi_file *file)
* @return An avi_error.
*/
-static avi_error soundbuf_initialize(avi_file *file)
+avi_file::error avi_file_impl::soundbuf_initialize()
{
- avi_stream *audio = get_audio_stream(file, 0, nullptr);
- avi_stream *video = get_video_stream(file);
+ int offset;
+ avi_stream *const audio = get_audio_stream(0, offset);
+ avi_stream *const video = get_video_stream();
/* we require a video stream */
if (video == nullptr)
- return AVIERR_UNSUPPORTED_VIDEO_FORMAT;
+ return error::UNSUPPORTED_VIDEO_FORMAT;
/* skip if no audio stream */
if (audio == nullptr)
- return AVIERR_NONE;
+ return error::NONE;
/* determine the number of samples we want in our buffer; 2 seconds should be enough */
- file->soundbuf_samples = file->info.audio_samplerate * SOUND_BUFFER_MSEC / 1000;
+ m_soundbuf_samples = m_info.audio_samplerate * SOUND_BUFFER_MSEC / 1000;
/* allocate a buffer */
- file->soundbuf = (INT16 *)malloc(file->soundbuf_samples * file->info.audio_channels * sizeof(file->soundbuf[0]));
- if (file->soundbuf == nullptr)
- return AVIERR_NO_MEMORY;
- memset(file->soundbuf, 0, file->soundbuf_samples * file->info.audio_channels * sizeof(file->soundbuf[0]));
+ m_soundbuf.clear();
+ try { m_soundbuf.resize(m_soundbuf_samples * m_info.audio_channels, 0); }
+ catch (...) { return error::NO_MEMORY; }
/* determine the number of frames to be ahead (0.75secs) */
- file->soundbuf_frames = ((UINT64)video->rate * 75) / ((UINT64)video->scale * 100) + 1;
- return AVIERR_NONE;
+ m_soundbuf_frames = (std::uint64_t(video->rate()) * 75) / (std::uint64_t(video->scale()) * 100) + 1;
+ return error::NONE;
}
@@ -3003,7 +3289,7 @@ static avi_error soundbuf_initialize(avi_file *file)
-------------------------------------------------*/
/**
- * @fn static avi_error soundbuf_write_chunk(avi_file *file, UINT32 framenum)
+ * @fn static avi_error soundbuf_write_chunk(avi_file *file, std::uint32_t framenum)
*
* @brief Soundbuf write chunk.
*
@@ -3013,30 +3299,30 @@ static avi_error soundbuf_initialize(avi_file *file)
* @return An avi_error.
*/
-static avi_error soundbuf_write_chunk(avi_file *file, UINT32 framenum)
+avi_file::error avi_file_impl::soundbuf_write_chunk(std::uint32_t framenum)
{
- avi_stream *stream = get_audio_stream(file, 0, nullptr);
- avi_error avierr;
- UINT32 length;
+ int offset;
+ avi_stream *const stream = get_audio_stream(0, offset);
+ std::uint32_t length;
/* skip if no audio stream */
if (stream == nullptr)
- return AVIERR_NONE;
+ return error::NONE;
/* determine the length of this chunk */
if (framenum == 0)
- length = framenum_to_samplenum(file, file->soundbuf_frames);
+ length = framenum_to_samplenum(m_soundbuf_frames);
else
- length = framenum_to_samplenum(file, framenum + 1 + file->soundbuf_frames) - framenum_to_samplenum(file, framenum + file->soundbuf_frames);
- length *= stream->channels * sizeof(INT16);
+ length = framenum_to_samplenum(framenum + 1 + m_soundbuf_frames) - framenum_to_samplenum(framenum + m_soundbuf_frames);
+ length *= stream->channels() * sizeof(std::int16_t);
/* then do the initial write */
- avierr = chunk_write(file, get_chunkid_for_stream(file, stream), file->soundbuf, length);
- if (avierr != AVIERR_NONE)
+ error const avierr = chunk_write(get_chunkid_for_stream(stream), &m_soundbuf[0], length);
+ if (avierr != error::NONE)
return avierr;
/* set the info for this new chunk */
- return set_stream_chunk_info(stream, stream->chunks, file->writeoffs - length - 8, length + 8);
+ return stream->set_chunk_info(stream->chunks(), m_writeoffs - length - 8, length + 8);
}
@@ -3056,36 +3342,35 @@ static avi_error soundbuf_write_chunk(avi_file *file, UINT32 framenum)
* @return An avi_error.
*/
-static avi_error soundbuf_flush(avi_file *file, int only_flush_full)
+avi_file::error avi_file_impl::soundbuf_flush(bool only_flush_full)
{
- avi_stream *stream = get_audio_stream(file, 0, nullptr);
- INT32 channelsamples = file->soundbuf_samples;
- INT32 processedsamples = 0;
- UINT32 bytes_per_sample;
- UINT32 finalchunks;
- avi_error avierr;
- UINT32 chunknum;
- UINT32 chunkid;
- int channel;
+ int offset;
+ avi_stream *const stream = get_audio_stream(0, offset);
+ std::int32_t channelsamples = m_soundbuf_samples;
+ std::int32_t processedsamples = 0;
+ std::uint32_t finalchunks;
+ error avierr;
+ std::uint32_t chunknum;
+ std::uint32_t chunkid;
/* skip if no stream */
if (stream == nullptr)
- return AVIERR_NONE;
+ return error::NONE;
/* get the chunk ID for this stream */
- chunkid = get_chunkid_for_stream(file, stream);
- bytes_per_sample = stream->channels * sizeof(INT16);
- finalchunks = stream->chunks;
+ chunkid = get_chunkid_for_stream(stream);
+ std::uint32_t const bytes_per_sample = stream->channels() * sizeof(std::int16_t);
+ finalchunks = stream->chunks();
/* find out how many samples we've accumulated */
- for (channel = 0; channel < stream->channels; channel++)
- channelsamples = MIN(channelsamples, file->soundbuf_chansamples[channel]);
+ for (int channel = 0; channel < stream->channels(); channel++)
+ channelsamples = (std::min<std::int32_t>)(channelsamples, m_soundbuf_chansamples[channel]);
/* loop over pending sound chunks */
- for (chunknum = file->soundbuf_chunks; chunknum < stream->chunks; chunknum++)
+ for (chunknum = m_soundbuf_chunks; chunknum < stream->chunks(); chunknum++)
{
- avi_chunk_list *chunk = &stream->chunk[chunknum];
- UINT32 chunksamples = (chunk->length - 8) / bytes_per_sample;
+ avi_chunk_list &chunk = stream->chunk(chunknum);
+ std::uint32_t const chunksamples = (chunk.length - 8) / bytes_per_sample;
/* stop if we don't have enough to satisfy this chunk */
if (only_flush_full && channelsamples < chunksamples)
@@ -3094,696 +3379,300 @@ static avi_error soundbuf_flush(avi_file *file, int only_flush_full)
/* if we don't have all the samples we need, pad with 0's */
if (channelsamples > 0 && channelsamples < chunksamples)
{
- if (processedsamples + chunksamples > file->soundbuf_samples)
- return AVIERR_EXCEEDED_SOUND_BUFFER;
- memset(&file->soundbuf[(processedsamples + channelsamples) * stream->channels], 0, (chunksamples - channelsamples) * bytes_per_sample);
+ if (processedsamples + chunksamples > m_soundbuf_samples)
+ return error::EXCEEDED_SOUND_BUFFER;
+ std::memset(&m_soundbuf[(processedsamples + channelsamples) * stream->channels()], 0, (chunksamples - channelsamples) * bytes_per_sample);
}
/* if we're completely out of samples, clear the buffer entirely and use the end */
else if (channelsamples <= 0)
{
- processedsamples = file->soundbuf_samples - chunksamples;
- memset(&file->soundbuf[processedsamples * stream->channels], 0, chunksamples * bytes_per_sample);
+ processedsamples = m_soundbuf_samples - chunksamples;
+ std::memset(&m_soundbuf[processedsamples * stream->channels()], 0, chunksamples * bytes_per_sample);
chunkid = CHUNKTYPE_JUNK;
finalchunks--;
}
/* copy the sample data in */
- avierr = chunk_overwrite(file, chunkid, &file->soundbuf[processedsamples * stream->channels], chunk->length - 8, &chunk->offset, FALSE);
- if (avierr != AVIERR_NONE)
+ avierr = chunk_overwrite(chunkid, &m_soundbuf[processedsamples * stream->channels()], chunk.length - 8, chunk.offset, false);
+ if (avierr != error::NONE)
return avierr;
/* add up the samples */
if (channelsamples > chunksamples)
- file->info.audio_numsamples = stream->samples += chunksamples;
+ m_info.audio_numsamples = stream->add_samples(chunksamples);
else if (channelsamples > 0)
- file->info.audio_numsamples = stream->samples += channelsamples;
+ m_info.audio_numsamples = stream->add_samples(channelsamples);
/* advance past those */
processedsamples += chunksamples;
channelsamples -= chunksamples;
- channelsamples = MAX(0, channelsamples);
+ channelsamples = (std::max)(0, channelsamples);
}
/* if we have a non-zero offset, shift everything down */
if (processedsamples > 0)
{
/* first account for the samples we processed */
- memmove(&file->soundbuf[0], &file->soundbuf[processedsamples * stream->channels], (file->soundbuf_samples - processedsamples) * bytes_per_sample);
- for (channel = 0; channel < stream->channels; channel++)
- file->soundbuf_chansamples[channel] -= processedsamples;
+ std::memmove(&m_soundbuf[0], &m_soundbuf[processedsamples * stream->channels()], (m_soundbuf_samples - processedsamples) * bytes_per_sample);
+ for (int channel = 0; channel < stream->channels(); channel++)
+ m_soundbuf_chansamples[channel] -= processedsamples;
}
/* update the final chunk count */
if (!only_flush_full)
- stream->chunks = finalchunks;
+ stream->set_chunks(finalchunks);
/* account for flushed chunks */
- file->soundbuf_chunks = chunknum;
- return AVIERR_NONE;
+ m_soundbuf_chunks = chunknum;
+ return error::NONE;
}
/*-------------------------------------------------
- rgb32_compress_to_rgb - "compress" an RGB32
- bitmap to an RGB encoded frame
+ printf_chunk_recursive - print information
+ about a chunk recursively
-------------------------------------------------*/
/**
- * @fn static avi_error rgb32_compress_to_rgb(avi_stream *stream, const bitmap_rgb32 &bitmap, UINT8 *data, UINT32 numbytes)
- *
- * @brief RGB 32 compress to RGB.
+ * @fn static void printf_chunk_recursive(avi_file *file, avi_chunk *container, int indent)
*
- * @param [in,out] stream If non-null, the stream.
- * @param bitmap The bitmap.
- * @param [in,out] data If non-null, the data.
- * @param numbytes The numbytes.
+ * @brief Printf chunk recursive.
*
- * @return An avi_error.
+ * @param [in,out] file If non-null, the file.
+ * @param [in,out] container If non-null, the container.
+ * @param indent The indent.
*/
-static avi_error rgb32_compress_to_rgb(avi_stream *stream, const bitmap_rgb32 &bitmap, UINT8 *data, UINT32 numbytes)
+void avi_file_impl::printf_chunk_recursive(avi_chunk const *container, int indent)
{
- int height = MIN(stream->height, bitmap.height());
- int width = MIN(stream->width, bitmap.width());
- UINT8 *dataend = data + numbytes;
- int x, y;
+ char size[20], offset[20];
+ avi_chunk curchunk;
+ error avierr;
- /* compressed video */
- for (y = 0; y < height; y++)
+ /* iterate over chunks in this container */
+ for (avierr = get_first_chunk(container, curchunk); avierr == error::NONE; avierr = get_next_chunk(container, curchunk))
{
- const UINT32 *source = &bitmap.pix32(y);
- UINT8 *dest = data + (stream->height - 1 - y) * stream->width * 3;
-
- for (x = 0; x < width && dest < dataend; x++)
- {
- rgb_t pix = *source++;
- *dest++ = pix.b();
- *dest++ = pix.g();
- *dest++ = pix.r();
- }
+ std::uint32_t chunksize = curchunk.size;
+ bool recurse = false;
- /* fill in any blank space on the right */
- for ( ; x < stream->width && dest < dataend; x++)
- {
- *dest++ = 0;
- *dest++ = 0;
- *dest++ = 0;
- }
- }
+ u64toa(curchunk.size, size);
+ u64toa(curchunk.offset, offset);
+ printf("%*schunk = %c%c%c%c, size=%s (%s)\n", indent, "",
+ std::uint8_t(curchunk.type >> 0),
+ std::uint8_t(curchunk.type >> 8),
+ std::uint8_t(curchunk.type >> 16),
+ std::uint8_t(curchunk.type >> 24),
+ size, offset);
- /* fill in any blank space on the bottom */
- for ( ; y < stream->height; y++)
- {
- UINT8 *dest = data + (stream->height - 1 - y) * stream->width * 3;
- for (x = 0; x < stream->width && dest < dataend; x++)
+ /* certain chunks are just containers; recurse into them */
+ switch (curchunk.type)
{
- *dest++ = 0;
- *dest++ = 0;
- *dest++ = 0;
+ /* basic containers */
+ case CHUNKTYPE_RIFF:
+ case CHUNKTYPE_LIST:
+ printf("%*stype = %c%c%c%c\n", indent, "",
+ std::uint8_t(curchunk.listtype >> 0),
+ std::uint8_t(curchunk.listtype >> 8),
+ std::uint8_t(curchunk.listtype >> 16),
+ std::uint8_t(curchunk.listtype >> 24));
+ recurse = true;
+ chunksize = 0;
+ break;
}
- }
-
- return AVIERR_NONE;
-}
-
-
-/*-------------------------------------------------
- yuv_decompress_to_yuy16 - decompress a YUV
- encoded frame to a YUY16 bitmap
--------------------------------------------------*/
-
-/**
- * @fn static avi_error yuv_decompress_to_yuy16(avi_stream *stream, const UINT8 *data, UINT32 numbytes, bitmap_yuy16 &bitmap)
- *
- * @brief Yuv decompress to yuy 16.
- *
- * @param [in,out] stream If non-null, the stream.
- * @param data The data.
- * @param numbytes The numbytes.
- * @param [in,out] bitmap The bitmap.
- *
- * @return An avi_error.
- */
-static avi_error yuv_decompress_to_yuy16(avi_stream *stream, const UINT8 *data, UINT32 numbytes, bitmap_yuy16 &bitmap)
-{
- const UINT16 *dataend = (const UINT16 *)(data + numbytes);
- int x, y;
-
- /* compressed video */
- for (y = 0; y < stream->height; y++)
- {
- const UINT16 *source = (const UINT16 *)data + y * stream->width;
- UINT16 *dest = &bitmap.pix16(y);
-
- /* switch off the compression */
- switch (stream->format)
+ /* print data within the chunk */
+ if (chunksize > 0 && curchunk.size < 1024 * 1024)
{
- case FORMAT_UYVY:
- for (x = 0; x < stream->width && source < dataend; x++)
- *dest++ = *source++;
- break;
+ std::unique_ptr<std::uint8_t []> data;
- case FORMAT_VYUY:
- case FORMAT_YUY2:
- for (x = 0; x < stream->width && source < dataend; x++)
+ /* read the data for a chunk */
+ avierr = read_chunk_data(curchunk, data);
+ if (avierr == error::NONE)
+ {
+ std::uint32_t const bytes = (std::min)(std::uint32_t(512), chunksize);
+ for (std::uint32_t i = 0; i < bytes; i++)
{
- UINT16 pix = *source++;
- *dest++ = (pix >> 8) | (pix << 8);
+ if (i % 16 == 0) printf("%*s ", indent, "");
+ printf("%02X ", data[i]);
+ if (i % 16 == 15) printf("\n");
}
- break;
+ if (chunksize % 16 != 0) printf("\n");
+ }
}
+
+ /* if we're recursing, dive down */
+ if (recurse)
+ printf_chunk_recursive(&curchunk, indent + 4);
}
- return AVIERR_NONE;
+ /* if we didn't get a legitimate error, indicate that */
+ if (avierr != error::END)
+ printf("[chunk error %d]\n", int(avierr));
}
+} // anonymous namespace
+
+
+
+/***************************************************************************
+ IMPLEMENTATION
+***************************************************************************/
/*-------------------------------------------------
- yuy16_compress_to_yuy - "compress" a YUY16
- bitmap to a YUV encoded frame
+ avi_open - open an AVI movie file for read
-------------------------------------------------*/
/**
- * @fn static avi_error yuy16_compress_to_yuy(avi_stream *stream, const bitmap_yuy16 &bitmap, UINT8 *data, UINT32 numbytes)
+ * @fn avi_error avi_open(const char *filename, avi_file **file)
*
- * @brief Yuy 16 compress to yuy.
+ * @brief Queries if a given avi open.
*
- * @param [in,out] stream If non-null, the stream.
- * @param bitmap The bitmap.
- * @param [in,out] data If non-null, the data.
- * @param numbytes The numbytes.
+ * @param filename Filename of the file.
+ * @param [in,out] file If non-null, the file.
*
* @return An avi_error.
*/
-static avi_error yuy16_compress_to_yuy(avi_stream *stream, const bitmap_yuy16 &bitmap, UINT8 *data, UINT32 numbytes)
+avi_file::error avi_file::open(std::string const &filename, ptr &file)
{
- const UINT16 *dataend = (const UINT16 *)(data + numbytes);
- int x, y;
-
- /* compressed video */
- for (y = 0; y < stream->height; y++)
- {
- const UINT16 *source = &bitmap.pix16(y);
- UINT16 *dest = (UINT16 *)data + y * stream->width;
+ /* open the file */
+ osd_file::ptr f;
+ std::uint64_t length;
+ if (osd_file::open(filename, OPEN_FLAG_READ, f, length) != osd_file::error::NONE)
+ return error::CANT_OPEN_FILE;
- /* switch off the compression */
- switch (stream->format)
- {
- case FORMAT_UYVY:
- for (x = 0; x < stream->width && dest < dataend; x++)
- *dest++ = *source++;
- break;
+ /* allocate the file */
+ std::unique_ptr<avi_file_impl> newfile;
+ try { newfile = std::make_unique<avi_file_impl>(std::move(f), length); }
+ catch (...) { return error::NO_MEMORY; }
- case FORMAT_VYUY:
- case FORMAT_YUY2:
- for (x = 0; x < stream->width && dest < dataend; x++)
- {
- UINT16 pix = *source++;
- *dest++ = (pix >> 8) | (pix << 8);
- }
- break;
- }
- }
+ /* parse the data */
+ error const avierr = newfile->read_movie_data();
+ if (avierr != error::NONE)
+ return avierr;
- return AVIERR_NONE;
+ file = std::move(newfile);
+ return error::NONE;
}
/*-------------------------------------------------
- huffyuv_extract_tables - extract HuffYUV
- tables
+ avi_create - create a new AVI movie file
-------------------------------------------------*/
/**
- * @fn static avi_error huffyuv_extract_tables(avi_stream *stream, const UINT8 *chunkdata, UINT32 size)
+ * @fn avi_error avi_create(const char *filename, const avi_movie_info *info, avi_file **file)
*
- * @brief Huffyuv extract tables.
+ * @brief Avi create.
*
- * @param [in,out] stream If non-null, the stream.
- * @param chunkdata The chunkdata.
- * @param size The size.
+ * @param filename Filename of the file.
+ * @param info The information.
+ * @param [in,out] file If non-null, the file.
*
* @return An avi_error.
*/
-static avi_error huffyuv_extract_tables(avi_stream *stream, const UINT8 *chunkdata, UINT32 size)
+avi_file::error avi_file::create(std::string const &filename, movie_info const &info, ptr &file)
{
- const UINT8 *chunkend = chunkdata + size;
- avi_error avierr = AVIERR_NONE;
- int tabnum;
-
- /* allocate memory for the data */
- stream->huffyuv = (huffyuv_data *)malloc(sizeof(*stream->huffyuv));
- if (stream->huffyuv == nullptr)
- {
- avierr = AVIERR_NO_MEMORY;
- goto error;
- }
-
- /* extract predictor information */
- if (&chunkdata[40] >= chunkend)
- return AVIERR_INVALID_DATA;
- stream->huffyuv->predictor = chunkdata[40];
+ /* validate video info */
+ if ((info.video_format != 0 && info.video_format != FORMAT_UYVY && info.video_format != FORMAT_VYUY && info.video_format != FORMAT_YUY2) ||
+ (info.video_width == 0) ||
+ (info.video_height == 0) ||
+ (info.video_depth == 0) ||
+ (info.video_depth % 8 != 0))
+ return error::UNSUPPORTED_VIDEO_FORMAT;
- /* make sure it's the left predictor */
- if ((stream->huffyuv->predictor & ~HUFFYUV_PREDICT_DECORR) != HUFFYUV_PREDICT_LEFT)
- return AVIERR_UNSUPPORTED_VIDEO_FORMAT;
+ /* validate audio info */
+ if (info.audio_format != 0 ||
+ info.audio_channels > MAX_SOUND_CHANNELS ||
+ info.audio_samplebits != 16)
+ return error::UNSUPPORTED_AUDIO_FORMAT;
- /* make sure it's 16bpp YUV data */
- if (chunkdata[41] != 16)
- return AVIERR_UNSUPPORTED_VIDEO_FORMAT;
- chunkdata += 44;
+ /* open the file */
+ osd_file::ptr f;
+ std::uint64_t length;
+ osd_file::error const filerr = osd_file::open(filename, OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS, f, length);
+ if (filerr != osd_file::error::NONE)
+ return error::CANT_OPEN_FILE;
- /* loop over tables */
- for (tabnum = 0; tabnum < 3; tabnum++)
+ /* allocate the file */
+ error avierr;
+ std::unique_ptr<avi_file_impl> newfile;
+ try { newfile = std::make_unique<avi_file_impl>(std::move(f), info); }
+ catch (...)
{
- huffyuv_table *table = &stream->huffyuv->table[tabnum];
- UINT32 curbits, bitadd;
- UINT16 bitsat16 = 0;
- int offset = 0, bits;
-
- /* loop until we populate the whole table */
- while (offset < 256)
- {
- int data, shift, count, i;
-
- /* extract the next run */
- if (chunkdata >= chunkend)
- {
- avierr = AVIERR_INVALID_DATA;
- goto error;
- }
- data = *chunkdata++;
- shift = data & 0x1f;
- count = data >> 5;
-
- /* zero count means next whole byte is a count */
- if (count == 0)
- {
- if (chunkdata >= chunkend)
- {
- avierr = AVIERR_INVALID_DATA;
- goto error;
- }
- count = *chunkdata++;
- }
- for (i = 0; i < count; i++)
- table->shift[offset++] = shift;
- }
-
- /* now determine bit patterns and masks */
- curbits = 0;
- for (bits = 31; bits >= 0; bits--)
- {
- bitadd = 1 << (32 - bits);
-
- /* make sure we've cleared out all the bits below */
- if ((curbits & (bitadd - 1)) != 0)
- {
- avierr = AVIERR_INVALID_DATA;
- goto error;
- }
-
- /* find all entries with this shift count and assign them */
- for (offset = 0; offset < 256; offset++)
- if (table->shift[offset] == bits)
- {
- table->bits[offset] = curbits;
- table->mask[offset] = ~(bitadd - 1);
- curbits += bitadd;
- }
+ avierr = error::NO_MEMORY;
+ goto error;
+ }
- /* remember the bit pattern when we complete all the 17-bit codes */
- if (bits == 17)
- bitsat16 = curbits >> 16;
- }
+ /* initialize the sound buffering */
+ avierr = newfile->soundbuf_initialize();
+ if (avierr != error::NONE)
+ goto error;
- /* allocate the number of extra lookup tables we need */
- if (bitsat16 > 0)
- {
- table->extralookup = (UINT16 *)malloc(bitsat16 * 65536 * sizeof(table->extralookup[0]));
- if (table->extralookup == nullptr)
- {
- avierr = AVIERR_NO_MEMORY;
- goto error;
- }
- for (offset = 0; offset < bitsat16; offset++)
- table->baselookup[offset] = (offset << 8) | 0;
- }
+ /* write the initial headers */
+ avierr = newfile->write_initial_headers();
+ if (avierr != error::NONE)
+ goto error;
- /* then create lookup tables */
- for (offset = 0; offset < 256; offset++)
- if (table->shift[offset] > 16)
- {
- UINT16 *tablebase = table->extralookup + (table->bits[offset] >> 16) * 65536;
- UINT32 start = table->bits[offset] & 0xffff;
- UINT32 end = start + ((1 << (32 - table->shift[offset])) - 1);
- while (start <= end)
- tablebase[start++] = (offset << 8) | (table->shift[offset] - 16);
- }
- else if (table->shift[offset] > 0)
- {
- UINT32 start = table->bits[offset] >> 16;
- UINT32 end = start + ((1 << (16 - table->shift[offset])) - 1);
- while (start <= end)
- table->baselookup[start++] = (offset << 8) | table->shift[offset];
- }
- }
+ file = std::move(newfile);
+ return error::NONE;
error:
- if (avierr != AVIERR_NONE && stream->huffyuv != nullptr)
- {
- free(stream->huffyuv);
- stream->huffyuv = nullptr;
- }
+ f.reset();
+ newfile.reset();
+ osd_file::remove(filename);
return avierr;
}
/*-------------------------------------------------
- huffyuv_decompress_to_yuy16 - decompress a
- HuffYUV-encoded frame to a YUY16 bitmap
+ avi_error_string - get the error string for
+ an avi_error
-------------------------------------------------*/
/**
- * @fn static avi_error huffyuv_decompress_to_yuy16(avi_stream *stream, const UINT8 *data, UINT32 numbytes, bitmap_yuy16 &bitmap)
+ * @fn const char *avi_error_string(avi_error err)
*
- * @brief Huffyuv decompress to yuy 16.
+ * @brief Avi error string.
*
- * @param [in,out] stream If non-null, the stream.
- * @param data The data.
- * @param numbytes The numbytes.
- * @param [in,out] bitmap The bitmap.
+ * @param err The error.
*
- * @return An avi_error.
+ * @return null if it fails, else a char*.
*/
-static avi_error huffyuv_decompress_to_yuy16(avi_stream *stream, const UINT8 *data, UINT32 numbytes, bitmap_yuy16 &bitmap)
+const char *avi_file::error_string(error err)
{
- huffyuv_data *huffyuv = stream->huffyuv;
- int prevlines = (stream->height > 288) ? 2 : 1;
- UINT8 lastprevy = 0, lastprevcb = 0, lastprevcr = 0;
- UINT8 lasty = 0, lastcb = 0, lastcr = 0;
- UINT8 bitsinbuffer = 0;
- UINT32 bitbuffer = 0;
- UINT32 dataoffs = 0;
- int x, y;
-
- /* compressed video */
- for (y = 0; y < stream->height; y++)
- {
- UINT16 *dest = &bitmap.pix16(y);
-
- /* handle the first four bytes independently */
- x = 0;
- if (y == 0)
- {
- /* first DWORD is stored as YUY2 */
- lasty = data[dataoffs++];
- lastcb = data[dataoffs++];
- *dest++ = (lasty << 8) | lastcb;
- lasty = data[dataoffs++];
- lastcr = data[dataoffs++];
- *dest++ = (lasty << 8) | lastcr;
- x = 2;
- }
-
- /* loop over pixels */
- for ( ; x < stream->width; x++)
- {
- huffyuv_table *ytable = &huffyuv->table[0];
- huffyuv_table *ctable = &huffyuv->table[1 + (x & 1)];
- UINT16 pixel, huffdata;
- int shift;
-
- /* fill up the buffer; they store little-endian DWORDs, so we XOR with 3 */
- while (bitsinbuffer <= 24 && dataoffs < numbytes)
- {
- bitbuffer |= data[dataoffs++ ^ 3] << (24 - bitsinbuffer);
- bitsinbuffer += 8;
- }
-
- /* look up the Y component */
- huffdata = ytable->baselookup[bitbuffer >> 16];
- shift = huffdata & 0xff;
- if (shift == 0)
- {
- bitsinbuffer -= 16;
- bitbuffer <<= 16;
-
- /* fill up the buffer; they store little-endian DWORDs, so we XOR with 3 */
- while (bitsinbuffer <= 24 && dataoffs < numbytes)
- {
- bitbuffer |= data[dataoffs++ ^ 3] << (24 - bitsinbuffer);
- bitsinbuffer += 8;
- }
-
- huffdata = ytable->extralookup[(huffdata >> 8) * 65536 + (bitbuffer >> 16)];
- shift = huffdata & 0xff;
- }
- bitsinbuffer -= shift;
- bitbuffer <<= shift;
- pixel = huffdata & 0xff00;
-
- /* fill up the buffer; they store little-endian DWORDs, so we XOR with 3 */
- while (bitsinbuffer <= 24 && dataoffs < numbytes)
- {
- bitbuffer |= data[dataoffs++ ^ 3] << (24 - bitsinbuffer);
- bitsinbuffer += 8;
- }
-
- /* look up the Cb/Cr component */
- huffdata = ctable->baselookup[bitbuffer >> 16];
- shift = huffdata & 0xff;
- if (shift == 0)
- {
- bitsinbuffer -= 16;
- bitbuffer <<= 16;
-
- /* fill up the buffer; they store little-endian DWORDs, so we XOR with 3 */
- while (bitsinbuffer <= 24 && dataoffs < numbytes)
- {
- bitbuffer |= data[dataoffs++ ^ 3] << (24 - bitsinbuffer);
- bitsinbuffer += 8;
- }
-
- huffdata = ctable->extralookup[(huffdata >> 8) * 65536 + (bitbuffer >> 16)];
- shift = huffdata & 0xff;
- }
- bitsinbuffer -= shift;
- bitbuffer <<= shift;
- *dest++ = pixel | (huffdata >> 8);
- }
- }
-
- /* apply deltas */
- lastprevy = lastprevcb = lastprevcr = 0;
- for (y = 0; y < stream->height; y++)
+ switch (err)
{
- UINT16 *prevrow = &bitmap.pix16(y - prevlines);
- UINT16 *dest = &bitmap.pix16(y);
-
- /* handle the first four bytes independently */
- x = 0;
- if (y == 0)
- {
- /* lasty, lastcr, lastcb are set up previously */
- x = 2;
- }
-
- /* left predict or gradient predict */
- if ((huffyuv->predictor & ~HUFFYUV_PREDICT_DECORR) == HUFFYUV_PREDICT_LEFT ||
- ((huffyuv->predictor & ~HUFFYUV_PREDICT_DECORR) == HUFFYUV_PREDICT_GRADIENT))
- {
- /* first do left deltas */
- for ( ; x < stream->width; x += 2)
- {
- UINT16 pixel0 = dest[x + 0];
- UINT16 pixel1 = dest[x + 1];
-
- lasty += pixel0 >> 8;
- lastcb += pixel0;
- dest[x + 0] = (lasty << 8) | lastcb;
-
- lasty += pixel1 >> 8;
- lastcr += pixel1;
- dest[x + 1] = (lasty << 8) | lastcr;
- }
-
- /* for gradient, we then add in the previous row */
- if ((huffyuv->predictor & ~HUFFYUV_PREDICT_DECORR) == HUFFYUV_PREDICT_GRADIENT && y >= prevlines)
- for (x = 0; x < stream->width; x++)
- {
- UINT16 curpix = dest[x];
- UINT16 prevpix = prevrow[x];
- UINT8 ysum = (curpix >> 8) + (prevpix >> 8);
- UINT8 csum = curpix + prevpix;
- dest[x] = (ysum << 8) | csum;
- }
- }
-
- /* median predict on rows > 0 */
- else if ((huffyuv->predictor & ~HUFFYUV_PREDICT_DECORR) == HUFFYUV_PREDICT_MEDIAN && y >= prevlines)
- {
- for ( ; x < stream->width; x += 2)
- {
- UINT16 prevpixel0 = prevrow[x + 0];
- UINT16 prevpixel1 = prevrow[x + 1];
- UINT16 pixel0 = dest[x + 0];
- UINT16 pixel1 = dest[x + 1];
- UINT8 a, b, c;
-
- /* compute previous, above, and (prev + above - above-left) */
- a = lasty;
- b = prevpixel0 >> 8;
- c = lastprevy;
- lastprevy = b;
- if (a > b) { UINT8 tmp = a; a = b; b = tmp; }
- if (a > c) { UINT8 tmp = a; a = c; c = tmp; }
- if (b > c) { UINT8 tmp = b; b = c; c = tmp; }
- lasty = (pixel0 >> 8) + b;
-
- /* compute previous, above, and (prev + above - above-left) */
- a = lastcb;
- b = prevpixel0 & 0xff;
- c = lastprevcb;
- lastprevcb = b;
- if (a > b) { UINT8 tmp = a; a = b; b = tmp; }
- if (a > c) { UINT8 tmp = a; a = c; c = tmp; }
- if (b > c) { UINT8 tmp = b; b = c; c = tmp; }
- lastcb = (pixel0 & 0xff) + b;
- dest[x + 0] = (lasty << 8) | lastcb;
-
- /* compute previous, above, and (prev + above - above-left) */
- a = lasty;
- b = prevpixel1 >> 8;
- c = lastprevy;
- lastprevy = b;
- if (a > b) { UINT8 tmp = a; a = b; b = tmp; }
- if (a > c) { UINT8 tmp = a; a = c; c = tmp; }
- if (b > c) { UINT8 tmp = b; b = c; c = tmp; }
- lasty = (pixel1 >> 8) + b;
-
- /* compute previous, above, and (prev + above - above-left) */
- a = lastcr;
- b = prevpixel1 & 0xff;
- c = lastprevcr;
- lastprevcr = b;
- if (a > b) { UINT8 tmp = a; a = b; b = tmp; }
- if (a > c) { UINT8 tmp = a; a = c; c = tmp; }
- if (b > c) { UINT8 tmp = b; b = c; c = tmp; }
- lastcr = (pixel1 & 0xff) + b;
- dest[x + 1] = (lasty << 8) | lastcr;
- }
- }
+ case error::NONE: return "success";
+ case error::END: return "hit end of file";
+ case error::INVALID_DATA: return "invalid data";
+ case error::NO_MEMORY: return "out of memory";
+ case error::READ_ERROR: return "read error";
+ case error::WRITE_ERROR: return "write error";
+ case error::STACK_TOO_DEEP: return "stack overflow";
+ case error::UNSUPPORTED_FEATURE: return "unsupported feature";
+ case error::CANT_OPEN_FILE: return "unable to open file";
+ case error::INCOMPATIBLE_AUDIO_STREAMS: return "found incompatible audio streams";
+ case error::INVALID_SAMPLERATE: return "found invalid sample rate";
+ case error::INVALID_STREAM: return "invalid stream";
+ case error::INVALID_FRAME: return "invalid frame index";
+ case error::INVALID_BITMAP: return "invalid bitmap";
+ case error::UNSUPPORTED_VIDEO_FORMAT: return "unsupported video format";
+ case error::UNSUPPORTED_AUDIO_FORMAT: return "unsupported audio format";
+ case error::EXCEEDED_SOUND_BUFFER: return "sound buffer overflow";
+ default: return "undocumented error";
}
-
- return AVIERR_NONE;
}
-/**
- * @fn static void u64toa(UINT64 val, char *output)
- *
- * @brief 64toas.
- *
- * @param val The value.
- * @param [in,out] output If non-null, the output.
- */
-static void u64toa(UINT64 val, char *output)
+avi_file::avi_file()
{
- UINT32 lo = (UINT32)(val & 0xffffffff);
- UINT32 hi = (UINT32)(val >> 32);
- if (hi != 0)
- sprintf(output, "%X%08X", hi, lo);
- else
- sprintf(output, "%X", lo);
}
-/*-------------------------------------------------
- printf_chunk_recursive - print information
- about a chunk recursively
--------------------------------------------------*/
-
-/**
- * @fn static void printf_chunk_recursive(avi_file *file, avi_chunk *container, int indent)
- *
- * @brief Printf chunk recursive.
- *
- * @param [in,out] file If non-null, the file.
- * @param [in,out] container If non-null, the container.
- * @param indent The indent.
- */
-
-static void printf_chunk_recursive(avi_file *file, avi_chunk *container, int indent)
+avi_file::~avi_file()
{
- char size[20], offset[20];
- avi_chunk curchunk;
- int avierr;
-
- /* iterate over chunks in this container */
- for (avierr = get_first_chunk(file, container, &curchunk); avierr == AVIERR_NONE; avierr = get_next_chunk(file, container, &curchunk))
- {
- UINT32 chunksize = curchunk.size;
- int recurse = FALSE;
-
- u64toa(curchunk.size, size);
- u64toa(curchunk.offset, offset);
- printf("%*schunk = %c%c%c%c, size=%s (%s)\n", indent, "",
- (UINT8)(curchunk.type >> 0),
- (UINT8)(curchunk.type >> 8),
- (UINT8)(curchunk.type >> 16),
- (UINT8)(curchunk.type >> 24),
- size, offset);
-
- /* certain chunks are just containers; recurse into them */
- switch (curchunk.type)
- {
- /* basic containers */
- case CHUNKTYPE_RIFF:
- case CHUNKTYPE_LIST:
- printf("%*stype = %c%c%c%c\n", indent, "",
- (UINT8)(curchunk.listtype >> 0),
- (UINT8)(curchunk.listtype >> 8),
- (UINT8)(curchunk.listtype >> 16),
- (UINT8)(curchunk.listtype >> 24));
- recurse = TRUE;
- chunksize = 0;
- break;
- }
-
- /* print data within the chunk */
- if (chunksize > 0 && curchunk.size < 1024 * 1024)
- {
- UINT8 *data = nullptr;
- int i;
-
- /* read the data for a chunk */
- avierr = read_chunk_data(file, &curchunk, &data);
- if (avierr == AVIERR_NONE)
- {
- int bytes = MIN(512, chunksize);
- for (i = 0; i < bytes; i++)
- {
- if (i % 16 == 0) printf("%*s ", indent, "");
- printf("%02X ", data[i]);
- if (i % 16 == 15) printf("\n");
- }
- if (chunksize % 16 != 0) printf("\n");
- free(data);
- }
- }
-
- /* if we're recursing, dive down */
- if (recurse)
- printf_chunk_recursive(file, &curchunk, indent + 4);
- }
-
- /* if we didn't get a legitimate error, indicate that */
- if (avierr != AVIERR_END)
- printf("[chunk error %d]\n", avierr);
}
diff --git a/src/lib/util/aviio.h b/src/lib/util/aviio.h
index 86e2fd19cd2..c6d547903fe 100644
--- a/src/lib/util/aviio.h
+++ b/src/lib/util/aviio.h
@@ -1,5 +1,5 @@
// license:BSD-3-Clause
-// copyright-holders:Aaron Giles
+// copyright-holders:Aaron Giles, Vas Crabb
/***************************************************************************
aviio.h
@@ -8,52 +8,15 @@
***************************************************************************/
-#ifndef __AVIIO_H__
-#define __AVIIO_H__
+#ifndef MAME_LIB_UTIL_AVIIO_H
+#define MAME_LIB_UTIL_AVIIO_H
#include "osdcore.h"
#include "bitmap.h"
-
-/***************************************************************************
- CONSTANTS
-***************************************************************************/
-
-enum avi_error
-{
- AVIERR_NONE = 0,
- AVIERR_END,
- AVIERR_INVALID_DATA,
- AVIERR_NO_MEMORY,
- AVIERR_READ_ERROR,
- AVIERR_WRITE_ERROR,
- AVIERR_STACK_TOO_DEEP,
- AVIERR_UNSUPPORTED_FEATURE,
- AVIERR_CANT_OPEN_FILE,
- AVIERR_INCOMPATIBLE_AUDIO_STREAMS,
- AVIERR_INVALID_SAMPLERATE,
- AVIERR_INVALID_STREAM,
- AVIERR_INVALID_FRAME,
- AVIERR_INVALID_BITMAP,
- AVIERR_UNSUPPORTED_VIDEO_FORMAT,
- AVIERR_UNSUPPORTED_AUDIO_FORMAT,
- AVIERR_EXCEEDED_SOUND_BUFFER
-};
-
-
-enum avi_datatype
-{
- AVIDATA_VIDEO,
- AVIDATA_AUDIO_CHAN0,
- AVIDATA_AUDIO_CHAN1,
- AVIDATA_AUDIO_CHAN2,
- AVIDATA_AUDIO_CHAN3,
- AVIDATA_AUDIO_CHAN4,
- AVIDATA_AUDIO_CHAN5,
- AVIDATA_AUDIO_CHAN6,
- AVIDATA_AUDIO_CHAN7
-};
-
+#include <cstdint>
+#include <memory>
+#include <string>
/***************************************************************************
@@ -69,53 +32,98 @@ enum avi_datatype
-/***************************************************************************
- TYPE DEFINITIONS
-***************************************************************************/
-
-struct avi_file;
-
-
-struct avi_movie_info
+class avi_file
{
- UINT32 video_format; /* format of video data */
- UINT32 video_timescale; /* timescale for video data */
- UINT32 video_sampletime; /* duration of a single video sample (frame) */
- UINT32 video_numsamples; /* total number of video samples */
- UINT32 video_width; /* width of the video */
- UINT32 video_height; /* height of the video */
- UINT32 video_depth; /* depth of the video */
-
- UINT32 audio_format; /* format of audio data */
- UINT32 audio_timescale; /* timescale for audio data */
- UINT32 audio_sampletime; /* duration of a single audio sample */
- UINT32 audio_numsamples; /* total number of audio samples */
- UINT32 audio_channels; /* number of audio channels */
- UINT32 audio_samplebits; /* number of bits per channel */
- UINT32 audio_samplerate; /* sample rate of audio */
+public:
+
+ /***********************************************************************
+ CONSTANTS
+ ***********************************************************************/
+
+ enum class error
+ {
+ NONE = 0,
+ END,
+ INVALID_DATA,
+ NO_MEMORY,
+ READ_ERROR,
+ WRITE_ERROR,
+ STACK_TOO_DEEP,
+ UNSUPPORTED_FEATURE,
+ CANT_OPEN_FILE,
+ INCOMPATIBLE_AUDIO_STREAMS,
+ INVALID_SAMPLERATE,
+ INVALID_STREAM,
+ INVALID_FRAME,
+ INVALID_BITMAP,
+ UNSUPPORTED_VIDEO_FORMAT,
+ UNSUPPORTED_AUDIO_FORMAT,
+ EXCEEDED_SOUND_BUFFER
+ };
+
+ enum class datatype
+ {
+ VIDEO,
+ AUDIO_CHAN0,
+ AUDIO_CHAN1,
+ AUDIO_CHAN2,
+ AUDIO_CHAN3,
+ AUDIO_CHAN4,
+ AUDIO_CHAN5,
+ AUDIO_CHAN6,
+ AUDIO_CHAN7
+ };
+
+
+ /***********************************************************************
+ TYPE DEFINITIONS
+ ***********************************************************************/
+
+ struct movie_info
+ {
+ std::uint32_t video_format; // format of video data
+ std::uint32_t video_timescale; // timescale for video data
+ std::uint32_t video_sampletime; // duration of a single video sample (frame)
+ std::uint32_t video_numsamples; // total number of video samples
+ std::uint32_t video_width; // width of the video
+ std::uint32_t video_height; // height of the video
+ std::uint32_t video_depth; // depth of the video
+
+ std::uint32_t audio_format; // format of audio data
+ std::uint32_t audio_timescale; // timescale for audio data
+ std::uint32_t audio_sampletime; // duration of a single audio sample
+ std::uint32_t audio_numsamples; // total number of audio samples
+ std::uint32_t audio_channels; // number of audio channels
+ std::uint32_t audio_samplebits; // number of bits per channel
+ std::uint32_t audio_samplerate; // sample rate of audio
+ };
+
+ typedef std::unique_ptr<avi_file> ptr;
+
+
+ /***********************************************************************
+ PROTOTYPES
+ ***********************************************************************/
+
+ static error open(std::string const &filename, ptr &file);
+ static error create(std::string const &filename, movie_info const &info, ptr &file);
+ virtual ~avi_file();
+
+ virtual void printf_chunks() = 0;
+ static const char *error_string(error err);
+
+ virtual movie_info const &get_movie_info() const = 0;
+ virtual std::uint32_t first_sample_in_frame(std::uint32_t framenum) const = 0;
+
+ virtual error read_video_frame(std::uint32_t framenum, bitmap_yuy16 &bitmap) = 0;
+ virtual error read_sound_samples(int channel, std::uint32_t firstsample, std::uint32_t numsamples, std::int16_t *output) = 0;
+
+ virtual error append_video_frame(bitmap_yuy16 &bitmap) = 0;
+ virtual error append_video_frame(bitmap_rgb32 &bitmap) = 0;
+ virtual error append_sound_samples(int channel, std::int16_t const *samples, std::uint32_t numsamples, std::uint32_t sampleskip) = 0;
+
+protected:
+ avi_file();
};
-
-
-/***************************************************************************
- PROTOTYPES
-***************************************************************************/
-
-avi_error avi_open(const char *filename, avi_file **file);
-avi_error avi_create(const char *filename, const avi_movie_info *info, avi_file **file);
-avi_error avi_close(avi_file *file);
-
-void avi_printf_chunks(avi_file *file);
-const char *avi_error_string(avi_error err);
-
-const avi_movie_info *avi_get_movie_info(avi_file *file);
-UINT32 avi_first_sample_in_frame(avi_file *file, UINT32 framenum);
-
-avi_error avi_read_video_frame(avi_file *file, UINT32 framenum, bitmap_yuy16 &bitmap);
-avi_error avi_read_sound_samples(avi_file *file, int channel, UINT32 firstsample, UINT32 numsamples, INT16 *output);
-
-avi_error avi_append_video_frame(avi_file *file, bitmap_yuy16 &bitmap);
-avi_error avi_append_video_frame(avi_file *file, bitmap_rgb32 &bitmap);
-avi_error avi_append_sound_samples(avi_file *file, int channel, const INT16 *samples, UINT32 numsamples, UINT32 sampleskip);
-
-#endif
+#endif // MAME_LIB_UTIL_AVIIO_H
diff --git a/src/lib/util/cdrom.cpp b/src/lib/util/cdrom.cpp
index 8bdf4af6c0f..bd48a73d8d8 100644
--- a/src/lib/util/cdrom.cpp
+++ b/src/lib/util/cdrom.cpp
@@ -244,8 +244,8 @@ cdrom_file *cdrom_open(const char *inputfile)
for (i = 0; i < file->cdtoc.numtrks; i++)
{
- file_error filerr = util::core_file::open(file->track_info.track[i].fname.c_str(), OPEN_FLAG_READ, file->fhandle[i]);
- if (filerr != FILERR_NONE)
+ osd_file::error filerr = util::core_file::open(file->track_info.track[i].fname.c_str(), OPEN_FLAG_READ, file->fhandle[i]);
+ if (filerr != osd_file::error::NONE)
{
fprintf(stderr, "Unable to open file: %s\n", file->track_info.track[i].fname.c_str());
cdrom_close(file);
diff --git a/src/lib/util/chd.cpp b/src/lib/util/chd.cpp
index 93a1b34ba29..3a97c6ce0fe 100644
--- a/src/lib/util/chd.cpp
+++ b/src/lib/util/chd.cpp
@@ -660,8 +660,8 @@ chd_error chd_file::create(const char *filename, UINT64 logicalbytes, UINT32 hun
// create the new file
util::core_file::ptr file;
- const file_error filerr = util::core_file::open(filename, OPEN_FLAG_READ | OPEN_FLAG_WRITE | OPEN_FLAG_CREATE, file);
- if (filerr != FILERR_NONE)
+ const osd_file::error filerr = util::core_file::open(filename, OPEN_FLAG_READ | OPEN_FLAG_WRITE | OPEN_FLAG_CREATE, file);
+ if (filerr != osd_file::error::NONE)
return CHDERR_FILE_NOT_FOUND;
// create the file normally, then claim the file
@@ -672,7 +672,7 @@ chd_error chd_file::create(const char *filename, UINT64 logicalbytes, UINT32 hun
if (chderr != CHDERR_NONE)
{
file.reset();
- osd_rmfile(filename);
+ osd_file::remove(filename);
}
else
{
@@ -705,8 +705,8 @@ chd_error chd_file::create(const char *filename, UINT64 logicalbytes, UINT32 hun
// create the new file
util::core_file::ptr file;
- const file_error filerr = util::core_file::open(filename, OPEN_FLAG_READ | OPEN_FLAG_WRITE | OPEN_FLAG_CREATE, file);
- if (filerr != FILERR_NONE)
+ const osd_file::error filerr = util::core_file::open(filename, OPEN_FLAG_READ | OPEN_FLAG_WRITE | OPEN_FLAG_CREATE, file);
+ if (filerr != osd_file::error::NONE)
return CHDERR_FILE_NOT_FOUND;
// create the file normally, then claim the file
@@ -717,7 +717,7 @@ chd_error chd_file::create(const char *filename, UINT64 logicalbytes, UINT32 hun
if (chderr != CHDERR_NONE)
{
file.reset();
- osd_rmfile(filename);
+ osd_file::remove(filename);
}
else
{
@@ -749,8 +749,8 @@ chd_error chd_file::open(const char *filename, bool writeable, chd_file *parent)
// open the file
const UINT32 openflags = writeable ? (OPEN_FLAG_READ | OPEN_FLAG_WRITE) : OPEN_FLAG_READ;
util::core_file::ptr file;
- const file_error filerr = util::core_file::open(filename, openflags, file);
- if (filerr != FILERR_NONE)
+ const osd_file::error filerr = util::core_file::open(filename, openflags, file);
+ if (filerr != osd_file::error::NONE)
return CHDERR_FILE_NOT_FOUND;
// now open the CHD
diff --git a/src/lib/util/chdcd.cpp b/src/lib/util/chdcd.cpp
index eeb196d242f..0e8b32b1ed6 100644
--- a/src/lib/util/chdcd.cpp
+++ b/src/lib/util/chdcd.cpp
@@ -87,13 +87,10 @@ static std::string get_file_path(std::string &path)
static UINT64 get_file_size(const char *filename)
{
- osd_file *file;
- UINT64 filesize = 0;
- file_error filerr;
+ osd_file::ptr file;
+ std::uint64_t filesize = 0;
- filerr = osd_open(filename, OPEN_FLAG_READ, &file, &filesize);
- if (filerr == FILERR_NONE)
- osd_close(file);
+ osd_file::open(filename, OPEN_FLAG_READ, file, filesize);
return filesize;
}
@@ -215,57 +212,51 @@ static UINT32 parse_wav_sample(const char *filename, UINT32 *dataoffs)
UINT32 length, rate, filesize;
UINT16 bits, temp16;
char buf[32];
- osd_file *file;
- file_error filerr;
+ osd_file::ptr file;
UINT64 fsize = 0;
- UINT32 actual;
+ std::uint32_t actual;
- filerr = osd_open(filename, OPEN_FLAG_READ, &file, &fsize);
- if (filerr != FILERR_NONE)
+ osd_file::error filerr = osd_file::open(filename, OPEN_FLAG_READ, file, fsize);
+ if (filerr != osd_file::error::NONE)
{
printf("ERROR: could not open (%s)\n", filename);
return 0;
}
/* read the core header and make sure it's a WAVE file */
- osd_read(file, buf, 0, 4, &actual);
+ file->read(buf, 0, 4, actual);
offset += actual;
if (offset < 4)
{
- osd_close(file);
printf("ERROR: unexpected RIFF offset %lu (%s)\n", offset, filename);
return 0;
}
if (memcmp(&buf[0], "RIFF", 4) != 0)
{
- osd_close(file);
printf("ERROR: could not find RIFF header (%s)\n", filename);
return 0;
}
/* get the total size */
- osd_read(file, &filesize, offset, 4, &actual);
+ file->read(&filesize, offset, 4, actual);
offset += actual;
if (offset < 8)
{
- osd_close(file);
printf("ERROR: unexpected size offset %lu (%s)\n", offset, filename);
return 0;
}
filesize = LITTLE_ENDIANIZE_INT32(filesize);
/* read the RIFF file type and make sure it's a WAVE file */
- osd_read(file, buf, offset, 4, &actual);
+ file->read(buf, offset, 4, actual);
offset += actual;
if (offset < 12)
{
- osd_close(file);
printf("ERROR: unexpected WAVE offset %lu (%s)\n", offset, filename);
return 0;
}
if (memcmp(&buf[0], "WAVE", 4) != 0)
{
- osd_close(file);
printf("ERROR: could not find WAVE header (%s)\n", filename);
return 0;
}
@@ -273,9 +264,9 @@ static UINT32 parse_wav_sample(const char *filename, UINT32 *dataoffs)
/* seek until we find a format tag */
while (1)
{
- osd_read(file, buf, offset, 4, &actual);
+ file->read(buf, offset, 4, actual);
offset += actual;
- osd_read(file, &length, offset, 4, &actual);
+ file->read(&length, offset, 4, actual);
offset += actual;
length = LITTLE_ENDIANIZE_INT32(length);
if (memcmp(&buf[0], "fmt ", 4) == 0)
@@ -285,56 +276,51 @@ static UINT32 parse_wav_sample(const char *filename, UINT32 *dataoffs)
offset += length;
if (offset >= filesize)
{
- osd_close(file);
printf("ERROR: could not find fmt tag (%s)\n", filename);
return 0;
}
}
/* read the format -- make sure it is PCM */
- osd_read(file, &temp16, offset, 2, &actual);
+ file->read(&temp16, offset, 2, actual);
offset += actual;
temp16 = LITTLE_ENDIANIZE_INT16(temp16);
if (temp16 != 1)
{
- osd_close(file);
printf("ERROR: unsupported format %u - only PCM is supported (%s)\n", temp16, filename);
return 0;
}
/* number of channels -- only stereo is supported */
- osd_read(file, &temp16, offset, 2, &actual);
+ file->read(&temp16, offset, 2, actual);
offset += actual;
temp16 = LITTLE_ENDIANIZE_INT16(temp16);
if (temp16 != 2)
{
- osd_close(file);
printf("ERROR: unsupported number of channels %u - only stereo is supported (%s)\n", temp16, filename);
return 0;
}
/* sample rate */
- osd_read(file, &rate, offset, 4, &actual);
+ file->read(&rate, offset, 4, actual);
offset += actual;
rate = LITTLE_ENDIANIZE_INT32(rate);
if (rate != 44100)
{
- osd_close(file);
printf("ERROR: unsupported samplerate %u - only 44100 is supported (%s)\n", rate, filename);
return 0;
}
/* bytes/second and block alignment are ignored */
- osd_read(file, buf, offset, 6, &actual);
+ file->read(buf, offset, 6, actual);
offset += actual;
/* bits/sample */
- osd_read(file, &bits, offset, 2, &actual);
+ file->read(&bits, offset, 2, actual);
offset += actual;
bits = LITTLE_ENDIANIZE_INT16(bits);
if (bits != 16)
{
- osd_close(file);
printf("ERROR: unsupported bits/sample %u - only 16 is supported (%s)\n", bits, filename);
return 0;
}
@@ -345,9 +331,9 @@ static UINT32 parse_wav_sample(const char *filename, UINT32 *dataoffs)
/* seek until we find a data tag */
while (1)
{
- osd_read(file, buf, offset, 4, &actual);
+ file->read(buf, offset, 4, actual);
offset += actual;
- osd_read(file, &length, offset, 4, &actual);
+ file->read(&length, offset, 4, actual);
offset += actual;
length = LITTLE_ENDIANIZE_INT32(length);
if (memcmp(&buf[0], "data", 4) == 0)
@@ -357,14 +343,11 @@ static UINT32 parse_wav_sample(const char *filename, UINT32 *dataoffs)
offset += length;
if (offset >= filesize)
{
- osd_close(file);
printf("ERROR: could not find data tag (%s)\n", filename);
return 0;
}
}
- osd_close(file);
-
/* if there was a 0 length data block, we're done */
if (length == 0)
{
diff --git a/src/lib/util/corefile.cpp b/src/lib/util/corefile.cpp
index 64169a606fc..ec1e25340e3 100644
--- a/src/lib/util/corefile.cpp
+++ b/src/lib/util/corefile.cpp
@@ -23,9 +23,7 @@
namespace util {
-
namespace {
-
/***************************************************************************
VALIDATION
***************************************************************************/
@@ -143,7 +141,7 @@ class core_proxy_file : public core_file
public:
core_proxy_file(core_file &file) : m_file(file) { }
virtual ~core_proxy_file() override { }
- virtual file_error compress(int level) override { return m_file.compress(level); }
+ virtual osd_file::error compress(int level) override { return m_file.compress(level); }
virtual int seek(std::int64_t offset, int whence) override { return m_file.seek(offset, whence); }
virtual std::uint64_t tell() const override { return m_file.tell(); }
@@ -159,9 +157,9 @@ public:
virtual std::uint32_t write(const void *buffer, std::uint32_t length) override { return m_file.write(buffer, length); }
virtual int puts(const char *s) override { return m_file.puts(s); }
virtual int vprintf(util::format_argument_pack<std::ostream> const &args) override { return m_file.vprintf(args); }
- virtual file_error truncate(std::uint64_t offset) override { return m_file.truncate(offset); }
+ virtual osd_file::error truncate(std::uint64_t offset) override { return m_file.truncate(offset); }
- virtual file_error flush() override { return m_file.flush(); }
+ virtual osd_file::error flush() override { return m_file.flush(); }
private:
core_file &m_file;
@@ -232,7 +230,7 @@ public:
}
~core_in_memory_file() override { purge(); }
- virtual file_error compress(int level) override { return FILERR_INVALID_ACCESS; }
+ virtual osd_file::error compress(int level) override { return osd_file::error::INVALID_ACCESS; }
virtual int seek(std::int64_t offset, int whence) override;
virtual std::uint64_t tell() const override { return m_offset; }
@@ -243,8 +241,8 @@ public:
virtual void const *buffer() override { return m_data; }
virtual std::uint32_t write(void const *buffer, std::uint32_t length) override { return 0; }
- virtual file_error truncate(std::uint64_t offset) override;
- virtual file_error flush() override { clear_putback(); return FILERR_NONE; }
+ virtual osd_file::error truncate(std::uint64_t offset) override;
+ virtual osd_file::error flush() override { clear_putback(); return osd_file::error::NONE; }
protected:
core_in_memory_file(std::uint32_t openflags, std::uint64_t length)
@@ -295,9 +293,9 @@ private:
class core_osd_file : public core_in_memory_file
{
public:
- core_osd_file(std::uint32_t openmode, osd_file *file, std::uint64_t length)
+ core_osd_file(std::uint32_t openmode, osd_file::ptr &&file, std::uint64_t length)
: core_in_memory_file(openmode, length)
- , m_file(file)
+ , m_file(std::move(file))
, m_zdata()
, m_bufferbase(0)
, m_bufferbytes(0)
@@ -305,7 +303,7 @@ public:
}
~core_osd_file() override;
- virtual file_error compress(int level) override;
+ virtual osd_file::error compress(int level) override;
virtual int seek(std::int64_t offset, int whence) override;
@@ -313,8 +311,8 @@ public:
virtual void const *buffer() override;
virtual std::uint32_t write(void const *buffer, std::uint32_t length) override;
- virtual file_error truncate(std::uint64_t offset) override;
- virtual file_error flush() override;
+ virtual osd_file::error truncate(std::uint64_t offset) override;
+ virtual osd_file::error flush() override;
protected:
@@ -323,10 +321,10 @@ protected:
private:
static constexpr std::size_t FILE_BUFFER_SIZE = 512;
- file_error osd_or_zlib_read(void *buffer, std::uint64_t offset, std::uint32_t length, std::uint32_t &actual);
- file_error osd_or_zlib_write(void const *buffer, std::uint64_t offset, std::uint32_t length, std::uint32_t &actual);
+ osd_file::error osd_or_zlib_read(void *buffer, std::uint64_t offset, std::uint32_t length, std::uint32_t &actual);
+ osd_file::error osd_or_zlib_write(void const *buffer, std::uint64_t offset, std::uint32_t length, std::uint32_t &actual);
- osd_file * m_file; // OSD file handle
+ osd_file::ptr m_file; // OSD file handle
zlib_data::ptr m_zdata; // compression data
std::uint64_t m_bufferbase; // base offset of internal buffer
std::uint32_t m_bufferbytes; // bytes currently loaded into buffer
@@ -688,14 +686,14 @@ std::uint32_t core_in_memory_file::read(void *buffer, std::uint32_t length)
truncate - truncate a file
-------------------------------------------------*/
-file_error core_in_memory_file::truncate(std::uint64_t offset)
+osd_file::error core_in_memory_file::truncate(std::uint64_t offset)
{
if (m_length < offset)
- return FILERR_FAILURE;
+ return osd_file::error::FAILURE;
// adjust to new length and offset
set_length(offset);
- return FILERR_NONE;
+ return osd_file::error::NONE;
}
@@ -736,8 +734,6 @@ core_osd_file::~core_osd_file()
// close files and free memory
if (m_zdata)
compress(FCOMPRESS_NONE);
- if (m_file)
- osd_close(m_file);
}
@@ -747,13 +743,13 @@ core_osd_file::~core_osd_file()
compression, or up to 9 for max compression
-------------------------------------------------*/
-file_error core_osd_file::compress(int level)
+osd_file::error core_osd_file::compress(int level)
{
- file_error result = FILERR_NONE;
+ osd_file::error result = osd_file::error::NONE;
// can only do this for read-only and write-only cases
if (read_access() && write_access())
- return FILERR_INVALID_ACCESS;
+ return osd_file::error::INVALID_ACCESS;
// if we have been compressing, flush and free the data
if (m_zdata && (level == FCOMPRESS_NONE))
@@ -767,7 +763,7 @@ file_error core_osd_file::compress(int level)
zerr = m_zdata->finalise();
if ((zerr != Z_STREAM_END) && (zerr != Z_OK))
{
- result = FILERR_INVALID_DATA;
+ result = osd_file::error::INVALID_DATA;
break;
}
@@ -775,8 +771,8 @@ file_error core_osd_file::compress(int level)
if (m_zdata->has_output())
{
std::uint32_t actualdata;
- auto const filerr = osd_write(m_file, m_zdata->buffer_data(), m_zdata->realoffset(), m_zdata->output_size(), &actualdata);
- if (filerr != FILERR_NONE)
+ auto const filerr = m_file->write(m_zdata->buffer_data(), m_zdata->realoffset(), m_zdata->output_size(), actualdata);
+ if (filerr != osd_file::error::NONE)
break;
m_zdata->add_realoffset(actualdata);
m_zdata->reset_output();
@@ -800,7 +796,7 @@ file_error core_osd_file::compress(int level)
// on error, return an error
if (zerr != Z_OK)
- return FILERR_OUT_OF_MEMORY;
+ return osd_file::error::OUT_OF_MEMORY;
// flush buffers
m_bufferbytes = 0;
@@ -888,13 +884,12 @@ void const *core_osd_file::buffer()
// read the file
std::uint32_t read_length = 0;
auto const filerr = osd_or_zlib_read(buf, 0, length(), read_length);
- if ((filerr != FILERR_NONE) || (read_length != length()))
+ if ((filerr != osd_file::error::NONE) || (read_length != length()))
purge();
else
{
// close the file because we don't need it anymore
- osd_close(m_file);
- m_file = nullptr;
+ m_file.reset();
}
}
return core_in_memory_file::buffer();
@@ -931,19 +926,19 @@ std::uint32_t core_osd_file::write(void const *buffer, std::uint32_t length)
truncate - truncate a file
-------------------------------------------------*/
-file_error core_osd_file::truncate(std::uint64_t offset)
+osd_file::error core_osd_file::truncate(std::uint64_t offset)
{
if (is_loaded())
return core_in_memory_file::truncate(offset);
// truncate file
- auto const err = osd_truncate(m_file, offset);
- if (err != FILERR_NONE)
+ auto const err = m_file->truncate(offset);
+ if (err != osd_file::error::NONE)
return err;
// and adjust to new length and offset
set_length(offset);
- return FILERR_NONE;
+ return osd_file::error::NONE;
}
@@ -951,7 +946,7 @@ file_error core_osd_file::truncate(std::uint64_t offset)
flush - flush file buffers
-------------------------------------------------*/
-file_error core_osd_file::flush()
+osd_file::error core_osd_file::flush()
{
if (is_loaded())
return core_in_memory_file::flush();
@@ -962,7 +957,7 @@ file_error core_osd_file::flush()
// invalidate any buffered data
m_bufferbytes = 0;
- return osd_fflush(m_file);
+ return m_file->flush();
}
@@ -971,18 +966,18 @@ file_error core_osd_file::flush()
handles zlib-compressed data
-------------------------------------------------*/
-file_error core_osd_file::osd_or_zlib_read(void *buffer, std::uint64_t offset, std::uint32_t length, std::uint32_t &actual)
+osd_file::error core_osd_file::osd_or_zlib_read(void *buffer, std::uint64_t offset, std::uint32_t length, std::uint32_t &actual)
{
// if no compression, just pass through
if (!m_zdata)
- return osd_read(m_file, buffer, offset, length, &actual);
+ return m_file->read(buffer, offset, length, actual);
// if the offset doesn't match the next offset, fail
if (!m_zdata->is_nextoffset(offset))
- return FILERR_INVALID_ACCESS;
+ return osd_file::error::INVALID_ACCESS;
// set up the destination
- file_error filerr = FILERR_NONE;
+ osd_file::error filerr = osd_file::error::NONE;
m_zdata->set_output(buffer, length);
while (!m_zdata->output_full())
{
@@ -992,7 +987,7 @@ file_error core_osd_file::osd_or_zlib_read(void *buffer, std::uint64_t offset, s
auto const zerr = m_zdata->decompress();
if (Z_OK != zerr)
{
- if (Z_STREAM_END != zerr) filerr = FILERR_INVALID_DATA;
+ if (Z_STREAM_END != zerr) filerr = osd_file::error::INVALID_DATA;
break;
}
}
@@ -1001,8 +996,8 @@ file_error core_osd_file::osd_or_zlib_read(void *buffer, std::uint64_t offset, s
if (!m_zdata->has_input())
{
std::uint32_t actualdata = 0;
- filerr = osd_read(m_file, m_zdata->buffer_data(), m_zdata->realoffset(), m_zdata->buffer_size(), &actualdata);
- if (filerr != FILERR_NONE) break;
+ filerr = m_file->read(m_zdata->buffer_data(), m_zdata->realoffset(), m_zdata->buffer_size(), actualdata);
+ if (filerr != osd_file::error::NONE) break;
m_zdata->add_realoffset(actualdata);
m_zdata->reset_input(actualdata);
if (!m_zdata->has_input()) break;
@@ -1022,7 +1017,7 @@ file_error core_osd_file::osd_or_zlib_read(void *buffer, std::uint64_t offset, s
-------------------------------------------------*/
/**
- * @fn file_error osd_or_zlib_write(void const *buffer, std::uint64_t offset, std::uint32_t length, std::uint32_t actual)
+ * @fn osd_file::error osd_or_zlib_write(void const *buffer, std::uint64_t offset, std::uint32_t length, std::uint32_t actual)
*
* @brief OSD or zlib write.
*
@@ -1031,18 +1026,18 @@ file_error core_osd_file::osd_or_zlib_read(void *buffer, std::uint64_t offset, s
* @param length The length.
* @param [in,out] actual The actual.
*
- * @return A file_error.
+ * @return A osd_file::error.
*/
-file_error core_osd_file::osd_or_zlib_write(void const *buffer, std::uint64_t offset, std::uint32_t length, std::uint32_t &actual)
+osd_file::error core_osd_file::osd_or_zlib_write(void const *buffer, std::uint64_t offset, std::uint32_t length, std::uint32_t &actual)
{
// if no compression, just pass through
if (!m_zdata)
- return osd_write(m_file, buffer, offset, length, &actual);
+ return m_file->write(buffer, offset, length, actual);
// if the offset doesn't match the next offset, fail
if (!m_zdata->is_nextoffset(offset))
- return FILERR_INVALID_ACCESS;
+ return osd_file::error::INVALID_ACCESS;
// set up the source
m_zdata->set_input(buffer, length);
@@ -1054,15 +1049,15 @@ file_error core_osd_file::osd_or_zlib_write(void const *buffer, std::uint64_t of
{
actual = length - m_zdata->input_size();
m_zdata->add_nextoffset(actual);
- return FILERR_INVALID_DATA;
+ return osd_file::error::INVALID_DATA;
}
// write more data if we are full up
if (m_zdata->output_full())
{
std::uint32_t actualdata = 0;
- auto const filerr = osd_write(m_file, m_zdata->buffer_data(), m_zdata->realoffset(), m_zdata->output_size(), &actualdata);
- if (filerr != FILERR_NONE)
+ auto const filerr = m_file->write(m_zdata->buffer_data(), m_zdata->realoffset(), m_zdata->output_size(), actualdata);
+ if (filerr != osd_file::error::NONE)
return filerr;
m_zdata->add_realoffset(actualdata);
m_zdata->reset_output();
@@ -1072,7 +1067,7 @@ file_error core_osd_file::osd_or_zlib_write(void const *buffer, std::uint64_t of
// we wrote everything
actual = length;
m_zdata->add_nextoffset(actual);
- return FILERR_NONE;
+ return osd_file::error::NONE;
}
} // anonymous namespace
@@ -1088,24 +1083,23 @@ file_error core_osd_file::osd_or_zlib_write(void const *buffer, std::uint64_t of
return an error code
-------------------------------------------------*/
-file_error core_file::open(char const *filename, std::uint32_t openflags, ptr &file)
+osd_file::error core_file::open(char const *filename, std::uint32_t openflags, ptr &file)
{
- // attempt to open the file
- osd_file *f = nullptr;
- std::uint64_t length = 0;
- auto const filerr = osd_open(filename, openflags, &f, &length);
- if (filerr != FILERR_NONE)
- return filerr;
-
try
{
- file = std::make_unique<core_osd_file>(openflags, f, length);
- return FILERR_NONE;
+ // attempt to open the file
+ osd_file::ptr f;
+ std::uint64_t length = 0;
+ auto const filerr = osd_file::open(filename, openflags, f, length);
+ if (filerr != osd_file::error::NONE)
+ return filerr;
+
+ file = std::make_unique<core_osd_file>(openflags, std::move(f), length);
+ return osd_file::error::NONE;
}
catch (...)
{
- osd_close(f);
- return FILERR_OUT_OF_MEMORY;
+ return osd_file::error::OUT_OF_MEMORY;
}
}
@@ -1115,20 +1109,20 @@ file_error core_file::open(char const *filename, std::uint32_t openflags, ptr &f
like access and return an error code
-------------------------------------------------*/
-file_error core_file::open_ram(void const *data, std::size_t length, std::uint32_t openflags, ptr &file)
+osd_file::error core_file::open_ram(void const *data, std::size_t length, std::uint32_t openflags, ptr &file)
{
// can only do this for read access
if ((openflags & OPEN_FLAG_WRITE) || (openflags & OPEN_FLAG_CREATE))
- return FILERR_INVALID_ACCESS;
+ return osd_file::error::INVALID_ACCESS;
try
{
file.reset(new core_in_memory_file(openflags, data, length, false));
- return FILERR_NONE;
+ return osd_file::error::NONE;
}
catch (...)
{
- return FILERR_OUT_OF_MEMORY;
+ return osd_file::error::OUT_OF_MEMORY;
}
}
@@ -1139,24 +1133,24 @@ file_error core_file::open_ram(void const *data, std::size_t length, std::uint32
error code
-------------------------------------------------*/
-file_error core_file::open_ram_copy(void const *data, std::size_t length, std::uint32_t openflags, ptr &file)
+osd_file::error core_file::open_ram_copy(void const *data, std::size_t length, std::uint32_t openflags, ptr &file)
{
// can only do this for read access
if ((openflags & OPEN_FLAG_WRITE) || (openflags & OPEN_FLAG_CREATE))
- return FILERR_INVALID_ACCESS;
+ return osd_file::error::INVALID_ACCESS;
try
{
ptr result(new core_in_memory_file(openflags, data, length, true));
if (!result->buffer())
- return FILERR_OUT_OF_MEMORY;
+ return osd_file::error::OUT_OF_MEMORY;
file = std::move(result);
- return FILERR_NONE;
+ return osd_file::error::NONE;
}
catch (...)
{
- return FILERR_OUT_OF_MEMORY;
+ return osd_file::error::OUT_OF_MEMORY;
}
}
@@ -1166,16 +1160,16 @@ file_error core_file::open_ram_copy(void const *data, std::size_t length, std::u
object and return an error code
-------------------------------------------------*/
-file_error core_file::open_proxy(core_file &file, ptr &proxy)
+osd_file::error core_file::open_proxy(core_file &file, ptr &proxy)
{
try
{
proxy = std::make_unique<core_proxy_file>(file);
- return FILERR_NONE;
+ return osd_file::error::NONE;
}
catch (...)
{
- return FILERR_OUT_OF_MEMORY;
+ return osd_file::error::OUT_OF_MEMORY;
}
}
@@ -1195,19 +1189,19 @@ core_file::~core_file()
pointer
-------------------------------------------------*/
-file_error core_file::load(char const *filename, void **data, std::uint32_t &length)
+osd_file::error core_file::load(char const *filename, void **data, std::uint32_t &length)
{
ptr file;
// attempt to open the file
auto const err = open(filename, OPEN_FLAG_READ, file);
- if (err != FILERR_NONE)
+ if (err != osd_file::error::NONE)
return err;
// get the size
auto const size = file->size();
if (std::uint32_t(size) != size)
- return FILERR_OUT_OF_MEMORY;
+ return osd_file::error::OUT_OF_MEMORY;
// allocate memory
*data = osd_malloc(size);
@@ -1217,26 +1211,26 @@ file_error core_file::load(char const *filename, void **data, std::uint32_t &len
if (file->read(*data, size) != size)
{
free(*data);
- return FILERR_FAILURE;
+ return osd_file::error::FAILURE;
}
// close the file and return data
- return FILERR_NONE;
+ return osd_file::error::NONE;
}
-file_error core_file::load(char const *filename, dynamic_buffer &data)
+osd_file::error core_file::load(char const *filename, dynamic_buffer &data)
{
ptr file;
// attempt to open the file
auto const err = open(filename, OPEN_FLAG_READ, file);
- if (err != FILERR_NONE)
+ if (err != osd_file::error::NONE)
return err;
// get the size
auto const size = file->size();
if (std::uint32_t(size) != size)
- return FILERR_OUT_OF_MEMORY;
+ return osd_file::error::OUT_OF_MEMORY;
// allocate memory
data.resize(size);
@@ -1245,11 +1239,11 @@ file_error core_file::load(char const *filename, dynamic_buffer &data)
if (file->read(&data[0], size) != size)
{
data.clear();
- return FILERR_FAILURE;
+ return osd_file::error::FAILURE;
}
// close the file and return data
- return FILERR_NONE;
+ return osd_file::error::NONE;
}
diff --git a/src/lib/util/corefile.h b/src/lib/util/corefile.h
index 7ec76af7cb5..e66545440c2 100644
--- a/src/lib/util/corefile.h
+++ b/src/lib/util/corefile.h
@@ -10,8 +10,8 @@
#pragma once
-#ifndef __COREFILE_H__
-#define __COREFILE_H__
+#ifndef MAME_LIB_UTIL_COREFILE_H
+#define MAME_LIB_UTIL_COREFILE_H
#include "corestr.h"
#include "coretmpl.h"
@@ -23,7 +23,6 @@
namespace util {
-
/***************************************************************************
ADDITIONAL OPEN FLAGS
***************************************************************************/
@@ -49,22 +48,22 @@ public:
// ----- file open/close -----
// open a file with the specified filename
- static file_error open(const char *filename, std::uint32_t openflags, ptr &file);
+ static osd_file::error open(const char *filename, std::uint32_t openflags, ptr &file);
// open a RAM-based "file" using the given data and length (read-only)
- static file_error open_ram(const void *data, std::size_t length, std::uint32_t openflags, ptr &file);
+ static osd_file::error open_ram(const void *data, std::size_t length, std::uint32_t openflags, ptr &file);
// open a RAM-based "file" using the given data and length (read-only), copying the data
- static file_error open_ram_copy(const void *data, std::size_t length, std::uint32_t openflags, ptr &file);
+ static osd_file::error open_ram_copy(const void *data, std::size_t length, std::uint32_t openflags, ptr &file);
// open a proxy "file" that forwards requests to another file object
- static file_error open_proxy(core_file &file, ptr &proxy);
+ static osd_file::error open_proxy(core_file &file, ptr &proxy);
// close an open file
virtual ~core_file();
// enable/disable streaming file compression via zlib; level is 0 to disable compression, or up to 9 for max compression
- virtual file_error compress(int level) = 0;
+ virtual osd_file::error compress(int level) = 0;
// ----- file positioning -----
@@ -101,8 +100,8 @@ public:
virtual const void *buffer() = 0;
// open a file with the specified filename, read it into memory, and return a pointer
- static file_error load(const char *filename, void **data, std::uint32_t &length);
- static file_error load(const char *filename, dynamic_buffer &data);
+ static osd_file::error load(const char *filename, void **data, std::uint32_t &length);
+ static osd_file::error load(const char *filename, dynamic_buffer &data);
// ----- file write -----
@@ -121,10 +120,10 @@ public:
}
// file truncation
- virtual file_error truncate(std::uint64_t offset) = 0;
+ virtual osd_file::error truncate(std::uint64_t offset) = 0;
// flush file buffers
- virtual file_error flush() = 0;
+ virtual osd_file::error flush() = 0;
protected:
@@ -147,4 +146,4 @@ std::string core_filename_extract_base(const char *name, bool strip_extension =
int core_filename_ends_with(const char *filename, const char *extension);
-#endif /* __COREFILE_H__ */
+#endif // MAME_LIB_UTIL_COREFILE_H
diff --git a/src/lib/util/un7z.cpp b/src/lib/util/un7z.cpp
index b9cfa13eafe..80c0a6bcba6 100644
--- a/src/lib/util/un7z.cpp
+++ b/src/lib/util/un7z.cpp
@@ -1,5 +1,5 @@
// license:BSD-3-Clause
-// copyright-holders:Aaron Giles
+// copyright-holders:Aaron Giles, Vas Crabb
/***************************************************************************
un7z.c
@@ -10,364 +10,285 @@
// this is based on unzip.c, with modifications needed to use the 7zip library
-#include "osdcore.h"
#include "un7z.h"
-#include <ctype.h>
-#include <stdlib.h>
-#include <zlib.h>
+#include "corestr.h"
+#include "unicode.h"
+#include "lzma/C/7z.h"
+#include "lzma/C/7zCrc.h"
+#include "lzma/C/7zVersion.h"
+
+#include <array>
+#include <cassert>
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+#include <utility>
+#include <vector>
+
+
+namespace {
/***************************************************************************
- 7Zip Memory / File handling (adapted from 7zfile.c/.h and 7zalloc.c/.h)
+ TYPE DEFINITIONS
***************************************************************************/
-void *SZipAlloc(void *p, size_t size)
+struct CSzFile
{
- if (size == 0)
- return nullptr;
+ CSzFile() : currfpos(0), length(0), osdfile() {}
- return malloc(size);
-}
+ long currfpos;
+ std::uint64_t length;
+ osd_file::ptr osdfile;
-void SZipFree(void *p, void *address)
-{
- free(address);
-}
+ WRes read(void *data, std::size_t &size)
+ {
+ if (!osdfile)
+ {
+ std::printf("un7z.c: called File_Read without file\n");
+ return 1;
+ }
+ if (!size) return 0;
+ size_t originalSize = size;
+ std::uint32_t read_length;
+ //osd_file::error err =
+ osdfile->read(data, currfpos, originalSize, read_length);
+ size = read_length;
+ currfpos += read_length;
-void File_Construct(CSzFile *p)
-{
- p->_7z_osdfile = nullptr;
-}
+ if (size == originalSize)
+ return 0;
-static WRes File_Open(CSzFile *p, const char *name, int writeMode)
-{
- /* we handle this ourselves ... */
- if (!p->_7z_osdfile) return 1;
- else return 0;
-}
+ return 0;
+ }
+
+ WRes seek(Int64 &pos, ESzSeek origin)
+ {
+ if (origin == 0) currfpos = pos;
+ if (origin == 1) currfpos = currfpos + pos;
+ if (origin == 2) currfpos = length -pos;
-WRes InFile_Open(CSzFile *p, const char *name) { return File_Open(p, name, 0); }
-WRes OutFile_Open(CSzFile *p, const char *name) { return File_Open(p, name, 1); }
+ pos = currfpos;
+ return 0;
+ }
+};
-WRes File_Close(CSzFile *p)
+struct CFileInStream : public ISeekInStream, public CSzFile
{
- /* we handle this ourselves ... */
- return 0;
-}
+ CFileInStream();
+};
-WRes File_Read(CSzFile *p, void *data, size_t *size)
+
+class m7z_file_impl
{
-// file_error err;
- UINT32 read_length;
+public:
+ typedef std::unique_ptr<m7z_file_impl> ptr;
- if (!p->_7z_osdfile)
+ m7z_file_impl(const std::string &filename);
+ ~m7z_file_impl()
{
- printf("un7z.c: called File_Read without file\n");
- return 1;
+ if (m_out_buffer)
+ IAlloc_Free(&m_alloc_imp, m_out_buffer);
+ if (m_inited)
+ SzArEx_Free(&m_db, &m_alloc_imp);
}
- size_t originalSize = *size;
- if (originalSize == 0)
- return 0;
+ static ptr find_cached(const std::string &filename)
+ {
+ for (std::size_t cachenum = 0; cachenum < s_cache.size(); cachenum++)
+ {
+ // if we have a valid entry and it matches our filename, use it and remove from the cache
+ if (s_cache[cachenum] && (filename == s_cache[cachenum]->m_filename))
+ {
+ ptr result;
+ std::swap(s_cache[cachenum], result);
+ return result;
+ }
+ }
+ return ptr();
+ }
+ static void close(ptr &&archive);
+ static void cache_clear()
+ {
+ // clear call cache entries
+ for (std::size_t cachenum = 0; cachenum < s_cache.size(); s_cache[cachenum++].reset()) { }
+ }
-// err =
- osd_read( p->_7z_osdfile, data, p->_7z_currfpos, originalSize, &read_length );
- *size = read_length;
- p->_7z_currfpos += read_length;
+ _7z_file::error initialize();
- if (*size == originalSize)
- return 0;
+ int first_file() { return search(0, 0, std::string(), false, false); }
+ int next_file() { return (m_curr_file_idx < 0) ? -1 : search(m_curr_file_idx + 1, 0, std::string(), false, false); }
- return 0;
-}
+ int search(std::uint32_t crc) { return search(0, crc, std::string(), true, false); }
+ int search(const std::string &filename) { return search(0, 0, filename, false, true); }
+ int search(std::uint32_t crc, const std::string &filename) { return search(0, crc, filename, true, true); }
-WRes File_Write(CSzFile *p, const void *data, size_t *size)
-{
- return 0;
-}
+ const std::string &current_name() const { return m_curr_name; }
+ std::uint64_t current_uncompressed_length() const { return m_curr_length; }
+ std::uint32_t current_crc() const { return m_curr_crc; }
-WRes File_Seek(CSzFile *p, Int64 *pos, ESzSeek origin)
-{
- if (origin==0) p->_7z_currfpos = *pos;
- if (origin==1) p->_7z_currfpos = p->_7z_currfpos + *pos;
- if (origin==2) p->_7z_currfpos = p->_7z_length - *pos;
+ _7z_file::error decompress(void *buffer, std::uint32_t length);
- *pos = p->_7z_currfpos;
+private:
+ m7z_file_impl(const m7z_file_impl &) = delete;
+ m7z_file_impl(m7z_file_impl &&) = delete;
+ m7z_file_impl &operator=(const m7z_file_impl &) = delete;
+ m7z_file_impl &operator=(m7z_file_impl &&) = delete;
- return 0;
-}
+ int search(int i, std::uint32_t search_crc, const std::string &search_filename, bool matchcrc, bool matchname);
+ void make_utf8_name(int index);
-WRes File_GetLength(CSzFile *p, UInt64 *length)
-{
- *length = p->_7z_length;
- return 0;
-}
+ static constexpr std::size_t CACHE_SIZE = 8;
+ static std::array<ptr, CACHE_SIZE> s_cache;
-/* ---------- FileSeqInStream ---------- */
+ const std::string m_filename; // copy of _7Z filename (for caching)
-static SRes FileSeqInStream_Read(void *pp, void *buf, size_t *size)
-{
- CFileSeqInStream *p = (CFileSeqInStream *)pp;
- return File_Read(&p->file, buf, size) == 0 ? SZ_OK : SZ_ERROR_READ;
-}
+ int m_curr_file_idx; // current file index
+ std::string m_curr_name; // current file name
+ std::uint64_t m_curr_length; // current file uncompressed length
+ std::uint32_t m_curr_crc; // current file crc
-void FileSeqInStream_CreateVTable(CFileSeqInStream *p)
-{
- p->s.Read = FileSeqInStream_Read;
-}
+ std::vector<UInt16> m_utf16_buf;
+ std::vector<unicode_char> m_uchar_buf;
+ std::vector<char> m_utf8_buf;
+ CFileInStream m_archive_stream;
+ CLookToRead m_look_stream;
+ CSzArEx m_db;
+ ISzAlloc m_alloc_imp;
+ ISzAlloc m_alloc_temp_imp;
+ bool m_inited;
-/* ---------- FileInStream ---------- */
+ // cached stuff for solid blocks
+ UInt32 m_block_index;
+ Byte * m_out_buffer;
+ std::size_t m_out_buffer_size;
-static SRes FileInStream_Read(void *pp, void *buf, size_t *size)
-{
- CFileInStream *p = (CFileInStream *)pp;
- return (File_Read(&p->file, buf, size) == 0) ? SZ_OK : SZ_ERROR_READ;
-}
+};
-static SRes FileInStream_Seek(void *pp, Int64 *pos, ESzSeek origin)
-{
- CFileInStream *p = (CFileInStream *)pp;
- return File_Seek(&p->file, pos, origin);
-}
-void FileInStream_CreateVTable(CFileInStream *p)
+class m7z_file_wrapper : public _7z_file
{
- p->s.Read = FileInStream_Read;
- p->s.Seek = FileInStream_Seek;
-}
+public:
+ m7z_file_wrapper(m7z_file_impl::ptr &&impl) : m_impl(std::move(impl)) { assert(m_impl); }
+ virtual ~m7z_file_wrapper() override { m7z_file_impl::close(std::move(m_impl)); }
-/* ---------- FileOutStream ---------- */
+ virtual int first_file() override { return m_impl->first_file(); }
+ virtual int next_file() override { return m_impl->next_file(); }
-static size_t FileOutStream_Write(void *pp, const void *data, size_t size)
-{
- CFileOutStream *p = (CFileOutStream *)pp;
- File_Write(&p->file, data, &size);
- return size;
-}
+ virtual int search(std::uint32_t crc) override { return m_impl->search(crc); }
+ virtual int search(const std::string &filename) override { return m_impl->search(filename); }
+ virtual int search(std::uint32_t crc, const std::string &filename) override { return m_impl->search(crc, filename); }
-void FileOutStream_CreateVTable(CFileOutStream *p)
-{
- p->s.Write = FileOutStream_Write;
-}
+ virtual const std::string &current_name() const override { return m_impl->current_name(); }
+ virtual std::uint64_t current_uncompressed_length() const override { return m_impl->current_uncompressed_length(); }
+ virtual std::uint32_t current_crc() const override { return m_impl->current_crc(); }
-/***************************************************************************
- CONSTANTS
-***************************************************************************/
+ virtual error decompress(void *buffer, std::uint32_t length) override { return m_impl->decompress(buffer, length); }
+
+private:
+ m7z_file_impl::ptr m_impl;
+};
-/* number of open files to cache */
-#define _7Z_CACHE_SIZE 8
/***************************************************************************
GLOBAL VARIABLES
***************************************************************************/
-static _7z_file *_7z_cache[_7Z_CACHE_SIZE];
-
-/***************************************************************************
- FUNCTION PROTOTYPES
-***************************************************************************/
+std::array<m7z_file_impl::ptr, m7z_file_impl::CACHE_SIZE> m7z_file_impl::s_cache;
-/* cache management */
-static void free__7z_file(_7z_file *_7z);
/***************************************************************************
- _7Z FILE ACCESS
+ 7Zip Memory / File handling (adapted from 7zfile.c/.h and 7zalloc.c/.h)
***************************************************************************/
-/*-------------------------------------------------
- _7z_file_open - opens a _7Z file for reading
--------------------------------------------------*/
-
-int _7z_search_crc_match(_7z_file *new_7z, UINT32 search_crc, const char* search_filename, int search_filename_length, bool matchcrc, bool matchname)
-{
- UInt16 *temp = nullptr;
- size_t tempSize = 0;
-
- for (int i = 0; i < new_7z->db.db.NumFiles; i++)
- {
- const CSzFileItem *f = new_7z->db.db.Files + i;
- size_t len;
-
- len = SzArEx_GetFileNameUtf16(&new_7z->db, i, nullptr);
-
- // if it's a directory entry we don't care about it..
- if (f->IsDir)
- continue;
-
- if (len > tempSize)
- {
- SZipFree(nullptr, temp);
- tempSize = len;
- temp = (UInt16 *)SZipAlloc(nullptr, tempSize * sizeof(temp[0]));
- if (temp == nullptr)
- {
- return -1; // memory error
- }
- }
-
- bool crcmatch = false;
- bool namematch = false;
-
- UINT64 size = f->Size;
- UINT32 crc = f->Crc;
-
- /* Check for a name match */
- SzArEx_GetFileNameUtf16(&new_7z->db, i, temp);
-
- if (len == search_filename_length+1)
- {
- int j;
- for (j=0;j<search_filename_length;j++)
- {
- UINT8 sn = search_filename[j];
- UINT16 zn = temp[j]; // these are utf16
-
- // MAME filenames are always lowercase so be case insensitive
- if ((zn>=0x41) && (zn<=0x5a)) zn+=0x20;
-
- if (sn != zn) break;
- }
- if (j==search_filename_length) namematch = true;
- }
-
-
- /* Check for a CRC match */
- if (crc==search_crc) crcmatch = true;
-
- bool found = false;
-
- if (matchcrc && matchname)
- {
- if (crcmatch && namematch)
- found = true;
- }
- else if (matchcrc)
- {
- if (crcmatch)
- found = true;
- }
- else if (matchname)
- {
- if (namematch)
- found = true;
- }
+/* ---------- FileInStream ---------- */
- if (found)
- {
- // printf("found %S %d %08x %08x %08x %s %d\n", temp, len, crc, search_crc, size, search_filename, search_filename_length);
- new_7z->curr_file_idx = i;
- new_7z->uncompressed_length = size;
- new_7z->crc = crc;
+extern "C" {
- SZipFree(nullptr, temp);
- return i;
- }
- }
+static void *SZipAlloc(void *p, std::size_t size)
+{
+ return (size == 0) ? nullptr : std::malloc(size);
+}
- SZipFree(nullptr, temp);
- return -1;
+static void SZipFree(void *p, void *address)
+{
+ std::free(address);
}
-_7z_error _7z_file_open(const char *filename, _7z_file **_7z)
+static SRes FileInStream_Read(void *pp, void *buf, size_t *size)
{
- file_error err;
- _7z_error _7zerr = _7ZERR_NONE;
-
+ return (reinterpret_cast<CFileInStream *>(pp)->read(buf, *size) == 0) ? SZ_OK : SZ_ERROR_READ;
+}
- _7z_file *new_7z;
- char *string;
- int cachenum;
+static SRes FileInStream_Seek(void *pp, Int64 *pos, ESzSeek origin)
+{
+ return reinterpret_cast<CFileInStream *>(pp)->seek(*pos, origin);
+}
- SRes res;
+} // extern "C"
- /* ensure we start with a NULL result */
- *_7z = nullptr;
- /* see if we are in the cache, and reopen if so */
- for (cachenum = 0; cachenum < ARRAY_LENGTH(_7z_cache); cachenum++)
- {
- _7z_file *cached = _7z_cache[cachenum];
+CFileInStream::CFileInStream()
+{
+ Read = &FileInStream_Read;
+ Seek = &FileInStream_Seek;
+}
- /* if we have a valid entry and it matches our filename, use it and remove from the cache */
- if (cached != nullptr && cached->filename != nullptr && strcmp(filename, cached->filename) == 0)
- {
- *_7z = cached;
- _7z_cache[cachenum] = nullptr;
- return _7ZERR_NONE;
- }
- }
- /* allocate memory for the _7z_file structure */
- new_7z = (_7z_file *)malloc(sizeof(*new_7z));
- if (new_7z == nullptr)
- return _7ZERR_OUT_OF_MEMORY;
- memset(new_7z, 0, sizeof(*new_7z));
- new_7z->inited = false;
- new_7z->archiveStream.file._7z_currfpos = 0;
- err = osd_open(filename, OPEN_FLAG_READ, &new_7z->archiveStream.file._7z_osdfile, &new_7z->archiveStream.file._7z_length);
- if (err != FILERR_NONE)
- {
- _7zerr = _7ZERR_FILE_ERROR;
- goto error;
- }
+/***************************************************************************
+ CACHE MANAGEMENT
+***************************************************************************/
- new_7z->allocImp.Alloc = SZipAlloc;
- new_7z->allocImp.Free = SZipFree;
+m7z_file_impl::m7z_file_impl(const std::string &filename)
+ : m_filename(filename)
+ , m_curr_file_idx(-1)
+ , m_curr_name()
+ , m_curr_length(0)
+ , m_curr_crc(0)
+ , m_utf16_buf(128)
+ , m_uchar_buf(128)
+ , m_utf8_buf(512)
+ , m_inited(false)
+ , m_block_index(0xffffffff) // it can have any value before first call (if outBuffer = 0)
+ , m_out_buffer(nullptr) // it must be 0 before first call for each new archive
+ , m_out_buffer_size(0) // it can have any value before first call (if outBuffer = 0)
+{
+ m_alloc_imp.Alloc = SZipAlloc;
+ m_alloc_imp.Free = SZipFree;
- new_7z->allocTempImp.Alloc = SZipAlloc;
- new_7z->allocTempImp.Free = SZipFree;
+ m_alloc_temp_imp.Alloc = SZipAlloc;
+ m_alloc_temp_imp.Free = SZipFree;
+}
- if (InFile_Open(&new_7z->archiveStream.file, filename))
- {
- _7zerr = _7ZERR_FILE_ERROR;
- goto error;
- }
- FileInStream_CreateVTable(&new_7z->archiveStream);
- LookToRead_CreateVTable(&new_7z->lookStream, False);
+_7z_file::error m7z_file_impl::initialize()
+{
+ osd_file::error const err = osd_file::open(m_filename, OPEN_FLAG_READ, m_archive_stream.osdfile, m_archive_stream.length);
+ if (err != osd_file::error::NONE)
+ return _7z_file::error::FILE_ERROR;
- new_7z->lookStream.realStream = &new_7z->archiveStream.s;
- LookToRead_Init(&new_7z->lookStream);
+ LookToRead_CreateVTable(&m_look_stream, False);
+ m_look_stream.realStream = &m_archive_stream;
+ LookToRead_Init(&m_look_stream);
CrcGenerateTable();
- SzArEx_Init(&new_7z->db);
- new_7z->inited = true;
+ SzArEx_Init(&m_db);
+ m_inited = true;
- res = SzArEx_Open(&new_7z->db, &new_7z->lookStream.s, &new_7z->allocImp, &new_7z->allocTempImp);
+ SRes const res = SzArEx_Open(&m_db, &m_look_stream.s, &m_alloc_imp, &m_alloc_temp_imp);
if (res != SZ_OK)
- {
- _7zerr = _7ZERR_FILE_ERROR;
- goto error;
- }
-
- new_7z->blockIndex = 0xFFFFFFFF; /* it can have any value before first call (if outBuffer = 0) */
- new_7z->outBuffer = nullptr; /* it must be 0 before first call for each new archive. */
- new_7z->outBufferSize = 0; /* it can have any value before first call (if outBuffer = 0) */
+ return _7z_file::error::FILE_ERROR;
- /* make a copy of the filename for caching purposes */
- string = (char *)malloc(strlen(filename) + 1);
- if (string == nullptr)
- {
- _7zerr = _7ZERR_OUT_OF_MEMORY;
- goto error;
- }
- strcpy(string, filename);
- new_7z->filename = string;
- *_7z = new_7z;
- return _7ZERR_NONE;
-
-error:
- free__7z_file(new_7z);
- return _7zerr;
+ return _7z_file::error::NONE;
}
@@ -376,119 +297,187 @@ error:
to the cache
-------------------------------------------------*/
-void _7z_file_close(_7z_file *_7z)
+void m7z_file_impl::close(ptr &&archive)
{
- int cachenum;
+ if (!archive) return;
- /* close the open files */
- if (_7z->archiveStream.file._7z_osdfile != nullptr)
- osd_close(_7z->archiveStream.file._7z_osdfile);
- _7z->archiveStream.file._7z_osdfile = nullptr;
+ // close the open files
+ archive->m_archive_stream.osdfile.reset();
- /* find the first NULL entry in the cache */
- for (cachenum = 0; cachenum < ARRAY_LENGTH(_7z_cache); cachenum++)
- if (_7z_cache[cachenum] == nullptr)
+ // find the first NULL entry in the cache
+ std::size_t cachenum;
+ for (cachenum = 0; cachenum < s_cache.size(); cachenum++)
+ if (!s_cache[cachenum])
break;
- /* if no room left in the cache, free the bottommost entry */
- if (cachenum == ARRAY_LENGTH(_7z_cache))
- free__7z_file(_7z_cache[--cachenum]);
+ // if no room left in the cache, free the bottommost entry
+ if (cachenum == s_cache.size())
+ s_cache[--cachenum].reset();
- /* move everyone else down and place us at the top */
- if (cachenum != 0)
- memmove(&_7z_cache[1], &_7z_cache[0], cachenum * sizeof(_7z_cache[0]));
- _7z_cache[0] = _7z;
+ // move everyone else down and place us at the top
+ for ( ; cachenum > 0; cachenum--)
+ s_cache[cachenum] = std::move(s_cache[cachenum - 1]);
+ s_cache[0] = std::move(archive);
}
-/*-------------------------------------------------
- _7z_file_cache_clear - clear the _7Z file
- cache and free all memory
--------------------------------------------------*/
-
-void _7z_file_cache_clear(void)
-{
- int cachenum;
-
- /* clear call cache entries */
- for (cachenum = 0; cachenum < ARRAY_LENGTH(_7z_cache); cachenum++)
- if (_7z_cache[cachenum] != nullptr)
- {
- free__7z_file(_7z_cache[cachenum]);
- _7z_cache[cachenum] = nullptr;
- }
-}
+/***************************************************************************
+ 7Z FILE ACCESS
+***************************************************************************/
/*-------------------------------------------------
_7z_file_decompress - decompress a file
from a _7Z into the target buffer
-------------------------------------------------*/
-_7z_error _7z_file_decompress(_7z_file *new_7z, void *buffer, UINT32 length)
+_7z_file::error m7z_file_impl::decompress(void *buffer, std::uint32_t length)
{
- file_error err;
- SRes res;
- int index = new_7z->curr_file_idx;
-
- /* make sure the file is open.. */
- if (new_7z->archiveStream.file._7z_osdfile==nullptr)
+ // make sure the file is open..
+ if (!m_archive_stream.osdfile)
{
- new_7z->archiveStream.file._7z_currfpos = 0;
- err = osd_open(new_7z->filename, OPEN_FLAG_READ, &new_7z->archiveStream.file._7z_osdfile, &new_7z->archiveStream.file._7z_length);
- if (err != FILERR_NONE)
- return _7ZERR_FILE_ERROR;
+ m_archive_stream.currfpos = 0;
+ osd_file::error const err = osd_file::open(m_filename, OPEN_FLAG_READ, m_archive_stream.osdfile, m_archive_stream.length);
+ if (err != osd_file::error::NONE)
+ return _7z_file::error::FILE_ERROR;
}
size_t offset = 0;
- size_t outSizeProcessed = 0;
+ size_t out_size_processed = 0;
- res = SzArEx_Extract(&new_7z->db, &new_7z->lookStream.s, index,
- &new_7z->blockIndex, &new_7z->outBuffer, &new_7z->outBufferSize,
- &offset, &outSizeProcessed,
- &new_7z->allocImp, &new_7z->allocTempImp);
+ SRes const res = SzArEx_Extract(
+ &m_db, &m_look_stream.s, m_curr_file_idx,
+ &m_block_index,
+ &m_out_buffer, &m_out_buffer_size,
+ &offset, &out_size_processed,
+ &m_alloc_imp, &m_alloc_temp_imp);
if (res != SZ_OK)
- return _7ZERR_FILE_ERROR;
+ return _7z_file::error::FILE_ERROR;
- memcpy(buffer, new_7z->outBuffer + offset, length);
+ std::memcpy(buffer, m_out_buffer + offset, length);
- return _7ZERR_NONE;
+ return _7z_file::error::NONE;
}
+int m7z_file_impl::search(int i, std::uint32_t search_crc, const std::string &search_filename, bool matchcrc, bool matchname)
+{
+ for ( ; i < m_db.db.NumFiles; i++)
+ {
+ const CSzFileItem &f(m_db.db.Files[i]);
-/***************************************************************************
- CACHE MANAGEMENT
-***************************************************************************/
+ // if it's a directory entry we don't care about it..
+ if (!f.IsDir)
+ {
+ make_utf8_name(i);
+ const std::uint64_t size(f.Size);
+ const std::uint32_t crc(f.Crc);
+ const bool crcmatch(crc == search_crc);
+ const bool namematch(core_stricmp(search_filename.c_str(), &m_utf8_buf[0]) == 0);
+
+ const bool found = (!matchcrc || crcmatch) && (!matchname || namematch);
+ if (found)
+ {
+ m_curr_file_idx = i;
+ m_curr_name = &m_utf8_buf[0];
+ m_curr_length = size;
+ m_curr_crc = crc;
-/*-------------------------------------------------
- free__7z_file - free all the data for a
- _7z_file
--------------------------------------------------*/
+ return i;
+ }
+ }
+ }
+
+ return -1;
+}
-/**
- * @fn static void free__7z_file(_7z_file *_7z)
- *
- * @brief Free 7z file.
- *
- * @param [in,out] _7z If non-null, the 7z.
- */
-static void free__7z_file(_7z_file *_7z)
+void m7z_file_impl::make_utf8_name(int index)
{
- if (_7z != nullptr)
+ std::size_t len, out_pos;
+
+ len = SzArEx_GetFileNameUtf16(&m_db, index, nullptr);
+ m_utf16_buf.resize((std::max<std::size_t>)(m_utf16_buf.size(), len));
+ SzArEx_GetFileNameUtf16(&m_db, index, &m_utf16_buf[0]);
+
+ m_uchar_buf.resize((std::max<std::size_t>)(m_uchar_buf.size(), len));
+ out_pos = 0;
+ for (std::size_t in_pos = 0; in_pos < (len - 1); )
+ {
+ const int used = uchar_from_utf16(&m_uchar_buf[out_pos], &m_utf16_buf[in_pos], len - in_pos);
+ if (used < 0)
+ {
+ in_pos++;
+ m_uchar_buf[out_pos++] = 0x00fffd; // Unicode REPLACEMENT CHARACTER
+ }
+ else
+ {
+ assert(used > 0);
+ in_pos += used;
+ out_pos++;
+ }
+ }
+ len = out_pos;
+
+ m_utf8_buf.resize((std::max<std::size_t>)(m_utf8_buf.size(), 4 * len + 1));
+ out_pos = 0;
+ for (std::size_t in_pos = 0; in_pos < len; in_pos++)
{
- if (_7z->archiveStream.file._7z_osdfile != nullptr)
- osd_close(_7z->archiveStream.file._7z_osdfile);
- if (_7z->filename != nullptr)
- free((void *)_7z->filename);
+ int produced = utf8_from_uchar(&m_utf8_buf[out_pos], m_utf8_buf.size() - out_pos, m_uchar_buf[in_pos]);
+ if (produced < 0)
+ produced = utf8_from_uchar(&m_utf8_buf[out_pos], m_utf8_buf.size() - out_pos, 0x00fffd);
+ if (produced >= 0)
+ out_pos += produced;
+ assert(out_pos < m_utf8_buf.size());
+ }
+ m_utf16_buf[out_pos++] = '\0';
+}
+
+} // anonymous namespace
+
+
+_7z_file::~_7z_file()
+{
+}
+
+_7z_file::error _7z_file::open(const std::string &filename, ptr &result)
+{
+ // ensure we start with a NULL result
+ result.reset();
- if (_7z->outBuffer) IAlloc_Free(&_7z->allocImp, _7z->outBuffer);
- if (_7z->inited) SzArEx_Free(&_7z->db, &_7z->allocImp);
+ // see if we are in the cache, and reopen if so
+ m7z_file_impl::ptr newimpl(m7z_file_impl::find_cached(filename));
+ if (!newimpl)
+ {
+ // allocate memory for the 7z file structure
+ try { newimpl = std::make_unique<m7z_file_impl>(filename); }
+ catch (...) { return error::OUT_OF_MEMORY; }
+ error const err = newimpl->initialize();
+ if (err != error::NONE) return err;
+ }
- free(_7z);
+ try
+ {
+ result = std::make_unique<m7z_file_wrapper>(std::move(newimpl));
+ return error::NONE;
+ }
+ catch (...)
+ {
+ m7z_file_impl::close(std::move(newimpl));
+ return error::OUT_OF_MEMORY;
}
}
+
+
+/*-------------------------------------------------
+ _7z_file_cache_clear - clear the _7Z file
+ cache and free all memory
+-------------------------------------------------*/
+
+void _7z_file::cache_clear()
+{
+ m7z_file_impl::cache_clear();
+}
diff --git a/src/lib/util/un7z.h b/src/lib/util/un7z.h
index d2c0c9f098a..d2d2e18e25f 100644
--- a/src/lib/util/un7z.h
+++ b/src/lib/util/un7z.h
@@ -1,5 +1,5 @@
// license:BSD-3-Clause
-// copyright-holders:Aaron Giles
+// copyright-holders:Aaron Giles, Vas Crabb
/***************************************************************************
un7z.h
@@ -12,132 +12,72 @@
#pragma once
-#ifndef __UN_7Z_H__
-#define __UN_7Z_H__
+#ifndef MAME_LIB_UTIL_UN7Z_H
+#define MAME_LIB_UTIL_UN7Z_H
#include "osdcore.h"
-#include "lzma/C/7z.h"
-#include "lzma/C/7zCrc.h"
-#include "lzma/C/7zVersion.h"
-
-
-void *SZipAlloc(void *p, size_t size);
-void SZipFree(void *p, void *address);
-void *SZipAllocTemp(void *p, size_t size);
-void SZipFreeTemp(void *p, void *address);
-
-struct CSzFile
-{
- long _7z_currfpos;
- UINT64 _7z_length;
- osd_file * _7z_osdfile; /* OSD file handle */
-
-};
-
-
-struct CFileSeqInStream
-{
- ISeqInStream s;
- CSzFile file;
-};
-
-void FileSeqInStream_CreateVTable(CFileSeqInStream *p);
-
-
-struct CFileInStream
-{
- ISeekInStream s;
- CSzFile file;
-};
-
-void FileInStream_CreateVTable(CFileInStream *p);
-
-
-struct CFileOutStream
-{
- ISeqOutStream s;
- CSzFile file;
-} ;
-
-void FileOutStream_CreateVTable(CFileOutStream *p);
-
-
-
-/***************************************************************************
- CONSTANTS
-***************************************************************************/
-
-
-/* Error types */
-enum _7z_error
-{
- _7ZERR_NONE = 0,
- _7ZERR_OUT_OF_MEMORY,
- _7ZERR_FILE_ERROR,
- _7ZERR_BAD_SIGNATURE,
- _7ZERR_DECOMPRESS_ERROR,
- _7ZERR_FILE_TRUNCATED,
- _7ZERR_FILE_CORRUPT,
- _7ZERR_UNSUPPORTED,
- _7ZERR_BUFFER_TOO_SMALL
-};
-
+#include <cstdint>
+#include <memory>
+#include <string>
/***************************************************************************
TYPE DEFINITIONS
***************************************************************************/
-/* describes an open _7Z file */
-struct _7z_file
+// describes an open _7Z file
+class _7z_file
{
- const char * filename; /* copy of _7Z filename (for caching) */
-
- int curr_file_idx; /* current file index */
- UINT64 uncompressed_length; /* current file uncompressed length */
- UINT64 crc; /* current file crc */
-
- CFileInStream archiveStream;
- CLookToRead lookStream;
- CSzArEx db;
- SRes res;
- ISzAlloc allocImp;
- ISzAlloc allocTempImp;
- bool inited;
-
- // cached stuff for solid blocks
- UInt32 blockIndex;// = 0xFFFFFFFF; /* it can have any value before first call (if outBuffer = 0) */
- Byte *outBuffer;// = 0; /* it must be 0 before first call for each new archive. */
- size_t outBufferSize;// = 0; /* it can have any value before first call (if outBuffer = 0) */
-};
+public:
+ // Error types
+ enum class error
+ {
+ NONE = 0,
+ OUT_OF_MEMORY,
+ FILE_ERROR,
+ BAD_SIGNATURE,
+ DECOMPRESS_ERROR,
+ FILE_TRUNCATED,
+ FILE_CORRUPT,
+ UNSUPPORTED,
+ BUFFER_TOO_SMALL
+ };
+ typedef std::unique_ptr<_7z_file> ptr;
-/***************************************************************************
- FUNCTION PROTOTYPES
-***************************************************************************/
+ virtual ~_7z_file();
-/* ----- _7Z file access ----- */
+ /* ----- 7Z file access ----- */
-/* open a _7Z file and parse its central directory */
-_7z_error _7z_file_open(const char *filename, _7z_file **_7z);
+ // open a 7Z file and parse its central directory
+ static error open(const std::string &filename, ptr &result);
-/* close a _7Z file (may actually be left open due to caching) */
-void _7z_file_close(_7z_file *_7z);
+ // clear out all open 7Z files from the cache
+ static void cache_clear();
-/* clear out all open _7Z files from the cache */
-void _7z_file_cache_clear(void);
+ /* ----- contained file access ----- */
-/* ----- contained file access ----- */
+ // iterating over files
+ virtual int first_file() = 0;
+ virtual int next_file() = 0;
-/* find a file index by crc, filename or both */
-int _7z_search_crc_match(_7z_file *new_7z, UINT32 crc, const char *search_filename, int search_filename_length, bool matchcrc, bool matchname);
+ // find a file index by crc, filename or both
+ virtual int search(std::uint32_t crc) = 0;
+ virtual int search(const std::string &filename) = 0;
+ virtual int search(std::uint32_t crc, const std::string &filename) = 0;
-/* decompress the most recently found file in the _7Z */
-_7z_error _7z_file_decompress(_7z_file *_7z, void *buffer, UINT32 length);
+ // information on most recently found file
+ virtual const std::string &current_name() const = 0;
+ virtual std::uint64_t current_uncompressed_length() const = 0;
+ virtual std::uint32_t current_crc() const = 0;
+ // decompress the most recently found file in the _7Z
+ virtual error decompress(void *buffer, std::uint32_t length) = 0;
+
+};
-#endif /* __UN_7Z_H__ */
+#endif // MAME_LIB_UTIL_UN7Z_H
diff --git a/src/lib/util/unzip.cpp b/src/lib/util/unzip.cpp
index 876d8ae90c5..321f4e0b69f 100644
--- a/src/lib/util/unzip.cpp
+++ b/src/lib/util/unzip.cpp
@@ -1,5 +1,5 @@
// license:BSD-3-Clause
-// copyright-holders:Aaron Giles
+// copyright-holders:Aaron Giles, Vas Crabb
/***************************************************************************
unzip.c
@@ -11,19 +11,23 @@
#include "osdcore.h"
#include "unzip.h"
-#include <ctype.h>
-#include <stdlib.h>
+#include <algorithm>
+#include <array>
+#include <cassert>
+#include <cstring>
+#include <cstdlib>
+#include <utility>
+#include <vector>
+
#include <zlib.h>
+namespace {
/***************************************************************************
CONSTANTS
***************************************************************************/
-/* number of open files to cache */
-#define ZIP_CACHE_SIZE 8
-
/* offsets in end of central directory structure */
#define ZIPESIG 0x00
#define ZIPEDSK 0x04
@@ -95,6 +99,162 @@
/***************************************************************************
+ TYPE DEFINITIONS
+***************************************************************************/
+
+class zip_file_impl
+{
+public:
+ typedef std::unique_ptr<zip_file_impl> ptr;
+
+ zip_file_impl(const std::string &filename)
+ : m_filename(filename)
+ , m_file()
+ , m_length(0)
+ , m_ecd()
+ , m_cd()
+ , m_cd_pos(0)
+ , m_header()
+ , m_buffer()
+ {
+ std::memset(&m_header, 0, sizeof(m_header));
+ std::fill(m_buffer.begin(), m_buffer.end(), 0);
+ }
+
+ static ptr find_cached(const std::string &filename)
+ {
+ for (std::size_t cachenum = 0; cachenum < s_cache.size(); cachenum++)
+ {
+ // if we have a valid entry and it matches our filename, use it and remove from the cache
+ if (s_cache[cachenum] && (filename == s_cache[cachenum]->m_filename))
+ {
+ ptr result;
+ std::swap(s_cache[cachenum], result);
+ return result;
+ }
+ }
+ return ptr();
+ }
+ static void close(ptr &&zip);
+ static void cache_clear()
+ {
+ // clear call cache entries
+ for (std::size_t cachenum = 0; cachenum < s_cache.size(); s_cache[cachenum++].reset()) { }
+ }
+
+ zip_file::error initialize()
+ {
+ // read ecd data
+ auto const ziperr = read_ecd();
+ if (ziperr != zip_file::error::NONE)
+ return ziperr;
+
+ // verify that we can work with this zipfile (no disk spanning allowed)
+ if ((m_ecd.disk_number != m_ecd.cd_start_disk_number) || (m_ecd.cd_disk_entries != m_ecd.cd_total_entries))
+ return zip_file::error::UNSUPPORTED;
+
+ // allocate memory for the central directory
+ try { m_cd.resize(m_ecd.cd_size + 1); }
+ catch (...) { return zip_file::error::OUT_OF_MEMORY; }
+
+ // read the central directory
+ std::uint32_t read_length;
+ auto const filerr = m_file->read(&m_cd[0], m_ecd.cd_start_disk_offset, m_ecd.cd_size, read_length);
+ if ((filerr != osd_file::error::NONE) || (read_length != m_ecd.cd_size))
+ return (filerr == osd_file::error::NONE) ? zip_file::error::FILE_TRUNCATED : zip_file::error::FILE_ERROR;
+
+ return zip_file::error::NONE;
+ }
+
+ // contained file access
+ const zip_file::file_header *first_file();
+ const zip_file::file_header *next_file();
+ zip_file::error decompress(void *buffer, std::uint32_t length);
+
+private:
+ zip_file_impl(const zip_file_impl &) = delete;
+ zip_file_impl(zip_file_impl &&) = delete;
+ zip_file_impl &operator=(const zip_file_impl &) = delete;
+ zip_file_impl &operator=(zip_file_impl &&) = delete;
+
+ zip_file::error reopen()
+ {
+ if (!m_file)
+ {
+ auto const filerr = osd_file::open(m_filename, OPEN_FLAG_READ, m_file, m_length);
+ if (filerr != osd_file::error::NONE)
+ return zip_file::error::FILE_ERROR;
+ }
+ return zip_file::error::NONE;
+ }
+
+ // ZIP file parsing
+ zip_file::error read_ecd();
+ zip_file::error get_compressed_data_offset(std::uint64_t &offset);
+
+ // decompression interfaces
+ zip_file::error decompress_data_type_0(std::uint64_t offset, void *buffer, std::uint32_t length);
+ zip_file::error decompress_data_type_8(std::uint64_t offset, void *buffer, std::uint32_t length);
+
+ struct file_header_int : zip_file::file_header
+ {
+ std::uint8_t * raw; // pointer to the raw data
+ std::uint32_t rawlength; // length of the raw data
+ std::uint8_t saved; // saved byte from after filename
+ };
+
+ // contains extracted end of central directory information
+ struct ecd
+ {
+ std::uint32_t signature; // end of central dir signature
+ std::uint16_t disk_number; // number of this disk
+ std::uint16_t cd_start_disk_number; // number of the disk with the start of the central directory
+ std::uint16_t cd_disk_entries; // total number of entries in the central directory on this disk
+ std::uint16_t cd_total_entries; // total number of entries in the central directory
+ std::uint32_t cd_size; // size of the central directory
+ std::uint32_t cd_start_disk_offset; // offset of start of central directory with respect to the starting disk number
+ std::uint16_t comment_length; // .ZIP file comment length
+ const char * comment; // .ZIP file comment
+
+ std::unique_ptr<std::uint8_t []> raw; // pointer to the raw data
+ std::uint32_t rawlength; // length of the raw data
+ };
+
+ static constexpr std::size_t DECOMPRESS_BUFSIZE = 16384;
+ static constexpr std::size_t CACHE_SIZE = 8; // number of open files to cache
+ static std::array<ptr, CACHE_SIZE> s_cache;
+
+ const std::string m_filename; // copy of ZIP filename (for caching)
+ osd_file::ptr m_file; // OSD file handle
+ std::uint64_t m_length; // length of zip file
+
+ ecd m_ecd; // end of central directory
+
+ std::vector<std::uint8_t> m_cd; // central directory raw data
+ std::uint32_t m_cd_pos; // position in central directory
+ file_header_int m_header; // current file header
+
+ std::array<std::uint8_t, DECOMPRESS_BUFSIZE> m_buffer; // buffer for decompression
+};
+
+
+class zip_file_wrapper : public zip_file
+{
+public:
+ zip_file_wrapper(zip_file_impl::ptr &&impl) : m_impl(std::move(impl)) { assert(m_impl); }
+ virtual ~zip_file_wrapper() { zip_file_impl::close(std::move(m_impl)); }
+
+ virtual const file_header *first_file() override { return m_impl->first_file(); }
+ virtual const file_header *next_file() override { return m_impl->next_file(); }
+ virtual error decompress(void *buffer, std::uint32_t length) override { return m_impl->decompress(buffer, length); }
+
+private:
+ zip_file_impl::ptr m_impl;
+};
+
+
+
+/***************************************************************************
INLINE FUNCTIONS
***************************************************************************/
@@ -108,7 +268,7 @@
* @return The word.
*/
-static inline UINT16 read_word(UINT8 *buf)
+inline UINT16 read_word(UINT8 *buf)
{
return (buf[1] << 8) | buf[0];
}
@@ -123,7 +283,7 @@ static inline UINT16 read_word(UINT8 *buf)
* @return The double word.
*/
-static inline UINT32 read_dword(UINT8 *buf)
+inline UINT32 read_dword(UINT8 *buf)
{
return (buf[3] << 24) | (buf[2] << 16) | (buf[1] << 8) | buf[0];
}
@@ -135,130 +295,8 @@ static inline UINT32 read_dword(UINT8 *buf)
***************************************************************************/
/** @brief The zip cache[ zip cache size]. */
-static zip_file *zip_cache[ZIP_CACHE_SIZE];
-
-
-
-/***************************************************************************
- FUNCTION PROTOTYPES
-***************************************************************************/
-
-/* cache management */
-static void free_zip_file(zip_file *zip);
+std::array<zip_file_impl::ptr, zip_file_impl::CACHE_SIZE> zip_file_impl::s_cache;
-/* ZIP file parsing */
-static zip_error read_ecd(zip_file *zip);
-static zip_error get_compressed_data_offset(zip_file *zip, UINT64 *offset);
-
-/* decompression interfaces */
-static zip_error decompress_data_type_0(zip_file *zip, UINT64 offset, void *buffer, UINT32 length);
-static zip_error decompress_data_type_8(zip_file *zip, UINT64 offset, void *buffer, UINT32 length);
-
-
-
-/***************************************************************************
- ZIP FILE ACCESS
-***************************************************************************/
-
-/*-------------------------------------------------
- zip_file_open - opens a ZIP file for reading
--------------------------------------------------*/
-
-/**
- * @fn zip_error zip_file_open(const char *filename, zip_file **zip)
- *
- * @brief Queries if a given zip file open.
- *
- * @param filename Filename of the file.
- * @param [in,out] zip If non-null, the zip.
- *
- * @return A zip_error.
- */
-
-zip_error zip_file_open(const char *filename, zip_file **zip)
-{
- zip_error ziperr = ZIPERR_NONE;
- file_error filerr;
- UINT32 read_length;
- zip_file *newzip;
- char *string;
- int cachenum;
-
- /* ensure we start with a NULL result */
- *zip = nullptr;
-
- /* see if we are in the cache, and reopen if so */
- for (cachenum = 0; cachenum < ARRAY_LENGTH(zip_cache); cachenum++)
- {
- zip_file *cached = zip_cache[cachenum];
-
- /* if we have a valid entry and it matches our filename, use it and remove from the cache */
- if (cached != nullptr && cached->filename != nullptr && strcmp(filename, cached->filename) == 0)
- {
- *zip = cached;
- zip_cache[cachenum] = nullptr;
- return ZIPERR_NONE;
- }
- }
-
- /* allocate memory for the zip_file structure */
- newzip = (zip_file *)malloc(sizeof(*newzip));
- if (newzip == nullptr)
- return ZIPERR_OUT_OF_MEMORY;
- memset(newzip, 0, sizeof(*newzip));
-
- /* open the file */
- filerr = osd_open(filename, OPEN_FLAG_READ, &newzip->file, &newzip->length);
- if (filerr != FILERR_NONE)
- {
- ziperr = ZIPERR_FILE_ERROR;
- goto error;
- }
-
- /* read ecd data */
- ziperr = read_ecd(newzip);
- if (ziperr != ZIPERR_NONE)
- goto error;
-
- /* verify that we can work with this zipfile (no disk spanning allowed) */
- if (newzip->ecd.disk_number != newzip->ecd.cd_start_disk_number || newzip->ecd.cd_disk_entries != newzip->ecd.cd_total_entries)
- {
- ziperr = ZIPERR_UNSUPPORTED;
- goto error;
- }
-
- /* allocate memory for the central directory */
- newzip->cd = (UINT8 *)malloc(newzip->ecd.cd_size + 1);
- if (newzip->cd == nullptr)
- {
- ziperr = ZIPERR_OUT_OF_MEMORY;
- goto error;
- }
-
- /* read the central directory */
- filerr = osd_read(newzip->file, newzip->cd, newzip->ecd.cd_start_disk_offset, newzip->ecd.cd_size, &read_length);
- if (filerr != FILERR_NONE || read_length != newzip->ecd.cd_size)
- {
- ziperr = (filerr == FILERR_NONE) ? ZIPERR_FILE_TRUNCATED : ZIPERR_FILE_ERROR;
- goto error;
- }
-
- /* make a copy of the filename for caching purposes */
- string = (char *)malloc(strlen(filename) + 1);
- if (string == nullptr)
- {
- ziperr = ZIPERR_OUT_OF_MEMORY;
- goto error;
- }
- strcpy(string, filename);
- newzip->filename = string;
- *zip = newzip;
- return ZIPERR_NONE;
-
-error:
- free_zip_file(newzip);
- return ziperr;
-}
/*-------------------------------------------------
@@ -274,57 +312,30 @@ error:
* @param [in,out] zip If non-null, the zip.
*/
-void zip_file_close(zip_file *zip)
+void zip_file_impl::close(ptr &&zip)
{
- int cachenum;
+ if (!zip) return;
- /* close the open files */
- if (zip->file != nullptr)
- osd_close(zip->file);
- zip->file = nullptr;
+ // close the open files
+ zip->m_file.reset();
- /* find the first NULL entry in the cache */
- for (cachenum = 0; cachenum < ARRAY_LENGTH(zip_cache); cachenum++)
- if (zip_cache[cachenum] == nullptr)
+ // find the first NULL entry in the cache
+ std::size_t cachenum;
+ for (cachenum = 0; cachenum < s_cache.size(); cachenum++)
+ if (!s_cache[cachenum])
break;
- /* if no room left in the cache, free the bottommost entry */
- if (cachenum == ARRAY_LENGTH(zip_cache))
- free_zip_file(zip_cache[--cachenum]);
-
- /* move everyone else down and place us at the top */
- if (cachenum != 0)
- memmove(&zip_cache[1], &zip_cache[0], cachenum * sizeof(zip_cache[0]));
- zip_cache[0] = zip;
-}
-
-
-/*-------------------------------------------------
- zip_file_cache_clear - clear the ZIP file
- cache and free all memory
--------------------------------------------------*/
-
-/**
- * @fn void zip_file_cache_clear(void)
- *
- * @brief Zip file cache clear.
- */
-
-void zip_file_cache_clear(void)
-{
- int cachenum;
+ // if no room left in the cache, free the bottommost entry
+ if (cachenum == s_cache.size())
+ s_cache[--cachenum].reset();
- /* clear call cache entries */
- for (cachenum = 0; cachenum < ARRAY_LENGTH(zip_cache); cachenum++)
- if (zip_cache[cachenum] != nullptr)
- {
- free_zip_file(zip_cache[cachenum]);
- zip_cache[cachenum] = nullptr;
- }
+ // move everyone else down and place us at the top
+ for ( ; cachenum > 0; cachenum--)
+ s_cache[cachenum] = std::move(s_cache[cachenum - 1]);
+ s_cache[0] = std::move(zip);
}
-
/***************************************************************************
CONTAINED FILE ACCESS
***************************************************************************/
@@ -344,11 +355,11 @@ void zip_file_cache_clear(void)
* @return null if it fails, else a zip_file_header*.
*/
-const zip_file_header *zip_file_first_file(zip_file *zip)
+const zip_file::file_header *zip_file_impl::first_file()
{
/* reset the position and go from there */
- zip->cd_pos = 0;
- return zip_file_next_file(zip);
+ m_cd_pos = 0;
+ return next_file();
}
@@ -367,55 +378,55 @@ const zip_file_header *zip_file_first_file(zip_file *zip)
* @return null if it fails, else a zip_file_header*.
*/
-const zip_file_header *zip_file_next_file(zip_file *zip)
+const zip_file::file_header *zip_file_impl::next_file()
{
- /* fix up any modified data */
- if (zip->header.raw != nullptr)
+ // fix up any modified data
+ if (m_header.raw)
{
- zip->header.raw[ZIPCFN + zip->header.filename_length] = zip->header.saved;
- zip->header.raw = nullptr;
+ m_header.raw[ZIPCFN + m_header.filename_length] = m_header.saved;
+ m_header.raw = nullptr;
}
- /* if we're at or past the end, we're done */
- if (zip->cd_pos >= zip->ecd.cd_size)
+ // if we're at or past the end, we're done
+ if (m_cd_pos >= m_ecd.cd_size)
return nullptr;
- /* extract file header info */
- zip->header.raw = zip->cd + zip->cd_pos;
- zip->header.rawlength = ZIPCFN;
- zip->header.signature = read_dword(zip->header.raw + ZIPCENSIG);
- zip->header.version_created = read_word (zip->header.raw + ZIPCVER);
- zip->header.version_needed = read_word (zip->header.raw + ZIPCVXT);
- zip->header.bit_flag = read_word (zip->header.raw + ZIPCFLG);
- zip->header.compression = read_word (zip->header.raw + ZIPCMTHD);
- zip->header.file_time = read_word (zip->header.raw + ZIPCTIM);
- zip->header.file_date = read_word (zip->header.raw + ZIPCDAT);
- zip->header.crc = read_dword(zip->header.raw + ZIPCCRC);
- zip->header.compressed_length = read_dword(zip->header.raw + ZIPCSIZ);
- zip->header.uncompressed_length = read_dword(zip->header.raw + ZIPCUNC);
- zip->header.filename_length = read_word (zip->header.raw + ZIPCFNL);
- zip->header.extra_field_length = read_word (zip->header.raw + ZIPCXTL);
- zip->header.file_comment_length = read_word (zip->header.raw + ZIPCCML);
- zip->header.start_disk_number = read_word (zip->header.raw + ZIPDSK);
- zip->header.internal_attributes = read_word (zip->header.raw + ZIPINT);
- zip->header.external_attributes = read_dword(zip->header.raw + ZIPEXT);
- zip->header.local_header_offset = read_dword(zip->header.raw + ZIPOFST);
- zip->header.filename = (char *)zip->header.raw + ZIPCFN;
-
- /* make sure we have enough data */
- zip->header.rawlength += zip->header.filename_length;
- zip->header.rawlength += zip->header.extra_field_length;
- zip->header.rawlength += zip->header.file_comment_length;
- if (zip->cd_pos + zip->header.rawlength > zip->ecd.cd_size)
+ // extract file header info
+ m_header.raw = &m_cd[0] + m_cd_pos;
+ m_header.rawlength = ZIPCFN;
+ m_header.signature = read_dword(m_header.raw + ZIPCENSIG);
+ m_header.version_created = read_word (m_header.raw + ZIPCVER);
+ m_header.version_needed = read_word (m_header.raw + ZIPCVXT);
+ m_header.bit_flag = read_word (m_header.raw + ZIPCFLG);
+ m_header.compression = read_word (m_header.raw + ZIPCMTHD);
+ m_header.file_time = read_word (m_header.raw + ZIPCTIM);
+ m_header.file_date = read_word (m_header.raw + ZIPCDAT);
+ m_header.crc = read_dword(m_header.raw + ZIPCCRC);
+ m_header.compressed_length = read_dword(m_header.raw + ZIPCSIZ);
+ m_header.uncompressed_length = read_dword(m_header.raw + ZIPCUNC);
+ m_header.filename_length = read_word (m_header.raw + ZIPCFNL);
+ m_header.extra_field_length = read_word (m_header.raw + ZIPCXTL);
+ m_header.file_comment_length = read_word (m_header.raw + ZIPCCML);
+ m_header.start_disk_number = read_word (m_header.raw + ZIPDSK);
+ m_header.internal_attributes = read_word (m_header.raw + ZIPINT);
+ m_header.external_attributes = read_dword(m_header.raw + ZIPEXT);
+ m_header.local_header_offset = read_dword(m_header.raw + ZIPOFST);
+ m_header.filename = reinterpret_cast<const char *>(m_header.raw + ZIPCFN);
+
+ // make sure we have enough data
+ m_header.rawlength += m_header.filename_length;
+ m_header.rawlength += m_header.extra_field_length;
+ m_header.rawlength += m_header.file_comment_length;
+ if (m_cd_pos + m_header.rawlength > m_ecd.cd_size)
return nullptr;
- /* NULL terminate the filename */
- zip->header.saved = zip->header.raw[ZIPCFN + zip->header.filename_length];
- zip->header.raw[ZIPCFN + zip->header.filename_length] = 0;
+ // NULL terminate the filename
+ m_header.saved = m_header.raw[ZIPCFN + m_header.filename_length];
+ m_header.raw[ZIPCFN + m_header.filename_length] = 0;
- /* advance the position */
- zip->cd_pos += zip->header.rawlength;
- return &zip->header;
+ // advance the position
+ m_cd_pos += m_header.rawlength;
+ return &m_header;
}
@@ -436,38 +447,38 @@ const zip_file_header *zip_file_next_file(zip_file *zip)
* @return A zip_error.
*/
-zip_error zip_file_decompress(zip_file *zip, void *buffer, UINT32 length)
+zip_file::error zip_file_impl::decompress(void *buffer, UINT32 length)
{
- zip_error ziperr;
- UINT64 offset;
+ zip_file::error ziperr;
+ std::uint64_t offset;
- /* if we don't have enough buffer, error */
- if (length < zip->header.uncompressed_length)
- return ZIPERR_BUFFER_TOO_SMALL;
+ // if we don't have enough buffer, error
+ if (length < m_header.uncompressed_length)
+ return zip_file::error::BUFFER_TOO_SMALL;
- /* make sure the info in the header aligns with what we know */
- if (zip->header.start_disk_number != zip->ecd.disk_number)
- return ZIPERR_UNSUPPORTED;
+ // make sure the info in the header aligns with what we know
+ if (m_header.start_disk_number != m_ecd.disk_number)
+ return zip_file::error::UNSUPPORTED;
- /* get the compressed data offset */
- ziperr = get_compressed_data_offset(zip, &offset);
- if (ziperr != ZIPERR_NONE)
+ // get the compressed data offset
+ ziperr = get_compressed_data_offset(offset);
+ if (ziperr != zip_file::error::NONE)
return ziperr;
- /* handle compression types */
- switch (zip->header.compression)
+ // handle compression types
+ switch (m_header.compression)
{
- case 0:
- ziperr = decompress_data_type_0(zip, offset, buffer, length);
- break;
+ case 0:
+ ziperr = decompress_data_type_0(offset, buffer, length);
+ break;
- case 8:
- ziperr = decompress_data_type_8(zip, offset, buffer, length);
- break;
+ case 8:
+ ziperr = decompress_data_type_8(offset, buffer, length);
+ break;
- default:
- ziperr = ZIPERR_UNSUPPORTED;
- break;
+ default:
+ ziperr = zip_file::error::UNSUPPORTED;
+ break;
}
return ziperr;
}
@@ -475,41 +486,6 @@ zip_error zip_file_decompress(zip_file *zip, void *buffer, UINT32 length)
/***************************************************************************
- CACHE MANAGEMENT
-***************************************************************************/
-
-/*-------------------------------------------------
- free_zip_file - free all the data for a
- zip_file
--------------------------------------------------*/
-
-/**
- * @fn static void free_zip_file(zip_file *zip)
- *
- * @brief Free zip file.
- *
- * @param [in,out] zip If non-null, the zip.
- */
-
-static void free_zip_file(zip_file *zip)
-{
- if (zip != nullptr)
- {
- if (zip->file != nullptr)
- osd_close(zip->file);
- if (zip->filename != nullptr)
- free((void *)zip->filename);
- if (zip->ecd.raw != nullptr)
- free(zip->ecd.raw);
- if (zip->cd != nullptr)
- free(zip->cd);
- free(zip);
- }
-}
-
-
-
-/***************************************************************************
ZIP FILE PARSING
***************************************************************************/
@@ -527,72 +503,69 @@ static void free_zip_file(zip_file *zip)
* @return The ecd.
*/
-static zip_error read_ecd(zip_file *zip)
+zip_file::error zip_file_impl::read_ecd()
{
- UINT32 buflen = 1024;
- UINT8 *buffer;
+ // make sure the file handle is open
+ auto const ziperr = reopen();
+ if (ziperr != zip_file::error::NONE)
+ return ziperr;
- /* we may need multiple tries */
+ // we may need multiple tries
+ std::uint32_t buflen = 1024;
while (buflen < 65536)
{
- file_error error;
- UINT32 read_length;
- INT32 offset;
-
- /* max out the buffer length at the size of the file */
- if (buflen > zip->length)
- buflen = zip->length;
-
- /* allocate buffer */
- buffer = (UINT8 *)malloc(buflen + 1);
- if (buffer == nullptr)
- return ZIPERR_OUT_OF_MEMORY;
-
- /* read in one buffers' worth of data */
- error = osd_read(zip->file, buffer, zip->length - buflen, buflen, &read_length);
- if (error != FILERR_NONE || read_length != buflen)
- {
- free(buffer);
- return ZIPERR_FILE_ERROR;
- }
-
- /* find the ECD signature */
+ // max out the buffer length at the size of the file
+ if (buflen > m_length)
+ buflen = m_length;
+
+ // allocate buffer
+ std::unique_ptr<std::uint8_t []> buffer;
+ try { buffer.reset(new std::uint8_t[buflen + 1]); }
+ catch (...) { return zip_file::error::OUT_OF_MEMORY; }
+
+ // read in one buffers' worth of data
+ std::uint32_t read_length;
+ auto const error = m_file->read(&buffer[0], m_length - buflen, buflen, read_length);
+ if (error != osd_file::error::NONE || read_length != buflen)
+ return zip_file::error::FILE_ERROR;
+
+ // find the ECD signature
+ std::int32_t offset;
for (offset = buflen - 22; offset >= 0; offset--)
if (buffer[offset + 0] == 'P' && buffer[offset + 1] == 'K' && buffer[offset + 2] == 0x05 && buffer[offset + 3] == 0x06)
break;
- /* if we found it, fill out the data */
+ // if we found it, fill out the data
if (offset >= 0)
{
- /* reuse the buffer as our ECD buffer */
- zip->ecd.raw = buffer;
- zip->ecd.rawlength = buflen - offset;
+ // reuse the buffer as our ECD buffer
+ m_ecd.raw = std::move(buffer);
+ m_ecd.rawlength = buflen - offset;
/* append a NULL terminator to the comment */
- memmove(&buffer[0], &buffer[offset], zip->ecd.rawlength);
- zip->ecd.raw[zip->ecd.rawlength] = 0;
+ memmove(&m_ecd.raw[0], &m_ecd.raw[offset], m_ecd.rawlength);
+ m_ecd.raw[m_ecd.rawlength] = 0;
/* extract ecd info */
- zip->ecd.signature = read_dword(zip->ecd.raw + ZIPESIG);
- zip->ecd.disk_number = read_word (zip->ecd.raw + ZIPEDSK);
- zip->ecd.cd_start_disk_number = read_word (zip->ecd.raw + ZIPECEN);
- zip->ecd.cd_disk_entries = read_word (zip->ecd.raw + ZIPENUM);
- zip->ecd.cd_total_entries = read_word (zip->ecd.raw + ZIPECENN);
- zip->ecd.cd_size = read_dword(zip->ecd.raw + ZIPECSZ);
- zip->ecd.cd_start_disk_offset = read_dword(zip->ecd.raw + ZIPEOFST);
- zip->ecd.comment_length = read_word (zip->ecd.raw + ZIPECOML);
- zip->ecd.comment = (const char *)(zip->ecd.raw + ZIPECOM);
- return ZIPERR_NONE;
+ m_ecd.signature = read_dword(&m_ecd.raw[ZIPESIG]);
+ m_ecd.disk_number = read_word (&m_ecd.raw[ZIPEDSK]);
+ m_ecd.cd_start_disk_number = read_word (&m_ecd.raw[ZIPECEN]);
+ m_ecd.cd_disk_entries = read_word (&m_ecd.raw[ZIPENUM]);
+ m_ecd.cd_total_entries = read_word (&m_ecd.raw[ZIPECENN]);
+ m_ecd.cd_size = read_dword(&m_ecd.raw[ZIPECSZ]);
+ m_ecd.cd_start_disk_offset = read_dword(&m_ecd.raw[ZIPEOFST]);
+ m_ecd.comment_length = read_word (&m_ecd.raw[ZIPECOML]);
+ m_ecd.comment = reinterpret_cast<const char *>(&m_ecd.raw[ZIPECOM]);
+ return zip_file::error::NONE;
}
- /* didn't find it; free this buffer and expand our search */
- free(buffer);
- if (buflen < zip->length)
+ // didn't find it; free this buffer and expand our search
+ if (buflen < m_length)
buflen *= 2;
else
- return ZIPERR_BAD_SIGNATURE;
+ return zip_file::error::BAD_SIGNATURE;
}
- return ZIPERR_OUT_OF_MEMORY;
+ return zip_file::error::OUT_OF_MEMORY;
}
@@ -612,30 +585,25 @@ static zip_error read_ecd(zip_file *zip)
* @return The compressed data offset.
*/
-static zip_error get_compressed_data_offset(zip_file *zip, UINT64 *offset)
+zip_file::error zip_file_impl::get_compressed_data_offset(std::uint64_t &offset)
{
- file_error error;
- UINT32 read_length;
-
- /* make sure the file handle is open */
- if (zip->file == nullptr)
- {
- int filerr = osd_open(zip->filename, OPEN_FLAG_READ, &zip->file, &zip->length);
- if (filerr != FILERR_NONE)
- return ZIPERR_FILE_ERROR;
- }
+ // make sure the file handle is open
+ auto const ziperr = reopen();
+ if (ziperr != zip_file::error::NONE)
+ return ziperr;
- /* now go read the fixed-sized part of the local file header */
- error = osd_read(zip->file, zip->buffer, zip->header.local_header_offset, ZIPNAME, &read_length);
- if (error != FILERR_NONE || read_length != ZIPNAME)
- return (error == FILERR_NONE) ? ZIPERR_FILE_TRUNCATED : ZIPERR_FILE_ERROR;
+ // now go read the fixed-sized part of the local file header
+ std::uint32_t read_length;
+ auto const error = m_file->read(&m_buffer[0], m_header.local_header_offset, ZIPNAME, read_length);
+ if (error != osd_file::error::NONE || read_length != ZIPNAME)
+ return (error == osd_file::error::NONE) ? zip_file::error::FILE_TRUNCATED : zip_file::error::FILE_ERROR;
/* compute the final offset */
- *offset = zip->header.local_header_offset + ZIPNAME;
- *offset += read_word(zip->buffer + ZIPFNLN);
- *offset += read_word(zip->buffer + ZIPXTRALN);
+ offset = m_header.local_header_offset + ZIPNAME;
+ offset += read_word(&m_buffer[ZIPFNLN]);
+ offset += read_word(&m_buffer[ZIPXTRALN]);
- return ZIPERR_NONE;
+ return zip_file::error::NONE;
}
@@ -662,19 +630,18 @@ static zip_error get_compressed_data_offset(zip_file *zip, UINT64 *offset)
* @return A zip_error.
*/
-static zip_error decompress_data_type_0(zip_file *zip, UINT64 offset, void *buffer, UINT32 length)
+zip_file::error zip_file_impl::decompress_data_type_0(std::uint64_t offset, void *buffer, std::uint32_t length)
{
- file_error filerr;
- UINT32 read_length;
-
- /* the data is uncompressed; just read it */
- filerr = osd_read(zip->file, buffer, offset, zip->header.compressed_length, &read_length);
- if (filerr != FILERR_NONE)
- return ZIPERR_FILE_ERROR;
- else if (read_length != zip->header.compressed_length)
- return ZIPERR_FILE_TRUNCATED;
+ std::uint32_t read_length;
+
+ // the data is uncompressed; just read it
+ auto const filerr = m_file->read(buffer, offset, m_header.compressed_length, read_length);
+ if (filerr != osd_file::error::NONE)
+ return zip_file::error::FILE_ERROR;
+ else if (read_length != m_header.compressed_length)
+ return zip_file::error::FILE_TRUNCATED;
else
- return ZIPERR_NONE;
+ return zip_file::error::NONE;
}
@@ -696,75 +663,148 @@ static zip_error decompress_data_type_0(zip_file *zip, UINT64 offset, void *buff
* @return A zip_error.
*/
-static zip_error decompress_data_type_8(zip_file *zip, UINT64 offset, void *buffer, UINT32 length)
+zip_file::error zip_file_impl::decompress_data_type_8(std::uint64_t offset, void *buffer, std::uint32_t length)
{
- UINT32 input_remaining = zip->header.compressed_length;
- UINT32 read_length;
- z_stream stream;
- int filerr;
+ std::uint32_t input_remaining = m_header.compressed_length;
int zerr;
- /* make sure we don't need a newer mechanism */
- if (zip->header.version_needed > 0x14)
- return ZIPERR_UNSUPPORTED;
+ // make sure we don't need a newer mechanism
+ if (m_header.version_needed > 0x14)
+ return zip_file::error::UNSUPPORTED;
/* reset the stream */
+ z_stream stream;
memset(&stream, 0, sizeof(stream));
stream.next_out = (Bytef *)buffer;
stream.avail_out = length;
- /* initialize the decompressor */
+ // initialize the decompressor
zerr = inflateInit2(&stream, -MAX_WBITS);
if (zerr != Z_OK)
- return ZIPERR_DECOMPRESS_ERROR;
+ return zip_file::error::DECOMPRESS_ERROR;
- /* loop until we're done */
+ // loop until we're done
while (1)
{
- /* read in the next chunk of data */
- filerr = osd_read(zip->file, zip->buffer, offset, MIN(input_remaining, sizeof(zip->buffer)), &read_length);
- if (filerr != FILERR_NONE)
+ // read in the next chunk of data
+ std::uint32_t read_length;
+ auto const filerr = m_file->read(&m_buffer[0], offset, (std::min<std::uint32_t>)(input_remaining, m_buffer.size()), read_length);
+ if (filerr != osd_file::error::NONE)
{
inflateEnd(&stream);
- return ZIPERR_FILE_ERROR;
+ return zip_file::error::FILE_ERROR;
}
offset += read_length;
- /* if we read nothing, but still have data left, the file is truncated */
+ // if we read nothing, but still have data left, the file is truncated
if (read_length == 0 && input_remaining > 0)
{
inflateEnd(&stream);
- return ZIPERR_FILE_TRUNCATED;
+ return zip_file::error::FILE_TRUNCATED;
}
- /* fill out the input data */
- stream.next_in = zip->buffer;
+ // fill out the input data
+ stream.next_in = &m_buffer[0];
stream.avail_in = read_length;
input_remaining -= read_length;
- /* add a dummy byte at end of compressed data */
+ // add a dummy byte at end of compressed data
if (input_remaining == 0)
stream.avail_in++;
- /* now inflate */
+ // now inflate
zerr = inflate(&stream, Z_NO_FLUSH);
if (zerr == Z_STREAM_END)
break;
if (zerr != Z_OK)
{
inflateEnd(&stream);
- return ZIPERR_DECOMPRESS_ERROR;
+ return zip_file::error::DECOMPRESS_ERROR;
}
}
- /* finish decompression */
+ // finish decompression
zerr = inflateEnd(&stream);
if (zerr != Z_OK)
- return ZIPERR_DECOMPRESS_ERROR;
+ return zip_file::error::DECOMPRESS_ERROR;
/* if anything looks funny, report an error */
if (stream.avail_out > 0 || input_remaining > 0)
- return ZIPERR_DECOMPRESS_ERROR;
+ return zip_file::error::DECOMPRESS_ERROR;
+
+ return zip_file::error::NONE;
+}
- return ZIPERR_NONE;
+} // anonymous namespace
+
+
+
+/***************************************************************************
+ ZIP FILE ACCESS
+***************************************************************************/
+
+/*-------------------------------------------------
+ zip_file_open - opens a ZIP file for reading
+-------------------------------------------------*/
+
+/**
+ * @fn zip_error zip_file_open(const char *filename, zip_file **zip)
+ *
+ * @brief Queries if a given zip file open.
+ *
+ * @param filename Filename of the file.
+ * @param [in,out] zip If non-null, the zip.
+ *
+ * @return A zip_error.
+ */
+
+zip_file::error zip_file::open(const std::string &filename, ptr &zip)
+{
+ // ensure we start with a NULL result
+ zip.reset();
+
+ // see if we are in the cache, and reopen if so
+ zip_file_impl::ptr newimpl(zip_file_impl::find_cached(filename));
+
+ if (!newimpl)
+ {
+ // allocate memory for the zip_file structure
+ try { newimpl = std::make_unique<zip_file_impl>(filename); }
+ catch (...) { return error::OUT_OF_MEMORY; }
+ auto const ziperr = newimpl->initialize();
+ if (ziperr != error::NONE) return ziperr;
+ }
+
+ try
+ {
+ zip = std::make_unique<zip_file_wrapper>(std::move(newimpl));
+ return error::NONE;
+ }
+ catch (...)
+ {
+ zip_file_impl::close(std::move(newimpl));
+ return error::OUT_OF_MEMORY;
+ }
+}
+
+
+/*-------------------------------------------------
+ zip_file_cache_clear - clear the ZIP file
+ cache and free all memory
+-------------------------------------------------*/
+
+/**
+ * @fn void zip_file_cache_clear(void)
+ *
+ * @brief Zip file cache clear.
+ */
+
+void zip_file::cache_clear()
+{
+ zip_file_impl::cache_clear();
+}
+
+
+zip_file::~zip_file()
+{
}
diff --git a/src/lib/util/unzip.h b/src/lib/util/unzip.h
index fa3956be8c3..2882cda0fc3 100644
--- a/src/lib/util/unzip.h
+++ b/src/lib/util/unzip.h
@@ -1,5 +1,5 @@
// license:BSD-3-Clause
-// copyright-holders:Aaron Giles
+// copyright-holders:Aaron Giles, Vas Crabb
/***************************************************************************
unzip.h
@@ -10,129 +10,88 @@
#pragma once
-#ifndef __UNZIP_H__
-#define __UNZIP_H__
+#ifndef MAME_LIB_UTIL_UNZIP_H
+#define MAME_LIB_UTIL_UNZIP_H
#include "osdcore.h"
-
-/***************************************************************************
- CONSTANTS
-***************************************************************************/
-
-#define ZIP_DECOMPRESS_BUFSIZE 16384
-
-/* Error types */
-enum zip_error
-{
- ZIPERR_NONE = 0,
- ZIPERR_OUT_OF_MEMORY,
- ZIPERR_FILE_ERROR,
- ZIPERR_BAD_SIGNATURE,
- ZIPERR_DECOMPRESS_ERROR,
- ZIPERR_FILE_TRUNCATED,
- ZIPERR_FILE_CORRUPT,
- ZIPERR_UNSUPPORTED,
- ZIPERR_BUFFER_TOO_SMALL
-};
-
+#include <cstdint>
+#include <memory>
+#include <string>
/***************************************************************************
TYPE DEFINITIONS
***************************************************************************/
-/* contains extracted file header information */
-struct zip_file_header
+// describes an open ZIP file
+class zip_file
{
- UINT32 signature; /* central file header signature */
- UINT16 version_created; /* version made by */
- UINT16 version_needed; /* version needed to extract */
- UINT16 bit_flag; /* general purpose bit flag */
- UINT16 compression; /* compression method */
- UINT16 file_time; /* last mod file time */
- UINT16 file_date; /* last mod file date */
- UINT32 crc; /* crc-32 */
- UINT32 compressed_length; /* compressed size */
- UINT32 uncompressed_length; /* uncompressed size */
- UINT16 filename_length; /* filename length */
- UINT16 extra_field_length; /* extra field length */
- UINT16 file_comment_length; /* file comment length */
- UINT16 start_disk_number; /* disk number start */
- UINT16 internal_attributes; /* internal file attributes */
- UINT32 external_attributes; /* external file attributes */
- UINT32 local_header_offset; /* relative offset of local header */
- const char * filename; /* filename */
-
- UINT8 * raw; /* pointer to the raw data */
- UINT32 rawlength; /* length of the raw data */
- UINT8 saved; /* saved byte from after filename */
-};
-
-
-/* contains extracted end of central directory information */
-struct zip_ecd
-{
- UINT32 signature; /* end of central dir signature */
- UINT16 disk_number; /* number of this disk */
- UINT16 cd_start_disk_number; /* number of the disk with the start of the central directory */
- UINT16 cd_disk_entries; /* total number of entries in the central directory on this disk */
- UINT16 cd_total_entries; /* total number of entries in the central directory */
- UINT32 cd_size; /* size of the central directory */
- UINT32 cd_start_disk_offset; /* offset of start of central directory with respect to the starting disk number */
- UINT16 comment_length; /* .ZIP file comment length */
- const char * comment; /* .ZIP file comment */
-
- UINT8 * raw; /* pointer to the raw data */
- UINT32 rawlength; /* length of the raw data */
-};
-
-
-/* describes an open ZIP file */
-struct zip_file
-{
- const char * filename; /* copy of ZIP filename (for caching) */
- osd_file * file; /* OSD file handle */
- UINT64 length; /* length of zip file */
-
- zip_ecd ecd; /* end of central directory */
-
- UINT8 * cd; /* central directory raw data */
- UINT32 cd_pos; /* position in central directory */
- zip_file_header header; /* current file header */
-
- UINT8 buffer[ZIP_DECOMPRESS_BUFSIZE]; /* buffer for decompression */
+public:
+
+ // Error types
+ enum class error
+ {
+ NONE = 0,
+ OUT_OF_MEMORY,
+ FILE_ERROR,
+ BAD_SIGNATURE,
+ DECOMPRESS_ERROR,
+ FILE_TRUNCATED,
+ FILE_CORRUPT,
+ UNSUPPORTED,
+ BUFFER_TOO_SMALL
+ };
+
+ // contains extracted file header information
+ struct file_header
+ {
+ std::uint32_t signature; // central file header signature
+ std::uint16_t version_created; // version made by
+ std::uint16_t version_needed; // version needed to extract
+ std::uint16_t bit_flag; // general purpose bit flag
+ std::uint16_t compression; // compression method
+ std::uint16_t file_time; // last mod file time
+ std::uint16_t file_date; // last mod file date
+ std::uint32_t crc; // crc-32
+ std::uint32_t compressed_length; // compressed size
+ std::uint32_t uncompressed_length; // uncompressed size
+ std::uint16_t filename_length; // filename length
+ std::uint16_t extra_field_length; // extra field length
+ std::uint16_t file_comment_length; // file comment length
+ std::uint16_t start_disk_number; // disk number start
+ std::uint16_t internal_attributes; // internal file attributes
+ std::uint32_t external_attributes; // external file attributes
+ std::uint32_t local_header_offset; // relative offset of local header
+ const char * filename; // filename
+ };
+
+ typedef std::unique_ptr<zip_file> ptr;
+
+
+ /* ----- ZIP file access ----- */
+
+ // open a ZIP file and parse its central directory
+ static error open(const std::string &filename, ptr &zip);
+
+ // close a ZIP file (may actually be left open due to caching)
+ virtual ~zip_file();
+
+ // clear out all open ZIP files from the cache
+ static void cache_clear();
+
+
+ /* ----- contained file access ----- */
+
+ // find the first file in the ZIP
+ virtual const file_header *first_file() = 0;
+
+ // find the next file in the ZIP
+ virtual const file_header *next_file() = 0;
+
+ // decompress the most recently found file in the ZIP
+ virtual error decompress(void *buffer, std::uint32_t length) = 0;
};
-
-/***************************************************************************
- FUNCTION PROTOTYPES
-***************************************************************************/
-
-
-/* ----- ZIP file access ----- */
-
-/* open a ZIP file and parse its central directory */
-zip_error zip_file_open(const char *filename, zip_file **zip);
-
-/* close a ZIP file (may actually be left open due to caching) */
-void zip_file_close(zip_file *zip);
-
-/* clear out all open ZIP files from the cache */
-void zip_file_cache_clear(void);
-
-
-/* ----- contained file access ----- */
-
-/* find the first file in the ZIP */
-const zip_file_header *zip_file_first_file(zip_file *zip);
-
-/* find the next file in the ZIP */
-const zip_file_header *zip_file_next_file(zip_file *zip);
-
-/* decompress the most recently found file in the ZIP */
-zip_error zip_file_decompress(zip_file *zip, void *buffer, UINT32 length);
-
-
-#endif /* __UNZIP_H__ */
+#endif // MAME_LIB_UTIL_UNZIP_H
diff --git a/src/lib/util/zippath.cpp b/src/lib/util/zippath.cpp
index efe7c710481..18e2031dcdd 100644
--- a/src/lib/util/zippath.cpp
+++ b/src/lib/util/zippath.cpp
@@ -66,7 +66,7 @@ public:
/** @brief true to called zip first. */
bool called_zip_first;
/** @brief The zipfile. */
- zip_file *zipfile;
+ zip_file::ptr zipfile;
/** @brief The zipprefix. */
std::string zipprefix;
/** @brief The returned dirlist. */
@@ -78,7 +78,7 @@ public:
FUNCTION PROTOTYPES
***************************************************************************/
-static const zip_file_header *zippath_find_sub_path(zip_file *zipfile, const char *subpath, osd_dir_entry_type *type);
+static const zip_file::file_header *zippath_find_sub_path(zip_file &zipfile, const char *subpath, osd_dir_entry_type *type);
static int is_zip_file(const char *path);
static int is_zip_file_separator(char c);
static int is_7z_file(const char *path);
@@ -251,42 +251,42 @@ std::string &zippath_combine(std::string &dst, const char *path1, const char *pa
/*-------------------------------------------------
file_error_from_zip_error - translates a
- file_error to a zip_error
+ osd_file::error to a zip_error
-------------------------------------------------*/
/**
- * @fn static file_error file_error_from_zip_error(zip_error ziperr)
+ * @fn static osd_file::error file_error_from_zip_error(zip_file::error ziperr)
*
* @brief File error from zip error.
*
* @param ziperr The ziperr.
*
- * @return A file_error.
+ * @return A osd_file::error.
*/
-static file_error file_error_from_zip_error(zip_error ziperr)
+static osd_file::error file_error_from_zip_error(zip_file::error ziperr)
{
- file_error filerr;
+ osd_file::error filerr;
switch(ziperr)
{
- case ZIPERR_NONE:
- filerr = FILERR_NONE;
- break;
- case ZIPERR_OUT_OF_MEMORY:
- filerr = FILERR_OUT_OF_MEMORY;
- break;
- case ZIPERR_BAD_SIGNATURE:
- case ZIPERR_DECOMPRESS_ERROR:
- case ZIPERR_FILE_TRUNCATED:
- case ZIPERR_FILE_CORRUPT:
- case ZIPERR_UNSUPPORTED:
- case ZIPERR_FILE_ERROR:
- filerr = FILERR_INVALID_DATA;
- break;
- case ZIPERR_BUFFER_TOO_SMALL:
- default:
- filerr = FILERR_FAILURE;
- break;
+ case zip_file::error::NONE:
+ filerr = osd_file::error::NONE;
+ break;
+ case zip_file::error::OUT_OF_MEMORY:
+ filerr = osd_file::error::OUT_OF_MEMORY;
+ break;
+ case zip_file::error::BAD_SIGNATURE:
+ case zip_file::error::DECOMPRESS_ERROR:
+ case zip_file::error::FILE_TRUNCATED:
+ case zip_file::error::FILE_CORRUPT:
+ case zip_file::error::UNSUPPORTED:
+ case zip_file::error::FILE_ERROR:
+ filerr = osd_file::error::INVALID_DATA;
+ break;
+ case zip_file::error::BUFFER_TOO_SMALL:
+ default:
+ filerr = osd_file::error::FAILURE;
+ break;
}
return filerr;
}
@@ -298,7 +298,7 @@ static file_error file_error_from_zip_error(zip_error ziperr)
-------------------------------------------------*/
/**
- * @fn static file_error create_core_file_from_zip(zip_file *zip, const zip_file_header *header, util::core_file::ptr &file)
+ * @fn static osd_file::error create_core_file_from_zip(zip_file *zip, const zip_file_header *header, util::core_file::ptr &file)
*
* @brief Creates core file from zip.
*
@@ -309,28 +309,28 @@ static file_error file_error_from_zip_error(zip_error ziperr)
* @return The new core file from zip.
*/
-static file_error create_core_file_from_zip(zip_file *zip, const zip_file_header *header, util::core_file::ptr &file)
+static osd_file::error create_core_file_from_zip(zip_file &zip, const zip_file::file_header *header, util::core_file::ptr &file)
{
- file_error filerr;
- zip_error ziperr;
+ osd_file::error filerr;
+ zip_file::error ziperr;
void *ptr;
ptr = malloc(header->uncompressed_length);
if (ptr == nullptr)
{
- filerr = FILERR_OUT_OF_MEMORY;
+ filerr = osd_file::error::OUT_OF_MEMORY;
goto done;
}
- ziperr = zip_file_decompress(zip, ptr, header->uncompressed_length);
- if (ziperr != ZIPERR_NONE)
+ ziperr = zip.decompress(ptr, header->uncompressed_length);
+ if (ziperr != zip_file::error::NONE)
{
filerr = file_error_from_zip_error(ziperr);
goto done;
}
filerr = util::core_file::open_ram_copy(ptr, header->uncompressed_length, OPEN_FLAG_READ, file);
- if (filerr != FILERR_NONE)
+ if (filerr != osd_file::error::NONE)
goto done;
done:
@@ -345,7 +345,7 @@ done:
-------------------------------------------------*/
/**
- * @fn file_error zippath_fopen(const char *filename, UINT32 openflags, util::core_file::ptr &file, std::string &revised_path)
+ * @fn osd_file::error zippath_fopen(const char *filename, UINT32 openflags, util::core_file::ptr &file, std::string &revised_path)
*
* @brief Zippath fopen.
*
@@ -354,17 +354,16 @@ done:
* @param [in,out] file [in,out] If non-null, the file.
* @param [in,out] revised_path Full pathname of the revised file.
*
- * @return A file_error.
+ * @return A osd_file::error.
*/
-file_error zippath_fopen(const char *filename, UINT32 openflags, util::core_file::ptr &file, std::string &revised_path)
+osd_file::error zippath_fopen(const char *filename, UINT32 openflags, util::core_file::ptr &file, std::string &revised_path)
{
- file_error filerr = FILERR_NOT_FOUND;
- zip_error ziperr;
- zip_file *zip = nullptr;
- const zip_file_header *header;
+ osd_file::error filerr = osd_file::error::NOT_FOUND;
+ zip_file::error ziperr;
+ zip_file::ptr zip;
+ const zip_file::file_header *header;
osd_dir_entry_type entry_type;
- char *alloc_fullpath = nullptr;
int len;
/* first, set up the two types of paths */
@@ -380,30 +379,30 @@ file_error zippath_fopen(const char *filename, UINT32 openflags, util::core_file
if (is_zip_file(mainpath.c_str()))
{
/* this file might be a zip file - lets take a look */
- ziperr = zip_file_open(mainpath.c_str(), &zip);
- if (ziperr == ZIPERR_NONE)
+ ziperr = zip_file::open(mainpath, zip);
+ if (ziperr == zip_file::error::NONE)
{
/* it is a zip file - error if we're not opening for reading */
if (openflags != OPEN_FLAG_READ)
{
- filerr = FILERR_ACCESS_DENIED;
+ filerr = osd_file::error::ACCESS_DENIED;
goto done;
}
if (subpath.length() > 0)
- header = zippath_find_sub_path(zip, subpath.c_str(), &entry_type);
+ header = zippath_find_sub_path(*zip, subpath.c_str(), &entry_type);
else
- header = zip_file_first_file(zip);
+ header = zip->first_file();
if (header == nullptr)
{
- filerr = FILERR_NOT_FOUND;
+ filerr = osd_file::error::NOT_FOUND;
goto done;
}
/* attempt to read the file */
- filerr = create_core_file_from_zip(zip, header, file);
- if (filerr != FILERR_NONE)
+ filerr = create_core_file_from_zip(*zip, header, file);
+ if (filerr != osd_file::error::NONE)
goto done;
/* update subpath, if appropriate */
@@ -416,17 +415,17 @@ file_error zippath_fopen(const char *filename, UINT32 openflags, util::core_file
}
else if (is_7z_file(mainpath.c_str()))
{
- filerr = FILERR_INVALID_DATA;
+ filerr = osd_file::error::INVALID_DATA;
goto done;
}
if (subpath.length() == 0)
filerr = util::core_file::open(filename, openflags, file);
else
- filerr = FILERR_NOT_FOUND;
+ filerr = osd_file::error::NOT_FOUND;
/* if we errored, then go up a directory */
- if (filerr != FILERR_NONE)
+ if (filerr != osd_file::error::NONE)
{
/* go up a directory */
std::string temp;
@@ -457,23 +456,19 @@ file_error zippath_fopen(const char *filename, UINT32 openflags, util::core_file
done:
/* store the revised path */
revised_path.clear();
- if (filerr == FILERR_NONE)
+ if (filerr == osd_file::error::NONE)
{
/* cannonicalize mainpath */
- filerr = osd_get_full_path(&alloc_fullpath, mainpath.c_str());
- if (filerr == FILERR_NONE)
+ std::string alloc_fullpath;
+ filerr = osd_get_full_path(alloc_fullpath, mainpath);
+ if (filerr == osd_file::error::NONE)
{
+ revised_path = alloc_fullpath;
if (subpath.length() > 0)
- revised_path.assign(alloc_fullpath).append(PATH_SEPARATOR).append(subpath);
- else
- revised_path.assign(alloc_fullpath);
+ revised_path.append(PATH_SEPARATOR).append(subpath);
}
}
- if (zip != nullptr)
- zip_file_close(zip);
- if (alloc_fullpath != nullptr)
- osd_free(alloc_fullpath);
return filerr;
}
@@ -672,13 +667,13 @@ static char next_path_char(const char *s, int *pos)
* @return null if it fails, else a zip_file_header*.
*/
-static const zip_file_header *zippath_find_sub_path(zip_file *zipfile, const char *subpath, osd_dir_entry_type *type)
+static const zip_file::file_header *zippath_find_sub_path(zip_file &zipfile, const char *subpath, osd_dir_entry_type *type)
{
int i, j;
char c1, c2, last_char;
- const zip_file_header *header;
+ const zip_file::file_header *header;
- for (header = zip_file_first_file(zipfile); header != nullptr; header = zip_file_next_file(zipfile))
+ for (header = zipfile.first_file(); header != nullptr; header = zipfile.next_file())
{
/* special case */
if (subpath == nullptr)
@@ -726,7 +721,7 @@ static const zip_file_header *zippath_find_sub_path(zip_file *zipfile, const cha
-------------------------------------------------*/
/**
- * @fn static file_error zippath_resolve(const char *path, osd_dir_entry_type &entry_type, zip_file *&zipfile, std::string &newpath)
+ * @fn static osd_file::error zippath_resolve(const char *path, osd_dir_entry_type &entry_type, zip_file *&zipfile, std::string &newpath)
*
* @brief Zippath resolve.
*
@@ -735,12 +730,12 @@ static const zip_file_header *zippath_find_sub_path(zip_file *zipfile, const cha
* @param [in,out] zipfile [in,out] If non-null, the zipfile.
* @param [in,out] newpath The newpath.
*
- * @return A file_error.
+ * @return A osd_file::error.
*/
-static file_error zippath_resolve(const char *path, osd_dir_entry_type &entry_type, zip_file *&zipfile, std::string &newpath)
+static osd_file::error zippath_resolve(const char *path, osd_dir_entry_type &entry_type, zip_file::ptr &zipfile, std::string &newpath)
{
- file_error err;
+ osd_file::error err;
osd_directory_entry *current_entry = nullptr;
osd_dir_entry_type current_entry_type;
int went_up = FALSE;
@@ -750,7 +745,7 @@ static file_error zippath_resolve(const char *path, osd_dir_entry_type &entry_ty
/* be conservative */
entry_type = ENTTYPE_NONE;
- zipfile = nullptr;
+ zipfile.reset();
std::string apath(path);
std::string apath_trimmed;
@@ -788,13 +783,13 @@ static file_error zippath_resolve(const char *path, osd_dir_entry_type &entry_ty
/* if we did not find anything, then error out */
if (current_entry_type == ENTTYPE_NONE)
{
- err = FILERR_NOT_FOUND;
+ err = osd_file::error::NOT_FOUND;
goto done;
}
/* is this file a ZIP file? */
if ((current_entry_type == ENTTYPE_FILE) && is_zip_file(apath_trimmed.c_str())
- && (zip_file_open(apath_trimmed.c_str(), &zipfile) == ZIPERR_NONE))
+ && (zip_file::open(apath_trimmed, zipfile) == zip_file::error::NONE))
{
i = strlen(path + apath.length());
while (i > 0 && is_zip_path_separator(path[apath.length() + i - 1]))
@@ -802,10 +797,10 @@ static file_error zippath_resolve(const char *path, osd_dir_entry_type &entry_ty
newpath.assign(path + apath.length(), i);
/* this was a true ZIP path - attempt to identify the type of path */
- zippath_find_sub_path(zipfile, newpath.c_str(), &current_entry_type);
+ zippath_find_sub_path(*zipfile, newpath.c_str(), &current_entry_type);
if (current_entry_type == ENTTYPE_NONE)
{
- err = FILERR_NOT_FOUND;
+ err = osd_file::error::NOT_FOUND;
goto done;
}
}
@@ -814,7 +809,7 @@ static file_error zippath_resolve(const char *path, osd_dir_entry_type &entry_ty
/* this was a normal path */
if (went_up)
{
- err = FILERR_NOT_FOUND;
+ err = osd_file::error::NOT_FOUND;
goto done;
}
newpath.assign(path);
@@ -822,7 +817,7 @@ static file_error zippath_resolve(const char *path, osd_dir_entry_type &entry_ty
/* success! */
entry_type = current_entry_type;
- err = FILERR_NONE;
+ err = osd_file::error::NONE;
done:
return err;
@@ -834,19 +829,19 @@ done:
-------------------------------------------------*/
/**
- * @fn file_error zippath_opendir(const char *path, zippath_directory **directory)
+ * @fn osd_file::error zippath_opendir(const char *path, zippath_directory **directory)
*
* @brief Zippath opendir.
*
* @param path Full pathname of the file.
* @param [in,out] directory If non-null, pathname of the directory.
*
- * @return A file_error.
+ * @return A osd_file::error.
*/
-file_error zippath_opendir(const char *path, zippath_directory **directory)
+osd_file::error zippath_opendir(const char *path, zippath_directory **directory)
{
- file_error err;
+ osd_file::error err;
/* allocate a directory */
zippath_directory *result = nullptr;
@@ -856,19 +851,19 @@ file_error zippath_opendir(const char *path, zippath_directory **directory)
}
catch (std::bad_alloc &)
{
- err = FILERR_OUT_OF_MEMORY;
+ err = osd_file::error::OUT_OF_MEMORY;
goto done;
}
/* resolve the path */
osd_dir_entry_type entry_type;
err = zippath_resolve(path, entry_type, result->zipfile, result->zipprefix);
- if (err != FILERR_NONE)
+ if (err != osd_file::error::NONE)
goto done;
/* we have to be a directory */
if (entry_type != ENTTYPE_DIR)
{
- err = FILERR_NOT_FOUND;
+ err = osd_file::error::NOT_FOUND;
goto done;
}
@@ -879,7 +874,7 @@ file_error zippath_opendir(const char *path, zippath_directory **directory)
result->directory = osd_opendir(path);
if (result->directory == nullptr)
{
- err = FILERR_FAILURE;
+ err = osd_file::error::FAILURE;
goto done;
}
@@ -889,7 +884,7 @@ file_error zippath_opendir(const char *path, zippath_directory **directory)
}
done:
- if ((directory == nullptr || err != FILERR_NONE) && result != nullptr)
+ if ((directory == nullptr || err != osd_file::error::NONE) && result != nullptr)
{
zippath_closedir(result);
result = nullptr;
@@ -918,7 +913,7 @@ void zippath_closedir(zippath_directory *directory)
osd_closedir(directory->directory);
if (directory->zipfile != nullptr)
- zip_file_close(directory->zipfile);
+ directory->zipfile.reset();
while (directory->returned_dirlist != nullptr)
{
@@ -948,7 +943,7 @@ void zippath_closedir(zippath_directory *directory)
* @return null if it fails, else the relative path.
*/
-static const char *get_relative_path(zippath_directory *directory, const zip_file_header *header)
+static const char *get_relative_path(zippath_directory *directory, const zip_file::file_header *header)
{
const char *result = nullptr;
int len = directory->zipprefix.length();
@@ -982,7 +977,7 @@ static const char *get_relative_path(zippath_directory *directory, const zip_fil
const osd_directory_entry *zippath_readdir(zippath_directory *directory)
{
const osd_directory_entry *result = nullptr;
- const zip_file_header *header;
+ const zip_file::file_header *header;
const char *relpath;
const char *separator;
const char *s;
@@ -1023,9 +1018,9 @@ const osd_directory_entry *zippath_readdir(zippath_directory *directory)
do
{
if (!directory->called_zip_first)
- header = zip_file_first_file(directory->zipfile);
+ header = directory->zipfile->first_file();
else
- header = zip_file_next_file(directory->zipfile);
+ header = directory->zipfile->next_file();
directory->called_zip_first = true;
relpath = nullptr;
}
diff --git a/src/lib/util/zippath.h b/src/lib/util/zippath.h
index ce40c87ba8d..d54dd68c38d 100644
--- a/src/lib/util/zippath.h
+++ b/src/lib/util/zippath.h
@@ -45,13 +45,13 @@ std::string &zippath_combine(std::string &dst, const char *path1, const char *pa
/* ----- file operations ----- */
/* opens a zip path file */
-file_error zippath_fopen(const char *filename, UINT32 openflags, util::core_file::ptr &file, std::string &revised_path);
+osd_file::error zippath_fopen(const char *filename, UINT32 openflags, util::core_file::ptr &file, std::string &revised_path);
/* ----- directory operations ----- */
/* opens a directory */
-file_error zippath_opendir(const char *path, zippath_directory **directory);
+osd_file::error zippath_opendir(const char *path, zippath_directory **directory);
/* closes a directory */
void zippath_closedir(zippath_directory *directory);
diff --git a/src/mame/drivers/jaguar.cpp b/src/mame/drivers/jaguar.cpp
index e2fe252fe93..ee33848dd11 100644
--- a/src/mame/drivers/jaguar.cpp
+++ b/src/mame/drivers/jaguar.cpp
@@ -481,13 +481,13 @@ void jaguar_state::machine_reset()
emu_file jaguar_state::*jaguar_nvram_fopen( UINT32 openflags)
{
device_image_interface *image = dynamic_cast<device_image_interface *>(machine().device("cart"));
- file_error filerr;
+ osd_file::error filerr;
emu_file *file;
if (image->exists())
{
std::string fname(machine().system().name, PATH_SEPARATOR, image->basename_noext(), ".nv");
filerr = mame_fopen( SEARCHPATH_NVRAM, fname, openflags, &file);
- return (filerr == FILERR_NONE) ? file : NULL;
+ return (filerr == osd_file::error::NONE) ? file : NULL;
}
else
return NULL;
diff --git a/src/mame/etc/jrcrypt.cpp b/src/mame/etc/jrcrypt.cpp
index e973df30753..89c1fc0b716 100644
--- a/src/mame/etc/jrcrypt.cpp
+++ b/src/mame/etc/jrcrypt.cpp
@@ -490,8 +490,8 @@ void Load(char *name,byte *buffer,int from, int length)
{
/*
emu_file file(options, NULL, OPEN_FLAG_READ);
- file_error filerr = file.open(name);
- if (filerr != FILERR_NONE)
+ osd_file::error filerr = file.open(name);
+ if (filerr != osd_file::error::NONE)
return;
while (length--)
buffer[from++]=file->getc();
diff --git a/src/mame/machine/fddebug.cpp b/src/mame/machine/fddebug.cpp
index fcb4a46bff8..9cf760337fc 100644
--- a/src/mame/machine/fddebug.cpp
+++ b/src/mame/machine/fddebug.cpp
@@ -591,8 +591,8 @@ static void load_overlay_file(running_machine &machine)
/* determine the filename and open the file */
emu_file file(OPEN_FLAG_READ);
- file_error filerr = file.open(machine.system().name, ".kov");
- if (filerr == FILERR_NONE)
+ osd_file::error filerr = file.open(machine.system().name, ".kov");
+ if (filerr == osd_file::error::NONE)
{
file.read(keystatus, keystatus_words * 2);
@@ -617,8 +617,8 @@ static void save_overlay_file(running_machine &machine)
/* determin the filename and open the file */
emu_file file(OPEN_FLAG_WRITE | OPEN_FLAG_CREATE);
- file_error filerr = file.open(machine.system().name, ".kov");
- if (filerr == FILERR_NONE)
+ osd_file::error filerr = file.open(machine.system().name, ".kov");
+ if (filerr == osd_file::error::NONE)
{
/* convert to big-endian */
for (pcaddr = 0; pcaddr < keystatus_words; pcaddr++)
@@ -760,8 +760,8 @@ static void execute_fdoutput(running_machine &machine, int ref, int params, cons
/* determin the filename and open the file */
emu_file file(OPEN_FLAG_WRITE | OPEN_FLAG_CREATE);
- file_error filerr = file.open(param[0]);
- if (filerr == FILERR_NONE)
+ osd_file::error filerr = file.open(param[0]);
+ if (filerr == osd_file::error::NONE)
file.write(keyregion, KEY_SIZE);
debug_console_printf(machine, "File '%s' saved\n", param[0]);
@@ -1183,8 +1183,8 @@ static void execute_fddasm(running_machine &machine, int ref, int params, const
/* open the file */
emu_file file(OPEN_FLAG_WRITE | OPEN_FLAG_CREATE);
- file_error filerr = file.open(filename);
- if (filerr != FILERR_NONE)
+ osd_file::error filerr = file.open(filename);
+ if (filerr != osd_file::error::NONE)
{
debug_console_printf(machine, "Unable to create file '%s'\n", filename);
return;
diff --git a/src/osd/modules/file/posixfile.cpp b/src/osd/modules/file/posixfile.cpp
new file mode 100644
index 00000000000..3fe7ca9fa90
--- /dev/null
+++ b/src/osd/modules/file/posixfile.cpp
@@ -0,0 +1,482 @@
+// license:BSD-3-Clause
+// copyright-holders:Olivier Galibert, R. Belmont, Vas Crabb
+//============================================================
+//
+// sdlfile.c - SDL file access functions
+//
+// SDLMAME by Olivier Galibert and R. Belmont
+//
+//============================================================
+
+
+#ifndef _LARGEFILE64_SOURCE
+#define _LARGEFILE64_SOURCE
+#endif
+
+#ifdef __linux__
+#define __USE_LARGEFILE64
+#endif
+
+#ifdef WIN32
+#define _FILE_OFFSET_BITS 64
+#endif
+
+#if !defined(__FreeBSD__) && !defined(__NetBSD__) && !defined(__OpenBSD__) && !defined(__bsdi__) && !defined(__DragonFly__)
+#ifdef _XOPEN_SOURCE
+#if _XOPEN_SOURCE < 500
+#undef _XOPEN_SOURCE
+#endif
+#endif
+#ifndef _XOPEN_SOURCE
+#define _XOPEN_SOURCE 500
+#endif
+#endif
+
+// MAME headers
+#include "posixfile.h"
+
+#include <cassert>
+#include <cerrno>
+#include <memory>
+#include <type_traits>
+#include <vector>
+
+#include <fcntl.h>
+#include <limits.h>
+#include <sys/stat.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+
+
+namespace {
+
+//============================================================
+// CONSTANTS
+//============================================================
+
+#if defined(WIN32)
+constexpr char PATHSEPCH = '\\';
+constexpr char INVPATHSEPCH = '/';
+#else
+constexpr char PATHSEPCH = '/';
+constexpr char INVPATHSEPCH = '\\';
+#endif
+
+
+
+class posix_osd_file : public osd_file
+{
+public:
+ posix_osd_file(posix_osd_file const &) = delete;
+ posix_osd_file(posix_osd_file &&) = delete;
+ posix_osd_file& operator=(posix_osd_file const &) = delete;
+ posix_osd_file& operator=(posix_osd_file &&) = delete;
+
+ posix_osd_file(int fd) : m_fd(fd)
+ {
+ assert(m_fd >= 0);
+ }
+
+ virtual ~posix_osd_file() override
+ {
+ ::close(m_fd);
+ }
+
+ virtual error read(void *buffer, std::uint64_t offset, std::uint32_t count, std::uint32_t &actual) override
+ {
+ ssize_t result;
+
+#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__bsdi__) || defined(__DragonFly__) || defined(EMSCRIPTEN)
+ result = ::pread(m_fd, buffer, size_t(count), off_t(std::make_unsigned_t<off_t>(offset)));
+#elif defined(WIN32) || defined(SDLMAME_NO64BITIO)
+ if (lseek(m_fd, off_t(std::make_unsigned_t<off_t>(offset)), SEEK_SET) < 0)
+ return errno_to_file_error(errno)
+ result = ::read(m_fd, buffer, size_t(count));
+#else
+ result = ::pread64(m_fd, buffer, size_t(count), off64_t(offset));
+#endif
+
+ if (result < 0)
+ return errno_to_file_error(errno);
+
+ actual = std::uint32_t(std::size_t(result));
+ return error::NONE;
+ }
+
+ virtual error write(void const *buffer, std::uint64_t offset, std::uint32_t count, std::uint32_t &actual) override
+ {
+ ssize_t result;
+
+#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__bsdi__) || defined(__DragonFly__) || defined(EMSCRIPTEN)
+ result = ::pwrite(m_fd, buffer, size_t(count), off_t(std::make_unsigned_t<off_t>(offset)));
+#elif defined(WIN32) || defined(SDLMAME_NO64BITIO)
+ if (lseek(m_fd, off_t(std::make_unsigned_t<off_t>(offset)), SEEK_SET) < 0)
+ return errno_to_file_error(errno)
+ result = ::write(m_fd, buffer, size_t(count));
+#else
+ result = ::pwrite64(m_fd, buffer, size_t(count), off64_t(offset));
+#endif
+
+ if (result < 0)
+ return errno_to_file_error(errno);
+
+ actual = std::uint32_t(std::size_t(result));
+ return error::NONE;
+ }
+
+ virtual error truncate(std::uint64_t offset) override
+ {
+ int result;
+
+#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__bsdi__) || defined(__DragonFly__) || defined(EMSCRIPTEN) || defined(WIN32) || defined(SDLMAME_NO64BITIO)
+ result = ::ftruncate(m_fd, off_t(std::make_unsigned_t<off_t>(offset)));
+#else
+ result = ::ftruncate64(m_fd, off64_t(offset));
+#endif
+
+ if (result < 0)
+ return errno_to_file_error(errno);
+
+ return error::NONE;
+ }
+
+ virtual error flush() override
+ {
+ // no user-space buffering on unistd I/O
+ return error::NONE;
+ }
+
+private:
+ int m_fd;
+};
+
+
+//============================================================
+// is_path_separator
+//============================================================
+
+bool is_path_separator(char c)
+{
+ return (c == PATHSEPCH) || (c == INVPATHSEPCH);
+}
+
+
+//============================================================
+// create_path_recursive
+//============================================================
+
+osd_file::error create_path_recursive(std::string const &path)
+{
+ // if there's still a separator, and it's not the root, nuke it and recurse
+ auto const sep = path.rfind(PATHSEPCH);
+ if ((sep != std::string::npos) && (sep > 0) && (path[sep] != ':') && (path[sep - 1] != PATHSEPCH))
+ {
+ osd_file::error const err = create_path_recursive(path.substr(0, sep));
+ if (err != osd_file::error::NONE)
+ return err;
+ }
+
+ // if the path already exists, we're done
+ struct stat st;
+ if (!::stat(path.c_str(), &st))
+ return osd_file::error::NONE;
+
+ // create the path
+#ifdef WIN32
+ if (mkdir(path.c_str()) < 0)
+#else
+ if (mkdir(path.c_str(), 0777) < 0)
+#endif
+ return errno_to_file_error(errno);
+ else
+ return osd_file::error::NONE;
+}
+
+} // anonymous namespace
+
+
+//============================================================
+// osd_file::open
+//============================================================
+
+osd_file::error osd_file::open(std::string const &path, std::uint32_t openflags, ptr &file, std::uint64_t &filesize)
+{
+ std::string dst;
+ if (posix_check_socket_path(path))
+ return posix_open_socket(path, openflags, file, filesize);
+ else if (posix_check_ptty_path(path))
+ return posix_open_ptty(openflags, file, filesize, dst);
+
+ // select the file open modes
+ int access;
+ if (openflags & OPEN_FLAG_WRITE)
+ {
+ access = (openflags & OPEN_FLAG_READ) ? O_RDWR : O_WRONLY;
+ access |= (openflags & OPEN_FLAG_CREATE) ? (O_CREAT | O_TRUNC) : 0;
+ }
+ else if (openflags & OPEN_FLAG_READ)
+ {
+ access = O_RDONLY;
+ }
+ else
+ {
+ return error::INVALID_ACCESS;
+ }
+#if defined(WIN32)
+ access |= O_BINARY;
+#endif
+
+ // convert the path into something compatible
+ dst = path;
+ for (auto it = dst.begin(); it != dst.end(); ++it)
+ *it = (INVPATHSEPCH == *it) ? PATHSEPCH : *it;
+ osd_subst_env(dst, dst);
+
+ // attempt to open the file
+ int fd = -1;
+#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__bsdi__) || defined(__DragonFly__) || defined(__HAIKU__) || defined(WIN32) || defined(SDLMAME_NO64BITIO)
+ fd = ::open(dst.c_str(), access, 0666);
+#else
+ fd = ::open64(dst.c_str(), access, 0666);
+#endif
+
+ if (fd < 0)
+ {
+ // create the path if necessary
+ if ((openflags & OPEN_FLAG_CREATE) && (openflags & OPEN_FLAG_CREATE_PATHS))
+ {
+ auto const pathsep = dst.rfind(dst, PATHSEPCH);
+ if (pathsep != std::string::npos)
+ {
+ // create the path up to the file
+ osd_file::error const error = create_path_recursive(dst.substr(0, pathsep));
+
+ // attempt to reopen the file
+ if (error == osd_file::error::NONE)
+ {
+#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__bsdi__) || defined(__DragonFly__) || defined(__HAIKU__) || defined(WIN32) || defined(SDLMAME_NO64BITIO)
+ fd = ::open(dst.c_str(), access, 0666);
+#else
+ fd = ::open64(dst.c_str(), access, 0666);
+#endif
+ }
+ }
+ }
+
+ // if we still failed, clean up and osd_free
+ if (fd < 0)
+ {
+ return errno_to_file_error(errno);
+ }
+ }
+
+ // get the file size
+#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__bsdi__) || defined(__DragonFly__) || defined(__HAIKU__) || defined(WIN32) || defined(SDLMAME_NO64BITIO)
+ struct stat st;
+ if (::fstat(fd, &st) < 0)
+#else
+ struct stat64 st;
+ if (::fstat64(fd, &st) < 0)
+#endif
+ {
+ int const error = errno;
+ ::close(fd);
+ return errno_to_file_error(error);
+ }
+ filesize = std::uint64_t(std::make_unsigned_t<decltype(st.st_size)>(st.st_size));
+
+ try
+ {
+ file = std::make_unique<posix_osd_file>(fd);
+ return error::NONE;
+ }
+ catch (...)
+ {
+ ::close(fd);
+ return error::OUT_OF_MEMORY;
+ }
+}
+
+
+//============================================================
+// osd_file::openpty
+//============================================================
+
+osd_file::error osd_file::openpty(ptr &file, std::string &name)
+{
+ std::uint64_t filesize;
+ return posix_open_ptty(OPEN_FLAG_READ | OPEN_FLAG_WRITE, file, filesize, name);
+}
+
+
+//============================================================
+// osd_file::remove
+//============================================================
+
+osd_file::error osd_file::remove(std::string const &filename)
+{
+ if (::unlink(filename.c_str()) < -1)
+ return errno_to_file_error(errno);
+ else
+ return error::NONE;
+}
+
+
+//============================================================
+// osd_get_physical_drive_geometry
+//============================================================
+
+int osd_get_physical_drive_geometry(const char *filename, UINT32 *cylinders, UINT32 *heads, UINT32 *sectors, UINT32 *bps)
+{
+ return FALSE; // no, no way, huh-uh, forget it
+}
+
+
+//============================================================
+// osd_stat
+//============================================================
+
+osd_directory_entry *osd_stat(const std::string &path)
+{
+#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__bsdi__) || defined(__DragonFly__) || defined(__HAIKU__) || defined(WIN32) || defined(SDLMAME_NO64BITIO)
+ struct stat st;
+ int const err = ::stat(path.c_str(), &st);
+#else
+ struct stat64 st;
+ int const err = ::stat64(path.c_str(), &st);
+#endif
+ if (err < 0) return nullptr;
+
+ // create an osd_directory_entry; be sure to make sure that the caller can
+ // free all resources by just freeing the resulting osd_directory_entry
+ osd_directory_entry *const result = reinterpret_cast<osd_directory_entry *>(osd_malloc_array(sizeof(osd_directory_entry) + path.length() + 1));
+ std::strcpy(reinterpret_cast<char *>(result) + sizeof(*result), path.c_str());
+ result->name = reinterpret_cast<char *>(result) + sizeof(*result);
+ result->type = S_ISDIR(st.st_mode) ? ENTTYPE_DIR : ENTTYPE_FILE;
+ result->size = std::uint64_t(std::make_unsigned_t<decltype(st.st_size)>(st.st_size));
+
+ return result;
+}
+
+
+//============================================================
+// osd_get_full_path
+//============================================================
+
+osd_file::error osd_get_full_path(std::string &dst, std::string const &path)
+{
+ try
+ {
+#if defined(WIN32)
+ std::vector<char> path_buffer(MAX_PATH);
+ if (::_fullpath(&path_buffer[0], path.c_str(), MAX_PATH))
+ {
+ dst = &path_buffer[0];
+ return osd_file::error::NONE;
+ }
+ else
+ {
+ return osd_file::error::FAILURE;
+ }
+#else
+ std::vector<char> path_buffer(PATH_MAX);
+ if (::realpath(path.c_str(), &path_buffer[0]))
+ {
+ dst = &path_buffer[0];
+ return osd_file::error::NONE;
+ }
+ else if (path[0] == PATHSEPCH)
+ {
+ dst = path;
+ return osd_file::error::NONE;
+ }
+ else
+ {
+ while (!::getcwd(&path_buffer[0], path_buffer.size()))
+ {
+ if (errno != ERANGE)
+ return errno_to_file_error(errno);
+ else
+ path_buffer.resize(path_buffer.size() * 2);
+ }
+ dst.assign(&path_buffer[0]).push_back(PATHSEPCH);
+ dst.append(path);
+ return osd_file::error::NONE;
+ }
+#endif
+ }
+ catch (...)
+ {
+ return osd_file::error::OUT_OF_MEMORY;
+ }
+}
+
+
+//============================================================
+// osd_is_absolute_path
+//============================================================
+
+bool osd_is_absolute_path(std::string const &path)
+{
+ if (!path.empty() && is_path_separator(path[0]))
+ return true;
+#if !defined(WIN32)
+ else if (!path.empty() && (path[0] == '.'))
+ return true;
+#elif !defined(UNDER_CE)
+ else if ((path.length() > 1) && (path[1] == ':'))
+ return true;
+#endif
+ else
+ return false;
+}
+
+
+//============================================================
+// osd_get_volume_name
+//============================================================
+
+const char *osd_get_volume_name(int idx)
+{
+ if (idx == 0)
+ return "/";
+ else
+ return nullptr;
+ }
+
+
+//============================================================
+// errno_to_file_error
+//============================================================
+
+osd_file::error errno_to_file_error(int error)
+{
+ switch (error)
+ {
+ case 0:
+ return osd_file::error::NONE;
+
+ case ENOENT:
+ case ENOTDIR:
+ return osd_file::error::NOT_FOUND;
+
+ case EACCES:
+ case EROFS:
+#ifndef WIN32
+ case ETXTBSY:
+#endif
+ case EEXIST:
+ case EPERM:
+ case EISDIR:
+ case EINVAL:
+ return osd_file::error::ACCESS_DENIED;
+
+ case ENFILE:
+ case EMFILE:
+ return osd_file::error::TOO_MANY_FILES;
+
+ default:
+ return osd_file::error::FAILURE;
+ }
+}
diff --git a/src/osd/modules/file/posixfile.h b/src/osd/modules/file/posixfile.h
new file mode 100644
index 00000000000..2339a52ceec
--- /dev/null
+++ b/src/osd/modules/file/posixfile.h
@@ -0,0 +1,28 @@
+// license:BSD-3-Clause
+// copyright-holders:Olivier Galibert, R. Belmont, Vas Crabb
+//============================================================
+//
+// sdlfile.h - SDL file access functions
+//
+// SDLMAME by Olivier Galibert and R. Belmont
+//
+//============================================================
+
+
+#include "osdcore.h"
+
+#include <cstdint>
+#include <string>
+
+
+//============================================================
+// PROTOTYPES
+//============================================================
+
+bool posix_check_socket_path(std::string const &path);
+osd_file::error posix_open_socket(std::string const &path, std::uint32_t openflags, osd_file::ptr &file, std::uint64_t &filesize);
+
+bool posix_check_ptty_path(std::string const &path);
+osd_file::error posix_open_ptty(std::uint32_t openflags, osd_file::ptr &file, std::uint64_t &filesize, std::string &name);
+
+osd_file::error errno_to_file_error(int error);
diff --git a/src/osd/modules/file/posixptty.cpp b/src/osd/modules/file/posixptty.cpp
new file mode 100644
index 00000000000..b84838c0578
--- /dev/null
+++ b/src/osd/modules/file/posixptty.cpp
@@ -0,0 +1,184 @@
+// license:BSD-3-Clause
+// copyright-holders:Olivier Galibert, R. Belmont, Vas Crabb
+//============================================================
+//
+// sdlptty_unix.c - SDL pseudo tty access functions
+//
+// SDLMAME by Olivier Galibert and R. Belmont
+//
+//============================================================
+
+#include "posixfile.h"
+
+#include <cassert>
+#include <cerrno>
+#include <cstring>
+
+#include <fcntl.h>
+#include <limits.h>
+#include <unistd.h>
+#include <stdlib.h>
+
+#if defined(__FreeBSD__) || defined(__DragonFly__)
+#include <termios.h>
+#include <libutil.h>
+#elif defined(__NetBSD__) || defined(__OpenBSD__) || defined(__APPLE__)
+#include <termios.h>
+#include <util.h>
+#elif defined(__linux__) || defined(EMSCRIPTEN)
+#include <pty.h>
+#elif defined(__HAIKU__)
+#include <bsd/pty.h>
+#endif
+
+
+namespace {
+#if defined(__APPLE__)
+char const *const posix_ptty_identifier = "/dev/pty";
+#else
+char const *const posix_ptty_identifier = "/dev/pts";
+#endif
+
+
+class posix_osd_ptty : public osd_file
+{
+public:
+ posix_osd_ptty(posix_osd_ptty const &) = delete;
+ posix_osd_ptty(posix_osd_ptty &&) = delete;
+ posix_osd_ptty& operator=(posix_osd_ptty const &) = delete;
+ posix_osd_ptty& operator=(posix_osd_ptty &&) = delete;
+
+ posix_osd_ptty(int fd) : m_fd(fd)
+ {
+ assert(m_fd >= 0);
+ }
+
+ virtual ~posix_osd_ptty()
+ {
+ ::close(m_fd);
+ }
+
+ virtual error read(void *buffer, std::uint64_t offset, std::uint32_t count, std::uint32_t &actual) override
+ {
+ ssize_t const result = ::read(m_fd, buffer, count);
+ if (result < 0)
+ return errno_to_file_error(errno);
+
+ actual = std::uint32_t(size_t(result));
+ return error::NONE;
+ }
+
+ virtual error write(void const *buffer, std::uint64_t offset, std::uint32_t count, std::uint32_t &actual) override
+ {
+ ssize_t const result = ::write(m_fd, buffer, count);
+ if (result < 0)
+ return errno_to_file_error(errno);
+
+ actual = std::uint32_t(size_t(result));
+ return error::NONE;
+ }
+
+ virtual error truncate(std::uint64_t offset) override
+ {
+ // doesn't make sense on ptty
+ return error::INVALID_ACCESS;
+ }
+
+ virtual error flush() override
+ {
+ // no userspace buffers on read/write
+ return error::NONE;
+ }
+
+private:
+ int m_fd;
+};
+
+} // anonymous namespace
+
+
+bool posix_check_ptty_path(std::string const &path)
+{
+ return strncmp(path.c_str(), posix_ptty_identifier, strlen(posix_ptty_identifier)) == 0;
+}
+
+
+osd_file::error posix_open_ptty(std::uint32_t openflags, osd_file::ptr &file, std::uint64_t &filesize, std::string &name)
+{
+#if (defined(sun) || defined(__sun)) && (defined(__SVR4) || defined(__svr4__))
+ int access = O_NOCTTY;
+ if (openflags & OPEN_FLAG_WRITE)
+ access |= (openflags & OPEN_FLAG_READ) ? O_RDWR : O_WRONLY;
+ else if (openflags & OPEN_FLAG_READ)
+ access |= O_RDONLY;
+ else
+ return error::INVALID_ACCESS;
+
+ int const masterfd = ::posix_openpt(access);
+ if (masterfd < 0)
+ return errno_to_file_error(errno);
+
+ // grant access to slave device and check that it can be opened
+ char const *slavepath;
+ int slavefd;
+ if ((::grantpt(masterfd) < 0) ||
+ (::unlockpt(masterfd) < 0) ||
+ ((slavepath = ::ptsname(masterfd)) == nullptr) ||
+ ((slavefd = ::open(slavepath, O_RDWR | O_NOCTTY)) < 0))
+ {
+ int const err = errno;
+ ::close(masterfd);
+ return errno_to_file_error(err);
+ }
+
+ // check that it's possible to stack BSD-compatibility STREAMS modules
+ if ((::ioctl(slavefd, I_PUSH, "ptem") < 0) ||
+ (::ioctl(slavefd, I_PUSH, "ldterm") < 0) ||
+ (::ioctl(slavefd, I_PUSH, "ttcompat") < 0))
+ {
+ int const err = errno;
+ ::close(slavefd);
+ ::close(masterfd);
+ return errno_to_file_error(err);
+ }
+#else
+ struct termios tios;
+ std::memset(&tios, 0, sizeof(tios));
+ ::cfmakeraw(&tios);
+
+ int masterfd = -1, slavefd = -1;
+ char slavepath[PATH_MAX];
+ if (::openpty(&masterfd, &slavefd, slavepath, &tios, nullptr) < 0)
+ return errno_to_file_error(errno);
+#endif
+
+ ::close(slavefd);
+
+ int const oldflags = ::fcntl(masterfd, F_GETFL, 0);
+ if (oldflags < 0)
+ {
+ int const err = errno;
+ ::close(masterfd);
+ return errno_to_file_error(err);
+ }
+
+ if (::fcntl(masterfd, F_SETFL, oldflags | O_NONBLOCK) < 0)
+ {
+ int const err = errno;
+ ::close(masterfd);
+ return errno_to_file_error(err);
+ }
+
+ try
+ {
+ name = slavepath;
+ file = std::make_unique<posix_osd_ptty>(masterfd);
+ filesize = 0;
+ return osd_file::error::NONE;
+ }
+ catch (...)
+ {
+ ::close(masterfd);
+ return osd_file::error::OUT_OF_MEMORY;
+ }
+}
diff --git a/src/osd/modules/file/posixsocket.cpp b/src/osd/modules/file/posixsocket.cpp
new file mode 100644
index 00000000000..e50d0636489
--- /dev/null
+++ b/src/osd/modules/file/posixsocket.cpp
@@ -0,0 +1,236 @@
+// license:BSD-3-Clause
+// copyright-holders:Olivier Galibert, R. Belmont, Vas Crabb
+//============================================================
+//
+// sdlsocket.c - SDL socket (inet) access functions
+//
+// SDLMAME by Olivier Galibert and R. Belmont
+//
+//============================================================
+
+#include "posixfile.h"
+
+#include <cassert>
+#include <cerrno>
+#include <cstdio>
+
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+#include <sys/select.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+#include <unistd.h>
+
+
+namespace {
+char const *const posixfile_socket_identifier = "socket.";
+
+
+class posix_osd_socket : public osd_file
+{
+public:
+ posix_osd_socket(posix_osd_socket const &) = delete;
+ posix_osd_socket(posix_osd_socket &&) = delete;
+ posix_osd_socket& operator=(posix_osd_socket const &) = delete;
+ posix_osd_socket& operator=(posix_osd_socket &&) = delete;
+
+ posix_osd_socket(int sock, bool listening)
+ : m_sock(sock)
+ , m_listening(listening)
+ {
+ assert(m_sock >= 0);
+ }
+
+ virtual ~posix_osd_socket()
+ {
+ ::close(m_sock);
+ }
+
+ virtual error read(void *buffer, std::uint64_t offset, std::uint32_t count, std::uint32_t &actual) override
+ {
+#if defined(EMSCRIPTEN)
+ return error::FAILED; // TODO: work out what it dislikes about emscripten
+#else
+ fd_set readfds;
+ FD_ZERO(&readfds);
+ FD_SET(m_sock, &readfds);
+
+ struct timeval timeout;
+ timeout.tv_sec = timeout.tv_usec = 0;
+
+ if (select(m_sock + 1, &readfds, nullptr, nullptr, &timeout) < 0)
+ {
+ char line[80];
+ std::sprintf(line, "%s : %s : %d ", __func__, __FILE__, __LINE__);
+ std::perror(line);
+ return errno_to_file_error(errno);
+ }
+ else if (FD_ISSET(m_sock, &readfds))
+ {
+ if (!m_listening)
+ {
+ // connected socket
+ ssize_t const result = ::read(m_sock, buffer, count);
+ if (result < 0)
+ {
+ return errno_to_file_error(errno);
+ }
+ else
+ {
+ actual = std::uint32_t(size_t(result));
+ return error::NONE;
+ }
+ }
+ else
+ {
+ // listening socket
+ int const accepted = ::accept(m_sock, nullptr, nullptr);
+ if (accepted < 0)
+ {
+ return errno_to_file_error(errno);
+ }
+ else
+ {
+ ::close(m_sock);
+ m_sock = accepted;
+ m_listening = false;
+ actual = 0;
+
+ return error::NONE;
+ }
+ }
+ }
+ else
+ {
+ return error::FAILURE;
+ }
+#endif
+ }
+
+ virtual error write(void const *buffer, std::uint64_t offset, std::uint32_t count, std::uint32_t &actual) override
+ {
+ ssize_t const result = ::write(m_sock, buffer, count);
+ if (result < 0)
+ return errno_to_file_error(errno);
+
+ actual = std::uint32_t(size_t(result));
+ return error::NONE;
+ }
+
+ virtual error truncate(std::uint64_t offset) override
+ {
+ // doesn't make sense on socket
+ return error::INVALID_ACCESS;
+ }
+
+ virtual error flush() override
+ {
+ // there's no simple way to flush buffers on a socket anyway
+ return error::NONE;
+ }
+
+private:
+ int m_sock;
+ bool m_listening;
+};
+
+} // anonymous namespace
+
+
+/*
+ Checks whether the path is a socket specification. A valid socket
+ specification has the format "socket." host ":" port. Host may be simple
+ or fully qualified. Port must be between 1 and 65535.
+*/
+bool posix_check_socket_path(std::string const &path)
+{
+ if (strncmp(path.c_str(), posixfile_socket_identifier, strlen(posixfile_socket_identifier)) == 0 &&
+ strchr(path.c_str(), ':') != nullptr) return true;
+ return false;
+}
+
+
+osd_file::error posix_open_socket(std::string const &path, std::uint32_t openflags, osd_file::ptr &file, std::uint64_t &filesize)
+{
+ char hostname[256];
+ int port;
+ std::sscanf(&path[strlen(posixfile_socket_identifier)], "%255[^:]:%d", hostname, &port);
+
+ struct hostent const *const localhost = ::gethostbyname(hostname);
+ if (!localhost)
+ return osd_file::error::NOT_FOUND;
+
+ struct sockaddr_in sai;
+ memset(&sai, 0, sizeof(sai));
+ sai.sin_family = AF_INET;
+ sai.sin_port = htons(port);
+ sai.sin_addr = *reinterpret_cast<struct in_addr *>(localhost->h_addr);
+
+ int const sock = ::socket(AF_INET, SOCK_STREAM, 0);
+ if (sock < 0)
+ return errno_to_file_error(errno);
+
+ int const flag = 1;
+ if (::setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, reinterpret_cast<const char *>(&flag), sizeof(flag)) < 0)
+ {
+ int const err = errno;
+ ::close(sock);
+ return errno_to_file_error(err);
+ }
+
+ // listening socket support
+ if (openflags & OPEN_FLAG_CREATE)
+ {
+ //printf("Listening for client at '%s' on port '%d'\n", hostname, port);
+ // bind socket...
+ if (::bind(sock, reinterpret_cast<struct sockaddr const *>(&sai), sizeof(struct sockaddr)) < 0)
+ {
+ int const err = errno;
+ ::close(sock);
+ return errno_to_file_error(err);
+ }
+
+ // start to listen...
+ if (::listen(sock, 1) < 0)
+ {
+ int const err = errno;
+ ::close(sock);
+ return errno_to_file_error(err);
+ }
+
+ // mark socket as "listening"
+ try
+ {
+ file = std::make_unique<posix_osd_socket>(sock, true);
+ filesize = 0;
+ return osd_file::error::NONE;
+ }
+ catch (...)
+ {
+ ::close(sock);
+ return osd_file::error::OUT_OF_MEMORY;
+ }
+ }
+ else
+ {
+ //printf("Connecting to server '%s' on port '%d'\n", hostname, port);
+ if (::connect(sock, reinterpret_cast<struct sockaddr const *>(&sai), sizeof(struct sockaddr)) < 0)
+ {
+ ::close(sock);
+ return osd_file::error::ACCESS_DENIED; // have to return this value or bitb won't try to bind on connect failure
+ }
+ try
+ {
+ file = std::make_unique<posix_osd_socket>(sock, false);
+ filesize = 0;
+ return osd_file::error::NONE;
+ }
+ catch (...)
+ {
+ ::close(sock);
+ return osd_file::error::OUT_OF_MEMORY;
+ }
+ }
+}
diff --git a/src/osd/modules/file/stdfile.cpp b/src/osd/modules/file/stdfile.cpp
new file mode 100644
index 00000000000..92920bba495
--- /dev/null
+++ b/src/osd/modules/file/stdfile.cpp
@@ -0,0 +1,251 @@
+// license:BSD-3-Clause
+// copyright-holders:Aaron Giles
+//============================================================
+//
+// minifile.c - Minimal core file access functions
+//
+//============================================================
+
+#include "osdcore.h"
+
+#include <cassert>
+#include <cstdint>
+#include <cstdio>
+#include <cstdlib>
+#include <string>
+
+#include <stdio.h> // for fileno
+#include <unistd.h> // for ftruncate
+
+
+namespace {
+class std_osd_file : public osd_file
+{
+public:
+
+ std_osd_file(FILE *f) : m_file(f) { assert(m_file); }
+
+ //============================================================
+ // osd_close
+ //============================================================
+
+ virtual ~std_osd_file() override
+ {
+ // close the file handle
+ if (m_file) std::fclose(m_file);
+ }
+
+ //============================================================
+ // osd_read
+ //============================================================
+
+ virtual error read(void *buffer, std::uint64_t offset, std::uint32_t length, std::uint32_t &actual) override
+ {
+ // seek to the new location; note that most fseek implementations are limited to 32 bits
+ if (std::fseek(m_file, offset, SEEK_SET) < 0)
+ return error::FAILURE;
+
+ // perform the read
+ std::size_t const count = std::fread(buffer, 1, length, m_file);
+ actual = count;
+
+ return error::NONE;
+ }
+
+ //============================================================
+ // osd_write
+ //============================================================
+
+ virtual error write(const void *buffer, std::uint64_t offset, std::uint32_t length, std::uint32_t &actual) override
+ {
+ // seek to the new location; note that most fseek implementations are limited to 32 bits
+ if (std::fseek(m_file, offset, SEEK_SET) < 0)
+ return error::FAILURE;
+
+ // perform the write
+ std::size_t const count = std::fwrite(buffer, 1, length, m_file);
+ actual = count;
+
+ return error::NONE;
+ }
+
+ //============================================================
+ // osd_truncate
+ //============================================================
+
+ error truncate(std::uint64_t offset) override
+ {
+ return (ftruncate(fileno(m_file), offset) < 0) ? error::FAILURE : error::NONE;
+ }
+
+ //============================================================
+ // osd_fflush
+ //============================================================
+
+ virtual error flush() override
+ {
+ return (std::fflush(m_file) == EOF) ? error::FAILURE : error::NONE;
+ }
+
+private:
+ FILE *m_file;
+};
+
+} // anonymous namespace
+
+
+//============================================================
+// osd_open
+//============================================================
+
+osd_file::error osd_file::open(std::string const &path, std::uint32_t openflags, ptr &file, std::uint64_t &filesize)
+{
+ // based on the flags, choose a mode
+ const char *mode;
+ if (openflags & OPEN_FLAG_WRITE)
+ {
+ if (openflags & OPEN_FLAG_READ)
+ mode = (openflags & OPEN_FLAG_CREATE) ? "w+b" : "r+b";
+ else
+ mode = "wb";
+ }
+ else if (openflags & OPEN_FLAG_READ)
+ mode = "rb";
+ else
+ return error::INVALID_ACCESS;
+
+ // open the file
+ FILE *const fileptr = std::fopen(path.c_str(), mode);
+ if (!fileptr)
+ return error::NOT_FOUND;
+
+ // get the size -- note that most fseek/ftell implementations are limited to 32 bits
+ long length;
+ if ((std::fseek(fileptr, 0, SEEK_END) < 0) ||
+ ((length = std::ftell(fileptr)) < 0) ||
+ (std::fseek(fileptr, 0, SEEK_SET) < 0))
+ {
+ std::fclose(fileptr);
+ return error::FAILURE;
+ }
+
+ try
+ {
+ file = std::make_unique<std_osd_file>(fileptr);
+ filesize = std::int64_t(length);
+ return error::NONE;
+ }
+ catch (...)
+ {
+ std::fclose(fileptr);
+ return error::OUT_OF_MEMORY;
+ }
+}
+
+
+//============================================================
+// osd_openpty
+//============================================================
+
+osd_file::error osd_file::openpty(ptr &file, std::string &name)
+{
+ return error::FAILURE;
+}
+
+
+//============================================================
+// osd_rmfile
+//============================================================
+
+osd_file::error osd_file::remove(std::string const &filename)
+{
+ return (std::remove(filename.c_str()) < 0) ? error::FAILURE : error::NONE;
+}
+
+
+//============================================================
+// osd_get_physical_drive_geometry
+//============================================================
+
+int osd_get_physical_drive_geometry(const char *filename, UINT32 *cylinders, UINT32 *heads, UINT32 *sectors, UINT32 *bps)
+{
+ // there is no standard way of doing this, so we always return FALSE, indicating
+ // that a given path is not a physical drive
+ return FALSE;
+}
+
+
+//============================================================
+// osd_uchar_from_osdchar
+//============================================================
+
+int osd_uchar_from_osdchar(UINT32 /* unicode_char */ *uchar, const char *osdchar, size_t count)
+{
+ // we assume a standard 1:1 mapping of characters to the first 256 unicode characters
+ *uchar = (UINT8)*osdchar;
+ return 1;
+}
+
+
+//============================================================
+// osd_stat
+//============================================================
+
+osd_directory_entry *osd_stat(const std::string &path)
+{
+ osd_directory_entry *result = nullptr;
+
+ // create an osd_directory_entry; be sure to make sure that the caller can
+ // free all resources by just freeing the resulting osd_directory_entry
+ result = (osd_directory_entry *)osd_malloc_array(sizeof(*result) + path.length() + 1);
+ strcpy((char *)(result + 1), path.c_str());
+ result->name = (char *)(result + 1);
+ result->type = ENTTYPE_NONE;
+ result->size = 0;
+
+ FILE *f = std::fopen(path.c_str(), "rb");
+ if (f != nullptr)
+ {
+ std::fseek(f, 0, SEEK_END);
+ result->type = ENTTYPE_FILE;
+ result->size = std::ftell(f);
+ std::fclose(f);
+ }
+ return result;
+}
+
+
+//============================================================
+// osd_get_full_path
+//============================================================
+
+osd_file::error osd_get_full_path(std::string &dst, std::string const &path)
+{
+ // derive the full path of the file in an allocated string
+ // for now just fake it since we don't presume any underlying file system
+ dst = path;
+
+ return osd_file::error::NONE;
+}
+
+
+//============================================================
+// osd_is_absolute_path
+//============================================================
+
+bool osd_is_absolute_path(std::string const &path)
+{
+ // assume no for everything
+ return false;
+}
+
+
+//============================================================
+// osd_get_volume_name
+//============================================================
+
+const char *osd_get_volume_name(int idx)
+{
+ // we don't expose volumes
+ return nullptr;
+}
diff --git a/src/osd/modules/file/winfile.cpp b/src/osd/modules/file/winfile.cpp
new file mode 100644
index 00000000000..67de56fec0a
--- /dev/null
+++ b/src/osd/modules/file/winfile.cpp
@@ -0,0 +1,513 @@
+// license:BSD-3-Clause
+// copyright-holders:Aaron Giles, Vas Crabb
+//============================================================
+//
+// winfile.c - Win32 OSD core file access functions
+//
+//============================================================
+
+#define WIN32_LEAN_AND_MEAN
+
+#include "winfile.h"
+
+// MAMEOS headers
+#include "strconv.h"
+#include "winutil.h"
+#include "winutf8.h"
+
+// MAME headers
+#include "osdcore.h"
+
+#include <cassert>
+
+// standard windows headers
+#include <windows.h>
+#include <winioctl.h>
+#include <tchar.h>
+#include <shlwapi.h>
+#include <stdlib.h>
+#include <ctype.h>
+
+
+namespace {
+//============================================================
+// TYPE DEFINITIONS
+//============================================================
+
+class win_osd_file : public osd_file
+{
+public:
+ win_osd_file(win_osd_file const &) = delete;
+ win_osd_file(win_osd_file &&) = delete;
+ win_osd_file& operator=(win_osd_file const &) = delete;
+ win_osd_file& operator=(win_osd_file &&) = delete;
+
+ win_osd_file(HANDLE handle) : m_handle(handle)
+ {
+ assert(m_handle);
+ assert(INVALID_HANDLE_VALUE != m_handle);
+ }
+
+ virtual ~win_osd_file() override
+ {
+ FlushFileBuffers(m_handle);
+ CloseHandle(m_handle);
+ }
+
+ virtual error read(void *buffer, std::uint64_t offset, std::uint32_t length, std::uint32_t &actual) override
+ {
+ // attempt to set the file pointer
+ LONG upper(std::uint32_t(offset >> 32));
+ DWORD result(SetFilePointer(m_handle, std::uint32_t(offset), &upper, FILE_BEGIN));
+ if (INVALID_SET_FILE_POINTER == result)
+ {
+ DWORD const err(GetLastError());
+ if (NO_ERROR != err)
+ win_error_to_file_error(err);
+ }
+
+ // then perform the read
+ if (!ReadFile(m_handle, buffer, length, &result, NULL))
+ return win_error_to_file_error(GetLastError());
+
+ actual = result;
+ return error::NONE;
+ }
+
+ virtual error write(void const *buffer, std::uint64_t offset, std::uint32_t length, std::uint32_t &actual) override
+ {
+ // attempt to set the file pointer
+ LONG upper(std::uint32_t(offset >> 32));
+ DWORD result(SetFilePointer(m_handle, std::uint32_t(offset), &upper, FILE_BEGIN));
+ if (INVALID_SET_FILE_POINTER == result)
+ {
+ DWORD const err(GetLastError());
+ if (NO_ERROR != err)
+ win_error_to_file_error(err);
+ }
+
+ // then perform the write
+ if (!WriteFile(m_handle, buffer, length, &result, NULL))
+ return win_error_to_file_error(GetLastError());
+
+ actual = result;
+ return error::NONE;
+ }
+
+ virtual error truncate(std::uint64_t offset) override
+ {
+ // attempt to set the file pointer
+ LONG upper(std::uint32_t(offset >> 32));
+ DWORD const result(SetFilePointer(m_handle, std::uint32_t(offset), &upper, FILE_BEGIN));
+ if (INVALID_SET_FILE_POINTER == result)
+ {
+ DWORD const err(GetLastError());
+ if (NO_ERROR != err)
+ win_error_to_file_error(err);
+ }
+
+ // then perform the truncation
+ if (!SetEndOfFile(m_handle))
+ return win_error_to_file_error(GetLastError());
+ else
+ return error::NONE;
+ }
+
+ virtual error flush() override
+ {
+ // shouldn't be any userspace buffers on the file handle
+ return error::NONE;
+ }
+
+private:
+ HANDLE m_handle;
+};
+
+
+template <typename T>
+class osd_disposer
+{
+public:
+ osd_disposer(T *&ptr) : m_ptr(ptr) { }
+ ~osd_disposer() { if (m_ptr) osd_free(m_ptr); }
+private:
+ T *&m_ptr;
+};
+
+
+
+//============================================================
+// INLINE FUNCTIONS
+//============================================================
+
+inline bool is_path_to_physical_drive(char const *path)
+{
+ return (_strnicmp(path, "\\\\.\\physicaldrive", 17) == 0);
+}
+
+
+
+//============================================================
+// create_path_recursive
+//============================================================
+
+DWORD create_path_recursive(TCHAR *path)
+{
+ // if there's still a separator, and it's not the root, nuke it and recurse
+ TCHAR *sep = _tcsrchr(path, '\\');
+ if (sep && (sep > path) && (sep[0] != ':') && (sep[-1] != '\\'))
+ {
+ *sep = 0;
+ create_path_recursive(path);
+ *sep = '\\';
+ }
+
+ // if the path already exists, we're done
+ if (GetFileAttributes(path) != INVALID_FILE_ATTRIBUTES)
+ return NO_ERROR;
+ else if (!CreateDirectory(path, NULL))
+ return GetLastError();
+ else
+ return NO_ERROR;
+}
+
+} // anonymous namespace
+
+
+
+//============================================================
+// osd_open
+//============================================================
+
+osd_file::error osd_file::open(std::string const &orig_path, UINT32 openflags, ptr &file, std::uint64_t &filesize)
+{
+ std::string path;
+ try { osd_subst_env(path, orig_path); }
+ catch (...) { return error::OUT_OF_MEMORY; }
+
+ if (win_check_socket_path(path))
+ return win_open_socket(path, openflags, file, filesize);
+ else if (win_check_ptty_path(path))
+ return win_open_ptty(path, openflags, file, filesize);
+
+ // convert path to TCHAR
+ TCHAR *t_path = tstring_from_utf8(path);
+ osd_disposer<TCHAR> t_path_disposer(t_path);
+ if (!t_path)
+ return error::OUT_OF_MEMORY;
+
+ // convert the path into something Windows compatible
+ for (TCHAR *src = t_path; *src != 0; src++)
+ *src = /* ('/' == *src) ? '\\' : */ *src;
+
+ // select the file open modes
+ DWORD disposition, access, sharemode;
+ if (openflags & OPEN_FLAG_WRITE)
+ {
+ disposition = (!is_path_to_physical_drive(path) && (openflags & OPEN_FLAG_CREATE)) ? CREATE_ALWAYS : OPEN_EXISTING;
+ access = (openflags & OPEN_FLAG_READ) ? (GENERIC_READ | GENERIC_WRITE) : GENERIC_WRITE;
+ sharemode = FILE_SHARE_READ;
+ }
+ else if (openflags & OPEN_FLAG_READ)
+ {
+ disposition = OPEN_EXISTING;
+ access = GENERIC_READ;
+ sharemode = FILE_SHARE_READ;
+ }
+ else
+ {
+ return error::INVALID_ACCESS;
+ }
+
+ // attempt to open the file
+ HANDLE h = CreateFile(t_path, access, sharemode, NULL, disposition, 0, NULL);
+ if (INVALID_HANDLE_VALUE == h)
+ {
+ DWORD err = GetLastError();
+ // create the path if necessary
+ if ((ERROR_PATH_NOT_FOUND == err) && (openflags & OPEN_FLAG_CREATE) && (openflags & OPEN_FLAG_CREATE_PATHS))
+ {
+ TCHAR *pathsep = _tcsrchr(t_path, '\\');
+ if (pathsep != NULL)
+ {
+ // create the path up to the file
+ *pathsep = 0;
+ err = create_path_recursive(t_path);
+ *pathsep = '\\';
+
+ // attempt to reopen the file
+ if (err == NO_ERROR)
+ h = CreateFile(t_path, access, sharemode, NULL, disposition, 0, NULL);
+ }
+ }
+
+ // if we still failed, clean up and free
+ if (h == INVALID_HANDLE_VALUE)
+ return win_error_to_file_error(err);
+ }
+
+ // get the file size
+ DWORD upper, lower;
+ lower = GetFileSize(h, &upper);
+ if (INVALID_FILE_SIZE == lower)
+ {
+ DWORD const err = GetLastError();
+ if (NO_ERROR != err)
+ {
+ CloseHandle(h);
+ return win_error_to_file_error(err);
+ }
+ }
+
+ try
+ {
+ file = std::make_unique<win_osd_file>(h);
+ filesize = (std::uint64_t(upper) << 32) | lower;
+ return error::NONE;
+ }
+ catch (...)
+ {
+ CloseHandle(h);
+ return error::OUT_OF_MEMORY;
+ }
+}
+
+
+
+//============================================================
+// osd_openpty
+//============================================================
+
+osd_file::error osd_file::openpty(ptr &file, std::string &name)
+{
+ return error::FAILURE;
+}
+
+
+
+//============================================================
+// osd_rmfile
+//============================================================
+
+osd_file::error osd_file::remove(std::string const &filename)
+{
+ TCHAR *tempstr = tstring_from_utf8(filename.c_str());
+ if (!tempstr)
+ return error::OUT_OF_MEMORY;
+
+ error filerr = error::NONE;
+ if (!DeleteFile(tempstr))
+ filerr = win_error_to_file_error(GetLastError());
+
+ osd_free(tempstr);
+ return filerr;
+}
+
+
+
+//============================================================
+// osd_get_physical_drive_geometry
+//============================================================
+
+int osd_get_physical_drive_geometry(const char *filename, UINT32 *cylinders, UINT32 *heads, UINT32 *sectors, UINT32 *bps)
+{
+ DISK_GEOMETRY dg;
+ DWORD bytesRead;
+ TCHAR *t_filename;
+ HANDLE file;
+ int result;
+
+ // if it doesn't smell like a physical drive, just return FALSE
+ if (!is_path_to_physical_drive(filename))
+ return FALSE;
+
+ // do a create file on the drive
+ t_filename = tstring_from_utf8(filename);
+ if (t_filename == NULL)
+ return FALSE;
+ file = CreateFile(t_filename, GENERIC_READ, FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_FLAG_NO_BUFFERING, NULL);
+ osd_free(t_filename);
+ if (file == INVALID_HANDLE_VALUE)
+ return FALSE;
+
+ // device I/O control should return the geometry
+ result = DeviceIoControl(file, IOCTL_DISK_GET_DRIVE_GEOMETRY, NULL, 0, &dg, sizeof(dg), &bytesRead, NULL);
+ CloseHandle(file);
+
+ // if that failed, return false
+ if (!result)
+ return FALSE;
+
+ // store the results
+ *cylinders = (UINT32)dg.Cylinders.QuadPart;
+ *heads = dg.TracksPerCylinder;
+ *sectors = dg.SectorsPerTrack;
+ *bps = dg.BytesPerSector;
+
+ // normalize
+ while (*heads > 16 && !(*heads & 1))
+ {
+ *heads /= 2;
+ *cylinders *= 2;
+ }
+ return TRUE;
+}
+
+
+
+//============================================================
+// osd_stat
+//============================================================
+
+osd_directory_entry *osd_stat(const std::string &path)
+{
+ osd_directory_entry *result = NULL;
+ TCHAR *t_path;
+ HANDLE find = INVALID_HANDLE_VALUE;
+ WIN32_FIND_DATA find_data;
+
+ // convert the path to TCHARs
+ t_path = tstring_from_utf8(path.c_str());
+ if (t_path == NULL)
+ goto done;
+
+ // is this path a root directory (e.g. - C:)?
+ if (isalpha(path[0]) && (path[1] == ':') && (path[2] == '\0'))
+ {
+ // need to do special logic for root directories
+ memset(&find_data, 0, sizeof(find_data));
+ find_data.dwFileAttributes = GetFileAttributes(t_path);
+ }
+ else
+ {
+ // attempt to find the first file
+ find = FindFirstFile(t_path, &find_data);
+ if (find == INVALID_HANDLE_VALUE)
+ goto done;
+ }
+
+ // create an osd_directory_entry; be sure to make sure that the caller can
+ // free all resources by just freeing the resulting osd_directory_entry
+ result = (osd_directory_entry *)osd_malloc_array(sizeof(*result) + path.length() + 1);
+ if (!result)
+ goto done;
+ strcpy(((char *) result) + sizeof(*result), path.c_str());
+ result->name = ((char *) result) + sizeof(*result);
+ result->type = win_attributes_to_entry_type(find_data.dwFileAttributes);
+ result->size = find_data.nFileSizeLow | ((UINT64) find_data.nFileSizeHigh << 32);
+
+done:
+ if (t_path != NULL)
+ osd_free(t_path);
+ return result;
+}
+
+
+//============================================================
+// osd_get_full_path
+//============================================================
+
+osd_file::error osd_get_full_path(std::string &dst, std::string const &path)
+{
+ // convert the path to TCHARs
+ TCHAR *t_path = tstring_from_utf8(path.c_str());
+ osd_disposer<TCHAR> t_path_disposer(t_path);
+ if (!t_path)
+ return osd_file::error::OUT_OF_MEMORY;
+
+ // cannonicalize the path
+ TCHAR buffer[MAX_PATH];
+ if (!GetFullPathName(t_path, ARRAY_LENGTH(buffer), buffer, NULL))
+ return win_error_to_file_error(GetLastError());
+
+ // convert the result back to UTF-8
+ char *result = utf8_from_tstring(buffer);
+ osd_disposer<char> result_disposer(result);
+ if (!result)
+ return osd_file::error::OUT_OF_MEMORY;
+
+ dst = result;
+ return osd_file::error::NONE;
+}
+
+
+
+//============================================================
+// osd_is_absolute_path
+//============================================================
+
+bool osd_is_absolute_path(std::string const &path)
+{
+ bool result = false;
+ TCHAR *t_path = tstring_from_utf8(path.c_str());
+ if (t_path != NULL)
+ {
+ result = !PathIsRelative(t_path);
+ osd_free(t_path);
+ }
+ return result;
+}
+
+
+
+//============================================================
+// osd_get_volume_name
+//============================================================
+
+const char *osd_get_volume_name(int idx)
+{
+ static char szBuffer[128];
+ const char *p;
+
+ GetLogicalDriveStringsA(ARRAY_LENGTH(szBuffer), szBuffer);
+
+ p = szBuffer;
+ while(idx--) {
+ p += strlen(p) + 1;
+ if (!*p) return NULL;
+ }
+
+ return p;
+}
+
+
+
+//============================================================
+// win_error_to_file_error
+//============================================================
+
+osd_file::error win_error_to_file_error(DWORD error)
+{
+ osd_file::error filerr;
+
+ // convert a Windows error to a osd_file::error
+ switch (error)
+ {
+ case ERROR_SUCCESS:
+ filerr = osd_file::error::NONE;
+ break;
+
+ case ERROR_OUTOFMEMORY:
+ filerr = osd_file::error::OUT_OF_MEMORY;
+ break;
+
+ case ERROR_FILE_NOT_FOUND:
+ case ERROR_FILENAME_EXCED_RANGE:
+ case ERROR_PATH_NOT_FOUND:
+ filerr = osd_file::error::NOT_FOUND;
+ break;
+
+ case ERROR_ACCESS_DENIED:
+ filerr = osd_file::error::ACCESS_DENIED;
+ break;
+
+ case ERROR_SHARING_VIOLATION:
+ filerr = osd_file::error::ALREADY_OPEN;
+ break;
+
+ default:
+ filerr = osd_file::error::FAILURE;
+ break;
+ }
+ return filerr;
+}
diff --git a/src/osd/modules/file/winfile.h b/src/osd/modules/file/winfile.h
new file mode 100644
index 00000000000..9a6f1b8fc34
--- /dev/null
+++ b/src/osd/modules/file/winfile.h
@@ -0,0 +1,34 @@
+// license:BSD-3-Clause
+// copyright-holders:Aaron Giles, Vas Crabb
+//============================================================
+//
+// winfile.h - File access functions
+//
+//============================================================
+#ifndef MAME_OSD_WINDOWS_WINFILE_H
+#define MAME_OSD_WINDOWS_WINFILE_H
+
+#include "osdcore.h"
+
+#include <cstdint>
+#include <string>
+
+#include <winsock2.h>
+
+
+//============================================================
+// PROTOTYPES
+//============================================================
+
+bool win_init_sockets();
+void win_cleanup_sockets();
+
+bool win_check_socket_path(std::string const &path);
+osd_file::error win_open_socket(std::string const &path, std::uint32_t openflags, osd_file::ptr &file, std::uint64_t &filesize);
+
+bool win_check_ptty_path(std::string const &path);
+osd_file::error win_open_ptty(std::string const &path, std::uint32_t openflags, osd_file::ptr &file, std::uint64_t &filesize);
+
+osd_file::error win_error_to_file_error(DWORD error);
+
+#endif // MAME_OSD_WINDOWS_WINFILE_H
diff --git a/src/osd/modules/file/winptty.cpp b/src/osd/modules/file/winptty.cpp
new file mode 100644
index 00000000000..44c42d40588
--- /dev/null
+++ b/src/osd/modules/file/winptty.cpp
@@ -0,0 +1,111 @@
+// license:BSD-3-Clause
+// copyright-holders:Aaron Giles, Vas Crabb
+
+#define WIN32_LEAN_AND_MEAN
+
+#include "winfile.h"
+
+#include "strconv.h"
+#include "winutil.h"
+
+#include <cassert>
+
+#include <windows.h>
+#include <stdlib.h>
+
+
+namespace {
+char const *const winfile_ptty_identifier = "\\\\.\\pipe\\";
+
+
+class win_osd_ptty : public osd_file
+{
+public:
+ win_osd_ptty(win_osd_ptty const &) = delete;
+ win_osd_ptty(win_osd_ptty &&) = delete;
+ win_osd_ptty& operator=(win_osd_ptty const &) = delete;
+ win_osd_ptty& operator=(win_osd_ptty &&) = delete;
+
+ win_osd_ptty(HANDLE handle) : m_handle(handle)
+ {
+ assert(m_handle);
+ assert(INVALID_HANDLE_VALUE != m_handle);
+ }
+
+ ~win_osd_ptty()
+ {
+ FlushFileBuffers(m_handle);
+ DisconnectNamedPipe(m_handle);
+ CloseHandle(m_handle);
+ }
+
+ virtual error read(void *buffer, std::uint64_t offset, std::uint32_t count, std::uint32_t &actual) override
+ {
+ DWORD bytes_read;
+ if (!ReadFile(m_handle, buffer, count, &bytes_read, NULL))
+ return win_error_to_file_error(GetLastError());
+
+ actual = bytes_read;
+ return error::NONE;
+ }
+
+ virtual error write(void const *buffer, std::uint64_t offset, std::uint32_t count, std::uint32_t &actual)
+ {
+ DWORD bytes_written;
+ if (!WriteFile(m_handle, buffer, count, &bytes_written, NULL))
+ return win_error_to_file_error(GetLastError());
+
+ actual = bytes_written;
+ return error::NONE;
+ }
+
+ virtual error truncate(std::uint64_t offset) override
+ {
+ // doesn't make sense for a PTTY
+ return error::INVALID_ACCESS;
+ }
+
+ virtual error flush() override
+ {
+ // don't want to wait for client to read all data as implied by FlushFileBuffers
+ return error::NONE;
+ }
+
+private:
+ HANDLE m_handle;
+};
+
+} // anonymous namespace
+
+
+bool win_check_ptty_path(std::string const &path)
+{
+ if (strncmp(path.c_str(), winfile_ptty_identifier, strlen(winfile_ptty_identifier)) == 0) return true;
+ return false;
+}
+
+
+osd_file::error win_open_ptty(std::string const &path, std::uint32_t openflags, osd_file::ptr &file, std::uint64_t &filesize)
+{
+ TCHAR *t_name = tstring_from_utf8(path.c_str());
+ if (!t_name)
+ return osd_file::error::OUT_OF_MEMORY;
+
+ HANDLE pipe = CreateNamedPipe(t_name, PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_NOWAIT, 1, 32, 32, 0, NULL);
+ osd_free(t_name);
+
+ if (INVALID_HANDLE_VALUE == pipe)
+ return osd_file::error::ACCESS_DENIED;
+
+ try
+ {
+ file = std::make_unique<win_osd_ptty>(pipe);
+ filesize = 0;
+ return osd_file::error::NONE;
+ }
+ catch (...)
+ {
+ CloseHandle(pipe);
+ return osd_file::error::OUT_OF_MEMORY;
+ }
+}
diff --git a/src/osd/modules/file/winsocket.cpp b/src/osd/modules/file/winsocket.cpp
new file mode 100644
index 00000000000..d1c3f4508e8
--- /dev/null
+++ b/src/osd/modules/file/winsocket.cpp
@@ -0,0 +1,277 @@
+// license:BSD-3-Clause
+// copyright-holders:Aaron Giles, Vas Crabb
+//============================================================
+//
+// winsocket.c - Windows socket (inet) access functions
+//
+//============================================================
+
+#define WIN32_LEAN_AND_MEAN
+
+#include "winfile.h"
+
+// MAMEOS headers
+#include "winutil.h"
+
+// MAME headers
+#include "osdcore.h"
+
+#include <cassert>
+#include <cstdio>
+
+// standard windows headers
+#include <windows.h>
+#include <winioctl.h>
+#include <tchar.h>
+#include <stdlib.h>
+#include <ctype.h>
+
+
+namespace {
+char const *const winfile_socket_identifier = "socket.";
+
+
+class win_osd_socket : public osd_file
+{
+public:
+ win_osd_socket(win_osd_socket const &) = delete;
+ win_osd_socket(win_osd_socket &&) = delete;
+ win_osd_socket& operator=(win_osd_socket const &) = delete;
+ win_osd_socket& operator=(win_osd_socket &&) = delete;
+
+ win_osd_socket(SOCKET s, bool l)
+ : m_socket(s)
+ , m_listening(l)
+ {
+ assert(INVALID_SOCKET != m_socket);
+ }
+
+ virtual ~win_osd_socket() override
+ {
+ closesocket(m_socket);
+ }
+
+ virtual error read(void *buffer, std::uint64_t offset, std::uint32_t length, std::uint32_t &actual) override
+ {
+ fd_set readfds;
+ FD_ZERO(&readfds);
+ FD_SET(m_socket, &readfds);
+
+ struct timeval timeout;
+ timeout.tv_sec = timeout.tv_usec = 0;
+
+ if (select(m_socket + 1, &readfds, nullptr, nullptr, &timeout) < 0)
+ {
+ char line[80];
+ std::sprintf(line, "win_read_socket : %s : %d ", __FILE__, __LINE__);
+ std::perror(line);
+ return error::FAILURE;
+ }
+ else if (FD_ISSET(m_socket, &readfds))
+ {
+ if (!m_listening)
+ {
+ // connected socket
+ int const result = recv(m_socket, (char*)buffer, length, 0);
+ if (result < 0)
+ {
+ return wsa_error_to_file_error(WSAGetLastError());
+ }
+ else
+ {
+ actual = result;
+ return error::NONE;
+ }
+ }
+ else
+ {
+ // listening socket
+ SOCKET const accepted = accept(m_socket, nullptr, nullptr);
+ if (INVALID_SOCKET == accepted)
+ {
+ return wsa_error_to_file_error(WSAGetLastError());
+ }
+ else
+ {
+ closesocket(m_socket);
+ m_socket = accepted;
+ m_listening = false;
+ actual = 0;
+
+ return error::NONE;
+ }
+ }
+ }
+ else
+ {
+ return error::FAILURE;
+ }
+ }
+
+ virtual error write(void const *buffer, std::uint64_t offset, std::uint32_t length, std::uint32_t &actual) override
+ {
+ auto const result = send(m_socket, reinterpret_cast<const char *>(buffer), length, 0);
+ if (result < 0)
+ return wsa_error_to_file_error(WSAGetLastError());
+
+ actual = result;
+ return error::NONE;
+ }
+
+ virtual error truncate(std::uint64_t offset) override
+ {
+ // doesn't make sense for a socket
+ return error::INVALID_ACCESS;
+ }
+
+ virtual error flush() override
+ {
+ // no buffers to flush
+ return error::NONE;
+ }
+
+ static error wsa_error_to_file_error(int err)
+ {
+ switch (err)
+ {
+ case 0: return error::NONE;
+ case WSAEACCES: return error::ACCESS_DENIED;
+ case WSAEADDRINUSE: return error::ALREADY_OPEN;
+ case WSAEADDRNOTAVAIL: return error::NOT_FOUND;
+ case WSAECONNREFUSED: return error::NOT_FOUND;
+ case WSAEHOSTUNREACH: return error::NOT_FOUND;
+ case WSAENETUNREACH: return error::NOT_FOUND;
+ default: return error::FAILURE;
+ }
+ }
+
+private:
+ SOCKET m_socket;
+ bool m_listening;
+};
+
+} // anonymous namespace
+
+
+bool win_init_sockets()
+{
+ WSADATA wsaData;
+ WORD const version = MAKEWORD(2, 0);
+ int const error = WSAStartup(version, &wsaData);
+
+ // check for error
+ if (error)
+ {
+ // error occurred
+ return false;
+ }
+
+ // check for correct version
+ if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion ) != 0)
+ {
+ // incorrect WinSock version
+ WSACleanup();
+ return false;
+ }
+
+ // WinSock has been initialized
+ return true;
+}
+
+
+void win_cleanup_sockets()
+{
+ WSACleanup();
+}
+
+
+bool win_check_socket_path(std::string const &path)
+{
+ if (strncmp(path.c_str(), winfile_socket_identifier, strlen(winfile_socket_identifier)) == 0 &&
+ strchr(path.c_str(), ':') != nullptr) return true;
+ return false;
+}
+
+
+osd_file::error win_open_socket(std::string const &path, std::uint32_t openflags, osd_file::ptr &file, std::uint64_t &filesize)
+{
+ char hostname[256];
+ int port;
+ std::sscanf(&path[strlen(winfile_socket_identifier)], "%255[^:]:%d", hostname, &port);
+
+ struct hostent const *const localhost = gethostbyname(hostname);
+ if (!localhost)
+ return osd_file::error::NOT_FOUND;
+
+ struct sockaddr_in sai;
+ memset(&sai, 0, sizeof(sai));
+ sai.sin_family = AF_INET;
+ sai.sin_port = htons(port);
+ sai.sin_addr = *reinterpret_cast<struct in_addr *>(localhost->h_addr);
+
+ SOCKET sock = socket(AF_INET, SOCK_STREAM, 0);
+ if (INVALID_SOCKET == sock)
+ return win_osd_socket::wsa_error_to_file_error(WSAGetLastError());
+
+ int const flag = 1;
+ if (setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, reinterpret_cast<const char *>(&flag), sizeof(flag)) == SOCKET_ERROR)
+ {
+ int const err = WSAGetLastError();
+ closesocket(sock);
+ return win_osd_socket::wsa_error_to_file_error(err);
+ }
+
+ // listening socket support
+ if (openflags & OPEN_FLAG_CREATE)
+ {
+ //printf("Listening for client at '%s' on port '%d'\n", hostname, port);
+ // bind socket...
+ if (bind(sock, reinterpret_cast<struct sockaddr const *>(&sai), sizeof(struct sockaddr)) == SOCKET_ERROR)
+ {
+ int const err = WSAGetLastError();
+ closesocket(sock);
+ return win_osd_socket::wsa_error_to_file_error(err);
+ }
+
+ // start to listen...
+ if (listen(sock, 1) == SOCKET_ERROR)
+ {
+ int const err = WSAGetLastError();
+ closesocket(sock);
+ return win_osd_socket::wsa_error_to_file_error(err);
+ }
+
+ // mark socket as "listening"
+ try
+ {
+ file = std::make_unique<win_osd_socket>(sock, true);
+ filesize = 0;
+ return osd_file::error::NONE;
+ }
+ catch (...)
+ {
+ closesocket(sock);
+ return osd_file::error::OUT_OF_MEMORY;
+ }
+ }
+ else
+ {
+ //printf("Connecting to server '%s' on port '%d'\n", hostname, port);
+ if (connect(sock, reinterpret_cast<struct sockaddr const *>(&sai), sizeof(struct sockaddr)) == SOCKET_ERROR)
+ {
+ closesocket(sock);
+ return osd_file::error::ACCESS_DENIED; // have to return this value or bitb won't try to bind on connect failure
+ }
+ try
+ {
+ file = std::make_unique<win_osd_socket>(sock, false);
+ filesize = 0;
+ return osd_file::error::NONE;
+ }
+ catch (...)
+ {
+ closesocket(sock);
+ return osd_file::error::OUT_OF_MEMORY;
+ }
+ }
+}
diff --git a/src/osd/modules/render/d3d/d3dhlsl.cpp b/src/osd/modules/render/d3d/d3dhlsl.cpp
index 17b2f411336..5fcc8209500 100644
--- a/src/osd/modules/render/d3d/d3dhlsl.cpp
+++ b/src/osd/modules/render/d3d/d3dhlsl.cpp
@@ -38,7 +38,7 @@
//============================================================
static slider_state *g_slider_list;
-static file_error open_next(renderer_d3d9 *d3d, emu_file &file, const char *templ, const char *extension, int idx);
+static osd_file::error open_next(renderer_d3d9 *d3d, emu_file &file, const char *templ, const char *extension, int idx);
//============================================================
// PROTOTYPES
@@ -279,8 +279,8 @@ void shaders::render_snapshot(surface *surface)
int idx = cy * 2 + cx;
emu_file file(machine->options().snapshot_directory(), OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS);
- file_error filerr = open_next(d3d, file, nullptr, "png", idx);
- if (filerr != FILERR_NONE)
+ osd_file::error filerr = open_next(d3d, file, nullptr, "png", idx);
+ if (filerr != osd_file::error::NONE)
{
return;
}
@@ -363,8 +363,8 @@ void shaders::record_texture()
{
// handle an AVI recording
// write the next frame
- avi_error avierr = avi_append_video_frame(avi_output_file, avi_snap);
- if (avierr != AVIERR_NONE)
+ avi_file::error avierr = avi_output_file->append_video_frame(avi_snap);
+ if (avierr != avi_file::error::NONE)
{
end_avi_recording();
return;
@@ -388,9 +388,9 @@ void shaders::end_avi_recording()
return;
}
- if (avi_output_file != nullptr)
+ if (avi_output_file)
{
- avi_close(avi_output_file);
+ avi_output_file.reset();
}
avi_output_file = nullptr;
@@ -463,7 +463,7 @@ void shaders::begin_avi_recording(const char *name)
avi_next_frame_time = machine->time();
// build up information about this new movie
- avi_movie_info info;
+ avi_file::movie_info info;
info.video_format = 0;
info.video_timescale = 1000 * ((machine->first_screen() != nullptr) ? ATTOSECONDS_TO_HZ(machine->first_screen()->frame_period().m_attoseconds) : screen_device::DEFAULT_FRAME_RATE);
info.video_sampletime = 1000;
@@ -481,7 +481,7 @@ void shaders::begin_avi_recording(const char *name)
info.audio_samplerate = machine->sample_rate();
// create a new temporary movie file
- file_error filerr;
+ osd_file::error filerr;
std::string fullpath;
{
emu_file tempfile(machine->options().snapshot_directory(), OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS);
@@ -500,19 +500,19 @@ void shaders::begin_avi_recording(const char *name)
}
// if we succeeded, make a copy of the name and create the real file over top
- if (filerr == FILERR_NONE)
+ if (filerr == osd_file::error::NONE)
{
fullpath = tempfile.fullpath();
}
}
- if (filerr == FILERR_NONE)
+ if (filerr == osd_file::error::NONE)
{
// create the file and free the string
- avi_error avierr = avi_create(fullpath.c_str(), &info, &avi_output_file);
- if (avierr != AVIERR_NONE)
+ avi_file::error avierr = avi_file::create(fullpath, info, avi_output_file);
+ if (avierr != avi_file::error::NONE)
{
- osd_printf_error("Error creating AVI: %s\n", avi_error_string(avierr));
+ osd_printf_error("Error creating AVI: %s\n", avi_file::error_string(avierr));
}
}
}
@@ -2420,7 +2420,7 @@ slider_desc shaders::s_sliders[] =
{ "Gamma,", -80, 0, 80, 1, SLIDER_COLOR, SLIDER_SCREEN_TYPE_ANY, SLIDER_POWER, 0.1f, "%2.2f", {} },
{ "Floor,", 0, 0, 100, 1, SLIDER_COLOR, SLIDER_SCREEN_TYPE_ANY, SLIDER_FLOOR, 0.01f, "%2.2f", {} },
{ "Phosphor Life,", 0, 0, 100, 1, SLIDER_COLOR, SLIDER_SCREEN_TYPE_ANY, SLIDER_PHOSPHOR, 0.01f, "%2.2f", {} },
- { "Bloom Blend Mode", 0, 0, 1, 1, SLIDER_INT_ENUM, SLIDER_SCREEN_TYPE_ANY, SLIDER_BLOOM_BLEND_MODE, 0, "%s", { "Brighten", "Darken" } },
+ { "Bloom Blend Mode", 0, 0, 1, 1, SLIDER_INT_ENUM, SLIDER_SCREEN_TYPE_ANY, SLIDER_BLOOM_BLEND_MODE, 0, "%s", { "Brighten", "Darken" } },
{ "Bloom Scale", 0, 0, 2000, 5, SLIDER_FLOAT, SLIDER_SCREEN_TYPE_ANY, SLIDER_BLOOM_SCALE, 0.001f, "%1.3f", {} },
{ "Bloom Overdrive,", 0, 0, 2000, 5, SLIDER_COLOR, SLIDER_SCREEN_TYPE_ANY, SLIDER_BLOOM_OVERDRIVE, 0.001f, "%1.3f", {} },
{ "Bloom Level 0 Scale", 0, 100, 100, 1, SLIDER_FLOAT, SLIDER_SCREEN_TYPE_ANY, SLIDER_BLOOM_LVL0_SCALE, 0.01f, "%1.2f", {} },
@@ -3153,7 +3153,7 @@ slider_state *renderer_d3d9::get_slider_list()
// scheme
//-------------------------------------------------
-static file_error open_next(renderer_d3d9 *d3d, emu_file &file, const char *templ, const char *extension, int idx)
+static osd_file::error open_next(renderer_d3d9 *d3d, emu_file &file, const char *templ, const char *extension, int idx)
{
UINT32 origflags = file.openflags();
@@ -3280,8 +3280,8 @@ static file_error open_next(renderer_d3d9 *d3d, emu_file &file, const char *temp
strreplace(fname.assign(snapstr), "%i", string_format("%04d_%d", seq, idx).c_str());
// try to open the file; stop when we fail
- file_error filerr = file.open(fname.c_str());
- if (filerr != FILERR_NONE)
+ osd_file::error filerr = file.open(fname.c_str());
+ if (filerr != osd_file::error::NONE)
{
break;
}
diff --git a/src/osd/modules/render/d3d/d3dhlsl.h b/src/osd/modules/render/d3d/d3dhlsl.h
index 4ff8b1ac88c..8358efc86e7 100644
--- a/src/osd/modules/render/d3d/d3dhlsl.h
+++ b/src/osd/modules/render/d3d/d3dhlsl.h
@@ -227,7 +227,7 @@ struct hlsl_options
float saturation;
// NTSC
- int yiq_enable;
+ int yiq_enable;
float yiq_jitter;
float yiq_cc;
float yiq_a;
@@ -264,17 +264,17 @@ struct hlsl_options
struct slider_desc
{
- const char * name;
- int minval;
- int defval;
- int maxval;
- int step;
- int slider_type;
- int screen_type;
- int id;
- float scale;
- const char * format;
- std::vector<const char *> strings;
+ const char * name;
+ int minval;
+ int defval;
+ int maxval;
+ int step;
+ int slider_type;
+ int screen_type;
+ int id;
+ float scale;
+ const char * format;
+ std::vector<const char *> strings;
};
class slider
@@ -285,9 +285,9 @@ public:
INT32 update(std::string *str, INT32 newval);
private:
- slider_desc * m_desc;
- void * m_value;
- bool * m_dirty;
+ slider_desc * m_desc;
+ void * m_value;
+ bool * m_dirty;
};
class shaders
@@ -402,7 +402,7 @@ private:
UINT32 vecbuf_index;
UINT32 vecbuf_count;
- avi_file * avi_output_file; // AVI file
+ avi_file::ptr avi_output_file; // AVI file
bitmap_rgb32 avi_snap; // AVI snapshot
int avi_frame; // AVI frame
attotime avi_frame_period; // AVI frame period
@@ -450,7 +450,7 @@ private:
d3d_render_target * targethead;
cache_target * cachehead;
- std::vector<slider*> sliders;
+ std::vector<slider*> sliders;
static slider_desc s_sliders[];
static hlsl_options last_options; // last used options
diff --git a/src/osd/osdcore.h b/src/osd/osdcore.h
index dec4a5c030b..899f024d9f4 100644
--- a/src/osd/osdcore.h
+++ b/src/osd/osdcore.h
@@ -16,11 +16,16 @@
#pragma once
-#ifndef __OSDCORE_H__
-#define __OSDCORE_H__
+#ifndef MAME_OSD_OSDCORE_H
+#define MAME_OSD_OSDCORE_H
#include "osdcomm.h"
-#include <stdarg.h>
+
+#include <cstdarg>
+#include <cstdint>
+#include <memory>
+#include <string>
+
/***************************************************************************
FILE I/O INTERFACES
@@ -42,194 +47,185 @@
#define OPEN_FLAG_CREATE_PATHS 0x0008 /* create paths as necessary */
#define OPEN_FLAG_NO_PRELOAD 0x0010 /* do not decompress on open */
-/* error codes returned by routines below */
-enum file_error
+// osd_file is an interface which represents an open file/PTY/socket
+class osd_file
{
- FILERR_NONE,
- FILERR_FAILURE,
- FILERR_OUT_OF_MEMORY,
- FILERR_NOT_FOUND,
- FILERR_ACCESS_DENIED,
- FILERR_ALREADY_OPEN,
- FILERR_TOO_MANY_FILES,
- FILERR_INVALID_DATA,
- FILERR_INVALID_ACCESS
-};
+public:
+ // error codes returned by routines below
+ enum class error
+ {
+ NONE,
+ FAILURE,
+ OUT_OF_MEMORY,
+ NOT_FOUND,
+ ACCESS_DENIED,
+ ALREADY_OPEN,
+ TOO_MANY_FILES,
+ INVALID_DATA,
+ INVALID_ACCESS
+ };
-/* osd_file is an opaque type which represents an open file */
-struct osd_file;
+ typedef std::unique_ptr<osd_file> ptr;
-/*-----------------------------------------------------------------------------
- osd_open: open a new file.
- Parameters:
+ /*-----------------------------------------------------------------------------
+ osd_file::open: open a new file.
- path - path to the file to open
+ Parameters:
- openflags - some combination of:
+ path - path to the file to open
- OPEN_FLAG_READ - open the file for read access
- OPEN_FLAG_WRITE - open the file for write access
- OPEN_FLAG_CREATE - create/truncate the file when opening
- OPEN_FLAG_CREATE_PATHS - specifies that non-existant paths
- should be created if necessary
+ openflags - some combination of:
- file - pointer to an osd_file * to receive the newly-opened file
- handle; this is only valid if the function returns FILERR_NONE
+ OPEN_FLAG_READ - open the file for read access
+ OPEN_FLAG_WRITE - open the file for write access
+ OPEN_FLAG_CREATE - create/truncate the file when opening
+ OPEN_FLAG_CREATE_PATHS - specifies that non-existant paths
+ should be created if necessary
- filesize - pointer to a UINT64 to receive the size of the opened
- file; this is only valid if the function returns FILERR_NONE
+ file - reference to an osd_file::ptr to receive the newly-opened file
+ handle; this is only valid if the function returns FILERR_NONE
- Return value:
+ filesize - reference to a UINT64 to receive the size of the opened
+ file; this is only valid if the function returns FILERR_NONE
- a file_error describing any error that occurred while opening
- the file, or FILERR_NONE if no error occurred
+ Return value:
- Notes:
+ a file_error describing any error that occurred while opening
+ the file, or FILERR_NONE if no error occurred
- This function is called by core_fopen and several other places in
- the core to access files. These functions will construct paths by
- concatenating various search paths held in the options.c options
- database with partial paths specified by the core. The core assumes
- that the path separator is the first character of the string
- PATH_SEPARATOR, but does not interpret any path separators in the
- search paths, so if you use a different path separator in a search
- path, you may get a mixture of PATH_SEPARATORs (from the core) and
- alternate path separators (specified by users and placed into the
- options database).
------------------------------------------------------------------------------*/
-file_error osd_open(const char *path, UINT32 openflags, osd_file **file, UINT64 *filesize);
+ Notes:
+ This function is called by core_fopen and several other places in
+ the core to access files. These functions will construct paths by
+ concatenating various search paths held in the options.c options
+ database with partial paths specified by the core. The core assumes
+ that the path separator is the first character of the string
+ PATH_SEPARATOR, but does not interpret any path separators in the
+ search paths, so if you use a different path separator in a search
+ path, you may get a mixture of PATH_SEPARATORs (from the core) and
+ alternate path separators (specified by users and placed into the
+ options database).
+ -----------------------------------------------------------------------------*/
+ static error open(std::string const &path, std::uint32_t openflags, ptr &file, std::uint64_t &filesize);
-/*-----------------------------------------------------------------------------
- osd_close: close an open file
- Parameters:
+ /*-----------------------------------------------------------------------------
+ osd_file::openpty: create a new PTY pair
- file - handle to a file previously opened via osd_open
+ Parameters:
- Return value:
+ file - reference to an osd_file::ptr to receive the handle of the master
+ side of the newly-created PTY; this is only valid if the function
+ returns FILERR_NONE
- a file_error describing any error that occurred while closing
- the file, or FILERR_NONE if no error occurred
------------------------------------------------------------------------------*/
-file_error osd_close(osd_file *file);
+ name - reference to string where slave filename will be stored
+ Return value:
-/*-----------------------------------------------------------------------------
- osd_read: read from an open file
+ a file_error describing any error that occurred while creating the
+ PTY, or FILERR_NONE if no error occurred
+ -----------------------------------------------------------------------------*/
+ static error openpty(ptr &file, std::string &name);
- Parameters:
- file - handle to a file previously opened via osd_open
+ /*-----------------------------------------------------------------------------
+ osd_file::~osd_file: close an open file
+ -----------------------------------------------------------------------------*/
+ virtual ~osd_file() { }
- buffer - pointer to memory that will receive the data read
- offset - offset within the file to read from
+ /*-----------------------------------------------------------------------------
+ osd_file::read: read from an open file
- length - number of bytes to read from the file
+ Parameters:
- actual - pointer to a UINT32 to receive the number of bytes actually
- read during the operation; valid only if the function returns
- FILERR_NONE
+ buffer - pointer to memory that will receive the data read
- Return value:
+ offset - offset within the file to read from
- a file_error describing any error that occurred while reading
- from the file, or FILERR_NONE if no error occurred
------------------------------------------------------------------------------*/
-file_error osd_read(osd_file *file, void *buffer, UINT64 offset, UINT32 length, UINT32 *actual);
+ length - number of bytes to read from the file
+ actual - reference to a UINT32 to receive the number of bytes actually
+ read during the operation; valid only if the function returns
+ FILERR_NONE
-/*-----------------------------------------------------------------------------
- osd_write: write to an open file
+ Return value:
- Parameters:
+ a file_error describing any error that occurred while reading
+ from the file, or FILERR_NONE if no error occurred
+ -----------------------------------------------------------------------------*/
+ virtual error read(void *buffer, std::uint64_t offset, std::uint32_t length, std::uint32_t &actual) = 0;
- file - handle to a file previously opened via osd_open
- buffer - pointer to memory that contains the data to write
+ /*-----------------------------------------------------------------------------
+ osd_file::write: write to an open file
- offset - offset within the file to write to
+ Parameters:
- length - number of bytes to write to the file
+ buffer - pointer to memory that contains the data to write
- actual - pointer to a UINT32 to receive the number of bytes actually
- written during the operation; valid only if the function returns
- FILERR_NONE
+ offset - offset within the file to write to
- Return value:
+ length - number of bytes to write to the file
- a file_error describing any error that occurred while writing to
- the file, or FILERR_NONE if no error occurred
------------------------------------------------------------------------------*/
-file_error osd_write(osd_file *file, const void *buffer, UINT64 offset, UINT32 length, UINT32 *actual);
+ actual - reference to a UINT32 to receive the number of bytes actually
+ written during the operation; valid only if the function returns
+ FILERR_NONE
-/*-----------------------------------------------------------------------------
- osd_openpty: create a new PTY pair
+ Return value:
- Parameters:
+ a file_error describing any error that occurred while writing to
+ the file, or FILERR_NONE if no error occurred
+ -----------------------------------------------------------------------------*/
+ virtual error write(void const *buffer, std::uint64_t offset, std::uint32_t length, std::uint32_t &actual) = 0;
- file - pointer to an osd_file * to receive the handle of the master
- side of the newly-created PTY; this is only valid if the function
- returns FILERR_NONE
- name - pointer to memory where slave filename will be stored
+ /*-----------------------------------------------------------------------------
+ osd_file::truncate: change the size of an open file
- name_len - space allocated for name
+ Parameters:
- Return value:
+. offset - future size of the file
- a file_error describing any error that occurred while creating the
- PTY, or FILERR_NONE if no error occurred
------------------------------------------------------------------------------*/
-file_error osd_openpty(osd_file **file, char *name, size_t name_len);
+ Return value:
-/*-----------------------------------------------------------------------------
- osd_truncate: change the size of an open file
+ a file_error describing any error that occurred while writing to
+ the file, or FILERR_NONE if no error occurred
+ -----------------------------------------------------------------------------*/
+ virtual error truncate(std::uint64_t offset) = 0;
- Parameters:
- file - handle to a file previously opened via osd_open
+ /*-----------------------------------------------------------------------------
+ osd_file::flush: flush file buffers
- offset - future size of the file
+ Parameters:
- Return value:
+ file - handle to a file previously opened via osd_open
- a file_error describing any error that occurred while writing to
- the file, or FILERR_NONE if no error occurred
------------------------------------------------------------------------------*/
-file_error osd_truncate(osd_file *file, UINT64 offset);
+ Return value:
+ a file_error describing any error that occurred while flushing file
+ buffers, or FILERR_NONE if no error occurred
+ -----------------------------------------------------------------------------*/
+ virtual error flush() = 0;
-/*-----------------------------------------------------------------------------
- osd_fflus: flush file buffers
- Parameters:
+ /*-----------------------------------------------------------------------------
+ osd_file::remove: deletes a file
- file - handle to a file previously opened via osd_open
+ Parameters:
- Return value:
+ filename - path to file to delete
- a file_error describing any error that occurred while writing to
- the file, or FILERR_NONE if no error occurred
------------------------------------------------------------------------------*/
-file_error osd_fflush(osd_file *file);
-
-
-/*-----------------------------------------------------------------------------
- osd_rmfile: deletes a file
-
- Parameters:
-
- filename - path to file to delete
+ Return value:
- Return value:
+ a file_error describing any error that occurred while deleting
+ the file, or FILERR_NONE if no error occurred
+ -----------------------------------------------------------------------------*/
+ static error remove(std::string const &filename);
+};
- a file_error describing any error that occurred while deleting
- the file, or FILERR_NONE if no error occurred
------------------------------------------------------------------------------*/
-file_error osd_rmfile(const char *filename);
/*-----------------------------------------------------------------------------
@@ -383,7 +379,7 @@ void osd_closedir(osd_directory *dir);
non-zero if the path is absolute, zero otherwise
-----------------------------------------------------------------------------*/
-int osd_is_absolute_path(const char *path);
+bool osd_is_absolute_path(const std::string &path);
@@ -812,7 +808,7 @@ char *osd_get_clipboard_text(void);
free with osd_free()
-----------------------------------------------------------------------------*/
-osd_directory_entry *osd_stat(const char *path);
+osd_directory_entry *osd_stat(std::string const &path);
/***************************************************************************
PATH INTERFACES
@@ -824,14 +820,14 @@ osd_directory_entry *osd_stat(const char *path);
Parameters:
path - the path in question
- dst - pointer to receive new path; the returned string needs to be osd_free()-ed!
+ dst - reference to receive new path
Return value:
file error
-----------------------------------------------------------------------------*/
-file_error osd_get_full_path(char **dst, const char *path);
+osd_file::error osd_get_full_path(std::string &dst, std::string const &path);
/***************************************************************************
@@ -882,7 +878,7 @@ const char *osd_get_volume_name(int idx);
src - source string
-----------------------------------------------------------------------------*/
-void osd_subst_env(char **dst, const char *src);
+void osd_subst_env(std::string &dst,std::string const &src);
/* ----- output management ----- */
@@ -933,4 +929,4 @@ void CLIB_DECL osd_printf_debug(const char *format, ...) ATTR_PRINTF(1,2);
#define printf !MUST_USE_osd_printf_*_CALLS_WITHIN_THE_CORE!
*/
-#endif /* __OSDEPEND_H__ */
+#endif // MAME_OSD_OSDCORE_H
diff --git a/src/osd/osdmini/minidir.cpp b/src/osd/osdmini/minidir.cpp
index e061b644cdf..dde1448a694 100644
--- a/src/osd/osdmini/minidir.cpp
+++ b/src/osd/osdmini/minidir.cpp
@@ -42,14 +42,3 @@ void osd_closedir(osd_directory *dir)
// since there are no standard C library routines for walking directories,
// we do nothing
}
-
-
-//============================================================
-// osd_is_absolute_path
-//============================================================
-
-int osd_is_absolute_path(const char *path)
-{
- // assume no for everything
- return FALSE;
-}
diff --git a/src/osd/osdmini/minifile.cpp b/src/osd/osdmini/minifile.cpp
deleted file mode 100644
index b963634da51..00000000000
--- a/src/osd/osdmini/minifile.cpp
+++ /dev/null
@@ -1,238 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Aaron Giles
-//============================================================
-//
-// minifile.c - Minimal core file access functions
-//
-//============================================================
-
-#include "osdcore.h"
-#include <stdlib.h>
-#include <unistd.h>
-
-
-//============================================================
-// osd_open
-//============================================================
-
-file_error osd_open(const char *path, UINT32 openflags, osd_file **file, UINT64 *filesize)
-{
- const char *mode;
- FILE *fileptr;
-
- // based on the flags, choose a mode
- if (openflags & OPEN_FLAG_WRITE)
- {
- if (openflags & OPEN_FLAG_READ)
- mode = (openflags & OPEN_FLAG_CREATE) ? "w+b" : "r+b";
- else
- mode = "wb";
- }
- else if (openflags & OPEN_FLAG_READ)
- mode = "rb";
- else
- return FILERR_INVALID_ACCESS;
-
- // open the file
- fileptr = fopen(path, mode);
- if (fileptr == nullptr)
- return FILERR_NOT_FOUND;
-
- // store the file pointer directly as an osd_file
- *file = (osd_file *)fileptr;
-
- // get the size -- note that most fseek/ftell implementations are limited to 32 bits
- fseek(fileptr, 0, SEEK_END);
- *filesize = ftell(fileptr);
- fseek(fileptr, 0, SEEK_SET);
-
- return FILERR_NONE;
-}
-
-
-//============================================================
-// osd_close
-//============================================================
-
-file_error osd_close(osd_file *file)
-{
- // close the file handle
- fclose((FILE *)file);
- return FILERR_NONE;
-}
-
-
-//============================================================
-// osd_read
-//============================================================
-
-file_error osd_read(osd_file *file, void *buffer, UINT64 offset, UINT32 length, UINT32 *actual)
-{
- size_t count;
-
- // seek to the new location; note that most fseek implementations are limited to 32 bits
- fseek((FILE *)file, offset, SEEK_SET);
-
- // perform the read
- count = fread(buffer, 1, length, (FILE *)file);
- if (actual != nullptr)
- *actual = count;
-
- return FILERR_NONE;
-}
-
-
-//============================================================
-// osd_write
-//============================================================
-
-file_error osd_write(osd_file *file, const void *buffer, UINT64 offset, UINT32 length, UINT32 *actual)
-{
- size_t count;
-
- // seek to the new location; note that most fseek implementations are limited to 32 bits
- fseek((FILE *)file, offset, SEEK_SET);
-
- // perform the write
- count = fwrite(buffer, 1, length, (FILE *)file);
- if (actual != nullptr)
- *actual = count;
-
- return FILERR_NONE;
-}
-
-//============================================================
-// osd_openpty
-//============================================================
-
-file_error osd_openpty(osd_file **file, char *name, size_t name_len)
-{
- return FILERR_FAILURE;
-}
-
-//============================================================
-// osd_truncate
-//============================================================
-
-file_error osd_truncate(osd_file *file, UINT64 offset)
-{
- UINT32 result;
-
- if (!file)
- return FILERR_FAILURE;
-
- result = ftruncate(fileno((FILE *)file), offset);
- if (result)
- return FILERR_FAILURE;
-
- return FILERR_NONE;
-}
-
-//============================================================
-// osd_fflush
-//============================================================
-
-file_error osd_fflush(osd_file *file)
-{
- if (!file)
- return FILERR_FAILURE;
-
- int result = fflush((FILE *)file);
- if (result == EOF)
- return FILERR_FAILURE;
-
- return FILERR_NONE;
-}
-
-
-//============================================================
-// osd_rmfile
-//============================================================
-
-file_error osd_rmfile(const char *filename)
-{
- return remove(filename) ? FILERR_FAILURE : FILERR_NONE;
-}
-
-
-//============================================================
-// osd_get_physical_drive_geometry
-//============================================================
-
-int osd_get_physical_drive_geometry(const char *filename, UINT32 *cylinders, UINT32 *heads, UINT32 *sectors, UINT32 *bps)
-{
- // there is no standard way of doing this, so we always return FALSE, indicating
- // that a given path is not a physical drive
- return FALSE;
-}
-
-
-//============================================================
-// osd_uchar_from_osdchar
-//============================================================
-
-int osd_uchar_from_osdchar(UINT32 /* unicode_char */ *uchar, const char *osdchar, size_t count)
-{
- // we assume a standard 1:1 mapping of characters to the first 256 unicode characters
- *uchar = (UINT8)*osdchar;
- return 1;
-}
-
-
-//============================================================
-// osd_stat
-//============================================================
-
-osd_directory_entry *osd_stat(const char *path)
-{
- osd_directory_entry *result = nullptr;
-
- // create an osd_directory_entry; be sure to make sure that the caller can
- // free all resources by just freeing the resulting osd_directory_entry
- result = (osd_directory_entry *)osd_malloc_array(sizeof(*result) + strlen(path) + 1);
- strcpy((char *)(result + 1), path);
- result->name = (char *)(result + 1);
- result->type = ENTTYPE_NONE;
- result->size = 0;
-
- FILE *f = fopen(path, "rb");
- if (f != nullptr)
- {
- fseek(f, 0, SEEK_END);
- result->type = ENTTYPE_FILE;
- result->size = ftell(f);
- fclose(f);
- }
- return result;
-}
-
-
-//============================================================
-// osd_get_full_path
-//============================================================
-
-file_error osd_get_full_path(char **dst, const char *path)
-{
- // derive the full path of the file in an allocated string
- // for now just fake it since we don't presume any underlying file system
- *dst = nullptr;
- if (path != nullptr)
- {
- *dst = (char *)osd_malloc_array(strlen(path) + 1);
- if (*dst != nullptr)
- strcpy(*dst, path);
- }
-
- return FILERR_NONE;
-}
-
-
-//============================================================
-// osd_get_volume_name
-//============================================================
-
-const char *osd_get_volume_name(int idx)
-{
- // we don't expose volumes
- return nullptr;
-}
diff --git a/src/osd/osdmini/minimisc.cpp b/src/osd/osdmini/minimisc.cpp
index 9891447359b..fb4901ca461 100644
--- a/src/osd/osdmini/minimisc.cpp
+++ b/src/osd/osdmini/minimisc.cpp
@@ -103,9 +103,7 @@ int osd_setenv(const char *name, const char *value, int overwrite)
//============================================================
// osd_subst_env
//============================================================
-void osd_subst_env(char **dst, const char *src)
+void osd_subst_env(std::string &dst, const std::string &src)
{
- *dst = (char *)osd_malloc_array(strlen(src) + 1);
- if (*dst != nullptr)
- strcpy(*dst, src);
+ dst = src;
}
diff --git a/src/osd/sdl/sdldir.cpp b/src/osd/sdl/sdldir.cpp
index 3d5071171d8..439eb0a9792 100644
--- a/src/osd/sdl/sdldir.cpp
+++ b/src/osd/sdl/sdldir.cpp
@@ -26,6 +26,10 @@
#define _XOPEN_SOURCE 500
#endif
+#include <cctype>
+#include <cstdlib>
+#include <utility>
+
//#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
@@ -234,4 +238,79 @@ void osd_closedir(osd_directory *dir)
}
+//============================================================
+// osd_subst_env
+//============================================================
+
+void osd_subst_env(std::string &dst, std::string const &src)
+{
+ std::string result, var;
+ auto start = src.begin();
+
+ // a leading tilde expands as $HOME
+ if ((src.end() != start) && ('~' == *start))
+ {
+ char const *const home = std::getenv("HOME");
+ if (home)
+ {
+ ++start;
+ if ((src.end() == start) || (PATHSEPCH == *start))
+ result.append(home);
+ else
+ result.push_back('~');
+ }
+ }
+
+ while (src.end() != start)
+ {
+ // find $ marking start of environment variable or end of string
+ auto it = start;
+ while ((src.end() != it) && ('$' != *it)) ++it;
+ if (start != it) result.append(start, it);
+ start = it;
+
+ if (src.end() != start)
+ {
+ start = ++it;
+ if ((src.end() != start) && ('{' == *start))
+ {
+ start = ++it;
+ for (++it; (src.end() != it) && ('}' != *it); ++it) { }
+ if (src.end() == it)
+ {
+ result.append("${").append(start, it);
+ start = it;
+ }
+ else
+ {
+ var.assign(start, it);
+ start = ++it;
+ const char *const exp = std::getenv(var.c_str());
+ if (exp)
+ result.append(exp);
+ else
+ fprintf(stderr, "Warning: osd_subst_env variable %s not found.\n", var.c_str());
+ }
+ }
+ else if ((src.end() != start) && (('_' == *start) || std::isalnum(*start)))
+ {
+ for (++it; (src.end() != it) && (('_' == *it) || std::isalnum(*it)); ++it) { }
+ var.assign(start, it);
+ start = it;
+ const char *const exp = std::getenv(var.c_str());
+ if (exp)
+ result.append(exp);
+ else
+ fprintf(stderr, "Warning: osd_subst_env variable %s not found.\n", var.c_str());
+ }
+ else
+ {
+ result.push_back('$');
+ }
+ }
+ }
+
+ dst = std::move(result);
+}
+
#endif
diff --git a/src/osd/sdl/sdlfile.cpp b/src/osd/sdl/sdlfile.cpp
deleted file mode 100644
index aa57e3356a0..00000000000
--- a/src/osd/sdl/sdlfile.cpp
+++ /dev/null
@@ -1,630 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Olivier Galibert, R. Belmont
-//============================================================
-//
-// sdlfile.c - SDL file access functions
-//
-// SDLMAME by Olivier Galibert and R. Belmont
-//
-//============================================================
-
-#ifdef SDLMAME_WIN32
-#include "../windows/winfile.cpp"
-#include "../windows/winutil.cpp"
-#else
-
-#ifndef _LARGEFILE64_SOURCE
-#define _LARGEFILE64_SOURCE
-#endif
-
-#ifdef SDLMAME_LINUX
-#define __USE_LARGEFILE64
-#endif
-
-#ifdef SDLMAME_WIN32
-#define _FILE_OFFSET_BITS 64
-#endif
-
-#ifndef SDLMAME_BSD
-#ifdef _XOPEN_SOURCE
-#undef _XOPEN_SOURCE
-#endif
-#define _XOPEN_SOURCE 500
-#endif
-
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <stdio.h>
-#include <errno.h>
-
-// MAME headers
-#include "sdlfile.h"
-#include "modules/lib/osdlib.h"
-
-//============================================================
-// GLOBAL IDENTIFIERS
-//============================================================
-
-extern const char *sdlfile_socket_identifier;
-extern const char *sdlfile_ptty_identifier;
-
-//============================================================
-// CONSTANTS
-//============================================================
-
-#if defined(SDLMAME_WIN32)
-#define PATHSEPCH '\\'
-#define INVPATHSEPCH '/'
-#else
-#define PATHSEPCH '/'
-#define INVPATHSEPCH '\\'
-#endif
-
-#define NO_ERROR (0)
-
-//============================================================
-// Prototypes
-//============================================================
-
-static UINT32 create_path_recursive(char *path);
-
-//============================================================
-// error_to_file_error
-// (does filling this out on non-Windows make any sense?)
-//============================================================
-
-file_error error_to_file_error(UINT32 error)
-{
- switch (error)
- {
- case ENOENT:
- case ENOTDIR:
- return FILERR_NOT_FOUND;
-
- case EACCES:
- case EROFS:
- #ifndef SDLMAME_WIN32
- case ETXTBSY:
- #endif
- case EEXIST:
- case EPERM:
- case EISDIR:
- case EINVAL:
- return FILERR_ACCESS_DENIED;
-
- case ENFILE:
- case EMFILE:
- return FILERR_TOO_MANY_FILES;
-
- default:
- return FILERR_FAILURE;
- }
-}
-
-
-//============================================================
-// osd_open
-//============================================================
-
-file_error osd_open(const char *path, UINT32 openflags, osd_file **file, UINT64 *filesize)
-{
- UINT32 access;
- const char *src;
- char *dst;
- #if defined(SDLMAME_DARWIN) || defined(SDLMAME_WIN32) || defined(SDLMAME_NO64BITIO) || defined(SDLMAME_BSD) || defined(SDLMAME_HAIKU)
- struct stat st;
- #else
- struct stat64 st;
- #endif
- char *tmpstr;
- file_error filerr = FILERR_NONE;
-
- tmpstr = NULL;
-
- // allocate a file object, plus space for the converted filename
- *file = (osd_file *) osd_malloc_array(sizeof(**file) + sizeof(char) * strlen(path));
- if (*file == NULL)
- {
- filerr = FILERR_OUT_OF_MEMORY;
- goto error;
- }
-
- if (sdl_check_socket_path(path))
- {
- (*file)->type = SDLFILE_SOCKET;
- filerr = sdl_open_socket(path, openflags, file, filesize);
- if(filerr != FILERR_NONE && (*file)->socket != -1)
- close((*file)->socket);
- goto error;
- }
-
- if (strlen(sdlfile_ptty_identifier) > 0 && strncmp(path, sdlfile_ptty_identifier, strlen(sdlfile_ptty_identifier)) == 0)
- {
- (*file)->type = SDLFILE_PTTY;
- filerr = sdl_open_ptty(path, openflags, file, filesize);
- goto error;
- }
-
- (*file)->type = SDLFILE_FILE;
-
- // convert the path into something compatible
- dst = (*file)->filename;
- for (src = path; *src != 0; src++)
- *dst++ = (*src == INVPATHSEPCH) ? PATHSEPCH : *src;
- *dst++ = 0;
-
- // select the file open modes
- if (openflags & OPEN_FLAG_WRITE)
- {
- access = (openflags & OPEN_FLAG_READ) ? O_RDWR : O_WRONLY;
- access |= (openflags & OPEN_FLAG_CREATE) ? (O_CREAT | O_TRUNC) : 0;
- }
- else if (openflags & OPEN_FLAG_READ)
- {
- access = O_RDONLY;
- }
- else
- {
- filerr = FILERR_INVALID_ACCESS;
- goto error;
- }
-
- osd_subst_env(&tmpstr, (*file)->filename);
-
- #if defined(SDLMAME_WIN32)
- access |= O_BINARY;
- #endif
-
- // attempt to open the file
- #if defined(SDLMAME_DARWIN) || defined(SDLMAME_WIN32) || defined(SDLMAME_NO64BITIO) || defined(SDLMAME_BSD) || defined(SDLMAME_HAIKU)
- (*file)->handle = open(tmpstr, access, 0666);
- #else
- (*file)->handle = open64(tmpstr, access, 0666);
- #endif
- if ((*file)->handle == -1)
- {
- // create the path if necessary
- if ((openflags & OPEN_FLAG_CREATE) && (openflags & OPEN_FLAG_CREATE_PATHS))
- {
- char *pathsep = strrchr(tmpstr, PATHSEPCH);
- if (pathsep != NULL)
- {
- int error;
-
- // create the path up to the file
- *pathsep = 0;
- error = create_path_recursive(tmpstr);
- *pathsep = PATHSEPCH;
-
- // attempt to reopen the file
- if (error == NO_ERROR)
- {
- #if defined(SDLMAME_DARWIN) || defined(SDLMAME_WIN32) || defined(SDLMAME_NO64BITIO) || defined(SDLMAME_BSD) || defined(SDLMAME_HAIKU)
- (*file)->handle = open(tmpstr, access, 0666);
- #else
- (*file)->handle = open64(tmpstr, access, 0666);
- #endif
- }
- }
- }
-
- // if we still failed, clean up and osd_free
- if ((*file)->handle == -1)
- {
- osd_free(*file);
- *file = NULL;
- osd_free(tmpstr);
- return error_to_file_error(errno);
- }
- }
-
- // get the file size
- #if defined(SDLMAME_DARWIN) || defined(SDLMAME_WIN32) || defined(SDLMAME_NO64BITIO) || defined(SDLMAME_BSD) || defined(SDLMAME_HAIKU)
- fstat((*file)->handle, &st);
- #else
- fstat64((*file)->handle, &st);
- #endif
-
- *filesize = (UINT64)st.st_size;
-
-error:
- // cleanup
- if (filerr != FILERR_NONE && *file != NULL)
- {
- osd_free(*file);
- *file = NULL;
- }
- if (tmpstr)
- osd_free(tmpstr);
- return filerr;
-}
-
-
-//============================================================
-// osd_read
-//============================================================
-
-file_error osd_read(osd_file *file, void *buffer, UINT64 offset, UINT32 count, UINT32 *actual)
-{
- ssize_t result;
-
- switch (file->type)
- {
- case SDLFILE_FILE:
-#if defined(SDLMAME_DARWIN) || defined(SDLMAME_BSD) || defined(SDLMAME_EMSCRIPTEN)
- result = pread(file->handle, buffer, count, offset);
- if (result < 0)
-#elif defined(SDLMAME_WIN32) || defined(SDLMAME_NO64BITIO)
- lseek(file->handle, (UINT32)offset&0xffffffff, SEEK_SET);
- result = read(file->handle, buffer, count);
- if (result < 0)
-#elif defined(SDLMAME_UNIX)
- result = pread64(file->handle, buffer, count, offset);
- if (result < 0)
-#else
-#error Unknown SDL SUBARCH!
-#endif
- return error_to_file_error(errno);
-
- if (actual != NULL)
- *actual = result;
-
- return FILERR_NONE;
-
- case SDLFILE_SOCKET:
- return sdl_read_socket(file, buffer, offset, count, actual);
-
- case SDLFILE_PTTY:
- return sdl_read_ptty(file, buffer, offset, count, actual);
-
- default:
- return FILERR_FAILURE;
- }
-}
-
-
-//============================================================
-// osd_write
-//============================================================
-
-file_error osd_write(osd_file *file, const void *buffer, UINT64 offset, UINT32 count, UINT32 *actual)
-{
- UINT32 result;
-
- switch (file->type)
- {
- case SDLFILE_FILE:
-#if defined(SDLMAME_DARWIN) || defined(SDLMAME_BSD) || defined(SDLMAME_EMSCRIPTEN)
- result = pwrite(file->handle, buffer, count, offset);
- if (!result)
-#elif defined(SDLMAME_WIN32) || defined(SDLMAME_NO64BITIO)
- lseek(file->handle, (UINT32)offset&0xffffffff, SEEK_SET);
- result = write(file->handle, buffer, count);
- if (!result)
-#elif defined(SDLMAME_UNIX)
- result = pwrite64(file->handle, buffer, count, offset);
- if (!result)
-#else
-#error Unknown SDL SUBARCH!
-#endif
- return error_to_file_error(errno);
-
- if (actual != NULL)
- *actual = result;
- return FILERR_NONE;
-
- case SDLFILE_SOCKET:
- return sdl_write_socket(file, buffer, offset, count, actual);
-
- case SDLFILE_PTTY:
- return sdl_write_ptty(file, buffer, offset, count, actual);
-
- default:
- return FILERR_FAILURE;
- }
-}
-
-//============================================================
-// osd_openpty
-//============================================================
-
-file_error osd_openpty(osd_file **file, char *name, size_t name_len)
-{
- file_error res;
- UINT64 filesize;
-
- if ((res = osd_open(sdlfile_ptty_identifier , 0 , file , &filesize)) != FILERR_NONE) {
- return res;
- }
-
- if ((res = sdl_slave_name_ptty(*file , name , name_len)) != FILERR_NONE) {
- osd_close(*file);
- }
-
- return res;
-}
-
-//============================================================
-// osd_truncate
-//============================================================
-
-file_error osd_truncate(osd_file *file, UINT64 offset)
-{
- UINT32 result;
-
- if (!file || !file->handle)
- return FILERR_FAILURE;
-
- switch (file->type)
- {
- case SDLFILE_FILE:
- result = ftruncate(file->handle, offset);
- if (result)
- return error_to_file_error(errno);
- return FILERR_NONE;
-
- default:
- return FILERR_FAILURE;
- }
-}
-
-//============================================================
-// osd_truncate
-//============================================================
-
-file_error osd_fflush(osd_file *file)
-{
- if (!file || !file->handle)
- return FILERR_FAILURE;
-
- switch (file->type)
- {
- case SDLFILE_FILE:
- return FILERR_NONE;
-
- default:
- return FILERR_FAILURE;
- }
-}
-
-
-//============================================================
-// osd_close
-//============================================================
-
-file_error osd_close(osd_file *file)
-{
- // close the file handle and free the file structure
- switch (file->type)
- {
- case SDLFILE_FILE:
- close(file->handle);
- osd_free(file);
- return FILERR_NONE;
-
- case SDLFILE_SOCKET:
- return sdl_close_socket(file);
-
- case SDLFILE_PTTY:
- return sdl_close_ptty(file);
-
- default:
- return FILERR_FAILURE;
- }
-}
-
-//============================================================
-// osd_rmfile
-//============================================================
-
-file_error osd_rmfile(const char *filename)
-{
- if (unlink(filename) == -1)
- {
- return error_to_file_error(errno);
- }
-
- return FILERR_NONE;
-}
-
-//============================================================
-// create_path_recursive
-//============================================================
-
-static UINT32 create_path_recursive(char *path)
-{
- char *sep = strrchr(path, PATHSEPCH);
- UINT32 filerr;
- struct stat st;
-
- // if there's still a separator, and it's not the root, nuke it and recurse
- if (sep != NULL && sep > path && sep[0] != ':' && sep[-1] != PATHSEPCH)
- {
- *sep = 0;
- filerr = create_path_recursive(path);
- *sep = PATHSEPCH;
- if (filerr != NO_ERROR)
- return filerr;
- }
-
- // if the path already exists, we're done
- if (!stat(path, &st))
- return NO_ERROR;
-
- // create the path
- #ifdef SDLMAME_WIN32
- if (mkdir(path) != 0)
- #else
- if (mkdir(path, 0777) != 0)
- #endif
- return error_to_file_error(errno);
- return NO_ERROR;
-}
-
-//============================================================
-// osd_get_physical_drive_geometry
-//============================================================
-
-int osd_get_physical_drive_geometry(const char *filename, UINT32 *cylinders, UINT32 *heads, UINT32 *sectors, UINT32 *bps)
-{
- return FALSE; // no, no way, huh-uh, forget it
-}
-
-//============================================================
-// osd_is_path_separator
-//============================================================
-
-static int osd_is_path_separator(char c)
-{
- return (c == PATHSEPCH) || (c == INVPATHSEPCH);
-}
-
-//============================================================
-// osd_is_absolute_path
-//============================================================
-
-int osd_is_absolute_path(const char *path)
-{
- int result;
-
- if (osd_is_path_separator(path[0]))
- result = TRUE;
-#if !defined(SDLMAME_WIN32)
- else if (path[0] == '.')
- result = TRUE;
-#else
- #ifndef UNDER_CE
- else if (*path && path[1] == ':')
- result = TRUE;
- #endif
-#endif
- else
- result = FALSE;
-
- return result;
-}
-
-//============================================================
-// osd_stat
-//============================================================
-
-osd_directory_entry *osd_stat(const char *path)
-{
- int err;
- osd_directory_entry *result = NULL;
- #if defined(SDLMAME_NO64BITIO) || defined(SDLMAME_BSD) || defined(SDLMAME_DARWIN)
- struct stat st;
- #else
- struct stat64 st;
- #endif
-
- #if defined(SDLMAME_NO64BITIO) || defined(SDLMAME_BSD) || defined(SDLMAME_DARWIN)
- err = stat(path, &st);
- #else
- err = stat64(path, &st);
- #endif
-
- if( err == -1) return NULL;
-
- // create an osd_directory_entry; be sure to make sure that the caller can
- // free all resources by just freeing the resulting osd_directory_entry
- result = (osd_directory_entry *) osd_malloc_array(sizeof(*result) + strlen(path) + 1);
- strcpy(((char *) result) + sizeof(*result), path);
- result->name = ((char *) result) + sizeof(*result);
- result->type = S_ISDIR(st.st_mode) ? ENTTYPE_DIR : ENTTYPE_FILE;
- result->size = (UINT64)st.st_size;
-
- return result;
-}
-
-//============================================================
-// osd_get_full_path
-//============================================================
-
-file_error osd_get_full_path(char **dst, const char *path)
-{
- file_error err;
- char path_buffer[512];
-
- err = FILERR_NONE;
-
- if (getcwd(path_buffer, 511) == NULL)
- {
- printf("osd_get_full_path: failed!\n");
- err = FILERR_FAILURE;
- }
- else
- {
- *dst = (char *)osd_malloc_array(strlen(path_buffer)+strlen(path)+3);
-
- // if it's already a full path, just pass it through
- if (path[0] == '/')
- {
- strcpy(*dst, path);
- }
- else
- {
- sprintf(*dst, "%s%s%s", path_buffer, PATH_SEPARATOR, path);
- }
- }
-
- return err;
-}
-
-//============================================================
-// osd_get_volume_name
-//============================================================
-
-const char *osd_get_volume_name(int idx)
-{
- if (idx!=0) return NULL;
- return "/";
-}
-
-//============================================================
-// osd_subst_env
-//============================================================
-void osd_subst_env(char **dst, const char *src)
-{
- int i, j;
- char *envstr;
-
- osd_free(*dst);
- *dst = (char *) osd_malloc_array(strlen(src)+1);
- strcpy(*dst, src);
-
- // start with an environment variable?
- if (*dst[0] == '$')
- {
- envstr = (char *) osd_malloc_array(strlen(src)+1);
- strcpy(envstr, src);
-
- i = 0;
- while (!osd_is_path_separator(envstr[i]) && envstr[i] != 0 && envstr[i] != '.')
- {
- i++;
- }
-
- envstr[i] = '\0';
-
- const char *envval = osd_getenv(&envstr[1]);
- if (envval != NULL)
- {
- j = strlen(envval) + strlen(*dst) + 1;
- osd_free(*dst);
- *dst = (char *) osd_malloc_array(j);
-
- // start with the value of $HOME
- strcpy(*dst, envval);
- // replace the null with a path separator again
- envstr[i] = PATHSEPCH;
- // append it
- strcat(*dst, &envstr[i]);
- }
- else
- fprintf(stderr, "Warning: osd_subst_env variable %s not found.\n", envstr);
- osd_free(envstr);
- }
-}
-#endif
diff --git a/src/osd/sdl/sdlfile.h b/src/osd/sdl/sdlfile.h
deleted file mode 100644
index 4bd1b2a6292..00000000000
--- a/src/osd/sdl/sdlfile.h
+++ /dev/null
@@ -1,51 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Olivier Galibert, R. Belmont
-//============================================================
-//
-// sdlfile.h - SDL file access functions
-//
-// SDLMAME by Olivier Galibert and R. Belmont
-//
-//============================================================
-
-#include "osdcore.h"
-
-//============================================================
-// ENUM DEFINITIONS
-//============================================================
-enum
-{
- SDLFILE_FILE = 0,
- SDLFILE_SOCKET,
- SDLFILE_PTTY
-};
-
-//============================================================
-// TYPE DEFINITIONS
-//============================================================
-
-struct osd_file
-{
- int handle;
- int socket;
- int type;
- char filename[1];
-};
-
-//============================================================
-// PROTOTYPES
-//============================================================
-
-bool sdl_check_socket_path(const char *path);
-file_error sdl_open_socket(const char *path, UINT32 openflags, osd_file **file, UINT64 *filesize);
-file_error sdl_read_socket(osd_file *file, void *buffer, UINT64 offset, UINT32 count, UINT32 *actual);
-file_error sdl_write_socket(osd_file *file, const void *buffer, UINT64 offset, UINT32 count, UINT32 *actual);
-file_error sdl_close_socket(osd_file *file);
-
-file_error sdl_open_ptty(const char *path, UINT32 openflags, osd_file **file, UINT64 *filesize);
-file_error sdl_read_ptty(osd_file *file, void *buffer, UINT64 offset, UINT32 count, UINT32 *actual);
-file_error sdl_write_ptty(osd_file *file, const void *buffer, UINT64 offset, UINT32 count, UINT32 *actual);
-file_error sdl_close_ptty(osd_file *file);
-file_error sdl_slave_name_ptty(osd_file *file , char *name , size_t name_len);
-
-file_error error_to_file_error(UINT32 error);
diff --git a/src/osd/sdl/sdlptty_unix.cpp b/src/osd/sdl/sdlptty_unix.cpp
deleted file mode 100644
index 063b999b75d..00000000000
--- a/src/osd/sdl/sdlptty_unix.cpp
+++ /dev/null
@@ -1,161 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Olivier Galibert, R. Belmont
-//============================================================
-//
-// sdlptty_unix.c - SDL pseudo tty access functions
-//
-// SDLMAME by Olivier Galibert and R. Belmont
-//
-//============================================================
-
-#if (!defined(SDLMAME_SOLARIS))
-
-#include <sys/types.h>
-#include <sys/uio.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <errno.h>
-#if defined(SDLMAME_FREEBSD) || defined(SDLMAME_DRAGONFLY)
-# include <termios.h>
-# include <libutil.h>
-#elif defined(SDLMAME_NETBSD) || defined(SDLMAME_MACOSX)
-# include <termios.h>
-# include <util.h>
-#elif defined(SDLMAME_OPENBSD)
-# include <termios.h>
-# include <util.h>
-#elif defined(SDLMAME_LINUX) || defined(SDLMAME_EMSCRIPTEN)
-# include <pty.h>
-#elif defined(SDLMAME_HAIKU)
-# include <bsd/pty.h>
-#endif
-#include <stdlib.h>
-
-#include "sdlfile.h"
-
-#if defined(SDLMAME_MACOSX)
-const char *sdlfile_ptty_identifier = "/dev/pty";
-#else
-const char *sdlfile_ptty_identifier = "/dev/pts";
-#endif
-
-file_error sdl_open_ptty(const char *path, UINT32 openflags, osd_file **file, UINT64 *filesize)
-{
- int master;
- int aslave;
- struct termios tios;
- int oldflags;
-
- memset(&tios , 0 , sizeof(tios));
- cfmakeraw(&tios);
-
- if (openpty(&master, &aslave, NULL, &tios, NULL) >= 0)
- {
- oldflags = fcntl(master, F_GETFL, 0);
- if (oldflags == -1) {
- close(master);
- return FILERR_FAILURE;
- }
-
- fcntl(master, F_SETFL, oldflags | O_NONBLOCK);
- close(aslave);
- (*file)->handle = master;
- *filesize = 0;
- }
- else
- {
- return FILERR_ACCESS_DENIED;
- }
-
- return FILERR_NONE;
-}
-
-file_error sdl_read_ptty(osd_file *file, void *buffer, UINT64 offset, UINT32 count, UINT32 *actual)
-{
- ssize_t result;
-
- result = read(file->handle, buffer, count);
-
- if (result < 0)
- {
- return error_to_file_error(errno);
- }
-
- if (actual != NULL )
- {
- *actual = result;
- }
-
- return FILERR_NONE;
-}
-
-file_error sdl_write_ptty(osd_file *file, const void *buffer, UINT64 offset, UINT32 count, UINT32 *actual)
-{
- ssize_t result;
- result = write(file->handle, buffer, count);
-
- if (result < 0)
- {
- return error_to_file_error(errno);
- }
-
- if (actual != NULL )
- {
- *actual = result;
- }
-
- return FILERR_NONE;
-}
-
-file_error sdl_close_ptty(osd_file *file)
-{
- close(file->handle);
- osd_free(file);
-
- return FILERR_NONE;
-}
-
-file_error sdl_slave_name_ptty(osd_file *file , char *name , size_t name_len)
-{
- const char *slave_name = ptsname(file->handle);
-
- if (slave_name == NULL || strlen(slave_name) >= name_len) {
- return FILERR_INVALID_ACCESS;
- }
-
- strcpy(name , slave_name);
-
- return FILERR_NONE;
-}
-
-#else
-#include "sdlfile.h"
-
-const char *sdlfile_ptty_identifier = "";
-
-file_error sdl_open_ptty(const char *path, UINT32 openflags, osd_file **file, UINT64 *filesize)
-{
- return FILERR_ACCESS_DENIED;
-}
-
-file_error sdl_read_ptty(osd_file *file, void *buffer, UINT64 offset, UINT32 count, UINT32 *actual)
-{
- return FILERR_ACCESS_DENIED;
-}
-
-file_error sdl_write_ptty(osd_file *file, const void *buffer, UINT64 offset, UINT32 count, UINT32 *actual)
-{
- return FILERR_ACCESS_DENIED;
-}
-
-file_error sdl_close_ptty(osd_file *file)
-{
- return FILERR_ACCESS_DENIED;
-}
-
-file_error sdl_slave_name_ptty(osd_file *file)
-{
- return FILERR_ACCESS_DENIED;
-}
-
-#endif
diff --git a/src/osd/sdl/sdlptty_win32.cpp b/src/osd/sdl/sdlptty_win32.cpp
deleted file mode 100644
index fca49a12a99..00000000000
--- a/src/osd/sdl/sdlptty_win32.cpp
+++ /dev/null
@@ -1,12 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Olivier Galibert, R. Belmont
-//============================================================
-//
-// sdlptty_win32 - SDL psuedo tty access functions
-// (passthrough to Windows OSD version)
-//
-// SDLMAME by Olivier Galibert and R. Belmont
-//
-//============================================================
-
-#include "../windows/winptty.cpp"
diff --git a/src/osd/sdl/sdlsocket.cpp b/src/osd/sdl/sdlsocket.cpp
deleted file mode 100644
index 5d3e7030deb..00000000000
--- a/src/osd/sdl/sdlsocket.cpp
+++ /dev/null
@@ -1,193 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Olivier Galibert, R. Belmont
-//============================================================
-//
-// sdlsocket.c - SDL socket (inet) access functions
-//
-// SDLMAME by Olivier Galibert and R. Belmont
-//
-//============================================================
-
-#ifdef SDLMAME_WIN32
-#include "../windows/winsocket.cpp"
-#else
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <sys/select.h>
-#include <netinet/in.h>
-#include <netinet/tcp.h>
-#include <sys/socket.h>
-#include <sys/types.h>
-#include <netdb.h>
-#include <errno.h>
-
-#include "emu.h"
-#include "sdlfile.h"
-
-const char *sdlfile_socket_identifier = "socket.";
-
-/*
- Checks whether the path is a socket specification. A valid socket
- specification has the format "socket." host ":" port. Host may be simple
- or fully qualified. Port must be between 1 and 65535.
-*/
-bool sdl_check_socket_path(const char *path)
-{
- if (strlen(sdlfile_socket_identifier) > 0 &&
- strncmp(path, sdlfile_socket_identifier, strlen(sdlfile_socket_identifier)) == 0 &&
- strchr(path, ':') != NULL) return true;
- return false;
-}
-
-file_error sdl_open_socket(const char *path, UINT32 openflags, osd_file **file, UINT64 *filesize)
-{
- char hostname[256];
- struct hostent *localhost;
- struct sockaddr_in sai;
- int flag = 1;
- int port;
-
- sscanf( path+strlen(sdlfile_socket_identifier), "%255[^:]:%d", hostname, &port );
-
-// printf("Connecting to server '%s' on port '%d'\n", hostname, port);
-
- if (((*file)->socket = socket(AF_INET, SOCK_STREAM, 0)) == -1)
- {
- return FILERR_ACCESS_DENIED;
- }
-
- if (setsockopt((*file)->socket, IPPROTO_TCP, TCP_NODELAY, (char *)&flag, sizeof(flag)) == -1)
- {
- return FILERR_ACCESS_DENIED;
- }
-
- localhost = gethostbyname(hostname);
-
- memset(&sai, 0, sizeof(sai));
- sai.sin_family = AF_INET;
- sai.sin_port = htons(port);
- sai.sin_addr = *((struct in_addr *)localhost->h_addr);
-
- // listening socket support
- if (openflags & OPEN_FLAG_CREATE)
- {
-// printf("Listening for client at '%s' on port '%d'\n", hostname, port);
- // bind socket...
- if (bind((*file)->socket, (struct sockaddr *)&sai, sizeof(struct sockaddr)) == -1)
- {
- return FILERR_ACCESS_DENIED;
- }
-
- // start to listen...
- if (listen((*file)->socket, 1) == -1) {
- return FILERR_ACCESS_DENIED;
- }
-
- // mark socket as "listening"
- (*file)->handle = 0;
- *filesize = 0;
- return FILERR_NONE;
- }
-
-// printf("Connecting to server '%s' on port '%d'\n", hostname, port);
- if (connect((*file)->socket, (struct sockaddr *)&sai, sizeof(struct sockaddr)) == -1)
- {
- return FILERR_ACCESS_DENIED;
- }
-
- *filesize = 0;
- (*file)->handle = -1;
- return FILERR_NONE;
-}
-
-file_error sdl_read_socket(osd_file *file, void *buffer, UINT64 offset, UINT32 count, UINT32 *actual)
-{
-#if (!defined(SDLMAME_EMSCRIPTEN))
- ssize_t result;
- char line[80];
- struct timeval timeout;
- fd_set readfds;
-
- FD_ZERO(&readfds);
- FD_SET(file->socket, &readfds);
- timeout.tv_sec = timeout.tv_usec = 0;
-
- if (select(file->socket + 1, &readfds, NULL, NULL, &timeout) < 0)
- {
- sprintf(line, "%s : %s : %d ", __func__, __FILE__, __LINE__);
- perror(line);
- return error_to_file_error(errno);
- }
- else if (FD_ISSET(file->socket, &readfds))
- {
- if (file->handle == -1)
- {
- // connected socket
- result = read(file->socket, buffer, count);
- }
- else
- {
- // listening socket
- int AcceptSocket;
- AcceptSocket = accept(file->socket, NULL, NULL);
- if (AcceptSocket < 0)
- {
- return FILERR_FAILURE;
- }
- close(file->socket);
- file->socket = AcceptSocket;
- file->handle = -1;
- if (actual != NULL )
- {
- *actual = 0;
- }
-
- return FILERR_NONE;
- }
- }
- else
- {
- return FILERR_FAILURE;
- }
-
- if (result < 0)
- {
- return error_to_file_error(errno);
- }
-
- if (actual != NULL )
- {
- *actual = result;
- }
-#endif
- return FILERR_NONE;
-}
-
-file_error sdl_write_socket(osd_file *file, const void *buffer, UINT64 offset, UINT32 count, UINT32 *actual)
-{
- ssize_t result;
-
- result = write(file->socket, buffer, count);
-
- if (result < 0)
- {
- return error_to_file_error(errno);
- }
-
- if (actual != NULL )
- {
- *actual = result;
- }
- return FILERR_NONE;
-}
-
-file_error sdl_close_socket(osd_file *file)
-{
- close(file->socket);
- osd_free(file);
- return FILERR_NONE;
-}
-#endif
diff --git a/src/osd/windows/windir.cpp b/src/osd/windows/windir.cpp
index 7f172d7338a..edbe688ffe9 100644
--- a/src/osd/windows/windir.cpp
+++ b/src/osd/windows/windir.cpp
@@ -134,20 +134,3 @@ void osd_closedir(osd_directory *dir)
FindClose(dir->find);
free(dir);
}
-
-
-//============================================================
-// osd_is_absolute_path
-//============================================================
-
-int osd_is_absolute_path(const char *path)
-{
- int result = FALSE;
- TCHAR *t_path = tstring_from_utf8(path);
- if (t_path != NULL)
- {
- result = !PathIsRelative(t_path);
- osd_free(t_path);
- }
- return result;
-}
diff --git a/src/osd/windows/winfile.cpp b/src/osd/windows/winfile.cpp
deleted file mode 100644
index 742f97363d6..00000000000
--- a/src/osd/windows/winfile.cpp
+++ /dev/null
@@ -1,571 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Aaron Giles
-//============================================================
-//
-// winfile.c - Win32 OSD core file access functions
-//
-//============================================================
-
-// standard windows headers
-#define WIN32_LEAN_AND_MEAN
-#include <windows.h>
-#include <winioctl.h>
-#include <tchar.h>
-#include <stdlib.h>
-#include <ctype.h>
-
-// MAME headers
-#include "osdcore.h"
-
-// MAMEOS headers
-#include "strconv.h"
-#include "winutil.h"
-#include "winutf8.h"
-
-#include "winfile.h"
-
-//============================================================
-// FUNCTION PROTOTYPES
-//============================================================
-
-static DWORD create_path_recursive(const TCHAR *path);
-
-//============================================================
-// INLINE FUNCTIONS
-//============================================================
-
-static inline int is_path_to_physical_drive(const char *path)
-{
- return (_strnicmp(path, "\\\\.\\physicaldrive", 17) == 0);
-}
-
-extern const char *winfile_ptty_identifier;
-
-
-//============================================================
-// osd_open
-//============================================================
-
-file_error osd_open(const char *orig_path, UINT32 openflags, osd_file **file, UINT64 *filesize)
-{
- file_error filerr = FILERR_NONE;
- char *path = nullptr;
-
- osd_subst_env(&path, orig_path);
-
- // convert path to TCHAR
- TCHAR *t_path = tstring_from_utf8(path);
- if (t_path == NULL)
- {
- filerr = FILERR_OUT_OF_MEMORY;
- goto error;
- }
-
- // allocate a file object, plus space for the converted filename
- *file = (osd_file *)osd_malloc_array(sizeof(**file) + sizeof(TCHAR) * _tcslen(t_path));
- if (*file == NULL)
- {
- filerr = FILERR_OUT_OF_MEMORY;
- goto error;
- }
- memset(*file, 0x00, sizeof(**file) + sizeof(TCHAR) * _tcslen(t_path));
-
- if (win_check_socket_path(path))
- {
- (*file)->type = WINFILE_SOCKET;
- filerr = win_open_socket(path, openflags, file, filesize);
- goto error;
- }
-
- if (strncmp(path, winfile_ptty_identifier, strlen(winfile_ptty_identifier)) == 0)
- {
- (*file)->type = WINFILE_PTTY;
- filerr = win_open_ptty(path, openflags, file, filesize);
- goto error;
- }
-
- (*file)->type = WINFILE_FILE;
-
- // convert the path into something Windows compatible
- {
- TCHAR *dst = (*file)->filename;
- for (TCHAR const *src = t_path; *src != 0; src++)
- *dst++ = *src;//(*src == '/') ? '\\' : *src;
- *dst++ = 0;
- }
-
- // select the file open modes
- DWORD disposition, access, sharemode;
- if (openflags & OPEN_FLAG_WRITE)
- {
- disposition = (!is_path_to_physical_drive(path) && (openflags & OPEN_FLAG_CREATE)) ? CREATE_ALWAYS : OPEN_EXISTING;
- access = (openflags & OPEN_FLAG_READ) ? (GENERIC_READ | GENERIC_WRITE) : GENERIC_WRITE;
- sharemode = FILE_SHARE_READ;
- }
- else if (openflags & OPEN_FLAG_READ)
- {
- disposition = OPEN_EXISTING;
- access = GENERIC_READ;
- sharemode = FILE_SHARE_READ;
- }
- else
- {
- filerr = FILERR_INVALID_ACCESS;
- goto error;
- }
-
- // attempt to open the file
- (*file)->handle = CreateFile((*file)->filename, access, sharemode, NULL, disposition, 0, NULL);
- if ((*file)->handle == INVALID_HANDLE_VALUE)
- {
- DWORD error = GetLastError();
- // create the path if necessary
- if (error == ERROR_PATH_NOT_FOUND && (openflags & OPEN_FLAG_CREATE) && (openflags & OPEN_FLAG_CREATE_PATHS))
- {
- TCHAR *pathsep = _tcsrchr((*file)->filename, '\\');
- if (pathsep != NULL)
- {
- // create the path up to the file
- *pathsep = 0;
- error = create_path_recursive((*file)->filename);
- *pathsep = '\\';
-
- // attempt to reopen the file
- if (error == NO_ERROR)
- (*file)->handle = CreateFile((*file)->filename, access, sharemode, NULL, disposition, 0, NULL);
- }
- }
-
- // if we still failed, clean up and free
- if ((*file)->handle == INVALID_HANDLE_VALUE)
- {
- filerr = win_error_to_file_error(error);
- goto error;
- }
- }
-
- // get the file size
- DWORD upper;
- *filesize = GetFileSize((*file)->handle, &upper);
- *filesize |= (UINT64)upper << 32;
-
-error:
- // cleanup
- if (filerr != FILERR_NONE && *file != NULL)
- {
- osd_free(*file);
- *file = NULL;
- }
- osd_free(t_path);
- osd_free(path);
- return filerr;
-}
-
-
-//============================================================
-// osd_read
-//============================================================
-
-file_error osd_read(osd_file *file, void *buffer, UINT64 offset, UINT32 length, UINT32 *actual)
-{
- LONG upper = offset >> 32;
- DWORD result;
-
- switch (file->type)
- {
- case WINFILE_FILE:
- // attempt to set the file pointer
- result = SetFilePointer(file->handle, (UINT32)offset, &upper, FILE_BEGIN);
- if (result == INVALID_SET_FILE_POINTER)
- {
- DWORD error = GetLastError();
- if (error != NO_ERROR)
- return win_error_to_mame_file_error(error);
- }
-
- // then perform the read
- if (!ReadFile(file->handle, buffer, length, &result, NULL))
- return win_error_to_mame_file_error(GetLastError());
- if (actual != NULL)
- *actual = result;
- break;
- case WINFILE_SOCKET:
- return win_read_socket(file, buffer, offset, length, actual);
- case WINFILE_PTTY:
- return win_read_ptty(file, buffer, offset, length, actual);
-
- }
- return FILERR_NONE;
-}
-
-
-//============================================================
-// osd_write
-//============================================================
-
-file_error osd_write(osd_file *file, const void *buffer, UINT64 offset, UINT32 length, UINT32 *actual)
-{
- LONG upper = offset >> 32;
- DWORD result;
-
- switch (file->type)
- {
- case WINFILE_FILE:
- // attempt to set the file pointer
- result = SetFilePointer(file->handle, (UINT32)offset, &upper, FILE_BEGIN);
- if (result == INVALID_SET_FILE_POINTER)
- {
- DWORD error = GetLastError();
- if (error != NO_ERROR)
- return win_error_to_mame_file_error(error);
- }
-
- // then perform the read
- if (!WriteFile(file->handle, buffer, length, &result, NULL))
- return win_error_to_mame_file_error(GetLastError());
- if (actual != NULL)
- *actual = result;
- break;
- case WINFILE_SOCKET:
- return win_write_socket(file, buffer, offset, length, actual);
- case WINFILE_PTTY:
- return win_write_ptty(file, buffer, offset, length, actual);
-
- }
- return FILERR_NONE;
-}
-
-//============================================================
-// osd_openpty
-//============================================================
-
-file_error osd_openpty(osd_file **file, char *name, size_t name_len)
-{
- return FILERR_FAILURE;
-}
-
-//============================================================
-// osd_truncate
-//============================================================
-
-file_error osd_truncate(osd_file *file, UINT64 offset)
-{
- if (!file || !file->handle)
- return FILERR_FAILURE;
-
- DWORD result;
- LONG upper = offset >> 32;
-
- switch (file->type)
- {
- case WINFILE_FILE:
- // attempt to set the file pointer
- result = SetFilePointer(file->handle, (UINT32)offset, &upper, FILE_BEGIN);
- if (result == INVALID_SET_FILE_POINTER)
- {
- DWORD error = GetLastError();
- if (error != NO_ERROR)
- return win_error_to_mame_file_error(error);
- }
-
- // then perform the truncation
- if (!SetEndOfFile(file->handle))
- return win_error_to_mame_file_error(GetLastError());
- break;
- case WINFILE_SOCKET:
- return FILERR_FAILURE;
- case WINFILE_PTTY:
- return FILERR_FAILURE;
-
- }
- return FILERR_NONE;
-}
-
-//============================================================
-// osd_fflush
-//============================================================
-
-file_error osd_fflush(osd_file *file)
-{
- if (!file || !file->handle)
- return FILERR_FAILURE;
-
- return FILERR_NONE;
-}
-
-
-//============================================================
-// osd_close
-//============================================================
-
-file_error osd_close(osd_file *file)
-{
- file_error result = FILERR_NONE;
-
- switch (file->type)
- {
- case WINFILE_FILE:
- CloseHandle(file->handle);
- break;
- case WINFILE_SOCKET:
- result = win_close_socket(file);
- break;
- case WINFILE_PTTY:
- result = win_close_ptty(file);
- break;
- }
-
- osd_free(file);
- return result;
-}
-
-
-//============================================================
-// osd_rmfile
-//============================================================
-
-file_error osd_rmfile(const char *filename)
-{
- file_error filerr = FILERR_NONE;
-
- TCHAR *tempstr = tstring_from_utf8(filename);
- if (!tempstr)
- {
- filerr = FILERR_OUT_OF_MEMORY;
- goto done;
- }
-
- if (!DeleteFile(tempstr))
- {
- filerr = win_error_to_file_error(GetLastError());
- goto done;
- }
-
-done:
- if (tempstr)
- osd_free(tempstr);
- return filerr;
-}
-
-
-//============================================================
-// osd_get_physical_drive_geometry
-//============================================================
-
-int osd_get_physical_drive_geometry(const char *filename, UINT32 *cylinders, UINT32 *heads, UINT32 *sectors, UINT32 *bps)
-{
- DISK_GEOMETRY dg;
- DWORD bytesRead;
- TCHAR *t_filename;
- HANDLE file;
- int result;
-
- // if it doesn't smell like a physical drive, just return FALSE
- if (!is_path_to_physical_drive(filename))
- return FALSE;
-
- // do a create file on the drive
- t_filename = tstring_from_utf8(filename);
- if (t_filename == NULL)
- return FALSE;
- file = CreateFile(t_filename, GENERIC_READ, FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_FLAG_NO_BUFFERING, NULL);
- osd_free(t_filename);
- if (file == INVALID_HANDLE_VALUE)
- return FALSE;
-
- // device I/O control should return the geometry
- result = DeviceIoControl(file, IOCTL_DISK_GET_DRIVE_GEOMETRY, NULL, 0, &dg, sizeof(dg), &bytesRead, NULL);
- CloseHandle(file);
-
- // if that failed, return false
- if (!result)
- return FALSE;
-
- // store the results
- *cylinders = (UINT32)dg.Cylinders.QuadPart;
- *heads = dg.TracksPerCylinder;
- *sectors = dg.SectorsPerTrack;
- *bps = dg.BytesPerSector;
-
- // normalize
- while (*heads > 16 && !(*heads & 1))
- {
- *heads /= 2;
- *cylinders *= 2;
- }
- return TRUE;
-}
-
-
-//============================================================
-// create_path_recursive
-//============================================================
-
-DWORD create_path_recursive(const TCHAR *path)
-{
- TCHAR *sep = (TCHAR *)_tcsrchr(path, '\\');
-
- // if there's still a separator, and it's not the root, nuke it and recurse
- if (sep != NULL && sep > path && sep[0] != ':' && sep[-1] != '\\')
- {
- *sep = 0;
- create_path_recursive(path);
- *sep = '\\';
- }
-
- // if the path already exists, we're done
- if (GetFileAttributes(path) != INVALID_FILE_ATTRIBUTES)
- return NO_ERROR;
-
- // create the path
- if (CreateDirectory(path, NULL) == 0)
- return GetLastError();
- return NO_ERROR;
-}
-
-//============================================================
-// win_error_to_mame_file_error
-//============================================================
-
-file_error win_error_to_mame_file_error(DWORD error)
-{
- file_error filerr;
-
- // convert a Windows error to a file_error
- switch (error)
- {
- case ERROR_SUCCESS:
- filerr = FILERR_NONE;
- break;
-
- case ERROR_OUTOFMEMORY:
- filerr = FILERR_OUT_OF_MEMORY;
- break;
-
- case ERROR_FILE_NOT_FOUND:
- case ERROR_PATH_NOT_FOUND:
- filerr = FILERR_NOT_FOUND;
- break;
-
- case ERROR_ACCESS_DENIED:
- filerr = FILERR_ACCESS_DENIED;
- break;
-
- case ERROR_SHARING_VIOLATION:
- filerr = FILERR_ALREADY_OPEN;
- break;
-
- default:
- filerr = FILERR_FAILURE;
- break;
- }
- return filerr;
-}
-
-//============================================================
-// osd_stat
-//============================================================
-
-osd_directory_entry *osd_stat(const char *path)
-{
- osd_directory_entry *result = NULL;
- TCHAR *t_path;
- HANDLE find = INVALID_HANDLE_VALUE;
- WIN32_FIND_DATA find_data;
-
- // convert the path to TCHARs
- t_path = tstring_from_utf8(path);
- if (t_path == NULL)
- goto done;
-
- // is this path a root directory (e.g. - C:)?
- if (isalpha(path[0]) && (path[1] == ':') && (path[2] == '\0'))
- {
- // need to do special logic for root directories
- memset(&find_data, 0, sizeof(find_data));
- find_data.dwFileAttributes = GetFileAttributes(t_path);
- }
- else
- {
- // attempt to find the first file
- find = FindFirstFile(t_path, &find_data);
- if (find == INVALID_HANDLE_VALUE)
- goto done;
- }
-
- // create an osd_directory_entry; be sure to make sure that the caller can
- // free all resources by just freeing the resulting osd_directory_entry
- result = (osd_directory_entry *)osd_malloc_array(sizeof(*result) + strlen(path) + 1);
- if (!result)
- goto done;
- strcpy(((char *) result) + sizeof(*result), path);
- result->name = ((char *) result) + sizeof(*result);
- result->type = win_attributes_to_entry_type(find_data.dwFileAttributes);
- result->size = find_data.nFileSizeLow | ((UINT64) find_data.nFileSizeHigh << 32);
-
-done:
- if (t_path != NULL)
- osd_free(t_path);
- return result;
-}
-
-//============================================================
-// osd_get_full_path
-//============================================================
-
-file_error osd_get_full_path(char **dst, const char *path)
-{
- file_error err;
- TCHAR *t_path;
- TCHAR buffer[MAX_PATH];
-
- // convert the path to TCHARs
- t_path = tstring_from_utf8(path);
- if (t_path == NULL)
- {
- err = FILERR_OUT_OF_MEMORY;
- goto done;
- }
-
- // cannonicalize the path
- if (!GetFullPathName(t_path, ARRAY_LENGTH(buffer), buffer, NULL))
- {
- err = win_error_to_mame_file_error(GetLastError());
- goto done;
- }
-
- // convert the result back to UTF-8
- *dst = utf8_from_tstring(buffer);
- if (!*dst)
- {
- err = FILERR_OUT_OF_MEMORY;
- goto done;
- }
-
- err = FILERR_NONE;
-
-done:
- if (t_path != NULL)
- osd_free(t_path);
- return err;
-}
-
-//============================================================
-// osd_get_volume_name
-//============================================================
-
-const char *osd_get_volume_name(int idx)
-{
- static char szBuffer[128];
- const char *p;
-
- GetLogicalDriveStringsA(ARRAY_LENGTH(szBuffer), szBuffer);
-
- p = szBuffer;
- while(idx--) {
- p += strlen(p) + 1;
- if (!*p) return NULL;
- }
-
- return p;
-}
diff --git a/src/osd/windows/winfile.h b/src/osd/windows/winfile.h
deleted file mode 100644
index 51e9acb5e0a..00000000000
--- a/src/osd/windows/winfile.h
+++ /dev/null
@@ -1,56 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Aaron Giles
-//============================================================
-//
-// winfile.h - File access functions
-//
-//============================================================
-#ifndef __WINFILE__
-#define __WINFILE__
-
-#include <winsock2.h>
-#include "osdcore.h"
-
-//============================================================
-// ENUM DEFINITIONS
-//============================================================
-enum
-{
- WINFILE_FILE = 0,
- WINFILE_SOCKET,
- WINFILE_PTTY
-};
-
-//============================================================
-// TYPE DEFINITIONS
-//============================================================
-
-struct osd_file
-{
- HANDLE handle;
- SOCKET socket;
- int type;
- TCHAR filename[1];
-};
-
-//============================================================
-// PROTOTYPES
-//============================================================
-
-bool win_init_sockets();
-void win_cleanup_sockets();
-
-bool win_check_socket_path(const char *path);
-file_error win_open_socket(const char *path, UINT32 openflags, osd_file **file, UINT64 *filesize);
-file_error win_read_socket(osd_file *file, void *buffer, UINT64 offset, UINT32 count, UINT32 *actual);
-file_error win_write_socket(osd_file *file, const void *buffer, UINT64 offset, UINT32 count, UINT32 *actual);
-file_error win_close_socket(osd_file *file);
-
-file_error win_open_ptty(const char *path, UINT32 openflags, osd_file **file, UINT64 *filesize);
-file_error win_read_ptty(osd_file *file, void *buffer, UINT64 offset, UINT32 count, UINT32 *actual);
-file_error win_write_ptty(osd_file *file, const void *buffer, UINT64 offset, UINT32 count, UINT32 *actual);
-file_error win_close_ptty(osd_file *file);
-
-file_error win_error_to_mame_file_error(DWORD error);
-
-#endif //__WINFILE__
diff --git a/src/osd/windows/winptty.cpp b/src/osd/windows/winptty.cpp
deleted file mode 100644
index d04592d1749..00000000000
--- a/src/osd/windows/winptty.cpp
+++ /dev/null
@@ -1,70 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Aaron Giles
-#define WIN32_LEAN_AND_MEAN
-
-#include <windows.h>
-#include <stdlib.h>
-
-#include "winfile.h"
-#include "strconv.h"
-#include "winutil.h"
-
-const char *winfile_ptty_identifier = "\\\\.\\pipe\\";
-
-file_error win_open_ptty(const char *path, UINT32 openflags, osd_file **file, UINT64 *filesize)
-{
- TCHAR *t_name;
- HANDLE pipe;
-
- if((t_name = tstring_from_utf8(path)) == NULL)
- return FILERR_OUT_OF_MEMORY;
-
- pipe = CreateNamedPipe(t_name, PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_NOWAIT, 1, 32, 32, 0, NULL);
-
- osd_free(t_name);
-
- if(pipe == INVALID_HANDLE_VALUE)
- return FILERR_ACCESS_DENIED;
-
- (*file)->handle = pipe;
- *filesize = 0;
- return FILERR_NONE;
-}
-
-file_error win_read_ptty(osd_file *file, void *buffer, UINT64 offset, UINT32 count, UINT32 *actual)
-{
- BOOL res;
- DWORD bytes_read;
-
- res = ReadFile(file->handle, buffer, count, &bytes_read, NULL);
- if(res == FALSE)
- return win_error_to_file_error(GetLastError());
-
- if(actual != NULL)
- *actual = bytes_read;
-
- return FILERR_NONE;
-}
-
-file_error win_write_ptty(osd_file *file, const void *buffer, UINT64 offset, UINT32 count, UINT32 *actual)
-{
- BOOL res;
- DWORD bytes_wrote;
-
- res = WriteFile(file->handle, buffer, count, &bytes_wrote, NULL);
- if(res == FALSE)
- return win_error_to_file_error(GetLastError());
-
- if(actual != NULL)
- *actual = bytes_wrote;
-
- return FILERR_NONE;
-}
-
-file_error win_close_ptty(osd_file *file)
-{
- FlushFileBuffers(file->handle);
- DisconnectNamedPipe(file->handle);
- CloseHandle(file->handle);
- return FILERR_NONE;
-}
diff --git a/src/osd/windows/winsocket.cpp b/src/osd/windows/winsocket.cpp
deleted file mode 100644
index cfa22dbbcb1..00000000000
--- a/src/osd/windows/winsocket.cpp
+++ /dev/null
@@ -1,204 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Aaron Giles
-//============================================================
-//
-// winsocket.c - Windows socket (inet) access functions
-//
-//============================================================
-// standard windows headers
-#define WIN32_LEAN_AND_MEAN
-#include <windows.h>
-#include <winioctl.h>
-#include <tchar.h>
-#include <stdlib.h>
-#include <ctype.h>
-
-// MAME headers
-#include "osdcore.h"
-
-#include "winfile.h"
-
-const char *winfile_socket_identifier = "socket.";
-
-bool win_init_sockets()
-{
- WSADATA wsaData;
- WORD version;
- int error;
-
- version = MAKEWORD( 2, 0 );
-
- error = WSAStartup( version, &wsaData );
-
- /* check for error */
- if ( error != 0 )
- {
- /* error occurred */
- return FALSE;
- }
-
-
- /* check for correct version */
- if ( LOBYTE( wsaData.wVersion ) != 2 ||
- HIBYTE( wsaData.wVersion ) != 0 )
- {
- /* incorrect WinSock version */
- WSACleanup();
- return FALSE;
- }
- /* WinSock has been initialized */
- return TRUE;
-}
-
-void win_cleanup_sockets()
-{
- WSACleanup();
-}
-
-bool win_check_socket_path(const char *path)
-{
- if (strlen(winfile_socket_identifier) > 0 &&
- strncmp(path, winfile_socket_identifier, strlen(winfile_socket_identifier)) == 0 &&
- strchr(path, ':') != nullptr) return true;
- return false;
-}
-
-file_error win_open_socket(const char *path, UINT32 openflags, osd_file **file, UINT64 *filesize)
-{
- char hostname[256];
- struct hostent *localhost;
- struct sockaddr_in sai;
- int flag = 1;
- int port;
-
- sscanf( path+strlen(winfile_socket_identifier), "%255[^:]:%d", hostname, &port );
-
- if (((*file)->socket = socket(AF_INET, SOCK_STREAM, 0)) == -1)
- {
- return FILERR_ACCESS_DENIED;
- }
-
- if (setsockopt((*file)->socket, IPPROTO_TCP, TCP_NODELAY, (char *)&flag, sizeof(flag)) == -1)
- {
- return FILERR_ACCESS_DENIED;
- }
- localhost = gethostbyname(hostname);
-
- memset(&sai, 0, sizeof(sai));
- sai.sin_family = AF_INET;
- sai.sin_port = htons(port);
- sai.sin_addr = *((struct in_addr *)localhost->h_addr);
-
- // listening socket support
- if (openflags & OPEN_FLAG_CREATE)
- {
-// printf("Listening for client at '%s' on port '%d'\n", hostname, port);
- // bind socket...
- if (bind((*file)->socket, (struct sockaddr *)&sai, sizeof(struct sockaddr)) == -1)
- {
- return FILERR_ACCESS_DENIED;
- }
-
- // start to listen...
- if (listen((*file)->socket, 1) == -1) {
- return FILERR_ACCESS_DENIED;
- }
-
- // mark socket as "listening"
- (*file)->handle = nullptr;
- *filesize = 0;
- return FILERR_NONE;
- }
-
-// printf("Connecting to server '%s' on port '%d'\n", hostname, port);
- if (connect((*file)->socket, (struct sockaddr *)&sai, sizeof(struct sockaddr)) == -1)
- {
- return FILERR_ACCESS_DENIED;
- }
- *filesize = 0;
- (*file)->handle = INVALID_HANDLE_VALUE;
- return FILERR_NONE;
-}
-
-file_error win_read_socket(osd_file *file, void *buffer, UINT64 offset, UINT32 count, UINT32 *actual)
-{
- int result;
- char line[80];
- struct timeval timeout;
- fd_set readfds;
-
- FD_ZERO(&readfds);
- FD_SET(file->socket, &readfds);
- timeout.tv_sec = timeout.tv_usec = 0;
-
- if (select(file->socket + 1, &readfds, nullptr, nullptr, &timeout) < 0)
- {
- sprintf(line, "win_read_socket : %s : %d ", __FILE__, __LINE__);
- perror(line);
- return win_error_to_mame_file_error(GetLastError());
- }
- else if (FD_ISSET(file->socket, &readfds))
- {
- if (file->handle == INVALID_HANDLE_VALUE)
- {
- // connected socket
- result = recv(file->socket, (char*)buffer, count, 0);
- }
- else
- {
- // listening socket
- SOCKET AcceptSocket;
- AcceptSocket = accept(file->socket, nullptr, nullptr);
- if (AcceptSocket == INVALID_SOCKET)
- {
- return FILERR_FAILURE;
- }
- closesocket(file->socket);
- file->socket = AcceptSocket;
- file->handle = INVALID_HANDLE_VALUE;
- if (actual != nullptr )
- {
- *actual = 0;
- }
-
- return FILERR_NONE;
- }
- }
- else
- {
- return FILERR_FAILURE;
- }
-
- if (result < 0)
- {
- return win_error_to_mame_file_error(GetLastError());
- }
-
- if (actual != nullptr )
- {
- *actual = result;
- }
- return FILERR_NONE;
-}
-
-file_error win_write_socket(osd_file *file, const void *buffer, UINT64 offset, UINT32 count, UINT32 *actual)
-{
- int result;
- result = send(file->socket, (const char*)buffer, count, 0);
- if (result < 0)
- {
- return win_error_to_mame_file_error(GetLastError());
- }
-
- if (actual != nullptr )
- {
- *actual = result;
- }
- return FILERR_NONE;
-}
-
-file_error win_close_socket(osd_file *file)
-{
- closesocket(file->socket);
- return FILERR_NONE;
-}
diff --git a/src/osd/windows/winutil.cpp b/src/osd/windows/winutil.cpp
index eb63eecacd0..ff162c9169a 100644
--- a/src/osd/windows/winutil.cpp
+++ b/src/osd/windows/winutil.cpp
@@ -18,47 +18,6 @@
#include "winutil.h"
#include "strconv.h"
-//============================================================
-// win_error_to_file_error
-//============================================================
-
-file_error win_error_to_file_error(DWORD error)
-{
- file_error filerr;
-
- // convert a Windows error to a file_error
- switch (error)
- {
- case ERROR_SUCCESS:
- filerr = FILERR_NONE;
- break;
-
- case ERROR_OUTOFMEMORY:
- filerr = FILERR_OUT_OF_MEMORY;
- break;
-
- case ERROR_FILE_NOT_FOUND:
- case ERROR_FILENAME_EXCED_RANGE:
- case ERROR_PATH_NOT_FOUND:
- filerr = FILERR_NOT_FOUND;
- break;
-
- case ERROR_ACCESS_DENIED:
- filerr = FILERR_ACCESS_DENIED;
- break;
-
- case ERROR_SHARING_VIOLATION:
- filerr = FILERR_ALREADY_OPEN;
- break;
-
- default:
- filerr = FILERR_FAILURE;
- break;
- }
- return filerr;
-}
-
-
//============================================================
// win_attributes_to_entry_type
diff --git a/src/osd/windows/winutil.h b/src/osd/windows/winutil.h
index 530327dcf61..6cb8297c277 100644
--- a/src/osd/windows/winutil.h
+++ b/src/osd/windows/winutil.h
@@ -14,7 +14,6 @@
#include <vector>
// Shared code
-file_error win_error_to_file_error(DWORD error);
osd_dir_entry_type win_attributes_to_entry_type(DWORD attributes);
BOOL win_is_gui_application(void);
HMODULE WINAPI GetModuleHandleUni();
@@ -26,10 +25,10 @@ HMODULE WINAPI GetModuleHandleUni();
class lazy_loaded_function
{
private:
- std::string m_name;
- std::vector<std::wstring> m_dll_names;
- HMODULE m_module;
- bool m_initialized;
+ std::string m_name;
+ std::vector<std::wstring> m_dll_names;
+ HMODULE m_module;
+ bool m_initialized;
protected:
void check_init();
diff --git a/src/tools/chdman.cpp b/src/tools/chdman.cpp
index 1a80bc76e13..6029f481e07 100644
--- a/src/tools/chdman.cpp
+++ b/src/tools/chdman.cpp
@@ -331,8 +331,8 @@ public:
{
m_file.reset();
m_lastfile = m_info.track[tracknum].fname;
- file_error filerr = util::core_file::open(m_lastfile.c_str(), OPEN_FLAG_READ, m_file);
- if (filerr != FILERR_NONE)
+ osd_file::error filerr = util::core_file::open(m_lastfile.c_str(), OPEN_FLAG_READ, m_file);
+ if (filerr != osd_file::error::NONE)
report_error(1, "Error opening input file (%s)'", m_lastfile.c_str());
}
@@ -438,15 +438,15 @@ public:
// read the sound samples
m_audio[chnum].resize(samples);
samplesptr[chnum] = &m_audio[chnum][0];
- avi_error avierr = avi_read_sound_samples(&m_file, chnum, first_sample, samples, &m_audio[chnum][0]);
- if (avierr != AVIERR_NONE)
- report_error(1, "Error reading audio samples %d-%d from channel %d: %s", first_sample, samples, chnum, avi_error_string(avierr));
+ avi_file::error avierr = m_file.read_sound_samples(chnum, first_sample, samples, &m_audio[chnum][0]);
+ if (avierr != avi_file::error::NONE)
+ report_error(1, "Error reading audio samples %d-%d from channel %d: %s", first_sample, samples, chnum, avi_file::error_string(avierr));
}
// read the video data
- avi_error avierr = avi_read_video_frame(&m_file, effframe / interlace_factor, m_bitmap);
- if (avierr != AVIERR_NONE)
- report_error(1, "Error reading AVI frame %d: %s", effframe / interlace_factor, avi_error_string(avierr));
+ avi_file::error avierr = m_file.read_video_frame(effframe / interlace_factor, m_bitmap);
+ if (avierr != avi_file::error::NONE)
+ report_error(1, "Error reading AVI frame %d: %s", effframe / interlace_factor, avi_file::error_string(avierr));
bitmap_yuy16 subbitmap(&m_bitmap.pix(effframe % interlace_factor), m_bitmap.width(), m_bitmap.height() / interlace_factor, m_bitmap.rowpixels() * interlace_factor);
// update metadata for this frame
@@ -1007,8 +1007,8 @@ static void check_existing_output_file(const parameters_t &params, const char *f
if (params.find(OPTION_OUTPUT_FORCE) == params.end())
{
util::core_file::ptr file;
- file_error filerr = util::core_file::open(filename, OPEN_FLAG_READ, file);
- if (filerr == FILERR_NONE)
+ osd_file::error filerr = util::core_file::open(filename, OPEN_FLAG_READ, file);
+ if (filerr == osd_file::error::NONE)
{
file.reset();
report_error(1, "Error: file already exists (%s)\nUse --force (or -f) to force overwriting", filename);
@@ -1572,8 +1572,8 @@ static void do_create_raw(parameters_t &params)
auto input_file_str = params.find(OPTION_INPUT);
if (input_file_str != params.end())
{
- file_error filerr = util::core_file::open(input_file_str->second->c_str(), OPEN_FLAG_READ, input_file);
- if (filerr != FILERR_NONE)
+ osd_file::error filerr = util::core_file::open(input_file_str->second->c_str(), OPEN_FLAG_READ, input_file);
+ if (filerr != osd_file::error::NONE)
report_error(1, "Unable to open file (%s)", input_file_str->second->c_str());
}
@@ -1651,7 +1651,7 @@ static void do_create_raw(parameters_t &params)
// delete the output file
auto output_chd_str = params.find(OPTION_OUTPUT);
if (output_chd_str != params.end())
- osd_rmfile(output_chd_str->second->c_str());
+ osd_file::remove(*output_chd_str->second);
throw;
}
}
@@ -1669,8 +1669,8 @@ static void do_create_hd(parameters_t &params)
auto input_file_str = params.find(OPTION_INPUT);
if (input_file_str != params.end())
{
- file_error filerr = util::core_file::open(input_file_str->second->c_str(), OPEN_FLAG_READ, input_file);
- if (filerr != FILERR_NONE)
+ osd_file::error filerr = util::core_file::open(input_file_str->second->c_str(), OPEN_FLAG_READ, input_file);
+ if (filerr != osd_file::error::NONE)
report_error(1, "Unable to open file (%s)", input_file_str->second->c_str());
}
@@ -1744,8 +1744,8 @@ static void do_create_hd(parameters_t &params)
if (ident_str != params.end())
{
// load the file
- file_error filerr = util::core_file::load(ident_str->second->c_str(), identdata);
- if (filerr != FILERR_NONE)
+ osd_file::error filerr = util::core_file::load(ident_str->second->c_str(), identdata);
+ if (filerr != osd_file::error::NONE)
report_error(1, "Error reading ident file (%s)", ident_str->second->c_str());
// must be at least 14 bytes; extract CHS data from there
@@ -1840,7 +1840,7 @@ static void do_create_hd(parameters_t &params)
// delete the output file
auto output_chd_str = params.find(OPTION_OUTPUT);
if (output_chd_str != params.end())
- osd_rmfile(output_chd_str->second->c_str());
+ osd_file::remove(*output_chd_str->second);
throw;
}
}
@@ -1932,7 +1932,7 @@ static void do_create_cd(parameters_t &params)
// delete the output file
auto output_chd_str = params.find(OPTION_OUTPUT);
if (output_chd_str != params.end())
- osd_rmfile(output_chd_str->second->c_str());
+ osd_file::remove(*output_chd_str->second);
throw;
}
}
@@ -1946,15 +1946,15 @@ static void do_create_cd(parameters_t &params)
static void do_create_ld(parameters_t &params)
{
// process input file
- avi_file *input_file = nullptr;
+ avi_file::ptr input_file;
auto input_file_str = params.find(OPTION_INPUT);
if (input_file_str != params.end())
{
- avi_error avierr = avi_open(input_file_str->second->c_str(), &input_file);
- if (avierr != AVIERR_NONE)
- report_error(1, "Error opening AVI file (%s): %s\n", input_file_str->second->c_str(), avi_error_string(avierr));
+ avi_file::error avierr = avi_file::open(*input_file_str->second, input_file);
+ if (avierr != avi_file::error::NONE)
+ report_error(1, "Error opening AVI file (%s): %s\n", input_file_str->second->c_str(), avi_file::error_string(avierr));
}
- const avi_movie_info *aviinfo = avi_get_movie_info(input_file);
+ const avi_file::movie_info &aviinfo = input_file->get_movie_info();
// process output CHD
chd_file output_parent;
@@ -1963,16 +1963,16 @@ static void do_create_ld(parameters_t &params)
// process input start/end
UINT64 input_start;
UINT64 input_end;
- parse_input_start_end(params, aviinfo->video_numsamples, 0, 1, input_start, input_end);
+ parse_input_start_end(params, aviinfo.video_numsamples, 0, 1, input_start, input_end);
// determine parameters of the incoming video stream
avi_info info;
- info.fps_times_1million = UINT64(aviinfo->video_timescale) * 1000000 / aviinfo->video_sampletime;
- info.width = aviinfo->video_width;
- info.height = aviinfo->video_height;
+ info.fps_times_1million = UINT64(aviinfo.video_timescale) * 1000000 / aviinfo.video_sampletime;
+ info.width = aviinfo.video_width;
+ info.height = aviinfo.video_height;
info.interlaced = ((info.fps_times_1million / 1000000) <= 30) && (info.height % 2 == 0) && (info.height > 288);
- info.channels = aviinfo->audio_channels;
- info.rate = aviinfo->audio_samplerate;
+ info.channels = aviinfo.audio_channels;
+ info.rate = aviinfo.audio_samplerate;
// adjust for interlacing
if (info.interlaced)
@@ -2008,7 +2008,7 @@ static void do_create_ld(parameters_t &params)
if (output_parent.opened())
printf("Parent CHD: %s\n", params.find(OPTION_OUTPUT_PARENT)->second->c_str());
printf("Input file: %s\n", input_file_str->second->c_str());
- if (input_start != 0 && input_end != aviinfo->video_numsamples)
+ if (input_start != 0 && input_end != aviinfo.video_numsamples)
printf("Input start: %s\n", big_int_string(tempstr, input_start));
printf("Input length: %s (%02d:%02d:%02d)\n", big_int_string(tempstr, input_end - input_start),
UINT32((UINT64(input_end - input_start) * 1000000 / info.fps_times_1million / 60 / 60)),
@@ -2059,7 +2059,7 @@ static void do_create_ld(parameters_t &params)
// delete the output file
auto output_chd_str = params.find(OPTION_OUTPUT);
if (output_chd_str != params.end())
- osd_rmfile(output_chd_str->second->c_str());
+ osd_file::remove(*output_chd_str->second);
throw;
}
}
@@ -2195,7 +2195,7 @@ static void do_copy(parameters_t &params)
// delete the output file
auto output_chd_str = params.find(OPTION_OUTPUT);
if (output_chd_str != params.end())
- osd_rmfile(output_chd_str->second->c_str());
+ osd_file::remove(*output_chd_str->second);
throw;
}
}
@@ -2238,8 +2238,8 @@ static void do_extract_raw(parameters_t &params)
try
{
// process output file
- file_error filerr = util::core_file::open(output_file_str->second->c_str(), OPEN_FLAG_WRITE | OPEN_FLAG_CREATE, output_file);
- if (filerr != FILERR_NONE)
+ osd_file::error filerr = util::core_file::open(output_file_str->second->c_str(), OPEN_FLAG_WRITE | OPEN_FLAG_CREATE, output_file);
+ if (filerr != osd_file::error::NONE)
report_error(1, "Unable to open file (%s)", output_file_str->second->c_str());
// copy all data
@@ -2273,7 +2273,7 @@ static void do_extract_raw(parameters_t &params)
if (output_file != nullptr)
{
output_file.reset();
- osd_rmfile(output_file_str->second->c_str());
+ osd_file::remove(*output_file_str->second);
}
throw;
}
@@ -2343,15 +2343,15 @@ static void do_extract_cd(parameters_t &params)
}
// process output file
- file_error filerr = util::core_file::open(output_file_str->second->c_str(), OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_NO_BOM, output_toc_file);
- if (filerr != FILERR_NONE)
+ osd_file::error filerr = util::core_file::open(output_file_str->second->c_str(), OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_NO_BOM, output_toc_file);
+ if (filerr != osd_file::error::NONE)
report_error(1, "Unable to open file (%s)", output_file_str->second->c_str());
// process output BIN file
if (mode != MODE_GDI)
{
filerr = util::core_file::open(output_bin_file_str->c_str(), OPEN_FLAG_WRITE | OPEN_FLAG_CREATE, output_bin_file);
- if (filerr != FILERR_NONE)
+ if (filerr != osd_file::error::NONE)
report_error(1, "Unable to open file (%s)", output_bin_file_str->c_str());
}
@@ -2387,7 +2387,7 @@ static void do_extract_cd(parameters_t &params)
output_bin_file.reset();
filerr = util::core_file::open(trackbin_name.c_str(), OPEN_FLAG_WRITE | OPEN_FLAG_CREATE, output_bin_file);
- if (filerr != FILERR_NONE)
+ if (filerr != osd_file::error::NONE)
report_error(1, "Unable to open file (%s)", trackbin_name.c_str());
outputoffs = 0;
@@ -2471,8 +2471,8 @@ static void do_extract_cd(parameters_t &params)
// delete the output files
output_bin_file.reset();
output_toc_file.reset();
- osd_rmfile(output_bin_file_str->c_str());
- osd_rmfile(output_file_str->second->c_str());
+ osd_file::remove(*output_bin_file_str);
+ osd_file::remove(*output_file_str->second);
throw;
}
}
@@ -2528,7 +2528,7 @@ static void do_extract_ld(parameters_t &params)
input_end *= interlace_factor;
// build up the movie info
- avi_movie_info info;
+ avi_file::movie_info info;
info.video_format = FORMAT_YUY2;
info.video_timescale = fps_times_1million / interlace_factor;
info.video_sampletime = 1000000;
@@ -2558,12 +2558,12 @@ static void do_extract_ld(parameters_t &params)
}
// catch errors so we can close & delete the output file
- avi_file *output_file = nullptr;
+ avi_file::ptr output_file;
try
{
// process output file
- avi_error avierr = avi_create(output_file_str->second->c_str(), &info, &output_file);
- if (avierr != AVIERR_NONE)
+ avi_file::error avierr = avi_file::create(*output_file_str->second, info, output_file);
+ if (avierr != avi_file::error::NONE)
report_error(1, "Unable to open file (%s)", output_file_str->second->c_str());
// create the codec configuration
@@ -2599,30 +2599,29 @@ static void do_extract_ld(parameters_t &params)
// write audio
for (int chnum = 0; chnum < channels; chnum++)
{
- avi_error avierr = avi_append_sound_samples(output_file, chnum, avconfig.audio[chnum], actsamples, 0);
- if (avierr != AVIERR_NONE)
- report_error(1, "Error writing samples for hunk %d to file (%s): %s\n", framenum, output_file_str->second->c_str(), avi_error_string(avierr));
+ avi_file::error avierr = output_file->append_sound_samples(chnum, avconfig.audio[chnum], actsamples, 0);
+ if (avierr != avi_file::error::NONE)
+ report_error(1, "Error writing samples for hunk %d to file (%s): %s\n", framenum, output_file_str->second->c_str(), avi_file::error_string(avierr));
}
// write video
if ((framenum + 1) % interlace_factor == 0)
{
- avi_error avierr = avi_append_video_frame(output_file, fullbitmap);
- if (avierr != AVIERR_NONE)
- report_error(1, "Error writing video for hunk %d to file (%s): %s\n", framenum, output_file_str->second->c_str(), avi_error_string(avierr));
+ avi_file::error avierr = output_file->append_video_frame(fullbitmap);
+ if (avierr != avi_file::error::NONE)
+ report_error(1, "Error writing video for hunk %d to file (%s): %s\n", framenum, output_file_str->second->c_str(), avi_file::error_string(avierr));
}
}
// close and return
- avi_close(output_file);
+ output_file.reset();
printf("Extraction complete \n");
}
catch (...)
{
// delete the output file
- if (output_file != nullptr)
- avi_close(output_file);
- osd_rmfile(output_file_str->second->c_str());
+ output_file.reset();
+ osd_file::remove(*output_file_str->second);
throw;
}
}
@@ -2670,8 +2669,8 @@ static void do_add_metadata(parameters_t &params)
dynamic_buffer file;
if (file_str != params.end())
{
- file_error filerr = util::core_file::load(file_str->second->c_str(), file);
- if (filerr != FILERR_NONE)
+ osd_file::error filerr = util::core_file::load(file_str->second->c_str(), file);
+ if (filerr != osd_file::error::NONE)
report_error(1, "Error reading metadata file (%s)", file_str->second->c_str());
}
@@ -2794,8 +2793,8 @@ static void do_dump_metadata(parameters_t &params)
// create the file
if (output_file_str != params.end())
{
- file_error filerr = util::core_file::open(output_file_str->second->c_str(), OPEN_FLAG_WRITE | OPEN_FLAG_CREATE, output_file);
- if (filerr != FILERR_NONE)
+ osd_file::error filerr = util::core_file::open(output_file_str->second->c_str(), OPEN_FLAG_WRITE | OPEN_FLAG_CREATE, output_file);
+ if (filerr != osd_file::error::NONE)
report_error(1, "Unable to open file (%s)", output_file_str->second->c_str());
// output the metadata
@@ -2820,7 +2819,7 @@ static void do_dump_metadata(parameters_t &params)
{
// delete the output file
output_file.reset();
- osd_rmfile(output_file_str->second->c_str());
+ osd_file::remove(*output_file_str->second);
throw;
}
}
diff --git a/src/tools/imgtool/stream.cpp b/src/tools/imgtool/stream.cpp
index 4cc4c9ec2db..d96cf325a7a 100644
--- a/src/tools/imgtool/stream.cpp
+++ b/src/tools/imgtool/stream.cpp
@@ -104,33 +104,27 @@ static imgtool_stream *stream_open_zip(const char *zipname, const char *subname,
imgfile->imgtype = IMG_MEM;
- zip_file *z = nullptr;
- const zip_file_header *zipent = nullptr;
- zip_file_open(zipname, &z);
+ zip_file::ptr z;
+ const zip_file::file_header *zipent = nullptr;
+ zip_file::open(zipname, z);
if (!z)
- goto error;
+ return nullptr;
- zipent = zip_file_first_file(z);
+ zipent = z->first_file();
while (zipent && subname && strcmp(subname, zipent->filename))
- zipent = zip_file_next_file(z);
+ zipent = z->next_file();
if (!zipent)
- goto error;
+ return nullptr;
imgfile->filesize = zipent->uncompressed_length;
imgfile->buffer = reinterpret_cast<std::uint8_t *>(malloc(zipent->uncompressed_length));
if (!imgfile->buffer)
- goto error;
+ return nullptr;
- if (zip_file_decompress(z, imgfile->buffer, zipent->uncompressed_length))
- goto error;
+ if (z->decompress(imgfile->buffer, zipent->uncompressed_length) != zip_file::error::NONE)
+ return nullptr;
- zip_file_close(z);
return imgfile.release();
-
-error:
- if (z)
- zip_file_close(z);
- return nullptr;
}
@@ -154,7 +148,7 @@ imgtool_stream *stream_open(const char *fname, int read_or_write)
util::core_file::ptr f = nullptr;
auto const filerr = util::core_file::open(fname, write_modes[read_or_write], f);
- if (filerr != FILERR_NONE)
+ if (filerr != osd_file::error::NONE)
{
if (!read_or_write)
{
diff --git a/src/tools/ldverify.cpp b/src/tools/ldverify.cpp
index ab3947dfaea..45c20d9d70c 100644
--- a/src/tools/ldverify.cpp
+++ b/src/tools/ldverify.cpp
@@ -102,23 +102,23 @@ static bool chdinterlaced;
static void *open_avi(const char *filename, movie_info &info)
{
// open the file
- avi_file *avi;
- avi_error avierr = avi_open(filename, &avi);
- if (avierr != AVIERR_NONE)
+ avi_file::ptr avi;
+ avi_file::error avierr = avi_file::open(filename, avi);
+ if (avierr != avi_file::error::NONE)
{
- fprintf(stderr, "Error opening AVI file: %s\n", avi_error_string(avierr));
+ fprintf(stderr, "Error opening AVI file: %s\n", avi_file::error_string(avierr));
return nullptr;
}
// extract movie info
- const avi_movie_info *aviinfo = avi_get_movie_info(avi);
- info.framerate = (double)aviinfo->video_timescale / (double)aviinfo->video_sampletime;
- info.numframes = aviinfo->video_numsamples;
- info.width = aviinfo->video_width;
- info.height = aviinfo->video_height;
- info.samplerate = aviinfo->audio_samplerate;
- info.channels = aviinfo->audio_channels;
- return avi;
+ const avi_file::movie_info &aviinfo = avi->get_movie_info();
+ info.framerate = (double)aviinfo.video_timescale / (double)aviinfo.video_sampletime;
+ info.numframes = aviinfo.video_numsamples;
+ info.width = aviinfo.video_width;
+ info.height = aviinfo.video_height;
+ info.samplerate = aviinfo.audio_samplerate;
+ info.channels = aviinfo.audio_channels;
+ return avi.release();
}
@@ -131,17 +131,17 @@ static bool read_avi(void *file, int frame, bitmap_yuy16 &bitmap, INT16 *lsound,
avi_file *avifile = reinterpret_cast<avi_file *>(file);
// read the frame
- avi_error avierr = avi_read_video_frame(avifile, frame, bitmap);
- if (avierr != AVIERR_NONE)
+ avi_file::error avierr = avifile->read_video_frame(frame, bitmap);
+ if (avierr != avi_file::error::NONE)
return FALSE;
// read the samples
- const avi_movie_info *aviinfo = avi_get_movie_info(avifile);
- UINT32 firstsample = (UINT64(aviinfo->audio_samplerate) * UINT64(frame) * UINT64(aviinfo->video_sampletime) + aviinfo->video_timescale - 1) / UINT64(aviinfo->video_timescale);
- UINT32 lastsample = (UINT64(aviinfo->audio_samplerate) * UINT64(frame + 1) * UINT64(aviinfo->video_sampletime) + aviinfo->video_timescale - 1) / UINT64(aviinfo->video_timescale);
- avierr = avi_read_sound_samples(avifile, 0, firstsample, lastsample - firstsample, lsound);
- avierr = avi_read_sound_samples(avifile, 1, firstsample, lastsample - firstsample, rsound);
- if (avierr != AVIERR_NONE)
+ const avi_file::movie_info &aviinfo = avifile->get_movie_info();
+ UINT32 firstsample = (UINT64(aviinfo.audio_samplerate) * UINT64(frame) * UINT64(aviinfo.video_sampletime) + aviinfo.video_timescale - 1) / UINT64(aviinfo.video_timescale);
+ UINT32 lastsample = (UINT64(aviinfo.audio_samplerate) * UINT64(frame + 1) * UINT64(aviinfo.video_sampletime) + aviinfo.video_timescale - 1) / UINT64(aviinfo.video_timescale);
+ avierr = avifile->read_sound_samples(0, firstsample, lastsample - firstsample, lsound);
+ avierr = avifile->read_sound_samples(1, firstsample, lastsample - firstsample, rsound);
+ if (avierr != avi_file::error::NONE)
return false;
samples = lastsample - firstsample;
return true;
@@ -155,7 +155,7 @@ static bool read_avi(void *file, int frame, bitmap_yuy16 &bitmap, INT16 *lsound,
static void close_avi(void *file)
{
avi_file *avifile = reinterpret_cast<avi_file *>(file);
- avi_close(avifile);
+ delete avifile;
}
diff --git a/src/tools/pngcmp.cpp b/src/tools/pngcmp.cpp
index 5103740389b..aa33a421e5d 100644
--- a/src/tools/pngcmp.cpp
+++ b/src/tools/pngcmp.cpp
@@ -73,7 +73,7 @@ static int generate_png_diff(const std::string& imgfile1, const std::string& img
bitmap_argb32 finalbitmap;
int width, height, maxwidth;
util::core_file::ptr file;
- file_error filerr;
+ osd_file::error filerr;
png_error pngerr;
int error = 100;
bool bitmaps_differ;
@@ -81,9 +81,9 @@ static int generate_png_diff(const std::string& imgfile1, const std::string& img
/* open the source image */
filerr = util::core_file::open(imgfile1.c_str(), OPEN_FLAG_READ, file);
- if (filerr != FILERR_NONE)
+ if (filerr != osd_file::error::NONE)
{
- printf("Could not open %s (%d)\n", imgfile1.c_str(), filerr);
+ printf("Could not open %s (%d)\n", imgfile1.c_str(), int(filerr));
goto error;
}
@@ -98,9 +98,9 @@ static int generate_png_diff(const std::string& imgfile1, const std::string& img
/* open the source image */
filerr = util::core_file::open(imgfile2.c_str(), OPEN_FLAG_READ, file);
- if (filerr != FILERR_NONE)
+ if (filerr != osd_file::error::NONE)
{
- printf("Could not open %s (%d)\n", imgfile2.c_str(), filerr);
+ printf("Could not open %s (%d)\n", imgfile2.c_str(), int(filerr));
goto error;
}
@@ -171,9 +171,9 @@ static int generate_png_diff(const std::string& imgfile1, const std::string& img
/* write the final PNG */
filerr = util::core_file::open(outfilename.c_str(), OPEN_FLAG_WRITE | OPEN_FLAG_CREATE, file);
- if (filerr != FILERR_NONE)
+ if (filerr != osd_file::error::NONE)
{
- printf("Could not open %s (%d)\n", outfilename.c_str(), filerr);
+ printf("Could not open %s (%d)\n", outfilename.c_str(), int(filerr));
goto error;
}
pngerr = png_write_bitmap(*file, nullptr, finalbitmap, 0, nullptr);
@@ -193,6 +193,6 @@ static int generate_png_diff(const std::string& imgfile1, const std::string& img
error:
if (error == -1)
- osd_rmfile(outfilename.c_str());
+ osd_file::remove(outfilename);
return error;
}
diff --git a/src/tools/regrep.cpp b/src/tools/regrep.cpp
index b0cad2497ae..4d02151672b 100644
--- a/src/tools/regrep.cpp
+++ b/src/tools/regrep.cpp
@@ -235,7 +235,7 @@ int main(int argc, char *argv[])
/* read the template file into an astring */
std::string tempheader;
- if (util::core_file::load(tempfilename.c_str(), &buffer, bufsize) == FILERR_NONE)
+ if (util::core_file::load(tempfilename.c_str(), &buffer, bufsize) == osd_file::error::NONE)
{
tempheader.assign((const char *)buffer, bufsize);
osd_free(buffer);
@@ -565,7 +565,7 @@ static util::core_file::ptr create_file_and_output_header(std::string &filename,
util::core_file::ptr file;
/* create the indexfile */
- if (util::core_file::open(filename.c_str(), OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS | OPEN_FLAG_NO_BOM, file) != FILERR_NONE)
+ if (util::core_file::open(filename.c_str(), OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS | OPEN_FLAG_NO_BOM, file) != osd_file::error::NONE)
return util::core_file::ptr();
/* print a header */
@@ -728,7 +728,7 @@ static int compare_screenshots(summary_file *curfile)
if (curfile->status[listnum] == STATUS_SUCCESS)
{
std::string fullname;
- file_error filerr;
+ osd_file::error filerr;
util::core_file::ptr file;
/* get the filename for the image */
@@ -738,7 +738,7 @@ static int compare_screenshots(summary_file *curfile)
filerr = util::core_file::open(fullname.c_str(), OPEN_FLAG_READ, file);
/* if that failed, look in the old location */
- if (filerr != FILERR_NONE)
+ if (filerr != osd_file::error::NONE)
{
/* get the filename for the image */
fullname = string_format("%s" PATH_SEPARATOR "snap" PATH_SEPARATOR "_%s.png", lists[listnum].dir, curfile->name);
@@ -748,7 +748,7 @@ static int compare_screenshots(summary_file *curfile)
}
/* if that worked, load the file */
- if (filerr == FILERR_NONE)
+ if (filerr == osd_file::error::NONE)
{
png_read_bitmap(*file, bitmaps[listnum]);
file.reset();
@@ -837,7 +837,7 @@ static int generate_png_diff(const summary_file *curfile, std::string &destdir,
int bitmapcount = 0;
int listnum, bmnum;
util::core_file::ptr file;
- file_error filerr;
+ osd_file::error filerr;
png_error pngerr;
int error = -1;
int starty;
@@ -854,7 +854,7 @@ static int generate_png_diff(const summary_file *curfile, std::string &destdir,
/* open the source image */
filerr = util::core_file::open(tempname.c_str(), OPEN_FLAG_READ, file);
- if (filerr != FILERR_NONE)
+ if (filerr != osd_file::error::NONE)
goto error;
/* load the source image */
@@ -926,7 +926,7 @@ static int generate_png_diff(const summary_file *curfile, std::string &destdir,
/* write the final PNG */
filerr = util::core_file::open(dstfilename.c_str(), OPEN_FLAG_WRITE | OPEN_FLAG_CREATE, file);
- if (filerr != FILERR_NONE)
+ if (filerr != osd_file::error::NONE)
goto error;
pngerr = png_write_bitmap(*file, nullptr, finalbitmap, 0, nullptr);
file.reset();
@@ -938,7 +938,7 @@ static int generate_png_diff(const summary_file *curfile, std::string &destdir,
error:
if (error)
- osd_rmfile(dstfilename.c_str());
+ osd_file::remove(dstfilename);
return error;
}
diff --git a/src/tools/romcmp.cpp b/src/tools/romcmp.cpp
index 4d89718abe9..a6919631cd8 100644
--- a/src/tools/romcmp.cpp
+++ b/src/tools/romcmp.cpp
@@ -393,11 +393,11 @@ static float filecompare(const fileinfo *file1,const fileinfo *file2,int mode1,i
static void readfile(const char *path,fileinfo *file)
{
- file_error filerr;
+ osd_file::error filerr;
UINT64 filesize;
UINT32 actual;
char fullname[256];
- osd_file *f = nullptr;
+ osd_file::ptr f;
if (path)
{
@@ -414,22 +414,19 @@ static void readfile(const char *path,fileinfo *file)
return;
}
- filerr = osd_open(fullname, OPEN_FLAG_READ, &f, &filesize);
- if (filerr != FILERR_NONE)
+ filerr = osd_file::open(fullname, OPEN_FLAG_READ, f, filesize);
+ if (filerr != osd_file::error::NONE)
{
- printf("%s: error %d\n", fullname, filerr);
+ printf("%s: error %d\n", fullname, int(filerr));
return;
}
- filerr = osd_read(f, file->buf, 0, file->size, &actual);
- if (filerr != FILERR_NONE)
+ filerr = f->read(file->buf, 0, file->size, actual);
+ if (filerr != osd_file::error::NONE)
{
- printf("%s: error %d\n", fullname, filerr);
- osd_close(f);
+ printf("%s: error %d\n", fullname, int(filerr));
return;
}
-
- osd_close(f);
}
@@ -493,20 +490,20 @@ static int load_files(int i, int *found, const char *path)
/* if not, try to open as a ZIP file */
else
{
- zip_file *zip;
- const zip_file_header* zipent;
- zip_error ziperr;
+ zip_file::ptr zip;
+ const zip_file::file_header* zipent;
+ zip_file::error ziperr;
/* wasn't a directory, so try to open it as a zip file */
- ziperr = zip_file_open(path, &zip);
- if (ziperr != ZIPERR_NONE)
+ ziperr = zip_file::open(path, zip);
+ if (ziperr != zip_file::error::NONE)
{
printf("Error, cannot open zip file '%s' !\n", path);
return 1;
}
/* load all files in zip file */
- for (zipent = zip_file_first_file(zip); zipent != nullptr; zipent = zip_file_next_file(zip))
+ for (zipent = zip->first_file(); zipent != nullptr; zipent = zip->next_file())
{
int size;
@@ -529,7 +526,7 @@ static int load_files(int i, int *found, const char *path)
printf("%s: out of memory!\n",file->name);
else
{
- if (zip_file_decompress(zip, (char *)file->buf, file->size) != ZIPERR_NONE)
+ if (zip->decompress(file->buf, file->size) != zip_file::error::NONE)
{
free(file->buf);
file->buf = nullptr;
@@ -545,7 +542,6 @@ static int load_files(int i, int *found, const char *path)
found[i]++;
}
}
- zip_file_close(zip);
}
return 0;
}
@@ -747,6 +743,6 @@ int CLIB_DECL main(int argc,char *argv[])
}
}
- zip_file_cache_clear();
+ zip_file::cache_clear();
return 0;
}
diff --git a/src/tools/split.cpp b/src/tools/split.cpp
index f942e1481c2..5151229edd8 100644
--- a/src/tools/split.cpp
+++ b/src/tools/split.cpp
@@ -69,7 +69,7 @@ static int split_file(const char *filename, const char *basename, UINT32 splitsi
void *splitbuffer = nullptr;
int index, partnum;
UINT64 totallength;
- file_error filerr;
+ osd_file::error filerr;
int error = 1;
// convert split size to MB
@@ -82,7 +82,7 @@ static int split_file(const char *filename, const char *basename, UINT32 splitsi
// open the file for read
filerr = util::core_file::open(filename, OPEN_FLAG_READ, infile);
- if (filerr != FILERR_NONE)
+ if (filerr != osd_file::error::NONE)
{
fprintf(stderr, "Fatal error: unable to open file '%s'\n", filename);
goto cleanup;
@@ -120,7 +120,7 @@ static int split_file(const char *filename, const char *basename, UINT32 splitsi
// create the split file
filerr = util::core_file::open(splitfilename.c_str(), OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_NO_BOM, splitfile);
- if (filerr != FILERR_NONE)
+ if (filerr != osd_file::error::NONE)
{
fprintf(stderr, "Fatal error: unable to create split file '%s'\n", splitfilename.c_str());
goto cleanup;
@@ -156,7 +156,7 @@ static int split_file(const char *filename, const char *basename, UINT32 splitsi
// create it
filerr = util::core_file::open(outfilename.c_str(), OPEN_FLAG_WRITE | OPEN_FLAG_CREATE, outfile);
- if (filerr != FILERR_NONE)
+ if (filerr != osd_file::error::NONE)
{
printf("\n");
fprintf(stderr, "Fatal error: unable to create output file '%s'\n", outfilename.c_str());
@@ -219,7 +219,7 @@ static int join_file(const char *filename, const char *outname, int write_output
std::string basepath;
util::core_file::ptr outfile, infile, splitfile;
void *splitbuffer = nullptr;
- file_error filerr;
+ osd_file::error filerr;
UINT32 splitsize;
char buffer[256];
int error = 1;
@@ -227,7 +227,7 @@ static int join_file(const char *filename, const char *outname, int write_output
// open the file for read
filerr = util::core_file::open(filename, OPEN_FLAG_READ, splitfile);
- if (filerr != FILERR_NONE)
+ if (filerr != osd_file::error::NONE)
{
fprintf(stderr, "Fatal error: unable to open file '%s'\n", filename);
goto cleanup;
@@ -268,7 +268,7 @@ static int join_file(const char *filename, const char *outname, int write_output
{
// don't overwrite the original!
filerr = util::core_file::open(outfilename.c_str(), OPEN_FLAG_READ, outfile);
- if (filerr == FILERR_NONE)
+ if (filerr == osd_file::error::NONE)
{
outfile.reset();
fprintf(stderr, "Fatal error: output file '%s' already exists\n", outfilename.c_str());
@@ -277,7 +277,7 @@ static int join_file(const char *filename, const char *outname, int write_output
// open the output for write
filerr = util::core_file::open(outfilename.c_str(), OPEN_FLAG_WRITE | OPEN_FLAG_CREATE, outfile);
- if (filerr != FILERR_NONE)
+ if (filerr != osd_file::error::NONE)
{
fprintf(stderr, "Fatal error: unable to create file '%s'\n", outfilename.c_str());
goto cleanup;
@@ -306,7 +306,7 @@ static int join_file(const char *filename, const char *outname, int write_output
// read the file's contents
infilename.insert(0, basepath);
filerr = util::core_file::load(infilename.c_str(), &splitbuffer, length);
- if (filerr != FILERR_NONE)
+ if (filerr != osd_file::error::NONE)
{
printf("\n");
fprintf(stderr, "Fatal error: unable to load file '%s'\n", infilename.c_str());
diff --git a/src/tools/src2html.cpp b/src/tools/src2html.cpp
index e95cbe11764..9b3110a212f 100644
--- a/src/tools/src2html.cpp
+++ b/src/tools/src2html.cpp
@@ -279,7 +279,7 @@ int main(int argc, char *argv[])
// read the template file into an std::string
UINT32 bufsize;
void *buffer;
- if (util::core_file::load(tempfilename.c_str(), &buffer, bufsize) == FILERR_NONE)
+ if (util::core_file::load(tempfilename.c_str(), &buffer, bufsize) == osd_file::error::NONE)
{
tempheader.assign((const char *)buffer, bufsize);
osd_free(buffer);
@@ -517,7 +517,7 @@ static int output_file(file_type type, int srcrootlen, int dstrootlen, std::stri
// open the source file
util::core_file::ptr src;
- if (util::core_file::open(srcfile.c_str(), OPEN_FLAG_READ, src) != FILERR_NONE)
+ if (util::core_file::open(srcfile.c_str(), OPEN_FLAG_READ, src) != osd_file::error::NONE)
{
fprintf(stderr, "Unable to read file '%s'\n", srcfile.c_str());
return 1;
@@ -732,7 +732,7 @@ static util::core_file::ptr create_file_and_output_header(std::string &filename,
{
// create the indexfile
util::core_file::ptr file;
- if (util::core_file::open(filename.c_str(), OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS | OPEN_FLAG_NO_BOM, file) != FILERR_NONE)
+ if (util::core_file::open(filename.c_str(), OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS | OPEN_FLAG_NO_BOM, file) != osd_file::error::NONE)
return util::core_file::ptr();
// print a header
@@ -865,7 +865,7 @@ static bool find_include_file(std::string &srcincpath, int srcrootlen, int dstro
// see if we can open it
util::core_file::ptr testfile;
- if (util::core_file::open(srcincpath.c_str(), OPEN_FLAG_READ, testfile) == FILERR_NONE)
+ if (util::core_file::open(srcincpath.c_str(), OPEN_FLAG_READ, testfile) == osd_file::error::NONE)
{
// close the file
testfile.reset();
diff --git a/src/tools/unidasm.cpp b/src/tools/unidasm.cpp
index f69de2b0864..bf0d7c42959 100644
--- a/src/tools/unidasm.cpp
+++ b/src/tools/unidasm.cpp
@@ -494,7 +494,7 @@ usage:
int main(int argc, char *argv[])
{
- file_error filerr;
+ osd_file::error filerr;
int displayendian;
int displaychunk;
UINT32 curbyte;
@@ -513,7 +513,7 @@ int main(int argc, char *argv[])
// load the file
filerr = util::core_file::load(opts.filename, &data, length);
- if (filerr != FILERR_NONE)
+ if (filerr != osd_file::error::NONE)
{
fprintf(stderr, "Error opening file '%s'\n", opts.filename);
return 1;