mirror of
https://github.com/holub/mame
synced 2025-06-29 23:48:56 +03:00
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
This commit is contained in:
parent
5fc2774703
commit
42fbb9c396
@ -120,9 +120,9 @@ project ("ocore_" .. _OPTIONS["osd"])
|
||||
MAME_DIR .. "src/osd/modules/osdmodule.cpp",
|
||||
MAME_DIR .. "src/osd/modules/osdmodule.h",
|
||||
MAME_DIR .. "src/osd/osdmini/minidir.cpp",
|
||||
MAME_DIR .. "src/osd/osdmini/minifile.cpp",
|
||||
MAME_DIR .. "src/osd/osdmini/minimisc.cpp",
|
||||
MAME_DIR .. "src/osd/osdmini/minitime.cpp",
|
||||
MAME_DIR .. "src/osd/modules/file/stdfile.cpp",
|
||||
MAME_DIR .. "src/osd/modules/sync/osdsync.cpp",
|
||||
MAME_DIR .. "src/osd/modules/sync/osdsync.h",
|
||||
MAME_DIR .. "src/osd/modules/sync/work_osd.cpp",
|
||||
|
@ -360,6 +360,7 @@ project ("osd_" .. _OPTIONS["osd"])
|
||||
MAME_DIR .. "src/osd",
|
||||
MAME_DIR .. "src/lib",
|
||||
MAME_DIR .. "src/lib/util",
|
||||
MAME_DIR .. "src/osd/modules/file",
|
||||
MAME_DIR .. "src/osd/modules/render",
|
||||
MAME_DIR .. "3rdparty",
|
||||
MAME_DIR .. "src/osd/sdl",
|
||||
@ -460,10 +461,6 @@ project ("ocore_" .. _OPTIONS["osd"])
|
||||
MAME_DIR .. "src/osd/strconv.cpp",
|
||||
MAME_DIR .. "src/osd/strconv.h",
|
||||
MAME_DIR .. "src/osd/sdl/sdldir.cpp",
|
||||
MAME_DIR .. "src/osd/sdl/sdlfile.cpp",
|
||||
MAME_DIR .. "src/osd/sdl/sdlfile.h",
|
||||
MAME_DIR .. "src/osd/sdl/sdlptty_" .. BASE_TARGETOS ..".cpp",
|
||||
MAME_DIR .. "src/osd/sdl/sdlsocket.cpp",
|
||||
MAME_DIR .. "src/osd/sdl/sdlos_" .. SDLOS_TARGETOS .. ".cpp",
|
||||
MAME_DIR .. "src/osd/modules/osdmodule.cpp",
|
||||
MAME_DIR .. "src/osd/modules/osdmodule.h",
|
||||
@ -474,6 +471,26 @@ project ("ocore_" .. _OPTIONS["osd"])
|
||||
MAME_DIR .. "src/osd/modules/sync/work_osd.cpp",
|
||||
}
|
||||
|
||||
if BASE_TARGETOS=="unix" then
|
||||
files {
|
||||
MAME_DIR .. "src/osd/modules/file/posixfile.cpp",
|
||||
MAME_DIR .. "src/osd/modules/file/posixfile.h",
|
||||
MAME_DIR .. "src/osd/modules/file/posixptty.cpp",
|
||||
MAME_DIR .. "src/osd/modules/file/posixsocket.cpp",
|
||||
}
|
||||
elseif BASE_TARGETOS=="win32" then
|
||||
files {
|
||||
MAME_DIR .. "src/osd/modules/file/winfile.cpp",
|
||||
MAME_DIR .. "src/osd/modules/file/winfile.h",
|
||||
MAME_DIR .. "src/osd/modules/file/winptty.cpp",
|
||||
MAME_DIR .. "src/osd/modules/file/winsocket.cpp",
|
||||
}
|
||||
else
|
||||
files {
|
||||
MAME_DIR .. "src/osd/modules/file/stdfile.cpp",
|
||||
}
|
||||
end
|
||||
|
||||
if _OPTIONS["targetos"]=="macosx" then
|
||||
files {
|
||||
MAME_DIR .. "src/osd/sdl/osxutils.h",
|
||||
|
@ -144,6 +144,7 @@ project ("osd_" .. _OPTIONS["osd"])
|
||||
MAME_DIR .. "src/osd",
|
||||
MAME_DIR .. "src/lib",
|
||||
MAME_DIR .. "src/lib/util",
|
||||
MAME_DIR .. "src/osd/modules/file",
|
||||
MAME_DIR .. "src/osd/modules/render",
|
||||
MAME_DIR .. "3rdparty",
|
||||
}
|
||||
@ -220,6 +221,7 @@ project ("ocore_" .. _OPTIONS["osd"])
|
||||
MAME_DIR .. "3rdparty",
|
||||
MAME_DIR .. "src/emu",
|
||||
MAME_DIR .. "src/osd",
|
||||
MAME_DIR .. "src/osd/modules/file",
|
||||
MAME_DIR .. "src/lib",
|
||||
MAME_DIR .. "src/lib/util",
|
||||
}
|
||||
@ -245,19 +247,19 @@ project ("ocore_" .. _OPTIONS["osd"])
|
||||
MAME_DIR .. "src/osd/strconv.h",
|
||||
MAME_DIR .. "src/osd/windows/main.cpp",
|
||||
MAME_DIR .. "src/osd/windows/windir.cpp",
|
||||
MAME_DIR .. "src/osd/windows/winfile.cpp",
|
||||
MAME_DIR .. "src/osd/modules/sync/osdsync.cpp",
|
||||
MAME_DIR .. "src/osd/modules/sync/osdsync.h",
|
||||
MAME_DIR .. "src/osd/windows/winutf8.cpp",
|
||||
MAME_DIR .. "src/osd/windows/winutf8.h",
|
||||
MAME_DIR .. "src/osd/windows/winutil.cpp",
|
||||
MAME_DIR .. "src/osd/windows/winutil.h",
|
||||
MAME_DIR .. "src/osd/windows/winfile.h",
|
||||
MAME_DIR .. "src/osd/windows/winclip.cpp",
|
||||
MAME_DIR .. "src/osd/windows/winsocket.cpp",
|
||||
MAME_DIR .. "src/osd/windows/winptty.cpp",
|
||||
MAME_DIR .. "src/osd/modules/osdmodule.cpp",
|
||||
MAME_DIR .. "src/osd/modules/osdmodule.h",
|
||||
MAME_DIR .. "src/osd/modules/file/winfile.cpp",
|
||||
MAME_DIR .. "src/osd/modules/file/winfile.h",
|
||||
MAME_DIR .. "src/osd/modules/file/winptty.cpp",
|
||||
MAME_DIR .. "src/osd/modules/file/winsocket.cpp",
|
||||
MAME_DIR .. "src/osd/modules/lib/osdlib_win32.cpp",
|
||||
MAME_DIR .. "src/osd/modules/sync/work_osd.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:
|
||||
|
@ -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;
|
||||
|
@ -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 };
|
||||
|
||||
|
@ -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 };
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
};
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
};
|
||||
|
@ -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();
|
||||
|
@ -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;
|
||||
|
@ -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();
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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());
|
||||
|
||||
|
@ -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)
|
||||
{
|
||||
// loop over entries in the .7z, skipping empty files and directories
|
||||
for (int i = 0; i < _7z->db.db.NumFiles; i++)
|
||||
{
|
||||
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];
|
||||
}
|
||||
std::vector<std::uint8_t> data;
|
||||
|
||||
if (!(f->IsDir) && (f->Size != 0))
|
||||
// loop over entries in the .7z, skipping empty files and directories
|
||||
for (int i = _7z->first_file(); i >= 0; i = _7z->next_file())
|
||||
{
|
||||
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);
|
||||
|
@ -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 */
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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 */
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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());
|
||||
|
@ -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());
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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();
|
||||
|
@ -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());
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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();
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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();
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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())
|
||||
{
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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"));
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -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 */
|
||||
public:
|
||||
|
||||
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 */
|
||||
/***********************************************************************
|
||||
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
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
@ -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
|
||||
|
@ -1,5 +1,5 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:Aaron Giles
|
||||
// copyright-holders:Aaron Giles, Vas Crabb
|
||||
/***************************************************************************
|
||||
|
||||
un7z.c
|
||||
@ -10,450 +10,235 @@
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void File_Construct(CSzFile *p)
|
||||
{
|
||||
p->_7z_osdfile = nullptr;
|
||||
}
|
||||
|
||||
static WRes File_Open(CSzFile *p, const char *name, int writeMode)
|
||||
{
|
||||
/* we handle this ourselves ... */
|
||||
if (!p->_7z_osdfile) return 1;
|
||||
else return 0;
|
||||
}
|
||||
|
||||
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); }
|
||||
|
||||
|
||||
WRes File_Close(CSzFile *p)
|
||||
{
|
||||
/* we handle this ourselves ... */
|
||||
return 0;
|
||||
}
|
||||
|
||||
WRes File_Read(CSzFile *p, void *data, size_t *size)
|
||||
{
|
||||
// file_error err;
|
||||
UINT32 read_length;
|
||||
|
||||
if (!p->_7z_osdfile)
|
||||
WRes read(void *data, std::size_t &size)
|
||||
{
|
||||
printf("un7z.c: called File_Read without file\n");
|
||||
return 1;
|
||||
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;
|
||||
|
||||
if (size == originalSize)
|
||||
return 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t originalSize = *size;
|
||||
if (originalSize == 0)
|
||||
WRes seek(Int64 &pos, ESzSeek origin)
|
||||
{
|
||||
if (origin == 0) currfpos = pos;
|
||||
if (origin == 1) currfpos = currfpos + pos;
|
||||
if (origin == 2) currfpos = length -pos;
|
||||
|
||||
pos = currfpos;
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
// err =
|
||||
osd_read( p->_7z_osdfile, data, p->_7z_currfpos, originalSize, &read_length );
|
||||
*size = read_length;
|
||||
p->_7z_currfpos += read_length;
|
||||
|
||||
if (*size == originalSize)
|
||||
return 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
WRes File_Write(CSzFile *p, const void *data, size_t *size)
|
||||
struct CFileInStream : public ISeekInStream, public CSzFile
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
CFileInStream();
|
||||
};
|
||||
|
||||
WRes File_Seek(CSzFile *p, Int64 *pos, ESzSeek origin)
|
||||
|
||||
class m7z_file_impl
|
||||
{
|
||||
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;
|
||||
public:
|
||||
typedef std::unique_ptr<m7z_file_impl> ptr;
|
||||
|
||||
*pos = p->_7z_currfpos;
|
||||
m7z_file_impl(const std::string &filename);
|
||||
~m7z_file_impl()
|
||||
{
|
||||
if (m_out_buffer)
|
||||
IAlloc_Free(&m_alloc_imp, m_out_buffer);
|
||||
if (m_inited)
|
||||
SzArEx_Free(&m_db, &m_alloc_imp);
|
||||
}
|
||||
|
||||
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()) { }
|
||||
}
|
||||
|
||||
WRes File_GetLength(CSzFile *p, UInt64 *length)
|
||||
_7z_file::error initialize();
|
||||
|
||||
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); }
|
||||
|
||||
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); }
|
||||
|
||||
const std::string ¤t_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; }
|
||||
|
||||
_7z_file::error decompress(void *buffer, std::uint32_t length);
|
||||
|
||||
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;
|
||||
|
||||
int search(int i, std::uint32_t search_crc, const std::string &search_filename, bool matchcrc, bool matchname);
|
||||
void make_utf8_name(int index);
|
||||
|
||||
static constexpr std::size_t CACHE_SIZE = 8;
|
||||
static std::array<ptr, CACHE_SIZE> s_cache;
|
||||
|
||||
const std::string m_filename; // copy of _7Z filename (for caching)
|
||||
|
||||
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
|
||||
|
||||
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;
|
||||
|
||||
// cached stuff for solid blocks
|
||||
UInt32 m_block_index;
|
||||
Byte * m_out_buffer;
|
||||
std::size_t m_out_buffer_size;
|
||||
|
||||
};
|
||||
|
||||
|
||||
class m7z_file_wrapper : public _7z_file
|
||||
{
|
||||
*length = p->_7z_length;
|
||||
return 0;
|
||||
}
|
||||
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)); }
|
||||
|
||||
/* ---------- FileSeqInStream ---------- */
|
||||
virtual int first_file() override { return m_impl->first_file(); }
|
||||
virtual int next_file() override { return m_impl->next_file(); }
|
||||
|
||||
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;
|
||||
}
|
||||
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 FileSeqInStream_CreateVTable(CFileSeqInStream *p)
|
||||
{
|
||||
p->s.Read = FileSeqInStream_Read;
|
||||
}
|
||||
virtual const std::string ¤t_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(); }
|
||||
|
||||
virtual error decompress(void *buffer, std::uint32_t length) override { return m_impl->decompress(buffer, length); }
|
||||
|
||||
/* ---------- FileInStream ---------- */
|
||||
private:
|
||||
m7z_file_impl::ptr m_impl;
|
||||
};
|
||||
|
||||
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)
|
||||
{
|
||||
p->s.Read = FileInStream_Read;
|
||||
p->s.Seek = FileInStream_Seek;
|
||||
}
|
||||
|
||||
/* ---------- FileOutStream ---------- */
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
void FileOutStream_CreateVTable(CFileOutStream *p)
|
||||
{
|
||||
p->s.Write = FileOutStream_Write;
|
||||
}
|
||||
|
||||
/***************************************************************************
|
||||
CONSTANTS
|
||||
***************************************************************************/
|
||||
|
||||
/* number of open files to cache */
|
||||
#define _7Z_CACHE_SIZE 8
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
GLOBAL VARIABLES
|
||||
***************************************************************************/
|
||||
|
||||
static _7z_file *_7z_cache[_7Z_CACHE_SIZE];
|
||||
std::array<m7z_file_impl::ptr, m7z_file_impl::CACHE_SIZE> m7z_file_impl::s_cache;
|
||||
|
||||
/***************************************************************************
|
||||
FUNCTION PROTOTYPES
|
||||
***************************************************************************/
|
||||
|
||||
/* 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
|
||||
-------------------------------------------------*/
|
||||
/* ---------- FileInStream ---------- */
|
||||
|
||||
int _7z_search_crc_match(_7z_file *new_7z, UINT32 search_crc, const char* search_filename, int search_filename_length, bool matchcrc, bool matchname)
|
||||
extern "C" {
|
||||
|
||||
static void *SZipAlloc(void *p, std::size_t size)
|
||||
{
|
||||
UInt16 *temp = nullptr;
|
||||
size_t tempSize = 0;
|
||||
return (size == 0) ? nullptr : std::malloc(size);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
SZipFree(nullptr, temp);
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
|
||||
_7z_file *new_7z;
|
||||
char *string;
|
||||
int cachenum;
|
||||
|
||||
SRes res;
|
||||
|
||||
/* 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];
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
new_7z->allocImp.Alloc = SZipAlloc;
|
||||
new_7z->allocImp.Free = SZipFree;
|
||||
|
||||
new_7z->allocTempImp.Alloc = SZipAlloc;
|
||||
new_7z->allocTempImp.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);
|
||||
|
||||
new_7z->lookStream.realStream = &new_7z->archiveStream.s;
|
||||
LookToRead_Init(&new_7z->lookStream);
|
||||
|
||||
CrcGenerateTable();
|
||||
|
||||
SzArEx_Init(&new_7z->db);
|
||||
new_7z->inited = true;
|
||||
|
||||
res = SzArEx_Open(&new_7z->db, &new_7z->lookStream.s, &new_7z->allocImp, &new_7z->allocTempImp);
|
||||
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) */
|
||||
|
||||
/* 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 (reinterpret_cast<CFileInStream *>(pp)->read(buf, *size) == 0) ? SZ_OK : SZ_ERROR_READ;
|
||||
}
|
||||
|
||||
|
||||
/*-------------------------------------------------
|
||||
_7z_file_close - close a _7Z file and add it
|
||||
to the cache
|
||||
-------------------------------------------------*/
|
||||
|
||||
void _7z_file_close(_7z_file *_7z)
|
||||
static SRes FileInStream_Seek(void *pp, Int64 *pos, ESzSeek origin)
|
||||
{
|
||||
int cachenum;
|
||||
|
||||
/* close the open files */
|
||||
if (_7z->archiveStream.file._7z_osdfile != nullptr)
|
||||
osd_close(_7z->archiveStream.file._7z_osdfile);
|
||||
_7z->archiveStream.file._7z_osdfile = nullptr;
|
||||
|
||||
/* find the first NULL entry in the cache */
|
||||
for (cachenum = 0; cachenum < ARRAY_LENGTH(_7z_cache); cachenum++)
|
||||
if (_7z_cache[cachenum] == nullptr)
|
||||
break;
|
||||
|
||||
/* if no room left in the cache, free the bottommost entry */
|
||||
if (cachenum == ARRAY_LENGTH(_7z_cache))
|
||||
free__7z_file(_7z_cache[--cachenum]);
|
||||
|
||||
/* 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;
|
||||
return reinterpret_cast<CFileInStream *>(pp)->seek(*pos, origin);
|
||||
}
|
||||
|
||||
} // extern "C"
|
||||
|
||||
/*-------------------------------------------------
|
||||
_7z_file_cache_clear - clear the _7Z file
|
||||
cache and free all memory
|
||||
-------------------------------------------------*/
|
||||
|
||||
void _7z_file_cache_clear(void)
|
||||
CFileInStream::CFileInStream()
|
||||
{
|
||||
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_decompress - decompress a file
|
||||
from a _7Z into the target buffer
|
||||
-------------------------------------------------*/
|
||||
|
||||
_7z_error _7z_file_decompress(_7z_file *new_7z, void *buffer, UINT32 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)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
size_t offset = 0;
|
||||
size_t outSizeProcessed = 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);
|
||||
|
||||
if (res != SZ_OK)
|
||||
return _7ZERR_FILE_ERROR;
|
||||
|
||||
memcpy(buffer, new_7z->outBuffer + offset, length);
|
||||
|
||||
return _7ZERR_NONE;
|
||||
Read = &FileInStream_Read;
|
||||
Seek = &FileInStream_Seek;
|
||||
}
|
||||
|
||||
|
||||
@ -462,33 +247,237 @@ _7z_error _7z_file_decompress(_7z_file *new_7z, void *buffer, UINT32 length)
|
||||
CACHE MANAGEMENT
|
||||
***************************************************************************/
|
||||
|
||||
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;
|
||||
|
||||
m_alloc_temp_imp.Alloc = SZipAlloc;
|
||||
m_alloc_temp_imp.Free = SZipFree;
|
||||
}
|
||||
|
||||
|
||||
_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;
|
||||
|
||||
LookToRead_CreateVTable(&m_look_stream, False);
|
||||
m_look_stream.realStream = &m_archive_stream;
|
||||
LookToRead_Init(&m_look_stream);
|
||||
|
||||
CrcGenerateTable();
|
||||
|
||||
SzArEx_Init(&m_db);
|
||||
m_inited = true;
|
||||
|
||||
SRes const res = SzArEx_Open(&m_db, &m_look_stream.s, &m_alloc_imp, &m_alloc_temp_imp);
|
||||
if (res != SZ_OK)
|
||||
return _7z_file::error::FILE_ERROR;
|
||||
|
||||
return _7z_file::error::NONE;
|
||||
}
|
||||
|
||||
|
||||
/*-------------------------------------------------
|
||||
free__7z_file - free all the data for a
|
||||
_7z_file
|
||||
_7z_file_close - close a _7Z file and add it
|
||||
to the cache
|
||||
-------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @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::close(ptr &&archive)
|
||||
{
|
||||
if (_7z != nullptr)
|
||||
if (!archive) return;
|
||||
|
||||
// close the open files
|
||||
archive->m_archive_stream.osdfile.reset();
|
||||
|
||||
// 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 == s_cache.size())
|
||||
s_cache[--cachenum].reset();
|
||||
|
||||
// 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 ACCESS
|
||||
***************************************************************************/
|
||||
|
||||
/*-------------------------------------------------
|
||||
_7z_file_decompress - decompress a file
|
||||
from a _7Z into the target buffer
|
||||
-------------------------------------------------*/
|
||||
|
||||
_7z_file::error m7z_file_impl::decompress(void *buffer, std::uint32_t length)
|
||||
{
|
||||
// make sure the file is open..
|
||||
if (!m_archive_stream.osdfile)
|
||||
{
|
||||
if (_7z->archiveStream.file._7z_osdfile != nullptr)
|
||||
osd_close(_7z->archiveStream.file._7z_osdfile);
|
||||
if (_7z->filename != nullptr)
|
||||
free((void *)_7z->filename);
|
||||
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 out_size_processed = 0;
|
||||
|
||||
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 _7z_file::error::FILE_ERROR;
|
||||
|
||||
std::memcpy(buffer, m_out_buffer + offset, length);
|
||||
|
||||
return _7z_file::error::NONE;
|
||||
}
|
||||
|
||||
|
||||
if (_7z->outBuffer) IAlloc_Free(&_7z->allocImp, _7z->outBuffer);
|
||||
if (_7z->inited) SzArEx_Free(&_7z->db, &_7z->allocImp);
|
||||
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]);
|
||||
|
||||
// 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;
|
||||
|
||||
return i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
free(_7z);
|
||||
void m7z_file_impl::make_utf8_name(int index)
|
||||
{
|
||||
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++)
|
||||
{
|
||||
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();
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
|
@ -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) */
|
||||
public:
|
||||
|
||||
int curr_file_idx; /* current file index */
|
||||
UINT64 uncompressed_length; /* current file uncompressed length */
|
||||
UINT64 crc; /* current file crc */
|
||||
// Error types
|
||||
enum class error
|
||||
{
|
||||
NONE = 0,
|
||||
OUT_OF_MEMORY,
|
||||
FILE_ERROR,
|
||||
BAD_SIGNATURE,
|
||||
DECOMPRESS_ERROR,
|
||||
FILE_TRUNCATED,
|
||||
FILE_CORRUPT,
|
||||
UNSUPPORTED,
|
||||
BUFFER_TOO_SMALL
|
||||
};
|
||||
|
||||
CFileInStream archiveStream;
|
||||
CLookToRead lookStream;
|
||||
CSzArEx db;
|
||||
SRes res;
|
||||
ISzAlloc allocImp;
|
||||
ISzAlloc allocTempImp;
|
||||
bool inited;
|
||||
typedef std::unique_ptr<_7z_file> ptr;
|
||||
|
||||
|
||||
virtual ~_7z_file();
|
||||
|
||||
/* ----- 7Z file access ----- */
|
||||
|
||||
// open a 7Z file and parse its central directory
|
||||
static error open(const std::string &filename, ptr &result);
|
||||
|
||||
// clear out all open 7Z files from the cache
|
||||
static void cache_clear();
|
||||
|
||||
|
||||
/* ----- 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
|
||||
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;
|
||||
|
||||
// information on most recently found file
|
||||
virtual const std::string ¤t_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;
|
||||
|
||||
// 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) */
|
||||
};
|
||||
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
FUNCTION PROTOTYPES
|
||||
***************************************************************************/
|
||||
|
||||
|
||||
/* ----- _7Z file access ----- */
|
||||
|
||||
/* open a _7Z file and parse its central directory */
|
||||
_7z_error _7z_file_open(const char *filename, _7z_file **_7z);
|
||||
|
||||
/* 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 */
|
||||
void _7z_file_cache_clear(void);
|
||||
|
||||
|
||||
/* ----- contained file access ----- */
|
||||
|
||||
/* 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);
|
||||
|
||||
/* decompress the most recently found file in the _7Z */
|
||||
_7z_error _7z_file_decompress(_7z_file *_7z, void *buffer, UINT32 length);
|
||||
|
||||
|
||||
#endif /* __UN_7Z_H__ */
|
||||
#endif // MAME_LIB_UTIL_UN7Z_H
|
||||
|
@ -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
|
||||
@ -94,6 +98,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,132 +295,10 @@ static inline UINT32 read_dword(UINT8 *buf)
|
||||
***************************************************************************/
|
||||
|
||||
/** @brief The zip cache[ zip cache size]. */
|
||||
static zip_file *zip_cache[ZIP_CACHE_SIZE];
|
||||
std::array<zip_file_impl::ptr, zip_file_impl::CACHE_SIZE> zip_file_impl::s_cache;
|
||||
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
FUNCTION PROTOTYPES
|
||||
***************************************************************************/
|
||||
|
||||
/* cache management */
|
||||
static void free_zip_file(zip_file *zip);
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
|
||||
/*-------------------------------------------------
|
||||
zip_file_close - close a ZIP file and add it
|
||||
to the cache
|
||||
@ -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]);
|
||||
// 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(&zip_cache[1], &zip_cache[0], cachenum * sizeof(zip_cache[0]));
|
||||
zip_cache[0] = zip;
|
||||
// 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);
|
||||
}
|
||||
|
||||
|
||||
/*-------------------------------------------------
|
||||
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;
|
||||
|
||||
/* 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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
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;
|
||||
// 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 */
|
||||
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)
|
||||
// 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,79 +447,44 @@ 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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
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 > m_length)
|
||||
buflen = m_length;
|
||||
|
||||
/* max out the buffer length at the size of the file */
|
||||
if (buflen > zip->length)
|
||||
buflen = zip->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; }
|
||||
|
||||
/* allocate buffer */
|
||||
buffer = (UINT8 *)malloc(buflen + 1);
|
||||
if (buffer == nullptr)
|
||||
return ZIPERR_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;
|
||||
|
||||
/* 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 */
|
||||
// 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
|
||||
auto const ziperr = reopen();
|
||||
if (ziperr != zip_file::error::NONE)
|
||||
return ziperr;
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
/* 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;
|
||||
std::uint32_t 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;
|
||||
// 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 ZIPERR_NONE;
|
||||
return zip_file::error::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()
|
||||
{
|
||||
}
|
||||
|
@ -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 */
|
||||
public:
|
||||
|
||||
UINT8 * raw; /* pointer to the raw data */
|
||||
UINT32 rawlength; /* length of the raw data */
|
||||
UINT8 saved; /* saved byte from after filename */
|
||||
// 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;
|
||||
};
|
||||
|
||||
|
||||
/* 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 */
|
||||
};
|
||||
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
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
|
||||
|
@ -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(), ¤t_entry_type);
|
||||
zippath_find_sub_path(*zipfile, newpath.c_str(), ¤t_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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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();
|
||||
|
@ -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;
|
||||
|
482
src/osd/modules/file/posixfile.cpp
Normal file
482
src/osd/modules/file/posixfile.cpp
Normal file
@ -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;
|
||||
}
|
||||
}
|
28
src/osd/modules/file/posixfile.h
Normal file
28
src/osd/modules/file/posixfile.h
Normal file
@ -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);
|
184
src/osd/modules/file/posixptty.cpp
Normal file
184
src/osd/modules/file/posixptty.cpp
Normal file
@ -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;
|
||||
}
|
||||
}
|
236
src/osd/modules/file/posixsocket.cpp
Normal file
236
src/osd/modules/file/posixsocket.cpp
Normal file
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
251
src/osd/modules/file/stdfile.cpp
Normal file
251
src/osd/modules/file/stdfile.cpp
Normal file
@ -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;
|
||||
}
|
513
src/osd/modules/file/winfile.cpp
Normal file
513
src/osd/modules/file/winfile.cpp
Normal file
@ -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;
|
||||
}
|
34
src/osd/modules/file/winfile.h
Normal file
34
src/osd/modules/file/winfile.h
Normal file
@ -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
|
111
src/osd/modules/file/winptty.cpp
Normal file
111
src/osd/modules/file/winptty.cpp
Normal file
@ -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;
|
||||
}
|
||||
}
|
277
src/osd/modules/file/winsocket.cpp
Normal file
277
src/osd/modules/file/winsocket.cpp
Normal file
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
};
|
||||
|
||||
typedef std::unique_ptr<osd_file> ptr;
|
||||
|
||||
|
||||
/*-----------------------------------------------------------------------------
|
||||
osd_file::open: open a new file.
|
||||
|
||||
Parameters:
|
||||
|
||||
path - path to the file to open
|
||||
|
||||
openflags - some combination of:
|
||||
|
||||
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
|
||||
|
||||
file - reference to an osd_file::ptr to receive the newly-opened file
|
||||
handle; this is only valid if the function returns FILERR_NONE
|
||||
|
||||
filesize - reference to a UINT64 to receive the size of the opened
|
||||
file; this is only valid if the function returns FILERR_NONE
|
||||
|
||||
Return value:
|
||||
|
||||
a file_error describing any error that occurred while opening
|
||||
the file, or FILERR_NONE if no error occurred
|
||||
|
||||
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_file::openpty: create a new PTY pair
|
||||
|
||||
Parameters:
|
||||
|
||||
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
|
||||
|
||||
name - reference to string where slave filename will be stored
|
||||
|
||||
Return value:
|
||||
|
||||
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);
|
||||
|
||||
|
||||
/*-----------------------------------------------------------------------------
|
||||
osd_file::~osd_file: close an open file
|
||||
-----------------------------------------------------------------------------*/
|
||||
virtual ~osd_file() { }
|
||||
|
||||
|
||||
/*-----------------------------------------------------------------------------
|
||||
osd_file::read: read from an open file
|
||||
|
||||
Parameters:
|
||||
|
||||
buffer - pointer to memory that will receive the data read
|
||||
|
||||
offset - offset within the file to read from
|
||||
|
||||
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
|
||||
|
||||
Return value:
|
||||
|
||||
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;
|
||||
|
||||
|
||||
/*-----------------------------------------------------------------------------
|
||||
osd_file::write: write to an open file
|
||||
|
||||
Parameters:
|
||||
|
||||
buffer - pointer to memory that contains the data to write
|
||||
|
||||
offset - offset within the file to write to
|
||||
|
||||
length - number of bytes to write to the file
|
||||
|
||||
actual - reference to a UINT32 to receive the number of bytes actually
|
||||
written during the operation; valid only if the function returns
|
||||
FILERR_NONE
|
||||
|
||||
Return value:
|
||||
|
||||
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;
|
||||
|
||||
|
||||
/*-----------------------------------------------------------------------------
|
||||
osd_file::truncate: change the size of an open file
|
||||
|
||||
Parameters:
|
||||
|
||||
. offset - future size of the file
|
||||
|
||||
Return value:
|
||||
|
||||
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;
|
||||
|
||||
|
||||
/*-----------------------------------------------------------------------------
|
||||
osd_file::flush: flush file buffers
|
||||
|
||||
Parameters:
|
||||
|
||||
file - handle to a file previously opened via osd_open
|
||||
|
||||
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_file::remove: deletes a file
|
||||
|
||||
Parameters:
|
||||
|
||||
filename - path to file to delete
|
||||
|
||||
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);
|
||||
};
|
||||
|
||||
/* osd_file is an opaque type which represents an open file */
|
||||
struct osd_file;
|
||||
|
||||
/*-----------------------------------------------------------------------------
|
||||
osd_open: open a new file.
|
||||
|
||||
Parameters:
|
||||
|
||||
path - path to the file to open
|
||||
|
||||
openflags - some combination of:
|
||||
|
||||
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
|
||||
|
||||
file - pointer to an osd_file * to receive the newly-opened file
|
||||
handle; this is only valid if the function returns FILERR_NONE
|
||||
|
||||
filesize - pointer to a UINT64 to receive the size of the opened
|
||||
file; this is only valid if the function returns FILERR_NONE
|
||||
|
||||
Return value:
|
||||
|
||||
a file_error describing any error that occurred while opening
|
||||
the file, or FILERR_NONE if no error occurred
|
||||
|
||||
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).
|
||||
-----------------------------------------------------------------------------*/
|
||||
file_error osd_open(const char *path, UINT32 openflags, osd_file **file, UINT64 *filesize);
|
||||
|
||||
|
||||
/*-----------------------------------------------------------------------------
|
||||
osd_close: close an open file
|
||||
|
||||
Parameters:
|
||||
|
||||
file - handle to a file previously opened via osd_open
|
||||
|
||||
Return value:
|
||||
|
||||
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);
|
||||
|
||||
|
||||
/*-----------------------------------------------------------------------------
|
||||
osd_read: read from an open file
|
||||
|
||||
Parameters:
|
||||
|
||||
file - handle to a file previously opened via osd_open
|
||||
|
||||
buffer - pointer to memory that will receive the data read
|
||||
|
||||
offset - offset within the file to read from
|
||||
|
||||
length - number of bytes to read from the file
|
||||
|
||||
actual - pointer to a UINT32 to receive the number of bytes actually
|
||||
read during the operation; valid only if the function returns
|
||||
FILERR_NONE
|
||||
|
||||
Return value:
|
||||
|
||||
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);
|
||||
|
||||
|
||||
/*-----------------------------------------------------------------------------
|
||||
osd_write: write to an open file
|
||||
|
||||
Parameters:
|
||||
|
||||
file - handle to a file previously opened via osd_open
|
||||
|
||||
buffer - pointer to memory that contains the data to write
|
||||
|
||||
offset - offset within the file to write to
|
||||
|
||||
length - number of bytes to write to the file
|
||||
|
||||
actual - pointer to a UINT32 to receive the number of bytes actually
|
||||
written during the operation; valid only if the function returns
|
||||
FILERR_NONE
|
||||
|
||||
Return value:
|
||||
|
||||
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);
|
||||
|
||||
/*-----------------------------------------------------------------------------
|
||||
osd_openpty: create a new PTY pair
|
||||
|
||||
Parameters:
|
||||
|
||||
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
|
||||
|
||||
name_len - space allocated for name
|
||||
|
||||
Return value:
|
||||
|
||||
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);
|
||||
|
||||
/*-----------------------------------------------------------------------------
|
||||
osd_truncate: change the size of an open file
|
||||
|
||||
Parameters:
|
||||
|
||||
file - handle to a file previously opened via osd_open
|
||||
|
||||
offset - future size of the file
|
||||
|
||||
Return value:
|
||||
|
||||
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);
|
||||
|
||||
|
||||
/*-----------------------------------------------------------------------------
|
||||
osd_fflus: flush file buffers
|
||||
|
||||
Parameters:
|
||||
|
||||
file - handle to a file previously opened via osd_open
|
||||
|
||||
Return value:
|
||||
|
||||
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:
|
||||
|
||||
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
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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
|
@ -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);
|
@ -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
|
@ -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"
|
@ -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
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
@ -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__
|
@ -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;
|
||||
}
|
@ -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;
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user