summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
author Vas Crabb <vas@vastheman.com>2016-03-13 13:54:57 +1100
committer Vas Crabb <vas@vastheman.com>2016-03-14 18:55:00 +1100
commit42fbb9c3967fcda37f2d9ae17d5796a79cf027b9 (patch)
treea43047ee00431e5e22bfc5f8f612ff775586e415 /src
parent5fc27747031b6ed6f6c0582502098ebfb960be67 (diff)
Make osd_file a polymorphic class that's held with smart pointers
Make avi_file a class that's held with smart pointers, encapsulate various AVI I/O structures Make zip_file and _7z_file classes rather than having free functions everywhere Hide zip/7z class implementation behind an interface, no longer need to call close() to send back to the cache Don't dump as much crap in global namespace Add solaris PTY implementation Improve variable expansion for SDL OSD - supports ~/$FOO/${BAR} syntax Rearrange stuff so the same things are in file module for all OSDs Move file stuff into its own module 7z/zip open and destruct are still not thread-safe due to lack of interlocks around cache access Directory functions still need to be moved to file module SDL OSD may not initialise WinSock on Windows
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;