From 0c49c74ada4fee63f0bfd14710a437b23fe57991 Mon Sep 17 00:00:00 2001 From: Vas Crabb Date: Fri, 20 Aug 2021 05:47:40 +1000 Subject: srcclean: Added JSON cleaning support, and some cleanup. Made pbobble parent of bublbust, as it seems to be more widespread and more complete. Also fixed some ROM labels for bublbust. Made tbyahhoo parent of mtwinbee as the latter has substantial content removed rather than being localised, making it less complete. Applied srcclean to JSON files in bgfx subtree. --- src/tools/srcclean.cpp | 304 ++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 302 insertions(+), 2 deletions(-) (limited to 'src/tools/srcclean.cpp') diff --git a/src/tools/srcclean.cpp b/src/tools/srcclean.cpp index 7f52c3c6feb..052d2a37334 100644 --- a/src/tools/srcclean.cpp +++ b/src/tools/srcclean.cpp @@ -38,6 +38,9 @@ may have spacing adjusted in a way that affects behaviour when uncommented + Known JSON limitations: + * Doesn't detect invalid numbers or literals + Known XML limitations: * No special handling for CDATA * No special handling for processing instructions @@ -102,14 +105,20 @@ protected: static constexpr char32_t HORIZONTAL_TAB = 0x0000'0009U; static constexpr char32_t LINE_FEED = 0x0000'000aU; static constexpr char32_t VERTICAL_TAB = 0x0000'000bU; + static constexpr char32_t FORM_FEED = 0x0000'000cU; + static constexpr char32_t C0_CONTROL_LAST = 0x0000'001fU; static constexpr char32_t SPACE = 0x0000'0020U; static constexpr char32_t DOUBLE_QUOTE = 0x0000'0022U; static constexpr char32_t SINGLE_QUOTE = 0x0000'0027U; + static constexpr char32_t ASTERISK = 0x0000'002aU; static constexpr char32_t HYPHEN_MINUS = 0x0000'002dU; + static constexpr char32_t SLASH = 0x0000'002fU; static constexpr char32_t QUESTION_MARK = 0x0000'003fU; static constexpr char32_t BACKSLASH = 0x0000'005cU; static constexpr char32_t BASIC_LATIN_LAST = 0x0000'007fU; static constexpr char32_t CYRILLIC_SUPPLEMENT_LAST = 0x0000'052fU; + static constexpr char32_t LINE_SEPARATOR = 0x0000'2028U; + static constexpr char32_t PARAGRAPH_SEPARATOR = 0x0000'2029U; template cleaner_base(OutputIt &&output, newline newline_mode, unsigned tab_width); @@ -825,8 +834,6 @@ protected: void output_character(char32_t ch); private: - static constexpr char32_t ASTERISK = 0x0000'002aU; - static constexpr char32_t SLASH = 0x0000'002fU; static constexpr char32_t UPPERCASE_FIRST = 0x0000'0041U; static constexpr char32_t UPPERCASE_B = 0x0000'0042U; static constexpr char32_t UPPERCASE_X = 0x0000'0058U; @@ -1740,6 +1747,289 @@ void lua_cleaner::process_long_string_constant(char32_t ch) +/*************************************************************************** + JSON DATA CLEANER CLASS +***************************************************************************/ + +class json_cleaner : public cleaner_base +{ +public: + template + json_cleaner(OutputIt &&output, newline newline_mode, unsigned tab_width); + + virtual bool affected() const override; + virtual void summarise(std::ostream &os) const override; + +protected: + void output_character(char32_t ch); + +private: + enum class parse_state + { + DEFAULT, + COMMENT, + LINE_COMMENT, + STRING_CONSTANT + }; + + virtual void process_characters(char32_t const *begin, char32_t const *end) override; + virtual void input_complete() override; + + void process_default(char32_t ch); + void process_comment(char32_t ch); + void process_line_comment(char32_t ch); + void process_text(char32_t ch); + + parse_state m_parse_state = parse_state::DEFAULT; + std::uint64_t m_input_line = 1U; + bool m_escape = false; + std::uint64_t m_comment_line = 0U; + + std::uint64_t m_tabs_escaped = 0U; + std::uint64_t m_newlines_escaped = 0U; + std::uint64_t m_form_feeds_escaped = 0U; + std::uint64_t m_line_separators_escaped = 0U; + std::uint64_t m_paragraph_separators_escaped = 0U; + std::uint64_t m_c0_control_escaped = 0U; + std::uint64_t m_non_ascii = 0U; +}; + + +template +json_cleaner::json_cleaner( + OutputIt &&output, + newline newline_mode, + unsigned tab_width) + : cleaner_base(std::forward(output), newline_mode, tab_width) +{ +} + + +bool json_cleaner::affected() const +{ + return + cleaner_base::affected() || + m_tabs_escaped || + m_newlines_escaped || + m_form_feeds_escaped || + m_line_separators_escaped || + m_paragraph_separators_escaped || + m_c0_control_escaped || + m_non_ascii; +} + + +void json_cleaner::summarise(std::ostream &os) const +{ + cleaner_base::summarise(os); + if (m_tabs_escaped) + util::stream_format(os, "%1$u tab(s) escaped\n", m_tabs_escaped); + if (m_newlines_escaped) + util::stream_format(os, "%1$u line feed(s) escaped\n", m_newlines_escaped); + if (m_form_feeds_escaped) + util::stream_format(os, "%1$u form feed(s) escaped\n", m_form_feeds_escaped); + if (m_line_separators_escaped) + util::stream_format(os, "%1$u line separator(s) escaped\n", m_line_separators_escaped); + if (m_paragraph_separators_escaped) + util::stream_format(os, "%1$u paragraph separator(s) escaped\n", m_paragraph_separators_escaped); + if (m_c0_control_escaped) + util::stream_format(os, "%1$u C0 control character(s) escaped\n", m_c0_control_escaped); + if (m_non_ascii) + util::stream_format(os, "%1$u non-ASCII character(s) replaced\n", m_non_ascii); +} + + +void json_cleaner::output_character(char32_t ch) +{ + switch (m_parse_state) + { + case parse_state::DEFAULT: + if (BASIC_LATIN_LAST < ch) + { + ++m_non_ascii; + ch = QUESTION_MARK; + } + break; + case parse_state::COMMENT: + case parse_state::LINE_COMMENT: + case parse_state::STRING_CONSTANT: + break; + } + + cleaner_base::output_character(ch); +} + + +void json_cleaner::process_characters(char32_t const *begin, char32_t const *end) +{ + while (begin != end) + { + char32_t const ch(*begin++); + switch (m_parse_state) + { + case parse_state::DEFAULT: + process_default(ch); + break; + case parse_state::COMMENT: + process_comment(ch); + break; + case parse_state::LINE_COMMENT: + process_line_comment(ch); + break; + case parse_state::STRING_CONSTANT: + process_text(ch); + break; + } + + if (LINE_FEED == ch) + ++m_input_line; + } +} + + +void json_cleaner::input_complete() +{ + switch (m_parse_state) + { + case parse_state::COMMENT: + throw std::runtime_error(util::string_format("unterminated multi-line comment beginning on line %1$u", m_comment_line)); + case parse_state::STRING_CONSTANT: + throw std::runtime_error(util::string_format("unterminated string literal on line %1$u", m_input_line)); + default: + break; + } +} + + +void json_cleaner::process_default(char32_t ch) +{ + switch (ch) + { + case DOUBLE_QUOTE: + m_parse_state = parse_state::STRING_CONSTANT; + break; + case ASTERISK: + if (m_escape) + { + m_parse_state = parse_state::COMMENT; + m_comment_line = m_input_line; + set_tab_limit(); + } + break; + case SLASH: + if (m_escape) + m_parse_state = parse_state::LINE_COMMENT; + break; + } + m_escape = (SLASH == ch) && !m_escape; + output_character(ch); +} + + +void json_cleaner::process_comment(char32_t ch) +{ + switch (ch) + { + case SLASH: + if (m_escape) + { + m_parse_state = parse_state::DEFAULT; + m_comment_line = 0U; + output_character(ch); + reset_tab_limit(); + } + else + { + output_character(ch); + } + m_escape = false; + break; + default: + m_escape = ASTERISK == ch; + output_character(ch); + } +} + + +void json_cleaner::process_line_comment(char32_t ch) +{ + switch (ch) + { + case LINE_FEED: + m_parse_state = parse_state::DEFAULT; + [[fallthrough]]; + default: + output_character(ch); + } +} + + +void json_cleaner::process_text(char32_t ch) +{ + switch (ch) + { + case HORIZONTAL_TAB: + ++m_tabs_escaped; + if (!m_escape) + output_character(BACKSLASH); + output_character(char32_t(std::uint8_t('t'))); + break; + case LINE_FEED: + ++m_newlines_escaped; + if (!m_escape) + output_character(BACKSLASH); + output_character(char32_t(std::uint8_t('n'))); + break; + case FORM_FEED: + ++m_form_feeds_escaped; + if (!m_escape) + output_character(BACKSLASH); + output_character(char32_t(std::uint8_t('f'))); + break; + case LINE_SEPARATOR: + ++m_line_separators_escaped; + if (!m_escape) + output_character(BACKSLASH); + output_character(char32_t(std::uint8_t('u'))); + output_character(char32_t(std::uint8_t('2'))); + output_character(char32_t(std::uint8_t('0'))); + output_character(char32_t(std::uint8_t('2'))); + output_character(char32_t(std::uint8_t('8'))); + break; + case PARAGRAPH_SEPARATOR: + ++m_paragraph_separators_escaped; + if (!m_escape) + output_character(BACKSLASH); + output_character(char32_t(std::uint8_t('u'))); + output_character(char32_t(std::uint8_t('2'))); + output_character(char32_t(std::uint8_t('0'))); + output_character(char32_t(std::uint8_t('2'))); + output_character(char32_t(std::uint8_t('9'))); + break; + default: + if (C0_CONTROL_LAST >= ch) + { + ++m_c0_control_escaped; + if (!m_escape) + output_character(BACKSLASH); + output_character(char32_t(std::uint8_t('u'))); + output_character(char32_t(std::uint8_t('0'))); + output_character(char32_t(std::uint8_t('0'))); + output_character(char32_t(std::uint8_t('0') + (ch / 0x10U))); + output_character(char32_t(std::uint8_t('0') + (ch % 0x10U))); + } + else + { + output_character(ch); + if (!m_escape && (DOUBLE_QUOTE == ch)) + m_parse_state = parse_state::DEFAULT; + } + } + m_escape = (BACKSLASH == ch) && !m_escape; +} + + + /*************************************************************************** XML DATA CLEANER CLASS ***************************************************************************/ @@ -1894,6 +2184,13 @@ bool is_lua_source_extension(char const *ext) } +bool is_json_extension(char const *ext) +{ + return + !core_stricmp(ext, ".json"); +} + + bool is_xml_extension(char const *ext) { return @@ -1974,12 +2271,15 @@ int main(int argc, char *argv[]) char const *const ext(std::strrchr(argv[i], '.')); bool const is_c_file(ext && is_c_source_extension(ext)); bool const is_lua_file(ext && is_lua_source_extension(ext)); + bool const is_json_file(ext && is_json_extension(ext)); bool const is_xml_file(ext && is_xml_extension(ext)); std::unique_ptr cleaner; if (is_c_file) cleaner = std::make_unique(std::back_inserter(output), newline_mode, 4U); else if (is_lua_file) cleaner = std::make_unique(std::back_inserter(output), newline_mode, 4U); + else if (is_json_file) + cleaner = std::make_unique(std::back_inserter(output), newline_mode, 4U); else if (is_xml_file) cleaner = std::make_unique(std::back_inserter(output), newline_mode, 4U); else -- cgit v1.2.3 From e8bbea1fc6e94e14768509d322f6c624403ffb36 Mon Sep 17 00:00:00 2001 From: Vas Crabb Date: Sun, 22 Aug 2021 09:06:15 +1000 Subject: formats, osd, util: Started refactoring file I/O stuff. (#8456) Added more modern generic I/O interfaces with implementation backed by stdio, osd_file and core_file, replacing io_generic. Also replaced core_file's build-in zlib compression with a filter. unzip.cpp, un7z.cpp: Added option to supply abstract I/O interface rather than filename. Converted osd_file, core_file, archive_file, chd_file and device_image_interface to use std::error_condition rather than their own error enums. Allow mounting TI-99 RPK from inside archives. --- scripts/src/formats.lua | 2 - scripts/src/lib.lua | 9 + scripts/src/osd/mac.lua | 1 - scripts/src/osd/sdl.lua | 1 - src/devices/bus/a7800/a78_slot.cpp | 2 +- src/devices/bus/acorn/system/8k.cpp | 2 +- src/devices/bus/apf/slot.cpp | 2 +- src/devices/bus/aquarius/slot.cpp | 2 +- src/devices/bus/ata/idehd.cpp | 2 +- src/devices/bus/bbc/1mhzbus/datacentre.cpp | 2 +- src/devices/bus/bbc/rom/slot.cpp | 2 +- src/devices/bus/c64/exp.cpp | 2 +- src/devices/bus/cgenie/expansion/floppy.cpp | 2 +- src/devices/bus/coco/coco_dwsock.cpp | 41 +- src/devices/bus/crvision/slot.cpp | 2 +- src/devices/bus/electron/cart/ap5.cpp | 2 +- src/devices/bus/electron/cart/romp144.cpp | 2 +- src/devices/bus/electron/cart/slot.cpp | 4 +- src/devices/bus/electron/plus1.cpp | 2 +- src/devices/bus/electron/plus2.cpp | 2 +- src/devices/bus/electron/rombox.cpp | 2 +- src/devices/bus/electron/romboxp.cpp | 2 +- src/devices/bus/electron/sidewndr.cpp | 2 +- src/devices/bus/gamate/slot.cpp | 2 +- src/devices/bus/gameboy/gb_slot.cpp | 2 +- src/devices/bus/gba/gba_slot.cpp | 2 +- src/devices/bus/isa/sc499.cpp | 25 +- src/devices/bus/m5/slot.cpp | 2 +- src/devices/bus/mc10/mc10_cart.cpp | 6 +- src/devices/bus/msx_slot/cartridge.cpp | 2 +- src/devices/bus/nes/nes_slot.cpp | 2 +- src/devices/bus/nubus/nubus_image.cpp | 10 +- src/devices/bus/plus4/exp.cpp | 2 +- src/devices/bus/scv/slot.cpp | 2 +- src/devices/bus/sega8/sega8_slot.cpp | 2 +- src/devices/bus/spectrum/intf2.cpp | 2 +- src/devices/bus/ti99/gromport/cartridges.cpp | 55 +- src/devices/bus/ti99/gromport/cartridges.h | 13 +- src/devices/bus/vboy/slot.cpp | 6 +- src/devices/bus/vc4000/slot.cpp | 2 +- src/devices/bus/vcs/vcs_slot.cpp | 2 +- src/devices/bus/vectrex/slot.cpp | 4 +- src/devices/bus/vsmile/vsmile_slot.cpp | 2 +- src/devices/imagedev/cassette.cpp | 118 ++- src/devices/imagedev/chd_cd.cpp | 23 +- src/devices/imagedev/diablo.cpp | 42 +- src/devices/imagedev/flopdrv.cpp | 80 +- src/devices/imagedev/floppy.cpp | 144 +-- src/devices/imagedev/harddriv.cpp | 52 +- src/devices/imagedev/mfmhd.cpp | 30 +- src/devices/imagedev/mfmhd.h | 6 +- src/devices/imagedev/midiin.cpp | 2 +- src/devices/machine/ataflash.cpp | 6 +- src/devices/machine/ch376.cpp | 2 +- src/devices/machine/hp_dc100_tape.cpp | 47 +- src/devices/machine/laserdsc.cpp | 27 +- src/devices/machine/laserdsc.h | 26 +- src/devices/sound/samples.cpp | 18 +- src/emu/addrmap.h | 2 +- src/emu/config.cpp | 20 +- src/emu/crsshair.cpp | 6 +- src/emu/debug/debugcmd.cpp | 6 +- src/emu/debug/debugcpu.cpp | 8 +- src/emu/devcb.h | 104 +- src/emu/devdelegate.h | 16 +- src/emu/devfind.h | 2 +- src/emu/device.h | 12 +- src/emu/diimage.cpp | 207 ++-- src/emu/diimage.h | 33 +- src/emu/dimemory.h | 10 +- src/emu/dipty.cpp | 9 +- src/emu/dipty.h | 8 +- src/emu/fileio.cpp | 69 +- src/emu/fileio.h | 26 +- src/emu/hashfile.cpp | 4 +- src/emu/http.cpp | 6 +- src/emu/image.cpp | 4 +- src/emu/ioport.cpp | 77 +- src/emu/ioport.h | 9 +- src/emu/machine.cpp | 16 +- src/emu/render.cpp | 5 +- src/emu/rendfont.cpp | 16 +- src/emu/rendlay.cpp | 41 +- src/emu/romload.cpp | 70 +- src/emu/romload.h | 13 +- src/emu/save.cpp | 55 +- src/emu/save.h | 8 +- src/emu/screen.cpp | 6 +- src/emu/softlist_dev.cpp | 6 +- src/emu/uiinput.h | 2 +- src/emu/video.cpp | 26 +- src/emu/video.h | 4 +- src/frontend/mame/audit.cpp | 16 +- src/frontend/mame/cheat.cpp | 6 +- src/frontend/mame/clifront.cpp | 6 +- src/frontend/mame/language.cpp | 2 +- src/frontend/mame/luaengine.cpp | 52 +- src/frontend/mame/luaengine.ipp | 8 +- src/frontend/mame/mame.cpp | 6 +- src/frontend/mame/mameopts.cpp | 4 +- src/frontend/mame/media_ident.cpp | 16 +- src/frontend/mame/ui/auditmenu.cpp | 2 +- src/frontend/mame/ui/filesel.cpp | 12 +- src/frontend/mame/ui/floppycntrl.cpp | 5 +- src/frontend/mame/ui/imgcntrl.cpp | 2 +- src/frontend/mame/ui/inifile.cpp | 8 +- src/frontend/mame/ui/menu.cpp | 4 +- src/frontend/mame/ui/miscmenu.cpp | 18 +- src/frontend/mame/ui/optsmenu.cpp | 2 +- src/frontend/mame/ui/selgame.cpp | 12 +- src/frontend/mame/ui/selmenu.cpp | 30 +- src/frontend/mame/ui/selsoft.cpp | 8 +- src/frontend/mame/ui/state.cpp | 10 +- src/frontend/mame/ui/ui.cpp | 13 +- src/lib/formats/acorn_dsk.cpp | 216 ++-- src/lib/formats/acorn_dsk.h | 30 +- src/lib/formats/afs_dsk.cpp | 3 +- src/lib/formats/afs_dsk.h | 2 +- src/lib/formats/aim_dsk.cpp | 19 +- src/lib/formats/aim_dsk.h | 11 +- src/lib/formats/ami_dsk.cpp | 80 +- src/lib/formats/ami_dsk.h | 6 +- src/lib/formats/ap2_dsk.cpp | 141 +-- src/lib/formats/ap2_dsk.h | 26 +- src/lib/formats/ap_dsk35.cpp | 83 +- src/lib/formats/ap_dsk35.h | 18 +- src/lib/formats/apd_dsk.cpp | 26 +- src/lib/formats/apd_dsk.h | 4 +- src/lib/formats/apollo_dsk.cpp | 14 +- src/lib/formats/apollo_dsk.h | 2 +- src/lib/formats/apridisk.cpp | 24 +- src/lib/formats/apridisk.h | 6 +- src/lib/formats/cassimg.cpp | 79 +- src/lib/formats/cassimg.h | 22 +- src/lib/formats/ccvf_dsk.cpp | 19 +- src/lib/formats/ccvf_dsk.h | 4 +- src/lib/formats/concept_dsk.cpp | 49 +- src/lib/formats/concept_dsk.h | 8 +- src/lib/formats/coupedsk.cpp | 28 +- src/lib/formats/coupedsk.h | 6 +- src/lib/formats/cqm_dsk.cpp | 36 +- src/lib/formats/cqm_dsk.h | 6 +- src/lib/formats/d64_dsk.cpp | 33 +- src/lib/formats/d64_dsk.h | 10 +- src/lib/formats/d80_dsk.cpp | 5 +- src/lib/formats/d88_dsk.cpp | 35 +- src/lib/formats/d88_dsk.h | 6 +- src/lib/formats/dcp_dsk.cpp | 28 +- src/lib/formats/dcp_dsk.h | 4 +- src/lib/formats/dfi_dsk.cpp | 25 +- src/lib/formats/dfi_dsk.h | 6 +- src/lib/formats/dim_dsk.cpp | 22 +- src/lib/formats/dim_dsk.h | 6 +- src/lib/formats/dip_dsk.cpp | 16 +- src/lib/formats/dip_dsk.h | 4 +- src/lib/formats/dmk_dsk.cpp | 27 +- src/lib/formats/dmk_dsk.h | 6 +- src/lib/formats/ds9_dsk.cpp | 24 +- src/lib/formats/ds9_dsk.h | 13 +- src/lib/formats/dsk_dsk.cpp | 35 +- src/lib/formats/dsk_dsk.h | 4 +- src/lib/formats/dvk_mx_dsk.cpp | 25 +- src/lib/formats/dvk_mx_dsk.h | 13 +- src/lib/formats/esq16_dsk.cpp | 40 +- src/lib/formats/esq16_dsk.h | 8 +- src/lib/formats/esq8_dsk.cpp | 38 +- src/lib/formats/esq8_dsk.h | 8 +- src/lib/formats/fdd_dsk.cpp | 18 +- src/lib/formats/fdd_dsk.h | 4 +- src/lib/formats/flex_dsk.cpp | 22 +- src/lib/formats/flex_dsk.h | 4 +- src/lib/formats/flopimg.cpp | 77 +- src/lib/formats/flopimg.h | 24 +- src/lib/formats/fsd_dsk.cpp | 16 +- src/lib/formats/fsd_dsk.h | 4 +- src/lib/formats/g64_dsk.cpp | 45 +- src/lib/formats/g64_dsk.h | 6 +- src/lib/formats/hpi_dsk.cpp | 23 +- src/lib/formats/hpi_dsk.h | 6 +- src/lib/formats/hti_tape.cpp | 52 +- src/lib/formats/hti_tape.h | 12 +- src/lib/formats/hxchfe_dsk.cpp | 26 +- src/lib/formats/hxchfe_dsk.h | 6 +- src/lib/formats/hxcmfm_dsk.cpp | 28 +- src/lib/formats/hxcmfm_dsk.h | 6 +- src/lib/formats/ibmxdf_dsk.cpp | 17 +- src/lib/formats/ibmxdf_dsk.h | 6 +- src/lib/formats/imd_dsk.cpp | 76 +- src/lib/formats/imd_dsk.h | 6 +- src/lib/formats/img_dsk.cpp | 22 +- src/lib/formats/img_dsk.h | 6 +- src/lib/formats/ioprocs.cpp | 214 ---- src/lib/formats/ioprocs.h | 70 -- src/lib/formats/ipf_dsk.cpp | 21 +- src/lib/formats/ipf_dsk.h | 4 +- src/lib/formats/jfd_dsk.cpp | 25 +- src/lib/formats/jfd_dsk.h | 4 +- src/lib/formats/jvc_dsk.cpp | 26 +- src/lib/formats/jvc_dsk.h | 8 +- src/lib/formats/m20_dsk.cpp | 42 +- src/lib/formats/m20_dsk.h | 6 +- src/lib/formats/mdos_dsk.cpp | 22 +- src/lib/formats/mdos_dsk.h | 4 +- src/lib/formats/mfi_dsk.cpp | 29 +- src/lib/formats/mfi_dsk.h | 6 +- src/lib/formats/mfm_hd.cpp | 17 +- src/lib/formats/mfm_hd.h | 8 +- src/lib/formats/nfd_dsk.cpp | 31 +- src/lib/formats/nfd_dsk.h | 4 +- src/lib/formats/opd_dsk.cpp | 5 +- src/lib/formats/opd_dsk.h | 2 +- src/lib/formats/oric_dsk.cpp | 53 +- src/lib/formats/oric_dsk.h | 12 +- src/lib/formats/os9_dsk.cpp | 15 +- src/lib/formats/os9_dsk.h | 4 +- src/lib/formats/pasti_dsk.cpp | 16 +- src/lib/formats/pasti_dsk.h | 4 +- src/lib/formats/pc98fdi_dsk.cpp | 54 +- src/lib/formats/pc98fdi_dsk.h | 4 +- src/lib/formats/pc_dsk.cpp | 13 +- src/lib/formats/pc_dsk.h | 2 +- src/lib/formats/poly_dsk.cpp | 31 +- src/lib/formats/poly_dsk.h | 4 +- src/lib/formats/rx50_dsk.cpp | 27 +- src/lib/formats/rx50_dsk.h | 8 +- src/lib/formats/sdd_dsk.cpp | 5 +- src/lib/formats/sdf_dsk.cpp | 23 +- src/lib/formats/sdf_dsk.h | 6 +- src/lib/formats/st_dsk.cpp | 66 +- src/lib/formats/st_dsk.h | 16 +- src/lib/formats/svi_dsk.cpp | 37 +- src/lib/formats/svi_dsk.h | 6 +- src/lib/formats/td0_dsk.cpp | 73 +- src/lib/formats/td0_dsk.h | 6 +- src/lib/formats/ti99_dsk.cpp | 75 +- src/lib/formats/ti99_dsk.h | 26 +- src/lib/formats/trd_dsk.cpp | 17 +- src/lib/formats/trd_dsk.h | 2 +- src/lib/formats/trs80_dsk.cpp | 58 +- src/lib/formats/trs80_dsk.h | 6 +- src/lib/formats/uniflex_dsk.cpp | 21 +- src/lib/formats/uniflex_dsk.h | 4 +- src/lib/formats/upd765_dsk.cpp | 21 +- src/lib/formats/upd765_dsk.h | 8 +- src/lib/formats/vdk_dsk.cpp | 42 +- src/lib/formats/vdk_dsk.h | 6 +- src/lib/formats/victor9k_dsk.cpp | 32 +- src/lib/formats/victor9k_dsk.h | 8 +- src/lib/formats/vt_dsk.cpp | 47 +- src/lib/formats/vt_dsk.h | 12 +- src/lib/formats/wd177x_dsk.cpp | 27 +- src/lib/formats/wd177x_dsk.h | 8 +- src/lib/util/avhuff.cpp | 4 +- src/lib/util/aviio.cpp | 84 +- src/lib/util/cdrom.cpp | 91 +- src/lib/util/cdrom.h | 14 +- src/lib/util/chd.cpp | 711 +++++++------- src/lib/util/chd.h | 274 +++--- src/lib/util/chdcd.cpp | 186 ++-- src/lib/util/chdcd.h | 12 +- src/lib/util/chdcodec.cpp | 260 ++--- src/lib/util/chdcodec.h | 95 +- src/lib/util/corefile.cpp | 441 ++------- src/lib/util/corefile.h | 49 +- src/lib/util/harddisk.cpp | 18 +- src/lib/util/harddisk.h | 10 +- src/lib/util/ioprocs.cpp | 1248 ++++++++++++++++++++++++ src/lib/util/ioprocs.h | 130 +++ src/lib/util/ioprocsfill.h | 163 ++++ src/lib/util/ioprocsfilter.cpp | 598 ++++++++++++ src/lib/util/ioprocsfilter.h | 31 + src/lib/util/ioprocsvec.h | 211 ++++ src/lib/util/path.cpp | 0 src/lib/util/path.h | 65 ++ src/lib/util/strformat.h | 54 +- src/lib/util/timeconv.cpp | 69 +- src/lib/util/timeconv.h | 39 +- src/lib/util/un7z.cpp | 467 +++++---- src/lib/util/unzip.cpp | 1050 +++++++++++--------- src/lib/util/unzip.h | 58 +- src/lib/util/utilfwd.h | 45 + src/lib/util/zippath.cpp | 149 ++- src/lib/util/zippath.h | 5 +- src/mame/drivers/aim65.cpp | 4 +- src/mame/drivers/alphatro.cpp | 2 +- src/mame/drivers/atom.cpp | 2 +- src/mame/drivers/beta.cpp | 2 +- src/mame/drivers/binbug.cpp | 10 +- src/mame/drivers/cc40.cpp | 2 +- src/mame/drivers/cd2650.cpp | 10 +- src/mame/drivers/d6800.cpp | 2 +- src/mame/drivers/elan_eu3a05.cpp | 2 +- src/mame/drivers/eti660.cpp | 2 +- src/mame/drivers/force68k.cpp | 2 +- src/mame/drivers/gameking.cpp | 2 +- src/mame/drivers/hh_tms1k.cpp | 4 +- src/mame/drivers/homelab.cpp | 10 +- src/mame/drivers/hx20.cpp | 2 +- src/mame/drivers/ibmpcjr.cpp | 2 +- src/mame/drivers/instruct.cpp | 10 +- src/mame/drivers/jtc.cpp | 14 +- src/mame/drivers/jupace.cpp | 4 +- src/mame/drivers/ldplayer.cpp | 9 +- src/mame/drivers/lynx.cpp | 4 +- src/mame/drivers/m68705prg.cpp | 4 +- src/mame/drivers/microvsn.cpp | 2 +- src/mame/drivers/myvision.cpp | 2 +- src/mame/drivers/nascom1.cpp | 4 +- src/mame/drivers/ngp.cpp | 2 +- src/mame/drivers/pegasus.cpp | 4 +- src/mame/drivers/phunsy.cpp | 2 +- src/mame/drivers/pipbug.cpp | 10 +- src/mame/drivers/pokemini.cpp | 4 +- src/mame/drivers/pv1000.cpp | 2 +- src/mame/drivers/pv2000.cpp | 2 +- src/mame/drivers/ravens.cpp | 10 +- src/mame/drivers/roland_cm32p.cpp | 2 +- src/mame/drivers/rx78.cpp | 2 +- src/mame/drivers/sag.cpp | 8 +- src/mame/drivers/spg2xx_ican.cpp | 2 +- src/mame/drivers/spg2xx_smarttv.cpp | 2 +- src/mame/drivers/spg2xx_telestory.cpp | 2 +- src/mame/drivers/spg2xx_tvgogo.cpp | 2 +- src/mame/drivers/spg2xx_vii.cpp | 2 +- src/mame/drivers/squale.cpp | 2 +- src/mame/drivers/studio2.cpp | 8 +- src/mame/drivers/supracan.cpp | 2 +- src/mame/drivers/sv8000.cpp | 2 +- src/mame/drivers/svision.cpp | 2 +- src/mame/drivers/ti74.cpp | 2 +- src/mame/drivers/timex.cpp | 8 +- src/mame/drivers/tispeak.cpp | 2 +- src/mame/drivers/vc4000.cpp | 16 +- src/mame/drivers/vtech1.cpp | 4 +- src/mame/drivers/x07.cpp | 2 +- src/mame/drivers/z1013.cpp | 4 +- src/mame/machine/amstrad.cpp | 4 +- src/mame/machine/electron.cpp | 2 +- src/mame/machine/gamecom.cpp | 2 +- src/mame/machine/m1comm.cpp | 10 +- src/mame/machine/m2comm.cpp | 10 +- src/mame/machine/mbee.cpp | 8 +- src/mame/machine/mtx.cpp | 12 +- src/mame/machine/s32comm.cpp | 10 +- src/mame/machine/sorcerer.cpp | 2 +- src/mame/machine/thomson.cpp | 8 +- src/mame/machine/vtech2.cpp | 2 +- src/mame/machine/z80bin.cpp | 8 +- src/mame/video/midtunit.cpp | 4 +- src/osd/modules/debugger/debuggdbstub.cpp | 4 +- src/osd/modules/debugger/debugimgui.cpp | 8 +- src/osd/modules/file/posixdomain.cpp | 208 ---- src/osd/modules/file/posixfile.cpp | 166 ++-- src/osd/modules/file/posixfile.h | 18 +- src/osd/modules/file/posixptty.cpp | 57 +- src/osd/modules/file/posixsocket.cpp | 187 ++-- src/osd/modules/file/stdfile.cpp | 104 +- src/osd/modules/file/winfile.cpp | 176 ++-- src/osd/modules/file/winfile.h | 23 +- src/osd/modules/file/winptty.cpp | 44 +- src/osd/modules/file/winsocket.cpp | 130 +-- src/osd/modules/font/font_sdl.cpp | 6 +- src/osd/modules/render/aviwrite.cpp | 4 +- src/osd/modules/render/bgfx/texturemanager.cpp | 2 +- src/osd/modules/render/d3d/d3dhlsl.cpp | 10 +- src/osd/osdfile.h | 66 +- src/tools/castool.cpp | 15 +- src/tools/chdman.cpp | 265 ++--- src/tools/floptool.cpp | 16 +- src/tools/image_handler.cpp | 116 +-- src/tools/image_handler.h | 22 +- src/tools/imgtool/iflopimg.cpp | 83 +- src/tools/imgtool/iflopimg.h | 11 +- src/tools/imgtool/imghd.cpp | 57 +- src/tools/imgtool/imghd.h | 3 + src/tools/imgtool/imgtool.cpp | 12 +- src/tools/imgtool/library.h | 28 +- src/tools/imgtool/main.cpp | 2 + src/tools/imgtool/modules/hp85_tape.cpp | 56 +- src/tools/imgtool/modules/hp9845_tape.cpp | 57 +- src/tools/imgtool/stream.cpp | 255 ++++- src/tools/imgtool/stream.h | 141 +-- src/tools/ldresample.cpp | 55 +- src/tools/ldverify.cpp | 29 +- src/tools/pngcmp.cpp | 14 +- src/tools/regrep.cpp | 16 +- src/tools/romcmp.cpp | 743 +++++++------- src/tools/split.cpp | 18 +- src/tools/srcclean.cpp | 6 +- src/tools/unidasm.cpp | 6 +- 390 files changed, 9006 insertions(+), 6553 deletions(-) delete mode 100644 src/lib/formats/ioprocs.cpp delete mode 100644 src/lib/formats/ioprocs.h create mode 100644 src/lib/util/ioprocs.cpp create mode 100644 src/lib/util/ioprocs.h create mode 100644 src/lib/util/ioprocsfill.h create mode 100644 src/lib/util/ioprocsfilter.cpp create mode 100644 src/lib/util/ioprocsfilter.h create mode 100644 src/lib/util/ioprocsvec.h create mode 100644 src/lib/util/path.cpp create mode 100644 src/lib/util/path.h create mode 100644 src/lib/util/utilfwd.h delete mode 100644 src/osd/modules/file/posixdomain.cpp (limited to 'src/tools/srcclean.cpp') diff --git a/scripts/src/formats.lua b/scripts/src/formats.lua index 5afef69d522..d2c7ceda4a5 100644 --- a/scripts/src/formats.lua +++ b/scripts/src/formats.lua @@ -33,8 +33,6 @@ project "formats" MAME_DIR .. "src/lib/formats/all.cpp", MAME_DIR .. "src/lib/formats/all.h", - MAME_DIR .. "src/lib/formats/ioprocs.cpp", - MAME_DIR .. "src/lib/formats/ioprocs.h", MAME_DIR .. "src/lib/formats/imageutl.cpp", MAME_DIR .. "src/lib/formats/imageutl.h", diff --git a/scripts/src/lib.lua b/scripts/src/lib.lua index c943656ca14..c24bb015cd4 100644 --- a/scripts/src/lib.lua +++ b/scripts/src/lib.lua @@ -71,6 +71,12 @@ project "utils" MAME_DIR .. "src/lib/util/hashing.h", MAME_DIR .. "src/lib/util/huffman.cpp", MAME_DIR .. "src/lib/util/huffman.h", + MAME_DIR .. "src/lib/util/ioprocs.cpp", + MAME_DIR .. "src/lib/util/ioprocs.h", + MAME_DIR .. "src/lib/util/ioprocsfill.h", + MAME_DIR .. "src/lib/util/ioprocsfilter.cpp", + MAME_DIR .. "src/lib/util/ioprocsfilter.h", + MAME_DIR .. "src/lib/util/ioprocsvec.h", MAME_DIR .. "src/lib/util/jedparse.cpp", MAME_DIR .. "src/lib/util/jedparse.h", MAME_DIR .. "src/lib/util/md5.cpp", @@ -85,6 +91,8 @@ project "utils" MAME_DIR .. "src/lib/util/options.h", MAME_DIR .. "src/lib/util/palette.cpp", MAME_DIR .. "src/lib/util/palette.h", + MAME_DIR .. "src/lib/util/path.cpp", + MAME_DIR .. "src/lib/util/path.h", MAME_DIR .. "src/lib/util/path_to_regex.cpp", MAME_DIR .. "src/lib/util/path_to_regex.hpp", MAME_DIR .. "src/lib/util/plaparse.cpp", @@ -104,6 +112,7 @@ project "utils" MAME_DIR .. "src/lib/util/unzip.cpp", MAME_DIR .. "src/lib/util/unzip.h", MAME_DIR .. "src/lib/util/un7z.cpp", + MAME_DIR .. "src/lib/util/utilfwd.h", MAME_DIR .. "src/lib/util/vbiparse.cpp", MAME_DIR .. "src/lib/util/vbiparse.h", MAME_DIR .. "src/lib/util/vecstream.cpp", diff --git a/scripts/src/osd/mac.lua b/scripts/src/osd/mac.lua index 2cc3e53c926..8a57b4ab4a3 100644 --- a/scripts/src/osd/mac.lua +++ b/scripts/src/osd/mac.lua @@ -166,7 +166,6 @@ project ("ocore_" .. _OPTIONS["osd"]) MAME_DIR .. "src/osd/modules/lib/osdlib_macosx.cpp", MAME_DIR .. "src/osd/modules/lib/osdlib.h", MAME_DIR .. "src/osd/modules/file/posixdir.cpp", - MAME_DIR .. "src/osd/modules/file/posixdomain.cpp", MAME_DIR .. "src/osd/modules/file/posixfile.cpp", MAME_DIR .. "src/osd/modules/file/posixfile.h", MAME_DIR .. "src/osd/modules/file/posixptty.cpp", diff --git a/scripts/src/osd/sdl.lua b/scripts/src/osd/sdl.lua index 37dfb221067..31dafbbeb20 100644 --- a/scripts/src/osd/sdl.lua +++ b/scripts/src/osd/sdl.lua @@ -482,7 +482,6 @@ project ("ocore_" .. _OPTIONS["osd"]) if BASE_TARGETOS=="unix" then files { MAME_DIR .. "src/osd/modules/file/posixdir.cpp", - MAME_DIR .. "src/osd/modules/file/posixdomain.cpp", MAME_DIR .. "src/osd/modules/file/posixfile.cpp", MAME_DIR .. "src/osd/modules/file/posixfile.h", MAME_DIR .. "src/osd/modules/file/posixptty.cpp", diff --git a/src/devices/bus/a7800/a78_slot.cpp b/src/devices/bus/a7800/a78_slot.cpp index 4a7392fc3f6..d55412058d1 100644 --- a/src/devices/bus/a7800/a78_slot.cpp +++ b/src/devices/bus/a7800/a78_slot.cpp @@ -491,7 +491,7 @@ image_verify_result a78_cart_slot_device::verify_header(char *header) if (strncmp(magic, header + 1, 9)) { logerror("Not a valid A7800 image\n"); - seterror(IMAGE_ERROR_UNSPECIFIED, "File is not a valid A7800 image"); + seterror(image_error::INVALIDIMAGE, "File is not a valid A7800 image"); return image_verify_result::FAIL; } diff --git a/src/devices/bus/acorn/system/8k.cpp b/src/devices/bus/acorn/system/8k.cpp index ecbd69c930f..b2e1c7bb3d2 100644 --- a/src/devices/bus/acorn/system/8k.cpp +++ b/src/devices/bus/acorn/system/8k.cpp @@ -144,7 +144,7 @@ image_init_result acorn_8k_device::load_rom(device_image_interface &image, gener // socket accepts 2K and 4K ROM only if (size != 0x0800 && size != 0x1000) { - image.seterror(IMAGE_ERROR_UNSPECIFIED, "Invalid size: Only 2K/4K is supported"); + image.seterror(image_error::INVALIDIMAGE, "Invalid size: Only 2K/4K is supported"); return image_init_result::FAIL; } diff --git a/src/devices/bus/apf/slot.cpp b/src/devices/bus/apf/slot.cpp index 0d44530a8b6..c43738fae2a 100644 --- a/src/devices/bus/apf/slot.cpp +++ b/src/devices/bus/apf/slot.cpp @@ -152,7 +152,7 @@ image_init_result apf_cart_slot_device::call_load() if (size > 0x3800) { - seterror(IMAGE_ERROR_UNSPECIFIED, "Image extends beyond the expected size for an APF cart"); + seterror(image_error::INVALIDIMAGE, "Image extends beyond the expected size for an APF cart"); return image_init_result::FAIL; } diff --git a/src/devices/bus/aquarius/slot.cpp b/src/devices/bus/aquarius/slot.cpp index 825e03f39d5..88be36900f4 100644 --- a/src/devices/bus/aquarius/slot.cpp +++ b/src/devices/bus/aquarius/slot.cpp @@ -91,7 +91,7 @@ image_init_result aquarius_cartridge_slot_device::call_load() if (size % 0x1000) { - seterror(IMAGE_ERROR_INVALIDIMAGE, "Invalid ROM size"); + seterror(image_error::INVALIDIMAGE, "Invalid ROM size"); return image_init_result::FAIL; } diff --git a/src/devices/bus/ata/idehd.cpp b/src/devices/bus/ata/idehd.cpp index 15a079963de..dd1a8f932ec 100644 --- a/src/devices/bus/ata/idehd.cpp +++ b/src/devices/bus/ata/idehd.cpp @@ -838,7 +838,7 @@ void ide_hdd_device::device_reset() // build the features page uint32_t metalength; - if (m_handle && m_handle->read_metadata (HARD_DISK_IDENT_METADATA_TAG, 0, &m_buffer[0], 512, metalength) == CHDERR_NONE) + if (m_handle && !m_handle->read_metadata(HARD_DISK_IDENT_METADATA_TAG, 0, &m_buffer[0], 512, metalength)) { for( int w = 0; w < 256; w++ ) { diff --git a/src/devices/bus/bbc/1mhzbus/datacentre.cpp b/src/devices/bus/bbc/1mhzbus/datacentre.cpp index 05ba11a3bab..f21d5af1d54 100644 --- a/src/devices/bus/bbc/1mhzbus/datacentre.cpp +++ b/src/devices/bus/bbc/1mhzbus/datacentre.cpp @@ -328,7 +328,7 @@ QUICKLOAD_LOAD_MEMBER(bbc_datacentre_device::quickload_cb) } else { - image.seterror(IMAGE_ERROR_INVALIDIMAGE, "Invalid filetype, must be SSD, DSD, or IMG"); + image.seterror(image_error::INVALIDIMAGE, "Invalid filetype, must be SSD, DSD, or IMG"); return image_init_result::FAIL; } diff --git a/src/devices/bus/bbc/rom/slot.cpp b/src/devices/bus/bbc/rom/slot.cpp index 8a315e12234..65acb920bca 100644 --- a/src/devices/bus/bbc/rom/slot.cpp +++ b/src/devices/bus/bbc/rom/slot.cpp @@ -122,7 +122,7 @@ image_init_result bbc_romslot_device::call_load() if (size % 0x2000) { - seterror(IMAGE_ERROR_INVALIDIMAGE, "Invalid ROM size"); + seterror(image_error::INVALIDIMAGE, "Invalid ROM size"); return image_init_result::FAIL; } diff --git a/src/devices/bus/c64/exp.cpp b/src/devices/bus/c64/exp.cpp index e4cc42f61d8..cf20f18fe45 100644 --- a/src/devices/bus/c64/exp.cpp +++ b/src/devices/bus/c64/exp.cpp @@ -191,7 +191,7 @@ image_init_result c64_expansion_slot_device::call_load() if ((m_card->m_roml_size & (m_card->m_roml_size - 1)) || (m_card->m_romh_size & (m_card->m_romh_size - 1))) { - seterror(IMAGE_ERROR_UNSPECIFIED, "ROM size must be power of 2"); + seterror(image_error::INVALIDIMAGE, "ROM size must be power of 2"); return image_init_result::FAIL; } } diff --git a/src/devices/bus/cgenie/expansion/floppy.cpp b/src/devices/bus/cgenie/expansion/floppy.cpp index b6f0a9c30ac..ee914179d10 100644 --- a/src/devices/bus/cgenie/expansion/floppy.cpp +++ b/src/devices/bus/cgenie/expansion/floppy.cpp @@ -181,7 +181,7 @@ DEVICE_IMAGE_LOAD_MEMBER( cgenie_fdc_device::socket_load ) if (size > 0x1000) { - image.seterror(IMAGE_ERROR_UNSPECIFIED, "Unsupported ROM size"); + image.seterror(image_error::INVALIDIMAGE, "Unsupported ROM size"); return image_init_result::FAIL; } diff --git a/src/devices/bus/coco/coco_dwsock.cpp b/src/devices/bus/coco/coco_dwsock.cpp index b970458c91c..a69ac57b4c4 100644 --- a/src/devices/bus/coco/coco_dwsock.cpp +++ b/src/devices/bus/coco/coco_dwsock.cpp @@ -82,18 +82,14 @@ beckerport_device::~beckerport_device() void beckerport_device::device_start() { - char chAddress[64]; - - /* format address string for opening the port */ - snprintf(chAddress, sizeof(chAddress), "socket.%s:%d", m_hostname, m_dwtcpport); - - osd_printf_verbose("Connecting to Drivewire server on %s:%d... ", m_hostname, m_dwtcpport); + osd_printf_verbose("%s: Connecting to Drivewire server on %s:%d... ", tag(), m_hostname, m_dwtcpport); u64 filesize; // unused - osd_file::error filerr = osd_file::open(chAddress, 0, m_pSocket, filesize); - if (filerr != osd_file::error::NONE) + /* format address string for opening the port */ + std::error_condition filerr = osd_file::open(util::string_format("socket.%s:%d", m_hostname, m_dwtcpport), 0, m_pSocket, filesize); + if (filerr) { - osd_printf_verbose("Error: osd_open returned error %i!\n", (int) filerr); + osd_printf_verbose("Error: osd_open returned error %s:%d %s!\n", filerr.category().name(), filerr.value(), filerr.message()); return; } @@ -108,7 +104,7 @@ void beckerport_device::device_stop() { if (m_pSocket) { - printf("Closing connection to Drivewire server\n"); + printf("%s: Closing connection to Drivewire server\n", tag()); m_pSocket.reset(); } } @@ -140,23 +136,24 @@ u8 beckerport_device::read(offs_t offset) if (!m_rx_pending) { /* Try to read from dws */ - 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)); + std::error_condition filerr = m_pSocket->read(m_buf, 0, sizeof(m_buf), m_rx_pending); + if (filerr) + osd_printf_error("%s: coco_dwsock.c: beckerport_device::read() socket read operation failed with error %s:%d %s\n", tag(), filerr.category().name(), filerr.value(), filerr.message()); else m_head = 0; } - //printf("beckerport_device: status read. %i bytes remaining.\n", m_rx_pending); + //logerror("beckerport_device: status read. %i bytes remaining.\n", m_rx_pending); data = (m_rx_pending > 0) ? 2 : 0; break; case DWS_DATA: - if (!m_rx_pending) { - fprintf(stderr, "coco_dwsock.c: beckerport_device::read() buffer underrun\n"); + if (!m_rx_pending) + { + osd_printf_error("%s: coco_dwsock.c: beckerport_device::read() buffer underrun\n", tag()); break; } data = m_buf[m_head++]; m_rx_pending--; - //printf("beckerport_device: data read 1 byte (0x%02x). %i bytes remaining.\n", data&0xff, m_rx_pending); + //logerror("beckerport_device: data read 1 byte (0x%02x). %i bytes remaining.\n", data&0xff, m_rx_pending); break; default: fprintf(stderr, "%s: read from bad offset %d\n", __FILE__, offset); @@ -172,7 +169,7 @@ u8 beckerport_device::read(offs_t offset) void beckerport_device::write(offs_t offset, u8 data) { char d = char(data); - osd_file::error filerr; + std::error_condition filerr; u32 written; if (!m_pSocket) @@ -181,13 +178,13 @@ void beckerport_device::write(offs_t offset, u8 data) switch (offset) { case DWS_STATUS: - //printf("beckerport_write: error: write (0x%02x) to status register\n", d); + //logerror("beckerport_write: error: write (0x%02x) to status register\n", d); break; case DWS_DATA: 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); + if (filerr) + osd_printf_error("%s: coco_dwsock.c: beckerport_device::write() socket write operation failed with error %s:%d %s\n", tag(), filerr.category().name(), filerr.value(), filerr.message()); + //logerror("beckerport_write: data write one byte (0x%02x)\n", d & 0xff); break; default: fprintf(stderr, "%s: write to bad offset %d\n", __FILE__, offset); diff --git a/src/devices/bus/crvision/slot.cpp b/src/devices/bus/crvision/slot.cpp index ecab87796e4..ce1e2a5ea1e 100644 --- a/src/devices/bus/crvision/slot.cpp +++ b/src/devices/bus/crvision/slot.cpp @@ -145,7 +145,7 @@ image_init_result crvision_cart_slot_device::call_load() if (size > 0x4800) { - seterror(IMAGE_ERROR_UNSPECIFIED, "Image extends beyond the expected size for an APF cart"); + seterror(image_error::INVALIDIMAGE, "Image extends beyond the expected size for an APF cart"); return image_init_result::FAIL; } diff --git a/src/devices/bus/electron/cart/ap5.cpp b/src/devices/bus/electron/cart/ap5.cpp index cc4c951a154..90c4188d7b1 100644 --- a/src/devices/bus/electron/cart/ap5.cpp +++ b/src/devices/bus/electron/cart/ap5.cpp @@ -161,7 +161,7 @@ image_init_result electron_ap5_device::load_rom(device_image_interface &image, g // socket accepts 8K and 16K ROM only if (size != 0x2000 && size != 0x4000) { - image.seterror(IMAGE_ERROR_UNSPECIFIED, "Invalid size: Only 8K/16K is supported"); + image.seterror(image_error::INVALIDIMAGE, "Invalid size: Only 8K/16K is supported"); return image_init_result::FAIL; } diff --git a/src/devices/bus/electron/cart/romp144.cpp b/src/devices/bus/electron/cart/romp144.cpp index de947454fd8..8bdeab7cc34 100644 --- a/src/devices/bus/electron/cart/romp144.cpp +++ b/src/devices/bus/electron/cart/romp144.cpp @@ -147,7 +147,7 @@ image_init_result electron_romp144_device::load_rom(device_image_interface &imag // socket accepts 8K and 16K ROM only if (size != 0x2000 && size != 0x4000) { - image.seterror(IMAGE_ERROR_UNSPECIFIED, "Invalid size: Only 8K/16K is supported"); + image.seterror(image_error::INVALIDIMAGE, "Invalid size: Only 8K/16K is supported"); return image_init_result::FAIL; } diff --git a/src/devices/bus/electron/cart/slot.cpp b/src/devices/bus/electron/cart/slot.cpp index 489cb567c4d..342cd3ae4f8 100644 --- a/src/devices/bus/electron/cart/slot.cpp +++ b/src/devices/bus/electron/cart/slot.cpp @@ -132,7 +132,7 @@ image_init_result electron_cartslot_device::call_load() if (size % 0x2000) { - seterror(IMAGE_ERROR_UNSPECIFIED, "Unsupported cartridge size"); + seterror(image_error::INVALIDIMAGE, "Unsupported cartridge size"); return image_init_result::FAIL; } @@ -152,7 +152,7 @@ image_init_result electron_cartslot_device::call_load() if ((upsize % 0x2000 && upsize != 0) || (losize % 0x2000 && losize != 0) || (romsize % 0x2000 && romsize != 0)) { - seterror(IMAGE_ERROR_UNSPECIFIED, "Unsupported cartridge size"); + seterror(image_error::INVALIDIMAGE, "Unsupported cartridge size"); return image_init_result::FAIL; } diff --git a/src/devices/bus/electron/plus1.cpp b/src/devices/bus/electron/plus1.cpp index 5bf61578b2b..4b2c3ba9dad 100644 --- a/src/devices/bus/electron/plus1.cpp +++ b/src/devices/bus/electron/plus1.cpp @@ -522,7 +522,7 @@ image_init_result electron_ap6_device::load_rom(device_image_interface &image, g // socket accepts 8K and 16K ROM only if (size != 0x2000 && size != 0x4000) { - image.seterror(IMAGE_ERROR_UNSPECIFIED, "Invalid size: Only 8K/16K is supported"); + image.seterror(image_error::INVALIDIMAGE, "Invalid size: Only 8K/16K is supported"); return image_init_result::FAIL; } diff --git a/src/devices/bus/electron/plus2.cpp b/src/devices/bus/electron/plus2.cpp index d379f053047..82e75bd6030 100644 --- a/src/devices/bus/electron/plus2.cpp +++ b/src/devices/bus/electron/plus2.cpp @@ -231,7 +231,7 @@ image_init_result electron_plus2_device::load_rom(device_image_interface &image, // socket accepts 8K and 16K ROM only if (size != 0x2000 && size != 0x4000) { - image.seterror(IMAGE_ERROR_UNSPECIFIED, "Invalid size: Only 8K/16K is supported"); + image.seterror(image_error::INVALIDIMAGE, "Invalid size: Only 8K/16K is supported"); return image_init_result::FAIL; } diff --git a/src/devices/bus/electron/rombox.cpp b/src/devices/bus/electron/rombox.cpp index 920419c2d66..47040271e7f 100644 --- a/src/devices/bus/electron/rombox.cpp +++ b/src/devices/bus/electron/rombox.cpp @@ -185,7 +185,7 @@ image_init_result electron_rombox_device::load_rom(device_image_interface &image // socket accepts 8K and 16K ROM only if (size != 0x2000 && size != 0x4000) { - image.seterror(IMAGE_ERROR_UNSPECIFIED, "Invalid size: Only 8K/16K is supported"); + image.seterror(image_error::INVALIDIMAGE, "Invalid size: Only 8K/16K is supported"); return image_init_result::FAIL; } diff --git a/src/devices/bus/electron/romboxp.cpp b/src/devices/bus/electron/romboxp.cpp index e6cfd472989..59d83bc4121 100644 --- a/src/devices/bus/electron/romboxp.cpp +++ b/src/devices/bus/electron/romboxp.cpp @@ -328,7 +328,7 @@ image_init_result electron_romboxp_device::load_rom(device_image_interface &imag // socket accepts 8K and 16K ROM only if (size != 0x2000 && size != 0x4000) { - image.seterror(IMAGE_ERROR_UNSPECIFIED, "Invalid size: Only 8K/16K is supported"); + image.seterror(image_error::INVALIDIMAGE, "Invalid size: Only 8K/16K is supported"); return image_init_result::FAIL; } diff --git a/src/devices/bus/electron/sidewndr.cpp b/src/devices/bus/electron/sidewndr.cpp index e66ac800f3c..a2ab8011b09 100644 --- a/src/devices/bus/electron/sidewndr.cpp +++ b/src/devices/bus/electron/sidewndr.cpp @@ -174,7 +174,7 @@ image_init_result electron_sidewndr_device::load_rom(device_image_interface &ima // socket accepts 8K and 16K ROM only if (size != 0x2000 && size != 0x4000) { - image.seterror(IMAGE_ERROR_UNSPECIFIED, "Invalid size: Only 8K/16K is supported"); + image.seterror(image_error::INVALIDIMAGE, "Invalid size: Only 8K/16K is supported"); return image_init_result::FAIL; } diff --git a/src/devices/bus/gamate/slot.cpp b/src/devices/bus/gamate/slot.cpp index 625e4103482..3f98a30927d 100644 --- a/src/devices/bus/gamate/slot.cpp +++ b/src/devices/bus/gamate/slot.cpp @@ -134,7 +134,7 @@ image_init_result gamate_cart_slot_device::call_load() if (len > 0x80000) { - seterror(IMAGE_ERROR_UNSPECIFIED, "Unsupported cartridge size"); + seterror(image_error::INVALIDIMAGE, "Unsupported cartridge size"); return image_init_result::FAIL; } diff --git a/src/devices/bus/gameboy/gb_slot.cpp b/src/devices/bus/gameboy/gb_slot.cpp index a408b9d15ff..79708f95314 100644 --- a/src/devices/bus/gameboy/gb_slot.cpp +++ b/src/devices/bus/gameboy/gb_slot.cpp @@ -267,7 +267,7 @@ image_init_result gb_cart_slot_device_base::call_load() /* Verify that the file contains 16kb blocks */ if ((len == 0) || ((len % 0x4000) != 0)) { - seterror(IMAGE_ERROR_UNSPECIFIED, "Invalid rom file size\n"); + seterror(image_error::INVALIDIMAGE, "Invalid ROM file size\n"); return image_init_result::FAIL; } } diff --git a/src/devices/bus/gba/gba_slot.cpp b/src/devices/bus/gba/gba_slot.cpp index 06ec379cf77..ac036718e2d 100644 --- a/src/devices/bus/gba/gba_slot.cpp +++ b/src/devices/bus/gba/gba_slot.cpp @@ -625,7 +625,7 @@ image_init_result gba_cart_slot_device::call_load() uint32_t size = loaded_through_softlist() ? get_software_region_length("rom") : length(); if (size > 0x4000000) { - seterror(IMAGE_ERROR_UNSPECIFIED, "Attempted loading a cart larger than 64MB"); + seterror(image_error::INVALIDIMAGE, "Attempted loading a cart larger than 64MB"); return image_init_result::FAIL; } diff --git a/src/devices/bus/isa/sc499.cpp b/src/devices/bus/isa/sc499.cpp index c313dd84148..bc942ede9e8 100644 --- a/src/devices/bus/isa/sc499.cpp +++ b/src/devices/bus/isa/sc499.cpp @@ -16,7 +16,7 @@ #include "emu.h" #include "sc499.h" -#include "formats/ioprocs.h" + #define VERBOSE 0 @@ -1310,18 +1310,17 @@ void sc499_ctape_image_device::write_block(int block_num, uint8_t *ptr) image_init_result sc499_ctape_image_device::call_load() { - uint32_t size; - io_generic io; - io.file = (device_image_interface *)this; - io.procs = &image_ioprocs; - io.filler = 0xff; - - size = io_generic_size(&io); - m_ctape_data.resize(size); - - io_generic_read(&io, &m_ctape_data[0], 0, size); - - return image_init_result::PASS; + try + { + auto const size = length(); + m_ctape_data.resize(size); + if (!fseek(0, SEEK_SET) && (fread(m_ctape_data.data(), size) == size)) + return image_init_result::PASS; + } + catch (...) + { + } + return image_init_result::FAIL; } void sc499_ctape_image_device::call_unload() diff --git a/src/devices/bus/m5/slot.cpp b/src/devices/bus/m5/slot.cpp index a1b9d551b23..a75599bb807 100644 --- a/src/devices/bus/m5/slot.cpp +++ b/src/devices/bus/m5/slot.cpp @@ -166,7 +166,7 @@ image_init_result m5_cart_slot_device::call_load() if (size > 0x5000 && m_type == M5_STD) { - seterror(IMAGE_ERROR_UNSPECIFIED, "Image extends beyond the expected size for an M5 cart"); + seterror(image_error::INVALIDIMAGE, "Image extends beyond the expected size for an M5 cart"); return image_init_result::FAIL; } diff --git a/src/devices/bus/mc10/mc10_cart.cpp b/src/devices/bus/mc10/mc10_cart.cpp index e8addd9939a..088b3ca8c81 100644 --- a/src/devices/bus/mc10/mc10_cart.cpp +++ b/src/devices/bus/mc10/mc10_cart.cpp @@ -96,14 +96,14 @@ image_init_result mc10cart_slot_device::call_load() memory_region *romregion(loaded_through_softlist() ? memregion("rom") : nullptr); if (loaded_through_softlist() && !romregion) { - seterror(IMAGE_ERROR_INVALIDIMAGE, "Software list item has no 'rom' data area"); + seterror(image_error::INVALIDIMAGE, "Software list item has no 'rom' data area"); return image_init_result::FAIL; } u32 const len(loaded_through_softlist() ? romregion->bytes() : length()); if (len > m_cart->max_rom_length()) { - seterror(IMAGE_ERROR_UNSUPPORTED, "Unsupported cartridge size"); + seterror(image_error::INVALIDIMAGE, "Unsupported cartridge size"); return image_init_result::FAIL; } @@ -114,7 +114,7 @@ image_init_result mc10cart_slot_device::call_load() u32 const cnt(fread(romregion->base(), len)); if (cnt != len) { - seterror(IMAGE_ERROR_UNSPECIFIED, "Error reading cartridge file"); + seterror(image_error::UNSPECIFIED, "Error reading cartridge file"); return image_init_result::FAIL; } } diff --git a/src/devices/bus/msx_slot/cartridge.cpp b/src/devices/bus/msx_slot/cartridge.cpp index 87b89f93c78..30c9f0a2b00 100644 --- a/src/devices/bus/msx_slot/cartridge.cpp +++ b/src/devices/bus/msx_slot/cartridge.cpp @@ -165,7 +165,7 @@ image_init_result msx_slot_cartridge_device::call_load() if (fread(m_cartridge->get_rom_base(), length) != length) { - seterror(IMAGE_ERROR_UNSPECIFIED, "Unable to fully read file"); + seterror(image_error::UNSPECIFIED, "Unable to fully read file"); return image_init_result::FAIL; } diff --git a/src/devices/bus/nes/nes_slot.cpp b/src/devices/bus/nes/nes_slot.cpp index 812aa738399..f75694bd041 100644 --- a/src/devices/bus/nes/nes_slot.cpp +++ b/src/devices/bus/nes/nes_slot.cpp @@ -887,7 +887,7 @@ image_init_result nes_cart_slot_device::call_load() else { logerror("%s is NOT a file in either iNES or UNIF format.\n", filename()); - seterror(IMAGE_ERROR_UNSPECIFIED, "File is neither iNES or UNIF format"); + seterror(image_error::INVALIDIMAGE, "File is neither iNES or UNIF format"); return image_init_result::FAIL; } } diff --git a/src/devices/bus/nubus/nubus_image.cpp b/src/devices/bus/nubus/nubus_image.cpp index 8c94882cd4f..80875c6bd41 100644 --- a/src/devices/bus/nubus/nubus_image.cpp +++ b/src/devices/bus/nubus/nubus_image.cpp @@ -295,8 +295,9 @@ void nubus_image_device::file_cmd_w(uint32_t data) std::string fullpath(filectx.curdir); fullpath += PATH_SEPARATOR; fullpath.append(std::begin(filectx.filename), std::find(std::begin(filectx.filename), std::end(filectx.filename), '\0')); - if (osd_file::open(fullpath, OPEN_FLAG_READ, filectx.fd, filectx.filelen) != osd_file::error::NONE) - osd_printf_error("Error opening %s\n", fullpath); + std::error_condition const filerr = osd_file::open(fullpath, OPEN_FLAG_READ, filectx.fd, filectx.filelen); + if (filerr) + osd_printf_error("%s: Error opening %s (%s:%d %s)\n", tag(), fullpath, filerr.category().name(), filerr.value(), filerr.message()); filectx.bytecount = 0; } break; @@ -306,8 +307,9 @@ void nubus_image_device::file_cmd_w(uint32_t data) fullpath += PATH_SEPARATOR; fullpath.append(std::begin(filectx.filename), std::find(std::begin(filectx.filename), std::end(filectx.filename), '\0')); uint64_t filesize; // unused, but it's an output from the open call - if (osd_file::open(fullpath, OPEN_FLAG_WRITE | OPEN_FLAG_CREATE, filectx.fd, filesize) != osd_file::error::NONE) - osd_printf_error("Error opening %s\n", fullpath); + std::error_condition const filerr = osd_file::open(fullpath, OPEN_FLAG_WRITE | OPEN_FLAG_CREATE, filectx.fd, filesize); + if (filerr) + osd_printf_error("%s: Error opening %s (%s:%d %s)\n", tag(), fullpath, filerr.category().name(), filerr.value(), filerr.message()); filectx.bytecount = 0; } break; diff --git a/src/devices/bus/plus4/exp.cpp b/src/devices/bus/plus4/exp.cpp index fb0387908ef..487de7ea3c2 100644 --- a/src/devices/bus/plus4/exp.cpp +++ b/src/devices/bus/plus4/exp.cpp @@ -118,7 +118,7 @@ image_init_result plus4_expansion_slot_device::call_load() if ((m_card->m_c1l_size & (m_card->m_c1l_size - 1)) || (m_card->m_c1h_size & (m_card->m_c1h_size - 1)) || (m_card->m_c2l_size & (m_card->m_c2l_size - 1)) || (m_card->m_c2h_size & (m_card->m_c2h_size - 1))) { - seterror(IMAGE_ERROR_UNSPECIFIED, "ROM size must be power of 2"); + seterror(image_error::INVALIDIMAGE, "ROM size must be power of 2"); return image_init_result::FAIL; } } diff --git a/src/devices/bus/scv/slot.cpp b/src/devices/bus/scv/slot.cpp index 65081801f30..86dc2d810c1 100644 --- a/src/devices/bus/scv/slot.cpp +++ b/src/devices/bus/scv/slot.cpp @@ -157,7 +157,7 @@ image_init_result scv_cart_slot_device::call_load() if (len > 0x20000) { - seterror(IMAGE_ERROR_UNSPECIFIED, "Unsupported cartridge size"); + seterror(image_error::INVALIDIMAGE, "Unsupported cartridge size"); return image_init_result::FAIL; } diff --git a/src/devices/bus/sega8/sega8_slot.cpp b/src/devices/bus/sega8/sega8_slot.cpp index 8330fc68915..8a998e71bf0 100644 --- a/src/devices/bus/sega8/sega8_slot.cpp +++ b/src/devices/bus/sega8/sega8_slot.cpp @@ -397,7 +397,7 @@ image_init_result sega8_cart_slot_device::call_load() if (m_is_card && len > 0x8000) { - seterror(IMAGE_ERROR_UNSPECIFIED, "Attempted loading a card larger than 32KB"); + seterror(image_error::INVALIDIMAGE, "Attempted loading a card larger than 32KB"); return image_init_result::FAIL; } diff --git a/src/devices/bus/spectrum/intf2.cpp b/src/devices/bus/spectrum/intf2.cpp index 7442dfe49a9..afce2005a99 100644 --- a/src/devices/bus/spectrum/intf2.cpp +++ b/src/devices/bus/spectrum/intf2.cpp @@ -99,7 +99,7 @@ DEVICE_IMAGE_LOAD_MEMBER(spectrum_intf2_device::cart_load) if (size != 0x4000) { - image.seterror(IMAGE_ERROR_UNSPECIFIED, "Unsupported cartridge size"); + image.seterror(image_error::INVALIDIMAGE, "Unsupported cartridge size"); return image_init_result::FAIL; } diff --git a/src/devices/bus/ti99/gromport/cartridges.cpp b/src/devices/bus/ti99/gromport/cartridges.cpp index 20831395a0c..2f5a558d29b 100644 --- a/src/devices/bus/ti99/gromport/cartridges.cpp +++ b/src/devices/bus/ti99/gromport/cartridges.cpp @@ -16,6 +16,10 @@ #include "cartridges.h" #include "corestr.h" +#include "ioprocs.h" +#include "unzip.h" +#include "xmlfile.h" + #define LOG_WARN (1U<<1) // Warnings #define LOG_CONFIG (1U<<2) // Configuration @@ -260,14 +264,14 @@ image_init_result ti99_cartridge_device::call_load() auto reader = std::make_unique(pcbdefs); try { - m_rpk = reader->open(machine().options(), filename(), machine().system().name); + m_rpk = reader->open(machine().options(), image_core_file(), machine().system().name); m_pcbtype = m_rpk->get_type(); } catch (rpk_exception& err) { LOGMASKED(LOG_WARN, "Failed to load cartridge '%s': %s\n", basename(), err.to_string().c_str()); m_rpk = nullptr; - m_err = IMAGE_ERROR_INVALIDIMAGE; + m_err = image_error::INVALIDIMAGE; return image_init_result::FAIL; } } @@ -1553,8 +1557,8 @@ void ti99_cartridge_device::rpk::close() throw emu_fatalerror("ti99_cartridge_device::rpk::close: Buffer is null or length is 0"); emu_file file(m_options.nvram_directory(), OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS); - osd_file::error filerr = file.open(socket.second->get_pathname()); - if (filerr == osd_file::error::NONE) + std::error_condition const filerr = file.open(socket.second->get_pathname()); + if (!filerr) file.write(socket.second->get_contents(), socket.second->get_content_length()); } @@ -1641,8 +1645,8 @@ std::unique_ptr ti99_cartridge_device::rpk_re catch (std::bad_alloc const &) { throw rpk_exception(RPK_OUT_OF_MEMORY); } // and unzip file from the zip file - util::archive_file::error ziperr = zip.decompress(contents.get(), length); - if (ziperr != util::archive_file::error::NONE) + std::error_condition const ziperr = zip.decompress(contents.get(), length); + if (ziperr) { if (ziperr == util::archive_file::error::UNSUPPORTED) throw rpk_exception(RPK_ZIP_UNSUPPORTED); else throw rpk_exception(RPK_ZIP_ERROR); @@ -1727,9 +1731,9 @@ std::unique_ptr ti99_cartridge_device::rpk_re // try to open the battery file and read it if possible emu_file file(options.nvram_directory(), OPEN_FLAG_READ); - osd_file::error filerr = file.open(ram_pname); + std::error_condition const filerr = file.open(ram_pname); int bytes_read = 0; - if (filerr == osd_file::error::NONE) + if (!filerr) bytes_read = file.read(contents.get(), length); // fill remaining bytes (if necessary) @@ -1747,33 +1751,30 @@ std::unique_ptr ti99_cartridge_device::rpk_re system_name - name of the driver (also just for NVRAM handling) -------------------------------------------------*/ -ti99_cartridge_device::rpk* ti99_cartridge_device::rpk_reader::open(emu_options &options, const char *filename, const char *system_name) +ti99_cartridge_device::rpk* ti99_cartridge_device::rpk_reader::open(emu_options &options, util::core_file &file, const char *system_name) { - util::archive_file::error ziperr; - - util::archive_file::ptr zipfile; - - std::vector layout_text; - - int i; - auto newrpk = new rpk(options, system_name); try { - /* open the ZIP file */ - ziperr = util::archive_file::open_zip(filename, zipfile); - if (ziperr != util::archive_file::error::NONE) throw rpk_exception(RPK_NOT_ZIP_FORMAT); + // open the ZIP file + auto reader = util::core_file_read(file); + if (!reader) throw rpk_exception(RPK_OUT_OF_MEMORY); + + std::error_condition ziperr; + util::archive_file::ptr zipfile; + ziperr = util::archive_file::open_zip(std::move(reader), zipfile); + if (ziperr) throw rpk_exception(RPK_NOT_ZIP_FORMAT); - /* find the layout.xml file */ + // find the layout.xml file if (find_file(*zipfile, "layout.xml", 0) < 0) throw rpk_exception(RPK_MISSING_LAYOUT); - /* reserve space for the layout file contents (+1 for the termination) */ - layout_text.resize(zipfile->current_uncompressed_length() + 1); + // reserve space for the layout file contents (+1 for the termination) + std::vector layout_text(zipfile->current_uncompressed_length() + 1); - /* uncompress the layout text */ + // uncompress the layout text ziperr = zipfile->decompress(&layout_text[0], zipfile->current_uncompressed_length()); - if (ziperr != util::archive_file::error::NONE) + if (ziperr) { if (ziperr == util::archive_file::error::UNSUPPORTED) throw rpk_exception(RPK_ZIP_UNSUPPORTED); else throw rpk_exception(RPK_ZIP_ERROR); @@ -1781,7 +1782,7 @@ ti99_cartridge_device::rpk* ti99_cartridge_device::rpk_reader::open(emu_options layout_text[zipfile->current_uncompressed_length()] = '\0'; // Null-terminate - /* parse the layout text */ + // parse the layout text util::xml::file::ptr const layout_xml = util::xml::file::string_read(&layout_text[0], nullptr); if (!layout_xml) throw rpk_exception(RPK_XML_ERROR); @@ -1808,7 +1809,7 @@ ti99_cartridge_device::rpk* ti99_cartridge_device::rpk_reader::open(emu_options if (!pcb_type) throw rpk_exception(RPK_INVALID_LAYOUT, " must have a 'type' attribute"); LOGMASKED(LOG_RPK, "[RPK handler] Cartridge says it has PCB type '%s'\n", *pcb_type); - i=0; + int i=0; do { if (*pcb_type == m_types[i].name) diff --git a/src/devices/bus/ti99/gromport/cartridges.h b/src/devices/bus/ti99/gromport/cartridges.h index db2de6b2672..df94321a5f9 100644 --- a/src/devices/bus/ti99/gromport/cartridges.h +++ b/src/devices/bus/ti99/gromport/cartridges.h @@ -8,12 +8,15 @@ #pragma once -#include "emuopts.h" +#include "gromport.h" + #include "machine/tmc0430.h" + +#include "emuopts.h" #include "softlist_dev.h" -#include "gromport.h" -#include "unzip.h" -#include "xmlfile.h" + +#include "utilfwd.h" + namespace bus::ti99::gromport { @@ -137,7 +140,7 @@ private: public: rpk_reader(const pcb_type *types) : m_types(types) { } - rpk *open(emu_options &options, const char *filename, const char *system_name); + rpk *open(emu_options &options, util::core_file &file, const char *system_name); private: int find_file(util::archive_file &zip, const char *filename, uint32_t crc); diff --git a/src/devices/bus/vboy/slot.cpp b/src/devices/bus/vboy/slot.cpp index 083c0db745b..70dd9e05063 100644 --- a/src/devices/bus/vboy/slot.cpp +++ b/src/devices/bus/vboy/slot.cpp @@ -54,14 +54,14 @@ image_init_result vboy_cart_slot_device::call_load() memory_region *romregion(loaded_through_softlist() ? memregion("rom") : nullptr); if (loaded_through_softlist() && !romregion) { - seterror(IMAGE_ERROR_INVALIDIMAGE, "Software list item has no 'rom' data area"); + seterror(image_error::INVALIDIMAGE, "Software list item has no 'rom' data area"); return image_init_result::FAIL; } u32 const len(loaded_through_softlist() ? romregion->bytes() : length()); if ((0x0000'0003 & len) || (0x0100'0000 < len)) { - seterror(IMAGE_ERROR_UNSUPPORTED, "Unsupported cartridge size (must be a multiple of 4 bytes no larger than 16 MiB)"); + seterror(image_error::INVALIDIMAGE, "Unsupported cartridge size (must be a multiple of 4 bytes no larger than 16 MiB)"); return image_init_result::FAIL; } @@ -72,7 +72,7 @@ image_init_result vboy_cart_slot_device::call_load() u32 const cnt(fread(romregion->base(), len)); if (cnt != len) { - seterror(IMAGE_ERROR_UNSPECIFIED, "Error reading cartridge file"); + seterror(image_error::UNSPECIFIED, "Error reading cartridge file"); return image_init_result::FAIL; } } diff --git a/src/devices/bus/vc4000/slot.cpp b/src/devices/bus/vc4000/slot.cpp index f33e5623639..8de01177448 100644 --- a/src/devices/bus/vc4000/slot.cpp +++ b/src/devices/bus/vc4000/slot.cpp @@ -176,7 +176,7 @@ image_init_result vc4000_cart_slot_device::call_load() if (size > 0x1800) { - seterror(IMAGE_ERROR_UNSPECIFIED, "Image extends beyond the expected size for a VC4000 cart"); + seterror(image_error::INVALIDIMAGE, "Image extends beyond the expected size for a VC4000 cart"); return image_init_result::FAIL; } diff --git a/src/devices/bus/vcs/vcs_slot.cpp b/src/devices/bus/vcs/vcs_slot.cpp index 28d402322d5..5efcc4ba32d 100644 --- a/src/devices/bus/vcs/vcs_slot.cpp +++ b/src/devices/bus/vcs/vcs_slot.cpp @@ -200,7 +200,7 @@ image_init_result vcs_cart_slot_device::call_load() break; default: - seterror(IMAGE_ERROR_UNSUPPORTED, "Invalid rom file size" ); + seterror(image_error::INVALIDIMAGE, "Invalid ROM file size" ); return image_init_result::FAIL; } diff --git a/src/devices/bus/vectrex/slot.cpp b/src/devices/bus/vectrex/slot.cpp index 014b6c9516c..9e3ebd14fa6 100644 --- a/src/devices/bus/vectrex/slot.cpp +++ b/src/devices/bus/vectrex/slot.cpp @@ -145,7 +145,7 @@ image_init_result vectrex_cart_slot_device::call_load() if (size > 0x10000) { - seterror(IMAGE_ERROR_UNSPECIFIED, "Unsupported cartridge size"); + seterror(image_error::INVALIDIMAGE, "Unsupported cartridge size"); return image_init_result::FAIL; } @@ -160,7 +160,7 @@ image_init_result vectrex_cart_slot_device::call_load() // Verify the file is accepted by the Vectrex bios if (memcmp(ROM, "g GCE", 5)) { - seterror(IMAGE_ERROR_UNSPECIFIED, "Invalid image"); + seterror(image_error::INVALIDIMAGE, "Invalid image"); return image_init_result::FAIL; } diff --git a/src/devices/bus/vsmile/vsmile_slot.cpp b/src/devices/bus/vsmile/vsmile_slot.cpp index 59f039c685d..9c2906826c9 100644 --- a/src/devices/bus/vsmile/vsmile_slot.cpp +++ b/src/devices/bus/vsmile/vsmile_slot.cpp @@ -139,7 +139,7 @@ image_init_result vsmile_cart_slot_device::call_load() uint32_t size = loaded_through_softlist() ? get_software_region_length("rom") : length(); if (size > 0x1000000) { - seterror(IMAGE_ERROR_UNSPECIFIED, "Attempted loading a cart larger than 16MB"); + seterror(image_error::INVALIDIMAGE, "Attempted loading a cart larger than 16MB"); return image_init_result::FAIL; } diff --git a/src/devices/imagedev/cassette.cpp b/src/devices/imagedev/cassette.cpp index 778b296d63d..52103cb1e7d 100644 --- a/src/devices/imagedev/cassette.cpp +++ b/src/devices/imagedev/cassette.cpp @@ -9,9 +9,12 @@ *********************************************************************/ #include "emu.h" -#include "formats/imageutl.h" #include "cassette.h" +#include "formats/imageutl.h" + +#include "util/ioprocs.h" + #define LOG_WARN (1U<<1) // Warnings #define LOG_DETAIL (1U<<2) // Details @@ -19,6 +22,7 @@ #include "logmacro.h" + // device type definition DEFINE_DEVICE_TYPE(CASSETTE, cassette_image_device, "cassette_image", "Cassette") @@ -253,12 +257,24 @@ image_init_result cassette_image_device::internal_load(bool is_create) device_image_interface *image = nullptr; interface(image); + check_for_file(); if (is_create || (length()==0)) // empty existing images are fine to write over. { - // creating an image - err = cassette_image::create((void *)image, &image_ioprocs, &cassette_image::wavfile_format, m_create_opts, cassette_image::FLAG_READWRITE|cassette_image::FLAG_SAVEONEXIT, m_cassette); - if (err != cassette_image::error::SUCCESS) - goto error; + auto io = util::core_file_read_write(image_core_file(), 0x00); + if (io) + { + // creating an image + err = cassette_image::create( + std::move(io), + &cassette_image::wavfile_format, + m_create_opts, + cassette_image::FLAG_READWRITE|cassette_image::FLAG_SAVEONEXIT, + m_cassette); + } + else + { + err = cassette_image::error::OUT_OF_MEMORY; + } } else { @@ -269,11 +285,24 @@ image_init_result cassette_image_device::internal_load(bool is_create) // we probably don't want to retry... retry = false; - // try opening the cassette - int cassette_flags = is_readonly() - ? cassette_image::FLAG_READONLY - : (cassette_image::FLAG_READWRITE | cassette_image::FLAG_SAVEONEXIT); - err = cassette_image::open_choices((void *)image, &image_ioprocs, filetype(), m_formats, cassette_flags, m_cassette); + auto io = util::core_file_read_write(image_core_file(), 0x00); + if (io) + { + // try opening the cassette + int const cassette_flags = is_readonly() + ? cassette_image::FLAG_READONLY + : (cassette_image::FLAG_READWRITE | cassette_image::FLAG_SAVEONEXIT); + err = cassette_image::open_choices( + std::move(io), + filetype(), + m_formats, + cassette_flags, + m_cassette); + } + else + { + err = cassette_image::error::OUT_OF_MEMORY; + } // special case - if we failed due to readwrite not being supported, make the image be read only and retry if (err == cassette_image::error::READ_WRITE_UNSUPPORTED) @@ -283,47 +312,48 @@ image_init_result cassette_image_device::internal_load(bool is_create) } } while(retry); - - if (err != cassette_image::error::SUCCESS) - goto error; } - /* set to default state, but only change the UI state */ - change_state(m_default_state, CASSETTE_MASK_UISTATE); - - /* reset the position */ - m_position = 0.0; - m_position_time = machine().time().as_double(); + if (err == cassette_image::error::SUCCESS) + { + /* set to default state, but only change the UI state */ + change_state(m_default_state, CASSETTE_MASK_UISTATE); - /* default channel to 0, speed multiplier to 1 */ - m_channel = 0; - m_speed = 1; - m_direction = 1; + /* reset the position */ + m_position = 0.0; + m_position_time = machine().time().as_double(); - return image_init_result::PASS; + /* default channel to 0, speed multiplier to 1 */ + m_channel = 0; + m_speed = 1; + m_direction = 1; -error: - image_error_t imgerr = IMAGE_ERROR_UNSPECIFIED; - switch(err) + return image_init_result::PASS; + } + else { - case cassette_image::error::INTERNAL: - imgerr = IMAGE_ERROR_INTERNAL; - break; - case cassette_image::error::UNSUPPORTED: - imgerr = IMAGE_ERROR_UNSUPPORTED; - break; - case cassette_image::error::OUT_OF_MEMORY: - imgerr = IMAGE_ERROR_OUTOFMEMORY; - break; - case cassette_image::error::INVALID_IMAGE: - imgerr = IMAGE_ERROR_INVALIDIMAGE; - break; - default: - imgerr = IMAGE_ERROR_UNSPECIFIED; - break; + std::error_condition imgerr = image_error::UNSPECIFIED; + switch(err) + { + case cassette_image::error::INTERNAL: + imgerr = image_error::INTERNAL; + break; + case cassette_image::error::UNSUPPORTED: + imgerr = image_error::UNSUPPORTED; + break; + case cassette_image::error::OUT_OF_MEMORY: + imgerr = std::errc::not_enough_memory; + break; + case cassette_image::error::INVALID_IMAGE: + imgerr = image_error::INVALIDIMAGE; + break; + default: + imgerr = image_error::UNSPECIFIED; + break; + } + image->seterror(imgerr, nullptr); + return image_init_result::FAIL; } - image->seterror(imgerr, "" ); - return image_init_result::FAIL; } diff --git a/src/devices/imagedev/chd_cd.cpp b/src/devices/imagedev/chd_cd.cpp index 5daaba2ed45..4eacb3d3b58 100644 --- a/src/devices/imagedev/chd_cd.cpp +++ b/src/devices/imagedev/chd_cd.cpp @@ -83,17 +83,16 @@ void cdrom_image_device::device_stop() image_init_result cdrom_image_device::call_load() { - chd_error err = (chd_error)0; - chd_file *chd = nullptr; + std::error_condition err; + chd_file *chd = nullptr; if (m_cdrom_handle) cdrom_close(m_cdrom_handle); - if (!loaded_through_softlist()) - { + if (!loaded_through_softlist()) { if (is_filetype("chd") && is_loaded()) { - err = m_self_chd.open( image_core_file() ); /* CDs are never writeable */ - if ( err ) + err = m_self_chd.open(util::core_file_read_write(image_core_file())); // CDs are never writeable + if (err) goto error; chd = &m_self_chd; } @@ -103,20 +102,20 @@ image_init_result cdrom_image_device::call_load() /* open the CHD file */ if (chd) { - m_cdrom_handle = cdrom_open( chd ); + m_cdrom_handle = cdrom_open(chd); } else { m_cdrom_handle = cdrom_open(filename()); } - if ( ! m_cdrom_handle ) + if (!m_cdrom_handle) goto error; return image_init_result::PASS; error: - if ( chd && chd == &m_self_chd ) - m_self_chd.close( ); - if ( err ) - seterror( IMAGE_ERROR_UNSPECIFIED, chd_file::error_string( err ) ); + if (chd && chd == &m_self_chd) + m_self_chd.close(); + if (err) + seterror(err, nullptr); return image_init_result::FAIL; } diff --git a/src/devices/imagedev/diablo.cpp b/src/devices/imagedev/diablo.cpp index 58a34a664f6..be09c263719 100644 --- a/src/devices/imagedev/diablo.cpp +++ b/src/devices/imagedev/diablo.cpp @@ -112,8 +112,6 @@ image_init_result diablo_image_device::call_load() image_init_result diablo_image_device::call_create(int create_format, util::option_resolution *create_args) { - int err; - if (!create_args) throw emu_fatalerror("diablo_image_device::call_create: Expected create_args to not be nullptr"); @@ -127,15 +125,15 @@ image_init_result diablo_image_device::call_create(int create_format, util::opti /* create the CHD file */ chd_codec_type compression[4] = { CHD_CODEC_NONE }; - err = m_origchd.create(image_core_file(), (uint64_t)totalsectors * (uint64_t)sectorsize, hunksize, sectorsize, compression); - if (err != CHDERR_NONE) + std::error_condition err = m_origchd.create(util::core_file_read_write(image_core_file()), uint64_t(totalsectors) * uint64_t(sectorsize), hunksize, sectorsize, compression); + if (err) return image_init_result::FAIL; /* if we created the image and hence, have metadata to set, set the metadata */ err = m_origchd.write_metadata(HARD_DISK_METADATA_TAG, 0, string_format(HARD_DISK_METADATA_FORMAT, cylinders, heads, sectors, sectorsize)); m_origchd.close(); - if (err != CHDERR_NONE) + if (err) return image_init_result::FAIL; return internal_load_dsk(); @@ -164,28 +162,28 @@ void diablo_image_device::call_unload() open_disk_diff - open a DISK diff file -------------------------------------------------*/ -static chd_error open_disk_diff(emu_options &options, const char *name, chd_file &source, chd_file &diff_chd) +static std::error_condition open_disk_diff(emu_options &options, const char *name, chd_file &source, chd_file &diff_chd) { std::string fname = std::string(name).append(".dif"); /* 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); - osd_file::error filerr = diff_file.open(fname.c_str()); - if (filerr == osd_file::error::NONE) + std::error_condition filerr = diff_file.open(fname); + if (!filerr) { std::string fullpath(diff_file.fullpath()); diff_file.close(); //printf("Opening differencing image file: %s\n", fullpath.c_str()); - return diff_chd.open(fullpath.c_str(), true, &source); + return diff_chd.open(fullpath, true, &source); } /* didn't work; try creating it instead */ //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 == osd_file::error::NONE) + filerr = diff_file.open(fname); + if (!filerr) { std::string fullpath(diff_file.fullpath()); diff_file.close(); @@ -193,19 +191,19 @@ static chd_error open_disk_diff(emu_options &options, const char *name, chd_file /* create the CHD */ //printf("Creating differencing image file: %s\n", fullpath.c_str()); chd_codec_type compression[4] = { CHD_CODEC_NONE }; - chd_error err = diff_chd.create(fullpath.c_str(), source.logical_bytes(), source.hunk_bytes(), compression, source); - if (err != CHDERR_NONE) + std::error_condition err = diff_chd.create(fullpath, source.logical_bytes(), source.hunk_bytes(), compression, source); + if (err) return err; return diff_chd.clone_all_metadata(source); } - return CHDERR_FILE_NOT_FOUND; + return std::errc::no_such_file_or_directory; } image_init_result diablo_image_device::internal_load_dsk() { - chd_error err = CHDERR_NONE; + std::error_condition err; m_chd = nullptr; @@ -219,18 +217,18 @@ image_init_result diablo_image_device::internal_load_dsk() } else { - err = m_origchd.open(image_core_file(), true); - if (err == CHDERR_NONE) + err = m_origchd.open(util::core_file_read_write(image_core_file()), true); + if (!err) { m_chd = &m_origchd; } - else if (err == CHDERR_FILE_NOT_WRITEABLE) + else if (err == chd_file::error::FILE_NOT_WRITEABLE) { - err = m_origchd.open(image_core_file(), false); - if (err == CHDERR_NONE) + err = m_origchd.open(util::core_file_read_write(image_core_file()), false); + if (!err) { err = open_disk_diff(device().machine().options(), basename_noext(), m_origchd, m_diffchd); - if (err == CHDERR_NONE) + if (!err) { m_chd = &m_diffchd; } @@ -250,7 +248,7 @@ image_init_result diablo_image_device::internal_load_dsk() m_origchd.close(); m_diffchd.close(); m_chd = nullptr; - seterror(IMAGE_ERROR_UNSPECIFIED, chd_file::error_string(err)); + seterror(err, nullptr); return image_init_result::FAIL; } diff --git a/src/devices/imagedev/flopdrv.cpp b/src/devices/imagedev/flopdrv.cpp index 6ab5028f2d8..316b66ef713 100644 --- a/src/devices/imagedev/flopdrv.cpp +++ b/src/devices/imagedev/flopdrv.cpp @@ -14,9 +14,13 @@ */ #include "emu.h" -#include "formats/imageutl.h" #include "flopdrv.h" +#include "formats/imageutl.h" + +#include "util/ioprocs.h" + + #define VERBOSE 0 #define LOG(x) do { if (VERBOSE) logerror x; } while (0) @@ -33,7 +37,7 @@ struct floppy_error_map { floperr_t ferr; - image_error_t ierr; + std::error_condition ierr; const char *message; }; @@ -45,11 +49,11 @@ struct floppy_error_map static const floppy_error_map errmap[] = { - { FLOPPY_ERROR_SUCCESS, IMAGE_ERROR_SUCCESS }, - { FLOPPY_ERROR_INTERNAL, IMAGE_ERROR_INTERNAL }, - { FLOPPY_ERROR_UNSUPPORTED, IMAGE_ERROR_UNSUPPORTED }, - { FLOPPY_ERROR_OUTOFMEMORY, IMAGE_ERROR_OUTOFMEMORY }, - { FLOPPY_ERROR_INVALIDIMAGE, IMAGE_ERROR_INVALIDIMAGE } + { FLOPPY_ERROR_SUCCESS, { } }, + { FLOPPY_ERROR_INTERNAL, { image_error::INTERNAL } }, + { FLOPPY_ERROR_UNSUPPORTED, { image_error::UNSUPPORTED } }, + { FLOPPY_ERROR_OUTOFMEMORY, { std::errc::not_enough_memory } }, + { FLOPPY_ERROR_INVALIDIMAGE, { image_error::INVALIDIMAGE } } }; /*************************************************************************** @@ -418,50 +422,52 @@ void legacy_floppy_image_device::floppy_drive_set_controller(device_t *controlle image_init_result legacy_floppy_image_device::internal_floppy_device_load(bool is_create, int create_format, util::option_resolution *create_args) { - floperr_t err; - const struct FloppyFormat *floppy_options; - int floppy_flags, i; + const struct FloppyFormat *floppy_options = m_config->formats; - device_image_interface *image = nullptr; - interface(image); /* figure out the floppy options */ - floppy_options = m_config->formats; - - if (is_create) + floperr_t err; + check_for_file(); + auto io = util::core_file_read_write(image_core_file(), 0xff); + if (!io) + { + err = FLOPPY_ERROR_OUTOFMEMORY; + } + else if (is_create) { /* creating an image */ assert(create_format >= 0); - err = floppy_create((void *) image, &image_ioprocs, &floppy_options[create_format], create_args, &m_floppy); - if (err) - goto error; + err = floppy_create(std::move(io), &floppy_options[create_format], create_args, &m_floppy); } else { /* opening an image */ - floppy_flags = !is_readonly() ? FLOPPY_FLAGS_READWRITE : FLOPPY_FLAGS_READONLY; - err = floppy_open_choices((void *) image, &image_ioprocs, filetype(), floppy_options, floppy_flags, &m_floppy); - if (err) - goto error; + int const floppy_flags = !is_readonly() ? FLOPPY_FLAGS_READWRITE : FLOPPY_FLAGS_READONLY; + err = floppy_open_choices(std::move(io), filetype(), floppy_options, floppy_flags, &m_floppy); } - if (floppy_callbacks(m_floppy)->get_heads_per_disk && floppy_callbacks(m_floppy)->get_tracks_per_disk) - { - floppy_drive_set_geometry_absolute(floppy_get_tracks_per_disk(m_floppy),floppy_get_heads_per_disk(m_floppy)); - } - /* disk changed */ - m_dskchg = CLEAR_LINE; - // If we have one of our hacky load procs, call it - if (m_load_proc) - m_load_proc(*this, is_create); + if (!err) + { + if (floppy_callbacks(m_floppy)->get_heads_per_disk && floppy_callbacks(m_floppy)->get_tracks_per_disk) + { + floppy_drive_set_geometry_absolute(floppy_get_tracks_per_disk(m_floppy),floppy_get_heads_per_disk(m_floppy)); + } + /* disk changed */ + m_dskchg = CLEAR_LINE; - return image_init_result::PASS; + // If we have one of our hacky load procs, call it + if (m_load_proc) + m_load_proc(*this, is_create); -error: - for (i = 0; i < std::size(errmap); i++) + return image_init_result::PASS; + } + else { - if (err == errmap[i].ferr) - seterror(errmap[i].ierr, errmap[i].message); + for (int i = 0; i < std::size(errmap); i++) + { + if (err == errmap[i].ferr) + seterror(errmap[i].ierr, errmap[i].message); + } + return image_init_result::FAIL; } - return image_init_result::FAIL; } TIMER_CALLBACK_MEMBER( legacy_floppy_image_device::set_wpt ) diff --git a/src/devices/imagedev/floppy.cpp b/src/devices/imagedev/floppy.cpp index 452fde35035..5d3956e2cab 100644 --- a/src/devices/imagedev/floppy.cpp +++ b/src/devices/imagedev/floppy.cpp @@ -26,8 +26,11 @@ #include "screen.h" #include "speaker.h" + #include "formats/imageutl.h" -#include "zippath.h" + +#include "util/ioprocs.h" +#include "util/zippath.h" /* Debugging flags. Set to 0 or 1. @@ -273,7 +276,7 @@ floppy_image_device::floppy_image_device(const machine_config &mconfig, device_t m_flux_screen(*this, "flux") { extension_list[0] = '\0'; - m_err = IMAGE_ERROR_INVALIDIMAGE; + m_err = image_error::INVALIDIMAGE; } //------------------------------------------------- @@ -398,17 +401,19 @@ void floppy_image_device::commit_image() image_dirty = false; if(!output_format || !output_format->supports_save()) return; - io_generic io; - // Do _not_ remove this cast otherwise the pointer will be incorrect when used by the ioprocs. - io.file = (device_image_interface *)this; - io.procs = &image_ioprocs; - io.filler = 0xff; - osd_file::error err = image_core_file().truncate(0); - if (err != osd_file::error::NONE) - popmessage("Error, unable to truncate image: %d", int(err)); + check_for_file(); + auto io = util::core_file_read_write(image_core_file(), 0xff); + if(!io) { + popmessage("Error, out of memory"); + return; + } + + std::error_condition const err = image_core_file().truncate(0); + if (err) + popmessage("Error, unable to truncate image: %s", err.message()); - output_format->save(&io, variants, image.get()); + output_format->save(*io, variants, image.get()); } void floppy_image_device::device_config_complete() @@ -532,28 +537,28 @@ floppy_image_format_t *floppy_image_device::identify(std::string filename) { util::core_file::ptr fd; std::string revised_path; + std::error_condition err = util::zippath_fopen(filename, OPEN_FLAG_READ, fd, revised_path); + if(err) { + seterror(err, nullptr); + return nullptr; + } - osd_file::error err = util::zippath_fopen(filename, OPEN_FLAG_READ, fd, revised_path); - if(err != osd_file::error::NONE) { - seterror(IMAGE_ERROR_INVALIDIMAGE, "Unable to open the image file"); + auto io = util::core_file_read(std::move(fd), 0xff); + if(!io) { + seterror(std::errc::not_enough_memory, nullptr); return nullptr; } - io_generic io; - io.file = fd.get(); - io.procs = &corefile_ioprocs_noclose; - io.filler = 0xff; int best = 0; floppy_image_format_t *best_format = nullptr; - for (floppy_image_format_t *format : fif_list) - { - int score = format->identify(&io, form_factor, variants); + for(floppy_image_format_t *format : fif_list) { + int score = format->identify(*io, form_factor, variants); if(score > best) { best = score; best_format = format; } } - fd.reset(); + return best_format; } @@ -585,16 +590,17 @@ void floppy_image_device::init_floppy_load(bool write_supported) image_init_result floppy_image_device::call_load() { - io_generic io; + check_for_file(); + auto io = util::core_file_read(image_core_file(), 0xff); + if(!io) { + seterror(std::errc::not_enough_memory, nullptr); + return image_init_result::FAIL; + } - // Do _not_ remove this cast otherwise the pointer will be incorrect when used by the ioprocs. - io.file = (device_image_interface *)this; - io.procs = &image_ioprocs; - io.filler = 0xff; int best = 0; floppy_image_format_t *best_format = nullptr; for (floppy_image_format_t *format : fif_list) { - int score = format->identify(&io, form_factor, variants); + int score = format->identify(*io, form_factor, variants); if(score > best) { best = score; best_format = format; @@ -602,13 +608,13 @@ image_init_result floppy_image_device::call_load() } if (!best_format) { - seterror(IMAGE_ERROR_INVALIDIMAGE, "Unable to identify the image format"); + seterror(image_error::INVALIDIMAGE, "Unable to identify the image format"); return image_init_result::FAIL; } image = std::make_unique(tracks, sides, form_factor); - if (!best_format->load(&io, form_factor, variants, image.get())) { - seterror(IMAGE_ERROR_UNSUPPORTED, "Incompatible image format or corrupted data"); + if (!best_format->load(*io, form_factor, variants, image.get())) { + seterror(image_error::UNSUPPORTED, "Incompatible image format or corrupted data"); image.reset(); return image_init_result::FAIL; } @@ -822,88 +828,22 @@ image_init_result floppy_image_device::call_create(int format_type, util::option return image_init_result::PASS; } -// Should that go into ioprocs? Should ioprocs be turned into something C++? - -struct iofile_ram { - std::vector *data; - int64_t pos; -}; - -static void ram_closeproc(void *file) -{ - auto f = (iofile_ram *)file; - delete f; -} - -static int ram_seekproc(void *file, int64_t offset, int whence) -{ - auto f = (iofile_ram *)file; - switch(whence) { - case SEEK_SET: f->pos = offset; break; - case SEEK_CUR: f->pos += offset; break; - case SEEK_END: f->pos = f->data->size() + offset; break; - } - - f->pos = std::clamp(f->pos, int64_t(0), int64_t(f->data->size())); - return 0; -} - -static size_t ram_readproc(void *file, void *buffer, size_t length) -{ - auto f = (iofile_ram *)file; - size_t l = std::min(length, size_t(f->data->size() - f->pos)); - memcpy(buffer, f->data->data() + f->pos, l); - return l; -} - -static size_t ram_writeproc(void *file, const void *buffer, size_t length) -{ - auto f = (iofile_ram *)file; - size_t l = std::min(length, size_t(f->data->size() - f->pos)); - memcpy(f->data->data() + f->pos, buffer, l); - return l; -} - -static uint64_t ram_filesizeproc(void *file) -{ - auto f = (iofile_ram *)file; - return f->data->size(); -} - - -static const io_procs iop_ram = { - ram_closeproc, - ram_seekproc, - ram_readproc, - ram_writeproc, - ram_filesizeproc -}; - -static io_generic *ram_open(std::vector &data) -{ - iofile_ram *f = new iofile_ram; - f->data = &data; - f->pos = 0; - return new io_generic({ &iop_ram, f }); -} - void floppy_image_device::init_fs(const fs_info *fs, const fs_meta_data &meta) { assert(image); - if (fs->m_type) - { + if (fs->m_type) { std::vector img(fs->m_image_size); fsblk_vec_t blockdev(img); auto cfs = fs->m_manager->mount(blockdev); cfs->format(meta); - auto iog = ram_open(img); auto source_format = fs->m_type(); - source_format->load(iog, floppy_image::FF_UNKNOWN, variants, image.get()); + auto io = util::ram_read(img.data(), img.size(), 0xff); + source_format->load(*io, floppy_image::FF_UNKNOWN, variants, image.get()); delete source_format; - delete iog; - } else + } else { fs_unformatted::format(fs->m_key, image.get()); + } } /* write protect, active high diff --git a/src/devices/imagedev/harddriv.cpp b/src/devices/imagedev/harddriv.cpp index e6e0c56f896..5a7b9fe8109 100644 --- a/src/devices/imagedev/harddriv.cpp +++ b/src/devices/imagedev/harddriv.cpp @@ -133,8 +133,6 @@ image_init_result harddisk_image_device::call_load() image_init_result harddisk_image_device::call_create(int create_format, util::option_resolution *create_args) { - int err; - if (!create_args) throw emu_fatalerror("harddisk_image_device::call_create: Expected create_args to not be nullptr"); @@ -148,15 +146,15 @@ image_init_result harddisk_image_device::call_create(int create_format, util::op /* create the CHD file */ chd_codec_type compression[4] = { CHD_CODEC_NONE }; - err = m_origchd.create(image_core_file(), (uint64_t)totalsectors * (uint64_t)sectorsize, hunksize, sectorsize, compression); - if (err != CHDERR_NONE) + std::error_condition err = m_origchd.create(util::core_file_read_write(image_core_file()), (uint64_t)totalsectors * (uint64_t)sectorsize, hunksize, sectorsize, compression); + if (err) return image_init_result::FAIL; /* if we created the image and hence, have metadata to set, set the metadata */ err = m_origchd.write_metadata(HARD_DISK_METADATA_TAG, 0, string_format(HARD_DISK_METADATA_FORMAT, cylinders, heads, sectors, sectorsize)); m_origchd.close(); - if (err != CHDERR_NONE) + if (err) return image_init_result::FAIL; return internal_load_hd(); @@ -168,7 +166,7 @@ void harddisk_image_device::call_unload() if (!m_device_image_unload.isnull()) m_device_image_unload(*this); - if (m_hard_disk_handle != nullptr) + if (m_hard_disk_handle) { hard_disk_close(m_hard_disk_handle); m_hard_disk_handle = nullptr; @@ -186,28 +184,28 @@ void harddisk_image_device::call_unload() open_disk_diff - open a DISK diff file -------------------------------------------------*/ -static chd_error open_disk_diff(emu_options &options, const char *name, chd_file &source, chd_file &diff_chd) +static std::error_condition open_disk_diff(emu_options &options, const char *name, chd_file &source, chd_file &diff_chd) { std::string fname = std::string(name).append(".dif"); /* 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); - osd_file::error filerr = diff_file.open(fname.c_str()); - if (filerr == osd_file::error::NONE) + std::error_condition filerr = diff_file.open(fname); + if (!filerr) { std::string fullpath(diff_file.fullpath()); diff_file.close(); //printf("Opening differencing image file: %s\n", fullpath.c_str()); - return diff_chd.open(fullpath.c_str(), true, &source); + return diff_chd.open(fullpath, true, &source); } /* didn't work; try creating it instead */ //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 == osd_file::error::NONE) + filerr = diff_file.open(fname); + if (!filerr) { std::string fullpath(diff_file.fullpath()); diff_file.close(); @@ -215,23 +213,23 @@ static chd_error open_disk_diff(emu_options &options, const char *name, chd_file /* create the CHD */ //printf("Creating differencing image file: %s\n", fupointllpath.c_str()); chd_codec_type compression[4] = { CHD_CODEC_NONE }; - chd_error err = diff_chd.create(fullpath.c_str(), source.logical_bytes(), source.hunk_bytes(), compression, source); - if (err != CHDERR_NONE) + std::error_condition err = diff_chd.create(fullpath, source.logical_bytes(), source.hunk_bytes(), compression, source); + if (err) return err; return diff_chd.clone_all_metadata(source); } - return CHDERR_FILE_NOT_FOUND; + return std::errc::no_such_file_or_directory; } image_init_result harddisk_image_device::internal_load_hd() { - chd_error err = CHDERR_NONE; + std::error_condition err; m_chd = nullptr; uint8_t header[64]; - if (m_hard_disk_handle != nullptr) + if (m_hard_disk_handle) { hard_disk_close(m_hard_disk_handle); m_hard_disk_handle = nullptr; @@ -250,19 +248,19 @@ image_init_result harddisk_image_device::internal_load_hd() if (!memcmp("MComprHD", header, 8)) { - err = m_origchd.open(image_core_file(), true); + err = m_origchd.open(util::core_file_read_write(image_core_file()), true); - if (err == CHDERR_NONE) + if (!err) { m_chd = &m_origchd; } - else if (err == CHDERR_FILE_NOT_WRITEABLE) + else if (err == chd_file::error::FILE_NOT_WRITEABLE) { - err = m_origchd.open(image_core_file(), false); - if (err == CHDERR_NONE) + err = m_origchd.open(util::core_file_read_write(image_core_file()), false); + if (!err) { err = open_disk_diff(device().machine().options(), basename_noext(), m_origchd, m_diffchd); - if (err == CHDERR_NONE) + if (!err) { m_chd = &m_diffchd; } @@ -271,11 +269,11 @@ image_init_result harddisk_image_device::internal_load_hd() } } - if (m_chd != nullptr) + if (m_chd) { /* open the hard disk file */ m_hard_disk_handle = hard_disk_open(m_chd); - if (m_hard_disk_handle != nullptr) + if (m_hard_disk_handle) return image_init_result::PASS; } else @@ -306,7 +304,7 @@ image_init_result harddisk_image_device::internal_load_hd() } m_hard_disk_handle = hard_disk_open(image_core_file(), skip); - if (m_hard_disk_handle != nullptr) + if (m_hard_disk_handle) return image_init_result::PASS; } @@ -317,7 +315,7 @@ image_init_result harddisk_image_device::internal_load_hd() m_origchd.close(); m_diffchd.close(); m_chd = nullptr; - seterror(IMAGE_ERROR_UNSPECIFIED, chd_file::error_string(err)); + seterror(err, nullptr); return image_init_result::FAIL; } diff --git a/src/devices/imagedev/mfmhd.cpp b/src/devices/imagedev/mfmhd.cpp index 61eabb12217..f309b8f0d0f 100644 --- a/src/devices/imagedev/mfmhd.cpp +++ b/src/devices/imagedev/mfmhd.cpp @@ -440,8 +440,8 @@ image_init_result mfm_harddisk_device::call_load() } // Read the hard disk metadata - chd_error state = chdfile->read_metadata(HARD_DISK_METADATA_TAG, 0, metadata); - if (state != CHDERR_NONE) + std::error_condition state = chdfile->read_metadata(HARD_DISK_METADATA_TAG, 0, metadata); + if (state) { LOG("Failed to read CHD metadata\n"); return image_init_result::FAIL; @@ -475,7 +475,7 @@ image_init_result mfm_harddisk_device::call_load() param.reduced_wcurr_cylinder = -1; state = chdfile->read_metadata(MFM_HARD_DISK_METADATA_TAG, 0, metadata); - if (state != CHDERR_NONE) + if (state) { LOGMASKED(LOG_WARN, "Failed to read CHD sector arrangement/recording specs, applying defaults\n"); } @@ -494,7 +494,7 @@ image_init_result mfm_harddisk_device::call_load() param.interleave, param.cylskew, param.headskew, param.write_precomp_cylinder, param.reduced_wcurr_cylinder); state = chdfile->read_metadata(MFM_HARD_DISK_METADATA_TAG, 1, metadata); - if (state != CHDERR_NONE) + if (state) { LOGMASKED(LOG_WARN, "Failed to read CHD track gap specs, applying defaults\n"); } @@ -561,8 +561,8 @@ void mfm_harddisk_device::call_unload() LOGMASKED(LOG_WARN, "MFM HD sector arrangement and recording specs have changed; updating CHD metadata\n"); chd_file* chdfile = get_chd_file(); - chd_error err = chdfile->write_metadata(MFM_HARD_DISK_METADATA_TAG, 0, string_format(MFMHD_REC_METADATA_FORMAT, params->interleave, params->cylskew, params->headskew, params->write_precomp_cylinder, params->reduced_wcurr_cylinder), 0); - if (err != CHDERR_NONE) + std::error_condition err = chdfile->write_metadata(MFM_HARD_DISK_METADATA_TAG, 0, string_format(MFMHD_REC_METADATA_FORMAT, params->interleave, params->cylskew, params->headskew, params->write_precomp_cylinder, params->reduced_wcurr_cylinder), 0); + if (err) { LOGMASKED(LOG_WARN, "Failed to save MFM HD sector arrangement/recording specs to CHD\n"); } @@ -573,8 +573,8 @@ void mfm_harddisk_device::call_unload() LOGMASKED(LOG_WARN, "MFM HD track gap specs have changed; updating CHD metadata\n"); chd_file* chdfile = get_chd_file(); - chd_error err = chdfile->write_metadata(MFM_HARD_DISK_METADATA_TAG, 1, string_format(MFMHD_GAP_METADATA_FORMAT, params->gap1, params->gap2, params->gap3, params->sync, params->headerlen, params->ecctype), 0); - if (err != CHDERR_NONE) + std::error_condition err = chdfile->write_metadata(MFM_HARD_DISK_METADATA_TAG, 1, string_format(MFMHD_GAP_METADATA_FORMAT, params->gap1, params->gap2, params->gap3, params->sync, params->headerlen, params->ecctype), 0); + if (err) { LOGMASKED(LOG_WARN, "Failed to save MFM HD track gap specs to CHD\n"); } @@ -919,10 +919,9 @@ bool mfm_harddisk_device::write(attotime &from_when, const attotime &limit, uint return false; } -chd_error mfm_harddisk_device::load_track(uint16_t* data, int cylinder, int head) +std::error_condition mfm_harddisk_device::load_track(uint16_t* data, int cylinder, int head) { - chd_error state = m_format->load(m_chd, data, m_trackimage_size, cylinder, head); - return state; + return m_format->load(m_chd, data, m_trackimage_size, cylinder, head); } void mfm_harddisk_device::write_track(uint16_t* data, int cylinder, int head) @@ -1070,7 +1069,7 @@ void mfmhd_trackimage_cache::init(mfm_harddisk_device* mfmhd, int tracksize, int { if (TRACE_CACHE) m_machine.logerror("[%s:cache] MFM HD cache init; cache size is %d tracks\n", mfmhd->tag(), trackslots); - chd_error state; + std::error_condition state; mfmhd_trackimage* previous; mfmhd_trackimage* current = nullptr; @@ -1091,7 +1090,8 @@ void mfmhd_trackimage_cache::init(mfm_harddisk_device* mfmhd, int tracksize, int // Load the first tracks into the slots state = m_mfmhd->load_track(current->encdata.get(), cylinder, head); - if (state != CHDERR_NONE) throw emu_fatalerror("Cannot load (c=%d,h=%d) from hard disk", cylinder, head); + if (state) + throw emu_fatalerror("Cannot load (c=%d,h=%d) from hard disk", cylinder, head); current->dirty = false; current->cylinder = cylinder; @@ -1128,11 +1128,11 @@ uint16_t* mfmhd_trackimage_cache::get_trackimage(int cylinder, int head) mfmhd_trackimage* current = m_tracks; mfmhd_trackimage* previous = nullptr; - chd_error state = CHDERR_NONE; + std::error_condition state; // Repeat the search. This loop should run at most twice; once for a direct hit, // and twice on miss, then the second iteration will be a hit. - while (state == CHDERR_NONE) + while (!state) { // A simple linear search while (current != nullptr) diff --git a/src/devices/imagedev/mfmhd.h b/src/devices/imagedev/mfmhd.h index 007be4be420..bb5d8493f97 100644 --- a/src/devices/imagedev/mfmhd.h +++ b/src/devices/imagedev/mfmhd.h @@ -17,8 +17,12 @@ #pragma once #include "imagedev/harddriv.h" + #include "formats/mfm_hd.h" +#include + + class mfm_harddisk_device; class mfmhd_trackimage @@ -94,7 +98,7 @@ public: attotime track_end_time(); // Access the tracks on the image. Used as a callback from the cache. - chd_error load_track(uint16_t* data, int cylinder, int head); + std::error_condition load_track(uint16_t* data, int cylinder, int head); void write_track(uint16_t* data, int cylinder, int head); // Delivers the number of heads according to the loaded image diff --git a/src/devices/imagedev/midiin.cpp b/src/devices/imagedev/midiin.cpp index 54a9f1c2297..e2386afb532 100644 --- a/src/devices/imagedev/midiin.cpp +++ b/src/devices/imagedev/midiin.cpp @@ -129,7 +129,7 @@ image_init_result midiin_device::call_load() { // attempt to load if it's a real file m_err = load_image_by_path(OPEN_FLAG_READ, filename()); - if (m_err == IMAGE_ERROR_SUCCESS) + if (!m_err) { // if the parsing succeeds, schedule the start to happen at least // 10 seconds after starting to allow the keyboards to initialize diff --git a/src/devices/machine/ataflash.cpp b/src/devices/machine/ataflash.cpp index 464bd074cdf..155ec34bcd3 100644 --- a/src/devices/machine/ataflash.cpp +++ b/src/devices/machine/ataflash.cpp @@ -140,7 +140,7 @@ void taito_pccard1_device::device_reset() uint32_t metalength; memset(m_key, 0, sizeof(m_key)); - if (m_handle != nullptr && m_handle->read_metadata(HARD_DISK_KEY_METADATA_TAG, 0, m_key, 5, metalength) == CHDERR_NONE) + if (m_handle && !m_handle->read_metadata(HARD_DISK_KEY_METADATA_TAG, 0, m_key, 5, metalength)) { m_locked = 0x1ff; } @@ -231,7 +231,7 @@ void taito_pccard2_device::device_reset() uint32_t metalength; memset(m_key, 0, sizeof(m_key)); - if (m_handle != nullptr && m_handle->read_metadata(HARD_DISK_KEY_METADATA_TAG, 0, m_key, 5, metalength) == CHDERR_NONE) + if (m_handle && !m_handle->read_metadata(HARD_DISK_KEY_METADATA_TAG, 0, m_key, 5, metalength)) { m_locked = true; } @@ -330,7 +330,7 @@ void taito_compact_flash_device::device_reset() uint32_t metalength; memset(m_key, 0, sizeof(m_key)); - if (m_handle != nullptr && m_handle->read_metadata(HARD_DISK_KEY_METADATA_TAG, 0, m_key, 5, metalength) == CHDERR_NONE) + if (m_handle && !m_handle->read_metadata(HARD_DISK_KEY_METADATA_TAG, 0, m_key, 5, metalength)) { m_locked = true; } diff --git a/src/devices/machine/ch376.cpp b/src/devices/machine/ch376.cpp index 8c13833292e..eeca140ec0a 100644 --- a/src/devices/machine/ch376.cpp +++ b/src/devices/machine/ch376.cpp @@ -255,7 +255,7 @@ void ch376_device::write(offs_t offset, u8 data) tmpPath.append(m_file_name); } - if (osd_file::open(tmpPath, OPEN_FLAG_READ|OPEN_FLAG_WRITE, m_file, size) == osd_file::error::NONE) + if (!osd_file::open(tmpPath, OPEN_FLAG_READ|OPEN_FLAG_WRITE, m_file, size)) { m_int_status = STATUS_USB_INT_SUCCESS; m_cur_file_size = size & 0xffffffff; diff --git a/src/devices/machine/hp_dc100_tape.cpp b/src/devices/machine/hp_dc100_tape.cpp index 2c4b55e0156..7d068af39d6 100644 --- a/src/devices/machine/hp_dc100_tape.cpp +++ b/src/devices/machine/hp_dc100_tape.cpp @@ -30,6 +30,8 @@ #include "emu.h" #include "hp_dc100_tape.h" +#include "util/ioprocs.h" + // Debugging #include "logmacro.h" #define LOG_TMR_MASK (LOG_GENERAL << 1) @@ -107,12 +109,12 @@ void hp_dc100_tape_device::call_unload() device_reset(); if (m_image_dirty) { - io_generic io; - io.file = (device_image_interface *)this; - io.procs = &image_ioprocs; - io.filler = 0; - m_image.save_tape(&io); - m_image_dirty = false; + check_for_file(); + auto io = util::core_file_read_write(image_core_file(), 0); + if (io) { + m_image.save_tape(*io); + m_image_dirty = false; + } } m_image.clear_tape(); @@ -602,18 +604,31 @@ image_init_result hp_dc100_tape_device::internal_load(bool is_create) device_reset(); - io_generic io; - io.file = (device_image_interface *)this; - io.procs = &image_ioprocs; - io.filler = 0; + check_for_file(); if (is_create) { + auto io = util::core_file_read_write(image_core_file(), 0); + if (!io) { + LOG("out of memory\n"); + seterror(std::errc::not_enough_memory, nullptr); + set_tape_present(false); + return image_init_result::FAIL; + } m_image.clear_tape(); - m_image.save_tape(&io); - } else if (!m_image.load_tape(&io)) { - LOG("load failed\n"); - seterror(IMAGE_ERROR_INVALIDIMAGE , "Wrong format"); - set_tape_present(false); - return image_init_result::FAIL; + m_image.save_tape(*io); + } else { + auto io = util::core_file_read(image_core_file(), 0); + if (!io) { + LOG("out of memory\n"); + seterror(std::errc::not_enough_memory, nullptr); + set_tape_present(false); + return image_init_result::FAIL; + } + if (!m_image.load_tape(*io)) { + LOG("load failed\n"); + seterror(image_error::INVALIDIMAGE , "Wrong format"); + set_tape_present(false); + return image_init_result::FAIL; + } } LOG("load OK\n"); diff --git a/src/devices/machine/laserdsc.cpp b/src/devices/machine/laserdsc.cpp index 92fad4019fd..6d1ef156bf9 100644 --- a/src/devices/machine/laserdsc.cpp +++ b/src/devices/machine/laserdsc.cpp @@ -10,11 +10,11 @@ #include "emu.h" #include "laserdsc.h" -#include "avhuff.h" -#include "vbiparse.h" + #include "config.h" #include "render.h" #include "romload.h" + #include "chd.h" @@ -73,7 +73,7 @@ laserdisc_device::laserdisc_device(const machine_config &mconfig, device_type ty m_height(0), m_fps_times_1million(0), m_samplerate(0), - m_readresult(CHDERR_NONE), + m_readresult(), m_chdtracks(0), m_work_queue(osd_work_queue_alloc(WORK_QUEUE_FLAG_IO)), m_audiosquelch(0), @@ -661,8 +661,9 @@ void laserdisc_device::init_disc() // read the metadata std::string metadata; - chd_error err = m_disc->read_metadata(AV_METADATA_TAG, 0, metadata); - if (err != CHDERR_NONE) + std::error_condition err; + err = m_disc->read_metadata(AV_METADATA_TAG, 0, metadata); + if (err) throw emu_fatalerror("Non-A/V CHD file specified"); // extract the metadata @@ -682,7 +683,7 @@ void laserdisc_device::init_disc() // allocate memory for the precomputed per-frame metadata err = m_disc->read_metadata(AV_LD_METADATA_TAG, 0, m_vbidata); - if (err != CHDERR_NONE || m_vbidata.size() != totalhunks * VBI_PACKED_BYTES) + if (err || (m_vbidata.size() != totalhunks * VBI_PACKED_BYTES)) throw emu_fatalerror("Precomputed VBI metadata missing or incorrect size"); } m_maxtrack = std::max(m_maxtrack, VIRTUAL_LEAD_IN_TRACKS + VIRTUAL_LEAD_OUT_TRACKS + m_chdtracks); @@ -959,14 +960,14 @@ void laserdisc_device::read_track_data() } // configure the codec and then read - m_readresult = CHDERR_FILE_NOT_FOUND; - if (m_disc != nullptr && !m_videosquelch) + m_readresult = std::errc::no_such_file_or_directory; + if (m_disc && !m_videosquelch) { m_readresult = m_disc->codec_configure(CHD_CODEC_AVHUFF, AVHUFF_CODEC_DECOMPRESS_CONFIG, &m_avhuff_config); - if (m_readresult == CHDERR_NONE) + if (!m_readresult) { m_queued_hunknum = readhunk; - m_readresult = CHDERR_OPERATION_PENDING; + m_readresult = chd_file::error::OPERATION_PENDING; osd_work_item_queue(m_work_queue, read_async_static, this, WORK_ITEM_FLAG_AUTO_RELEASE); } } @@ -994,12 +995,12 @@ void *laserdisc_device::read_async_static(void *param, int threadid) void laserdisc_device::process_track_data() { // wait for the async operation to complete - if (m_readresult == CHDERR_OPERATION_PENDING) + if (m_readresult == chd_file::error::OPERATION_PENDING) osd_work_queue_wait(m_work_queue, osd_ticks_per_second() * 10); - assert(m_readresult != CHDERR_OPERATION_PENDING); + assert(m_readresult != chd_file::error::OPERATION_PENDING); // remove the video if we had an error - if (m_readresult != CHDERR_NONE) + if (m_readresult) m_avhuff_video.reset(); // count the field as read if we are successful diff --git a/src/devices/machine/laserdsc.h b/src/devices/machine/laserdsc.h index 5fcc317a761..5eb06f105ea 100644 --- a/src/devices/machine/laserdsc.h +++ b/src/devices/machine/laserdsc.h @@ -18,8 +18,10 @@ #include "vbiparse.h" #include "avhuff.h" -#include +#include +#include #include +#include //************************************************************************** @@ -244,8 +246,8 @@ private: { bitmap_yuy16 m_bitmap; // cached bitmap bitmap_yuy16 m_visbitmap; // wrapper around bitmap with only visible lines - uint8_t m_numfields; // number of fields in this frame - int32_t m_lastfield; // last absolute field number + uint8_t m_numfields; // number of fields in this frame + int32_t m_lastfield; // last absolute field number }; // internal helpers @@ -267,19 +269,19 @@ private: get_disc_delegate m_getdisc_callback; audio_delegate m_audio_callback; // audio streaming callback laserdisc_overlay_config m_orig_config; // original overlay configuration - uint32_t m_overwidth; // overlay screen width - uint32_t m_overheight; // overlay screen height + uint32_t m_overwidth; // overlay screen width + uint32_t m_overheight; // overlay screen height rectangle m_overclip; // overlay visarea screen_update_rgb32_delegate m_overupdate_rgb32; // overlay update delegate // disc parameters chd_file * m_disc; // handle to the disc itself - std::vector m_vbidata; // pointer to precomputed VBI data + std::vector m_vbidata; // pointer to precomputed VBI data int m_width; // width of video int m_height; // height of video uint32_t m_fps_times_1million; // frame rate of video int m_samplerate; // audio samplerate - int m_readresult; // result of the most recent read + std::error_condition m_readresult; // result of the most recent read uint32_t m_chdtracks; // number of tracks in the CHD bitmap_yuy16 m_avhuff_video; // decompresed frame buffer avhuff_decoder::config m_avhuff_config; // decompression configuration @@ -305,11 +307,11 @@ private: // audio data sound_stream * m_stream; std::vector m_audiobuffer[2]; // buffer for audio samples - uint32_t m_audiobufsize; // size of buffer - uint32_t m_audiobufin; // input index - uint32_t m_audiobufout; // output index - uint32_t m_audiocursamples; // current samples this track - uint32_t m_audiomaxsamples; // maximum samples per track + uint32_t m_audiobufsize; // size of buffer + uint32_t m_audiobufin; // input index + uint32_t m_audiobufout; // output index + uint32_t m_audiocursamples; // current samples this track + uint32_t m_audiomaxsamples; // maximum samples per track // metadata vbi_metadata m_metadata[2]; // metadata parsed from the stream, for each field diff --git a/src/devices/sound/samples.cpp b/src/devices/sound/samples.cpp index 5c8d129b799..7663d921475 100644 --- a/src/devices/sound/samples.cpp +++ b/src/devices/sound/samples.cpp @@ -605,26 +605,28 @@ bool samples_device::load_samples() // load the samples int index = 0; - for (const char *samplename = iter.first(); samplename != nullptr; index++, samplename = iter.next()) + for (const char *samplename = iter.first(); samplename; index++, samplename = iter.next()) { // attempt to open as FLAC first emu_file file(machine().options().sample_path(), OPEN_FLAG_READ); - osd_file::error filerr = file.open(util::string_format("%s" PATH_SEPARATOR "%s.flac", basename, samplename)); - if (filerr != osd_file::error::NONE && altbasename != nullptr) + std::error_condition filerr = file.open(util::string_format("%s" PATH_SEPARATOR "%s.flac", basename, samplename)); + if (filerr && altbasename) filerr = file.open(util::string_format("%s" PATH_SEPARATOR "%s.flac", altbasename, samplename)); // if not, try as WAV - if (filerr != osd_file::error::NONE) + if (filerr) filerr = file.open(util::string_format("%s" PATH_SEPARATOR "%s.wav", basename, samplename)); - if (filerr != osd_file::error::NONE && altbasename != nullptr) + if (filerr && altbasename) filerr = file.open(util::string_format("%s" PATH_SEPARATOR "%s.wav", altbasename, samplename)); // if opened, read it - if (filerr == osd_file::error::NONE) + if (!filerr) + { read_sample(file, m_sample[index]); - else if (filerr == osd_file::error::NOT_FOUND) + } + else { - logerror("%s: Sample '%s' NOT FOUND\n", tag(), samplename); + logerror("Error opening sample '%s' (%s:%d %s)\n", samplename, filerr.category().name(), filerr.value(), filerr.message()); ok = false; } } diff --git a/src/emu/addrmap.h b/src/emu/addrmap.h index c5a6c17d128..76cdc6aef54 100644 --- a/src/emu/addrmap.h +++ b/src/emu/addrmap.h @@ -72,7 +72,7 @@ class address_map_entry friend class address_map; template - struct is_addrmap_method { static constexpr bool value = std::is_constructible::value; }; + using is_addrmap_method = std::bool_constant >; template static std::enable_if_t::value, address_map_constructor> make_delegate(Ret (T::*func)(Params...), const char *name, T *obj) diff --git a/src/emu/config.cpp b/src/emu/config.cpp index 46bec43c1dd..792da6f255d 100644 --- a/src/emu/config.cpp +++ b/src/emu/config.cpp @@ -64,16 +64,16 @@ bool configuration_manager::load_settings() type.load(config_type::INIT, config_level::DEFAULT, nullptr); // now load the controller file - const char *controller = machine().options().ctrlr(); + char const *const controller = machine().options().ctrlr(); if (controller && *controller) { // open the config file emu_file file(machine().options().ctrlr_path(), OPEN_FLAG_READ); osd_printf_verbose("Attempting to parse: %s.cfg\n", controller); - osd_file::error filerr = file.open(std::string(controller) + ".cfg"); + std::error_condition const filerr = file.open(std::string(controller) + ".cfg"); - if (filerr != osd_file::error::NONE) - throw emu_fatalerror("Could not open controller file %s.cfg", controller); + if (filerr) + throw emu_fatalerror("Could not open controller file %s.cfg (%s:%d %s)", controller, filerr.category().name(), filerr.value(), filerr.message()); // load the XML if (!load_xml(file, config_type::CONTROLLER)) @@ -82,15 +82,15 @@ bool configuration_manager::load_settings() // next load the defaults file emu_file file(machine().options().cfg_directory(), OPEN_FLAG_READ); - osd_file::error filerr = file.open("default.cfg"); + std::error_condition filerr = file.open("default.cfg"); osd_printf_verbose("Attempting to parse: default.cfg\n"); - if (filerr == osd_file::error::NONE) + if (!filerr) load_xml(file, config_type::DEFAULT); // finally, load the game-specific file filerr = file.open(machine().basename() + ".cfg"); osd_printf_verbose("Attempting to parse: %s.cfg\n",machine().basename()); - const bool loaded = (osd_file::error::NONE == filerr) && load_xml(file, config_type::SYSTEM); + const bool loaded = !filerr && load_xml(file, config_type::SYSTEM); // loop over all registrants and call their final function for (const auto &type : m_typelist) @@ -110,13 +110,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); - osd_file::error filerr = file.open("default.cfg"); - if (filerr == osd_file::error::NONE) + std::error_condition filerr = file.open("default.cfg"); + if (!filerr) save_xml(file, config_type::DEFAULT); // finally, save the system-specific file filerr = file.open(machine().basename() + ".cfg"); - if (filerr == osd_file::error::NONE) + if (!filerr) save_xml(file, config_type::SYSTEM); // loop over all registrants and call their final function diff --git a/src/emu/crsshair.cpp b/src/emu/crsshair.cpp index 43eac50587b..3c6a6b807f0 100644 --- a/src/emu/crsshair.cpp +++ b/src/emu/crsshair.cpp @@ -189,7 +189,7 @@ void render_crosshair::create_bitmap() if (!m_name.empty()) { // look for user specified file - if (crossfile.open(m_name + ".png") == osd_file::error::NONE) + if (!crossfile.open(m_name + ".png")) { render_load_png(*m_bitmap, crossfile); crossfile.close(); @@ -199,14 +199,14 @@ void render_crosshair::create_bitmap() { // look for default cross?.png in crsshair/game dir std::string const filename = string_format("cross%d.png", m_player + 1); - if (crossfile.open(m_machine.system().name + (PATH_SEPARATOR + filename)) == osd_file::error::NONE) + if (!crossfile.open(m_machine.system().name + (PATH_SEPARATOR + filename))) { render_load_png(*m_bitmap, crossfile); crossfile.close(); } // look for default cross?.png in crsshair dir - if (!m_bitmap->valid() && (crossfile.open(filename) == osd_file::error::NONE)) + if (!m_bitmap->valid() && !crossfile.open(filename)) { render_load_png(*m_bitmap, crossfile); crossfile.close(); diff --git a/src/emu/debug/debugcmd.cpp b/src/emu/debug/debugcmd.cpp index bd537935851..58cc85f7a86 100644 --- a/src/emu/debug/debugcmd.cpp +++ b/src/emu/debug/debugcmd.cpp @@ -3671,11 +3671,11 @@ void debugger_commands::execute_snap(int ref, const std::vector &pa if (fname.find(".png") == -1) fname.append(".png"); emu_file file(m_machine.options().snapshot_directory(), OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS); - osd_file::error filerr = file.open(std::move(fname)); + std::error_condition filerr = file.open(std::move(fname)); - if (filerr != osd_file::error::NONE) + if (filerr) { - m_console.printf("Error creating file '%s'\n", filename); + m_console.printf("Error creating file '%s' (%s:%d %s)\n", filename, filerr.category().name(), filerr.value(), filerr.message()); return; } diff --git a/src/emu/debug/debugcpu.cpp b/src/emu/debug/debugcpu.cpp index 1399a6b8ec2..233e369433e 100644 --- a/src/emu/debug/debugcpu.cpp +++ b/src/emu/debug/debugcpu.cpp @@ -168,8 +168,8 @@ bool debugger_cpu::comment_save() if (found_comments) { emu_file file(m_machine.options().comment_directory(), OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS); - osd_file::error filerr = file.open(m_machine.basename() + ".cmt"); - if (filerr == osd_file::error::NONE) + std::error_condition const filerr = file.open(m_machine.basename() + ".cmt"); + if (!filerr) { root->write(file); comments_saved = true; @@ -194,10 +194,10 @@ bool debugger_cpu::comment_load(bool is_inline) { // open the file emu_file file(m_machine.options().comment_directory(), OPEN_FLAG_READ); - osd_file::error filerr = file.open(m_machine.basename() + ".cmt"); + std::error_condition const filerr = file.open(m_machine.basename() + ".cmt"); // if an error, just return false - if (filerr != osd_file::error::NONE) + if (filerr) return false; // wrap in a try/catch to handle errors diff --git a/src/emu/devcb.h b/src/emu/devcb.h index ec543aa48d6..d27d3beb74d 100644 --- a/src/emu/devcb.h +++ b/src/emu/devcb.h @@ -82,16 +82,16 @@ protected: template using mask_t = std::make_unsigned_t >; // Detecting candidates for transform functions - template struct is_transform_form1 { static constexpr bool value = false; }; - template struct is_transform_form2 { static constexpr bool value = false; }; - template struct is_transform_form3 { static constexpr bool value = false; }; - template struct is_transform_form4 { static constexpr bool value = false; }; - template struct is_transform_form5 { static constexpr bool value = false; }; - template struct is_transform_form6 { static constexpr bool value = false; }; - template struct is_transform_form3 &>, Result>::value> > { static constexpr bool value = true; }; - template struct is_transform_form4, Result>::value> > { static constexpr bool value = true; }; - template struct is_transform_form6, Result>::value> > { static constexpr bool value = true; }; - template struct is_transform { static constexpr bool value = is_transform_form1::value || is_transform_form2::value || is_transform_form3::value || is_transform_form4::value || is_transform_form5::value || is_transform_form6::value; }; + template struct is_transform_form1 : public std::false_type { }; + template struct is_transform_form2 : public std::false_type { }; + template struct is_transform_form3 : public std::false_type { }; + template struct is_transform_form4 : public std::false_type { }; + template struct is_transform_form5 : public std::false_type { }; + template struct is_transform_form6 : public std::false_type { }; + template struct is_transform_form3 &>, Result>::value> > : public std::true_type { }; + template struct is_transform_form4, Result>::value> > : public std::true_type { }; + template struct is_transform_form6, Result>::value> > : public std::true_type { }; + template struct is_transform : public std::bool_constant::value || is_transform_form2::value || is_transform_form3::value || is_transform_form4::value || is_transform_form5::value || is_transform_form6::value> { }; // Determining the result type of a transform function template struct transform_result; @@ -211,13 +211,13 @@ class devcb_read_base : public devcb_base { protected: // Detecting candidates for read functions - template struct is_read_form1 { static constexpr bool value = false; }; - template struct is_read_form2 { static constexpr bool value = false; }; - template struct is_read_form3 { static constexpr bool value = false; }; - template struct is_read_form1, Result>::value> > { static constexpr bool value = true; }; - template struct is_read_form2, Result>::value> > { static constexpr bool value = true; }; - template struct is_read_form3, Result>::value> > { static constexpr bool value = true; }; - template struct is_read { static constexpr bool value = is_read_form1::value || is_read_form2::value || is_read_form3::value; }; + template struct is_read_form1 : public std::false_type { }; + template struct is_read_form2 : public std::false_type { }; + template struct is_read_form3 : public std::false_type { }; + template struct is_read_form1, Result>::value> > : public std::true_type { }; + template struct is_read_form2, Result>::value> > : public std::true_type { }; + template struct is_read_form3, Result>::value> > : public std::true_type { }; + template struct is_read : public std::bool_constant::value || is_read_form2::value || is_read_form3::value> { }; // Determining the result type of a read function template struct read_result; @@ -227,20 +227,20 @@ protected: template using read_result_t = typename read_result::type; // Detecting candidates for read delegates - template struct is_read_method { static constexpr bool value = false; }; - template struct is_read_method > > > { static constexpr bool value = true; }; - template struct is_read_method > > > { static constexpr bool value = true; }; - template struct is_read_method > > > { static constexpr bool value = true; }; - template struct is_read_method > > > { static constexpr bool value = true; }; - template struct is_read_method > > > { static constexpr bool value = true; }; - template struct is_read_method > > > { static constexpr bool value = true; }; - template struct is_read_method > > > { static constexpr bool value = true; }; - template struct is_read_method > > > { static constexpr bool value = true; }; - template struct is_read_method > > > { static constexpr bool value = true; }; - template struct is_read_method > > > { static constexpr bool value = true; }; - template struct is_read_method > > > { static constexpr bool value = true; }; - template struct is_read_method > > > { static constexpr bool value = true; }; - template struct is_read_method > > > { static constexpr bool value = true; }; + template struct is_read_method : public std::false_type { }; + template struct is_read_method > > > : public std::true_type { }; + template struct is_read_method > > > : public std::true_type { }; + template struct is_read_method > > > : public std::true_type { }; + template struct is_read_method > > > : public std::true_type { }; + template struct is_read_method > > > : public std::true_type { }; + template struct is_read_method > > > : public std::true_type { }; + template struct is_read_method > > > : public std::true_type { }; + template struct is_read_method > > > : public std::true_type { }; + template struct is_read_method > > > : public std::true_type { }; + template struct is_read_method > > > : public std::true_type { }; + template struct is_read_method > > > : public std::true_type { }; + template struct is_read_method > > > : public std::true_type { }; + template struct is_read_method > > > : public std::true_type { }; // Invoking read callbacks template static std::enable_if_t::value, mask_t, Result> > invoke_read(T const &cb, offs_t offset, std::make_unsigned_t mem_mask) { return std::make_unsigned_t >(cb(offset, mem_mask)); } @@ -275,29 +275,29 @@ class devcb_write_base : public devcb_base { protected: // Detecting candidates for write functions - template struct is_write_form1 { static constexpr bool value = false; }; - template struct is_write_form2 { static constexpr bool value = false; }; - template struct is_write_form3 { static constexpr bool value = false; }; - template struct is_write_form1> > > { static constexpr bool value = true; }; - template struct is_write_form2 > > { static constexpr bool value = true; }; - template struct is_write_form3 > > { static constexpr bool value = true; }; - template struct is_write { static constexpr bool value = is_write_form1::value || is_write_form2::value || is_write_form3::value; }; + template struct is_write_form1 : public std::false_type { }; + template struct is_write_form2 : public std::false_type { }; + template struct is_write_form3 : public std::false_type { }; + template struct is_write_form1> > > : public std::true_type { }; + template struct is_write_form2 > > : public std::true_type { }; + template struct is_write_form3 > > : public std::true_type { }; + template struct is_write : public std::bool_constant::value || is_write_form2::value || is_write_form3::value> { }; // Detecting candidates for write delegates - template struct is_write_method { static constexpr bool value = false; }; - template struct is_write_method > > > { static constexpr bool value = true; }; - template struct is_write_method > > > { static constexpr bool value = true; }; - template struct is_write_method > > > { static constexpr bool value = true; }; - template struct is_write_method > > > { static constexpr bool value = true; }; - template struct is_write_method > > > { static constexpr bool value = true; }; - template struct is_write_method > > > { static constexpr bool value = true; }; - template struct is_write_method > > > { static constexpr bool value = true; }; - template struct is_write_method > > > { static constexpr bool value = true; }; - template struct is_write_method > > > { static constexpr bool value = true; }; - template struct is_write_method > > > { static constexpr bool value = true; }; - template struct is_write_method > > > { static constexpr bool value = true; }; - template struct is_write_method > > > { static constexpr bool value = true; }; - template struct is_write_method > > > { static constexpr bool value = true; }; + template struct is_write_method : public std::false_type { }; + template struct is_write_method > > > : public std::true_type { }; + template struct is_write_method > > > : public std::true_type { }; + template struct is_write_method > > > : public std::true_type { }; + template struct is_write_method > > > : public std::true_type { }; + template struct is_write_method > > > : public std::true_type { }; + template struct is_write_method > > > : public std::true_type { }; + template struct is_write_method > > > : public std::true_type { }; + template struct is_write_method > > > : public std::true_type { }; + template struct is_write_method > > > : public std::true_type { }; + template struct is_write_method > > > : public std::true_type { }; + template struct is_write_method > > > : public std::true_type { }; + template struct is_write_method > > > : public std::true_type { }; + template struct is_write_method > > > : public std::true_type { }; // Invoking write callbacks template static std::enable_if_t::value> invoke_write(T const &cb, offs_t &offset, Input data, std::make_unsigned_t mem_mask) { return cb(offset, data, mem_mask); } diff --git a/src/emu/devdelegate.h b/src/emu/devdelegate.h index 1ba303d3ef3..906e1da9274 100644 --- a/src/emu/devdelegate.h +++ b/src/emu/devdelegate.h @@ -111,12 +111,12 @@ class device_delegate : protected named_delegate; - template struct is_related_device_implementation - { static constexpr bool value = std::is_base_of::value && std::is_base_of::value; }; - template struct is_related_device_interface - { static constexpr bool value = std::is_base_of::value && std::is_base_of::value && !std::is_base_of::value; }; - template struct is_related_device - { static constexpr bool value = is_related_device_implementation::value || is_related_device_interface::value; }; + template + using is_related_device_implementation = std::bool_constant && std::is_base_of_v >; + template + using is_related_device_interface = std::bool_constant && std::is_base_of_v && !std::is_base_of_v >; + template + using is_related_device = std::bool_constant::value || is_related_device_interface::value>; template static std::enable_if_t::value, device_t &> get_device(T &object) { return object; } template static std::enable_if_t::value, device_t &> get_device(T &object) { return object.device(); } @@ -124,8 +124,8 @@ private: public: template using array = device_delegate_array; - template struct supports_callback - { static constexpr bool value = std::is_constructible::value; }; + template + using supports_callback = std::bool_constant >; // construct/assign explicit device_delegate(device_t &owner) : basetype(), detail::device_delegate_helper(owner) { } diff --git a/src/emu/devfind.h b/src/emu/devfind.h index c5f7a04929a..8253fb123f6 100644 --- a/src/emu/devfind.h +++ b/src/emu/devfind.h @@ -308,7 +308,7 @@ public: } /// \brief Dummy tag always treated as not found - constexpr static char DUMMY_TAG[17] = "finder_dummy_tag"; + static constexpr char DUMMY_TAG[17] = "finder_dummy_tag"; protected: /// \brief Designated constructor diff --git a/src/emu/device.h b/src/emu/device.h index 21ac3bcba6e..d5fe81dd305 100644 --- a/src/emu/device.h +++ b/src/emu/device.h @@ -69,15 +69,11 @@ namespace emu::detail { class device_type_impl_base; -template struct is_device_implementation -{ - static constexpr bool value = std::is_base_of::value; -}; +template +using is_device_implementation = std::bool_constant >; -template struct is_device_interface -{ - static constexpr bool value = std::is_base_of::value && !is_device_implementation::value; -}; +template +using is_device_interface = std::bool_constant && !is_device_implementation::value>; struct device_feature diff --git a/src/emu/diimage.cpp b/src/emu/diimage.cpp index 55a9193f3f1..e38b4939a2b 100644 --- a/src/emu/diimage.cpp +++ b/src/emu/diimage.cpp @@ -10,14 +10,15 @@ #include "emu.h" -#include "corestr.h" #include "emuopts.h" #include "romload.h" -#include "ui/uimain.h" -#include "zippath.h" #include "softlist.h" #include "softlist_dev.h" -#include "formats/ioprocs.h" + +#include "ui/uimain.h" + +#include "corestr.h" +#include "zippath.h" #include #include @@ -270,11 +271,8 @@ void device_image_interface::add_format(std::string &&name, std::string &&descri void device_image_interface::clear_error() { - m_err = IMAGE_ERROR_SUCCESS; - if (!m_err_message.empty()) - { - m_err_message.clear(); - } + m_err.clear(); + m_err_message.clear(); } @@ -284,21 +282,38 @@ void device_image_interface::clear_error() // error //------------------------------------------------- -static std::string_view messages[] = +std::error_category const &image_category() noexcept { - "", - "Internal error", - "Unsupported operation", - "Out of memory", - "File not found", - "Invalid image", - "File already open", - "Unspecified error" -}; + class image_category_impl : public std::error_category + { + public: + virtual char const *name() const noexcept override { return "image"; } + + virtual std::string message(int condition) const override + { + using namespace std::literals; + static std::string_view const s_messages[] = { + "No error"sv, + "Internal error"sv, + "Unsupported operation"sv, + "Invalid image"sv, + "File already open"sv, + "Unspecified error"sv }; + if ((0 <= condition) && (std::size(s_messages) > condition)) + return std::string(s_messages[condition]); + else + return "Unknown error"s; + } + }; + static image_category_impl const s_image_category_instance; + return s_image_category_instance; +} std::string_view device_image_interface::error() { - return (!m_err_message.empty()) ? m_err_message : messages[m_err]; + if (m_err && m_err_message.empty()) + m_err_message = m_err.message(); + return m_err_message; } @@ -307,14 +322,12 @@ std::string_view device_image_interface::error() // seterror - specifies an error on an image //------------------------------------------------- -void device_image_interface::seterror(image_error_t err, const char *message) +void device_image_interface::seterror(std::error_condition err, const char *message) { clear_error(); m_err = err; - if (message != nullptr) - { + if (message) m_err_message = message; - } } @@ -544,14 +557,13 @@ void device_image_interface::battery_load(void *buffer, int length, int fill) if (!buffer || (length <= 0)) throw emu_fatalerror("device_image_interface::battery_load: Must specify sensical buffer/length"); - osd_file::error filerr; - int bytes_read = 0; - std::string fname = std::string(device().machine().system().name).append(PATH_SEPARATOR).append(m_basename_noext).append(".nv"); + std::string const fname = std::string(device().machine().system().name).append(PATH_SEPARATOR).append(m_basename_noext).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); - if (filerr == osd_file::error::NONE) + std::error_condition const filerr = file.open(fname); + int bytes_read = 0; + if (!filerr) bytes_read = file.read(buffer, length); // fill remaining bytes (if necessary) @@ -563,14 +575,13 @@ void device_image_interface::battery_load(void *buffer, int length, const void * if (!buffer || (length <= 0)) throw emu_fatalerror("device_image_interface::battery_load: Must specify sensical buffer/length"); - osd_file::error filerr; - int bytes_read = 0; - std::string fname = std::string(device().machine().system().name).append(PATH_SEPARATOR).append(m_basename_noext).append(".nv"); + std::string const fname = std::string(device().machine().system().name).append(PATH_SEPARATOR).append(m_basename_noext).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); - if (filerr == osd_file::error::NONE) + std::error_condition const filerr = file.open(fname); + int bytes_read = 0; + if (!filerr) bytes_read = file.read(buffer, length); // if no file was present, copy the default contents @@ -598,8 +609,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); - osd_file::error filerr = file.open(fname); - if (filerr == osd_file::error::NONE) + std::error_condition const filerr = file.open(fname); + if (!filerr) file.write(buffer, length); } @@ -636,59 +647,31 @@ bool device_image_interface::uses_file_extension(const char *file_extension) con // IMAGE LOADING // *************************************************************************** -//------------------------------------------------- -// image_error_from_file_error - converts an image -// error to a file error -//------------------------------------------------- - -image_error_t device_image_interface::image_error_from_file_error(osd_file::error filerr) -{ - switch (filerr) - { - case osd_file::error::NONE: - return IMAGE_ERROR_SUCCESS; - - case osd_file::error::NOT_FOUND: - case osd_file::error::ACCESS_DENIED: - // file not found (or otherwise cannot open) - return IMAGE_ERROR_FILENOTFOUND; - - case osd_file::error::OUT_OF_MEMORY: - // out of memory - return IMAGE_ERROR_OUTOFMEMORY; - - case osd_file::error::ALREADY_OPEN: - // this shouldn't happen - return IMAGE_ERROR_ALREADYOPEN; - - case osd_file::error::FAILURE: - case osd_file::error::TOO_MANY_FILES: - case osd_file::error::INVALID_DATA: - default: - // other errors - return IMAGE_ERROR_INTERNAL; - } -} - - //------------------------------------------------- // load_image_by_path - loads an image with a // specific path //------------------------------------------------- -image_error_t device_image_interface::load_image_by_path(u32 open_flags, std::string_view path) +std::error_condition device_image_interface::load_image_by_path(u32 open_flags, std::string_view path) { std::string revised_path; // attempt to read the file - auto const filerr = util::zippath_fopen(path, open_flags, m_file, revised_path); - if (filerr != osd_file::error::NONE) - return image_error_from_file_error(filerr); + auto filerr = util::zippath_fopen(path, open_flags, m_file, revised_path); + if (filerr) + { + osd_printf_verbose("%s: error opening image file %s with flags=%08X (%s:%d %s)\n", device().tag(), path, open_flags, filerr.category().name(), filerr.value(), filerr.message()); + return filerr; + } + else + { + osd_printf_verbose("%s: opened image file %s with flags=%08X\n", device().tag(), path, open_flags); + } m_readonly = (open_flags & OPEN_FLAG_WRITE) ? 0 : 1; m_created = (open_flags & OPEN_FLAG_CREATE) ? 1 : 0; set_image_filename(revised_path); - return IMAGE_ERROR_SUCCESS; + return std::error_condition(); } @@ -696,7 +679,7 @@ image_error_t device_image_interface::load_image_by_path(u32 open_flags, std::st // reopen_for_write //------------------------------------------------- -int device_image_interface::reopen_for_write(std::string_view path) +std::error_condition device_image_interface::reopen_for_write(std::string_view path) { m_file.reset(); @@ -704,15 +687,15 @@ int device_image_interface::reopen_for_write(std::string_view path) // attempt to open the file for writing auto const filerr = util::zippath_fopen(path, OPEN_FLAG_READ|OPEN_FLAG_WRITE|OPEN_FLAG_CREATE, m_file, revised_path); - if (filerr != osd_file::error::NONE) - return image_error_from_file_error(filerr); + if (filerr) + return filerr; // success! m_readonly = 0; m_created = 1; set_image_filename(revised_path); - return IMAGE_ERROR_SUCCESS; + return std::error_condition(); } @@ -823,19 +806,19 @@ bool device_image_interface::load_software(software_list_device &swlist, std::st // try to load the file m_mame_file.reset(new emu_file(device().machine().options().media_path(), searchpath, OPEN_FLAG_READ)); m_mame_file->set_restrict_to_mediapath(1); - osd_file::error filerr; + std::error_condition filerr; if (has_crc) filerr = m_mame_file->open(romp->name(), crc); else filerr = m_mame_file->open(romp->name()); - if (filerr != osd_file::error::NONE) + if (filerr) m_mame_file.reset(); warningcount += verify_length_and_hash(m_mame_file.get(), romp->name(), romp->get_length(), util::hash_collection(romp->hashdata())); - if (filerr == osd_file::error::NONE) + if (!filerr) filerr = util::core_file::open_proxy(*m_mame_file, m_file); - if (filerr == osd_file::error::NONE) + if (!filerr) retval = true; break; // load first item for start @@ -878,14 +861,14 @@ image_init_result device_image_interface::load_internal(std::string_view path, b { // open the file m_err = load_image_by_path(*iter, path); - if (m_err && (m_err != IMAGE_ERROR_FILENOTFOUND)) + if (m_err && (m_err != std::errc::no_such_file_or_directory) && (m_err != std::errc::permission_denied)) goto done; } // did we fail to find the file? if (!m_file) { - m_err = IMAGE_ERROR_FILENOTFOUND; + m_err = std::errc::no_such_file_or_directory; goto done; } } @@ -894,15 +877,17 @@ image_init_result device_image_interface::load_internal(std::string_view path, b m_create_format = create_format; m_create_args = create_args; - if (init_phase()==false) { - m_err = (finish_load() == image_init_result::PASS) ? IMAGE_ERROR_SUCCESS : IMAGE_ERROR_INTERNAL; + if (!init_phase()) + { + m_err = (finish_load() == image_init_result::PASS) ? std::error_condition() : image_error::INTERNAL; if (m_err) goto done; } // success! done: - if (m_err!=0) { + if (m_err) + { if (!init_phase()) { if (device().machine().phase() == machine_phase::RUNNING) @@ -1004,7 +989,7 @@ image_init_result device_image_interface::finish_load() { if (!image_checkhash()) { - m_err = IMAGE_ERROR_INVALIDIMAGE; + m_err = image_error::INVALIDIMAGE; err = image_init_result::FAIL; } @@ -1016,7 +1001,7 @@ image_init_result device_image_interface::finish_load() if (err != image_init_result::PASS) { if (!m_err) - m_err = IMAGE_ERROR_UNSPECIFIED; + m_err = image_error::UNSPECIFIED; } } else @@ -1026,7 +1011,7 @@ image_init_result device_image_interface::finish_load() if (err != image_init_result::PASS) { if (!m_err) - m_err = IMAGE_ERROR_UNSPECIFIED; + m_err = image_error::UNSPECIFIED; } } } @@ -1354,41 +1339,3 @@ bool device_image_interface::init_phase() const return !device().has_running_machine() || device().machine().phase() == machine_phase::INIT; } - - -//---------------------------------------------------------------------------- - -static int image_fseek_thunk(void *file, s64 offset, int whence) -{ - device_image_interface *image = (device_image_interface *) file; - return image->fseek(offset, whence); -} - -static size_t image_fread_thunk(void *file, void *buffer, size_t length) -{ - device_image_interface *image = (device_image_interface *) file; - return image->fread(buffer, length); -} - -static size_t image_fwrite_thunk(void *file, const void *buffer, size_t length) -{ - device_image_interface *image = (device_image_interface *) file; - return image->fwrite(buffer, length); -} - -static u64 image_fsize_thunk(void *file) -{ - device_image_interface *image = (device_image_interface *) file; - return image->length(); -} - -//---------------------------------------------------------------------------- - -struct io_procs image_ioprocs = -{ - nullptr, - image_fseek_thunk, - image_fread_thunk, - image_fwrite_thunk, - image_fsize_thunk -}; diff --git a/src/emu/diimage.h b/src/emu/diimage.h index 507fd34e1d3..05f714f2647 100644 --- a/src/emu/diimage.h +++ b/src/emu/diimage.h @@ -19,6 +19,7 @@ #include #include +#include #include @@ -26,8 +27,6 @@ // TYPE DEFINITIONS //************************************************************************** -extern struct io_procs image_ioprocs; - enum iodevice_t { /* List of all supported devices. Refer to the device by these names only */ @@ -55,18 +54,19 @@ enum iodevice_t IO_COUNT /* 21 - Total Number of IO_devices for searching */ }; -enum image_error_t +enum class image_error : int { - IMAGE_ERROR_SUCCESS, - IMAGE_ERROR_INTERNAL, - IMAGE_ERROR_UNSUPPORTED, - IMAGE_ERROR_OUTOFMEMORY, - IMAGE_ERROR_FILENOTFOUND, - IMAGE_ERROR_INVALIDIMAGE, - IMAGE_ERROR_ALREADYOPEN, - IMAGE_ERROR_UNSPECIFIED + INTERNAL = 1, + UNSUPPORTED, + INVALIDIMAGE, + ALREADYOPEN, + UNSPECIFIED }; +const std::error_category &image_category() noexcept; +inline std::error_condition make_error_condition(image_error e) noexcept { return std::error_condition(int(e), image_category()); } +namespace std { template <> struct is_error_condition_enum : public std::true_type { }; } + struct image_device_type_info { iodevice_t m_type; @@ -150,7 +150,7 @@ public: const util::option_guide &device_get_creation_option_guide() const { return create_option_guide(); } std::string_view error(); - void seterror(image_error_t err, const char *message); + void seterror(std::error_condition err, const char *message); void message(const char *format, ...) ATTR_PRINTF(2,3); bool exists() const noexcept { return !m_image_name.empty(); } @@ -172,7 +172,7 @@ public: int fgetc() { char ch; if (fread(&ch, 1) != 1) ch = '\0'; return ch; } char *fgets(char *buffer, u32 length) { check_for_file(); return m_file->gets(buffer, length); } int image_feof() { check_for_file(); return m_file->eof(); } - void *ptr() {check_for_file(); return const_cast(m_file->buffer()); } + void *ptr() { check_for_file(); return const_cast(m_file->buffer()); } // configuration access const software_info *software_entry() const noexcept; @@ -217,7 +217,7 @@ public: image_init_result create(std::string_view path, const image_device_format *create_format, util::option_resolution *create_args); image_init_result create(std::string_view path); bool load_software(software_list_device &swlist, std::string_view swname, const rom_entry *entry); - int reopen_for_write(std::string_view path); + std::error_condition reopen_for_write(std::string_view path); void set_user_loadable(bool user_loadable) { m_user_loadable = user_loadable; } @@ -233,7 +233,7 @@ protected: virtual const bool use_software_list_file_extension_for_filetype() const { return false; } image_init_result load_internal(std::string_view path, bool is_create, int create_format, util::option_resolution *create_args); - image_error_t load_image_by_path(u32 open_flags, std::string_view path); + std::error_condition load_image_by_path(u32 open_flags, std::string_view path); void clear(); bool is_loaded() const { return m_file != nullptr; } @@ -260,7 +260,7 @@ protected: static const image_device_type_info m_device_info_array[]; // error related info - image_error_t m_err; + std::error_condition m_err; std::string m_err_message; private: @@ -277,7 +277,6 @@ private: const software_part *m_software_part_ptr; std::string m_software_list_name; - static image_error_t image_error_from_file_error(osd_file::error filerr); std::vector determine_open_plan(bool is_create); void update_names(); bool load_software_part(std::string_view identifier); diff --git a/src/emu/dimemory.h b/src/emu/dimemory.h index f15a04166f4..119ec9bc6f9 100644 --- a/src/emu/dimemory.h +++ b/src/emu/dimemory.h @@ -50,11 +50,11 @@ constexpr int TRANSLATE_FETCH_DEBUG = (TRANSLATE_FETCH | TRANSLATE_DEBUG_MAS class device_memory_interface : public device_interface { friend class device_scheduler; - template struct is_related_class { static constexpr bool value = std::is_convertible, std::add_pointer_t >::value; }; - template struct is_related_device { static constexpr bool value = emu::detail::is_device_implementation::value && is_related_class::value; }; - template struct is_related_interface { static constexpr bool value = emu::detail::is_device_interface::value && is_related_class::value; }; - template struct is_unrelated_device { static constexpr bool value = emu::detail::is_device_implementation::value && !is_related_class::value; }; - template struct is_unrelated_interface { static constexpr bool value = emu::detail::is_device_interface::value && !is_related_class::value; }; + template using is_related_class = std::bool_constant, std::add_pointer_t > >; + template using is_related_device = std::bool_constant::value && is_related_class::value >; + template using is_related_interface = std::bool_constant::value && is_related_class::value >; + template using is_unrelated_device = std::bool_constant::value && !is_related_class::value >; + template using is_unrelated_interface = std::bool_constant::value && !is_related_class::value >; public: // construction/destruction diff --git a/src/emu/dipty.cpp b/src/emu/dipty.cpp index 925113edd08..6a323d84e7f 100644 --- a/src/emu/dipty.cpp +++ b/src/emu/dipty.cpp @@ -27,7 +27,7 @@ bool device_pty_interface::open() { if (!m_opened) { - if (osd_file::openpty(m_pty_master, m_slave_name) == osd_file::error::NONE) + if (!osd_file::openpty(m_pty_master, m_slave_name)) { m_opened = true; } @@ -54,7 +54,7 @@ bool device_pty_interface::is_open() const ssize_t device_pty_interface::read(u8 *rx_chars , size_t count) const { u32 actual_bytes; - if (m_opened && m_pty_master->read(rx_chars, 0, count, actual_bytes) == osd_file::error::NONE) + if (m_opened && !m_pty_master->read(rx_chars, 0, count, actual_bytes)) return actual_bytes; else return -1; @@ -72,8 +72,3 @@ bool device_pty_interface::is_slave_connected() const // TODO: really check for slave status return m_opened; } - -const char *device_pty_interface::slave_name() const -{ - return m_slave_name.c_str(); -} diff --git a/src/emu/dipty.h b/src/emu/dipty.h index 790d4ec39b0..9fc1ddbc7e1 100644 --- a/src/emu/dipty.h +++ b/src/emu/dipty.h @@ -7,10 +7,14 @@ Device PTY interface ***************************************************************************/ - #ifndef MAME_EMU_DIPTY_H #define MAME_EMU_DIPTY_H +#pragma once + +#include + + class device_pty_interface : public device_interface { public: @@ -28,7 +32,7 @@ public: bool is_slave_connected() const; - const char *slave_name() const; + const std::string &slave_name() const { return m_slave_name; } protected: osd_file::ptr m_pty_master; diff --git a/src/emu/fileio.cpp b/src/emu/fileio.cpp index 293c23045b4..0fa41d3cd11 100644 --- a/src/emu/fileio.cpp +++ b/src/emu/fileio.cpp @@ -11,7 +11,8 @@ #include "emu.h" #include "fileio.h" -#include "unzip.h" +#include "util/path.h" +#include "util/unzip.h" //#define VERBOSE 1 #define LOG_OUTPUT_FUNC osd_printf_verbose @@ -121,12 +122,7 @@ bool path_iterator::next(std::string &buffer, const char *name) // append the name if we have one if (name) - { - // compute the full pathname - if (!buffer.empty() && !util::is_directory_separator(buffer.back())) - buffer.append(PATH_SEPARATOR); - buffer.append(name); - } + util::path_append(buffer, name); // bump the index and return true m_is_first = false; @@ -298,7 +294,7 @@ util::hash_collection &emu_file::hashes(std::string_view types) // open - open a file by searching paths //------------------------------------------------- -osd_file::error emu_file::open(std::string &&name) +std::error_condition emu_file::open(std::string &&name) { // remember the filename and CRC info m_filename = std::move(name); @@ -310,7 +306,7 @@ osd_file::error emu_file::open(std::string &&name) return open_next(); } -osd_file::error emu_file::open(std::string &&name, u32 crc) +std::error_condition emu_file::open(std::string &&name, u32 crc) { // remember the filename and CRC info m_filename = std::move(name); @@ -328,7 +324,7 @@ osd_file::error emu_file::open(std::string &&name, u32 crc) // the filename by iterating over paths //------------------------------------------------- -osd_file::error emu_file::open_next() +std::error_condition emu_file::open_next() { // if we're open from a previous attempt, close up now if (m_file) @@ -336,8 +332,8 @@ osd_file::error emu_file::open_next() // loop over paths LOG("emu_file: open next '%s'\n", m_filename); - osd_file::error filerr = osd_file::error::NOT_FOUND; - while (osd_file::error::NONE != filerr) + std::error_condition filerr = std::errc::no_such_file_or_directory; + while (filerr) { if (m_first) { @@ -385,7 +381,7 @@ osd_file::error emu_file::open_next() filerr = util::core_file::open(m_fullpath, m_openflags, m_file); // if we're opening for read-only we have other options - if ((osd_file::error::NONE != filerr) && ((m_openflags & (OPEN_FLAG_READ | OPEN_FLAG_WRITE)) == OPEN_FLAG_READ)) + if (filerr && ((m_openflags & (OPEN_FLAG_READ | OPEN_FLAG_WRITE)) == OPEN_FLAG_READ)) { LOG("emu_file: attempting to open '%s' from archives\n", m_fullpath); filerr = attempt_zipped(); @@ -400,7 +396,7 @@ osd_file::error emu_file::open_next() // just an array of data in RAM //------------------------------------------------- -osd_file::error emu_file::open_ram(const void *data, u32 length) +std::error_condition emu_file::open_ram(const void *data, u32 length) { // set a fake filename and CRC m_filename = "RAM"; @@ -434,30 +430,15 @@ void emu_file::close() } -//------------------------------------------------- -// compress - enable/disable streaming file -// compression via zlib; level is 0 to disable -// compression, or up to 9 for max compression -//------------------------------------------------- - -osd_file::error emu_file::compress(int level) -{ - return m_file->compress(level); -} - - //------------------------------------------------- // compressed_file_ready - ensure our zip is ready // loading if needed //------------------------------------------------- -bool emu_file::compressed_file_ready() +std::error_condition emu_file::compressed_file_ready() { // load the ZIP file now if we haven't yet - if (m_zipfile && (load_zipped_file() != osd_file::error::NONE)) - return true; - - return false; + return m_zipfile ? load_zipped_file() : std::error_condition(); } //------------------------------------------------- @@ -715,9 +696,9 @@ bool emu_file::part_of_mediapath(const std::string &path) // attempt_zipped - attempt to open a ZIPped file //------------------------------------------------- -osd_file::error emu_file::attempt_zipped() +std::error_condition emu_file::attempt_zipped() { - typedef util::archive_file::error (*open_func)(const std::string &filename, util::archive_file::ptr &result); + typedef std::error_condition (*open_func)(std::string_view filename, util::archive_file::ptr &result); char const *const suffixes[] = { ".zip", ".7z" }; open_func const open_funcs[std::size(suffixes)] = { &util::archive_file::open_zip, &util::archive_file::open_7z }; @@ -750,13 +731,13 @@ osd_file::error emu_file::attempt_zipped() // attempt to open the archive file util::archive_file::ptr zip; - util::archive_file::error ziperr = open_funcs[i](m_fullpath, zip); + std::error_condition ziperr = open_funcs[i](m_fullpath, zip); // chop the archive suffix back off the filename before continuing m_fullpath = m_fullpath.substr(0, dirsep); // if we failed to open this file, continue scanning - if (ziperr != util::archive_file::error::NONE) + if (ziperr) continue; int header = -1; @@ -788,14 +769,14 @@ osd_file::error emu_file::attempt_zipped() m_hashes.reset(); m_hashes.add_crc(m_zipfile->current_crc()); m_fullpath = savepath; - return (m_openflags & OPEN_FLAG_NO_PRELOAD) ? osd_file::error::NONE : load_zipped_file(); + return (m_openflags & OPEN_FLAG_NO_PRELOAD) ? std::error_condition() : load_zipped_file(); } // close up the archive file and try the next level zip.reset(); } } - return osd_file::error::NOT_FOUND; + return std::errc::no_such_file_or_directory; } @@ -803,7 +784,7 @@ osd_file::error emu_file::attempt_zipped() // load_zipped_file - load a ZIPped file //------------------------------------------------- -osd_file::error emu_file::load_zipped_file() +std::error_condition emu_file::load_zipped_file() { assert(m_file == nullptr); assert(m_zipdata.empty()); @@ -814,21 +795,21 @@ osd_file::error emu_file::load_zipped_file() // read the data into our buffer and return auto const ziperr = m_zipfile->decompress(&m_zipdata[0], m_zipdata.size()); - if (ziperr != util::archive_file::error::NONE) + if (ziperr) { m_zipdata.clear(); - return osd_file::error::FAILURE; + return ziperr; } // convert to RAM file - 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) + std::error_condition const filerr = util::core_file::open_ram(&m_zipdata[0], m_zipdata.size(), m_openflags, m_file); + if (filerr) { m_zipdata.clear(); - return osd_file::error::FAILURE; + return filerr; } // close out the ZIP file m_zipfile.reset(); - return osd_file::error::NONE; + return std::error_condition(); } diff --git a/src/emu/fileio.h b/src/emu/fileio.h index d05905efa83..f05706dffed 100644 --- a/src/emu/fileio.h +++ b/src/emu/fileio.h @@ -18,6 +18,7 @@ #include #include +#include #include #include #include @@ -156,19 +157,16 @@ public: void set_restrict_to_mediapath(int rtmp) { m_restrict_to_mediapath = rtmp; } // open/close - osd_file::error open(std::string &&name); - osd_file::error open(std::string &&name, u32 crc); - osd_file::error open(std::string_view name) { return open(std::string(name)); } - osd_file::error open(std::string_view name, u32 crc) { return open(std::string(name), crc); } - osd_file::error open(const char *name) { return open(std::string(name)); } - osd_file::error open(const char *name, u32 crc) { return open(std::string(name), crc); } - osd_file::error open_next(); - osd_file::error open_ram(const void *data, u32 length); + std::error_condition open(std::string &&name); + std::error_condition open(std::string &&name, u32 crc); + std::error_condition open(std::string_view name) { return open(std::string(name)); } + std::error_condition open(std::string_view name, u32 crc) { return open(std::string(name), crc); } + std::error_condition open(const char *name) { return open(std::string(name)); } + std::error_condition open(const char *name, u32 crc) { return open(std::string(name), crc); } + std::error_condition open_next(); + std::error_condition open_ram(const void *data, u32 length); void close(); - // control - osd_file::error compress(int compress); - // position int seek(s64 offset, int whence); u64 tell(); @@ -213,11 +211,11 @@ private: } bool part_of_mediapath(const std::string &path); - bool compressed_file_ready(); + std::error_condition compressed_file_ready(); // internal helpers - osd_file::error attempt_zipped(); - osd_file::error load_zipped_file(); + std::error_condition attempt_zipped(); + std::error_condition load_zipped_file(); // internal state std::string m_filename; // original filename provided diff --git a/src/emu/hashfile.cpp b/src/emu/hashfile.cpp index 50a32a60b29..a6107e5e630 100644 --- a/src/emu/hashfile.cpp +++ b/src/emu/hashfile.cpp @@ -27,10 +27,8 @@ static bool read_hash_config(const char *hash_path, const util::hash_collection { /* open a file */ emu_file file(hash_path, OPEN_FLAG_READ); - if (file.open(std::string(sysname) + ".hsi") != osd_file::error::NONE) - { + if (file.open(std::string(sysname) + ".hsi")) return false; - } pugi::xml_document doc; diff --git a/src/emu/http.cpp b/src/emu/http.cpp index b384049a37f..42d8120d32e 100644 --- a/src/emu/http.cpp +++ b/src/emu/http.cpp @@ -422,8 +422,8 @@ bool http_manager::read_file(std::ostream &os, const std::string &path) { std::ostringstream full_path; full_path << m_root << path; util::core_file::ptr f; - osd_file::error e = util::core_file::open(full_path.str(), OPEN_FLAG_READ, f); - if (e == osd_file::error::NONE) + std::error_condition const e = util::core_file::open(full_path.str(), OPEN_FLAG_READ, f); + if (!e) { int c; while ((c = f->getc()) >= 0) @@ -431,7 +431,7 @@ bool http_manager::read_file(std::ostream &os, const std::string &path) { os.put(c); } } - return e == osd_file::error::NONE; + return !e; } void http_manager::serve_document(http_request_ptr request, http_response_ptr response, const std::string &filename) { diff --git a/src/emu/image.cpp b/src/emu/image.cpp index c80d9bafde7..02cc25ce80b 100644 --- a/src/emu/image.cpp +++ b/src/emu/image.cpp @@ -173,8 +173,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); - osd_file::error filerr = file.open(filename); - if (filerr == osd_file::error::NONE) + std::error_condition const filerr = file.open(filename); + if (!filerr) { std::string inistring = options.output_ini(); file.puts(inistring); diff --git a/src/emu/ioport.cpp b/src/emu/ioport.cpp index 2e9d115e46e..cae37f28c17 100644 --- a/src/emu/ioport.cpp +++ b/src/emu/ioport.cpp @@ -99,9 +99,11 @@ #include "inputdev.h" #include "natkeyboard.h" -#include "corestr.h" +#include "util/corestr.h" +#include "util/ioprocsfilter.h" +#include "util/unicode.h" + #include "osdepend.h" -#include "unicode.h" #include #include @@ -2652,23 +2654,26 @@ template Type ioport_manager::playback_read(Type &result) { // protect against nullptr handles if previous reads fail - if (!m_playback_file.is_open()) - result = 0; + if (!m_playback_stream) + return result = Type(0); // read the value; if we fail, end playback - else if (m_playback_file.read(&result, sizeof(result)) != sizeof(result)) + size_t read; + m_playback_stream->read(&result, sizeof(result), read); + if (sizeof(result) != read) { playback_end("End of file"); - result = 0; + return result = Type(0); } - // return the appropriate value - else if (sizeof(result) == 8) + // normalize byte order + if (sizeof(result) == 8) result = little_endianize_int64(result); else if (sizeof(result) == 4) result = little_endianize_int32(result); else if (sizeof(result) == 2) result = little_endianize_int16(result); + return result; } @@ -2693,15 +2698,15 @@ time_t ioport_manager::playback_init() return 0; // open the playback file - osd_file::error filerr = m_playback_file.open(filename); + std::error_condition const filerr = m_playback_file.open(filename); // return an explicit error if file isn't found in given path - if(filerr == osd_file::error::NOT_FOUND) + if (filerr == std::errc::no_such_file_or_directory) fatalerror("Input file %s not found\n",filename); // TODO: bail out any other error laconically for now - if(filerr != osd_file::error::NONE) - fatalerror("Failed to open file %s for playback (code error=%d)\n",filename,int(filerr)); + if (filerr) + fatalerror("Failed to open file %s for playback (%s:%d %s)\n", filename, filerr.category().name(), filerr.value(), filerr.message()); // read the header and verify that it is a modern version; if not, print an error inp_header header; @@ -2725,7 +2730,7 @@ time_t ioport_manager::playback_init() osd_printf_info("Input file is for machine '%s', not for current machine '%s'\n", sysname, machine().system().name); // enable compression - m_playback_file.compress(FCOMPRESS_MEDIUM); + m_playback_stream = util::zlib_read(util::core_file_read(m_playback_file), 16386); return basetime; } @@ -2737,9 +2742,10 @@ time_t ioport_manager::playback_init() void ioport_manager::playback_end(const char *message) { // only applies if we have a live file - if (m_playback_file.is_open()) + if (m_playback_stream) { // close the file + m_playback_stream.reset(); m_playback_file.close(); // pop a message @@ -2753,7 +2759,8 @@ void ioport_manager::playback_end(const char *message) osd_printf_info("Average recorded speed: %d%%\n", u32((m_playback_accumulated_speed * 200 + 1) >> 21)); // close the program at the end of inp file playback - if (machine().options().exit_after_playback()) { + if (machine().options().exit_after_playback()) + { osd_printf_info("Exiting MAME now...\n"); machine().schedule_exit(); } @@ -2769,7 +2776,7 @@ void ioport_manager::playback_end(const char *message) void ioport_manager::playback_frame(const attotime &curtime) { // if playing back, fetch the information and verify - if (m_playback_file.is_open()) + if (m_playback_stream) { // first the absolute time seconds_t seconds_temp; @@ -2795,7 +2802,7 @@ void ioport_manager::playback_frame(const attotime &curtime) void ioport_manager::playback_port(ioport_port &port) { // if playing back, fetch information about this port - if (m_playback_file.is_open()) + if (m_playback_stream) { // read the default value and the digital state playback_read(port.live().defvalue); @@ -2824,11 +2831,20 @@ template void ioport_manager::record_write(Type value) { // protect against nullptr handles if previous reads fail - if (!m_record_file.is_open()) + if (!m_record_stream) return; - // read the value; if we fail, end playback - if (m_record_file.write(&value, sizeof(value)) != sizeof(value)) + // normalize byte order + if (sizeof(value) == 8) + value = little_endianize_int64(value); + else if (sizeof(value) == 4) + value = little_endianize_int32(value); + else if (sizeof(value) == 2) + value = little_endianize_int16(value); + + // write the value; if we fail, end recording + size_t written; + if (m_record_stream->write(&value, sizeof(value), written) || (sizeof(value) != written)) record_end("Out of space"); } @@ -2875,9 +2891,9 @@ void ioport_manager::record_init() return; // open the record file - osd_file::error filerr = m_record_file.open(filename); - if (filerr != osd_file::error::NONE) - throw emu_fatalerror("ioport_manager::record_init: Failed to open file for recording"); + std::error_condition const filerr = m_record_file.open(filename); + if (filerr) + throw emu_fatalerror("ioport_manager::record_init: Failed to open file for recording (%s:%d %s)", filerr.category().name(), filerr.value(), filerr.message()); // get the base time system_time systime; @@ -2895,7 +2911,7 @@ void ioport_manager::record_init() header.write(m_record_file); // enable compression - m_record_file.compress(FCOMPRESS_MEDIUM); + m_record_stream = util::zlib_write(util::core_file_read_write(m_record_file), 6, 16384); } @@ -2922,9 +2938,9 @@ void ioport_manager::timecode_init() filename.append(record_filename).append(".timecode"); osd_printf_info("Record input timecode file: %s\n", record_filename); - osd_file::error filerr = m_timecode_file.open(filename); - if (filerr != osd_file::error::NONE) - throw emu_fatalerror("ioport_manager::timecode_init: Failed to open file for input timecode recording"); + std::error_condition const filerr = m_timecode_file.open(filename); + if (filerr) + throw emu_fatalerror("ioport_manager::timecode_init: Failed to open file for input timecode recording (%s:%d %s)", filerr.category().name(), filerr.value(), filerr.message()); m_timecode_file.puts("# ==========================================\n"); m_timecode_file.puts("# TIMECODE FILE FOR VIDEO PREVIEW GENERATION\n"); @@ -2948,9 +2964,10 @@ void ioport_manager::timecode_init() void ioport_manager::record_end(const char *message) { // only applies if we have a live file - if (m_record_file.is_open()) + if (m_record_stream) { // close the file + m_record_stream.reset(); // TODO: check for errors flushing the last compressed block before doing this m_record_file.close(); // pop a message @@ -2981,7 +2998,7 @@ void ioport_manager::timecode_end(const char *message) void ioport_manager::record_frame(const attotime &curtime) { // if recording, record information about the current frame - if (m_record_file.is_open()) + if (m_record_stream) { // first the absolute time record_write(curtime.seconds()); @@ -3091,7 +3108,7 @@ void ioport_manager::record_frame(const attotime &curtime) void ioport_manager::record_port(ioport_port &port) { // if recording, store information about this port - if (m_record_file.is_open()) + if (m_record_stream) { // store the default value and digital state record_write(port.live().defvalue); diff --git a/src/emu/ioport.h b/src/emu/ioport.h index 11dcf006be9..fdf859b9afd 100644 --- a/src/emu/ioport.h +++ b/src/emu/ioport.h @@ -17,11 +17,14 @@ #ifndef MAME_EMU_IOPORT_H #define MAME_EMU_IOPORT_H +#include "ioprocs.h" + #include #include #include #include #include +#include #include @@ -1447,8 +1450,10 @@ private: attoseconds_t m_last_delta_nsec; // nanoseconds that passed since the previous callback // playback/record information - emu_file m_record_file; // recording file (nullptr if not recording) - emu_file m_playback_file; // playback file (nullptr if not recording) + emu_file m_record_file; // recording file (closed if not recording) + emu_file m_playback_file; // playback file (closed if not recording) + util::write_stream::ptr m_record_stream; // recording stream (nullptr if not recording) + util::read_stream::ptr m_playback_stream; // playback stream (nullptr if not recording) u64 m_playback_accumulated_speed; // accumulated speed during playback u32 m_playback_accumulated_frames; // accumulated frames during playback emu_file m_timecode_file; // timecode/frames playback file (nullptr if not recording) diff --git a/src/emu/machine.cpp b/src/emu/machine.cpp index 5568bb48e85..3721ba9bec8 100644 --- a/src/emu/machine.cpp +++ b/src/emu/machine.cpp @@ -313,8 +313,8 @@ int running_machine::run(bool quiet) if (options().log() && !quiet) { m_logfile = std::make_unique(OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS); - osd_file::error filerr = m_logfile->open("error.log"); - if (filerr != osd_file::error::NONE) + std::error_condition const filerr = m_logfile->open("error.log"); + if (filerr) throw emu_fatalerror("running_machine::run: unable to open error.log file"); using namespace std::placeholders; @@ -324,8 +324,8 @@ int running_machine::run(bool quiet) if (options().debug() && options().debuglog()) { m_debuglogfile = std::make_unique(OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS); - osd_file::error filerr = m_debuglogfile->open("debug.log"); - if (filerr != osd_file::error::NONE) + std::error_condition const filerr = m_debuglogfile->open("debug.log"); + if (filerr) throw emu_fatalerror("running_machine::run: unable to open debug.log file"); } @@ -931,7 +931,7 @@ void running_machine::handle_saveload() // open the file emu_file file(m_saveload_searchpath ? m_saveload_searchpath : "", openflags); auto const filerr = file.open(m_saveload_pending_file); - if (filerr == osd_file::error::NONE) + if (!filerr) { const char *const opnamed = (m_saveload_schedule == saveload_schedule::LOAD) ? "loaded" : "saved"; @@ -973,7 +973,7 @@ void running_machine::handle_saveload() if (saverr != STATERR_NONE && m_saveload_schedule == saveload_schedule::SAVE) file.remove_on_close(); } - else if (openflags == OPEN_FLAG_READ && filerr == osd_file::error::NOT_FOUND) + else if ((openflags == OPEN_FLAG_READ) && (std::errc::no_such_file_or_directory == filerr)) { // attempt to load a non-existent savestate, report empty slot popmessage("Error: No savestate file to load.", opname); @@ -1174,7 +1174,7 @@ void running_machine::nvram_load() for (device_nvram_interface &nvram : nvram_interface_enumerator(root_device())) { emu_file file(options().nvram_directory(), OPEN_FLAG_READ); - if (file.open(nvram_filename(nvram.device())) == osd_file::error::NONE) + if (!file.open(nvram_filename(nvram.device()))) { nvram.nvram_load(file); file.close(); @@ -1196,7 +1196,7 @@ void running_machine::nvram_save() if (nvram.nvram_can_save()) { emu_file file(options().nvram_directory(), OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS); - if (file.open(nvram_filename(nvram.device())) == osd_file::error::NONE) + if (!file.open(nvram_filename(nvram.device()))) { nvram.nvram_save(file); file.close(); diff --git a/src/emu/render.cpp b/src/emu/render.cpp index 1c176929aad..2c4541cb6b9 100644 --- a/src/emu/render.cpp +++ b/src/emu/render.cpp @@ -50,7 +50,8 @@ #include "ui/uimain.h" -#include "xmlfile.h" +#include "util/path.h" +#include "util/xmlfile.h" #include @@ -2186,7 +2187,7 @@ bool render_target::load_layout_file(const char *dirname, const char *filename) emu_file layoutfile(m_manager.machine().options().art_path(), OPEN_FLAG_READ); layoutfile.set_restrict_to_mediapath(1); bool result(false); - for (osd_file::error filerr = layoutfile.open(fname); osd_file::error::NONE == filerr; filerr = layoutfile.open_next()) + for (std::error_condition filerr = layoutfile.open(fname); !filerr; filerr = layoutfile.open_next()) { // read the file and parse as XML util::xml::file::ptr const rootnode(util::xml::file::read(layoutfile, &parseopt)); diff --git a/src/emu/rendfont.cpp b/src/emu/rendfont.cpp index c20a7979bbc..ae295e39e2d 100644 --- a/src/emu/rendfont.cpp +++ b/src/emu/rendfont.cpp @@ -594,8 +594,8 @@ render_font::render_font(render_manager &manager, const char *filename) // load the compiled in data instead emu_file ramfile(OPEN_FLAG_READ); - osd_file::error const filerr(ramfile.open_ram(font_uismall, sizeof(font_uismall))); - if (osd_file::error::NONE == filerr) + std::error_condition const filerr(ramfile.open_ram(font_uismall, sizeof(font_uismall))); + if (!filerr) load_cached(ramfile, 0, 0); render_font_command_glyph(); } @@ -908,14 +908,14 @@ float render_font::utf8string_width(float height, float aspect, std::string_view bool render_font::load_cached_bdf(const char *filename) { - osd_file::error filerr; + std::error_condition filerr; u32 chunk; u64 bytes; // first try to open the BDF itself emu_file file(m_manager.machine().options().font_path(), OPEN_FLAG_READ); filerr = file.open(filename); - if (filerr != osd_file::error::NONE) + if (filerr) return false; // determine the file size and allocate memory @@ -952,7 +952,7 @@ bool render_font::load_cached_bdf(const char *filename) { emu_file cachefile(m_manager.machine().options().font_path(), OPEN_FLAG_READ); filerr = cachefile.open(cachedname); - if (filerr == osd_file::error::NONE) + if (!filerr) { // if we have a cached version, load it bool const result = load_cached(cachefile, m_rawsize, hash); @@ -1456,8 +1456,8 @@ bool render_font::save_cached(const char *filename, u64 length, u32 hash) // attempt to open the file emu_file file(m_manager.machine().options().font_path(), OPEN_FLAG_WRITE | OPEN_FLAG_CREATE); - osd_file::error const filerr = file.open(filename); - if (osd_file::error::NONE != filerr) + std::error_condition const filerr = file.open(filename); + if (filerr) return false; // count glyphs @@ -1596,7 +1596,7 @@ void render_font::render_font_command_glyph() { // FIXME: this is copy/pasta from the BDC loading, and it shouldn't be injected into every font emu_file file(OPEN_FLAG_READ); - if (file.open_ram(font_uicmd14, sizeof(font_uicmd14)) == osd_file::error::NONE) + if (!file.open_ram(font_uicmd14, sizeof(font_uicmd14))) { // get the file size, read the header, and check that it looks good u64 const filesize(file.size()); diff --git a/src/emu/rendlay.cpp b/src/emu/rendlay.cpp index 13b2d6e16c1..c3f7a70a2e8 100644 --- a/src/emu/rendlay.cpp +++ b/src/emu/rendlay.cpp @@ -17,10 +17,11 @@ #include "rendutil.h" #include "video/rgbutil.h" -#include "nanosvg.h" -#include "unicode.h" -#include "vecstream.h" -#include "xmlfile.h" +#include "util/nanosvg.h" +#include "util/path.h" +#include "util/unicode.h" +#include "util/vecstream.h" +#include "util/xmlfile.h" #include #include @@ -1713,12 +1714,10 @@ private: std::string filename; if (!m_searchpath.empty()) filename = m_dirname; - if (!filename.empty() && !util::is_directory_separator(filename[filename.size() - 1])) - filename.append(PATH_SEPARATOR); - filename.append(m_imagefile); + util::path_append(filename, m_imagefile); LOGMASKED(LOG_IMAGE_LOAD, "Image component attempt to load image file '%s'\n", filename); - osd_file::error const imgerr = file.open(filename); - if (osd_file::error::NONE == imgerr) + std::error_condition const imgerr = file.open(filename); + if (!imgerr) { if (!load_bitmap(file)) { @@ -1729,7 +1728,8 @@ private: } else { - LOGMASKED(LOG_IMAGE_LOAD, "Image component unable to open image file '%s'\n", filename); + LOGMASKED(LOG_IMAGE_LOAD, "Image component unable to open image file '%s' (%s:%d %s)\n", + filename, imgerr.category().name(), imgerr.value(), imgerr.message()); } } else if (!m_data.empty()) @@ -1745,12 +1745,10 @@ private: std::string filename; if (!m_searchpath.empty()) filename = m_dirname; - if (!filename.empty() && !util::is_directory_separator(filename[filename.size() - 1])) - filename.append(PATH_SEPARATOR); - filename.append(m_alphafile); + util::path_append(filename, m_alphafile); LOGMASKED(LOG_IMAGE_LOAD, "Image component attempt to load alpha channel from file '%s'\n", filename); - osd_file::error const alferr = file.open(filename); - if (osd_file::error::NONE == alferr) + std::error_condition const alferr = file.open(filename); + if (!alferr) { // TODO: no way to detect corner case where we had alpha from the image but the alpha PNG makes it entirely opaque if (render_load_png(m_bitmap, file, true)) @@ -1759,7 +1757,8 @@ private: } else { - LOGMASKED(LOG_IMAGE_LOAD, "Image component unable to open alpha channel file '%s'\n", filename); + LOGMASKED(LOG_IMAGE_LOAD, "Image component unable to open alpha channel file '%s' (%s:%d %s)\n", + filename, alferr.category().name(), alferr.value(), alferr.message()); } } else if (m_svg) @@ -1841,8 +1840,8 @@ private: // make a file wrapper for the data and see if it looks like a bitmap util::core_file::ptr file; - osd_file::error const filerr(util::core_file::open_ram(m_data.c_str(), m_data.size(), OPEN_FLAG_READ, file)); - bool const bitmapdata((osd_file::error::NONE == filerr) && file && load_bitmap(*file)); + std::error_condition const filerr(util::core_file::open_ram(m_data.c_str(), m_data.size(), OPEN_FLAG_READ, file)); + bool const bitmapdata(!filerr && file && load_bitmap(*file)); file.reset(); // if it didn't look like a bitmap, see if it looks like it might be XML and hence SVG @@ -3398,12 +3397,10 @@ private: std::string filename; if (!m_searchpath.empty()) filename = m_dirname; - if (!filename.empty() && !util::is_directory_separator(filename[filename.size() - 1])) - filename.append(PATH_SEPARATOR); - filename.append(m_imagefile[number]); + util::path_append(filename, m_imagefile[number]); // load the basic bitmap - if (file.open(filename) == osd_file::error::NONE) + if (!file.open(filename)) render_load_png(m_bitmap[number], file); // if we can't load the bitmap just use text rendering diff --git a/src/emu/romload.cpp b/src/emu/romload.cpp index 36d7896e467..c4c3101bc89 100644 --- a/src/emu/romload.cpp +++ b/src/emu/romload.cpp @@ -101,15 +101,15 @@ std::vector make_software_searchpath(software_list_device &swlist, } -chd_error do_open_disk(const emu_options &options, std::initializer_list > > searchpath, const rom_entry *romp, chd_file &chd, std::function next_parent) +std::error_condition do_open_disk(const emu_options &options, std::initializer_list > > searchpath, const rom_entry *romp, chd_file &chd, std::function next_parent) { // hashes are fixed, but we might need to try multiple filenames std::set tried; const util::hash_collection hashes(romp->hashdata()); std::string filename, fullpath; const rom_entry *parent(nullptr); - chd_error result(CHDERR_FILE_NOT_FOUND); - while (romp && (CHDERR_NONE != result)) + std::error_condition result(std::errc::no_such_file_or_directory); + while (romp && result) { filename = romp->name() + ".chd"; if (tried.insert(filename).second) @@ -120,8 +120,8 @@ chd_error do_open_disk(const emu_options &options, std::initializer_listset_restrict_to_mediapath(1); - const osd_file::error filerr(imgfile->open(filename, OPEN_FLAG_READ)); - if (osd_file::error::NONE == filerr) + const std::error_condition filerr(imgfile->open(filename, OPEN_FLAG_READ)); + if (!filerr) break; else imgfile.reset(); @@ -132,12 +132,12 @@ chd_error do_open_disk(const emu_options &options, std::initializer_listfullpath(); imgfile.reset(); - result = chd.open(fullpath.c_str()); + result = chd.open(fullpath); } } // walk the parents looking for a CHD with the same hashes but a different name - if (CHDERR_NONE != result) + if (result) { while (romp) { @@ -345,11 +345,11 @@ chd_file *rom_load_manager::get_disk_handle(std::string_view region) file associated with the given region -------------------------------------------------*/ -int rom_load_manager::set_disk_handle(std::string_view region, const char *fullpath) +std::error_condition rom_load_manager::set_disk_handle(std::string_view region, const char *fullpath) { auto chd = std::make_unique(region); auto err = chd->orig_chd().open(fullpath); - if (err == CHDERR_NONE) + if (!err) m_chd_list.push_back(std::move(chd)); return err; } @@ -439,7 +439,7 @@ void rom_load_manager::fill_random(u8 *base, u32 length) for missing files -------------------------------------------------*/ -void rom_load_manager::handle_missing_file(const rom_entry *romp, const std::vector &tried_file_names, chd_error chderr) +void rom_load_manager::handle_missing_file(const rom_entry *romp, const std::vector &tried_file_names, std::error_condition chderr) { std::string tried; if (!tried_file_names.empty()) @@ -453,12 +453,12 @@ void rom_load_manager::handle_missing_file(const rom_entry *romp, const std::vec tried += ')'; } - const bool is_chd(chderr != CHDERR_NONE); + const bool is_chd(chderr); const std::string name(is_chd ? romp->name() + ".chd" : romp->name()); - const bool is_chd_error(is_chd && chderr != CHDERR_FILE_NOT_FOUND); + const bool is_chd_error(is_chd && chderr != std::errc::no_such_file_or_directory); if (is_chd_error) - m_errorstring.append(string_format("%s CHD ERROR: %s\n", name, chd_file::error_string(chderr))); + m_errorstring.append(string_format("%s CHD ERROR: %s\n", name, chderr.message())); if (ROM_ISOPTIONAL(romp)) { @@ -638,7 +638,7 @@ void rom_load_manager::region_post_process(memory_region *region, bool invert) std::unique_ptr rom_load_manager::open_rom_file(std::initializer_list > > searchpath, const rom_entry *romp, std::vector &tried_file_names, bool from_list) { - osd_file::error filerr = osd_file::error::NOT_FOUND; + std::error_condition filerr = std::errc::no_such_file_or_directory; u32 const romsize = rom_file_size(romp); tried_file_names.clear(); @@ -664,14 +664,14 @@ std::unique_ptr rom_load_manager::open_rom_file(std::initializer_list< m_romsloadedsize += romsize; // return the result - if (osd_file::error::NONE != filerr) + if (filerr) return nullptr; else return result; } -std::unique_ptr rom_load_manager::open_rom_file(const std::vector &paths, std::vector &tried, bool has_crc, u32 crc, std::string_view name, osd_file::error &filerr) +std::unique_ptr rom_load_manager::open_rom_file(const std::vector &paths, std::vector &tried, bool has_crc, u32 crc, std::string_view name, std::error_condition &filerr) { // record the set names we search tried.insert(tried.end(), paths.begin(), paths.end()); @@ -685,7 +685,7 @@ std::unique_ptr rom_load_manager::open_rom_file(const std::vectoropen(name); // don't return anything if unsuccessful - if (osd_file::error::NONE != filerr) + if (filerr) return nullptr; else return result; @@ -939,7 +939,7 @@ void rom_load_manager::process_rom_entries(std::initializer_listname() + ".dif"; - /* try to open the diff */ + // 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); - osd_file::error filerr = diff_file.open(fname); - if (filerr == osd_file::error::NONE) + std::error_condition filerr = diff_file.open(fname); + if (!filerr) { std::string fullpath(diff_file.fullpath()); diff_file.close(); LOG("Opening differencing image file: %s\n", fullpath.c_str()); - return diff_chd.open(fullpath.c_str(), true, &source); + return diff_chd.open(fullpath, true, &source); } - /* didn't work; try creating it instead */ + // didn't work; try creating it instead 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); - if (filerr == osd_file::error::NONE) + if (!filerr) { std::string fullpath(diff_file.fullpath()); diff_file.close(); - /* create the CHD */ + // create the CHD LOG("Creating differencing image file: %s\n", fullpath.c_str()); chd_codec_type compression[4] = { CHD_CODEC_NONE }; - chd_error err = diff_chd.create(fullpath.c_str(), source.logical_bytes(), source.hunk_bytes(), compression, source); - if (err != CHDERR_NONE) + std::error_condition err = diff_chd.create(fullpath, source.logical_bytes(), source.hunk_bytes(), compression, source); + if (err) return err; return diff_chd.clone_all_metadata(source); } - return CHDERR_FILE_NOT_FOUND; + return std::errc::no_such_file_or_directory; } @@ -1059,7 +1059,7 @@ void rom_load_manager::process_disk_entries(std::initializer_list(regiontag); - chd_error err; + std::error_condition err; /* make the filename of the source */ const std::string filename = romp->name() + ".chd"; @@ -1068,7 +1068,7 @@ void rom_load_manager::process_disk_entries(std::initializer_listorig_chd(), next_parent); - if (err != CHDERR_NONE) + if (err) { handle_missing_file(romp, std::vector(), err); chd = nullptr; @@ -1098,9 +1098,9 @@ void rom_load_manager::process_disk_entries(std::initializer_listorig_chd(), chd->diff_chd()); - if (err != CHDERR_NONE) + if (err) { - m_errorstring.append(string_format("%s DIFF CHD ERROR: %s\n", filename, chd_file::error_string(err))); + m_errorstring.append(string_format("%s DIFF CHD ERROR: %s\n", filename, err.message())); m_errors++; chd = nullptr; continue; @@ -1132,7 +1132,7 @@ std::vector rom_load_manager::get_software_searchpath(software_list device -------------------------------------------------*/ -chd_error rom_load_manager::open_disk_image(const emu_options &options, const device_t &device, const rom_entry *romp, chd_file &image_chd) +std::error_condition rom_load_manager::open_disk_image(const emu_options &options, const device_t &device, const rom_entry *romp, chd_file &image_chd) { const std::vector searchpath(device.searchpath()); @@ -1151,7 +1151,7 @@ chd_error rom_load_manager::open_disk_image(const emu_options &options, const de software item -------------------------------------------------*/ -chd_error rom_load_manager::open_disk_image(const emu_options &options, software_list_device &swlist, const software_info &swinfo, const rom_entry *romp, chd_file &image_chd) +std::error_condition rom_load_manager::open_disk_image(const emu_options &options, software_list_device &swlist, const software_info &swinfo, const rom_entry *romp, chd_file &image_chd) { std::vector parents; std::vector searchpath = make_software_searchpath(swlist, swinfo, parents); diff --git a/src/emu/romload.h b/src/emu/romload.h index 29caaf8e124..76fdb111cc6 100644 --- a/src/emu/romload.h +++ b/src/emu/romload.h @@ -18,6 +18,7 @@ #include #include #include +#include #include #include @@ -419,7 +420,7 @@ public: chd_file *get_disk_handle(std::string_view region); /* set a pointer to the CHD file associated with the given region */ - int set_disk_handle(std::string_view region, const char *fullpath); + std::error_condition set_disk_handle(std::string_view region, const char *fullpath); void load_software_part_region(device_t &device, software_list_device &swlist, std::string_view swname, const rom_entry *start_region); @@ -427,27 +428,27 @@ public: static std::vector get_software_searchpath(software_list_device &swlist, const software_info &swinfo); /* open a disk image, searching up the parent and loading by checksum */ - static chd_error open_disk_image(const emu_options &options, const device_t &device, const rom_entry *romp, chd_file &image_chd); - static chd_error open_disk_image(const emu_options &options, software_list_device &swlist, const software_info &swinfo, const rom_entry *romp, chd_file &image_chd); + static std::error_condition open_disk_image(const emu_options &options, const device_t &device, const rom_entry *romp, chd_file &image_chd); + static std::error_condition open_disk_image(const emu_options &options, software_list_device &swlist, const software_info &swinfo, const rom_entry *romp, chd_file &image_chd); private: void determine_bios_rom(device_t &device, const char *specbios); void count_roms(); void fill_random(u8 *base, u32 length); - void handle_missing_file(const rom_entry *romp, const std::vector &tried_file_names, chd_error chderr); + void handle_missing_file(const rom_entry *romp, const std::vector &tried_file_names, std::error_condition chderr); void dump_wrong_and_correct_checksums(const util::hash_collection &hashes, const util::hash_collection &acthashes); void verify_length_and_hash(emu_file *file, std::string_view name, u32 explength, const util::hash_collection &hashes); void display_loading_rom_message(const char *name, bool from_list); void display_rom_load_results(bool from_list); void region_post_process(memory_region *region, bool invert); std::unique_ptr open_rom_file(std::initializer_list > > searchpath, const rom_entry *romp, std::vector &tried_file_names, bool from_list); - std::unique_ptr open_rom_file(const std::vector &paths, std::vector &tried, bool has_crc, u32 crc, std::string_view name, osd_file::error &filerr); + std::unique_ptr open_rom_file(const std::vector &paths, std::vector &tried, bool has_crc, u32 crc, std::string_view name, std::error_condition &filerr); int rom_fread(emu_file *file, u8 *buffer, int length, const rom_entry *parent_region); int read_rom_data(emu_file *file, const rom_entry *parent_region, const rom_entry *romp); void fill_rom_data(const rom_entry *romp); void copy_rom_data(const rom_entry *romp); void process_rom_entries(std::initializer_list > > searchpath, u8 bios, const rom_entry *parent_region, const rom_entry *romp, bool from_list); - chd_error open_disk_diff(emu_options &options, const rom_entry *romp, chd_file &source, chd_file &diff_chd); + std::error_condition open_disk_diff(emu_options &options, const rom_entry *romp, chd_file &source, chd_file &diff_chd); void process_disk_entries(std::initializer_list > > searchpath, std::string_view regiontag, const rom_entry *romp, std::function next_parent); void normalize_flags_for_device(std::string_view rgntag, u8 &width, endianness_t &endian); void process_region_list(); diff --git a/src/emu/save.cpp b/src/emu/save.cpp index 96fb3429a1c..120fa883655 100644 --- a/src/emu/save.cpp +++ b/src/emu/save.cpp @@ -24,7 +24,10 @@ #include "emu.h" #include "emuopts.h" -#include "coreutil.h" + +#include "util/coreutil.h" +#include "util/ioprocs.h" +#include "util/ioprocsfilter.h" //************************************************************************** @@ -212,7 +215,6 @@ save_error save_manager::check_file(running_machine &machine, emu_file &file, co sig = machine.save().signature(); // seek to the beginning and read the header - file.compress(FCOMPRESS_NONE); file.seek(0, SEEK_SET); u8 header[HEADER_SIZE]; if (file.read(header, sizeof(header)) != sizeof(header)) @@ -257,20 +259,28 @@ void save_manager::dispatch_presave() save_error save_manager::write_file(emu_file &file) { - return do_write( + util::write_stream::ptr writer; + save_error err = do_write( [] (size_t total_size) { return true; }, - [&file] (const void *data, size_t size) { return file.write(data, size) == size; }, - [&file] () + [&writer] (const void *data, size_t size) { - file.compress(FCOMPRESS_NONE); - file.seek(0, SEEK_SET); - return true; + size_t written; + std::error_condition filerr = writer->write(data, size, written); + return !filerr && (size == written); }, - [&file] () + [&file, &writer] () { - file.compress(FCOMPRESS_MEDIUM); - return true; + if (file.seek(0, SEEK_SET)) + return false; + writer = util::core_file_read_write(file); + return bool(writer); + }, + [&file, &writer] () + { + writer = util::zlib_write(util::core_file_read_write(file), 6, 16384); + return bool(writer); }); + return (STATERR_NONE != err) ? err : writer->finalize() ? STATERR_WRITE_ERROR : STATERR_NONE; } @@ -280,19 +290,26 @@ save_error save_manager::write_file(emu_file &file) save_error save_manager::read_file(emu_file &file) { + util::read_stream::ptr reader; return do_read( [] (size_t total_size) { return true; }, - [&file] (void *data, size_t size) { return file.read(data, size) == size; }, - [&file] () + [&reader] (void *data, size_t size) { - file.compress(FCOMPRESS_NONE); - file.seek(0, SEEK_SET); - return true; + std::size_t read; + std::error_condition filerr = reader->read(data, size, read); + return !filerr && (read == size); }, - [&file] () + [&file, &reader] () { - file.compress(FCOMPRESS_MEDIUM); - return true; + if (file.seek(0, SEEK_SET)) + return false; + reader = util::core_file_read(file); + return bool(reader); + }, + [&file, &reader] () + { + reader = util::zlib_read(util::core_file_read(file), 16384); + return bool(reader); }); } diff --git a/src/emu/save.h b/src/emu/save.h index 32ba0526486..cfd674e738e 100644 --- a/src/emu/save.h +++ b/src/emu/save.h @@ -55,12 +55,12 @@ typedef named_delegate save_prepost_delegate; // saved; in general, this is intended only to be used for specific enum types // defined by your device #define ALLOW_SAVE_TYPE(TYPE) \ - template <> struct save_manager::is_atom { static constexpr bool value = true; }; + template <> struct save_manager::is_atom : public std::true_type { }; // use this as above, but also to declare that std::vector is safe as well #define ALLOW_SAVE_TYPE_AND_VECTOR(TYPE) \ ALLOW_SAVE_TYPE(TYPE) \ - template <> struct save_manager::is_vector_safe { static constexpr bool value = true; }; + template <> struct save_manager::is_vector_safe : public std::true_type { }; // use this for saving members of structures in arrays #define STRUCT_MEMBER(s, m) s, &save_manager::pointer_unwrap::underlying_type::m, #s "." #m @@ -99,8 +99,8 @@ class save_manager }; // set of templates to identify valid save types - template struct is_atom { static constexpr bool value = false; }; - template struct is_vector_safe { static constexpr bool value = false; }; + template struct is_atom : public std::false_type { }; + template struct is_vector_safe : public std::false_type { }; class state_entry { diff --git a/src/emu/screen.cpp b/src/emu/screen.cpp index 1a1c5dee8ad..0993473de49 100644 --- a/src/emu/screen.cpp +++ b/src/emu/screen.cpp @@ -1911,8 +1911,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); - osd_file::error filerr = file.open(util::string_format("%s" PATH_SEPARATOR "burnin-%s.png", machine().basename(), tag() + 1)); - if (filerr == osd_file::error::NONE) + std::error_condition const filerr = file.open(util::string_format("%s" PATH_SEPARATOR "burnin-%s.png", machine().basename(), tag() + 1)); + if (!filerr) { util::png_info pnginfo; @@ -1942,7 +1942,7 @@ void screen_device::load_effect_overlay(const char *filename) // load the file m_screen_overlay_bitmap.reset(); emu_file file(machine().options().art_path(), OPEN_FLAG_READ); - if (file.open(fullname) == osd_file::error::NONE) + if (!file.open(fullname)) { render_load_png(m_screen_overlay_bitmap, file); file.close(); diff --git a/src/emu/softlist_dev.cpp b/src/emu/softlist_dev.cpp index c48f7820c23..7d25dd17013 100644 --- a/src/emu/softlist_dev.cpp +++ b/src/emu/softlist_dev.cpp @@ -288,9 +288,9 @@ void software_list_device::parse() // attempt to open the file emu_file file(mconfig().options().hash_path(), OPEN_FLAG_READ); - const osd_file::error filerr = file.open(m_list_name + ".xml"); + const std::error_condition filerr = file.open(m_list_name + ".xml"); m_filename = file.filename(); - if (filerr == osd_file::error::NONE) + if (!filerr) { // parse if no error std::ostringstream errs; @@ -298,7 +298,7 @@ void software_list_device::parse() file.close(); m_errors = errs.str(); } - else if (filerr == osd_file::error::NOT_FOUND) + else if (std::errc::no_such_file_or_directory == filerr) { osd_printf_verbose("%s: Software list %s not found\n", tag(), m_filename); } diff --git a/src/emu/uiinput.h b/src/emu/uiinput.h index 29b18d06d30..3fc89d7a4ff 100644 --- a/src/emu/uiinput.h +++ b/src/emu/uiinput.h @@ -103,7 +103,7 @@ public: private: // constants - constexpr static unsigned EVENT_QUEUE_SIZE = 128; + static constexpr unsigned EVENT_QUEUE_SIZE = 128; // internal state running_machine & m_machine; // reference to our machine diff --git a/src/emu/video.cpp b/src/emu/video.cpp index b6dada1c0b5..56f877ec8fa 100644 --- a/src/emu/video.cpp +++ b/src/emu/video.cpp @@ -359,8 +359,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); - osd_file::error filerr = open_next(file, "png"); - if (filerr == osd_file::error::NONE) + std::error_condition const filerr = open_next(file, "png"); + if (!filerr) save_snapshot(&screen, file); } } @@ -368,8 +368,8 @@ void video_manager::save_active_screen_snapshots() { // otherwise, just write a single snapshot emu_file file(machine().options().snapshot_directory(), OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS); - osd_file::error filerr = open_next(file, "png"); - if (filerr == osd_file::error::NONE) + std::error_condition const filerr = open_next(file, "png"); + if (!filerr) save_snapshot(nullptr, file); } } @@ -431,12 +431,12 @@ void video_manager::begin_recording_screen(const std::string &filename, uint32_t OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS); // and open the actual file - osd_file::error filerr = filename.empty() + std::error_condition filerr = filename.empty() ? open_next(*movie_file, extension) : movie_file->open(filename); - if (filerr != osd_file::error::NONE) + if (filerr) { - osd_printf_error("Error creating movie, osd_file::error=%d\n", int(filerr)); + osd_printf_error("Error creating movie, %s:%d %s\n", filerr.category().name(), filerr.value(), filerr.message()); return; } @@ -1007,8 +1007,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); - osd_file::error filerr = file.open(machine().basename() + PATH_SEPARATOR "final.png"); - if (filerr == osd_file::error::NONE) + std::error_condition filerr = file.open(machine().basename() + PATH_SEPARATOR "final.png"); + if (!filerr) save_snapshot(nullptr, file); //printf("Scheduled exit at %f\n", emutime.as_double()); @@ -1096,7 +1096,7 @@ void video_manager::pixels(u32 *buffer) // scheme //------------------------------------------------- -osd_file::error video_manager::open_next(emu_file &file, const char *extension, uint32_t added_index) +std::error_condition video_manager::open_next(emu_file &file, const char *extension, uint32_t added_index) { u32 origflags = file.openflags(); @@ -1205,11 +1205,9 @@ osd_file::error video_manager::open_next(emu_file &file, const char *extension, strreplace(fname, "%i", string_format("%04d", seq)); // try to open the file; stop when we fail - osd_file::error filerr = file.open(fname); - if (filerr == osd_file::error::NOT_FOUND) - { + std::error_condition const filerr = file.open(fname); + if (std::errc::no_such_file_or_directory == filerr) break; - } } } diff --git a/src/emu/video.h b/src/emu/video.h index bd58db9ca1d..3544bf19823 100644 --- a/src/emu/video.h +++ b/src/emu/video.h @@ -19,6 +19,8 @@ #include "recording.h" +#include + //************************************************************************** // CONSTANTS @@ -61,7 +63,7 @@ public: // misc void toggle_record_movie(movie_recording::format format); - osd_file::error open_next(emu_file &file, const char *extension, uint32_t index = 0); + std::error_condition open_next(emu_file &file, const char *extension, uint32_t index = 0); void compute_snapshot_size(s32 &width, s32 &height); void pixels(u32 *buffer); diff --git a/src/frontend/mame/audit.cpp b/src/frontend/mame/audit.cpp index 42ddcdad438..0a37c4a3fff 100644 --- a/src/frontend/mame/audit.cpp +++ b/src/frontend/mame/audit.cpp @@ -425,11 +425,11 @@ media_auditor::summary media_auditor::audit_samples() while (path.next(curpath, samplename)) { // attempt to access the file (.flac) or (.wav) - osd_file::error filerr = file.open(curpath + ".flac"); - if (filerr != osd_file::error::NONE) + std::error_condition filerr = file.open(curpath + ".flac"); + if (filerr) filerr = file.open(curpath + ".wav"); - if (filerr == osd_file::error::NONE) + if (!filerr) { record.set_status(audit_status::GOOD, audit_substatus::GOOD); found++; @@ -589,14 +589,14 @@ media_auditor::audit_record &media_auditor::audit_one_rom(const std::vector(args)..., rom, source); + const std::error_condition err = rom_load_manager::open_disk_image(m_enumerator.options(), std::forward(args)..., rom, source); // if we succeeded, get the hashes - if (err == CHDERR_NONE) + if (!err) { util::hash_collection hashes; @@ -633,7 +633,7 @@ media_auditor::audit_record &media_auditor::audit_one_disk(const rom_entry *rom, } // compute the final status - compute_status(record, rom, err == CHDERR_NONE); + compute_status(record, rom, !err); return record; } diff --git a/src/frontend/mame/cheat.cpp b/src/frontend/mame/cheat.cpp index bc266cc6aae..f4a567db28f 100644 --- a/src/frontend/mame/cheat.cpp +++ b/src/frontend/mame/cheat.cpp @@ -1191,10 +1191,10 @@ bool cheat_manager::save_all(std::string const &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); - osd_file::error const filerr(cheatfile.open(filename + ".xml")); + std::error_condition const filerr(cheatfile.open(filename + ".xml")); // if that failed, return nothing - if (filerr != osd_file::error::NONE) + if (filerr) return false; // wrap the rest of catch errors @@ -1391,7 +1391,7 @@ void cheat_manager::load_cheats(std::string const &filename) try { // loop over all instrances of the files found in our search paths - for (osd_file::error filerr = cheatfile.open(filename + ".xml"); filerr == osd_file::error::NONE; filerr = cheatfile.open_next()) + for (std::error_condition filerr = cheatfile.open(filename + ".xml"); !filerr; filerr = cheatfile.open_next()) { osd_printf_verbose("Loading cheats file from %s\n", cheatfile.fullpath()); diff --git a/src/frontend/mame/clifront.cpp b/src/frontend/mame/clifront.cpp index 38b61b9755f..eb77ead8e5c 100644 --- a/src/frontend/mame/clifront.cpp +++ b/src/frontend/mame/clifront.cpp @@ -1681,7 +1681,7 @@ void cli_frontend::execute_commands(std::string_view exename) { // attempt to open the output file emu_file file(OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS); - if (file.open(std::string(emulator_info::get_configname()) + ".ini") != osd_file::error::NONE) + if (file.open(std::string(emulator_info::get_configname()) + ".ini")) throw emu_fatalerror("Unable to create file %s.ini\n",emulator_info::get_configname()); // generate the updated INI @@ -1689,7 +1689,7 @@ void cli_frontend::execute_commands(std::string_view 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") != osd_file::error::NONE) + if (file_ui.open("ui.ini")) throw emu_fatalerror("Unable to create file ui.ini\n"); // generate the updated INI @@ -1704,7 +1704,7 @@ void cli_frontend::execute_commands(std::string_view exename) plugin_opts.scan_directory(pluginpath, true); } emu_file file_plugin(OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS); - if (file_plugin.open("plugin.ini") != osd_file::error::NONE) + if (file_plugin.open("plugin.ini")) throw emu_fatalerror("Unable to create file plugin.ini\n"); // generate the updated INI diff --git a/src/frontend/mame/language.cpp b/src/frontend/mame/language.cpp index 1cd0d1be65e..eae75b3fd6f 100644 --- a/src/frontend/mame/language.cpp +++ b/src/frontend/mame/language.cpp @@ -70,7 +70,7 @@ void load_translation(emu_options &m_options) strreplace(name, "(", ""); strreplace(name, ")", ""); emu_file file(m_options.language_path(), OPEN_FLAG_READ); - if (file.open(name + PATH_SEPARATOR "strings.mo") != osd_file::error::NONE) + if (file.open(name + PATH_SEPARATOR "strings.mo")) { osd_printf_error("Error opening translation file %s\n", name); return; diff --git a/src/frontend/mame/luaengine.cpp b/src/frontend/mame/luaengine.cpp index 9dfc9aeee0b..54fdd78b01c 100644 --- a/src/frontend/mame/luaengine.cpp +++ b/src/frontend/mame/luaengine.cpp @@ -322,48 +322,12 @@ public: } // namespace sol -int sol_lua_push(sol::types, lua_State *L, osd_file::error &&value) +int sol_lua_push(sol::types, lua_State *L, std::error_condition &&value) { - const char *strerror; - switch(value) - { - case osd_file::error::NONE: - return sol::stack::push(L, sol::lua_nil); - case osd_file::error::FAILURE: - strerror = "failure"; - break; - case osd_file::error::OUT_OF_MEMORY: - strerror = "out_of_memory"; - break; - case osd_file::error::NOT_FOUND: - strerror = "not_found"; - break; - case osd_file::error::ACCESS_DENIED: - strerror = "access_denied"; - break; - case osd_file::error::ALREADY_OPEN: - strerror = "already_open"; - break; - case osd_file::error::TOO_MANY_FILES: - strerror = "too_many_files"; - break; - case osd_file::error::INVALID_DATA: - strerror = "invalid_data"; - break; - case osd_file::error::INVALID_ACCESS: - strerror = "invalid_access"; - break; - default: - strerror = "unknown_error"; - break; - } - return sol::stack::push(L, strerror); -} - -template -bool sol_lua_check(sol::types, lua_State *L, int index, Handler &&handler, sol::stack::record &tracking) -{ - return sol::stack::check(L, index, std::forward(handler)); + if (!value) + return sol::stack::push(L, sol::lua_nil); + else + return sol::stack::push(L, value.message()); } @@ -884,7 +848,7 @@ void lua_engine::initialize() })); file_type.set("read", [](emu_file &file, sol::buffer *buff) { buff->set_len(file.read(buff->get_ptr(), buff->get_len())); return buff; }); file_type.set("write", [](emu_file &file, const std::string &data) { return file.write(data.data(), data.size()); }); - file_type.set("open", static_cast(&emu_file::open)); + file_type.set("open", static_cast(&emu_file::open)); file_type.set("open_next", &emu_file::open_next); file_type.set("seek", sol::overload( [](emu_file &file) { return file.tell(); }, @@ -1534,12 +1498,12 @@ void lua_engine::initialize() // open the file emu_file file(is_absolute_path ? "" : machine().options().snapshot_directory(), OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS); - osd_file::error filerr; + std::error_condition filerr; if (!snapstr.empty()) filerr = file.open(snapstr); else filerr = machine().video().open_next(file, "png"); - if (filerr != osd_file::error::NONE) + if (filerr) return sol::make_object(sol(), filerr); // and save the snapshot diff --git a/src/frontend/mame/luaengine.ipp b/src/frontend/mame/luaengine.ipp index d532b8be1b4..f995b0a4a7b 100644 --- a/src/frontend/mame/luaengine.ipp +++ b/src/frontend/mame/luaengine.ipp @@ -16,6 +16,8 @@ #include +#include + template @@ -258,10 +260,8 @@ public: } // namespace sol -// osd_file::error customisation -int sol_lua_push(sol::types, lua_State *L, osd_file::error &&value); -template -bool sol_lua_check(sol::types, lua_State *L, int index, Handler &&handler, sol::stack::record &tracking); +// automatically convert std::error_condition to string +int sol_lua_push(sol::types, lua_State &L, std::error_condition &&value); // enums to automatically convert to strings int sol_lua_push(sol::types, lua_State *L, map_handler_type &&value); diff --git a/src/frontend/mame/mame.cpp b/src/frontend/mame/mame.cpp index 1158666ff92..c7bc0879909 100644 --- a/src/frontend/mame/mame.cpp +++ b/src/frontend/mame/mame.cpp @@ -152,7 +152,7 @@ void mame_machine_manager::start_luaengine() // parse the file // attempt to open the output file emu_file file(options().ini_path(), OPEN_FLAG_READ); - if (file.open("plugin.ini") == osd_file::error::NONE) + if (!file.open("plugin.ini")) { try { @@ -198,8 +198,8 @@ void mame_machine_manager::start_luaengine() { emu_file file(options().plugins_path(), OPEN_FLAG_READ); - osd_file::error filerr = file.open("boot.lua"); - if (filerr == osd_file::error::NONE) + std::error_condition const filerr = file.open("boot.lua"); + if (!filerr) { std::string exppath; osd_subst_env(exppath, std::string(file.fullpath())); diff --git a/src/frontend/mame/mameopts.cpp b/src/frontend/mame/mameopts.cpp index 0e6c28da23d..a1d370ddb74 100644 --- a/src/frontend/mame/mameopts.cpp +++ b/src/frontend/mame/mameopts.cpp @@ -130,8 +130,8 @@ void mame_options::parse_one_ini(emu_options &options, const char *basename, int // open the file; if we fail, that's ok emu_file file(options.ini_path(), OPEN_FLAG_READ); osd_printf_verbose("Attempting load of %s.ini\n", basename); - osd_file::error filerr = file.open(std::string(basename) + ".ini"); - if (filerr != osd_file::error::NONE) + std::error_condition const filerr = file.open(std::string(basename) + ".ini"); + if (filerr) return; // parse the file diff --git a/src/frontend/mame/media_ident.cpp b/src/frontend/mame/media_ident.cpp index 690996145b2..08a7381ad3e 100644 --- a/src/frontend/mame/media_ident.cpp +++ b/src/frontend/mame/media_ident.cpp @@ -134,13 +134,13 @@ void media_identifier::collect_files(std::vector &info, char const *p { // first attempt to examine it as a valid zip/7z file util::archive_file::ptr archive; - util::archive_file::error err; + std::error_condition err; if (core_filename_ends_with(path, ".7z")) err = util::archive_file::open_7z(path, archive); else err = util::archive_file::open_zip(path, archive); - if ((util::archive_file::error::NONE == err) && archive) + if (!err && archive) { std::vector data; @@ -158,10 +158,10 @@ void media_identifier::collect_files(std::vector &info, char const *p { data.resize(std::size_t(length)); err = archive->decompress(&data[0], std::uint32_t(length)); - if (util::archive_file::error::NONE == err) + if (!err) digest_data(info, curfile.c_str(), &data[0], length); else - osd_printf_error("%s: error decompressing file\n", curfile); + osd_printf_error("%s: error decompressing file (%s:%d %s)\n", curfile, err.category().name(), err.value(), err.message()); } catch (...) { @@ -205,9 +205,9 @@ void media_identifier::digest_file(std::vector &info, char const *pat { // attempt to open as a CHD; fail if not chd_file chd; - chd_error const err = chd.open(path); + std::error_condition const err = chd.open(path); m_total++; - if (err != CHDERR_NONE) + if (err) { osd_printf_info("%-20s NOT A CHD\n", core_filename_extract_base(path)); m_nonroms++; @@ -233,7 +233,7 @@ void media_identifier::digest_file(std::vector &info, char const *pat // load the file and process if it opens and has a valid length uint32_t length; void *data; - if (osd_file::error::NONE == util::core_file::load(path, &data, length)) + if (!util::core_file::load(path, &data, length)) { jed_data jed; if (JEDERR_NONE == jed_parse(data, length, &jed)) @@ -260,7 +260,7 @@ void media_identifier::digest_file(std::vector &info, char const *pat // load the file and process if it opens and has a valid length util::core_file::ptr file; - if ((osd_file::error::NONE == util::core_file::open(path, OPEN_FLAG_READ, file)) && file) + if (!util::core_file::open(path, OPEN_FLAG_READ, file) && file) { util::hash_collection hashes; hashes.begin(util::hash_collection::HASH_TYPES_CRC_SHA1); diff --git a/src/frontend/mame/ui/auditmenu.cpp b/src/frontend/mame/ui/auditmenu.cpp index 9cadb5b5d97..66c1aab0597 100644 --- a/src/frontend/mame/ui/auditmenu.cpp +++ b/src/frontend/mame/ui/auditmenu.cpp @@ -229,7 +229,7 @@ void menu_audit::save_available_machines() { // attempt to open the output file emu_file file(ui().options().ui_path(), OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS); - if (file.open(std::string(emulator_info::get_configname()) + "_avail.ini") == osd_file::error::NONE) + if (!file.open(std::string(emulator_info::get_configname()) + "_avail.ini")) { // generate header file.printf("#\n%s%s\n#\n\n", UI_VERSION_TAG, emulator_info::get_bare_build_version()); diff --git a/src/frontend/mame/ui/filesel.cpp b/src/frontend/mame/ui/filesel.cpp index b722afab60d..bc5c5abbd12 100644 --- a/src/frontend/mame/ui/filesel.cpp +++ b/src/frontend/mame/ui/filesel.cpp @@ -316,8 +316,8 @@ void menu_file_selector::select_item(const file_selector_entry &entry) { // drive/directory - first check the path util::zippath_directory::ptr dir; - osd_file::error const err = util::zippath_directory::open(entry.fullpath, dir); - if (err != osd_file::error::NONE) + std::error_condition const err = util::zippath_directory::open(entry.fullpath, dir); + if (err) { // this path is problematic; present the user with an error and bail ui().popup_time(1, _("Error accessing %s"), entry.fullpath); @@ -399,7 +399,7 @@ void menu_file_selector::populate(float &customtop, float &custombottom) // open the directory util::zippath_directory::ptr directory; - osd_file::error const err = util::zippath_directory::open(m_current_directory, directory); + std::error_condition const err = util::zippath_directory::open(m_current_directory, directory); // add the "[empty slot]" entry if available if (m_has_empty) @@ -421,9 +421,11 @@ void menu_file_selector::populate(float &customtop, float &custombottom) std::size_t const first = m_entrylist.size() + 1; // build the menu for each item - if (osd_file::error::NONE != err) + if (err) { - osd_printf_verbose("menu_file_selector::populate: error opening directory '%s' (%d)\n", m_current_directory, int(err)); + osd_printf_verbose( + "menu_file_selector::populate: error opening directory '%s' (%s:%d %s)\n", + m_current_directory, err.category().name(), err.value(), err.message()); } else { diff --git a/src/frontend/mame/ui/floppycntrl.cpp b/src/frontend/mame/ui/floppycntrl.cpp index 0cfc8ac2333..2f1cc9e0192 100644 --- a/src/frontend/mame/ui/floppycntrl.cpp +++ b/src/frontend/mame/ui/floppycntrl.cpp @@ -79,12 +79,11 @@ void menu_control_floppy_image::hook_load(const std::string &filename) bool can_in_place = input_format->supports_save(); if(can_in_place) { - 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 = util::zippath_fopen(filename, OPEN_FLAG_READ | OPEN_FLAG_WRITE, tmp_file, tmp_path); - if(filerr == osd_file::error::NONE) + std::error_condition const filerr = util::zippath_fopen(filename, OPEN_FLAG_READ | OPEN_FLAG_WRITE, tmp_file, tmp_path); + if(!filerr) tmp_file.reset(); else can_in_place = false; diff --git a/src/frontend/mame/ui/imgcntrl.cpp b/src/frontend/mame/ui/imgcntrl.cpp index 33a71b7354a..43f40603479 100644 --- a/src/frontend/mame/ui/imgcntrl.cpp +++ b/src/frontend/mame/ui/imgcntrl.cpp @@ -85,7 +85,7 @@ menu_control_device_image::menu_control_device_image(mame_ui_manager &mui, rende // check to see if the path exists; if not then set to current directory util::zippath_directory::ptr dir; - if (util::zippath_directory::open(m_current_directory, dir) != osd_file::error::NONE) + if (util::zippath_directory::open(m_current_directory, dir)) osd_get_full_path(m_current_directory, "."); } } diff --git a/src/frontend/mame/ui/inifile.cpp b/src/frontend/mame/ui/inifile.cpp index f1e0346769a..000ea922a4a 100644 --- a/src/frontend/mame/ui/inifile.cpp +++ b/src/frontend/mame/ui/inifile.cpp @@ -45,7 +45,7 @@ inifile_manager::inifile_manager(ui_options &options) if (core_filename_ends_with(name, ".ini")) { emu_file file(m_options.categoryini_path(), OPEN_FLAG_READ); - if (file.open(name) == osd_file::error::NONE) + if (!file.open(name)) { init_category(std::move(name), file); file.close(); @@ -63,7 +63,7 @@ void inifile_manager::load_ini_category(size_t file, size_t category, std::unord { std::string const &filename(m_ini_index[file].first); emu_file fp(m_options.categoryini_path(), OPEN_FLAG_READ); - if (fp.open(filename) != osd_file::error::NONE) + if (fp.open(filename)) { osd_printf_error("Failed to open category file %s for reading\n", filename); return; @@ -216,7 +216,7 @@ favorite_manager::favorite_manager(ui_options &options) , m_need_sort(true) { emu_file file(m_options.ui_path(), OPEN_FLAG_READ); - if (file.open(FAVORITE_FILENAME) == osd_file::error::NONE) + if (!file.open(FAVORITE_FILENAME)) { char readbuf[1024]; file.gets(readbuf, 1024); @@ -537,7 +537,7 @@ void favorite_manager::save_favorites() { // attempt to open the output file emu_file file(m_options.ui_path(), OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS); - if (file.open(FAVORITE_FILENAME) == osd_file::error::NONE) + if (!file.open(FAVORITE_FILENAME)) { if (m_favorites.empty()) { diff --git a/src/frontend/mame/ui/menu.cpp b/src/frontend/mame/ui/menu.cpp index 8eb1eab47c9..923a0fae6df 100644 --- a/src/frontend/mame/ui/menu.cpp +++ b/src/frontend/mame/ui/menu.cpp @@ -92,13 +92,13 @@ menu::global_state::global_state(running_machine &machine, ui_options const &opt { m_bgrnd_bitmap = std::make_unique(0, 0); emu_file backgroundfile(".", OPEN_FLAG_READ); - if (backgroundfile.open("background.jpg") == osd_file::error::NONE) + if (!backgroundfile.open("background.jpg")) { render_load_jpeg(*m_bgrnd_bitmap, backgroundfile); backgroundfile.close(); } - if (!m_bgrnd_bitmap->valid() && (backgroundfile.open("background.png") == osd_file::error::NONE)) + if (!m_bgrnd_bitmap->valid() && !backgroundfile.open("background.png")) { render_load_png(*m_bgrnd_bitmap, backgroundfile); backgroundfile.close(); diff --git a/src/frontend/mame/ui/miscmenu.cpp b/src/frontend/mame/ui/miscmenu.cpp index bf1754481dc..da7989e6e3b 100644 --- a/src/frontend/mame/ui/miscmenu.cpp +++ b/src/frontend/mame/ui/miscmenu.cpp @@ -599,11 +599,11 @@ void menu_export::handle() { std::string filename("exported"); emu_file infile(ui().options().ui_path(), OPEN_FLAG_READ); - if (infile.open(filename + ".xml") == osd_file::error::NONE) + if (!infile.open(filename + ".xml")) for (int seq = 0; ; ++seq) { const std::string seqtext = string_format("%s_%04d", filename, seq); - if (infile.open(seqtext + ".xml") != osd_file::error::NONE) + if (infile.open(seqtext + ".xml")) { filename = seqtext; break; @@ -612,7 +612,7 @@ void menu_export::handle() // attempt to open the output file emu_file file(ui().options().ui_path(), OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS); - if (file.open(filename + ".xml") == osd_file::error::NONE) + if (!file.open(filename + ".xml")) { const std::string fullpath(file.fullpath()); file.close(); @@ -644,11 +644,11 @@ void menu_export::handle() { std::string filename("exported"); emu_file infile(ui().options().ui_path(), OPEN_FLAG_READ); - if (infile.open(filename + ".txt") == osd_file::error::NONE) + if (!infile.open(filename + ".txt")) for (int seq = 0; ; ++seq) { const std::string seqtext = string_format("%s_%04d", filename, seq); - if (infile.open(seqtext + ".txt") != osd_file::error::NONE) + if (infile.open(seqtext + ".txt")) { filename = seqtext; break; @@ -657,7 +657,7 @@ void menu_export::handle() // attempt to open the output file emu_file file(ui().options().ui_path(), OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS); - if (file.open(filename + ".txt") == osd_file::error::NONE) + if (!file.open(filename + ".txt")) { // print the header std::ostringstream buffer; @@ -754,8 +754,8 @@ void menu_machine_configure::handle() { const std::string filename(m_drv.name); emu_file file(machine().options().ini_path(), OPEN_FLAG_WRITE | OPEN_FLAG_CREATE); - osd_file::error filerr = file.open(filename + ".ini"); - if (filerr == osd_file::error::NONE) + std::error_condition const filerr = file.open(filename + ".ini"); + if (!filerr) { std::string inistring = m_opts.output_ini(); file.puts(inistring); @@ -891,7 +891,7 @@ menu_plugins_configure::menu_plugins_configure(mame_ui_manager &mui, render_cont menu_plugins_configure::~menu_plugins_configure() { emu_file file_plugin(machine().options().ini_path(), OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS); - if (file_plugin.open("plugin.ini") != osd_file::error::NONE) + if (file_plugin.open("plugin.ini")) // Can't throw in a destructor, so let's ignore silently for // now. We shouldn't write files in a destructor in any case. // diff --git a/src/frontend/mame/ui/optsmenu.cpp b/src/frontend/mame/ui/optsmenu.cpp index 0ceeca25ce2..922bbb5b6fa 100644 --- a/src/frontend/mame/ui/optsmenu.cpp +++ b/src/frontend/mame/ui/optsmenu.cpp @@ -265,7 +265,7 @@ void menu_game_options::handle_item_event(event const &menu_event) if (machine_filter::CUSTOM == filter.get_type()) { emu_file file(ui().options().ui_path(), OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS); - if (file.open(util::string_format("custom_%s_filter.ini", emulator_info::get_configname())) == osd_file::error::NONE) + if (!file.open(util::string_format("custom_%s_filter.ini", emulator_info::get_configname()))) { filter.save_ini(file, 0); file.close(); diff --git a/src/frontend/mame/ui/selgame.cpp b/src/frontend/mame/ui/selgame.cpp index 338f98c42d0..ece205a8ef4 100644 --- a/src/frontend/mame/ui/selgame.cpp +++ b/src/frontend/mame/ui/selgame.cpp @@ -266,7 +266,7 @@ menu_select_game::menu_select_game(mame_ui_manager &mui, render_container &conta } emu_file file(ui().options().ui_path(), OPEN_FLAG_READ); - if (file.open_ram(fake_ini.c_str(), fake_ini.size()) == osd_file::error::NONE) + if (!file.open_ram(fake_ini.c_str(), fake_ini.size())) { m_persistent_data.filter_data().load_ini(file); file.close(); @@ -1259,12 +1259,12 @@ render_texture *menu_select_game::get_icon_texture(int linenum, void *selectedre bitmap_argb32 tmp; emu_file snapfile(std::string(m_icon_paths), OPEN_FLAG_READ); - if (snapfile.open(std::string(driver->name) + ".ico") == osd_file::error::NONE) + if (!snapfile.open(std::string(driver->name) + ".ico")) { render_load_ico_highest_detail(snapfile, tmp); snapfile.close(); } - if (!tmp.valid() && cloneof && (snapfile.open(std::string(driver->parent) + ".ico") == osd_file::error::NONE)) + if (!tmp.valid() && cloneof && !snapfile.open(std::string(driver->parent) + ".ico")) { render_load_ico_highest_detail(snapfile, tmp); snapfile.close(); @@ -1309,7 +1309,7 @@ bool menu_select_game::load_available_machines() { // try to load available drivers from file emu_file file(ui().options().ui_path(), OPEN_FLAG_READ); - if (file.open(std::string(emulator_info::get_configname()) + "_avail.ini") != osd_file::error::NONE) + if (file.open(std::string(emulator_info::get_configname()) + "_avail.ini")) return false; char rbuf[MAX_CHAR_INFO]; @@ -1361,7 +1361,7 @@ bool menu_select_game::load_available_machines() void menu_select_game::load_custom_filters() { emu_file file(ui().options().ui_path(), OPEN_FLAG_READ); - if (file.open(util::string_format("custom_%s_filter.ini", emulator_info::get_configname())) == osd_file::error::NONE) + if (!file.open(util::string_format("custom_%s_filter.ini", emulator_info::get_configname()))) { machine_filter::ptr flt(machine_filter::create(file, m_persistent_data.filter_data())); if (flt) @@ -1456,7 +1456,7 @@ void menu_select_game::filter_selected() if (machine_filter::CUSTOM == new_type) { emu_file file(ui().options().ui_path(), OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS); - if (file.open(util::string_format("custom_%s_filter.ini", emulator_info::get_configname())) == osd_file::error::NONE) + if (!file.open(util::string_format("custom_%s_filter.ini", emulator_info::get_configname()))) { filter.save_ini(file, 0); file.close(); diff --git a/src/frontend/mame/ui/selmenu.cpp b/src/frontend/mame/ui/selmenu.cpp index fb3f7087e27..15c7e1c3364 100644 --- a/src/frontend/mame/ui/selmenu.cpp +++ b/src/frontend/mame/ui/selmenu.cpp @@ -36,6 +36,8 @@ #include "uiinput.h" #include "luaengine.h" +#include "util/path.h" + #include #include #include @@ -99,19 +101,19 @@ char const *const hover_msg[] = { void load_image(bitmap_argb32 &bitmap, emu_file &file, std::string const &base) { - if (file.open(base + ".png") == osd_file::error::NONE) + if (!file.open(base + ".png")) { render_load_png(bitmap, file); file.close(); } - if (!bitmap.valid() && (file.open(base + ".jpg") == osd_file::error::NONE)) + if (!bitmap.valid() && !file.open(base + ".jpg")) { render_load_jpeg(bitmap, file); file.close(); } - if (!bitmap.valid() && (file.open(base + ".bmp") == osd_file::error::NONE)) + if (!bitmap.valid() && !file.open(base + ".bmp")) { render_load_msdib(bitmap, file); file.close(); @@ -123,7 +125,7 @@ void load_driver_image(bitmap_argb32 &bitmap, emu_file &file, game_driver const { // try to load snapshot first from saved "0000.png" file std::string fullname = driver.name; - load_image(bitmap, file, fullname + PATH_SEPARATOR + "0000"); + load_image(bitmap, file, util::path_concat(fullname, "0000")); // if fail, attempt to load from standard file if (!bitmap.valid()) @@ -144,7 +146,7 @@ void load_driver_image(bitmap_argb32 &bitmap, emu_file &file, game_driver const if (isclone) { fullname = driver.parent; - load_image(bitmap, file, fullname + PATH_SEPARATOR + "0000"); + load_image(bitmap, file, util::path_concat(fullname, "0000")); if (!bitmap.valid()) load_image(bitmap, file, fullname); @@ -621,7 +623,7 @@ void menu_select_launch::launch_system(mame_ui_manager &mui, game_driver const & else moptions.set_value(OPTION_SOFTWARENAME, util::string_format("%s:%s", swinfo->listname, swinfo->shortname), OPTION_PRIORITY_CMDLINE); - moptions.set_value(OPTION_SNAPNAME, util::string_format("%s%s%s", swinfo->listname, PATH_SEPARATOR, swinfo->shortname), OPTION_PRIORITY_CMDLINE); + moptions.set_value(OPTION_SNAPNAME, util::path_concat(swinfo->listname, swinfo->shortname), OPTION_PRIORITY_CMDLINE); } reselect_last::set_software(driver, *swinfo); } @@ -1087,11 +1089,7 @@ void menu_select_launch::check_for_icons(char const *listname) { // if we're doing a software list, append it to the configured path if (listname) - { - if (!current.empty() && !util::is_directory_separator(current.back())) - current.append(PATH_SEPARATOR); - current.append(listname); - } + util::path_append(current, listname); osd_printf_verbose("Checking for icons in directory %s\n", current); // open and walk the directory @@ -1136,11 +1134,7 @@ std::string menu_select_launch::make_icon_paths(char const *listname) const { // if we're doing a software list, append it to the configured path if (listname) - { - if (!current.empty() && !util::is_directory_separator(current.back())) - current.append(PATH_SEPARATOR); - current.append(listname); - } + util::path_append(current, listname); // append the configured path if (!result.empty()) @@ -2286,11 +2280,11 @@ void menu_select_launch::arts_render(float origx1, float origy1, float origx2, f else { // First attempt from name list - load_image(tmp_bitmap, snapfile, software->listname + PATH_SEPARATOR + software->shortname); + load_image(tmp_bitmap, snapfile, util::path_concat(software->listname, software->shortname)); // Second attempt from driver name + part name if (!tmp_bitmap.valid()) - load_image(tmp_bitmap, snapfile, software->driver->name + software->part + PATH_SEPARATOR + software->shortname); + load_image(tmp_bitmap, snapfile, util::path_concat(software->driver->name + software->part, software->shortname)); } m_cache->set_snapx_software(software); diff --git a/src/frontend/mame/ui/selsoft.cpp b/src/frontend/mame/ui/selsoft.cpp index 2ac32cce987..95c02a9d853 100644 --- a/src/frontend/mame/ui/selsoft.cpp +++ b/src/frontend/mame/ui/selsoft.cpp @@ -517,7 +517,7 @@ void menu_select_software::load_sw_custom_filters() { // attempt to open the output file emu_file file(ui().options().ui_path(), OPEN_FLAG_READ); - if (file.open(util::string_format("custom_%s_filter.ini", m_driver.name)) == osd_file::error::NONE) + if (!file.open(util::string_format("custom_%s_filter.ini", m_driver.name))) { software_filter::ptr flt(software_filter::create(file, m_filter_data)); if (flt) @@ -593,12 +593,12 @@ render_texture *menu_select_software::get_icon_texture(int linenum, void *select bitmap_argb32 tmp; emu_file snapfile(std::string(paths->second), OPEN_FLAG_READ); - if (snapfile.open(std::string(swinfo->shortname) + ".ico") == osd_file::error::NONE) + if (!snapfile.open(std::string(swinfo->shortname) + ".ico")) { render_load_ico_highest_detail(snapfile, tmp); snapfile.close(); } - if (!tmp.valid() && !swinfo->parentname.empty() && (snapfile.open(std::string(swinfo->parentname) + ".ico") == osd_file::error::NONE)) + if (!tmp.valid() && !swinfo->parentname.empty() && !snapfile.open(std::string(swinfo->parentname) + ".ico")) { render_load_ico_highest_detail(snapfile, tmp); snapfile.close(); @@ -668,7 +668,7 @@ void menu_select_software::filter_selected() if (software_filter::CUSTOM == new_type) { emu_file file(ui().options().ui_path(), OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS); - if (file.open(util::string_format("custom_%s_filter.ini", m_driver.name)) == osd_file::error::NONE) + if (!file.open(util::string_format("custom_%s_filter.ini", m_driver.name))) { filter.save_ini(file, 0); file.close(); diff --git a/src/frontend/mame/ui/state.cpp b/src/frontend/mame/ui/state.cpp index 8f911b8f15b..6bb0b9ccdc5 100644 --- a/src/frontend/mame/ui/state.cpp +++ b/src/frontend/mame/ui/state.cpp @@ -365,14 +365,16 @@ void menu_load_save_state_base::handle_keys(uint32_t flags, int &iptkey) machine().options().state_directory(), machine().get_statename(machine().options().state_name()), m_confirm_delete->file_name())); - osd_file::error const err(osd_file::remove(filename)); - if (osd_file::error::NONE != err) + std::error_condition const err(osd_file::remove(filename)); + if (err) { osd_printf_error( - "Error removing file %s for state %s (%d)\n", + "Error removing file %s for state %s (%s:%d %s)\n", filename, m_confirm_delete->visible_name(), - std::underlying_type_t(err)); + err.category().name(), + err.value(), + err.message()); machine().popmessage(_("Error removing saved state file %1$s"), filename); } diff --git a/src/frontend/mame/ui/ui.cpp b/src/frontend/mame/ui/ui.cpp index 9f176cca141..22404f32364 100644 --- a/src/frontend/mame/ui/ui.cpp +++ b/src/frontend/mame/ui/ui.cpp @@ -2136,7 +2136,7 @@ void mame_ui_manager::load_ui_options() // parse the file // attempt to open the output file emu_file file(machine().options().ini_path(), OPEN_FLAG_READ); - if (file.open("ui.ini") == osd_file::error::NONE) + if (!file.open("ui.ini")) { try { @@ -2157,7 +2157,7 @@ void mame_ui_manager::save_ui_options() { // 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") == osd_file::error::NONE) + if (!file.open("ui.ini")) { // generate the updated INI file.puts(options().output_ini()); @@ -2185,13 +2185,13 @@ void mame_ui_manager::save_main_option() // attempt to open the main ini file { emu_file file(machine().options().ini_path(), OPEN_FLAG_READ); - if (file.open(std::string(emulator_info::get_configname()) + ".ini") == osd_file::error::NONE) + if (!file.open(std::string(emulator_info::get_configname()) + ".ini")) { try { options.parse_ini_file((util::core_file&)file, OPTION_PRIORITY_MAME_INI, OPTION_PRIORITY_MAME_INI < OPTION_PRIORITY_DRIVER_INI, true); } - catch(options_error_exception &) + catch (options_error_exception &) { osd_printf_error("**Error loading %s.ini**\n", emulator_info::get_configname()); return; @@ -2215,13 +2215,14 @@ void mame_ui_manager::save_main_option() // 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(std::string(emulator_info::get_configname()) + ".ini") == osd_file::error::NONE) + if (!file.open(std::string(emulator_info::get_configname()) + ".ini")) { // generate the updated INI file.puts(options.output_ini()); file.close(); } - else { + else + { machine().popmessage(_("**Error saving %s.ini**"), emulator_info::get_configname()); return; } diff --git a/src/lib/formats/acorn_dsk.cpp b/src/lib/formats/acorn_dsk.cpp index c4668478b05..40ab6eb1029 100644 --- a/src/lib/formats/acorn_dsk.cpp +++ b/src/lib/formats/acorn_dsk.cpp @@ -10,6 +10,9 @@ #include "acorn_dsk.h" +#include "ioprocs.h" + + acorn_ssd_format::acorn_ssd_format() : wd177x_format(formats) { } @@ -29,29 +32,36 @@ const char *acorn_ssd_format::extensions() const return "ssd,bbc,img"; } -int acorn_ssd_format::find_size(io_generic *io, uint32_t form_factor, const std::vector &variants) +int acorn_ssd_format::find_size(util::random_read &io, uint32_t form_factor, const std::vector &variants) { uint8_t cat[8]; uint32_t sectors0, sectors2; - uint64_t size = io_generic_size(io); + uint64_t size; + if (io.length(size)) + { + LOG_FORMATS("ssd: error getting image size\n"); + return -1; + } - for(int i=0; formats[i].form_factor; i++) { + for (int i=0; formats[i].form_factor; i++) + { + size_t actual; const format &f = formats[i]; - if(form_factor != floppy_image::FF_UNKNOWN && form_factor != f.form_factor) + if (form_factor != floppy_image::FF_UNKNOWN && form_factor != f.form_factor) continue; // test for Torch CPN - test pattern at sector &0018 - io_generic_read(io, cat, 0x32800, 8); + io.read_at(0x32800, cat, 8, actual); if (memcmp(cat, "\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd", 4) == 0 && size == (uint64_t)compute_track_size(f) * f.track_count * f.head_count) return i; // test for HADFS - test pattern at sector 70 - io_generic_read(io, cat, 0x04610, 8); + io.read_at(0x04610, cat, 8, actual); if (memcmp(cat, "\x00\x28\x43\x29\x4a\x47\x48\x00", 4) == 0 && size == (uint64_t)compute_track_size(f) * f.track_count * f.head_count) return i; // test for Kenda SD - offset &0962 = 0 SD/1 DD, offset &0963 = disk size blocks / 4 (block size = 1K, ie. 0x400 bytes), reserved tracks = 3, ie. 0x1e00 bytes, soft stagger = 2 sectors, ie. 0x200 bytes - io_generic_read(io, cat, 0x0960, 8); + io.read_at(0x0960, cat, 8, actual); if (cat[2] == 0 && ((uint64_t)cat[3] * 4 * 0x400 + 0x2000) == size && size == (uint64_t)compute_track_size(f) * f.track_count * f.head_count) { // valid blocks for single sided @@ -63,20 +73,22 @@ int acorn_ssd_format::find_size(io_generic *io, uint32_t form_factor, const std: } // read sector count from side 0 catalogue - io_generic_read(io, cat, 0x100, 8); + io.read_at(0x100, cat, 8, actual); sectors0 = ((cat[6] & 3) << 8) + cat[7]; LOG_FORMATS("ssd: sector count 0: %d %s\n", sectors0, sectors0 % 10 != 0 ? "invalid" : ""); - if ((size <= (uint64_t)compute_track_size(f) * f.track_count * f.head_count) && (sectors0 <= f.track_count * f.sector_count)) { + if ((size <= (uint64_t)compute_track_size(f) * f.track_count * f.head_count) && (sectors0 <= f.track_count * f.sector_count)) + { if (f.head_count == 2) { // read sector count from side 2 catalogue - io_generic_read(io, cat, (uint64_t)compute_track_size(f) * f.track_count + 0x100, 8); // sequential + io.read_at((uint64_t)compute_track_size(f) * f.track_count + 0x100, cat, 8, actual); // sequential sectors2 = ((cat[6] & 3) << 8) + cat[7]; // exception case for Acorn CP/M System Disc 1 - io_generic_read(io, cat, 0x367ec, 8); - if (memcmp(cat, "/M ", 4) == 0) sectors2 = ((cat[6] & 3) << 8) + cat[7]; + io.read_at(0x367ec, cat, 8, actual); + if (memcmp(cat, "/M ", 4) == 0) + sectors2 = ((cat[6] & 3) << 8) + cat[7]; LOG_FORMATS("ssd: sector count 2: %d %s\n", sectors2, sectors2 % 10 != 0 ? "invalid" : ""); } @@ -93,12 +105,13 @@ int acorn_ssd_format::find_size(io_generic *io, uint32_t form_factor, const std: return -1; } -int acorn_ssd_format::identify(io_generic *io, uint32_t form_factor, const std::vector &variants) +int acorn_ssd_format::identify(util::random_read &io, uint32_t form_factor, const std::vector &variants) { int type = find_size(io, form_factor, variants); - if(type != -1) + if (type != -1) return 90; + return 0; } @@ -171,40 +184,49 @@ const char *acorn_dsd_format::extensions() const return "dsd"; } -int acorn_dsd_format::find_size(io_generic *io, uint32_t form_factor, const std::vector &variants) +int acorn_dsd_format::find_size(util::random_read &io, uint32_t form_factor, const std::vector &variants) { uint8_t cat[8]; uint32_t sectors0, sectors2; - uint64_t size = io_generic_size(io); + uint64_t size; + if (io.length(size)) + { + LOG_FORMATS("dsd: error getting image size\n"); + return -1; + } - for (int i = 0; formats[i].form_factor; i++) { + for (int i = 0; formats[i].form_factor; i++) + { + size_t actual; const format &f = formats[i]; if (form_factor != floppy_image::FF_UNKNOWN && form_factor != f.form_factor) continue; // test for Torch CPN - test pattern at sector &0018 - io_generic_read(io, cat, 0x1200, 8); + io.read_at(0x1200, cat, 8, actual); if (memcmp(cat, "\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd", 4) == 0 && size == (uint64_t)compute_track_size(f) * f.track_count * f.head_count) return i; // test for HADFS - test pattern at sector 70 - io_generic_read(io, cat, 0x08c10, 8); + io.read_at(0x08c10, cat, 8, actual); if (memcmp(cat, "\x00\x28\x43\x29\x4a\x47\x48\x00", 4) == 0 && size == (uint64_t)compute_track_size(f) * f.track_count * f.head_count) return i; // read sector count from side 0 catalogue - io_generic_read(io, cat, 0x100, 8); + io.read_at(0x100, cat, 8, actual); sectors0 = ((cat[6] & 3) << 8) + cat[7]; LOG_FORMATS("dsd: sector count 0: %d %s\n", sectors0, sectors0 % 10 != 0 ? "invalid" : ""); - if ((size <= (uint64_t)compute_track_size(f) * f.track_count * f.head_count) && (sectors0 <= f.track_count * f.sector_count)) { + if ((size <= (uint64_t)compute_track_size(f) * f.track_count * f.head_count) && (sectors0 <= f.track_count * f.sector_count)) + { // read sector count from side 2 catalogue - io_generic_read(io, cat, 0xb00, 8); // interleaved + io.read_at(0xb00, cat, 8, actual); // interleaved sectors2 = ((cat[6] & 3) << 8) + cat[7]; // exception case for Acorn CP/M System Disc 1 - io_generic_read(io, cat, 0x97ec, 8); - if (memcmp(cat, "/M ", 4) == 0) sectors2 = ((cat[6] & 3) << 8) + cat[7]; + io.read_at(0x97ec, cat, 8, actual); + if (memcmp(cat, "/M ", 4) == 0) + sectors2 = ((cat[6] & 3) << 8) + cat[7]; LOG_FORMATS("dsd: sector count 2: %d %s\n", sectors2, sectors2 % 10 != 0 ? "invalid" : ""); @@ -216,12 +238,13 @@ int acorn_dsd_format::find_size(io_generic *io, uint32_t form_factor, const std: return -1; } -int acorn_dsd_format::identify(io_generic *io, uint32_t form_factor, const std::vector &variants) +int acorn_dsd_format::identify(util::random_read &io, uint32_t form_factor, const std::vector &variants) { int type = find_size(io, form_factor, variants); if (type != -1) return 90; + return 0; } @@ -274,27 +297,36 @@ const char *opus_ddos_format::extensions() const return "dds"; } -int opus_ddos_format::find_size(io_generic *io, uint32_t form_factor, const std::vector &variants) +int opus_ddos_format::find_size(util::random_read &io, uint32_t form_factor, const std::vector &variants) { + size_t actual; uint8_t cat[8]; uint32_t sectors0, sectors2; // read sector count from side 0 catalogue - io_generic_read(io, cat, 0x1000, 8); + io.read_at(0x1000, cat, 8, actual); sectors0 = (cat[1] << 8) + cat[2]; LOG_FORMATS("ddos: sector count 0: %d %s\n", sectors0, sectors0 % 18 != 0 ? "invalid" : ""); - uint64_t size = io_generic_size(io); - for (int i = 0; formats[i].form_factor; i++) { + uint64_t size; + if (io.length(size)) + { + LOG_FORMATS("ddos: error getting image size\n"); + return -1; + } + + for (int i = 0; formats[i].form_factor; i++) + { const format &f = formats[i]; if (form_factor != floppy_image::FF_UNKNOWN && form_factor != f.form_factor) continue; - if ((size <= (uint64_t)compute_track_size(f) * f.track_count * f.head_count) && (sectors0 <= f.track_count * f.sector_count)) { + if ((size <= (uint64_t)compute_track_size(f) * f.track_count * f.head_count) && (sectors0 <= f.track_count * f.sector_count)) + { if (f.head_count == 2) { // read sector count from side 2 catalogue - io_generic_read(io, cat, (uint64_t)compute_track_size(f) * f.track_count + 0x1000, 8); // sequential + io.read_at((uint64_t)compute_track_size(f) * f.track_count + 0x1000, cat, 8, actual); // sequential sectors2 = (cat[1] << 8) + cat[2]; LOG_FORMATS("ddos: sector count 2: %d %s\n", sectors2, sectors2 % 18 != 0 ? "invalid" : ""); } @@ -311,12 +343,13 @@ int opus_ddos_format::find_size(io_generic *io, uint32_t form_factor, const std: return -1; } -int opus_ddos_format::identify(io_generic *io, uint32_t form_factor, const std::vector &variants) +int opus_ddos_format::identify(util::random_read &io, uint32_t form_factor, const std::vector &variants) { int type = find_size(io, form_factor, variants); if (type != -1) return 90; + return 0; } @@ -369,25 +402,33 @@ const char *acorn_adfs_old_format::extensions() const return "adf,ads,adm,adl"; } -int acorn_adfs_old_format::find_size(io_generic *io, uint32_t form_factor, const std::vector &variants) +int acorn_adfs_old_format::find_size(util::random_read &io, uint32_t form_factor, const std::vector &variants) { + size_t actual; uint8_t map[3]; uint32_t sectors; uint8_t oldmap[4]; // read sector count from free space map - io_generic_read(io, map, 0xfc, 3); + io.read_at(0xfc, map, 3, actual); sectors = map[0] + (map[1] << 8) + (map[2] << 16); LOG_FORMATS("adfs_o: sector count %d %s\n", sectors, sectors % 16 != 0 ? "invalid" : ""); // read map identifier - io_generic_read(io, oldmap, 0x201, 4); + io.read_at(0x201, oldmap, 4, actual); LOG_FORMATS("adfs_o: map identifier %s %s\n", oldmap, memcmp(oldmap, "Hugo", 4) != 0 ? "invalid" : ""); - uint64_t size = io_generic_size(io); - for(int i=0; formats[i].form_factor; i++) { + uint64_t size; + if (io.length(size)) + { + LOG_FORMATS("adfs_o: error getting image size\n"); + return -1; + } + + for (int i=0; formats[i].form_factor; i++) + { const format &f = formats[i]; - if(form_factor != floppy_image::FF_UNKNOWN && form_factor != f.form_factor) + if (form_factor != floppy_image::FF_UNKNOWN && form_factor != f.form_factor) continue; // valid images will have map identifier 'Hugo' and sector counts adfs-s = 0x280; adfs-m = 0x500; adfs-l = 0xa00; adfs-dos = 0xaa0; though many adfs-s images are incorrect @@ -399,12 +440,13 @@ int acorn_adfs_old_format::find_size(io_generic *io, uint32_t form_factor, const return -1; } -int acorn_adfs_old_format::identify(io_generic *io, uint32_t form_factor, const std::vector &variants) +int acorn_adfs_old_format::identify(util::random_read &io, uint32_t form_factor, const std::vector &variants) { int type = find_size(io, form_factor, variants); if(type != -1) return 100; + return 0; } @@ -465,43 +507,50 @@ const char *acorn_adfs_new_format::extensions() const return "adf"; } -int acorn_adfs_new_format::find_size(io_generic *io, uint32_t form_factor, const std::vector &variants) +int acorn_adfs_new_format::find_size(util::random_read &io, uint32_t form_factor, const std::vector &variants) { + size_t actual; uint8_t dform[4]; uint8_t eform[4]; // read map identifiers for D and E formats - io_generic_read(io, dform, 0x401, 4); + io.read_at(0x401, dform, 4, actual); LOG_FORMATS("adfs_n: map identifier (D format) %s %s\n", dform, (memcmp(dform, "Hugo", 4) != 0 && memcmp(dform, "Nick", 4) != 0) ? "invalid" : ""); - io_generic_read(io, eform, 0x801, 4); + io.read_at(0x801, eform, 4, actual); LOG_FORMATS("adfs_n: map identifier (E format) %s %s\n", eform, memcmp(eform, "Nick", 4) != 0 ? "invalid" : ""); - uint64_t size = io_generic_size(io); - for (int i = 0; formats[i].form_factor; i++) { + uint64_t size; + if (io.length(size)) + { + LOG_FORMATS("adfs_n: error getting image size\n"); + return -1; + } + + for (int i = 0; formats[i].form_factor; i++) + { const format &f = formats[i]; if (form_factor != floppy_image::FF_UNKNOWN && form_factor != f.form_factor) continue; // no further checks for 1600K images - if ((size == (uint64_t)compute_track_size(f) * f.track_count * f.head_count) && size == 0x190000) { + if ((size == (uint64_t)compute_track_size(f) * f.track_count * f.head_count) && size == 0x190000) return i; - } // valid 800K images will have map identifier Nick, Arthur D format still use Hugo - if ((size <= (uint64_t)compute_track_size(f) * f.track_count * f.head_count) && (memcmp(dform, "Hugo", 4) == 0 || memcmp(dform, "Nick", 4) == 0 || memcmp(eform, "Nick", 4) == 0)) { + if ((size <= (uint64_t)compute_track_size(f) * f.track_count * f.head_count) && (memcmp(dform, "Hugo", 4) == 0 || memcmp(dform, "Nick", 4) == 0 || memcmp(eform, "Nick", 4) == 0)) return i; - } } LOG_FORMATS("adfs_n: no match\n"); return -1; } -int acorn_adfs_new_format::identify(io_generic *io, uint32_t form_factor, const std::vector &variants) +int acorn_adfs_new_format::identify(util::random_read &io, uint32_t form_factor, const std::vector &variants) { int type = find_size(io, form_factor, variants); if (type != -1) return 100; + return 0; } @@ -546,33 +595,43 @@ const char *acorn_dos_format::extensions() const return "img"; } -int acorn_dos_format::find_size(io_generic *io, uint32_t form_factor, const std::vector &variants) +int acorn_dos_format::find_size(util::random_read &io, uint32_t form_factor, const std::vector &variants) { - uint8_t type; + uint64_t size; + if (io.length(size)) + { + LOG_FORMATS("dos: error getting image size\n"); + return -1; + } - uint64_t size = io_generic_size(io); - for(int i=0; formats[i].form_factor; i++) { + for (int i=0; formats[i].form_factor; i++) + { const format &f = formats[i]; - if(form_factor != floppy_image::FF_UNKNOWN && form_factor != f.form_factor) + if (form_factor != floppy_image::FF_UNKNOWN && form_factor != f.form_factor) continue; - if (size == (uint64_t)compute_track_size(f) * f.track_count * f.head_count) { + if (size == (uint64_t)compute_track_size(f) * f.track_count * f.head_count) + { // read media type ID from FAT - Acorn DOS = 0xfd - io_generic_read(io, &type, 0, 1); + size_t actual; + uint8_t type; + io.read_at(0, &type, 1, actual); LOG_FORMATS("dos: 800k media type id %02X %s\n", type, type != 0xfd ? "invalid" : ""); - if (type == 0xfd) return i; + if (type == 0xfd) + return i; } } LOG_FORMATS("dos: no match\n"); return -1; } -int acorn_dos_format::identify(io_generic *io, uint32_t form_factor, const std::vector &variants) +int acorn_dos_format::identify(util::random_read &io, uint32_t form_factor, const std::vector &variants) { int type = find_size(io, form_factor, variants); - if(type != -1) + if (type != -1) return 90; + return 0; } @@ -618,19 +677,28 @@ bool opus_ddcpm_format::supports_save() const return false; } -int opus_ddcpm_format::identify(io_generic *io, uint32_t form_factor, const std::vector &variants) +int opus_ddcpm_format::identify(util::random_read &io, uint32_t form_factor, const std::vector &variants) { + size_t actual; uint8_t h[8]; - io_generic_read(io, h, 0, 8); + io.read_at(0, h, 8, actual); + + uint64_t size; + if (io.length(size)) + { + LOG_FORMATS("ddcpm: error getting image size\n"); + return -1; + } - if (io_generic_size(io) == 819200 && memcmp(h, "Slogger ", 8) == 0) + if (size == 819200 && memcmp(h, "Slogger ", 8) == 0) return 100; + LOG_FORMATS("ddcpm: no match\n"); return 0; } -bool opus_ddcpm_format::load(io_generic *io, uint32_t form_factor, const std::vector &variants, floppy_image *image) +bool opus_ddcpm_format::load(util::random_read &io, uint32_t form_factor, const std::vector &variants, floppy_image *image) { // Double density discs formatted with DDCPM : // @@ -644,19 +712,21 @@ bool opus_ddcpm_format::load(io_generic *io, uint32_t form_factor, const std::ve // Sector skew of 1 // Sector interleave of 2 // - int spt, bps; - - for (int head = 0; head < 2; head++) { - for (int track = 0; track < 80; track++) { - bool mfm = track > 2 || head; - bps = mfm ? 512 : 256; - spt = 10; + for (int head = 0; head < 2; head++) + { + for (int track = 0; track < 80; track++) + { + bool const mfm = track > 2 || head; + int const bps = mfm ? 512 : 256; + int const spt = 10; desc_pc_sector sects[10]; uint8_t sectdata[10*512]; - io_generic_read(io, sectdata, head * 80 * spt * 512 + track * spt * 512, spt * 512); + size_t actual; + io.read_at(head * 80 * spt * 512 + track * spt * 512, sectdata, spt * 512, actual); - for (int i = 0; i < spt; i++) { + for (int i = 0; i < spt; i++) + { sects[i].track = track; sects[i].head = head; sects[i].sector = i; @@ -677,7 +747,7 @@ bool opus_ddcpm_format::load(io_generic *io, uint32_t form_factor, const std::ve return true; } -bool opus_ddcpm_format::save(io_generic *io, const std::vector &variants, floppy_image *image) +bool opus_ddcpm_format::save(util::random_read_write &io, const std::vector &variants, floppy_image *image) { return false; } diff --git a/src/lib/formats/acorn_dsk.h b/src/lib/formats/acorn_dsk.h index 1428212cfaa..de07e8b9fed 100644 --- a/src/lib/formats/acorn_dsk.h +++ b/src/lib/formats/acorn_dsk.h @@ -20,8 +20,8 @@ class acorn_ssd_format : public wd177x_format public: acorn_ssd_format(); - virtual int find_size(io_generic *io, uint32_t form_factor, const std::vector &variants) override; - virtual int identify(io_generic *io, uint32_t form_factor, const std::vector &variants) override; + virtual int find_size(util::random_read &io, uint32_t form_factor, const std::vector &variants) override; + virtual int identify(util::random_read &io, uint32_t form_factor, const std::vector &variants) override; virtual int get_image_offset(const format &f, int head, int track) override; virtual const char *name() const override; virtual const char *description() const override; @@ -36,8 +36,8 @@ class acorn_dsd_format : public wd177x_format public: acorn_dsd_format(); - virtual int find_size(io_generic *io, uint32_t form_factor, const std::vector &variants) override; - virtual int identify(io_generic *io, uint32_t form_factor, const std::vector &variants) override; + virtual int find_size(util::random_read &io, uint32_t form_factor, const std::vector &variants) override; + virtual int identify(util::random_read &io, uint32_t form_factor, const std::vector &variants) override; virtual int get_image_offset(const format &f, int head, int track) override; virtual const char *name() const override; virtual const char *description() const override; @@ -52,8 +52,8 @@ class opus_ddos_format : public wd177x_format public: opus_ddos_format(); - virtual int find_size(io_generic *io, uint32_t form_factor, const std::vector &variants) override; - virtual int identify(io_generic *io, uint32_t form_factor, const std::vector &variants) override; + virtual int find_size(util::random_read &io, uint32_t form_factor, const std::vector &variants) override; + virtual int identify(util::random_read &io, uint32_t form_factor, const std::vector &variants) override; virtual int get_image_offset(const format &f, int head, int track) override; virtual const char *name() const override; virtual const char *description() const override; @@ -68,8 +68,8 @@ class acorn_adfs_old_format : public wd177x_format public: acorn_adfs_old_format(); - virtual int find_size(io_generic *io, uint32_t form_factor, const std::vector &variants) override; - virtual int identify(io_generic *io, uint32_t form_factor, const std::vector &variants) override; + virtual int find_size(util::random_read &io, uint32_t form_factor, const std::vector &variants) override; + virtual int identify(util::random_read &io, uint32_t form_factor, const std::vector &variants) override; virtual int get_image_offset(const format &f, int head, int track) override; virtual const char *name() const override; virtual const char *description() const override; @@ -84,8 +84,8 @@ class acorn_adfs_new_format : public wd177x_format public: acorn_adfs_new_format(); - virtual int find_size(io_generic *io, uint32_t form_factor, const std::vector &variants) override; - virtual int identify(io_generic *io, uint32_t form_factor, const std::vector &variants) override; + virtual int find_size(util::random_read &io, uint32_t form_factor, const std::vector &variants) override; + virtual int identify(util::random_read &io, uint32_t form_factor, const std::vector &variants) override; virtual int get_image_offset(const format &f, int head, int track) override; virtual const char *name() const override; virtual const char *description() const override; @@ -100,8 +100,8 @@ class acorn_dos_format : public wd177x_format public: acorn_dos_format(); - virtual int find_size(io_generic *io, uint32_t form_factor, const std::vector &variants) override; - virtual int identify(io_generic *io, uint32_t form_factor, const std::vector &variants) override; + virtual int find_size(util::random_read &io, uint32_t form_factor, const std::vector &variants) override; + virtual int identify(util::random_read &io, uint32_t form_factor, const std::vector &variants) override; virtual int get_image_offset(const format &f, int head, int track) override; virtual const char *name() const override; virtual const char *description() const override; @@ -116,9 +116,9 @@ class opus_ddcpm_format : public floppy_image_format_t public: opus_ddcpm_format(); - virtual int identify(io_generic *io, uint32_t form_factor, const std::vector &variants) override; - virtual bool load(io_generic *io, uint32_t form_factor, const std::vector &variants, floppy_image *image) override; - virtual bool save(io_generic *io, const std::vector &variants, floppy_image *image) override; + virtual int identify(util::random_read &io, uint32_t form_factor, const std::vector &variants) override; + virtual bool load(util::random_read &io, uint32_t form_factor, const std::vector &variants, floppy_image *image) override; + virtual bool save(util::random_read_write &io, const std::vector &variants, floppy_image *image) override; virtual const char *name() const override; virtual const char *description() const override; diff --git a/src/lib/formats/afs_dsk.cpp b/src/lib/formats/afs_dsk.cpp index d6b275240de..000daf62df7 100644 --- a/src/lib/formats/afs_dsk.cpp +++ b/src/lib/formats/afs_dsk.cpp @@ -30,12 +30,13 @@ const char *afs_format::extensions() const return "adl,img"; } -int afs_format::identify(io_generic *io, uint32_t form_factor, const std::vector &variants) +int afs_format::identify(util::random_read &io, uint32_t form_factor, const std::vector &variants) { int type = find_size(io, form_factor, variants); if (type != -1) return 50; + return 0; } diff --git a/src/lib/formats/afs_dsk.h b/src/lib/formats/afs_dsk.h index 1a15e54d90d..f56b2dcb1f4 100644 --- a/src/lib/formats/afs_dsk.h +++ b/src/lib/formats/afs_dsk.h @@ -20,7 +20,7 @@ class afs_format : public wd177x_format public: afs_format(); - virtual int identify(io_generic *io, uint32_t form_factor, const std::vector &variants) override; + virtual int identify(util::random_read &io, uint32_t form_factor, const std::vector &variants) override; virtual int get_image_offset(const format &f, int head, int track) override; virtual const char *name() const override; virtual const char *description() const override; diff --git a/src/lib/formats/aim_dsk.cpp b/src/lib/formats/aim_dsk.cpp index 489ec1752e4..6ad49b22969 100644 --- a/src/lib/formats/aim_dsk.cpp +++ b/src/lib/formats/aim_dsk.cpp @@ -12,10 +12,10 @@ *********************************************************************/ -#include - #include "aim_dsk.h" +#include "ioprocs.h" + aim_format::aim_format() { @@ -40,18 +40,20 @@ const char *aim_format::extensions() const } -int aim_format::identify(io_generic *io, uint32_t form_factor, const std::vector &variants) +int aim_format::identify(util::random_read &io, uint32_t form_factor, const std::vector &variants) { - if (io_generic_size(io) == 2068480) - { + uint64_t size; + if (io.length(size)) + return 0; + + if (size == 2068480) return 100; - } return 0; } -bool aim_format::load(io_generic *io, uint32_t form_factor, const std::vector &variants, floppy_image *image) +bool aim_format::load(util::random_read &io, uint32_t form_factor, const std::vector &variants, floppy_image *image) { image->set_variant(floppy_image::DSQD); @@ -70,7 +72,8 @@ bool aim_format::load(io_generic *io, uint32_t form_factor, const std::vector &variants) override; - virtual bool load(io_generic *io, uint32_t form_factor, const std::vector &variants, floppy_image *image) override; + virtual int identify(util::random_read &io, uint32_t form_factor, const std::vector &variants) override; + virtual bool load(util::random_read &io, uint32_t form_factor, const std::vector &variants, floppy_image *image) override; virtual const char *name() const override; virtual const char *description() const override; @@ -31,4 +32,4 @@ public: extern const floppy_format_type FLOPPY_AIM_FORMAT; -#endif /* AIM_DSK_H */ +#endif // MAME_FORMATS_AIM_DSK_H diff --git a/src/lib/formats/ami_dsk.cpp b/src/lib/formats/ami_dsk.cpp index 5973bc69dab..eb96b01377d 100644 --- a/src/lib/formats/ami_dsk.cpp +++ b/src/lib/formats/ami_dsk.cpp @@ -8,10 +8,11 @@ *********************************************************************/ -#include - #include "formats/ami_dsk.h" +#include "ioprocs.h" + + adf_format::adf_format() : floppy_image_format_t() { } @@ -36,59 +37,61 @@ bool adf_format::supports_save() const return true; } -int adf_format::identify(io_generic *io, uint32_t form_factor, const std::vector &variants) +int adf_format::identify(util::random_read &io, uint32_t form_factor, const std::vector &variants) { - uint64_t size = io_generic_size(io); + uint64_t size; + if (io.length(size)) + return 0; + if ((size == 901120) || (size == 912384) || (size == 1802240)) - { return 50; - } + return 0; } -bool adf_format::load(io_generic *io, uint32_t form_factor, const std::vector &variants, floppy_image *image) +bool adf_format::load(util::random_read &io, uint32_t form_factor, const std::vector &variants, floppy_image *image) { desc_s sectors[22]; uint8_t sectdata[512*22]; bool is_hd = false; int tracks = 80; - for(int i=0; i<22; i++) { + for (int i=0; i<22; i++) { sectors[i].data = sectdata + 512*i; sectors[i].size = 512; sectors[i].sector_id = i; } - uint64_t size = io_generic_size(io); - if(size == 901120) - { + uint64_t size; + if (io.length(size)) + return false; + + if (size == 901120) { is_hd = false; tracks = 80; - } - else if (size == 912384) - { + } else if (size == 912384) { is_hd = false; tracks = 81; - } - else - { + } else { is_hd = true; tracks = 80; } if (!is_hd) { image->set_variant(floppy_image::DSDD); - for(int track=0; track < tracks; track++) { - for(int side=0; side < 2; side++) { - io_generic_read(io, sectdata, (track*2 + side)*512*11, 512*11); + for (int track=0; track < tracks; track++) { + for (int side=0; side < 2; side++) { + size_t actual; + io.read_at((track*2 + side)*512*11, sectdata, 512*11, actual); generate_track(amiga_11, track, side, sectors, 11, 100000, image); } } } else { image->set_variant(floppy_image::DSHD); - for(int track=0; track < tracks; track++) { - for(int side=0; side < 2; side++) { - io_generic_read(io, sectdata, (track*2 + side)*512*22, 512*22); + for (int track=0; track < tracks; track++) { + for (int side=0; side < 2; side++) { + size_t actual; + io.read_at((track*2 + side)*512*22, sectdata, 512*22, actual); generate_track(amiga_22, track, side, sectors, 22, 200000, image); } } @@ -100,11 +103,11 @@ bool adf_format::load(io_generic *io, uint32_t form_factor, const std::vector &trackbuf, uint32_t pos) { uint32_t res = 0; - for(int i=0; i != 32; i++) { - if(trackbuf[pos]) + for (int i=0; i != 32; i++) { + if (trackbuf[pos]) res |= 0x80000000 >> i; - pos ++; - if(pos == trackbuf.size()) + pos++; + if (pos == trackbuf.size()) pos = 0; } return res; @@ -113,34 +116,34 @@ uint32_t adf_format::g32(const std::vector &trackbuf, uint32_t pos) uint32_t adf_format::checksum(const std::vector &trackbuf, uint32_t pos, int long_count) { uint32_t check = 0; - for(int i=0; i &variants, floppy_image *image) +bool adf_format::save(util::random_read_write &io, const std::vector &variants, floppy_image *image) { uint8_t sectdata[512*22]; - bool hd = image->get_variant() == floppy_image::DSHD; + bool const hd = image->get_variant() == floppy_image::DSHD; - int data_track_size = hd ? 512*22 : 512*11; + int const data_track_size = hd ? 512*22 : 512*11; - for(int track=0; track < 80; track++) { - for(int side=0; side < 2; side++) { + for (int track=0; track < 80; track++) { + for (int side=0; side < 2; side++) { auto trackbuf = generate_bitstream_from_track(track, side, hd ? 1000 : 2000, image); - for(uint32_t i=0; i> 8) & 0xff; - if(sect > (hd ? 22 : 11)) + if (sect > (hd ? 22 : 11)) continue; uint8_t *dest = sectdata + 512*sect; - for(int j=0; j<128; j++) { + for (int j=0; j<128; j++) { uint32_t val = ((g32(trackbuf, i+480+32*j) & 0x55555555) << 1) | (g32(trackbuf, i+4576+32*j) & 0x55555555); *dest++ = val >> 24; *dest++ = val >> 16; @@ -148,7 +151,8 @@ bool adf_format::save(io_generic *io, const std::vector &variants, flo *dest++ = val; } - io_generic_write(io, sectdata, (track*2 + side)*data_track_size, data_track_size); + size_t actual; + io.write_at((track*2 + side) * data_track_size, sectdata, data_track_size, actual); } } } diff --git a/src/lib/formats/ami_dsk.h b/src/lib/formats/ami_dsk.h index d25fd45a210..595beb1bcd3 100644 --- a/src/lib/formats/ami_dsk.h +++ b/src/lib/formats/ami_dsk.h @@ -19,9 +19,9 @@ class adf_format : public floppy_image_format_t public: adf_format(); - virtual int identify(io_generic *io, uint32_t form_factor, const std::vector &variants) override; - virtual bool load(io_generic *io, uint32_t form_factor, const std::vector &variants, floppy_image *image) override; - virtual bool save(io_generic *io, const std::vector &variants, floppy_image *image) override; + virtual int identify(util::random_read &io, uint32_t form_factor, const std::vector &variants) override; + virtual bool load(util::random_read &io, uint32_t form_factor, const std::vector &variants, floppy_image *image) override; + virtual bool save(util::random_read_write &io, const std::vector &variants, floppy_image *image) override; virtual const char *name() const override; virtual const char *description() const override; diff --git a/src/lib/formats/ap2_dsk.cpp b/src/lib/formats/ap2_dsk.cpp index 50b071d6432..8adc13d69d3 100644 --- a/src/lib/formats/ap2_dsk.cpp +++ b/src/lib/formats/ap2_dsk.cpp @@ -8,13 +8,15 @@ *********************************************************************/ -#include -#include -#include - #include "ap2_dsk.h" #include "basicdsk.h" +#include "ioprocs.h" + +#include +#include +#include + #define APPLE2_IMAGE_DO 0 #define APPLE2_IMAGE_PO 1 @@ -559,9 +561,12 @@ bool a2_16sect_format::supports_save() const return true; } -int a2_16sect_format::identify(io_generic *io, uint32_t form_factor, const std::vector &variants) +int a2_16sect_format::identify(util::random_read &io, uint32_t form_factor, const std::vector &variants) { - uint64_t size = io_generic_size(io); + uint64_t size; + if (io.length(size)) + return 0; + //uint32_t expected_size = 35 * 16 * 256; uint32_t expected_size = APPLE2_TRACK_COUNT * 16 * 256; @@ -574,9 +579,11 @@ int a2_16sect_format::identify(io_generic *io, uint32_t form_factor, const std:: return 0; } -bool a2_16sect_format::load(io_generic *io, uint32_t form_factor, const std::vector &variants, floppy_image *image) +bool a2_16sect_format::load(util::random_read &io, uint32_t form_factor, const std::vector &variants, floppy_image *image) { - uint64_t size = io_generic_size(io); + uint64_t size; + if (io.length(size)) + return false; image->set_form_variant(floppy_image::FF_525, floppy_image::SSSD); @@ -595,7 +602,8 @@ bool a2_16sect_format::load(io_generic *io, uint32_t form_factor, const std::vec static const unsigned char cpm22_block1[8] = { 0xa2, 0x55, 0xa9, 0x00, 0x9d, 0x00, 0x0d, 0xca }; static const unsigned char subnod_block1[8] = { 0x63, 0xaa, 0xf0, 0x76, 0x8d, 0x63, 0xaa, 0x8e }; - io_generic_read(io, sector_data, fpos, 256*16); + size_t actual; + io.read_at(fpos, sector_data, 256*16, actual); if (track == 0 && fpos == 0) { @@ -740,7 +748,7 @@ void a2_16sect_format::update_chk(const uint8_t *data, int size, uint32_t &chk) //#define VERBOSE_SAVE -bool a2_16sect_format::save(io_generic *io, const std::vector &variants, floppy_image *image) +bool a2_16sect_format::save(util::random_read_write &io, const std::vector &variants, floppy_image *image) { int g_tracks, g_heads; int visualgrid[16][APPLE2_TRACK_COUNT]; // visualizer grid, cleared/initialized below @@ -938,8 +946,9 @@ bool a2_16sect_format::save(io_generic *io, const std::vector &variant } for(int i=0; i0) printf("t%d,", track); - uint8_t *data = sectdata + (256)*i; - io_generic_write(io, data, pos_data, 256); + uint8_t const *const data = sectdata + (256)*i; + size_t actual; + io.write_at(pos_data, data, 256, actual); pos_data += 256; } //printf("\n"); @@ -952,11 +961,11 @@ bool a2_16sect_format::save(io_generic *io, const std::vector &variant for (int i = 0; i < 16; i++) { if (visualgrid[i][j] == NOTFOUND) printf("-NF- "); else { - if (visualgrid[i][j] & ADDRFOUND) printf("a"); else printf(" "); - if (visualgrid[i][j] & ADDRGOOD) printf("A"); else printf(" "); - if (visualgrid[i][j] & DATAFOUND) printf("d"); else printf(" "); - if (visualgrid[i][j] & DATAGOOD) { printf("D"); total_good++; } else printf(" "); - if (visualgrid[i][j] & DATAPOST) printf("."); else printf(" "); + if (visualgrid[i][j] & ADDRFOUND) printf("a"); else printf(" "); + if (visualgrid[i][j] & ADDRGOOD) printf("A"); else printf(" "); + if (visualgrid[i][j] & DATAFOUND) printf("d"); else printf(" "); + if (visualgrid[i][j] & DATAGOOD) { printf("D"); total_good++; } else printf(" "); + if (visualgrid[i][j] & DATAPOST) printf("."); else printf(" "); } } printf("\n"); @@ -1019,14 +1028,16 @@ bool a2_rwts18_format::supports_save() const return true; } -int a2_rwts18_format::identify(io_generic *io, uint32_t form_factor, const std::vector &variants) +int a2_rwts18_format::identify(util::random_read &io, uint32_t form_factor, const std::vector &variants) { - uint64_t size = io_generic_size(io); - uint32_t expected_size = APPLE2_TRACK_COUNT * 16 * 256; + uint64_t size; + if(io.length(size)) + return 0; + uint32_t const expected_size = APPLE2_TRACK_COUNT * 16 * 256; return size == expected_size; } -bool a2_rwts18_format::load(io_generic *io, uint32_t form_factor, const std::vector &variants, floppy_image *image) +bool a2_rwts18_format::load(util::random_read &io, uint32_t form_factor, const std::vector &variants, floppy_image *image) { /* TODO: rewrite me properly uint8_t sector_data[(256)*16]; @@ -1046,7 +1057,8 @@ bool a2_rwts18_format::load(io_generic *io, uint32_t form_factor, const std::vec sectors[si].size = 256; sectors[si].sector_id = si; sectors[si].sector_info = format; - io_generic_read(io, data, pos_data, 256); + size_t actual; + io.read_at(pos_data, data, 256, actual); pos_data += 256; } generate_track(mac_gcr, track, head, sectors, 16, 3104*16, image); @@ -1075,7 +1087,7 @@ void a2_rwts18_format::update_chk(const uint8_t *data, int size, uint32_t &chk) { } -bool a2_rwts18_format::save(io_generic *io, const std::vector &variants, floppy_image *image) +bool a2_rwts18_format::save(util::random_read_write &io, const std::vector &variants, floppy_image *image) { int g_tracks, g_heads; int visualgrid[18][APPLE2_TRACK_COUNT]; // visualizer grid, cleared/initialized below @@ -1266,8 +1278,9 @@ bool a2_rwts18_format::save(io_generic *io, const std::vector &variant } for(int i=0; i0) printf("t%d,", track); - uint8_t *data = sectdata + (256)*i; - io_generic_write(io, data, pos_data, 256); + uint8_t const *const data = sectdata + (256)*i; + size_t actual; + io.write_at(pos_data, data, 256, actual); pos_data += 256; } @@ -1447,8 +1460,9 @@ bool a2_rwts18_format::save(io_generic *io, const std::vector &variant } for(int i=0; i0) printf("t%d,", track); - uint8_t *data = sectdata + (256)*i; - io_generic_write(io, data, pos_data, 256); + uint8_t const *const data = sectdata + (256)*i; + size_t actual; + io.write_at(pos_data, data, 256, actual); pos_data += 256; } //printf("\n"); @@ -1500,9 +1514,12 @@ bool a2_edd_format::supports_save() const return false; } -int a2_edd_format::identify(io_generic *io, uint32_t form_factor, const std::vector &variants) +int a2_edd_format::identify(util::random_read &io, uint32_t form_factor, const std::vector &variants) { - return ((io_generic_size(io) == 2244608) || (io_generic_size(io) == 2310144)) ? 50 : 0; + uint64_t size; + if (io.length(size)) + return 0; + return ((size == 2244608) || (size == 2310144)) ? 50 : 0; } uint8_t a2_edd_format::pick(const uint8_t *data, int pos) @@ -1510,23 +1527,20 @@ uint8_t a2_edd_format::pick(const uint8_t *data, int pos) return ((data[pos>>3] << 8) | data[(pos>>3)+1]) >> (8-(pos & 7)); } -bool a2_edd_format::load(io_generic *io, uint32_t form_factor, const std::vector &variants, floppy_image *image) +bool a2_edd_format::load(util::random_read &io, uint32_t form_factor, const std::vector &variants, floppy_image *image) { - uint8_t *img; uint8_t nibble[16384], stream[16384]; int npos[16384]; - img = (uint8_t *) malloc(2244608); - + std::unique_ptr img(new (std::nothrow) uint8_t[2244608]); if (!img) - { return false; - } - io_generic_read(io, img, 0, 2244608); + size_t actual; + io.read_at(0, img.get(), 2244608, actual); for(int i=0; i<137; i++) { - const uint8_t *trk = img + 16384*i; + uint8_t const *const trk = &img[16384*i]; int pos = 0; int wpos = 0; while(pos < 16383*8) { @@ -1590,7 +1604,7 @@ bool a2_edd_format::load(io_generic *io, uint32_t form_factor, const std::vector generate_track_from_bitstream(i >> 2, 0, stream, len, image, i & 3); image->set_write_splice_position(i >> 2, 0, uint32_t(uint64_t(200'000'000)*splice/len), i & 3); } - free(img); + img.reset(); image->set_form_variant(floppy_image::FF_525, floppy_image::SSSD); @@ -1627,26 +1641,31 @@ bool a2_woz_format::supports_save() const const uint8_t a2_woz_format::signature[8] = { 0x57, 0x4f, 0x5a, 0x31, 0xff, 0x0a, 0x0d, 0x0a }; const uint8_t a2_woz_format::signature2[8] = { 0x57, 0x4f, 0x5a, 0x32, 0xff, 0x0a, 0x0d, 0x0a }; -int a2_woz_format::identify(io_generic *io, uint32_t form_factor, const std::vector &variants) +int a2_woz_format::identify(util::random_read &io, uint32_t form_factor, const std::vector &variants) { uint8_t header[8]; - io_generic_read(io, header, 0, 8); + size_t actual; + io.read_at(0, header, 8, actual); if (!memcmp(header, signature, 8)) return 100; if (!memcmp(header, signature2, 8)) return 100; return 0; } -bool a2_woz_format::load(io_generic *io, uint32_t form_factor, const std::vector &variants, floppy_image *image) +bool a2_woz_format::load(util::random_read &io, uint32_t form_factor, const std::vector &variants, floppy_image *image) { - std::vector img(io_generic_size(io)); - io_generic_read(io, &img[0], 0, img.size()); + uint64_t image_size; + if(io.length(image_size)) + return false; + std::vector img(image_size); + size_t actual; + io.read_at(0, &img[0], img.size(), actual); // Check signature - if ((memcmp(&img[0], signature, 8)) && (memcmp(&img[0], signature2, 8))) + if((memcmp(&img[0], signature, 8)) && (memcmp(&img[0], signature2, 8))) return false; uint32_t woz_vers = 1; - if (!memcmp(&img[0], signature2, 8)) woz_vers = 2; + if(!memcmp(&img[0], signature2, 8)) woz_vers = 2; // Check integrity uint32_t crc = crc32r(&img[12], img.size() - 12); @@ -1663,7 +1682,7 @@ bool a2_woz_format::load(io_generic *io, uint32_t form_factor, const std::vector uint32_t info_vers = r8(img, off_info + 0); - if ((info_vers != 1) && (info_vers != 2)) + if((info_vers != 1) && (info_vers != 2)) return false; bool is_35 = r8(img, off_info + 1) == 2; @@ -1721,7 +1740,7 @@ bool a2_woz_format::load(io_generic *io, uint32_t form_factor, const std::vector return true; } -bool a2_woz_format::save(io_generic *io, const std::vector &variants, floppy_image *image) +bool a2_woz_format::save(util::random_read_write &io, const std::vector &variants, floppy_image *image) { std::vector> tracks(160); bool twosided = false; @@ -1823,7 +1842,8 @@ bool a2_woz_format::save(io_generic *io, const std::vector &variants, w32(data, 8, crc32r(&data[12], data.size() - 12)); - io_generic_write(io, data.data(), 0, data.size()); + size_t actual; + io.write_at(0, data.data(), data.size(), actual); return true; } @@ -1911,12 +1931,15 @@ bool a2_nib_format::supports_save() const return false; } -int a2_nib_format::identify(io_generic *io, uint32_t form_factor, const std::vector &variants) +int a2_nib_format::identify(util::random_read &io, uint32_t form_factor, const std::vector &variants) { - const auto size = io_generic_size(io); - if (size == expected_size_35t || size == expected_size_40t) { + uint64_t size; + if (io.length(size)) + return 0; + + if (size == expected_size_35t || size == expected_size_40t) return 50; - } + return 0; } @@ -2031,18 +2054,20 @@ std::vector a2_nib_format::generate_levels_from_nibbles(const std::vec return levels; } -bool a2_nib_format::load(io_generic *io, uint32_t form_factor, const std::vector &variants, floppy_image *image) +bool a2_nib_format::load(util::random_read &io, uint32_t form_factor, const std::vector &variants, floppy_image *image) { - auto size = io_generic_size(io); - if (size != expected_size_35t && size != expected_size_40t) { + uint64_t size; + if (io.length(size)) return false; - } + if (size != expected_size_35t && size != expected_size_40t) + return false; + const auto nr_tracks = size == expected_size_35t? 35 : 40; std::vector nibbles(nibbles_per_track); for (unsigned track = 0; track < nr_tracks; ++track) { - io_generic_read(io, &nibbles[0], - track * nibbles_per_track, nibbles_per_track); + size_t actual; + io.read_at(track * nibbles_per_track, &nibbles[0], nibbles_per_track, actual); auto levels = generate_levels_from_nibbles(nibbles); generate_track_from_levels(track, 0, levels, diff --git a/src/lib/formats/ap2_dsk.h b/src/lib/formats/ap2_dsk.h index 7420d72d818..bab61cf96b8 100644 --- a/src/lib/formats/ap2_dsk.h +++ b/src/lib/formats/ap2_dsk.h @@ -41,9 +41,9 @@ class a2_16sect_format : public floppy_image_format_t public: a2_16sect_format(); - virtual int identify(io_generic *io, uint32_t form_factor, const std::vector &variants) override; - virtual bool load(io_generic *io, uint32_t form_factor, const std::vector &variants, floppy_image *image) override; - virtual bool save(io_generic *io, const std::vector &variants, floppy_image *image) override; + virtual int identify(util::random_read &io, uint32_t form_factor, const std::vector &variants) override; + virtual bool load(util::random_read &io, uint32_t form_factor, const std::vector &variants, floppy_image *image) override; + virtual bool save(util::random_read_write &io, const std::vector &variants, floppy_image *image) override; virtual const char *name() const override; virtual const char *description() const override; @@ -68,9 +68,9 @@ class a2_rwts18_format : public floppy_image_format_t public: a2_rwts18_format(); - virtual int identify(io_generic *io, uint32_t form_factor, const std::vector &variants) override; - virtual bool load(io_generic *io, uint32_t form_factor, const std::vector &variants, floppy_image *image) override; - virtual bool save(io_generic *io, const std::vector &variants, floppy_image *image) override; + virtual int identify(util::random_read &io, uint32_t form_factor, const std::vector &variants) override; + virtual bool load(util::random_read &io, uint32_t form_factor, const std::vector &variants, floppy_image *image) override; + virtual bool save(util::random_read_write &io, const std::vector &variants, floppy_image *image) override; virtual const char *name() const override; virtual const char *description() const override; @@ -92,8 +92,8 @@ class a2_edd_format : public floppy_image_format_t public: a2_edd_format(); - virtual int identify(io_generic *io, uint32_t form_factor, const std::vector &variants) override; - virtual bool load(io_generic *io, uint32_t form_factor, const std::vector &variants, floppy_image *image) override; + virtual int identify(util::random_read &io, uint32_t form_factor, const std::vector &variants) override; + virtual bool load(util::random_read &io, uint32_t form_factor, const std::vector &variants, floppy_image *image) override; virtual bool supports_save() const override; virtual const char *name() const override; @@ -111,9 +111,9 @@ class a2_woz_format : public floppy_image_format_t public: a2_woz_format(); - virtual int identify(io_generic *io, uint32_t form_factor, const std::vector &variants) override; - virtual bool load(io_generic *io, uint32_t form_factor, const std::vector &variants, floppy_image *image) override; - virtual bool save(io_generic *io, const std::vector &variants, floppy_image *image) override; + virtual int identify(util::random_read &io, uint32_t form_factor, const std::vector &variants) override; + virtual bool load(util::random_read &io, uint32_t form_factor, const std::vector &variants, floppy_image *image) override; + virtual bool save(util::random_read_write &io, const std::vector &variants, floppy_image *image) override; virtual bool supports_save() const override; virtual const char *name() const override; @@ -141,8 +141,8 @@ class a2_nib_format : public floppy_image_format_t public: a2_nib_format(); - virtual int identify(io_generic *io, uint32_t form_factor, const std::vector &variants) override; - virtual bool load(io_generic *io, uint32_t form_factor, const std::vector &variants, floppy_image *image) override; + virtual int identify(util::random_read &io, uint32_t form_factor, const std::vector &variants) override; + virtual bool load(util::random_read &io, uint32_t form_factor, const std::vector &variants, floppy_image *image) override; virtual bool supports_save() const override; virtual const char *name() const override; diff --git a/src/lib/formats/ap_dsk35.cpp b/src/lib/formats/ap_dsk35.cpp index 9819406183c..6a3fa5d742b 100644 --- a/src/lib/formats/ap_dsk35.cpp +++ b/src/lib/formats/ap_dsk35.cpp @@ -100,6 +100,8 @@ #include "ap_dsk35.h" +#include "ioprocs.h" + #include #include @@ -1233,14 +1235,15 @@ bool dc42_format::supports_save() const return true; } -int dc42_format::identify(io_generic *io, uint32_t form_factor, const std::vector &variants) +int dc42_format::identify(util::random_read &io, uint32_t form_factor, const std::vector &variants) { - uint8_t h[0x54]; - uint64_t size = io_generic_size(io); - if(size < 0x54) + uint64_t size; + if(io.length(size) || (size < 0x54)) return 0; - io_generic_read(io, h, 0, 0x54); + uint8_t h[0x54]; + size_t actual; + io.read_at(0, h, 0x54, actual); uint32_t dsize = (h[0x40] << 24) | (h[0x41] << 16) | (h[0x42] << 8) | h[0x43]; uint32_t tsize = (h[0x44] << 24) | (h[0x45] << 16) | (h[0x46] << 8) | h[0x47]; @@ -1252,13 +1255,14 @@ int dc42_format::identify(io_generic *io, uint32_t form_factor, const std::vecto return 0; } - return size == 0x54+tsize+dsize && h[0] < 64 && h[0x52] == 1 && h[0x53] == 0 ? 100 : 0; + return (size == 0x54+tsize+dsize && h[0] < 64 && h[0x52] == 1 && h[0x53] == 0) ? 100 : 0; } -bool dc42_format::load(io_generic *io, uint32_t form_factor, const std::vector &variants, floppy_image *image) +bool dc42_format::load(util::random_read &io, uint32_t form_factor, const std::vector &variants, floppy_image *image) { + size_t actual; uint8_t h[0x54]; - io_generic_read(io, h, 0, 0x54); + io.read_at(0, h, 0x54, actual); int dsize = (h[0x40] << 24) | (h[0x41] << 16) | (h[0x42] << 8) | h[0x43]; int tsize = (h[0x44] << 24) | (h[0x45] << 16) | (h[0x46] << 8) | h[0x47]; @@ -1270,8 +1274,7 @@ bool dc42_format::load(io_generic *io, uint32_t form_factor, const std::vectorset_form_variant(floppy_image::FF_35, floppy_image::SSDD); break; @@ -1315,13 +1318,14 @@ bool dc42_format::load(io_generic *io, uint32_t form_factor, const std::vector &variants, floppy_image *image) +bool dc42_format::save(util::random_read_write &io, const std::vector &variants, floppy_image *image) { int g_tracks, g_heads; image->get_actual_geometry(g_tracks, g_heads); @@ -1381,8 +1385,9 @@ bool dc42_format::save(io_generic *io, const std::vector &variants, fl for(unsigned int i=0; i < sectors.size(); i++) { auto &sdata = sectors[i]; sdata.resize(512+12); - io_generic_write(io, &sdata[0], pos_tag, 12); - io_generic_write(io, &sdata[12], pos_data, 512); + size_t actual; + io.write_at(pos_tag, &sdata[0], 12, actual); + io.write_at(pos_data, &sdata[12], 512, actual); pos_tag += 12; pos_data += 512; if(track || head || i) @@ -1401,7 +1406,8 @@ bool dc42_format::save(io_generic *io, const std::vector &variants, fl h[0x4e] = tchk >> 8; h[0x4f] = tchk; - io_generic_write(io, h, 0, 0x54); + size_t actual; + io.write_at(0, h, 0x54, actual); return true; } @@ -1432,26 +1438,32 @@ bool apple_gcr_format::supports_save() const return true; } -int apple_gcr_format::identify(io_generic *io, uint32_t form_factor, const std::vector &variants) +int apple_gcr_format::identify(util::random_read &io, uint32_t form_factor, const std::vector &variants) { - uint64_t size = io_generic_size(io); + uint64_t size; + if(io.length(size)) + return 0; + if(size == 409600 || (size == 819200 && (variants.empty() || has_variant(variants, floppy_image::DSDD)))) return 50; return 0; } -bool apple_gcr_format::load(io_generic *io, uint32_t form_factor, const std::vector &variants, floppy_image *image) +bool apple_gcr_format::load(util::random_read &io, uint32_t form_factor, const std::vector &variants, floppy_image *image) { + size_t actual; desc_gcr_sector sectors[12]; uint8_t sdata[512*12]; int pos_data = 0; uint8_t header[64]; - io_generic_read(io, header, 0, 64); + io.read_at(0, header, 64, actual); - uint64_t size = io_generic_size(io); + uint64_t size; + if(io.length(size)) + return false; int head_count = size == 409600 ? 1 : size == 819200 ? 2 : 0; image->set_form_variant(floppy_image::FF_35, head_count == 2 ? floppy_image::DSDD : floppy_image::SSDD); @@ -1461,7 +1473,7 @@ bool apple_gcr_format::load(io_generic *io, uint32_t form_factor, const std::vec for(int track=0; track < 80; track++) { for(int head=0; head < head_count; head++) { int ns = 12 - (track/16); - io_generic_read(io, sdata, pos_data, 512*ns); + io.read_at(pos_data, sdata, 512*ns, actual); pos_data += 512*ns; int si = 0; @@ -1482,7 +1494,7 @@ bool apple_gcr_format::load(io_generic *io, uint32_t form_factor, const std::vec return true; } -bool apple_gcr_format::save(io_generic *io, const std::vector &variants, floppy_image *image) +bool apple_gcr_format::save(util::random_read_write &io, const std::vector &variants, floppy_image *image) { int g_tracks, g_heads; image->get_actual_geometry(g_tracks, g_heads); @@ -1498,7 +1510,8 @@ bool apple_gcr_format::save(io_generic *io, const std::vector &variant for(unsigned int i=0; i < sectors.size(); i++) { auto &sdata = sectors[i]; sdata.resize(512+12); - io_generic_write(io, &sdata[12], pos_data, 512); + size_t actual; + io.write_at(pos_data, &sdata[12], 512, actual); pos_data += 512; } } @@ -1534,10 +1547,11 @@ bool apple_2mg_format::supports_save() const return true; } -int apple_2mg_format::identify(io_generic *io, uint32_t form_factor, const std::vector &variants) +int apple_2mg_format::identify(util::random_read &io, uint32_t form_factor, const std::vector &variants) { uint8_t signature[4]; - io_generic_read(io, signature, 0, 4); + size_t actual; + io.read_at(0, signature, 4, actual); if (!strncmp(reinterpret_cast(signature), "2IMG", 4)) { return 100; @@ -1552,11 +1566,12 @@ int apple_2mg_format::identify(io_generic *io, uint32_t form_factor, const std:: return 0; } -bool apple_2mg_format::load(io_generic *io, uint32_t form_factor, const std::vector &variants, floppy_image *image) +bool apple_2mg_format::load(util::random_read &io, uint32_t form_factor, const std::vector &variants, floppy_image *image) { + size_t actual; desc_gcr_sector sectors[12]; uint8_t sdata[512*12], header[64]; - io_generic_read(io, header, 0, 64); + io.read_at(0, header, 64, actual); uint32_t blocks = header[0x14] | (header[0x15] << 8) | (header[0x16] << 16) | (header[0x17] << 24); uint32_t pos_data = header[0x18] | (header[0x19] << 8) | (header[0x1a] << 16) | (header[0x1b] << 24); @@ -1568,7 +1583,7 @@ bool apple_2mg_format::load(io_generic *io, uint32_t form_factor, const std::vec for(int track=0; track < 80; track++) { for(int head=0; head < 2; head++) { int ns = 12 - (track/16); - io_generic_read(io, sdata, pos_data, 512*ns); + io.read_at(pos_data, sdata, 512*ns, actual); pos_data += 512*ns; int si = 0; @@ -1589,8 +1604,10 @@ bool apple_2mg_format::load(io_generic *io, uint32_t form_factor, const std::vec return true; } -bool apple_2mg_format::save(io_generic *io, const std::vector &variants, floppy_image *image) +bool apple_2mg_format::save(util::random_read_write &io, const std::vector &variants, floppy_image *image) { + size_t actual; + uint8_t header[0x40]; int pos_data = 0x40; @@ -1611,7 +1628,7 @@ bool apple_2mg_format::save(io_generic *io, const std::vector &variant header[0x18] = 0x40; // bytes of disk data header[0x1c] = 0x00; header[0x1d] = 0x80; header[0x1e] = 0x0c; // 0xC8000 (819200) - io_generic_write(io, header, 0, 0x40); + io.write_at(0, header, 0x40, actual); for(int track=0; track < 80; track++) { for(int head=0; head < 2; head++) { @@ -1619,7 +1636,7 @@ bool apple_2mg_format::save(io_generic *io, const std::vector &variant for(unsigned int i=0; i < sectors.size(); i++) { auto &sdata = sectors[i]; sdata.resize(512+12); - io_generic_write(io, &sdata[12], pos_data, 512); + io.write_at(pos_data, &sdata[12], 512, actual); pos_data += 512; } } diff --git a/src/lib/formats/ap_dsk35.h b/src/lib/formats/ap_dsk35.h index def1cb86856..f4a8ec7bff8 100644 --- a/src/lib/formats/ap_dsk35.h +++ b/src/lib/formats/ap_dsk35.h @@ -29,9 +29,9 @@ class dc42_format : public floppy_image_format_t public: dc42_format(); - virtual int identify(io_generic *io, uint32_t form_factor, const std::vector &variants) override; - virtual bool load(io_generic *io, uint32_t form_factor, const std::vector &variants, floppy_image *image) override; - virtual bool save(io_generic *io, const std::vector &variants, floppy_image *image) override; + virtual int identify(util::random_read &io, uint32_t form_factor, const std::vector &variants) override; + virtual bool load(util::random_read &io, uint32_t form_factor, const std::vector &variants, floppy_image *image) override; + virtual bool save(util::random_read_write &io, const std::vector &variants, floppy_image *image) override; virtual const char *name() const override; virtual const char *description() const override; @@ -49,9 +49,9 @@ class apple_gcr_format : public floppy_image_format_t public: apple_gcr_format(); - virtual int identify(io_generic *io, uint32_t form_factor, const std::vector &variants) override; - virtual bool load(io_generic *io, uint32_t form_factor, const std::vector &variants, floppy_image *image) override; - virtual bool save(io_generic *io, const std::vector &variants, floppy_image *image) override; + virtual int identify(util::random_read &io, uint32_t form_factor, const std::vector &variants) override; + virtual bool load(util::random_read &io, uint32_t form_factor, const std::vector &variants, floppy_image *image) override; + virtual bool save(util::random_read_write &io, const std::vector &variants, floppy_image *image) override; virtual const char *name() const override; virtual const char *description() const override; @@ -66,9 +66,9 @@ class apple_2mg_format : public floppy_image_format_t public: apple_2mg_format(); - virtual int identify(io_generic *io, uint32_t form_factor, const std::vector &variants) override; - virtual bool load(io_generic *io, uint32_t form_factor, const std::vector &variants, floppy_image *image) override; - virtual bool save(io_generic *io, const std::vector &variants, floppy_image *image) override; + virtual int identify(util::random_read &io, uint32_t form_factor, const std::vector &variants) override; + virtual bool load(util::random_read &io, uint32_t form_factor, const std::vector &variants, floppy_image *image) override; + virtual bool save(util::random_read_write &io, const std::vector &variants, floppy_image *image) override; virtual const char *name() const override; virtual const char *description() const override; diff --git a/src/lib/formats/apd_dsk.cpp b/src/lib/formats/apd_dsk.cpp index 45d385a0800..f882d90fe23 100644 --- a/src/lib/formats/apd_dsk.cpp +++ b/src/lib/formats/apd_dsk.cpp @@ -60,9 +60,13 @@ *********************************************************************/ -#include #include "formats/apd_dsk.h" +#include "ioprocs.h" + +#include + + static const uint8_t APD_HEADER[8] = { 'A', 'P', 'D', 'X', '0', '0', '0', '1' }; static const uint8_t GZ_HEADER[2] = { 0x1f, 0x8b }; @@ -85,11 +89,15 @@ const char *apd_format::extensions() const return "apd"; } -int apd_format::identify(io_generic *io, uint32_t form_factor, const std::vector &variants) +int apd_format::identify(util::random_read &io, uint32_t form_factor, const std::vector &variants) { - uint64_t size = io_generic_size(io); + uint64_t size; + if (io.length(size)) + return 0; + std::vector img(size); - io_generic_read(io, &img[0], 0, size); + size_t actual; + io.read_at(0, &img[0], size, actual); int err; std::vector gz_ptr(8); @@ -123,11 +131,15 @@ int apd_format::identify(io_generic *io, uint32_t form_factor, const std::vector return 0; } -bool apd_format::load(io_generic *io, uint32_t form_factor, const std::vector &variants, floppy_image *image) +bool apd_format::load(util::random_read &io, uint32_t form_factor, const std::vector &variants, floppy_image *image) { - uint64_t size = io_generic_size(io); + uint64_t size; + if (io.length(size)) + return false; + std::vector img(size); - io_generic_read(io, &img[0], 0, size); + size_t actual; + io.read_at(0, &img[0], size, actual); int err; std::vector gz_ptr; diff --git a/src/lib/formats/apd_dsk.h b/src/lib/formats/apd_dsk.h index bc551973c4a..8c3ac6f0d42 100644 --- a/src/lib/formats/apd_dsk.h +++ b/src/lib/formats/apd_dsk.h @@ -23,8 +23,8 @@ public: virtual const char *description() const override; virtual const char *extensions() const override; - virtual int identify(io_generic *io, uint32_t form_factor, const std::vector &variants) override; - virtual bool load(io_generic *io, uint32_t form_factor, const std::vector &variants, floppy_image *image) override; + virtual int identify(util::random_read &io, uint32_t form_factor, const std::vector &variants) override; + virtual bool load(util::random_read &io, uint32_t form_factor, const std::vector &variants, floppy_image *image) override; virtual bool supports_save() const override; }; diff --git a/src/lib/formats/apollo_dsk.cpp b/src/lib/formats/apollo_dsk.cpp index 75c31cfe7f8..a1159ac68c8 100644 --- a/src/lib/formats/apollo_dsk.cpp +++ b/src/lib/formats/apollo_dsk.cpp @@ -8,10 +8,11 @@ *********************************************************************/ -#include - #include "formats/apollo_dsk.h" +#include "ioprocs.h" + + apollo_format::apollo_format() : upd765_format(formats) { } @@ -46,10 +47,13 @@ const apollo_format::format apollo_format::formats[] = { const floppy_format_type FLOPPY_APOLLO_FORMAT = &floppy_image_format_creator; -int apollo_format::identify(io_generic *io, uint32_t form_factor, const std::vector &variants) +int apollo_format::identify(util::random_read &io, uint32_t form_factor, const std::vector &variants) { - uint64_t size = io_generic_size(io); - uint32_t expected_size = 77*2*8*1024; + uint64_t size; + if (io.length(size)) + return 0; + + constexpr uint32_t expected_size = 77*2*8*1024; return ((size == expected_size) || (size == 0)) ? 1 : 0; } diff --git a/src/lib/formats/apollo_dsk.h b/src/lib/formats/apollo_dsk.h index 6376c77b067..1c2c6d81030 100644 --- a/src/lib/formats/apollo_dsk.h +++ b/src/lib/formats/apollo_dsk.h @@ -19,7 +19,7 @@ class apollo_format : public upd765_format public: apollo_format(); - virtual int identify(io_generic *io, uint32_t form_factor, const std::vector &variants) override; + virtual int identify(util::random_read &io, uint32_t form_factor, const std::vector &variants) override; virtual const char *name() const override; virtual const char *description() const override; virtual const char *extensions() const override; diff --git a/src/lib/formats/apridisk.cpp b/src/lib/formats/apridisk.cpp index 388d358f6f8..1560c199149 100644 --- a/src/lib/formats/apridisk.cpp +++ b/src/lib/formats/apridisk.cpp @@ -12,6 +12,8 @@ #include "imageutl.h" +#include "ioprocs.h" + apridisk_format::apridisk_format() { @@ -32,10 +34,11 @@ const char *apridisk_format::extensions() const return "dsk"; } -int apridisk_format::identify(io_generic *io, uint32_t form_factor, const std::vector &variants) +int apridisk_format::identify(util::random_read &io, uint32_t form_factor, const std::vector &variants) { uint8_t header[APR_HEADER_SIZE]; - io_generic_read(io, header, 0, APR_HEADER_SIZE); + size_t actual; + io.read_at(0, header, APR_HEADER_SIZE, actual); const char magic[] = "ACT Apricot disk image\x1a\x04"; @@ -45,21 +48,26 @@ int apridisk_format::identify(io_generic *io, uint32_t form_factor, const std::v return 0; } -bool apridisk_format::load(io_generic *io, uint32_t form_factor, const std::vector &variants, floppy_image *image) +bool apridisk_format::load(util::random_read &io, uint32_t form_factor, const std::vector &variants, floppy_image *image) { desc_pc_sector sectors[80][2][18]; std::unique_ptr sector_data(new uint8_t [MAX_SECTORS * SECTOR_SIZE]); uint8_t *data_ptr = sector_data.get(); int track_count = 0, head_count = 0, sector_count = 0; - uint64_t file_size = io_generic_size(io); + uint64_t file_size; + if (io.length(file_size)) + return false; + uint64_t file_offset = APR_HEADER_SIZE; while (file_offset < file_size) { + size_t actual; + // read sector header uint8_t sector_header[16]; - io_generic_read(io, sector_header, file_offset, 16); + io.read_at(file_offset, sector_header, 16, actual); uint32_t type = pick_integer_le(§or_header, 0, 4); uint16_t compression = pick_integer_le(§or_header, 4, 2); @@ -94,7 +102,7 @@ bool apridisk_format::load(io_generic *io, uint32_t form_factor, const std::vect case APR_COMPRESSED: { uint8_t comp[3]; - io_generic_read(io, comp, file_offset, 3); + io.read_at(file_offset, comp, 3, actual); uint16_t length = pick_integer_le(comp, 0, 2); if (length != SECTOR_SIZE) @@ -108,7 +116,7 @@ bool apridisk_format::load(io_generic *io, uint32_t form_factor, const std::vect break; case APR_UNCOMPRESSED: - io_generic_read(io, data_ptr, file_offset, SECTOR_SIZE); + io.read_at(file_offset, data_ptr, SECTOR_SIZE, actual); break; default: @@ -140,7 +148,7 @@ bool apridisk_format::load(io_generic *io, uint32_t form_factor, const std::vect return true; } -bool apridisk_format::save(io_generic *io, const std::vector &variants, floppy_image *image) +bool apridisk_format::save(util::random_read_write &io, const std::vector &variants, floppy_image *image) { return false; } diff --git a/src/lib/formats/apridisk.h b/src/lib/formats/apridisk.h index 3e751f8d6ec..5cc8a1403fb 100644 --- a/src/lib/formats/apridisk.h +++ b/src/lib/formats/apridisk.h @@ -23,9 +23,9 @@ public: virtual const char *description() const override; virtual const char *extensions() const override; - virtual int identify(io_generic *io, uint32_t form_factor, const std::vector &variants) override; - virtual bool load(io_generic *io, uint32_t form_factor, const std::vector &variants, floppy_image *image) override; - virtual bool save(io_generic *io, const std::vector &variants, floppy_image *image) override; + virtual int identify(util::random_read &io, uint32_t form_factor, const std::vector &variants) override; + virtual bool load(util::random_read &io, uint32_t form_factor, const std::vector &variants, floppy_image *image) override; + virtual bool save(util::random_read_write &io, const std::vector &variants, floppy_image *image) override; virtual bool supports_save() const override; private: diff --git a/src/lib/formats/cassimg.cpp b/src/lib/formats/cassimg.cpp index cf5812c67c1..2fab4a1ec8b 100644 --- a/src/lib/formats/cassimg.cpp +++ b/src/lib/formats/cassimg.cpp @@ -199,12 +199,15 @@ cassette_image::error cassette_image::lookup_sample(int channel, size_t sample, -cassette_image::cassette_image(const Format *format, void *file, const io_procs *procs, int flags) +cassette_image::cassette_image(const Format *format, util::random_read_write::ptr &&io, int flags) : + m_format(format), + m_io(std::move(io)), + m_channels(0), + m_flags(flags), + m_sample_frequency(0), + m_blocks(), + m_sample_count(0) { - m_format = format; - m_io.file = file; - m_io.procs = procs; - m_flags = flags; } @@ -217,17 +220,24 @@ cassette_image::~cassette_image() -cassette_image::error cassette_image::open(void *file, const io_procs *procs, - const Format *format, int flags, ptr &outcassette) +cassette_image::error cassette_image::open( + util::random_read_write::ptr &&io, + const Format *format, + int flags, + ptr &outcassette) { const Format *const formats[2] = { format, nullptr }; - return open_choices(file, procs, {}, formats, flags, outcassette); + return open_choices(std::move(io), { }, formats, flags, outcassette); } -cassette_image::error cassette_image::open_choices(void *file, const io_procs *procs, const std::string &extension, - const Format *const *formats, int flags, ptr &outcassette) +cassette_image::error cassette_image::open_choices( + util::random_read_write::ptr &&io, + const std::string &extension, + const Format *const *formats, + int flags, + ptr &outcassette) { // if not specified, use the dummy arguments if (!formats) @@ -235,7 +245,7 @@ cassette_image::error cassette_image::open_choices(void *file, const io_procs *p // create the cassette object ptr cassette; - try { cassette.reset(new cassette_image(nullptr, file, procs, flags)); } + try { cassette.reset(new cassette_image(nullptr, std::move(io), flags)); } catch (std::bad_alloc const &) { return error::OUT_OF_MEMORY; } // identify the image @@ -275,8 +285,12 @@ cassette_image::error cassette_image::open_choices(void *file, const io_procs *p -cassette_image::error cassette_image::create(void *file, const io_procs *procs, const Format *format, - const Options *opts, int flags, ptr &outcassette) +cassette_image::error cassette_image::create( + util::random_read_write::ptr &&io, + const Format *format, + const Options *opts, + int flags, + ptr &outcassette) { static const Options default_options = { 1, 16, 44100 }; @@ -294,7 +308,7 @@ cassette_image::error cassette_image::create(void *file, const io_procs *procs, // create the cassette object ptr cassette; - try { cassette.reset(new cassette_image(format, file, procs, flags)); } + try { cassette.reset(new cassette_image(format, std::move(io), flags)); } catch (std::bad_alloc const &) { return error::OUT_OF_MEMORY; } // read the options @@ -334,13 +348,13 @@ cassette_image::Info cassette_image::get_info() const -void cassette_image::change(void *file, const io_procs *procs, const Format *format, int flags) +void cassette_image::change(util::random_read_write::ptr &&io, const Format *format, int flags) { - if ((flags & FLAG_READONLY) == 0) + if (!(flags & FLAG_READONLY)) flags |= CASSETTE_FLAG_DIRTY; - m_io.file = file; - m_io.procs = procs; + m_format = format; + m_io = std::move(io); m_flags = flags; } @@ -352,7 +366,8 @@ void cassette_image::change(void *file, const io_procs *procs, const Format *for void cassette_image::image_read(void *buffer, uint64_t offset, size_t length) { - io_generic_read(&m_io, buffer, offset, length); + size_t actual; + m_io->read_at(offset, buffer, length, actual); } @@ -360,7 +375,7 @@ void cassette_image::image_read(void *buffer, uint64_t offset, size_t length) uint8_t cassette_image::image_read_byte(uint64_t offset) { uint8_t data; - io_generic_read(&m_io, &data, offset, 1); + image_read(&data, offset, 1); return data; } @@ -368,14 +383,17 @@ uint8_t cassette_image::image_read_byte(uint64_t offset) void cassette_image::image_write(const void *buffer, uint64_t offset, size_t length) { - io_generic_write(&m_io, buffer, offset, length); + size_t actual; + m_io->write_at(offset, buffer, length, actual); } uint64_t cassette_image::image_size() { - return io_generic_size(&m_io); + uint64_t size = 0; + m_io->length(size); + return size; } @@ -900,20 +918,19 @@ done: void cassette_image::dump(const char *filename) { - FILE *f = fopen(filename, "wb"); - if (!f) + util::random_read_write::ptr saved_io = util::stdio_read_write(fopen(filename, "wb"), 0); + if (!saved_io) return; - io_generic saved_io = m_io; - const Format *saved_format = m_format; + Format const *const saved_format = m_format; - m_io.file = f; - m_io.procs = &stdio_ioprocs_noclose; + using std::swap; + + swap(m_io, saved_io); m_format = &wavfile_format; + perform_save(); - m_io = saved_io; + swap(m_io, saved_io); m_format = saved_format; - - fclose(f); } diff --git a/src/lib/formats/cassimg.h b/src/lib/formats/cassimg.h index 3a59870571a..765b860b659 100644 --- a/src/lib/formats/cassimg.h +++ b/src/lib/formats/cassimg.h @@ -185,14 +185,14 @@ public: void dump(const char *filename); error save(); - void change(void *file, const io_procs *procs, const Format *format, int flags); + void change(util::random_read_write::ptr &&io, const Format *format, int flags); Info get_info() const; - static error open(void *file, const io_procs *procs, + static error open(util::random_read_write::ptr &&io, const Format *format, int flags, ptr &outcassette); - static error open_choices(void *file, const io_procs *procs, const std::string &extension, + static error open_choices(util::random_read_write::ptr &&io, const std::string &extension, const Format *const *formats, int flags, ptr &outcassette); - static error create(void *file, const io_procs *procs, const cassette_image::Format *format, + static error create(util::random_read_write::ptr &&io, const cassette_image::Format *format, const cassette_image::Options *opts, int flags, ptr &outcassette); // builtin formats @@ -201,7 +201,7 @@ public: private: struct manipulation_ranges; - cassette_image(const Format *format, void *file, const io_procs *procs, int flags); + cassette_image(const Format *format, util::random_read_write::ptr &&io, int flags); cassette_image(const cassette_image &) = delete; cassette_image(cassette_image &&) = delete; cassette_image &operator=(const cassette_image &) = delete; @@ -212,15 +212,15 @@ private: error compute_manipulation_ranges(int channel, double time_index, double sample_period, manipulation_ranges &ranges) const; error lookup_sample(int channel, size_t sample, int32_t *&ptr); - const Format *m_format = nullptr; - io_generic m_io; + const Format *m_format; + util::random_read_write::ptr m_io; - int m_channels = 0; - int m_flags = 0; - uint32_t m_sample_frequency = 0; + int m_channels; + int m_flags; + uint32_t m_sample_frequency; std::vector > m_blocks; - size_t m_sample_count = 0; + size_t m_sample_count; }; /* macros for specifying format lists */ diff --git a/src/lib/formats/ccvf_dsk.cpp b/src/lib/formats/ccvf_dsk.cpp index bba52d3922a..6ed0c14038a 100644 --- a/src/lib/formats/ccvf_dsk.cpp +++ b/src/lib/formats/ccvf_dsk.cpp @@ -11,6 +11,7 @@ #include "formats/ccvf_dsk.h" #include "coretmpl.h" // BIT +#include "ioprocs.h" ccvf_format::ccvf_format() @@ -46,12 +47,12 @@ const ccvf_format::format ccvf_format::file_formats[] = { {} }; -int ccvf_format::identify(io_generic *io, uint32_t form_factor, const std::vector &variants) +int ccvf_format::identify(util::random_read &io, uint32_t form_factor, const std::vector &variants) { char h[36]; - - io_generic_read(io, h, 0, 36); - if(!memcmp(h, "Compucolor Virtual Floppy Disk Image", 36)) + size_t actual; + io.read_at(0, h, 36, actual); + if (!memcmp(h, "Compucolor Virtual Floppy Disk Image", 36)) return 100; return 0; @@ -87,13 +88,17 @@ floppy_image_format_t::desc_e* ccvf_format::get_desc_8n1(const format &f, int &c return desc; } -bool ccvf_format::load(io_generic *io, uint32_t form_factor, const std::vector &variants, floppy_image *image) +bool ccvf_format::load(util::random_read &io, uint32_t form_factor, const std::vector &variants, floppy_image *image) { const format &f = formats[0]; - uint64_t size = io_generic_size(io); + uint64_t size; + if (io.length(size)) + return false; + std::vector img(size); - io_generic_read(io, &img[0], 0, size); + size_t actual; + io.read_at(0, &img[0], size, actual); std::string ccvf = std::string((const char *)&img[0], size); std::vector bytes(78720); diff --git a/src/lib/formats/ccvf_dsk.h b/src/lib/formats/ccvf_dsk.h index 5895a882550..92f04e03ddd 100644 --- a/src/lib/formats/ccvf_dsk.h +++ b/src/lib/formats/ccvf_dsk.h @@ -39,8 +39,8 @@ public: virtual const char *description() const override; virtual const char *extensions() const override; - virtual int identify(io_generic *io, uint32_t form_factor, const std::vector &variants) override; - virtual bool load(io_generic *io, uint32_t form_factor, const std::vector &variants, floppy_image *image) override; + virtual int identify(util::random_read &io, uint32_t form_factor, const std::vector &variants) override; + virtual bool load(util::random_read &io, uint32_t form_factor, const std::vector &variants, floppy_image *image) override; virtual bool supports_save() const override; protected: diff --git a/src/lib/formats/concept_dsk.cpp b/src/lib/formats/concept_dsk.cpp index 67c8562e1c3..7f5edce3363 100644 --- a/src/lib/formats/concept_dsk.cpp +++ b/src/lib/formats/concept_dsk.cpp @@ -10,11 +10,11 @@ *********************************************************************/ -#include - -#include "flopimg.h" #include "formats/concept_dsk.h" +#include "ioprocs.h" + + /* 9 sectors / track, 512 bytes per sector */ const floppy_image_format_t::desc_e cc525dsdd_format::cc_9_desc[] = { { MFM, 0x4e, 80 }, @@ -72,50 +72,50 @@ bool cc525dsdd_format::supports_save() const return true; } -void cc525dsdd_format::find_size(io_generic *io, uint8_t &track_count, uint8_t &head_count, uint8_t §or_count) +void cc525dsdd_format::find_size(util::random_read &io, uint8_t &track_count, uint8_t &head_count, uint8_t §or_count) { - uint64_t size = io_generic_size(io); - track_count = 77; head_count = 2; sector_count = 9; - uint32_t expected_size = 512 * track_count*head_count*sector_count; - if (size == expected_size) - { + uint32_t const expected_size = 512 * track_count*head_count*sector_count; + + uint64_t size; + if (!io.length(size) && (size == expected_size)) return; - } track_count = head_count = sector_count = 0; } -int cc525dsdd_format::identify(io_generic *io, uint32_t form_factor, const std::vector &variants) +int cc525dsdd_format::identify(util::random_read &io, uint32_t form_factor, const std::vector &variants) { uint8_t track_count, head_count, sector_count; find_size(io, track_count, head_count, sector_count); - if(track_count) + if (track_count) return 50; + return 0; } -bool cc525dsdd_format::load(io_generic *io, uint32_t form_factor, const std::vector &variants, floppy_image *image) +bool cc525dsdd_format::load(util::random_read &io, uint32_t form_factor, const std::vector &variants, floppy_image *image) { uint8_t track_count, head_count, sector_count; find_size(io, track_count, head_count, sector_count); uint8_t sectdata[10*512]; desc_s sectors[10]; - for(int i=0; i &variants, floppy_image *image) +bool cc525dsdd_format::save(util::random_read_write &io, const std::vector &variants, floppy_image *image) { int track_count, head_count, sector_count; get_geometry_mfm_pc(image, 2000, track_count, head_count, sector_count); - if(track_count != 77) + if (track_count != 77) track_count = 77; // Happens for a fully unformatted floppy - if(!head_count) + if (!head_count) head_count = 2; - if(sector_count != 9) + if (sector_count != 9) sector_count = 9; uint8_t sectdata[9*512]; int track_size = sector_count*512; - for(int track=0; track < track_count; track++) { - for(int head=0; head < head_count; head++) { + for (int track=0; track < track_count; track++) { + for (int head=0; head < head_count; head++) { get_track_data_mfm_pc(track, head, image, 2000, 512, sector_count, sectdata); - io_generic_write(io, sectdata, (track*head_count + head)*track_size, track_size); + size_t actual; + io.write_at((track*head_count + head)*track_size, sectdata, track_size, actual); } } diff --git a/src/lib/formats/concept_dsk.h b/src/lib/formats/concept_dsk.h index 58d4e1c52b3..36e3f790a84 100644 --- a/src/lib/formats/concept_dsk.h +++ b/src/lib/formats/concept_dsk.h @@ -17,9 +17,9 @@ class cc525dsdd_format : public floppy_image_format_t public: cc525dsdd_format(); - virtual int identify(io_generic *io, uint32_t form_factor, const std::vector &variants) override; - virtual bool load(io_generic *io, uint32_t form_factor, const std::vector &variants, floppy_image *image) override; - virtual bool save(io_generic *io, const std::vector &variants, floppy_image *image) override; + virtual int identify(util::random_read &io, uint32_t form_factor, const std::vector &variants) override; + virtual bool load(util::random_read &io, uint32_t form_factor, const std::vector &variants, floppy_image *image) override; + virtual bool save(util::random_read_write &io, const std::vector &variants, floppy_image *image) override; virtual const char *name() const override; virtual const char *description() const override; @@ -29,7 +29,7 @@ public: static const desc_e cc_9_desc[]; private: - void find_size(io_generic *io, uint8_t &track_count, uint8_t &head_count, uint8_t §or_count); + void find_size(util::random_read &io, uint8_t &track_count, uint8_t &head_count, uint8_t §or_count); }; extern const floppy_format_type FLOPPY_CONCEPT_525DSDD_FORMAT; diff --git a/src/lib/formats/coupedsk.cpp b/src/lib/formats/coupedsk.cpp index 16842583855..9400cd41bb6 100644 --- a/src/lib/formats/coupedsk.cpp +++ b/src/lib/formats/coupedsk.cpp @@ -8,10 +8,10 @@ **************************************************************************/ -#include +#include "coupedsk.h" + +#include "ioprocs.h" -#include "formats/coupedsk.h" -#include "flopimg.h" const floppy_image_format_t::desc_e mgt_format::desc_10[] = { { MFM, 0x4e, 60 }, @@ -64,9 +64,11 @@ bool mgt_format::supports_save() const return true; } -int mgt_format::identify(io_generic *io, uint32_t form_factor, const std::vector &variants) +int mgt_format::identify(util::random_read &io, uint32_t form_factor, const std::vector &variants) { - uint64_t size = io_generic_size(io); + uint64_t size; + if(io.length(size)) + return 0; if(/*size == 737280 || */ size == 819200) return 50; @@ -74,10 +76,12 @@ int mgt_format::identify(io_generic *io, uint32_t form_factor, const std::vector return 0; } -bool mgt_format::load(io_generic *io, uint32_t form_factor, const std::vector &variants, floppy_image *image) +bool mgt_format::load(util::random_read &io, uint32_t form_factor, const std::vector &variants, floppy_image *image) { - uint64_t size = io_generic_size(io); - int sector_count = size == 737280 ? 9 : 10; + uint64_t size; + if(io.length(size)) + return false; + int const sector_count = (size == 737280) ? 9 : 10; uint8_t sectdata[10*512]; desc_s sectors[10]; @@ -90,7 +94,8 @@ bool mgt_format::load(io_generic *io, uint32_t form_factor, const std::vector &variants, floppy_image *image) +bool mgt_format::save(util::random_read_write &io, const std::vector &variants, floppy_image *image) { int track_count, head_count, sector_count; get_geometry_mfm_pc(image, 2000, track_count, head_count, sector_count); @@ -115,7 +120,8 @@ bool mgt_format::save(io_generic *io, const std::vector &variants, flo for(int head=0; head < 2; head++) { for(int track=0; track < 80; track++) { get_track_data_mfm_pc(track, head, image, 2000, 512, sector_count, sectdata); - io_generic_write(io, sectdata, (track*2+head)*track_size, track_size); + size_t actual; + io.write_at((track*2+head)*track_size, sectdata, track_size, actual); } } diff --git a/src/lib/formats/coupedsk.h b/src/lib/formats/coupedsk.h index 3700d3e9974..e9ef4b118ca 100644 --- a/src/lib/formats/coupedsk.h +++ b/src/lib/formats/coupedsk.h @@ -19,9 +19,9 @@ class mgt_format : public floppy_image_format_t public: mgt_format(); - virtual int identify(io_generic *io, uint32_t form_factor, const std::vector &variants) override; - virtual bool load(io_generic *io, uint32_t form_factor, const std::vector &variants, floppy_image *image) override; - virtual bool save(io_generic *io, const std::vector &variants, floppy_image *image) override; + virtual int identify(util::random_read &io, uint32_t form_factor, const std::vector &variants) override; + virtual bool load(util::random_read &io, uint32_t form_factor, const std::vector &variants, floppy_image *image) override; + virtual bool save(util::random_read_write &io, const std::vector &variants, floppy_image *image) override; virtual const char *name() const override; virtual const char *description() const override; diff --git a/src/lib/formats/cqm_dsk.cpp b/src/lib/formats/cqm_dsk.cpp index 5f79a4d3694..6639e50f801 100644 --- a/src/lib/formats/cqm_dsk.cpp +++ b/src/lib/formats/cqm_dsk.cpp @@ -8,9 +8,12 @@ *********************************************************************/ +#include "cqm_dsk.h" + +#include "ioprocs.h" + #include -#include -#include "flopimg.h" + #define CQM_HEADER_SIZE 133 @@ -231,17 +234,6 @@ FLOPPY_CONSTRUCT( cqm_dsk_construct ) - -/********************************************************************* - - formats/cqm_dsk.c - - CopyQM disk images - -*********************************************************************/ - -#include "cqm_dsk.h" - cqm_format::cqm_format() { } @@ -261,10 +253,11 @@ const char *cqm_format::extensions() const return "cqm,cqi,dsk"; } -int cqm_format::identify(io_generic *io, uint32_t form_factor, const std::vector &variants) +int cqm_format::identify(util::random_read &io, uint32_t form_factor, const std::vector &variants) { uint8_t h[3]; - io_generic_read(io, h, 0, 3); + size_t actual; + io.read_at(0, h, 3, actual); if (h[0] == 'C' && h[1] == 'Q' && h[2] == 0x14) return 100; @@ -272,12 +265,13 @@ int cqm_format::identify(io_generic *io, uint32_t form_factor, const std::vector return 0; } -bool cqm_format::load(io_generic *io, uint32_t form_factor, const std::vector &variants, floppy_image *image) +bool cqm_format::load(util::random_read &io, uint32_t form_factor, const std::vector &variants, floppy_image *image) { + size_t actual; const int max_size = 4*1024*1024; // 4MB ought to be large enough for any floppy std::vector imagebuf(max_size); uint8_t header[CQM_HEADER_SIZE]; - io_generic_read(io, header, 0, CQM_HEADER_SIZE); + io.read_at(0, header, CQM_HEADER_SIZE, actual); int sector_size = (header[0x04] << 8) | header[0x03]; int sector_per_track = (header[0x11] << 8) | header[0x10]; @@ -318,9 +312,11 @@ bool cqm_format::load(io_generic *io, uint32_t form_factor, const std::vector= 300000) ? 360 : 300; int base_cell_count = rate*60/rpm; - int cqm_size = io_generic_size(io); + uint64_t cqm_size; + if (io.length(cqm_size)) + return false; std::vector cqmbuf(cqm_size); - io_generic_read(io, &cqmbuf[0], 0, cqm_size); + io.read_at(0, &cqmbuf[0], cqm_size, actual); // decode the RLE data for (int s = 0, pos = CQM_HEADER_SIZE + comment_size; pos < cqm_size; ) @@ -369,7 +365,7 @@ bool cqm_format::load(io_generic *io, uint32_t form_factor, const std::vector &variants, floppy_image *image) +bool cqm_format::save(util::random_read_write &io, const std::vector &variants, floppy_image *image) { return false; } diff --git a/src/lib/formats/cqm_dsk.h b/src/lib/formats/cqm_dsk.h index 183c0b83e68..fc8376a2b85 100644 --- a/src/lib/formats/cqm_dsk.h +++ b/src/lib/formats/cqm_dsk.h @@ -19,9 +19,9 @@ class cqm_format : public floppy_image_format_t public: cqm_format(); - virtual int identify(io_generic *io, uint32_t form_factor, const std::vector &variants) override; - virtual bool load(io_generic *io, uint32_t form_factor, const std::vector &variants, floppy_image *image) override; - virtual bool save(io_generic *io, const std::vector &variants, floppy_image *image) override; + virtual int identify(util::random_read &io, uint32_t form_factor, const std::vector &variants) override; + virtual bool load(util::random_read &io, uint32_t form_factor, const std::vector &variants, floppy_image *image) override; + virtual bool save(util::random_read_write &io, const std::vector &variants, floppy_image *image) override; virtual const char *name() const override; virtual const char *description() const override; diff --git a/src/lib/formats/d64_dsk.cpp b/src/lib/formats/d64_dsk.cpp index 4819ecc68d2..149130f0b3c 100644 --- a/src/lib/formats/d64_dsk.cpp +++ b/src/lib/formats/d64_dsk.cpp @@ -12,6 +12,8 @@ #include "formats/d64_dsk.h" +#include "ioprocs.h" + d64_format::d64_format() { @@ -79,9 +81,12 @@ const int d64_format::speed_zone[] = 0, 0 // 41-42 }; -int d64_format::find_size(io_generic *io, uint32_t form_factor) const +int d64_format::find_size(util::random_read &io, uint32_t form_factor) const { - uint64_t size = io_generic_size(io); + uint64_t size; + if(io.length(size)) + return 0; + for(int i=0; formats[i].sector_count; i++) { const format &f = formats[i]; if(size == (uint32_t) f.sector_count*f.sector_base_size*f.head_count) @@ -89,12 +94,13 @@ int d64_format::find_size(io_generic *io, uint32_t form_factor) const if(size == (uint32_t) (f.sector_count*f.sector_base_size*f.head_count) + f.sector_count) return i; } + return -1; } -int d64_format::identify(io_generic *io, uint32_t form_factor, const std::vector &variants) +int d64_format::identify(util::random_read &io, uint32_t form_factor, const std::vector &variants) { - int type = find_size(io, form_factor); + const int type = find_size(io, form_factor); if (type != -1) return 50; @@ -114,10 +120,11 @@ int d64_format::get_disk_id_offset(const format &f) return 0x165a2; } -void d64_format::get_disk_id(const format &f, io_generic *io, uint8_t &id1, uint8_t &id2) +void d64_format::get_disk_id(const format &f, util::random_read &io, uint8_t &id1, uint8_t &id2) { uint8_t id[2]; - io_generic_read(io, id, get_disk_id_offset(f), 2); + size_t actual; + io.read_at(get_disk_id_offset(f), id, 2, actual); id1 = id[0]; id2 = id[1]; } @@ -206,7 +213,7 @@ void d64_format::fix_end_gap(floppy_image_format_t::desc_e* desc, int remaining_ desc[22].p1 >>= remaining_size & 0x01; } -bool d64_format::load(io_generic *io, uint32_t form_factor, const std::vector &variants, floppy_image *image) +bool d64_format::load(util::random_read &io, uint32_t form_factor, const std::vector &variants, floppy_image *image) { int type = find_size(io, form_factor); if(type == -1) @@ -214,7 +221,9 @@ bool d64_format::load(io_generic *io, uint32_t form_factor, const std::vector img; if(size == (uint32_t)f.sector_count*f.sector_base_size) { @@ -225,7 +234,8 @@ bool d64_format::load(io_generic *io, uint32_t form_factor, const std::vector &variants, floppy_image *image) +bool d64_format::save(util::random_read_write &io, const std::vector &variants, floppy_image *image) { const format &f = formats[0]; @@ -280,7 +290,8 @@ bool d64_format::save(io_generic *io, const std::vector &variants, flo build_sector_description(f, sectdata, 0, 0, sectors, sector_count); extract_sectors(image, f, sectors, track, head, sector_count); - io_generic_write(io, sectdata, offset, track_size); + size_t actual; + io.write_at(offset, sectdata, track_size, actual); } } diff --git a/src/lib/formats/d64_dsk.h b/src/lib/formats/d64_dsk.h index 665f6489a81..13f1bd4e91c 100644 --- a/src/lib/formats/d64_dsk.h +++ b/src/lib/formats/d64_dsk.h @@ -37,9 +37,9 @@ public: virtual const char *description() const override; virtual const char *extensions() const override; - virtual int identify(io_generic *io, uint32_t form_factor, const std::vector &variants) override; - virtual bool load(io_generic *io, uint32_t form_factor, const std::vector &variants, floppy_image *image) override; - virtual bool save(io_generic *io, const std::vector &variants, floppy_image *image) override; + virtual int identify(util::random_read &io, uint32_t form_factor, const std::vector &variants) override; + virtual bool load(util::random_read &io, uint32_t form_factor, const std::vector &variants, floppy_image *image) override; + virtual bool save(util::random_read_write &io, const std::vector &variants, floppy_image *image) override; virtual bool supports_save() const override { return true; } protected: @@ -61,12 +61,12 @@ protected: const format *formats; - int find_size(io_generic *io, uint32_t form_factor) const; + int find_size(util::random_read &io, uint32_t form_factor) const; virtual int get_physical_track(const format &f, int head, int track); virtual uint32_t get_cell_size(const format &f, int track); virtual int get_sectors_per_track(const format &f, int track); virtual int get_disk_id_offset(const format &f); - void get_disk_id(const format &f, io_generic *io, uint8_t &id1, uint8_t &id2); + void get_disk_id(const format &f, util::random_read &io, uint8_t &id1, uint8_t &id2); virtual int get_image_offset(const format &f, int head, int track); int compute_track_size(const format &f, int track); virtual int get_gap2(const format &f, int head, int track) { return f.gap_2; } diff --git a/src/lib/formats/d80_dsk.cpp b/src/lib/formats/d80_dsk.cpp index d350411b159..338f00292a9 100644 --- a/src/lib/formats/d80_dsk.cpp +++ b/src/lib/formats/d80_dsk.cpp @@ -8,10 +8,11 @@ *********************************************************************/ -#include - #include "formats/d80_dsk.h" +#include "ioprocs.h" + + d80_format::d80_format() : d64_format(file_formats), formats(nullptr) { } diff --git a/src/lib/formats/d88_dsk.cpp b/src/lib/formats/d88_dsk.cpp index 7c4eaa079dc..6e29f10df6a 100644 --- a/src/lib/formats/d88_dsk.cpp +++ b/src/lib/formats/d88_dsk.cpp @@ -29,11 +29,12 @@ * */ - #include - #include "flopimg.h" #include "imageutl.h" +#include "ioprocs.h" + + #define D88_HEADER_LEN 0x2b0 struct d88_tag @@ -414,12 +415,15 @@ const char *d88_format::extensions() const return "d77,d88,1dd"; } -int d88_format::identify(io_generic *io, uint32_t form_factor, const std::vector &variants) +int d88_format::identify(util::random_read &io, uint32_t form_factor, const std::vector &variants) { - uint64_t size = io_generic_size(io); - uint8_t h[32]; + uint64_t size; + if(io.length(size)) + return 0; - io_generic_read(io, h, 0, 32); + uint8_t h[32]; + size_t actual; + io.read_at(0, h, 32, actual); if((little_endianize_int32(*(uint32_t *)(h+0x1c)) == size) && (h[0x1b] == 0x00 || h[0x1b] == 0x10 || h[0x1b] == 0x20 || h[0x1b] == 0x30 || h[0x1b] == 0x40)) return 100; @@ -427,11 +431,12 @@ int d88_format::identify(io_generic *io, uint32_t form_factor, const std::vector return 0; } -bool d88_format::load(io_generic *io, uint32_t form_factor, const std::vector &variants, floppy_image *image) +bool d88_format::load(util::random_read &io, uint32_t form_factor, const std::vector &variants, floppy_image *image) { - uint8_t h[32]; + size_t actual; - io_generic_read(io, h, 0, 32); + uint8_t h[32]; + io.read_at(0, h, 32, actual); int cell_count = 0; int track_count = 0; @@ -477,9 +482,11 @@ bool d88_format::load(io_generic *io, uint32_t form_factor, const std::vector &variants, floppy_image *image) +bool d88_format::save(util::random_read_write &io, const std::vector &variants, floppy_image *image) { return false; } diff --git a/src/lib/formats/d88_dsk.h b/src/lib/formats/d88_dsk.h index c7c85fc1949..aeed5ed16e8 100644 --- a/src/lib/formats/d88_dsk.h +++ b/src/lib/formats/d88_dsk.h @@ -20,9 +20,9 @@ class d88_format : public floppy_image_format_t public: d88_format(); - virtual int identify(io_generic *io, uint32_t form_factor, const std::vector &variants) override; - virtual bool load(io_generic *io, uint32_t form_factor, const std::vector &variants, floppy_image *image) override; - virtual bool save(io_generic *io, const std::vector &variants, floppy_image *image) override; + virtual int identify(util::random_read &io, uint32_t form_factor, const std::vector &variants) override; + virtual bool load(util::random_read &io, uint32_t form_factor, const std::vector &variants, floppy_image *image) override; + virtual bool save(util::random_read_write &io, const std::vector &variants, floppy_image *image) override; virtual const char *name() const override; virtual const char *description() const override; diff --git a/src/lib/formats/dcp_dsk.cpp b/src/lib/formats/dcp_dsk.cpp index b3beb40404f..7d419628bdc 100644 --- a/src/lib/formats/dcp_dsk.cpp +++ b/src/lib/formats/dcp_dsk.cpp @@ -20,10 +20,11 @@ *********************************************************************/ -#include - #include "dcp_dsk.h" +#include "ioprocs.h" + + dcp_format::dcp_format() { } @@ -43,14 +44,18 @@ const char *dcp_format::extensions() const return "dcp,dcu"; } -int dcp_format::identify(io_generic *io, uint32_t form_factor, const std::vector &variants) +int dcp_format::identify(util::random_read &io, uint32_t form_factor, const std::vector &variants) { - uint64_t size = io_generic_size(io); + uint64_t size; + if (io.length(size)) + return 0; + uint8_t h[0xa2]; int heads, tracks, spt, bps, count_tracks = 0; bool is_hdb = false; - io_generic_read(io, h, 0, 0xa2); + size_t actual; + io.read_at(0, h, 0xa2, actual); // First byte is the disk format (see below in load() for details) switch (h[0]) @@ -112,13 +117,14 @@ int dcp_format::identify(io_generic *io, uint32_t form_factor, const std::vector return 0; } -bool dcp_format::load(io_generic *io, uint32_t form_factor, const std::vector &variants, floppy_image *image) +bool dcp_format::load(util::random_read &io, uint32_t form_factor, const std::vector &variants, floppy_image *image) { + size_t actual; uint8_t h[0xa2]; int heads, tracks, spt, bps; bool is_hdb = false; - io_generic_read(io, h, 0, 0xa2); + io.read_at(0, h, 0xa2, actual); // First byte is the disk format: switch (h[0]) @@ -215,7 +221,7 @@ bool dcp_format::load(io_generic *io, uint32_t form_factor, const std::vector &variants) override; - virtual bool load(io_generic *io, uint32_t form_factor, const std::vector &variants, floppy_image *image) override; + virtual int identify(util::random_read &io, uint32_t form_factor, const std::vector &variants) override; + virtual bool load(util::random_read &io, uint32_t form_factor, const std::vector &variants, floppy_image *image) override; virtual const char *name() const override; virtual const char *description() const override; diff --git a/src/lib/formats/dfi_dsk.cpp b/src/lib/formats/dfi_dsk.cpp index 409797e9583..607be56f741 100644 --- a/src/lib/formats/dfi_dsk.cpp +++ b/src/lib/formats/dfi_dsk.cpp @@ -13,7 +13,8 @@ #include "dfi_dsk.h" -#include +#include "ioprocs.h" + #define NUMBER_OF_MULTIREADS 3 // thresholds for brickwall windowing @@ -56,24 +57,28 @@ bool dfi_format::supports_save() const return false; } -int dfi_format::identify(io_generic *io, uint32_t form_factor, const std::vector &variants) +int dfi_format::identify(util::random_read &io, uint32_t form_factor, const std::vector &variants) { char sign[4]; - io_generic_read(io, sign, 0, 4); + size_t actual; + io.read_at(0, sign, 4, actual); return memcmp(sign, "DFE2", 4) ? 0 : 100; } -bool dfi_format::load(io_generic *io, uint32_t form_factor, const std::vector &variants, floppy_image *image) +bool dfi_format::load(util::random_read &io, uint32_t form_factor, const std::vector &variants, floppy_image *image) { + size_t actual; char sign[4]; - io_generic_read(io, sign, 0, 4); - if (memcmp(sign, "DFER", 4) == 0) - { + io.read_at(0, sign, 4, actual); + if(memcmp(sign, "DFER", 4) == 0) { osd_printf_error("dfi_dsk: Old type Discferret image detected; the mess Discferret decoder will not handle this properly, bailing out!\n"); return false; } - uint64_t size = io_generic_size(io); + uint64_t size; + if(io.length(size)) + return false; + uint64_t pos = 4; std::vector data; int onerev_time = 0; // time for one revolution, used to guess clock and rpm for DFE2 files @@ -81,7 +86,7 @@ bool dfi_format::load(io_generic *io, uint32_t form_factor, const std::vector &variants) override; - virtual bool load(io_generic *io, uint32_t form_factor, const std::vector &variants, floppy_image *image) override; - // virtual bool save(io_generic *io, const std::vector &variants, floppy_image *image); + virtual int identify(util::random_read &io, uint32_t form_factor, const std::vector &variants) override; + virtual bool load(util::random_read &io, uint32_t form_factor, const std::vector &variants, floppy_image *image) override; + // virtual bool save(util::random_read_write &io, const std::vector &variants, floppy_image *image); virtual const char *name() const override; virtual const char *description() const override; diff --git a/src/lib/formats/dim_dsk.cpp b/src/lib/formats/dim_dsk.cpp index 964f19ce028..04f6e3b8995 100644 --- a/src/lib/formats/dim_dsk.cpp +++ b/src/lib/formats/dim_dsk.cpp @@ -8,12 +8,14 @@ *********************************************************************/ -#include -#include - #include "dim_dsk.h" #include "basicdsk.h" +#include "ioprocs.h" + +#include + + FLOPPY_IDENTIFY(dim_dsk_identify) { uint8_t dim_header[16]; @@ -132,11 +134,12 @@ const char *dim_format::extensions() const return "dim"; } -int dim_format::identify(io_generic *io, uint32_t form_factor, const std::vector &variants) +int dim_format::identify(util::random_read &io, uint32_t form_factor, const std::vector &variants) { uint8_t h[16]; - io_generic_read(io, h, 0xab, 16); + size_t actual; + io.read_at(0xab, h, 16, actual); if(strncmp((const char *)h, "DIFC HEADER", 11) == 0) return 100; @@ -144,14 +147,15 @@ int dim_format::identify(io_generic *io, uint32_t form_factor, const std::vector return 0; } -bool dim_format::load(io_generic *io, uint32_t form_factor, const std::vector &variants, floppy_image *image) +bool dim_format::load(util::random_read &io, uint32_t form_factor, const std::vector &variants, floppy_image *image) { + size_t actual; int offset = 0x100; uint8_t h; uint8_t track_total = 77; int cell_count = form_factor == floppy_image::FF_35 ? 200000 : 166666; - io_generic_read(io, &h, 0, 1); + io.read_at(0, &h, 1, actual); int spt, gap3, bps, size; switch(h) { @@ -211,7 +215,7 @@ bool dim_format::load(io_generic *io, uint32_t form_factor, const std::vector &variants, floppy_image *image) +bool dim_format::save(util::random_read_write &io, const std::vector &variants, floppy_image *image) { return false; } diff --git a/src/lib/formats/dim_dsk.h b/src/lib/formats/dim_dsk.h index e0227e2e221..5c84f329cb6 100644 --- a/src/lib/formats/dim_dsk.h +++ b/src/lib/formats/dim_dsk.h @@ -25,9 +25,9 @@ class dim_format : public floppy_image_format_t public: dim_format(); - virtual int identify(io_generic *io, uint32_t form_factor, const std::vector &variants) override; - virtual bool load(io_generic *io, uint32_t form_factor, const std::vector &variants, floppy_image *image) override; - virtual bool save(io_generic *io, const std::vector &variants, floppy_image *image) override; + virtual int identify(util::random_read &io, uint32_t form_factor, const std::vector &variants) override; + virtual bool load(util::random_read &io, uint32_t form_factor, const std::vector &variants, floppy_image *image) override; + virtual bool save(util::random_read_write &io, const std::vector &variants, floppy_image *image) override; virtual const char *name() const override; virtual const char *description() const override; diff --git a/src/lib/formats/dip_dsk.cpp b/src/lib/formats/dip_dsk.cpp index a33d6fe35d6..17a7f856efe 100644 --- a/src/lib/formats/dip_dsk.cpp +++ b/src/lib/formats/dip_dsk.cpp @@ -14,10 +14,11 @@ *********************************************************************/ -#include - #include "dip_dsk.h" +#include "ioprocs.h" + + dip_format::dip_format() { } @@ -37,9 +38,11 @@ const char *dip_format::extensions() const return "dip"; } -int dip_format::identify(io_generic *io, uint32_t form_factor, const std::vector &variants) +int dip_format::identify(util::random_read &io, uint32_t form_factor, const std::vector &variants) { - uint64_t size = io_generic_size(io); + uint64_t size; + if (io.length(size)) + return 0; if (size == 0x134000 + 0x100) return 100; @@ -47,7 +50,7 @@ int dip_format::identify(io_generic *io, uint32_t form_factor, const std::vector return 0; } -bool dip_format::load(io_generic *io, uint32_t form_factor, const std::vector &variants, floppy_image *image) +bool dip_format::load(util::random_read &io, uint32_t form_factor, const std::vector &variants, floppy_image *image) { int heads, tracks, spt, bps; @@ -69,7 +72,8 @@ bool dip_format::load(io_generic *io, uint32_t form_factor, const std::vector &variants) override; - virtual bool load(io_generic *io, uint32_t form_factor, const std::vector &variants, floppy_image *image) override; + virtual int identify(util::random_read &io, uint32_t form_factor, const std::vector &variants) override; + virtual bool load(util::random_read &io, uint32_t form_factor, const std::vector &variants, floppy_image *image) override; virtual const char *name() const override; virtual const char *description() const override; diff --git a/src/lib/formats/dmk_dsk.cpp b/src/lib/formats/dmk_dsk.cpp index 39c23223ec5..6a9e1dc0f0b 100644 --- a/src/lib/formats/dmk_dsk.cpp +++ b/src/lib/formats/dmk_dsk.cpp @@ -13,10 +13,10 @@ TODO: *********************************************************************/ -#include - #include "dmk_dsk.h" +#include "ioprocs.h" + dmk_format::dmk_format() { @@ -41,14 +41,16 @@ const char *dmk_format::extensions() const } -int dmk_format::identify(io_generic *io, uint32_t form_factor, const std::vector &variants) +int dmk_format::identify(util::random_read &io, uint32_t form_factor, const std::vector &variants) { + uint64_t size; + if (io.length(size)) + return 0; + const int header_size = 16; uint8_t header[header_size]; - - uint64_t size = io_generic_size(io); - - io_generic_read(io, header, 0, header_size); + size_t actual; + io.read_at(0, header, header_size, actual); int tracks = header[1]; int track_size = ( header[3] << 8 ) | header[2]; @@ -81,12 +83,13 @@ int dmk_format::identify(io_generic *io, uint32_t form_factor, const std::vector } -bool dmk_format::load(io_generic *io, uint32_t form_factor, const std::vector &variants, floppy_image *image) +bool dmk_format::load(util::random_read &io, uint32_t form_factor, const std::vector &variants, floppy_image *image) { + size_t actual; + const int header_size = 16; uint8_t header[header_size]; - - io_generic_read(io, header, 0, header_size); + io.read_at(0, header, header_size, actual); const int tracks = header[1]; const int track_size = ( header[3] << 8 ) | header[2]; @@ -128,7 +131,7 @@ bool dmk_format::load(io_generic *io, uint32_t form_factor, const std::vector &variants, floppy_image *image) +bool dmk_format::save(util::random_read_write &io, const std::vector &variants, floppy_image *image) { return false; } diff --git a/src/lib/formats/dmk_dsk.h b/src/lib/formats/dmk_dsk.h index a2e7898dece..5485869b5b6 100644 --- a/src/lib/formats/dmk_dsk.h +++ b/src/lib/formats/dmk_dsk.h @@ -21,9 +21,9 @@ class dmk_format : public floppy_image_format_t public: dmk_format(); - virtual int identify(io_generic *io, uint32_t form_factor, const std::vector &variants) override; - virtual bool load(io_generic *io, uint32_t form_factor, const std::vector &variants, floppy_image *image) override; - virtual bool save(io_generic *io, const std::vector &variants, floppy_image *image) override; + virtual int identify(util::random_read &io, uint32_t form_factor, const std::vector &variants) override; + virtual bool load(util::random_read &io, uint32_t form_factor, const std::vector &variants, floppy_image *image) override; + virtual bool save(util::random_read_write &io, const std::vector &variants, floppy_image *image) override; virtual const char *name() const override; virtual const char *description() const override; diff --git a/src/lib/formats/ds9_dsk.cpp b/src/lib/formats/ds9_dsk.cpp index fdf4f5e2299..c97a2cced51 100644 --- a/src/lib/formats/ds9_dsk.cpp +++ b/src/lib/formats/ds9_dsk.cpp @@ -14,10 +14,10 @@ ************************************************************************/ -#include - #include "formats/ds9_dsk.h" +#include "ioprocs.h" + static FLOPPY_IDENTIFY(ds9_dsk_identify) { @@ -97,33 +97,32 @@ const char *ds9_format::extensions() const return "ds9"; } -void ds9_format::find_size(io_generic *io, uint8_t &track_count, uint8_t &head_count, uint8_t §or_count) +void ds9_format::find_size(util::random_read &io, uint8_t &track_count, uint8_t &head_count, uint8_t §or_count) { - uint32_t expected_size = 0; - uint64_t size = io_generic_size(io); - head_count = 2; track_count = 80; sector_count = 21; - expected_size = 256 * track_count * head_count * sector_count; + uint32_t const expected_size = 256 * track_count * head_count * sector_count; - if (size >= expected_size) // standard format has 860160 bytes + uint64_t size; + if (!io.length(size) && (size >= expected_size)) // standard format has 860160 bytes return; track_count = head_count = sector_count = 0; } -int ds9_format::identify(io_generic *io, uint32_t form_factor, const std::vector &variants) +int ds9_format::identify(util::random_read &io, uint32_t form_factor, const std::vector &variants) { uint8_t track_count, head_count, sector_count; find_size(io, track_count, head_count, sector_count); - if (track_count) return 50; + if (track_count) + return 50; return 0; } -bool ds9_format::load(io_generic *io, uint32_t form_factor, const std::vector &variants, floppy_image *image) +bool ds9_format::load(util::random_read &io, uint32_t form_factor, const std::vector &variants, floppy_image *image) { uint8_t track_count, head_count, sector_count; find_size(io, track_count, head_count, sector_count); @@ -143,7 +142,8 @@ bool ds9_format::load(io_generic *io, uint32_t form_factor, const std::vector &variants) override; - virtual bool load(io_generic *io, uint32_t form_factor, const std::vector &variants, floppy_image *image) override; + virtual int identify(util::random_read &io, uint32_t form_factor, const std::vector &variants) override; + virtual bool load(util::random_read &io, uint32_t form_factor, const std::vector &variants, floppy_image *image) override; virtual const char *name() const override; virtual const char *description() const override; @@ -30,9 +31,9 @@ public: static const desc_e ds9_desc[]; private: - void find_size(io_generic *io, uint8_t &track_count, uint8_t &head_count, uint8_t §or_count); + void find_size(util::random_read &io, uint8_t &track_count, uint8_t &head_count, uint8_t §or_count); }; extern const floppy_format_type FLOPPY_DS9_FORMAT; -#endif /* DS9_DSK_H_ */ +#endif // MAME_FORMATS_DS9_DSK_H diff --git a/src/lib/formats/dsk_dsk.cpp b/src/lib/formats/dsk_dsk.cpp index dba11347887..fcf967edcb1 100644 --- a/src/lib/formats/dsk_dsk.cpp +++ b/src/lib/formats/dsk_dsk.cpp @@ -8,11 +8,12 @@ *********************************************************************/ -#include -#include - +#include "dsk_dsk.h" #include "imageutl.h" -#include "flopimg.h" + +#include "ioprocs.h" + +#include #define MV_CPC "MV - CPC" #define EXTENDED "EXTENDED" @@ -270,7 +271,8 @@ FLOPPY_CONSTRUCT( dsk_dsk_construct ) return FLOPPY_ERROR_SUCCESS; } -#include "dsk_dsk.h" + + #define DSK_FORMAT_HEADER "MV - CPC" #define EXT_FORMAT_HEADER "EXTENDED CPC DSK" @@ -299,11 +301,12 @@ bool dsk_format::supports_save() const return false; } -int dsk_format::identify(io_generic *io, uint32_t form_factor, const std::vector &variants) +int dsk_format::identify(util::random_read &io, uint32_t form_factor, const std::vector &variants) { uint8_t header[16]; - io_generic_read(io, &header, 0, sizeof(header)); + size_t actual; + io.read_at(0, &header, sizeof(header), actual); if ( memcmp( header, DSK_FORMAT_HEADER, 8 ) ==0) { return 100; } @@ -344,14 +347,18 @@ struct sector_header #pragma pack() -bool dsk_format::load(io_generic *io, uint32_t form_factor, const std::vector &variants, floppy_image *image) +bool dsk_format::load(util::random_read &io, uint32_t form_factor, const std::vector &variants, floppy_image *image) { + size_t actual; + uint8_t header[0x100]; bool extendformat = false; - uint64_t image_size = io_generic_size(io); + uint64_t image_size; + if (io.length(image_size)) + return false; - io_generic_read(io, &header, 0, sizeof(header)); + io.read_at(0, &header, sizeof(header), actual); if ( memcmp( header, EXT_FORMAT_HEADER, 16 ) ==0) { extendformat = true; } @@ -418,7 +425,7 @@ bool dsk_format::load(io_generic *io, uint32_t form_factor, const std::vector= image_size) continue; track_header tr; - io_generic_read(io, &tr,track_offsets[(track<<1)+side],sizeof(tr)); + io.read_at(track_offsets[(track<<1)+side], &tr, sizeof(tr), actual); // skip if there are no sectors in this track if (tr.number_of_sector == 0) @@ -428,7 +435,7 @@ bool dsk_format::load(io_generic *io, uint32_t form_factor, const std::vector &variants) override; - virtual bool load(io_generic *io, uint32_t form_factor, const std::vector &variants, floppy_image *image) override; + virtual int identify(util::random_read &io, uint32_t form_factor, const std::vector &variants) override; + virtual bool load(util::random_read &io, uint32_t form_factor, const std::vector &variants, floppy_image *image) override; virtual const char *name() const override; virtual const char *description() const override; diff --git a/src/lib/formats/dvk_mx_dsk.cpp b/src/lib/formats/dvk_mx_dsk.cpp index 07d7a38cf95..08156d29e9c 100644 --- a/src/lib/formats/dvk_mx_dsk.cpp +++ b/src/lib/formats/dvk_mx_dsk.cpp @@ -18,11 +18,11 @@ ************************************************************************/ -#include - -#include "flopimg.h" #include "formats/dvk_mx_dsk.h" +#include "ioprocs.h" + + const floppy_image_format_t::desc_e dvk_mx_format::dvk_mx_new_desc[] = { /* 01 */ { FM, 0x00, 8*2 }, // eight 0x0000 words /* 03 */ { FM, 0x00, 1 }, @@ -81,9 +81,14 @@ bool dvk_mx_format::supports_save() const return false; } -void dvk_mx_format::find_size(io_generic *io, uint8_t &track_count, uint8_t &head_count, uint8_t §or_count) +void dvk_mx_format::find_size(util::random_read &io, uint8_t &track_count, uint8_t &head_count, uint8_t §or_count) { - uint64_t size = io_generic_size(io); + uint64_t size; + if (io.length(size)) + { + track_count = head_count = sector_count = 0; + return; + } switch (size) { @@ -108,7 +113,7 @@ void dvk_mx_format::find_size(io_generic *io, uint8_t &track_count, uint8_t &hea } } -int dvk_mx_format::identify(io_generic *io, uint32_t form_factor, const std::vector &variants) +int dvk_mx_format::identify(util::random_read &io, uint32_t form_factor, const std::vector &variants) { uint8_t track_count, head_count, sector_count; @@ -117,7 +122,8 @@ int dvk_mx_format::identify(io_generic *io, uint32_t form_factor, const std::vec if (track_count) { uint8_t sectdata[512]; - io_generic_read(io, sectdata, 512, 512); + size_t actual; + io.read_at(512, sectdata, 512, actual); // check value in RT-11 home block. see src/tools/imgtool/modules/rt11.cpp if (pick_integer_le(sectdata, 0724, 2) == 6) return 100; @@ -129,7 +135,7 @@ int dvk_mx_format::identify(io_generic *io, uint32_t form_factor, const std::vec return 0; } -bool dvk_mx_format::load(io_generic *io, uint32_t form_factor, const std::vector &variants, floppy_image *image) +bool dvk_mx_format::load(util::random_read &io, uint32_t form_factor, const std::vector &variants, floppy_image *image) { uint8_t track_count, head_count, sector_count; @@ -150,7 +156,8 @@ bool dvk_mx_format::load(io_generic *io, uint32_t form_factor, const std::vector { for (int head = 0; head < head_count; head++) { - io_generic_read(io, sectdata, (track * head_count + head) * track_size, track_size); + size_t actual; + io.read_at((track * head_count + head) * track_size, sectdata, track_size, actual); generate_track(dvk_mx_new_desc, track, head, sectors, sector_count, 45824, image); } } diff --git a/src/lib/formats/dvk_mx_dsk.h b/src/lib/formats/dvk_mx_dsk.h index 38fd895d154..e20066fc3ec 100644 --- a/src/lib/formats/dvk_mx_dsk.h +++ b/src/lib/formats/dvk_mx_dsk.h @@ -5,9 +5,8 @@ formats/dvk_mx_dsk.h *********************************************************************/ - -#ifndef DVK_MX_DSK_H_ -#define DVK_MX_DSK_H_ +#ifndef MAME_FORMATS_DVK_MX_DSK_H +#define MAME_FORMATS_DVK_MX_DSK_H #pragma once @@ -19,8 +18,8 @@ class dvk_mx_format : public floppy_image_format_t public: dvk_mx_format(); - virtual int identify(io_generic *io, uint32_t form_factor, const std::vector &variants) override; - virtual bool load(io_generic *io, uint32_t form_factor, const std::vector &variants, floppy_image *image) override; + virtual int identify(util::random_read &io, uint32_t form_factor, const std::vector &variants) override; + virtual bool load(util::random_read &io, uint32_t form_factor, const std::vector &variants, floppy_image *image) override; virtual const char *name() const override; virtual const char *description() const override; @@ -31,9 +30,9 @@ public: static const desc_e dvk_mx_new_desc[]; private: - void find_size(io_generic *io, uint8_t &track_count, uint8_t &head_count, uint8_t §or_count); + void find_size(util::random_read &io, uint8_t &track_count, uint8_t &head_count, uint8_t §or_count); }; extern const floppy_format_type FLOPPY_DVK_MX_FORMAT; -#endif /* DVK_MX_DSK_H_ */ +#endif // MAME_FORMATS_DVK_MX_DSK_H diff --git a/src/lib/formats/esq16_dsk.cpp b/src/lib/formats/esq16_dsk.cpp index 10802d26495..b33e529fef2 100644 --- a/src/lib/formats/esq16_dsk.cpp +++ b/src/lib/formats/esq16_dsk.cpp @@ -10,10 +10,10 @@ *********************************************************************/ -#include +#include "esq16_dsk.h" + +#include "ioprocs.h" -#include "flopimg.h" -#include "formats/esq16_dsk.h" const floppy_image_format_t::desc_e esqimg_format::esq_10_desc[] = { { MFM, 0x4e, 80 }, @@ -71,23 +71,23 @@ bool esqimg_format::supports_save() const return true; } -void esqimg_format::find_size(io_generic *io, uint8_t &track_count, uint8_t &head_count, uint8_t §or_count) +void esqimg_format::find_size(util::random_read &io, uint8_t &track_count, uint8_t &head_count, uint8_t §or_count) { - uint64_t size = io_generic_size(io); - track_count = 80; - head_count = 2; - sector_count = 10; - - uint32_t expected_size = 512 * track_count*head_count*sector_count; - if (size == expected_size) - { - return; - } + uint64_t size; + if(!io.length(size)) { + track_count = 80; + head_count = 2; + sector_count = 10; + uint32_t expected_size = 512 * track_count*head_count*sector_count; + if(size == expected_size) { + return; + } + } track_count = head_count = sector_count = 0; } -int esqimg_format::identify(io_generic *io, uint32_t form_factor, const std::vector &variants) +int esqimg_format::identify(util::random_read &io, uint32_t form_factor, const std::vector &variants) { uint8_t track_count, head_count, sector_count; find_size(io, track_count, head_count, sector_count); @@ -97,7 +97,7 @@ int esqimg_format::identify(io_generic *io, uint32_t form_factor, const std::vec return 0; } -bool esqimg_format::load(io_generic *io, uint32_t form_factor, const std::vector &variants, floppy_image *image) +bool esqimg_format::load(util::random_read &io, uint32_t form_factor, const std::vector &variants, floppy_image *image) { uint8_t track_count, head_count, sector_count; find_size(io, track_count, head_count, sector_count); @@ -113,7 +113,8 @@ bool esqimg_format::load(io_generic *io, uint32_t form_factor, const std::vector int track_size = sector_count*512; for(int track=0; track < track_count; track++) { for(int head=0; head < head_count; head++) { - io_generic_read(io, sectdata, (track*head_count + head)*track_size, track_size); + size_t actual; + io.read_at((track*head_count + head)*track_size, sectdata, track_size, actual); generate_track(esq_10_desc, track, head, sectors, sector_count, 110528, image); } } @@ -123,7 +124,7 @@ bool esqimg_format::load(io_generic *io, uint32_t form_factor, const std::vector return true; } -bool esqimg_format::save(io_generic *io, const std::vector &variants, floppy_image *image) +bool esqimg_format::save(util::random_read_write &io, const std::vector &variants, floppy_image *image) { int track_count, head_count, sector_count; get_geometry_mfm_pc(image, 2000, track_count, head_count, sector_count); @@ -144,7 +145,8 @@ bool esqimg_format::save(io_generic *io, const std::vector &variants, for(int track=0; track < track_count; track++) { for(int head=0; head < head_count; head++) { get_track_data_mfm_pc(track, head, image, 2000, 512, sector_count, sectdata); - io_generic_write(io, sectdata, (track*head_count + head)*track_size, track_size); + size_t actual; + io.write_at((track*head_count + head)*track_size, sectdata, track_size, actual); } } diff --git a/src/lib/formats/esq16_dsk.h b/src/lib/formats/esq16_dsk.h index 8cc49150d2c..2347d64f59c 100644 --- a/src/lib/formats/esq16_dsk.h +++ b/src/lib/formats/esq16_dsk.h @@ -21,9 +21,9 @@ class esqimg_format : public floppy_image_format_t public: esqimg_format(); - virtual int identify(io_generic *io, uint32_t form_factor, const std::vector &variants) override; - virtual bool load(io_generic *io, uint32_t form_factor, const std::vector &variants, floppy_image *image) override; - virtual bool save(io_generic *io, const std::vector &variants, floppy_image *image) override; + virtual int identify(util::random_read &io, uint32_t form_factor, const std::vector &variants) override; + virtual bool load(util::random_read &io, uint32_t form_factor, const std::vector &variants, floppy_image *image) override; + virtual bool save(util::random_read_write &io, const std::vector &variants, floppy_image *image) override; virtual const char *name() const override; virtual const char *description() const override; @@ -33,7 +33,7 @@ public: static const desc_e esq_10_desc[]; private: - void find_size(io_generic *io, uint8_t &track_count, uint8_t &head_count, uint8_t §or_count); + void find_size(util::random_read &io, uint8_t &track_count, uint8_t &head_count, uint8_t §or_count); }; extern const floppy_format_type FLOPPY_ESQIMG_FORMAT; diff --git a/src/lib/formats/esq8_dsk.cpp b/src/lib/formats/esq8_dsk.cpp index f9dcb3d0727..952dd16edbd 100644 --- a/src/lib/formats/esq8_dsk.cpp +++ b/src/lib/formats/esq8_dsk.cpp @@ -12,10 +12,10 @@ *********************************************************************/ -#include +#include "esq8_dsk.h" + +#include "ioprocs.h" -#include "flopimg.h" -#include "formats/esq8_dsk.h" const floppy_image_format_t::desc_e esq8img_format::esq_6_desc[] = { { MFM, 0x4e, 80 }, @@ -73,22 +73,24 @@ bool esq8img_format::supports_save() const return true; } -void esq8img_format::find_size(io_generic *io, int &track_count, int &head_count, int §or_count) +void esq8img_format::find_size(util::random_read &io, int &track_count, int &head_count, int §or_count) { - uint64_t size = io_generic_size(io); - track_count = 80; - head_count = 1; - sector_count = 6; - - if(size == 5632 * 80) + uint64_t size; + if(!io.length(size)) { - return; - } + track_count = 80; + head_count = 1; + sector_count = 6; + if(size == 5632 * 80) + { + return; + } + } track_count = head_count = sector_count = 0; } -int esq8img_format::identify(io_generic *io, uint32_t form_factor, const std::vector &variants) +int esq8img_format::identify(util::random_read &io, uint32_t form_factor, const std::vector &variants) { int track_count, head_count, sector_count; find_size(io, track_count, head_count, sector_count); @@ -99,7 +101,7 @@ int esq8img_format::identify(io_generic *io, uint32_t form_factor, const std::ve return 0; } -bool esq8img_format::load(io_generic *io, uint32_t form_factor, const std::vector &variants, floppy_image *image) +bool esq8img_format::load(util::random_read &io, uint32_t form_factor, const std::vector &variants, floppy_image *image) { int track_count, head_count, sector_count; find_size(io, track_count, head_count, sector_count); @@ -128,7 +130,8 @@ bool esq8img_format::load(io_generic *io, uint32_t form_factor, const std::vecto { for(int head=0; head < head_count; head++) { - io_generic_read(io, sectdata, (track*head_count + head)*track_size, track_size); + size_t actual; + io.read_at((track*head_count + head)*track_size, sectdata, track_size, actual); generate_track(esq_6_desc, track, head, sectors, sector_count, 109376, image); } } @@ -138,7 +141,7 @@ bool esq8img_format::load(io_generic *io, uint32_t form_factor, const std::vecto return true; } -bool esq8img_format::save(io_generic *io, const std::vector &variants, floppy_image *image) +bool esq8img_format::save(util::random_read_write &io, const std::vector &variants, floppy_image *image) { uint64_t file_offset = 0; int track_count, head_count, sector_count; @@ -175,7 +178,8 @@ bool esq8img_format::save(io_generic *io, const std::vector &variants, return false; } - io_generic_write(io, sectors[sector].data(), file_offset, sector_expected_size); + size_t actual; + io.write_at(file_offset, sectors[sector].data(), sector_expected_size, actual); file_offset += sector_expected_size; } } diff --git a/src/lib/formats/esq8_dsk.h b/src/lib/formats/esq8_dsk.h index c4fe5a74f1b..aa09fd278a7 100644 --- a/src/lib/formats/esq8_dsk.h +++ b/src/lib/formats/esq8_dsk.h @@ -23,9 +23,9 @@ class esq8img_format : public floppy_image_format_t public: esq8img_format(); - virtual int identify(io_generic *io, uint32_t form_factor, const std::vector &variants) override; - virtual bool load(io_generic *io, uint32_t form_factor, const std::vector &variants, floppy_image *image) override; - virtual bool save(io_generic *io, const std::vector &variants, floppy_image *image) override; + virtual int identify(util::random_read &io, uint32_t form_factor, const std::vector &variants) override; + virtual bool load(util::random_read &io, uint32_t form_factor, const std::vector &variants, floppy_image *image) override; + virtual bool save(util::random_read_write &io, const std::vector &variants, floppy_image *image) override; virtual const char *name() const override; virtual const char *description() const override; @@ -35,7 +35,7 @@ public: static const desc_e esq_6_desc[]; private: - void find_size(io_generic *io, int &track_count, int &head_count, int §or_count); + void find_size(util::random_read &io, int &track_count, int &head_count, int §or_count); }; extern const floppy_format_type FLOPPY_ESQ8IMG_FORMAT; diff --git a/src/lib/formats/fdd_dsk.cpp b/src/lib/formats/fdd_dsk.cpp index df5fd3caa8c..8c8249c9452 100644 --- a/src/lib/formats/fdd_dsk.cpp +++ b/src/lib/formats/fdd_dsk.cpp @@ -31,10 +31,11 @@ *********************************************************************/ -#include - #include "fdd_dsk.h" +#include "ioprocs.h" + + fdd_format::fdd_format() { } @@ -54,10 +55,11 @@ const char *fdd_format::extensions() const return "fdd"; } -int fdd_format::identify(io_generic *io, uint32_t form_factor, const std::vector &variants) +int fdd_format::identify(util::random_read &io, uint32_t form_factor, const std::vector &variants) { uint8_t h[7]; - io_generic_read(io, h, 0, 7); + size_t actual; + io.read_at(0, h, 7, actual); if (strncmp((const char *)h, "VFD1.0", 6) == 0) return 100; @@ -65,7 +67,7 @@ int fdd_format::identify(io_generic *io, uint32_t form_factor, const std::vector return 0; } -bool fdd_format::load(io_generic *io, uint32_t form_factor, const std::vector &variants, floppy_image *image) +bool fdd_format::load(util::random_read &io, uint32_t form_factor, const std::vector &variants, floppy_image *image) { uint8_t hsec[0x0c]; @@ -86,7 +88,8 @@ bool fdd_format::load(io_generic *io, uint32_t form_factor, const std::vector &variants) override; - virtual bool load(io_generic *io, uint32_t form_factor, const std::vector &variants, floppy_image *image) override; + virtual int identify(util::random_read &io, uint32_t form_factor, const std::vector &variants) override; + virtual bool load(util::random_read &io, uint32_t form_factor, const std::vector &variants, floppy_image *image) override; virtual const char *name() const override; virtual const char *description() const override; diff --git a/src/lib/formats/flex_dsk.cpp b/src/lib/formats/flex_dsk.cpp index 692cc4bdc9d..4989a25e707 100644 --- a/src/lib/formats/flex_dsk.cpp +++ b/src/lib/formats/flex_dsk.cpp @@ -50,7 +50,11 @@ */ #include "flex_dsk.h" -#include "formats/imageutl.h" + +#include "imageutl.h" + +#include "ioprocs.h" + flex_format::flex_format() : wd177x_format(formats) { @@ -71,7 +75,7 @@ const char *flex_format::extensions() const return "dsk"; } -int flex_format::identify(io_generic *io, uint32_t form_factor, const std::vector &variants) +int flex_format::identify(util::random_read &io, uint32_t form_factor, const std::vector &variants) { int type = find_size(io, form_factor, variants); @@ -80,17 +84,21 @@ int flex_format::identify(io_generic *io, uint32_t form_factor, const std::vecto return 0; } -int flex_format::find_size(io_generic *io, uint32_t form_factor, const std::vector &variants) +int flex_format::find_size(util::random_read &io, uint32_t form_factor, const std::vector &variants) { - uint64_t size = io_generic_size(io); + uint64_t size; + if (io.length(size)) + return -1; + uint8_t boot0[256], boot1[256]; + size_t actual; // Look at the boot sector. // Density, sides, link?? - io_generic_read(io, &boot0, 256 * 0, sizeof(boot0)); - io_generic_read(io, &boot1, 256 * 1, sizeof(boot1)); + io.read_at(256 * 0, &boot0, sizeof(boot0), actual); + io.read_at(256 * 1, &boot1, sizeof(boot1), actual); // Look at the system information sector. - io_generic_read(io, &info, 256 * 2, sizeof(struct sysinfo_sector)); + io.read_at(256 * 2, &info, sizeof(struct sysinfo_sector), actual); LOG_FORMATS("FLEX floppy dsk: size %d bytes, %d total sectors, %d remaining bytes, expected form factor %x\n", (uint32_t)size, (uint32_t)size / 256, (uint32_t)size % 256, form_factor); diff --git a/src/lib/formats/flex_dsk.h b/src/lib/formats/flex_dsk.h index 094c6854b24..0048e4e088f 100644 --- a/src/lib/formats/flex_dsk.h +++ b/src/lib/formats/flex_dsk.h @@ -21,8 +21,8 @@ public: virtual const char *name() const override; virtual const char *description() const override; virtual const char *extensions() const override; - virtual int identify(io_generic *io, uint32_t form_factor, const std::vector &variants) override; - virtual int find_size(io_generic *io, uint32_t form_factor, const std::vector &variants) override; + virtual int identify(util::random_read &io, uint32_t form_factor, const std::vector &variants) override; + virtual int find_size(util::random_read &io, uint32_t form_factor, const std::vector &variants) override; virtual const wd177x_format::format &get_track_format(const format &f, int head, int track) override; private: diff --git a/src/lib/formats/flopimg.cpp b/src/lib/formats/flopimg.cpp index 48c2fa1b610..55d00d1bb83 100644 --- a/src/lib/formats/flopimg.cpp +++ b/src/lib/formats/flopimg.cpp @@ -11,9 +11,10 @@ #include "flopimg.h" #include "imageutl.h" -#include "osdcore.h" #include "ioprocs.h" +#include "osdcore.h" + #include #include #include @@ -30,7 +31,7 @@ using util::BIT; struct floppy_image_legacy { - struct io_generic io = { 0 }; + util::random_read_write::ptr io = nullptr; const struct FloppyFormat *floppy_option = nullptr; struct FloppyCallbacks format = { 0 }; @@ -69,22 +70,20 @@ OPTION_GUIDE_START(floppy_option_guide) OPTION_GUIDE_END -static void floppy_close_internal(floppy_image_legacy *floppy, bool close_file); +static void floppy_close_internal(floppy_image_legacy *floppy); /********************************************************************* opening, closing and creating of floppy images *********************************************************************/ /* basic floppy_image_legacy initialization common to floppy_open() and floppy_create() */ -static floppy_image_legacy *floppy_init(void *fp, const struct io_procs *procs, int flags) +static floppy_image_legacy *floppy_init(util::random_read_write::ptr &&io, int flags) { floppy_image_legacy *floppy; floppy = new floppy_image_legacy; - floppy->io.file = fp; - floppy->io.procs = procs; - floppy->io.filler = 0xFF; + floppy->io = std::move(io); floppy->flags = (uint8_t) flags; return floppy; } @@ -93,7 +92,7 @@ static floppy_image_legacy *floppy_init(void *fp, const struct io_procs *procs, /* main code for identifying and maybe opening a disk image; not exposed * directly because this function is big and hideous */ -static floperr_t floppy_open_internal(void *fp, const struct io_procs *procs, const std::string &extension, +static floperr_t floppy_open_internal(util::random_read_write::ptr &&io, const std::string &extension, const struct FloppyFormat *floppy_options, int max_options, int flags, floppy_image_legacy **outfloppy, int *outoption) { @@ -104,7 +103,7 @@ static floperr_t floppy_open_internal(void *fp, const struct io_procs *procs, co int vote; size_t i; - floppy = floppy_init(fp, procs, flags); + floppy = floppy_init(std::move(io), flags); if (!floppy) { err = FLOPPY_ERROR_OUTOFMEMORY; @@ -163,7 +162,7 @@ done: /* if we have a floppy disk and we either errored or are not keeping it, close it */ if (floppy && (!outfloppy || err)) { - floppy_close_internal(floppy, false); + floppy_close_internal(floppy); floppy = nullptr; } @@ -176,31 +175,31 @@ done: -floperr_t floppy_identify(void *fp, const struct io_procs *procs, const char *extension, +floperr_t floppy_identify(util::random_read_write::ptr &&io, const char *extension, const struct FloppyFormat *formats, int *identified_format) { - return floppy_open_internal(fp, procs, extension, formats, INT_MAX, FLOPPY_FLAGS_READONLY, nullptr, identified_format); + return floppy_open_internal(std::move(io), extension, formats, INT_MAX, FLOPPY_FLAGS_READONLY, nullptr, identified_format); } -floperr_t floppy_open(void *fp, const struct io_procs *procs, const std::string &extension, +floperr_t floppy_open(util::random_read_write::ptr &&io, const std::string &extension, const struct FloppyFormat *format, int flags, floppy_image_legacy **outfloppy) { - return floppy_open_internal(fp, procs, extension, format, 1, flags, outfloppy, nullptr); + return floppy_open_internal(std::move(io), extension, format, 1, flags, outfloppy, nullptr); } -floperr_t floppy_open_choices(void *fp, const struct io_procs *procs, const std::string &extension, +floperr_t floppy_open_choices(util::random_read_write::ptr &&io, const std::string &extension, const struct FloppyFormat *formats, int flags, floppy_image_legacy **outfloppy) { - return floppy_open_internal(fp, procs, extension, formats, INT_MAX, flags, outfloppy, nullptr); + return floppy_open_internal(std::move(io), extension, formats, INT_MAX, flags, outfloppy, nullptr); } -floperr_t floppy_create(void *fp, const struct io_procs *procs, const struct FloppyFormat *format, util::option_resolution *parameters, floppy_image_legacy **outfloppy) +floperr_t floppy_create(util::random_read_write::ptr &&io, const struct FloppyFormat *format, util::option_resolution *parameters, floppy_image_legacy **outfloppy) { floppy_image_legacy *floppy = nullptr; floperr_t err; @@ -210,7 +209,7 @@ floperr_t floppy_create(void *fp, const struct io_procs *procs, const struct Flo assert(format); /* create the new image */ - floppy = floppy_init(fp, procs, 0); + floppy = floppy_init(std::move(io), 0); if (!floppy) { err = FLOPPY_ERROR_OUTOFMEMORY; @@ -266,28 +265,26 @@ floperr_t floppy_create(void *fp, const struct io_procs *procs, const struct Flo done: if (err && floppy) { - floppy_close_internal(floppy, false); + floppy_close_internal(floppy); floppy = nullptr; } if (outfloppy) *outfloppy = floppy; else if (floppy) - floppy_close_internal(floppy, false); + floppy_close_internal(floppy); return err; } -static void floppy_close_internal(floppy_image_legacy *floppy, bool close_file) +static void floppy_close_internal(floppy_image_legacy *floppy) { if (floppy) { floppy_track_unload(floppy); if(floppy->floppy_option && floppy->floppy_option->destruct) floppy->floppy_option->destruct(floppy, floppy->floppy_option); - if (close_file) - io_generic_close(&floppy->io); delete floppy; } @@ -297,7 +294,7 @@ static void floppy_close_internal(floppy_image_legacy *floppy, bool close_file) void floppy_close(floppy_image_legacy *floppy) { - floppy_close_internal(floppy, true); + floppy_close_internal(floppy); } @@ -332,14 +329,16 @@ void *floppy_create_tag(floppy_image_legacy *floppy, size_t tagsize) uint8_t floppy_get_filler(floppy_image_legacy *floppy) { - return floppy->io.filler; + // FIXME: remove this function, it's here for legacy reasons + // the caller actually sets the filler byte - in practice it's always 0xff but there's no actual guarantee + return 0xff; } -void floppy_set_filler(floppy_image_legacy *floppy, uint8_t filler) +util::random_read_write &floppy_get_io(floppy_image_legacy *floppy) { - floppy->io.filler = filler; + return *floppy->io; } @@ -350,28 +349,42 @@ void floppy_set_filler(floppy_image_legacy *floppy, uint8_t filler) void floppy_image_read(floppy_image_legacy *floppy, void *buffer, uint64_t offset, size_t length) { - io_generic_read(&floppy->io, buffer, offset, length); + size_t actual; + floppy->io->read_at(offset, buffer, length, actual); } void floppy_image_write(floppy_image_legacy *floppy, const void *buffer, uint64_t offset, size_t length) { - io_generic_write(&floppy->io, buffer, offset, length); + size_t actual; + floppy->io->write_at(offset, buffer, length, actual); } void floppy_image_write_filler(floppy_image_legacy *floppy, uint8_t filler, uint64_t offset, size_t length) { - io_generic_write_filler(&floppy->io, filler, offset, length); + uint8_t buffer[512]; + memset(buffer, filler, std::min(sizeof(buffer), length)); + + while (length) + { + size_t const block = std::min(sizeof(buffer), length); + size_t actual; + floppy->io->write_at(offset, buffer, block, actual); + offset += block; + length -= block; + } } uint64_t floppy_image_size(floppy_image_legacy *floppy) { - return io_generic_size(&floppy->io); + uint64_t result; + floppy->io->length(result); + return result; } @@ -976,7 +989,7 @@ bool floppy_image_format_t::has_variant(const std::vector &variants, u return false; } -bool floppy_image_format_t::save(io_generic *, const std::vector &, floppy_image *) +bool floppy_image_format_t::save(util::random_read_write &io, const std::vector &, floppy_image *) { return false; } diff --git a/src/lib/formats/flopimg.h b/src/lib/formats/flopimg.h index 101d9bd86bd..6279def82f8 100644 --- a/src/lib/formats/flopimg.h +++ b/src/lib/formats/flopimg.h @@ -12,11 +12,13 @@ #pragma once -#include "osdcore.h" -#include "ioprocs.h" -#include "opresolv.h" #include "coretmpl.h" +#include "opresolv.h" +#include "utilfwd.h" + +#include "osdcore.h" +#include #include #ifndef LOG_FORMATS @@ -166,20 +168,20 @@ LEGACY_FLOPPY_OPTIONS_EXTERN(default); OPTION_GUIDE_EXTERN(floppy_option_guide); /* opening, closing and creating of floppy images */ -floperr_t floppy_open(void *fp, const struct io_procs *procs, const std::string &extension, const struct FloppyFormat *format, int flags, floppy_image_legacy **outfloppy); -floperr_t floppy_open_choices(void *fp, const struct io_procs *procs, const std::string &extension, const struct FloppyFormat *formats, int flags, floppy_image_legacy **outfloppy); -floperr_t floppy_create(void *fp, const struct io_procs *procs, const struct FloppyFormat *format, util::option_resolution *parameters, floppy_image_legacy **outfloppy); +floperr_t floppy_open(std::unique_ptr &&io, const std::string &extension, const struct FloppyFormat *format, int flags, floppy_image_legacy **outfloppy); +floperr_t floppy_open_choices(std::unique_ptr &&io, const std::string &extension, const struct FloppyFormat *formats, int flags, floppy_image_legacy **outfloppy); +floperr_t floppy_create(std::unique_ptr &&io, const struct FloppyFormat *format, util::option_resolution *parameters, floppy_image_legacy **outfloppy); void floppy_close(floppy_image_legacy *floppy); /* useful for identifying a floppy image */ -floperr_t floppy_identify(void *fp, const struct io_procs *procs, const char *extension, const struct FloppyFormat *formats, int *identified_format); +floperr_t floppy_identify(std::unique_ptr &&io, const char *extension, const struct FloppyFormat *formats, int *identified_format); /* functions useful within format constructors */ void *floppy_tag(floppy_image_legacy *floppy); void *floppy_create_tag(floppy_image_legacy *floppy, size_t tagsize); struct FloppyCallbacks *floppy_callbacks(floppy_image_legacy *floppy); uint8_t floppy_get_filler(floppy_image_legacy *floppy); -void floppy_set_filler(floppy_image_legacy *floppy, uint8_t filler); +util::random_read_write &floppy_get_io(floppy_image_legacy *floppy); /* calls for accessing disk image data */ floperr_t floppy_read_sector(floppy_image_legacy *floppy, int head, int track, int sector, int offset, void *buffer, size_t buffer_len); @@ -235,7 +237,7 @@ public: @param variants the variants from floppy_image the drive can handle @return 1 if image valid, 0 otherwise. */ - virtual int identify(io_generic *io, uint32_t form_factor, const std::vector &variants) = 0; + virtual int identify(util::random_read &io, uint32_t form_factor, const std::vector &variants) = 0; /*! @brief Load an image. The load function opens an image file and converts it to the @@ -247,7 +249,7 @@ public: @param image output buffer for data in MESS internal format. @return true on success, false otherwise. */ - virtual bool load(io_generic *io, uint32_t form_factor, const std::vector &variants, floppy_image *image) = 0; + virtual bool load(util::random_read &io, uint32_t form_factor, const std::vector &variants, floppy_image *image) = 0; /*! @brief Save an image. The save function writes back an image from the MESS internal @@ -257,7 +259,7 @@ public: @param image source buffer containing data in MESS internal format. @return true on success, false otherwise. */ - virtual bool save(io_generic *io, const std::vector &variants, floppy_image *image); + virtual bool save(util::random_read_write &io, const std::vector &variants, floppy_image *image); //! @returns string containing name of format. virtual const char *name() const = 0; diff --git a/src/lib/formats/fsd_dsk.cpp b/src/lib/formats/fsd_dsk.cpp index c5ebd243875..ffb23035420 100644 --- a/src/lib/formats/fsd_dsk.cpp +++ b/src/lib/formats/fsd_dsk.cpp @@ -10,6 +10,8 @@ #include "fsd_dsk.h" +#include "ioprocs.h" + /********************************************************************* @@ -83,11 +85,12 @@ bool fsd_format::supports_save() const return false; } -int fsd_format::identify(io_generic *io, uint32_t form_factor, const std::vector &variants) +int fsd_format::identify(util::random_read &io, uint32_t form_factor, const std::vector &variants) { uint8_t h[3]; - io_generic_read(io, h, 0, 3); + size_t actual; + io.read_at(0, h, 3, actual); if (memcmp(h, "FSD", 3) == 0) { return 100; } @@ -95,16 +98,19 @@ int fsd_format::identify(io_generic *io, uint32_t form_factor, const std::vector return 0; } -bool fsd_format::load(io_generic *io, uint32_t form_factor, const std::vector &variants, floppy_image *image) +bool fsd_format::load(util::random_read &io, uint32_t form_factor, const std::vector &variants, floppy_image *image) { const char* result[255]; result[0x00] = "OK"; result[0x0e] = "Data CRC Error"; result[0x20] = "Deleted Data"; - uint64_t size = io_generic_size(io); + uint64_t size; + if(io.length(size)) + return false; std::vector img(size); - io_generic_read(io, &img[0], 0, size); + size_t actual; + io.read_at(0, &img[0], size, actual); uint64_t pos; std::string title; diff --git a/src/lib/formats/fsd_dsk.h b/src/lib/formats/fsd_dsk.h index ee2c4aa466c..779ee28ec02 100644 --- a/src/lib/formats/fsd_dsk.h +++ b/src/lib/formats/fsd_dsk.h @@ -33,8 +33,8 @@ public: virtual const char *extensions() const override; virtual bool supports_save() const override; - virtual int identify(io_generic *io, uint32_t form_factor, const std::vector &variants) override; - virtual bool load(io_generic *io, uint32_t form_factor, const std::vector &variants, floppy_image *image) override; + virtual int identify(util::random_read &io, uint32_t form_factor, const std::vector &variants) override; + virtual bool load(util::random_read &io, uint32_t form_factor, const std::vector &variants, floppy_image *image) override; }; extern const floppy_format_type FLOPPY_FSD_FORMAT; diff --git a/src/lib/formats/g64_dsk.cpp b/src/lib/formats/g64_dsk.cpp index 02098db88e0..8e6b9c75e44 100644 --- a/src/lib/formats/g64_dsk.cpp +++ b/src/lib/formats/g64_dsk.cpp @@ -12,6 +12,8 @@ #include "formats/g64_dsk.h" +#include "ioprocs.h" + #define G64_FORMAT_HEADER "GCR-1541" @@ -27,22 +29,27 @@ const uint32_t g64_format::c1541_cell_size[] = 3250 // 16MHz/13/4 }; -int g64_format::identify(io_generic *io, uint32_t form_factor, const std::vector &variants) +int g64_format::identify(util::random_read &io, uint32_t form_factor, const std::vector &variants) { char h[8]; - io_generic_read(io, h, 0, 8); + size_t actual; + io.read_at(0, h, 8, actual); if (!memcmp(h, G64_FORMAT_HEADER, 8)) return 100; return 0; } -bool g64_format::load(io_generic *io, uint32_t form_factor, const std::vector &variants, floppy_image *image) +bool g64_format::load(util::random_read &io, uint32_t form_factor, const std::vector &variants, floppy_image *image) { - uint64_t size = io_generic_size(io); + uint64_t size; + if (io.length(size)) + return false; + std::vector img(size); - io_generic_read(io, &img[0], 0, size); + size_t actual; + io.read_at(0, &img[0], size, actual); if (img[POS_VERSION]) { @@ -109,15 +116,19 @@ int g64_format::generate_bitstream(int track, int head, int speed_zone, std::vec return ((actual_cell_size >= cell_size-10) && (actual_cell_size <= cell_size+10)) ? speed_zone : -1; } -bool g64_format::save(io_generic *io, const std::vector &variants, floppy_image *image) +bool g64_format::save(util::random_read_write &io, const std::vector &variants, floppy_image *image) { + uint8_t const zerofill[] = { 0x00, 0x00, 0x00, 0x00 }; + std::vector const prefill(TRACK_LENGTH, 0xff); + size_t actual; + int tracks, heads; image->get_actual_geometry(tracks, heads); tracks = TRACK_COUNT * heads; // write header uint8_t header[] = { 'G', 'C', 'R', '-', '1', '5', '4', '1', 0x00, static_cast(tracks), TRACK_LENGTH & 0xff, TRACK_LENGTH >> 8 }; - io_generic_write(io, header, POS_SIGNATURE, sizeof(header)); + io.write_at(POS_SIGNATURE, header, sizeof(header), actual); // write tracks for (int head = 0; head < heads; head++) { @@ -126,12 +137,12 @@ bool g64_format::save(io_generic *io, const std::vector &variants, flo std::vector trackbuf; for (int track = 0; track < TRACK_COUNT; track++) { - uint32_t tpos = POS_TRACK_OFFSET + (track * 4); - uint32_t spos = tpos + (tracks * 4); - uint32_t dpos = POS_TRACK_OFFSET + (tracks * 4 * 2) + (tracks_written * TRACK_LENGTH); + uint32_t const tpos = POS_TRACK_OFFSET + (track * 4); + uint32_t const spos = tpos + (tracks * 4); + uint32_t const dpos = POS_TRACK_OFFSET + (tracks * 4 * 2) + (tracks_written * TRACK_LENGTH); - io_generic_write_filler(io, 0x00, tpos, 4); - io_generic_write_filler(io, 0x00, spos, 4); + io.write_at(tpos, zerofill, 4, actual); + io.write_at(spos, zerofill, 4, actual); if (image->get_buffer(track, head).size() <= 1) continue; @@ -163,11 +174,11 @@ bool g64_format::save(io_generic *io, const std::vector &variants, flo place_integer_le(speed_offset, 0, 4, speed_zone); place_integer_le(track_length, 0, 2, packed.size()); - io_generic_write(io, track_offset, tpos, 4); - io_generic_write(io, speed_offset, spos, 4); - io_generic_write_filler(io, 0xff, dpos, TRACK_LENGTH); - io_generic_write(io, track_length, dpos, 2); - io_generic_write(io, packed.data(), dpos + 2, packed.size()); + io.write_at(tpos, track_offset, 4, actual); + io.write_at(spos, speed_offset, 4, actual); + io.write_at(dpos, prefill.data(), TRACK_LENGTH, actual); + io.write_at(dpos, track_length, 2, actual); + io.write_at(dpos + 2, packed.data(), packed.size(), actual); tracks_written++; } diff --git a/src/lib/formats/g64_dsk.h b/src/lib/formats/g64_dsk.h index 6691146c70e..fcd48d96796 100644 --- a/src/lib/formats/g64_dsk.h +++ b/src/lib/formats/g64_dsk.h @@ -20,9 +20,9 @@ class g64_format : public floppy_image_format_t public: g64_format(); - virtual int identify(io_generic *io, uint32_t form_factor, const std::vector &variants) override; - virtual bool load(io_generic *io, uint32_t form_factor, const std::vector &variants, floppy_image *image) override; - virtual bool save(io_generic *io, const std::vector &variants, floppy_image *image) override; + virtual int identify(util::random_read &io, uint32_t form_factor, const std::vector &variants) override; + virtual bool load(util::random_read &io, uint32_t form_factor, const std::vector &variants, floppy_image *image) override; + virtual bool save(util::random_read_write &io, const std::vector &variants, floppy_image *image) override; virtual const char *name() const override; virtual const char *description() const override; diff --git a/src/lib/formats/hpi_dsk.cpp b/src/lib/formats/hpi_dsk.cpp index d9fc788fd45..bdccc66803d 100644 --- a/src/lib/formats/hpi_dsk.cpp +++ b/src/lib/formats/hpi_dsk.cpp @@ -48,6 +48,7 @@ #include "hpi_dsk.h" #include "coretmpl.h" // BIT +#include "ioprocs.h" // Debugging @@ -78,9 +79,12 @@ hpi_format::hpi_format() (void)HPI_RED_IMAGE_SIZE; } -int hpi_format::identify(io_generic *io, uint32_t form_factor, const std::vector &variants) +int hpi_format::identify(util::random_read &io, uint32_t form_factor, const std::vector &variants) { - uint64_t size = io_generic_size(io); + uint64_t size; + if (io.length(size)) { + return 0; + } // we try to stay back and give only 50 points, since another image // format may also have images of the same size (there is no header and no @@ -142,12 +146,15 @@ bool hpi_format::geometry_from_size(uint64_t image_size , unsigned& heads , unsi } } -bool hpi_format::load(io_generic *io, uint32_t form_factor, const std::vector &variants, floppy_image *image) +bool hpi_format::load(util::random_read &io, uint32_t form_factor, const std::vector &variants, floppy_image *image) { unsigned heads; unsigned cylinders; - uint64_t size = io_generic_size(io); + uint64_t size; + if (io.length(size)) { + return false; + } if (!geometry_from_size(size, heads, cylinders)) { return false; } @@ -161,7 +168,8 @@ bool hpi_format::load(io_generic *io, uint32_t form_factor, const std::vector image_data(size); - io_generic_read(io, (void *)image_data.data(), 0, size); + size_t actual; + io.read_at(0, image_data.data(), size, actual); // Get interleave factor from image unsigned il = (unsigned)image_data[ IL_OFFSET ] * 256 + image_data[ IL_OFFSET + 1 ]; @@ -191,7 +199,7 @@ bool hpi_format::load(io_generic *io, uint32_t form_factor, const std::vector &variants, floppy_image *image) +bool hpi_format::save(util::random_read_write &io, const std::vector &variants, floppy_image *image) { int tracks; int heads; @@ -206,7 +214,8 @@ bool hpi_format::save(io_generic *io, const std::vector &variants, flo while (get_next_sector(bitstream , pos , track_no , head_no , sector_no , sector_data)) { if (track_no == cyl && head_no == head && sector_no < HPI_SECTORS) { unsigned offset_in_image = chs_to_lba(cyl, head, sector_no, heads) * HPI_SECTOR_SIZE; - io_generic_write(io, sector_data, offset_in_image, HPI_SECTOR_SIZE); + size_t actual; + io.write_at(offset_in_image, sector_data, HPI_SECTOR_SIZE, actual); } } } diff --git a/src/lib/formats/hpi_dsk.h b/src/lib/formats/hpi_dsk.h index 38c70e91c33..ca8aa1ffe11 100644 --- a/src/lib/formats/hpi_dsk.h +++ b/src/lib/formats/hpi_dsk.h @@ -28,9 +28,9 @@ class hpi_format : public floppy_image_format_t public: hpi_format(); - virtual int identify(io_generic *io, uint32_t form_factor, const std::vector &variants) override; - virtual bool load(io_generic *io, uint32_t form_factor, const std::vector &variants, floppy_image *image) override; - virtual bool save(io_generic *io, const std::vector &variants, floppy_image *image) override; + virtual int identify(util::random_read &io, uint32_t form_factor, const std::vector &variants) override; + virtual bool load(util::random_read &io, uint32_t form_factor, const std::vector &variants, floppy_image *image) override; + virtual bool save(util::random_read_write &io, const std::vector &variants, floppy_image *image) override; virtual const char *name() const override; virtual const char *description() const override; virtual const char *extensions() const override; diff --git a/src/lib/formats/hti_tape.cpp b/src/lib/formats/hti_tape.cpp index 7f77e3f99df..8fbaeef91cc 100644 --- a/src/lib/formats/hti_tape.cpp +++ b/src/lib/formats/hti_tape.cpp @@ -10,6 +10,8 @@ #include "imageutl.h" +#include "ioprocs.h" + static constexpr uint32_t OLD_FILE_MAGIC = 0x5441434f; // Magic value at start of old-format image file: "TACO" static constexpr uint32_t FILE_MAGIC_DELTA = 0x48544930; // Magic value at start of delta-modulation image file: "HTI0" @@ -47,22 +49,25 @@ hti_format_t::hti_format_t() clear_tape(); } -bool hti_format_t::load_tape(io_generic *io) +bool hti_format_t::load_tape(util::random_read &io) { + if (io.seek(0, SEEK_SET)) { + return false; + } + + size_t actual; uint8_t tmp[ 4 ]; - io_generic_read(io, tmp, 0, 4); + io.read(tmp, 4, actual); auto magic = pick_integer_be(tmp , 0 , 4); if (((m_img_format == HTI_DELTA_MOD_16_BITS || m_img_format == HTI_DELTA_MOD_17_BITS) && magic != FILE_MAGIC_DELTA && magic != OLD_FILE_MAGIC) || (m_img_format == HTI_MANCHESTER_MOD && magic != FILE_MAGIC_MANCHESTER)) { return false; } - uint64_t offset = 4; - for (unsigned i = 0; i < no_of_tracks(); i++) { tape_track_t& track = m_tracks[ i ]; - if (!load_track(io , offset , track , magic == OLD_FILE_MAGIC)) { + if (!load_track(io, track, magic == OLD_FILE_MAGIC)) { clear_tape(); return false; } @@ -71,14 +76,15 @@ bool hti_format_t::load_tape(io_generic *io) return true; } -void hti_format_t::save_tape(io_generic *io) +void hti_format_t::save_tape(util::random_read_write &io) { + io.seek(0, SEEK_SET); + + size_t actual; uint8_t tmp[ 4 ]; place_integer_be(tmp, 0, 4, m_img_format == HTI_MANCHESTER_MOD ? FILE_MAGIC_MANCHESTER : FILE_MAGIC_DELTA); - io_generic_write(io, tmp, 0, 4); - - uint64_t offset = 4; + io.write(tmp, 4, actual); for (unsigned i = 0; i < no_of_tracks(); i++) { const tape_track_t& track = m_tracks[ i ]; @@ -87,18 +93,17 @@ void hti_format_t::save_tape(io_generic *io) tape_track_t::const_iterator it_start; for (tape_track_t::const_iterator it = track.cbegin(); it != track.cend(); ++it) { if (it->first != next_pos) { - dump_sequence(io , offset , it_start , n_words); + dump_sequence(io, it_start, n_words); it_start = it; n_words = 0; } next_pos = it->first + word_length(it->second); n_words++; } - dump_sequence(io , offset , it_start , n_words); + dump_sequence(io, it_start, n_words); // End of track place_integer_le(tmp, 0, 4, (uint32_t)-1); - io_generic_write(io, tmp, offset, 4); - offset += 4; + io.write(tmp, 4, actual); } } @@ -374,8 +379,9 @@ bool hti_format_t::next_gap(unsigned track_no , tape_pos_t& pos , bool forward , return n_gaps == 0; } -bool hti_format_t::load_track(io_generic *io , uint64_t& offset , tape_track_t& track , bool old_format) +bool hti_format_t::load_track(util::random_read &io , tape_track_t& track , bool old_format) { + size_t actual; uint8_t tmp[ 4 ]; uint32_t tmp32; tape_pos_t delta_pos = 0; @@ -385,8 +391,7 @@ bool hti_format_t::load_track(io_generic *io , uint64_t& offset , tape_track_t& while (1) { // Read no. of words to follow - io_generic_read(io, tmp, offset, 4); - offset += 4; + io.read(tmp, 4, actual); tmp32 = pick_integer_le(tmp, 0, 4); @@ -398,8 +403,7 @@ bool hti_format_t::load_track(io_generic *io , uint64_t& offset , tape_track_t& unsigned n_words = tmp32; // Read tape position of block - io_generic_read(io, tmp, offset, 4); - offset += 4; + io.read(tmp, 4, actual); tmp32 = pick_integer_le(tmp, 0, 4); @@ -411,8 +415,7 @@ bool hti_format_t::load_track(io_generic *io , uint64_t& offset , tape_track_t& for (unsigned i = 0; i < n_words; i++) { uint16_t tmp16; - io_generic_read(io, tmp, offset, 2); - offset += 2; + io.read(tmp, 2, actual); tmp16 = pick_integer_le(tmp, 0, 2); if (!old_format) { @@ -469,19 +472,18 @@ bool hti_format_t::load_track(io_generic *io , uint64_t& offset , tape_track_t& } } -void hti_format_t::dump_sequence(io_generic *io , uint64_t& offset , tape_track_t::const_iterator it_start , unsigned n_words) +void hti_format_t::dump_sequence(util::random_read_write &io , tape_track_t::const_iterator it_start , unsigned n_words) { if (n_words) { + size_t actual; uint8_t tmp[ 8 ]; place_integer_le(tmp, 0, 4, n_words); place_integer_le(tmp, 4, 4, it_start->first); - io_generic_write(io, tmp, offset, 8); - offset += 8; + io.write(tmp, 8, actual); for (unsigned i = 0; i < n_words; i++) { place_integer_le(tmp, 0, 2, it_start->second); - io_generic_write(io, tmp, offset, 2); - offset += 2; + io.write(tmp, 2, actual); ++it_start; } } diff --git a/src/lib/formats/hti_tape.h b/src/lib/formats/hti_tape.h index 7725b87fa2a..373c971d174 100644 --- a/src/lib/formats/hti_tape.h +++ b/src/lib/formats/hti_tape.h @@ -13,10 +13,12 @@ #pragma once -#include "ioprocs.h" +#include "utilfwd.h" +#include #include + class hti_format_t { public: @@ -71,8 +73,8 @@ public: // Return number of tracks unsigned no_of_tracks() const { return m_img_format == HTI_MANCHESTER_MOD ? 1 : 2; } - bool load_tape(io_generic *io); - void save_tape(io_generic *io); + bool load_tape(util::random_read &io); + void save_tape(util::random_read_write &io); void clear_tape(); // Return physical length of a bit on tape @@ -127,8 +129,8 @@ private: // Image format image_format_t m_img_format; - bool load_track(io_generic *io , uint64_t& offset , tape_track_t& track , bool old_format); - static void dump_sequence(io_generic *io , uint64_t& offset , tape_track_t::const_iterator it_start , unsigned n_words); + bool load_track(util::random_read &io , tape_track_t& track , bool old_format); + static void dump_sequence(util::random_read_write &io , tape_track_t::const_iterator it_start , unsigned n_words); tape_pos_t word_end_pos(const track_iterator_t& it) const; void adjust_it(tape_track_t& track , track_iterator_t& it , tape_pos_t pos) const; diff --git a/src/lib/formats/hxchfe_dsk.cpp b/src/lib/formats/hxchfe_dsk.cpp index 68360f4e9bb..15598bbd746 100644 --- a/src/lib/formats/hxchfe_dsk.cpp +++ b/src/lib/formats/hxchfe_dsk.cpp @@ -101,6 +101,9 @@ #include "hxchfe_dsk.h" +#include "ioprocs.h" + + #define HFE_FORMAT_HEADER "HXCPICFE" #define HEADER_LENGTH 512 @@ -144,19 +147,21 @@ bool hfe_format::supports_save() const return true; } -int hfe_format::identify(io_generic *io, uint32_t form_factor, const std::vector &variants) +int hfe_format::identify(util::random_read &io, uint32_t form_factor, const std::vector &variants) { uint8_t header[8]; - io_generic_read(io, &header, 0, sizeof(header)); + size_t actual; + io.read_at(0, &header, sizeof(header), actual); if ( memcmp( header, HFE_FORMAT_HEADER, 8 ) ==0) { return 100; } return 0; } -bool hfe_format::load(io_generic *io, uint32_t form_factor, const std::vector &variants, floppy_image *image) +bool hfe_format::load(util::random_read &io, uint32_t form_factor, const std::vector &variants, floppy_image *image) { + size_t actual; uint8_t header[HEADER_LENGTH]; uint8_t track_table[TRACK_TABLE_LENGTH]; @@ -164,7 +169,7 @@ bool hfe_format::load(io_generic *io, uint32_t form_factor, const std::vectorget_maximal_geometry(drivecyl, driveheads); // read header - io_generic_read(io, header, 0, HEADER_LENGTH); + io.read_at(0, header, HEADER_LENGTH, actual); // get values // Format revision must be 0 @@ -236,7 +241,7 @@ bool hfe_format::load(io_generic *io, uint32_t form_factor, const std::vectorset_write_splice_position(cyl, head, 0, 0); } -bool hfe_format::save(io_generic *io, const std::vector &variants, floppy_image *image) +bool hfe_format::save(util::random_read_write &io, const std::vector &variants, floppy_image *image) { + size_t actual; std::vector cylbuf; // Create a buffer that is big enough to handle HD formats. We don't @@ -484,7 +490,7 @@ bool hfe_format::save(io_generic *io, const std::vector &variants, flo header[13] = (m_bit_rate >> 8) & 0xff; // Now write the header - io_generic_write(io, header, 0, HEADER_LENGTH); + io.write_at(0, header, HEADER_LENGTH, actual); // Set up the track lookup table // We need the encoding value to be sure about the track length @@ -505,10 +511,10 @@ bool hfe_format::save(io_generic *io, const std::vector &variants, flo for (int i=m_cylinders*4; i < TRACK_TABLE_LENGTH; i++) track_table[i] = 0xff; - io_generic_write(io, track_table, 0x200, TRACK_TABLE_LENGTH); + io.write_at(0x200, track_table, TRACK_TABLE_LENGTH, actual); } // Write the current cylinder - io_generic_write(io, &cylbuf[0], m_cyl_offset[cyl]<<9, (m_cyl_length[cyl] + 0x1ff) & 0xfe00); + io.write_at(m_cyl_offset[cyl]<<9, &cylbuf[0], (m_cyl_length[cyl] + 0x1ff) & 0xfe00, actual); } return true; } diff --git a/src/lib/formats/hxchfe_dsk.h b/src/lib/formats/hxchfe_dsk.h index 9d2dbdeae77..4ea98ed861c 100644 --- a/src/lib/formats/hxchfe_dsk.h +++ b/src/lib/formats/hxchfe_dsk.h @@ -47,9 +47,9 @@ public: hfe_format(); - virtual int identify(io_generic *io, uint32_t form_factor, const std::vector &variants) override; - virtual bool load(io_generic *io, uint32_t form_factor, const std::vector &variants, floppy_image *image) override; - virtual bool save(io_generic *io, const std::vector &variants, floppy_image *image) override; + virtual int identify(util::random_read &io, uint32_t form_factor, const std::vector &variants) override; + virtual bool load(util::random_read &io, uint32_t form_factor, const std::vector &variants, floppy_image *image) override; + virtual bool save(util::random_read_write &io, const std::vector &variants, floppy_image *image) override; virtual const char *name() const override; virtual const char *description() const override; diff --git a/src/lib/formats/hxcmfm_dsk.cpp b/src/lib/formats/hxcmfm_dsk.cpp index b6845b28e4a..e7bf03acd2f 100644 --- a/src/lib/formats/hxcmfm_dsk.cpp +++ b/src/lib/formats/hxcmfm_dsk.cpp @@ -1,10 +1,11 @@ // license:BSD-3-Clause // copyright-holders:Olivier Galibert -#include - #include "hxcmfm_dsk.h" +#include "ioprocs.h" + + #define MFM_FORMAT_HEADER "HXCMFM" #pragma pack(1) @@ -57,24 +58,26 @@ bool mfm_format::supports_save() const return true; } -int mfm_format::identify(io_generic *io, uint32_t form_factor, const std::vector &variants) +int mfm_format::identify(util::random_read &io, uint32_t form_factor, const std::vector &variants) { uint8_t header[7]; - io_generic_read(io, &header, 0, sizeof(header)); + size_t actual; + io.read_at(0, &header, sizeof(header), actual); if ( memcmp( header, MFM_FORMAT_HEADER, 6 ) ==0) { return 100; } return 0; } -bool mfm_format::load(io_generic *io, uint32_t form_factor, const std::vector &variants, floppy_image *image) +bool mfm_format::load(util::random_read &io, uint32_t form_factor, const std::vector &variants, floppy_image *image) { + size_t actual; MFMIMG header; MFMTRACKIMG trackdesc; // read header - io_generic_read(io, &header, 0, sizeof(header)); + io.read_at(0, &header, sizeof(header), actual); int drivecyl, driveheads; image->get_maximal_geometry(drivecyl, driveheads); @@ -86,12 +89,12 @@ bool mfm_format::load(io_generic *io, uint32_t form_factor, const std::vector &variants, floppy_image *image) +bool mfm_format::save(util::random_read_write &io, const std::vector &variants, floppy_image *image) { // TODO: HD support + size_t actual; MFMIMG header; int track_count, head_count; image->get_actual_geometry(track_count, head_count); @@ -124,7 +128,7 @@ bool mfm_format::save(io_generic *io, const std::vector &variants, flo header.floppyiftype = 4; header.mfmtracklistoffset = sizeof(MFMIMG); - io_generic_write(io, &header, 0, sizeof(MFMIMG)); + io.write_at(0, &header, sizeof(MFMIMG), actual); int tpos = sizeof(MFMIMG); int dpos = tpos + track_count*head_count*sizeof(MFMTRACKIMG); @@ -143,8 +147,8 @@ bool mfm_format::save(io_generic *io, const std::vector &variants, flo trackdesc.mfmtracksize = packed.size(); trackdesc.mfmtrackoffset = dpos; - io_generic_write(io, &trackdesc, tpos, sizeof(MFMTRACKIMG)); - io_generic_write(io, packed.data(), dpos, packed.size()); + io.write_at(tpos, &trackdesc, sizeof(MFMTRACKIMG), actual); + io.write_at(dpos, packed.data(), packed.size(), actual); tpos += sizeof(MFMTRACKIMG); dpos += packed.size(); diff --git a/src/lib/formats/hxcmfm_dsk.h b/src/lib/formats/hxcmfm_dsk.h index a6f884ab03e..c42190f3aae 100644 --- a/src/lib/formats/hxcmfm_dsk.h +++ b/src/lib/formats/hxcmfm_dsk.h @@ -19,9 +19,9 @@ class mfm_format : public floppy_image_format_t public: mfm_format(); - virtual int identify(io_generic *io, uint32_t form_factor, const std::vector &variants) override; - virtual bool load(io_generic *io, uint32_t form_factor, const std::vector &variants, floppy_image *image) override; - virtual bool save(io_generic *io, const std::vector &variants, floppy_image *image) override; + virtual int identify(util::random_read &io, uint32_t form_factor, const std::vector &variants) override; + virtual bool load(util::random_read &io, uint32_t form_factor, const std::vector &variants, floppy_image *image) override; + virtual bool save(util::random_read_write &io, const std::vector &variants, floppy_image *image) override; virtual const char *name() const override; virtual const char *description() const override; diff --git a/src/lib/formats/ibmxdf_dsk.cpp b/src/lib/formats/ibmxdf_dsk.cpp index b18ffad63dc..5a44290a337 100644 --- a/src/lib/formats/ibmxdf_dsk.cpp +++ b/src/lib/formats/ibmxdf_dsk.cpp @@ -32,6 +32,8 @@ #include "ibmxdf_dsk.h" +#include "ioprocs.h" + ibmxdf_format::ibmxdf_format() : wd177x_format(formats) { @@ -52,7 +54,7 @@ const char *ibmxdf_format::extensions() const return "xdf,img"; } -int ibmxdf_format::identify(io_generic *io, uint32_t form_factor, const std::vector &variants) +int ibmxdf_format::identify(util::random_read &io, uint32_t form_factor, const std::vector &variants) { int type = find_size(io, form_factor, variants); @@ -61,9 +63,11 @@ int ibmxdf_format::identify(io_generic *io, uint32_t form_factor, const std::vec return 0; } -int ibmxdf_format::find_size(io_generic *io, uint32_t form_factor, const std::vector &variants) +int ibmxdf_format::find_size(util::random_read &io, uint32_t form_factor, const std::vector &variants) { - uint64_t size = io_generic_size(io); + uint64_t size; + if (io.length(size)) + return -1; if (size != 1884160) return -1; @@ -173,7 +177,7 @@ const ibmxdf_format::format ibmxdf_format::formats_head1_track0[] = { {} }; -bool ibmxdf_format::load(io_generic *io, uint32_t form_factor, const std::vector &variants, floppy_image *image) +bool ibmxdf_format::load(util::random_read &io, uint32_t form_factor, const std::vector &variants, floppy_image *image) { int type = find_size(io, form_factor, variants); if(type == -1) @@ -207,8 +211,9 @@ bool ibmxdf_format::load(io_generic *io, uint32_t form_factor, const std::vector desc[16].p1 = get_track_dam_mfm(tf, head, track); build_sector_description(tf, sectdata, sectors, track, head); - int track_size = compute_track_size(f) * 2; // read both sides at once - io_generic_read(io, sectdata, get_image_offset(f, head, track), track_size); + int const track_size = compute_track_size(f) * 2; // read both sides at once + size_t actual; + io.read_at(get_image_offset(f, head, track), sectdata, track_size, actual); generate_track(desc, track, head, sectors, tf.sector_count, total_size, image); } diff --git a/src/lib/formats/ibmxdf_dsk.h b/src/lib/formats/ibmxdf_dsk.h index 6d37142ac30..dbb448f8ad3 100644 --- a/src/lib/formats/ibmxdf_dsk.h +++ b/src/lib/formats/ibmxdf_dsk.h @@ -23,11 +23,11 @@ public: virtual const char *description() const override; virtual const char *extensions() const override; - virtual int identify(io_generic *io, uint32_t form_factor, const std::vector &variants) override; - virtual bool load(io_generic *io, uint32_t form_factor, const std::vector &variants, floppy_image *image) override; + virtual int identify(util::random_read &io, uint32_t form_factor, const std::vector &variants) override; + virtual bool load(util::random_read &io, uint32_t form_factor, const std::vector &variants, floppy_image *image) override; virtual bool supports_save() const override { return false; } - virtual int find_size(io_generic *io, uint32_t form_factor, const std::vector &variants) override; + virtual int find_size(util::random_read &io, uint32_t form_factor, const std::vector &variants) override; virtual int get_image_offset(const format &f, int head, int track) override; virtual const wd177x_format::format &get_track_format(const format &f, int head, int track) override; diff --git a/src/lib/formats/imd_dsk.cpp b/src/lib/formats/imd_dsk.cpp index b3d4eac8229..b0e9a4159d9 100644 --- a/src/lib/formats/imd_dsk.cpp +++ b/src/lib/formats/imd_dsk.cpp @@ -10,7 +10,8 @@ #include "imd_dsk.h" -#include +#include "ioprocs.h" + #include @@ -409,25 +410,29 @@ void imd_format::fixnum(char *start, char *end) const }; } -int imd_format::identify(io_generic *io, uint32_t form_factor, const std::vector &variants) +int imd_format::identify(util::random_read &io, uint32_t form_factor, const std::vector &variants) { char h[4]; - io_generic_read(io, h, 0, 4); + size_t actual; + io.read_at(0, h, 4, actual); if(!memcmp(h, "IMD ", 4)) return 100; return 0; } -bool imd_format::load(io_generic *io, uint32_t form_factor, const std::vector &variants, floppy_image *image) +bool imd_format::load(util::random_read &io, uint32_t form_factor, const std::vector &variants, floppy_image *image) { - uint64_t size = io_generic_size(io); + uint64_t size; + if(io.length(size)) + return false; std::vector img(size); - io_generic_read(io, &img[0], 0, size); + size_t actual; + io.read_at(0, &img[0], size, actual); uint64_t pos, savepos; - for(pos=0; pos < size && img[pos] != 0x1a; pos++) {}; + for(pos=0; pos < size && img[pos] != 0x1a; pos++) { } pos++; m_comment.resize(pos); @@ -627,39 +632,34 @@ bool can_compress(const uint8_t* buffer, uint8_t ptrn, uint64_t size) return true; } -bool imd_format::save(io_generic *io, const std::vector &variants, floppy_image *image) +bool imd_format::save(util::random_read_write &io, const std::vector &variants, floppy_image *image) { - uint64_t pos = 0; - io_generic_write(io, &m_comment[0], pos, m_comment.size()); - pos += m_comment.size(); + if(io.seek(0, SEEK_SET)) + return false; + + size_t written; + io.write(&m_comment[0], m_comment.size(), written); for (int i = 0; i < m_mode.size(); i++) { - io_generic_write(io, &m_mode[i], pos++, 1); - io_generic_write(io, &m_track[i], pos++, 1); - io_generic_write(io, &m_head[i], pos++, 1); - io_generic_write(io, &m_sector_count[i], pos++, 1); - io_generic_write(io, &m_ssize[i], pos++, 1); + io.write(&m_mode[i], 1, written); + io.write(&m_track[i], 1, written); + io.write(&m_head[i], 1, written); + io.write(&m_sector_count[i], 1, written); + io.write(&m_ssize[i], 1, written); - io_generic_write(io, &m_snum[i][0], pos, m_sector_count[i]); - pos += m_sector_count[i]; + io.write(&m_snum[i][0], m_sector_count[i], written); if (m_tnum[i].size()) - { - io_generic_write(io, &m_tnum[i][0], pos, m_sector_count[i]); - pos += m_sector_count[i]; - } + io.write(&m_tnum[i][0], m_sector_count[i], written); if (m_hnum[i].size()) - { - io_generic_write(io, &m_hnum[i][0], pos, m_sector_count[i]); - pos += m_sector_count[i]; - } + io.write(&m_hnum[i][0], m_sector_count[i], written); - uint32_t actual_size = m_ssize[i] < 7 ? 128 << m_ssize[i] : 8192; - uint8_t head = m_head[i] & 0x3f; + uint32_t const actual_size = m_ssize[i] < 7 ? 128 << m_ssize[i] : 8192; + uint8_t const head = m_head[i] & 0x3f; - bool fm = m_mode[i]< 3; + bool const fm = m_mode[i]< 3; auto bitstream = generate_bitstream_from_track(m_track[i]*m_trackmult, head, fm ? 4000 : 2000, image); std::vector> sectors; @@ -674,11 +674,10 @@ bool imd_format::save(io_generic *io, const std::vector &variants, flo const auto &data = sectors[m_snum[i][j]]; - uint8_t mode; if (data.empty()) { - mode = 0; - io_generic_write(io, &mode, pos++, 1); + uint8_t const mode = 0; + io.write(&mode, 1, written); continue; } else if (data.size() < actual_size) { @@ -690,16 +689,15 @@ bool imd_format::save(io_generic *io, const std::vector &variants, flo if (can_compress(sdata, sdata[0], actual_size)) { - mode = 2; - io_generic_write(io, &mode, pos++, 1); - io_generic_write(io, &sdata[0], pos++, 1); + uint8_t const mode = 2; + io.write(&mode, 1, written); + io.write(&sdata[0], 1, written); } else { - mode = 1; - io_generic_write(io, &mode, pos++, 1); - io_generic_write(io, &sdata, pos, actual_size); - pos += actual_size; + uint8_t const mode = 1; + io.write(&mode, 1, written); + io.write(&sdata, actual_size, written); } } } diff --git a/src/lib/formats/imd_dsk.h b/src/lib/formats/imd_dsk.h index ba04a0c09e7..acf7da9b892 100644 --- a/src/lib/formats/imd_dsk.h +++ b/src/lib/formats/imd_dsk.h @@ -17,9 +17,9 @@ class imd_format : public floppy_image_format_t public: imd_format(); - virtual int identify(io_generic *io, uint32_t form_factor, const std::vector &variants) override; - virtual bool load(io_generic *io, uint32_t form_factor, const std::vector &variants, floppy_image *image) override; - virtual bool save(io_generic *io, const std::vector &variants, floppy_image* image) override; + virtual int identify(util::random_read &io, uint32_t form_factor, const std::vector &variants) override; + virtual bool load(util::random_read &io, uint32_t form_factor, const std::vector &variants, floppy_image *image) override; + virtual bool save(util::random_read_write &io, const std::vector &variants, floppy_image* image) override; virtual const char *name() const override; virtual const char *description() const override; diff --git a/src/lib/formats/img_dsk.cpp b/src/lib/formats/img_dsk.cpp index 757f695d923..73ae499c764 100644 --- a/src/lib/formats/img_dsk.cpp +++ b/src/lib/formats/img_dsk.cpp @@ -17,6 +17,7 @@ #include "img_dsk.h" #include "coretmpl.h" // BIT +#include "ioprocs.h" // Debugging @@ -40,9 +41,12 @@ img_format::img_format() { } -int img_format::identify(io_generic *io, uint32_t form_factor, const std::vector &variants) +int img_format::identify(util::random_read &io, uint32_t form_factor, const std::vector &variants) { - uint64_t size = io_generic_size(io); + uint64_t size; + if (io.length(size)) { + return 0; + } if (((form_factor == floppy_image::FF_8) || (form_factor == floppy_image::FF_UNKNOWN)) && size == IMG_IMAGE_SIZE) { @@ -52,17 +56,18 @@ int img_format::identify(io_generic *io, uint32_t form_factor, const std::vector } } -bool img_format::load(io_generic *io, uint32_t form_factor, const std::vector &variants, floppy_image *image) +bool img_format::load(util::random_read &io, uint32_t form_factor, const std::vector &variants, floppy_image *image) { - uint64_t size = io_generic_size(io); - if (size != IMG_IMAGE_SIZE) { + uint64_t size; + if (io.length(size) || (size != IMG_IMAGE_SIZE)) { return false; } image->set_variant(floppy_image::SSDD); // Suck in the whole image std::vector image_data(size); - io_generic_read(io, (void *)image_data.data(), 0, size); + size_t actual; + io.read_at(0, image_data.data(), size, actual); for (unsigned cyl = 0; cyl < TRACKS; cyl++) { std::vector track_data; @@ -96,7 +101,7 @@ bool img_format::load(io_generic *io, uint32_t form_factor, const std::vector &variants, floppy_image *image) +bool img_format::save(util::random_read_write &io, const std::vector &variants, floppy_image *image) { for (int cyl = 0; cyl < TRACKS; cyl++) { auto bitstream = generate_bitstream_from_track(cyl , 0 , CELL_SIZE , image , 0); @@ -106,7 +111,8 @@ bool img_format::save(io_generic *io, const std::vector &variants, flo while (get_next_sector(bitstream , pos , track_no , sector_no , sector_data)) { if (track_no == cyl && sector_no >= 1 && sector_no <= SECTORS) { unsigned offset_in_image = (cyl * SECTORS + sector_no - 1) * SECTOR_SIZE; - io_generic_write(io, sector_data, offset_in_image, SECTOR_SIZE); + size_t actual; + io.write_at(offset_in_image, sector_data, SECTOR_SIZE, actual); } } } diff --git a/src/lib/formats/img_dsk.h b/src/lib/formats/img_dsk.h index af9a2d62466..bbd7a0fc03e 100644 --- a/src/lib/formats/img_dsk.h +++ b/src/lib/formats/img_dsk.h @@ -27,9 +27,9 @@ public: img_format(); - virtual int identify(io_generic *io, uint32_t form_factor, const std::vector &variants) override; - virtual bool load(io_generic *io, uint32_t form_factor, const std::vector &variants, floppy_image *image) override; - virtual bool save(io_generic *io, const std::vector &variants, floppy_image *image) override; + virtual int identify(util::random_read &io, uint32_t form_factor, const std::vector &variants) override; + virtual bool load(util::random_read &io, uint32_t form_factor, const std::vector &variants, floppy_image *image) override; + virtual bool save(util::random_read_write &io, const std::vector &variants, floppy_image *image) override; virtual const char *name() const override; virtual const char *description() const override; virtual const char *extensions() const override; diff --git a/src/lib/formats/ioprocs.cpp b/src/lib/formats/ioprocs.cpp deleted file mode 100644 index 78e009aa112..00000000000 --- a/src/lib/formats/ioprocs.cpp +++ /dev/null @@ -1,214 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Nathan Woods -#include -#include -#include -#include "ioprocs.h" -#include "corefile.h" - - -/********************************************************************* - ioprocs implementation on stdio -*********************************************************************/ - -static void stdio_closeproc(void *file) -{ - fclose((FILE*)file); -} - -static int stdio_seekproc(void *file, int64_t offset, int whence) -{ - return fseek((FILE*)file, (long) offset, whence); -} - -static size_t stdio_readproc(void *file, void *buffer, size_t length) -{ - return fread(buffer, 1, length, (FILE*)file); -} - -static size_t stdio_writeproc(void *file, const void *buffer, size_t length) -{ - return fwrite(buffer, 1, length, (FILE*)file); -} - -static uint64_t stdio_filesizeproc(void *file) -{ - long l, sz; - l = ftell((FILE*)file); - if (fseek((FILE*)file, 0, SEEK_END)) - return (size_t) -1; - sz = ftell((FILE*)file); - if (fseek((FILE*)file, l, SEEK_SET)) - return (size_t) -1; - return (size_t) sz; -} - -const struct io_procs stdio_ioprocs = -{ - stdio_closeproc, - stdio_seekproc, - stdio_readproc, - stdio_writeproc, - stdio_filesizeproc -}; - -const struct io_procs stdio_ioprocs_noclose = -{ - nullptr, - stdio_seekproc, - stdio_readproc, - stdio_writeproc, - stdio_filesizeproc -}; - -/********************************************************************* - ioprocs implementation on corefile -*********************************************************************/ - -static void corefile_closeproc(void *file) -{ - delete (util::core_file*)file; -} - -static int corefile_seekproc(void *file, int64_t offset, int whence) -{ - return ((util::core_file*)file)->seek(offset, whence); -} - -static size_t corefile_readproc(void *file, void *buffer, size_t length) -{ - return ((util::core_file*)file)->read(buffer, length); -} - -static size_t corefile_writeproc(void *file, const void *buffer, size_t length) -{ - return ((util::core_file*)file)->write(buffer, length); -} - -static uint64_t corefile_filesizeproc(void *file) -{ - const auto l = ((util::core_file*)file)->tell(); - if (((util::core_file*)file)->seek(0, SEEK_END)) - return (size_t) -1; - const auto sz = ((util::core_file*)file)->tell(); - if (((util::core_file*)file)->seek(l, SEEK_SET)) - return uint64_t(-1); - return uint64_t(sz); -} - -const struct io_procs corefile_ioprocs = -{ - corefile_closeproc, - corefile_seekproc, - corefile_readproc, - corefile_writeproc, - corefile_filesizeproc -}; - -const struct io_procs corefile_ioprocs_noclose = -{ - nullptr, - corefile_seekproc, - corefile_readproc, - corefile_writeproc, - corefile_filesizeproc -}; - - - -/********************************************************************* - calls for accessing generic IO -*********************************************************************/ - -static void io_generic_seek(struct io_generic *genio, uint64_t offset) -{ - genio->procs->seekproc(genio->file, offset, SEEK_SET); -} - - - -void io_generic_close(struct io_generic *genio) -{ - if (genio->procs->closeproc) - genio->procs->closeproc(genio->file); -} - - - -void io_generic_read(struct io_generic *genio, void *buffer, uint64_t offset, size_t length) -{ - uint64_t size; - size_t bytes_read; - - size = io_generic_size(genio); - if (size <= offset) - { - bytes_read = 0; - } - else - { - io_generic_seek(genio, offset); - bytes_read = genio->procs->readproc(genio->file, buffer, length); - } - memset(((uint8_t *) buffer) + bytes_read, genio->filler, length - bytes_read); -} - - - -void io_generic_write(struct io_generic *genio, const void *buffer, uint64_t offset, size_t length) -{ - uint64_t filler_size = 0; - char filler_buffer[1024]; - size_t bytes_to_write; - uint64_t size; - - size = io_generic_size(genio); - - if (size < offset) - { - filler_size = offset - size; - offset = size; - } - - io_generic_seek(genio, offset); - - if (filler_size) - { - memset(filler_buffer, genio->filler, sizeof(filler_buffer)); - do - { - bytes_to_write = (filler_size > sizeof(filler_buffer)) ? sizeof(filler_buffer) : (size_t) filler_size; - genio->procs->writeproc(genio->file, filler_buffer, bytes_to_write); - filler_size -= bytes_to_write; - } - while(filler_size > 0); - } - - if (length > 0) - genio->procs->writeproc(genio->file, buffer, length); -} - - - -void io_generic_write_filler(struct io_generic *genio, uint8_t filler, uint64_t offset, size_t length) -{ - uint8_t buffer[512]; - size_t this_length; - - memset(buffer, filler, std::min(length, sizeof(buffer))); - - while(length > 0) - { - this_length = std::min(length, sizeof(buffer)); - io_generic_write(genio, buffer, offset, this_length); - offset += this_length; - length -= this_length; - } -} - - - -uint64_t io_generic_size(struct io_generic *genio) -{ - return genio->procs->filesizeproc(genio->file); -} diff --git a/src/lib/formats/ioprocs.h b/src/lib/formats/ioprocs.h deleted file mode 100644 index 1244873f14c..00000000000 --- a/src/lib/formats/ioprocs.h +++ /dev/null @@ -1,70 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Nathan Woods -/********************************************************************* - - ioprocs.h - - File IO abstraction layer - -*********************************************************************/ -#ifndef MAME_FORMATS_IOPROCS_H -#define MAME_FORMATS_IOPROCS_H - -#pragma once - -#include -#include - - - -/*************************************************************************** - - Type definitions - -***************************************************************************/ - -struct io_procs -{ - void (*closeproc)(void *file) = nullptr; - int (*seekproc)(void *file, int64_t offset, int whence) = nullptr; - size_t (*readproc)(void *file, void *buffer, size_t length) = nullptr; - size_t (*writeproc)(void *file, const void *buffer, size_t length) = nullptr; - uint64_t (*filesizeproc)(void *file) = nullptr; -}; - - - -struct io_generic -{ - const struct io_procs *procs = nullptr; - void *file = nullptr; - uint8_t filler = 0; -}; - - -/*************************************************************************** - - Globals - -***************************************************************************/ - -extern const io_procs stdio_ioprocs; -extern const io_procs stdio_ioprocs_noclose; -extern const io_procs corefile_ioprocs; -extern const io_procs corefile_ioprocs_noclose; - - - -/*************************************************************************** - - Prototypes - -***************************************************************************/ - -void io_generic_close(struct io_generic *genio); -void io_generic_read(struct io_generic *genio, void *buffer, uint64_t offset, size_t length); -void io_generic_write(struct io_generic *genio, const void *buffer, uint64_t offset, size_t length); -void io_generic_write_filler(struct io_generic *genio, uint8_t filler, uint64_t offset, size_t length); -uint64_t io_generic_size(struct io_generic *genio); - -#endif // MAME_FORMATS_IOPROCS_H diff --git a/src/lib/formats/ipf_dsk.cpp b/src/lib/formats/ipf_dsk.cpp index 0f1725f5c14..10c9ba2c4a9 100644 --- a/src/lib/formats/ipf_dsk.cpp +++ b/src/lib/formats/ipf_dsk.cpp @@ -2,6 +2,8 @@ // copyright-holders:Olivier Galibert #include "ipf_dsk.h" +#include "ioprocs.h" + #include @@ -27,11 +29,12 @@ bool ipf_format::supports_save() const return false; } -int ipf_format::identify(io_generic *io, uint32_t form_factor, const std::vector &variants) +int ipf_format::identify(util::random_read &io, uint32_t form_factor, const std::vector &variants) { static const uint8_t refh[12] = { 0x43, 0x41, 0x50, 0x53, 0x00, 0x00, 0x00, 0x0c, 0x1c, 0xd5, 0x73, 0xba }; uint8_t h[12]; - io_generic_read(io, h, 0, 12); + size_t actual; + io.read_at(0, h, 12, actual); if(!memcmp(h, refh, 12)) return 100; @@ -39,14 +42,16 @@ int ipf_format::identify(io_generic *io, uint32_t form_factor, const std::vector return 0; } -bool ipf_format::load(io_generic *io, uint32_t form_factor, const std::vector &variants, floppy_image *image) +bool ipf_format::load(util::random_read &io, uint32_t form_factor, const std::vector &variants, floppy_image *image) { - ipf_decode dec; - uint64_t size = io_generic_size(io); + uint64_t size; + if (io.length(size)) + return false; std::vector data(size); - io_generic_read(io, &data[0], 0, size); - bool res = dec.parse(data, image); - return res; + size_t actual; + io.read_at(0, &data[0], size, actual); + ipf_decode dec; + return dec.parse(data, image); } uint32_t ipf_format::ipf_decode::r32(const uint8_t *p) diff --git a/src/lib/formats/ipf_dsk.h b/src/lib/formats/ipf_dsk.h index d848a5bb3a0..28d552d5812 100644 --- a/src/lib/formats/ipf_dsk.h +++ b/src/lib/formats/ipf_dsk.h @@ -12,8 +12,8 @@ class ipf_format : public floppy_image_format_t { public: - virtual int identify(io_generic *io, uint32_t form_factor, const std::vector &variants) override; - virtual bool load(io_generic *io, uint32_t form_factor, const std::vector &variants, floppy_image *image) override; + virtual int identify(util::random_read &io, uint32_t form_factor, const std::vector &variants) override; + virtual bool load(util::random_read &io, uint32_t form_factor, const std::vector &variants, floppy_image *image) override; virtual const char *name() const override; virtual const char *description() const override; diff --git a/src/lib/formats/jfd_dsk.cpp b/src/lib/formats/jfd_dsk.cpp index 947d6ba4022..7a1da472356 100644 --- a/src/lib/formats/jfd_dsk.cpp +++ b/src/lib/formats/jfd_dsk.cpp @@ -158,9 +158,13 @@ *********************************************************************/ -#include #include "formats/jfd_dsk.h" +#include "ioprocs.h" + +#include + + static const uint8_t JFD_HEADER[4] = { 'J', 'F', 'D', 'I' }; static const uint8_t GZ_HEADER[2] = { 0x1f, 0x8b }; @@ -183,11 +187,14 @@ const char *jfd_format::extensions() const return "jfd"; } -int jfd_format::identify(io_generic *io, uint32_t form_factor, const std::vector &variants) +int jfd_format::identify(util::random_read &io, uint32_t form_factor, const std::vector &variants) { - uint64_t size = io_generic_size(io); + uint64_t size; + if (io.length(size)) + return 0; std::vector img(size); - io_generic_read(io, &img[0], 0, size); + size_t actual; + io.read_at(0, &img[0], size, actual); int err; std::vector gz_ptr(4); @@ -221,11 +228,15 @@ int jfd_format::identify(io_generic *io, uint32_t form_factor, const std::vector return 0; } -bool jfd_format::load(io_generic *io, uint32_t form_factor, const std::vector &variants, floppy_image *image) +bool jfd_format::load(util::random_read &io, uint32_t form_factor, const std::vector &variants, floppy_image *image) { - uint64_t size = io_generic_size(io); + uint64_t size; + if (io.length(size)) + return false; + std::vector img(size); - io_generic_read(io, &img[0], 0, size); + size_t actual; + io.read_at(0, &img[0], size, actual); int err; std::vector gz_ptr; diff --git a/src/lib/formats/jfd_dsk.h b/src/lib/formats/jfd_dsk.h index 75b9910c426..7231ccf3460 100644 --- a/src/lib/formats/jfd_dsk.h +++ b/src/lib/formats/jfd_dsk.h @@ -23,8 +23,8 @@ public: virtual const char *description() const override; virtual const char *extensions() const override; - virtual int identify(io_generic *io, uint32_t form_factor, const std::vector &variants) override; - virtual bool load(io_generic *io, uint32_t form_factor, const std::vector &variants, floppy_image *image) override; + virtual int identify(util::random_read &io, uint32_t form_factor, const std::vector &variants) override; + virtual bool load(util::random_read &io, uint32_t form_factor, const std::vector &variants, floppy_image *image) override; virtual bool supports_save() const override; }; diff --git a/src/lib/formats/jvc_dsk.cpp b/src/lib/formats/jvc_dsk.cpp index 8332f86bace..c71f2c3be06 100644 --- a/src/lib/formats/jvc_dsk.cpp +++ b/src/lib/formats/jvc_dsk.cpp @@ -106,6 +106,8 @@ #include "jvc_dsk.h" +#include "ioprocs.h" + jvc_format::jvc_format() { @@ -126,19 +128,22 @@ const char *jvc_format::extensions() const return "jvc,dsk"; } -bool jvc_format::parse_header(io_generic *io, int &header_size, int &tracks, int &heads, int §ors, int §or_size, int &base_sector_id) +bool jvc_format::parse_header(util::random_read &io, int &header_size, int &tracks, int &heads, int §ors, int §or_size, int &base_sector_id) { // The JVC format has a header whose size is the size of the image modulo 256. Currently, we only // handle up to five header bytes - uint64_t size = io_generic_size(io); + uint64_t size; + if (io.length(size)) + return false; header_size = size % 256; uint8_t header[5]; // if we know that this is a header of a bad size, we can fail immediately; otherwise read the header + size_t actual; if (header_size >= sizeof(header)) return false; if (header_size > 0) - io_generic_read(io, header, 0, header_size); + io.read_at(0, header, header_size, actual); // default values heads = 1; @@ -168,13 +173,13 @@ bool jvc_format::parse_header(io_generic *io, int &header_size, int &tracks, int return tracks * heads * sectors * sector_size == (size - header_size); } -int jvc_format::identify(io_generic *io, uint32_t form_factor, const std::vector &variants) +int jvc_format::identify(util::random_read &io, uint32_t form_factor, const std::vector &variants) { int header_size, tracks, heads, sectors, sector_size, sector_base_id; return parse_header(io, header_size, tracks, heads, sectors, sector_size, sector_base_id) ? 50 : 0; } -bool jvc_format::load(io_generic *io, uint32_t form_factor, const std::vector &variants, floppy_image *image) +bool jvc_format::load(util::random_read &io, uint32_t form_factor, const std::vector &variants, floppy_image *image) { int header_size, track_count, head_count, sector_count, sector_size, sector_base_id; @@ -210,7 +215,8 @@ bool jvc_format::load(io_generic *io, uint32_t form_factor, const std::vector &variants, floppy_image *image) +bool jvc_format::save(util::random_read_write &io, const std::vector &variants, floppy_image *image) { uint64_t file_offset = 0; @@ -236,7 +242,8 @@ bool jvc_format::save(io_generic *io, const std::vector &variants, flo uint8_t header[2]; header[0] = 18; header[1] = 2; - io_generic_write(io, header, file_offset, sizeof(header)); + size_t actual; + io.write_at(file_offset, header, sizeof(header), actual); file_offset += sizeof(header); } @@ -256,7 +263,8 @@ bool jvc_format::save(io_generic *io, const std::vector &variants, flo return false; } - io_generic_write(io, sectors[1 + i].data(), file_offset, 256); + size_t actual; + io.write_at(file_offset, sectors[1 + i].data(), 256, actual); file_offset += 256; } } diff --git a/src/lib/formats/jvc_dsk.h b/src/lib/formats/jvc_dsk.h index 7c744a0acb5..1b8b59c725f 100644 --- a/src/lib/formats/jvc_dsk.h +++ b/src/lib/formats/jvc_dsk.h @@ -35,13 +35,13 @@ public: virtual const char *description() const override; virtual const char *extensions() const override; - virtual int identify(io_generic *io, uint32_t form_factor, const std::vector &variants) override; - virtual bool load(io_generic *io, uint32_t form_factor, const std::vector &variants, floppy_image *image) override; - virtual bool save(io_generic *io, const std::vector &variants, floppy_image *image) override; + virtual int identify(util::random_read &io, uint32_t form_factor, const std::vector &variants) override; + virtual bool load(util::random_read &io, uint32_t form_factor, const std::vector &variants, floppy_image *image) override; + virtual bool save(util::random_read_write &io, const std::vector &variants, floppy_image *image) override; virtual bool supports_save() const override; private: - bool parse_header(io_generic *io, int &header_size, int &tracks, int &heads, int §ors, int §or_size, int &base_sector_id); + bool parse_header(util::random_read &io, int &header_size, int &tracks, int &heads, int §ors, int §or_size, int &base_sector_id); }; extern const floppy_format_type FLOPPY_JVC_FORMAT; diff --git a/src/lib/formats/m20_dsk.cpp b/src/lib/formats/m20_dsk.cpp index 60b2ae58176..05c52c2f211 100644 --- a/src/lib/formats/m20_dsk.cpp +++ b/src/lib/formats/m20_dsk.cpp @@ -16,6 +16,9 @@ #include "m20_dsk.h" +#include "ioprocs.h" + + m20_format::m20_format() { } @@ -40,21 +43,27 @@ bool m20_format::supports_save() const return true; } -int m20_format::identify(io_generic *io, uint32_t form_factor, const std::vector &variants) +int m20_format::identify(util::random_read &io, uint32_t form_factor, const std::vector &variants) { - if(io_generic_size(io) == 286720) + uint64_t size; + if (io.length(size)) + return 0; + + if (size == 286720) return 50; + return 0; } -bool m20_format::load(io_generic *io, uint32_t form_factor, const std::vector &variants, floppy_image *image) +bool m20_format::load(util::random_read &io, uint32_t form_factor, const std::vector &variants, floppy_image *image) { for (int track = 0; track < 35; track++) for (int head = 0; head < 2; head ++) { bool mfm = track || head; desc_pc_sector sects[16]; uint8_t sectdata[16*256]; - io_generic_read(io, sectdata, 16*256*(track*2+head), 16*256); + size_t actual; + io.read_at(16*256*(track*2+head), sectdata, 16*256, actual); for (int i = 0; i < 16; i++) { int j = i/2 + (i & 1 ? 0 : 8); sects[i].track = track; @@ -76,7 +85,7 @@ bool m20_format::load(io_generic *io, uint32_t form_factor, const std::vector &variants, floppy_image *image) +bool m20_format::save(util::random_read_write &io, const std::vector &variants, floppy_image *image) { uint64_t file_offset = 0; @@ -87,26 +96,27 @@ bool m20_format::save(io_generic *io, const std::vector &variants, flo auto bitstream = generate_bitstream_from_track(0, 0, 4000, image); auto sectors = extract_sectors_from_bitstream_fm_pc(bitstream); - for (int i = 0; i < 16; i++) - { - io_generic_write(io, sectors[i + 1].data(), file_offset, 128); + for (int i = 0; i < 16; i++) { + size_t actual; + io.write_at(file_offset, sectors[i + 1].data(), 128, actual); file_offset += 256; //128; } // rest are mfm tracks - for (int track = 0; track < track_count; track++) - { - for (int head = 0; head < head_count; head++) - { + for (int track = 0; track < track_count; track++) { + for (int head = 0; head < head_count; head++) { // skip track 0, head 0 - if (track == 0) { if (head_count == 1) break; else head++; } + if (track == 0) { + if (head_count == 1) break; + else head++; + } bitstream = generate_bitstream_from_track(track, head, 2000, image); sectors = extract_sectors_from_bitstream_mfm_pc(bitstream); - for (int i = 0; i < 16; i++) - { - io_generic_write(io, sectors[i + 1].data(), file_offset, 256); + for (int i = 0; i < 16; i++) { + size_t actual; + io.write_at(file_offset, sectors[i + 1].data(), 256, actual); file_offset += 256; } } diff --git a/src/lib/formats/m20_dsk.h b/src/lib/formats/m20_dsk.h index ed8a7bc4517..d9bd7a45425 100644 --- a/src/lib/formats/m20_dsk.h +++ b/src/lib/formats/m20_dsk.h @@ -18,9 +18,9 @@ class m20_format : public floppy_image_format_t { public: m20_format(); - virtual int identify(io_generic *io, uint32_t form_factor, const std::vector &variants) override; - virtual bool load(io_generic *io, uint32_t form_factor, const std::vector &variants, floppy_image *image) override; - virtual bool save(io_generic *io, const std::vector &variants, floppy_image *image) override; + virtual int identify(util::random_read &io, uint32_t form_factor, const std::vector &variants) override; + virtual bool load(util::random_read &io, uint32_t form_factor, const std::vector &variants, floppy_image *image) override; + virtual bool save(util::random_read_write &io, const std::vector &variants, floppy_image *image) override; virtual const char *name() const override; virtual const char *description() const override; diff --git a/src/lib/formats/mdos_dsk.cpp b/src/lib/formats/mdos_dsk.cpp index b96be2f327e..e49d825ea9a 100644 --- a/src/lib/formats/mdos_dsk.cpp +++ b/src/lib/formats/mdos_dsk.cpp @@ -50,7 +50,9 @@ */ #include "mdos_dsk.h" -#include "formats/imageutl.h" +#include "imageutl.h" + +#include "ioprocs.h" mdos_format::mdos_format() : wd177x_format(formats) @@ -72,12 +74,13 @@ const char *mdos_format::extensions() const return "dsk"; } -int mdos_format::identify(io_generic *io, uint32_t form_factor, const std::vector &variants) +int mdos_format::identify(util::random_read &io, uint32_t form_factor, const std::vector &variants) { - int type = find_size(io, form_factor, variants); + int type = find_size(io, form_factor, variants); if (type != -1) return 75; + return 0; } @@ -109,12 +112,15 @@ int mdos_format::parse_date_field(uint8_t *str) return (high - 0x30) * 10 + (low - 0x30); } -int mdos_format::find_size(io_generic *io, uint32_t form_factor, const std::vector &variants) +int mdos_format::find_size(util::random_read &io, uint32_t form_factor, const std::vector &variants) { - uint64_t size = io_generic_size(io); + size_t actual; + uint64_t size; + if (io.length(size)) + return -1; // Look at the disk id sector. - io_generic_read(io, &info, 0, sizeof(struct disk_id_sector)); + io.read_at(0, &info, sizeof(struct disk_id_sector), actual); LOG_FORMATS("MDOS floppy dsk: size %d bytes, %d total sectors, %d remaining bytes, expected form factor %x\n", (uint32_t)size, (uint32_t)size / 128, (uint32_t)size % 128, form_factor); @@ -176,8 +182,8 @@ int mdos_format::find_size(io_generic *io, uint32_t form_factor, const std::vect // the extent of the disk are free or available. uint8_t cluster_allocation[128], cluster_available[128]; - io_generic_read(io, &cluster_allocation, 1 * 128, sizeof(cluster_allocation)); - io_generic_read(io, &cluster_available, 2 * 128, sizeof(cluster_available)); + io.read_at(1 * 128, &cluster_allocation, sizeof(cluster_allocation), actual); + io.read_at(2 * 128, &cluster_available, sizeof(cluster_available), actual); for (int cluster = 0; cluster < sizeof(cluster_allocation) * 8; cluster++) { if (cluster * 4 * 128 + 4 * 128 > size) { diff --git a/src/lib/formats/mdos_dsk.h b/src/lib/formats/mdos_dsk.h index 65e7bca9f14..56dd29c9954 100644 --- a/src/lib/formats/mdos_dsk.h +++ b/src/lib/formats/mdos_dsk.h @@ -19,8 +19,8 @@ public: virtual const char *name() const override; virtual const char *description() const override; virtual const char *extensions() const override; - virtual int identify(io_generic *io, uint32_t form_factor, const std::vector &variants) override; - virtual int find_size(io_generic *io, uint32_t form_factor, const std::vector &variants) override; + virtual int identify(util::random_read &io, uint32_t form_factor, const std::vector &variants) override; + virtual int find_size(util::random_read &io, uint32_t form_factor, const std::vector &variants) override; virtual const wd177x_format::format &get_track_format(const format &f, int head, int track) override; private: diff --git a/src/lib/formats/mfi_dsk.cpp b/src/lib/formats/mfi_dsk.cpp index 7670bf6bfb9..8272253c36a 100644 --- a/src/lib/formats/mfi_dsk.cpp +++ b/src/lib/formats/mfi_dsk.cpp @@ -1,10 +1,12 @@ // license:BSD-3-Clause // copyright-holders:Olivier Galibert -#include - #include "mfi_dsk.h" + +#include "ioprocs.h" + #include + /* Mess floppy image structure: @@ -94,11 +96,12 @@ bool mfi_format::supports_save() const return true; } -int mfi_format::identify(io_generic *io, uint32_t form_factor, const std::vector &variants) +int mfi_format::identify(util::random_read &io, uint32_t form_factor, const std::vector &variants) { header h; - io_generic_read(io, &h, 0, sizeof(header)); + size_t actual; + io.read_at(0, &h, sizeof(header), actual); if(memcmp( h.sign, sign, 16 ) == 0 && (h.cyl_count & CYLINDER_MASK) <= 84 && (h.cyl_count >> RESOLUTION_SHIFT) < 3 && @@ -108,15 +111,16 @@ int mfi_format::identify(io_generic *io, uint32_t form_factor, const std::vector return 0; } -bool mfi_format::load(io_generic *io, uint32_t form_factor, const std::vector &variants, floppy_image *image) +bool mfi_format::load(util::random_read &io, uint32_t form_factor, const std::vector &variants, floppy_image *image) { + size_t actual; header h; entry entries[84*2*4]; - io_generic_read(io, &h, 0, sizeof(header)); + io.read_at(0, &h, sizeof(header), actual); int resolution = h.cyl_count >> RESOLUTION_SHIFT; h.cyl_count &= CYLINDER_MASK; - io_generic_read(io, &entries, sizeof(header), (h.cyl_count << resolution)*h.head_count*sizeof(entry)); + io.read_at(sizeof(header), &entries, (h.cyl_count << resolution)*h.head_count*sizeof(entry), actual); image->set_form_variant(h.form_factor, h.variant); @@ -139,7 +143,7 @@ bool mfi_format::load(io_generic *io, uint32_t form_factor, const std::vectorcompressed_size); - io_generic_read(io, &compressed[0], ent->offset, ent->compressed_size); + io.read_at(ent->offset, &compressed[0], ent->compressed_size, actual); unsigned int cell_count = ent->uncompressed_size/4; std::vector &trackbuf = image->get_buffer(cyl >> 2, head, cyl & 3);; @@ -169,8 +173,9 @@ bool mfi_format::load(io_generic *io, uint32_t form_factor, const std::vector &variants, floppy_image *image) +bool mfi_format::save(util::random_read_write &io, const std::vector &variants, floppy_image *image) { + size_t actual; int tracks, heads; image->get_actual_geometry(tracks, heads); int resolution = image->get_resolution(); @@ -190,7 +195,7 @@ bool mfi_format::save(io_generic *io, const std::vector &variants, flo h.form_factor = image->get_form_factor(); h.variant = image->get_variant(); - io_generic_write(io, &h, 0, sizeof(header)); + io.write_at(0, &h, sizeof(header), actual); memset(entries, 0, sizeof(entries)); @@ -226,11 +231,11 @@ bool mfi_format::save(io_generic *io, const std::vector &variants, flo entries[epos].write_splice = image->get_write_splice_position(track >> 2, head, track & 3); epos++; - io_generic_write(io, postcomp.get(), pos, csize); + io.write_at(pos, postcomp.get(), csize, actual); pos += csize; } - io_generic_write(io, entries, sizeof(header), (tracks << resolution)*heads*sizeof(entry)); + io.write_at(sizeof(header), entries, (tracks << resolution)*heads*sizeof(entry), actual); return true; } diff --git a/src/lib/formats/mfi_dsk.h b/src/lib/formats/mfi_dsk.h index 129a9ee599e..d0dd36c3d68 100644 --- a/src/lib/formats/mfi_dsk.h +++ b/src/lib/formats/mfi_dsk.h @@ -12,9 +12,9 @@ class mfi_format : public floppy_image_format_t public: mfi_format(); - virtual int identify(io_generic *io, uint32_t form_factor, const std::vector &variants) override; - virtual bool load(io_generic *io, uint32_t form_factor, const std::vector &variants, floppy_image *image) override; - virtual bool save(io_generic *io, const std::vector &variants, floppy_image *image) override; + virtual int identify(util::random_read &io, uint32_t form_factor, const std::vector &variants) override; + virtual bool load(util::random_read &io, uint32_t form_factor, const std::vector &variants, floppy_image *image) override; + virtual bool save(util::random_read_write &io, const std::vector &variants, floppy_image *image) override; virtual const char *name() const override; virtual const char *description() const override; diff --git a/src/lib/formats/mfm_hd.cpp b/src/lib/formats/mfm_hd.cpp index 98d8079443c..738f0999863 100644 --- a/src/lib/formats/mfm_hd.cpp +++ b/src/lib/formats/mfm_hd.cpp @@ -294,9 +294,9 @@ int mfmhd_generic_format::chs_to_lba(int cylinder, int head, int sector) else return -1; } -chd_error mfmhd_generic_format::load(chd_file* chdfile, uint16_t* trackimage, int tracksize, int cylinder, int head) +std::error_condition mfmhd_generic_format::load(chd_file* chdfile, uint16_t* trackimage, int tracksize, int cylinder, int head) { - chd_error state = CHDERR_NONE; + std::error_condition state; uint8_t sector_content[16384]; int sectorcount = m_param.sectors_per_track; @@ -382,8 +382,9 @@ chd_error mfmhd_generic_format::load(chd_file* chdfile, uint16_t* trackimage, in int lbaposition = chs_to_lba(cylinder, head, sec_number); if (lbaposition>=0) { - chd_error state = chdfile->read_units(lbaposition, sector_content); - if (state != CHDERR_NONE) break; + state = chdfile->read_units(lbaposition, sector_content); + if (state) + break; } else { @@ -413,7 +414,7 @@ chd_error mfmhd_generic_format::load(chd_file* chdfile, uint16_t* trackimage, in if (TRACE_LAYOUT) osd_printf_verbose("\n"); // Gap 4 - if (state == CHDERR_NONE) + if (!state) { // Fill the rest with 0x4e mfm_encode(trackimage, position, 0x4e, tracksize-position); @@ -433,7 +434,7 @@ enum CHECK_CRC }; -chd_error mfmhd_generic_format::save(chd_file* chdfile, uint16_t* trackimage, int tracksize, int current_cylinder, int current_head) +std::error_condition mfmhd_generic_format::save(chd_file* chdfile, uint16_t* trackimage, int tracksize, int current_cylinder, int current_head) { if (TRACE_RWTRACK) osd_printf_verbose("%s: write back (c=%d,h=%d) to CHD\n", tag(), current_cylinder, current_head); @@ -490,7 +491,7 @@ chd_error mfmhd_generic_format::save(chd_file* chdfile, uint16_t* trackimage, in bool countgap3 = false; bool countsync = false; - chd_error chdstate = CHDERR_NONE; + std::error_condition chdstate; if (TRACE_IMAGE) { @@ -643,7 +644,7 @@ chd_error mfmhd_generic_format::save(chd_file* chdfile, uint16_t* trackimage, in if (TRACE_DETAIL) osd_printf_verbose("%s: Writing sector chs=(%d,%d,%d) to CHD\n", tag(), current_cylinder, current_head, sector); chdstate = chdfile->write_units(chs_to_lba(current_cylinder, current_head, sector), buffer); - if (chdstate != CHDERR_NONE) + if (chdstate) { osd_printf_verbose("%s: Write error while writing sector chs=(%d,%d,%d)\n", tag(), cylinder, head, sector); } diff --git a/src/lib/formats/mfm_hd.h b/src/lib/formats/mfm_hd.h index 7d28adc518d..472062d1440 100644 --- a/src/lib/formats/mfm_hd.h +++ b/src/lib/formats/mfm_hd.h @@ -151,10 +151,10 @@ public: virtual ~mfmhd_image_format_t() {}; // Load the image. - virtual chd_error load(chd_file* chdfile, uint16_t* trackimage, int tracksize, int cylinder, int head) = 0; + virtual std::error_condition load(chd_file* chdfile, uint16_t* trackimage, int tracksize, int cylinder, int head) = 0; // Save the image. - virtual chd_error save(chd_file* chdfile, uint16_t* trackimage, int tracksize, int cylinder, int head) = 0; + virtual std::error_condition save(chd_file* chdfile, uint16_t* trackimage, int tracksize, int cylinder, int head) = 0; // Return the original parameters of the image mfmhd_layout_params* get_initial_params() { return &m_param_old; } @@ -196,8 +196,8 @@ class mfmhd_generic_format : public mfmhd_image_format_t { public: mfmhd_generic_format() { m_devtag = std::string("mfmhd_generic_format"); }; - chd_error load(chd_file* chdfile, uint16_t* trackimage, int tracksize, int cylinder, int head) override; - chd_error save(chd_file* chdfile, uint16_t* trackimage, int tracksize, int cylinder, int head) override; + std::error_condition load(chd_file* chdfile, uint16_t* trackimage, int tracksize, int cylinder, int head) override; + std::error_condition save(chd_file* chdfile, uint16_t* trackimage, int tracksize, int cylinder, int head) override; // Yes, we want to save all parameters virtual bool save_param(mfmhd_param_t type) override { return true; } diff --git a/src/lib/formats/nfd_dsk.cpp b/src/lib/formats/nfd_dsk.cpp index 1a0430f9af1..4a51e0db54c 100644 --- a/src/lib/formats/nfd_dsk.cpp +++ b/src/lib/formats/nfd_dsk.cpp @@ -77,10 +77,11 @@ *********************************************************************/ - #include - #include "nfd_dsk.h" +#include "ioprocs.h" + + nfd_format::nfd_format() { } @@ -100,10 +101,11 @@ const char *nfd_format::extensions() const return "nfd"; } -int nfd_format::identify(io_generic *io, uint32_t form_factor, const std::vector &variants) +int nfd_format::identify(util::random_read &io, uint32_t form_factor, const std::vector &variants) { uint8_t h[16]; - io_generic_read(io, h, 0, 16); + size_t actual; + io.read_at(0, h, 16, actual); if (strncmp((const char *)h, "T98FDDIMAGE.R0", 14) == 0 || strncmp((const char *)h, "T98FDDIMAGE.R1", 14) == 0) return 100; @@ -111,11 +113,14 @@ int nfd_format::identify(io_generic *io, uint32_t form_factor, const std::vector return 0; } -bool nfd_format::load(io_generic *io, uint32_t form_factor, const std::vector &variants, floppy_image *image) +bool nfd_format::load(util::random_read &io, uint32_t form_factor, const std::vector &variants, floppy_image *image) { - uint64_t size = io_generic_size(io); + size_t actual; + uint64_t size; + if (io.length(size)) + return false; uint8_t h[0x120], hsec[0x10]; - io_generic_read(io, h, 0, 0x120); + io.read_at(0, h, 0x120, actual); int format_version = !strncmp((const char *)h, "T98FDDIMAGE.R0", 14) ? 0 : 1; // sector map (the 164th entry is only used by rev.1 format, loops with track < 163 are correct for rev.0) @@ -140,7 +145,7 @@ bool nfd_format::load(io_generic *io, uint32_t form_factor, const std::vector &variants) override; - virtual bool load(io_generic *io, uint32_t form_factor, const std::vector &variants, floppy_image *image) override; + virtual int identify(util::random_read &io, uint32_t form_factor, const std::vector &variants) override; + virtual bool load(util::random_read &io, uint32_t form_factor, const std::vector &variants, floppy_image *image) override; virtual const char *name() const override; virtual const char *description() const override; diff --git a/src/lib/formats/opd_dsk.cpp b/src/lib/formats/opd_dsk.cpp index e105d53d678..964b30b75a0 100644 --- a/src/lib/formats/opd_dsk.cpp +++ b/src/lib/formats/opd_dsk.cpp @@ -30,12 +30,13 @@ const char *opd_format::extensions() const return "opd,opu"; } -int opd_format::identify(io_generic *io, uint32_t form_factor, const std::vector &variants) +int opd_format::identify(util::random_read &io, uint32_t form_factor, const std::vector &variants) { - int type = find_size(io, form_factor, variants); + int const type = find_size(io, form_factor, variants); if (type != -1) return 90; + return 0; } diff --git a/src/lib/formats/opd_dsk.h b/src/lib/formats/opd_dsk.h index 9a4205314ec..9236320f154 100644 --- a/src/lib/formats/opd_dsk.h +++ b/src/lib/formats/opd_dsk.h @@ -21,7 +21,7 @@ class opd_format : public wd177x_format public: opd_format(); - virtual int identify(io_generic *io, uint32_t form_factor, const std::vector &variants) override; + virtual int identify(util::random_read &io, uint32_t form_factor, const std::vector &variants) override; virtual int get_image_offset(const format &f, int head, int track) override; virtual const char *name() const override; virtual const char *description() const override; diff --git a/src/lib/formats/oric_dsk.cpp b/src/lib/formats/oric_dsk.cpp index 22d70124572..f5b0783a112 100644 --- a/src/lib/formats/oric_dsk.cpp +++ b/src/lib/formats/oric_dsk.cpp @@ -8,7 +8,9 @@ *********************************************************************/ -#include "formats/oric_dsk.h" +#include "oric_dsk.h" + +#include "ioprocs.h" const char *oric_dsk_format::name() const @@ -31,10 +33,11 @@ bool oric_dsk_format::supports_save() const return true; } -int oric_dsk_format::identify(io_generic *io, uint32_t form_factor, const std::vector &variants) +int oric_dsk_format::identify(util::random_read &io, uint32_t form_factor, const std::vector &variants) { uint8_t h[256]; - io_generic_read(io, h, 0, 256); + size_t actual; + io.read_at(0, h, 256, actual); if(memcmp(h, "MFM_DISK", 8)) return 0; @@ -43,27 +46,30 @@ int oric_dsk_format::identify(io_generic *io, uint32_t form_factor, const std::v int tracks = (h[15] << 24) | (h[14] << 16) | (h[13] << 8) | h[12]; int geom = (h[19] << 24) | (h[18] << 16) | (h[17] << 8) | h[16]; - int size = io_generic_size(io); + uint64_t size; + if(io.length(size)) + return 0; if(sides < 0 || sides > 2 || geom != 1 || size != 256+6400*sides*tracks) return 0; return 100; } -bool oric_dsk_format::load(io_generic *io, uint32_t form_factor, const std::vector &variants, floppy_image *image) +bool oric_dsk_format::load(util::random_read &io, uint32_t form_factor, const std::vector &variants, floppy_image *image) { + size_t actual; uint8_t h[256]; uint8_t t[6250+3]; t[6250] = t[6251] = t[6252] = 0; - io_generic_read(io, h, 0, 256); + io.read_at(0, h, 256, actual); int sides = (h[11] << 24) | (h[10] << 16) | (h[ 9] << 8) | h[ 8]; int tracks = (h[15] << 24) | (h[14] << 16) | (h[13] << 8) | h[12]; for(int side=0; side stream; int sector_size = 128; for(int i=0; i<6250; i++) { @@ -99,8 +105,9 @@ bool oric_dsk_format::load(io_generic *io, uint32_t form_factor, const std::vect return true; } -bool oric_dsk_format::save(io_generic *io, const std::vector &variants, floppy_image *image) +bool oric_dsk_format::save(util::random_read_write &io, const std::vector &variants, floppy_image *image) { + // FIXME: surely this should return false, since it does't actually save anything? return true; } @@ -127,28 +134,35 @@ bool oric_jasmin_format::supports_save() const return true; } -int oric_jasmin_format::identify(io_generic *io, uint32_t form_factor, const std::vector &variants) +int oric_jasmin_format::identify(util::random_read &io, uint32_t form_factor, const std::vector &variants) { - int size = io_generic_size(io); - bool can_ds = variants.empty() || has_variant(variants, floppy_image::DSDD); + uint64_t size; + if(io.length(size)) + return 0; + + bool const can_ds = variants.empty() || has_variant(variants, floppy_image::DSDD); if(size == 41*17*256 || (can_ds && size == 41*17*256*2)) return 50; return 0; } -bool oric_jasmin_format::load(io_generic *io, uint32_t form_factor, const std::vector &variants, floppy_image *image) +bool oric_jasmin_format::load(util::random_read &io, uint32_t form_factor, const std::vector &variants, floppy_image *image) { - int size = io_generic_size(io); - bool can_ds = variants.empty() || has_variant(variants, floppy_image::DSDD); + uint64_t size; + if(io.length(size)) + return false; + + bool const can_ds = variants.empty() || has_variant(variants, floppy_image::DSDD); if(size != 41*17*256 && (!can_ds || size != 41*17*256*2)) return false; - int heads = size == 41*17*256 ? 1 : 2; + int const heads = size == 41*17*256 ? 1 : 2; std::vector data(size); - io_generic_read(io, data.data(), 0, size); + size_t actual; + io.read_at(0, data.data(), size, actual); for(int head = 0; head != heads; head++) for(int track = 0; track != 41; track++) { @@ -173,7 +187,7 @@ bool oric_jasmin_format::load(io_generic *io, uint32_t form_factor, const std::v return true; } -bool oric_jasmin_format::save(io_generic *io, const std::vector &variants, floppy_image *image) +bool oric_jasmin_format::save(util::random_read_write &io, const std::vector &variants, floppy_image *image) { int tracks, heads; image->get_actual_geometry(tracks, heads); @@ -191,8 +205,9 @@ bool oric_jasmin_format::save(io_generic *io, const std::vector &varia for(int track = 0; track != 41; track++) { auto sectors = extract_sectors_from_bitstream_mfm_pc(generate_bitstream_from_track(track, head, 2000, image)); for(unsigned int sector = 0; sector != 17; sector ++) { - const uint8_t *data = sector+1 < sectors.size() && !sectors[sector+1].empty() ? sectors[sector+1].data() : zero; - io_generic_write(io, data, 256 * (sector + track*17 + head*17*41), 256); + uint8_t const *const data = (sector+1 < sectors.size() && !sectors[sector+1].empty()) ? sectors[sector+1].data() : zero; + size_t actual; + io.write_at(256 * (sector + track*17 + head*17*41), data, 256, actual); } } return true; diff --git a/src/lib/formats/oric_dsk.h b/src/lib/formats/oric_dsk.h index e42b876e52f..6fd1021384b 100644 --- a/src/lib/formats/oric_dsk.h +++ b/src/lib/formats/oric_dsk.h @@ -18,9 +18,9 @@ class oric_dsk_format : public floppy_image_format_t { public: oric_dsk_format() = default; - virtual int identify(io_generic *io, uint32_t form_factor, const std::vector &variants) override; - virtual bool load(io_generic *io, uint32_t form_factor, const std::vector &variants, floppy_image *image) override; - virtual bool save(io_generic *io, const std::vector &variants, floppy_image *image) override; + virtual int identify(util::random_read &io, uint32_t form_factor, const std::vector &variants) override; + virtual bool load(util::random_read &io, uint32_t form_factor, const std::vector &variants, floppy_image *image) override; + virtual bool save(util::random_read_write &io, const std::vector &variants, floppy_image *image) override; virtual const char *name() const override; virtual const char *description() const override; @@ -35,9 +35,9 @@ class oric_jasmin_format : public floppy_image_format_t public: oric_jasmin_format() = default; - virtual int identify(io_generic *io, uint32_t form_factor, const std::vector &variants) override; - virtual bool load(io_generic *io, uint32_t form_factor, const std::vector &variants, floppy_image *image) override; - virtual bool save(io_generic *io, const std::vector &variants, floppy_image *image) override; + virtual int identify(util::random_read &io, uint32_t form_factor, const std::vector &variants) override; + virtual bool load(util::random_read &io, uint32_t form_factor, const std::vector &variants, floppy_image *image) override; + virtual bool save(util::random_read_write &io, const std::vector &variants, floppy_image *image) override; virtual const char *name() const override; virtual const char *description() const override; diff --git a/src/lib/formats/os9_dsk.cpp b/src/lib/formats/os9_dsk.cpp index b28e4f8d293..ba1b2427811 100644 --- a/src/lib/formats/os9_dsk.cpp +++ b/src/lib/formats/os9_dsk.cpp @@ -48,6 +48,7 @@ #include "imageutl.h" #include "coretmpl.h" // BIT +#include "ioprocs.h" os9_format::os9_format() : wd177x_format(formats) @@ -69,21 +70,25 @@ const char *os9_format::extensions() const return "dsk,os9"; } -int os9_format::identify(io_generic *io, uint32_t form_factor, const std::vector &variants) +int os9_format::identify(util::random_read &io, uint32_t form_factor, const std::vector &variants) { - int type = find_size(io, form_factor, variants); + int const type = find_size(io, form_factor, variants); if (type != -1) return 75; + return 0; } -int os9_format::find_size(io_generic *io, uint32_t form_factor, const std::vector &variants) +int os9_format::find_size(util::random_read &io, uint32_t form_factor, const std::vector &variants) { - uint64_t size = io_generic_size(io); + uint64_t size; + if (io.length(size)) + return -1; uint8_t os9_header[0x60]; - io_generic_read(io, os9_header, 0, sizeof(os9_header)); + size_t actual; + io.read_at(0, os9_header, sizeof(os9_header), actual); int os9_total_sectors = pick_integer_be(os9_header, 0x00, 3); int os9_heads = util::BIT(os9_header[0x10], 0) ? 2 : 1; diff --git a/src/lib/formats/os9_dsk.h b/src/lib/formats/os9_dsk.h index 57dfbfc9ab5..124c019d155 100644 --- a/src/lib/formats/os9_dsk.h +++ b/src/lib/formats/os9_dsk.h @@ -21,8 +21,8 @@ public: virtual const char *name() const override; virtual const char *description() const override; virtual const char *extensions() const override; - virtual int identify(io_generic *io, uint32_t form_factor, const std::vector &variants) override; - virtual int find_size(io_generic *io, uint32_t form_factor, const std::vector &variants) override; + virtual int identify(util::random_read &io, uint32_t form_factor, const std::vector &variants) override; + virtual int find_size(util::random_read &io, uint32_t form_factor, const std::vector &variants) override; virtual const wd177x_format::format &get_track_format(const format &f, int head, int track) override; private: diff --git a/src/lib/formats/pasti_dsk.cpp b/src/lib/formats/pasti_dsk.cpp index 0ab6dc2f064..1a418096cd3 100644 --- a/src/lib/formats/pasti_dsk.cpp +++ b/src/lib/formats/pasti_dsk.cpp @@ -2,6 +2,8 @@ // copyright-holders:Olivier Galibert #include "pasti_dsk.h" +#include "ioprocs.h" + // Pasti format supported using the documentation at // http://www.sarnau.info/atari:pasti_file_format @@ -36,10 +38,11 @@ bool pasti_format::supports_save() const return false; } -int pasti_format::identify(io_generic *io, uint32_t form_factor, const std::vector &variants) +int pasti_format::identify(util::random_read &io, uint32_t form_factor, const std::vector &variants) { uint8_t h[16]; - io_generic_read(io, h, 0, 16); + size_t actual; + io.read_at(0, h, 16, actual); if(!memcmp(h, "RSY\0\3\0", 6) && (1 || (h[10] >= 80 && h[10] <= 82) || (h[10] >= 160 && h[10] <= 164))) @@ -58,10 +61,11 @@ static void hexdump(const uint8_t *d, int s) } } -bool pasti_format::load(io_generic *io, uint32_t form_factor, const std::vector &variants, floppy_image *image) +bool pasti_format::load(util::random_read &io, uint32_t form_factor, const std::vector &variants, floppy_image *image) { + size_t actual; uint8_t fh[16]; - io_generic_read(io, fh, 0, 16); + io.read_at(0, fh, 16, actual); std::vector raw_track; @@ -76,7 +80,7 @@ bool pasti_format::load(io_generic *io, uint32_t form_factor, const std::vector< for(int track=0; track < tracks; track++) { for(int head=0; head < heads; head++) { uint8_t th[16]; - io_generic_read(io, th, pos, 16); + io.read_at(pos, th, 16, actual); int entry_len = th[0] | (th[1] << 8) | (th[2] << 16) | (th[3] << 24); int fuzz_len = th[4] | (th[5] << 8) | (th[6] << 16) | (th[7] << 24); int sect = th[8] | (th[9] << 8); @@ -87,7 +91,7 @@ bool pasti_format::load(io_generic *io, uint32_t form_factor, const std::vector< raw_track.resize(entry_len-16); - io_generic_read(io, &raw_track[0], pos+16, entry_len-16); + io.read_at(pos+16, &raw_track[0], entry_len-16, actual); uint8_t *fuzz = fuzz_len ? &raw_track[16*sect] : nullptr; uint8_t *bdata = fuzz ? fuzz+fuzz_len : &raw_track[16*sect]; diff --git a/src/lib/formats/pasti_dsk.h b/src/lib/formats/pasti_dsk.h index b3fc869da4d..2575c12eeb4 100644 --- a/src/lib/formats/pasti_dsk.h +++ b/src/lib/formats/pasti_dsk.h @@ -12,8 +12,8 @@ class pasti_format : public floppy_image_format_t public: pasti_format(); - virtual int identify(io_generic *io, uint32_t form_factor, const std::vector &variants) override; - virtual bool load(io_generic *io, uint32_t form_factor, const std::vector &variants, floppy_image *image) override; + virtual int identify(util::random_read &io, uint32_t form_factor, const std::vector &variants) override; + virtual bool load(util::random_read &io, uint32_t form_factor, const std::vector &variants, floppy_image *image) override; virtual const char *name() const override; virtual const char *description() const override; diff --git a/src/lib/formats/pc98fdi_dsk.cpp b/src/lib/formats/pc98fdi_dsk.cpp index 2d503acebe4..61fb8fb8fe3 100644 --- a/src/lib/formats/pc98fdi_dsk.cpp +++ b/src/lib/formats/pc98fdi_dsk.cpp @@ -8,9 +8,11 @@ *********************************************************************/ -#include #include "pc98fdi_dsk.h" +#include "ioprocs.h" + + pc98fdi_format::pc98fdi_format() { } @@ -30,47 +32,53 @@ const char *pc98fdi_format::extensions() const return "fdi"; } -int pc98fdi_format::identify(io_generic *io, uint32_t form_factor, const std::vector &variants) +int pc98fdi_format::identify(util::random_read &io, uint32_t form_factor, const std::vector &variants) { - uint64_t size = io_generic_size(io); - uint8_t h[32]; + uint64_t size; + if(io.length(size)) + return 0; - io_generic_read(io, h, 0, 32); - uint32_t hsize = little_endianize_int32(*(uint32_t *) (h + 0x8)); - uint32_t psize = little_endianize_int32(*(uint32_t *) (h + 0xc)); - uint32_t ssize = little_endianize_int32(*(uint32_t *) (h + 0x10)); - uint32_t scnt = little_endianize_int32(*(uint32_t *) (h + 0x14)); - uint32_t sides = little_endianize_int32(*(uint32_t *) (h + 0x18)); - uint32_t ntrk = little_endianize_int32(*(uint32_t *) (h + 0x1c)); + uint8_t h[32]; + size_t actual; + io.read_at(0, h, 32, actual); + + uint32_t const hsize = little_endianize_int32(*(uint32_t *) (h + 0x8)); + uint32_t const psize = little_endianize_int32(*(uint32_t *) (h + 0xc)); + uint32_t const ssize = little_endianize_int32(*(uint32_t *) (h + 0x10)); + uint32_t const scnt = little_endianize_int32(*(uint32_t *) (h + 0x14)); + uint32_t const sides = little_endianize_int32(*(uint32_t *) (h + 0x18)); + uint32_t const ntrk = little_endianize_int32(*(uint32_t *) (h + 0x1c)); if(size == hsize + psize && psize == ssize*scnt*sides*ntrk) return 100; return 0; } -bool pc98fdi_format::load(io_generic *io, uint32_t form_factor, const std::vector &variants, floppy_image *image) +bool pc98fdi_format::load(util::random_read &io, uint32_t form_factor, const std::vector &variants, floppy_image *image) { - uint8_t h[32]; + size_t actual; - io_generic_read(io, h, 0, 32); + uint8_t h[32]; + io.read_at(0, h, 32, actual); - uint32_t hsize = little_endianize_int32(*(uint32_t *)(h+0x8)); - uint32_t sector_size = little_endianize_int32(*(uint32_t *)(h+0x10)); - uint32_t sector_count = little_endianize_int32(*(uint32_t *)(h+0x14)); - uint32_t head_count = little_endianize_int32(*(uint32_t *)(h+0x18)); - uint32_t track_count = little_endianize_int32(*(uint32_t *)(h+0x1c)); + uint32_t const hsize = little_endianize_int32(*(uint32_t *)(h+0x8)); + uint32_t const sector_size = little_endianize_int32(*(uint32_t *)(h+0x10)); + uint32_t const sector_count = little_endianize_int32(*(uint32_t *)(h+0x14)); + uint32_t const head_count = little_endianize_int32(*(uint32_t *)(h+0x18)); + uint32_t const track_count = little_endianize_int32(*(uint32_t *)(h+0x1c)); - int cell_count = form_factor == floppy_image::FF_35 ? 200000 : 166666; + int const cell_count = form_factor == floppy_image::FF_35 ? 200000 : 166666; - int ssize; - for(ssize=0; (128 << ssize) < sector_size; ssize++) {}; + int ssize = 0; + while ((128 << ssize) < sector_size) + ssize++; desc_pc_sector sects[256]; uint8_t sect_data[65536]; for(int track=0; track < track_count; track++) for(int head=0; head < head_count; head++) { - io_generic_read(io, sect_data, hsize + sector_size*sector_count*(track*head_count + head), sector_size*sector_count); + io.read_at(hsize + sector_size*sector_count*(track*head_count + head), sect_data, sector_size*sector_count, actual); for(int i=0; i &variants) override; - virtual bool load(io_generic *io, uint32_t form_factor, const std::vector &variants, floppy_image *image) override; + virtual int identify(util::random_read &io, uint32_t form_factor, const std::vector &variants) override; + virtual bool load(util::random_read &io, uint32_t form_factor, const std::vector &variants, floppy_image *image) override; virtual const char *name() const override; virtual const char *description() const override; diff --git a/src/lib/formats/pc_dsk.cpp b/src/lib/formats/pc_dsk.cpp index c814afbe6dc..6fe2a82196a 100644 --- a/src/lib/formats/pc_dsk.cpp +++ b/src/lib/formats/pc_dsk.cpp @@ -8,10 +8,12 @@ *********************************************************************/ +#include "formats/pc_dsk.h" + +#include "ioprocs.h" + #include -#include -#include "formats/pc_dsk.h" pc_format::pc_format() : upd765_format(formats) { @@ -32,9 +34,12 @@ const char *pc_format::extensions() const return "dsk,ima,img,ufi,360"; } -int pc_format::identify(io_generic *io, uint32_t form_factor, const std::vector &variants) +int pc_format::identify(util::random_read &io, uint32_t form_factor, const std::vector &variants) { - uint64_t size = io_generic_size(io); + uint64_t size; + if (io.length(size)) { + return 0; + } /* some 360K images have a 512-byte header */ if (size == 368640 + 0x200) { diff --git a/src/lib/formats/pc_dsk.h b/src/lib/formats/pc_dsk.h index d53879611b9..8c99a35457f 100644 --- a/src/lib/formats/pc_dsk.h +++ b/src/lib/formats/pc_dsk.h @@ -20,7 +20,7 @@ class pc_format : public upd765_format public: pc_format(); - virtual int identify(io_generic *io, uint32_t form_factor, const std::vector &variants) override; + virtual int identify(util::random_read &io, uint32_t form_factor, const std::vector &variants) override; virtual const char *name() const override; virtual const char *description() const override; diff --git a/src/lib/formats/poly_dsk.cpp b/src/lib/formats/poly_dsk.cpp index a865729864e..8845643eb72 100644 --- a/src/lib/formats/poly_dsk.cpp +++ b/src/lib/formats/poly_dsk.cpp @@ -10,6 +10,9 @@ #include "poly_dsk.h" +#include "ioprocs.h" + + poly_cpm_format::poly_cpm_format() { } @@ -34,30 +37,35 @@ bool poly_cpm_format::supports_save() const return true; } -int poly_cpm_format::identify(io_generic *io, uint32_t form_factor, const std::vector &variants) +int poly_cpm_format::identify(util::random_read &io, uint32_t form_factor, const std::vector &variants) { - uint8_t boot[16]; - uint64_t size = io_generic_size(io); + uint64_t size; + if (io.length(size)) + return 0; // check for valid sizes if (size == 630784 || size == 622592 || size == 256256) { // check for Poly CP/M boot sector - io_generic_read(io, boot, 0, 16); + uint8_t boot[16]; + size_t actual; + io.read_at(0, boot, 16, actual); if (memcmp(boot, "\x86\xc3\xb7\x00\x00\x8e\x10\xc0\xbf\x00\x01\xbf\xe0\x60\x00\x00", 16) == 0) { return 100; } } + return 0; } -bool poly_cpm_format::load(io_generic *io, uint32_t form_factor, const std::vector &variants, floppy_image *image) +bool poly_cpm_format::load(util::random_read &io, uint32_t form_factor, const std::vector &variants, floppy_image *image) { - int total_tracks, spt, bps, head_num; - - uint64_t size = io_generic_size(io); + uint64_t size; + if (io.length(size) || io.seek(0, SEEK_SET)) + return false; + int total_tracks, spt, bps, head_num; switch (size) { case 622592: @@ -83,8 +91,7 @@ bool poly_cpm_format::load(io_generic *io, uint32_t form_factor, const std::vect break; } - int cell_count = (form_factor == floppy_image::FF_525) ? 50000 : 100000; - int offset = 0; + int const cell_count = (form_factor == floppy_image::FF_525) ? 50000 : 100000; for (int track = 0; track < total_tracks; track++) for (int head = 0; head < head_num; head++) @@ -105,8 +112,8 @@ bool poly_cpm_format::load(io_generic *io, uint32_t form_factor, const std::vect sects[i].deleted = false; sects[i].bad_crc = false; sects[i].data = §_data[sdatapos]; - io_generic_read(io, sects[i].data, offset, bps); - offset += bps; + size_t actual; + io.read(sects[i].data, bps, actual); sdatapos += bps; } // gap sizes unverified diff --git a/src/lib/formats/poly_dsk.h b/src/lib/formats/poly_dsk.h index 8fd3c9be4a5..8afb6836302 100644 --- a/src/lib/formats/poly_dsk.h +++ b/src/lib/formats/poly_dsk.h @@ -20,8 +20,8 @@ public: virtual const char *name() const override; virtual const char *description() const override; virtual const char *extensions() const override; - virtual int identify(io_generic *io, uint32_t form_factor, const std::vector &variants) override; - virtual bool load(io_generic *io, uint32_t form_factor, const std::vector &variants, floppy_image *image) override; + virtual int identify(util::random_read &io, uint32_t form_factor, const std::vector &variants) override; + virtual bool load(util::random_read &io, uint32_t form_factor, const std::vector &variants, floppy_image *image) override; virtual bool supports_save() const override; }; diff --git a/src/lib/formats/rx50_dsk.cpp b/src/lib/formats/rx50_dsk.cpp index d0d8f270c56..f81e2fa5b67 100644 --- a/src/lib/formats/rx50_dsk.cpp +++ b/src/lib/formats/rx50_dsk.cpp @@ -29,11 +29,11 @@ FORMAT A: /F:160 on DOS; turn MEDIACHK ON ************************************************************************/ -#include - -#include "flopimg.h" #include "formats/rx50_dsk.h" +#include "ioprocs.h" + + // Controller: WD1793 // TRACK LAYOUT IS UNVERIFED. SEE SOURCES: // - 'esq_dsk16' (uses WD 1772) @@ -95,12 +95,17 @@ bool rx50img_format::supports_save() const return true; } -void rx50img_format::find_size(io_generic *io, uint8_t &track_count, uint8_t &head_count, uint8_t §or_count) +void rx50img_format::find_size(util::random_read &io, uint8_t &track_count, uint8_t &head_count, uint8_t §or_count) { head_count = 1; uint32_t expected_size = 0; - uint64_t size = io_generic_size(io); + uint64_t size; + if (io.length(size)) + { + track_count = head_count = sector_count = 0; + return; + } track_count = 80; sector_count = 10; @@ -124,7 +129,7 @@ void rx50img_format::find_size(io_generic *io, uint8_t &track_count, uint8_t &he track_count = head_count = sector_count = 0; } -int rx50img_format::identify(io_generic *io, uint32_t form_factor, const std::vector &variants) +int rx50img_format::identify(util::random_read &io, uint32_t form_factor, const std::vector &variants) { uint8_t track_count, head_count, sector_count; find_size(io, track_count, head_count, sector_count); @@ -135,7 +140,7 @@ int rx50img_format::identify(io_generic *io, uint32_t form_factor, const std::ve } // /* Sectors are numbered 1 to 10 */ -bool rx50img_format::load(io_generic *io, uint32_t form_factor, const std::vector &variants, floppy_image *image) +bool rx50img_format::load(util::random_read &io, uint32_t form_factor, const std::vector &variants, floppy_image *image) { uint8_t track_count, head_count, sector_count; find_size(io, track_count, head_count, sector_count); @@ -153,7 +158,8 @@ bool rx50img_format::load(io_generic *io, uint32_t form_factor, const std::vecto int track_size = sector_count*512; for(int track=0; track < track_count; track++) { for(int head=0; head < head_count; head++) { - io_generic_read(io, sectdata, (track*head_count + head)*track_size, track_size); + size_t actual; + io.read_at((track*head_count + head)*track_size, sectdata, track_size, actual); generate_track(rx50_10_desc, track, head, sectors, sector_count, 102064, image); // 98480 } } @@ -163,7 +169,7 @@ bool rx50img_format::load(io_generic *io, uint32_t form_factor, const std::vecto return true; } -bool rx50img_format::save(io_generic *io, const std::vector &variants, floppy_image *image) +bool rx50img_format::save(util::random_read_write &io, const std::vector &variants, floppy_image *image) { int track_count, head_count, sector_count; get_geometry_mfm_pc(image, 2000, track_count, head_count, sector_count); @@ -199,7 +205,8 @@ bool rx50img_format::save(io_generic *io, const std::vector &variants, for(int track=0; track < track_count; track++) { for(int head=0; head < head_count; head++) { get_track_data_mfm_pc(track, head, image, 2000, 512, sector_count, sectdata); - io_generic_write(io, sectdata, (track*head_count + head)*track_size, track_size); + size_t actual; + io.write_at((track*head_count + head)*track_size, sectdata, track_size, actual); } } return true; diff --git a/src/lib/formats/rx50_dsk.h b/src/lib/formats/rx50_dsk.h index 9cac83bd67f..d28ea398d30 100644 --- a/src/lib/formats/rx50_dsk.h +++ b/src/lib/formats/rx50_dsk.h @@ -23,9 +23,9 @@ class rx50img_format : public floppy_image_format_t public: rx50img_format(); - virtual int identify(io_generic *io, uint32_t form_factor, const std::vector &variants) override; - virtual bool load(io_generic *io, uint32_t form_factor, const std::vector &variants, floppy_image *image) override; - virtual bool save(io_generic *io, const std::vector &variants, floppy_image *image) override; + virtual int identify(util::random_read &io, uint32_t form_factor, const std::vector &variants) override; + virtual bool load(util::random_read &io, uint32_t form_factor, const std::vector &variants, floppy_image *image) override; + virtual bool save(util::random_read_write &io, const std::vector &variants, floppy_image *image) override; virtual const char *name() const override; virtual const char *description() const override; @@ -35,7 +35,7 @@ public: static const desc_e rx50_10_desc[]; private: - void find_size(io_generic *io, uint8_t &track_count, uint8_t &head_count, uint8_t §or_count); + void find_size(util::random_read &io, uint8_t &track_count, uint8_t &head_count, uint8_t §or_count); }; extern const floppy_format_type FLOPPY_RX50IMG_FORMAT; diff --git a/src/lib/formats/sdd_dsk.cpp b/src/lib/formats/sdd_dsk.cpp index cac33948db0..f3e8df51bda 100644 --- a/src/lib/formats/sdd_dsk.cpp +++ b/src/lib/formats/sdd_dsk.cpp @@ -8,10 +8,11 @@ *********************************************************************/ -#include - #include "formats/sdd_dsk.h" +#include "ioprocs.h" + + sdd_format::sdd_format() : wd177x_format(formats) { } diff --git a/src/lib/formats/sdf_dsk.cpp b/src/lib/formats/sdf_dsk.cpp index 223b6dc8d8a..f57540f3c35 100644 --- a/src/lib/formats/sdf_dsk.cpp +++ b/src/lib/formats/sdf_dsk.cpp @@ -12,7 +12,9 @@ *********************************************************************/ #include "sdf_dsk.h" -#include + +#include "ioprocs.h" + sdf_format::sdf_format() { @@ -37,18 +39,18 @@ const char *sdf_format::extensions() const } -int sdf_format::identify(io_generic *io, uint32_t form_factor, const std::vector &variants) +int sdf_format::identify(util::random_read &io, uint32_t form_factor, const std::vector &variants) { uint8_t header[HEADER_SIZE]; - uint64_t size = io_generic_size(io); - - if (size < HEADER_SIZE) + uint64_t size; + if (io.length(size) || (size < HEADER_SIZE)) { return 0; } - io_generic_read(io, header, 0, HEADER_SIZE); + size_t actual; + io.read_at(0, header, HEADER_SIZE, actual); int tracks = header[4]; int heads = header[5]; @@ -74,13 +76,14 @@ int sdf_format::identify(io_generic *io, uint32_t form_factor, const std::vector } -bool sdf_format::load(io_generic *io, uint32_t form_factor, const std::vector &variants, floppy_image *image) +bool sdf_format::load(util::random_read &io, uint32_t form_factor, const std::vector &variants, floppy_image *image) { + size_t actual; uint8_t header[HEADER_SIZE]; std::vector track_data(TOTAL_TRACK_SIZE); std::vector raw_track_data; - io_generic_read(io, header, 0, HEADER_SIZE); + io.read_at(0, header, HEADER_SIZE, actual); const int tracks = header[4]; const int heads = header[5]; @@ -104,7 +107,7 @@ bool sdf_format::load(io_generic *io, uint32_t form_factor, const std::vector &variants, floppy_image *image) +bool sdf_format::save(util::random_read_write &io, const std::vector &variants, floppy_image *image) { return false; } diff --git a/src/lib/formats/sdf_dsk.h b/src/lib/formats/sdf_dsk.h index fe3f6eb7a98..b86692f618a 100644 --- a/src/lib/formats/sdf_dsk.h +++ b/src/lib/formats/sdf_dsk.h @@ -22,9 +22,9 @@ class sdf_format : public floppy_image_format_t public: sdf_format(); - virtual int identify(io_generic *io, uint32_t form_factor, const std::vector &variants) override; - virtual bool load(io_generic *io, uint32_t form_factor, const std::vector &variants, floppy_image *image) override; - virtual bool save(io_generic *io, const std::vector &variants, floppy_image *image) override; + virtual int identify(util::random_read &io, uint32_t form_factor, const std::vector &variants) override; + virtual bool load(util::random_read &io, uint32_t form_factor, const std::vector &variants, floppy_image *image) override; + virtual bool save(util::random_read_write &io, const std::vector &variants, floppy_image *image) override; virtual const char *name() const override; virtual const char *description() const override; diff --git a/src/lib/formats/st_dsk.cpp b/src/lib/formats/st_dsk.cpp index cb363cbe3e3..d044bc5bdac 100644 --- a/src/lib/formats/st_dsk.cpp +++ b/src/lib/formats/st_dsk.cpp @@ -8,10 +8,11 @@ *********************************************************************/ -#include - #include "formats/st_dsk.h" +#include "ioprocs.h" + + st_format::st_format() { } @@ -36,18 +37,20 @@ bool st_format::supports_save() const return true; } -void st_format::find_size(io_generic *io, uint8_t &track_count, uint8_t &head_count, uint8_t §or_count) +void st_format::find_size(util::random_read &io, uint8_t &track_count, uint8_t &head_count, uint8_t §or_count) { - uint64_t size = io_generic_size(io); - for(track_count=80; track_count <= 82; track_count++) - for(head_count=1; head_count <= 2; head_count++) - for(sector_count=9; sector_count <= 11; sector_count++) - if(size == (uint32_t)512*track_count*head_count*sector_count) - return; + uint64_t size; + if(!io.length(size)) { + for(track_count=80; track_count <= 82; track_count++) + for(head_count=1; head_count <= 2; head_count++) + for(sector_count=9; sector_count <= 11; sector_count++) + if(size == (uint32_t)512*track_count*head_count*sector_count) + return; + } track_count = head_count = sector_count = 0; } -int st_format::identify(io_generic *io, uint32_t form_factor, const std::vector &variants) +int st_format::identify(util::random_read &io, uint32_t form_factor, const std::vector &variants) { uint8_t track_count, head_count, sector_count; find_size(io, track_count, head_count, sector_count); @@ -57,7 +60,7 @@ int st_format::identify(io_generic *io, uint32_t form_factor, const std::vector< return 0; } -bool st_format::load(io_generic *io, uint32_t form_factor, const std::vector &variants, floppy_image *image) +bool st_format::load(util::random_read &io, uint32_t form_factor, const std::vector &variants, floppy_image *image) { uint8_t track_count, head_count, sector_count; find_size(io, track_count, head_count, sector_count); @@ -73,7 +76,8 @@ bool st_format::load(io_generic *io, uint32_t form_factor, const std::vector &variants, floppy_image *image) +bool st_format::save(util::random_read_write &io, const std::vector &variants, floppy_image *image) { int track_count, head_count, sector_count; get_geometry_mfm_pc(image, 2000, track_count, head_count, sector_count); @@ -109,7 +113,8 @@ bool st_format::save(io_generic *io, const std::vector &variants, flop for(int track=0; track < track_count; track++) { for(int head=0; head < head_count; head++) { get_track_data_mfm_pc(track, head, image, 2000, 512, sector_count, sectdata); - io_generic_write(io, sectdata, (track*head_count + head)*track_size, track_size); + size_t actual; + io.write_at((track*head_count + head)*track_size, sectdata, track_size, actual); } } @@ -141,10 +146,11 @@ bool msa_format::supports_save() const return true; } -void msa_format::read_header(io_generic *io, uint16_t &sign, uint16_t §, uint16_t &head, uint16_t &strack, uint16_t &etrack) +void msa_format::read_header(util::random_read &io, uint16_t &sign, uint16_t §, uint16_t &head, uint16_t &strack, uint16_t &etrack) { uint8_t h[10]; - io_generic_read(io, h, 0, 10); + size_t actual; + io.read_at(0, h, 10, actual); sign = (h[0] << 8) | h[1]; sect = (h[2] << 8) | h[3]; head = (h[4] << 8) | h[5]; @@ -206,7 +212,7 @@ bool msa_format::compress(const uint8_t *buffer, int usize, uint8_t *dest, int & return dst < usize; } -int msa_format::identify(io_generic *io, uint32_t form_factor, const std::vector &variants) +int msa_format::identify(util::random_read &io, uint32_t form_factor, const std::vector &variants) { uint16_t sign, sect, head, strack, etrack; read_header(io, sign, sect, head, strack, etrack); @@ -220,7 +226,7 @@ int msa_format::identify(io_generic *io, uint32_t form_factor, const std::vector return 0; } -bool msa_format::load(io_generic *io, uint32_t form_factor, const std::vector &variants, floppy_image *image) +bool msa_format::load(util::random_read &io, uint32_t form_factor, const std::vector &variants, floppy_image *image) { uint16_t sign, sect, heads, strack, etrack; read_header(io, sign, sect, heads, strack, etrack); @@ -238,11 +244,12 @@ bool msa_format::load(io_generic *io, uint32_t form_factor, const std::vector &variants, floppy_image *image) +bool msa_format::save(util::random_read_write &io, const std::vector &variants, floppy_image *image) { int track_count, head_count, sector_count; get_geometry_mfm_pc(image, 2000, track_count, head_count, sector_count); @@ -289,9 +296,10 @@ bool msa_format::save(io_generic *io, const std::vector &variants, flo header[8] = 0; header[9] = track_count-1; - io_generic_write(io, header, 0, 10); - - int pos = 10; + if(io.seek(0, SEEK_SET)) + return false; + size_t actual; + io.write(header, 10, actual); uint8_t sectdata[11*512]; uint8_t compdata[11*512]; @@ -305,16 +313,14 @@ bool msa_format::save(io_generic *io, const std::vector &variants, flo uint8_t th[2]; th[0] = csize >> 8; th[1] = csize; - io_generic_write(io, th, pos, 2); - io_generic_write(io, compdata, pos+2, csize); - pos += 2+csize; + io.write(th, 2, actual); + io.write(compdata, csize, actual); } else { uint8_t th[2]; th[0] = track_size >> 8; th[1] = track_size; - io_generic_write(io, th, pos, 2); - io_generic_write(io, sectdata, pos+2, track_size); - pos += 2+track_size; + io.write(th, 2, actual); + io.write(sectdata, track_size, actual); } } } diff --git a/src/lib/formats/st_dsk.h b/src/lib/formats/st_dsk.h index ce501a9f516..34f303bb1ae 100644 --- a/src/lib/formats/st_dsk.h +++ b/src/lib/formats/st_dsk.h @@ -19,9 +19,9 @@ class st_format : public floppy_image_format_t public: st_format(); - virtual int identify(io_generic *io, uint32_t form_factor, const std::vector &variants) override; - virtual bool load(io_generic *io, uint32_t form_factor, const std::vector &variants, floppy_image *image) override; - virtual bool save(io_generic *io, const std::vector &variants, floppy_image *image) override; + virtual int identify(util::random_read &io, uint32_t form_factor, const std::vector &variants) override; + virtual bool load(util::random_read &io, uint32_t form_factor, const std::vector &variants, floppy_image *image) override; + virtual bool save(util::random_read_write &io, const std::vector &variants, floppy_image *image) override; virtual const char *name() const override; virtual const char *description() const override; @@ -29,7 +29,7 @@ public: virtual bool supports_save() const override; private: - void find_size(io_generic *io, uint8_t &track_count, uint8_t &head_count, uint8_t §or_count); + void find_size(util::random_read &io, uint8_t &track_count, uint8_t &head_count, uint8_t §or_count); }; class msa_format : public floppy_image_format_t @@ -37,9 +37,9 @@ class msa_format : public floppy_image_format_t public: msa_format(); - virtual int identify(io_generic *io, uint32_t form_factor, const std::vector &variants) override; - virtual bool load(io_generic *io, uint32_t form_factor, const std::vector &variants, floppy_image *image) override; - virtual bool save(io_generic *io, const std::vector &variants, floppy_image *image) override; + virtual int identify(util::random_read &io, uint32_t form_factor, const std::vector &variants) override; + virtual bool load(util::random_read &io, uint32_t form_factor, const std::vector &variants, floppy_image *image) override; + virtual bool save(util::random_read_write &io, const std::vector &variants, floppy_image *image) override; virtual const char *name() const override; virtual const char *description() const override; @@ -49,7 +49,7 @@ public: private: bool uncompress(uint8_t *buffer, int csize, int usize); bool compress(const uint8_t *src, int usize, uint8_t *dest, int &csize); - void read_header(io_generic *io, uint16_t &sign, uint16_t §, uint16_t &head, uint16_t &strack, uint16_t &etrack); + void read_header(util::random_read &io, uint16_t &sign, uint16_t §, uint16_t &head, uint16_t &strack, uint16_t &etrack); }; extern const floppy_format_type FLOPPY_ST_FORMAT; diff --git a/src/lib/formats/svi_dsk.cpp b/src/lib/formats/svi_dsk.cpp index e3cfa294fcb..0a05bd15c80 100644 --- a/src/lib/formats/svi_dsk.cpp +++ b/src/lib/formats/svi_dsk.cpp @@ -10,6 +10,9 @@ #include "svi_dsk.h" +#include "ioprocs.h" + + svi_format::svi_format() { } @@ -29,9 +32,11 @@ const char *svi_format::extensions() const return "dsk"; } -int svi_format::identify(io_generic *io, uint32_t form_factor, const std::vector &variants) +int svi_format::identify(util::random_read &io, uint32_t form_factor, const std::vector &variants) { - uint64_t size = io_generic_size(io); + uint64_t size; + if (io.length(size)) + return 0; if (size == 172032 || size == 346112) return 50; @@ -39,11 +44,13 @@ int svi_format::identify(io_generic *io, uint32_t form_factor, const std::vector return 0; } -bool svi_format::load(io_generic *io, uint32_t form_factor, const std::vector &variants, floppy_image *image) +bool svi_format::load(util::random_read &io, uint32_t form_factor, const std::vector &variants, floppy_image *image) { - uint64_t size = io_generic_size(io); - int head_count; + uint64_t size; + if (io.length(size)) + return false; + int head_count; switch (size) { case 172032: head_count = 1; break; @@ -51,7 +58,8 @@ bool svi_format::load(io_generic *io, uint32_t form_factor, const std::vector &variants, floppy_image *image) +bool svi_format::save(util::random_read_write &io, const std::vector &variants, floppy_image *image) { - uint64_t file_offset = 0; + if (io.seek(0, SEEK_SET)) + return false; int track_count, head_count; image->get_actual_geometry(track_count, head_count); @@ -104,8 +113,8 @@ bool svi_format::save(io_generic *io, const std::vector &variants, flo for (int i = 0; i < 18; i++) { - io_generic_write(io, sectors[i + 1].data(), file_offset, 128); - file_offset += 128; + size_t actual; + io.write(sectors[i + 1].data(), 128, actual); } // rest are mfm tracks @@ -121,8 +130,8 @@ bool svi_format::save(io_generic *io, const std::vector &variants, flo for (int i = 0; i < 17; i++) { - io_generic_write(io, sectors[i + 1].data(), file_offset, 256); - file_offset += 256; + size_t actual; + io.write(sectors[i + 1].data(), 256, actual); } } } diff --git a/src/lib/formats/svi_dsk.h b/src/lib/formats/svi_dsk.h index 57f4f89ccca..a631bdf498c 100644 --- a/src/lib/formats/svi_dsk.h +++ b/src/lib/formats/svi_dsk.h @@ -23,9 +23,9 @@ public: virtual const char *description() const override; virtual const char *extensions() const override; - virtual int identify(io_generic *io, uint32_t form_factor, const std::vector &variants) override; - virtual bool load(io_generic *io, uint32_t form_factor, const std::vector &variants, floppy_image *image) override; - virtual bool save(io_generic *io, const std::vector &variants, floppy_image *image) override; + virtual int identify(util::random_read &io, uint32_t form_factor, const std::vector &variants) override; + virtual bool load(util::random_read &io, uint32_t form_factor, const std::vector &variants, floppy_image *image) override; + virtual bool save(util::random_read_write &io, const std::vector &variants, floppy_image *image) override; virtual bool supports_save() const override; }; diff --git a/src/lib/formats/td0_dsk.cpp b/src/lib/formats/td0_dsk.cpp index edac0aae010..345a242c86b 100644 --- a/src/lib/formats/td0_dsk.cpp +++ b/src/lib/formats/td0_dsk.cpp @@ -16,9 +16,11 @@ #include "flopimg.h" -#include +#include "ioprocs.h" + #include + #define BUFSZ 512 // new input buffer /* LZSS Parameters */ @@ -59,7 +61,16 @@ struct tdlzhuf { struct td0dsk_t { - io_generic *floppy_file; +public: + td0dsk_t(util::random_read &f) : floppy_file(f) { } + + void set_floppy_file_offset(uint64_t o) { floppy_file_offset = o; } + + void init_Decode(); + int Decode(uint8_t *buf, int len); + +private: + util::random_read &floppy_file; uint64_t floppy_file_offset; struct tdlzhuf tdctl; @@ -87,29 +98,10 @@ struct td0dsk_t void update(int c); int16_t DecodeChar(); int16_t DecodePosition(); - void init_Decode(); - int Decode(uint8_t *buf, int len); }; //static td0dsk_t td0dsk; -struct floppy_image_legacy -{ - struct io_generic io; - - const struct FloppyFormat *floppy_option; - struct FloppyCallbacks format; - - /* loaded track stuff */ - int loaded_track_head; - int loaded_track_index; - uint32_t loaded_track_size; - void *loaded_track_data; - uint8_t loaded_track_status; - uint8_t flags; -}; - - static struct td0dsk_tag *get_tag(floppy_image_legacy *floppy) { struct td0dsk_tag *tag; @@ -332,11 +324,13 @@ static floperr_t td0_get_indexed_sector_info(floppy_image_legacy *floppy, int he int td0dsk_t::data_read(uint8_t *buf, uint16_t size) { - uint64_t image_size = io_generic_size(floppy_file); + uint64_t image_size = 0; + floppy_file.length(image_size); if (size > image_size - floppy_file_offset) { size = image_size - floppy_file_offset; } - io_generic_read(floppy_file,buf,floppy_file_offset,size); + size_t actual; + floppy_file.read_at(floppy_file_offset, buf, size, actual); floppy_file_offset += size; return size; } @@ -675,7 +669,6 @@ int td0dsk_t::Decode(uint8_t *buf, int len) /* Decoding/Uncompressing */ FLOPPY_CONSTRUCT( td0_dsk_construct ) { - td0dsk_t state; struct FloppyCallbacks *callbacks; struct td0dsk_tag *tag; uint8_t *header; @@ -706,9 +699,9 @@ FLOPPY_CONSTRUCT( td0_dsk_construct ) int rd; int off = 12; int size = 0; - state.floppy_file = &(floppy->io); + td0dsk_t state(floppy_get_io(floppy)); state.init_Decode(); - state.floppy_file_offset = 12; + state.set_floppy_file_offset(12); do { if((rd = state.Decode(obuf, BUFSZ)) > 0) size += rd; @@ -720,7 +713,7 @@ FLOPPY_CONSTRUCT( td0_dsk_construct ) return FLOPPY_ERROR_OUTOFMEMORY; } memcpy(tag->data,obuf,12); - state.floppy_file_offset = 12; + state.set_floppy_file_offset(12); state.init_Decode(); do { @@ -815,20 +808,22 @@ const char *td0_format::extensions() const return "td0"; } -int td0_format::identify(io_generic *io, uint32_t form_factor, const std::vector &variants) +int td0_format::identify(util::random_read &io, uint32_t form_factor, const std::vector &variants) { + size_t actual; uint8_t h[7]; - io_generic_read(io, h, 0, 7); + io.read_at(0, h, 7, actual); if(((h[0] == 'T') && (h[1] == 'D')) || ((h[0] == 't') && (h[1] == 'd'))) { - return 100; + return 100; } return 0; } -bool td0_format::load(io_generic *io, uint32_t form_factor, const std::vector &variants, floppy_image *image) +bool td0_format::load(util::random_read &io, uint32_t form_factor, const std::vector &variants, floppy_image *image) { + size_t actual; int track_count = 0; int head_count = 0; int track_spt; @@ -837,20 +832,24 @@ bool td0_format::load(io_generic *io, uint32_t form_factor, const std::vector imagebuf(max_size); uint8_t header[12]; - io_generic_read(io, header, 0, 12); + io.read_at(0, header, 12, actual); head_count = header[9]; if(header[0] == 't') { - td0dsk_t disk_decode; + td0dsk_t disk_decode(io); - disk_decode.floppy_file = io; disk_decode.init_Decode(); - disk_decode.floppy_file_offset = 12; + disk_decode.set_floppy_file_offset(12); disk_decode.Decode(&imagebuf[0], max_size); } else - io_generic_read(io, &imagebuf[0], 12, io_generic_size(io)); + { + uint64_t image_size; + if(io.length(image_size)) + return false; + io.read_at(12, &imagebuf[0], image_size, actual); + } if(header[7] & 0x80) offset = 10 + imagebuf[2] + (imagebuf[3] << 8); @@ -1024,7 +1023,7 @@ bool td0_format::load(io_generic *io, uint32_t form_factor, const std::vector &variants, floppy_image *image) +bool td0_format::save(util::random_read_write &io, const std::vector &variants, floppy_image *image) { return false; } diff --git a/src/lib/formats/td0_dsk.h b/src/lib/formats/td0_dsk.h index b4656305920..cf625374130 100644 --- a/src/lib/formats/td0_dsk.h +++ b/src/lib/formats/td0_dsk.h @@ -13,9 +13,9 @@ class td0_format : public floppy_image_format_t public: td0_format(); - virtual int identify(io_generic *io, uint32_t form_factor, const std::vector &variants) override; - virtual bool load(io_generic *io, uint32_t form_factor, const std::vector &variants, floppy_image *image) override; - virtual bool save(io_generic *io, const std::vector &variants, floppy_image *image) override; + virtual int identify(util::random_read &io, uint32_t form_factor, const std::vector &variants) override; + virtual bool load(util::random_read &io, uint32_t form_factor, const std::vector &variants, floppy_image *image) override; + virtual bool save(util::random_read_write &io, const std::vector &variants, floppy_image *image) override; virtual const char *name() const override; virtual const char *description() const override; diff --git a/src/lib/formats/ti99_dsk.cpp b/src/lib/formats/ti99_dsk.cpp index 06ce98dfda0..507d7dc0ae0 100644 --- a/src/lib/formats/ti99_dsk.cpp +++ b/src/lib/formats/ti99_dsk.cpp @@ -43,6 +43,8 @@ #include "ti99_dsk.h" #include "imageutl.h" +#include "ioprocs.h" + #include "osdcore.h" // osd_printf_* (in osdcore.h) #include @@ -80,13 +82,16 @@ int ti99_floppy_format::get_encoding(int cell_size) /* Load the image from disk and convert it into a sequence of flux levels. */ -bool ti99_floppy_format::load(io_generic *io, uint32_t form_factor, const std::vector &variants, floppy_image *image) +bool ti99_floppy_format::load(util::random_read &io, uint32_t form_factor, const std::vector &variants, floppy_image *image) { + uint64_t file_size; + if (io.length(file_size)) + return false; + int cell_size = 0; int sector_count = 0; int heads = 0; int log_track_count = 0; - int file_size = io_generic_size(io); bool img_high_tpi = false; bool drive_high_tpi = false; @@ -211,7 +216,7 @@ bool ti99_floppy_format::load(io_generic *io, uint32_t form_factor, const std::v /* Save all tracks to the image file. */ -bool ti99_floppy_format::save(io_generic *io, const std::vector &variants, floppy_image *image) +bool ti99_floppy_format::save(util::random_read_write &io, const std::vector &variants, floppy_image *image) { uint8_t sectordata[9216]; // max size (36*256) @@ -916,9 +921,12 @@ const char *ti99_sdf_format::extensions() const return "dsk"; } -int ti99_sdf_format::identify(io_generic *io, uint32_t form_factor, const std::vector &variants) +int ti99_sdf_format::identify(util::random_read &io, uint32_t form_factor, const std::vector &variants) { - uint64_t file_size = io_generic_size(io); + uint64_t file_size; + if (io.length(file_size)) + return 0; + int vote = 0; // Adding support for another sector image format which adds 768 bytes @@ -947,7 +955,8 @@ int ti99_sdf_format::identify(io_generic *io, uint32_t form_factor, const std::v { // Read first sector (Volume Information Block) ti99vib vib; - io_generic_read(io, &vib, 0, sizeof(ti99vib)); + size_t actual; + io.read_at(0, &vib, sizeof(ti99vib), actual); // Check from contents if ((vib.id[0]=='D')&&(vib.id[1]=='S')&&(vib.id[2]=='K')) @@ -964,10 +973,14 @@ int ti99_sdf_format::identify(io_generic *io, uint32_t form_factor, const std::v return vote; } -void ti99_sdf_format::determine_sizes(io_generic *io, int& cell_size, int& sector_count, int& heads, int& tracks) +void ti99_sdf_format::determine_sizes(util::random_read &io, int& cell_size, int& sector_count, int& heads, int& tracks) { - uint64_t file_size = io_generic_size(io); - ti99vib vib; + uint64_t file_size; + if (io.length(file_size)) + { + cell_size = sector_count = heads = tracks = 0; + return; + } cell_size = 0; sector_count = 0; @@ -980,7 +993,9 @@ void ti99_sdf_format::determine_sizes(io_generic *io, int& cell_size, int& secto file_size -= 768; // Read first sector - io_generic_read(io, &vib, 0, sizeof(ti99vib)); + ti99vib vib; + size_t actual; + io.read_at(0, &vib, sizeof(ti99vib), actual); // Check from contents if ((vib.id[0]=='D')&&(vib.id[1]=='S')&&(vib.id[2]=='K')) @@ -1059,13 +1074,14 @@ int ti99_sdf_format::get_track_size(int sector_count) return sector_count * SECTOR_SIZE; } -void ti99_sdf_format::load_track(io_generic *io, uint8_t *sectordata, int *sector, int *secoffset, int head, int track, int sectorcount, int trackcount) +void ti99_sdf_format::load_track(util::random_read &io, uint8_t *sectordata, int *sector, int *secoffset, int head, int track, int sectorcount, int trackcount) { // Calculate the track offset from the beginning of the image file int logicaltrack = (head==0)? track : (2*trackcount - track - 1); int position = logicaltrack * get_track_size(sectorcount); - io_generic_read(io, sectordata, position, sectorcount*SECTOR_SIZE); + size_t actual; + io.read_at(position, sectordata, sectorcount*SECTOR_SIZE, actual); // Interleave and skew int interleave = 7; @@ -1133,19 +1149,18 @@ std::string ti99_floppy_format::dumpline(uint8_t* line, int address) const Write the data to the disk. We have a list of sector positions, so we just need to go through that list and save each sector in the sector data. */ -void ti99_sdf_format::write_track(io_generic *io, uint8_t *sectordata, int *sector, int track, int head, int sector_count, int track_count) +void ti99_sdf_format::write_track(util::random_read_write &io, uint8_t *sectordata, int *sector, int track, int head, int sector_count, int track_count) { - uint8_t* buf; - int logicaltrack = head * track_count; logicaltrack += ((head&1)==0)? track : (track_count - 1 - track); int trackoffset = logicaltrack * sector_count * SECTOR_SIZE; for (int i=0; i < sector_count; i++) { - buf = sectordata + i * SECTOR_SIZE; + uint8_t const *const buf = sectordata + i * SECTOR_SIZE; LOGMASKED(LOG_DETAIL, "[ti99_dsk] Writing sector %d (offset %06x)\n", sector[i], sector[i] * SECTOR_SIZE); - io_generic_write(io, buf, trackoffset + sector[i] * SECTOR_SIZE, SECTOR_SIZE); + size_t actual; + io.write_at(trackoffset + sector[i] * SECTOR_SIZE, buf, SECTOR_SIZE, actual); } } @@ -1209,7 +1224,7 @@ const char *ti99_tdf_format::extensions() const /* Determine whether the image file can be interpreted as a track dump */ -int ti99_tdf_format::identify(io_generic *io, uint32_t form_factor, const std::vector &variants) +int ti99_tdf_format::identify(util::random_read &io, uint32_t form_factor, const std::vector &variants) { int vote = 0; uint8_t fulltrack[6872]; @@ -1232,7 +1247,8 @@ int ti99_tdf_format::identify(io_generic *io, uint32_t form_factor, const std::v LOGMASKED(LOG_INFO, "[ti99_dsk] Image file length matches TDF\n"); // Fetch track 0 - io_generic_read(io, fulltrack, 0, get_track_size(sector_count)); + size_t actual; + io.read_at(0, fulltrack, get_track_size(sector_count), actual); if (sector_count == 9) { @@ -1279,9 +1295,14 @@ int ti99_tdf_format::identify(io_generic *io, uint32_t form_factor, const std::v Find the proper format for a given image file. Tracks are counted per side. Note that only two formats are actually compatible with the PC99 emulator. */ -void ti99_tdf_format::determine_sizes(io_generic *io, int& cell_size, int& sector_count, int& heads, int& tracks) +void ti99_tdf_format::determine_sizes(util::random_read &io, int& cell_size, int& sector_count, int& heads, int& tracks) { - uint64_t file_size = io_generic_size(io); + uint64_t file_size; + if (io.length(file_size)) + { + cell_size = sector_count = heads = tracks = 0; + return; + } // LOGMASKED(LOG_INFO, "[ti99_dsk] Image size = %ld\n", file_size); // doesn't compile switch (file_size) @@ -1336,13 +1357,14 @@ void ti99_tdf_format::determine_sizes(io_generic *io, int& cell_size, int& secto track from scratch. TDF is not as flexible as it suggests, it does not allow different gap lengths and so on. */ -void ti99_tdf_format::load_track(io_generic *io, uint8_t *sectordata, int *sector, int *secoffset, int head, int track, int sectorcount, int trackcount) +void ti99_tdf_format::load_track(util::random_read &io, uint8_t *sectordata, int *sector, int *secoffset, int head, int track, int sectorcount, int trackcount) { + size_t actual; uint8_t fulltrack[12544]; // space for a full TDF track // Read beginning of track 0. We need this to get the first gap, according // to the format - io_generic_read(io, fulltrack, 0, 100); + io.read_at(0, fulltrack, 100, actual); int offset = 0; int tracksize = get_track_size(sectorcount); @@ -1383,7 +1405,7 @@ void ti99_tdf_format::load_track(io_generic *io, uint8_t *sectordata, int *secto int base = (head * trackcount + track) * tracksize; int position = 0; - io_generic_read(io, fulltrack, base, tracksize); + io.read_at(base, fulltrack, tracksize, actual); for (int i=0; i < sectorcount; i++) { @@ -1431,7 +1453,7 @@ void ti99_tdf_format::load_track(io_generic *io, uint8_t *sectordata, int *secto need the sector contents and the sector sequence, which are passed via sectordata, sector, and sector_count. */ -void ti99_tdf_format::write_track(io_generic *io, uint8_t *sectordata, int *sector, int track, int head, int sector_count, int track_count) +void ti99_tdf_format::write_track(util::random_read_write &io, uint8_t *sectordata, int *sector, int track, int head, int sector_count, int track_count) { uint8_t trackdata[12544]; int offset = ((track_count * head) + track) * get_track_size(sector_count); @@ -1485,7 +1507,8 @@ void ti99_tdf_format::write_track(io_generic *io, uint8_t *sectordata, int *sect for (int i=0; i < param[WGAP3]; i++) trackdata[pos++] = param[WGAPBYTE]; } for (int i=0; i < param[WGAP4]; i++) trackdata[pos++] = param[WGAPBYTE]; - io_generic_write(io, trackdata, offset, get_track_size(sector_count)); + size_t actual; + io.write_at(offset, trackdata, get_track_size(sector_count), actual); } int ti99_tdf_format::get_track_size(int sector_count) diff --git a/src/lib/formats/ti99_dsk.h b/src/lib/formats/ti99_dsk.h index 5b59b164344..6590d1e7dd2 100644 --- a/src/lib/formats/ti99_dsk.h +++ b/src/lib/formats/ti99_dsk.h @@ -23,8 +23,8 @@ class ti99_floppy_format : public floppy_image_format_t { public: bool supports_save() const override { return true; } - bool load(io_generic *io, uint32_t form_factor, const std::vector &variants, floppy_image *image) override; - bool save(io_generic *io, const std::vector &variants, floppy_image *image) override; + bool load(util::random_read &io, uint32_t form_factor, const std::vector &variants, floppy_image *image) override; + bool save(util::random_read_write &io, const std::vector &variants, floppy_image *image) override; protected: uint8_t get_data_from_encoding(uint16_t raw); @@ -32,10 +32,10 @@ protected: virtual int min_heads() =0; - virtual void determine_sizes(io_generic *io, int& cell_size, int& sector_count, int& heads, int& tracks) =0; + virtual void determine_sizes(util::random_read &io, int& cell_size, int& sector_count, int& heads, int& tracks) =0; virtual int get_track_size(int sector_count) =0; - virtual void load_track(io_generic *io, uint8_t *sectordata, int *sector, int *secoffset, int head, int track, int sectorcount, int trackcount) =0; - virtual void write_track(io_generic *io, uint8_t *sectordata, int *sector, int track, int head, int sector_count, int track_count) =0; + virtual void load_track(util::random_read &io, uint8_t *sectordata, int *sector, int *secoffset, int head, int track, int sectorcount, int trackcount) =0; + virtual void write_track(util::random_read_write &io, uint8_t *sectordata, int *sector, int track, int head, int sector_count, int track_count) =0; int get_encoding(int cell_size); @@ -53,16 +53,16 @@ protected: class ti99_sdf_format : public ti99_floppy_format { public: - int identify(io_generic *io, uint32_t form_factor, const std::vector &variants) override; + int identify(util::random_read &io, uint32_t form_factor, const std::vector &variants) override; const char *name() const override; const char *description() const override; const char *extensions() const override; private: - void determine_sizes(io_generic *io, int& cell_size, int& sector_count, int& heads, int& tracks) override; + void determine_sizes(util::random_read &io, int& cell_size, int& sector_count, int& heads, int& tracks) override; int get_track_size(int sector_count) override; - void write_track(io_generic *io, uint8_t *sectordata, int *sector, int track, int head, int sector_count, int track_count) override; - void load_track(io_generic *io, uint8_t *sectordata, int *sector, int *secoffset, int head, int track, int sector_count, int track_count) override; + void write_track(util::random_read_write &io, uint8_t *sectordata, int *sector, int track, int head, int sector_count, int track_count) override; + void load_track(util::random_read &io, uint8_t *sectordata, int *sector, int *secoffset, int head, int track, int sector_count, int track_count) override; // This format supports single-sided images int min_heads() override { return 1; } @@ -92,15 +92,15 @@ extern const floppy_format_type FLOPPY_TI99_SDF_FORMAT; class ti99_tdf_format : public ti99_floppy_format { public: - int identify(io_generic *io, uint32_t form_factor, const std::vector &variants) override; + int identify(util::random_read &io, uint32_t form_factor, const std::vector &variants) override; const char *name() const override; const char *description() const override; const char *extensions() const override; private: - void determine_sizes(io_generic *io, int& cell_size, int& sector_count, int& heads, int& tracks) override; - void load_track(io_generic *io, uint8_t *sectordata, int *sector, int *secoffset, int head, int track, int sectorcount, int trackcount) override; - void write_track(io_generic *io, uint8_t *sectordata, int *sector, int track, int head, int sector_count, int track_count) override; + void determine_sizes(util::random_read &io, int& cell_size, int& sector_count, int& heads, int& tracks) override; + void load_track(util::random_read &io, uint8_t *sectordata, int *sector, int *secoffset, int head, int track, int sectorcount, int trackcount) override; + void write_track(util::random_read_write &io, uint8_t *sectordata, int *sector, int track, int head, int sector_count, int track_count) override; int get_track_size(int sector_count) override; // This format only supports double-sided images diff --git a/src/lib/formats/trd_dsk.cpp b/src/lib/formats/trd_dsk.cpp index 26b6ce5b6a5..4236259cca5 100644 --- a/src/lib/formats/trd_dsk.cpp +++ b/src/lib/formats/trd_dsk.cpp @@ -8,10 +8,11 @@ *********************************************************************/ -#include - #include "formats/trd_dsk.h" +#include "ioprocs.h" + + trd_format::trd_format() : wd177x_format(formats) { } @@ -31,10 +32,13 @@ const char *trd_format::extensions() const return "trd"; } -int trd_format::find_size(io_generic *io, uint32_t form_factor, const std::vector &variants) +int trd_format::find_size(util::random_read &io, uint32_t form_factor, const std::vector &variants) { + uint64_t size; + if (io.length(size)) + return -1; + int index = -1; - uint64_t size = io_generic_size(io); for (int i = 0; formats[i].form_factor; i++) { const format &f = formats[i]; @@ -47,12 +51,13 @@ int trd_format::find_size(io_generic *io, uint32_t form_factor, const std::vecto { index = i; // at least size match, save it for the case if there will be no exact matches + size_t actual; uint8_t sectdata[0x100]; if (f.encoding == floppy_image::MFM) - io_generic_read(io, sectdata, 0x800, 0x100); + io.read_at(0x800, sectdata, 0x100, actual); else { - io_generic_read(io, sectdata, 0x100, 0x100); + io.read_at(0x100, sectdata, 0x100, actual); for (int i = 0; i < 0x100; i++) sectdata[i] ^= 0xff; } diff --git a/src/lib/formats/trd_dsk.h b/src/lib/formats/trd_dsk.h index 6f19f9976a5..c5a411c60bb 100644 --- a/src/lib/formats/trd_dsk.h +++ b/src/lib/formats/trd_dsk.h @@ -24,7 +24,7 @@ public: private: static const format formats[]; - virtual int find_size(io_generic *io, uint32_t form_factor, const std::vector &variants) override; + virtual int find_size(util::random_read &io, uint32_t form_factor, const std::vector &variants) override; }; extern const floppy_format_type FLOPPY_TRD_FORMAT; diff --git a/src/lib/formats/trs80_dsk.cpp b/src/lib/formats/trs80_dsk.cpp index f010a24e570..acd48368239 100644 --- a/src/lib/formats/trs80_dsk.cpp +++ b/src/lib/formats/trs80_dsk.cpp @@ -66,6 +66,9 @@ Description of JV3: #include "trs80_dsk.h" +#include "ioprocs.h" + + jv1_format::jv1_format() : wd177x_format(formats) { } @@ -132,15 +135,18 @@ const char *jv3_format::extensions() const return "jv3,dsk"; } -int jv3_format::identify(io_generic *io, uint32_t form_factor, const std::vector &variants) +int jv3_format::identify(util::random_read &io, uint32_t form_factor, const std::vector &variants) { - uint32_t image_size = io_generic_size(io); + uint64_t image_size; + if (io.length(image_size)) + return 0; if (image_size < 0x2200) return 0; // too small, silent return std::vector data(image_size); - io_generic_read(io, data.data(), 0, image_size); + size_t actual; + io.read_at(0, data.data(), image_size, actual); const uint32_t entries = 2901; const uint32_t header_size = entries *3 +1; @@ -181,20 +187,20 @@ int jv3_format::identify(io_generic *io, uint32_t form_factor, const std::vector // validate so we don't overrun the array if (track >= MAX_TRACKS) { - printf("jv3_format::identify - track %d exceeds maximum allowed (%d)\n",track,MAX_TRACKS-1); + osd_printf_info("jv3_format::identify - track %d exceeds maximum allowed (%d)\n",track,MAX_TRACKS-1); return 0; } if (sector >= MAX_SECTORS) { - printf("jv3_format::identify - sector %d exceeds maximum allowed (%d)\n",sector,MAX_SECTORS-1); + osd_printf_info("jv3_format::identify - sector %d exceeds maximum allowed (%d)\n",sector,MAX_SECTORS-1); return 0; } // check if sector already exists if (sector_array[flag_side][track][sector]) { - printf("jv3_format::identify - side %d track %d sector %d is duplicated\n",flag_side,track,sector); + osd_printf_info("jv3_format::identify - side %d track %d sector %d is duplicated\n",flag_side,track,sector); return 0; } @@ -214,21 +220,25 @@ int jv3_format::identify(io_generic *io, uint32_t form_factor, const std::vector // Is all data in the image? (unused tracks at the end are optional) if (last_data > image_size) { - printf("jv3_format::identify - disk is missing some data. Expected 0x%X, Actual = 0x%X\n",last_data,image_size); + osd_printf_info("jv3_format::identify - disk is missing some data. Expected 0x%X, Actual = 0x%X\n",last_data,image_size); return 0; } return 80; } -bool jv3_format::load(io_generic *io, uint32_t form_factor, const std::vector &variants, floppy_image *image) +bool jv3_format::load(util::random_read &io, uint32_t form_factor, const std::vector &variants, floppy_image *image) { // disk has already been validated in every way except if it exceeds drive tracks, we do that below - printf("Disk detected as JV3\n");fflush(stdout); + osd_printf_info("Disk detected as JV3\n"); int drive_tracks, drive_sides; image->get_maximal_geometry(drive_tracks, drive_sides); - std::vector data(io_generic_size(io)); - io_generic_read(io, data.data(), 0, data.size()); + uint64_t image_size; + if (io.length(image_size)) + return false; + std::vector data(image_size); + size_t actual; + io.read_at(0, data.data(), data.size(), actual); const uint32_t entries = 2901; const uint32_t header_size = entries *3 +1; bool is_dd = false, is_ds = false; @@ -313,7 +323,7 @@ bool jv3_format::load(io_generic *io, uint32_t form_factor, const std::vector &variants, floppy_image *image) +bool jv3_format::save(util::random_read_write &io, const std::vector &variants, floppy_image *image) { int track_count, head_count; image->get_actual_geometry(track_count, head_count); @@ -352,10 +362,15 @@ bool jv3_format::save(io_generic *io, const std::vector &variants, flo if (track_count) { // If the disk already exists, find out if it's writable - std::vector data(io_generic_size(io)); - io_generic_read(io, data.data(), 0, data.size()); - if ((data.size() >= 0x2200) && (data[0x21ff] == 0)) - return false; // disk is readonly + uint64_t image_size; + if (!io.length(image_size)) + { + std::vector data(image_size); + size_t actual; + io.read_at(0, data.data(), data.size(), actual); + if ((data.size() >= 0x2200) && (data[0x21ff] == 0)) + return false; // disk is readonly + } } uint32_t data_ptr = 0x2200, sect_ptr = 0; @@ -396,7 +411,8 @@ bool jv3_format::save(io_generic *io, const std::vector &variants, flo header[sect_ptr++] = track; header[sect_ptr++] = i; header[sect_ptr++] = head ? 0x10 : 0; - io_generic_write(io, &dummy[0], data_ptr, 256); + size_t actual; + io.write_at(data_ptr, &dummy[0], 256, actual); data_ptr += 256; } } @@ -417,14 +433,16 @@ bool jv3_format::save(io_generic *io, const std::vector &variants, flo flags |= (sectors[i].size() >> 8) ^1; flags |= head ? 0x10 : 0; header[sect_ptr++] = flags; - io_generic_write(io, sectors[i].data(), data_ptr, sectors[i].size()); + size_t actual; + io.write_at(data_ptr, sectors[i].data(), sectors[i].size(), actual); data_ptr += sectors[i].size(); } } } } // Save the header - io_generic_write(io, header, 0, 0x2200); + size_t actual; + io.write_at(0, header, 0x2200, actual); return true; } diff --git a/src/lib/formats/trs80_dsk.h b/src/lib/formats/trs80_dsk.h index 60618a93693..31955fe4a5e 100644 --- a/src/lib/formats/trs80_dsk.h +++ b/src/lib/formats/trs80_dsk.h @@ -35,9 +35,9 @@ class jv3_format : public floppy_image_format_t public: jv3_format(); - virtual int identify(io_generic *io, uint32_t form_factor, const std::vector &variants) override; - virtual bool load(io_generic *io, uint32_t form_factor, const std::vector &variants, floppy_image *image) override; - virtual bool save(io_generic *io, const std::vector &variants, floppy_image *image) override; + virtual int identify(util::random_read &io, uint32_t form_factor, const std::vector &variants) override; + virtual bool load(util::random_read &io, uint32_t form_factor, const std::vector &variants, floppy_image *image) override; + virtual bool save(util::random_read_write &io, const std::vector &variants, floppy_image *image) override; virtual const char *name() const override; virtual const char *description() const override; diff --git a/src/lib/formats/uniflex_dsk.cpp b/src/lib/formats/uniflex_dsk.cpp index fa5d9b50acc..f85da09b75e 100644 --- a/src/lib/formats/uniflex_dsk.cpp +++ b/src/lib/formats/uniflex_dsk.cpp @@ -10,7 +10,10 @@ */ #include "uniflex_dsk.h" -#include "formats/imageutl.h" +#include "imageutl.h" + +#include "ioprocs.h" + uniflex_format::uniflex_format() : wd177x_format(formats) { @@ -31,22 +34,26 @@ const char *uniflex_format::extensions() const return "dsk"; } -int uniflex_format::identify(io_generic *io, uint32_t form_factor, const std::vector &variants) +int uniflex_format::identify(util::random_read &io, uint32_t form_factor, const std::vector &variants) { - int type = find_size(io, form_factor, variants); + int const type = find_size(io, form_factor, variants); if (type != -1) return 75; + return 0; } -int uniflex_format::find_size(io_generic *io, uint32_t form_factor, const std::vector &variants) +int uniflex_format::find_size(util::random_read &io, uint32_t form_factor, const std::vector &variants) { - uint64_t size = io_generic_size(io); - uint8_t sir[192]; + uint64_t size; + if (io.length(size)) + return -1; // Look at the SIR sector, the second sector. - io_generic_read(io, sir, 1 * 512, sizeof(sir)); + uint8_t sir[192]; + size_t actual; + io.read_at(1 * 512, sir, sizeof(sir), actual); uint16_t fdn_block_count = pick_integer_be(sir, 0x10, 2); uint32_t last_block_number = pick_integer_be(sir, 0x12, 3); diff --git a/src/lib/formats/uniflex_dsk.h b/src/lib/formats/uniflex_dsk.h index fad6741f533..af39a09678e 100644 --- a/src/lib/formats/uniflex_dsk.h +++ b/src/lib/formats/uniflex_dsk.h @@ -19,8 +19,8 @@ public: virtual const char *name() const override; virtual const char *description() const override; virtual const char *extensions() const override; - virtual int identify(io_generic *io, uint32_t form_factor, const std::vector &variants) override; - virtual int find_size(io_generic *io, uint32_t form_factor, const std::vector &variants) override; + virtual int identify(util::random_read &io, uint32_t form_factor, const std::vector &variants) override; + virtual int find_size(util::random_read &io, uint32_t form_factor, const std::vector &variants) override; void build_sector_description(const format &f, uint8_t *sectdata, desc_s *sectors, int track, int head) const override; private: diff --git a/src/lib/formats/upd765_dsk.cpp b/src/lib/formats/upd765_dsk.cpp index e7118dde236..d0afab39352 100644 --- a/src/lib/formats/upd765_dsk.cpp +++ b/src/lib/formats/upd765_dsk.cpp @@ -10,14 +10,19 @@ #include "formats/upd765_dsk.h" +#include "ioprocs.h" + upd765_format::upd765_format(const format *_formats) : file_header_skip_bytes(0), file_footer_skip_bytes(0), formats(_formats) { } -int upd765_format::find_size(io_generic *io, uint32_t form_factor, const std::vector &variants) const +int upd765_format::find_size(util::random_read &io, uint32_t form_factor, const std::vector &variants) const { - uint64_t size = io_generic_size(io); + uint64_t size; + if(io.length(size)) + return -1; + for(int i=0; formats[i].form_factor; i++) { const format &f = formats[i]; if(form_factor != floppy_image::FF_UNKNOWN && form_factor != f.form_factor) @@ -31,7 +36,7 @@ int upd765_format::find_size(io_generic *io, uint32_t form_factor, const std::ve return -1; } -int upd765_format::identify(io_generic *io, uint32_t form_factor, const std::vector &variants) +int upd765_format::identify(util::random_read &io, uint32_t form_factor, const std::vector &variants) { int type = find_size(io, form_factor, variants); @@ -175,7 +180,7 @@ floppy_image_format_t::desc_e* upd765_format::get_desc_mfm(const format &f, int return desc; } -bool upd765_format::load(io_generic *io, uint32_t form_factor, const std::vector &variants, floppy_image *image) +bool upd765_format::load(util::random_read &io, uint32_t form_factor, const std::vector &variants, floppy_image *image) { int type = find_size(io, form_factor, variants); if(type == -1) @@ -222,7 +227,8 @@ bool upd765_format::load(io_generic *io, uint32_t form_factor, const std::vector for(int track=0; track < f.track_count; track++) for(int head=0; head < f.head_count; head++) { build_sector_description(f, sectdata, sectors, track, head); - io_generic_read(io, sectdata, file_header_skip_bytes + (track*f.head_count + head)*track_size, track_size); + size_t actual; + io.read_at(file_header_skip_bytes + (track*f.head_count + head)*track_size, sectdata, track_size, actual); generate_track(desc, track, head, sectors, f.sector_count, total_size, image); } @@ -236,7 +242,7 @@ bool upd765_format::supports_save() const return true; } -bool upd765_format::save(io_generic *io, const std::vector &variants, floppy_image *image) +bool upd765_format::save(util::random_read_write &io, const std::vector &variants, floppy_image *image) { // Count the number of formats int formats_count; @@ -346,7 +352,8 @@ bool upd765_format::save(io_generic *io, const std::vector &variants, for(int head=0; head < f.head_count; head++) { build_sector_description(f, sectdata, sectors, track, head); extract_sectors(image, f, sectors, track, head); - io_generic_write(io, sectdata, (track*f.head_count + head)*track_size, track_size); + size_t actual; + io.write_at((track*f.head_count + head)*track_size, sectdata, track_size, actual); } return true; diff --git a/src/lib/formats/upd765_dsk.h b/src/lib/formats/upd765_dsk.h index e93a0f24326..48acfc02a88 100644 --- a/src/lib/formats/upd765_dsk.h +++ b/src/lib/formats/upd765_dsk.h @@ -39,9 +39,9 @@ public: // End the array with {} upd765_format(const format *formats); - virtual int identify(io_generic *io, uint32_t form_factor, const std::vector &variants) override; - virtual bool load(io_generic *io, uint32_t form_factor, const std::vector &variants, floppy_image *image) override; - virtual bool save(io_generic *io, const std::vector &variants, floppy_image *image) override; + virtual int identify(util::random_read &io, uint32_t form_factor, const std::vector &variants) override; + virtual bool load(util::random_read &io, uint32_t form_factor, const std::vector &variants, floppy_image *image) override; + virtual bool save(util::random_read_write &io, const std::vector &variants, floppy_image *image) override; virtual bool supports_save() const override; protected: @@ -50,7 +50,7 @@ protected: floppy_image_format_t::desc_e* get_desc_fm(const format &f, int ¤t_size, int &end_gap_index); floppy_image_format_t::desc_e* get_desc_mfm(const format &f, int ¤t_size, int &end_gap_index); - int find_size(io_generic *io, uint32_t form_factor, const std::vector &variants) const; + int find_size(util::random_read &io, uint32_t form_factor, const std::vector &variants) const; int compute_track_size(const format &f) const; virtual void build_sector_description(const format &d, uint8_t *sectdata, desc_s *sectors, int track, int head) const; void check_compatibility(floppy_image *image, std::vector &candidates); diff --git a/src/lib/formats/vdk_dsk.cpp b/src/lib/formats/vdk_dsk.cpp index 57c44f8bb29..759697f852f 100644 --- a/src/lib/formats/vdk_dsk.cpp +++ b/src/lib/formats/vdk_dsk.cpp @@ -12,6 +12,9 @@ #include "vdk_dsk.h" +#include "ioprocs.h" + + vdk_format::vdk_format() { } @@ -31,10 +34,11 @@ const char *vdk_format::extensions() const return "vdk"; } -int vdk_format::identify(io_generic *io, uint32_t form_factor, const std::vector &variants) +int vdk_format::identify(util::random_read &io, uint32_t form_factor, const std::vector &variants) { + size_t actual; uint8_t id[2]; - io_generic_read(io, id, 0, 2); + io.read_at(0, id, 2, actual); if (id[0] == 'd' && id[1] == 'k') return 50; @@ -42,16 +46,21 @@ int vdk_format::identify(io_generic *io, uint32_t form_factor, const std::vector return 0; } -bool vdk_format::load(io_generic *io, uint32_t form_factor, const std::vector &variants, floppy_image *image) +bool vdk_format::load(util::random_read &io, uint32_t form_factor, const std::vector &variants, floppy_image *image) { + size_t actual; + if (io.seek(0, SEEK_SET)) + return false; + uint8_t header[0x100]; - io_generic_read(io, header, 0, 0x100); + io.read(header, 0x100, actual); - int header_size = header[3] * 0x100 + header[2]; - int track_count = header[8]; - int head_count = header[9]; + int const header_size = header[3] * 0x100 + header[2]; + int const track_count = header[8]; + int const head_count = header[9]; - int file_offset = header_size; + if (io.seek(header_size, SEEK_SET)) + return false; for (int track = 0; track < track_count; track++) { @@ -72,10 +81,9 @@ bool vdk_format::load(io_generic *io, uint32_t form_factor, const std::vector &variants, floppy_image *image) +bool vdk_format::save(util::random_read_write &io, const std::vector &variants, floppy_image *image) { - uint64_t file_offset = 0; + size_t actual; + if (io.seek(0, SEEK_SET)) + return false; int track_count, head_count; image->get_actual_geometry(track_count, head_count); @@ -108,8 +118,7 @@ bool vdk_format::save(io_generic *io, const std::vector &variants, flo header[10] = 0; header[11] = 0; - io_generic_write(io, header, file_offset, sizeof(header)); - file_offset += sizeof(header); + io.write(header, sizeof(header), actual); // write disk data for (int track = 0; track < track_count; track++) @@ -120,10 +129,7 @@ bool vdk_format::save(io_generic *io, const std::vector &variants, flo auto sectors = extract_sectors_from_bitstream_mfm_pc(bitstream); for (int i = 0; i < SECTOR_COUNT; i++) - { - io_generic_write(io, sectors[FIRST_SECTOR_ID + i].data(), file_offset, SECTOR_SIZE); - file_offset += SECTOR_SIZE; - } + io.write(sectors[FIRST_SECTOR_ID + i].data(), SECTOR_SIZE, actual); } } diff --git a/src/lib/formats/vdk_dsk.h b/src/lib/formats/vdk_dsk.h index 94347b326f6..797d2644972 100644 --- a/src/lib/formats/vdk_dsk.h +++ b/src/lib/formats/vdk_dsk.h @@ -25,9 +25,9 @@ public: virtual const char *description() const override; virtual const char *extensions() const override; - virtual int identify(io_generic *io, uint32_t form_factor, const std::vector &variants) override; - virtual bool load(io_generic *io, uint32_t form_factor, const std::vector &variants, floppy_image *image) override; - virtual bool save(io_generic *io, const std::vector &variants, floppy_image *image) override; + virtual int identify(util::random_read &io, uint32_t form_factor, const std::vector &variants) override; + virtual bool load(util::random_read &io, uint32_t form_factor, const std::vector &variants, floppy_image *image) override; + virtual bool save(util::random_read_write &io, const std::vector &variants, floppy_image *image) override; virtual bool supports_save() const override; private: diff --git a/src/lib/formats/victor9k_dsk.cpp b/src/lib/formats/victor9k_dsk.cpp index ace1ec50933..3a142629726 100644 --- a/src/lib/formats/victor9k_dsk.cpp +++ b/src/lib/formats/victor9k_dsk.cpp @@ -99,6 +99,8 @@ #include "formats/victor9k_dsk.h" +#include "ioprocs.h" + victor9k_format::victor9k_format() { @@ -119,18 +121,22 @@ const char *victor9k_format::extensions() const return "img"; } -int victor9k_format::find_size(io_generic *io, uint32_t form_factor) +int victor9k_format::find_size(util::random_read &io, uint32_t form_factor) { - uint64_t size = io_generic_size(io); + uint64_t size; + if(io.length(size)) + return -1; + for(int i=0; formats[i].sector_count; i++) { const format &f = formats[i]; if(size == (uint32_t) f.sector_count*f.sector_base_size*f.head_count) return i; } + return -1; } -int victor9k_format::identify(io_generic *io, uint32_t form_factor, const std::vector &variants) +int victor9k_format::identify(util::random_read &io, uint32_t form_factor, const std::vector &variants) { int type = find_size(io, form_factor); @@ -248,19 +254,24 @@ void victor9k_format::build_sector_description(const format &f, uint8_t *sectdat } } -bool victor9k_format::load(io_generic *io, uint32_t form_factor, const std::vector &variants, floppy_image *image) +bool victor9k_format::load(util::random_read &io, uint32_t form_factor, const std::vector &variants, floppy_image *image) { - int type = find_size(io, form_factor); + int const type = find_size(io, form_factor); if(type == -1) return false; const format &f = formats[type]; - uint64_t size = io_generic_size(io); + uint64_t size; + if(io.length(size)) + return false; + std::vector img; - img.resize(size); + try { img.resize(size); } + catch (...) { return false; } - io_generic_read(io, &img[0], 0, size); + size_t actual; + io.read_at(0, &img[0], size, actual); log_boot_sector(&img[0]); @@ -392,7 +403,7 @@ const int victor9k_format::rpm[9] = 252, 267, 283, 300, 321, 342, 368, 401, 417 }; -bool victor9k_format::save(io_generic *io, const std::vector &variants, floppy_image *image) +bool victor9k_format::save(util::random_read_write &io, const std::vector &variants, floppy_image *image) { const format &f = formats[0]; @@ -406,7 +417,8 @@ bool victor9k_format::save(io_generic *io, const std::vector &variants build_sector_description(f, sectdata, 0, sectors, sector_count); extract_sectors(image, f, sectors, track, head, sector_count); - io_generic_write(io, sectdata, offset, track_size); + size_t actual; + io.write_at(offset, sectdata, track_size, actual); } } diff --git a/src/lib/formats/victor9k_dsk.h b/src/lib/formats/victor9k_dsk.h index 92d1c664a5f..aafd8fdcb14 100644 --- a/src/lib/formats/victor9k_dsk.h +++ b/src/lib/formats/victor9k_dsk.h @@ -34,9 +34,9 @@ public: virtual const char *description() const override; virtual const char *extensions() const override; - virtual int identify(io_generic *io, uint32_t form_factor, const std::vector &variants) override; - virtual bool load(io_generic *io, uint32_t form_factor, const std::vector &variants, floppy_image *image) override; - virtual bool save(io_generic *io, const std::vector &variants, floppy_image *image) override; + virtual int identify(util::random_read &io, uint32_t form_factor, const std::vector &variants) override; + virtual bool load(util::random_read &io, uint32_t form_factor, const std::vector &variants, floppy_image *image) override; + virtual bool save(util::random_read_write &io, const std::vector &variants, floppy_image *image) override; virtual bool supports_save() const override { return true; } static int get_rpm(int head, int track); @@ -49,7 +49,7 @@ protected: static const int speed_zone[2][80]; static const int rpm[9]; - int find_size(io_generic *io, uint32_t form_factor); + int find_size(util::random_read &io, uint32_t form_factor); void log_boot_sector(uint8_t *data); floppy_image_format_t::desc_e* get_sector_desc(const format &f, int ¤t_size, int sector_count); void build_sector_description(const format &f, uint8_t *sectdata, uint32_t sect_offs, desc_s *sectors, int sector_count) const; diff --git a/src/lib/formats/vt_dsk.cpp b/src/lib/formats/vt_dsk.cpp index d6cc3da4521..15c6955bfcc 100644 --- a/src/lib/formats/vt_dsk.cpp +++ b/src/lib/formats/vt_dsk.cpp @@ -10,6 +10,9 @@ #include "formats/vt_dsk.h" +#include "ioprocs.h" + + // Zero = | 9187 | // One = | 2237 | 6950 | // 0.5us ~= 143 @@ -213,9 +216,11 @@ const char *vtech_dsk_format::extensions() const return "dsk"; } -int vtech_bin_format::identify(io_generic *io, uint32_t form_factor, const std::vector &variants) +int vtech_bin_format::identify(util::random_read &io, uint32_t form_factor, const std::vector &variants) { - int size = io_generic_size(io); + uint64_t size; + if(io.length(size)) + return 0; if(size == 40*16*256) return 50; @@ -223,14 +228,18 @@ int vtech_bin_format::identify(io_generic *io, uint32_t form_factor, const std:: return 0; } -int vtech_dsk_format::identify(io_generic *io, uint32_t form_factor, const std::vector &variants) +int vtech_dsk_format::identify(util::random_read &io, uint32_t form_factor, const std::vector &variants) { - int size = io_generic_size(io); + uint64_t size; + if(io.length(size)) + return 0; + if(size < 256) return 0; std::vector bdata(size); - io_generic_read(io, bdata.data(), 0, size); + size_t actual; + io.read_at(0, bdata.data(), size, actual); // Structurally validate the presence of sector headers and data int count_sh = 0, count_sd = 0; @@ -246,25 +255,29 @@ int vtech_dsk_format::identify(io_generic *io, uint32_t form_factor, const std:: return count_sh >= 30*16 && count_sd >= 30*16 ? 100 : 0; } -bool vtech_bin_format::load(io_generic *io, uint32_t form_factor, const std::vector &variants, floppy_image *image) +bool vtech_bin_format::load(util::random_read &io, uint32_t form_factor, const std::vector &variants, floppy_image *image) { - int size = io_generic_size(io); - if(size != 40*16*256) + uint64_t size; + if(io.length(size) || (size != 40*16*256)) return false; std::vector bdata(size); - io_generic_read(io, bdata.data(), 0, size); + size_t actual; + io.read_at(0, bdata.data(), size, actual); image_to_flux(bdata, image); image->set_form_variant(floppy_image::FF_525, floppy_image::SSSD); return true; } -bool vtech_dsk_format::load(io_generic *io, uint32_t form_factor, const std::vector &variants, floppy_image *image) +bool vtech_dsk_format::load(util::random_read &io, uint32_t form_factor, const std::vector &variants, floppy_image *image) { - int size = io_generic_size(io); + uint64_t size; + if(io.length(size)) + return false; std::vector bdata(size); - io_generic_read(io, bdata.data(), 0, size); + size_t actual; + io.read_at(0, bdata.data(), size, actual); std::vector bdatax(128*16*40, 0); @@ -327,7 +340,7 @@ bool vtech_dsk_format::load(io_generic *io, uint32_t form_factor, const std::vec return true; } -bool vtech_bin_format::save(io_generic *io, const std::vector &variants, floppy_image *image) +bool vtech_bin_format::save(util::random_read_write &io, const std::vector &variants, floppy_image *image) { int tracks, heads; image->get_maximal_geometry(tracks, heads); @@ -335,11 +348,12 @@ bool vtech_bin_format::save(io_generic *io, const std::vector &variant return false; auto bdata = flux_to_image(image); - io_generic_write(io, bdata.data(), 0, bdata.size()); + size_t actual; + io.write_at(0, bdata.data(), bdata.size(), actual); return true; } -bool vtech_dsk_format::save(io_generic *io, const std::vector &variants, floppy_image *image) +bool vtech_dsk_format::save(util::random_read_write &io, const std::vector &variants, floppy_image *image) { int tracks, heads; image->get_maximal_geometry(tracks, heads); @@ -387,7 +401,8 @@ bool vtech_dsk_format::save(io_generic *io, const std::vector &variant } } - io_generic_write(io, bdatax.data(), 0, bdatax.size()); + size_t actual; + io.write_at(0, bdatax.data(), bdatax.size(), actual); return true; } diff --git a/src/lib/formats/vt_dsk.h b/src/lib/formats/vt_dsk.h index 739e5234a3f..4bc46871e7e 100644 --- a/src/lib/formats/vt_dsk.h +++ b/src/lib/formats/vt_dsk.h @@ -34,9 +34,9 @@ public: virtual const char *description() const override; virtual const char *extensions() const override; - virtual int identify(io_generic *io, uint32_t form_factor, const std::vector &variants) override; - virtual bool load(io_generic *io, uint32_t form_factor, const std::vector &variants, floppy_image *image) override; - virtual bool save(io_generic *io, const std::vector &variants, floppy_image *image) override; + virtual int identify(util::random_read &io, uint32_t form_factor, const std::vector &variants) override; + virtual bool load(util::random_read &io, uint32_t form_factor, const std::vector &variants, floppy_image *image) override; + virtual bool save(util::random_read_write &io, const std::vector &variants, floppy_image *image) override; }; class vtech_dsk_format : public vtech_common_format { @@ -47,9 +47,9 @@ public: virtual const char *description() const override; virtual const char *extensions() const override; - virtual int identify(io_generic *io, uint32_t form_factor, const std::vector &variants) override; - virtual bool load(io_generic *io, uint32_t form_factor, const std::vector &variants, floppy_image *image) override; - virtual bool save(io_generic *io, const std::vector &variants, floppy_image *image) override; + virtual int identify(util::random_read &io, uint32_t form_factor, const std::vector &variants) override; + virtual bool load(util::random_read &io, uint32_t form_factor, const std::vector &variants, floppy_image *image) override; + virtual bool save(util::random_read_write &io, const std::vector &variants, floppy_image *image) override; }; extern const floppy_format_type FLOPPY_VTECH_BIN_FORMAT; diff --git a/src/lib/formats/wd177x_dsk.cpp b/src/lib/formats/wd177x_dsk.cpp index 22309f32a12..da900b03db5 100644 --- a/src/lib/formats/wd177x_dsk.cpp +++ b/src/lib/formats/wd177x_dsk.cpp @@ -10,6 +10,8 @@ #include "formats/wd177x_dsk.h" +#include "ioprocs.h" + wd177x_format::wd177x_format(const format *_formats) { @@ -29,9 +31,12 @@ const wd177x_format::format &wd177x_format::get_track_format(const format &f, in /* Default implementation for find_size. May be overwritten by subclasses. */ -int wd177x_format::find_size(io_generic *io, uint32_t form_factor, const std::vector &variants) +int wd177x_format::find_size(util::random_read &io, uint32_t form_factor, const std::vector &variants) { - uint64_t size = io_generic_size(io); + uint64_t size; + if(io.length(size)) + return -1; + for(int i=0; formats[i].form_factor; i++) { const format &f = formats[i]; if(form_factor != floppy_image::FF_UNKNOWN && form_factor != f.form_factor) @@ -49,15 +54,17 @@ int wd177x_format::find_size(io_generic *io, uint32_t form_factor, const std::ve if(size == format_size) return i; } + return -1; } -int wd177x_format::identify(io_generic *io, uint32_t form_factor, const std::vector &variants) +int wd177x_format::identify(util::random_read &io, uint32_t form_factor, const std::vector &variants) { - int type = find_size(io, form_factor, variants); + int const type = find_size(io, form_factor, variants); if(type != -1) return 50; + return 0; } @@ -197,9 +204,9 @@ floppy_image_format_t::desc_e* wd177x_format::get_desc_mfm(const format &f, int return desc; } -bool wd177x_format::load(io_generic *io, uint32_t form_factor, const std::vector &variants, floppy_image *image) +bool wd177x_format::load(util::random_read &io, uint32_t form_factor, const std::vector &variants, floppy_image *image) { - int type = find_size(io, form_factor, variants); + int const type = find_size(io, form_factor, variants); if(type == -1) return false; @@ -251,7 +258,8 @@ bool wd177x_format::load(io_generic *io, uint32_t form_factor, const std::vector build_sector_description(tf, sectdata, sectors, track, head); int track_size = compute_track_size(tf); - io_generic_read(io, sectdata, get_image_offset(f, head, track), track_size); + size_t actual; + io.read_at(get_image_offset(f, head, track), sectdata, track_size, actual); generate_track(desc, track, head, sectors, tf.sector_count, total_size, image); } @@ -265,7 +273,7 @@ bool wd177x_format::supports_save() const return true; } -bool wd177x_format::save(io_generic *io, const std::vector &variants, floppy_image *image) +bool wd177x_format::save(util::random_read_write &io, const std::vector &variants, floppy_image *image) { // Count the number of formats int formats_count; @@ -377,7 +385,8 @@ bool wd177x_format::save(io_generic *io, const std::vector &variants, build_sector_description(tf, sectdata, sectors, track, head); extract_sectors(image, tf, sectors, track, head); int track_size = compute_track_size(tf); - io_generic_write(io, sectdata, get_image_offset(f, head, track), track_size); + size_t actual; + io.write_at(get_image_offset(f, head, track), sectdata, track_size, actual); } } diff --git a/src/lib/formats/wd177x_dsk.h b/src/lib/formats/wd177x_dsk.h index 4cae9ffa754..a7bd92994e6 100644 --- a/src/lib/formats/wd177x_dsk.h +++ b/src/lib/formats/wd177x_dsk.h @@ -38,9 +38,9 @@ public: // End the array with {} wd177x_format(const format *formats); - virtual int identify(io_generic *io, uint32_t form_factor, const std::vector &variants) override; - virtual bool load(io_generic *io, uint32_t form_factor, const std::vector &variants, floppy_image *image) override; - virtual bool save(io_generic *io, const std::vector &variants, floppy_image *image) override; + virtual int identify(util::random_read &io, uint32_t form_factor, const std::vector &variants) override; + virtual bool load(util::random_read &io, uint32_t form_factor, const std::vector &variants, floppy_image *image) override; + virtual bool save(util::random_read_write &io, const std::vector &variants, floppy_image *image) override; virtual bool supports_save() const override; protected: @@ -51,7 +51,7 @@ protected: virtual const wd177x_format::format &get_track_format(const format &f, int head, int track); virtual floppy_image_format_t::desc_e* get_desc_fm(const format &f, int ¤t_size, int &end_gap_index); virtual floppy_image_format_t::desc_e* get_desc_mfm(const format &f, int ¤t_size, int &end_gap_index); - virtual int find_size(io_generic *io, uint32_t form_factor, const std::vector &variants); + virtual int find_size(util::random_read &io, uint32_t form_factor, const std::vector &variants); virtual int get_image_offset(const format &f, int head, int track); virtual int get_track_dam_fm(const format &f, int head, int track); virtual int get_track_dam_mfm(const format &f, int head, int track); diff --git a/src/lib/util/avhuff.cpp b/src/lib/util/avhuff.cpp index ac5cea71526..0689fe25b80 100644 --- a/src/lib/util/avhuff.cpp +++ b/src/lib/util/avhuff.cpp @@ -896,9 +896,9 @@ avhuff_error avhuff_decoder::decode_audio(int channels, int samples, const uint8 { // reset and decode if (!m_flac_decoder.reset(48000, 1, samples, source, size)) - throw CHDERR_DECOMPRESSION_ERROR; + throw std::error_condition(chd_file::error::DECOMPRESSION_ERROR); if (!m_flac_decoder.decode_interleaved(reinterpret_cast(curdest), samples, swap_endian)) - throw CHDERR_DECOMPRESSION_ERROR; + throw std::error_condition(chd_file::error::DECOMPRESSION_ERROR); // finish up m_flac_decoder.finish(); diff --git a/src/lib/util/aviio.cpp b/src/lib/util/aviio.cpp index 03014611873..3a3a1a412f6 100644 --- a/src/lib/util/aviio.cpp +++ b/src/lib/util/aviio.cpp @@ -1710,8 +1710,8 @@ avi_file::error avi_file_impl::read_uncompressed_video_frame(std::uint32_t frame /* read in the data */ std::uint32_t bytes_read; - osd_file::error const filerr = m_file->read(&m_tempbuffer[0], stream->chunk(framenum).offset, stream->chunk(framenum).length, bytes_read); - if (filerr != osd_file::error::NONE || bytes_read != stream->chunk(framenum).length) + std::error_condition const filerr = m_file->read(&m_tempbuffer[0], stream->chunk(framenum).offset, stream->chunk(framenum).length, bytes_read); + if (filerr || bytes_read != stream->chunk(framenum).length) return error::READ_ERROR; /* validate this is good data */ @@ -1765,8 +1765,8 @@ avi_file::error avi_file_impl::read_video_frame(std::uint32_t framenum, bitmap_y /* read in the data */ std::uint32_t bytes_read; - osd_file::error const filerr = m_file->read(&m_tempbuffer[0], stream->chunk(framenum).offset, stream->chunk(framenum).length, bytes_read); - if (filerr != osd_file::error::NONE || bytes_read != stream->chunk(framenum).length) + std::error_condition const filerr = m_file->read(&m_tempbuffer[0], stream->chunk(framenum).offset, stream->chunk(framenum).length, bytes_read); + if (filerr || bytes_read != stream->chunk(framenum).length) return error::READ_ERROR; /* validate this is good data */ @@ -1857,8 +1857,8 @@ avi_file::error avi_file_impl::read_sound_samples(int channel, std::uint32_t fir return avierr; /* read in the data */ - auto const filerr = m_file->read(&m_tempbuffer[0], stream->chunk(chunknum).offset, stream->chunk(chunknum).length, bytes_read); - if (filerr != osd_file::error::NONE || bytes_read != stream->chunk(chunknum).length) + std::error_condition const filerr = m_file->read(&m_tempbuffer[0], stream->chunk(chunknum).offset, stream->chunk(chunknum).length, bytes_read); + if (filerr || bytes_read != stream->chunk(chunknum).length) return error::READ_ERROR; /* validate this is good data */ @@ -2085,14 +2085,15 @@ avi_file::error avi_file_impl::append_sound_samples(int channel, const std::int1 avi_file::error avi_file_impl::read_chunk_data(avi_chunk const &chunk, std::unique_ptr &buffer) { - /* allocate memory for the data */ - try { buffer.reset(new std::uint8_t[chunk.size]); } - catch (...) { return error::NO_MEMORY; } + // allocate memory for the data + buffer.reset(new (std::nothrow) std::uint8_t[chunk.size]); + if (!buffer) + return error::NO_MEMORY; - /* read from the file */ + // read from the file std::uint32_t bytes_read; - osd_file::error const filerr = m_file->read(&buffer[0], chunk.offset + 8, chunk.size, bytes_read); - if (filerr != osd_file::error::NONE || bytes_read != chunk.size) + std::error_condition const filerr = m_file->read(&buffer[0], chunk.offset + 8, chunk.size, bytes_read); + if (filerr || bytes_read != chunk.size) { buffer.reset(); return error::READ_ERROR; @@ -2292,35 +2293,33 @@ avi_file::error avi_file_impl::find_next_list(std::uint32_t findme, const avi_ch avi_file::error avi_file_impl::get_next_chunk_internal(const avi_chunk *parent, avi_chunk &newchunk, std::uint64_t offset) { - osd_file::error filerr; - std::uint8_t buffer[12]; - std::uint32_t bytesread; - - /* nullptr parent implies the root */ - if (parent == nullptr) + // nullptr parent implies the root + if (!parent) parent = &m_rootchunk; - /* start at the current offset */ + // start at the current offset newchunk.offset = offset; - /* if we're past the bounds of the parent, bail */ + // if we're past the bounds of the parent, bail if (newchunk.offset + 8 >= parent->offset + 8 + parent->size) return error::END; - /* read the header */ - filerr = m_file->read(buffer, newchunk.offset, 8, bytesread); - if (filerr != osd_file::error::NONE || bytesread != 8) + // read the header + std::uint8_t buffer[12]; + std::uint32_t bytesread; + std::error_condition filerr = m_file->read(buffer, newchunk.offset, 8, bytesread); + if (filerr || bytesread != 8) return error::INVALID_DATA; - /* fill in the new chunk */ + // fill in the new chunk newchunk.type = fetch_32bits(&buffer[0]); newchunk.size = fetch_32bits(&buffer[4]); - /* if we are a list, fetch the list type */ + // if we are a list, fetch the list type if (newchunk.type == CHUNKTYPE_LIST || newchunk.type == CHUNKTYPE_RIFF) { filerr = m_file->read(&buffer[8], newchunk.offset + 8, 4, bytesread); - if (filerr != osd_file::error::NONE || bytesread != 4) + if (filerr || bytesread != 4) return error::INVALID_DATA; newchunk.listtype = fetch_32bits(&buffer[8]); } @@ -2643,16 +2642,15 @@ avi_file::error avi_file_impl::parse_indx_chunk(avi_stream &stream, avi_chunk co /* loop over entries and create subchunks for each */ for (std::uint32_t entry = 0; entry < entries; entry++) { - const std::uint8_t *base = &chunkdata[24 + entry * 16]; - osd_file::error filerr; + std::uint8_t const *const base = &chunkdata[24 + entry * 16]; avi_chunk subchunk; - std::uint32_t bytes_read; - std::uint8_t buffer[8]; /* go read the subchunk */ subchunk.offset = fetch_64bits(&base[0]); - filerr = m_file->read(buffer, subchunk.offset, sizeof(buffer), bytes_read); - if (filerr != osd_file::error::NONE || bytes_read != sizeof(buffer)) + std::uint32_t bytes_read; + std::uint8_t buffer[8]; + std::error_condition const filerr = m_file->read(buffer, subchunk.offset, sizeof(buffer), bytes_read); + if (filerr || bytes_read != sizeof(buffer)) { avierr = error::READ_ERROR; break; @@ -2788,8 +2786,8 @@ avi_file::error avi_file_impl::chunk_open(std::uint32_t type, std::uint32_t list /* write the header */ std::uint32_t written; - osd_file::error const filerr = m_file->write(buffer, m_writeoffs, sizeof(buffer), written); - if (filerr != osd_file::error::NONE || written != sizeof(buffer)) + std::error_condition const filerr = m_file->write(buffer, m_writeoffs, sizeof(buffer), written); + if (filerr || written != sizeof(buffer)) return error::WRITE_ERROR; m_writeoffs += written; } @@ -2806,8 +2804,8 @@ avi_file::error avi_file_impl::chunk_open(std::uint32_t type, std::uint32_t list /* write the header */ std::uint32_t written; - osd_file::error const filerr = m_file->write(buffer, m_writeoffs, sizeof(buffer), written); - if (filerr != osd_file::error::NONE || written != sizeof(buffer)) + std::error_condition const filerr = m_file->write(buffer, m_writeoffs, sizeof(buffer), written); + if (filerr || written != sizeof(buffer)) return error::WRITE_ERROR; m_writeoffs += written; } @@ -2846,8 +2844,8 @@ avi_file::error avi_file_impl::chunk_close() put_32bits(&buffer[0], std::uint32_t(chunksize)); std::uint32_t written; - osd_file::error const filerr = m_file->write(buffer, chunk.offset + 4, sizeof(buffer), written); - if (filerr != osd_file::error::NONE || written != sizeof(buffer)) + std::error_condition const filerr = m_file->write(buffer, chunk.offset + 4, sizeof(buffer), written); + if (filerr || written != sizeof(buffer)) return error::WRITE_ERROR; } @@ -2925,8 +2923,8 @@ avi_file::error avi_file_impl::chunk_write(std::uint32_t type, const void *data, /* write the data */ std::uint32_t written; - osd_file::error const filerr = m_file->write(data, m_writeoffs, length, written); - if (filerr != osd_file::error::NONE || written != length) + std::error_condition const filerr = m_file->write(data, m_writeoffs, length, written); + if (filerr || written != length) return error::WRITE_ERROR; m_writeoffs += written; @@ -3678,7 +3676,7 @@ avi_file::error avi_file::open(std::string const &filename, ptr &file) /* open the file */ osd_file::ptr f; std::uint64_t length; - if (osd_file::open(filename, OPEN_FLAG_READ, f, length) != osd_file::error::NONE) + if (osd_file::open(filename, OPEN_FLAG_READ, f, length)) return error::CANT_OPEN_FILE; /* allocate the file */ @@ -3731,8 +3729,8 @@ avi_file::error avi_file::create(std::string const &filename, movie_info const & /* open the file */ osd_file::ptr f; std::uint64_t length; - osd_file::error const filerr = osd_file::open(filename, OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS, f, length); - if (filerr != osd_file::error::NONE) + std::error_condition const filerr = osd_file::open(filename, OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS, f, length); + if (filerr) return error::CANT_OPEN_FILE; /* allocate the file */ diff --git a/src/lib/util/cdrom.cpp b/src/lib/util/cdrom.cpp index 4ac1ab6e865..7510a1f9b47 100644 --- a/src/lib/util/cdrom.cpp +++ b/src/lib/util/cdrom.cpp @@ -19,6 +19,7 @@ #include "cdrom.h" #include "chdcd.h" +#include "corefile.h" #include #include @@ -223,10 +224,10 @@ cdrom_file *cdrom_open(const char *inputfile) return nullptr; // set up the CD-ROM module and get the disc info - chd_error err = chdcd_parse_toc(inputfile, file->cdtoc, file->track_info); - if (err != CHDERR_NONE) + std::error_condition err = chdcd_parse_toc(inputfile, file->cdtoc, file->track_info); + if (err) { - fprintf(stderr, "Error reading input file: %s\n", chd_file::error_string(err)); + fprintf(stderr, "Error reading input file: %s\n", err.message().c_str()); delete file; return nullptr; } @@ -238,14 +239,15 @@ cdrom_file *cdrom_open(const char *inputfile) for (i = 0; i < file->cdtoc.numtrks; i++) { - osd_file::error filerr = util::core_file::open(file->track_info.track[i].fname, OPEN_FLAG_READ, file->fhandle[i]); - if (filerr != osd_file::error::NONE) + std::error_condition const filerr = util::core_file::open(file->track_info.track[i].fname, OPEN_FLAG_READ, file->fhandle[i]); + if (filerr) { fprintf(stderr, "Unable to open file: %s\n", file->track_info.track[i].fname.c_str()); cdrom_close(file); return nullptr; } } + /* calculate the starting frame for each track, keeping in mind that CHDMAN pads tracks out with extra frames to fit 4-frame size boundries */ @@ -336,8 +338,8 @@ cdrom_file *cdrom_open(chd_file *chd) file->chd = chd; /* read the CD-ROM metadata */ - chd_error err = cdrom_parse_metadata(chd, &file->cdtoc); - if (err != CHDERR_NONE) + std::error_condition err = cdrom_parse_metadata(chd, &file->cdtoc); + if (err) { delete file; return nullptr; @@ -446,7 +448,7 @@ void cdrom_close(cdrom_file *file) ***************************************************************************/ /** - * @fn chd_error read_partial_sector(cdrom_file *file, void *dest, uint32_t lbasector, uint32_t chdsector, uint32_t tracknum, uint32_t startoffs, uint32_t length) + * @fn std::error_condition read_partial_sector(cdrom_file *file, void *dest, uint32_t lbasector, uint32_t chdsector, uint32_t tracknum, uint32_t startoffs, uint32_t length) * * @brief Reads partial sector. * @@ -461,9 +463,9 @@ void cdrom_close(cdrom_file *file) * @return The partial sector. */ -chd_error read_partial_sector(cdrom_file *file, void *dest, uint32_t lbasector, uint32_t chdsector, uint32_t tracknum, uint32_t startoffs, uint32_t length, bool phys=false) +std::error_condition read_partial_sector(cdrom_file *file, void *dest, uint32_t lbasector, uint32_t chdsector, uint32_t tracknum, uint32_t startoffs, uint32_t length, bool phys=false) { - chd_error result = CHDERR_NONE; + std::error_condition result; bool needswap = false; // if this is pregap info that isn't actually in the file, just return blank data @@ -570,14 +572,14 @@ uint32_t cdrom_read_data(cdrom_file *file, uint32_t lbasector, void *buffer, uin if ((datatype == tracktype) || (datatype == CD_TRACK_RAW_DONTCARE)) { - return (read_partial_sector(file, buffer, lbasector, chdsector, tracknum, 0, file->cdtoc.tracks[tracknum].datasize, phys) == CHDERR_NONE); + return !read_partial_sector(file, buffer, lbasector, chdsector, tracknum, 0, file->cdtoc.tracks[tracknum].datasize, phys); } else { // return 2048 bytes of mode 1 data from a 2352 byte mode 1 raw sector if ((datatype == CD_TRACK_MODE1) && (tracktype == CD_TRACK_MODE1_RAW)) { - return (read_partial_sector(file, buffer, lbasector, chdsector, tracknum, 16, 2048, phys) == CHDERR_NONE); + return !read_partial_sector(file, buffer, lbasector, chdsector, tracknum, 16, 2048, phys); } // return 2352 byte mode 1 raw sector from 2048 bytes of mode 1 data @@ -593,25 +595,25 @@ uint32_t cdrom_read_data(cdrom_file *file, uint32_t lbasector, void *buffer, uin bufptr[14] = msf&0xff; bufptr[15] = 1; // mode 1 LOG(("CDROM: promotion of mode1/form1 sector to mode1 raw is not complete!\n")); - return (read_partial_sector(file, bufptr+16, lbasector, chdsector, tracknum, 0, 2048, phys) == CHDERR_NONE); + return !read_partial_sector(file, bufptr+16, lbasector, chdsector, tracknum, 0, 2048, phys); } // return 2048 bytes of mode 1 data from a mode2 form1 or raw sector if ((datatype == CD_TRACK_MODE1) && ((tracktype == CD_TRACK_MODE2_FORM1)||(tracktype == CD_TRACK_MODE2_RAW))) { - return (read_partial_sector(file, buffer, lbasector, chdsector, tracknum, 24, 2048, phys) == CHDERR_NONE); + return !read_partial_sector(file, buffer, lbasector, chdsector, tracknum, 24, 2048, phys); } // return 2048 bytes of mode 1 data from a mode2 form2 or XA sector if ((datatype == CD_TRACK_MODE1) && (tracktype == CD_TRACK_MODE2_FORM_MIX)) { - return (read_partial_sector(file, buffer, lbasector, chdsector, tracknum, 8, 2048, phys) == CHDERR_NONE); + return !read_partial_sector(file, buffer, lbasector, chdsector, tracknum, 8, 2048, phys); } // return mode 2 2336 byte data from a 2352 byte mode 1 or 2 raw sector (skip the header) if ((datatype == CD_TRACK_MODE2) && ((tracktype == CD_TRACK_MODE1_RAW) || (tracktype == CD_TRACK_MODE2_RAW))) { - return (read_partial_sector(file, buffer, lbasector, chdsector, tracknum, 16, 2336, phys) == CHDERR_NONE); + return !read_partial_sector(file, buffer, lbasector, chdsector, tracknum, 16, 2336, phys); } LOG(("CDROM: Conversion from type %d to type %d not supported!\n", tracktype, datatype)); @@ -660,8 +662,8 @@ uint32_t cdrom_read_subcode(cdrom_file *file, uint32_t lbasector, void *buffer, return 0; // read the data - chd_error err = read_partial_sector(file, buffer, lbasector, chdsector, tracknum, file->cdtoc.tracks[tracknum].datasize, file->cdtoc.tracks[tracknum].subsize); - return (err == CHDERR_NONE); + std::error_condition err = read_partial_sector(file, buffer, lbasector, chdsector, tracknum, file->cdtoc.tracks[tracknum].datasize, file->cdtoc.tracks[tracknum].subsize); + return !err; } @@ -1139,21 +1141,20 @@ const char *cdrom_get_subtype_string(uint32_t subtype) -------------------------------------------------*/ /** - * @fn chd_error cdrom_parse_metadata(chd_file *chd, cdrom_toc *toc) + * @fn std::error_condition cdrom_parse_metadata(chd_file *chd, cdrom_toc *toc) * * @brief Cdrom parse metadata. * * @param [in,out] chd If non-null, the chd. * @param [in,out] toc If non-null, the TOC. * - * @return A chd_error. + * @return A std::error_condition. */ -chd_error cdrom_parse_metadata(chd_file *chd, cdrom_toc *toc) +std::error_condition cdrom_parse_metadata(chd_file *chd, cdrom_toc *toc) { std::string metadata; - chd_error err; - int i; + std::error_condition err; toc->flags = 0; @@ -1168,49 +1169,49 @@ chd_error cdrom_parse_metadata(chd_file *chd, cdrom_toc *toc) /* fetch the metadata for this track */ err = chd->read_metadata(CDROM_TRACK_METADATA_TAG, toc->numtrks, metadata); - if (err == CHDERR_NONE) + if (!err) { /* parse the metadata */ type[0] = subtype[0] = 0; pgtype[0] = pgsub[0] = 0; if (sscanf(metadata.c_str(), CDROM_TRACK_METADATA_FORMAT, &tracknum, type, subtype, &frames) != 4) - return CHDERR_INVALID_DATA; + return chd_file::error::INVALID_DATA; if (tracknum == 0 || tracknum > CD_MAX_TRACKS) - return CHDERR_INVALID_DATA; + return chd_file::error::INVALID_DATA; track = &toc->tracks[tracknum - 1]; } else { err = chd->read_metadata(CDROM_TRACK_METADATA2_TAG, toc->numtrks, metadata); - if (err == CHDERR_NONE) + if (!err) { /* parse the metadata */ type[0] = subtype[0] = 0; pregap = postgap = 0; if (sscanf(metadata.c_str(), CDROM_TRACK_METADATA2_FORMAT, &tracknum, type, subtype, &frames, &pregap, pgtype, pgsub, &postgap) != 8) - return CHDERR_INVALID_DATA; + return chd_file::error::INVALID_DATA; if (tracknum == 0 || tracknum > CD_MAX_TRACKS) - return CHDERR_INVALID_DATA; + return chd_file::error::INVALID_DATA; track = &toc->tracks[tracknum - 1]; } else { err = chd->read_metadata(GDROM_OLD_METADATA_TAG, toc->numtrks, metadata); - if (err == CHDERR_NONE) + if (!err) /* legacy GDROM track was detected */ toc->flags |= CD_FLAG_GDROMLE; else err = chd->read_metadata(GDROM_TRACK_METADATA_TAG, toc->numtrks, metadata); - if (err == CHDERR_NONE) + if (!err) { /* parse the metadata */ type[0] = subtype[0] = 0; pregap = postgap = 0; if (sscanf(metadata.c_str(), GDROM_TRACK_METADATA_FORMAT, &tracknum, type, subtype, &frames, &padframes, &pregap, pgtype, pgsub, &postgap) != 9) - return CHDERR_INVALID_DATA; + return chd_file::error::INVALID_DATA; if (tracknum == 0 || tracknum > CD_MAX_TRACKS) - return CHDERR_INVALID_DATA; + return chd_file::error::INVALID_DATA; track = &toc->tracks[tracknum - 1]; toc->flags |= CD_FLAG_GDROM; } @@ -1226,7 +1227,7 @@ chd_error cdrom_parse_metadata(chd_file *chd, cdrom_toc *toc) track->datasize = 0; cdrom_convert_type_string_to_track_info(type, track); if (track->datasize == 0) - return CHDERR_INVALID_DATA; + return chd_file::error::INVALID_DATA; /* extract the subtype and determine the subcode data size */ track->subtype = CD_SUB_NONE; @@ -1261,21 +1262,21 @@ chd_error cdrom_parse_metadata(chd_file *chd, cdrom_toc *toc) /* if we got any tracks this way, we're done */ if (toc->numtrks > 0) - return CHDERR_NONE; + return std::error_condition(); printf("toc->numtrks = %u?!\n", toc->numtrks); /* look for old-style metadata */ std::vector oldmetadata; err = chd->read_metadata(CDROM_OLD_METADATA_TAG, 0, oldmetadata); - if (err != CHDERR_NONE) + if (err) return err; /* reconstruct the TOC from it */ auto *mrp = reinterpret_cast(&oldmetadata[0]); toc->numtrks = *mrp++; - for (i = 0; i < CD_MAX_TRACKS; i++) + for (int i = 0; i < CD_MAX_TRACKS; i++) { toc->tracks[i].trktype = *mrp++; toc->tracks[i].subtype = *mrp++; @@ -1295,7 +1296,7 @@ chd_error cdrom_parse_metadata(chd_file *chd, cdrom_toc *toc) if (toc->numtrks > CD_MAX_TRACKS) { toc->numtrks = swapendian_int32(toc->numtrks); - for (i = 0; i < CD_MAX_TRACKS; i++) + for (int i = 0; i < CD_MAX_TRACKS; i++) { toc->tracks[i].trktype = swapendian_int32(toc->tracks[i].trktype); toc->tracks[i].subtype = swapendian_int32(toc->tracks[i].subtype); @@ -1307,7 +1308,7 @@ chd_error cdrom_parse_metadata(chd_file *chd, cdrom_toc *toc) } } - return CHDERR_NONE; + return std::error_condition(); } @@ -1316,19 +1317,19 @@ chd_error cdrom_parse_metadata(chd_file *chd, cdrom_toc *toc) -------------------------------------------------*/ /** - * @fn chd_error cdrom_write_metadata(chd_file *chd, const cdrom_toc *toc) + * @fn std::error_condition cdrom_write_metadata(chd_file *chd, const cdrom_toc *toc) * * @brief Cdrom write metadata. * * @param [in,out] chd If non-null, the chd. * @param toc The TOC. * - * @return A chd_error. + * @return A std::error_condition. */ -chd_error cdrom_write_metadata(chd_file *chd, const cdrom_toc *toc) +std::error_condition cdrom_write_metadata(chd_file *chd, const cdrom_toc *toc) { - chd_error err; + std::error_condition err; /* write the metadata */ for (int i = 0; i < toc->numtrks; i++) @@ -1363,10 +1364,10 @@ chd_error cdrom_write_metadata(chd_file *chd, const cdrom_toc *toc) err = chd->write_metadata(GDROM_TRACK_METADATA_TAG, i, metadata); } - if (err != CHDERR_NONE) + if (err) return err; } - return CHDERR_NONE; + return std::error_condition(); } /** diff --git a/src/lib/util/cdrom.h b/src/lib/util/cdrom.h index 27d41da845e..1847a1db83a 100644 --- a/src/lib/util/cdrom.h +++ b/src/lib/util/cdrom.h @@ -7,15 +7,15 @@ Generic MAME cd-rom implementation ***************************************************************************/ - -#ifndef MAME_UTIL_CDROM_H -#define MAME_UTIL_CDROM_H +#ifndef MAME_LIB_UTIL_CDROM_H +#define MAME_LIB_UTIL_CDROM_H #pragma once -#include "osdcore.h" #include "chd.h" +#include "osdcore.h" + /*************************************************************************** @@ -137,8 +137,8 @@ void cdrom_convert_subtype_string_to_track_info(const char *typestring, cdrom_tr void cdrom_convert_subtype_string_to_pregap_info(const char *typestring, cdrom_track_info *info); const char *cdrom_get_type_string(uint32_t trktype); const char *cdrom_get_subtype_string(uint32_t subtype); -chd_error cdrom_parse_metadata(chd_file *chd, cdrom_toc *toc); -chd_error cdrom_write_metadata(chd_file *chd, const cdrom_toc *toc); +std::error_condition cdrom_parse_metadata(chd_file *chd, cdrom_toc *toc); +std::error_condition cdrom_write_metadata(chd_file *chd, const cdrom_toc *toc); // ECC utilities bool ecc_verify(const uint8_t *sector); @@ -184,4 +184,4 @@ static inline uint32_t lba_to_msf_alt(int lba) return ret; } -#endif // MAME_UTIL_CDROM_H +#endif // MAME_LIB_UTIL_CDROM_H diff --git a/src/lib/util/chd.cpp b/src/lib/util/chd.cpp index 0de05849cdd..29792fc36df 100644 --- a/src/lib/util/chd.cpp +++ b/src/lib/util/chd.cpp @@ -8,20 +8,24 @@ ***************************************************************************/ -#include - #include "chd.h" + #include "avhuff.h" -#include "hashing.h" -#include "flac.h" #include "cdrom.h" +#include "corefile.h" #include "coretmpl.h" +#include "flac.h" +#include "hashing.h" + +#include "eminline.h" + #include -#include + +#include #include #include +#include #include -#include "eminline.h" //************************************************************************** @@ -186,14 +190,17 @@ inline void chd_file::be_write_sha1(uint8_t *base, util::sha1_t value) inline void chd_file::file_read(uint64_t offset, void *dest, uint32_t length) { // no file = failure - if (m_file == nullptr) - throw CHDERR_NOT_OPEN; + if (!m_file) + throw std::error_condition(error::NOT_OPEN); // seek and read m_file->seek(offset, SEEK_SET); - uint32_t count = m_file->read(dest, length); - if (count != length) - throw CHDERR_READ_ERROR; + size_t count; + std::error_condition err = m_file->read(dest, length, count); + if (err) + throw err; + else if (count != length) + throw std::error_condition(std::errc::io_error); // TODO: revisit this error code (happens if file is cut off) } @@ -205,14 +212,17 @@ inline void chd_file::file_read(uint64_t offset, void *dest, uint32_t length) inline void chd_file::file_write(uint64_t offset, const void *source, uint32_t length) { // no file = failure - if (m_file == nullptr) - throw CHDERR_NOT_OPEN; + if (!m_file) + throw std::error_condition(error::NOT_OPEN); // seek and write m_file->seek(offset, SEEK_SET); - uint32_t count = m_file->write(source, length); - if (count != length) - throw CHDERR_WRITE_ERROR; + size_t count; + std::error_condition err = m_file->write(source, length, count); + if (err) + throw err; + else if (count != length) + throw std::error_condition(std::errc::interrupted); // can theoretically happen if write is inuterrupted by a signal } @@ -224,15 +234,22 @@ inline void chd_file::file_write(uint64_t offset, const void *source, uint32_t l inline uint64_t chd_file::file_append(const void *source, uint32_t length, uint32_t alignment) { + std::error_condition err; + // no file = failure - if (m_file == nullptr) - throw CHDERR_NOT_OPEN; + if (!m_file) + throw std::error_condition(error::NOT_OPEN); // seek to the end and align if necessary - m_file->seek(0, SEEK_END); + err = m_file->seek(0, SEEK_END); + if (err) + throw err; if (alignment != 0) { - uint64_t offset = m_file->tell(); + uint64_t offset; + err = m_file->tell(offset); + if (err) + throw err; uint32_t delta = offset % alignment; if (delta != 0) { @@ -242,20 +259,27 @@ inline uint64_t chd_file::file_append(const void *source, uint32_t length, uint3 delta = alignment - delta; while (delta != 0) { - uint32_t bytes_to_write = (std::min)(sizeof(buffer), delta); - uint32_t count = m_file->write(buffer, bytes_to_write); - if (count != bytes_to_write) - throw CHDERR_WRITE_ERROR; - delta -= bytes_to_write; + uint32_t bytes_to_write = std::min(sizeof(buffer), delta); + size_t count; + err = m_file->write(buffer, bytes_to_write, count); + if (err) + throw err; + delta -= count; } } } // write the real data - uint64_t offset = m_file->tell(); - uint32_t count = m_file->write(source, length); - if (count != length) - throw CHDERR_READ_ERROR; + uint64_t offset; + err = m_file->tell(offset); + if (err) + throw err; + size_t count; + err = m_file->write(source, length, count); + if (err) + throw err; + else if (count != length) + throw std::error_condition(std::errc::interrupted); // can theoretically happen if write is interrupted by a signal return offset; } @@ -288,11 +312,8 @@ inline uint8_t chd_file::bits_for_value(uint64_t value) */ chd_file::chd_file() - : m_file(nullptr), - m_owns_file(false) { // reset state - memset(m_decompressor, 0, sizeof(m_decompressor)); close(); } @@ -310,6 +331,22 @@ chd_file::~chd_file() close(); } +/** + * @fn util::random_read chd_file::file() + * + * @brief ------------------------------------------------- + * file - return our underlying file + * -------------------------------------------------. + * + * @return A random_read. + */ + +util::random_read &chd_file::file() +{ + assert(m_file); + return *m_file; +} + /** * @fn util::sha1_t chd_file::sha1() * @@ -329,7 +366,7 @@ util::sha1_t chd_file::sha1() file_read(m_sha1_offset, rawbuf, sizeof(rawbuf)); return be_read_sha1(rawbuf); } - catch (chd_error &) + catch (std::error_condition const &) { // on failure, return nullptr return util::sha1_t::null; @@ -354,15 +391,15 @@ util::sha1_t chd_file::raw_sha1() try { // determine offset within the file for data-only - if (m_rawsha1_offset == 0) - throw CHDERR_UNSUPPORTED_VERSION; + if (!m_rawsha1_offset) + throw std::error_condition(error::UNSUPPORTED_VERSION); // read the big-endian version uint8_t rawbuf[sizeof(util::sha1_t)]; file_read(m_rawsha1_offset, rawbuf, sizeof(rawbuf)); return be_read_sha1(rawbuf); } - catch (chd_error &) + catch (std::error_condition const &) { // on failure, return nullptr return util::sha1_t::null; @@ -387,15 +424,15 @@ util::sha1_t chd_file::parent_sha1() try { // determine offset within the file - if (m_parentsha1_offset == 0) - throw CHDERR_UNSUPPORTED_VERSION; + if (!m_parentsha1_offset) + throw std::error_condition(error::UNSUPPORTED_VERSION); // read the big-endian version uint8_t rawbuf[sizeof(util::sha1_t)]; file_read(m_parentsha1_offset, rawbuf, sizeof(rawbuf)); return be_read_sha1(rawbuf); } - catch (chd_error &) + catch (std::error_condition const &) { // on failure, return nullptr return util::sha1_t::null; @@ -403,7 +440,7 @@ util::sha1_t chd_file::parent_sha1() } /** - * @fn chd_error chd_file::hunk_info(uint32_t hunknum, chd_codec_type &compressor, uint32_t &compbytes) + * @fn std::error_condition chd_file::hunk_info(uint32_t hunknum, chd_codec_type &compressor, uint32_t &compbytes) * * @brief ------------------------------------------------- * hunk_info - return information about this hunk @@ -413,14 +450,14 @@ util::sha1_t chd_file::parent_sha1() * @param [in,out] compressor The compressor. * @param [in,out] compbytes The compbytes. * - * @return A chd_error. + * @return A std::error_condition. */ -chd_error chd_file::hunk_info(uint32_t hunknum, chd_codec_type &compressor, uint32_t &compbytes) +std::error_condition chd_file::hunk_info(uint32_t hunknum, chd_codec_type &compressor, uint32_t &compbytes) { // error if invalid if (hunknum >= m_hunkcount) - return CHDERR_HUNK_OUT_OF_RANGE; + return std::error_condition(error::HUNK_OUT_OF_RANGE); // get the map pointer uint8_t *rawmap; @@ -506,11 +543,11 @@ chd_error chd_file::hunk_info(uint32_t hunknum, chd_codec_type &compressor, uint break; default: - return CHDERR_UNKNOWN_COMPRESSION; + return error::UNKNOWN_COMPRESSION; } break; } - return CHDERR_NONE; + return std::error_condition(); } /** @@ -554,8 +591,8 @@ void chd_file::set_raw_sha1(util::sha1_t rawdata) void chd_file::set_parent_sha1(util::sha1_t parent) { // if no file, fail - if (m_file == nullptr) - throw CHDERR_INVALID_FILE; + if (!m_file) + throw std::error_condition(error::INVALID_FILE); // create a big-endian version uint8_t rawbuf[sizeof(util::sha1_t)]; @@ -567,7 +604,7 @@ void chd_file::set_parent_sha1(util::sha1_t parent) } /** - * @fn chd_error chd_file::create(util::core_file &file, uint64_t logicalbytes, uint32_t hunkbytes, uint32_t unitbytes, chd_codec_type compression[4]) + * @fn std::error_condition chd_file::create(util::random_read_write::ptr &&file, uint64_t logicalbytes, uint32_t hunkbytes, uint32_t unitbytes, chd_codec_type compression[4]) * * @brief ------------------------------------------------- * create - create a new file with no parent using an existing opened file handle @@ -579,14 +616,16 @@ void chd_file::set_parent_sha1(util::sha1_t parent) * @param unitbytes The unitbytes. * @param compression The compression. * - * @return A chd_error. + * @return A std::error_condition. */ -chd_error chd_file::create(util::core_file &file, uint64_t logicalbytes, uint32_t hunkbytes, uint32_t unitbytes, chd_codec_type compression[4]) +std::error_condition chd_file::create(util::random_read_write::ptr &&file, uint64_t logicalbytes, uint32_t hunkbytes, uint32_t unitbytes, chd_codec_type compression[4]) { // make sure we don't already have a file open - if (m_file != nullptr) - return CHDERR_ALREADY_OPEN; + if (m_file) + return error::ALREADY_OPEN; + else if (!file) + return std::errc::invalid_argument; // set the header parameters m_logicalbytes = logicalbytes; @@ -596,13 +635,12 @@ chd_error chd_file::create(util::core_file &file, uint64_t logicalbytes, uint32_ m_parent = nullptr; // take ownership of the file - m_file = &file; - m_owns_file = false; + m_file = std::move(file); return create_common(); } /** - * @fn chd_error chd_file::create(util::core_file &file, uint64_t logicalbytes, uint32_t hunkbytes, chd_codec_type compression[4], chd_file &parent) + * @fn std::error_condition chd_file::create(util::random_read_write::ptr &&file, uint64_t logicalbytes, uint32_t hunkbytes, chd_codec_type compression[4], chd_file &parent) * * @brief ------------------------------------------------- * create - create a new file with a parent using an existing opened file handle @@ -614,14 +652,16 @@ chd_error chd_file::create(util::core_file &file, uint64_t logicalbytes, uint32_ * @param compression The compression. * @param [in,out] parent The parent. * - * @return A chd_error. + * @return A std::error_condition. */ -chd_error chd_file::create(util::core_file &file, uint64_t logicalbytes, uint32_t hunkbytes, chd_codec_type compression[4], chd_file &parent) +std::error_condition chd_file::create(util::random_read_write::ptr &&file, uint64_t logicalbytes, uint32_t hunkbytes, chd_codec_type compression[4], chd_file &parent) { // make sure we don't already have a file open - if (m_file != nullptr) - return CHDERR_ALREADY_OPEN; + if (m_file) + return error::ALREADY_OPEN; + else if (!file) + return std::errc::invalid_argument; // set the header parameters m_logicalbytes = logicalbytes; @@ -631,13 +671,12 @@ chd_error chd_file::create(util::core_file &file, uint64_t logicalbytes, uint32_ m_parent = &parent; // take ownership of the file - m_file = &file; - m_owns_file = false; + m_file = std::move(file); return create_common(); } /** - * @fn chd_error chd_file::create(const char *filename, uint64_t logicalbytes, uint32_t hunkbytes, uint32_t unitbytes, chd_codec_type compression[4]) + * @fn std::error_condition chd_file::create(std::string_view filename, uint64_t logicalbytes, uint32_t hunkbytes, uint32_t unitbytes, chd_codec_type compression[4]) * * @brief ------------------------------------------------- * create - create a new file with no parent using a filename @@ -649,40 +688,38 @@ chd_error chd_file::create(util::core_file &file, uint64_t logicalbytes, uint32_ * @param unitbytes The unitbytes. * @param compression The compression. * - * @return A chd_error. + * @return A std::error_condition. */ -chd_error chd_file::create(const char *filename, uint64_t logicalbytes, uint32_t hunkbytes, uint32_t unitbytes, chd_codec_type compression[4]) +std::error_condition chd_file::create(std::string_view filename, uint64_t logicalbytes, uint32_t hunkbytes, uint32_t unitbytes, chd_codec_type compression[4]) { // make sure we don't already have a file open - if (m_file != nullptr) - return CHDERR_ALREADY_OPEN; + if (m_file) + return error::ALREADY_OPEN; // create the new file util::core_file::ptr file; - 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; + std::error_condition filerr = util::core_file::open(filename, OPEN_FLAG_READ | OPEN_FLAG_WRITE | OPEN_FLAG_CREATE, file); + if (filerr) + return filerr; + util::random_read_write::ptr io = util::core_file_read_write(std::move(file)); + if (!io) + return std::errc::not_enough_memory; // create the file normally, then claim the file - const chd_error chderr = create(*file, logicalbytes, hunkbytes, unitbytes, compression); - m_owns_file = true; + std::error_condition chderr = create(std::move(io), logicalbytes, hunkbytes, unitbytes, compression); // if an error happened, close and delete the file - if (chderr != CHDERR_NONE) + if (chderr) { - file.reset(); - osd_file::remove(filename); - } - else - { - file.release(); + io.reset(); + osd_file::remove(std::string(filename)); // FIXME: allow osd_file to use std::string_view } return chderr; } /** - * @fn chd_error chd_file::create(const char *filename, uint64_t logicalbytes, uint32_t hunkbytes, chd_codec_type compression[4], chd_file &parent) + * @fn std::error_condition chd_file::create(std::string_view filename, uint64_t logicalbytes, uint32_t hunkbytes, chd_codec_type compression[4], chd_file &parent) * * @brief ------------------------------------------------- * create - create a new file with a parent using a filename @@ -694,40 +731,38 @@ chd_error chd_file::create(const char *filename, uint64_t logicalbytes, uint32_t * @param compression The compression. * @param [in,out] parent The parent. * - * @return A chd_error. + * @return A std::error_condition. */ -chd_error chd_file::create(const char *filename, uint64_t logicalbytes, uint32_t hunkbytes, chd_codec_type compression[4], chd_file &parent) +std::error_condition chd_file::create(std::string_view filename, uint64_t logicalbytes, uint32_t hunkbytes, chd_codec_type compression[4], chd_file &parent) { // make sure we don't already have a file open - if (m_file != nullptr) - return CHDERR_ALREADY_OPEN; + if (m_file) + return error::ALREADY_OPEN; // create the new file util::core_file::ptr file; - 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; + std::error_condition filerr = util::core_file::open(filename, OPEN_FLAG_READ | OPEN_FLAG_WRITE | OPEN_FLAG_CREATE, file); + if (filerr) + return filerr; + util::random_read_write::ptr io = util::core_file_read_write(std::move(file)); + if (!io) + return std::errc::not_enough_memory; // create the file normally, then claim the file - const chd_error chderr = create(*file, logicalbytes, hunkbytes, compression, parent); - m_owns_file = true; + std::error_condition chderr = create(std::move(io), logicalbytes, hunkbytes, compression, parent); // if an error happened, close and delete the file - if (chderr != CHDERR_NONE) - { - file.reset(); - osd_file::remove(filename); - } - else + if (chderr) { - file.release(); + io.reset(); + osd_file::remove(std::string(filename)); // FIXME: allow osd_file to use std::string_view } return chderr; } /** - * @fn chd_error chd_file::open(const char *filename, bool writeable, chd_file *parent) + * @fn std::error_condition chd_file::open(std::string_view filename, bool writeable, chd_file *parent) * * @brief ------------------------------------------------- * open - open an existing file for read or read/write @@ -737,35 +772,36 @@ chd_error chd_file::create(const char *filename, uint64_t logicalbytes, uint32_t * @param writeable true if writeable. * @param [in,out] parent If non-null, the parent. * - * @return A chd_error. + * @return A std::error_condition. */ -chd_error chd_file::open(const char *filename, bool writeable, chd_file *parent) +std::error_condition chd_file::open(std::string_view filename, bool writeable, chd_file *parent) { // make sure we don't already have a file open - if (m_file != nullptr) - return CHDERR_ALREADY_OPEN; + if (m_file) + return error::ALREADY_OPEN; // open the file const uint32_t openflags = writeable ? (OPEN_FLAG_READ | OPEN_FLAG_WRITE) : OPEN_FLAG_READ; util::core_file::ptr file; - const osd_file::error filerr = util::core_file::open(filename, openflags, file); - if (filerr != osd_file::error::NONE) - return CHDERR_FILE_NOT_FOUND; + std::error_condition filerr = util::core_file::open(filename, openflags, file); + if (filerr) + return filerr; + util::random_read_write::ptr io = util::core_file_read_write(std::move(file)); + if (!io) + return std::errc::not_enough_memory; // now open the CHD - chd_error err = open(*file, writeable, parent); - if (err != CHDERR_NONE) + std::error_condition err = open(std::move(io), writeable, parent); + if (err) return err; // we now own this file - file.release(); - m_owns_file = true; return err; } /** - * @fn chd_error chd_file::open(util::core_file &file, bool writeable, chd_file *parent) + * @fn std::error_condition chd_file::open(util::random_read_write::ptr &&file, bool writeable, chd_file *parent) * * @brief ------------------------------------------------- * open - open an existing file for read or read/write @@ -775,18 +811,19 @@ chd_error chd_file::open(const char *filename, bool writeable, chd_file *parent) * @param writeable true if writeable. * @param [in,out] parent If non-null, the parent. * - * @return A chd_error. + * @return A std::error_condition. */ -chd_error chd_file::open(util::core_file &file, bool writeable, chd_file *parent) +std::error_condition chd_file::open(util::random_read_write::ptr &&file, bool writeable, chd_file *parent) { // make sure we don't already have a file open - if (m_file != nullptr) - return CHDERR_ALREADY_OPEN; + if (m_file) + return error::ALREADY_OPEN; + else if (!file) + return std::errc::invalid_argument; // open the file - m_file = &file; - m_owns_file = false; + m_file = std::move(file); m_parent = parent; m_cachehunk = ~0; return open_common(writeable); @@ -803,10 +840,7 @@ chd_error chd_file::open(util::core_file &file, bool writeable, chd_file *parent void chd_file::close() { // reset file characteristics - if (m_owns_file && m_file) - delete m_file; - m_file = nullptr; - m_owns_file = false; + m_file.reset(); m_allow_reads = false; m_allow_writes = false; @@ -836,10 +870,7 @@ void chd_file::close() // reset compression management for (auto & elem : m_decompressor) - { - delete elem; - elem = nullptr; - } + elem.reset(); m_compressed.clear(); // reset caching @@ -848,7 +879,7 @@ void chd_file::close() } /** - * @fn chd_error chd_file::read_hunk(uint32_t hunknum, void *buffer) + * @fn std::error_condition chd_file::read_hunk(uint32_t hunknum, void *buffer) * * @brief ------------------------------------------------- * read - read a single hunk from the CHD file @@ -870,18 +901,18 @@ void chd_file::close() * @return The hunk. */ -chd_error chd_file::read_hunk(uint32_t hunknum, void *buffer) +std::error_condition chd_file::read_hunk(uint32_t hunknum, void *buffer) { // wrap this for clean reporting try { // punt if no file - if (m_file == nullptr) - throw CHDERR_NOT_OPEN; + if (!m_file) + throw std::error_condition(error::NOT_OPEN); // return an error if out of range if (hunknum >= m_hunkcount) - throw CHDERR_HUNK_OUT_OF_RANGE; + throw std::error_condition(error::HUNK_OUT_OF_RANGE); // get a pointer to the map entry uint64_t blockoffs; @@ -904,29 +935,29 @@ chd_error chd_file::read_hunk(uint32_t hunknum, void *buffer) file_read(blockoffs, &m_compressed[0], blocklen); m_decompressor[0]->decompress(&m_compressed[0], blocklen, dest, m_hunkbytes); if (!(rawmap[15] & V34_MAP_ENTRY_FLAG_NO_CRC) && dest != nullptr && util::crc32_creator::simple(dest, m_hunkbytes) != blockcrc) - throw CHDERR_DECOMPRESSION_ERROR; - return CHDERR_NONE; + throw std::error_condition(error::DECOMPRESSION_ERROR); + return std::error_condition(); case V34_MAP_ENTRY_TYPE_UNCOMPRESSED: file_read(blockoffs, dest, m_hunkbytes); if (!(rawmap[15] & V34_MAP_ENTRY_FLAG_NO_CRC) && util::crc32_creator::simple(dest, m_hunkbytes) != blockcrc) - throw CHDERR_DECOMPRESSION_ERROR; - return CHDERR_NONE; + throw std::error_condition(error::DECOMPRESSION_ERROR); + return std::error_condition(); case V34_MAP_ENTRY_TYPE_MINI: be_write(dest, blockoffs, 8); for (uint32_t bytes = 8; bytes < m_hunkbytes; bytes++) dest[bytes] = dest[bytes - 8]; if (!(rawmap[15] & V34_MAP_ENTRY_FLAG_NO_CRC) && util::crc32_creator::simple(dest, m_hunkbytes) != blockcrc) - throw CHDERR_DECOMPRESSION_ERROR; - return CHDERR_NONE; + throw std::error_condition(error::DECOMPRESSION_ERROR); + return std::error_condition(); case V34_MAP_ENTRY_TYPE_SELF_HUNK: return read_hunk(blockoffs, dest); case V34_MAP_ENTRY_TYPE_PARENT_HUNK: if (m_parent_missing) - throw CHDERR_REQUIRES_PARENT; + throw std::error_condition(error::REQUIRES_PARENT); return m_parent->read_hunk(blockoffs, dest); } break; @@ -942,12 +973,12 @@ chd_error chd_file::read_hunk(uint32_t hunknum, void *buffer) if (blockoffs != 0) file_read(blockoffs, dest, m_hunkbytes); else if (m_parent_missing) - throw CHDERR_REQUIRES_PARENT; + throw std::error_condition(error::REQUIRES_PARENT); else if (m_parent != nullptr) m_parent->read_hunk(hunknum, dest); else memset(dest, 0, m_hunkbytes); - return CHDERR_NONE; + return std::error_condition(); } // compressed case @@ -963,41 +994,40 @@ chd_error chd_file::read_hunk(uint32_t hunknum, void *buffer) file_read(blockoffs, &m_compressed[0], blocklen); m_decompressor[rawmap[0]]->decompress(&m_compressed[0], blocklen, dest, m_hunkbytes); if (!m_decompressor[rawmap[0]]->lossy() && dest != nullptr && util::crc16_creator::simple(dest, m_hunkbytes) != blockcrc) - throw CHDERR_DECOMPRESSION_ERROR; + throw std::error_condition(error::DECOMPRESSION_ERROR); if (m_decompressor[rawmap[0]]->lossy() && util::crc16_creator::simple(&m_compressed[0], blocklen) != blockcrc) - throw CHDERR_DECOMPRESSION_ERROR; - return CHDERR_NONE; + throw std::error_condition(error::DECOMPRESSION_ERROR); + return std::error_condition(); case COMPRESSION_NONE: file_read(blockoffs, dest, m_hunkbytes); if (util::crc16_creator::simple(dest, m_hunkbytes) != blockcrc) - throw CHDERR_DECOMPRESSION_ERROR; - return CHDERR_NONE; + throw std::error_condition(error::DECOMPRESSION_ERROR); + return std::error_condition(); case COMPRESSION_SELF: return read_hunk(blockoffs, dest); case COMPRESSION_PARENT: if (m_parent_missing) - throw CHDERR_REQUIRES_PARENT; + throw std::error_condition(error::REQUIRES_PARENT); return m_parent->read_bytes(uint64_t(blockoffs) * uint64_t(m_parent->unit_bytes()), dest, m_hunkbytes); } break; } // if we get here, something was wrong - throw CHDERR_READ_ERROR; + throw std::error_condition(std::errc::io_error); } - - // just return errors - catch (chd_error &err) + catch (std::error_condition const &err) { + // just return errors return err; } } /** - * @fn chd_error chd_file::write_hunk(uint32_t hunknum, const void *buffer) + * @fn std::error_condition chd_file::write_hunk(uint32_t hunknum, const void *buffer) * * @brief ------------------------------------------------- * write - write a single hunk to the CHD file @@ -1012,29 +1042,29 @@ chd_error chd_file::read_hunk(uint32_t hunknum, void *buffer) * @param hunknum The hunknum. * @param buffer The buffer. * - * @return A chd_error. + * @return A std::error_condition. */ -chd_error chd_file::write_hunk(uint32_t hunknum, const void *buffer) +std::error_condition chd_file::write_hunk(uint32_t hunknum, const void *buffer) { // wrap this for clean reporting try { // punt if no file - if (m_file == nullptr) - throw CHDERR_NOT_OPEN; + if (!m_file) + throw std::error_condition(error::NOT_OPEN); // return an error if out of range if (hunknum >= m_hunkcount) - throw CHDERR_HUNK_OUT_OF_RANGE; + throw std::error_condition(error::HUNK_OUT_OF_RANGE); // if not writeable, fail if (!m_allow_writes) - throw CHDERR_FILE_NOT_WRITEABLE; + throw std::error_condition(error::FILE_NOT_WRITEABLE); // uncompressed writes only via this interface if (compressed()) - throw CHDERR_FILE_NOT_WRITEABLE; + throw std::error_condition(error::FILE_NOT_WRITEABLE); // see if we have allocated the space on disk for this hunk uint8_t *rawmap = &m_rawmap[hunknum * 4]; @@ -1055,7 +1085,7 @@ chd_error chd_file::write_hunk(uint32_t hunknum, const void *buffer) // if it's all zeros, do nothing more if (all_zeros) - return CHDERR_NONE; + return std::error_condition(); // append new data to the end of the file, aligning the first chunk rawentry = file_append(buffer, m_hunkbytes, m_hunkbytes) / m_hunkbytes; @@ -1068,22 +1098,22 @@ chd_error chd_file::write_hunk(uint32_t hunknum, const void *buffer) if (hunknum == m_cachehunk && buffer != &m_cache[0]) memcpy(&m_cache[0], buffer, m_hunkbytes); } - - // otherwise, just overwrite else + { + // otherwise, just overwrite file_write(uint64_t(rawentry) * uint64_t(m_hunkbytes), buffer, m_hunkbytes); - return CHDERR_NONE; + } + return std::error_condition(); } - - // just return errors - catch (chd_error &err) + catch (std::error_condition const &err) { + // just return errors return err; } } /** - * @fn chd_error chd_file::read_units(uint64_t unitnum, void *buffer, uint32_t count) + * @fn std::error_condition chd_file::read_units(uint64_t unitnum, void *buffer, uint32_t count) * * @brief ------------------------------------------------- * read_units - read the given number of units from the CHD @@ -1096,13 +1126,13 @@ chd_error chd_file::write_hunk(uint32_t hunknum, const void *buffer) * @return The units. */ -chd_error chd_file::read_units(uint64_t unitnum, void *buffer, uint32_t count) +std::error_condition chd_file::read_units(uint64_t unitnum, void *buffer, uint32_t count) { return read_bytes(unitnum * uint64_t(m_unitbytes), buffer, count * m_unitbytes); } /** - * @fn chd_error chd_file::write_units(uint64_t unitnum, const void *buffer, uint32_t count) + * @fn std::error_condition chd_file::write_units(uint64_t unitnum, const void *buffer, uint32_t count) * * @brief ------------------------------------------------- * write_units - write the given number of units to the CHD @@ -1112,16 +1142,16 @@ chd_error chd_file::read_units(uint64_t unitnum, void *buffer, uint32_t count) * @param buffer The buffer. * @param count Number of. * - * @return A chd_error. + * @return A std::error_condition. */ -chd_error chd_file::write_units(uint64_t unitnum, const void *buffer, uint32_t count) +std::error_condition chd_file::write_units(uint64_t unitnum, const void *buffer, uint32_t count) { return write_bytes(unitnum * uint64_t(m_unitbytes), buffer, count * m_unitbytes); } /** - * @fn chd_error chd_file::read_bytes(uint64_t offset, void *buffer, uint32_t bytes) + * @fn std::error_condition chd_file::read_bytes(uint64_t offset, void *buffer, uint32_t bytes) * * @brief ------------------------------------------------- * read_bytes - read from the CHD at a byte level, using the cache to handle partial @@ -1135,7 +1165,7 @@ chd_error chd_file::write_units(uint64_t unitnum, const void *buffer, uint32_t c * @return The bytes. */ -chd_error chd_file::read_bytes(uint64_t offset, void *buffer, uint32_t bytes) +std::error_condition chd_file::read_bytes(uint64_t offset, void *buffer, uint32_t bytes) { // iterate over hunks uint32_t first_hunk = offset / m_hunkbytes; @@ -1148,7 +1178,7 @@ chd_error chd_file::read_bytes(uint64_t offset, void *buffer, uint32_t bytes) uint32_t endoffs = (curhunk == last_hunk) ? ((offset + bytes - 1) % m_hunkbytes) : (m_hunkbytes - 1); // if it's a full block, just read directly from disk unless it's the cached hunk - chd_error err = CHDERR_NONE; + std::error_condition err; if (startoffs == 0 && endoffs == m_hunkbytes - 1 && curhunk != m_cachehunk) err = read_hunk(curhunk, dest); @@ -1158,7 +1188,7 @@ chd_error chd_file::read_bytes(uint64_t offset, void *buffer, uint32_t bytes) if (curhunk != m_cachehunk) { err = read_hunk(curhunk, &m_cache[0]); - if (err != CHDERR_NONE) + if (err) return err; m_cachehunk = curhunk; } @@ -1166,15 +1196,15 @@ chd_error chd_file::read_bytes(uint64_t offset, void *buffer, uint32_t bytes) } // handle errors and advance - if (err != CHDERR_NONE) + if (err) return err; dest += endoffs + 1 - startoffs; } - return CHDERR_NONE; + return std::error_condition(); } /** - * @fn chd_error chd_file::write_bytes(uint64_t offset, const void *buffer, uint32_t bytes) + * @fn std::error_condition chd_file::write_bytes(uint64_t offset, const void *buffer, uint32_t bytes) * * @brief ------------------------------------------------- * write_bytes - write to the CHD at a byte level, using the cache to handle partial @@ -1185,10 +1215,10 @@ chd_error chd_file::read_bytes(uint64_t offset, void *buffer, uint32_t bytes) * @param buffer The buffer. * @param bytes The bytes. * - * @return A chd_error. + * @return A std::error_condition. */ -chd_error chd_file::write_bytes(uint64_t offset, const void *buffer, uint32_t bytes) +std::error_condition chd_file::write_bytes(uint64_t offset, const void *buffer, uint32_t bytes) { // iterate over hunks uint32_t first_hunk = offset / m_hunkbytes; @@ -1201,7 +1231,7 @@ chd_error chd_file::write_bytes(uint64_t offset, const void *buffer, uint32_t by uint32_t endoffs = (curhunk == last_hunk) ? ((offset + bytes - 1) % m_hunkbytes) : (m_hunkbytes - 1); // if it's a full block, just write directly to disk unless it's the cached hunk - chd_error err = CHDERR_NONE; + std::error_condition err; if (startoffs == 0 && endoffs == m_hunkbytes - 1 && curhunk != m_cachehunk) err = write_hunk(curhunk, source); @@ -1211,7 +1241,7 @@ chd_error chd_file::write_bytes(uint64_t offset, const void *buffer, uint32_t by if (curhunk != m_cachehunk) { err = read_hunk(curhunk, &m_cache[0]); - if (err != CHDERR_NONE) + if (err) return err; m_cachehunk = curhunk; } @@ -1220,15 +1250,15 @@ chd_error chd_file::write_bytes(uint64_t offset, const void *buffer, uint32_t by } // handle errors and advance - if (err != CHDERR_NONE) + if (err) return err; source += endoffs + 1 - startoffs; } - return CHDERR_NONE; + return std::error_condition(); } /** - * @fn chd_error chd_file::read_metadata(chd_metadata_tag searchtag, uint32_t searchindex, std::string &output) + * @fn std::error_condition chd_file::read_metadata(chd_metadata_tag searchtag, uint32_t searchindex, std::string &output) * * @brief ------------------------------------------------- * read_metadata - read the indexed metadata of the given type @@ -1244,7 +1274,7 @@ chd_error chd_file::write_bytes(uint64_t offset, const void *buffer, uint32_t by * @return The metadata. */ -chd_error chd_file::read_metadata(chd_metadata_tag searchtag, uint32_t searchindex, std::string &output) +std::error_condition chd_file::read_metadata(chd_metadata_tag searchtag, uint32_t searchindex, std::string &output) { // wrap this for clean reporting try @@ -1252,23 +1282,22 @@ chd_error chd_file::read_metadata(chd_metadata_tag searchtag, uint32_t searchind // if we didn't find it, just return metadata_entry metaentry; if (!metadata_find(searchtag, searchindex, metaentry)) - throw CHDERR_METADATA_NOT_FOUND; + throw std::error_condition(error::METADATA_NOT_FOUND); // read the metadata output.assign(metaentry.length, '\0'); file_read(metaentry.offset + METADATA_HEADER_SIZE, &output[0], metaentry.length); - return CHDERR_NONE; + return std::error_condition(); } - - // just return errors - catch (chd_error &err) + catch (std::error_condition const &err) { + // just return errors return err; } } /** - * @fn chd_error chd_file::read_metadata(chd_metadata_tag searchtag, uint32_t searchindex, std::vector &output) + * @fn std::error_condition chd_file::read_metadata(chd_metadata_tag searchtag, uint32_t searchindex, std::vector &output) * * @brief Reads a metadata. * @@ -1282,7 +1311,7 @@ chd_error chd_file::read_metadata(chd_metadata_tag searchtag, uint32_t searchind * @return The metadata. */ -chd_error chd_file::read_metadata(chd_metadata_tag searchtag, uint32_t searchindex, std::vector &output) +std::error_condition chd_file::read_metadata(chd_metadata_tag searchtag, uint32_t searchindex, std::vector &output) { // wrap this for clean reporting try @@ -1290,23 +1319,22 @@ chd_error chd_file::read_metadata(chd_metadata_tag searchtag, uint32_t searchind // if we didn't find it, just return metadata_entry metaentry; if (!metadata_find(searchtag, searchindex, metaentry)) - throw CHDERR_METADATA_NOT_FOUND; + throw std::error_condition(error::METADATA_NOT_FOUND); // read the metadata output.resize(metaentry.length); file_read(metaentry.offset + METADATA_HEADER_SIZE, &output[0], metaentry.length); - return CHDERR_NONE; + return std::error_condition(); } - - // just return errors - catch (chd_error &err) + catch (std::error_condition const &err) { + // just return errors return err; } } /** - * @fn chd_error chd_file::read_metadata(chd_metadata_tag searchtag, uint32_t searchindex, void *output, uint32_t outputlen, uint32_t &resultlen) + * @fn std::error_condition chd_file::read_metadata(chd_metadata_tag searchtag, uint32_t searchindex, void *output, uint32_t outputlen, uint32_t &resultlen) * * @brief Reads a metadata. * @@ -1322,7 +1350,7 @@ chd_error chd_file::read_metadata(chd_metadata_tag searchtag, uint32_t searchind * @return The metadata. */ -chd_error chd_file::read_metadata(chd_metadata_tag searchtag, uint32_t searchindex, void *output, uint32_t outputlen, uint32_t &resultlen) +std::error_condition chd_file::read_metadata(chd_metadata_tag searchtag, uint32_t searchindex, void *output, uint32_t outputlen, uint32_t &resultlen) { // wrap this for clean reporting try @@ -1330,23 +1358,22 @@ chd_error chd_file::read_metadata(chd_metadata_tag searchtag, uint32_t searchind // if we didn't find it, just return metadata_entry metaentry; if (!metadata_find(searchtag, searchindex, metaentry)) - throw CHDERR_METADATA_NOT_FOUND; + throw std::error_condition(error::METADATA_NOT_FOUND); // read the metadata resultlen = metaentry.length; file_read(metaentry.offset + METADATA_HEADER_SIZE, output, std::min(outputlen, resultlen)); - return CHDERR_NONE; + return std::error_condition(); } - - // just return errors - catch (chd_error &err) + catch (std::error_condition const &err) { + // just return errors return err; } } /** - * @fn chd_error chd_file::read_metadata(chd_metadata_tag searchtag, uint32_t searchindex, std::vector &output, chd_metadata_tag &resulttag, uint8_t &resultflags) + * @fn std::error_condition chd_file::read_metadata(chd_metadata_tag searchtag, uint32_t searchindex, std::vector &output, chd_metadata_tag &resulttag, uint8_t &resultflags) * * @brief Reads a metadata. * @@ -1362,7 +1389,7 @@ chd_error chd_file::read_metadata(chd_metadata_tag searchtag, uint32_t searchind * @return The metadata. */ -chd_error chd_file::read_metadata(chd_metadata_tag searchtag, uint32_t searchindex, std::vector &output, chd_metadata_tag &resulttag, uint8_t &resultflags) +std::error_condition chd_file::read_metadata(chd_metadata_tag searchtag, uint32_t searchindex, std::vector &output, chd_metadata_tag &resulttag, uint8_t &resultflags) { // wrap this for clean reporting try @@ -1370,25 +1397,24 @@ chd_error chd_file::read_metadata(chd_metadata_tag searchtag, uint32_t searchind // if we didn't find it, just return metadata_entry metaentry; if (!metadata_find(searchtag, searchindex, metaentry)) - throw CHDERR_METADATA_NOT_FOUND; + throw std::error_condition(error::METADATA_NOT_FOUND); // read the metadata output.resize(metaentry.length); file_read(metaentry.offset + METADATA_HEADER_SIZE, &output[0], metaentry.length); resulttag = metaentry.metatag; resultflags = metaentry.flags; - return CHDERR_NONE; + return std::error_condition(); } - - // just return errors - catch (chd_error &err) + catch (std::error_condition const &err) { + // just return errors return err; } } /** - * @fn chd_error chd_file::write_metadata(chd_metadata_tag metatag, uint32_t metaindex, const void *inputbuf, uint32_t inputlen, uint8_t flags) + * @fn std::error_condition chd_file::write_metadata(chd_metadata_tag metatag, uint32_t metaindex, const void *inputbuf, uint32_t inputlen, uint8_t flags) * * @brief ------------------------------------------------- * write_metadata - write the indexed metadata of the given type @@ -1400,17 +1426,17 @@ chd_error chd_file::read_metadata(chd_metadata_tag searchtag, uint32_t searchind * @param inputlen The inputlen. * @param flags The flags. * - * @return A chd_error. + * @return A std::error_condition. */ -chd_error chd_file::write_metadata(chd_metadata_tag metatag, uint32_t metaindex, const void *inputbuf, uint32_t inputlen, uint8_t flags) +std::error_condition chd_file::write_metadata(chd_metadata_tag metatag, uint32_t metaindex, const void *inputbuf, uint32_t inputlen, uint8_t flags) { // wrap this for clean reporting try { // must write at least 1 byte and no more than 16MB if (inputlen < 1 || inputlen >= 16 * 1024 * 1024) - return CHDERR_INVALID_PARAMETER; + return std::error_condition(std::errc::invalid_argument); // find the entry if it already exists metadata_entry metaentry; @@ -1459,18 +1485,17 @@ chd_error chd_file::write_metadata(chd_metadata_tag metatag, uint32_t metaindex, // update the hash metadata_update_hash(); - return CHDERR_NONE; + return std::error_condition(); } - - // return any errors - catch (chd_error &err) + catch (std::error_condition const &err) { + // return any errors return err; } } /** - * @fn chd_error chd_file::delete_metadata(chd_metadata_tag metatag, uint32_t metaindex) + * @fn std::error_condition chd_file::delete_metadata(chd_metadata_tag metatag, uint32_t metaindex) * * @brief ------------------------------------------------- * delete_metadata - remove the given metadata from the list @@ -1482,10 +1507,10 @@ chd_error chd_file::write_metadata(chd_metadata_tag metatag, uint32_t metaindex, * @param metatag The metatag. * @param metaindex The metaindex. * - * @return A chd_error. + * @return A std::error_condition. */ -chd_error chd_file::delete_metadata(chd_metadata_tag metatag, uint32_t metaindex) +std::error_condition chd_file::delete_metadata(chd_metadata_tag metatag, uint32_t metaindex) { // wrap this for clean reporting try @@ -1493,22 +1518,21 @@ chd_error chd_file::delete_metadata(chd_metadata_tag metatag, uint32_t metaindex // find the entry metadata_entry metaentry; if (!metadata_find(metatag, metaindex, metaentry)) - throw CHDERR_METADATA_NOT_FOUND; + throw std::error_condition(error::METADATA_NOT_FOUND); // point the previous to the next, unlinking us metadata_set_previous_next(metaentry.prev, metaentry.next); - return CHDERR_NONE; + return std::error_condition(); } - - // return any errors - catch (chd_error &err) + catch (std::error_condition const &err) { + // return any errors return err; } } /** - * @fn chd_error chd_file::clone_all_metadata(chd_file &source) + * @fn std::error_condition chd_file::clone_all_metadata(chd_file &source) * * @brief ------------------------------------------------- * clone_all_metadata - clone the metadata from one CHD to a second @@ -1518,10 +1542,10 @@ chd_error chd_file::delete_metadata(chd_metadata_tag metatag, uint32_t metaindex * * @param [in,out] source Another instance to copy. * - * @return A chd_error. + * @return A std::error_condition. */ -chd_error chd_file::clone_all_metadata(chd_file &source) +std::error_condition chd_file::clone_all_metadata(chd_file &source) { // wrap this for clean reporting try @@ -1540,16 +1564,15 @@ chd_error chd_file::clone_all_metadata(chd_file &source) source.file_read(metaentry.offset + METADATA_HEADER_SIZE, &filedata[0], metaentry.length); // write it to the destination - chd_error err = write_metadata(metaentry.metatag, (uint32_t)-1, &filedata[0], metaentry.length, metaentry.flags); - if (err != CHDERR_NONE) + std::error_condition err = write_metadata(metaentry.metatag, (uint32_t)-1, &filedata[0], metaentry.length, metaentry.flags); + if (err) throw err; } - return CHDERR_NONE; + return std::error_condition(); } - - // return any errors - catch (chd_error &err) + catch (std::error_condition const &err) { + // return any errors return err; } } @@ -1607,7 +1630,7 @@ util::sha1_t chd_file::compute_overall_sha1(util::sha1_t rawsha1) } /** - * @fn chd_error chd_file::codec_configure(chd_codec_type codec, int param, void *config) + * @fn std::error_condition chd_file::codec_configure(chd_codec_type codec, int param, void *config) * * @brief ------------------------------------------------- * codec_config - set internal codec parameters @@ -1617,10 +1640,10 @@ util::sha1_t chd_file::compute_overall_sha1(util::sha1_t rawsha1) * @param param The parameter. * @param [in,out] config If non-null, the configuration. * - * @return A chd_error. + * @return A std::error_condition. */ -chd_error chd_file::codec_configure(chd_codec_type codec, int param, void *config) +std::error_condition chd_file::codec_configure(chd_codec_type codec, int param, void *config) { // wrap this for clean reporting try @@ -1630,14 +1653,13 @@ chd_error chd_file::codec_configure(chd_codec_type codec, int param, void *confi if (m_compression[codecnum] == codec) { m_decompressor[codecnum]->configure(param, config); - return CHDERR_NONE; + return std::error_condition(); } - return CHDERR_INVALID_PARAMETER; + return std::errc::invalid_argument; } - - // return any errors - catch (chd_error &err) + catch (std::error_condition const &err) { + // return any errors return err; } } @@ -1654,44 +1676,49 @@ chd_error chd_file::codec_configure(chd_codec_type codec, int param, void *confi * @return null if it fails, else a char*. */ -const char *chd_file::error_string(chd_error err) +std::error_category const &chd_category() noexcept { - switch (err) + class chd_category_impl : public std::error_category { - case CHDERR_NONE: return "no error"; - case CHDERR_NO_INTERFACE: return "no drive interface"; - case CHDERR_OUT_OF_MEMORY: return "out of memory"; - case CHDERR_NOT_OPEN: return "file not open"; - case CHDERR_ALREADY_OPEN: return "file already open"; - case CHDERR_INVALID_FILE: return "invalid file"; - case CHDERR_INVALID_PARAMETER: return "invalid parameter"; - case CHDERR_INVALID_DATA: return "invalid data"; - case CHDERR_FILE_NOT_FOUND: return "file not found"; - case CHDERR_REQUIRES_PARENT: return "requires parent"; - case CHDERR_FILE_NOT_WRITEABLE: return "file not writeable"; - case CHDERR_READ_ERROR: return "read error"; - case CHDERR_WRITE_ERROR: return "write error"; - case CHDERR_CODEC_ERROR: return "codec error"; - case CHDERR_INVALID_PARENT: return "invalid parent"; - case CHDERR_HUNK_OUT_OF_RANGE: return "hunk out of range"; - case CHDERR_DECOMPRESSION_ERROR: return "decompression error"; - case CHDERR_COMPRESSION_ERROR: return "compression error"; - case CHDERR_CANT_CREATE_FILE: return "can't create file"; - case CHDERR_CANT_VERIFY: return "can't verify file"; - case CHDERR_NOT_SUPPORTED: return "operation not supported"; - case CHDERR_METADATA_NOT_FOUND: return "can't find metadata"; - case CHDERR_INVALID_METADATA_SIZE: return "invalid metadata size"; - case CHDERR_UNSUPPORTED_VERSION: return "mismatched DIFF and CHD or unsupported CHD version"; - case CHDERR_VERIFY_INCOMPLETE: return "incomplete verify"; - case CHDERR_INVALID_METADATA: return "invalid metadata"; - case CHDERR_INVALID_STATE: return "invalid state"; - case CHDERR_OPERATION_PENDING: return "operation pending"; - case CHDERR_UNSUPPORTED_FORMAT: return "unsupported format"; - case CHDERR_UNKNOWN_COMPRESSION: return "unknown compression type"; - case CHDERR_WALKING_PARENT: return "currently examining parent"; - case CHDERR_COMPRESSING: return "currently compressing"; - default: return "undocumented error"; - } + virtual char const *name() const noexcept override { return "chd"; } + + virtual std::string message(int condition) const override + { + using namespace std::literals; + static std::string_view const s_messages[] = { + "No error"sv, + "No drive interface"sv, + "File not open"sv, + "File already open"sv, + "Invalid file"sv, + "Invalid data"sv, + "Requires parent"sv, + "File not writeable"sv, + "Codec error"sv, + "Invalid parent"sv, + "Hunk out of range"sv, + "Decompression error"sv, + "Compression error"sv, + "Can't verify file"sv, + "Can't find metadata"sv, + "Invalid metadata size"sv, + "Mismatched DIFF and CHD or unsupported CHD version"sv, + "Incomplete verify"sv, + "Invalid metadata"sv, + "Invalid state"sv, + "Operation pending"sv, + "Unsupported format"sv, + "Unknown compression type"sv, + "Currently examining parent"sv, + "Currently compressing"sv }; + if ((0 <= condition) && (std::size(s_messages) > condition)) + return std::string(s_messages[condition]); + else + return "Unknown error"s; + } + }; + static chd_category_impl const s_chd_category_instance; + return s_chd_category_instance; } @@ -1716,15 +1743,15 @@ uint32_t chd_file::guess_unitbytes() // look for hard disk metadata; if found, then the unit size == sector size std::string metadata; int i0, i1, i2, i3; - if (read_metadata(HARD_DISK_METADATA_TAG, 0, metadata) == CHDERR_NONE && sscanf(metadata.c_str(), HARD_DISK_METADATA_FORMAT, &i0, &i1, &i2, &i3) == 4) + if (!read_metadata(HARD_DISK_METADATA_TAG, 0, metadata) && sscanf(metadata.c_str(), HARD_DISK_METADATA_FORMAT, &i0, &i1, &i2, &i3) == 4) return i3; // look for CD-ROM metadata; if found, then the unit size == CD frame size - if (read_metadata(CDROM_OLD_METADATA_TAG, 0, metadata) == CHDERR_NONE || - read_metadata(CDROM_TRACK_METADATA_TAG, 0, metadata) == CHDERR_NONE || - read_metadata(CDROM_TRACK_METADATA2_TAG, 0, metadata) == CHDERR_NONE || - read_metadata(GDROM_OLD_METADATA_TAG, 0, metadata) == CHDERR_NONE || - read_metadata(GDROM_TRACK_METADATA_TAG, 0, metadata) == CHDERR_NONE) + if (!read_metadata(CDROM_OLD_METADATA_TAG, 0, metadata) || + !read_metadata(CDROM_TRACK_METADATA_TAG, 0, metadata) || + !read_metadata(CDROM_TRACK_METADATA2_TAG, 0, metadata) || + !read_metadata(GDROM_OLD_METADATA_TAG, 0, metadata) || + !read_metadata(GDROM_TRACK_METADATA_TAG, 0, metadata)) return CD_FRAME_SIZE; // otherwise, just map 1:1 with the hunk size @@ -1751,7 +1778,7 @@ void chd_file::parse_v3_header(uint8_t *rawheader, util::sha1_t &parentsha1) { // verify header length if (be_read(&rawheader[8], 4) != V3_HEADER_SIZE) - throw CHDERR_INVALID_FILE; + throw std::error_condition(error::INVALID_FILE); // extract core info m_logicalbytes = be_read(&rawheader[28], 8); @@ -1771,7 +1798,7 @@ void chd_file::parse_v3_header(uint8_t *rawheader, util::sha1_t &parentsha1) case 1: m_compression[0] = CHD_CODEC_ZLIB; break; case 2: m_compression[0] = CHD_CODEC_ZLIB; break; case 3: m_compression[0] = CHD_CODEC_AVHUFF; break; - default: throw CHDERR_UNKNOWN_COMPRESSION; + default: throw std::error_condition(error::UNKNOWN_COMPRESSION); } m_compression[1] = m_compression[2] = m_compression[3] = CHD_CODEC_NONE; @@ -1814,7 +1841,7 @@ void chd_file::parse_v4_header(uint8_t *rawheader, util::sha1_t &parentsha1) { // verify header length if (be_read(&rawheader[8], 4) != V4_HEADER_SIZE) - throw CHDERR_INVALID_FILE; + throw std::error_condition(error::INVALID_FILE); // extract core info m_logicalbytes = be_read(&rawheader[28], 8); @@ -1834,7 +1861,7 @@ void chd_file::parse_v4_header(uint8_t *rawheader, util::sha1_t &parentsha1) case 1: m_compression[0] = CHD_CODEC_ZLIB; break; case 2: m_compression[0] = CHD_CODEC_ZLIB; break; case 3: m_compression[0] = CHD_CODEC_AVHUFF; break; - default: throw CHDERR_UNKNOWN_COMPRESSION; + default: throw std::error_condition(error::UNKNOWN_COMPRESSION); } m_compression[1] = m_compression[2] = m_compression[3] = CHD_CODEC_NONE; @@ -1874,7 +1901,7 @@ void chd_file::parse_v5_header(uint8_t *rawheader, util::sha1_t &parentsha1) { // verify header length if (be_read(&rawheader[8], 4) != V5_HEADER_SIZE) - throw CHDERR_INVALID_FILE; + throw std::error_condition(error::INVALID_FILE); // extract core info m_logicalbytes = be_read(&rawheader[32], 8); @@ -1908,7 +1935,7 @@ void chd_file::parse_v5_header(uint8_t *rawheader, util::sha1_t &parentsha1) } /** - * @fn chd_error chd_file::compress_v5_map() + * @fn std::error_condition chd_file::compress_v5_map() * * @brief ------------------------------------------------- * compress_v5_map - compress the v5 map and write it to the end of the file @@ -1917,10 +1944,10 @@ void chd_file::parse_v5_header(uint8_t *rawheader, util::sha1_t &parentsha1) * @exception CHDERR_COMPRESSION_ERROR Thrown when a chderr compression error error * condition occurs. * - * @return A chd_error. + * @return A std::error_condition. */ -chd_error chd_file::compress_v5_map() +std::error_condition chd_file::compress_v5_map() { try { @@ -2015,10 +2042,10 @@ chd_error chd_file::compress_v5_map() bitstream_out bitbuf(&compressed[16], compressed.size() - 16); huffman_error err = encoder.compute_tree_from_histo(); if (err != HUFFERR_NONE) - throw CHDERR_COMPRESSION_ERROR; + throw std::error_condition(error::COMPRESSION_ERROR); err = encoder.export_tree_rle(bitbuf); if (err != HUFFERR_NONE) - throw CHDERR_COMPRESSION_ERROR; + throw std::error_condition(error::COMPRESSION_ERROR); // encode the data for (uint8_t *src = &compression_rle[0]; src < dest; src++) @@ -2113,9 +2140,9 @@ chd_error chd_file::compress_v5_map() uint8_t rawbuf[sizeof(uint64_t)]; be_write(rawbuf, m_mapoffset, 8); file_write(m_mapoffset_offset, rawbuf, sizeof(rawbuf)); - return CHDERR_NONE; + return std::error_condition(); } - catch (chd_error &err) + catch (std::error_condition const &err) { return err; } @@ -2160,7 +2187,7 @@ void chd_file::decompress_v5_map() huffman_decoder<16, 8> decoder; huffman_error err = decoder.import_tree_rle(bitbuf); if (err != HUFFERR_NONE) - throw CHDERR_DECOMPRESSION_ERROR; + throw std::error_condition(error::DECOMPRESSION_ERROR); uint8_t lastcomp = 0; int repcount = 0; for (int hunknum = 0; hunknum < m_hunkcount; hunknum++) @@ -2244,11 +2271,11 @@ void chd_file::decompress_v5_map() // verify the final CRC if (util::crc16_creator::simple(&m_rawmap[0], m_hunkcount * 12) != mapcrc) - throw CHDERR_DECOMPRESSION_ERROR; + throw std::error_condition(error::DECOMPRESSION_ERROR); } /** - * @fn chd_error chd_file::create_common() + * @fn std::error_condition chd_file::create_common() * * @brief ------------------------------------------------- * create_common - command path when creating a new CHD file @@ -2264,7 +2291,7 @@ void chd_file::decompress_v5_map() * @return The new common. */ -chd_error chd_file::create_common() +std::error_condition chd_file::create_common() { // wrap in try for proper error handling try @@ -2273,14 +2300,14 @@ chd_error chd_file::create_common() m_metaoffset = 0; // if we have a parent, it must be V3 or later - if (m_parent != nullptr && m_parent->version() < 3) - throw CHDERR_UNSUPPORTED_VERSION; + if (m_parent && m_parent->version() < 3) + throw std::error_condition(error::UNSUPPORTED_VERSION); // must be an even number of units per hunk if (m_hunkbytes % m_unitbytes != 0) - throw CHDERR_INVALID_PARAMETER; - if (m_parent != nullptr && m_unitbytes != m_parent->unit_bytes()) - throw CHDERR_INVALID_PARAMETER; + throw std::error_condition(std::errc::invalid_argument); + if (m_parent && m_unitbytes != m_parent->unit_bytes()) + throw std::error_condition(std::errc::invalid_argument); // verify the compression types bool found_zero = false; @@ -2290,9 +2317,9 @@ chd_error chd_file::create_common() if (elem == CHD_CODEC_NONE) found_zero = true; else if (found_zero) - throw CHDERR_INVALID_PARAMETER; + throw std::error_condition(std::errc::invalid_argument); else if (!chd_codec_list::codec_exists(elem)) - throw CHDERR_UNKNOWN_COMPRESSION; + throw std::error_condition(error::UNKNOWN_COMPRESSION); } // create our V5 header @@ -2342,10 +2369,9 @@ chd_error chd_file::create_common() // finish opening the file create_open_common(); } - - // handle errors by closing ourself - catch (chd_error &err) + catch (std::error_condition const &err) { + // handle errors by closing ourself close(); return err; } @@ -2354,11 +2380,11 @@ chd_error chd_file::create_common() close(); throw; } - return CHDERR_NONE; + return std::error_condition(); } /** - * @fn chd_error chd_file::open_common(bool writeable) + * @fn std::error_condition chd_file::open_common(bool writeable) * * @brief ------------------------------------------------- * open_common - common path when opening an existing CHD file for input @@ -2377,10 +2403,10 @@ chd_error chd_file::create_common() * * @param writeable true if writeable. * - * @return A chd_error. + * @return A std::error_condition. */ -chd_error chd_file::open_common(bool writeable) +std::error_condition chd_file::open_common(bool writeable) { // wrap in try for proper error handling try @@ -2394,7 +2420,7 @@ chd_error chd_file::open_common(bool writeable) // verify the signature if (memcmp(rawheader, "MComprHD", 8) != 0) - throw CHDERR_INVALID_FILE; + throw std::error_condition(error::INVALID_FILE); m_version = be_read(&rawheader[12], 4); @@ -2405,7 +2431,7 @@ chd_error chd_file::open_common(bool writeable) case 3: parse_v3_header(rawheader, parentsha1); break; case 4: parse_v4_header(rawheader, parentsha1); break; case 5: parse_v5_header(rawheader, parentsha1); break; - default: throw CHDERR_UNSUPPORTED_VERSION; + default: throw std::error_condition(error::UNSUPPORTED_VERSION); } // only allow writes to the most recent version @@ -2413,27 +2439,26 @@ chd_error chd_file::open_common(bool writeable) m_allow_writes = false; if (writeable && !m_allow_writes) - throw CHDERR_FILE_NOT_WRITEABLE; + throw std::error_condition(error::FILE_NOT_WRITEABLE); // make sure we have a parent if we need one (and don't if we don't) if (parentsha1 != util::sha1_t::null) { - if (m_parent == nullptr) + if (!m_parent) m_parent_missing = true; else if (m_parent->sha1() != parentsha1) - throw CHDERR_INVALID_PARENT; + throw std::error_condition(error::INVALID_PARENT); } - else if (m_parent != nullptr) - throw CHDERR_INVALID_PARAMETER; + else if (m_parent) + throw std::error_condition(std::errc::invalid_argument); // finish opening the file create_open_common(); - return CHDERR_NONE; + return std::error_condition(); } - - // handle errors by closing ourself - catch (chd_error &err) + catch (std::error_condition const &err) { + // handle errors by closing ourself close(); return err; } @@ -2457,7 +2482,7 @@ void chd_file::create_open_common() { m_decompressor[decompnum] = chd_codec_list::new_decompressor(m_compression[decompnum], *this); if (m_decompressor[decompnum] == nullptr && m_compression[decompnum] != 0) - throw CHDERR_UNKNOWN_COMPRESSION; + throw std::error_condition(error::UNKNOWN_COMPRESSION); } // read the map; v5+ compressed drives need to read and decompress their map @@ -2494,30 +2519,30 @@ void chd_file::create_open_common() void chd_file::verify_proper_compression_append(uint32_t hunknum) { // punt if no file - if (m_file == nullptr) - throw CHDERR_NOT_OPEN; + if (!m_file) + throw std::error_condition(error::NOT_OPEN); // return an error if out of range if (hunknum >= m_hunkcount) - throw CHDERR_HUNK_OUT_OF_RANGE; + throw std::error_condition(error::HUNK_OUT_OF_RANGE); // if not writeable, fail if (!m_allow_writes) - throw CHDERR_FILE_NOT_WRITEABLE; + throw std::error_condition(error::FILE_NOT_WRITEABLE); // compressed writes only via this interface if (!compressed()) - throw CHDERR_FILE_NOT_WRITEABLE; + throw std::error_condition(error::FILE_NOT_WRITEABLE); // only permitted to write new blocks uint8_t *rawmap = &m_rawmap[hunknum * 12]; if (rawmap[0] != 0xff) - throw CHDERR_COMPRESSION_ERROR; + throw std::error_condition(error::COMPRESSION_ERROR); // if this isn't the first block, only permitted to write immediately // after the previous one if (hunknum != 0 && rawmap[-12] == 0xff) - throw CHDERR_COMPRESSION_ERROR; + throw std::error_condition(error::COMPRESSION_ERROR); } /** @@ -2572,7 +2597,7 @@ void chd_file::hunk_copy_from_self(uint32_t hunknum, uint32_t otherhunk) // only permitted to reference prior hunks if (otherhunk >= hunknum) - throw CHDERR_INVALID_PARAMETER; + throw std::error_condition(std::errc::invalid_argument); // update the map entry uint8_t *rawmap = &m_rawmap[hunknum * 12]; @@ -2841,7 +2866,7 @@ void chd_file_compressor::compress_begin() } /** - * @fn chd_error chd_file_compressor::compress_continue(double &progress, double &ratio) + * @fn std::error_condition chd_file_compressor::compress_continue(double &progress, double &ratio) * * @brief ------------------------------------------------- * compress_continue - continue compression @@ -2850,14 +2875,14 @@ void chd_file_compressor::compress_begin() * @param [in,out] progress The progress. * @param [in,out] ratio The ratio. * - * @return A chd_error. + * @return A std::error_condition. */ -chd_error chd_file_compressor::compress_continue(double &progress, double &ratio) +std::error_condition chd_file_compressor::compress_continue(double &progress, double &ratio) { // if we got an error, return an error if (m_read_error) - return CHDERR_READ_ERROR; + return std::errc::io_error; // if done reading, queue some more while (m_read_queue_offset < m_logicalbytes && osd_work_queue_items(m_read_queue) < 2) @@ -2911,8 +2936,8 @@ chd_error chd_file_compressor::compress_continue(double &progress, double &ratio // if we're uncompressed, use regular writes else if (!compressed()) { - chd_error err = write_hunk(item.m_hunknum, item.m_data); - if (err != CHDERR_NONE) + std::error_condition err = write_hunk(item.m_hunknum, item.m_data); + if (err) return err; // writes of all-0 data don't actually take space, so see if we count this @@ -2973,7 +2998,7 @@ chd_error chd_file_compressor::compress_continue(double &progress, double &ratio { osd_work_queue_wait(m_read_queue, 30 * osd_ticks_per_second()); if (!compressed()) - return CHDERR_NONE; + return std::error_condition(); set_raw_sha1(m_compsha1.finish()); return compress_v5_map(); } @@ -2994,7 +3019,7 @@ chd_error chd_file_compressor::compress_continue(double &progress, double &ratio m_work_item[m_write_hunk % WORK_BUFFER_HUNKS].m_osd != nullptr) osd_work_item_wait(m_work_item[m_write_hunk % WORK_BUFFER_HUNKS].m_osd, osd_ticks_per_second()); - return m_walking_parent ? CHDERR_WALKING_PARENT : CHDERR_COMPRESSING; + return m_walking_parent ? error::WALKING_PARENT : error::COMPRESSING; } /** @@ -3171,12 +3196,12 @@ void chd_file_compressor::async_read() // advance the read pointer m_read_done_offset += numbytes; } - catch (chd_error& err) + catch (std::error_condition const &err) { - fprintf(stderr, "CHD error occurred: %s\n", chd_file::error_string(err)); + fprintf(stderr, "CHD error occurred: %s\n", err.message().c_str()); m_read_error = true; } - catch (std::exception& ex) + catch (std::exception const &ex) { fprintf(stderr, "exception occurred: %s\n", ex.what()); m_read_error = true; diff --git a/src/lib/util/chd.h b/src/lib/util/chd.h index 705967d3dda..8d3e639438b 100644 --- a/src/lib/util/chd.h +++ b/src/lib/util/chd.h @@ -7,18 +7,22 @@ MAME Compressed Hunks of Data file format ***************************************************************************/ - -#ifndef MAME_UTIL_CHD_H -#define MAME_UTIL_CHD_H +#ifndef MAME_LIB_UTIL_CHD_H +#define MAME_LIB_UTIL_CHD_H #pragma once -#include "osdcore.h" -#include -#include "corefile.h" -#include "hashing.h" #include "chdcodec.h" +#include "hashing.h" +#include "ioprocs.h" + +#include "osdcore.h" + #include +#include +#include +#include + /*************************************************************************** @@ -190,86 +194,49 @@ //************************************************************************** // pseudo-codecs returned by hunk_info -const chd_codec_type CHD_CODEC_SELF = 1; // copy of another hunk -const chd_codec_type CHD_CODEC_PARENT = 2; // copy of a parent's hunk -const chd_codec_type CHD_CODEC_MINI = 3; // legacy "mini" 8-byte repeat +constexpr chd_codec_type CHD_CODEC_SELF = 1; // copy of another hunk +constexpr chd_codec_type CHD_CODEC_PARENT = 2; // copy of a parent's hunk +constexpr chd_codec_type CHD_CODEC_MINI = 3; // legacy "mini" 8-byte repeat // core types typedef uint32_t chd_metadata_tag; // metadata parameters -const chd_metadata_tag CHDMETATAG_WILDCARD = 0; -const uint32_t CHDMETAINDEX_APPEND = ~0; +constexpr chd_metadata_tag CHDMETATAG_WILDCARD = 0; +constexpr uint32_t CHDMETAINDEX_APPEND = ~0; // metadata flags -const uint8_t CHD_MDFLAGS_CHECKSUM = 0x01; // indicates data is checksummed +constexpr uint8_t CHD_MDFLAGS_CHECKSUM = 0x01; // indicates data is checksummed // standard hard disk metadata -const chd_metadata_tag HARD_DISK_METADATA_TAG = CHD_MAKE_TAG('G','D','D','D'); +constexpr chd_metadata_tag HARD_DISK_METADATA_TAG = CHD_MAKE_TAG('G','D','D','D'); extern const char *HARD_DISK_METADATA_FORMAT; // hard disk identify information -const chd_metadata_tag HARD_DISK_IDENT_METADATA_TAG = CHD_MAKE_TAG('I','D','N','T'); +constexpr chd_metadata_tag HARD_DISK_IDENT_METADATA_TAG = CHD_MAKE_TAG('I','D','N','T'); // hard disk key information -const chd_metadata_tag HARD_DISK_KEY_METADATA_TAG = CHD_MAKE_TAG('K','E','Y',' '); +constexpr chd_metadata_tag HARD_DISK_KEY_METADATA_TAG = CHD_MAKE_TAG('K','E','Y',' '); // pcmcia CIS information -const chd_metadata_tag PCMCIA_CIS_METADATA_TAG = CHD_MAKE_TAG('C','I','S',' '); +constexpr chd_metadata_tag PCMCIA_CIS_METADATA_TAG = CHD_MAKE_TAG('C','I','S',' '); // standard CD-ROM metadata -const chd_metadata_tag CDROM_OLD_METADATA_TAG = CHD_MAKE_TAG('C','H','C','D'); -const chd_metadata_tag CDROM_TRACK_METADATA_TAG = CHD_MAKE_TAG('C','H','T','R'); +constexpr chd_metadata_tag CDROM_OLD_METADATA_TAG = CHD_MAKE_TAG('C','H','C','D'); +constexpr chd_metadata_tag CDROM_TRACK_METADATA_TAG = CHD_MAKE_TAG('C','H','T','R'); extern const char *CDROM_TRACK_METADATA_FORMAT; -const chd_metadata_tag CDROM_TRACK_METADATA2_TAG = CHD_MAKE_TAG('C','H','T','2'); +constexpr chd_metadata_tag CDROM_TRACK_METADATA2_TAG = CHD_MAKE_TAG('C','H','T','2'); extern const char *CDROM_TRACK_METADATA2_FORMAT; -const chd_metadata_tag GDROM_OLD_METADATA_TAG = CHD_MAKE_TAG('C','H','G','T'); -const chd_metadata_tag GDROM_TRACK_METADATA_TAG = CHD_MAKE_TAG('C', 'H', 'G', 'D'); +constexpr chd_metadata_tag GDROM_OLD_METADATA_TAG = CHD_MAKE_TAG('C','H','G','T'); +constexpr chd_metadata_tag GDROM_TRACK_METADATA_TAG = CHD_MAKE_TAG('C', 'H', 'G', 'D'); extern const char *GDROM_TRACK_METADATA_FORMAT; // standard A/V metadata -const chd_metadata_tag AV_METADATA_TAG = CHD_MAKE_TAG('A','V','A','V'); +constexpr chd_metadata_tag AV_METADATA_TAG = CHD_MAKE_TAG('A','V','A','V'); extern const char *AV_METADATA_FORMAT; // A/V laserdisc frame metadata -const chd_metadata_tag AV_LD_METADATA_TAG = CHD_MAKE_TAG('A','V','L','D'); - -// error types -enum chd_error -{ - CHDERR_NONE, - CHDERR_NO_INTERFACE, - CHDERR_OUT_OF_MEMORY, - CHDERR_NOT_OPEN, - CHDERR_ALREADY_OPEN, - CHDERR_INVALID_FILE, - CHDERR_INVALID_PARAMETER, - CHDERR_INVALID_DATA, - CHDERR_FILE_NOT_FOUND, - CHDERR_REQUIRES_PARENT, - CHDERR_FILE_NOT_WRITEABLE, - CHDERR_READ_ERROR, - CHDERR_WRITE_ERROR, - CHDERR_CODEC_ERROR, - CHDERR_INVALID_PARENT, - CHDERR_HUNK_OUT_OF_RANGE, - CHDERR_DECOMPRESSION_ERROR, - CHDERR_COMPRESSION_ERROR, - CHDERR_CANT_CREATE_FILE, - CHDERR_CANT_VERIFY, - CHDERR_NOT_SUPPORTED, - CHDERR_METADATA_NOT_FOUND, - CHDERR_INVALID_METADATA_SIZE, - CHDERR_UNSUPPORTED_VERSION, - CHDERR_VERIFY_INCOMPLETE, - CHDERR_INVALID_METADATA, - CHDERR_INVALID_STATE, - CHDERR_OPERATION_PENDING, - CHDERR_UNSUPPORTED_FORMAT, - CHDERR_UNKNOWN_COMPRESSION, - CHDERR_WALKING_PARENT, - CHDERR_COMPRESSING -}; +constexpr chd_metadata_tag AV_LD_METADATA_TAG = CHD_MAKE_TAG('A','V','L','D'); @@ -277,9 +244,6 @@ enum chd_error // TYPE DEFINITIONS //************************************************************************** -class chd_codec; - - // ======================> chd_file // core file class @@ -289,22 +253,49 @@ class chd_file friend class chd_verifier; // constants - static const uint32_t HEADER_VERSION = 5; - static const uint32_t V3_HEADER_SIZE = 120; - static const uint32_t V4_HEADER_SIZE = 108; - static const uint32_t V5_HEADER_SIZE = 124; - static const uint32_t MAX_HEADER_SIZE = V5_HEADER_SIZE; + static constexpr uint32_t HEADER_VERSION = 5; + static constexpr uint32_t V3_HEADER_SIZE = 120; + static constexpr uint32_t V4_HEADER_SIZE = 108; + static constexpr uint32_t V5_HEADER_SIZE = 124; + static constexpr uint32_t MAX_HEADER_SIZE = V5_HEADER_SIZE; public: + // error types + enum class error + { + NO_INTERFACE = 1, + NOT_OPEN, + ALREADY_OPEN, + INVALID_FILE, + INVALID_DATA, + REQUIRES_PARENT, + FILE_NOT_WRITEABLE, + CODEC_ERROR, + INVALID_PARENT, + HUNK_OUT_OF_RANGE, + DECOMPRESSION_ERROR, + COMPRESSION_ERROR, + CANT_VERIFY, + METADATA_NOT_FOUND, + INVALID_METADATA_SIZE, + UNSUPPORTED_VERSION, + VERIFY_INCOMPLETE, + INVALID_METADATA, + INVALID_STATE, + OPERATION_PENDING, + UNSUPPORTED_FORMAT, + UNKNOWN_COMPRESSION, + WALKING_PARENT, + COMPRESSING + }; + // construction/destruction chd_file(); virtual ~chd_file(); - // operators - operator util::core_file &() { return *m_file; } - // getters - bool opened() const { return (m_file != nullptr); } + util::random_read &file(); + bool opened() const { return bool(m_file); } uint32_t version() const { return m_version; } uint64_t logical_bytes() const { return m_logicalbytes; } uint32_t hunk_bytes() const { return m_hunkbytes; } @@ -317,52 +308,49 @@ public: util::sha1_t sha1(); util::sha1_t raw_sha1(); util::sha1_t parent_sha1(); - chd_error hunk_info(uint32_t hunknum, chd_codec_type &compressor, uint32_t &compbytes); + std::error_condition hunk_info(uint32_t hunknum, chd_codec_type &compressor, uint32_t &compbytes); // setters void set_raw_sha1(util::sha1_t rawdata); void set_parent_sha1(util::sha1_t parent); // file create - chd_error create(const char *filename, uint64_t logicalbytes, uint32_t hunkbytes, uint32_t unitbytes, chd_codec_type compression[4]); - chd_error create(util::core_file &file, uint64_t logicalbytes, uint32_t hunkbytes, uint32_t unitbytes, chd_codec_type compression[4]); - chd_error create(const char *filename, uint64_t logicalbytes, uint32_t hunkbytes, chd_codec_type compression[4], chd_file &parent); - chd_error create(util::core_file &file, uint64_t logicalbytes, uint32_t hunkbytes, chd_codec_type compression[4], chd_file &parent); + std::error_condition create(std::string_view filename, uint64_t logicalbytes, uint32_t hunkbytes, uint32_t unitbytes, chd_codec_type compression[4]); + std::error_condition create(util::random_read_write::ptr &&file, uint64_t logicalbytes, uint32_t hunkbytes, uint32_t unitbytes, chd_codec_type compression[4]); + std::error_condition create(std::string_view filename, uint64_t logicalbytes, uint32_t hunkbytes, chd_codec_type compression[4], chd_file &parent); + std::error_condition create(util::random_read_write::ptr &&file, uint64_t logicalbytes, uint32_t hunkbytes, chd_codec_type compression[4], chd_file &parent); // file open - chd_error open(const char *filename, bool writeable = false, chd_file *parent = nullptr); - chd_error open(util::core_file &file, bool writeable = false, chd_file *parent = nullptr); + std::error_condition open(std::string_view filename, bool writeable = false, chd_file *parent = nullptr); + std::error_condition open(util::random_read_write::ptr &&file, bool writeable = false, chd_file *parent = nullptr); // file close void close(); // read/write - chd_error read_hunk(uint32_t hunknum, void *buffer); - chd_error write_hunk(uint32_t hunknum, const void *buffer); - chd_error read_units(uint64_t unitnum, void *buffer, uint32_t count = 1); - chd_error write_units(uint64_t unitnum, const void *buffer, uint32_t count = 1); - chd_error read_bytes(uint64_t offset, void *buffer, uint32_t bytes); - chd_error write_bytes(uint64_t offset, const void *buffer, uint32_t bytes); + std::error_condition read_hunk(uint32_t hunknum, void *buffer); + std::error_condition write_hunk(uint32_t hunknum, const void *buffer); + std::error_condition read_units(uint64_t unitnum, void *buffer, uint32_t count = 1); + std::error_condition write_units(uint64_t unitnum, const void *buffer, uint32_t count = 1); + std::error_condition read_bytes(uint64_t offset, void *buffer, uint32_t bytes); + std::error_condition write_bytes(uint64_t offset, const void *buffer, uint32_t bytes); // metadata management - chd_error read_metadata(chd_metadata_tag searchtag, uint32_t searchindex, std::string &output); - chd_error read_metadata(chd_metadata_tag searchtag, uint32_t searchindex, std::vector &output); - chd_error read_metadata(chd_metadata_tag searchtag, uint32_t searchindex, void *output, uint32_t outputlen, uint32_t &resultlen); - chd_error read_metadata(chd_metadata_tag searchtag, uint32_t searchindex, std::vector &output, chd_metadata_tag &resulttag, uint8_t &resultflags); - chd_error write_metadata(chd_metadata_tag metatag, uint32_t metaindex, const void *inputbuf, uint32_t inputlen, uint8_t flags = CHD_MDFLAGS_CHECKSUM); - chd_error write_metadata(chd_metadata_tag metatag, uint32_t metaindex, const std::string &input, uint8_t flags = CHD_MDFLAGS_CHECKSUM) { return write_metadata(metatag, metaindex, input.c_str(), input.length() + 1, flags); } - chd_error write_metadata(chd_metadata_tag metatag, uint32_t metaindex, const std::vector &input, uint8_t flags = CHD_MDFLAGS_CHECKSUM) { return write_metadata(metatag, metaindex, &input[0], input.size(), flags); } - chd_error delete_metadata(chd_metadata_tag metatag, uint32_t metaindex); - chd_error clone_all_metadata(chd_file &source); + std::error_condition read_metadata(chd_metadata_tag searchtag, uint32_t searchindex, std::string &output); + std::error_condition read_metadata(chd_metadata_tag searchtag, uint32_t searchindex, std::vector &output); + std::error_condition read_metadata(chd_metadata_tag searchtag, uint32_t searchindex, void *output, uint32_t outputlen, uint32_t &resultlen); + std::error_condition read_metadata(chd_metadata_tag searchtag, uint32_t searchindex, std::vector &output, chd_metadata_tag &resulttag, uint8_t &resultflags); + std::error_condition write_metadata(chd_metadata_tag metatag, uint32_t metaindex, const void *inputbuf, uint32_t inputlen, uint8_t flags = CHD_MDFLAGS_CHECKSUM); + std::error_condition write_metadata(chd_metadata_tag metatag, uint32_t metaindex, const std::string &input, uint8_t flags = CHD_MDFLAGS_CHECKSUM) { return write_metadata(metatag, metaindex, input.c_str(), input.length() + 1, flags); } + std::error_condition write_metadata(chd_metadata_tag metatag, uint32_t metaindex, const std::vector &input, uint8_t flags = CHD_MDFLAGS_CHECKSUM) { return write_metadata(metatag, metaindex, &input[0], input.size(), flags); } + std::error_condition delete_metadata(chd_metadata_tag metatag, uint32_t metaindex); + std::error_condition clone_all_metadata(chd_file &source); // hashing helper util::sha1_t compute_overall_sha1(util::sha1_t rawsha1); // codec interfaces - chd_error codec_configure(chd_codec_type codec, int param, void *config); - - // static helpers - static const char *error_string(chd_error err); + std::error_condition codec_configure(chd_codec_type codec, int param, void *config); private: struct metadata_entry; @@ -383,10 +371,10 @@ private: void parse_v3_header(uint8_t *rawheader, util::sha1_t &parentsha1); void parse_v4_header(uint8_t *rawheader, util::sha1_t &parentsha1); void parse_v5_header(uint8_t *rawheader, util::sha1_t &parentsha1); - chd_error compress_v5_map(); + std::error_condition compress_v5_map(); void decompress_v5_map(); - chd_error create_common(); - chd_error open_common(bool writeable); + std::error_condition create_common(); + std::error_condition open_common(bool writeable); void create_open_common(); void verify_proper_compression_append(uint32_t hunknum); void hunk_write_compressed(uint32_t hunknum, int8_t compression, const uint8_t *compressed, uint32_t complength, util::crc16_t crc16); @@ -398,42 +386,41 @@ private: static int CLIB_DECL metadata_hash_compare(const void *elem1, const void *elem2); // file characteristics - util::core_file * m_file; // handle to the open core file - bool m_owns_file; // flag indicating if this file should be closed on chd_close() + util::random_read_write::ptr m_file; // handle to the open core file bool m_allow_reads; // permit reads from this CHD? bool m_allow_writes; // permit writes to this CHD? // core parameters from the header - uint32_t m_version; // version of the header - uint64_t m_logicalbytes; // logical size of the raw CHD data in bytes - uint64_t m_mapoffset; // offset of map - uint64_t m_metaoffset; // offset to first metadata bit - uint32_t m_hunkbytes; // size of each raw hunk in bytes - uint32_t m_hunkcount; // number of hunks represented - uint32_t m_unitbytes; // size of each unit in bytes - uint64_t m_unitcount; // number of units represented + uint32_t m_version; // version of the header + uint64_t m_logicalbytes; // logical size of the raw CHD data in bytes + uint64_t m_mapoffset; // offset of map + uint64_t m_metaoffset; // offset to first metadata bit + uint32_t m_hunkbytes; // size of each raw hunk in bytes + uint32_t m_hunkcount; // number of hunks represented + uint32_t m_unitbytes; // size of each unit in bytes + uint64_t m_unitcount; // number of units represented chd_codec_type m_compression[4]; // array of compression types used chd_file * m_parent; // pointer to parent file, or nullptr if none bool m_parent_missing; // are we missing our parent? // key offsets within the header - uint64_t m_mapoffset_offset; // offset of map offset field - uint64_t m_metaoffset_offset;// offset of metaoffset field - uint64_t m_sha1_offset; // offset of SHA1 field - uint64_t m_rawsha1_offset; // offset of raw SHA1 field - uint64_t m_parentsha1_offset;// offset of paren SHA1 field + uint64_t m_mapoffset_offset; // offset of map offset field + uint64_t m_metaoffset_offset;// offset of metaoffset field + uint64_t m_sha1_offset; // offset of SHA1 field + uint64_t m_rawsha1_offset; // offset of raw SHA1 field + uint64_t m_parentsha1_offset;// offset of paren SHA1 field // map information - uint32_t m_mapentrybytes; // length of each entry in a map - std::vector m_rawmap; // raw map data + uint32_t m_mapentrybytes; // length of each entry in a map + std::vector m_rawmap; // raw map data // compression management - chd_decompressor * m_decompressor[4]; // array of decompression codecs - std::vector m_compressed; // temporary buffer for compressed data + chd_decompressor::ptr m_decompressor[4]; // array of decompression codecs + std::vector m_compressed; // temporary buffer for compressed data // caching - std::vector m_cache; // single-hunk cache for partial reads/writes - uint32_t m_cachehunk; // which hunk is in the cache? + std::vector m_cache; // single-hunk cache for partial reads/writes + uint32_t m_cachehunk; // which hunk is in the cache? }; @@ -449,7 +436,7 @@ public: // compression management void compress_begin(); - chd_error compress_continue(double &progress, double &ratio); + std::error_condition compress_continue(double &progress, double &ratio); protected: // required override: read more data @@ -470,24 +457,24 @@ private: void add(uint64_t itemnum, util::crc16_t crc16, util::sha1_t sha1); // constants - static const uint64_t NOT_FOUND = ~uint64_t(0); + static constexpr uint64_t NOT_FOUND = ~uint64_t(0); + private: // internal entry struct entry_t { entry_t * m_next; // next entry in list - uint64_t m_itemnum; // item number + uint64_t m_itemnum; // item number util::sha1_t m_sha1; // SHA-1 of the block }; // block of entries struct entry_block { - entry_block(entry_block *prev) - : m_next(prev), m_nextalloc(0) { } + entry_block(entry_block *prev) : m_next(prev), m_nextalloc(0) { } entry_block * m_next; // next block in list - uint32_t m_nextalloc; // next to be allocated + uint32_t m_nextalloc; // next to be allocated entry_t m_array[16384]; // array of entries }; @@ -551,8 +538,8 @@ private: // current compression status bool m_walking_parent; // are we building the parent map? - uint64_t m_total_in; // total bytes in - uint64_t m_total_out; // total bytes out + uint64_t m_total_in; // total bytes in + uint64_t m_total_out; // total bytes out util::sha1_creator m_compsha1; // running SHA-1 on raw data // hash lookup maps @@ -561,20 +548,31 @@ private: // read I/O thread osd_work_queue * m_read_queue; // work queue for reading - uint64_t m_read_queue_offset;// next offset to enqueue - uint64_t m_read_done_offset; // next offset that will complete + uint64_t m_read_queue_offset;// next offset to enqueue + uint64_t m_read_done_offset; // next offset that will complete bool m_read_error; // error during reading? // work item thread - static const int WORK_BUFFER_HUNKS = 256; + static constexpr int WORK_BUFFER_HUNKS = 256; osd_work_queue * m_work_queue; // queue for doing work on other threads - std::vector m_work_buffer; // buffer containing hunk data to work on - std::vector m_compressed_buffer;// buffer containing compressed data + std::vector m_work_buffer; // buffer containing hunk data to work on + std::vector m_compressed_buffer;// buffer containing compressed data work_item m_work_item[WORK_BUFFER_HUNKS]; // status of each hunk chd_compressor_group * m_codecs[WORK_MAX_THREADS]; // codecs to use // output state - uint32_t m_write_hunk; // next hunk to write + uint32_t m_write_hunk; // next hunk to write }; -#endif // MAME_UTIL_CHD_H + +// error category for CHD errors +std::error_category const &chd_category() noexcept; +inline std::error_condition make_error_condition(chd_file::error err) noexcept { return std::error_condition(int(err), chd_category()); } + +namespace std { + +template <> struct is_error_condition_enum : public std::true_type { }; + +} // namespace std + +#endif // MAME_LIB_UTIL_CHD_H diff --git a/src/lib/util/chdcd.cpp b/src/lib/util/chdcd.cpp index ef013b41f48..63b633536bf 100644 --- a/src/lib/util/chdcd.cpp +++ b/src/lib/util/chdcd.cpp @@ -7,15 +7,19 @@ ***************************************************************************/ -#include -#include -#include -#include "osdcore.h" -#include "chd.h" #include "chdcd.h" + +#include "chd.h" #include "corefile.h" #include "corestr.h" +#include "osdcore.h" + +#include +#include +#include +#include + /*************************************************************************** @@ -230,8 +234,8 @@ static uint32_t parse_wav_sample(const char *filename, uint32_t *dataoffs) uint64_t fsize = 0; std::uint32_t actual; - osd_file::error filerr = osd_file::open(filename, OPEN_FLAG_READ, file, fsize); - if (filerr != osd_file::error::NONE) + std::error_condition const filerr = osd_file::open(filename, OPEN_FLAG_READ, file, fsize); + if (filerr) { printf("ERROR: could not open (%s)\n", filename); return 0; @@ -449,7 +453,7 @@ uint64_t read_uint64(FILE *infile) -------------------------------------------------*/ /** - * @fn chd_error chdcd_parse_nero(const char *tocfname, cdrom_toc &outtoc, chdcd_track_input_info &outinfo) + * @fn std::error_condition chdcd_parse_nero(const char *tocfname, cdrom_toc &outtoc, chdcd_track_input_info &outinfo) * * @brief Chdcd parse nero. * @@ -457,26 +461,25 @@ uint64_t read_uint64(FILE *infile) * @param [in,out] outtoc The outtoc. * @param [in,out] outinfo The outinfo. * - * @return A chd_error. + * @return A std::error_condition. */ -chd_error chdcd_parse_nero(const char *tocfname, cdrom_toc &outtoc, chdcd_track_input_info &outinfo) +std::error_condition chdcd_parse_nero(const char *tocfname, cdrom_toc &outtoc, chdcd_track_input_info &outinfo) { - FILE *infile; unsigned char buffer[12]; uint32_t chain_offs, chunk_size; int done = 0; std::string path = std::string(tocfname); - infile = fopen(tocfname, "rb"); - path = get_file_path(path); - - if (infile == (FILE *)nullptr) + FILE *infile = fopen(tocfname, "rb"); + if (!infile) { - return CHDERR_FILE_NOT_FOUND; + return std::error_condition(errno, std::generic_category()); } + path = get_file_path(path); + /* clear structures */ memset(&outtoc, 0, sizeof(outtoc)); outinfo.reset(); @@ -489,7 +492,7 @@ chd_error chdcd_parse_nero(const char *tocfname, cdrom_toc &outtoc, chdcd_track_ { printf("ERROR: Not a Nero 5.5 or later image!\n"); fclose(infile); - return CHDERR_UNSUPPORTED_VERSION; + return chd_file::error::UNSUPPORTED_FORMAT; } chain_offs = buffer[11] | (buffer[10]<<8) | (buffer[9]<<16) | (buffer[8]<<24); @@ -498,7 +501,7 @@ chd_error chdcd_parse_nero(const char *tocfname, cdrom_toc &outtoc, chdcd_track_ { printf("ERROR: File size is > 4GB, this version of CHDMAN cannot handle it."); fclose(infile); - return CHDERR_UNSUPPORTED_FORMAT; + return chd_file::error::UNSUPPORTED_FORMAT; } // printf("NER5 detected, chain offset: %x\n", chain_offs); @@ -559,12 +562,12 @@ chd_error chdcd_parse_nero(const char *tocfname, cdrom_toc &outtoc, chdcd_track_ case 0x0300: // Mode 2 Form 1 printf("ERROR: Mode 2 Form 1 tracks not supported\n"); fclose(infile); - return CHDERR_UNSUPPORTED_FORMAT; + return chd_file::error::UNSUPPORTED_FORMAT; case 0x0500: // raw data printf("ERROR: Raw data tracks not supported\n"); fclose(infile); - return CHDERR_UNSUPPORTED_FORMAT; + return chd_file::error::UNSUPPORTED_FORMAT; case 0x0600: // 2352 byte mode 2 raw outtoc.tracks[track-1].trktype = CD_TRACK_MODE2_RAW; @@ -579,22 +582,22 @@ chd_error chdcd_parse_nero(const char *tocfname, cdrom_toc &outtoc, chdcd_track_ case 0x0f00: // raw data with sub-channel printf("ERROR: Raw data tracks with sub-channel not supported\n"); fclose(infile); - return CHDERR_UNSUPPORTED_FORMAT; + return chd_file::error::UNSUPPORTED_FORMAT; case 0x1000: // audio with sub-channel printf("ERROR: Audio tracks with sub-channel not supported\n"); fclose(infile); - return CHDERR_UNSUPPORTED_FORMAT; + return chd_file::error::UNSUPPORTED_FORMAT; case 0x1100: // raw Mode 2 Form 1 with sub-channel printf("ERROR: Raw Mode 2 Form 1 tracks with sub-channel not supported\n"); fclose(infile); - return CHDERR_UNSUPPORTED_FORMAT; + return chd_file::error::UNSUPPORTED_FORMAT; default: printf("ERROR: Unknown track type %x, contact MAMEDEV!\n", mode); fclose(infile); - return CHDERR_UNSUPPORTED_FORMAT; + return chd_file::error::UNSUPPORTED_FORMAT; } outtoc.tracks[track-1].datasize = size; @@ -627,7 +630,7 @@ chd_error chdcd_parse_nero(const char *tocfname, cdrom_toc &outtoc, chdcd_track_ fclose(infile); - return CHDERR_NONE; + return std::error_condition(); } /*------------------------------------------------- @@ -635,7 +638,7 @@ chd_error chdcd_parse_nero(const char *tocfname, cdrom_toc &outtoc, chdcd_track_ -------------------------------------------------*/ /** - * @fn chd_error chdcd_parse_iso(const char *tocfname, cdrom_toc &outtoc, chdcd_track_input_info &outinfo) + * @fn std::error_condition chdcd_parse_iso(const char *tocfname, cdrom_toc &outtoc, chdcd_track_input_info &outinfo) * * @brief Chdcd parse ISO. * @@ -643,22 +646,21 @@ chd_error chdcd_parse_nero(const char *tocfname, cdrom_toc &outtoc, chdcd_track_ * @param [in,out] outtoc The outtoc. * @param [in,out] outinfo The outinfo. * - * @return A chd_error. + * @return A std::error_condition. */ -chd_error chdcd_parse_iso(const char *tocfname, cdrom_toc &outtoc, chdcd_track_input_info &outinfo) +std::error_condition chdcd_parse_iso(const char *tocfname, cdrom_toc &outtoc, chdcd_track_input_info &outinfo) { - FILE *infile; std::string path = std::string(tocfname); - infile = fopen(tocfname, "rb"); - path = get_file_path(path); - - if (infile == (FILE *)nullptr) + FILE *infile = fopen(tocfname, "rb"); + if (!infile) { - return CHDERR_FILE_NOT_FOUND; + return std::error_condition(errno, std::generic_category()); } + path = get_file_path(path); + /* clear structures */ memset(&outtoc, 0, sizeof(outtoc)); outinfo.reset(); @@ -693,7 +695,7 @@ chd_error chdcd_parse_iso(const char *tocfname, cdrom_toc &outtoc, chdcd_track_i outinfo.track[0].swap = false; } else { printf("ERROR: Unrecognized track type\n"); - return CHDERR_UNSUPPORTED_FORMAT; + return chd_file::error::UNSUPPORTED_FORMAT; } outtoc.tracks[0].subtype = CD_SUB_NONE; @@ -709,7 +711,7 @@ chd_error chdcd_parse_iso(const char *tocfname, cdrom_toc &outtoc, chdcd_track_i outtoc.tracks[0].padframes = 0; - return CHDERR_NONE; + return std::error_condition(); } /*------------------------------------------------- @@ -717,7 +719,7 @@ chd_error chdcd_parse_iso(const char *tocfname, cdrom_toc &outtoc, chdcd_track_i -------------------------------------------------*/ /** - * @fn static chd_error chdcd_parse_gdi(const char *tocfname, cdrom_toc &outtoc, chdcd_track_input_info &outinfo) + * @fn static std::error_condition chdcd_parse_gdi(const char *tocfname, cdrom_toc &outtoc, chdcd_track_input_info &outinfo) * * @brief Chdcd parse GDI. * @@ -725,24 +727,23 @@ chd_error chdcd_parse_iso(const char *tocfname, cdrom_toc &outtoc, chdcd_track_i * @param [in,out] outtoc The outtoc. * @param [in,out] outinfo The outinfo. * - * @return A chd_error. + * @return A std::error_condition. */ -static chd_error chdcd_parse_gdi(const char *tocfname, cdrom_toc &outtoc, chdcd_track_input_info &outinfo) +static std::error_condition chdcd_parse_gdi(const char *tocfname, cdrom_toc &outtoc, chdcd_track_input_info &outinfo) { - FILE *infile; int i, numtracks; std::string path = std::string(tocfname); - infile = fopen(tocfname, "rt"); - path = get_file_path(path); - - if (infile == (FILE *)nullptr) + FILE *infile = fopen(tocfname, "rt"); + if (!infile) { - return CHDERR_FILE_NOT_FOUND; + return std::error_condition(errno, std::generic_category()); } + path = get_file_path(path); + /* clear structures */ memset(&outtoc, 0, sizeof(outtoc)); outinfo.reset(); @@ -841,7 +842,7 @@ static chd_error chdcd_parse_gdi(const char *tocfname, cdrom_toc &outtoc, chdcd_ /* store the number of tracks found */ outtoc.numtrks = numtracks; - return CHDERR_NONE; + return std::error_condition(); } /*------------------------------------------------- @@ -849,7 +850,7 @@ static chd_error chdcd_parse_gdi(const char *tocfname, cdrom_toc &outtoc, chdcd_ -------------------------------------------------*/ /** - * @fn chd_error chdcd_parse_cue(const char *tocfname, cdrom_toc &outtoc, chdcd_track_input_info &outinfo) + * @fn std::error_condition chdcd_parse_cue(const char *tocfname, cdrom_toc &outtoc, chdcd_track_input_info &outinfo) * * @brief Chdcd parse cue. * @@ -857,25 +858,25 @@ static chd_error chdcd_parse_gdi(const char *tocfname, cdrom_toc &outtoc, chdcd_ * @param [in,out] outtoc The outtoc. * @param [in,out] outinfo The outinfo. * - * @return A chd_error. + * @return A std::error_condition. */ -chd_error chdcd_parse_cue(const char *tocfname, cdrom_toc &outtoc, chdcd_track_input_info &outinfo) +std::error_condition chdcd_parse_cue(const char *tocfname, cdrom_toc &outtoc, chdcd_track_input_info &outinfo) { - FILE *infile; int i, trknum; static char token[512]; std::string lastfname; uint32_t wavlen, wavoffs; std::string path = std::string(tocfname); - infile = fopen(tocfname, "rt"); - path = get_file_path(path); - if (infile == (FILE *)nullptr) + FILE *infile = fopen(tocfname, "rt"); + if (!infile) { - return CHDERR_FILE_NOT_FOUND; + return std::error_condition(errno, std::generic_category()); } + path = get_file_path(path); + /* clear structures */ memset(&outtoc, 0, sizeof(outtoc)); outinfo.reset(); @@ -921,14 +922,14 @@ chd_error chdcd_parse_cue(const char *tocfname, cdrom_toc &outtoc, chdcd_track_i { fclose(infile); printf("ERROR: couldn't read [%s] or not a valid .WAV\n", lastfname.c_str()); - return CHDERR_INVALID_DATA; + return chd_file::error::INVALID_DATA; } } else { fclose(infile); printf("ERROR: Unhandled track type %s\n", token); - return CHDERR_UNSUPPORTED_FORMAT; + return chd_file::error::UNSUPPORTED_FORMAT; } } else if (!strcmp(token, "TRACK")) @@ -970,7 +971,7 @@ chd_error chdcd_parse_cue(const char *tocfname, cdrom_toc &outtoc, chdcd_track_i { fclose(infile); printf("ERROR: Unknown track type [%s]. Contact MAMEDEV.\n", token); - return CHDERR_UNSUPPORTED_FORMAT; + return chd_file::error::UNSUPPORTED_FORMAT; } /* next (optional) token on the line is the subcode type */ @@ -1083,7 +1084,7 @@ chd_error chdcd_parse_cue(const char *tocfname, cdrom_toc &outtoc, chdcd_track_i if (tlen == 0) { printf("ERROR: couldn't find bin file [%s]\n", outinfo.track[trknum-1].fname.c_str()); - return CHDERR_FILE_NOT_FOUND; + return std::errc::no_such_file_or_directory; } outinfo.track[trknum].offset = outinfo.track[trknum-1].offset + outtoc.tracks[trknum-1].frames * (outtoc.tracks[trknum-1].datasize + outtoc.tracks[trknum-1].subsize); outtoc.tracks[trknum].frames = (tlen - outinfo.track[trknum].offset) / (outtoc.tracks[trknum].datasize + outtoc.tracks[trknum].subsize); @@ -1094,7 +1095,7 @@ chd_error chdcd_parse_cue(const char *tocfname, cdrom_toc &outtoc, chdcd_track_i if (tlen == 0) { printf("ERROR: couldn't find bin file [%s]\n", outinfo.track[trknum-1].fname.c_str()); - return CHDERR_FILE_NOT_FOUND; + return std::errc::no_such_file_or_directory; } tlen /= (outtoc.tracks[trknum].datasize + outtoc.tracks[trknum].subsize); outtoc.tracks[trknum].frames = tlen; @@ -1120,7 +1121,7 @@ chd_error chdcd_parse_cue(const char *tocfname, cdrom_toc &outtoc, chdcd_track_i if (!outtoc.tracks[trknum].frames) { printf("ERROR: unable to determine size of track %d, missing INDEX 01 markers?\n", trknum+1); - return CHDERR_INVALID_DATA; + return chd_file::error::INVALID_DATA; } } else /* data files are different */ @@ -1129,7 +1130,7 @@ chd_error chdcd_parse_cue(const char *tocfname, cdrom_toc &outtoc, chdcd_track_i if (tlen == 0) { printf("ERROR: couldn't find bin file [%s]\n", outinfo.track[trknum].fname.c_str()); - return CHDERR_FILE_NOT_FOUND; + return std::errc::no_such_file_or_directory; } tlen /= (outtoc.tracks[trknum].datasize + outtoc.tracks[trknum].subsize); outtoc.tracks[trknum].frames = tlen; @@ -1140,7 +1141,7 @@ chd_error chdcd_parse_cue(const char *tocfname, cdrom_toc &outtoc, chdcd_track_i //printf("trk %d: %d frames @ offset %d\n", trknum+1, outtoc.tracks[trknum].frames, outinfo.track[trknum].offset); } - return CHDERR_NONE; + return std::error_condition(); } /*--------------------------------------------------------------------------------------- @@ -1161,18 +1162,18 @@ chd_error chdcd_parse_cue(const char *tocfname, cdrom_toc &outtoc, chdcd_track_i bool chdcd_is_gdicue(const char *tocfname) { - FILE *infile; bool has_rem_singledensity = false; bool has_rem_highdensity = false; std::string path = std::string(tocfname); - infile = fopen(tocfname, "rt"); - path = get_file_path(path); - if (infile == (FILE *)nullptr) + FILE *infile = fopen(tocfname, "rt"); + if (!infile) { return false; } + path = get_file_path(path); + while (!feof(infile)) { fgets(linebuffer, 511, infile); @@ -1195,7 +1196,7 @@ bool chdcd_is_gdicue(const char *tocfname) ------------------------------------------------------------------*/ /** - * @fn chd_error chdcd_parse_gdicue(const char *tocfname, cdrom_toc &outtoc, chdcd_track_input_info &outinfo) + * @fn std::error_condition chdcd_parse_gdicue(const char *tocfname, cdrom_toc &outtoc, chdcd_track_input_info &outinfo) * * @brief Chdcd parse cue. * @@ -1203,7 +1204,7 @@ bool chdcd_is_gdicue(const char *tocfname) * @param [in,out] outtoc The outtoc. * @param [in,out] outinfo The outinfo. * - * @return A chd_error. + * @return A std::error_condition. * * Dreamcast discs have two images on a single disc. The first image is SINGLE-DENSITY and the second image * is HIGH-DENSITY. The SINGLE-DENSITY area starts 0 LBA and HIGH-DENSITY area starts 45000 LBA. @@ -1218,9 +1219,8 @@ bool chdcd_is_gdicue(const char *tocfname) * layout from a TOSEC .gdi. */ -chd_error chdcd_parse_gdicue(const char *tocfname, cdrom_toc &outtoc, chdcd_track_input_info &outinfo) +std::error_condition chdcd_parse_gdicue(const char *tocfname, cdrom_toc &outtoc, chdcd_track_input_info &outinfo) { - FILE *infile; int i, trknum; static char token[512]; std::string lastfname; @@ -1229,13 +1229,14 @@ chd_error chdcd_parse_gdicue(const char *tocfname, cdrom_toc &outtoc, chdcd_trac enum gdi_area current_area = SINGLE_DENSITY; enum gdi_pattern disc_pattern = TYPE_UNKNOWN; - infile = fopen(tocfname, "rt"); - path = get_file_path(path); - if (infile == (FILE *)nullptr) + FILE *infile = fopen(tocfname, "rt"); + if (!infile) { - return CHDERR_FILE_NOT_FOUND; + return std::error_condition(errno, std::generic_category()); } + path = get_file_path(path); + /* clear structures */ memset(&outtoc, 0, sizeof(outtoc)); outinfo.reset(); @@ -1297,14 +1298,14 @@ chd_error chdcd_parse_gdicue(const char *tocfname, cdrom_toc &outtoc, chdcd_trac { fclose(infile); printf("ERROR: couldn't read [%s] or not a valid .WAV\n", lastfname.c_str()); - return CHDERR_INVALID_DATA; + return chd_file::error::INVALID_DATA; } } else { fclose(infile); printf("ERROR: Unhandled track type %s\n", token); - return CHDERR_UNSUPPORTED_FORMAT; + return chd_file::error::UNSUPPORTED_FORMAT; } } else if (!strcmp(token, "TRACK")) @@ -1349,7 +1350,7 @@ chd_error chdcd_parse_gdicue(const char *tocfname, cdrom_toc &outtoc, chdcd_trac { fclose(infile); printf("ERROR: Unknown track type [%s]. Contact MAMEDEV.\n", token); - return CHDERR_UNSUPPORTED_FORMAT; + return chd_file::error::UNSUPPORTED_FORMAT; } /* next (optional) token on the line is the subcode type */ @@ -1462,7 +1463,7 @@ chd_error chdcd_parse_gdicue(const char *tocfname, cdrom_toc &outtoc, chdcd_trac if (tlen == 0) { printf("ERROR: couldn't find bin file [%s]\n", outinfo.track[trknum-1].fname.c_str()); - return CHDERR_FILE_NOT_FOUND; + return std::errc::no_such_file_or_directory; } outinfo.track[trknum].offset = outinfo.track[trknum-1].offset + outtoc.tracks[trknum-1].frames * (outtoc.tracks[trknum-1].datasize + outtoc.tracks[trknum-1].subsize); outtoc.tracks[trknum].frames = (tlen - outinfo.track[trknum].offset) / (outtoc.tracks[trknum].datasize + outtoc.tracks[trknum].subsize); @@ -1473,7 +1474,7 @@ chd_error chdcd_parse_gdicue(const char *tocfname, cdrom_toc &outtoc, chdcd_trac if (tlen == 0) { printf("ERROR: couldn't find bin file [%s]\n", outinfo.track[trknum-1].fname.c_str()); - return CHDERR_FILE_NOT_FOUND; + return std::errc::no_such_file_or_directory; } tlen /= (outtoc.tracks[trknum].datasize + outtoc.tracks[trknum].subsize); outtoc.tracks[trknum].frames = tlen; @@ -1499,7 +1500,7 @@ chd_error chdcd_parse_gdicue(const char *tocfname, cdrom_toc &outtoc, chdcd_trac if (!outtoc.tracks[trknum].frames) { printf("ERROR: unable to determine size of track %d, missing INDEX 01 markers?\n", trknum+1); - return CHDERR_INVALID_DATA; + return chd_file::error::INVALID_DATA; } } else /* data files are different */ @@ -1508,7 +1509,7 @@ chd_error chdcd_parse_gdicue(const char *tocfname, cdrom_toc &outtoc, chdcd_trac if (tlen == 0) { printf("ERROR: couldn't find bin file [%s]\n", outinfo.track[trknum].fname.c_str()); - return CHDERR_FILE_NOT_FOUND; + return std::errc::no_such_file_or_directory; } tlen /= (outtoc.tracks[trknum].datasize + outtoc.tracks[trknum].subsize); outtoc.tracks[trknum].frames = tlen; @@ -1638,7 +1639,7 @@ chd_error chdcd_parse_gdicue(const char *tocfname, cdrom_toc &outtoc, chdcd_trac } #endif - return CHDERR_NONE; + return std::error_condition(); } /*------------------------------------------------- @@ -1646,7 +1647,7 @@ chd_error chdcd_parse_gdicue(const char *tocfname, cdrom_toc &outtoc, chdcd_trac -------------------------------------------------*/ /** - * @fn chd_error chdcd_parse_toc(const char *tocfname, cdrom_toc &outtoc, chdcd_track_input_info &outinfo) + * @fn std::error_condition chdcd_parse_toc(const char *tocfname, cdrom_toc &outtoc, chdcd_track_input_info &outinfo) * * @brief Chdcd parse TOC. * @@ -1654,12 +1655,11 @@ chd_error chdcd_parse_gdicue(const char *tocfname, cdrom_toc &outtoc, chdcd_trac * @param [in,out] outtoc The outtoc. * @param [in,out] outinfo The outinfo. * - * @return A chd_error. + * @return A std::error_condition. */ -chd_error chdcd_parse_toc(const char *tocfname, cdrom_toc &outtoc, chdcd_track_input_info &outinfo) +std::error_condition chdcd_parse_toc(const char *tocfname, cdrom_toc &outtoc, chdcd_track_input_info &outinfo) { - FILE *infile; int i, trknum; static char token[512]; char tocftemp[512]; @@ -1695,14 +1695,14 @@ chd_error chdcd_parse_toc(const char *tocfname, cdrom_toc &outtoc, chdcd_track_i std::string path = std::string(tocfname); - infile = fopen(tocfname, "rt"); - path = get_file_path(path); - - if (infile == (FILE *)nullptr) + FILE *infile = fopen(tocfname, "rt"); + if (!infile) { - return CHDERR_FILE_NOT_FOUND; + return std::error_condition(errno, std::generic_category()); } + path = get_file_path(path); + /* clear structures */ memset(&outtoc, 0, sizeof(outtoc)); outinfo.reset(); @@ -1817,7 +1817,7 @@ chd_error chdcd_parse_toc(const char *tocfname, cdrom_toc &outtoc, chdcd_track_i { fclose(infile); printf("ERROR: Unknown track type [%s]. Contact MAMEDEV.\n", token); - return CHDERR_UNSUPPORTED_FORMAT; + return chd_file::error::UNSUPPORTED_FORMAT; } /* next (optional) token on the line is the subcode type */ @@ -1844,5 +1844,5 @@ chd_error chdcd_parse_toc(const char *tocfname, cdrom_toc &outtoc, chdcd_track_i /* store the number of tracks found */ outtoc.numtrks = trknum + 1; - return CHDERR_NONE; + return std::error_condition(); } diff --git a/src/lib/util/chdcd.h b/src/lib/util/chdcd.h index 65e4b943964..95f214e5831 100644 --- a/src/lib/util/chdcd.h +++ b/src/lib/util/chdcd.h @@ -5,14 +5,16 @@ CDRDAO TOC parser for CHD compression frontend ***************************************************************************/ - -#ifndef MAME_UTIL_CHDCD_H -#define MAME_UTIL_CHDCD_H +#ifndef MAME_LIB_UTIL_CHDCD_H +#define MAME_LIB_UTIL_CHDCD_H #pragma once #include "cdrom.h" +#include + + struct chdcd_track_input_entry { chdcd_track_input_entry() { reset(); } @@ -33,6 +35,6 @@ struct chdcd_track_input_info }; -chd_error chdcd_parse_toc(const char *tocfname, cdrom_toc &outtoc, chdcd_track_input_info &outinfo); +std::error_condition chdcd_parse_toc(const char *tocfname, cdrom_toc &outtoc, chdcd_track_input_info &outinfo); -#endif // MAME_UTIL_CHDCD_H +#endif // MAME_LIB_UTIL_CHDCD_H diff --git a/src/lib/util/chdcodec.cpp b/src/lib/util/chdcodec.cpp index 4f5c23b3104..eca9403b56c 100644 --- a/src/lib/util/chdcodec.cpp +++ b/src/lib/util/chdcodec.cpp @@ -8,24 +8,29 @@ ***************************************************************************/ -#include +#include "chdcodec.h" -#include "chd.h" -#include "hashing.h" #include "avhuff.h" -#include "flac.h" #include "cdrom.h" -#include -#include "lzma/C/LzmaEnc.h" +#include "chd.h" +#include "flac.h" +#include "hashing.h" + #include "lzma/C/LzmaDec.h" +#include "lzma/C/LzmaEnc.h" + +#include + #include +namespace { + //************************************************************************** // GLOBAL VARIABLES //************************************************************************** -static const uint8_t s_cd_sync_header[12] = { 0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00 }; +constexpr uint8_t f_cd_sync_header[12] = { 0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00 }; @@ -35,7 +40,7 @@ static const uint8_t s_cd_sync_header[12] = { 0x00,0xff,0xff,0xff,0xff,0xff,0xff // ======================> chd_zlib_allocator -// allocation helper clas for zlib +// allocation helper class for zlib class chd_zlib_allocator { public: @@ -51,7 +56,8 @@ private: static voidpf fast_alloc(voidpf opaque, uInt items, uInt size); static void fast_free(voidpf opaque, voidpf address); - static const int MAX_ZLIB_ALLOCS = 64; + static constexpr int MAX_ZLIB_ALLOCS = 64; + uint32_t * m_allocptr[MAX_ZLIB_ALLOCS]; }; @@ -111,7 +117,7 @@ private: static void *fast_alloc(void *p, size_t size); static void fast_free(void *p, void *address); - static const int MAX_LZMA_ALLOCS = 64; + static constexpr int MAX_LZMA_ALLOCS = 64; uint32_t * m_allocptr[MAX_LZMA_ALLOCS]; }; @@ -287,7 +293,7 @@ private: // ======================> chd_cd_compressor -template +template class chd_cd_compressor : public chd_compressor { public: @@ -300,7 +306,7 @@ public: { // make sure the CHD's hunk size is an even multiple of the frame size if (hunkbytes % CD_FRAME_SIZE != 0) - throw CHDERR_CODEC_ERROR; + throw std::error_condition(chd_file::error::CODEC_ERROR); } // core functionality @@ -323,10 +329,10 @@ public: // clear out ECC data if we can uint8_t *sector = &m_buffer[framenum * CD_MAX_SECTOR_DATA]; - if (memcmp(sector, s_cd_sync_header, sizeof(s_cd_sync_header)) == 0 && ecc_verify(sector)) + if (memcmp(sector, f_cd_sync_header, sizeof(f_cd_sync_header)) == 0 && ecc_verify(sector)) { dest[framenum / 8] |= 1 << (framenum % 8); - memset(sector, 0, sizeof(s_cd_sync_header)); + memset(sector, 0, sizeof(f_cd_sync_header)); ecc_clear(sector); } } @@ -334,7 +340,7 @@ public: // encode the base portion uint32_t complen = m_base_compressor.compress(&m_buffer[0], frames * CD_MAX_SECTOR_DATA, &dest[header_bytes]); if (complen >= srclen) - throw CHDERR_COMPRESSION_ERROR; + throw std::error_condition(chd_file::error::COMPRESSION_ERROR); // write compressed length dest[ecc_bytes + 0] = complen >> ((complen_bytes - 1) * 8); @@ -348,15 +354,15 @@ public: private: // internal state - _BaseCompressor m_base_compressor; - _SubcodeCompressor m_subcode_compressor; + BaseCompressor m_base_compressor; + SubcodeCompressor m_subcode_compressor; std::vector m_buffer; }; // ======================> chd_cd_decompressor -template +template class chd_cd_decompressor : public chd_decompressor { public: @@ -369,7 +375,7 @@ public: { // make sure the CHD's hunk size is an even multiple of the frame size if (hunkbytes % CD_FRAME_SIZE != 0) - throw CHDERR_CODEC_ERROR; + throw std::error_condition(chd_file::error::CODEC_ERROR); } // core functionality @@ -400,7 +406,7 @@ public: uint8_t *sector = &dest[framenum * CD_FRAME_SIZE]; if ((src[framenum / 8] & (1 << (framenum % 8))) != 0) { - memcpy(sector, s_cd_sync_header, sizeof(s_cd_sync_header)); + memcpy(sector, f_cd_sync_header, sizeof(f_cd_sync_header)); ecc_generate(sector); } } @@ -408,8 +414,8 @@ public: private: // internal state - _BaseDecompressor m_base_decompressor; - _SubcodeDecompressor m_subcode_decompressor; + BaseDecompressor m_base_decompressor; + SubcodeDecompressor m_subcode_decompressor; std::vector m_buffer; }; @@ -460,25 +466,65 @@ private: // CODEC LIST //************************************************************************** +// an entry in the list +struct codec_entry +{ + chd_codec_type m_type; + bool m_lossy; + const char * m_name; + chd_compressor::ptr (*m_construct_compressor)(chd_file &, uint32_t, bool); + chd_decompressor::ptr (*m_construct_decompressor)(chd_file &, uint32_t, bool); + + template + static chd_compressor::ptr construct_compressor(chd_file &chd, uint32_t hunkbytes, bool lossy) + { + return std::make_unique(chd, hunkbytes, lossy); + } + + template + static chd_decompressor::ptr construct_decompressor(chd_file &chd, uint32_t hunkbytes, bool lossy) + { + return std::make_unique(chd, hunkbytes, lossy); + } +}; + + // static list of available known codecs -const chd_codec_list::codec_entry chd_codec_list::s_codec_list[] = +const codec_entry f_codec_list[] = { // general codecs - { CHD_CODEC_ZLIB, false, "Deflate", &chd_codec_list::construct_compressor, &chd_codec_list::construct_decompressor }, - { CHD_CODEC_LZMA, false, "LZMA", &chd_codec_list::construct_compressor, &chd_codec_list::construct_decompressor }, - { CHD_CODEC_HUFFMAN, false, "Huffman", &chd_codec_list::construct_compressor, &chd_codec_list::construct_decompressor }, - { CHD_CODEC_FLAC, false, "FLAC", &chd_codec_list::construct_compressor, &chd_codec_list::construct_decompressor }, + { CHD_CODEC_ZLIB, false, "Deflate", &codec_entry::construct_compressor, &codec_entry::construct_decompressor }, + { CHD_CODEC_LZMA, false, "LZMA", &codec_entry::construct_compressor, &codec_entry::construct_decompressor }, + { CHD_CODEC_HUFFMAN, false, "Huffman", &codec_entry::construct_compressor, &codec_entry::construct_decompressor }, + { CHD_CODEC_FLAC, false, "FLAC", &codec_entry::construct_compressor, &codec_entry::construct_decompressor }, // general codecs with CD frontend - { CHD_CODEC_CD_ZLIB, false, "CD Deflate", &chd_codec_list::construct_compressor >, &chd_codec_list::construct_decompressor > }, - { CHD_CODEC_CD_LZMA, false, "CD LZMA", &chd_codec_list::construct_compressor >, &chd_codec_list::construct_decompressor > }, - { CHD_CODEC_CD_FLAC, false, "CD FLAC", &chd_codec_list::construct_compressor, &chd_codec_list::construct_decompressor }, + { CHD_CODEC_CD_ZLIB, false, "CD Deflate", &codec_entry::construct_compressor >, &codec_entry::construct_decompressor > }, + { CHD_CODEC_CD_LZMA, false, "CD LZMA", &codec_entry::construct_compressor >, &codec_entry::construct_decompressor > }, + { CHD_CODEC_CD_FLAC, false, "CD FLAC", &codec_entry::construct_compressor, &codec_entry::construct_decompressor }, // A/V codecs - { CHD_CODEC_AVHUFF, false, "A/V Huffman", &chd_codec_list::construct_compressor, &chd_codec_list::construct_decompressor }, + { CHD_CODEC_AVHUFF, false, "A/V Huffman", &codec_entry::construct_compressor, &codec_entry::construct_decompressor }, }; +//------------------------------------------------- +// find_in_list - create a new compressor +// instance of the given type +//------------------------------------------------- + +const codec_entry *find_in_list(chd_codec_type type) +{ + // find in the list and construct the class + for (auto & elem : f_codec_list) + if (elem.m_type == type) + return &elem; + return nullptr; +} + +} // anonymous namespace + + //************************************************************************** // CHD CODEC @@ -512,7 +558,7 @@ chd_codec::~chd_codec() void chd_codec::configure(int param, void *config) { // if not overridden, it is always a failure - throw CHDERR_INVALID_PARAMETER; + throw std::error_condition(std::errc::invalid_argument); } @@ -556,11 +602,11 @@ chd_decompressor::chd_decompressor(chd_file &chd, uint32_t hunkbytes, bool lossy // instance of the given type //------------------------------------------------- -chd_compressor *chd_codec_list::new_compressor(chd_codec_type type, chd_file &chd) +chd_compressor::ptr chd_codec_list::new_compressor(chd_codec_type type, chd_file &chd) { // find in the list and construct the class - const codec_entry *entry = find_in_list(type); - return (entry == nullptr) ? nullptr : (*entry->m_construct_compressor)(chd, chd.hunk_bytes(), entry->m_lossy); + codec_entry const *const entry = find_in_list(type); + return entry ? (*entry->m_construct_compressor)(chd, chd.hunk_bytes(), entry->m_lossy) : nullptr; } @@ -569,39 +615,36 @@ chd_compressor *chd_codec_list::new_compressor(chd_codec_type type, chd_file &ch // instance of the given type //------------------------------------------------- -chd_decompressor *chd_codec_list::new_decompressor(chd_codec_type type, chd_file &chd) +chd_decompressor::ptr chd_codec_list::new_decompressor(chd_codec_type type, chd_file &chd) { // find in the list and construct the class const codec_entry *entry = find_in_list(type); - return (entry == nullptr) ? nullptr : (*entry->m_construct_decompressor)(chd, chd.hunk_bytes(), entry->m_lossy); + return entry ? (*entry->m_construct_decompressor)(chd, chd.hunk_bytes(), entry->m_lossy) : nullptr; } //------------------------------------------------- -// codec_name - return the name of the given -// codec +// codec_exists - determine whether a codec type +// corresponds to a supported codec //------------------------------------------------- -const char *chd_codec_list::codec_name(chd_codec_type type) +bool chd_codec_list::codec_exists(chd_codec_type type) { // find in the list and construct the class - const codec_entry *entry = find_in_list(type); - return (entry == nullptr) ? nullptr : entry->m_name; + return bool(find_in_list(type)); } //------------------------------------------------- -// find_in_list - create a new compressor -// instance of the given type +// codec_name - return the name of the given +// codec //------------------------------------------------- -const chd_codec_list::codec_entry *chd_codec_list::find_in_list(chd_codec_type type) +const char *chd_codec_list::codec_name(chd_codec_type type) { // find in the list and construct the class - for (auto & elem : s_codec_list) - if (elem.m_type == type) - return &elem; - return nullptr; + const codec_entry *entry = find_in_list(type); + return entry ? entry->m_name : nullptr; } @@ -615,25 +658,24 @@ const chd_codec_list::codec_entry *chd_codec_list::find_in_list(chd_codec_type t //------------------------------------------------- chd_compressor_group::chd_compressor_group(chd_file &chd, uint32_t compressor_list[4]) - : m_hunkbytes(chd.hunk_bytes()), - m_compress_test(m_hunkbytes) + : m_hunkbytes(chd.hunk_bytes()) + , m_compress_test(m_hunkbytes) #if CHDCODEC_VERIFY_COMPRESSION - ,m_decompressed(m_hunkbytes) + , m_decompressed(m_hunkbytes) #endif { // verify the compression types and initialize the codecs for (int codecnum = 0; codecnum < std::size(m_compressor); codecnum++) { - m_compressor[codecnum] = nullptr; if (compressor_list[codecnum] != CHD_CODEC_NONE) { m_compressor[codecnum] = chd_codec_list::new_compressor(compressor_list[codecnum], chd); - if (m_compressor[codecnum] == nullptr) - throw CHDERR_UNKNOWN_COMPRESSION; + if (!m_compressor[codecnum]) + throw std::error_condition(chd_file::error::UNKNOWN_COMPRESSION); #if CHDCODEC_VERIFY_COMPRESSION m_decompressor[codecnum] = chd_codec_list::new_decompressor(compressor_list[codecnum], chd); - if (m_decompressor[codecnum] == nullptr) - throw CHDERR_UNKNOWN_COMPRESSION; + if (!m_decompressor[codecnum]) + throw std::error_condition(chd_file::error::UNKNOWN_COMPRESSION); #endif } } @@ -646,9 +688,7 @@ chd_compressor_group::chd_compressor_group(chd_file &chd, uint32_t compressor_li chd_compressor_group::~chd_compressor_group() { - // delete the codecs and the test buffer - for (auto & elem : m_compressor) - delete elem; + // codecs and test buffer deleted automatically } @@ -664,7 +704,7 @@ int8_t chd_compressor_group::find_best_compressor(const uint8_t *src, uint8_t *c complen = m_hunkbytes; int8_t compression = -1; for (int codecnum = 0; codecnum < std::size(m_compressor); codecnum++) - if (m_compressor[codecnum] != nullptr) + if (m_compressor[codecnum]) { // attempt to compress, swallowing errors try @@ -702,7 +742,9 @@ printf(" codec%d=%d bytes \n", codecnum, compbytes); memcpy(compressed, &m_compress_test[0], compbytes); } } - catch (...) { } + catch (...) + { + } } // if the best is none, copy it over @@ -835,7 +877,7 @@ chd_zlib_compressor::chd_zlib_compressor(chd_file &chd, uint32_t hunkbytes, bool if (zerr == Z_MEM_ERROR) throw std::bad_alloc(); else if (zerr != Z_OK) - throw CHDERR_CODEC_ERROR; + throw std::error_condition(chd_file::error::CODEC_ERROR); } @@ -864,14 +906,14 @@ uint32_t chd_zlib_compressor::compress(const uint8_t *src, uint32_t srclen, uint m_deflater.total_out = 0; int zerr = deflateReset(&m_deflater); if (zerr != Z_OK) - throw CHDERR_COMPRESSION_ERROR; + throw std::error_condition(chd_file::error::COMPRESSION_ERROR); // do it zerr = deflate(&m_deflater, Z_FINISH); // if we ended up with more data than we started with, return an error if (zerr != Z_STREAM_END || m_deflater.total_out >= srclen) - throw CHDERR_COMPRESSION_ERROR; + throw std::error_condition(chd_file::error::COMPRESSION_ERROR); // otherwise, return the length return m_deflater.total_out; @@ -900,7 +942,7 @@ chd_zlib_decompressor::chd_zlib_decompressor(chd_file &chd, uint32_t hunkbytes, if (zerr == Z_MEM_ERROR) throw std::bad_alloc(); else if (zerr != Z_OK) - throw CHDERR_CODEC_ERROR; + throw std::error_condition(chd_file::error::CODEC_ERROR); } @@ -930,14 +972,14 @@ void chd_zlib_decompressor::decompress(const uint8_t *src, uint32_t complen, uin m_inflater.total_out = 0; int zerr = inflateReset(&m_inflater); if (zerr != Z_OK) - throw CHDERR_DECOMPRESSION_ERROR; + throw std::error_condition(chd_file::error::DECOMPRESSION_ERROR); // do it zerr = inflate(&m_inflater, Z_FINISH); if (zerr != Z_STREAM_END) - throw CHDERR_DECOMPRESSION_ERROR; + throw std::error_condition(chd_file::error::DECOMPRESSION_ERROR); if (m_inflater.total_out != destlen) - throw CHDERR_DECOMPRESSION_ERROR; + throw std::error_condition(chd_file::error::DECOMPRESSION_ERROR); } @@ -1071,20 +1113,20 @@ uint32_t chd_lzma_compressor::compress(const uint8_t *src, uint32_t srclen, uint // allocate the encoder CLzmaEncHandle encoder = LzmaEnc_Create(&m_allocator); if (encoder == nullptr) - throw CHDERR_COMPRESSION_ERROR; + throw std::error_condition(chd_file::error::COMPRESSION_ERROR); try { // configure the encoder SRes res = LzmaEnc_SetProps(encoder, &m_props); if (res != SZ_OK) - throw CHDERR_COMPRESSION_ERROR; + throw std::error_condition(chd_file::error::COMPRESSION_ERROR); // run it SizeT complen = srclen; res = LzmaEnc_MemEncode(encoder, dest, &complen, src, srclen, 0, nullptr, &m_allocator, &m_allocator); if (res != SZ_OK) - throw CHDERR_COMPRESSION_ERROR; + throw std::error_condition(chd_file::error::COMPRESSION_ERROR); // clean up LzmaEnc_Destroy(encoder, &m_allocator, &m_allocator); @@ -1140,24 +1182,24 @@ chd_lzma_decompressor::chd_lzma_decompressor(chd_file &chd, uint32_t hunkbytes, // convert to decoder properties CLzmaEncHandle enc = LzmaEnc_Create(&m_allocator); if (!enc) - throw CHDERR_DECOMPRESSION_ERROR; + throw std::error_condition(chd_file::error::DECOMPRESSION_ERROR); if (LzmaEnc_SetProps(enc, &encoder_props) != SZ_OK) { LzmaEnc_Destroy(enc, &m_allocator, &m_allocator); - throw CHDERR_DECOMPRESSION_ERROR; + throw std::error_condition(chd_file::error::DECOMPRESSION_ERROR); } Byte decoder_props[LZMA_PROPS_SIZE]; SizeT props_size = sizeof(decoder_props); if (LzmaEnc_WriteProperties(enc, decoder_props, &props_size) != SZ_OK) { LzmaEnc_Destroy(enc, &m_allocator, &m_allocator); - throw CHDERR_DECOMPRESSION_ERROR; + throw std::error_condition(chd_file::error::DECOMPRESSION_ERROR); } LzmaEnc_Destroy(enc, &m_allocator, &m_allocator); // do memory allocations if (LzmaDec_Allocate(&m_decoder, decoder_props, LZMA_PROPS_SIZE, &m_allocator) != SZ_OK) - throw CHDERR_DECOMPRESSION_ERROR; + throw std::error_condition(chd_file::error::DECOMPRESSION_ERROR); } @@ -1188,7 +1230,7 @@ void chd_lzma_decompressor::decompress(const uint8_t *src, uint32_t complen, uin ELzmaStatus status; SRes res = LzmaDec_DecodeToBuf(&m_decoder, dest, &decodedlen, src, &consumedlen, LZMA_FINISH_END, &status); if ((res != SZ_OK && res != LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK) || consumedlen != complen || decodedlen != destlen) - throw CHDERR_DECOMPRESSION_ERROR; + throw std::error_condition(chd_file::error::DECOMPRESSION_ERROR); } @@ -1216,7 +1258,7 @@ uint32_t chd_huffman_compressor::compress(const uint8_t *src, uint32_t srclen, u { uint32_t complen; if (m_encoder.encode(src, srclen, dest, srclen, complen) != HUFFERR_NONE) - throw CHDERR_COMPRESSION_ERROR; + throw std::error_condition(chd_file::error::COMPRESSION_ERROR); return complen; } @@ -1244,7 +1286,7 @@ chd_huffman_decompressor::chd_huffman_decompressor(chd_file &chd, uint32_t hunkb void chd_huffman_decompressor::decompress(const uint8_t *src, uint32_t complen, uint8_t *dest, uint32_t destlen) { if (m_decoder.decode(src, complen, dest, destlen) != HUFFERR_NONE) - throw CHDERR_COMPRESSION_ERROR; + throw std::error_condition(chd_file::error::COMPRESSION_ERROR); } @@ -1282,19 +1324,19 @@ uint32_t chd_flac_compressor::compress(const uint8_t *src, uint32_t srclen, uint // reset and encode big-endian m_encoder.reset(dest + 1, hunkbytes() - 1); if (!m_encoder.encode_interleaved(reinterpret_cast(src), srclen / 4, !m_big_endian)) - throw CHDERR_COMPRESSION_ERROR; + throw std::error_condition(chd_file::error::COMPRESSION_ERROR); uint32_t complen_be = m_encoder.finish(); // reset and encode little-endian m_encoder.reset(dest + 1, hunkbytes() - 1); if (!m_encoder.encode_interleaved(reinterpret_cast(src), srclen / 4, m_big_endian)) - throw CHDERR_COMPRESSION_ERROR; + throw std::error_condition(chd_file::error::COMPRESSION_ERROR); uint32_t complen_le = m_encoder.finish(); // pick the best one and add a byte uint32_t complen = std::min(complen_le, complen_be); if (complen + 1 >= hunkbytes()) - throw CHDERR_COMPRESSION_ERROR; + throw std::error_condition(chd_file::error::COMPRESSION_ERROR); // if big-endian was better, re-do it dest[0] = 'L'; @@ -1303,7 +1345,7 @@ uint32_t chd_flac_compressor::compress(const uint8_t *src, uint32_t srclen, uint dest[0] = 'B'; m_encoder.reset(dest + 1, hunkbytes() - 1); if (!m_encoder.encode_interleaved(reinterpret_cast(src), srclen / 4, !m_big_endian)) - throw CHDERR_COMPRESSION_ERROR; + throw std::error_condition(chd_file::error::COMPRESSION_ERROR); m_encoder.finish(); } return complen + 1; @@ -1358,13 +1400,13 @@ void chd_flac_decompressor::decompress(const uint8_t *src, uint32_t complen, uin else if (src[0] == 'B') swap_endian = !m_big_endian; else - throw CHDERR_DECOMPRESSION_ERROR; + throw std::error_condition(chd_file::error::DECOMPRESSION_ERROR); // reset and decode if (!m_decoder.reset(44100, 2, chd_flac_compressor::blocksize(destlen), src + 1, complen - 1)) - throw CHDERR_DECOMPRESSION_ERROR; + throw std::error_condition(chd_file::error::DECOMPRESSION_ERROR); if (!m_decoder.decode_interleaved(reinterpret_cast(dest), destlen / 4, swap_endian)) - throw CHDERR_DECOMPRESSION_ERROR; + throw std::error_condition(chd_file::error::DECOMPRESSION_ERROR); // finish up m_decoder.finish(); @@ -1386,7 +1428,7 @@ chd_cd_flac_compressor::chd_cd_flac_compressor(chd_file &chd, uint32_t hunkbytes { // make sure the CHD's hunk size is an even multiple of the frame size if (hunkbytes % CD_FRAME_SIZE != 0) - throw CHDERR_CODEC_ERROR; + throw std::error_condition(chd_file::error::CODEC_ERROR); // determine whether we want native or swapped samples uint16_t native_endian = 0; @@ -1409,7 +1451,7 @@ chd_cd_flac_compressor::chd_cd_flac_compressor(chd_file &chd, uint32_t hunkbytes if (zerr == Z_MEM_ERROR) throw std::bad_alloc(); else if (zerr != Z_OK) - throw CHDERR_CODEC_ERROR; + throw std::error_condition(chd_file::error::CODEC_ERROR); } @@ -1442,7 +1484,7 @@ uint32_t chd_cd_flac_compressor::compress(const uint8_t *src, uint32_t srclen, u m_encoder.reset(dest, hunkbytes()); uint8_t *buffer = &m_buffer[0]; if (!m_encoder.encode_interleaved(reinterpret_cast(buffer), frames * CD_MAX_SECTOR_DATA/4, m_swap_endian)) - throw CHDERR_COMPRESSION_ERROR; + throw std::error_condition(chd_file::error::COMPRESSION_ERROR); // finish up uint32_t complen = m_encoder.finish(); @@ -1456,7 +1498,7 @@ uint32_t chd_cd_flac_compressor::compress(const uint8_t *src, uint32_t srclen, u m_deflater.total_out = 0; int zerr = deflateReset(&m_deflater); if (zerr != Z_OK) - throw CHDERR_COMPRESSION_ERROR; + throw std::error_condition(chd_file::error::COMPRESSION_ERROR); // do it zerr = deflate(&m_deflater, Z_FINISH); @@ -1464,7 +1506,7 @@ uint32_t chd_cd_flac_compressor::compress(const uint8_t *src, uint32_t srclen, u // if we ended up with more data than we started with, return an error complen += m_deflater.total_out; if (zerr != Z_STREAM_END || complen >= srclen) - throw CHDERR_COMPRESSION_ERROR; + throw std::error_condition(chd_file::error::COMPRESSION_ERROR); return complen; } @@ -1515,7 +1557,7 @@ chd_cd_flac_decompressor::chd_cd_flac_decompressor(chd_file &chd, uint32_t hunkb { // make sure the CHD's hunk size is an even multiple of the frame size if (hunkbytes % CD_FRAME_SIZE != 0) - throw CHDERR_CODEC_ERROR; + throw std::error_condition(chd_file::error::CODEC_ERROR); // determine whether we want native or swapped samples uint16_t native_endian = 0; @@ -1532,7 +1574,7 @@ chd_cd_flac_decompressor::chd_cd_flac_decompressor(chd_file &chd, uint32_t hunkb if (zerr == Z_MEM_ERROR) throw std::bad_alloc(); else if (zerr != Z_OK) - throw CHDERR_CODEC_ERROR; + throw std::error_condition(chd_file::error::CODEC_ERROR); } /** @@ -1569,10 +1611,10 @@ void chd_cd_flac_decompressor::decompress(const uint8_t *src, uint32_t complen, // reset and decode uint32_t frames = destlen / CD_FRAME_SIZE; if (!m_decoder.reset(44100, 2, chd_cd_flac_compressor::blocksize(frames * CD_MAX_SECTOR_DATA), src, complen)) - throw CHDERR_DECOMPRESSION_ERROR; + throw std::error_condition(chd_file::error::DECOMPRESSION_ERROR); uint8_t *buffer = &m_buffer[0]; if (!m_decoder.decode_interleaved(reinterpret_cast(buffer), frames * CD_MAX_SECTOR_DATA/4, m_swap_endian)) - throw CHDERR_DECOMPRESSION_ERROR; + throw std::error_condition(chd_file::error::DECOMPRESSION_ERROR); // inflate the subcode data uint32_t offset = m_decoder.finish(); @@ -1584,14 +1626,14 @@ void chd_cd_flac_decompressor::decompress(const uint8_t *src, uint32_t complen, m_inflater.total_out = 0; int zerr = inflateReset(&m_inflater); if (zerr != Z_OK) - throw CHDERR_DECOMPRESSION_ERROR; + throw std::error_condition(chd_file::error::DECOMPRESSION_ERROR); // do it zerr = inflate(&m_inflater, Z_FINISH); if (zerr != Z_STREAM_END) - throw CHDERR_DECOMPRESSION_ERROR; + throw std::error_condition(chd_file::error::DECOMPRESSION_ERROR); if (m_inflater.total_out != frames * CD_MAX_SUBCODE_DATA) - throw CHDERR_DECOMPRESSION_ERROR; + throw std::error_condition(chd_file::error::DECOMPRESSION_ERROR); // reassemble the data for (uint32_t framenum = 0; framenum < frames; framenum++) @@ -1620,15 +1662,15 @@ void chd_cd_flac_decompressor::decompress(const uint8_t *src, uint32_t complen, */ chd_avhuff_compressor::chd_avhuff_compressor(chd_file &chd, uint32_t hunkbytes, bool lossy) - : chd_compressor(chd, hunkbytes, lossy), - m_postinit(false) + : chd_compressor(chd, hunkbytes, lossy) + , m_postinit(false) { try { // attempt to do a post-init now postinit(); } - catch (chd_error &) + catch (std::error_condition const &) { // if we're creating a new CHD, it won't work but that's ok } @@ -1665,14 +1707,14 @@ uint32_t chd_avhuff_compressor::compress(const uint8_t *src, uint32_t srclen, ui int size = avhuff_encoder::raw_data_size(src); while (size < srclen) if (src[size++] != 0) - throw CHDERR_INVALID_DATA; + throw std::error_condition(chd_file::error::INVALID_DATA); } // encode the audio and video uint32_t complen; avhuff_error averr = m_encoder.encode_data(src, dest, complen); if (averr != AVHERR_NONE || complen > srclen) - throw CHDERR_COMPRESSION_ERROR; + throw std::error_condition(chd_file::error::COMPRESSION_ERROR); return complen; } @@ -1693,21 +1735,21 @@ void chd_avhuff_compressor::postinit() { // get the metadata std::string metadata; - chd_error err = chd().read_metadata(AV_METADATA_TAG, 0, metadata); - if (err != CHDERR_NONE) + std::error_condition err = chd().read_metadata(AV_METADATA_TAG, 0, metadata); + if (err) throw err; // extract the info int fps, fpsfrac, width, height, interlaced, channels, rate; if (sscanf(metadata.c_str(), AV_METADATA_FORMAT, &fps, &fpsfrac, &width, &height, &interlaced, &channels, &rate) != 7) - throw CHDERR_INVALID_METADATA; + throw std::error_condition(chd_file::error::INVALID_METADATA); // compute the bytes per frame uint32_t fps_times_1million = fps * 1000000 + fpsfrac; uint32_t max_samples_per_frame = (uint64_t(rate) * 1000000 + fps_times_1million - 1) / fps_times_1million; uint32_t bytes_per_frame = 12 + channels * max_samples_per_frame * 2 + width * height * 2; if (bytes_per_frame > hunkbytes()) - throw CHDERR_INVALID_METADATA; + throw std::error_condition(chd_file::error::INVALID_METADATA); // done with post-init m_postinit = true; @@ -1757,7 +1799,7 @@ void chd_avhuff_decompressor::decompress(const uint8_t *src, uint32_t complen, u // decode the audio and video avhuff_error averr = m_decoder.decode_data(src, complen, dest); if (averr != AVHERR_NONE) - throw CHDERR_DECOMPRESSION_ERROR; + throw std::error_condition(chd_file::error::DECOMPRESSION_ERROR); // pad short frames with 0 if (dest != nullptr) @@ -1790,5 +1832,5 @@ void chd_avhuff_decompressor::configure(int param, void *config) // anything else is invalid else - throw CHDERR_INVALID_PARAMETER; + throw std::error_condition(std::errc::invalid_argument); } diff --git a/src/lib/util/chdcodec.h b/src/lib/util/chdcodec.h index dc9c074fd37..700ae8f8979 100644 --- a/src/lib/util/chdcodec.h +++ b/src/lib/util/chdcodec.h @@ -7,34 +7,25 @@ Codecs used by the CHD format ***************************************************************************/ - -#ifndef MAME_UTIL_CHDCODEC_H -#define MAME_UTIL_CHDCODEC_H +#ifndef MAME_LIB_UTIL_CHDCODEC_H +#define MAME_LIB_UTIL_CHDCODEC_H #pragma once +#include "utilfwd.h" + #include +#include #include #define CHDCODEC_VERIFY_COMPRESSION 0 -//************************************************************************** -// MACROS -//************************************************************************** - -#define CHD_MAKE_TAG(a,b,c,d) (((a) << 24) | ((b) << 16) | ((c) << 8) | (d)) - - - //************************************************************************** // TYPE DEFINITIONS //************************************************************************** -// forward references -class chd_file; - // base types typedef uint32_t chd_codec_type; @@ -63,7 +54,7 @@ public: private: // internal state chd_file & m_chd; - uint32_t m_hunkbytes; + uint32_t m_hunkbytes; bool m_lossy; }; @@ -78,6 +69,8 @@ protected: chd_compressor(chd_file &file, uint32_t hunkbytes, bool lossy); public: + using ptr = std::unique_ptr; + // implementation virtual uint32_t compress(const uint8_t *src, uint32_t srclen, uint8_t *dest) = 0; }; @@ -93,6 +86,8 @@ protected: chd_decompressor(chd_file &file, uint32_t hunkbytes, bool lossy); public: + using ptr = std::unique_ptr; + // implementation virtual void decompress(const uint8_t *src, uint32_t complen, uint8_t *dest, uint32_t destlen) = 0; }; @@ -105,35 +100,12 @@ class chd_codec_list { public: // create compressors or decompressors - static chd_compressor *new_compressor(chd_codec_type type, chd_file &file); - static chd_decompressor *new_decompressor(chd_codec_type type, chd_file &file); + static chd_compressor::ptr new_compressor(chd_codec_type type, chd_file &file); + static chd_decompressor::ptr new_decompressor(chd_codec_type type, chd_file &file); // utilities - static bool codec_exists(chd_codec_type type) { return (find_in_list(type) != nullptr); } + static bool codec_exists(chd_codec_type type); static const char *codec_name(chd_codec_type type); - -private: - // an entry in the list - struct codec_entry - { - chd_codec_type m_type; - bool m_lossy; - const char * m_name; - chd_compressor * (*m_construct_compressor)(chd_file &, uint32_t, bool); - chd_decompressor * (*m_construct_decompressor)(chd_file &, uint32_t, bool); - }; - - // internal helper functions - static const codec_entry *find_in_list(chd_codec_type type); - - template - static chd_compressor *construct_compressor(chd_file &chd, uint32_t hunkbytes, bool lossy) { return new _CompressorClass(chd, hunkbytes, lossy); } - - template - static chd_decompressor *construct_decompressor(chd_file &chd, uint32_t hunkbytes, bool lossy) { return new _DecompressorClass(chd, hunkbytes, lossy); } - - // the static list - static const codec_entry s_codec_list[]; }; @@ -152,37 +124,48 @@ public: private: // internal state - uint32_t m_hunkbytes; // number of bytes in a hunk - chd_compressor * m_compressor[4]; // array of active codecs - std::vector m_compress_test; // test buffer for compression + uint32_t m_hunkbytes; // number of bytes in a hunk + chd_compressor::ptr m_compressor[4]; // array of active codecs + std::vector m_compress_test; // test buffer for compression #if CHDCODEC_VERIFY_COMPRESSION - chd_decompressor * m_decompressor[4]; // array of active codecs - std::vector m_decompressed; // verification buffer + chd_decompressor::ptr m_decompressor[4]; // array of active codecs + std::vector m_decompressed; // verification buffer #endif }; +//************************************************************************** +// MACROS +//************************************************************************** + +constexpr chd_codec_type CHD_MAKE_TAG(char a, char b, char c, char d) +{ + return (uint32_t(uint8_t(a)) << 24) | uint32_t(uint8_t((b)) << 16) | uint32_t(uint8_t((c)) << 8) | uint32_t(uint8_t(d)); +} + + + //************************************************************************** // CONSTANTS //************************************************************************** // currently-defined codecs -const chd_codec_type CHD_CODEC_NONE = 0; +constexpr chd_codec_type CHD_CODEC_NONE = 0; // general codecs -const chd_codec_type CHD_CODEC_ZLIB = CHD_MAKE_TAG('z','l','i','b'); -const chd_codec_type CHD_CODEC_LZMA = CHD_MAKE_TAG('l','z','m','a'); -const chd_codec_type CHD_CODEC_HUFFMAN = CHD_MAKE_TAG('h','u','f','f'); -const chd_codec_type CHD_CODEC_FLAC = CHD_MAKE_TAG('f','l','a','c'); +constexpr chd_codec_type CHD_CODEC_ZLIB = CHD_MAKE_TAG('z','l','i','b'); +constexpr chd_codec_type CHD_CODEC_LZMA = CHD_MAKE_TAG('l','z','m','a'); +constexpr chd_codec_type CHD_CODEC_HUFFMAN = CHD_MAKE_TAG('h','u','f','f'); +constexpr chd_codec_type CHD_CODEC_FLAC = CHD_MAKE_TAG('f','l','a','c'); // general codecs with CD frontend -const chd_codec_type CHD_CODEC_CD_ZLIB = CHD_MAKE_TAG('c','d','z','l'); -const chd_codec_type CHD_CODEC_CD_LZMA = CHD_MAKE_TAG('c','d','l','z'); -const chd_codec_type CHD_CODEC_CD_FLAC = CHD_MAKE_TAG('c','d','f','l'); +constexpr chd_codec_type CHD_CODEC_CD_ZLIB = CHD_MAKE_TAG('c','d','z','l'); +constexpr chd_codec_type CHD_CODEC_CD_LZMA = CHD_MAKE_TAG('c','d','l','z'); +constexpr chd_codec_type CHD_CODEC_CD_FLAC = CHD_MAKE_TAG('c','d','f','l'); // A/V codecs -const chd_codec_type CHD_CODEC_AVHUFF = CHD_MAKE_TAG('a','v','h','u'); +constexpr chd_codec_type CHD_CODEC_AVHUFF = CHD_MAKE_TAG('a','v','h','u'); // A/V codec configuration parameters enum @@ -190,4 +173,4 @@ enum AVHUFF_CODEC_DECOMPRESS_CONFIG = 1 }; -#endif // MAME_UTIL_CHDCODEC_H +#endif // MAME_LIB_UTIL_CHDCODEC_H diff --git a/src/lib/util/corefile.cpp b/src/lib/util/corefile.cpp index e681c0f1fac..0c72e1337be 100644 --- a/src/lib/util/corefile.cpp +++ b/src/lib/util/corefile.cpp @@ -12,18 +12,16 @@ #include "coretmpl.h" #include "osdcore.h" +#include "path.h" #include "unicode.h" #include "vecstream.h" -#include - #include #include +#include #include #include -#include - namespace util { @@ -43,110 +41,11 @@ namespace { TYPE DEFINITIONS ***************************************************************************/ -class zlib_data -{ -public: - typedef std::unique_ptr ptr; - - static int start_compression(int level, std::uint64_t offset, ptr &data) - { - ptr result(new zlib_data(offset)); - result->reset_output(); - auto const zerr = deflateInit(&result->m_stream, level); - result->m_compress = (Z_OK == zerr); - if (result->m_compress) data = std::move(result); - return zerr; - } - static int start_decompression(std::uint64_t offset, ptr &data) - { - ptr result(new zlib_data(offset)); - auto const zerr = inflateInit(&result->m_stream); - result->m_decompress = (Z_OK == zerr); - if (result->m_decompress) data = std::move(result); - return zerr; - } - - ~zlib_data() - { - if (m_compress) deflateEnd(&m_stream); - else if (m_decompress) inflateEnd(&m_stream); - } - - std::size_t buffer_size() const { return sizeof(m_buffer); } - void const *buffer_data() const { return m_buffer; } - void *buffer_data() { return m_buffer; } - - // general-purpose output buffer manipulation - bool output_full() const { return 0 == m_stream.avail_out; } - std::size_t output_space() const { return m_stream.avail_out; } - void set_output(void *data, std::uint32_t size) - { - m_stream.next_out = reinterpret_cast(data); - m_stream.avail_out = size; - } - - // working with output to the internal buffer - bool has_output() const { return m_stream.avail_out != sizeof(m_buffer); } - std::size_t output_size() const { return sizeof(m_buffer) - m_stream.avail_out; } - void reset_output() - { - m_stream.next_out = m_buffer; - m_stream.avail_out = sizeof(m_buffer); - } - - // general-purpose input buffer manipulation - bool has_input() const { return 0 != m_stream.avail_in; } - std::size_t input_size() const { return m_stream.avail_in; } - void set_input(void const *data, std::uint32_t size) - { - m_stream.next_in = const_cast(reinterpret_cast(data)); - m_stream.avail_in = size; - } - - // working with input from the internal buffer - void reset_input(std::uint32_t size) - { - m_stream.next_in = m_buffer; - m_stream.avail_in = size; - } - - int compress() { assert(m_compress); return deflate(&m_stream, Z_NO_FLUSH); } - int finalise() { assert(m_compress); return deflate(&m_stream, Z_FINISH); } - int decompress() { assert(m_decompress); return inflate(&m_stream, Z_SYNC_FLUSH); } - - std::uint64_t realoffset() const { return m_realoffset; } - void add_realoffset(std::uint32_t increment) { m_realoffset += increment; } - - bool is_nextoffset(std::uint64_t value) const { return m_nextoffset == value; } - void add_nextoffset(std::uint32_t increment) { m_nextoffset += increment; } - -private: - zlib_data(std::uint64_t offset) - : m_compress(false) - , m_decompress(false) - , m_realoffset(offset) - , m_nextoffset(offset) - { - m_stream.zalloc = Z_NULL; - m_stream.zfree = Z_NULL; - m_stream.opaque = Z_NULL; - m_stream.avail_in = m_stream.avail_out = 0; - } - - bool m_compress, m_decompress; - z_stream m_stream; - std::uint8_t m_buffer[1024]; - std::uint64_t m_realoffset; - std::uint64_t m_nextoffset; -}; - - class core_proxy_file : public core_file { public: - core_proxy_file(core_file &file) : m_file(file) { } + core_proxy_file(core_file &file) noexcept : m_file(file) { } virtual ~core_proxy_file() override { } - 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(); } @@ -162,9 +61,9 @@ public: virtual std::uint32_t write(const void *buffer, std::uint32_t length) override { return m_file.write(buffer, length); } virtual int puts(std::string_view s) override { return m_file.puts(s); } virtual int vprintf(util::format_argument_pack const &args) override { return m_file.vprintf(args); } - virtual osd_file::error truncate(std::uint64_t offset) override { return m_file.truncate(offset); } + virtual std::error_condition truncate(std::uint64_t offset) override { return m_file.truncate(offset); } - virtual osd_file::error flush() override { return m_file.flush(); } + virtual std::error_condition flush() override { return m_file.flush(); } private: core_file &m_file; @@ -230,12 +129,12 @@ public: if (copy) { void *const buf = allocate(); - if (buf) std::memcpy(buf, data, length); + if (buf) + std::memcpy(buf, data, length); } } ~core_in_memory_file() override { purge(); } - 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; } @@ -246,8 +145,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 osd_file::error truncate(std::uint64_t offset) override; - virtual osd_file::error flush() override { clear_putback(); return osd_file::error::NONE; } + virtual std::error_condition truncate(std::uint64_t offset) override; + virtual std::error_condition flush() override { clear_putback(); return std::error_condition(); } protected: core_in_memory_file(std::uint32_t openflags, std::uint64_t length) @@ -262,7 +161,8 @@ protected: bool is_loaded() const { return nullptr != m_data; } void *allocate() { - if (m_data) return nullptr; + if (m_data) + return nullptr; void *data = malloc(m_length); if (data) { @@ -273,7 +173,8 @@ protected: } void purge() { - if (m_data && m_data_allocated) free(const_cast(m_data)); + if (m_data && m_data_allocated) + free(const_cast(m_data)); m_data_allocated = false; m_data = nullptr; } @@ -301,23 +202,18 @@ public: core_osd_file(std::uint32_t openmode, osd_file::ptr &&file, std::uint64_t length) : core_in_memory_file(openmode, length) , m_file(std::move(file)) - , m_zdata() , m_bufferbase(0) , m_bufferbytes(0) { } ~core_osd_file() override; - virtual osd_file::error compress(int level) override; - - virtual int seek(std::int64_t offset, int whence) override; - virtual std::uint32_t read(void *buffer, std::uint32_t length) override; virtual void const *buffer() override; virtual std::uint32_t write(void const *buffer, std::uint32_t length) override; - virtual osd_file::error truncate(std::uint64_t offset) override; - virtual osd_file::error flush() override; + virtual std::error_condition truncate(std::uint64_t offset) override; + virtual std::error_condition flush() override; protected: @@ -326,11 +222,7 @@ protected: private: static constexpr std::size_t FILE_BUFFER_SIZE = 512; - 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::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 std::uint8_t m_buffer[FILE_BUFFER_SIZE]; // buffer data @@ -673,14 +565,14 @@ std::uint32_t core_in_memory_file::read(void *buffer, std::uint32_t length) truncate - truncate a file -------------------------------------------------*/ -osd_file::error core_in_memory_file::truncate(std::uint64_t offset) +std::error_condition core_in_memory_file::truncate(std::uint64_t offset) { if (m_length < offset) - return osd_file::error::FAILURE; + return std::errc::io_error; // TODO: revisit this error code // adjust to new length and offset set_length(offset); - return osd_file::error::NONE; + return std::error_condition(); } @@ -719,91 +611,6 @@ std::size_t core_in_memory_file::safe_buffer_copy( core_osd_file::~core_osd_file() { // close files and free memory - if (m_zdata) - core_osd_file::compress(FCOMPRESS_NONE); -} - - -/*------------------------------------------------- - compress - enable/disable streaming file - compression via zlib; level is 0 to disable - compression, or up to 9 for max compression --------------------------------------------------*/ - -osd_file::error core_osd_file::compress(int level) -{ - 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 osd_file::error::INVALID_ACCESS; - - // if we have been compressing, flush and free the data - if (m_zdata && (level == FCOMPRESS_NONE)) - { - int zerr = Z_OK; - - // flush any remaining data if we are writing - while (write_access() && (zerr != Z_STREAM_END)) - { - // deflate some more - zerr = m_zdata->finalise(); - if ((zerr != Z_STREAM_END) && (zerr != Z_OK)) - { - result = osd_file::error::INVALID_DATA; - break; - } - - // write the data - if (m_zdata->has_output()) - { - std::uint32_t actualdata; - 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(); - } - } - - // free memory - m_zdata.reset(); - } - - // if we are just starting to compress, allocate a new buffer - if (!m_zdata && (level > FCOMPRESS_NONE)) - { - int zerr; - - // initialize the stream and compressor - if (write_access()) - zerr = zlib_data::start_compression(level, offset(), m_zdata); - else - zerr = zlib_data::start_decompression(offset(), m_zdata); - - // on error, return an error - if (zerr != Z_OK) - return osd_file::error::OUT_OF_MEMORY; - - // flush buffers - m_bufferbytes = 0; - } - - return result; -} - - -/*------------------------------------------------- - seek - seek within a file --------------------------------------------------*/ - -int core_osd_file::seek(std::int64_t offset, int whence) -{ - // error if compressing - if (m_zdata) - return 1; - else - return core_in_memory_file::seek(offset, whence); } @@ -833,7 +640,7 @@ std::uint32_t core_osd_file::read(void *buffer, std::uint32_t length) // read as much as makes sense into the buffer m_bufferbase = offset() + bytes_read; m_bufferbytes = 0; - osd_or_zlib_read(m_buffer, m_bufferbase, sizeof(m_buffer), m_bufferbytes); + m_file->read(m_buffer, m_bufferbase, sizeof(m_buffer), m_bufferbytes); // do a bounded copy from the buffer to the destination bytes_read += safe_buffer_copy(m_buffer, 0, m_bufferbytes, buffer, bytes_read, length); @@ -842,7 +649,7 @@ std::uint32_t core_osd_file::read(void *buffer, std::uint32_t length) { // read the remainder directly from the file std::uint32_t new_bytes_read = 0; - osd_or_zlib_read(reinterpret_cast(buffer) + bytes_read, offset() + bytes_read, length - bytes_read, new_bytes_read); + m_file->read(reinterpret_cast(buffer) + bytes_read, offset() + bytes_read, length - bytes_read, new_bytes_read); bytes_read += new_bytes_read; } } @@ -866,18 +673,16 @@ void const *core_osd_file::buffer() { // allocate some memory void *buf = allocate(); - if (!buf) return nullptr; + if (!buf) + return nullptr; // read the file std::uint32_t read_length = 0; - auto const filerr = osd_or_zlib_read(buf, 0, length(), read_length); - if ((filerr != osd_file::error::NONE) || (read_length != length())) + auto const filerr = m_file->read(buf, 0, length(), read_length); + if (filerr || (read_length != length())) purge(); else - { - // close the file because we don't need it anymore - m_file.reset(); - } + m_file.reset(); // close the file because we don't need it anymore } return core_in_memory_file::buffer(); } @@ -901,7 +706,7 @@ std::uint32_t core_osd_file::write(void const *buffer, std::uint32_t length) // do the write std::uint32_t bytes_written = 0; - osd_or_zlib_write(buffer, offset(), length, bytes_written); + m_file->write(buffer, offset(), length, bytes_written); // return the number of bytes written add_offset(bytes_written); @@ -913,19 +718,19 @@ std::uint32_t core_osd_file::write(void const *buffer, std::uint32_t length) truncate - truncate a file -------------------------------------------------*/ -osd_file::error core_osd_file::truncate(std::uint64_t offset) +std::error_condition core_osd_file::truncate(std::uint64_t offset) { if (is_loaded()) return core_in_memory_file::truncate(offset); // truncate file auto const err = m_file->truncate(offset); - if (err != osd_file::error::NONE) + if (err) return err; // and adjust to new length and offset set_length(offset); - return osd_file::error::NONE; + return std::error_condition(); } @@ -933,7 +738,7 @@ osd_file::error core_osd_file::truncate(std::uint64_t offset) flush - flush file buffers -------------------------------------------------*/ -osd_file::error core_osd_file::flush() +std::error_condition core_osd_file::flush() { if (is_loaded()) return core_in_memory_file::flush(); @@ -947,116 +752,6 @@ osd_file::error core_osd_file::flush() return m_file->flush(); } - -/*------------------------------------------------- - osd_or_zlib_read - wrapper for osd_read that - handles zlib-compressed data --------------------------------------------------*/ - -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 m_file->read(buffer, offset, length, actual); - - // if the offset doesn't match the next offset, fail - if (!m_zdata->is_nextoffset(offset)) - return osd_file::error::INVALID_ACCESS; - - // set up the destination - osd_file::error filerr = osd_file::error::NONE; - m_zdata->set_output(buffer, length); - while (!m_zdata->output_full()) - { - // if we didn't make progress, report an error or the end - if (m_zdata->has_input()) - { - auto const zerr = m_zdata->decompress(); - if (Z_OK != zerr) - { - if (Z_STREAM_END != zerr) filerr = osd_file::error::INVALID_DATA; - break; - } - } - - // fetch more data if needed - if (!m_zdata->has_input()) - { - std::uint32_t actualdata = 0; - 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; - } - } - - // adjust everything - actual = length - m_zdata->output_space(); - m_zdata->add_nextoffset(actual); - return filerr; -} - - -/*------------------------------------------------- - osd_or_zlib_write - wrapper for osd_write that - handles zlib-compressed data --------------------------------------------------*/ - -/** - * @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. - * - * @param buffer The buffer. - * @param offset The offset. - * @param length The length. - * @param [in,out] actual The actual. - * - * @return A osd_file::error. - */ - -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 m_file->write(buffer, offset, length, actual); - - // if the offset doesn't match the next offset, fail - if (!m_zdata->is_nextoffset(offset)) - return osd_file::error::INVALID_ACCESS; - - // set up the source - m_zdata->set_input(buffer, length); - while (m_zdata->has_input()) - { - // if we didn't make progress, report an error or the end - auto const zerr = m_zdata->compress(); - if (zerr != Z_OK) - { - actual = length - m_zdata->input_size(); - m_zdata->add_nextoffset(actual); - 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 = 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(); - } - } - - // we wrote everything - actual = length; - m_zdata->add_nextoffset(actual); - return osd_file::error::NONE; -} - } // anonymous namespace @@ -1070,23 +765,23 @@ osd_file::error core_osd_file::osd_or_zlib_write(void const *buffer, std::uint64 return an error code -------------------------------------------------*/ -osd_file::error core_file::open(std::string const &filename, std::uint32_t openflags, ptr &file) +std::error_condition core_file::open(std::string_view filename, std::uint32_t openflags, ptr &file) { try { // 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) + auto const filerr = osd_file::open(std::string(filename), openflags, f, length); // FIXME: allow osd_file to accept std::string_view + if (filerr) return filerr; file = std::make_unique(openflags, std::move(f), length); - return osd_file::error::NONE; + return std::error_condition(); } catch (...) { - return osd_file::error::OUT_OF_MEMORY; + return std::errc::not_enough_memory; } } @@ -1096,20 +791,20 @@ osd_file::error core_file::open(std::string const &filename, std::uint32_t openf like access and return an error code -------------------------------------------------*/ -osd_file::error core_file::open_ram(void const *data, std::size_t length, std::uint32_t openflags, ptr &file) +std::error_condition 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 osd_file::error::INVALID_ACCESS; + return std::errc::invalid_argument; try { file.reset(new core_in_memory_file(openflags, data, length, false)); - return osd_file::error::NONE; + return std::error_condition(); } catch (...) { - return osd_file::error::OUT_OF_MEMORY; + return std::errc::not_enough_memory; } } @@ -1120,24 +815,24 @@ osd_file::error core_file::open_ram(void const *data, std::size_t length, std::u error code -------------------------------------------------*/ -osd_file::error core_file::open_ram_copy(void const *data, std::size_t length, std::uint32_t openflags, ptr &file) +std::error_condition 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 osd_file::error::INVALID_ACCESS; + return std::errc::invalid_argument; try { ptr result(new core_in_memory_file(openflags, data, length, true)); if (!result->buffer()) - return osd_file::error::OUT_OF_MEMORY; + return std::errc::not_enough_memory; file = std::move(result); - return osd_file::error::NONE; + return std::error_condition(); } catch (...) { - return osd_file::error::OUT_OF_MEMORY; + return std::errc::not_enough_memory; } } @@ -1147,17 +842,14 @@ osd_file::error core_file::open_ram_copy(void const *data, std::size_t length, s object and return an error code -------------------------------------------------*/ -osd_file::error core_file::open_proxy(core_file &file, ptr &proxy) +std::error_condition core_file::open_proxy(core_file &file, ptr &proxy) { - try - { - proxy = std::make_unique(file); - return osd_file::error::NONE; - } - catch (...) - { - return osd_file::error::OUT_OF_MEMORY; - } + ptr result(new (std::nothrow) core_proxy_file(file)); + if (!result) + return std::errc::not_enough_memory; + + proxy = std::move(result); + return std::error_condition(); } @@ -1176,61 +868,64 @@ core_file::~core_file() pointer -------------------------------------------------*/ -osd_file::error core_file::load(std::string const &filename, void **data, std::uint32_t &length) +std::error_condition core_file::load(std::string_view 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 != osd_file::error::NONE) + if (err) return err; // get the size auto const size = file->size(); if (std::uint32_t(size) != size) - return osd_file::error::OUT_OF_MEMORY; + return std::errc::file_too_large; // allocate memory *data = malloc(size); + if (!*data) + return std::errc::not_enough_memory; length = std::uint32_t(size); // read the data if (file->read(*data, size) != size) { free(*data); - return osd_file::error::FAILURE; + return std::errc::io_error; // TODO: revisit this error code } // close the file and return data - return osd_file::error::NONE; + return std::error_condition(); } -osd_file::error core_file::load(std::string const &filename, std::vector &data) +std::error_condition core_file::load(std::string_view filename, std::vector &data) { ptr file; // attempt to open the file auto const err = open(filename, OPEN_FLAG_READ, file); - if (err != osd_file::error::NONE) + if (err) return err; // get the size auto const size = file->size(); if (std::uint32_t(size) != size) - return osd_file::error::OUT_OF_MEMORY; + return std::errc::file_too_large; // allocate memory - data.resize(size); + try { data.resize(size); } + catch (...) { return std::errc::not_enough_memory; } // read the data if (file->read(&data[0], size) != size) { data.clear(); - return osd_file::error::FAILURE; + return std::errc::io_error; // TODO: revisit this error code } // close the file and return data - return osd_file::error::NONE; + return std::error_condition(); } @@ -1256,7 +951,7 @@ core_file::core_file() // assumptions about path separators // ------------------------------------------------- -std::string_view core_filename_extract_base(std::string_view name, bool strip_extension) +std::string_view core_filename_extract_base(std::string_view name, bool strip_extension) noexcept { // find the start of the basename auto const start = std::find_if(name.rbegin(), name.rend(), &util::is_directory_separator); @@ -1279,7 +974,7 @@ std::string_view core_filename_extract_base(std::string_view name, bool strip_ex // core_filename_extract_extension // ------------------------------------------------- -std::string_view core_filename_extract_extension(std::string_view filename, bool strip_period) +std::string_view core_filename_extract_extension(std::string_view filename, bool strip_period) noexcept { auto loc = filename.find_last_of('.'); if (loc != std::string_view::npos) @@ -1294,7 +989,7 @@ std::string_view core_filename_extract_extension(std::string_view filename, bool // filename end with the specified extension? // ------------------------------------------------- -bool core_filename_ends_with(std::string_view filename, std::string_view extension) +bool core_filename_ends_with(std::string_view filename, std::string_view extension) noexcept { auto namelen = filename.length(); auto extlen = extension.length(); diff --git a/src/lib/util/corefile.h b/src/lib/util/corefile.h index 6aaa8f609e1..19febbb46f1 100644 --- a/src/lib/util/corefile.h +++ b/src/lib/util/corefile.h @@ -12,14 +12,13 @@ #pragma once - #include "osdfile.h" #include "strformat.h" #include #include -#include #include +#include namespace util { @@ -30,11 +29,6 @@ namespace util { #define OPEN_FLAG_NO_BOM 0x0100 /* don't output BOM */ -#define FCOMPRESS_NONE 0 /* no compression */ -#define FCOMPRESS_MIN 1 /* minimal compression */ -#define FCOMPRESS_MEDIUM 6 /* standard compression */ -#define FCOMPRESS_MAX 9 /* maximum compression */ - /*************************************************************************** TYPE DEFINITIONS @@ -49,23 +43,20 @@ public: // ----- file open/close ----- // open a file with the specified filename - static osd_file::error open(std::string const &filename, std::uint32_t openflags, ptr &file); + static std::error_condition open(std::string_view filename, std::uint32_t openflags, ptr &file); // open a RAM-based "file" using the given data and length (read-only) - static osd_file::error open_ram(const void *data, std::size_t length, std::uint32_t openflags, ptr &file); + static std::error_condition 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 osd_file::error open_ram_copy(const void *data, std::size_t length, std::uint32_t openflags, ptr &file); + static std::error_condition 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 osd_file::error open_proxy(core_file &file, ptr &proxy); + static std::error_condition 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 osd_file::error compress(int level) = 0; - // ----- file positioning ----- @@ -101,8 +92,8 @@ public: virtual const void *buffer() = 0; // open a file with the specified filename, read it into memory, and return a pointer - static osd_file::error load(std::string const &filename, void **data, std::uint32_t &length); - static osd_file::error load(std::string const &filename, std::vector &data); + static std::error_condition load(std::string_view filename, void **data, std::uint32_t &length); + static std::error_condition load(std::string_view filename, std::vector &data); // ----- file write ----- @@ -121,32 +112,16 @@ public: } // file truncation - virtual osd_file::error truncate(std::uint64_t offset) = 0; + virtual std::error_condition truncate(std::uint64_t offset) = 0; // flush file buffers - virtual osd_file::error flush() = 0; + virtual std::error_condition flush() = 0; protected: core_file(); }; - -/*************************************************************************** - INLINE FUNCTIONS -***************************************************************************/ - -// is a given character a directory separator? - -constexpr bool is_directory_separator(char c) -{ -#if defined(WIN32) - return ('\\' == c) || ('/' == c) || (':' == c); -#else - return '/' == c; -#endif -} - } // namespace util @@ -157,13 +132,13 @@ constexpr bool is_directory_separator(char c) /* ----- filename utilities ----- */ // extract the base part of a filename (remove extensions and paths) -std::string_view core_filename_extract_base(std::string_view name, bool strip_extension = false); +std::string_view core_filename_extract_base(std::string_view name, bool strip_extension = false) noexcept; // extracts the file extension from a filename -std::string_view core_filename_extract_extension(std::string_view filename, bool strip_period = false); +std::string_view core_filename_extract_extension(std::string_view filename, bool strip_period = false) noexcept; // true if the given filename ends with a particular extension -bool core_filename_ends_with(std::string_view filename, std::string_view extension); +bool core_filename_ends_with(std::string_view filename, std::string_view extension) noexcept; #endif // MAME_LIB_UTIL_COREFILE_H diff --git a/src/lib/util/harddisk.cpp b/src/lib/util/harddisk.cpp index e91759c44f2..2e8d14f9a8a 100644 --- a/src/lib/util/harddisk.cpp +++ b/src/lib/util/harddisk.cpp @@ -8,11 +8,13 @@ ***************************************************************************/ -#include #include "harddisk.h" -#include "osdcore.h" + +#include "corefile.h" + #include + /*************************************************************************** TYPE DEFINITIONS ***************************************************************************/ @@ -40,7 +42,7 @@ hard_disk_file *hard_disk_open(chd_file *chd) int cylinders, heads, sectors, sectorbytes; hard_disk_file *file; std::string metadata; - chd_error err; + std::error_condition err; /* punt if no CHD */ if (chd == nullptr) @@ -48,7 +50,7 @@ hard_disk_file *hard_disk_open(chd_file *chd) /* read the hard disk metadata */ err = chd->read_metadata(HARD_DISK_METADATA_TAG, 0, metadata); - if (err != CHDERR_NONE) + if (err) return nullptr; /* parse the metadata */ @@ -177,8 +179,8 @@ uint32_t hard_disk_read(hard_disk_file *file, uint32_t lbasector, void *buffer) { if (file->chd) { - chd_error err = file->chd->read_units(lbasector, buffer); - return (err == CHDERR_NONE); + std::error_condition err = file->chd->read_units(lbasector, buffer); + return !err; } else { @@ -211,8 +213,8 @@ uint32_t hard_disk_write(hard_disk_file *file, uint32_t lbasector, const void *b { if (file->chd) { - chd_error err = file->chd->write_units(lbasector, buffer); - return (err == CHDERR_NONE); + std::error_condition err = file->chd->write_units(lbasector, buffer); + return !err; } else { diff --git a/src/lib/util/harddisk.h b/src/lib/util/harddisk.h index 2a4b727e7e7..e6fae165f19 100644 --- a/src/lib/util/harddisk.h +++ b/src/lib/util/harddisk.h @@ -8,13 +8,15 @@ ***************************************************************************/ -#ifndef MAME_UTIL_HARDDISK_H -#define MAME_UTIL_HARDDISK_H +#ifndef MAME_LIB_UTIL_HARDDISK_H +#define MAME_LIB_UTIL_HARDDISK_H #pragma once -#include "osdcore.h" #include "chd.h" +#include "utilfwd.h" + +#include "osdcore.h" /*************************************************************************** @@ -49,4 +51,4 @@ hard_disk_info *hard_disk_get_info(hard_disk_file *file); uint32_t hard_disk_read(hard_disk_file *file, uint32_t lbasector, void *buffer); uint32_t hard_disk_write(hard_disk_file *file, uint32_t lbasector, const void *buffer); -#endif // MAME_UTIL_HARDDISK_H +#endif // MAME_LIB_UTIL_HARDDISK_H diff --git a/src/lib/util/ioprocs.cpp b/src/lib/util/ioprocs.cpp new file mode 100644 index 00000000000..1f52a3daf97 --- /dev/null +++ b/src/lib/util/ioprocs.cpp @@ -0,0 +1,1248 @@ +// license:BSD-3-Clause +// copyright-holders:Vas Crabb +/*************************************************************************** + + ioprocs.h + + I/O interfaces + +***************************************************************************/ + +#include "ioprocs.h" + +#include "corefile.h" +#include "ioprocsfill.h" + +#include "osdfile.h" + +#include +#include +#include +#include +#include +#include +#include + + +namespace util { + +namespace { + +// helper for holding a block of memory and deallocating it (or not) as necessary + +template +class ram_adapter_base : public virtual random_access +{ +public: + virtual ~ram_adapter_base() + { + if constexpr (Owned) + std::free(m_data); + } + + virtual std::error_condition seek(std::int64_t offset, int whence) noexcept override + { + switch (whence) + { + case SEEK_SET: + if (0 > offset) + return std::errc::invalid_argument; + m_pointer = std::uint64_t(offset); + return std::error_condition(); + + case SEEK_CUR: + if (0 > offset) + { + if (std::uint64_t(-offset) > m_pointer) + return std::errc::invalid_argument; + } + else if ((std::numeric_limits::max() - offset) < m_pointer) + { + return std::errc::invalid_argument; + } + m_pointer += offset; + return std::error_condition(); + + case SEEK_END: + if (0 > offset) + { + if (std::uint64_t(-offset) > m_size) + return std::errc::invalid_argument; + } + else if ((std::numeric_limits::max() - offset) < m_size) + { + return std::errc::invalid_argument; + } + m_pointer = std::uint64_t(m_size) + offset; + return std::error_condition(); + + default: + return std::errc::invalid_argument; + } + } + + virtual std::error_condition tell(std::uint64_t &result) noexcept override + { + result = m_pointer; + return std::error_condition(); + } + + virtual std::error_condition length(std::uint64_t &result) noexcept override + { + if (std::numeric_limits::max() < m_size) + return std::errc::file_too_large; + + result = m_size; + return std::error_condition(); + } + +protected: + template + ram_adapter_base(U *data, std::size_t size) noexcept : m_data(reinterpret_cast(data)), m_size(size) + { + static_assert(sizeof(*m_data) == 1U, "Element type must be byte-sized"); + assert(m_data || !m_size); + } + + T m_data; + std::uint64_t m_pointer = 0U; + std::size_t m_size; +}; + + +// RAM read implementation + +template +class ram_read_adapter : public ram_adapter_base, public virtual random_read +{ +public: + template + ram_read_adapter(U *data, std::size_t size) noexcept : ram_adapter_base(data, size) + { + } + + virtual std::error_condition read(void *buffer, std::size_t length, std::size_t &actual) noexcept override + { + do_read(this->m_pointer, buffer, length, actual); + this->m_pointer += actual; + return std::error_condition(); + } + + virtual std::error_condition read_at(std::uint64_t offset, void *buffer, std::size_t length, std::size_t &actual) noexcept override + { + do_read(offset, buffer, length, actual); + return std::error_condition(); + } + +private: + void do_read(std::uint64_t offset, void *buffer, std::size_t length, std::size_t &actual) const noexcept + { + if ((offset < this->m_size) && length) + { + actual = std::min(std::size_t(this->m_size - offset), length); + if constexpr (Owned) + std::memcpy(buffer, this->m_data + offset, actual); + else + std::memmove(buffer, this->m_data + offset, actual); + } + else + { + actual = 0U; + } + } +}; + + +// helper for holding a stdio FILE and closing it (or not) as necessary + +class stdio_adapter_base : public virtual random_access +{ +public: + virtual ~stdio_adapter_base() + { + if (m_close) + std::fclose(m_file); + } + + virtual std::error_condition seek(std::int64_t offset, int whence) noexcept override + { + if ((std::numeric_limits::max() < offset) || (std::numeric_limits::min() > offset)) + return std::errc::invalid_argument; + else if (!std::fseek(m_file, long(offset), whence)) + return std::error_condition(); + else + return std::error_condition(errno, std::generic_category()); + } + + virtual std::error_condition tell(std::uint64_t &result) noexcept override + { + long const pos = std::ftell(m_file); + if (0 > pos) + return std::error_condition(errno, std::generic_category()); + result = static_cast(pos); + return std::error_condition(); + } + + virtual std::error_condition length(std::uint64_t &result) noexcept override + { + std::fpos_t oldpos; + if (std::fgetpos(m_file, &oldpos)) + return std::error_condition(errno, std::generic_category()); + + long endpos = -1; + if (!std::fseek(m_file, 0, SEEK_END)) + { + m_dangling_read = m_dangling_write = false; + endpos = std::ftell(m_file); + } + std::error_condition err; + if (0 > endpos) + err.assign(errno, std::generic_category()); + else if (std::numeric_limits::max() < static_cast(endpos)) + err = std::errc::file_too_large; + else + result = static_cast(endpos); + + if (!std::fsetpos(m_file, &oldpos)) + m_dangling_read = m_dangling_write = false; + else if (!err) + err.assign(errno, std::generic_category()); + + return err; + } + +protected: + stdio_adapter_base(FILE *file, bool close) noexcept : m_file(file), m_close(close) + { + assert(m_file); + } + + FILE *file() noexcept + { + return m_file; + } + +private: + FILE *const m_file; + bool const m_close; + +protected: + bool m_dangling_read = true, m_dangling_write = true; +}; + + +// stdio read implementation + +class stdio_read_adapter : public stdio_adapter_base, public virtual random_read +{ +public: + stdio_read_adapter(FILE *file, bool close) noexcept : stdio_adapter_base(file, close) + { + } + + virtual std::error_condition read(void *buffer, std::size_t length, std::size_t &actual) noexcept override + { + if (m_dangling_write) + { + if (std::fflush(file())) + { + std::clearerr(file()); + actual = 0U; + return std::error_condition(errno, std::generic_category()); + } + m_dangling_write = false; + } + + actual = std::fread(buffer, sizeof(std::uint8_t), length, file()); + m_dangling_read = true; + if (length != actual) + { + if (std::ferror(file())) + { + std::clearerr(file()); + return std::error_condition(errno, std::generic_category()); + } + else if (std::feof(file())) + { + m_dangling_read = false; + } + } + + return std::error_condition(); + } + + virtual std::error_condition read_at(std::uint64_t offset, void *buffer, std::size_t length, std::size_t &actual) noexcept override + { + actual = 0U; + + if (static_cast(std::numeric_limits::max()) < offset) + return std::errc::invalid_argument; + + std::fpos_t oldpos; + if (std::fgetpos(file(), &oldpos)) + return std::error_condition(errno, std::generic_category()); + + std::error_condition err; + if (std::fseek(file(), long(static_cast(offset)), SEEK_SET)) + { + err.assign(errno, std::generic_category()); + } + else + { + m_dangling_write = false; + actual = std::fread(buffer, sizeof(std::uint8_t), length, file()); + m_dangling_read = true; + if (length != actual) + { + if (std::ferror(file())) + { + err.assign(errno, std::generic_category()); + std::clearerr(file()); + } + else if (std::feof(file())) + { + m_dangling_read = false; + } + } + } + + if (!std::fsetpos(file(), &oldpos)) + m_dangling_read = m_dangling_write = false; + else if (!err) + err.assign(errno, std::generic_category()); + + return err; + } +}; + + +// stdio read/write implementation + +class stdio_read_write_adapter : public stdio_read_adapter, public random_read_write +{ +public: + using stdio_read_adapter::stdio_read_adapter; + + virtual std::error_condition finalize() noexcept override + { + return std::error_condition(); + } + + virtual std::error_condition flush() noexcept override + { + if (std::fflush(file())) + { + std::clearerr(file()); + return std::error_condition(errno, std::generic_category()); + } + m_dangling_write = false; + return std::error_condition(); + } + + virtual std::error_condition write(void const *buffer, std::size_t length, std::size_t &actual) noexcept override + { + if (m_dangling_read) + { + if (std::fseek(file(), 0, SEEK_CUR)) + { + actual = 0U; + return std::error_condition(errno, std::generic_category()); + } + m_dangling_read = false; + } + + actual = std::fwrite(buffer, sizeof(std::uint8_t), length, file()); + m_dangling_write = true; + if (length != actual) + { + std::clearerr(file()); + return std::error_condition(errno, std::generic_category()); + } + + return std::error_condition(); + } + + virtual std::error_condition write_at(std::uint64_t offset, void const *buffer, std::size_t length, std::size_t &actual) noexcept override + { + actual = 0U; + + if (static_cast(std::numeric_limits::max()) < offset) + return std::errc::invalid_argument; + + std::fpos_t oldpos; + if (std::fgetpos(file(), &oldpos)) + return std::error_condition(errno, std::generic_category()); + + std::error_condition err; + if (std::fseek(file(), long(static_cast(offset)), SEEK_SET)) + { + err.assign(errno, std::generic_category()); + } + else + { + m_dangling_read = false; + actual = std::fwrite(buffer, sizeof(std::uint8_t), length, file()); + m_dangling_write = true; + if (length != actual) + { + err.assign(errno, std::generic_category()); + std::clearerr(file()); + } + } + + if (!std::fsetpos(file(), &oldpos)) + m_dangling_read = m_dangling_write = false; + else if (!err) + err.assign(errno, std::generic_category()); + + return err; + } +}; + + +// stdio helper that fills space when writing past the end-of-file + +class stdio_read_write_filler : public random_read_fill_wrapper +{ +public: + stdio_read_write_filler(FILE *file, bool close, std::uint8_t fill) noexcept : random_read_fill_wrapper(file, close) + { + set_filler(fill); + } + + virtual std::error_condition write(void const *buffer, std::size_t length, std::size_t &actual) noexcept override + { + actual = 0U; + + long const offset = std::ftell(file()); + if (0 > offset) + return std::error_condition(errno, std::generic_category()); + + if (std::fseek(file(), 0, SEEK_END)) + { + std::error_condition err(errno, std::generic_category()); + if (!std::fseek(file(), offset, SEEK_SET)) + m_dangling_read = m_dangling_write = false; + return err; + } + m_dangling_read = m_dangling_write = false; + long endpos = std::ftell(file()); + if (0 > endpos) + { + std::error_condition err(errno, std::generic_category()); + std::fseek(file(), offset, SEEK_SET); + return err; + } + + if (offset > endpos) + { + std::uint8_t block[1024]; + std::fill_n( + block, + std::min >(std::size(block), offset - endpos), + get_filler()); + do + { + std::size_t const chunk = std::min >(std::size(block), offset - endpos); + std::size_t const filled = std::fwrite(block, sizeof(block[0]), chunk, file()); + endpos += filled; + m_dangling_write = true; + if (chunk != filled) + { + std::error_condition err(errno, std::generic_category()); + std::clearerr(file()); + if (!std::fseek(file(), offset, SEEK_SET)) + m_dangling_write = false; + return err; + } + } + while (static_cast(endpos) < offset); + } + else if ((offset < endpos) && std::fseek(file(), offset, SEEK_SET)) + { + return std::error_condition(errno, std::generic_category()); + } + + actual = std::fwrite(buffer, sizeof(std::uint8_t), length, file()); + m_dangling_write = true; + if (length != actual) + { + std::clearerr(file()); + return std::error_condition(errno, std::generic_category()); + } + + return std::error_condition(); + } + + virtual std::error_condition write_at(std::uint64_t offset, void const *buffer, std::size_t length, std::size_t &actual) noexcept override + { + actual = 0U; + + if (static_cast(std::numeric_limits::max()) < offset) + return std::errc::invalid_argument; + + std::fpos_t oldpos; + if (std::fgetpos(file(), &oldpos)) + return std::error_condition(errno, std::generic_category()); + + std::error_condition err; + if (std::fseek(file(), 0, SEEK_END)) + { + err.assign(errno, std::generic_category()); + } + else + { + m_dangling_read = m_dangling_write = false; + long endpos = std::ftell(file()); + if (0 > endpos) + { + err.assign(errno, std::generic_category()); + } + else if (static_cast(endpos) > offset) + { + if (std::fseek(file(), long(static_cast(offset)), SEEK_SET)) + err.assign(errno, std::generic_category()); + } + else if (static_cast(endpos) < offset) + { + std::uint8_t block[1024]; + std::fill_n( + block, + std::min >(std::size(block), offset - endpos), + get_filler()); + do + { + std::size_t const chunk = std::min >(std::size(block), offset - endpos); + std::size_t const filled = std::fwrite(block, sizeof(block[0]), chunk, file()); + endpos += filled; + m_dangling_write = true; + if (chunk != filled) + { + err.assign(errno, std::generic_category()); + std::clearerr(file()); + } + } + while (!err && (static_cast(endpos) < offset)); + } + } + + if (!err) + { + actual = std::fwrite(buffer, sizeof(std::uint8_t), length, file()); + m_dangling_write = true; + if (length != actual) + { + err.assign(errno, std::generic_category()); + std::clearerr(file()); + } + } + + if (!std::fsetpos(file(), &oldpos)) + m_dangling_read = m_dangling_write = false; + else if (!err) + err.assign(errno, std::generic_category()); + + return err; + } +}; + + +// helper class for holding an osd_file and closing it (or not) as necessary + +class osd_file_adapter_base : public virtual random_access +{ +public: + virtual ~osd_file_adapter_base() + { + if (m_close) + delete m_file; + } + + virtual std::error_condition seek(std::int64_t offset, int whence) noexcept override + { + switch (whence) + { + case SEEK_SET: + if (0 > offset) + return std::errc::invalid_argument; + m_pointer = std::uint64_t(offset); + return std::error_condition(); + + case SEEK_CUR: + if (0 > offset) + { + if (std::uint64_t(-offset) > m_pointer) + return std::errc::invalid_argument; + } + else if ((std::numeric_limits::max() - offset) < m_pointer) + { + return std::errc::invalid_argument; + } + m_pointer += offset; + return std::error_condition(); + + // TODO: add SEEK_END when osd_file can support it - should it return a different error? + default: + return std::errc::invalid_argument; + } + } + + virtual std::error_condition tell(std::uint64_t &result) noexcept override + { + result = m_pointer; + return std::error_condition(); + } + + virtual std::error_condition length(std::uint64_t &result) noexcept override + { + // not supported by osd_file + return std::errc::not_supported; // TODO: revisit this error code + } + +protected: + osd_file_adapter_base(osd_file::ptr &&file) noexcept : m_file(file.release()), m_close(true) + { + assert(m_file); + } + + osd_file_adapter_base(osd_file &file) noexcept : m_file(&file), m_close(false) + { + } + + osd_file &file() noexcept + { + return *m_file; + } + + std::uint64_t m_pointer = 0U; + +private: + osd_file *const m_file; + bool const m_close; +}; + + +// osd_file read implementation + +class osd_file_read_adapter : public osd_file_adapter_base, public virtual random_read +{ +public: + osd_file_read_adapter(osd_file::ptr &&file) noexcept : osd_file_adapter_base(std::move(file)) + { + } + + osd_file_read_adapter(osd_file &file) noexcept : osd_file_adapter_base(file) + { + } + + virtual std::error_condition read(void *buffer, std::size_t length, std::size_t &actual) noexcept override + { + // TODO: should the client have to deal with reading less than expected even if EOF isn't hit? + if (std::numeric_limits::max() < length) + { + actual = 0U; + return std::errc::invalid_argument; + } + + // actual length not valid on error + std::uint32_t count; + std::error_condition err = file().read(buffer, m_pointer, std::uint32_t(length), count); + if (!err) + { + m_pointer += count; + actual = std::size_t(count); + } + else + { + actual = 0U; + } + return err; + } + + virtual std::error_condition read_at(std::uint64_t offset, void *buffer, std::size_t length, std::size_t &actual) noexcept override + { + // TODO: should the client have to deal with reading less than expected even if EOF isn't hit? + if (std::numeric_limits::max() < length) + { + actual = 0U; + return std::errc::invalid_argument; + } + + // actual length not valid on error + std::uint32_t count; + std::error_condition err = file().read(buffer, offset, std::uint32_t(length), count); + if (!err) + actual = std::size_t(count); + else + actual = 0U; + return err; + } +}; + + +// osd_file read/write implementation + +class osd_file_read_write_adapter : public osd_file_read_adapter, public random_read_write +{ +public: + using osd_file_read_adapter::osd_file_read_adapter; + + virtual std::error_condition finalize() noexcept override + { + return std::error_condition(); + } + + virtual std::error_condition flush() noexcept override + { + return file().flush(); + } + + virtual std::error_condition write(void const *buffer, std::size_t length, std::size_t &actual) noexcept override + { + actual = 0U; + while (length) + { + // actual length not valid on error + std::uint32_t const chunk = std::min >(std::numeric_limits::max(), length); + std::uint32_t written; + std::error_condition err = file().write(buffer, m_pointer, chunk, written); + if (err) + return err; + m_pointer += written; + buffer = reinterpret_cast(buffer) + written; + length -= written; + actual += written; + } + return std::error_condition(); + } + + virtual std::error_condition write_at(std::uint64_t offset, void const *buffer, std::size_t length, std::size_t &actual) noexcept override + { + actual = 0U; + while (length) + { + // actual length not valid on error + std::uint32_t const chunk = std::min >(std::numeric_limits::max(), length); + std::uint32_t written; + std::error_condition err = file().write(buffer, offset, chunk, written); + if (err) + return err; + offset += written; + buffer = reinterpret_cast(buffer) + written; + length -= written; + actual += written; + } + return std::error_condition(); + } +}; + + +// helper class for holding a core_file and closing it (or not) as necessary + +class core_file_adapter_base : public virtual random_access +{ +public: + virtual ~core_file_adapter_base() + { + if (m_close) + delete m_file; + } + + virtual std::error_condition seek(std::int64_t offset, int whence) noexcept override + { + if (!m_file->seek(offset, whence)) + return std::error_condition(); + else + return std::errc::invalid_argument; // TODO: better error reporting for core_file + } + + virtual std::error_condition tell(std::uint64_t &result) noexcept override + { + // no error reporting + result = m_file->tell(); + return std::error_condition(); + } + + virtual std::error_condition length(std::uint64_t &result) noexcept override + { + // no error reporting + result = m_file->size(); + return std::error_condition(); + } + +protected: + core_file_adapter_base(core_file::ptr &&file) noexcept : m_file(file.release()), m_close(true) + { + assert(m_file); + } + + core_file_adapter_base(core_file &file) noexcept : m_file(&file), m_close(false) + { + } + + core_file &file() noexcept + { + return *m_file; + } + +private: + core_file *const m_file; + bool const m_close; +}; + + +// core_file read implementation + +class core_file_read_adapter : public core_file_adapter_base, public virtual random_read +{ +public: + core_file_read_adapter(core_file::ptr &&file) noexcept : core_file_adapter_base(std::move(file)) + { + } + + core_file_read_adapter(core_file &file) noexcept : core_file_adapter_base(file) + { + } + + virtual std::error_condition read(void *buffer, std::size_t length, std::size_t &actual) noexcept override + { + // TODO: should the client have to deal with reading less than expected even if EOF isn't hit? + if (std::numeric_limits::max() < length) + { + actual = 0U; + return std::errc::invalid_argument; + } + + // no way to distinguish between EOF and error + actual = file().read(buffer, std::uint32_t(length)); + return std::error_condition(); + } + + virtual std::error_condition read_at(std::uint64_t offset, void *buffer, std::size_t length, std::size_t &actual) noexcept override + { + actual = 0U; + + // TODO: should the client have to deal with reading less than expected even if EOF isn't hit? + if (std::numeric_limits::max() < length) + return std::errc::invalid_argument; + + // no error reporting for tell + std::uint64_t const oldpos = file().tell(); + if (file().seek(offset, SEEK_SET)) + { + file().seek(oldpos, SEEK_SET); + return std::errc::invalid_argument; // TODO: better error reporting for core_file + } + + // no way to distinguish between EOF and error + actual = file().read(buffer, std::uint32_t(length)); + + if (!file().seek(oldpos, SEEK_SET)) + return std::error_condition(); + else + return std::errc::invalid_argument; // TODO: better error reporting for core_file + } +}; + + +// core_file read/write implementation + +class core_file_read_write_adapter : public core_file_read_adapter, public random_read_write +{ +public: + using core_file_read_adapter::core_file_read_adapter; + + virtual std::error_condition finalize() noexcept override + { + return std::error_condition(); + } + + virtual std::error_condition flush() noexcept override + { + return file().flush(); + } + + virtual std::error_condition write(void const *buffer, std::size_t length, std::size_t &actual) noexcept override + { + actual = 0U; + while (length) + { + std::uint32_t const chunk = std::min >(std::numeric_limits::max(), length); + std::uint32_t const written = file().write(buffer, chunk); + actual += written; + if (written < chunk) + return std::errc::io_error; // TODO: better error reporting for core_file + buffer = reinterpret_cast(buffer) + written; + length -= written; + } + return std::error_condition(); + } + + virtual std::error_condition write_at(std::uint64_t offset, void const *buffer, std::size_t length, std::size_t &actual) noexcept override + { + actual = 0U; + + // no error reporting for tell + std::uint64_t const oldpos = file().tell(); + if (file().seek(offset, SEEK_SET)) + { + file().seek(oldpos, SEEK_SET); + return std::errc::invalid_argument; // TODO: better error reporting for core_file + } + + std::error_condition err; + while (!err && length) + { + std::uint32_t const chunk = std::min >(std::numeric_limits::max(), length); + std::uint32_t const written = file().write(buffer, chunk); + actual += written; + if (written < chunk) + { + err = std::errc::io_error; // TODO: better error reporting for core_file + } + else + { + buffer = reinterpret_cast(buffer) + written; + length -= written; + } + } + + if (!file().seek(oldpos, SEEK_SET) || err) + return err; + else + return std::errc::invalid_argument; // TODO: better error reporting for core_file + } +}; + + +// core_file helper that fills space when writing past the end-of-file + +class core_file_read_write_filler : public random_read_fill_wrapper +{ +public: + core_file_read_write_filler(core_file::ptr &&file, std::uint8_t fill) noexcept : random_read_fill_wrapper(std::move(file)) + { + set_filler(fill); + } + + core_file_read_write_filler(core_file &file, std::uint8_t fill) noexcept : random_read_fill_wrapper(file) + { + set_filler(fill); + } + + virtual std::error_condition write(void const *buffer, std::size_t length, std::size_t &actual) noexcept override + { + // no error reporting for tell or size + std::uint64_t const offset = file().tell(); + std::uint64_t endpos = file().size(); + if (endpos < offset) + { + if (file().seek(endpos, SEEK_SET)) + { + file().seek(offset, SEEK_SET); + actual = 0U; + return std::errc::invalid_argument; // TODO: better error reporting for core_file + } + std::uint8_t block[1024]; + std::fill_n( + block, + std::min >(std::size(block), offset - endpos), + get_filler()); + do + { + std::uint32_t const chunk = std::min >(sizeof(block), offset - endpos); + std::uint32_t const filled = file().write(block, chunk); + endpos += filled; + if (chunk != filled) + { + file().seek(offset, SEEK_SET); + actual = 0U; + return std::errc::io_error; // TODO: better error reporting for core_file + } + } + while (endpos < offset); + } + + return core_file_read_write_adapter::write(buffer, length, actual); + } + + virtual std::error_condition write_at(std::uint64_t offset, void const *buffer, std::size_t length, std::size_t &actual) noexcept override + { + actual = 0U; + + // no error reporting for tell + std::uint64_t const oldpos = file().tell(); + if (file().seek(0, SEEK_END)) + { + file().seek(oldpos, SEEK_SET); + return std::errc::invalid_argument; // TODO: better error reporting for core_file + } + std::uint64_t endpos = file().tell(); + + std::error_condition err; + if (endpos > offset) + { + if (file().seek(offset, SEEK_SET)) + err = std::errc::invalid_argument; // TODO: better error reporting for core_file + } + else if (endpos < offset) + { + std::uint8_t block[1024]; + std::fill_n( + block, + std::min >(std::size(block), offset - endpos), + get_filler()); + do + { + std::uint32_t const chunk = std::min >(sizeof(block), offset - endpos); + std::uint32_t const filled = file().write(block, chunk); + endpos += filled; + if (chunk != filled) + err = std::errc::io_error; // TODO: better error reporting for core_file + } + while (!err && (endpos < offset)); + } + + while (!err && length) + { + std::uint32_t const chunk = std::min >(std::numeric_limits::max(), length); + std::uint32_t const written = file().write(buffer, chunk); + actual += written; + if (written < chunk) + { + err = std::errc::io_error; // TODO: better error reporting for core_file + } + else + { + buffer = reinterpret_cast(buffer) + written; + length -= written; + } + } + + if (!file().seek(oldpos, SEEK_SET) || err) + return err; + else + return std::errc::invalid_argument; // TODO: better error reporting for core_file + } +}; + +} // anonymous namespace + + +// creating RAM read adapters + +random_read::ptr ram_read(void const *data, std::size_t size) noexcept +{ + random_read::ptr result; + if (data || !size) + result.reset(new (std::nothrow) ram_read_adapter(data, size)); + return result; +} + +random_read::ptr ram_read(void const *data, std::size_t size, std::uint8_t filler) noexcept +{ + std::unique_ptr > > result; + if (data || !size) + result.reset(new (std::nothrow) decltype(result)::element_type(data, size)); + if (result) + result->set_filler(filler); + return result; +} + +random_read::ptr ram_read_copy(void const *data, std::size_t size) noexcept +{ + random_read::ptr result; + void *const copy = size ? std::malloc(size) : nullptr; + if (copy) + std::memcpy(copy, data, size); + if (copy || !size) + result.reset(new (std::nothrow) ram_read_adapter(copy, size)); + if (!result) + std::free(copy); + return result; +} + +random_read::ptr ram_read_copy(void const *data, std::size_t size, std::uint8_t filler) noexcept +{ + std::unique_ptr > > result; + void *const copy = size ? std::malloc(size) : nullptr; + if (copy) + std::memcpy(copy, data, size); + if (copy || !size) + result.reset(new (std::nothrow) decltype(result)::element_type(copy, size)); + if (!result) + std::free(copy); + return result; +} + + +// creating stdio read adapters + +random_read::ptr stdio_read(FILE *file) noexcept +{ + random_read::ptr result; + if (file) + result.reset(new (std::nothrow) stdio_read_adapter(file, true)); + return result; +} + +random_read::ptr stdio_read(FILE *file, std::uint8_t filler) noexcept +{ + std::unique_ptr > result; + if (file) + result.reset(new (std::nothrow) decltype(result)::element_type(file, true)); + if (result) + result->set_filler(filler); + return result; +} + +random_read::ptr stdio_read_noclose(FILE *file) noexcept +{ + random_read::ptr result; + if (file) + result.reset(new (std::nothrow) stdio_read_adapter(file, false)); + return result; +} + +random_read::ptr stdio_read_noclose(FILE *file, std::uint8_t filler) noexcept +{ + std::unique_ptr > result; + if (file) + result.reset(new (std::nothrow) decltype(result)::element_type(file, false)); + if (result) + result->set_filler(filler); + return result; +} + + +// creating stdio read/write adapters + +random_read_write::ptr stdio_read_write(FILE *file) noexcept +{ + random_read_write::ptr result; + if (file) + result.reset(new (std::nothrow) stdio_read_write_adapter(file, true)); + return result; +} + +random_read_write::ptr stdio_read_write(FILE *file, std::uint8_t filler) noexcept +{ + random_read_write::ptr result; + if (file) + result.reset(new (std::nothrow) stdio_read_write_filler(file, true, filler)); + return result; +} + +random_read_write::ptr stdio_read_write_noclose(FILE *file) noexcept +{ + random_read_write::ptr result; + if (file) + result.reset(new (std::nothrow) stdio_read_write_adapter(file, false)); + return result; +} + +random_read_write::ptr stdio_read_write_noclose(FILE *file, std::uint8_t filler) noexcept +{ + random_read_write::ptr result; + if (file) + result.reset(new (std::nothrow) stdio_read_write_filler(file, false, filler)); + return result; +} + + +// creating osd_file read adapters + +random_read::ptr osd_file_read(osd_file::ptr &&file) noexcept +{ + random_read::ptr result; + if (file) + result.reset(new (std::nothrow) osd_file_read_adapter(std::move(file))); + return result; +} + +random_read::ptr osd_file_read(osd_file &file) noexcept +{ + return random_read::ptr(new (std::nothrow) osd_file_read_adapter(file)); +} + + +// creating osd_file read/write adapters + +random_read_write::ptr osd_file_read_write(osd_file::ptr &&file) noexcept +{ + random_read_write::ptr result; + if (file) + result.reset(new (std::nothrow) osd_file_read_write_adapter(std::move(file))); + return result; +} + +random_read_write::ptr osd_file_read_write(osd_file &file) noexcept +{ + return random_read_write::ptr(new (std::nothrow) osd_file_read_write_adapter(file)); +} + + +// creating core_file read adapters + +random_read::ptr core_file_read(core_file::ptr &&file) noexcept +{ + random_read::ptr result; + if (file) + result.reset(new (std::nothrow) core_file_read_adapter(std::move(file))); + return result; +} + +random_read::ptr core_file_read(core_file::ptr &&file, std::uint8_t filler) noexcept +{ + std::unique_ptr > result; + if (file) + result.reset(new (std::nothrow) decltype(result)::element_type(std::move(file))); + if (result) + result->set_filler(filler); + return result; +} + +random_read::ptr core_file_read(core_file &file) noexcept +{ + return random_read::ptr(new (std::nothrow) core_file_read_adapter(file)); +} + +random_read::ptr core_file_read(core_file &file, std::uint8_t filler) noexcept +{ + std::unique_ptr > result; + result.reset(new (std::nothrow) decltype(result)::element_type(file)); + if (result) + result->set_filler(filler); + return result; +} + + +// creating core_file read/write adapters + +random_read_write::ptr core_file_read_write(core_file::ptr &&file) noexcept +{ + random_read_write::ptr result; + if (file) + result.reset(new (std::nothrow) core_file_read_write_adapter(std::move(file))); + return result; +} + +random_read_write::ptr core_file_read_write(core_file::ptr &&file, std::uint8_t filler) noexcept +{ + random_read_write::ptr result; + if (file) + result.reset(new (std::nothrow) core_file_read_write_filler(std::move(file), filler)); + return result; +} + +random_read_write::ptr core_file_read_write(core_file &file) noexcept +{ + return random_read_write::ptr(new (std::nothrow) core_file_read_write_adapter(file)); +} + +random_read_write::ptr core_file_read_write(core_file &file, std::uint8_t filler) noexcept +{ + return random_read_write::ptr(new (std::nothrow) core_file_read_write_filler(file, filler)); +} + +} // namespace util diff --git a/src/lib/util/ioprocs.h b/src/lib/util/ioprocs.h new file mode 100644 index 00000000000..78c06e71318 --- /dev/null +++ b/src/lib/util/ioprocs.h @@ -0,0 +1,130 @@ +// license:BSD-3-Clause +// copyright-holders:Vas Crabb +/*************************************************************************** + + ioprocs.h + + I/O interfaces + +***************************************************************************/ +#ifndef MAME_LIB_UTIL_IOPROCS_H +#define MAME_LIB_UTIL_IOPROCS_H + +#pragma once + +#include "utilfwd.h" + +#include +#include +#include +#include +#include + + +// FIXME: make a proper place for OSD forward declarations +class osd_file; + + +namespace util { + +class read_stream +{ +public: + using ptr = std::unique_ptr; + + virtual ~read_stream() = default; + + virtual std::error_condition read(void *buffer, std::size_t length, std::size_t &actual) noexcept = 0; +}; + + +class write_stream +{ +public: + using ptr = std::unique_ptr; + + virtual ~write_stream() = default; + + virtual std::error_condition finalize() noexcept = 0; + virtual std::error_condition flush() noexcept = 0; + virtual std::error_condition write(void const *buffer, std::size_t length, std::size_t &actual) noexcept = 0; +}; + + +class read_write_stream : public virtual read_stream, public virtual write_stream +{ +public: + using ptr = std::unique_ptr; +}; + + +class random_access +{ +public: + virtual ~random_access() = default; + + virtual std::error_condition seek(std::int64_t offset, int whence) noexcept = 0; + virtual std::error_condition tell(std::uint64_t &result) noexcept = 0; + virtual std::error_condition length(std::uint64_t &result) noexcept = 0; +}; + + +class random_read : public virtual read_stream, public virtual random_access +{ +public: + using ptr = std::unique_ptr; + + virtual std::error_condition read_at(std::uint64_t offset, void *buffer, std::size_t length, std::size_t &actual) noexcept = 0; +}; + + +class random_write : public virtual write_stream, public virtual random_access +{ +public: + using ptr = std::unique_ptr; + + virtual std::error_condition write_at(std::uint64_t offset, void const *buffer, std::size_t length, std::size_t &actual) noexcept = 0; +}; + + +class random_read_write : public read_write_stream, public virtual random_read, public virtual random_write +{ +public: + using ptr = std::unique_ptr; +}; + + +random_read::ptr ram_read(void const *data, std::size_t size) noexcept; +random_read::ptr ram_read(void const *data, std::size_t size, std::uint8_t filler) noexcept; +random_read::ptr ram_read_copy(void const *data, std::size_t size) noexcept; +random_read::ptr ram_read_copy(void const *data, std::size_t size, std::uint8_t filler) noexcept; + +random_read::ptr stdio_read(FILE *file) noexcept; +random_read::ptr stdio_read(FILE *file, std::uint8_t filler) noexcept; +random_read::ptr stdio_read_noclose(FILE *file) noexcept; +random_read::ptr stdio_read_noclose(FILE *file, std::uint8_t filler) noexcept; + +random_read_write::ptr stdio_read_write(FILE *file) noexcept; +random_read_write::ptr stdio_read_write(FILE *file, std::uint8_t filler) noexcept; +random_read_write::ptr stdio_read_write_noclose(FILE *file) noexcept; +random_read_write::ptr stdio_read_write_noclose(FILE *file, std::uint8_t filler) noexcept; + +random_read::ptr osd_file_read(std::unique_ptr &&file) noexcept; +random_read::ptr osd_file_read(osd_file &file) noexcept; + +random_read_write::ptr osd_file_read_write(std::unique_ptr &&file) noexcept; +random_read_write::ptr osd_file_read_write(osd_file &file) noexcept; + +random_read::ptr core_file_read(std::unique_ptr &&file) noexcept; +random_read::ptr core_file_read(std::unique_ptr &&file, std::uint8_t filler) noexcept; +random_read::ptr core_file_read(core_file &file) noexcept; +random_read::ptr core_file_read(core_file &file, std::uint8_t filler) noexcept; + +random_read_write::ptr core_file_read_write(std::unique_ptr &&file) noexcept; +random_read_write::ptr core_file_read_write(std::unique_ptr &&file, std::uint8_t filler) noexcept; +random_read_write::ptr core_file_read_write(core_file &file) noexcept; +random_read_write::ptr core_file_read_write(core_file &file, std::uint8_t filler) noexcept; + +} // namespace util + +#endif // MAME_LIB_UTIL_IOPROCS_H diff --git a/src/lib/util/ioprocsfill.h b/src/lib/util/ioprocsfill.h new file mode 100644 index 00000000000..e49b10687f0 --- /dev/null +++ b/src/lib/util/ioprocsfill.h @@ -0,0 +1,163 @@ +// license:BSD-3-Clause +// copyright-holders:Vas Crabb +/*************************************************************************** + + ioprocsfill.h + + Wrappers that automatically fill extra space + +***************************************************************************/ +#ifndef MAME_LIB_UTIL_IOPROCSFILL_H +#define MAME_LIB_UTIL_IOPROCSFILL_H + +#pragma once + +#include +#include +#include +#include + + +namespace util { + +template +class fill_wrapper_base +{ +public: + std::uint8_t get_filler() const noexcept + { + return m_filler; + } + + void set_filler(std::uint8_t filler) noexcept + { + m_filler = filler; + } + +private: + std::uint8_t m_filler = DefaultFiller; +}; + + +template +class read_stream_fill_wrapper : public Base, public virtual fill_wrapper_base +{ +public: + using Base::Base; + + virtual std::error_condition read(void *buffer, std::size_t length, std::size_t &actual) noexcept override + { + std::error_condition err = Base::read(buffer, length, actual); + assert(length >= actual); + std::fill( + reinterpret_cast(buffer) + actual, + reinterpret_cast(buffer) + length, + fill_wrapper_base::get_filler()); + return err; + } +}; + + +template +class random_read_fill_wrapper : public read_stream_fill_wrapper +{ +public: + using read_stream_fill_wrapper::read_stream_fill_wrapper; + + virtual std::error_condition read_at(std::uint64_t offset, void *buffer, std::size_t length, std::size_t &actual) noexcept override + { + std::error_condition err = Base::read_at(offset, buffer, length, actual); + assert(length >= actual); + std::fill( + reinterpret_cast(buffer) + actual, + reinterpret_cast(buffer) + length, + fill_wrapper_base::get_filler()); + return err; + } +}; + + +template +class random_write_fill_wrapper : public Base, public virtual fill_wrapper_base +{ +public: + using Base::Base; + + virtual std::error_condition write(void const *buffer, std::size_t length, std::size_t &actual) noexcept override + { + std::error_condition err; + actual = 0U; + + std::uint64_t offset; + std::uint64_t current; + err = Base::tell(offset); + if (err) + return err; + err = Base::length(current); + if (err) + return err; + + if (current < offset) + { + std::uint64_t unfilled = offset - current; + std::uint8_t fill_buffer[FillBlock]; + std::fill( + fill_buffer, + fill_buffer + std::min >(FillBlock, unfilled), + fill_wrapper_base::get_filler()); + do + { + std::size_t const chunk = std::min >(FillBlock, unfilled); + err = Base::write_at(current, fill_buffer, chunk, actual); + if (err) + { + actual = 0U; + return err; + } + current += chunk; + unfilled -= chunk; + } + while (unfilled); + } + + return Base::write(buffer, length, actual); + } + + virtual std::error_condition write_at(std::uint64_t offset, void const *buffer, std::size_t length, std::size_t &actual) noexcept override + { + std::error_condition err; + std::uint64_t current; + err = Base::length(current); + if (!err && (current < offset)) + { + std::uint64_t unfilled = offset - current; + std::uint8_t fill_buffer[FillBlock]; + std::fill( + fill_buffer, + fill_buffer + std::min >(FillBlock, unfilled), + fill_wrapper_base::get_filler()); + do + { + std::size_t const chunk = std::min >(FillBlock, unfilled); + err = Base::write_at(current, fill_buffer, chunk, actual); + current += chunk; + unfilled -= chunk; + } + while (unfilled && !err); + } + if (err) + { + actual = 0U; + return err; + } + return Base::write_at(offset, buffer, length, actual); + } +}; + + +template +using random_read_write_fill_wrapper = random_write_fill_wrapper, DefaultFiller, FillBlock>; + +} // namespace util + +#endif // MAME_LIB_UTIL_IOPROCSFILL_H diff --git a/src/lib/util/ioprocsfilter.cpp b/src/lib/util/ioprocsfilter.cpp new file mode 100644 index 00000000000..da67b8c41f2 --- /dev/null +++ b/src/lib/util/ioprocsfilter.cpp @@ -0,0 +1,598 @@ +// license:BSD-3-Clause +// copyright-holders:Vas Crabb +/*************************************************************************** + + ioprocs.h + + I/O filters + +***************************************************************************/ + +#include "ioprocsfilter.h" + +#include "ioprocs.h" + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + + +namespace util { + +namespace { + +// helper class for holding zlib data + +class zlib_data +{ +protected: + zlib_data(std::size_t buffer_size) noexcept : + m_buffer_size(std::min >(std::numeric_limits::max(), buffer_size)) + { + assert(buffer_size); + } + + z_stream &get_z_stream() noexcept { return m_z_stream; } + z_stream const &get_z_stream() const noexcept { return m_z_stream; } + Bytef *get_buffer() noexcept { return m_buffer.get(); } + Bytef const *get_buffer() const noexcept { return m_buffer.get(); } + std::size_t get_buffer_size() const noexcept { return m_buffer_size; } + + bool input_empty() const noexcept { return !m_z_stream.avail_in; } + bool output_available() const noexcept { return bool(m_z_stream.avail_out); } + + void initialize_z_stream() noexcept + { + m_z_stream.zalloc = Z_NULL; + m_z_stream.zfree = Z_NULL; + m_z_stream.opaque = Z_NULL; + } + + std::error_condition allocate_buffer() noexcept + { + if (!m_buffer) + m_buffer.reset(new (std::nothrow) Bytef [m_buffer_size]); + return m_buffer ? std::error_condition() : std::errc::not_enough_memory; + } + + void release_buffer() noexcept + { + m_buffer.reset(); + } + + static std::error_condition convert_z_error(int err) noexcept + { + switch (err) + { + case Z_OK: + case Z_STREAM_END: + return std::error_condition(); + case Z_NEED_DICT: + return std::errc::invalid_argument; + case Z_ERRNO: + return std::error_condition(errno, std::generic_category()); + case Z_STREAM_ERROR: + return std::errc::invalid_argument; + case Z_DATA_ERROR: + return std::errc::invalid_argument; // TODO: revisit this error code + case Z_MEM_ERROR: + return std::errc::not_enough_memory; + case Z_BUF_ERROR: + return std::errc::operation_would_block; // TODO: revisit this error code (should be handled internally) + case Z_VERSION_ERROR: + return std::errc::invalid_argument; // TODO: revisit this error code (library ABI mismatch) + default: + return std::errc::io_error; // TODO: better default error code + } + } + +private: + z_stream m_z_stream; + std::unique_ptr m_buffer; + std::size_t const m_buffer_size; +}; + + +// helper class for decompressing deflated data + +class inflate_data : private zlib_data +{ +protected: + using zlib_data::zlib_data; + + ~inflate_data() + { + if (m_inflate_initialized) + inflateEnd(&get_z_stream()); + } + + using zlib_data::input_empty; + + bool stream_initialized() const noexcept + { + return m_inflate_initialized; + } + + std::error_condition initialize_z_stream() noexcept + { + if (m_inflate_initialized) + return std::errc::invalid_argument; + std::error_condition err = allocate_buffer(); + if (err) + return err; + zlib_data::initialize_z_stream(); + int const zerr = inflateInit(&get_z_stream()); + if (Z_OK == zerr) + m_inflate_initialized = true; + return convert_z_error(zerr); + } + + std::error_condition close_z_stream() noexcept + { + if (!m_inflate_initialized) + return std::errc::invalid_argument; + int const zerr = inflateEnd(&get_z_stream()); + m_inflate_initialized = false; + return convert_z_error(zerr); + } + + std::error_condition decompress_some(bool &stream_end) noexcept + { + assert(m_inflate_initialized); + int const zerr = inflate(&get_z_stream(), Z_SYNC_FLUSH); + if (!get_z_stream().avail_in) + reset_input(); + stream_end = Z_STREAM_END == zerr; + return convert_z_error(zerr); + } + + std::size_t input_available() const noexcept + { + return std::size_t(get_z_stream().avail_in); + } + + void reset_input() noexcept + { + get_z_stream().next_in = get_buffer(); + get_z_stream().avail_in = 0U; + } + + std::pair get_unfilled_input() noexcept + { + assert(get_buffer()); + Bytef *const base = get_z_stream().next_in + get_z_stream().avail_in; + return std::make_pair(base, get_buffer() + get_buffer_size() - base); + } + + void add_input(std::size_t length) noexcept + { + assert(get_buffer()); + get_z_stream().avail_in += length; + assert((get_buffer() + get_buffer_size()) >= (get_z_stream().next_in + get_z_stream().avail_in)); + } + + std::size_t output_produced() const noexcept + { + return m_output_max - get_z_stream().avail_out; + } + + void set_output(void *buffer, std::size_t length) noexcept + { + m_output_max = std::min >(std::numeric_limits::max(), length); + get_z_stream().next_out = reinterpret_cast(buffer); + get_z_stream().avail_out = uInt(m_output_max); + } + +private: + std::error_condition allocate_buffer() noexcept + { + std::error_condition err; + if (!get_buffer()) + { + err = zlib_data::allocate_buffer(); + reset_input(); + } + return err; + } + + bool m_inflate_initialized = false; + std::size_t m_output_max = 0U; +}; + + +// helper class for deflating data + +class deflate_data : private zlib_data +{ +protected: + deflate_data(int level, std::size_t buffer_size) noexcept : zlib_data(buffer_size), m_level(level) + { + } + + ~deflate_data() + { + if (m_deflate_initialized) + deflateEnd(&get_z_stream()); + } + + using zlib_data::input_empty; + using zlib_data::output_available; + + bool stream_initialized() const noexcept + { + return m_deflate_initialized; + } + + bool compression_finished() const noexcept + { + return m_compression_finished; + } + + std::error_condition initialize_z_stream() noexcept + { + if (m_deflate_initialized) + return std::errc::invalid_argument; + std::error_condition err = allocate_buffer(); + if (err) + return err; + zlib_data::initialize_z_stream(); + int const zerr = deflateInit(&get_z_stream(), m_level); + reset_output(); + if (Z_OK == zerr) + m_deflate_initialized = true; + return convert_z_error(zerr); + } + + std::error_condition close_z_stream() noexcept + { + if (!m_deflate_initialized) + return std::errc::invalid_argument; + m_deflate_initialized = m_compression_finished = false; + return convert_z_error(deflateEnd(&get_z_stream())); + } + + std::error_condition reset_z_stream() noexcept + { + if (!m_deflate_initialized) + return std::errc::invalid_argument; + assert(get_buffer()); + reset_output(); + m_compression_finished = false; + return convert_z_error(deflateReset(&get_z_stream())); + } + + std::error_condition compress_some() noexcept + { + assert(m_deflate_initialized); + return convert_z_error(deflate(&get_z_stream(), Z_NO_FLUSH)); + } + + std::error_condition finish_compression() noexcept + { + assert(m_deflate_initialized); + int const zerr = deflate(&get_z_stream(), Z_FINISH); + if (Z_STREAM_END == zerr) + m_compression_finished = true; + return convert_z_error(zerr); + } + + std::size_t input_used() const noexcept + { + return m_input_max - get_z_stream().avail_in; + } + + void set_input(void const *data, std::size_t length) noexcept + { + m_input_max = std::min >(std::numeric_limits::max(), length); + get_z_stream().next_in = const_cast(reinterpret_cast(data)); + get_z_stream().avail_in = uInt(m_input_max); + } + + std::pair get_output() const noexcept + { + assert(get_buffer()); + return std::make_pair( + &get_buffer()[m_output_used], + get_buffer_size() - get_z_stream().avail_out - m_output_used); + } + + void consume_output(std::size_t length) noexcept + { + m_output_used += length; + assert(m_output_used <= (get_buffer_size() - get_z_stream().avail_out)); + if (m_output_used == (get_buffer_size() - get_z_stream().avail_out)) + reset_output(); + } + +private: + void reset_output() noexcept + { + assert(get_buffer()); + m_output_used = 0U; + get_z_stream().next_out = get_buffer(); + get_z_stream().avail_out = uInt(get_buffer_size()); + } + + int const m_level; + bool m_deflate_initialized = false; + bool m_compression_finished = false; + std::size_t m_output_used = 0U; + std::size_t m_input_max = 0U; +}; + + +// helper for holding an object and deleting it (or not) as necessary + +template +class filter_base +{ +protected: + filter_base(std::unique_ptr &&object) noexcept : m_object(object.release()), m_owned(true) + { + assert(m_object); + } + + filter_base(T &object) noexcept : m_object(&object), m_owned(false) + { + } + + ~filter_base() + { + if (m_owned) + delete m_object; + } + + T &object() noexcept + { + return *m_object; + } + +private: + T *const m_object; + bool const m_owned; +}; + + +// filter for decompressing deflated data + +template +class zlib_read_filter : public read_stream, protected filter_base, protected inflate_data +{ +public: + zlib_read_filter(std::unique_ptr &&stream, std::size_t read_chunk) noexcept : + filter_base(std::move(stream)), + inflate_data(read_chunk) + { + } + + zlib_read_filter(Stream &stream, std::size_t read_chunk) noexcept : + filter_base(stream), + inflate_data(read_chunk) + { + } + + virtual std::error_condition read(void *buffer, std::size_t length, std::size_t &actual) noexcept override + { + std::error_condition err; + actual = 0U; + + if (!stream_initialized()) + err = initialize_z_stream(); + + if (!err && (length > actual)) + { + bool short_input = false; + do + { + if (input_empty()) + { + auto const space = get_unfilled_input(); + std::size_t filled; + err = this->object().read(space.first, space.second, filled); + add_input(filled); + short_input = space.second > filled; + } + + if (!err && !input_empty()) + { + set_output(reinterpret_cast(buffer) + actual, length - actual); + bool stream_end; + err = decompress_some(stream_end); + actual += output_produced(); + + if (stream_end) + { + assert(!err); + if constexpr (std::is_base_of_v) + { + if (!input_empty()) + { + std::int64_t const overshoot = std::uint64_t(input_available()); + reset_input(); + return this->object().seek(-overshoot, SEEK_CUR); + } + } + else + { + return std::error_condition(); + } + } + } + } + while (!err && (length > actual) && !short_input); + } + + return err; + } +}; + + +// filter for deflating data + +class zlib_write_filter : public write_stream, protected filter_base, protected deflate_data +{ +public: + zlib_write_filter(write_stream::ptr &&stream, int level, std::size_t buffer_size) noexcept : + filter_base(std::move(stream)), + deflate_data(level, buffer_size) + { + } + + zlib_write_filter(write_stream &stream, int level, std::size_t buffer_size) noexcept : + filter_base(stream), + deflate_data(level, buffer_size) + { + } + + ~zlib_write_filter() + { + finalize(); + } + + virtual std::error_condition finalize() noexcept override + { + if (!stream_initialized()) + return std::error_condition(); + + do + { + if (!compression_finished() && output_available()) + { + std::error_condition err = finish_compression(); + if (err) + return err; + } + + while ((compression_finished() && get_output().second) || !output_available()) + { + std::error_condition err = write_some(); + if (err) + return err; + } + } + while (!compression_finished()); + + return close_z_stream(); + } + + virtual std::error_condition flush() noexcept override + { + if (stream_initialized()) + { + auto const output = get_output(); + if (output.second) + { + std::size_t written; + std::error_condition err = object().write(output.first, output.second, written); + consume_output(written); + if (err) + { + object().flush(); + return err; + } + } + } + return object().flush(); + } + + virtual std::error_condition write(void const *buffer, std::size_t length, std::size_t &actual) noexcept override + { + std::error_condition err; + actual = 0U; + + if (!stream_initialized()) + { + err = initialize_z_stream(); + } + else if (compression_finished()) + { + while (!err && get_output().second) + err = write_some(); + if (!err) + err = reset_z_stream(); + } + + while (!err && (length > actual)) + { + set_input(reinterpret_cast(buffer) + actual, length - actual); + do + { + if (output_available()) + err = compress_some(); + + while (!err && !output_available()) + err = write_some(); + } + while (!err && !input_empty()); + actual += input_used(); + } + + return err; + } + +private: + std::error_condition write_some() noexcept + { + auto const output = get_output(); + std::size_t written; + std::error_condition err = object().write(output.first, output.second, written); + consume_output(written); + return err; + } +}; + +} // anonymous namespace + + +// creating decompressing filters + +read_stream::ptr zlib_read(read_stream::ptr &&stream, std::size_t read_chunk) noexcept +{ + read_stream::ptr result; + if (stream) + result.reset(new (std::nothrow) zlib_read_filter(std::move(stream), read_chunk)); + return result; +} + +read_stream::ptr zlib_read(random_read::ptr &&stream, std::size_t read_chunk) noexcept +{ + read_stream::ptr result; + if (stream) + result.reset(new (std::nothrow) zlib_read_filter(std::move(stream), read_chunk)); + return result; +} + +read_stream::ptr zlib_read(read_stream &stream, std::size_t read_chunk) noexcept +{ + return read_stream::ptr(new (std::nothrow) zlib_read_filter(stream, read_chunk)); +} + +read_stream::ptr zlib_read(random_read &stream, std::size_t read_chunk) noexcept +{ + return read_stream::ptr(new (std::nothrow) zlib_read_filter(stream, read_chunk)); +} + + +// creating compressing filters + +write_stream::ptr zlib_write(write_stream::ptr &&stream, int level, std::size_t buffer_size) noexcept +{ + write_stream::ptr result; + if (stream) + result.reset(new (std::nothrow) zlib_write_filter(std::move(stream), level, buffer_size)); + return result; +} + +write_stream::ptr zlib_write(write_stream &stream, int level, std::size_t buffer_size) noexcept +{ + return write_stream::ptr(new (std::nothrow) zlib_write_filter(stream, level, buffer_size)); +} + +} // namespace util diff --git a/src/lib/util/ioprocsfilter.h b/src/lib/util/ioprocsfilter.h new file mode 100644 index 00000000000..a146dd737ce --- /dev/null +++ b/src/lib/util/ioprocsfilter.h @@ -0,0 +1,31 @@ +// license:BSD-3-Clause +// copyright-holders:Vas Crabb +/*************************************************************************** + + ioprocs.h + + I/O filters + +***************************************************************************/ +#ifndef MAME_LIB_UTIL_IOPROCSFILTER_H +#define MAME_LIB_UTIL_IOPROCSFILTER_H + +#include "utilfwd.h" + +#include +#include + + +namespace util { + +std::unique_ptr zlib_read(std::unique_ptr &&stream, std::size_t read_chunk) noexcept; +std::unique_ptr zlib_read(std::unique_ptr &&stream, std::size_t read_chunk) noexcept; +std::unique_ptr zlib_read(read_stream &stream, std::size_t read_chunk) noexcept; +std::unique_ptr zlib_read(random_read &stream, std::size_t read_chunk) noexcept; + +std::unique_ptr zlib_write(std::unique_ptr &&stream, int level, std::size_t buffer_size) noexcept; +std::unique_ptr zlib_write(write_stream &stream, int level, std::size_t buffer_size) noexcept; + +} // namespace util + +#endif // MAME_LIB_UTIL_IOPROCSFILTER_H diff --git a/src/lib/util/ioprocsvec.h b/src/lib/util/ioprocsvec.h new file mode 100644 index 00000000000..27dda095ad3 --- /dev/null +++ b/src/lib/util/ioprocsvec.h @@ -0,0 +1,211 @@ +// license:BSD-3-Clause +// copyright-holders:Vas Crabb +/*************************************************************************** + + ioprocsvec.h + + Helper for using a vector as an in-memory file + +***************************************************************************/ +#ifndef MAME_LIB_UTIL_IOPROCSVEC_H +#define MAME_LIB_UTIL_IOPROCSVEC_H + +#include "ioprocs.h" + +#include +#include +#include +#include +#include +#include +#include + + +namespace util { + +template +class vector_read_write_adapter : public random_read_write +{ +public: + vector_read_write_adapter(std::vector &storage) noexcept : m_storage(storage) + { + check_resized(); + } + + virtual std::error_condition seek(std::int64_t offset, int whence) noexcept override + { + switch (whence) + { + case SEEK_SET: + if (0 > offset) + return std::errc::invalid_argument; + m_pointer = std::uint64_t(offset); + return std::error_condition(); + + case SEEK_CUR: + if (0 > offset) + { + if (std::uint64_t(-offset) > m_pointer) + return std::errc::invalid_argument; + } + else if ((std::numeric_limits::max() - offset) < m_pointer) + { + return std::errc::invalid_argument; + } + m_pointer += offset; + return std::error_condition(); + + case SEEK_END: + check_resized(); + if (0 > offset) + { + if (std::uint64_t(-offset) > m_size) + return std::errc::invalid_argument; + } + else if ((std::numeric_limits::max() - offset) < m_size) + { + return std::errc::invalid_argument; + } + m_pointer = std::uint64_t(m_size) + offset; + return std::error_condition(); + + default: + return std::errc::invalid_argument; + } + } + + virtual std::error_condition tell(std::uint64_t &result) noexcept override + { + result = m_pointer; + return std::error_condition(); + } + + virtual std::error_condition length(std::uint64_t &result) noexcept override + { + check_resized(); + if (std::numeric_limits::max() < m_size) + return std::errc::file_too_large; + + result = m_size; + return std::error_condition(); + } + + virtual std::error_condition read(void *buffer, std::size_t length, std::size_t &actual) noexcept override + { + do_read(m_pointer, buffer, length, actual); + m_pointer += actual; + return std::error_condition(); + } + + virtual std::error_condition read_at(std::uint64_t offset, void *buffer, std::size_t length, std::size_t &actual) noexcept override + { + do_read(offset, buffer, length, actual); + return std::error_condition(); + } + + virtual std::error_condition finalize() noexcept override + { + return std::error_condition(); + } + + virtual std::error_condition flush() noexcept override + { + return std::error_condition(); + } + + virtual std::error_condition write(void const *buffer, std::size_t length, std::size_t &actual) noexcept override + { + std::error_condition result = do_write(m_pointer, buffer, length, actual); + m_pointer += actual; + return result; + } + + virtual std::error_condition write_at(std::uint64_t offset, void const *buffer, std::size_t length, std::size_t &actual) noexcept override + { + return do_write(offset, buffer, length, actual); + } + +private: + using elements_type = typename std::vector::size_type; + using common_size_type = std::common_type_t; + + void check_resized() noexcept + { + if (m_storage.size() != m_elements) + { + m_elements = m_storage.size(); + m_size = m_elements * sizeof(T); + } + } + + void do_read(std::uint64_t offset, void *buffer, std::size_t length, std::size_t &actual) noexcept + { + check_resized(); + if ((offset < m_size) && length) + { + actual = std::min(std::size_t(m_size - offset), length); + std::memmove(buffer, reinterpret_cast(m_storage.data()) + offset, actual); + } + else + { + actual = 0U; + } + } + + std::error_condition do_write(std::uint64_t offset, void const *buffer, std::size_t length, std::size_t &actual) noexcept + { + check_resized(); + std::size_t allocated = m_elements * sizeof(T); + std::uint64_t const target = ((std::numeric_limits::max() - offset) >= length) + ? (offset + length) + : std::numeric_limits::max(); + + std::error_condition result; + if (target > allocated) + { + elements_type const required = std::min >( + std::numeric_limits::max(), + (target + sizeof(T) - 1) / sizeof(T)); // technically can overflow but unlikely + try { m_storage.resize(required); } // unpredictable if constructing/assigning T can throw + catch (...) { result = std::errc::not_enough_memory; } + m_elements = m_storage.size(); + allocated = m_elements * sizeof(T); + assert(allocated >= m_size); + + if (offset > m_size) + { + std::size_t const new_size = std::size_t(std::min(allocated, offset)); + std::memset( + reinterpret_cast(m_storage.data()) + m_size, + 0x00, // POSIX says unwritten areas of files should read as zero + new_size - m_size); + m_size = new_size; + } + } + + std::size_t const limit = std::min(target, allocated); + if (limit > offset) + { + actual = std::size_t(limit - offset); + std::memmove(reinterpret_cast(m_storage.data()) + offset, buffer, actual); + m_size = limit; + } + else + { + actual = 0U; + } + if (!result && (actual < length)) + result = std::errc::no_space_on_device; + + return result; + } + + std::vector &m_storage; + std::uint64_t m_pointer = 0U; + elements_type m_elements = 0U; + std::size_t m_size = 0U; +}; + +} // namespace util + +#endif // MAME_LIB_UTIL_IOPROCSVEC_H diff --git a/src/lib/util/path.cpp b/src/lib/util/path.cpp new file mode 100644 index 00000000000..e69de29bb2d diff --git a/src/lib/util/path.h b/src/lib/util/path.h new file mode 100644 index 00000000000..1291d7b17d3 --- /dev/null +++ b/src/lib/util/path.h @@ -0,0 +1,65 @@ +// license:BSD-3-Clause +// copyright-holders:Vas Crabb +/*************************************************************************** + + path.h + + Filesystem path utilties + +***************************************************************************/ +#ifndef MAME_LIB_UTIL_PATH_H +#define MAME_LIB_UTIL_PATH_H + +#include "osdfile.h" // for PATH_SEPARATOR + +#include +#include + + +namespace util { + +/*************************************************************************** + INLINE FUNCTIONS +***************************************************************************/ + +// is a given character a directory separator? + +constexpr bool is_directory_separator(char c) +{ +#if defined(WIN32) + return ('\\' == c) || ('/' == c) || (':' == c); +#else + return '/' == c; +#endif +} + + +// append to a path + +template +inline std::string &path_append(std::string &path, T &&next, U &&... more) +{ + if (!path.empty() && !is_directory_separator(path.back())) + path.append(PATH_SEPARATOR); + path.append(std::forward(next)); + if constexpr (sizeof...(U)) + return path_append(std::forward(more)...); + else + return path; +} + + +// concatenate paths + +template +inline std::string path_concat(T &&first, U &&... more) +{ + std::string result(std::forward(first)); + if constexpr (sizeof...(U)) + path_append(result, std::forward(more)...); + return result; +} + +} // namespace util + +#endif // MAME_LIB_UTIL_PATH_H diff --git a/src/lib/util/strformat.h b/src/lib/util/strformat.h index b8c9b4f1a99..a3ba1d11261 100644 --- a/src/lib/util/strformat.h +++ b/src/lib/util/strformat.h @@ -578,16 +578,16 @@ template class format_output { private: - template struct string_semantics - { static constexpr bool value = false; }; - template struct string_semantics > - { static constexpr bool value = true; }; - template struct string_semantics > - { static constexpr bool value = true; }; - template struct signed_integer_semantics - { static constexpr bool value = std::is_integral_v&& std::is_signed_v; }; - template struct unsigned_integer_semantics - { static constexpr bool value = std::is_integral_v&& !std::is_signed_v; }; + template + struct string_semantics : public std::false_type { }; + template + struct string_semantics > : public std::true_type { }; + template + struct string_semantics > : public std::true_type { }; + template + using signed_integer_semantics = std::bool_constant && std::is_signed_v >; + template + using unsigned_integer_semantics = std::bool_constant && !std::is_signed_v >; static void apply_signed(Stream &str, char16_t const &value) { @@ -865,8 +865,8 @@ template class format_output { protected: - template struct string_semantics - { static constexpr bool value = std::is_same, typename Stream::char_type>::value; }; + template + using string_semantics = std::bool_constant, typename Stream::char_type> >; public: template @@ -940,10 +940,10 @@ template class format_make_integer { private: - template struct use_unsigned_cast - { static constexpr bool value = std::is_convertible::value && std::is_unsigned::value; }; - template struct use_signed_cast - { static constexpr bool value = !use_unsigned_cast::value && std::is_convertible::value; }; + template + using use_unsigned_cast = std::bool_constant && std::is_unsigned_v >; + template + using use_signed_cast = std::bool_constant::value && std::is_convertible_v >; public: template static bool apply(U const &value, int &result) @@ -974,14 +974,14 @@ template class format_store_integer { private: - template struct is_non_const_ptr - { static constexpr bool value = std::is_pointer::value && !std::is_const >::value; }; - template struct is_unsigned_ptr - { static constexpr bool value = std::is_pointer::value && std::is_unsigned >::value; }; - template struct use_unsigned_cast - { static constexpr bool value = is_non_const_ptr::value && is_unsigned_ptr::value && std::is_convertible, std::remove_pointer_t >::value; }; - template struct use_signed_cast - { static constexpr bool value = is_non_const_ptr::value && !use_unsigned_cast::value && std::is_convertible >::value; }; + template + using is_non_const_ptr = std::bool_constant && !std::is_const_v > >; + template + using is_unsigned_ptr = std::bool_constant && std::is_unsigned_v > >; + template + using use_unsigned_cast = std::bool_constant::value && is_unsigned_ptr::value && std::is_convertible_v, std::remove_pointer_t > >; + template + using use_signed_cast = std::bool_constant::value && !use_unsigned_cast::value && std::is_convertible_v > >; public: template static bool apply(U const &value, std::streamoff data) @@ -1091,11 +1091,11 @@ public: protected: template - struct handle_char_ptr { static constexpr bool value = std::is_pointer::value && std::is_same >, char_type>::value; }; + using handle_char_ptr = std::bool_constant && std::is_same_v >, char_type> >; template - struct handle_char_array { static constexpr bool value = std::is_array::value && std::is_same >, char_type>::value; }; + using handle_char_array = std::bool_constant && std::is_same_v >, char_type> >; template - struct handle_container { static constexpr bool value = !handle_char_ptr::value && !handle_char_array::value; }; + using handle_container = std::bool_constant::value && !handle_char_array::value>; template format_argument_pack( diff --git a/src/lib/util/timeconv.cpp b/src/lib/util/timeconv.cpp index 99953712003..469b6b592a2 100644 --- a/src/lib/util/timeconv.cpp +++ b/src/lib/util/timeconv.cpp @@ -14,42 +14,10 @@ namespace util { -/*************************************************************************** - PROTOTYPES -***************************************************************************/ - -static std::chrono::system_clock::duration calculate_system_clock_adjustment(); - - -/*************************************************************************** - GLOBAL VARIABLES -***************************************************************************/ - -std::chrono::system_clock::duration system_clock_adjustment(calculate_system_clock_adjustment()); - - -/*************************************************************************** - IMPLEMENTATION -***************************************************************************/ - -arbitrary_datetime arbitrary_datetime::now() -{ - time_t sec; - time(&sec); - auto t = *localtime(&sec); - - arbitrary_datetime dt; - dt.year = t.tm_year + 1900; - dt.month = t.tm_mon + 1; - dt.day_of_month = t.tm_mday; - dt.hour = t.tm_hour; - dt.minute = t.tm_min; - dt.second = t.tm_sec; - return dt; -} +namespace { -static std::chrono::system_clock::duration calculate_system_clock_adjustment() +std::chrono::system_clock::duration calculate_system_clock_adjustment() { constexpr auto days_in_year(365); constexpr auto days_in_four_years((days_in_year * 4) + 1); @@ -84,6 +52,39 @@ static std::chrono::system_clock::duration calculate_system_clock_adjustment() return result - std::chrono::system_clock::from_time_t(0).time_since_epoch(); } +} // anonymous namespace + + + +/*************************************************************************** + GLOBAL VARIABLES +***************************************************************************/ + +std::chrono::system_clock::duration system_clock_adjustment(calculate_system_clock_adjustment()); + + + +/*************************************************************************** + IMPLEMENTATION +***************************************************************************/ + +arbitrary_datetime arbitrary_datetime::now() +{ + time_t sec; + time(&sec); + auto t = *localtime(&sec); + + arbitrary_datetime dt; + dt.year = t.tm_year + 1900; + dt.month = t.tm_mon + 1; + dt.day_of_month = t.tm_mday; + dt.hour = t.tm_hour; + dt.minute = t.tm_min; + dt.second = t.tm_sec; + + return dt; +} + // ------------------------------------------------- diff --git a/src/lib/util/timeconv.h b/src/lib/util/timeconv.h index f9d1b070012..91327dbac16 100644 --- a/src/lib/util/timeconv.h +++ b/src/lib/util/timeconv.h @@ -22,6 +22,7 @@ namespace util { + /*************************************************************************** GLOBAL VARIABLES ***************************************************************************/ @@ -58,7 +59,7 @@ struct arbitrary_datetime // date of the epoch's begining //--------------------------------------------------------- -template +template class arbitrary_clock { public: @@ -89,7 +90,7 @@ public: // with a different scale to this arbitrary_clock's scale //--------------------------------------------------------- - template + template static time_point from_arbitrary_time_point(const std::chrono::time_point > &tp) { arbitrary_datetime dt; @@ -111,7 +112,7 @@ public: // of this scale to one of different scale //--------------------------------------------------------- - template + template static std::chrono::time_point > to_arbitrary_time_point(const time_point &tp) { return arbitrary_clock::from_arbitrary_time_point(tp); @@ -125,14 +126,14 @@ public: static struct tm to_tm(const time_point &tp) { std::chrono::time_point normalized_tp = to_arbitrary_time_point< - std::int64_t, - tm_conversion_clock::base_year, - tm_conversion_clock::base_month, - tm_conversion_clock::base_day, - tm_conversion_clock::base_hour, - tm_conversion_clock::base_minute, - tm_conversion_clock::base_second, - tm_conversion_clock::period>(tp); + std::int64_t, + tm_conversion_clock::base_year, + tm_conversion_clock::base_month, + tm_conversion_clock::base_day, + tm_conversion_clock::base_hour, + tm_conversion_clock::base_minute, + tm_conversion_clock::base_second, + tm_conversion_clock::period>(tp); return internal_to_tm(normalized_tp.time_since_epoch()); } @@ -144,14 +145,14 @@ public: static std::chrono::time_point to_system_clock(const time_point &tp) { auto normalized_tp = to_arbitrary_time_point< - std::int64_t, - system_conversion_clock::base_year, - system_conversion_clock::base_month, - system_conversion_clock::base_day, - system_conversion_clock::base_hour, - system_conversion_clock::base_minute, - system_conversion_clock::base_second, - system_conversion_clock::period>(tp); + std::int64_t, + system_conversion_clock::base_year, + system_conversion_clock::base_month, + system_conversion_clock::base_day, + system_conversion_clock::base_hour, + system_conversion_clock::base_minute, + system_conversion_clock::base_second, + system_conversion_clock::period>(tp); return std::chrono::time_point(normalized_tp.time_since_epoch() + system_clock_adjustment); } diff --git a/src/lib/util/un7z.cpp b/src/lib/util/un7z.cpp index 879da294c69..b35af479d5d 100644 --- a/src/lib/util/un7z.cpp +++ b/src/lib/util/un7z.cpp @@ -13,11 +13,13 @@ #include "unzip.h" #include "corestr.h" -#include "osdcore.h" -#include "osdfile.h" +#include "ioprocs.h" #include "unicode.h" #include "timeconv.h" +#include "osdcore.h" +#include "osdfile.h" + #include "lzma/C/7z.h" #include "lzma/C/7zAlloc.h" #include "lzma/C/7zCrc.h" @@ -38,47 +40,71 @@ namespace util { + namespace { + /*************************************************************************** TYPE DEFINITIONS ***************************************************************************/ -struct CSzFile +struct CFileInStream : public ISeekInStream { - CSzFile() : currfpos(0), length(0), osdfile() {} + CFileInStream() noexcept + { + Read = [] (void *pp, void *buf, size_t *size) { return reinterpret_cast(pp)->read(buf, *size); }; + Seek = [] (void *pp, Int64 *pos, ESzSeek origin) { return reinterpret_cast(pp)->seek(*pos, origin); }; + } - std::uint64_t currfpos; - std::uint64_t length; - osd_file::ptr osdfile; + random_read::ptr file; + std::uint64_t currfpos = 0; + std::uint64_t length = 0; - SRes read(void *data, std::size_t &size) +private: + SRes read(void *data, std::size_t &size) noexcept { - if (!osdfile) + if (!file) { - osd_printf_error("un7z: called CSzFile::read without file\n"); + osd_printf_error("un7z: called CFileInStream::read without file\n"); return SZ_ERROR_READ; } if (!size) return SZ_OK; - // TODO: this casts a size_t to a uint32_t, so it will fail if >=4GB is requested at once (need a loop) - std::uint32_t read_length(0); - auto const err = osdfile->read(data, currfpos, size, read_length); + std::size_t read_length(0); + std::error_condition const err = file->read_at(currfpos, data, size, read_length); size = read_length; currfpos += read_length; - return (osd_file::error::NONE == err) ? SZ_OK : SZ_ERROR_READ; + return !err ? SZ_OK : SZ_ERROR_READ; } - SRes seek(Int64 &pos, ESzSeek origin) + SRes seek(Int64 &pos, ESzSeek origin) noexcept { + // need to synthesise this because the OSD file wrapper doesn't implement SEEK_END switch (origin) { - case SZ_SEEK_CUR: currfpos += pos; break; - case SZ_SEEK_SET: currfpos = pos; break; - case SZ_SEEK_END: currfpos = length + pos; break; - default: return SZ_ERROR_READ; + case SZ_SEEK_CUR: + if ((0 > pos) && (-pos > currfpos)) + { + osd_printf_error("un7z: attemped to seek back %d bytes when current offset is %u\n", -pos, currfpos); + return SZ_ERROR_READ; + } + currfpos += pos; + break; + case SZ_SEEK_SET: + currfpos = pos; + break; + case SZ_SEEK_END: + if ((0 > pos) && (-pos > length)) + { + osd_printf_error("un7z: attemped to seek %d bytes before end of file %u\n", -pos, currfpos); + return SZ_ERROR_READ; + } + currfpos = length + pos; + break; + default: + return SZ_ERROR_READ; } pos = currfpos; return SZ_OK; @@ -86,18 +112,18 @@ struct CSzFile }; -struct CFileInStream : public ISeekInStream, public CSzFile -{ - CFileInStream(); -}; - - -class m7z_file_impl +class m7z_file_impl { public: typedef std::unique_ptr ptr; - m7z_file_impl(const std::string &filename); + m7z_file_impl(std::string &&filename) noexcept; + + m7z_file_impl(random_read::ptr &&file) noexcept + : m7z_file_impl(std::string()) + { + m_archive_stream.file = std::move(file); + } virtual ~m7z_file_impl() { @@ -107,7 +133,7 @@ public: SzArEx_Free(&m_db, &m_alloc_imp); } - static ptr find_cached(const std::string &filename) + static ptr find_cached(std::string_view filename) noexcept { std::lock_guard guard(s_cache_mutex); for (std::size_t cachenum = 0; cachenum < s_cache.size(); cachenum++) @@ -115,47 +141,60 @@ public: // 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)) { + using std::swap; ptr result; - std::swap(s_cache[cachenum], result); + swap(s_cache[cachenum], result); osd_printf_verbose("un7z: found %s in cache\n", filename); return result; } } return ptr(); } - static void close(ptr &&archive); - static void cache_clear() + + static void close(ptr &&archive) noexcept; + + static void cache_clear() noexcept { // clear call cache entries std::lock_guard guard(s_cache_mutex); - for (std::size_t cachenum = 0; cachenum < s_cache.size(); s_cache[cachenum++].reset()) { } + for (auto &cached : s_cache) + cached.reset(); } - archive_file::error initialize(); + std::error_condition initialize() noexcept; - int first_file() { return search(0, 0, std::string(), false, false, false); } - int next_file() { return (m_curr_file_idx < 0) ? -1 : search(m_curr_file_idx + 1, 0, std::string(), false, false, false); } + int first_file() noexcept + { + return search(0, 0, std::string_view(), false, false, false); + } - int search(std::uint32_t crc) + int next_file() noexcept { - return search(0, crc, std::string(), true, false, false); + return (m_curr_file_idx < 0) ? -1 : search(m_curr_file_idx + 1, 0, std::string_view(), false, false, false); } - int search(const std::string &filename, bool partialpath) + + int search(std::uint32_t crc) noexcept + { + return search(0, crc, std::string_view(), true, false, false); + } + + int search(std::string_view filename, bool partialpath) noexcept { return search(0, 0, filename, false, true, partialpath); } - int search(std::uint32_t crc, const std::string &filename, bool partialpath) + + int search(std::uint32_t crc, std::string_view filename, bool partialpath) noexcept { return search(0, crc, filename, true, true, partialpath); } - bool current_is_directory() const { return m_curr_is_dir; } - const std::string ¤t_name() const { return m_curr_name; } - std::uint64_t current_uncompressed_length() const { return m_curr_length; } - virtual std::chrono::system_clock::time_point current_last_modified() const { return m_curr_modified; } - std::uint32_t current_crc() const { return m_curr_crc; } + bool current_is_directory() const noexcept { return m_curr_is_dir; } + const std::string ¤t_name() const noexcept { return m_curr_name; } + std::uint64_t current_uncompressed_length() const noexcept { return m_curr_length; } + virtual std::chrono::system_clock::time_point current_last_modified() const noexcept { return m_curr_modified; } + std::uint32_t current_crc() const noexcept { return m_curr_crc; } - archive_file::error decompress(void *buffer, std::uint32_t length); + std::error_condition decompress(void *buffer, std::size_t length) noexcept; private: m7z_file_impl(const m7z_file_impl &) = delete; @@ -166,12 +205,12 @@ private: int search( int i, std::uint32_t search_crc, - const std::string &search_filename, + std::string_view search_filename, bool matchcrc, bool matchname, - bool partialpath); + bool partialpath) noexcept; void make_utf8_name(int index); - void set_curr_modified(); + void set_curr_modified() noexcept; static constexpr std::size_t CACHE_SIZE = 8; static std::array s_cache; @@ -187,7 +226,7 @@ private: std::uint32_t m_curr_crc; // current file crc std::vector m_utf16_buf; - std::vector m_uchar_buf; + std::vector m_uchar_buf; std::vector m_utf8_buf; CFileInStream m_archive_stream; @@ -201,39 +240,38 @@ private: UInt32 m_block_index; Byte * m_out_buffer; std::size_t m_out_buffer_size; - }; class m7z_file_wrapper : public archive_file { public: - m7z_file_wrapper(m7z_file_impl::ptr &&impl) : m_impl(std::move(impl)) { assert(m_impl); } + m7z_file_wrapper(m7z_file_impl::ptr &&impl) noexcept : m_impl(std::move(impl)) { assert(m_impl); } virtual ~m7z_file_wrapper() override { m7z_file_impl::close(std::move(m_impl)); } - virtual int first_file() override { return m_impl->first_file(); } - virtual int next_file() override { return m_impl->next_file(); } + virtual int first_file() noexcept override { return m_impl->first_file(); } + virtual int next_file() noexcept override { return m_impl->next_file(); } - virtual int search(std::uint32_t crc) override + virtual int search(std::uint32_t crc) noexcept override { return m_impl->search(crc); } - virtual int search(const std::string &filename, bool partialpath) override + virtual int search(std::string_view filename, bool partialpath) noexcept override { return m_impl->search(filename, partialpath); } - virtual int search(std::uint32_t crc, const std::string &filename, bool partialpath) override + virtual int search(std::uint32_t crc, std::string_view filename, bool partialpath) noexcept override { return m_impl->search(crc, filename, partialpath); } - virtual bool current_is_directory() const override { return m_impl->current_is_directory(); } - 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::chrono::system_clock::time_point current_last_modified() const override { return m_impl->current_last_modified(); } - virtual std::uint32_t current_crc() const override { return m_impl->current_crc(); } + virtual bool current_is_directory() const noexcept override { return m_impl->current_is_directory(); } + virtual const std::string ¤t_name() const noexcept override { return m_impl->current_name(); } + virtual std::uint64_t current_uncompressed_length() const noexcept override { return m_impl->current_uncompressed_length(); } + virtual std::chrono::system_clock::time_point current_last_modified() const noexcept override { return m_impl->current_last_modified(); } + virtual std::uint32_t current_crc() const noexcept override { return m_impl->current_crc(); } - virtual error decompress(void *buffer, std::uint32_t length) override { return m_impl->decompress(buffer, length); } + virtual std::error_condition decompress(void *buffer, std::size_t length) noexcept override { return m_impl->decompress(buffer, length); } private: m7z_file_impl::ptr m_impl; @@ -250,49 +288,21 @@ std::mutex m7z_file_impl::s_cache_mutex; -/*************************************************************************** - 7Zip Memory / File handling (adapted from 7zfile.c/.h and 7zalloc.c/.h) -***************************************************************************/ - -/* ---------- FileInStream ---------- */ - -extern "C" { -static SRes FileInStream_Read(void *pp, void *buf, size_t *size) -{ - return (reinterpret_cast(pp)->read(buf, *size) == 0) ? SZ_OK : SZ_ERROR_READ; -} - -static SRes FileInStream_Seek(void *pp, Int64 *pos, ESzSeek origin) -{ - return reinterpret_cast(pp)->seek(*pos, origin); -} - -} // extern "C" - - -CFileInStream::CFileInStream() -{ - Read = &FileInStream_Read; - Seek = &FileInStream_Seek; -} - - - /*************************************************************************** CACHE MANAGEMENT ***************************************************************************/ -m7z_file_impl::m7z_file_impl(const std::string &filename) - : m_filename(filename) +m7z_file_impl::m7z_file_impl(std::string &&filename) noexcept + : m_filename(std::move(filename)) , m_curr_file_idx(-1) , m_curr_is_dir(false) , m_curr_name() , m_curr_length(0) , m_curr_modified() , m_curr_crc(0) - , m_utf16_buf(128) - , m_uchar_buf(128) - , m_utf8_buf(512) + , m_utf16_buf() + , m_uchar_buf() + , m_utf8_buf() , m_inited(false) , m_block_index(0) , m_out_buffer(nullptr) @@ -310,15 +320,45 @@ m7z_file_impl::m7z_file_impl(const std::string &filename) } -archive_file::error m7z_file_impl::initialize() +std::error_condition m7z_file_impl::initialize() noexcept { - 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 archive_file::error::FILE_ERROR; + try + { + if (m_utf16_buf.size() < 128) + m_utf16_buf.resize(128); + if (m_uchar_buf.size() < 128) + m_uchar_buf.resize(128); + m_utf8_buf.reserve(512); + } + catch (...) + { + return std::errc::not_enough_memory; + } - osd_printf_verbose("un7z: opened archive file %s\n", m_filename); + if (!m_archive_stream.file) + { + osd_file::ptr file; + std::error_condition const err = osd_file::open(m_filename, OPEN_FLAG_READ, file, m_archive_stream.length); + if (err) + return err; + m_archive_stream.file = osd_file_read(std::move(file)); + osd_printf_verbose("un7z: opened archive file %s\n", m_filename); + } + else if (!m_archive_stream.length) + { + std::error_condition const err = m_archive_stream.file->length(m_archive_stream.length); + if (err) + { + osd_printf_verbose( + "un7z: error getting length of archive file %s (%s:%d %s)\n", + m_filename, err.category().name(), err.value(), err.message()); + return err; + } + } - CrcGenerateTable(); // FIXME: doesn't belong here - it should be called once statically + // TODO: coordinate this with other LZMA users in the codebase? + struct crc_table_generator { crc_table_generator() { CrcGenerateTable(); } }; + static crc_table_generator crc_table; SzArEx_Init(&m_db); m_inited = true; @@ -329,13 +369,13 @@ archive_file::error m7z_file_impl::initialize() switch (res) { case SZ_ERROR_UNSUPPORTED: return archive_file::error::UNSUPPORTED; - case SZ_ERROR_MEM: return archive_file::error::OUT_OF_MEMORY; + case SZ_ERROR_MEM: return std::errc::not_enough_memory; case SZ_ERROR_INPUT_EOF: return archive_file::error::FILE_TRUNCATED; - default: return archive_file::error::FILE_ERROR; + default: return std::errc::io_error; // TODO: better default error? } } - return archive_file::error::NONE; + return std::error_condition(); } @@ -344,33 +384,38 @@ archive_file::error m7z_file_impl::initialize() to the cache -------------------------------------------------*/ -void m7z_file_impl::close(ptr &&archive) +void m7z_file_impl::close(ptr &&archive) noexcept { - if (!archive) return; + // if the filename isn't empty, the implementation can be cached + if (archive && !archive->m_filename.empty()) + { + // close the open files + osd_printf_verbose("un7z: closing archive file %s and sending to cache\n", archive->m_filename); + archive->m_archive_stream.file.reset(); - // close the open files - osd_printf_verbose("un7z: closing archive file %s and sending to cache\n", archive->m_filename); - archive->m_archive_stream.osdfile.reset(); + // find the first nullptr entry in the cache + std::lock_guard guard(s_cache_mutex); + std::size_t cachenum; + for (cachenum = 0; cachenum < s_cache.size(); cachenum++) + if (!s_cache[cachenum]) + break; - // find the first nullptr entry in the cache - std::lock_guard guard(s_cache_mutex); - 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()) + { + cachenum--; + osd_printf_verbose("un7z: removing %s from cache to make space\n", s_cache[cachenum]->m_filename); + s_cache[cachenum].reset(); + } - // if no room left in the cache, free the bottommost entry - if (cachenum == s_cache.size()) - { - cachenum--; - osd_printf_verbose("un7z: removing %s from cache to make space\n", s_cache[cachenum]->m_filename); - 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); } - // 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); + // make sure it's cleaned up + archive.reset(); } @@ -384,7 +429,7 @@ void m7z_file_impl::close(ptr &&archive) from a _7Z into the target buffer -------------------------------------------------*/ -archive_file::error m7z_file_impl::decompress(void *buffer, std::uint32_t length) +std::error_condition m7z_file_impl::decompress(void *buffer, std::size_t length) noexcept { // if we don't have enough buffer, error if (length < m_curr_length) @@ -394,15 +439,19 @@ archive_file::error m7z_file_impl::decompress(void *buffer, std::uint32_t length } // make sure the file is open.. - if (!m_archive_stream.osdfile) + if (!m_archive_stream.file) { - 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) + m_archive_stream.currfpos = 0; // FIXME: should it really be changing the file pointer out from under LZMA? + osd_file::ptr file; + std::error_condition const err = osd_file::open(m_filename, OPEN_FLAG_READ, file, m_archive_stream.length); + if (err) { - osd_printf_error("un7z: error reopening archive file %s (%d)\n", m_filename, int(err)); - return archive_file::error::FILE_ERROR; + osd_printf_error( + "un7z: error reopening archive file %s (%s:%d %s)\n", + m_filename, err.category().name(), err.value(), err.message()); + return err; } + m_archive_stream.file = osd_file_read(std::move(file)); osd_printf_verbose("un7z: reopened archive file %s\n", m_filename); } @@ -419,7 +468,7 @@ archive_file::error m7z_file_impl::decompress(void *buffer, std::uint32_t length switch (res) { case SZ_ERROR_UNSUPPORTED: return archive_file::error::UNSUPPORTED; - case SZ_ERROR_MEM: return archive_file::error::OUT_OF_MEMORY; + case SZ_ERROR_MEM: return std::errc::not_enough_memory; case SZ_ERROR_INPUT_EOF: return archive_file::error::FILE_TRUNCATED; default: return archive_file::error::DECOMPRESS_ERROR; } @@ -427,45 +476,64 @@ archive_file::error m7z_file_impl::decompress(void *buffer, std::uint32_t length // copy to destination buffer std::memcpy(buffer, m_out_buffer + offset, (std::min)(length, out_size_processed)); - return archive_file::error::NONE; + return std::error_condition(); } int m7z_file_impl::search( int i, std::uint32_t search_crc, - const std::string &search_filename, + std::string_view search_filename, bool matchcrc, bool matchname, - bool partialpath) + bool partialpath) noexcept { - for ( ; i < m_db.NumFiles; i++) - { - make_utf8_name(i); - bool const is_dir(SzArEx_IsDir(&m_db, i)); - const std::uint64_t size(SzArEx_GetFileSize(&m_db, i)); - const std::uint32_t crc(m_db.CRCs.Vals[i]); - const bool crcmatch(SzBitArray_Check(m_db.CRCs.Defs, i) && (crc == search_crc)); - auto const partialoffset(m_utf8_buf.size() - 1 - search_filename.length()); - bool const partialpossible((m_utf8_buf.size() > (search_filename.length() + 1)) && (m_utf8_buf[partialoffset - 1] == '/')); - const bool namematch( - !core_stricmp(search_filename.c_str(), &m_utf8_buf[0]) || - (partialpath && partialpossible && !core_stricmp(search_filename.c_str(), &m_utf8_buf[partialoffset]))); - - const bool found = ((!matchcrc && !matchname) || !is_dir) && (!matchcrc || crcmatch) && (!matchname || namematch); - if (found) + try + { + for ( ; i < m_db.NumFiles; i++) { - m_curr_file_idx = i; - m_curr_is_dir = is_dir; - m_curr_name = &m_utf8_buf[0]; - m_curr_length = size; - set_curr_modified(); - m_curr_crc = crc; - - return i; + make_utf8_name(i); + bool const is_dir(SzArEx_IsDir(&m_db, i)); + const std::uint64_t size(SzArEx_GetFileSize(&m_db, i)); + const std::uint32_t crc(m_db.CRCs.Vals[i]); + + const bool crcmatch(SzBitArray_Check(m_db.CRCs.Defs, i) && (crc == search_crc)); + bool found; + if (!matchname) + { + found = !matchcrc || (crcmatch && !is_dir); + } + else + { + auto const partialoffset = m_utf8_buf.size() - search_filename.length(); + const bool namematch = + (search_filename.length() == m_utf8_buf.size()) && + (search_filename.empty() || !core_strnicmp(&search_filename[0], &m_utf8_buf[0], search_filename.length())); + bool const partialmatch = + partialpath && + ((m_utf8_buf.size() > search_filename.length()) && (m_utf8_buf[partialoffset - 1] == '/')) && + (search_filename.empty() || !core_strnicmp(&search_filename[0], &m_utf8_buf[partialoffset], search_filename.length())); + found = (!matchcrc || crcmatch) && (namematch || partialmatch); + } + + if (found) + { + // set the name first - resizing it can throw an exception, and we want the state to be consistent + m_curr_name.assign(m_utf8_buf.begin(), m_utf8_buf.end()); + m_curr_file_idx = i; + m_curr_is_dir = is_dir; + m_curr_length = size; + set_curr_modified(); + m_curr_crc = crc; + + return i; + } } } - + catch (...) + { + // allocation error handling name + } return -1; } @@ -475,14 +543,14 @@ 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)(m_utf16_buf.size(), len)); + m_utf16_buf.resize(std::max(m_utf16_buf.size(), len)); SzArEx_GetFileNameUtf16(&m_db, index, &m_utf16_buf[0]); - m_uchar_buf.resize((std::max)(m_uchar_buf.size(), len)); + m_uchar_buf.resize(std::max(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], (char16_t *)&m_utf16_buf[in_pos], len - in_pos); + const int used = uchar_from_utf16(&m_uchar_buf[out_pos], reinterpret_cast(&m_utf16_buf[in_pos]), len - in_pos); if (used < 0) { in_pos++; @@ -497,7 +565,7 @@ void m7z_file_impl::make_utf8_name(int index) } len = out_pos; - m_utf8_buf.resize((std::max)(m_utf8_buf.size(), 4 * len + 1)); + m_utf8_buf.resize((std::max)(m_utf8_buf.size(), 4 * len)); out_pos = 0; for (std::size_t in_pos = 0; in_pos < len; in_pos++) { @@ -508,30 +576,35 @@ void m7z_file_impl::make_utf8_name(int index) out_pos += produced; assert(out_pos < m_utf8_buf.size()); } - m_utf8_buf[out_pos++] = '\0'; m_utf8_buf.resize(out_pos); } -void m7z_file_impl::set_curr_modified() +void m7z_file_impl::set_curr_modified() noexcept { if (SzBitWithVals_Check(&m_db.MTime, m_curr_file_idx)) { CNtfsFileTime const &file_time(m_db.MTime.Vals[m_curr_file_idx]); - auto ticks = ntfs_duration_from_filetime(file_time.High, file_time.Low); - m_curr_modified = system_clock_time_point_from_ntfs_duration(ticks); - } - else - { - // FIXME: what do we do about a lack of time? + try + { + auto ticks = ntfs_duration_from_filetime(file_time.High, file_time.Low); + m_curr_modified = system_clock_time_point_from_ntfs_duration(ticks); + return; + } + catch (...) + { + } } + + // no modification time available, or out-of-range exception + m_curr_modified = std::chrono::system_clock::from_time_t(std::time_t(0)); } } // anonymous namespace -archive_file::error archive_file::open_7z(const std::string &filename, ptr &result) +std::error_condition archive_file::open_7z(std::string_view filename, ptr &result) noexcept { // ensure we start with a nullptr result result.reset(); @@ -542,21 +615,49 @@ archive_file::error archive_file::open_7z(const std::string &filename, ptr &resu if (!newimpl) { // allocate memory for the 7z file structure - try { newimpl = std::make_unique(filename); } - catch (...) { return error::OUT_OF_MEMORY; } - error const err = newimpl->initialize(); - if (err != error::NONE) return err; + try { newimpl = std::make_unique(std::string(filename)); } + catch (...) { return std::errc::not_enough_memory; } + auto const err = newimpl->initialize(); + if (err) + return err; } - try + // allocate the archive API wrapper + result.reset(new (std::nothrow) m7z_file_wrapper(std::move(newimpl))); + if (result) { - result = std::make_unique(std::move(newimpl)); - return error::NONE; + return std::error_condition(); } - catch (...) + else + { + m7z_file_impl::close(std::move(newimpl)); + return std::errc::not_enough_memory; + } +} + +std::error_condition archive_file::open_7z(random_read::ptr &&file, ptr &result) noexcept +{ + // ensure we start with a nullptr result + result.reset(); + + // allocate memory for the zip_file structure + m7z_file_impl::ptr newimpl(new (std::nothrow) m7z_file_impl(std::move(file))); + if (!newimpl) + return std::errc::not_enough_memory; + auto const err = newimpl->initialize(); + if (err) + return err; + + // allocate the archive API wrapper + result.reset(new (std::nothrow) m7z_file_wrapper(std::move(newimpl))); + if (result) + { + return std::error_condition(); + } + else { m7z_file_impl::close(std::move(newimpl)); - return error::OUT_OF_MEMORY; + return std::errc::not_enough_memory; } } @@ -566,7 +667,7 @@ archive_file::error archive_file::open_7z(const std::string &filename, ptr &resu cache and free all memory -------------------------------------------------*/ -void m7z_file_cache_clear() +void m7z_file_cache_clear() noexcept { // This is a trampoline called from unzip.cpp to avoid the need to have the zip and 7zip code in one file m7z_file_impl::cache_clear(); diff --git a/src/lib/util/unzip.cpp b/src/lib/util/unzip.cpp index a275cc7df06..d7df8fa5ce9 100644 --- a/src/lib/util/unzip.cpp +++ b/src/lib/util/unzip.cpp @@ -12,9 +12,11 @@ #include "corestr.h" #include "hashing.h" +#include "ioprocs.h" +#include "timeconv.h" + #include "osdcore.h" #include "osdfile.h" -#include "timeconv.h" #include "lzma/C/LzmaDec.h" @@ -23,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -34,31 +37,55 @@ namespace util { + namespace { + /*************************************************************************** TYPE DEFINITIONS ***************************************************************************/ +class archive_category_impl : public std::error_category +{ +public: + virtual char const *name() const noexcept override { return "archive"; } + + virtual std::string message(int condition) const override + { + using namespace std::literals; + static std::string_view const s_messages[] = { + "No error"sv, + "Bad archive signature"sv, + "Decompression error"sv, + "Archive file truncated"sv, + "Archive file corrupt"sv, + "Archive file uses unsupported features"sv, + "Buffer too small for data"sv }; + if ((0 <= condition) && (std::size(s_messages) > condition)) + return std::string(s_messages[condition]); + else + return "Unknown error"s; + } +}; + + class zip_file_impl { public: - typedef std::unique_ptr 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_curr_is_dir(false) - , m_buffer() + using ptr = std::unique_ptr; + + zip_file_impl(std::string &&filename) noexcept + : m_filename(std::move(filename)) { std::fill(m_buffer.begin(), m_buffer.end(), 0); } - static ptr find_cached(const std::string &filename) + zip_file_impl(random_read::ptr &&file) noexcept + : zip_file_impl(std::string()) + { + m_file = std::move(file); + } + + static ptr find_cached(std::string_view filename) noexcept { std::lock_guard guard(s_cache_mutex); for (std::size_t cachenum = 0; cachenum < s_cache.size(); cachenum++) @@ -66,27 +93,31 @@ public: // 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)) { + using std::swap; ptr result; - std::swap(s_cache[cachenum], result); + swap(s_cache[cachenum], result); osd_printf_verbose("unzip: found %s in cache\n", filename); return result; } } return ptr(); } - static void close(ptr &&zip); - static void cache_clear() + + static void close(ptr &&zip) noexcept; + + static void cache_clear() noexcept { // clear call cache entries std::lock_guard guard(s_cache_mutex); - for (std::size_t cachenum = 0; cachenum < s_cache.size(); s_cache[cachenum++].reset()) { } + for (auto &cached : s_cache) + cached.reset(); } - archive_file::error initialize() + std::error_condition initialize() noexcept { // read ecd data auto const ziperr = read_ecd(); - if (ziperr != archive_file::error::NONE) + if (ziperr) return ziperr; // verify that we can work with this zipfile (no disk spanning allowed) @@ -111,7 +142,7 @@ public: catch (...) { osd_printf_error("unzip: %s failed to allocate memory for central directory\n", m_filename); - return archive_file::error::OUT_OF_MEMORY; + return std::errc::not_enough_memory; } // read the central directory @@ -119,13 +150,15 @@ public: std::size_t cd_offs(0); while (cd_remaining) { - std::uint32_t const chunk(std::uint32_t((std::min)(std::numeric_limits::max(), cd_remaining))); - std::uint32_t read_length(0); - auto const filerr = m_file->read(&m_cd[cd_offs], m_ecd.cd_start_disk_offset + cd_offs, chunk, read_length); - if (filerr != osd_file::error::NONE) + std::size_t const chunk(std::size_t(std::min(std::numeric_limits::max(), cd_remaining))); + std::size_t read_length(0); + std::error_condition const filerr = m_file->read_at(m_ecd.cd_start_disk_offset + cd_offs, &m_cd[cd_offs], chunk, read_length); + if (filerr) { - osd_printf_error("unzip: %s error reading central directory (%d)\n", m_filename, int(filerr)); - return archive_file::error::FILE_ERROR; + osd_printf_error( + "unzip: %s error reading central directory (%s:%d %s)\n", + m_filename, filerr.category().name(), filerr.value(), filerr.message()); + return filerr; } if (!read_length) { @@ -137,39 +170,45 @@ public: } osd_printf_verbose("unzip: read %s central directory\n", m_filename); - return archive_file::error::NONE; + return std::error_condition(); } - int first_file() + int first_file() noexcept { m_cd_pos = 0; - return search(0, std::string(), false, false, false); + return search(0, std::string_view(), false, false, false); } - int next_file() + + int next_file() noexcept { - return search(0, std::string(), false, false, false); + return search(0, std::string_view(), false, false, false); } - int search(std::uint32_t crc) + int search(std::uint32_t crc) noexcept { m_cd_pos = 0; - return search(crc, std::string(), true, false, false); + return search(crc, std::string_view(), true, false, false); } - int search(const std::string &filename, bool partialpath) + + int search(std::string_view filename, bool partialpath) noexcept { m_cd_pos = 0; return search(0, filename, false, true, partialpath); } - int search(std::uint32_t crc, const std::string &filename, bool partialpath) + + int search(std::uint32_t crc, std::string_view filename, bool partialpath) noexcept { m_cd_pos = 0; return search(crc, filename, true, true, partialpath); } - bool current_is_directory() const { return m_curr_is_dir; } - const std::string ¤t_name() const { return m_header.file_name; } - std::uint64_t current_uncompressed_length() const { return m_header.uncompressed_length; } - std::chrono::system_clock::time_point current_last_modified() const + bool current_is_directory() const noexcept { return m_curr_is_dir; } + + const std::string ¤t_name() const noexcept { return m_header.file_name; } + + std::uint64_t current_uncompressed_length() const noexcept { return m_header.uncompressed_length; } + + std::chrono::system_clock::time_point current_last_modified() const noexcept { if (!m_header.modified_cached) { @@ -178,9 +217,10 @@ public: } return m_header.modified; } - std::uint32_t current_crc() const { return m_header.crc; } - archive_file::error decompress(void *buffer, std::uint32_t length); + std::uint32_t current_crc() const noexcept { return m_header.crc; } + + std::error_condition decompress(void *buffer, std::size_t length) noexcept; private: zip_file_impl(const zip_file_impl &) = delete; @@ -188,28 +228,43 @@ private: zip_file_impl &operator=(const zip_file_impl &) = delete; zip_file_impl &operator=(zip_file_impl &&) = delete; - int search(std::uint32_t search_crc, const std::string &search_filename, bool matchcrc, bool matchname, bool partialpath); + int search(std::uint32_t search_crc, std::string_view search_filename, bool matchcrc, bool matchname, bool partialpath) noexcept; - archive_file::error reopen() + std::error_condition reopen() noexcept { if (!m_file) { - auto const filerr = osd_file::open(m_filename, OPEN_FLAG_READ, m_file, m_length); - if (filerr != osd_file::error::NONE) + osd_file::ptr file; + auto const filerr = osd_file::open(m_filename, OPEN_FLAG_READ, file, m_length); + if (filerr) { // this would spam every time it looks for a non-existent archive, which is a lot - //osd_printf_error("unzip: error reopening archive file %s (%d)\n", m_filename, int(filerr)); - return archive_file::error::FILE_ERROR; + //osd_printf_error("unzip: error reopening archive file %s (%s:%d %s)\n", m_filename, filerr.category().name(), filerr.value(), filerr.message()); + return filerr; } - else + m_file = osd_file_read(std::move(file)); + if (!m_file) { - osd_printf_verbose("unzip: opened archive file %s\n", m_filename); + osd_printf_error("unzip: not enough memory to open archive file %s\n", m_filename); + return std::errc::not_enough_memory; } + osd_printf_verbose("unzip: opened archive file %s\n", m_filename); } - return archive_file::error::NONE; + else if (!m_length) + { + auto const filerr = m_file->length(m_length); + if (filerr) + { + osd_printf_verbose( + "unzip: error getting length of archive file %s (%s:%d %s)\n", + m_filename, filerr.category().name(), filerr.value(), filerr.message()); + return filerr; + } + } + return std::error_condition(); } - static std::chrono::system_clock::time_point decode_dos_time(std::uint16_t date, std::uint16_t time) + static std::chrono::system_clock::time_point decode_dos_time(std::uint16_t date, std::uint16_t time) noexcept { // FIXME: work out why this doesn't always work // negative tm_isdst should automatically determine whether DST is in effect for the date, @@ -228,16 +283,22 @@ private: } // ZIP file parsing - archive_file::error read_ecd(); - archive_file::error get_compressed_data_offset(std::uint64_t &offset); + std::error_condition read_ecd() noexcept; + std::error_condition get_compressed_data_offset(std::uint64_t &offset) noexcept; // decompression interfaces - archive_file::error decompress_data_type_0(std::uint64_t offset, void *buffer, std::uint32_t length); - archive_file::error decompress_data_type_8(std::uint64_t offset, void *buffer, std::uint32_t length); - archive_file::error decompress_data_type_14(std::uint64_t offset, void *buffer, std::uint32_t length); + std::error_condition decompress_data_type_0(std::uint64_t offset, void *buffer, std::size_t length) noexcept; + std::error_condition decompress_data_type_8(std::uint64_t offset, void *buffer, std::size_t length) noexcept; + std::error_condition decompress_data_type_14(std::uint64_t offset, void *buffer, std::size_t length) noexcept; struct file_header { + file_header() noexcept { } + file_header(file_header const &) = default; + file_header(file_header &&) noexcept = default; + file_header &operator=(file_header const &) = default; + file_header &operator=(file_header &&) noexcept = default; + 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 @@ -271,15 +332,15 @@ private: static std::mutex s_cache_mutex; 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 + random_read::ptr m_file; // file handle + std::uint64_t m_length = 0; // length of zip file ecd m_ecd; // end of central directory std::vector m_cd; // central directory raw data - std::uint32_t m_cd_pos; // position in central directory + std::uint32_t m_cd_pos = 0; // position in central directory file_header m_header; // current file header - bool m_curr_is_dir; // current file is directory + bool m_curr_is_dir = false; // current file is directory std::array m_buffer; // buffer for decompression }; @@ -288,32 +349,32 @@ private: class zip_file_wrapper : public archive_file { public: - zip_file_wrapper(zip_file_impl::ptr &&impl) : m_impl(std::move(impl)) { assert(m_impl); } + zip_file_wrapper(zip_file_impl::ptr &&impl) noexcept : m_impl(std::move(impl)) { assert(m_impl); } virtual ~zip_file_wrapper() { zip_file_impl::close(std::move(m_impl)); } - virtual int first_file() override { return m_impl->first_file(); } - virtual int next_file() override { return m_impl->next_file(); } + virtual int first_file() noexcept override { return m_impl->first_file(); } + virtual int next_file() noexcept override { return m_impl->next_file(); } - virtual int search(std::uint32_t crc) override + virtual int search(std::uint32_t crc) noexcept override { return m_impl->search(crc); } - virtual int search(const std::string &filename, bool partialpath) override + virtual int search(std::string_view filename, bool partialpath) noexcept override { return m_impl->search(filename, partialpath); } - virtual int search(std::uint32_t crc, const std::string &filename, bool partialpath) override + virtual int search(std::uint32_t crc, std::string_view filename, bool partialpath) noexcept override { return m_impl->search(crc, filename, partialpath); } - virtual bool current_is_directory() const override { return m_impl->current_is_directory(); } - 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::chrono::system_clock::time_point current_last_modified() const override { return m_impl->current_last_modified(); } - virtual std::uint32_t current_crc() const override { return m_impl->current_crc(); } + virtual bool current_is_directory() const noexcept override { return m_impl->current_is_directory(); } + virtual const std::string ¤t_name() const noexcept override { return m_impl->current_name(); } + virtual std::uint64_t current_uncompressed_length() const noexcept override { return m_impl->current_uncompressed_length(); } + virtual std::chrono::system_clock::time_point current_last_modified() const noexcept override { return m_impl->current_last_modified(); } + virtual std::uint32_t current_crc() const noexcept override { return m_impl->current_crc(); } - virtual error decompress(void *buffer, std::uint32_t length) override { return m_impl->decompress(buffer, length); } + virtual std::error_condition decompress(void *buffer, std::size_t length) noexcept override { return m_impl->decompress(buffer, length); } private: zip_file_impl::ptr m_impl; @@ -323,19 +384,19 @@ private: class reader_base { protected: - reader_base(void const *buf) : m_buffer(reinterpret_cast(buf)) { } + reader_base(void const *buf) noexcept : m_buffer(reinterpret_cast(buf)) { } - std::uint8_t read_byte(std::size_t offs) const + std::uint8_t read_byte(std::size_t offs) const noexcept { return m_buffer[offs]; } - std::uint16_t read_word(std::size_t offs) const + std::uint16_t read_word(std::size_t offs) const noexcept { return (std::uint16_t(m_buffer[offs + 1]) << 8) | (std::uint16_t(m_buffer[offs + 0]) << 0); } - std::uint32_t read_dword(std::size_t offs) const + std::uint32_t read_dword(std::size_t offs) const noexcept { return (std::uint32_t(m_buffer[offs + 3]) << 24) | @@ -343,7 +404,7 @@ protected: (std::uint32_t(m_buffer[offs + 1]) << 8) | (std::uint32_t(m_buffer[offs + 0]) << 0); } - std::uint64_t read_qword(std::size_t offs) const + std::uint64_t read_qword(std::size_t offs) const noexcept { return (std::uint64_t(m_buffer[offs + 7]) << 56) | @@ -371,17 +432,17 @@ protected: class extra_field_reader : private reader_base { public: - extra_field_reader(void const *buf, std::size_t len) : reader_base(buf), m_length(len) { } + extra_field_reader(void const *buf, std::size_t len) noexcept : reader_base(buf), m_length(len) { } - std::uint16_t header_id() const { return read_word(0x00); } - std::uint16_t data_size() const { return read_word(0x02); } - void const * data() const { return m_buffer + 0x04; } - extra_field_reader next() const { return extra_field_reader(m_buffer + total_length(), m_length - total_length()); } + std::uint16_t header_id() const noexcept { return read_word(0x00); } + std::uint16_t data_size() const noexcept { return read_word(0x02); } + void const * data() const noexcept { return m_buffer + 0x04; } + extra_field_reader next() const noexcept { return extra_field_reader(m_buffer + total_length(), m_length - total_length()); } - bool length_sufficient() const { return (m_length >= minimum_length()) && (m_length >= total_length()); } + bool length_sufficient() const noexcept { return (m_length >= minimum_length()) && (m_length >= total_length()); } - std::size_t total_length() const { return minimum_length() + data_size(); } - static std::size_t minimum_length() { return 0x04; } + std::size_t total_length() const noexcept { return minimum_length() + data_size(); } + static constexpr std::size_t minimum_length() { return 0x04; } private: std::size_t m_length; @@ -391,131 +452,131 @@ private: class local_file_header_reader : private reader_base { public: - local_file_header_reader(void const *buf) : reader_base(buf) { } - - std::uint32_t signature() const { return read_dword(0x00); } - std::uint8_t version_needed() const { return m_buffer[0x04]; } - std::uint8_t os_needed() const { return m_buffer[0x05]; } - std::uint16_t general_flag() const { return read_word(0x06); } - std::uint16_t compression_method() const { return read_word(0x08); } - std::uint16_t modified_time() const { return read_word(0x0a); } - std::uint16_t modified_date() const { return read_word(0x0c); } - std::uint32_t crc32() const { return read_dword(0x0e); } - std::uint32_t compressed_size() const { return read_dword(0x12); } - std::uint32_t uncompressed_size() const { return read_dword(0x16); } - std::uint16_t file_name_length() const { return read_word(0x1a); } - std::uint16_t extra_field_length() const { return read_word(0x1c); } + local_file_header_reader(void const *buf) noexcept : reader_base(buf) { } + + std::uint32_t signature() const noexcept { return read_dword(0x00); } + std::uint8_t version_needed() const noexcept { return m_buffer[0x04]; } + std::uint8_t os_needed() const noexcept { return m_buffer[0x05]; } + std::uint16_t general_flag() const noexcept { return read_word(0x06); } + std::uint16_t compression_method() const noexcept { return read_word(0x08); } + std::uint16_t modified_time() const noexcept { return read_word(0x0a); } + std::uint16_t modified_date() const noexcept { return read_word(0x0c); } + std::uint32_t crc32() const noexcept { return read_dword(0x0e); } + std::uint32_t compressed_size() const noexcept { return read_dword(0x12); } + std::uint32_t uncompressed_size() const noexcept { return read_dword(0x16); } + std::uint16_t file_name_length() const noexcept { return read_word(0x1a); } + std::uint16_t extra_field_length() const noexcept { return read_word(0x1c); } std::string file_name() const { return read_string(0x1e, file_name_length()); } void file_name(std::string &result) const { read_string(result, 0x1e, file_name_length()); } - extra_field_reader extra_field() const { return extra_field_reader(m_buffer + 0x1e + file_name_length(), extra_field_length()); } + extra_field_reader extra_field() const noexcept { return extra_field_reader(m_buffer + 0x1e + file_name_length(), extra_field_length()); } - bool signature_correct() const { return signature() == 0x04034b50; } + bool signature_correct() const noexcept { return signature() == 0x04034b50; } - std::size_t total_length() const { return minimum_length() + file_name_length() + extra_field_length(); } - static std::size_t minimum_length() { return 0x1e; } + std::size_t total_length() const noexcept { return minimum_length() + file_name_length() + extra_field_length(); } + static constexpr std::size_t minimum_length() { return 0x1e; } }; class central_dir_entry_reader : private reader_base { public: - central_dir_entry_reader(void const *buf) : reader_base(buf) { } - - std::uint32_t signature() const { return read_dword(0x00); } - std::uint8_t version_created() const { return m_buffer[0x04]; } - std::uint8_t os_created() const { return m_buffer[0x05]; } - std::uint8_t version_needed() const { return m_buffer[0x06]; } - std::uint8_t os_needed() const { return m_buffer[0x07]; } - std::uint16_t general_flag() const { return read_word(0x08); } - std::uint16_t compression_method() const { return read_word(0x0a); } - std::uint16_t modified_time() const { return read_word(0x0c); } - std::uint16_t modified_date() const { return read_word(0x0e); } - std::uint32_t crc32() const { return read_dword(0x10); } - std::uint32_t compressed_size() const { return read_dword(0x14); } - std::uint32_t uncompressed_size() const { return read_dword(0x18); } - std::uint16_t file_name_length() const { return read_word(0x1c); } - std::uint16_t extra_field_length() const { return read_word(0x1e); } - std::uint16_t file_comment_length() const { return read_word(0x20); } - std::uint16_t start_disk() const { return read_word(0x22); } - std::uint16_t int_file_attr() const { return read_word(0x24); } - std::uint32_t ext_file_attr() const { return read_dword(0x26); } - std::uint32_t header_offset() const { return read_dword(0x2a); } + central_dir_entry_reader(void const *buf) noexcept : reader_base(buf) { } + + std::uint32_t signature() const noexcept { return read_dword(0x00); } + std::uint8_t version_created() const noexcept { return m_buffer[0x04]; } + std::uint8_t os_created() const noexcept { return m_buffer[0x05]; } + std::uint8_t version_needed() const noexcept { return m_buffer[0x06]; } + std::uint8_t os_needed() const noexcept { return m_buffer[0x07]; } + std::uint16_t general_flag() const noexcept { return read_word(0x08); } + std::uint16_t compression_method() const noexcept { return read_word(0x0a); } + std::uint16_t modified_time() const noexcept { return read_word(0x0c); } + std::uint16_t modified_date() const noexcept { return read_word(0x0e); } + std::uint32_t crc32() const noexcept { return read_dword(0x10); } + std::uint32_t compressed_size() const noexcept { return read_dword(0x14); } + std::uint32_t uncompressed_size() const noexcept { return read_dword(0x18); } + std::uint16_t file_name_length() const noexcept { return read_word(0x1c); } + std::uint16_t extra_field_length() const noexcept { return read_word(0x1e); } + std::uint16_t file_comment_length() const noexcept { return read_word(0x20); } + std::uint16_t start_disk() const noexcept { return read_word(0x22); } + std::uint16_t int_file_attr() const noexcept { return read_word(0x24); } + std::uint32_t ext_file_attr() const noexcept { return read_dword(0x26); } + std::uint32_t header_offset() const noexcept { return read_dword(0x2a); } std::string file_name() const { return read_string(0x2e, file_name_length()); } void file_name(std::string &result) const { read_string(result, 0x2e, file_name_length()); } - extra_field_reader extra_field() const { return extra_field_reader(m_buffer + 0x2e + file_name_length(), extra_field_length()); } + extra_field_reader extra_field() const noexcept { return extra_field_reader(m_buffer + 0x2e + file_name_length(), extra_field_length()); } std::string file_comment() const { return read_string(0x2e + file_name_length() + extra_field_length(), file_comment_length()); } void file_comment(std::string &result) const { read_string(result, 0x2e + file_name_length() + extra_field_length(), file_comment_length()); } - bool signature_correct() const { return signature() == 0x02014b50; } + bool signature_correct() const noexcept { return signature() == 0x02014b50; } - std::size_t total_length() const { return minimum_length() + file_name_length() + extra_field_length() + file_comment_length(); } - static std::size_t minimum_length() { return 0x2e; } + std::size_t total_length() const noexcept { return minimum_length() + file_name_length() + extra_field_length() + file_comment_length(); } + static constexpr std::size_t minimum_length() { return 0x2e; } }; class ecd64_reader : private reader_base { public: - ecd64_reader(void const *buf) : reader_base(buf) { } - - std::uint32_t signature() const { return read_dword(0x00); } - std::uint64_t ecd64_size() const { return read_qword(0x04); } - std::uint8_t version_created() const { return m_buffer[0x0c]; } - std::uint8_t os_created() const { return m_buffer[0x0d]; } - std::uint8_t version_needed() const { return m_buffer[0x0e]; } - std::uint8_t os_needed() const { return m_buffer[0x0f]; } - std::uint32_t this_disk_no() const { return read_dword(0x10); } - std::uint32_t dir_start_disk() const { return read_dword(0x14); } - std::uint64_t dir_disk_entries() const { return read_qword(0x18); } - std::uint64_t dir_total_entries() const { return read_qword(0x20); } - std::uint64_t dir_size() const { return read_qword(0x28); } - std::uint64_t dir_offset() const { return read_qword(0x30); } - void const * extensible_data() const { return m_buffer + 0x38; } - - bool signature_correct() const { return signature() == 0x06064b50; } - - std::size_t total_length() const { return 0x0c + ecd64_size(); } - static std::size_t minimum_length() { return 0x38; } + ecd64_reader(void const *buf) noexcept : reader_base(buf) { } + + std::uint32_t signature() const noexcept { return read_dword(0x00); } + std::uint64_t ecd64_size() const noexcept { return read_qword(0x04); } + std::uint8_t version_created() const noexcept { return m_buffer[0x0c]; } + std::uint8_t os_created() const noexcept { return m_buffer[0x0d]; } + std::uint8_t version_needed() const noexcept { return m_buffer[0x0e]; } + std::uint8_t os_needed() const noexcept { return m_buffer[0x0f]; } + std::uint32_t this_disk_no() const noexcept { return read_dword(0x10); } + std::uint32_t dir_start_disk() const noexcept { return read_dword(0x14); } + std::uint64_t dir_disk_entries() const noexcept { return read_qword(0x18); } + std::uint64_t dir_total_entries() const noexcept { return read_qword(0x20); } + std::uint64_t dir_size() const noexcept { return read_qword(0x28); } + std::uint64_t dir_offset() const noexcept { return read_qword(0x30); } + void const * extensible_data() const noexcept { return m_buffer + 0x38; } + + bool signature_correct() const noexcept { return signature() == 0x06064b50; } + + std::size_t total_length() const noexcept { return 0x0c + ecd64_size(); } + static constexpr std::size_t minimum_length() { return 0x38; } }; class ecd64_locator_reader : private reader_base { public: - ecd64_locator_reader(void const *buf) : reader_base(buf) { } + ecd64_locator_reader(void const *buf) noexcept : reader_base(buf) { } - std::uint32_t signature() const { return read_dword(0x00); } - std::uint32_t ecd64_disk() const { return read_dword(0x04); } - std::uint64_t ecd64_offset() const { return read_qword(0x08); } - std::uint32_t total_disks() const { return read_dword(0x10); } + std::uint32_t signature() const noexcept { return read_dword(0x00); } + std::uint32_t ecd64_disk() const noexcept { return read_dword(0x04); } + std::uint64_t ecd64_offset() const noexcept { return read_qword(0x08); } + std::uint32_t total_disks() const noexcept { return read_dword(0x10); } - bool signature_correct() const { return signature() == 0x07064b50; } + bool signature_correct() const noexcept { return signature() == 0x07064b50; } - std::size_t total_length() const { return minimum_length(); } - static std::size_t minimum_length() { return 0x14; } + std::size_t total_length() const noexcept { return minimum_length(); } + static constexpr std::size_t minimum_length() { return 0x14; } }; class ecd_reader : private reader_base { public: - ecd_reader(void const *buf) : reader_base(buf) { } - - std::uint32_t signature() const { return read_dword(0x00); } - std::uint16_t this_disk_no() const { return read_word(0x04); } - std::uint16_t dir_start_disk() const { return read_word(0x06); } - std::uint16_t dir_disk_entries() const { return read_word(0x08); } - std::uint16_t dir_total_entries() const { return read_word(0x0a); } - std::uint32_t dir_size() const { return read_dword(0x0c); } - std::uint32_t dir_offset() const { return read_dword(0x10); } - std::uint16_t comment_length() const { return read_word(0x14); } + ecd_reader(void const *buf) noexcept : reader_base(buf) { } + + std::uint32_t signature() const noexcept { return read_dword(0x00); } + std::uint16_t this_disk_no() const noexcept { return read_word(0x04); } + std::uint16_t dir_start_disk() const noexcept { return read_word(0x06); } + std::uint16_t dir_disk_entries() const noexcept { return read_word(0x08); } + std::uint16_t dir_total_entries() const noexcept { return read_word(0x0a); } + std::uint32_t dir_size() const noexcept { return read_dword(0x0c); } + std::uint32_t dir_offset() const noexcept { return read_dword(0x10); } + std::uint16_t comment_length() const noexcept { return read_word(0x14); } std::string comment() const { return read_string(0x16, comment_length()); } void comment(std::string &result) const { read_string(result, 0x16, comment_length()); } - bool signature_correct() const { return signature() == 0x06054b50; } + bool signature_correct() const noexcept { return signature() == 0x06054b50; } - std::size_t total_length() const { return minimum_length() + comment_length(); } - static std::size_t minimum_length() { return 0x16; } + std::size_t total_length() const noexcept { return minimum_length() + comment_length(); } + static constexpr std::size_t minimum_length() { return 0x16; } }; @@ -525,7 +586,7 @@ public: template zip64_ext_info_reader( T const &header, - extra_field_reader const &field) + extra_field_reader const &field) noexcept : reader_base(field.data()) , m_uncompressed_size(header.uncompressed_size()) , m_compressed_size(header.compressed_size()) @@ -538,13 +599,13 @@ public: { } - std::uint64_t uncompressed_size() const { return ~m_uncompressed_size ? m_uncompressed_size : read_qword(0x00); } - std::uint64_t compressed_size() const { return ~m_compressed_size ? m_compressed_size : read_qword(m_offs_compressed_size); } - std::uint64_t header_offset() const { return ~m_header_offset ? m_header_offset : read_qword(m_offs_header_offset); } - std::uint32_t start_disk() const { return ~m_start_disk ? m_start_disk : read_dword(m_offs_start_disk); } + std::uint64_t uncompressed_size() const noexcept { return ~m_uncompressed_size ? m_uncompressed_size : read_qword(0x00); } + std::uint64_t compressed_size() const noexcept { return ~m_compressed_size ? m_compressed_size : read_qword(m_offs_compressed_size); } + std::uint64_t header_offset() const noexcept { return ~m_header_offset ? m_header_offset : read_qword(m_offs_header_offset); } + std::uint32_t start_disk() const noexcept { return ~m_start_disk ? m_start_disk : read_dword(m_offs_start_disk); } - std::size_t total_length() const { return minimum_length() + m_offs_end; } - static std::size_t minimum_length() { return 0x00; } + std::size_t total_length() const noexcept { return minimum_length() + m_offs_end; } + static constexpr std::size_t minimum_length() { return 0x00; } private: std::uint32_t m_uncompressed_size; @@ -562,15 +623,15 @@ private: class utf8_path_reader : private reader_base { public: - utf8_path_reader(extra_field_reader const &field) : reader_base(field.data()), m_length(field.data_size()) { } + utf8_path_reader(extra_field_reader const &field) noexcept : reader_base(field.data()), m_length(field.data_size()) { } - std::uint8_t version() const { return m_buffer[0]; } - std::uint32_t name_crc32() const { return read_dword(0x01); } + std::uint8_t version() const noexcept { return m_buffer[0]; } + std::uint32_t name_crc32() const noexcept { return read_dword(0x01); } std::string unicode_name() const { return read_string(0x05, m_length - 0x05); } void unicode_name(std::string &result) const { return read_string(result, 0x05, m_length - 0x05); } - std::size_t total_length() const { return m_length; } - static std::size_t minimum_length() { return 0x05; } + std::size_t total_length() const noexcept { return m_length; } + static constexpr std::size_t minimum_length() { return 0x05; } private: std::size_t m_length; @@ -580,17 +641,17 @@ private: class ntfs_tag_reader : private reader_base { public: - ntfs_tag_reader(void const *buf, std::size_t len) : reader_base(buf), m_length(len) { } + ntfs_tag_reader(void const *buf, std::size_t len) noexcept : reader_base(buf), m_length(len) { } - std::uint16_t tag() const { return read_word(0x00); } - std::uint16_t size() const { return read_word(0x02); } - void const * data() const { return m_buffer + 0x04; } - ntfs_tag_reader next() const { return ntfs_tag_reader(m_buffer + total_length(), m_length - total_length()); } + std::uint16_t tag() const noexcept { return read_word(0x00); } + std::uint16_t size() const noexcept { return read_word(0x02); } + void const * data() const noexcept { return m_buffer + 0x04; } + ntfs_tag_reader next() const noexcept { return ntfs_tag_reader(m_buffer + total_length(), m_length - total_length()); } - bool length_sufficient() const { return (m_length >= minimum_length()) && (m_length >= total_length()); } + bool length_sufficient() const noexcept { return (m_length >= minimum_length()) && (m_length >= total_length()); } - std::size_t total_length() const { return minimum_length() + size(); } - static std::size_t minimum_length() { return 0x04; } + std::size_t total_length() const noexcept { return minimum_length() + size(); } + static constexpr std::size_t minimum_length() { return 0x04; } private: std::size_t m_length; @@ -600,13 +661,13 @@ private: class ntfs_reader : private reader_base { public: - ntfs_reader(extra_field_reader const &field) : reader_base(field.data()), m_length(field.data_size()) { } + ntfs_reader(extra_field_reader const &field) noexcept : reader_base(field.data()), m_length(field.data_size()) { } - std::uint32_t reserved() const { return read_dword(0x00); } - ntfs_tag_reader tag1() const { return ntfs_tag_reader(m_buffer + 0x04, m_length - 4); } + std::uint32_t reserved() const noexcept { return read_dword(0x00); } + ntfs_tag_reader tag1() const noexcept { return ntfs_tag_reader(m_buffer + 0x04, m_length - 4); } - std::size_t total_length() const { return m_length; } - static std::size_t minimum_length() { return 0x08; } + std::size_t total_length() const noexcept { return m_length; } + static constexpr std::size_t minimum_length() { return 0x08; } private: std::size_t m_length; @@ -616,14 +677,14 @@ private: class ntfs_times_reader : private reader_base { public: - ntfs_times_reader(ntfs_tag_reader const &tag) : reader_base(tag.data()) { } + ntfs_times_reader(ntfs_tag_reader const &tag) noexcept : reader_base(tag.data()) { } - std::uint64_t mtime() const { return read_qword(0x00); } - std::uint64_t atime() const { return read_qword(0x08); } - std::uint64_t ctime() const { return read_qword(0x10); } + std::uint64_t mtime() const noexcept { return read_qword(0x00); } + std::uint64_t atime() const noexcept { return read_qword(0x08); } + std::uint64_t ctime() const noexcept { return read_qword(0x10); } - std::size_t total_length() const { return minimum_length(); } - static std::size_t minimum_length() { return 0x18; } + std::size_t total_length() const noexcept { return minimum_length(); } + static constexpr std::size_t minimum_length() { return 0x18; } }; @@ -632,16 +693,16 @@ class general_flag_reader public: general_flag_reader(std::uint16_t val) : m_value(val) { } - bool encrypted() const { return bool(m_value & 0x0001); } - bool implode_8k_dict() const { return bool(m_value & 0x0002); } - bool implode_3_trees() const { return bool(m_value & 0x0004); } - unsigned deflate_option() const { return unsigned((m_value >> 1) & 0x0003); } - bool lzma_eos_mark() const { return bool(m_value & 0x0002); } - bool use_descriptor() const { return bool(m_value & 0x0008); } - bool patch_data() const { return bool(m_value & 0x0020); } - bool strong_encryption() const { return bool(m_value & 0x0040); } - bool utf8_encoding() const { return bool(m_value & 0x0800); } - bool directory_encryption() const { return bool(m_value & 0x2000); } + bool encrypted() const noexcept { return bool(m_value & 0x0001); } + bool implode_8k_dict() const noexcept { return bool(m_value & 0x0002); } + bool implode_3_trees() const noexcept { return bool(m_value & 0x0004); } + unsigned deflate_option() const noexcept { return unsigned((m_value >> 1) & 0x0003); } + bool lzma_eos_mark() const noexcept { return bool(m_value & 0x0002); } + bool use_descriptor() const noexcept { return bool(m_value & 0x0008); } + bool patch_data() const noexcept { return bool(m_value & 0x0020); } + bool strong_encryption() const noexcept { return bool(m_value & 0x0040); } + bool utf8_encoding() const noexcept { return bool(m_value & 0x0800); } + bool directory_encryption() const noexcept { return bool(m_value & 0x2000); } private: std::uint16_t m_value; @@ -653,6 +714,8 @@ private: GLOBAL VARIABLES ***************************************************************************/ +archive_category_impl const f_archive_category_instance; + std::array zip_file_impl::s_cache; std::mutex zip_file_impl::s_cache_mutex; @@ -663,33 +726,38 @@ std::mutex zip_file_impl::s_cache_mutex; to the cache -------------------------------------------------*/ -void zip_file_impl::close(ptr &&zip) +void zip_file_impl::close(ptr &&zip) noexcept { - if (!zip) return; + // if the filename isn't empty, the cached directory can be reused + if (zip && !zip->m_filename.empty()) + { + // close the open files + osd_printf_verbose("unzip: closing archive file %s and sending to cache\n", zip->m_filename); + zip->m_file.reset(); - // close the open files - osd_printf_verbose("unzip: closing archive file %s and sending to cache\n", zip->m_filename); - zip->m_file.reset(); + // find the first nullptr entry in the cache + std::lock_guard guard(s_cache_mutex); + std::size_t cachenum; + for (cachenum = 0; cachenum < s_cache.size(); cachenum++) + if (!s_cache[cachenum]) + break; - // find the first nullptr entry in the cache - std::lock_guard guard(s_cache_mutex); - 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()) + { + cachenum--; + osd_printf_verbose("unzip: removing %s from cache to make space\n", s_cache[cachenum]->m_filename); + s_cache[cachenum].reset(); + } - // if no room left in the cache, free the bottommost entry - if (cachenum == s_cache.size()) - { - cachenum--; - osd_printf_verbose("unzip: removing %s from cache to make space\n", s_cache[cachenum]->m_filename); - 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(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); + // make sure it's cleaned up + zip.reset(); } @@ -702,7 +770,7 @@ void zip_file_impl::close(ptr &&zip) entry in the ZIP -------------------------------------------------*/ -int zip_file_impl::search(std::uint32_t search_crc, const std::string &search_filename, bool matchcrc, bool matchname, bool partialpath) +int zip_file_impl::search(std::uint32_t search_crc, std::string_view search_filename, bool matchcrc, bool matchname, bool partialpath) noexcept { // if we're at or past the end, we're done while ((m_cd_pos + central_dir_entry_reader::minimum_length()) <= m_ecd.cd_size) @@ -712,98 +780,123 @@ int zip_file_impl::search(std::uint32_t search_crc, const std::string &search_fi if (!reader.signature_correct() || ((m_cd_pos + reader.total_length()) > m_ecd.cd_size)) break; - // extract file header info - m_header.version_created = reader.version_created(); - m_header.version_needed = reader.version_needed(); - m_header.bit_flag = reader.general_flag(); - m_header.compression = reader.compression_method(); - m_header.crc = reader.crc32(); - m_header.compressed_length = reader.compressed_size(); - m_header.uncompressed_length = reader.uncompressed_size(); - m_header.start_disk_number = reader.start_disk(); - m_header.local_header_offset = reader.header_offset(); - - // don't immediately decode DOS timestamp - it's expensive - m_header.modified_date = reader.modified_date(); - m_header.modified_time = reader.modified_time(); - m_header.modified_cached = false; - - // advance the position - m_cd_pos += reader.total_length(); - - // copy the filename - bool is_utf8(general_flag_reader(m_header.bit_flag).utf8_encoding()); - reader.file_name(m_header.file_name); - - // walk the extra data - for (auto extra = reader.extra_field(); extra.length_sufficient(); extra = extra.next()) + // setting std::string can raise allocation exceptions + try { - // look for ZIP64 extended info - if ((extra.header_id() == 0x0001) && (extra.data_size() >= zip64_ext_info_reader::minimum_length())) + // extract file header info + file_header header; + header.version_created = reader.version_created(); + header.version_needed = reader.version_needed(); + header.bit_flag = reader.general_flag(); + header.compression = reader.compression_method(); + header.crc = reader.crc32(); + header.compressed_length = reader.compressed_size(); + header.uncompressed_length = reader.uncompressed_size(); + header.start_disk_number = reader.start_disk(); + header.local_header_offset = reader.header_offset(); + + // don't immediately decode DOS timestamp - it's expensive + header.modified_date = reader.modified_date(); + header.modified_time = reader.modified_time(); + header.modified_cached = false; + + // copy the filename + bool is_utf8(general_flag_reader(header.bit_flag).utf8_encoding()); + reader.file_name(header.file_name); + + // walk the extra data + for (auto extra = reader.extra_field(); extra.length_sufficient(); extra = extra.next()) { - zip64_ext_info_reader const ext64(reader, extra); - if (extra.data_size() >= ext64.total_length()) + // look for ZIP64 extended info + if ((extra.header_id() == 0x0001) && (extra.data_size() >= zip64_ext_info_reader::minimum_length())) { - m_header.compressed_length = ext64.compressed_size(); - m_header.uncompressed_length = ext64.uncompressed_size(); - m_header.start_disk_number = ext64.start_disk(); - m_header.local_header_offset = ext64.header_offset(); + zip64_ext_info_reader const ext64(reader, extra); + if (extra.data_size() >= ext64.total_length()) + { + header.compressed_length = ext64.compressed_size(); + header.uncompressed_length = ext64.uncompressed_size(); + header.start_disk_number = ext64.start_disk(); + header.local_header_offset = ext64.header_offset(); + } } - } - // look for Info-ZIP UTF-8 path - if (!is_utf8 && (extra.header_id() == 0x7075) && (extra.data_size() >= utf8_path_reader::minimum_length())) - { - utf8_path_reader const utf8path(extra); - if (utf8path.version() == 1) + // look for Info-ZIP UTF-8 path + if (!is_utf8 && (extra.header_id() == 0x7075) && (extra.data_size() >= utf8_path_reader::minimum_length())) { - auto const addr(m_header.file_name.empty() ? nullptr : &m_header.file_name[0]); - auto const length(m_header.file_name.empty() ? 0 : m_header.file_name.length() * sizeof(m_header.file_name[0])); - auto const crc(crc32_creator::simple(addr, length)); - if (utf8path.name_crc32() == crc.m_raw) + utf8_path_reader const utf8path(extra); + if (utf8path.version() == 1) { - utf8path.unicode_name(m_header.file_name); - is_utf8 = true; + auto const addr(header.file_name.empty() ? nullptr : &header.file_name[0]); + auto const length(header.file_name.empty() ? 0 : header.file_name.length() * sizeof(header.file_name[0])); + auto const crc(crc32_creator::simple(addr, length)); + if (utf8path.name_crc32() == crc.m_raw) + { + utf8path.unicode_name(header.file_name); + is_utf8 = true; + } } } - } - // look for NTFS extra field - if ((extra.header_id() == 0x000a) && (extra.data_size() >= ntfs_reader::minimum_length())) - { - ntfs_reader const ntfs(extra); - for (auto tag = ntfs.tag1(); tag.length_sufficient(); tag = tag.next()) + // look for NTFS extra field + if ((extra.header_id() == 0x000a) && (extra.data_size() >= ntfs_reader::minimum_length())) { - if ((tag.tag() == 0x0001) && (tag.size() >= ntfs_times_reader::minimum_length())) + ntfs_reader const ntfs(extra); + for (auto tag = ntfs.tag1(); tag.length_sufficient(); tag = tag.next()) { - ntfs_times_reader const times(tag); - ntfs_duration const ticks(times.mtime()); - m_header.modified = system_clock_time_point_from_ntfs_duration(ticks); - m_header.modified_cached = true; + if ((tag.tag() == 0x0001) && (tag.size() >= ntfs_times_reader::minimum_length())) + { + ntfs_times_reader const times(tag); + ntfs_duration const ticks(times.mtime()); + try + { + header.modified = system_clock_time_point_from_ntfs_duration(ticks); + header.modified_cached = true; + } + catch (...) + { + // out-of-range exception - let it fall back to DOS-style timestamp + } + } } } } - } - // FIXME: if (!is_utf8) convert filename to UTF8 (assume CP437 or something) + // FIXME: if (!is_utf8) convert filename to UTF8 (assume CP437 or something) - // chop off trailing slash for directory entries - bool const is_dir(!m_header.file_name.empty() && (m_header.file_name.back() == '/')); - if (is_dir) m_header.file_name.resize(m_header.file_name.length() - 1); + // chop off trailing slash for directory entries + bool const is_dir(!header.file_name.empty() && (header.file_name.back() == '/')); + if (is_dir) + header.file_name.resize(header.file_name.length() - 1); - // check to see if it matches query - bool const crcmatch(search_crc == m_header.crc); - auto const partialoffset(m_header.file_name.length() - search_filename.length()); - bool const partialpossible((m_header.file_name.length() > search_filename.length()) && (m_header.file_name[partialoffset - 1] == '/')); - const bool namematch( - !core_stricmp(search_filename.c_str(), m_header.file_name.c_str()) || - (partialpath && partialpossible && !core_stricmp(search_filename.c_str(), m_header.file_name.c_str() + partialoffset))); + // advance the position + m_header = std::move(header); + m_curr_is_dir = is_dir; + m_cd_pos += reader.total_length(); + } + catch (...) + { + break; + } - bool const found = ((!matchcrc && !matchname) || !is_dir) && (!matchcrc || crcmatch) && (!matchname || namematch); - if (found) + // quick return if not required to match on name + if (!matchname) { - m_curr_is_dir = is_dir; - return 0; + if (!matchcrc || ((search_crc == m_header.crc) && !m_curr_is_dir)) + return 0; + } + else if (!m_curr_is_dir) + { + // check to see if it matches query + auto const partialoffset = m_header.file_name.length() - search_filename.length(); + const bool namematch = + (search_filename.length() == m_header.file_name.length()) && + (search_filename.empty() || !core_strnicmp(&search_filename[0], &m_header.file_name[0], search_filename.length())); + bool const partialmatch = + partialpath && + ((m_header.file_name.length() > search_filename.length()) && (m_header.file_name[partialoffset - 1] == '/')) && + (search_filename.empty() || !core_strnicmp(&search_filename[0], &m_header.file_name[partialoffset], search_filename.length())); + if ((!matchcrc || (search_crc == m_header.crc)) && (namematch || partialmatch)) + return 0; } } return -1; @@ -815,11 +908,8 @@ int zip_file_impl::search(std::uint32_t search_crc, const std::string &search_fi from a ZIP into the target buffer -------------------------------------------------*/ -archive_file::error zip_file_impl::decompress(void *buffer, std::uint32_t length) +std::error_condition zip_file_impl::decompress(void *buffer, std::size_t length) noexcept { - archive_file::error ziperr; - std::uint64_t offset; - // if we don't have enough buffer, error if (length < m_header.uncompressed_length) { @@ -835,33 +925,29 @@ archive_file::error zip_file_impl::decompress(void *buffer, std::uint32_t length } // get the compressed data offset - ziperr = get_compressed_data_offset(offset); - if (ziperr != archive_file::error::NONE) + std::uint64_t offset; + auto const ziperr = get_compressed_data_offset(offset); + if (ziperr) return ziperr; // handle compression types switch (m_header.compression) { case 0: - ziperr = decompress_data_type_0(offset, buffer, length); - break; + return decompress_data_type_0(offset, buffer, length); case 8: - ziperr = decompress_data_type_8(offset, buffer, length); - break; + return decompress_data_type_8(offset, buffer, length); case 14: - ziperr = decompress_data_type_14(offset, buffer, length); - break; + return decompress_data_type_14(offset, buffer, length); default: osd_printf_error( "unzip: %s in %s uses unsupported compression method %u\n", - m_header.file_name.c_str(), m_filename.c_str(), m_header.compression); - ziperr = archive_file::error::UNSUPPORTED; - break; + m_header.file_name, m_filename, m_header.compression); + return archive_file::error::UNSUPPORTED; } - return ziperr; } @@ -874,16 +960,16 @@ archive_file::error zip_file_impl::decompress(void *buffer, std::uint32_t length read_ecd - read the ECD data -------------------------------------------------*/ -archive_file::error zip_file_impl::read_ecd() +std::error_condition zip_file_impl::read_ecd() noexcept { // make sure the file handle is open auto const ziperr = reopen(); - if (ziperr != archive_file::error::NONE) + if (ziperr) return ziperr; // we may need multiple tries - osd_file::error error; - std::uint32_t read_length; + std::error_condition filerr; + std::size_t read_length; std::uint32_t buflen = 1024; while (buflen < 65536) { @@ -893,19 +979,26 @@ archive_file::error zip_file_impl::read_ecd() // allocate buffer std::unique_ptr buffer; - try { buffer.reset(new std::uint8_t[buflen + 1]); } - catch (...) + buffer.reset(new (std::nothrow) std::uint8_t[buflen + 1]); + if (!buffer) { osd_printf_error("unzip: %s failed to allocate memory for ECD search\n", m_filename); - return archive_file::error::OUT_OF_MEMORY; + return std::errc::not_enough_memory; } // read in one buffers' worth of data - error = m_file->read(&buffer[0], m_length - buflen, buflen, read_length); - if ((error != osd_file::error::NONE) || (read_length != buflen)) + filerr = m_file->read_at(m_length - buflen, &buffer[0], buflen, read_length); + if (filerr) + { + osd_printf_error( + "unzip: error reading %s to search for ECD (%s:%d %s)\n", + m_filename, filerr.category().name(), filerr.value(), filerr.message()); + return filerr; + } + if (read_length != buflen) { - osd_printf_error("unzip: %s error reading file to search for ECD (%d)\n", m_filename, int(error)); - return archive_file::error::FILE_ERROR; + osd_printf_error("unzip: unexpectedly reached end-of-file while reading %s to search for ECD\n", m_filename); + return archive_file::error::FILE_TRUNCATED; } // find the ECD signature @@ -935,19 +1028,26 @@ archive_file::error zip_file_impl::read_ecd() if ((m_length - buflen + offset) < ecd64_locator_reader::minimum_length()) { osd_printf_verbose("unzip: %s too small to contain ZIP64 ECD locator\n", m_filename); - return archive_file::error::NONE; + return std::error_condition(); } // try to read the ZIP64 ECD locator - error = m_file->read( - &buffer[0], + filerr = m_file->read_at( m_length - buflen + offset - ecd64_locator_reader::minimum_length(), + &buffer[0], ecd64_locator_reader::minimum_length(), read_length); - if ((error != osd_file::error::NONE) || (read_length != ecd64_locator_reader::minimum_length())) + if (filerr) + { + osd_printf_error( + "unzip: error reading %s to search for ZIP64 ECD locator (%s:%d %s)\n", + m_filename, filerr.category().name(), filerr.value(), filerr.message()); + return filerr; + } + if (read_length != ecd64_locator_reader::minimum_length()) { - osd_printf_error("unzip: error reading %s to search for ZIP64 ECD locator (%d)\n", m_filename, int(error)); - return archive_file::error::FILE_ERROR; + osd_printf_error("unzip: unexpectedly reached end-of-file while reading %s to search for ZIP64 ECD locator\n", m_filename); + return archive_file::error::FILE_TRUNCATED; } // if the signature isn't correct, it's not a ZIP64 archive @@ -955,7 +1055,7 @@ archive_file::error zip_file_impl::read_ecd() if (!ecd64_loc_rd.signature_correct()) { osd_printf_verbose("unzip: %s has no ZIP64 ECD locator\n", m_filename); - return archive_file::error::NONE; + return std::error_condition(); } // check that the ZIP64 ECD is in this segment (assuming this segment is the last segment) @@ -966,11 +1066,13 @@ archive_file::error zip_file_impl::read_ecd() } // try to read the ZIP64 ECD - error = m_file->read(&buffer[0], ecd64_loc_rd.ecd64_offset(), ecd64_reader::minimum_length(), read_length); - if (error != osd_file::error::NONE) + filerr = m_file->read_at(ecd64_loc_rd.ecd64_offset(), &buffer[0], ecd64_reader::minimum_length(), read_length); + if (filerr) { - osd_printf_error("unzip: error reading %s ZIP64 ECD (%d)\n", m_filename, int(error)); - return archive_file::error::FILE_ERROR; + osd_printf_error( + "unzip: error reading %s ZIP64 ECD (%s:%d %s)\n", + m_filename, filerr.category().name(), filerr.value(), filerr.message()); + return filerr; } if (read_length != ecd64_reader::minimum_length()) { @@ -983,8 +1085,8 @@ archive_file::error zip_file_impl::read_ecd() if (!ecd64_rd.signature_correct()) { osd_printf_error( - "unzip: %s ZIP64 ECD has incorrect signature 0x%08lx\n", - m_filename.c_str(), long(ecd64_rd.signature())); + "unzip: %s ZIP64 ECD has incorrect signature 0x%08x\n", + m_filename, ecd64_rd.signature()); return archive_file::error::BAD_SIGNATURE; } if (ecd64_rd.total_length() < ecd64_reader::minimum_length()) @@ -996,7 +1098,7 @@ archive_file::error zip_file_impl::read_ecd() { osd_printf_error( "unzip: %s ZIP64 ECD requires unsupported version %u.%u\n", - m_filename.c_str(), unsigned(ecd64_rd.version_needed() / 10), unsigned(ecd64_rd.version_needed() % 10)); + m_filename, ecd64_rd.version_needed() / 10, ecd64_rd.version_needed() % 10); return archive_file::error::UNSUPPORTED; } osd_printf_verbose("unzip: found %s ZIP64 ECD\n", m_filename); @@ -1009,7 +1111,7 @@ archive_file::error zip_file_impl::read_ecd() m_ecd.cd_size = ecd64_rd.dir_size(); m_ecd.cd_start_disk_offset = ecd64_rd.dir_offset(); - return archive_file::error::NONE; + return std::error_condition(); } // didn't find it; free this buffer and expand our search @@ -1024,7 +1126,7 @@ archive_file::error zip_file_impl::read_ecd() } } osd_printf_error("unzip: %s couldn't find ECD in last 64KiB\n", m_filename); - return archive_file::error::OUT_OF_MEMORY; + return archive_file::error::UNSUPPORTED; // TODO: revisit this error code } @@ -1033,7 +1135,7 @@ archive_file::error zip_file_impl::read_ecd() offset of the compressed data -------------------------------------------------*/ -archive_file::error zip_file_impl::get_compressed_data_offset(std::uint64_t &offset) +std::error_condition zip_file_impl::get_compressed_data_offset(std::uint64_t &offset) noexcept { // don't support a number of features general_flag_reader const flags(m_header.bit_flag); @@ -1046,7 +1148,7 @@ archive_file::error zip_file_impl::get_compressed_data_offset(std::uint64_t &off { osd_printf_error( "unzip: %s in %s requires unsupported version %u.%u\n", - m_header.file_name.c_str(), m_filename.c_str(), unsigned(m_header.version_needed / 10), unsigned(m_header.version_needed % 10)); + m_header.file_name, m_filename, m_header.version_needed / 10, m_header.version_needed % 10); return archive_file::error::UNSUPPORTED; } if (flags.encrypted() || flags.strong_encryption()) @@ -1062,24 +1164,24 @@ archive_file::error zip_file_impl::get_compressed_data_offset(std::uint64_t &off // make sure the file handle is open auto const ziperr = reopen(); - if (ziperr != archive_file::error::NONE) + if (ziperr) return ziperr; // 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, local_file_header_reader::minimum_length(), read_length); - if (error != osd_file::error::NONE) + std::size_t read_length; + std::error_condition const filerr = m_file->read_at(m_header.local_header_offset, &m_buffer[0], local_file_header_reader::minimum_length(), read_length); + if (filerr) { osd_printf_error( - "unzip: error reading local file header for %s in %s (%d)\n", - m_header.file_name.c_str(), m_filename.c_str(), int(error)); - return archive_file::error::FILE_ERROR; + "unzip: error reading local file header for %s in %s (%s:%d %s)\n", + m_header.file_name, m_filename, filerr.category().name(), filerr.value(), filerr.message()); + return filerr; } if (read_length != local_file_header_reader::minimum_length()) { osd_printf_error( "unzip: unexpectedly reached end-of-file while reading local file header for %s in %s\n", - m_header.file_name.c_str(), m_filename.c_str()); + m_header.file_name, m_filename); return archive_file::error::FILE_TRUNCATED; } @@ -1088,13 +1190,13 @@ archive_file::error zip_file_impl::get_compressed_data_offset(std::uint64_t &off if (!reader.signature_correct()) { osd_printf_error( - "unzip: local file header for %s in %s has incorrect signature %04lx\n", - m_header.file_name.c_str(), m_filename.c_str(), long(reader.signature())); + "unzip: local file header for %s in %s has incorrect signature %04x\n", + m_header.file_name, m_filename, reader.signature()); return archive_file::error::BAD_SIGNATURE; } offset = m_header.local_header_offset + reader.total_length(); - return archive_file::error::NONE; + return std::error_condition(); } @@ -1108,24 +1210,28 @@ archive_file::error zip_file_impl::get_compressed_data_offset(std::uint64_t &off type 0 data (which is uncompressed) -------------------------------------------------*/ -archive_file::error zip_file_impl::decompress_data_type_0(std::uint64_t offset, void *buffer, std::uint32_t length) +std::error_condition zip_file_impl::decompress_data_type_0(std::uint64_t offset, void *buffer, std::size_t length) noexcept { // the data is uncompressed; just read it - std::uint32_t read_length(0); - auto const filerr = m_file->read(buffer, offset, m_header.compressed_length, read_length); - if (filerr != osd_file::error::NONE) + std::size_t read_length(0); + std::error_condition const filerr = m_file->read_at(offset, buffer, m_header.compressed_length, read_length); + if (filerr) { - osd_printf_error("unzip: error reading %s from %s (%d)\n", m_header.file_name, m_filename, int(filerr)); - return archive_file::error::FILE_ERROR; + osd_printf_error( + "unzip: error reading %s from %s (%s:%d %s)\n", + m_header.file_name, m_filename, filerr.category().name(), filerr.value(), filerr.message()); + return filerr; } else if (read_length != m_header.compressed_length) { - osd_printf_error("unzip: unexpectedly reached end-of-file while reading %s from %s\n", m_header.file_name, m_filename); + osd_printf_error( + "unzip: unexpectedly reached end-of-file while reading %s from %s\n", + m_header.file_name, m_filename); return archive_file::error::FILE_TRUNCATED; } else { - return archive_file::error::NONE; + return std::error_condition(); } } @@ -1135,8 +1241,23 @@ archive_file::error zip_file_impl::decompress_data_type_0(std::uint64_t offset, type 8 data (which is deflated) -------------------------------------------------*/ -archive_file::error zip_file_impl::decompress_data_type_8(std::uint64_t offset, void *buffer, std::uint32_t length) +std::error_condition zip_file_impl::decompress_data_type_8(std::uint64_t offset, void *buffer, std::size_t length) noexcept { + auto const convert_zerr = + [] (int e) -> std::error_condition + { + switch (e) + { + case Z_OK: + return std::error_condition(); + case Z_ERRNO: + return std::error_condition(errno, std::generic_category()); + case Z_MEM_ERROR: + return std::errc::not_enough_memory; + default: + return archive_file::error::DECOMPRESS_ERROR; + } + }; std::uint64_t input_remaining = m_header.compressed_length; int zerr; @@ -1153,38 +1274,39 @@ archive_file::error zip_file_impl::decompress_data_type_8(std::uint64_t offset, zerr = inflateInit2(&stream, -MAX_WBITS); if (zerr != Z_OK) { + auto result = convert_zerr(zerr); osd_printf_error( "unzip: error allocating zlib stream to inflate %s from %s (%d)\n", - m_header.file_name.c_str(), m_filename.c_str(), zerr); - return archive_file::error::DECOMPRESS_ERROR; + m_header.file_name, m_filename, zerr); + return result; } // loop until we're done while (true) { // read in the next chunk of data - std::uint32_t read_length(0); - auto const filerr = m_file->read( - &m_buffer[0], + std::size_t read_length(0); + auto const filerr = m_file->read_at( offset, - std::uint32_t((std::min)(input_remaining, m_buffer.size())), + &m_buffer[0], + std::size_t((std::min)(input_remaining, m_buffer.size())), read_length); - if (filerr != osd_file::error::NONE) + if (filerr) { osd_printf_error( - "unzip: error reading compressed data for %s in %s (%d)\n", - m_header.file_name.c_str(), m_filename.c_str(), int(filerr)); + "unzip: error reading compressed data for %s in %s (%s:%d %s)\n", + m_header.file_name, m_filename, filerr.category().name(), filerr.value(), filerr.message()); inflateEnd(&stream); - return archive_file::error::FILE_ERROR; + return filerr; } offset += read_length; // if we read nothing, but still have data left, the file is truncated - if ((read_length == 0) && (input_remaining > 0)) + if (!read_length && input_remaining) { osd_printf_error( "unzip: unexpectedly reached end-of-file while reading compressed data for %s in %s\n", - m_header.file_name.c_str(), m_filename.c_str()); + m_header.file_name, m_filename); inflateEnd(&stream); return archive_file::error::FILE_TRUNCATED; } @@ -1206,9 +1328,12 @@ archive_file::error zip_file_impl::decompress_data_type_8(std::uint64_t offset, } else if (zerr != Z_OK) { - osd_printf_error("unzip: error inflating %s from %s (%d)\n", m_header.file_name, m_filename, zerr); + auto result = convert_zerr(zerr); + osd_printf_error( + "unzip: error inflating %s from %s (%d)\n", + m_header.file_name, m_filename, zerr); inflateEnd(&stream); - return archive_file::error::DECOMPRESS_ERROR; + return result; } } @@ -1216,20 +1341,23 @@ archive_file::error zip_file_impl::decompress_data_type_8(std::uint64_t offset, zerr = inflateEnd(&stream); if (zerr != Z_OK) { - osd_printf_error("unzip: error finishing inflation of %s from %s (%d)\n", m_header.file_name, m_filename, zerr); - return archive_file::error::DECOMPRESS_ERROR; + auto result = convert_zerr(zerr); + osd_printf_error( + "unzip: error finishing inflation of %s from %s (%d)\n", + m_header.file_name, m_filename, zerr); + return result; } // if anything looks funny, report an error - if ((stream.avail_out > 0) || (input_remaining > 0)) + if (stream.avail_out || input_remaining) { osd_printf_error( "unzip: inflation of %s from %s doesn't appear to have completed correctly\n", - m_header.file_name.c_str(), m_filename.c_str()); + m_header.file_name, m_filename); return archive_file::error::DECOMPRESS_ERROR; } - return archive_file::error::NONE; + return std::error_condition(); } @@ -1238,7 +1366,7 @@ archive_file::error zip_file_impl::decompress_data_type_8(std::uint64_t offset, type 14 data (LZMA) -------------------------------------------------*/ -archive_file::error zip_file_impl::decompress_data_type_14(std::uint64_t offset, void *buffer, std::uint32_t length) +std::error_condition zip_file_impl::decompress_data_type_14(std::uint64_t offset, void *buffer, std::size_t length) noexcept { // two-byte version // two-byte properties size (little-endian) @@ -1253,15 +1381,15 @@ archive_file::error zip_file_impl::decompress_data_type_14(std::uint64_t offset, SizeT output_remaining(length); std::uint64_t input_remaining(m_header.compressed_length); - std::uint32_t read_length; - osd_file::error filerr; + std::size_t read_length; + std::error_condition filerr; SRes lzerr; ELzmaStatus lzstatus(LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK); // reset the stream ISzAlloc alloc_imp; - alloc_imp.Alloc = [](void *p, std::size_t size) -> void * { return (size == 0) ? nullptr : std::malloc(size); }; - alloc_imp.Free = [](void *p, void *address) -> void { std::free(address); }; + alloc_imp.Alloc = [] (void *p, std::size_t size) -> void * { return size ? std::malloc(size) : nullptr; }; + alloc_imp.Free = [] (void *p, void *address) -> void { std::free(address); }; CLzmaDec stream; LzmaDec_Construct(&stream); @@ -1270,16 +1398,16 @@ archive_file::error zip_file_impl::decompress_data_type_14(std::uint64_t offset, { osd_printf_error( "unzip:compressed data for %s in %s is too small to hold LZMA properties header\n", - m_header.file_name.c_str(), m_filename.c_str()); + m_header.file_name, m_filename); return archive_file::error::DECOMPRESS_ERROR; } - filerr = m_file->read(&m_buffer[0], offset, 4, read_length); - if (filerr != osd_file::error::NONE) + filerr = m_file->read_at(offset, &m_buffer[0], 4, read_length); + if (filerr) { osd_printf_error( - "unzip: error reading LZMA properties header for %s in %s (%d)\n", - m_header.file_name.c_str(), m_filename.c_str(), int(filerr)); - return archive_file::error::FILE_ERROR; + "unzip: error reading LZMA properties header for %s in %s (%s:%d %s)\n", + m_header.file_name, m_filename, filerr.category().name(), filerr.value(), filerr.message()); + return filerr; } offset += read_length; input_remaining -= read_length; @@ -1287,7 +1415,7 @@ archive_file::error zip_file_impl::decompress_data_type_14(std::uint64_t offset, { osd_printf_error( "unzip: unexpectedly reached end-of-file while reading LZMA properties header for %s in %s\n", - m_header.file_name.c_str(), m_filename.c_str()); + m_header.file_name, m_filename); return archive_file::error::FILE_TRUNCATED; } std::uint16_t const props_size((std::uint16_t(m_buffer[3]) << 8) | std::uint16_t(m_buffer[2])); @@ -1295,23 +1423,23 @@ archive_file::error zip_file_impl::decompress_data_type_14(std::uint64_t offset, { osd_printf_error( "unzip: %s in %s has excessively large LZMA properties\n", - m_header.file_name.c_str(), m_filename.c_str()); + m_header.file_name, m_filename); return archive_file::error::UNSUPPORTED; } else if (props_size > input_remaining) { osd_printf_error( "unzip:compressed data for %s in %s is too small to hold LZMA properties\n", - m_header.file_name.c_str(), m_filename.c_str()); + m_header.file_name, m_filename); return archive_file::error::DECOMPRESS_ERROR; } - filerr = m_file->read(&m_buffer[0], offset, props_size, read_length); - if (filerr != osd_file::error::NONE) + filerr = m_file->read_at(offset, &m_buffer[0], props_size, read_length); + if (filerr) { osd_printf_error( - "unzip: error reading LZMA properties for %s in %s (%d)\n", - m_header.file_name.c_str(), m_filename.c_str(), int(filerr)); - return archive_file::error::FILE_ERROR; + "unzip: error reading LZMA properties for %s in %s (%s:%d %s)\n", + m_header.file_name, m_filename, filerr.category().name(), filerr.value(), filerr.message()); + return filerr; } offset += read_length; input_remaining -= read_length; @@ -1319,7 +1447,7 @@ archive_file::error zip_file_impl::decompress_data_type_14(std::uint64_t offset, { osd_printf_error( "unzip: unexpectedly reached end-of-file while reading LZMA properties for %s in %s\n", - m_header.file_name.c_str(), m_filename.c_str()); + m_header.file_name, m_filename); return archive_file::error::FILE_TRUNCATED; } @@ -1329,14 +1457,21 @@ archive_file::error zip_file_impl::decompress_data_type_14(std::uint64_t offset, { osd_printf_error( "unzip: memory error allocating LZMA decoder to decompress %s from %s\n", - m_header.file_name.c_str(), m_filename.c_str()); - return archive_file::error::OUT_OF_MEMORY; + m_header.file_name, m_filename); + return std::errc::not_enough_memory; + } + else if (SZ_ERROR_UNSUPPORTED) + { + osd_printf_error( + "unzip: LZMA decoder does not support properties for %s in %s\n", + m_header.file_name, m_filename); + return archive_file::error::UNSUPPORTED; } else if (SZ_OK != lzerr) { osd_printf_error( "unzip: error allocating LZMA decoder to decompress %s from %s (%d)\n", - m_header.file_name.c_str(), m_filename.c_str(), int(lzerr)); + m_header.file_name, m_filename, int(lzerr)); return archive_file::error::DECOMPRESS_ERROR; } LzmaDec_Init(&stream); @@ -1345,28 +1480,28 @@ archive_file::error zip_file_impl::decompress_data_type_14(std::uint64_t offset, while (0 < input_remaining) { // read in the next chunk of data - filerr = m_file->read( - &m_buffer[0], + filerr = m_file->read_at( offset, - std::uint32_t((std::min)(input_remaining, m_buffer.size())), + &m_buffer[0], + std::size_t((std::min)(input_remaining, m_buffer.size())), read_length); - if (filerr != osd_file::error::NONE) + if (filerr) { osd_printf_error( - "unzip: error reading compressed data for %s in %s (%d)\n", - m_header.file_name.c_str(), m_filename.c_str(), int(filerr)); + "unzip: error reading compressed data for %s in %s (%s)\n", + m_header.file_name, m_filename); LzmaDec_Free(&stream, &alloc_imp); - return archive_file::error::FILE_ERROR; + return filerr; } offset += read_length; input_remaining -= read_length; // if we read nothing, but still have data left, the file is truncated - if ((0 == read_length) && (0 < input_remaining)) + if (!read_length && input_remaining) { osd_printf_error( "unzip: unexpectedly reached end-of-file while reading compressed data for %s in %s\n", - m_header.file_name.c_str(), m_filename.c_str()); + m_header.file_name, m_filename); LzmaDec_Free(&stream, &alloc_imp); return archive_file::error::FILE_TRUNCATED; } @@ -1381,7 +1516,7 @@ archive_file::error zip_file_impl::decompress_data_type_14(std::uint64_t offset, &output_remaining, reinterpret_cast(&m_buffer[0]), &len, - ((0 == input_remaining) && eos_mark) ? LZMA_FINISH_END : LZMA_FINISH_ANY, + (!input_remaining && eos_mark) ? LZMA_FINISH_END : LZMA_FINISH_ANY, &lzstatus); if (SZ_OK != lzerr) { @@ -1397,25 +1532,25 @@ archive_file::error zip_file_impl::decompress_data_type_14(std::uint64_t offset, // if anything looks funny, report an error if (LZMA_STATUS_FINISHED_WITH_MARK == lzstatus) { - return archive_file::error::NONE; + return std::error_condition(); } else if (eos_mark) { osd_printf_error( "unzip: LZMA end mark not found for %s in %s (%d)\n", - m_header.file_name.c_str(), m_filename.c_str(), int(lzstatus)); + m_header.file_name, m_filename, int(lzstatus)); return archive_file::error::DECOMPRESS_ERROR; } else if (LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK != lzstatus) { osd_printf_error( "unzip: LZMA decompression of %s from %s doesn't appear to have completed correctly (%d)\n", - m_header.file_name.c_str(), m_filename.c_str(), int(lzstatus)); + m_header.file_name, m_filename, int(lzstatus)); return archive_file::error::DECOMPRESS_ERROR; } else { - return archive_file::error::NONE; + return std::error_condition(); } } @@ -1427,7 +1562,7 @@ archive_file::error zip_file_impl::decompress_data_type_14(std::uint64_t offset, un7z.cpp TRAMPOLINES ***************************************************************************/ -void m7z_file_cache_clear(); +void m7z_file_cache_clear() noexcept; @@ -1439,7 +1574,7 @@ void m7z_file_cache_clear(); zip_file_open - opens a ZIP file for reading -------------------------------------------------*/ -archive_file::error archive_file::open_zip(const std::string &filename, ptr &result) +std::error_condition archive_file::open_zip(std::string_view filename, ptr &result) noexcept { // ensure we start with a nullptr result result.reset(); @@ -1450,21 +1585,49 @@ archive_file::error archive_file::open_zip(const std::string &filename, ptr &res if (!newimpl) { // allocate memory for the zip_file structure - try { newimpl = std::make_unique(filename); } - catch (...) { return error::OUT_OF_MEMORY; } - auto const ziperr = newimpl->initialize(); - if (ziperr != error::NONE) return ziperr; + try { newimpl = std::make_unique(std::string(filename)); } + catch (...) { return std::errc::not_enough_memory; } + auto const err = newimpl->initialize(); + if (err) + return err; + } + + // allocate the archive API wrapper + result.reset(new (std::nothrow) zip_file_wrapper(std::move(newimpl))); + if (result) + { + return std::error_condition(); + } + else + { + zip_file_impl::close(std::move(newimpl)); + return std::errc::not_enough_memory; } +} - try +std::error_condition archive_file::open_zip(random_read::ptr &&file, ptr &result) noexcept +{ + // ensure we start with a nullptr result + result.reset(); + + // allocate memory for the zip_file structure + zip_file_impl::ptr newimpl(new (std::nothrow) zip_file_impl(std::move(file))); + if (!newimpl) + return std::errc::not_enough_memory; + auto const err = newimpl->initialize(); + if (err) + return err; + + // allocate the archive API wrapper + result.reset(new (std::nothrow) zip_file_wrapper(std::move(newimpl))); + if (result) { - result = std::make_unique(std::move(newimpl)); - return error::NONE; + return std::error_condition(); } - catch (...) + else { zip_file_impl::close(std::move(newimpl)); - return error::OUT_OF_MEMORY; + return std::errc::not_enough_memory; } } @@ -1474,7 +1637,7 @@ archive_file::error archive_file::open_zip(const std::string &filename, ptr &res cache and free all memory -------------------------------------------------*/ -void archive_file::cache_clear() +void archive_file::cache_clear() noexcept { zip_file_impl::cache_clear(); m7z_file_cache_clear(); @@ -1485,4 +1648,15 @@ archive_file::~archive_file() { } + +/*------------------------------------------------- + archive_category - gets the archive error + category instance +-------------------------------------------------*/ + +std::error_category const &archive_category() noexcept +{ + return f_archive_category_instance; +} + } // namespace util diff --git a/src/lib/util/unzip.h b/src/lib/util/unzip.h index b1ddb7a27d1..2108eadee28 100644 --- a/src/lib/util/unzip.h +++ b/src/lib/util/unzip.h @@ -7,19 +7,24 @@ archive file management. ***************************************************************************/ +#ifndef MAME_LIB_UTIL_UNZIP_H +#define MAME_LIB_UTIL_UNZIP_H #pragma once -#ifndef MAME_LIB_UTIL_UNZIP_H -#define MAME_LIB_UTIL_UNZIP_H +#include "utilfwd.h" #include #include #include #include +#include +#include +#include namespace util { + /*************************************************************************** TYPE DEFINITIONS ***************************************************************************/ @@ -30,12 +35,9 @@ class archive_file public: // Error types - enum class error + enum class error : int { - NONE = 0, - OUT_OF_MEMORY, - FILE_ERROR, - BAD_SIGNATURE, + BAD_SIGNATURE = 1, DECOMPRESS_ERROR, FILE_TRUNCATED, FILE_CORRUPT, @@ -49,40 +51,54 @@ public: /* ----- archive file access ----- */ // open a ZIP file and parse its central directory - static error open_zip(const std::string &filename, ptr &zip); + static std::error_condition open_zip(std::string_view filename, ptr &result) noexcept; + static std::error_condition open_zip(std::unique_ptr &&file, ptr &result) noexcept; // open a 7Z file and parse its central directory - static error open_7z(const std::string &filename, ptr &result); + static std::error_condition open_7z(std::string_view filename, ptr &result) noexcept; + static std::error_condition open_7z(std::unique_ptr &&file, ptr &result) noexcept; // close an archive file (may actually be left open due to caching) virtual ~archive_file(); // clear out all open files from the cache - static void cache_clear(); + static void cache_clear() noexcept; /* ----- contained file access ----- */ // iterating over files - returns negative on reaching end - virtual int first_file() = 0; - virtual int next_file() = 0; + virtual int first_file() noexcept = 0; + virtual int next_file() noexcept = 0; // find a file index by crc, filename or both - returns non-negative on match - virtual int search(std::uint32_t crc) = 0; - virtual int search(const std::string &filename, bool partialpath) = 0; - virtual int search(std::uint32_t crc, const std::string &filename, bool partialpath) = 0; + virtual int search(std::uint32_t crc) noexcept = 0; + virtual int search(std::string_view filename, bool partialpath) noexcept = 0; + virtual int search(std::uint32_t crc, std::string_view filename, bool partialpath) noexcept = 0; // information on most recently found file - virtual bool current_is_directory() const = 0; - virtual const std::string ¤t_name() const = 0; - virtual std::uint64_t current_uncompressed_length() const = 0; - virtual std::chrono::system_clock::time_point current_last_modified() const = 0; - virtual std::uint32_t current_crc() const = 0; + virtual bool current_is_directory() const noexcept = 0; + virtual const std::string ¤t_name() const noexcept = 0; + virtual std::uint64_t current_uncompressed_length() const noexcept = 0; + virtual std::chrono::system_clock::time_point current_last_modified() const noexcept = 0; + virtual std::uint32_t current_crc() const noexcept = 0; // decompress the most recently found file in the ZIP - virtual error decompress(void *buffer, std::uint32_t length) = 0; + virtual std::error_condition decompress(void *buffer, std::size_t length) noexcept = 0; }; + +// error category for archive errors +std::error_category const &archive_category() noexcept; +inline std::error_condition make_error_condition(archive_file::error err) noexcept { return std::error_condition(int(err), archive_category()); } + } // namespace util + +namespace std { + +template <> struct is_error_condition_enum : public std::true_type { }; + +} // namespace std + #endif // MAME_LIB_UTIL_UNZIP_H diff --git a/src/lib/util/utilfwd.h b/src/lib/util/utilfwd.h new file mode 100644 index 00000000000..fefe0631c68 --- /dev/null +++ b/src/lib/util/utilfwd.h @@ -0,0 +1,45 @@ +// license:BSD-3-Clause +// copyright-holders:Vas Crabb +/********************************************************************** + + utilfwd.h + + Forward declarations of types + +**********************************************************************/ +#ifndef MAME_LIB_UTIL_UTILFWD_H +#define MAME_LIB_UTIL_UTILFWD_H + +// chd.h +class chd_file; + + +namespace util { + +// corefile.h +class core_file; + +// ioprocs.h +class read_stream; +class write_stream; +class read_write_stream; +class random_access; +class random_read; +class random_write; +class random_read_write; + +// unzip.h +class archive_file; + +} // namespace util + + +namespace util::xml { + +// xmlfile.h +class data_node; +class file; + +} // namespace util::xml + +#endif // MAME_LIB_UTIL_UTILFWD_H diff --git a/src/lib/util/zippath.cpp b/src/lib/util/zippath.cpp index 023484010b8..f317319c8c3 100644 --- a/src/lib/util/zippath.cpp +++ b/src/lib/util/zippath.cpp @@ -9,13 +9,13 @@ ***************************************************************************/ #include "zippath.h" -#include "unzip.h" -#include "corestr.h" -#include +#include "corestr.h" +#include "unzip.h" #include #include +#include #include #include @@ -192,7 +192,7 @@ int zippath_find_sub_path(archive_file &zipfile, std::string_view subpath, osd:: // true path and ZIP entry components // ------------------------------------------------- -osd_file::error zippath_resolve(std::string_view path, osd::directory::entry::entry_type &entry_type, archive_file::ptr &zipfile, std::string &newpath) +std::error_condition zippath_resolve(std::string_view path, osd::directory::entry::entry_type &entry_type, archive_file::ptr &zipfile, std::string &newpath) { newpath.clear(); @@ -238,13 +238,13 @@ osd_file::error zippath_resolve(std::string_view path, osd::directory::entry::en if (current_entry_type == osd::directory::entry::entry_type::NONE) { entry_type = osd::directory::entry::entry_type::NONE; - return osd_file::error::NOT_FOUND; + return std::errc::no_such_file_or_directory; } // is this file a ZIP file? if ((current_entry_type == osd::directory::entry::entry_type::FILE) && - ((is_zip_file(apath_trimmed) && (archive_file::open_zip(apath_trimmed, zipfile) == archive_file::error::NONE)) || - (is_7z_file(apath_trimmed) && (archive_file::open_7z(apath_trimmed, zipfile) == archive_file::error::NONE)))) + ((is_zip_file(apath_trimmed) && !archive_file::open_zip(apath_trimmed, zipfile)) || + (is_7z_file(apath_trimmed) && !archive_file::open_7z(apath_trimmed, zipfile)))) { auto i = path.length() - apath.length(); while ((i > 0) && is_zip_path_separator(path[apath.length() + i - 1])) @@ -254,53 +254,20 @@ osd_file::error zippath_resolve(std::string_view path, osd::directory::entry::en // this was a true ZIP path - attempt to identify the type of path zippath_find_sub_path(*zipfile, newpath, current_entry_type); if (current_entry_type == osd::directory::entry::entry_type::NONE) - return osd_file::error::NOT_FOUND; + return std::errc::no_such_file_or_directory; } else { // this was a normal path if (went_up) - return osd_file::error::NOT_FOUND; + return std::errc::no_such_file_or_directory; newpath = path; } // success! entry_type = current_entry_type; - return osd_file::error::NONE; -} - - -// ------------------------------------------------- -// file_error_from_zip_error - translates a -// osd_file::error to a zip_error -// ------------------------------------------------- - -osd_file::error file_error_from_zip_error(archive_file::error ziperr) -{ - osd_file::error filerr; - switch(ziperr) - { - case archive_file::error::NONE: - filerr = osd_file::error::NONE; - break; - case archive_file::error::OUT_OF_MEMORY: - filerr = osd_file::error::OUT_OF_MEMORY; - break; - case archive_file::error::BAD_SIGNATURE: - case archive_file::error::DECOMPRESS_ERROR: - case archive_file::error::FILE_TRUNCATED: - case archive_file::error::FILE_CORRUPT: - case archive_file::error::UNSUPPORTED: - case archive_file::error::FILE_ERROR: - filerr = osd_file::error::INVALID_DATA; - break; - case archive_file::error::BUFFER_TOO_SMALL: - default: - filerr = osd_file::error::FAILURE; - break; - } - return filerr; + return std::error_condition(); } @@ -309,27 +276,24 @@ osd_file::error file_error_from_zip_error(archive_file::error ziperr) // from a zip file entry // ------------------------------------------------- -osd_file::error create_core_file_from_zip(archive_file &zip, util::core_file::ptr &file) +std::error_condition create_core_file_from_zip(archive_file &zip, util::core_file::ptr &file) { - osd_file::error filerr; - archive_file::error ziperr; + // TODO: would be more efficient if we could open a memory-based core_file with uninitialised contents and decompress into it + std::error_condition filerr; void *ptr = malloc(zip.current_uncompressed_length()); if (!ptr) { - filerr = osd_file::error::OUT_OF_MEMORY; + filerr = std::errc::not_enough_memory; goto done; } - ziperr = zip.decompress(ptr, zip.current_uncompressed_length()); - if (ziperr != archive_file::error::NONE) - { - filerr = file_error_from_zip_error(ziperr); + filerr = zip.decompress(ptr, zip.current_uncompressed_length()); + if (filerr) goto done; - } filerr = util::core_file::open_ram_copy(ptr, zip.current_uncompressed_length(), OPEN_FLAG_READ, file); - if (filerr != osd_file::error::NONE) + if (filerr) goto done; done: @@ -545,7 +509,7 @@ private: // zippath_directory::open - opens a directory // ------------------------------------------------- -osd_file::error zippath_directory::open(std::string_view path, ptr &directory) +std::error_condition zippath_directory::open(std::string_view path, ptr &directory) { try { @@ -553,34 +517,34 @@ osd_file::error zippath_directory::open(std::string_view path, ptr &directory) osd::directory::entry::entry_type entry_type; archive_file::ptr zipfile; std::string zipprefix; - osd_file::error const err = zippath_resolve(path, entry_type, zipfile, zipprefix); - if (osd_file::error::NONE != err) + std::error_condition const err = zippath_resolve(path, entry_type, zipfile, zipprefix); + if (err) return err; // we have to be a directory if (osd::directory::entry::entry_type::DIR != entry_type) - return osd_file::error::NOT_FOUND; + return std::errc::not_a_directory; // was the result a ZIP? if (zipfile) { directory = std::make_unique(std::move(zipfile), std::move(zipprefix)); - return osd_file::error::NONE; + return std::error_condition(); } else { // a conventional directory std::unique_ptr result(new filesystem_directory_impl(path)); if (!*result) - return osd_file::error::FAILURE; + return std::errc::io_error; // TODO: any way to give a better error here? directory = std::move(result); - return osd_file::error::NONE; + return std::error_condition(); } } catch (std::bad_alloc const &) { - return osd_file::error::OUT_OF_MEMORY; + return std::errc::not_enough_memory; } } @@ -681,7 +645,7 @@ std::string zippath_combine(const std::string &path1, const std::string &path2) // ------------------------------------------------- /** - * @fn osd_file::error zippath_fopen(std::string_view filename, uint32_t openflags, util::core_file::ptr &file, std::string &revised_path) + * @fn std::error_condition zippath_fopen(std::string_view filename, uint32_t openflags, util::core_file::ptr &file, std::string &revised_path) * * @brief Zippath fopen. * @@ -693,38 +657,35 @@ std::string zippath_combine(const std::string &path1, const std::string &path2) * @return A osd_file::error. */ -osd_file::error zippath_fopen(std::string_view filename, uint32_t openflags, util::core_file::ptr &file, std::string &revised_path) +std::error_condition zippath_fopen(std::string_view filename, uint32_t openflags, util::core_file::ptr &file, std::string &revised_path) { - osd_file::error filerr = osd_file::error::NOT_FOUND; - archive_file::error ziperr; + std::error_condition filerr = std::errc::no_such_file_or_directory; archive_file::ptr zip; - int header; - osd::directory::entry::entry_type entry_type; - int len; - /* first, set up the two types of paths */ + // first, set up the two types of paths std::string mainpath(filename); std::string subpath; file = nullptr; - /* loop through */ - while((file == nullptr) && (mainpath.length() > 0) - && ((openflags == OPEN_FLAG_READ) || subpath.empty())) + // loop through + while (!file && !mainpath.empty() && ((openflags == OPEN_FLAG_READ) || subpath.empty())) { - /* is the mainpath a ZIP path? */ + // is the mainpath a ZIP path? if (is_zip_file(mainpath) || is_7z_file(mainpath)) { - /* this file might be a zip file - lets take a look */ - ziperr = is_zip_file(mainpath) ? archive_file::open_zip(mainpath, zip) : archive_file::open_7z(mainpath, zip); - if (ziperr == archive_file::error::NONE) + // this file might be a zip file - lets take a look + std::error_condition const ziperr = is_zip_file(mainpath) ? archive_file::open_zip(mainpath, zip) : archive_file::open_7z(mainpath, zip); + if (!ziperr) { - /* it is a zip file - error if we're not opening for reading */ + // it is a zip file - error if we're not opening for reading if (openflags != OPEN_FLAG_READ) { - filerr = osd_file::error::ACCESS_DENIED; + filerr = std::errc::permission_denied; goto done; } + osd::directory::entry::entry_type entry_type; + int header; if (!subpath.empty()) header = zippath_find_sub_path(*zip, subpath, entry_type); else @@ -732,20 +693,20 @@ osd_file::error zippath_fopen(std::string_view filename, uint32_t openflags, uti if (header < 0) { - filerr = osd_file::error::NOT_FOUND; + filerr = std::errc::no_such_file_or_directory; goto done; } - /* attempt to read the file */ + // attempt to read the file filerr = create_core_file_from_zip(*zip, file); - if (filerr != osd_file::error::NONE) + if (filerr) goto done; - /* update subpath, if appropriate */ + // update subpath, if appropriate if (subpath.empty()) subpath.assign(zip->current_name()); - /* we're done */ + // we're done goto done; } } @@ -753,15 +714,15 @@ osd_file::error zippath_fopen(std::string_view filename, uint32_t openflags, uti if (subpath.empty()) filerr = util::core_file::open(std::string(filename), openflags, file); else - filerr = osd_file::error::NOT_FOUND; + filerr = std::errc::no_such_file_or_directory; - /* if we errored, then go up a directory */ - if (filerr != osd_file::error::NONE) + // if we errored, then go up a directory + if (filerr) { - /* go up a directory */ + // go up a directory auto temp = zippath_parent(mainpath); - /* append to the sub path */ + // append to the sub path if (!subpath.empty()) { std::string temp2; @@ -774,8 +735,8 @@ osd_file::error zippath_fopen(std::string_view filename, uint32_t openflags, uti mainpath = mainpath.substr(temp.length()); subpath.assign(mainpath); } - /* get the new main path, truncating path separators */ - len = temp.length(); + // get the new main path, truncating path separators + auto len = temp.length(); while (len > 0 && is_zip_file_separator(temp[len - 1])) len--; temp = temp.substr(0, len); @@ -784,14 +745,14 @@ osd_file::error zippath_fopen(std::string_view filename, uint32_t openflags, uti } done: - /* store the revised path */ + // store the revised path revised_path.clear(); - if (filerr == osd_file::error::NONE) + if (!filerr) { - /* canonicalize mainpath */ + // canonicalize mainpath std::string alloc_fullpath; filerr = osd_get_full_path(alloc_fullpath, mainpath); - if (filerr == osd_file::error::NONE) + if (!filerr) { revised_path = alloc_fullpath; if (!subpath.empty()) diff --git a/src/lib/util/zippath.h b/src/lib/util/zippath.h index 1eb92aa1c1d..955c75cfc8f 100644 --- a/src/lib/util/zippath.h +++ b/src/lib/util/zippath.h @@ -18,6 +18,7 @@ #include #include +#include namespace util { @@ -32,7 +33,7 @@ public: typedef std::unique_ptr ptr; // opens a directory - static osd_file::error open(std::string_view path, ptr &directory); + static std::error_condition open(std::string_view path, ptr &directory); // closes a directory virtual ~zippath_directory(); @@ -63,7 +64,7 @@ std::string zippath_combine(const std::string &path1, const std::string &path2); // ----- file operations ----- // opens a zip path file -osd_file::error zippath_fopen(std::string_view filename, uint32_t openflags, util::core_file::ptr &file, std::string &revised_path); +std::error_condition zippath_fopen(std::string_view filename, uint32_t openflags, util::core_file::ptr &file, std::string &revised_path); } // namespace util diff --git a/src/mame/drivers/aim65.cpp b/src/mame/drivers/aim65.cpp index 94870fd4f11..703c35146cb 100644 --- a/src/mame/drivers/aim65.cpp +++ b/src/mame/drivers/aim65.cpp @@ -184,7 +184,7 @@ image_init_result aim65_state::load_cart(device_image_interface &image, generic_ if (size > 0x1000) { - image.seterror(IMAGE_ERROR_UNSPECIFIED, "Unsupported ROM size"); + image.seterror(image_error::INVALIDIMAGE, "Unsupported ROM size"); return image_init_result::FAIL; } @@ -193,7 +193,7 @@ image_init_result aim65_state::load_cart(device_image_interface &image, generic_ std::string errmsg = string_format( "Attempted to load file with wrong extension\nSocket '%s' only accepts files with '.%s' extension", slot_tag, slot_tag); - image.seterror(IMAGE_ERROR_UNSPECIFIED, errmsg.c_str()); + image.seterror(image_error::INVALIDIMAGE, errmsg.c_str()); return image_init_result::FAIL; } diff --git a/src/mame/drivers/alphatro.cpp b/src/mame/drivers/alphatro.cpp index e07c89a1f3f..d6ec5f4bc9d 100644 --- a/src/mame/drivers/alphatro.cpp +++ b/src/mame/drivers/alphatro.cpp @@ -702,7 +702,7 @@ image_init_result alphatro_state::load_cart(device_image_interface &image, gener if ((size != 0x4000) && (size != 0x2000)) { - image.seterror(IMAGE_ERROR_UNSUPPORTED, "Invalid size, must be 8 or 16 K" ); + image.seterror(image_error::INVALIDIMAGE, "Invalid size, must be 8 or 16 K" ); return image_init_result::FAIL; } diff --git a/src/mame/drivers/atom.cpp b/src/mame/drivers/atom.cpp index d5cf875810b..d703f967a70 100644 --- a/src/mame/drivers/atom.cpp +++ b/src/mame/drivers/atom.cpp @@ -683,7 +683,7 @@ image_init_result atom_state::load_cart(device_image_interface &image, generic_s if (size > 0x1000) { - image.seterror(IMAGE_ERROR_UNSPECIFIED, "Unsupported ROM size"); + image.seterror(image_error::INVALIDIMAGE, "Unsupported ROM size"); return image_init_result::FAIL; } diff --git a/src/mame/drivers/beta.cpp b/src/mame/drivers/beta.cpp index 4639ec0fcde..0e543f91230 100644 --- a/src/mame/drivers/beta.cpp +++ b/src/mame/drivers/beta.cpp @@ -297,7 +297,7 @@ DEVICE_IMAGE_LOAD_MEMBER(beta_state::load_beta_eprom) if (size != 0x800) { - image.seterror(IMAGE_ERROR_UNSPECIFIED, "Unsupported cartridge size"); + image.seterror(image_error::INVALIDIMAGE, "Unsupported cartridge size"); return image_init_result::FAIL; } diff --git a/src/mame/drivers/binbug.cpp b/src/mame/drivers/binbug.cpp index 1bcba2984a0..3855bc393aa 100644 --- a/src/mame/drivers/binbug.cpp +++ b/src/mame/drivers/binbug.cpp @@ -189,12 +189,12 @@ QUICKLOAD_LOAD_MEMBER(binbug_state::quickload_cb) quick_length = image.length(); if (quick_length < 0x0444) { - image.seterror(IMAGE_ERROR_INVALIDIMAGE, "File too short"); + image.seterror(image_error::INVALIDIMAGE, "File too short"); image.message(" File too short"); } else if (quick_length > 0x8000) { - image.seterror(IMAGE_ERROR_INVALIDIMAGE, "File too long"); + image.seterror(image_error::INVALIDIMAGE, "File too long"); image.message(" File too long"); } else @@ -203,12 +203,12 @@ QUICKLOAD_LOAD_MEMBER(binbug_state::quickload_cb) read_ = image.fread( &quick_data[0], quick_length); if (read_ != quick_length) { - image.seterror(IMAGE_ERROR_INVALIDIMAGE, "Cannot read the file"); + image.seterror(image_error::INVALIDIMAGE, "Cannot read the file"); image.message(" Cannot read the file"); } else if (quick_data[0] != 0xc4) { - image.seterror(IMAGE_ERROR_INVALIDIMAGE, "Invalid header"); + image.seterror(image_error::INVALIDIMAGE, "Invalid header"); image.message(" Invalid header"); } else @@ -217,7 +217,7 @@ QUICKLOAD_LOAD_MEMBER(binbug_state::quickload_cb) if (exec_addr >= quick_length) { - image.seterror(IMAGE_ERROR_INVALIDIMAGE, "Exec address beyond end of file"); + image.seterror(image_error::INVALIDIMAGE, "Exec address beyond end of file"); image.message(" Exec address beyond end of file"); } else diff --git a/src/mame/drivers/cc40.cpp b/src/mame/drivers/cc40.cpp index 3766231c469..6e737b9b134 100644 --- a/src/mame/drivers/cc40.cpp +++ b/src/mame/drivers/cc40.cpp @@ -196,7 +196,7 @@ DEVICE_IMAGE_LOAD_MEMBER(cc40_state::cart_load) // max size is 4*32KB if (size > 0x20000) { - image.seterror(IMAGE_ERROR_UNSPECIFIED, "Invalid file size"); + image.seterror(image_error::INVALIDIMAGE, "Invalid file size"); return image_init_result::FAIL; } diff --git a/src/mame/drivers/cd2650.cpp b/src/mame/drivers/cd2650.cpp index 01760a14fbd..cf8203a25fd 100644 --- a/src/mame/drivers/cd2650.cpp +++ b/src/mame/drivers/cd2650.cpp @@ -259,13 +259,13 @@ QUICKLOAD_LOAD_MEMBER(cd2650_state::quickload_cb) int quick_length = image.length(); if (quick_length < 0x1500) { - image.seterror(IMAGE_ERROR_INVALIDIMAGE, "File too short"); + image.seterror(image_error::INVALIDIMAGE, "File too short"); image.message(" File too short"); } else if (quick_length > 0x8000) { - image.seterror(IMAGE_ERROR_INVALIDIMAGE, "File too long"); + image.seterror(image_error::INVALIDIMAGE, "File too long"); image.message(" File too long"); } else @@ -274,13 +274,13 @@ QUICKLOAD_LOAD_MEMBER(cd2650_state::quickload_cb) int read_ = image.fread( &quick_data[0], quick_length); if (read_ != quick_length) { - image.seterror(IMAGE_ERROR_INVALIDIMAGE, "Cannot read the file"); + image.seterror(image_error::INVALIDIMAGE, "Cannot read the file"); image.message(" Cannot read the file"); } else if (quick_data[0] != 0x40) { - image.seterror(IMAGE_ERROR_INVALIDIMAGE, "Invalid header"); + image.seterror(image_error::INVALIDIMAGE, "Invalid header"); image.message(" Invalid header"); } else @@ -289,7 +289,7 @@ QUICKLOAD_LOAD_MEMBER(cd2650_state::quickload_cb) if (exec_addr >= quick_length) { - image.seterror(IMAGE_ERROR_INVALIDIMAGE, "Exec address beyond end of file"); + image.seterror(image_error::INVALIDIMAGE, "Exec address beyond end of file"); image.message(" Exec address beyond end of file"); } else diff --git a/src/mame/drivers/d6800.cpp b/src/mame/drivers/d6800.cpp index ca08bcbc118..1bffd36f07a 100644 --- a/src/mame/drivers/d6800.cpp +++ b/src/mame/drivers/d6800.cpp @@ -346,7 +346,7 @@ QUICKLOAD_LOAD_MEMBER(d6800_state::quickload_cb) u32 quick_length = image.length(); if (quick_length > 0xe00) { - image.seterror(IMAGE_ERROR_INVALIDIMAGE, "File exceeds 3584 bytes"); + image.seterror(image_error::INVALIDIMAGE, "File exceeds 3584 bytes"); image.message(" File exceeds 3584 bytes"); return image_init_result::FAIL; } diff --git a/src/mame/drivers/elan_eu3a05.cpp b/src/mame/drivers/elan_eu3a05.cpp index 29abd9ff08d..f4327818657 100644 --- a/src/mame/drivers/elan_eu3a05.cpp +++ b/src/mame/drivers/elan_eu3a05.cpp @@ -360,7 +360,7 @@ DEVICE_IMAGE_LOAD_MEMBER(elan_eu3a05_buzztime_state::cart_load) if (size != 0x200000) { - image.seterror(IMAGE_ERROR_UNSPECIFIED, "Unsupported cartridge size"); + image.seterror(image_error::INVALIDIMAGE, "Unsupported cartridge size"); return image_init_result::FAIL; } diff --git a/src/mame/drivers/eti660.cpp b/src/mame/drivers/eti660.cpp index 379cdb2d55b..5ffea04f6d2 100644 --- a/src/mame/drivers/eti660.cpp +++ b/src/mame/drivers/eti660.cpp @@ -325,7 +325,7 @@ QUICKLOAD_LOAD_MEMBER(eti660_state::quickload_cb) read_ = image.fread( &quick_data[0], quick_length); if (read_ != quick_length) { - image.seterror(IMAGE_ERROR_INVALIDIMAGE, "Cannot read the file"); + image.seterror(image_error::INVALIDIMAGE, "Cannot read the file"); image.message(" Cannot read the file"); } else diff --git a/src/mame/drivers/force68k.cpp b/src/mame/drivers/force68k.cpp index 47e7fe73f48..03d594ca831 100644 --- a/src/mame/drivers/force68k.cpp +++ b/src/mame/drivers/force68k.cpp @@ -514,7 +514,7 @@ image_init_result force68k_state::force68k_load_cart(device_image_interface &ima if (size > 0x20000) // Max 128Kb { LOG("Cartridge size exceeding max size (128Kb): %d\n", size); - image.seterror(IMAGE_ERROR_UNSPECIFIED, "Cartridge size exceeding max size (128Kb)"); + image.seterror(image_error::INVALIDIMAGE, "Cartridge size exceeding max size (128Kb)"); return image_init_result::FAIL; } diff --git a/src/mame/drivers/gameking.cpp b/src/mame/drivers/gameking.cpp index 8d398756c38..737445f5928 100644 --- a/src/mame/drivers/gameking.cpp +++ b/src/mame/drivers/gameking.cpp @@ -261,7 +261,7 @@ DEVICE_IMAGE_LOAD_MEMBER(gameking_state::cart_load) if (size > 0x100000) { - image.seterror(IMAGE_ERROR_UNSPECIFIED, "Unsupported cartridge size"); + image.seterror(image_error::INVALIDIMAGE, "Unsupported cartridge size"); return image_init_result::FAIL; } diff --git a/src/mame/drivers/hh_tms1k.cpp b/src/mame/drivers/hh_tms1k.cpp index 8493a40b9a5..82e2eeb6042 100644 --- a/src/mame/drivers/hh_tms1k.cpp +++ b/src/mame/drivers/hh_tms1k.cpp @@ -2391,7 +2391,7 @@ DEVICE_IMAGE_LOAD_MEMBER(quizwizc_state::cart_load) { if (!image.loaded_through_softlist()) { - image.seterror(IMAGE_ERROR_UNSPECIFIED, "Can only load through softwarelist"); + image.seterror(image_error::UNSUPPORTED, "Can only load through softwarelist"); return image_init_result::FAIL; } @@ -2579,7 +2579,7 @@ DEVICE_IMAGE_LOAD_MEMBER(tc4_state::cart_load) { if (!image.loaded_through_softlist()) { - image.seterror(IMAGE_ERROR_UNSPECIFIED, "Can only load through softwarelist"); + image.seterror(image_error::UNSUPPORTED, "Can only load through softwarelist"); return image_init_result::FAIL; } diff --git a/src/mame/drivers/homelab.cpp b/src/mame/drivers/homelab.cpp index 3de88cb8ee7..8516773a6b2 100644 --- a/src/mame/drivers/homelab.cpp +++ b/src/mame/drivers/homelab.cpp @@ -683,7 +683,7 @@ QUICKLOAD_LOAD_MEMBER(homelab_state::quickload_cb) u8 ch = image.fgetc(); if (ch != 0xA5) { - image.seterror(IMAGE_ERROR_INVALIDIMAGE, "Invalid header"); + image.seterror(image_error::INVALIDIMAGE, "Invalid header"); image.message(" Invalid header"); return image_init_result::FAIL; } @@ -692,7 +692,7 @@ QUICKLOAD_LOAD_MEMBER(homelab_state::quickload_cb) { if (i >= (std::size(pgmname) - 1)) { - image.seterror(IMAGE_ERROR_INVALIDIMAGE, "File name too long"); + image.seterror(image_error::INVALIDIMAGE, "File name too long"); image.message(" File name too long"); return image_init_result::FAIL; } @@ -706,7 +706,7 @@ QUICKLOAD_LOAD_MEMBER(homelab_state::quickload_cb) if (image.fread(args, sizeof(args)) != sizeof(args)) { - image.seterror(IMAGE_ERROR_INVALIDIMAGE, "Unexpected EOF while getting file size"); + image.seterror(image_error::INVALIDIMAGE, "Unexpected EOF while getting file size"); image.message(" Unexpected EOF while getting file size"); return image_init_result::FAIL; } @@ -717,7 +717,7 @@ QUICKLOAD_LOAD_MEMBER(homelab_state::quickload_cb) if (quick_end > 0x7fff) { - image.seterror(IMAGE_ERROR_INVALIDIMAGE, "File too large"); + image.seterror(image_error::INVALIDIMAGE, "File too large"); image.message(" File too large"); return image_init_result::FAIL; } @@ -732,7 +732,7 @@ QUICKLOAD_LOAD_MEMBER(homelab_state::quickload_cb) { char message[512]; snprintf(message, std::size(message), "%s: Unexpected EOF while writing byte to %04X", pgmname, (unsigned) j); - image.seterror(IMAGE_ERROR_INVALIDIMAGE, message); + image.seterror(image_error::INVALIDIMAGE, message); image.message("%s: Unexpected EOF while writing byte to %04X", pgmname, (unsigned) j); return image_init_result::FAIL; } diff --git a/src/mame/drivers/hx20.cpp b/src/mame/drivers/hx20.cpp index b877e8f86a7..708a7126bf1 100644 --- a/src/mame/drivers/hx20.cpp +++ b/src/mame/drivers/hx20.cpp @@ -835,7 +835,7 @@ DEVICE_IMAGE_LOAD_MEMBER(hx20_state::optrom_load) if (size != 0x2000) { - image.seterror(IMAGE_ERROR_UNSPECIFIED, "Unsupported ROM size"); + image.seterror(image_error::INVALIDIMAGE, "Unsupported ROM size"); return image_init_result::FAIL; } diff --git a/src/mame/drivers/ibmpcjr.cpp b/src/mame/drivers/ibmpcjr.cpp index 05d6714ac0a..38bf2f19424 100644 --- a/src/mame/drivers/ibmpcjr.cpp +++ b/src/mame/drivers/ibmpcjr.cpp @@ -467,7 +467,7 @@ image_init_result pcjr_state::load_cart(device_image_interface &image, generic_s header_size = 0x200; break; default: - image.seterror(IMAGE_ERROR_UNSUPPORTED, "Invalid header size" ); + image.seterror(image_error::INVALIDIMAGE, "Invalid header size"); return image_init_result::FAIL; } if (size - header_size == 0xa000) diff --git a/src/mame/drivers/instruct.cpp b/src/mame/drivers/instruct.cpp index 1f14360e37e..fd3f3b9622b 100644 --- a/src/mame/drivers/instruct.cpp +++ b/src/mame/drivers/instruct.cpp @@ -356,13 +356,13 @@ QUICKLOAD_LOAD_MEMBER(instruct_state::quickload_cb) quick_length = image.length(); if (quick_length < 0x0100) { - image.seterror(IMAGE_ERROR_INVALIDIMAGE, "File too short"); + image.seterror(image_error::INVALIDIMAGE, "File too short"); image.message(" File too short"); } else if (quick_length > 0x8000) { - image.seterror(IMAGE_ERROR_INVALIDIMAGE, "File too long"); + image.seterror(image_error::INVALIDIMAGE, "File too long"); image.message(" File too long"); } else @@ -371,12 +371,12 @@ QUICKLOAD_LOAD_MEMBER(instruct_state::quickload_cb) read_ = image.fread( &quick_data[0], quick_length); if (read_ != quick_length) { - image.seterror(IMAGE_ERROR_INVALIDIMAGE, "Cannot read the file"); + image.seterror(image_error::INVALIDIMAGE, "Cannot read the file"); image.message(" Cannot read the file"); } else if (quick_data[0] != 0xc5) { - image.seterror(IMAGE_ERROR_INVALIDIMAGE, "Invalid header"); + image.seterror(image_error::INVALIDIMAGE, "Invalid header"); image.message(" Invalid header"); } else @@ -385,7 +385,7 @@ QUICKLOAD_LOAD_MEMBER(instruct_state::quickload_cb) if (exec_addr >= quick_length) { - image.seterror(IMAGE_ERROR_INVALIDIMAGE, "Exec address beyond end of file"); + image.seterror(image_error::INVALIDIMAGE, "Exec address beyond end of file"); image.message(" Exec address beyond end of file"); } else diff --git a/src/mame/drivers/jtc.cpp b/src/mame/drivers/jtc.cpp index 506d620658d..9cfda169f3a 100644 --- a/src/mame/drivers/jtc.cpp +++ b/src/mame/drivers/jtc.cpp @@ -597,22 +597,22 @@ QUICKLOAD_LOAD_MEMBER(jtc_state::quickload_cb) { if (quick_length < 0x0088) { - image.seterror(IMAGE_ERROR_INVALIDIMAGE, "File too short"); + image.seterror(image_error::INVALIDIMAGE, "File too short"); image.message(" File too short"); } else if (quick_length > 0x8000) { - image.seterror(IMAGE_ERROR_INVALIDIMAGE, "File too long"); + image.seterror(image_error::INVALIDIMAGE, "File too long"); image.message(" File too long"); } else { quick_data.resize(quick_length+1); - u16 read_ = image.fread( &quick_data[0], quick_length); + u16 read_ = image.fread(&quick_data[0], quick_length); if (read_ != quick_length) { - image.seterror(IMAGE_ERROR_INVALIDIMAGE, "Cannot read the file"); + image.seterror(image_error::INVALIDIMAGE, "Cannot read the file"); image.message(" Cannot read the file"); } else @@ -621,7 +621,7 @@ QUICKLOAD_LOAD_MEMBER(jtc_state::quickload_cb) quick_length = quick_data[0x14] * 256 + quick_data[0x13] - quick_addr + 0x81; if (image.length() != quick_length) { - image.seterror(IMAGE_ERROR_INVALIDIMAGE, "Invalid file header"); + image.seterror(image_error::INVALIDIMAGE, "Invalid file header"); image.message(" Invalid file header"); } else @@ -643,7 +643,7 @@ QUICKLOAD_LOAD_MEMBER(jtc_state::quickload_cb) quick_addr = 0xe000; if (quick_length > 0x8000) { - image.seterror(IMAGE_ERROR_INVALIDIMAGE, "File too long"); + image.seterror(image_error::INVALIDIMAGE, "File too long"); image.message(" File too long"); } else @@ -652,7 +652,7 @@ QUICKLOAD_LOAD_MEMBER(jtc_state::quickload_cb) u16 read_ = image.fread( &quick_data[0], quick_length); if (read_ != quick_length) { - image.seterror(IMAGE_ERROR_INVALIDIMAGE, "Cannot read the file"); + image.seterror(image_error::INVALIDIMAGE, "Cannot read the file"); image.message(" Cannot read the file"); } else diff --git a/src/mame/drivers/jupace.cpp b/src/mame/drivers/jupace.cpp index 05fd4f0a850..a822f1448da 100644 --- a/src/mame/drivers/jupace.cpp +++ b/src/mame/drivers/jupace.cpp @@ -179,7 +179,7 @@ SNAPSHOT_LOAD_MEMBER(ace_state::snapshot_cb) if (m_ram->size() < 16*1024) { - image.seterror(IMAGE_ERROR_INVALIDIMAGE, "At least 16KB RAM expansion required"); + image.seterror(image_error::INVALIDIMAGE, "At least 16KB RAM expansion required"); image.message("At least 16KB RAM expansion required"); return image_init_result::FAIL; } @@ -216,7 +216,7 @@ SNAPSHOT_LOAD_MEMBER(ace_state::snapshot_cb) if (!done) { - image.seterror(IMAGE_ERROR_INVALIDIMAGE, "EOF marker not found"); + image.seterror(image_error::INVALIDIMAGE, "EOF marker not found"); image.message("EOF marker not found"); return image_init_result::FAIL; } diff --git a/src/mame/drivers/ldplayer.cpp b/src/mame/drivers/ldplayer.cpp index e0d92cf5997..9afb99f9332 100644 --- a/src/mame/drivers/ldplayer.cpp +++ b/src/mame/drivers/ldplayer.cpp @@ -185,15 +185,15 @@ chd_file *ldplayer_state::get_disc() { // open the file itself via our search path emu_file image_file(machine().options().media_path(), OPEN_FLAG_READ); - osd_file::error filerr = image_file.open(dir->name); - if (filerr == osd_file::error::NONE) + std::error_condition filerr = image_file.open(dir->name); + if (!filerr) { std::string fullpath(image_file.fullpath()); image_file.close(); // try to open the CHD - if (machine().rom_load().set_disk_handle("laserdisc", fullpath.c_str()) == CHDERR_NONE) + if (!machine().rom_load().set_disk_handle("laserdisc", fullpath.c_str())) { m_filename.assign(dir->name); found = true; @@ -204,7 +204,8 @@ chd_file *ldplayer_state::get_disc() } // if we failed, pop a message and exit - if (found == false) { + if (!found) + { machine().ui().popup_time(10, "No valid image file found!\n"); return nullptr; } diff --git a/src/mame/drivers/lynx.cpp b/src/mame/drivers/lynx.cpp index 2d1c00e9dfc..68a5e89ebc8 100644 --- a/src/mame/drivers/lynx.cpp +++ b/src/mame/drivers/lynx.cpp @@ -170,7 +170,7 @@ QUICKLOAD_LOAD_MEMBER(lynx_state::quickload_cb) /* Check the image */ if (lynx_verify_cart((char*)header, LYNX_QUICKLOAD) != image_verify_result::PASS) { - image.seterror(IMAGE_ERROR_UNSPECIFIED, "Not a valid Lynx file"); + image.seterror(image_error::INVALIDIMAGE, "Not a valid Lynx file"); return image_init_result::FAIL; } @@ -182,7 +182,7 @@ QUICKLOAD_LOAD_MEMBER(lynx_state::quickload_cb) if (image.fread( &data[0], length) != length) { - image.seterror(IMAGE_ERROR_UNSPECIFIED, "Invalid length in file header"); + image.seterror(image_error::INVALIDIMAGE, "Invalid length in file header"); return image_init_result::FAIL; } diff --git a/src/mame/drivers/m68705prg.cpp b/src/mame/drivers/m68705prg.cpp index 0bd877b0cf2..5bb9359813c 100644 --- a/src/mame/drivers/m68705prg.cpp +++ b/src/mame/drivers/m68705prg.cpp @@ -67,7 +67,7 @@ protected: auto const actual(m_eprom_image->common_get_size("rom")); if (desired > actual) { - image.seterror(IMAGE_ERROR_UNSPECIFIED, "Unsupported EPROM size"); + image.seterror(image_error::INVALIDIMAGE, "Unsupported EPROM size"); return image_init_result::FAIL; } else @@ -84,7 +84,7 @@ protected: auto const actual(m_mcu_image->common_get_size("rom")); if (desired != actual) { - image.seterror(IMAGE_ERROR_UNSPECIFIED, "Incorrect internal MCU EPROM size"); + image.seterror(image_error::INVALIDIMAGE, "Incorrect internal MCU EPROM size"); return image_init_result::FAIL; } else diff --git a/src/mame/drivers/microvsn.cpp b/src/mame/drivers/microvsn.cpp index 4447ded8659..9d830012994 100644 --- a/src/mame/drivers/microvsn.cpp +++ b/src/mame/drivers/microvsn.cpp @@ -188,7 +188,7 @@ DEVICE_IMAGE_LOAD_MEMBER(microvision_state::cart_load) if (size != 0x400 && size != 0x800) { - image.seterror(IMAGE_ERROR_UNSPECIFIED, "Invalid ROM file size"); + image.seterror(image_error::INVALIDIMAGE, "Invalid ROM file size"); return image_init_result::FAIL; } diff --git a/src/mame/drivers/myvision.cpp b/src/mame/drivers/myvision.cpp index 801f2611239..4005ca42bcd 100644 --- a/src/mame/drivers/myvision.cpp +++ b/src/mame/drivers/myvision.cpp @@ -158,7 +158,7 @@ DEVICE_IMAGE_LOAD_MEMBER( myvision_state::cart_load ) if (size != 0x4000 && size != 0x6000) { - image.seterror(IMAGE_ERROR_UNSPECIFIED, "Unsupported cartridge size"); + image.seterror(image_error::INVALIDIMAGE, "Unsupported cartridge size"); return image_init_result::FAIL; } diff --git a/src/mame/drivers/nascom1.cpp b/src/mame/drivers/nascom1.cpp index 6f14e852191..040b84d54f1 100644 --- a/src/mame/drivers/nascom1.cpp +++ b/src/mame/drivers/nascom1.cpp @@ -367,7 +367,7 @@ SNAPSHOT_LOAD_MEMBER(nascom_state::snapshot_cb) } else { - image.seterror(IMAGE_ERROR_UNSPECIFIED, "Unsupported file format"); + image.seterror(image_error::INVALIDIMAGE, "Unsupported file format"); return image_init_result::FAIL; } dummy = 0x00; @@ -392,7 +392,7 @@ image_init_result nascom2_state::load_cart(device_image_interface &image, generi { if (slot->length() > 0x1000) { - image.seterror(IMAGE_ERROR_UNSPECIFIED, "Unsupported file size"); + image.seterror(image_error::INVALIDIMAGE, "Unsupported file size"); return image_init_result::FAIL; } diff --git a/src/mame/drivers/ngp.cpp b/src/mame/drivers/ngp.cpp index c0e8e51e98d..4e045d22d9c 100644 --- a/src/mame/drivers/ngp.cpp +++ b/src/mame/drivers/ngp.cpp @@ -754,7 +754,7 @@ DEVICE_IMAGE_LOAD_MEMBER(ngp_state::load_ngp_cart) if (size != 0x8000 && size != 0x80000 && size != 0x100000 && size != 0x200000 && size != 0x400000) { - image.seterror(IMAGE_ERROR_UNSPECIFIED, "Unsupported cartridge size"); + image.seterror(image_error::INVALIDIMAGE, "Unsupported cartridge size"); return image_init_result::FAIL; } diff --git a/src/mame/drivers/pegasus.cpp b/src/mame/drivers/pegasus.cpp index 55eae153890..a8bd6934e77 100644 --- a/src/mame/drivers/pegasus.cpp +++ b/src/mame/drivers/pegasus.cpp @@ -427,7 +427,7 @@ image_init_result pegasus_state::load_cart(device_image_interface &image, generi if (size > 0x1000) { - image.seterror(IMAGE_ERROR_UNSPECIFIED, "Unsupported cartridge size"); + image.seterror(image_error::INVALIDIMAGE, "Unsupported cartridge size"); return image_init_result::FAIL; } @@ -443,7 +443,7 @@ image_init_result pegasus_state::load_cart(device_image_interface &image, generi std::string errmsg = string_format( "Attempted to load a file that does not work in this socket.\n" "Please check \"Usage\" field in the software list for the correct socket(s) to use."); - image.seterror(IMAGE_ERROR_UNSPECIFIED, errmsg.c_str()); + image.seterror(image_error::INVALIDIMAGE, errmsg.c_str()); return image_init_result::FAIL; } } diff --git a/src/mame/drivers/phunsy.cpp b/src/mame/drivers/phunsy.cpp index fc5c5776fa5..25a260c9c5f 100644 --- a/src/mame/drivers/phunsy.cpp +++ b/src/mame/drivers/phunsy.cpp @@ -291,7 +291,7 @@ QUICKLOAD_LOAD_MEMBER(phunsy_state::quickload_cb) int quick_length = image.length(); if (quick_length > 0x4000) { - image.seterror(IMAGE_ERROR_INVALIDIMAGE, "File too long"); + image.seterror(image_error::INVALIDIMAGE, "File too long"); image.message(" File too long"); } else diff --git a/src/mame/drivers/pipbug.cpp b/src/mame/drivers/pipbug.cpp index dee8696c1b1..a7214dbb094 100644 --- a/src/mame/drivers/pipbug.cpp +++ b/src/mame/drivers/pipbug.cpp @@ -160,12 +160,12 @@ QUICKLOAD_LOAD_MEMBER(pipbug_state::quickload_cb) quick_length = image.length(); if (quick_length < 0x0444) { - image.seterror(IMAGE_ERROR_INVALIDIMAGE, "File too short"); + image.seterror(image_error::INVALIDIMAGE, "File too short"); image.message(" File too short"); } else if (quick_length > 0x8000) { - image.seterror(IMAGE_ERROR_INVALIDIMAGE, "File too long"); + image.seterror(image_error::INVALIDIMAGE, "File too long"); image.message(" File too long"); } else @@ -174,12 +174,12 @@ QUICKLOAD_LOAD_MEMBER(pipbug_state::quickload_cb) read_ = image.fread( &quick_data[0], quick_length); if (read_ != quick_length) { - image.seterror(IMAGE_ERROR_INVALIDIMAGE, "Cannot read the file"); + image.seterror(image_error::INVALIDIMAGE, "Cannot read the file"); image.message(" Cannot read the file"); } else if (quick_data[0] != 0xc4) { - image.seterror(IMAGE_ERROR_INVALIDIMAGE, "Invalid header"); + image.seterror(image_error::INVALIDIMAGE, "Invalid header"); image.message(" Invalid header"); } else @@ -188,7 +188,7 @@ QUICKLOAD_LOAD_MEMBER(pipbug_state::quickload_cb) if (exec_addr >= quick_length) { - image.seterror(IMAGE_ERROR_INVALIDIMAGE, "Exec address beyond end of file"); + image.seterror(image_error::INVALIDIMAGE, "Exec address beyond end of file"); image.message(" Exec address beyond end of file"); } else diff --git a/src/mame/drivers/pokemini.cpp b/src/mame/drivers/pokemini.cpp index d99f74beb14..297b491228b 100644 --- a/src/mame/drivers/pokemini.cpp +++ b/src/mame/drivers/pokemini.cpp @@ -1516,14 +1516,14 @@ DEVICE_IMAGE_LOAD_MEMBER( pokemini_state::cart_load ) /* Verify that the image is big enough */ if (size <= 0x2100) { - image.seterror(IMAGE_ERROR_UNSPECIFIED, "Invalid ROM image: ROM image is too small"); + image.seterror(image_error::INVALIDIMAGE, "Invalid ROM image: ROM image is too small"); return image_init_result::FAIL; } /* Verify that the image is not too big */ if (size > 0x1fffff) { - image.seterror(IMAGE_ERROR_UNSPECIFIED, "Invalid ROM image: ROM image is too big"); + image.seterror(image_error::INVALIDIMAGE, "Invalid ROM image: ROM image is too big"); return image_init_result::FAIL; } diff --git a/src/mame/drivers/pv1000.cpp b/src/mame/drivers/pv1000.cpp index 63b19c16975..f3dcef31f94 100644 --- a/src/mame/drivers/pv1000.cpp +++ b/src/mame/drivers/pv1000.cpp @@ -307,7 +307,7 @@ DEVICE_IMAGE_LOAD_MEMBER( pv1000_state::cart_load ) if (size != 0x2000 && size != 0x4000) { - image.seterror(IMAGE_ERROR_UNSPECIFIED, "Unsupported cartridge size"); + image.seterror(image_error::INVALIDIMAGE, "Unsupported cartridge size"); return image_init_result::FAIL; } diff --git a/src/mame/drivers/pv2000.cpp b/src/mame/drivers/pv2000.cpp index d3080bfffc3..eefb89a8b02 100644 --- a/src/mame/drivers/pv2000.cpp +++ b/src/mame/drivers/pv2000.cpp @@ -373,7 +373,7 @@ DEVICE_IMAGE_LOAD_MEMBER( pv2000_state::cart_load ) if (size != 0x2000 && size != 0x4000) { - image.seterror(IMAGE_ERROR_UNSPECIFIED, "Unsupported cartridge size"); + image.seterror(image_error::INVALIDIMAGE, "Unsupported cartridge size"); return image_init_result::FAIL; } diff --git a/src/mame/drivers/ravens.cpp b/src/mame/drivers/ravens.cpp index a557347644a..41171b74b79 100644 --- a/src/mame/drivers/ravens.cpp +++ b/src/mame/drivers/ravens.cpp @@ -322,12 +322,12 @@ QUICKLOAD_LOAD_MEMBER(ravens_base::quickload_cb) quick_length = image.length(); if (quick_length < 0x0900) { - image.seterror(IMAGE_ERROR_INVALIDIMAGE, "File too short"); + image.seterror(image_error::INVALIDIMAGE, "File too short"); image.message(" File too short"); } else if (quick_length > 0x8000) { - image.seterror(IMAGE_ERROR_INVALIDIMAGE, "File too long"); + image.seterror(image_error::INVALIDIMAGE, "File too long"); image.message(" File too long"); } else @@ -336,12 +336,12 @@ QUICKLOAD_LOAD_MEMBER(ravens_base::quickload_cb) read_ = image.fread( &quick_data[0], quick_length); if (read_ != quick_length) { - image.seterror(IMAGE_ERROR_INVALIDIMAGE, "Cannot read the file"); + image.seterror(image_error::INVALIDIMAGE, "Cannot read the file"); image.message(" Cannot read the file"); } else if (quick_data[0] != 0xc6) { - image.seterror(IMAGE_ERROR_INVALIDIMAGE, "Invalid header"); + image.seterror(image_error::INVALIDIMAGE, "Invalid header"); image.message(" Invalid header"); } else @@ -350,7 +350,7 @@ QUICKLOAD_LOAD_MEMBER(ravens_base::quickload_cb) if (exec_addr >= quick_length) { - image.seterror(IMAGE_ERROR_INVALIDIMAGE, "Exec address beyond end of file"); + image.seterror(image_error::INVALIDIMAGE, "Exec address beyond end of file"); image.message(" Exec address beyond end of file"); } else diff --git a/src/mame/drivers/roland_cm32p.cpp b/src/mame/drivers/roland_cm32p.cpp index e26027acef2..cefe4efe729 100644 --- a/src/mame/drivers/roland_cm32p.cpp +++ b/src/mame/drivers/roland_cm32p.cpp @@ -398,7 +398,7 @@ DEVICE_IMAGE_LOAD_MEMBER(cm32p_state::card_load) uint32_t size = pcmcard->common_get_size("rom"); if (size > 0x080000) { - image.seterror(IMAGE_ERROR_UNSPECIFIED, "Invalid size: Only up to 512K is supported"); + image.seterror(image_error::INVALIDIMAGE, "Invalid size: Only up to 512K is supported"); return image_init_result::FAIL; } diff --git a/src/mame/drivers/rx78.cpp b/src/mame/drivers/rx78.cpp index b7b3075130a..77696012e17 100644 --- a/src/mame/drivers/rx78.cpp +++ b/src/mame/drivers/rx78.cpp @@ -489,7 +489,7 @@ DEVICE_IMAGE_LOAD_MEMBER( rx78_state::cart_load ) if (size != 0x2000 && size != 0x4000 && size != 0x8000) { - image.seterror(IMAGE_ERROR_UNSPECIFIED, "Unsupported cartridge size"); + image.seterror(image_error::INVALIDIMAGE, "Unsupported cartridge size"); return image_init_result::FAIL; } diff --git a/src/mame/drivers/sag.cpp b/src/mame/drivers/sag.cpp index 9a530c24bfd..8799ba83bb8 100644 --- a/src/mame/drivers/sag.cpp +++ b/src/mame/drivers/sag.cpp @@ -112,7 +112,7 @@ DEVICE_IMAGE_LOAD_MEMBER(sag_state::cart_load) if (size != 0x1000 && size != 0x1100 && size != 0x2000) { - image.seterror(IMAGE_ERROR_UNSPECIFIED, "Invalid ROM file size"); + image.seterror(image_error::INVALIDIMAGE, "Invalid ROM file size"); return image_init_result::FAIL; } @@ -125,7 +125,7 @@ DEVICE_IMAGE_LOAD_MEMBER(sag_state::cart_load) // TMS1670 MCU if (!image.loaded_through_softlist()) { - image.seterror(IMAGE_ERROR_UNSPECIFIED, "Can only load TMS1670 type through softwarelist"); + image.seterror(image_error::INVALIDIMAGE, "Can only load TMS1670 type through softwarelist"); return image_init_result::FAIL; } @@ -136,7 +136,7 @@ DEVICE_IMAGE_LOAD_MEMBER(sag_state::cart_load) size = image.get_software_region_length("rom:mpla"); if (size != 867) { - image.seterror(IMAGE_ERROR_UNSPECIFIED, "Invalid MPLA file size"); + image.seterror(image_error::INVALIDIMAGE, "Invalid MPLA file size"); return image_init_result::FAIL; } memcpy(memregion("tms1k_cpu:mpla")->base(), image.get_software_region("rom:mpla"), size); @@ -144,7 +144,7 @@ DEVICE_IMAGE_LOAD_MEMBER(sag_state::cart_load) size = image.get_software_region_length("rom:opla"); if (size != 557) { - image.seterror(IMAGE_ERROR_UNSPECIFIED, "Invalid OPLA file size"); + image.seterror(image_error::INVALIDIMAGE, "Invalid OPLA file size"); return image_init_result::FAIL; } memcpy(memregion("tms1k_cpu:opla")->base(), image.get_software_region("rom:opla"), size); diff --git a/src/mame/drivers/spg2xx_ican.cpp b/src/mame/drivers/spg2xx_ican.cpp index 0398e13935e..d346c9ad549 100644 --- a/src/mame/drivers/spg2xx_ican.cpp +++ b/src/mame/drivers/spg2xx_ican.cpp @@ -430,7 +430,7 @@ DEVICE_IMAGE_LOAD_MEMBER(icanguit_state::cart_load_icanguit) if (size < 0x800000) { - image.seterror(IMAGE_ERROR_UNSPECIFIED, "Unsupported cartridge size"); + image.seterror(image_error::INVALIDIMAGE, "Unsupported cartridge size"); return image_init_result::FAIL; } diff --git a/src/mame/drivers/spg2xx_smarttv.cpp b/src/mame/drivers/spg2xx_smarttv.cpp index 27f042d8a7a..bc315ae4a43 100644 --- a/src/mame/drivers/spg2xx_smarttv.cpp +++ b/src/mame/drivers/spg2xx_smarttv.cpp @@ -193,7 +193,7 @@ DEVICE_IMAGE_LOAD_MEMBER(smarttv_state::cart_load_smarttv) if (size > 0x800000) { - image.seterror(IMAGE_ERROR_UNSPECIFIED, "Unsupported cartridge size"); + image.seterror(image_error::INVALIDIMAGE, "Unsupported cartridge size"); return image_init_result::FAIL; } diff --git a/src/mame/drivers/spg2xx_telestory.cpp b/src/mame/drivers/spg2xx_telestory.cpp index 972cf1206fb..b8a0dd24411 100644 --- a/src/mame/drivers/spg2xx_telestory.cpp +++ b/src/mame/drivers/spg2xx_telestory.cpp @@ -257,7 +257,7 @@ DEVICE_IMAGE_LOAD_MEMBER(telestory_state::cart_load_telestory) if (size > 0x800000) { - image.seterror(IMAGE_ERROR_UNSPECIFIED, "Unsupported cartridge size"); + image.seterror(image_error::INVALIDIMAGE, "Unsupported cartridge size"); return image_init_result::FAIL; } diff --git a/src/mame/drivers/spg2xx_tvgogo.cpp b/src/mame/drivers/spg2xx_tvgogo.cpp index df0bc746d07..b1bf613e7d0 100644 --- a/src/mame/drivers/spg2xx_tvgogo.cpp +++ b/src/mame/drivers/spg2xx_tvgogo.cpp @@ -210,7 +210,7 @@ DEVICE_IMAGE_LOAD_MEMBER(tvgogo_state::cart_load_tvgogo) if (size > 0x800000) { - image.seterror(IMAGE_ERROR_UNSPECIFIED, "Unsupported cartridge size"); + image.seterror(image_error::INVALIDIMAGE, "Unsupported cartridge size"); return image_init_result::FAIL; } diff --git a/src/mame/drivers/spg2xx_vii.cpp b/src/mame/drivers/spg2xx_vii.cpp index ab86e434895..9ed30031233 100644 --- a/src/mame/drivers/spg2xx_vii.cpp +++ b/src/mame/drivers/spg2xx_vii.cpp @@ -153,7 +153,7 @@ DEVICE_IMAGE_LOAD_MEMBER(vii_state::cart_load_vii) if (size < 0x800000) { - image.seterror(IMAGE_ERROR_UNSPECIFIED, "Unsupported cartridge size"); + image.seterror(image_error::INVALIDIMAGE, "Unsupported cartridge size"); return image_init_result::FAIL; } diff --git a/src/mame/drivers/squale.cpp b/src/mame/drivers/squale.cpp index e0b7dce8e0b..018f9a12903 100644 --- a/src/mame/drivers/squale.cpp +++ b/src/mame/drivers/squale.cpp @@ -629,7 +629,7 @@ DEVICE_IMAGE_LOAD_MEMBER( squale_state::cart_load ) if ( ! size || size > 0x10000) { - image.seterror(IMAGE_ERROR_UNSPECIFIED, "Unsupported cartridge size"); + image.seterror(image_error::INVALIDIMAGE, "Unsupported cartridge size"); return image_init_result::FAIL; } diff --git a/src/mame/drivers/studio2.cpp b/src/mame/drivers/studio2.cpp index 44278fe4780..f51c62a7d79 100644 --- a/src/mame/drivers/studio2.cpp +++ b/src/mame/drivers/studio2.cpp @@ -604,7 +604,7 @@ DEVICE_IMAGE_LOAD_MEMBER( studio2_state::cart_load ) if (image.length() < 0x200) { - image.seterror(IMAGE_ERROR_UNSPECIFIED, "Invalid ROM file"); + image.seterror(image_error::INVALIDIMAGE, "Invalid ROM file"); return image_init_result::FAIL; } @@ -613,14 +613,14 @@ DEVICE_IMAGE_LOAD_MEMBER( studio2_state::cart_load ) // validate if (strncmp((const char *)header, "RCA2", 4)) { - image.seterror(IMAGE_ERROR_UNSPECIFIED, "Not an .ST2 file"); + image.seterror(image_error::INVALIDIMAGE, "Not an .ST2 file"); return image_init_result::FAIL; } blocks = header[4]; if ((blocks < 2) || (blocks > 11)) { - image.seterror(IMAGE_ERROR_UNSPECIFIED, "Invalid .ST2 file"); + image.seterror(image_error::INVALIDIMAGE, "Invalid .ST2 file"); return image_init_result::FAIL; } @@ -654,7 +654,7 @@ DEVICE_IMAGE_LOAD_MEMBER( studio2_state::cart_load ) size = image.length(); if (size > 0x400) { - image.seterror(IMAGE_ERROR_UNSPECIFIED, "Unsupported cartridge size"); + image.seterror(image_error::INVALIDIMAGE, "Unsupported cartridge size"); return image_init_result::FAIL; } else diff --git a/src/mame/drivers/supracan.cpp b/src/mame/drivers/supracan.cpp index 9090c1c59de..524cfa70056 100644 --- a/src/mame/drivers/supracan.cpp +++ b/src/mame/drivers/supracan.cpp @@ -1922,7 +1922,7 @@ DEVICE_IMAGE_LOAD_MEMBER(supracan_state::cart_load) if (size > 0x400000) { - image.seterror(IMAGE_ERROR_UNSPECIFIED, "Unsupported cartridge size"); + image.seterror(image_error::INVALIDIMAGE, "Unsupported cartridge size"); return image_init_result::FAIL; } diff --git a/src/mame/drivers/sv8000.cpp b/src/mame/drivers/sv8000.cpp index d671302c563..5302f27a27e 100644 --- a/src/mame/drivers/sv8000.cpp +++ b/src/mame/drivers/sv8000.cpp @@ -207,7 +207,7 @@ DEVICE_IMAGE_LOAD_MEMBER( sv8000_state::cart_load ) if (size != 0x1000) { - image.seterror(IMAGE_ERROR_UNSPECIFIED, "Incorrect or not support cartridge size"); + image.seterror(image_error::INVALIDIMAGE, "Incorrect or not support cartridge size"); return image_init_result::FAIL; } diff --git a/src/mame/drivers/svision.cpp b/src/mame/drivers/svision.cpp index ce3e08c94b1..52cf9b295b7 100644 --- a/src/mame/drivers/svision.cpp +++ b/src/mame/drivers/svision.cpp @@ -449,7 +449,7 @@ DEVICE_IMAGE_LOAD_MEMBER( svision_state::cart_load ) if (size > 0x80000) { - image.seterror(IMAGE_ERROR_UNSPECIFIED, "Unsupported cartridge size"); + image.seterror(image_error::INVALIDIMAGE, "Unsupported cartridge size"); return image_init_result::FAIL; } diff --git a/src/mame/drivers/ti74.cpp b/src/mame/drivers/ti74.cpp index 3047da4e1b1..7d034c30ef1 100644 --- a/src/mame/drivers/ti74.cpp +++ b/src/mame/drivers/ti74.cpp @@ -148,7 +148,7 @@ DEVICE_IMAGE_LOAD_MEMBER(ti74_state::cart_load) // max size is 32KB if (size > 0x8000) { - image.seterror(IMAGE_ERROR_UNSPECIFIED, "Invalid file size"); + image.seterror(image_error::INVALIDIMAGE, "Invalid file size"); return image_init_result::FAIL; } diff --git a/src/mame/drivers/timex.cpp b/src/mame/drivers/timex.cpp index a5bb629ca0f..70b3bfb824f 100644 --- a/src/mame/drivers/timex.cpp +++ b/src/mame/drivers/timex.cpp @@ -608,12 +608,12 @@ DEVICE_IMAGE_LOAD_MEMBER( ts2068_state::cart_load ) if (size % 0x2000 != 9) { - image.seterror(IMAGE_ERROR_UNSPECIFIED, "File corrupted"); + image.seterror(image_error::INVALIDIMAGE, "File corrupted"); return image_init_result::FAIL; } if (!image.loaded_through_softlist()) { - image.seterror(IMAGE_ERROR_UNSPECIFIED, "Loading from softlist is not supported yet"); + image.seterror(image_error::UNSUPPORTED, "Loading from softlist is not supported yet"); return image_init_result::FAIL; } @@ -628,7 +628,7 @@ DEVICE_IMAGE_LOAD_MEMBER( ts2068_state::cart_load ) if (chunks_in_file * 0x2000 + 0x09 != size) { - image.seterror(IMAGE_ERROR_UNSPECIFIED, "File corrupted"); + image.seterror(image_error::INVALIDIMAGE, "File corrupted"); return image_init_result::FAIL; } @@ -652,7 +652,7 @@ DEVICE_IMAGE_LOAD_MEMBER( ts2068_state::cart_load ) break; default: - image.seterror(IMAGE_ERROR_UNSPECIFIED, "Cart type not supported"); + image.seterror(image_error::INVALIDIMAGE, "Cart type not supported"); return image_init_result::FAIL; } diff --git a/src/mame/drivers/tispeak.cpp b/src/mame/drivers/tispeak.cpp index 707690af65a..b858d0e60c5 100644 --- a/src/mame/drivers/tispeak.cpp +++ b/src/mame/drivers/tispeak.cpp @@ -551,7 +551,7 @@ DEVICE_IMAGE_LOAD_MEMBER(tispeak_state::cart_load) if (size > m_cart_max_size) { - image.seterror(IMAGE_ERROR_UNSPECIFIED, "Invalid file size"); + image.seterror(image_error::INVALIDIMAGE, "Invalid file size"); return image_init_result::FAIL; } diff --git a/src/mame/drivers/vc4000.cpp b/src/mame/drivers/vc4000.cpp index b3c8427ed8d..bace6ae8ab2 100644 --- a/src/mame/drivers/vc4000.cpp +++ b/src/mame/drivers/vc4000.cpp @@ -410,7 +410,7 @@ QUICKLOAD_LOAD_MEMBER(vc4000_state::quickload_cb) read_ = image.fread( &quick_data[0], quick_length); if (read_ != quick_length) { - image.seterror(IMAGE_ERROR_INVALIDIMAGE, "Cannot read the file"); + image.seterror(image_error::INVALIDIMAGE, "Cannot read the file"); image.message(" Cannot read the file"); } else @@ -419,7 +419,7 @@ QUICKLOAD_LOAD_MEMBER(vc4000_state::quickload_cb) { if (quick_data[0] != 2) { - image.seterror(IMAGE_ERROR_INVALIDIMAGE, "Invalid header"); + image.seterror(image_error::INVALIDIMAGE, "Invalid header"); image.message(" Invalid header"); } else @@ -429,13 +429,13 @@ QUICKLOAD_LOAD_MEMBER(vc4000_state::quickload_cb) if (quick_length < 0x5) { - image.seterror(IMAGE_ERROR_INVALIDIMAGE, "File too short"); + image.seterror(image_error::INVALIDIMAGE, "File too short"); image.message(" File too short"); } else if ((quick_length + quick_addr - 5) > 0x1600) { - image.seterror(IMAGE_ERROR_INVALIDIMAGE, "File too long"); + image.seterror(image_error::INVALIDIMAGE, "File too long"); image.message(" File too long"); } else @@ -460,7 +460,7 @@ QUICKLOAD_LOAD_MEMBER(vc4000_state::quickload_cb) { if (quick_data[0] != 0) { - image.seterror(IMAGE_ERROR_INVALIDIMAGE, "Invalid header"); + image.seterror(image_error::INVALIDIMAGE, "Invalid header"); image.message(" Invalid header"); } else @@ -469,19 +469,19 @@ QUICKLOAD_LOAD_MEMBER(vc4000_state::quickload_cb) if (exec_addr >= quick_length) { - image.seterror(IMAGE_ERROR_INVALIDIMAGE, "Exec address beyond end of file"); + image.seterror(image_error::INVALIDIMAGE, "Exec address beyond end of file"); image.message(" Exec address beyond end of file"); } else if (quick_length < 0x904) { - image.seterror(IMAGE_ERROR_INVALIDIMAGE, "File too short"); + image.seterror(image_error::INVALIDIMAGE, "File too short"); image.message(" File too short"); } else if (quick_length > 0x2000) { - image.seterror(IMAGE_ERROR_INVALIDIMAGE, "File too long"); + image.seterror(image_error::INVALIDIMAGE, "File too long"); image.message(" File too long"); } else diff --git a/src/mame/drivers/vtech1.cpp b/src/mame/drivers/vtech1.cpp index 101f3b4a214..029c7417461 100644 --- a/src/mame/drivers/vtech1.cpp +++ b/src/mame/drivers/vtech1.cpp @@ -184,7 +184,7 @@ SNAPSHOT_LOAD_MEMBER(vtech1_base_state::snapshot_cb) // verify if (space.read_byte(addr) != to_write) { - image.seterror(IMAGE_ERROR_INVALIDIMAGE, "Insufficient RAM to load snapshot"); + image.seterror(image_error::INVALIDIMAGE, "Insufficient RAM to load snapshot"); image.message("Insufficient RAM to load snapshot (%d bytes needed) [%s]", size, pgmname); return image_init_result::FAIL; @@ -214,7 +214,7 @@ SNAPSHOT_LOAD_MEMBER(vtech1_base_state::snapshot_cb) break; default: - image.seterror(IMAGE_ERROR_UNSUPPORTED, "Snapshot format not supported."); + image.seterror(image_error::INVALIDIMAGE, "Snapshot format not supported."); image.message("Snapshot format not supported."); return image_init_result::FAIL; } diff --git a/src/mame/drivers/x07.cpp b/src/mame/drivers/x07.cpp index f103a68e766..dcd9bb93ea1 100644 --- a/src/mame/drivers/x07.cpp +++ b/src/mame/drivers/x07.cpp @@ -1063,7 +1063,7 @@ DEVICE_IMAGE_LOAD_MEMBER( x07_state::card_load ) if (strcmp(card_type, "xp140")) { - image.seterror(IMAGE_ERROR_UNSPECIFIED, "Unsupported card type"); + image.seterror(image_error::INVALIDIMAGE, "Unsupported card type"); return image_init_result::FAIL; } } diff --git a/src/mame/drivers/z1013.cpp b/src/mame/drivers/z1013.cpp index dd938204e1a..4cb97de983e 100644 --- a/src/mame/drivers/z1013.cpp +++ b/src/mame/drivers/z1013.cpp @@ -380,7 +380,7 @@ SNAPSHOT_LOAD_MEMBER(z1013_state::snapshot_cb) { } else { - image.seterror(IMAGE_ERROR_INVALIDIMAGE, "Not a Z1013 image"); + image.seterror(image_error::INVALIDIMAGE, "Not a Z1013 image"); image.message(" Not a Z1013 image"); return image_init_result::FAIL; } @@ -392,7 +392,7 @@ SNAPSHOT_LOAD_MEMBER(z1013_state::snapshot_cb) m_maincpu->set_state_int(Z80_PC, runaddr); else { - image.seterror(IMAGE_ERROR_INVALIDIMAGE, "Loaded but cannot run"); + image.seterror(image_error::INVALIDIMAGE, "Loaded but cannot run"); image.message(" Loaded but cannot run"); } diff --git a/src/mame/machine/amstrad.cpp b/src/mame/machine/amstrad.cpp index c8b37acd746..f32b13830c1 100644 --- a/src/mame/machine/amstrad.cpp +++ b/src/mame/machine/amstrad.cpp @@ -3315,7 +3315,7 @@ DEVICE_IMAGE_LOAD_MEMBER(amstrad_state::amstrad_plus_cartridge) logerror("IMG: raw CPC+ cartridge file\n"); if (size % 0x4000) { - image.seterror(IMAGE_ERROR_UNSPECIFIED, "Attempt to load a raw binary with some block smaller than 16kB in size"); + image.seterror(image_error::INVALIDIMAGE, "Attempt to load a raw binary with some block smaller than 16kB in size"); return image_init_result::FAIL; } else @@ -3346,7 +3346,7 @@ DEVICE_IMAGE_LOAD_MEMBER(amstrad_state::amstrad_plus_cartridge) // Is RIFF format (*.cpr) if (strncmp((char*)(header + 8), "AMS!", 4) != 0) { - image.seterror(IMAGE_ERROR_UNSPECIFIED, "Not an Amstrad CPC cartridge image (despite RIFF header)"); + image.seterror(image_error::INVALIDIMAGE, "Not an Amstrad CPC cartridge image (despite RIFF header)"); return image_init_result::FAIL; } diff --git a/src/mame/machine/electron.cpp b/src/mame/machine/electron.cpp index ac6b9df4dc4..464f4f7a0da 100644 --- a/src/mame/machine/electron.cpp +++ b/src/mame/machine/electron.cpp @@ -654,7 +654,7 @@ image_init_result electronsp_state::load_rom(device_image_interface &image, gene // socket accepts 8K and 16K ROM only if (size != 0x2000 && size != 0x4000) { - image.seterror(IMAGE_ERROR_UNSPECIFIED, "Invalid size: Only 8K/16K is supported"); + image.seterror(image_error::INVALIDIMAGE, "Invalid size: Only 8K/16K is supported"); return image_init_result::FAIL; } diff --git a/src/mame/machine/gamecom.cpp b/src/mame/machine/gamecom.cpp index 94ce240f443..727f4f8e8ab 100644 --- a/src/mame/machine/gamecom.cpp +++ b/src/mame/machine/gamecom.cpp @@ -627,7 +627,7 @@ image_init_result gamecom_state::common_load(device_image_interface &image, gene if (size != 0x008000 && size != 0x040000 && size != 0x080000 && size != 0x100000 && size != 0x1c0000 && size != 0x200000) { - image.seterror(IMAGE_ERROR_UNSPECIFIED, "Unsupported cartridge size"); + image.seterror(image_error::INVALIDIMAGE, "Unsupported cartridge size"); return image_init_result::FAIL; } diff --git a/src/mame/machine/m1comm.cpp b/src/mame/machine/m1comm.cpp index e43d5251845..64e763e41f7 100644 --- a/src/mame/machine/m1comm.cpp +++ b/src/mame/machine/m1comm.cpp @@ -560,7 +560,7 @@ int m1comm_device::read_frame(int dataSize) // try to read a message std::uint32_t recv = 0; - osd_file::error filerr = m_line_rx->read(m_buffer0, 0, dataSize, recv); + std::error_condition filerr = m_line_rx->read(m_buffer0, 0, dataSize, recv); if (recv > 0) { // check if message complete @@ -581,14 +581,14 @@ int m1comm_device::read_frame(int dataSize) togo -= recv; offset += recv; } - else if (filerr == osd_file::error::NONE && recv == 0) + else if (!filerr && recv == 0) { togo = 0; } } } } - else if (filerr == osd_file::error::NONE && recv == 0) + else if (!filerr && recv == 0) { if (m_linkalive == 0x01) { @@ -619,11 +619,11 @@ void m1comm_device::send_frame(int dataSize){ if (!m_line_tx) return; - osd_file::error filerr; + std::error_condition filerr; std::uint32_t written; filerr = m_line_tx->write(&m_buffer0, 0, dataSize, written); - if (filerr != osd_file::error::NONE) + if (filerr) { if (m_linkalive == 0x01) { diff --git a/src/mame/machine/m2comm.cpp b/src/mame/machine/m2comm.cpp index 4008cd9fd3f..dd25325f6f6 100644 --- a/src/mame/machine/m2comm.cpp +++ b/src/mame/machine/m2comm.cpp @@ -632,7 +632,7 @@ int m2comm_device::read_frame(int dataSize) // try to read a message std::uint32_t recv = 0; - osd_file::error filerr = m_line_rx->read(m_buffer0, 0, dataSize, recv); + std::error_condition filerr = m_line_rx->read(m_buffer0, 0, dataSize, recv); if (recv > 0) { // check if message complete @@ -653,14 +653,14 @@ int m2comm_device::read_frame(int dataSize) togo -= recv; offset += recv; } - else if (filerr == osd_file::error::NONE && recv == 0) + else if (!filerr && recv == 0) { togo = 0; } } } } - else if (filerr == osd_file::error::NONE && recv == 0) + else if (!filerr && recv == 0) { if (m_linkalive == 0x01) { @@ -687,11 +687,11 @@ void m2comm_device::send_frame(int dataSize){ if (!m_line_tx) return; - osd_file::error filerr; + std::error_condition filerr; std::uint32_t written; filerr = m_line_tx->write(&m_buffer0, 0, dataSize, written); - if (filerr != osd_file::error::NONE) + if (filerr) { if (m_linkalive == 0x01) { diff --git a/src/mame/machine/mbee.cpp b/src/mame/machine/mbee.cpp index a70c470c445..c6a9ec55763 100644 --- a/src/mame/machine/mbee.cpp +++ b/src/mame/machine/mbee.cpp @@ -731,7 +731,7 @@ image_init_result mbee_state::load_cart(device_image_interface &image, generic_s // "mbp" roms if ((size == 0) || (size > 0x4000)) { - image.seterror(IMAGE_ERROR_UNSPECIFIED, "Unsupported ROM size"); + image.seterror(image_error::INVALIDIMAGE, "Unsupported ROM size"); return image_init_result::FAIL; } @@ -744,7 +744,7 @@ image_init_result mbee_state::load_cart(device_image_interface &image, generic_s logerror ("Rom header = %02X %02X %02X\n", slot->read_rom(0), slot->read_rom(1), slot->read_rom(2)); if ((slot->read_rom(0) != 0xc3) || ((slot->read_rom(2) & 0xe0) != 0xc0)) { - image.seterror(IMAGE_ERROR_UNSPECIFIED, "Not a PAK rom"); + image.seterror(image_error::INVALIDIMAGE, "Not a PAK rom"); slot->call_unload(); return image_init_result::FAIL; } @@ -754,7 +754,7 @@ image_init_result mbee_state::load_cart(device_image_interface &image, generic_s // "mbn" roms if ((size == 0) || (size > 0x2000)) { - image.seterror(IMAGE_ERROR_UNSPECIFIED, "Unsupported ROM size"); + image.seterror(image_error::INVALIDIMAGE, "Unsupported ROM size"); return image_init_result::FAIL; } m_pak_extended[pak_index] = (size > 0x1000) ? true : false; @@ -768,7 +768,7 @@ image_init_result mbee_state::load_cart(device_image_interface &image, generic_s { if ((slot->read_rom(0) != 0xc3) || ((slot->read_rom(2) & 0xf0) != 0xe0)) { - image.seterror(IMAGE_ERROR_UNSPECIFIED, "Not a NET rom"); + image.seterror(image_error::INVALIDIMAGE, "Not a NET rom"); slot->call_unload(); return image_init_result::FAIL; } diff --git a/src/mame/machine/mtx.cpp b/src/mame/machine/mtx.cpp index 8c0c086aab0..3cccaa3d7bf 100644 --- a/src/mame/machine/mtx.cpp +++ b/src/mame/machine/mtx.cpp @@ -397,7 +397,7 @@ DEVICE_IMAGE_LOAD_MEMBER( mtx_state::extrom_load ) if (size > 0x80000) { - image.seterror(IMAGE_ERROR_UNSPECIFIED, "Unsupported rom size"); + image.seterror(image_error::INVALIDIMAGE, "Unsupported rom size"); return image_init_result::FAIL; } @@ -417,7 +417,7 @@ DEVICE_IMAGE_LOAD_MEMBER( mtx_state::rompak_load ) if (size > 0x2000) { - image.seterror(IMAGE_ERROR_UNSPECIFIED, "Unsupported cartridge size"); + image.seterror(image_error::INVALIDIMAGE, "Unsupported cartridge size"); return image_init_result::FAIL; } @@ -441,7 +441,7 @@ SNAPSHOT_LOAD_MEMBER(mtx_state::snapshot_cb) // verify first byte if (data[0] != 0xff) { - image.seterror(IMAGE_ERROR_INVALIDIMAGE, nullptr); + image.seterror(image_error::INVALIDIMAGE, nullptr); return image_init_result::FAIL; } @@ -488,7 +488,7 @@ QUICKLOAD_LOAD_MEMBER(mtx_state::quickload_cb) if (image.length() < 4) { - image.seterror(IMAGE_ERROR_INVALIDIMAGE, "File too short"); + image.seterror(image_error::INVALIDIMAGE, "File too short"); return image_init_result::FAIL; } @@ -497,13 +497,13 @@ QUICKLOAD_LOAD_MEMBER(mtx_state::quickload_cb) if (image.length() < code_length) { - image.seterror(IMAGE_ERROR_INVALIDIMAGE, "File too short"); + image.seterror(image_error::INVALIDIMAGE, "File too short"); return image_init_result::FAIL; } if (code_base < 0x4000 || (code_base + code_length) >= 0x10000) { - image.seterror(IMAGE_ERROR_INVALIDIMAGE, "Invalid code base and length"); + image.seterror(image_error::INVALIDIMAGE, "Invalid code base and length"); return image_init_result::FAIL; } diff --git a/src/mame/machine/s32comm.cpp b/src/mame/machine/s32comm.cpp index b53448b46d3..420b7d54471 100644 --- a/src/mame/machine/s32comm.cpp +++ b/src/mame/machine/s32comm.cpp @@ -266,7 +266,7 @@ int s32comm_device::read_frame(int dataSize) // try to read a message std::uint32_t recv = 0; - osd_file::error filerr = m_line_rx->read(m_buffer0, 0, dataSize, recv); + std::error_condition filerr = m_line_rx->read(m_buffer0, 0, dataSize, recv); if (recv > 0) { // check if message complete @@ -287,14 +287,14 @@ int s32comm_device::read_frame(int dataSize) togo -= recv; offset += recv; } - else if (filerr == osd_file::error::NONE && recv == 0) + else if (!filerr && recv == 0) { togo = 0; } } } } - else if (filerr == osd_file::error::NONE && recv == 0) + else if (!filerr && recv == 0) { if (m_linkalive == 0x01) { @@ -322,11 +322,11 @@ void s32comm_device::send_frame(int dataSize){ if (!m_line_tx) return; - osd_file::error filerr; + std::error_condition filerr; std::uint32_t written; filerr = m_line_tx->write(&m_buffer0, 0, dataSize, written); - if (filerr != osd_file::error::NONE) + if (filerr) { if (m_linkalive == 0x01) { diff --git a/src/mame/machine/sorcerer.cpp b/src/mame/machine/sorcerer.cpp index d4eac2ac17d..84a696c1040 100644 --- a/src/mame/machine/sorcerer.cpp +++ b/src/mame/machine/sorcerer.cpp @@ -600,7 +600,7 @@ QUICKLOAD_LOAD_MEMBER(sorcerer_state::quickload_cb) // check size if (image.length() != 0x1001c) { - image.seterror(IMAGE_ERROR_INVALIDIMAGE, "Snapshot must be 65564 bytes"); + image.seterror(image_error::INVALIDIMAGE, "Snapshot must be 65564 bytes"); image.message("Snapshot must be 65564 bytes"); return image_init_result::FAIL; } diff --git a/src/mame/machine/thomson.cpp b/src/mame/machine/thomson.cpp index 16afac21ceb..f8201ded8da 100644 --- a/src/mame/machine/thomson.cpp +++ b/src/mame/machine/thomson.cpp @@ -281,7 +281,7 @@ DEVICE_IMAGE_LOAD_MEMBER( thomson_state::to7_cartridge ) m_thom_cart_nb_banks = 4; else { - image.seterror(IMAGE_ERROR_UNSUPPORTED, string_format("Invalid cartridge size %u", size).c_str()); + image.seterror(image_error::INVALIDIMAGE, string_format("Invalid cartridge size %u", size).c_str()); return image_init_result::FAIL; } @@ -289,7 +289,7 @@ DEVICE_IMAGE_LOAD_MEMBER( thomson_state::to7_cartridge ) { if ( image.fread( pos, size ) != size ) { - image.seterror(IMAGE_ERROR_INVALIDIMAGE, "Read error"); + image.seterror(image_error::INVALIDIMAGE, "Read error"); return image_init_result::FAIL; } } @@ -1389,7 +1389,7 @@ DEVICE_IMAGE_LOAD_MEMBER( thomson_state::mo5_cartridge ) m_thom_cart_nb_banks = 4; else { - image.seterror(IMAGE_ERROR_UNSUPPORTED, string_format("Invalid cartridge size %d", size).c_str()); + image.seterror(image_error::INVALIDIMAGE, string_format("Invalid cartridge size %d", size).c_str()); return image_init_result::FAIL; } @@ -1397,7 +1397,7 @@ DEVICE_IMAGE_LOAD_MEMBER( thomson_state::mo5_cartridge ) { if ( image.fread(pos, size ) != size ) { - image.seterror(IMAGE_ERROR_INVALIDIMAGE, "Read error"); + image.seterror(image_error::INVALIDIMAGE, "Read error"); return image_init_result::FAIL; } } diff --git a/src/mame/machine/vtech2.cpp b/src/mame/machine/vtech2.cpp index 3ac1e62ce3f..0e8a2bea126 100644 --- a/src/mame/machine/vtech2.cpp +++ b/src/mame/machine/vtech2.cpp @@ -54,7 +54,7 @@ DEVICE_IMAGE_LOAD_MEMBER( vtech2_state::cart_load ) if (m_cart_size > 0x10000) { - image.seterror(IMAGE_ERROR_UNSPECIFIED, "Cartridge bigger than 64k"); + image.seterror(image_error::INVALIDIMAGE, "Cartridge bigger than 64k"); m_cart_size = 0; return image_init_result::FAIL; } diff --git a/src/mame/machine/z80bin.cpp b/src/mame/machine/z80bin.cpp index ba24d545d1f..c14cf196819 100644 --- a/src/mame/machine/z80bin.cpp +++ b/src/mame/machine/z80bin.cpp @@ -23,7 +23,7 @@ image_init_result z80bin_load_file(device_image_interface &image, address_space { if (ch == EOF) { - image.seterror(IMAGE_ERROR_INVALIDIMAGE, "Unexpected EOF while getting file name"); + image.seterror(image_error::INVALIDIMAGE, "Unexpected EOF while getting file name"); image.message(" Unexpected EOF while getting file name"); return image_init_result::FAIL; } @@ -32,7 +32,7 @@ image_init_result z80bin_load_file(device_image_interface &image, address_space { if (i >= (std::size(pgmname) - 1)) { - image.seterror(IMAGE_ERROR_INVALIDIMAGE, "File name too long"); + image.seterror(image_error::INVALIDIMAGE, "File name too long"); image.message(" File name too long"); return image_init_result::FAIL; } @@ -46,7 +46,7 @@ image_init_result z80bin_load_file(device_image_interface &image, address_space if (image.fread(args, sizeof(args)) != sizeof(args)) { - image.seterror(IMAGE_ERROR_INVALIDIMAGE, "Unexpected EOF while getting file size"); + image.seterror(image_error::INVALIDIMAGE, "Unexpected EOF while getting file size"); image.message(" Unexpected EOF while getting file size"); return image_init_result::FAIL; } @@ -66,7 +66,7 @@ image_init_result z80bin_load_file(device_image_interface &image, address_space if (image.fread(&data, 1) != 1) { snprintf(message, std::size(message), "%s: Unexpected EOF while writing byte to %04X", pgmname, (unsigned) j); - image.seterror(IMAGE_ERROR_INVALIDIMAGE, message); + image.seterror(image_error::INVALIDIMAGE, message); image.message("%s: Unexpected EOF while writing byte to %04X", pgmname, (unsigned) j); return image_init_result::FAIL; } diff --git a/src/mame/video/midtunit.cpp b/src/mame/video/midtunit.cpp index 4a74af2b188..7301e883fb6 100644 --- a/src/mame/video/midtunit.cpp +++ b/src/mame/video/midtunit.cpp @@ -902,7 +902,7 @@ void midtunit_video_device::log_bitmap(int command, int bpp, bool Skip) char name_buf[256]; snprintf(name_buf, 255, "0x%08x.png", raw_offset); auto const filerr = file.open(name_buf); - if (filerr != osd_file::error::NONE) + if (filerr) { return; } @@ -1029,7 +1029,7 @@ void midtunit_video_device::log_bitmap(int command, int bpp, bool Skip) snprintf(name_buf, 255, "0x%08x.json", raw_offset); auto const jsonerr = json.open(name_buf); - if (jsonerr != osd_file::error::NONE) + if (jsonerr) { return; } diff --git a/src/osd/modules/debugger/debuggdbstub.cpp b/src/osd/modules/debugger/debuggdbstub.cpp index 52289b9997d..6229e6ffba5 100644 --- a/src/osd/modules/debugger/debuggdbstub.cpp +++ b/src/osd/modules/debugger/debuggdbstub.cpp @@ -707,8 +707,8 @@ void debug_gdbstub::wait_for_debugger(device_t &device, bool firststop) #endif std::string socket_name = string_format("socket.localhost:%d", m_debugger_port); - osd_file::error filerr = m_socket.open(socket_name); - if ( filerr != osd_file::error::NONE ) + std::error_condition const filerr = m_socket.open(socket_name); + if ( filerr ) fatalerror("gdbstub: failed to start listening on port %d\n", m_debugger_port); osd_printf_info("gdbstub: listening on port %d\n", m_debugger_port); diff --git a/src/osd/modules/debugger/debugimgui.cpp b/src/osd/modules/debugger/debugimgui.cpp index 8c161792f9d..1046118899c 100644 --- a/src/osd/modules/debugger/debugimgui.cpp +++ b/src/osd/modules/debugger/debugimgui.cpp @@ -938,7 +938,7 @@ void debug_imgui::mount_image() { if(m_selected_file != nullptr) { - osd_file::error err; + std::error_condition err; switch(m_selected_file->type) { case file_entry_type::DRIVE: @@ -947,7 +947,7 @@ void debug_imgui::mount_image() util::zippath_directory::ptr dir; err = util::zippath_directory::open(m_selected_file->fullpath, dir); } - if(err == osd_file::error::NONE) + if(!err) { m_filelist_refresh = true; strcpy(m_path,m_selected_file->fullpath.c_str()); @@ -989,8 +989,8 @@ void debug_imgui::refresh_filelist() m_filelist_refresh = false; util::zippath_directory::ptr dir; - osd_file::error const err = util::zippath_directory::open(m_path,dir); - if(err == osd_file::error::NONE) + std::error_condition const err = util::zippath_directory::open(m_path,dir); + if(!err) { int x = 0; // add drives diff --git a/src/osd/modules/file/posixdomain.cpp b/src/osd/modules/file/posixdomain.cpp deleted file mode 100644 index 13d564d1738..00000000000 --- a/src/osd/modules/file/posixdomain.cpp +++ /dev/null @@ -1,208 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Olivier Galibert, R. Belmont, Vas Crabb -//============================================================ -// -// sdldomain.c - SDL socket (unix) access functions -// -// SDLMAME by Olivier Galibert and R. Belmont -// -//============================================================ - -#include "posixfile.h" - -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - - -namespace { -char const *const posixfile_domain_identifier = "domain."; - - -class posix_osd_domain : public osd_file -{ -public: - posix_osd_domain(posix_osd_domain const &) = delete; - posix_osd_domain(posix_osd_domain &&) = delete; - posix_osd_domain& operator=(posix_osd_domain const &) = delete; - posix_osd_domain& operator=(posix_osd_domain &&) = delete; - - posix_osd_domain(int sock, bool listening) - : m_sock(sock) - , m_listening(listening) - { - assert(m_sock >= 0); - } - - virtual ~posix_osd_domain() - { - ::close(m_sock); - } - - virtual error read(void *buffer, std::uint64_t offset, std::uint32_t count, std::uint32_t &actual) override - { - 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; - } - } - - 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 - - -bool posix_check_domain_path(std::string const &path) -{ - if (strncmp(path.c_str(), posixfile_domain_identifier, strlen(posixfile_domain_identifier)) == 0) - return true; - return false; -} - - -osd_file::error posix_open_domain(std::string const &path, std::uint32_t openflags, osd_file::ptr &file, std::uint64_t &filesize) -{ - struct sockaddr_un sau; - memset(&sau, 0, sizeof(sau)); - sau.sun_family = AF_UNIX; - strncpy(sau.sun_path, &path.c_str()[strlen(posixfile_domain_identifier)], sizeof(sau.sun_path)-1); - - int const sock = ::socket(AF_UNIX, SOCK_STREAM, 0); - if (sock < 0) - return errno_to_file_error(errno); - - fcntl(sock, F_SETFL, O_NONBLOCK); - - // listening socket support - if (openflags & OPEN_FLAG_CREATE) - { - if (::bind(sock, reinterpret_cast(&sau), sizeof(struct sockaddr_un)) < 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(sock, true); - filesize = 0; - return osd_file::error::NONE; - } - catch (...) - { - ::close(sock); - return osd_file::error::OUT_OF_MEMORY; - } - } - else - { - if (::connect(sock, reinterpret_cast(&sau), sizeof(struct sockaddr_un)) < 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(sock, false); - filesize = 0; - return osd_file::error::NONE; - } - catch (...) - { - ::close(sock); - return osd_file::error::OUT_OF_MEMORY; - } - } -} diff --git a/src/osd/modules/file/posixfile.cpp b/src/osd/modules/file/posixfile.cpp index ffdd4c4d477..b7c1cde7442 100644 --- a/src/osd/modules/file/posixfile.cpp +++ b/src/osd/modules/file/posixfile.cpp @@ -64,6 +64,7 @@ namespace { + //============================================================ // CONSTANTS //============================================================ @@ -85,7 +86,7 @@ public: 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) + posix_osd_file(int fd) noexcept : m_fd(fd) { assert(m_fd >= 0); } @@ -95,7 +96,7 @@ public: ::close(m_fd); } - virtual error read(void *buffer, std::uint64_t offset, std::uint32_t count, std::uint32_t &actual) override + virtual std::error_condition read(void *buffer, std::uint64_t offset, std::uint32_t count, std::uint32_t &actual) noexcept override { ssize_t result; @@ -103,20 +104,20 @@ public: result = ::pread(m_fd, buffer, size_t(count), off_t(std::make_unsigned_t(offset))); #elif defined(WIN32) || defined(SDLMAME_NO64BITIO) if (lseek(m_fd, off_t(std::make_unsigned_t(offset)), SEEK_SET) < 0) - return errno_to_file_error(errno) + return std::error_condition(errno, std::generic_category()); 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); + return std::error_condition(errno, std::generic_category()); actual = std::uint32_t(std::size_t(result)); - return error::NONE; + return std::error_condition(); } - virtual error write(void const *buffer, std::uint64_t offset, std::uint32_t count, std::uint32_t &actual) override + virtual std::error_condition write(void const *buffer, std::uint64_t offset, std::uint32_t count, std::uint32_t &actual) noexcept override { ssize_t result; @@ -124,20 +125,20 @@ public: result = ::pwrite(m_fd, buffer, size_t(count), off_t(std::make_unsigned_t(offset))); #elif defined(WIN32) || defined(SDLMAME_NO64BITIO) if (lseek(m_fd, off_t(std::make_unsigned_t(offset)), SEEK_SET) < 0) - return errno_to_file_error(errno) + return std::error_condition(errno, std::generic_category()); 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); + return std::error_condition(errno, std::generic_category()); actual = std::uint32_t(std::size_t(result)); - return error::NONE; + return std::error_condition(); } - virtual error truncate(std::uint64_t offset) override + virtual std::error_condition truncate(std::uint64_t offset) noexcept override { int result; @@ -148,15 +149,15 @@ public: #endif if (result < 0) - return errno_to_file_error(errno); + return std::error_condition(errno, std::generic_category()); - return error::NONE; + return std::error_condition(); } - virtual error flush() override + virtual std::error_condition flush() noexcept override { // no user-space buffering on unistd I/O - return error::NONE; + return std::error_condition(); } private: @@ -168,7 +169,7 @@ private: // is_path_separator //============================================================ -bool is_path_separator(char c) +bool is_path_separator(char c) noexcept { #if defined(WIN32) return (c == PATHSEPCH) || (c == INVPATHSEPCH); @@ -182,31 +183,36 @@ bool is_path_separator(char c) // create_path_recursive //============================================================ -osd_file::error create_path_recursive(std::string const &path) +std::error_condition create_path_recursive(std::string_view path) noexcept { // 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 - 1] != PATHSEPCH)) + if ((sep != std::string_view::npos) && (sep > 0) && (path[sep - 1] != PATHSEPCH)) { - osd_file::error const err = create_path_recursive(path.substr(0, sep)); - if (err != osd_file::error::NONE) + std::error_condition err = create_path_recursive(path.substr(0, sep)); + if (err) return err; } + // need a NUL-terminated version of the subpath + std::string p; + try { p = path; } + catch (...) { return std::errc::not_enough_memory; } + // if the path already exists, we're done struct stat st; - if (!::stat(path.c_str(), &st)) - return osd_file::error::NONE; + if (!::stat(p.c_str(), &st)) + return std::error_condition(); // create the path #ifdef WIN32 - if (mkdir(path.c_str()) < 0) + if (mkdir(p.c_str()) < 0) #else - if (mkdir(path.c_str(), 0777) < 0) + if (mkdir(p.c_str(), 0777) < 0) #endif - return errno_to_file_error(errno); + return std::error_condition(errno, std::generic_category()); else - return osd_file::error::NONE; + return std::error_condition(); } } // anonymous namespace @@ -216,7 +222,7 @@ osd_file::error create_path_recursive(std::string const &path) // osd_file::open //============================================================ -osd_file::error osd_file::open(std::string const &path, std::uint32_t openflags, ptr &file, std::uint64_t &filesize) +std::error_condition osd_file::open(std::string const &path, std::uint32_t openflags, ptr &file, std::uint64_t &filesize) noexcept { std::string dst; if (posix_check_socket_path(path)) @@ -239,7 +245,7 @@ osd_file::error osd_file::open(std::string const &path, std::uint32_t openflags, } else { - return error::INVALID_ACCESS; + return std::errc::invalid_argument; } #if defined(WIN32) access |= O_BINARY; @@ -251,7 +257,8 @@ osd_file::error osd_file::open(std::string const &path, std::uint32_t openflags, for (auto it = dst.begin(); it != dst.end(); ++it) *it = (INVPATHSEPCH == *it) ? PATHSEPCH : *it; #endif - osd_subst_env(dst, dst); + try { osd_subst_env(dst, dst); } + catch (...) { return std::errc::not_enough_memory; } // attempt to open the file int fd = -1; @@ -263,6 +270,9 @@ osd_file::error osd_file::open(std::string const &path, std::uint32_t openflags, if (fd < 0) { + // save the error from the first attempt to open the file + std::error_condition openerr(errno, std::generic_category()); + // create the path if necessary if ((openflags & OPEN_FLAG_CREATE) && (openflags & OPEN_FLAG_CREATE_PATHS)) { @@ -270,10 +280,10 @@ osd_file::error osd_file::open(std::string const &path, std::uint32_t openflags, if (pathsep != std::string::npos) { // create the path up to the file - osd_file::error const error = create_path_recursive(dst.substr(0, pathsep)); + std::error_condition const createrr = create_path_recursive(dst.substr(0, pathsep)); // attempt to reopen the file - if (error == osd_file::error::NONE) + if (!createrr) { #if defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__bsdi__) || defined(__DragonFly__) || defined(__HAIKU__) || defined(WIN32) || defined(SDLMAME_NO64BITIO) || defined(__ANDROID__) fd = ::open(dst.c_str(), access, 0666); @@ -281,13 +291,17 @@ osd_file::error osd_file::open(std::string const &path, std::uint32_t openflags, fd = ::open64(dst.c_str(), access, 0666); #endif } + if (fd < 0) + { + openerr.assign(errno, std::generic_category()); + } } } // if we still failed, clean up and free if (fd < 0) { - return errno_to_file_error(errno); + return openerr; } } @@ -300,22 +314,20 @@ osd_file::error osd_file::open(std::string const &path, std::uint32_t openflags, if (::fstat64(fd, &st) < 0) #endif { - int const error = errno; + std::error_condition staterr(errno, std::generic_category()); ::close(fd); - return errno_to_file_error(error); + return staterr; } - filesize = std::uint64_t(std::make_unsigned_t(st.st_size)); - try - { - file = std::make_unique(fd); - return error::NONE; - } - catch (...) + osd_file::ptr result(new (std::nothrow) posix_osd_file(fd)); + if (!result) { ::close(fd); - return error::OUT_OF_MEMORY; + return std::errc::not_enough_memory; } + file = std::move(result); + filesize = std::uint64_t(std::make_unsigned_t(st.st_size)); + return std::error_condition(); } @@ -323,9 +335,9 @@ osd_file::error osd_file::open(std::string const &path, std::uint32_t openflags, // osd_file::openpty //============================================================ -osd_file::error osd_file::openpty(ptr &file, std::string &name) +std::error_condition osd_file::openpty(ptr &file, std::string &name) noexcept { - std::uint64_t filesize; + std::uint64_t filesize; return posix_open_ptty(OPEN_FLAG_READ | OPEN_FLAG_WRITE, file, filesize, name); } @@ -334,12 +346,12 @@ osd_file::error osd_file::openpty(ptr &file, std::string &name) // osd_file::remove //============================================================ -osd_file::error osd_file::remove(std::string const &filename) +std::error_condition osd_file::remove(std::string const &filename) noexcept { if (::unlink(filename.c_str()) < -1) - return errno_to_file_error(errno); + return std::error_condition(errno, std::generic_category()); else - return error::NONE; + return std::error_condition(); } @@ -347,7 +359,7 @@ osd_file::error osd_file::remove(std::string const &filename) // osd_get_physical_drive_geometry //============================================================ -bool osd_get_physical_drive_geometry(const char *filename, uint32_t *cylinders, uint32_t *heads, uint32_t *sectors, uint32_t *bps) +bool osd_get_physical_drive_geometry(const char *filename, uint32_t *cylinders, uint32_t *heads, uint32_t *sectors, uint32_t *bps) noexcept { return false; // no, no way, huh-uh, forget it } @@ -389,7 +401,7 @@ std::unique_ptr osd_stat(const std::string &path) // osd_get_full_path //============================================================ -osd_file::error osd_get_full_path(std::string &dst, std::string const &path) +std::error_condition osd_get_full_path(std::string &dst, std::string const &path) noexcept { try { @@ -398,49 +410,49 @@ osd_file::error osd_get_full_path(std::string &dst, std::string const &path) if (::_fullpath(&path_buffer[0], path.c_str(), MAX_PATH)) { dst = &path_buffer[0]; - return osd_file::error::NONE; + return std::error_condition(); } else { - return osd_file::error::FAILURE; + return std::errc::io_error; // TODO: better error reporting? } #else std::unique_ptr canonical(::realpath(path.c_str(), nullptr), &std::free); if (canonical) { dst = canonical.get(); - return osd_file::error::NONE; + return std::error_condition(); } std::vector path_buffer(PATH_MAX); if (::realpath(path.c_str(), &path_buffer[0])) { dst = &path_buffer[0]; - return osd_file::error::NONE; + return std::error_condition(); } else if (path[0] == PATHSEPCH) { dst = path; - return osd_file::error::NONE; + return std::error_condition(); } else { while (!::getcwd(&path_buffer[0], path_buffer.size())) { if (errno != ERANGE) - return errno_to_file_error(errno); + return std::error_condition(errno, std::generic_category()); else path_buffer.resize(path_buffer.size() * 2); } dst.assign(&path_buffer[0]).push_back(PATHSEPCH); dst.append(path); - return osd_file::error::NONE; + return std::error_condition(); } #endif } catch (...) { - return osd_file::error::OUT_OF_MEMORY; + return std::errc::not_enough_memory; } } @@ -449,7 +461,7 @@ osd_file::error osd_get_full_path(std::string &dst, std::string const &path) // osd_is_absolute_path //============================================================ -bool osd_is_absolute_path(std::string const &path) +bool osd_is_absolute_path(std::string const &path) noexcept { if (!path.empty() && is_path_separator(path[0])) return true; @@ -492,7 +504,7 @@ std::vector osd_get_volume_names() // osd_is_valid_filename_char //============================================================ -bool osd_is_valid_filename_char(char32_t uchar) +bool osd_is_valid_filename_char(char32_t uchar) noexcept { // The only one that's actually invalid is the slash // The other two are just problematic because they're the escape character and path separator @@ -512,7 +524,7 @@ bool osd_is_valid_filename_char(char32_t uchar) // osd_is_valid_filepath_char //============================================================ -bool osd_is_valid_filepath_char(char32_t uchar) +bool osd_is_valid_filepath_char(char32_t uchar) noexcept { // One could argue that colon should be in here too because it functions as path separator return uchar >= 0x20 @@ -527,39 +539,3 @@ bool osd_is_valid_filepath_char(char32_t uchar) #endif && uchar_isvalid(uchar); } - - -//============================================================ -// errno_to_file_error -//============================================================ - -osd_file::error errno_to_file_error(int error) -{ - switch (error) - { - case 0: - return osd_file::error::NONE; - - case ENOENT: - case ENOTDIR: - return osd_file::error::NOT_FOUND; - - case EACCES: - case EROFS: -#ifndef WIN32 - case ETXTBSY: -#endif - case EEXIST: - case EPERM: - case EISDIR: - case EINVAL: - return osd_file::error::ACCESS_DENIED; - - case ENFILE: - case EMFILE: - return osd_file::error::TOO_MANY_FILES; - - default: - return osd_file::error::FAILURE; - } -} diff --git a/src/osd/modules/file/posixfile.h b/src/osd/modules/file/posixfile.h index d47c03d691e..eb6f010859e 100644 --- a/src/osd/modules/file/posixfile.h +++ b/src/osd/modules/file/posixfile.h @@ -7,25 +7,29 @@ // SDLMAME by Olivier Galibert and R. Belmont // //============================================================ +#ifndef MAME_OSD_MODULES_FILE_POSIXFILE_H +#define MAME_OSD_MODULES_FILE_POSIXFILE_H +#pragma once #include "osdfile.h" #include #include +#include //============================================================ // 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_socket_path(std::string const &path) noexcept; +std::error_condition posix_open_socket(std::string const &path, std::uint32_t openflags, osd_file::ptr &file, std::uint64_t &filesize) noexcept; -bool posix_check_domain_path(std::string const &path); -osd_file::error posix_open_domain(std::string const &path, std::uint32_t openflags, osd_file::ptr &file, std::uint64_t &filesize); +bool posix_check_domain_path(std::string const &path) noexcept; +std::error_condition posix_open_domain(std::string const &path, std::uint32_t openflags, osd_file::ptr &file, std::uint64_t &filesize) noexcept; -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); +bool posix_check_ptty_path(std::string const &path) noexcept; +std::error_condition posix_open_ptty(std::uint32_t openflags, osd_file::ptr &file, std::uint64_t &filesize, std::string &name) noexcept; -osd_file::error errno_to_file_error(int error); +#endif // MAME_OSD_MODULES_FILE_POSIXFILE_H diff --git a/src/osd/modules/file/posixptty.cpp b/src/osd/modules/file/posixptty.cpp index 5ecb37057ad..57ff069a2ce 100644 --- a/src/osd/modules/file/posixptty.cpp +++ b/src/osd/modules/file/posixptty.cpp @@ -52,7 +52,7 @@ public: 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) + posix_osd_ptty(int fd) noexcept : m_fd(fd) { assert(m_fd >= 0); } @@ -62,36 +62,36 @@ public: ::close(m_fd); } - virtual error read(void *buffer, std::uint64_t offset, std::uint32_t count, std::uint32_t &actual) override + virtual std::error_condition read(void *buffer, std::uint64_t offset, std::uint32_t count, std::uint32_t &actual) noexcept override { ssize_t const result = ::read(m_fd, buffer, count); if (result < 0) - return errno_to_file_error(errno); + return std::error_condition(errno, std::generic_category()); actual = std::uint32_t(size_t(result)); - return error::NONE; + return std::error_condition(); } - virtual error write(void const *buffer, std::uint64_t offset, std::uint32_t count, std::uint32_t &actual) override + virtual std::error_condition write(void const *buffer, std::uint64_t offset, std::uint32_t count, std::uint32_t &actual) noexcept override { ssize_t const result = ::write(m_fd, buffer, count); if (result < 0) - return errno_to_file_error(errno); + return std::error_condition(errno, std::generic_category()); actual = std::uint32_t(size_t(result)); - return error::NONE; + return std::error_condition(); } - virtual error truncate(std::uint64_t offset) override + virtual std::error_condition truncate(std::uint64_t offset) noexcept override { // doesn't make sense on ptty - return error::INVALID_ACCESS; + return std::errc::bad_file_descriptor; } - virtual error flush() override + virtual std::error_condition flush() noexcept override { // no userspace buffers on read/write - return error::NONE; + return std::error_condition(); } private: @@ -101,17 +101,18 @@ private: } // anonymous namespace -bool posix_check_ptty_path(std::string const &path) +bool posix_check_ptty_path(std::string const &path) noexcept { 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) +std::error_condition posix_open_ptty(std::uint32_t openflags, osd_file::ptr &file, std::uint64_t &filesize, std::string &name) noexcept { #if defined(__ANDROID__) - return osd_file::error::FAILURE; + return std::errc::not_supported; // TODO: revisit this error code #else // defined(__ANDROID__) + // TODO: handling of the slave path is insecure - should use ptsname_r/ttyname_r in a loop #if (defined(sun) || defined(__sun)) && (defined(__SVR4) || defined(__svr4__)) int access = O_NOCTTY; if (openflags & OPEN_FLAG_WRITE) @@ -119,11 +120,11 @@ osd_file::error posix_open_ptty(std::uint32_t openflags, osd_file::ptr &file, st else if (openflags & OPEN_FLAG_READ) access |= O_RDONLY; else - return osd_file::error::INVALID_ACCESS; + return std::errc::invalid_argument; int const masterfd = ::posix_openpt(access); if (masterfd < 0) - return errno_to_file_error(errno); + return std::error_condition(errno, std::generic_category()); // grant access to slave device and check that it can be opened char const *slavepath; @@ -133,9 +134,9 @@ osd_file::error posix_open_ptty(std::uint32_t openflags, osd_file::ptr &file, st ((slavepath = ::ptsname(masterfd)) == nullptr) || ((slavefd = ::open(slavepath, O_RDWR | O_NOCTTY)) < 0)) { - int const err = errno; + std::error_condition err(errno, std::generic_category()); ::close(masterfd); - return errno_to_file_error(err); + return err; } // check that it's possible to stack BSD-compatibility STREAMS modules @@ -143,20 +144,20 @@ osd_file::error posix_open_ptty(std::uint32_t openflags, osd_file::ptr &file, st (::ioctl(slavefd, I_PUSH, "ldterm") < 0) || (::ioctl(slavefd, I_PUSH, "ttcompat") < 0)) { - int const err = errno; + std::error_condition err(errno, std::generic_category()); ::close(slavefd); ::close(masterfd); - return errno_to_file_error(err); + return err; } #else struct termios tios; std::memset(&tios, 0, sizeof(tios)); - ::cfmakeraw(&tios); + ::cfmakeraw(&tios); // TODO: this is a non-standard BSDism - should set flags some other way int masterfd = -1, slavefd = -1; char slavepath[PATH_MAX]; if (::openpty(&masterfd, &slavefd, slavepath, &tios, nullptr) < 0) - return errno_to_file_error(errno); + return std::error_condition(errno, std::generic_category()); #endif ::close(slavefd); @@ -164,16 +165,16 @@ osd_file::error posix_open_ptty(std::uint32_t openflags, osd_file::ptr &file, st int const oldflags = ::fcntl(masterfd, F_GETFL, 0); if (oldflags < 0) { - int const err = errno; + std::error_condition err(errno, std::generic_category()); ::close(masterfd); - return errno_to_file_error(err); + return err; } if (::fcntl(masterfd, F_SETFL, oldflags | O_NONBLOCK) < 0) { - int const err = errno; + std::error_condition err(errno, std::generic_category()); ::close(masterfd); - return errno_to_file_error(err); + return err; } try @@ -181,12 +182,12 @@ osd_file::error posix_open_ptty(std::uint32_t openflags, osd_file::ptr &file, st name = slavepath; file = std::make_unique(masterfd); filesize = 0; - return osd_file::error::NONE; + return std::error_condition(); } catch (...) { ::close(masterfd); - return osd_file::error::OUT_OF_MEMORY; + return std::errc::not_enough_memory; } #endif // defined(__ANDROID__) } diff --git a/src/osd/modules/file/posixsocket.cpp b/src/osd/modules/file/posixsocket.cpp index 2ce5ad05d5c..4770e91c6a9 100644 --- a/src/osd/modules/file/posixsocket.cpp +++ b/src/osd/modules/file/posixsocket.cpp @@ -2,7 +2,8 @@ // copyright-holders:Olivier Galibert, R. Belmont, Vas Crabb //============================================================ // -// sdlsocket.c - SDL socket (inet) access functions +// sdlsocket.c - SDL socket (inet, unix domain) access +// functions // // SDLMAME by Olivier Galibert and R. Belmont // @@ -16,17 +17,21 @@ #include #include +#include #include #include #include #include #include #include +#include #include namespace { + char const *const posixfile_socket_identifier = "socket."; +char const *const posixfile_domain_identifier = "domain."; class posix_osd_socket : public osd_file @@ -37,7 +42,7 @@ public: posix_osd_socket& operator=(posix_osd_socket const &) = delete; posix_osd_socket& operator=(posix_osd_socket &&) = delete; - posix_osd_socket(int sock, bool listening) + posix_osd_socket(int sock, bool listening) noexcept : m_sock(sock) , m_listening(listening) { @@ -49,7 +54,7 @@ public: ::close(m_sock); } - virtual error read(void *buffer, std::uint64_t offset, std::uint32_t count, std::uint32_t &actual) override + virtual std::error_condition read(void *buffer, std::uint64_t offset, std::uint32_t count, std::uint32_t &actual) noexcept override { fd_set readfds; FD_ZERO(&readfds); @@ -58,12 +63,9 @@ public: struct timeval timeout; timeout.tv_sec = timeout.tv_usec = 0; - if (select(m_sock + 1, &readfds, nullptr, nullptr, &timeout) < 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); + return std::error_condition(errno, std::generic_category()); } else if (FD_ISSET(m_sock, &readfds)) { @@ -73,12 +75,12 @@ public: ssize_t const result = ::read(m_sock, buffer, count); if (result < 0) { - return errno_to_file_error(errno); + return std::error_condition(errno, std::generic_category()); } else { actual = std::uint32_t(size_t(result)); - return error::NONE; + return std::error_condition(); } } else @@ -87,7 +89,7 @@ public: int const accepted = ::accept(m_sock, nullptr, nullptr); if (accepted < 0) { - return errno_to_file_error(errno); + return std::error_condition(errno, std::generic_category()); } else { @@ -96,36 +98,38 @@ public: m_listening = false; actual = 0; - return error::NONE; + return std::error_condition(); } } } else { - return error::FAILURE; + // no data available + actual = 0; + return std::error_condition(); } } - virtual error write(void const *buffer, std::uint64_t offset, std::uint32_t count, std::uint32_t &actual) override + virtual std::error_condition write(void const *buffer, std::uint64_t offset, std::uint32_t count, std::uint32_t &actual) noexcept override { ssize_t const result = ::write(m_sock, buffer, count); if (result < 0) - return errno_to_file_error(errno); + return std::error_condition(errno, std::generic_category()); actual = std::uint32_t(size_t(result)); - return error::NONE; + return std::error_condition(); } - virtual error truncate(std::uint64_t offset) override + virtual std::error_condition truncate(std::uint64_t offset) noexcept override { // doesn't make sense on socket - return error::INVALID_ACCESS; + return std::errc::bad_file_descriptor; } - virtual error flush() override + virtual std::error_condition flush() noexcept override { // there's no simple way to flush buffers on a socket anyway - return error::NONE; + return std::error_condition(); } private: @@ -133,6 +137,54 @@ private: bool m_listening; }; + +template +std::error_condition create_socket(T const &sa, int sock, std::uint32_t openflags, osd_file::ptr &file, std::uint64_t &filesize) noexcept +{ + osd_file::ptr result; + if (openflags & OPEN_FLAG_CREATE) + { + // listening socket support + // bind socket... + if (::bind(sock, reinterpret_cast(&sa), sizeof(sa)) < 0) + { + std::error_condition binderr(errno, std::generic_category()); + ::close(sock); + return binderr; + } + + // start to listen... + if (::listen(sock, 1) < 0) + { + std::error_condition lstnerr(errno, std::generic_category()); + ::close(sock); + return lstnerr; + } + + // mark socket as "listening" + result.reset(new (std::nothrow) posix_osd_socket(sock, true)); + } + else + { + if (::connect(sock, reinterpret_cast(&sa), sizeof(sa)) < 0) + { + std::error_condition connerr(errno, std::generic_category()); + ::close(sock); + return connerr; + } + result.reset(new (std::nothrow) posix_osd_socket(sock, false)); + } + + if (!result) + { + ::close(sock); + return std::errc::not_enough_memory; + } + file = std::move(result); + filesize = 0; + return std::error_condition(); +} + } // anonymous namespace @@ -141,7 +193,7 @@ private: 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) +bool posix_check_socket_path(std::string const &path) noexcept { if (strncmp(path.c_str(), posixfile_socket_identifier, strlen(posixfile_socket_identifier)) == 0 && strchr(path.c_str(), ':') != nullptr) return true; @@ -149,7 +201,15 @@ 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_domain_path(std::string const &path) noexcept +{ + if (strncmp(path.c_str(), posixfile_domain_identifier, strlen(posixfile_domain_identifier)) == 0) + return true; + return false; +} + + +std::error_condition posix_open_socket(std::string const &path, std::uint32_t openflags, osd_file::ptr &file, std::uint64_t &filesize) noexcept { char hostname[256]; int port; @@ -157,7 +217,7 @@ osd_file::error posix_open_socket(std::string const &path, std::uint32_t openfla struct hostent const *const localhost = ::gethostbyname(hostname); if (!localhost) - return osd_file::error::NOT_FOUND; + return std::errc::no_such_file_or_directory; struct sockaddr_in sai; memset(&sai, 0, sizeof(sai)); @@ -167,75 +227,38 @@ osd_file::error posix_open_socket(std::string const &path, std::uint32_t openfla int const sock = ::socket(AF_INET, SOCK_STREAM, 0); if (sock < 0) - return errno_to_file_error(errno); + return std::error_condition(errno, std::generic_category()); int const flag = 1; - if (::setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, reinterpret_cast(&flag), sizeof(flag)) < 0) + if ((::setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, reinterpret_cast(&flag), sizeof(flag)) < 0) || + (::setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, reinterpret_cast(&flag), sizeof(flag)) < 0)) { - int const err = errno; + std::error_condition sockopterr(errno, std::generic_category()); ::close(sock); - return errno_to_file_error(err); + return sockopterr; } - if (::setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, reinterpret_cast(&flag), sizeof(flag)) < 0) - { - int const err = errno; - ::close(sock); - return errno_to_file_error(err); - } + return create_socket(sai, sock, openflags, file, filesize); +} - // 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(&sai), sizeof(struct sockaddr)) < 0) - { - int const err = errno; - ::close(sock); - return errno_to_file_error(err); - } +std::error_condition posix_open_domain(std::string const &path, std::uint32_t openflags, osd_file::ptr &file, std::uint64_t &filesize) noexcept +{ + struct sockaddr_un sau; + memset(&sau, 0, sizeof(sau)); + sau.sun_family = AF_UNIX; + strncpy(sau.sun_path, &path.c_str()[strlen(posixfile_domain_identifier)], sizeof(sau.sun_path)-1); - // start to listen... - if (::listen(sock, 1) < 0) - { - int const err = errno; - ::close(sock); - return errno_to_file_error(err); - } + int const sock = ::socket(AF_UNIX, SOCK_STREAM, 0); + if (sock < 0) + return std::error_condition(errno, std::generic_category()); - // mark socket as "listening" - try - { - file = std::make_unique(sock, true); - filesize = 0; - return osd_file::error::NONE; - } - catch (...) - { - ::close(sock); - return osd_file::error::OUT_OF_MEMORY; - } - } - else + if (fcntl(sock, F_SETFL, O_NONBLOCK) < 0) { - //printf("Connecting to server '%s' on port '%d'\n", hostname, port); - if (::connect(sock, reinterpret_cast(&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(sock, false); - filesize = 0; - return osd_file::error::NONE; - } - catch (...) - { - ::close(sock); - return osd_file::error::OUT_OF_MEMORY; - } + std::error_condition cntlerr(errno, std::generic_category()); + ::close(sock); + return cntlerr; } + + return create_socket(sau, sock, openflags, file, filesize); } diff --git a/src/osd/modules/file/stdfile.cpp b/src/osd/modules/file/stdfile.cpp index 96d7e53ebbe..4fd4662b884 100644 --- a/src/osd/modules/file/stdfile.cpp +++ b/src/osd/modules/file/stdfile.cpp @@ -10,12 +10,14 @@ #include "osdfile.h" #include +#include #include #include #include +#include #include -#include // for fileno +#include // for fileno #include // for ftruncate @@ -25,7 +27,10 @@ class std_osd_file : public osd_file { public: - std_osd_file(FILE *f) : m_file(f) { assert(m_file); } + std_osd_file(FILE *f) noexcept : m_file(f) + { + assert(m_file); + } //============================================================ // osd_close @@ -34,59 +39,81 @@ public: virtual ~std_osd_file() override { // close the file handle - if (m_file) std::fclose(m_file); + 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 + virtual std::error_condition read(void *buffer, std::uint64_t offset, std::uint32_t length, std::uint32_t &actual) noexcept override { - // seek to the new location; note that most fseek implementations are limited to 32 bits + // seek to the new location; note that most fseek implementations are limited to the range of long int + if (std::numeric_limits::max() < offset) + return std::errc::invalid_argument; if (std::fseek(m_file, offset, SEEK_SET) < 0) - return error::FAILURE; + return std::error_condition(errno, std::generic_category()); // perform the read std::size_t const count = std::fread(buffer, 1, length, m_file); + if ((count < length) && std::ferror(m_file)) + { + std::clearerr(m_file); + return std::error_condition(errno, std::generic_category()); + } actual = count; - return error::NONE; + return std::error_condition(); } //============================================================ // osd_write //============================================================ - virtual error write(const void *buffer, std::uint64_t offset, std::uint32_t length, std::uint32_t &actual) override + virtual std::error_condition write(const void *buffer, std::uint64_t offset, std::uint32_t length, std::uint32_t &actual) noexcept override { - // seek to the new location; note that most fseek implementations are limited to 32 bits + // seek to the new location; note that most fseek implementations are limited to the range of long int + if (std::numeric_limits::max() < offset) + return std::errc::invalid_argument; if (std::fseek(m_file, offset, SEEK_SET) < 0) - return error::FAILURE; + return std::error_condition(errno, std::generic_category()); // perform the write std::size_t const count = std::fwrite(buffer, 1, length, m_file); + if (count < length) + { + std::clearerr(m_file); + return std::error_condition(errno, std::generic_category()); + } actual = count; - return error::NONE; + return std::error_condition(); } //============================================================ // osd_truncate //============================================================ - error truncate(std::uint64_t offset) override + virtual std::error_condition truncate(std::uint64_t offset) noexcept override { - return (ftruncate(fileno(m_file), offset) < 0) ? error::FAILURE : error::NONE; + // this is present in POSIX but not C/C++ + if (::ftruncate(::fileno(m_file), offset) < 0) + return std::error_condition(errno, std::generic_category()); + else + return std::error_condition(); } //============================================================ // osd_fflush //============================================================ - virtual error flush() override + virtual std::error_condition flush() noexcept override { - return (std::fflush(m_file) == EOF) ? error::FAILURE : error::NONE; + if (!std::fflush(m_file)) + return std::error_condition(); + else + return std::error_condition(errno, std::generic_category()); } private: @@ -100,7 +127,7 @@ private: // osd_open //============================================================ -osd_file::error osd_file::open(std::string const &path, std::uint32_t openflags, ptr &file, std::uint64_t &filesize) +std::error_condition osd_file::open(std::string const &path, std::uint32_t openflags, ptr &file, std::uint64_t &filesize) noexcept { // based on the flags, choose a mode const char *mode; @@ -114,12 +141,12 @@ osd_file::error osd_file::open(std::string const &path, std::uint32_t openflags, else if (openflags & OPEN_FLAG_READ) mode = "rb"; else - return error::INVALID_ACCESS; + return std::errc::invalid_argument; // open the file FILE *const fileptr = std::fopen(path.c_str(), mode); if (!fileptr) - return error::NOT_FOUND; + return std::error_condition(errno, std::generic_category()); // get the size -- note that most fseek/ftell implementations are limited to 32 bits long length; @@ -127,21 +154,20 @@ osd_file::error osd_file::open(std::string const &path, std::uint32_t openflags, ((length = std::ftell(fileptr)) < 0) || (std::fseek(fileptr, 0, SEEK_SET) < 0)) { + std::error_condition err(errno, std::generic_category()); std::fclose(fileptr); - return error::FAILURE; + return err; } - try - { - file = std::make_unique(fileptr); - filesize = std::int64_t(length); - return error::NONE; - } - catch (...) + osd_file::ptr result(new (std::nothrow) std_osd_file(fileptr)); + if (!result) { std::fclose(fileptr); - return error::OUT_OF_MEMORY; + return std::errc::not_enough_memory; } + file = std::move(result); + filesize = std::int64_t(length); + return std::error_condition(); } @@ -149,9 +175,9 @@ osd_file::error osd_file::open(std::string const &path, std::uint32_t openflags, // osd_openpty //============================================================ -osd_file::error osd_file::openpty(ptr &file, std::string &name) +std::error_condition osd_file::openpty(ptr &file, std::string &name) noexcept { - return error::FAILURE; + return std::errc::not_supported; } @@ -159,9 +185,12 @@ osd_file::error osd_file::openpty(ptr &file, std::string &name) // osd_rmfile //============================================================ -osd_file::error osd_file::remove(std::string const &filename) +std::error_condition osd_file::remove(std::string const &filename) noexcept { - return (std::remove(filename.c_str()) < 0) ? error::FAILURE : error::NONE; + if (!std::remove(filename.c_str())) + return std::error_condition(); + else + return std::error_condition(errno, std::generic_category()); } @@ -169,7 +198,7 @@ osd_file::error osd_file::remove(std::string const &filename) // osd_get_physical_drive_geometry //============================================================ -bool osd_get_physical_drive_geometry(const char *filename, uint32_t *cylinders, uint32_t *heads, uint32_t *sectors, uint32_t *bps) +bool osd_get_physical_drive_geometry(const char *filename, uint32_t *cylinders, uint32_t *heads, uint32_t *sectors, uint32_t *bps) noexcept { // there is no standard way of doing this, so we always return false, indicating // that a given path is not a physical drive @@ -181,7 +210,7 @@ bool osd_get_physical_drive_geometry(const char *filename, uint32_t *cylinders, // osd_uchar_from_osdchar //============================================================ -int osd_uchar_from_osdchar(char32_t *uchar, const char *osdchar, size_t count) +int osd_uchar_from_osdchar(char32_t *uchar, const char *osdchar, size_t count) noexcept { // we assume a standard 1:1 mapping of characters to the first 256 unicode characters *uchar = (uint8_t)*osdchar; @@ -221,13 +250,14 @@ osd_directory_entry *osd_stat(const std::string &path) // osd_get_full_path //============================================================ -osd_file::error osd_get_full_path(std::string &dst, std::string const &path) +std::error_condition osd_get_full_path(std::string &dst, std::string const &path) noexcept { // 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; + try { dst = path; } + catch (...) { return std::errc::not_enough_memory; } - return osd_file::error::NONE; + return std::error_condition(); } @@ -235,7 +265,7 @@ osd_file::error osd_get_full_path(std::string &dst, std::string const &path) // osd_is_absolute_path //============================================================ -bool osd_is_absolute_path(std::string const &path) +bool osd_is_absolute_path(std::string const &path) noexcept { // assume no for everything return false; diff --git a/src/osd/modules/file/winfile.cpp b/src/osd/modules/file/winfile.cpp index 4c265be613d..be4fa6f70c3 100644 --- a/src/osd/modules/file/winfile.cpp +++ b/src/osd/modules/file/winfile.cpp @@ -6,7 +6,6 @@ // //============================================================ - #include "winfile.h" // MAMEOS headers @@ -45,7 +44,7 @@ public: 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) + win_osd_file(HANDLE handle) noexcept : m_handle(handle) { assert(m_handle); assert(INVALID_HANDLE_VALUE != m_handle); @@ -57,7 +56,7 @@ public: CloseHandle(m_handle); } - virtual error read(void *buffer, std::uint64_t offset, std::uint32_t length, std::uint32_t &actual) override + virtual std::error_condition read(void *buffer, std::uint64_t offset, std::uint32_t length, std::uint32_t &actual) noexcept override { // attempt to set the file pointer LARGE_INTEGER largeOffset; @@ -71,10 +70,10 @@ public: return win_error_to_file_error(GetLastError()); actual = result; - return error::NONE; + return std::error_condition(); } - virtual error write(void const *buffer, std::uint64_t offset, std::uint32_t length, std::uint32_t &actual) override + virtual std::error_condition write(void const *buffer, std::uint64_t offset, std::uint32_t length, std::uint32_t &actual) noexcept override { // attempt to set the file pointer LARGE_INTEGER largeOffset; @@ -88,10 +87,10 @@ public: return win_error_to_file_error(GetLastError()); actual = result; - return error::NONE; + return std::error_condition(); } - virtual error truncate(std::uint64_t offset) override + virtual std::error_condition truncate(std::uint64_t offset) noexcept override { // attempt to set the file pointer LARGE_INTEGER largeOffset; @@ -103,13 +102,13 @@ public: if (!SetEndOfFile(m_handle)) return win_error_to_file_error(GetLastError()); else - return error::NONE; + return std::error_condition(); } - virtual error flush() override + virtual std::error_condition flush() noexcept override { // shouldn't be any userspace buffers on the file handle - return error::NONE; + return std::error_condition(); } private: @@ -162,11 +161,11 @@ DWORD create_path_recursive(TCHAR *path) // osd_open //============================================================ -osd_file::error osd_file::open(std::string const &orig_path, uint32_t openflags, ptr &file, std::uint64_t &filesize) +std::error_condition osd_file::open(std::string const &orig_path, uint32_t openflags, ptr &file, std::uint64_t &filesize) noexcept { std::string path; try { osd_subst_env(path, orig_path); } - catch (...) { return error::OUT_OF_MEMORY; } + catch (...) { return std::errc::not_enough_memory; } if (win_check_socket_path(path)) return win_open_socket(path, openflags, file, filesize); @@ -174,10 +173,11 @@ osd_file::error osd_file::open(std::string const &orig_path, uint32_t openflags, return win_open_ptty(path, openflags, file, filesize); // convert path to TCHAR - osd::text::tstring t_path = osd::text::to_tstring(path); + osd::text::tstring t_path; + try { t_path = osd::text::to_tstring(path); } + catch (...) { return std::errc::not_enough_memory; } - // convert the path into something Windows compatible (the actual interesting part appears - // to have been commented out???) + // convert the path into something Windows compatible (the actual interesting part appears to have been commented out???) for (auto iter = t_path.begin(); iter != t_path.end(); iter++) *iter = /* ('/' == *iter) ? '\\' : */ *iter; @@ -187,7 +187,8 @@ osd_file::error osd_file::open(std::string const &orig_path, uint32_t openflags, { disposition = (!is_path_to_physical_drive(path.c_str()) && (openflags & OPEN_FLAG_CREATE)) ? CREATE_ALWAYS : OPEN_EXISTING; access = (openflags & OPEN_FLAG_READ) ? (GENERIC_READ | GENERIC_WRITE) : GENERIC_WRITE; - if (is_path_to_physical_drive(path.c_str())) access |= GENERIC_READ; + if (is_path_to_physical_drive(path.c_str())) + access |= GENERIC_READ; sharemode = FILE_SHARE_READ; } else if (openflags & OPEN_FLAG_READ) @@ -198,7 +199,7 @@ osd_file::error osd_file::open(std::string const &orig_path, uint32_t openflags, } else { - return error::INVALID_ACCESS; + return std::errc::invalid_argument; } // attempt to open the file @@ -262,17 +263,15 @@ osd_file::error osd_file::open(std::string const &orig_path, uint32_t openflags, } } - try - { - file = std::make_unique(h); - filesize = (std::uint64_t(upper) << 32) | lower; - return error::NONE; - } - catch (...) + osd_file::ptr result(new (std::nothrow) win_osd_file(h)); + if (!result) { CloseHandle(h); - return error::OUT_OF_MEMORY; + return std::errc::not_enough_memory; } + file = std::move(result); + filesize = (std::uint64_t(upper) << 32) | lower; + return std::error_condition(); } @@ -281,9 +280,9 @@ osd_file::error osd_file::open(std::string const &orig_path, uint32_t openflags, // osd_openpty //============================================================ -osd_file::error osd_file::openpty(ptr &file, std::string &name) +std::error_condition osd_file::openpty(ptr &file, std::string &name) noexcept { - return error::FAILURE; + return std::errc::not_supported; // TODO: revisit this error code } @@ -292,11 +291,13 @@ osd_file::error osd_file::openpty(ptr &file, std::string &name) // osd_rmfile //============================================================ -osd_file::error osd_file::remove(std::string const &filename) +std::error_condition osd_file::remove(std::string const &filename) noexcept { - osd::text::tstring tempstr = osd::text::to_tstring(filename); + osd::text::tstring tempstr; + try { tempstr = osd::text::to_tstring(filename); } + catch (...) { return std::errc::not_enough_memory; } - error filerr = error::NONE; + std::error_condition filerr; if (!DeleteFile(tempstr.c_str())) filerr = win_error_to_file_error(GetLastError()); @@ -309,7 +310,7 @@ osd_file::error osd_file::remove(std::string const &filename) // osd_get_physical_drive_geometry //============================================================ -bool osd_get_physical_drive_geometry(const char *filename, uint32_t *cylinders, uint32_t *heads, uint32_t *sectors, uint32_t *bps) +bool osd_get_physical_drive_geometry(const char *filename, uint32_t *cylinders, uint32_t *heads, uint32_t *sectors, uint32_t *bps) noexcept { DISK_GEOMETRY dg; DWORD bytesRead; @@ -321,10 +322,17 @@ bool osd_get_physical_drive_geometry(const char *filename, uint32_t *cylinders, return false; // do a create file on the drive - auto t_filename = osd::text::to_tstring(filename); - file = CreateFile(t_filename.c_str(), GENERIC_READ, FILE_SHARE_WRITE, nullptr, OPEN_EXISTING, FILE_FLAG_NO_BUFFERING, nullptr); - if (file == INVALID_HANDLE_VALUE) + try + { + auto t_filename = osd::text::to_tstring(filename); + file = CreateFile(t_filename.c_str(), GENERIC_READ, FILE_SHARE_WRITE, nullptr, OPEN_EXISTING, FILE_FLAG_NO_BUFFERING, nullptr); + if (file == INVALID_HANDLE_VALUE) + return false; + } + catch (...) + { return false; + } // device I/O control should return the geometry result = DeviceIoControl(file, IOCTL_DISK_GET_DRIVE_GEOMETRY, nullptr, 0, &dg, sizeof(dg), &bytesRead, nullptr); @@ -399,22 +407,29 @@ std::unique_ptr osd_stat(const std::string &path) // osd_get_full_path //============================================================ -osd_file::error osd_get_full_path(std::string &dst, std::string const &path) +std::error_condition osd_get_full_path(std::string &dst, std::string const &path) noexcept { - // get the length of the full path - std::wstring const w_path(osd::text::to_wstring(path)); - DWORD const length(GetFullPathNameW(w_path.c_str(), 0, nullptr, nullptr)); - if (!length) - return win_error_to_file_error(GetLastError()); + try + { + // get the length of the full path + std::wstring const w_path(osd::text::to_wstring(path)); + DWORD const length(GetFullPathNameW(w_path.c_str(), 0, nullptr, nullptr)); + if (!length) + return win_error_to_file_error(GetLastError()); - // allocate a buffer and get the canonical path - std::unique_ptr buffer(std::make_unique(length)); - if (!GetFullPathNameW(w_path.c_str(), length, buffer.get(), nullptr)) - return win_error_to_file_error(GetLastError()); + // allocate a buffer and get the canonical path + std::unique_ptr buffer(std::make_unique(length)); + if (!GetFullPathNameW(w_path.c_str(), length, buffer.get(), nullptr)) + return win_error_to_file_error(GetLastError()); - // convert the result back to UTF-8 - osd::text::from_wstring(dst, buffer.get()); - return osd_file::error::NONE; + // convert the result back to UTF-8 + osd::text::from_wstring(dst, buffer.get()); + return std::error_condition(); + } + catch (...) + { + return std::errc::not_enough_memory; // the string conversions can throw bad_alloc + } } @@ -423,7 +438,7 @@ osd_file::error osd_get_full_path(std::string &dst, std::string const &path) // osd_is_absolute_path //============================================================ -bool osd_is_absolute_path(std::string const &path) +bool osd_is_absolute_path(std::string const &path) noexcept { return !PathIsRelativeW(osd::text::to_wstring(path).c_str()); } @@ -493,7 +508,7 @@ std::vector osd_get_volume_names() // osd_is_valid_filename_char //============================================================ -bool osd_is_valid_filename_char(char32_t uchar) +bool osd_is_valid_filename_char(char32_t uchar) noexcept { return osd_is_valid_filepath_char(uchar) && uchar != '/' @@ -507,7 +522,7 @@ bool osd_is_valid_filename_char(char32_t uchar) // osd_is_valid_filepath_char //============================================================ -bool osd_is_valid_filepath_char(char32_t uchar) +bool osd_is_valid_filepath_char(char32_t uchar) noexcept { return uchar >= 0x20 && uchar != '<' @@ -526,39 +541,62 @@ bool osd_is_valid_filepath_char(char32_t uchar) // win_error_to_file_error //============================================================ -osd_file::error win_error_to_file_error(DWORD error) +std::error_condition win_error_to_file_error(DWORD error) noexcept { - osd_file::error filerr; - - // convert a Windows error to a osd_file::error + // TODO: work out if there's a better way to do this switch (error) { case ERROR_SUCCESS: - filerr = osd_file::error::NONE; - break; + return std::error_condition(); + + case ERROR_INVALID_HANDLE: + return std::errc::bad_file_descriptor; case ERROR_OUTOFMEMORY: - filerr = osd_file::error::OUT_OF_MEMORY; - break; + return std::errc::not_enough_memory; + + case ERROR_NOT_SUPPORTED: + return std::errc::not_supported; case ERROR_FILE_NOT_FOUND: - case ERROR_FILENAME_EXCED_RANGE: case ERROR_PATH_NOT_FOUND: case ERROR_INVALID_NAME: - filerr = osd_file::error::NOT_FOUND; - break; + return std::errc::no_such_file_or_directory; - case ERROR_ACCESS_DENIED: - filerr = osd_file::error::ACCESS_DENIED; - break; + case ERROR_FILENAME_EXCED_RANGE: + return std::errc::filename_too_long; + case ERROR_ACCESS_DENIED: case ERROR_SHARING_VIOLATION: - filerr = osd_file::error::ALREADY_OPEN; - break; + return std::errc::permission_denied; + + case ERROR_ALREADY_EXISTS: + return std::errc::file_exists; + + case ERROR_TOO_MANY_OPEN_FILES: + return std::errc::too_many_files_open; + + case ERROR_WRITE_FAULT: + case ERROR_READ_FAULT: + return std::errc::io_error; + + case ERROR_HANDLE_DISK_FULL: + case ERROR_DISK_FULL: + return std::errc::no_space_on_device; + + case ERROR_PATH_BUSY: + case ERROR_BUSY: + return std::errc::device_or_resource_busy; + + case ERROR_FILE_TOO_LARGE: + return std::errc::file_too_large; + + case ERROR_INVALID_ACCESS: + case ERROR_NEGATIVE_SEEK: + case ERROR_BAD_ARGUMENTS: + return std::errc::invalid_argument; default: - filerr = osd_file::error::FAILURE; - break; + return std::error_condition(error, std::system_category()); } - return filerr; } diff --git a/src/osd/modules/file/winfile.h b/src/osd/modules/file/winfile.h index 927cb299545..83f0814733d 100644 --- a/src/osd/modules/file/winfile.h +++ b/src/osd/modules/file/winfile.h @@ -5,13 +5,16 @@ // winfile.h - File access functions // //============================================================ -#ifndef MAME_OSD_WINDOWS_WINFILE_H -#define MAME_OSD_WINDOWS_WINFILE_H +#ifndef MAME_OSD_MODULES_FILE_WINFILE_H +#define MAME_OSD_MODULES_FILE_WINFILE_H + +#pragma once #include "osdfile.h" #include #include +#include #include @@ -20,15 +23,15 @@ // PROTOTYPES //============================================================ -bool win_init_sockets(); -void win_cleanup_sockets(); +bool win_init_sockets() noexcept; +void win_cleanup_sockets() noexcept; -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_socket_path(std::string const &path) noexcept; +std::error_condition win_open_socket(std::string const &path, std::uint32_t openflags, osd_file::ptr &file, std::uint64_t &filesize) noexcept; -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); +bool win_check_ptty_path(std::string const &path) noexcept; +std::error_condition win_open_ptty(std::string const &path, std::uint32_t openflags, osd_file::ptr &file, std::uint64_t &filesize) noexcept; -osd_file::error win_error_to_file_error(DWORD error); +std::error_condition win_error_to_file_error(DWORD error) noexcept; -#endif // MAME_OSD_WINDOWS_WINFILE_H +#endif // MAME_OSD_MODULES_FILE_WINFILE_H diff --git a/src/osd/modules/file/winptty.cpp b/src/osd/modules/file/winptty.cpp index 65650fd4bfe..7feeacce137 100644 --- a/src/osd/modules/file/winptty.cpp +++ b/src/osd/modules/file/winptty.cpp @@ -15,6 +15,7 @@ namespace { + char const *const winfile_ptty_identifier = "\\\\.\\pipe\\"; @@ -26,7 +27,7 @@ public: 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) + win_osd_ptty(HANDLE handle) noexcept : m_handle(handle) { assert(m_handle); assert(INVALID_HANDLE_VALUE != m_handle); @@ -39,36 +40,36 @@ public: CloseHandle(m_handle); } - virtual error read(void *buffer, std::uint64_t offset, std::uint32_t count, std::uint32_t &actual) override + virtual std::error_condition read(void *buffer, std::uint64_t offset, std::uint32_t count, std::uint32_t &actual) noexcept override { DWORD bytes_read; if (!ReadFile(m_handle, buffer, count, &bytes_read, nullptr)) return win_error_to_file_error(GetLastError()); actual = bytes_read; - return error::NONE; + return std::error_condition(); } - virtual error write(void const *buffer, std::uint64_t offset, std::uint32_t count, std::uint32_t &actual) override + virtual std::error_condition write(void const *buffer, std::uint64_t offset, std::uint32_t count, std::uint32_t &actual) noexcept override { DWORD bytes_written; if (!WriteFile(m_handle, buffer, count, &bytes_written, nullptr)) return win_error_to_file_error(GetLastError()); actual = bytes_written; - return error::NONE; + return std::error_condition(); } - virtual error truncate(std::uint64_t offset) override + virtual std::error_condition truncate(std::uint64_t offset) noexcept override { // doesn't make sense for a PTTY - return error::INVALID_ACCESS; + return std::errc::bad_file_descriptor; } - virtual error flush() override + virtual std::error_condition flush() noexcept override { // don't want to wait for client to read all data as implied by FlushFileBuffers - return error::NONE; + return std::error_condition(); } private: @@ -78,16 +79,18 @@ private: } // anonymous namespace -bool win_check_ptty_path(std::string const &path) +bool win_check_ptty_path(std::string const &path) noexcept { 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) +std::error_condition win_open_ptty(std::string const &path, std::uint32_t openflags, osd_file::ptr &file, std::uint64_t &filesize) noexcept { - osd::text::tstring t_name = osd::text::to_tstring(path); + osd::text::tstring t_name; + try { t_name = osd::text::to_tstring(path); } + catch (...) { return std::errc::not_enough_memory; } HANDLE pipe = CreateFileW(t_name.c_str(), GENERIC_READ | GENERIC_WRITE, 0, nullptr, OPEN_EXISTING, 0, nullptr); @@ -96,23 +99,22 @@ osd_file::error win_open_ptty(std::string const &path, std::uint32_t openflags, if (openflags & OPEN_FLAG_CREATE) pipe = CreateNamedPipe(t_name.c_str(), PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_NOWAIT, 1, 32, 32, 0, nullptr); if (INVALID_HANDLE_VALUE == pipe) - return osd_file::error::ACCESS_DENIED; + return win_error_to_file_error(GetLastError()); } else { DWORD state = PIPE_NOWAIT; SetNamedPipeHandleState(pipe, &state, nullptr, nullptr); + // TODO: check for error? } - try - { - file = std::make_unique(pipe); - filesize = 0; - return osd_file::error::NONE; - } - catch (...) + osd_file::ptr result(new (std::nothrow) win_osd_ptty(pipe)); + if (!result) { CloseHandle(pipe); - return osd_file::error::OUT_OF_MEMORY; + return std::errc::not_enough_memory; } + file = std::move(result); + filesize = 0; + return std::error_condition(); } diff --git a/src/osd/modules/file/winsocket.cpp b/src/osd/modules/file/winsocket.cpp index 948e57db822..f818f3b1991 100644 --- a/src/osd/modules/file/winsocket.cpp +++ b/src/osd/modules/file/winsocket.cpp @@ -6,7 +6,6 @@ // //============================================================ - #include "winfile.h" // MAMEOS headers @@ -28,6 +27,7 @@ namespace { + char const *const winfile_socket_identifier = "socket."; @@ -39,7 +39,7 @@ public: win_osd_socket& operator=(win_osd_socket const &) = delete; win_osd_socket& operator=(win_osd_socket &&) = delete; - win_osd_socket(SOCKET s, bool l) + win_osd_socket(SOCKET s, bool l) noexcept : m_socket(s) , m_listening(l) { @@ -51,7 +51,7 @@ public: closesocket(m_socket); } - virtual error read(void *buffer, std::uint64_t offset, std::uint32_t length, std::uint32_t &actual) override + virtual std::error_condition read(void *buffer, std::uint64_t offset, std::uint32_t length, std::uint32_t &actual) noexcept override { fd_set readfds; FD_ZERO(&readfds); @@ -62,10 +62,7 @@ public: 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; + return wsa_error_to_file_error(WSAGetLastError()); } else if (FD_ISSET(m_socket, &readfds)) { @@ -80,7 +77,7 @@ public: else { actual = result; - return error::NONE; + return std::error_condition(); } } else @@ -98,50 +95,82 @@ public: m_listening = false; actual = 0; - return error::NONE; + return std::error_condition(); } } } else { - return error::FAILURE; + // no data available + actual = 0; + return std::error_condition(); } } - virtual error write(void const *buffer, std::uint64_t offset, std::uint32_t length, std::uint32_t &actual) override + virtual std::error_condition write(void const *buffer, std::uint64_t offset, std::uint32_t length, std::uint32_t &actual) noexcept override { auto const result = send(m_socket, reinterpret_cast(buffer), length, 0); if (result < 0) return wsa_error_to_file_error(WSAGetLastError()); actual = result; - return error::NONE; + return std::error_condition(); } - virtual error truncate(std::uint64_t offset) override + virtual std::error_condition truncate(std::uint64_t offset) noexcept override { // doesn't make sense for a socket - return error::INVALID_ACCESS; + return std::errc::bad_file_descriptor; } - virtual error flush() override + virtual std::error_condition flush() noexcept override { // no buffers to flush - return error::NONE; + return std::error_condition(); } - static error wsa_error_to_file_error(int err) + static std::error_condition wsa_error_to_file_error(int err) { + // TODO: determine if there's a better way to do this 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; + case 0: return std::error_condition(); + case WSA_NOT_ENOUGH_MEMORY: return std::errc::not_enough_memory; + case WSA_INVALID_PARAMETER: return std::errc::invalid_argument; + case WSAEINTR: return std::errc::interrupted; + case WSAEBADF: return std::errc::bad_file_descriptor; + case WSAEACCES: return std::errc::permission_denied; + case WSAEFAULT: return std::errc::bad_address; + case WSAEINVAL: return std::errc::invalid_argument; + case WSAEMFILE: return std::errc::too_many_files_open; + case WSAENETRESET: return std::errc::network_reset; + case WSAECONNABORTED: return std::errc::connection_aborted; + case WSAEWOULDBLOCK: return std::errc::operation_would_block; + case WSAEINPROGRESS: return std::errc::operation_in_progress; + case WSAEALREADY: return std::errc::connection_already_in_progress; + case WSAENOTSOCK: return std::errc::not_a_socket; + case WSAEDESTADDRREQ: return std::errc::destination_address_required; + case WSAEMSGSIZE: return std::errc::message_size; + case WSAEPROTOTYPE: return std::errc::wrong_protocol_type; + case WSAENOPROTOOPT: return std::errc::no_protocol_option; + case WSAEPROTONOSUPPORT: return std::errc::protocol_not_supported; + case WSAEOPNOTSUPP: return std::errc::operation_not_supported; + case WSAEAFNOSUPPORT: return std::errc::address_family_not_supported; + case WSAEADDRINUSE: return std::errc::address_in_use; + case WSAEADDRNOTAVAIL: return std::errc::address_not_available; + case WSAENETDOWN: return std::errc::network_down; + case WSAENETUNREACH: return std::errc::network_unreachable; + case WSAECONNRESET: return std::errc::connection_reset; + case WSAENOBUFS: return std::errc::no_buffer_space; + case WSAEISCONN: return std::errc::already_connected; + case WSAENOTCONN: return std::errc::not_connected; + case WSAETIMEDOUT: return std::errc::timed_out; + case WSAECONNREFUSED: return std::errc::connection_refused; + case WSAEHOSTUNREACH: return std::errc::host_unreachable; + case WSAECANCELLED: return std::errc::operation_canceled; + + // TODO: better default error code? + default: return std::errc::io_error; } } @@ -153,7 +182,7 @@ private: } // anonymous namespace -bool win_init_sockets() +bool win_init_sockets() noexcept { WSADATA wsaData; WORD const version = MAKEWORD(2, 0); @@ -179,13 +208,13 @@ bool win_init_sockets() } -void win_cleanup_sockets() +void win_cleanup_sockets() noexcept { WSACleanup(); } -bool win_check_socket_path(std::string const &path) +bool win_check_socket_path(std::string const &path) noexcept { if (strncmp(path.c_str(), winfile_socket_identifier, strlen(winfile_socket_identifier)) == 0 && strchr(path.c_str(), ':') != nullptr) return true; @@ -193,7 +222,7 @@ 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) +std::error_condition win_open_socket(std::string const &path, std::uint32_t openflags, osd_file::ptr &file, std::uint64_t &filesize) noexcept { char hostname[256]; int port; @@ -201,7 +230,7 @@ osd_file::error win_open_socket(std::string const &path, std::uint32_t openflags struct hostent const *const localhost = gethostbyname(hostname); if (!localhost) - return osd_file::error::NOT_FOUND; + return std::errc::no_such_file_or_directory; struct sockaddr_in sai; memset(&sai, 0, sizeof(sai)); @@ -222,11 +251,12 @@ osd_file::error win_open_socket(std::string const &path, std::uint32_t openflags } // listening socket support + osd_file::ptr result; if (openflags & OPEN_FLAG_CREATE) { //printf("Listening for client at '%s' on port '%d'\n", hostname, port); // bind socket... - if (bind(sock, reinterpret_cast(&sai), sizeof(struct sockaddr)) == SOCKET_ERROR) + if (bind(sock, reinterpret_cast(&sai), sizeof(sai)) == SOCKET_ERROR) { int const err = WSAGetLastError(); closesocket(sock); @@ -242,36 +272,26 @@ osd_file::error win_open_socket(std::string const &path, std::uint32_t openflags } // mark socket as "listening" - try - { - file = std::make_unique(sock, true); - filesize = 0; - return osd_file::error::NONE; - } - catch (...) - { - closesocket(sock); - return osd_file::error::OUT_OF_MEMORY; - } + result.reset(new (std::nothrow) win_osd_socket(sock, true)); } else { //printf("Connecting to server '%s' on port '%d'\n", hostname, port); - if (connect(sock, reinterpret_cast(&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(sock, false); - filesize = 0; - return osd_file::error::NONE; - } - catch (...) + if (connect(sock, reinterpret_cast(&sai), sizeof(sai)) == SOCKET_ERROR) { + int const err = WSAGetLastError(); closesocket(sock); - return osd_file::error::OUT_OF_MEMORY; + return win_osd_socket::wsa_error_to_file_error(err); } + result.reset(new (std::nothrow) win_osd_socket(sock, false)); + } + + if (!result) + { + closesocket(sock); + return std::errc::not_enough_memory; } + file = std::move(result); + filesize = 0; + return std::error_condition(); } diff --git a/src/osd/modules/font/font_sdl.cpp b/src/osd/modules/font/font_sdl.cpp index a17b87cdc13..5cad4a3fab8 100644 --- a/src/osd/modules/font/font_sdl.cpp +++ b/src/osd/modules/font/font_sdl.cpp @@ -90,7 +90,7 @@ bool osd_font_sdl::open(std::string const &font_path, std::string const &_name, osd_printf_verbose("Searching font %s in -%s path/s\n", family, font_path); //emu_file file(options().font_path(), OPEN_FLAG_READ); emu_file file(font_path, OPEN_FLAG_READ); - if (file.open(family) == osd_file::error::NONE) + if (!file.open(family)) { std::string full_name = file.fullpath(); font = TTF_OpenFont_Magic(full_name, POINT_SIZE, 0); @@ -193,7 +193,7 @@ bool osd_font_sdl::get_bitmap(char32_t chnum, bitmap_argb32 &bitmap, std::int32_ osd_font_sdl::TTF_Font_ptr osd_font_sdl::TTF_OpenFont_Magic(std::string const &name, int fsize, long index) { emu_file file(OPEN_FLAG_READ); - if (file.open(name) == osd_file::error::NONE) + if (!file.open(name)) { unsigned char const ttf_magic[] = { 0x00, 0x01, 0x00, 0x00, 0x00 }; unsigned char const ttc1_magic[] = { 0x74, 0x74, 0x63, 0x66, 0x00, 0x01, 0x00, 0x00 }; @@ -214,7 +214,7 @@ osd_font_sdl::TTF_Font_ptr osd_font_sdl::TTF_OpenFont_Magic(std::string const &n bool osd_font_sdl::BDF_Check_Magic(std::string const &name) { emu_file file(OPEN_FLAG_READ); - if (file.open(name) == osd_file::error::NONE) + if (!file.open(name)) { unsigned char const magic[] = { 'S', 'T', 'A', 'R', 'T', 'F', 'O', 'N', 'T' }; unsigned char buffer[sizeof(magic)]; diff --git a/src/osd/modules/render/aviwrite.cpp b/src/osd/modules/render/aviwrite.cpp index aff5429446e..ec6ce21c543 100644 --- a/src/osd/modules/render/aviwrite.cpp +++ b/src/osd/modules/render/aviwrite.cpp @@ -80,12 +80,12 @@ void avi_write::begin_avi_recording(const char *name) // create a new temporary movie file emu_file tempfile(m_machine.options().snapshot_directory(), OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS); - const osd_file::error filerr = (!name || !name[0] || !std::strcmp(name, OSDOPTVAL_AUTO)) + const std::error_condition filerr = (!name || !name[0] || !std::strcmp(name, OSDOPTVAL_AUTO)) ? m_machine.video().open_next(tempfile, "avi") : tempfile.open(name); // if we succeeded, make a copy of the name and create the real file over top - if (filerr == osd_file::error::NONE) + if (!filerr) { const std::string fullpath = tempfile.fullpath(); tempfile.close(); diff --git a/src/osd/modules/render/bgfx/texturemanager.cpp b/src/osd/modules/render/bgfx/texturemanager.cpp index 6c760c10203..f03d66e051a 100644 --- a/src/osd/modules/render/bgfx/texturemanager.cpp +++ b/src/osd/modules/render/bgfx/texturemanager.cpp @@ -59,7 +59,7 @@ bgfx_texture* texture_manager::create_png_texture(std::string path, std::string { bitmap_argb32 bitmap; emu_file file(path, OPEN_FLAG_READ); - if (file.open(file_name) == osd_file::error::NONE) + if (!file.open(file_name)) { render_load_png(bitmap, file); file.close(); diff --git a/src/osd/modules/render/d3d/d3dhlsl.cpp b/src/osd/modules/render/d3d/d3dhlsl.cpp index 0137e23acce..6aa69383233 100644 --- a/src/osd/modules/render/d3d/d3dhlsl.cpp +++ b/src/osd/modules/render/d3d/d3dhlsl.cpp @@ -353,8 +353,8 @@ void shaders::render_snapshot(IDirect3DSurface9 *surface) } emu_file file(machine->options().snapshot_directory(), OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS); - osd_file::error filerr = machine->video().open_next(file, "png"); - if (filerr != osd_file::error::NONE) + std::error_condition const filerr = machine->video().open_next(file, "png"); + if (filerr) return; // add two text entries describing the image @@ -722,7 +722,7 @@ int shaders::create_resources() osd_printf_verbose("Direct3D: Error %08lX during device SetRenderTarget call\n", result); emu_file file(machine->options().art_path(), OPEN_FLAG_READ); - if (file.open(options->shadow_mask_texture) == osd_file::error::NONE) + if (!file.open(options->shadow_mask_texture)) { render_load_png(shadow_bitmap, file); file.close(); @@ -747,7 +747,7 @@ int shaders::create_resources() d3d->get_texture_manager()->m_texture_list.push_back(std::move(tex)); } - if (file.open(options->lut_texture) == osd_file::error::NONE) + if (!file.open(options->lut_texture)) { render_load_png(lut_bitmap, file); file.close(); @@ -770,7 +770,7 @@ int shaders::create_resources() d3d->get_texture_manager()->m_texture_list.push_back(std::move(tex)); } - if (file.open(options->ui_lut_texture) == osd_file::error::NONE) + if (!file.open(options->ui_lut_texture)) { render_load_png(ui_lut_bitmap, file); file.close(); diff --git a/src/osd/osdfile.h b/src/osd/osdfile.h index ffd4346d7c0..bc3efbde805 100644 --- a/src/osd/osdfile.h +++ b/src/osd/osdfile.h @@ -16,6 +16,7 @@ #include #include #include +#include #include @@ -61,47 +62,6 @@ constexpr uint32_t OPEN_FLAG_NO_PRELOAD = 0x0010; class osd_file { public: - /// \brief Result of a file operation - /// - /// Returned by most members of osd_file, and also used by other - /// classes that access files or other file-like resources. - enum class error - { - /// Operation completed successfully. - NONE, - - /// Operation failed, but there is no more specific code to - /// describe the failure. - FAILURE, - - /// Operation failed due to an error allocating memory. - OUT_OF_MEMORY, - - /// The requested file, path or resource was not found. - NOT_FOUND, - - /// Current permissions do not allow the requested access. - ACCESS_DENIED, - - /// Requested access is not permitted because the file or - /// resource is currently open for exclusive access. - ALREADY_OPEN, - - /// Request cannot be completed due to resource exhaustion - /// (maximum number of open files or other objects has been - /// reached). - TOO_MANY_FILES, - - /// The request cannot be completed because invalid data was - /// encountered (for example an inconsistent filesystem, or a - /// corrupt archive file). - INVALID_DATA, - - /// The requested access mode is invalid, or not appropriate for - /// the file or resource. - INVALID_ACCESS - }; - /// \brief Smart pointer to a file handle typedef std::unique_ptr ptr; @@ -129,7 +89,7 @@ public: /// Will be zero for stream-like objects (e.g. TCP sockets or /// named pipes). /// \return Result of the operation. - static error open(std::string const &path, std::uint32_t openflags, ptr &file, std::uint64_t &filesize); + static std::error_condition open(std::string const &path, std::uint32_t openflags, ptr &file, std::uint64_t &filesize) noexcept; /// \brief Create a new pseudo-terminal (PTY) pair /// @@ -140,7 +100,7 @@ public: /// pseudo-terminal if the operation succeeds. Not valid if the /// operation fails. /// \return Result of the operation. - static error openpty(ptr &file, std::string &name); + static std::error_condition openpty(ptr &file, std::string &name) noexcept; /// \brief Close an open file virtual ~osd_file() { } @@ -161,7 +121,7 @@ public: /// \param [out] actual Receives the number of bytes read if the /// operation succeeds. Not valid if the operation fails. /// \return Result of the operation. - virtual error read(void *buffer, std::uint64_t offset, std::uint32_t length, std::uint32_t &actual) = 0; + virtual std::error_condition read(void *buffer, std::uint64_t offset, std::uint32_t length, std::uint32_t &actual) noexcept = 0; /// \brief Write to an open file /// @@ -176,26 +136,26 @@ public: /// \param [out] actual Receives the number of bytes written if the /// operation succeeds. Not valid if the operation fails. /// \return Result of the operation. - virtual error write(void const *buffer, std::uint64_t offset, std::uint32_t length, std::uint32_t &actual) = 0; + virtual std::error_condition write(void const *buffer, std::uint64_t offset, std::uint32_t length, std::uint32_t &actual) noexcept = 0; /// \brief Change the size of an open file /// /// \param [in] offset Desired size of the file. /// \return Result of the operation. - virtual error truncate(std::uint64_t offset) = 0; + virtual std::error_condition truncate(std::uint64_t offset) noexcept = 0; /// \brief Flush file buffers /// /// This flushes any data cached by the application, but does not /// guarantee that all prior writes have reached persistent storage. /// \return Result of the operation. - virtual error flush() = 0; + virtual std::error_condition flush() noexcept = 0; /// \brief Delete a file /// /// \param [in] filename Path to the file to delete. /// \return Result of the operation. - static error remove(std::string const &filename); + static std::error_condition remove(std::string const &filename) noexcept; }; @@ -217,21 +177,21 @@ public: /// \return true if the filename points to a physical drive and if the /// values pointed to by cylinders, heads, sectors, and bps are valid; /// false in any other case -bool osd_get_physical_drive_geometry(const char *filename, uint32_t *cylinders, uint32_t *heads, uint32_t *sectors, uint32_t *bps); +bool osd_get_physical_drive_geometry(const char *filename, uint32_t *cylinders, uint32_t *heads, uint32_t *sectors, uint32_t *bps) noexcept; /// \brief Is the given character legal for filenames? /// /// \param [in] uchar The character to check. /// \return Whether this character is legal in a filename. -bool osd_is_valid_filename_char(char32_t uchar); +bool osd_is_valid_filename_char(char32_t uchar) noexcept; /// \brief Is the given character legal for paths? /// /// \param [in] uchar The character to check. /// \return Whether this character is legal in a file path. -bool osd_is_valid_filepath_char(char32_t uchar); +bool osd_is_valid_filepath_char(char32_t uchar) noexcept; /*************************************************************************** @@ -301,14 +261,14 @@ std::unique_ptr osd_stat(std::string const &path); /// /// \param [in] path The path in question. /// \return true if the path is absolute, false otherwise. -bool osd_is_absolute_path(const std::string &path); +bool osd_is_absolute_path(const std::string &path) noexcept; /// \brief Retrieves the full path. /// \param [in] path The path in question. /// \param [out] dst Reference to receive new path. /// \return File error. -osd_file::error osd_get_full_path(std::string &dst, std::string const &path); +std::error_condition osd_get_full_path(std::string &dst, std::string const &path) noexcept; /// \brief Retrieves the volume name. diff --git a/src/tools/castool.cpp b/src/tools/castool.cpp index e03a15203d5..896c0bde5c2 100644 --- a/src/tools/castool.cpp +++ b/src/tools/castool.cpp @@ -53,6 +53,7 @@ #include "formats/zx81_p.h" #include "corestr.h" +#include "ioprocs.h" #include #include @@ -162,7 +163,6 @@ int CLIB_DECL main(int argc, char *argv[]) int found =0; const cassette_image::Format * const *selected_formats = nullptr; cassette_image::ptr cassette; - FILE *f; if (argc > 1) { @@ -188,21 +188,26 @@ int CLIB_DECL main(int argc, char *argv[]) return -1; } - f = fopen(argv[3], "rb"); + FILE *f = fopen(argv[3], "rb"); if (!f) { fprintf(stderr, "File %s not found.\n",argv[3]); return -1; } - if (cassette_image::open_choices(f, &stdio_ioprocs, get_extension(argv[3]), selected_formats, cassette_image::FLAG_READONLY, cassette) != cassette_image::error::SUCCESS) { + auto io = util::stdio_read_write(f, 0x00); + f = nullptr; + if (!io) { + fprintf(stderr, "Out of memory.\n"); + return -1; + } + + if (cassette_image::open_choices(std::move(io), get_extension(argv[3]), selected_formats, cassette_image::FLAG_READONLY, cassette) != cassette_image::error::SUCCESS) { fprintf(stderr, "Invalid format of input file.\n"); - fclose(f); return -1; } cassette->dump(argv[4]); cassette.reset(); - fclose(f); goto theend; } } diff --git a/src/tools/chdman.cpp b/src/tools/chdman.cpp index 835a87c18c3..e0243ce7277 100644 --- a/src/tools/chdman.cpp +++ b/src/tools/chdman.cpp @@ -294,8 +294,8 @@ public: return 0; if (offset + length > m_maxoffset) length = m_maxoffset - offset; - chd_error err = m_file.read_bytes(offset, dest, length); - if (err != CHDERR_NONE) + std::error_condition err = m_file.read_bytes(offset, dest, length); + if (err) throw err; // if we have TOC - detect audio sectors and swap data @@ -385,9 +385,9 @@ public: { m_file.reset(); m_lastfile = m_info.track[tracknum].fname; - osd_file::error filerr = util::core_file::open(m_lastfile, OPEN_FLAG_READ, m_file); - if (filerr != osd_file::error::NONE) - report_error(1, "Error opening input file (%s)'", m_lastfile.c_str()); + std::error_condition const filerr = util::core_file::open(m_lastfile, OPEN_FLAG_READ, m_file); + if (filerr) + report_error(1, "Error opening input file (%s): %s", m_lastfile, filerr.message()); } // iterate over frames @@ -411,9 +411,9 @@ public: { m_file.reset(); m_lastfile = m_info.track[tracknum+1].fname; - osd_file::error filerr = util::core_file::open(m_lastfile, OPEN_FLAG_READ, m_file); - if (filerr != osd_file::error::NONE) - report_error(1, "Error opening input file (%s)'", m_lastfile.c_str()); + std::error_condition const filerr = util::core_file::open(m_lastfile, OPEN_FLAG_READ, m_file); + if (filerr) + report_error(1, "Error opening input file (%s): %s", m_lastfile, filerr.message()); } if (src_frame_start < src_track_end) @@ -430,7 +430,7 @@ public: : src_frame_start, SEEK_SET); uint32_t count = m_file->read(dest, bytesperframe); if (count != bytesperframe) - report_error(1, "Error reading input file (%s)'", m_lastfile.c_str()); + report_error(1, "Error reading input file (%s)'", m_lastfile); } // swap if appropriate @@ -1035,18 +1035,18 @@ static void parse_input_chd_parameters(const parameters_map ¶ms, chd_file &i auto input_chd_parent_str = params.find(OPTION_INPUT_PARENT); if (input_chd_parent_str != params.end()) { - chd_error err = input_parent_chd.open(input_chd_parent_str->second->c_str()); - if (err != CHDERR_NONE) - report_error(1, "Error opening parent CHD file (%s): %s", input_chd_parent_str->second->c_str(), chd_file::error_string(err)); + std::error_condition err = input_parent_chd.open(*input_chd_parent_str->second); + if (err) + report_error(1, "Error opening parent CHD file (%s): %s", *input_chd_parent_str->second, err.message()); } // process input file auto input_chd_str = params.find(OPTION_INPUT); if (input_chd_str != params.end()) { - chd_error err = input_chd.open(input_chd_str->second->c_str(), writeable, input_parent_chd.opened() ? &input_parent_chd : nullptr); - if (err != CHDERR_NONE) - report_error(1, "Error opening CHD file (%s): %s", input_chd_str->second->c_str(), chd_file::error_string(err)); + std::error_condition err = input_chd.open(*input_chd_str->second, writeable, input_parent_chd.opened() ? &input_parent_chd : nullptr); + if (err) + report_error(1, "Error opening CHD file (%s): %s", *input_chd_str->second, err.message()); } } @@ -1102,8 +1102,8 @@ static void check_existing_output_file(const parameters_map ¶ms, const char if (params.find(OPTION_OUTPUT_FORCE) == params.end()) { util::core_file::ptr file; - osd_file::error filerr = util::core_file::open(filename, OPEN_FLAG_READ, file); - if (filerr == osd_file::error::NONE) + std::error_condition const filerr = util::core_file::open(filename, OPEN_FLAG_READ, file); + if (!filerr) { file.reset(); report_error(1, "Error: file already exists (%s)\nUse --force (or -f) to force overwriting", filename); @@ -1123,9 +1123,9 @@ static std::string *parse_output_chd_parameters(const parameters_map ¶ms, ch auto output_chd_parent_str = params.find(OPTION_OUTPUT_PARENT); if (output_chd_parent_str != params.end()) { - chd_error err = output_parent_chd.open(output_chd_parent_str->second->c_str()); - if (err != CHDERR_NONE) - report_error(1, "Error opening parent CHD file (%s): %s", output_chd_parent_str->second->c_str(), chd_file::error_string(err)); + std::error_condition err = output_parent_chd.open(*output_chd_parent_str->second); + if (err) + report_error(1, "Error opening parent CHD file (%s): %s", *output_chd_parent_str->second, err.message()); } // process output file @@ -1180,10 +1180,10 @@ static void parse_compression(const parameters_map ¶ms, chd_codec_type compr { std::string name(*compression_str->second, start, (end == -1) ? -1 : end - start); if (name.length() != 4) - report_error(1, "Invalid compressor '%s' specified", name.c_str()); + report_error(1, "Invalid compressor '%s' specified", name); chd_codec_type type = CHD_MAKE_TAG(name[0], name[1], name[2], name[3]); if (!chd_codec_list::codec_exists(type)) - report_error(1, "Invalid compressor '%s' specified", name.c_str()); + report_error(1, "Invalid compressor '%s' specified", name); compression[index++] = type; if (end == -1) break; @@ -1257,16 +1257,16 @@ static void compress_common(chd_file_compressor &chd) // loop until done double complete, ratio; - chd_error err; - while ((err = chd.compress_continue(complete, ratio)) == CHDERR_WALKING_PARENT || err == CHDERR_COMPRESSING) - if (err == CHDERR_WALKING_PARENT) + std::error_condition err; + while ((err = chd.compress_continue(complete, ratio)) == chd_file::error::WALKING_PARENT || err == chd_file::error::COMPRESSING) + if (err == chd_file::error::WALKING_PARENT) progress(false, "Examining parent, %.1f%% complete... \r", 100.0 * complete); else progress(false, "Compressing, %.1f%% complete... (ratio=%.1f%%) \r", 100.0 * complete, 100.0 * ratio); // handle errors - if (err != CHDERR_NONE) - report_error(1, "Error during compression: %-40s", chd_file::error_string(err)); + if (err) + report_error(1, "Error during compression: %-40s", err.message()); // final progress update progress(true, "Compression complete ... final ratio = %.1f%% \n", 100.0 * ratio); @@ -1447,15 +1447,17 @@ static void do_info(parameters_map ¶ms) // output cmpression and size information chd_codec_type compression[4] = { input_chd.compression(0), input_chd.compression(1), input_chd.compression(2), input_chd.compression(3) }; + uint64_t filesize = 0; + input_chd.file().length(filesize); printf("Logical size: %s bytes\n", big_int_string(input_chd.logical_bytes()).c_str()); printf("Hunk Size: %s bytes\n", big_int_string(input_chd.hunk_bytes()).c_str()); printf("Total Hunks: %s\n", big_int_string(input_chd.hunk_count()).c_str()); printf("Unit Size: %s bytes\n", big_int_string(input_chd.unit_bytes()).c_str()); printf("Total Units: %s\n", big_int_string(input_chd.unit_count()).c_str()); printf("Compression: %s\n", compression_string(compression).c_str()); - printf("CHD size: %s bytes\n", big_int_string(static_cast(input_chd).size()).c_str()); + printf("CHD size: %s bytes\n", big_int_string(filesize).c_str()); if (compression[0] != CHD_CODEC_NONE) - printf("Ratio: %.1f%%\n", 100.0 * double(static_cast(input_chd).size()) / double(input_chd.logical_bytes())); + printf("Ratio: %.1f%%\n", 100.0 * double(filesize) / double(input_chd.logical_bytes())); // add SHA1 output util::sha1_t overall = input_chd.sha1(); @@ -1477,8 +1479,8 @@ static void do_info(parameters_map ¶ms) // get the indexed metadata item; stop when we hit an error chd_metadata_tag metatag; uint8_t metaflags; - chd_error err = input_chd.read_metadata(CHDMETATAG_WILDCARD, index, buffer, metatag, metaflags); - if (err != CHDERR_NONE) + std::error_condition err = input_chd.read_metadata(CHDMETATAG_WILDCARD, index, buffer, metatag, metaflags); + if (err) break; // determine our index @@ -1523,9 +1525,9 @@ static void do_info(parameters_map ¶ms) // get info on this hunk chd_codec_type codec; uint32_t compbytes; - chd_error err = input_chd.hunk_info(hunknum, codec, compbytes); - if (err != CHDERR_NONE) - report_error(1, "Error getting info on hunk %d: %s", hunknum, chd_file::error_string(err)); + std::error_condition err = input_chd.hunk_info(hunknum, codec, compbytes); + if (err) + report_error(1, "Error getting info on hunk %d: %s", hunknum, err.message()); // decode into our data if (codec > CHD_CODEC_MINI) @@ -1603,9 +1605,9 @@ static void do_verify(parameters_map ¶ms) // determine how much to read uint32_t bytes_to_read = (std::min)(buffer.size(), input_chd.logical_bytes() - offset); - chd_error err = input_chd.read_bytes(offset, &buffer[0], bytes_to_read); - if (err != CHDERR_NONE) - report_error(1, "Error reading CHD file (%s): %s", params.find(OPTION_INPUT)->second->c_str(), chd_file::error_string(err)); + std::error_condition err = input_chd.read_bytes(offset, &buffer[0], bytes_to_read); + if (err) + report_error(1, "Error reading CHD file (%s): %s", *params.find(OPTION_INPUT)->second, err.message()); // add to the checksum rawsha1.append(&buffer[0], bytes_to_read); @@ -1665,9 +1667,9 @@ static void do_create_raw(parameters_map ¶ms) auto input_file_str = params.find(OPTION_INPUT); if (input_file_str != params.end()) { - osd_file::error filerr = util::core_file::open(*input_file_str->second, OPEN_FLAG_READ, input_file); - if (filerr != osd_file::error::NONE) - report_error(1, "Unable to open file (%s)", input_file_str->second->c_str()); + std::error_condition const filerr = util::core_file::open(*input_file_str->second, OPEN_FLAG_READ, input_file); + if (filerr) + report_error(1, "Unable to open file (%s): %s", *input_file_str->second, filerr.message()); } // process output CHD @@ -1720,13 +1722,13 @@ static void do_create_raw(parameters_map ¶ms) { // create the new CHD std::unique_ptr chd(new chd_rawfile_compressor(*input_file, input_start, input_end)); - chd_error err; + std::error_condition err; if (output_parent.opened()) err = chd->create(output_chd_str->c_str(), input_end - input_start, hunk_size, compression, output_parent); else err = chd->create(output_chd_str->c_str(), input_end - input_start, hunk_size, unit_size, compression); - if (err != CHDERR_NONE) - report_error(1, "Error creating CHD file (%s): %s", output_chd_str->c_str(), chd_file::error_string(err)); + if (err) + report_error(1, "Error creating CHD file (%s): %s", output_chd_str, err.message()); // if we have a parent, copy forward all the metadata if (output_parent.opened()) @@ -1758,9 +1760,9 @@ static void do_create_hd(parameters_map ¶ms) auto input_file_str = params.find(OPTION_INPUT); if (input_file_str != params.end()) { - osd_file::error filerr = util::core_file::open(*input_file_str->second, OPEN_FLAG_READ, input_file); - if (filerr != osd_file::error::NONE) - report_error(1, "Unable to open file (%s)", input_file_str->second->c_str()); + std::error_condition const filerr = util::core_file::open(*input_file_str->second, OPEN_FLAG_READ, input_file); + if (filerr) + report_error(1, "Unable to open file (%s): %s", *input_file_str->second, filerr.message()); } // process output CHD @@ -1833,13 +1835,13 @@ static void do_create_hd(parameters_map ¶ms) if (ident_str != params.end()) { // load the file - osd_file::error filerr = util::core_file::load(ident_str->second->c_str(), identdata); - if (filerr != osd_file::error::NONE) - report_error(1, "Error reading ident file (%s)", ident_str->second->c_str()); + std::error_condition const filerr = util::core_file::load(*ident_str->second, identdata); + if (filerr) + report_error(1, "Error reading ident file (%s): %s", *ident_str->second, filerr.message()); // must be at least 14 bytes; extract CHS data from there if (identdata.size() < 14) - report_error(1, "Ident file '%s' is invalid (too short)", ident_str->second->c_str()); + report_error(1, "Ident file '%s' is invalid (too short)", *ident_str->second); cylinders = (identdata[3] << 8) | identdata[2]; heads = (identdata[7] << 8) | identdata[6]; sectors = (identdata[13] << 8) | identdata[12]; @@ -1870,7 +1872,7 @@ static void do_create_hd(parameters_map ¶ms) if (output_parent.opened() && cylinders == 0) { std::string metadata; - if (output_parent.read_metadata(HARD_DISK_METADATA_TAG, 0, metadata) != CHDERR_NONE) + if (output_parent.read_metadata(HARD_DISK_METADATA_TAG, 0, metadata)) report_error(1, "Unable to find hard disk metadata in parent CHD"); if (sscanf(metadata.c_str(), HARD_DISK_METADATA_FORMAT, &cylinders, &heads, §ors, §or_size) != 4) report_error(1, "Error parsing hard disk metadata in parent CHD"); @@ -1917,26 +1919,26 @@ static void do_create_hd(parameters_map ¶ms) std::unique_ptr chd; if (input_file) chd.reset(new chd_rawfile_compressor(*input_file, input_start, input_end)); else chd.reset(new chd_zero_compressor(input_start, input_end)); - chd_error err; + std::error_condition err; if (output_parent.opened()) err = chd->create(output_chd_str->c_str(), uint64_t(totalsectors) * uint64_t(sector_size), hunk_size, compression, output_parent); else err = chd->create(output_chd_str->c_str(), uint64_t(totalsectors) * uint64_t(sector_size), hunk_size, sector_size, compression); - if (err != CHDERR_NONE) - report_error(1, "Error creating CHD file (%s): %s", output_chd_str->c_str(), chd_file::error_string(err)); + if (err) + report_error(1, "Error creating CHD file (%s): %s", output_chd_str, err.message()); // add the standard hard disk metadata std::string metadata = string_format(HARD_DISK_METADATA_FORMAT, cylinders, heads, sectors, sector_size); err = chd->write_metadata(HARD_DISK_METADATA_TAG, 0, metadata); - if (err != CHDERR_NONE) - report_error(1, "Error adding hard disk metadata: %s", chd_file::error_string(err)); + if (err) + report_error(1, "Error adding hard disk metadata: %s", err.message()); // write the ident if present if (!identdata.empty()) { err = chd->write_metadata(HARD_DISK_IDENT_METADATA_TAG, 0, identdata); - if (err != CHDERR_NONE) - report_error(1, "Error adding hard disk metadata: %s", chd_file::error_string(err)); + if (err) + report_error(1, "Error adding hard disk metadata: %s", err.message()); } // compress it generically @@ -1967,9 +1969,9 @@ static void do_create_cd(parameters_map ¶ms) auto input_file_str = params.find(OPTION_INPUT); if (input_file_str != params.end()) { - chd_error err = chdcd_parse_toc(input_file_str->second->c_str(), toc, track_info); - if (err != CHDERR_NONE) - report_error(1, "Error parsing input file (%s: %s)\n", input_file_str->second->c_str(), chd_file::error_string(err)); + std::error_condition err = chdcd_parse_toc(input_file_str->second->c_str(), toc, track_info); + if (err) + report_error(1, "Error parsing input file (%s: %s)\n", *input_file_str->second, err.message()); } // process output CHD @@ -2016,18 +2018,18 @@ static void do_create_cd(parameters_map ¶ms) { // create the new CD chd = new chd_cd_compressor(toc, track_info); - chd_error err; + std::error_condition err; if (output_parent.opened()) err = chd->create(output_chd_str->c_str(), uint64_t(totalsectors) * uint64_t(CD_FRAME_SIZE), hunk_size, compression, output_parent); else err = chd->create(output_chd_str->c_str(), uint64_t(totalsectors) * uint64_t(CD_FRAME_SIZE), hunk_size, CD_FRAME_SIZE, compression); - if (err != CHDERR_NONE) - report_error(1, "Error creating CHD file (%s): %s", output_chd_str->c_str(), chd_file::error_string(err)); + if (err) + report_error(1, "Error creating CHD file (%s): %s", *output_chd_str, err.message()); // add the standard CD metadata; we do this even if we have a parent because it might be different err = cdrom_write_metadata(chd, &toc); - if (err != CHDERR_NONE) - report_error(1, "Error adding CD metadata: %s", chd_file::error_string(err)); + if (err) + report_error(1, "Error adding CD metadata: %s", err.message()); // compress it generically compress_common(*chd); @@ -2059,7 +2061,7 @@ static void do_create_ld(parameters_map ¶ms) { avi_file::error avierr = avi_file::open(*input_file_str->second, input_file); if (avierr != avi_file::error::NONE) - report_error(1, "Error opening AVI file (%s): %s\n", input_file_str->second->c_str(), avi_file::error_string(avierr)); + report_error(1, "Error opening AVI file (%s): %s\n", *input_file_str->second, avi_file::error_string(avierr)); } const avi_file::movie_info &aviinfo = input_file->get_movie_info(); @@ -2133,19 +2135,19 @@ static void do_create_ld(parameters_map ¶ms) { // create the new CHD chd = new chd_avi_compressor(*input_file, info, input_start, input_end); - chd_error err; + std::error_condition err; if (output_parent.opened()) err = chd->create(output_chd_str->c_str(), uint64_t(input_end - input_start) * hunk_size, hunk_size, compression, output_parent); else err = chd->create(output_chd_str->c_str(), uint64_t(input_end - input_start) * hunk_size, hunk_size, info.bytes_per_frame, compression); - if (err != CHDERR_NONE) - report_error(1, "Error creating CHD file (%s): %s", output_chd_str->c_str(), chd_file::error_string(err)); + if (err) + report_error(1, "Error creating CHD file (%s): %s", *output_chd_str, err.message()); // write the core A/V metadata std::string metadata = string_format(AV_METADATA_FORMAT, info.fps_times_1million / 1000000, info.fps_times_1million % 1000000, info.width, info.height, info.interlaced, info.channels, info.rate); err = chd->write_metadata(AV_METADATA_TAG, 0, metadata); - if (err != CHDERR_NONE) - report_error(1, "Error adding AV metadata: %s\n", chd_file::error_string(err)); + if (err) + report_error(1, "Error adding AV metadata: %s\n", err.message()); // create the compressor and then run it generically compress_common(*chd); @@ -2154,8 +2156,8 @@ static void do_create_ld(parameters_map ¶ms) if (info.height == 524/2 || info.height == 624/2) { err = chd->write_metadata(AV_LD_METADATA_TAG, 0, chd->ldframedata(), 0); - if (err != CHDERR_NONE) - report_error(1, "Error adding AVLD metadata: %s\n", chd_file::error_string(err)); + if (err) + report_error(1, "Error adding AVLD metadata: %s\n", err.message()); } delete chd; } @@ -2202,15 +2204,15 @@ static void do_copy(parameters_map ¶ms) chd_codec_type compression[4]; { std::vector metadata; - if (input_chd.read_metadata(HARD_DISK_METADATA_TAG, 0, metadata) == CHDERR_NONE) + if (!input_chd.read_metadata(HARD_DISK_METADATA_TAG, 0, metadata)) memcpy(compression, s_default_hd_compression, sizeof(compression)); - else if (input_chd.read_metadata(AV_METADATA_TAG, 0, metadata) == CHDERR_NONE) + else if (!input_chd.read_metadata(AV_METADATA_TAG, 0, metadata)) memcpy(compression, s_default_ld_compression, sizeof(compression)); - else if (input_chd.read_metadata(CDROM_OLD_METADATA_TAG, 0, metadata) == CHDERR_NONE || - input_chd.read_metadata(CDROM_TRACK_METADATA_TAG, 0, metadata) == CHDERR_NONE || - input_chd.read_metadata(CDROM_TRACK_METADATA2_TAG, 0, metadata) == CHDERR_NONE || - input_chd.read_metadata(GDROM_OLD_METADATA_TAG, 0, metadata) == CHDERR_NONE || - input_chd.read_metadata(GDROM_TRACK_METADATA_TAG, 0, metadata) == CHDERR_NONE) + else if (!input_chd.read_metadata(CDROM_OLD_METADATA_TAG, 0, metadata) || + !input_chd.read_metadata(CDROM_TRACK_METADATA_TAG, 0, metadata) || + !input_chd.read_metadata(CDROM_TRACK_METADATA2_TAG, 0, metadata) || + !input_chd.read_metadata(GDROM_OLD_METADATA_TAG, 0, metadata) || + !input_chd.read_metadata(GDROM_TRACK_METADATA_TAG, 0, metadata)) memcpy(compression, s_default_cd_compression, sizeof(compression)); else memcpy(compression, s_default_raw_compression, sizeof(compression)); @@ -2240,13 +2242,13 @@ static void do_copy(parameters_map ¶ms) { // create the new CHD chd = new chd_chdfile_compressor(input_chd, input_start, input_end); - chd_error err; + std::error_condition err; if (output_parent.opened()) err = chd->create(output_chd_str->c_str(), input_end - input_start, hunk_size, compression, output_parent); else err = chd->create(output_chd_str->c_str(), input_end - input_start, hunk_size, input_chd.unit_bytes(), compression); - if (err != CHDERR_NONE) - report_error(1, "Error creating CHD file (%s): %s", output_chd_str->c_str(), chd_file::error_string(err)); + if (err) + report_error(1, "Error creating CHD file (%s): %s", *output_chd_str, err.message()); // clone all the metadata, upgrading where appropriate std::vector metadata; @@ -2255,7 +2257,7 @@ static void do_copy(parameters_map ¶ms) uint32_t index = 0; bool redo_cd = false; bool cdda_swap = false; - for (err = input_chd.read_metadata(CHDMETATAG_WILDCARD, index++, metadata, metatag, metaflags); err == CHDERR_NONE; err = input_chd.read_metadata(CHDMETATAG_WILDCARD, index++, metadata, metatag, metaflags)) + for (err = input_chd.read_metadata(CHDMETATAG_WILDCARD, index++, metadata, metatag, metaflags); !err; err = input_chd.read_metadata(CHDMETATAG_WILDCARD, index++, metadata, metatag, metaflags)) { // if this is an old CD-CHD tag, note that we want to re-do it if (metatag == CDROM_OLD_METADATA_TAG || metatag == CDROM_TRACK_METADATA_TAG) @@ -2272,8 +2274,8 @@ static void do_copy(parameters_map ¶ms) // otherwise, clone it err = chd->write_metadata(metatag, CHDMETAINDEX_APPEND, metadata, metaflags); - if (err != CHDERR_NONE) - report_error(1, "Error writing cloned metadata: %s", chd_file::error_string(err)); + if (err) + report_error(1, "Error writing cloned metadata: %s", err.message()); } // if we need to re-do the CD metadata, do it now @@ -2284,8 +2286,8 @@ static void do_copy(parameters_map ¶ms) report_error(1, "Error upgrading CD metadata"); const cdrom_toc *toc = cdrom_get_toc(cdrom); err = cdrom_write_metadata(chd, toc); - if (err != CHDERR_NONE) - report_error(1, "Error writing upgraded CD metadata: %s", chd_file::error_string(err)); + if (err) + report_error(1, "Error writing upgraded CD metadata: %s", err.message()); if (cdda_swap) chd->m_toc = toc; } @@ -2342,9 +2344,9 @@ static void do_extract_raw(parameters_map ¶ms) try { // process output file - osd_file::error filerr = util::core_file::open(*output_file_str->second, OPEN_FLAG_WRITE | OPEN_FLAG_CREATE, output_file); - if (filerr != osd_file::error::NONE) - report_error(1, "Unable to open file (%s)", output_file_str->second->c_str()); + std::error_condition const filerr = util::core_file::open(*output_file_str->second, OPEN_FLAG_WRITE | OPEN_FLAG_CREATE, output_file); + if (filerr) + report_error(1, "Unable to open file (%s): %s", *output_file_str->second, filerr.message()); // copy all data std::vector buffer((TEMP_BUFFER_SIZE / input_chd.hunk_bytes()) * input_chd.hunk_bytes()); @@ -2354,14 +2356,14 @@ static void do_extract_raw(parameters_map ¶ms) // determine how much to read uint32_t bytes_to_read = (std::min)(buffer.size(), input_end - offset); - chd_error err = input_chd.read_bytes(offset, &buffer[0], bytes_to_read); - if (err != CHDERR_NONE) - report_error(1, "Error reading CHD file (%s): %s", params.find(OPTION_INPUT)->second->c_str(), chd_file::error_string(err)); + std::error_condition err = input_chd.read_bytes(offset, &buffer[0], bytes_to_read); + if (err) + report_error(1, "Error reading CHD file (%s): %s", *params.find(OPTION_INPUT)->second, err.message()); // write to the output uint32_t count = output_file->write(&buffer[0], bytes_to_read); if (count != bytes_to_read) - report_error(1, "Error writing to file; check disk space (%s)", output_file_str->second->c_str()); + report_error(1, "Error writing to file; check disk space (%s)", *output_file_str->second); // advance offset += bytes_to_read; @@ -2446,16 +2448,16 @@ static void do_extract_cd(parameters_map ¶ms) } // process output file - osd_file::error filerr = util::core_file::open(*output_file_str->second, OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_NO_BOM, output_toc_file); - if (filerr != osd_file::error::NONE) - report_error(1, "Unable to open file (%s)", output_file_str->second->c_str()); + std::error_condition filerr = util::core_file::open(*output_file_str->second, OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_NO_BOM, output_toc_file); + if (filerr) + report_error(1, "Unable to open file (%s): %s", *output_file_str->second, filerr.message()); // process output BIN file if (mode != MODE_GDI) { filerr = util::core_file::open(*output_bin_file_str, OPEN_FLAG_WRITE | OPEN_FLAG_CREATE, output_bin_file); - if (filerr != osd_file::error::NONE) - report_error(1, "Unable to open file (%s)", output_bin_file_str->c_str()); + if (filerr) + report_error(1, "Unable to open file (%s): %s", *output_bin_file_str, filerr.message()); } // determine total frames @@ -2490,8 +2492,8 @@ static void do_extract_cd(parameters_map ¶ms) output_bin_file.reset(); filerr = util::core_file::open(trackbin_name, OPEN_FLAG_WRITE | OPEN_FLAG_CREATE, output_bin_file); - if (filerr != osd_file::error::NONE) - report_error(1, "Unable to open file (%s)", trackbin_name.c_str()); + if (filerr) + report_error(1, "Unable to open file (%s): %s", trackbin_name, filerr.message()); outputoffs = 0; } @@ -2555,7 +2557,7 @@ static void do_extract_cd(parameters_map ¶ms) output_bin_file->seek(outputoffs, SEEK_SET); uint32_t byteswritten = output_bin_file->write(&buffer[0], bufferoffs); if (byteswritten != bufferoffs) - report_error(1, "Error writing frame %d to file (%s): %s\n", frame, output_file_str->second->c_str(), chd_file::error_string(CHDERR_WRITE_ERROR)); + report_error(1, "Error writing frame %d to file (%s): %s\n", frame, *output_file_str->second, "Write error"); outputoffs += bufferoffs; bufferoffs = 0; } @@ -2595,8 +2597,8 @@ static void do_extract_ld(parameters_map ¶ms) // read core metadata std::string metadata; - chd_error err = input_chd.read_metadata(AV_METADATA_TAG, 0, metadata); - if (err != CHDERR_NONE) + std::error_condition err = input_chd.read_metadata(AV_METADATA_TAG, 0, metadata); + if (err) report_error(1, "Unable to find A/V metadata in the input CHD"); // parse the metadata @@ -2666,7 +2668,7 @@ static void do_extract_ld(parameters_map ¶ms) // process output file avi_file::error avierr = avi_file::create(*output_file_str->second, info, output_file); if (avierr != avi_file::error::NONE) - report_error(1, "Unable to open file (%s)", output_file_str->second->c_str()); + report_error(1, "Unable to open file (%s)", *output_file_str->second); // create the codec configuration avhuff_decoder::config avconfig; @@ -2693,11 +2695,12 @@ static void do_extract_ld(parameters_map ¶ms) input_chd.codec_configure(CHD_CODEC_AVHUFF, AVHUFF_CODEC_DECOMPRESS_CONFIG, &avconfig); // read the hunk into the buffers - chd_error err = input_chd.read_hunk(framenum, nullptr); - if (err != CHDERR_NONE) + std::error_condition err = input_chd.read_hunk(framenum, nullptr); + if (err) { - uint64_t filepos = static_cast(input_chd).tell(); - report_error(1, "Error reading hunk %d at offset %d from CHD file (%s): %s\n", framenum, filepos, params.find(OPTION_INPUT)->second->c_str(), chd_file::error_string(err)); + uint64_t filepos = ~uint64_t(0); + input_chd.file().tell(filepos); + report_error(1, "Error reading hunk %d at offset %d from CHD file (%s): %s\n", framenum, filepos, *params.find(OPTION_INPUT)->second, err.message()); } // write audio @@ -2705,7 +2708,7 @@ static void do_extract_ld(parameters_map ¶ms) { avi_file::error avierr = output_file->append_sound_samples(chnum, avconfig.audio[chnum], actsamples, 0); if (avierr != avi_file::error::NONE) - report_error(1, "Error writing samples for hunk %d to file (%s): %s\n", framenum, output_file_str->second->c_str(), avi_file::error_string(avierr)); + report_error(1, "Error writing samples for hunk %d to file (%s): %s\n", framenum, *output_file_str->second, avi_file::error_string(avierr)); } // write video @@ -2713,7 +2716,7 @@ static void do_extract_ld(parameters_map ¶ms) { avi_file::error avierr = output_file->append_video_frame(fullbitmap); if (avierr != avi_file::error::NONE) - report_error(1, "Error writing video for hunk %d to file (%s): %s\n", framenum, output_file_str->second->c_str(), avi_file::error_string(avierr)); + report_error(1, "Error writing video for hunk %d to file (%s): %s\n", framenum, *output_file_str->second, avi_file::error_string(avierr)); } } @@ -2773,9 +2776,9 @@ static void do_add_metadata(parameters_map ¶ms) std::vector file; if (file_str != params.end()) { - osd_file::error filerr = util::core_file::load(file_str->second->c_str(), file); - if (filerr != osd_file::error::NONE) - report_error(1, "Error reading metadata file (%s)", file_str->second->c_str()); + std::error_condition const filerr = util::core_file::load(*file_str->second, file); + if (filerr) + report_error(1, "Error reading metadata file (%s): %s", *file_str->second, filerr.message()); } // make sure we have one or the other @@ -2799,13 +2802,13 @@ static void do_add_metadata(parameters_map ¶ms) printf("Data: %s (%d bytes)\n", file_str->second->c_str(), int(file.size())); // write the metadata - chd_error err; + std::error_condition err; if (text_str != params.end()) err = input_chd.write_metadata(tag, index, text, flags); else err = input_chd.write_metadata(tag, index, file, flags); - if (err != CHDERR_NONE) - report_error(1, "Error adding metadata: %s", chd_file::error_string(err)); + if (err) + report_error(1, "Error adding metadata: %s", err.message()); else printf("Metadata added\n"); } @@ -2843,9 +2846,9 @@ static void do_del_metadata(parameters_map ¶ms) printf("Index: %d\n", index); // write the metadata - chd_error err = input_chd.delete_metadata(tag, index); - if (err != CHDERR_NONE) - report_error(1, "Error removing metadata: %s", chd_file::error_string(err)); + std::error_condition err = input_chd.delete_metadata(tag, index); + if (err) + report_error(1, "Error removing metadata: %s", err.message()); else printf("Metadata removed\n"); } @@ -2884,9 +2887,9 @@ static void do_dump_metadata(parameters_map ¶ms) // write the metadata std::vector buffer; - chd_error err = input_chd.read_metadata(tag, index, buffer); - if (err != CHDERR_NONE) - report_error(1, "Error reading metadata: %s", chd_file::error_string(err)); + std::error_condition err = input_chd.read_metadata(tag, index, buffer); + if (err) + report_error(1, "Error reading metadata: %s", err.message()); // catch errors so we can close & delete the output file util::core_file::ptr output_file; @@ -2895,14 +2898,14 @@ static void do_dump_metadata(parameters_map ¶ms) // create the file if (output_file_str != params.end()) { - osd_file::error filerr = util::core_file::open(*output_file_str->second, OPEN_FLAG_WRITE | OPEN_FLAG_CREATE, output_file); - if (filerr != osd_file::error::NONE) - report_error(1, "Unable to open file (%s)", output_file_str->second->c_str()); + std::error_condition const filerr = util::core_file::open(*output_file_str->second, OPEN_FLAG_WRITE | OPEN_FLAG_CREATE, output_file); + if (filerr) + report_error(1, "Unable to open file (%s): %s", *output_file_str->second, filerr.message()); // output the metadata uint32_t count = output_file->write(&buffer[0], buffer.size()); if (count != buffer.size()) - report_error(1, "Error writing file (%s)", output_file_str->second->c_str()); + report_error(1, "Error writing file (%s)", *output_file_str->second); output_file.reset(); // provide some feedback @@ -3056,9 +3059,9 @@ int CLIB_DECL main(int argc, char *argv[]) (*s_command.handler)(parameters); return 0; } - catch (chd_error &err) + catch (std::error_condition const &err) { - fprintf(stderr, "CHD error occurred (main): %s\n", chd_file::error_string(err)); + fprintf(stderr, "CHD error occurred (main): %s\n", err.message().c_str()); return 1; } catch (fatal_error &err) diff --git a/src/tools/floptool.cpp b/src/tools/floptool.cpp index 6e9e2097233..f021e084a62 100644 --- a/src/tools/floptool.cpp +++ b/src/tools/floptool.cpp @@ -6,17 +6,19 @@ ***************************************************************************/ -#include -#include +#include "image_handler.h" + +#include "corestr.h" +#include "ioprocs.h" + +#include #include +#include +#include #include +#include #include -#include -#include -#include -#include "image_handler.h" -#include "corestr.h" static formats_table formats; diff --git a/src/tools/image_handler.cpp b/src/tools/image_handler.cpp index abb45de2db3..a520383846d 100644 --- a/src/tools/image_handler.cpp +++ b/src/tools/image_handler.cpp @@ -4,10 +4,16 @@ // Image generic handler class and helpers #include "image_handler.h" + #include "formats/all.h" #include "formats/fsblk_vec.h" #include "formats/fs_unformatted.h" +#include "ioprocs.h" +#include "ioprocsfill.h" +#include "ioprocsvec.h" + + // Fatalerror implementation emu_fatalerror::emu_fatalerror(util::format_argument_pack const &args) @@ -21,70 +27,6 @@ emu_fatalerror::emu_fatalerror(int _exitcode, util::format_argument_pack - -static void ram_closeproc(void *file) -{ - auto f = (iofile_ram *)file; - delete f; -} - -static int ram_seekproc(void *file, int64_t offset, int whence) -{ - auto f = (iofile_ram *)file; - switch(whence) { - case SEEK_SET: f->pos = offset; break; - case SEEK_CUR: f->pos += offset; break; - case SEEK_END: f->pos = f->data->size() + offset; break; - } - - if(whence == SEEK_CUR) - f->pos = std::max(f->pos, 0); - else - f->pos = std::clamp(f->pos, 0, f->data->size()); - return 0; -} - -static size_t ram_readproc(void *file, void *buffer, size_t length) -{ - auto f = (iofile_ram *)file; - size_t l = std::min >(length, f->data->size() - f->pos); - memcpy(buffer, f->data->data() + f->pos, l); - return l; -} - -static size_t ram_writeproc(void *file, const void *buffer, size_t length) -{ - auto f = (iofile_ram *)file; - size_t l = std::max >(f->pos + length, f->data->size()); - f->data->resize(l); - memcpy(f->data->data() + f->pos, buffer, length); - return length; -} - -static uint64_t ram_filesizeproc(void *file) -{ - auto f = (iofile_ram *)file; - return f->data->size(); -} - - -static const io_procs iop_ram = { - ram_closeproc, - ram_seekproc, - ram_readproc, - ram_writeproc, - ram_filesizeproc -}; - -io_generic *ram_open(std::vector &data) -{ - iofile_ram *f = new iofile_ram; - f->data = &data; - f->pos = 0; - return new io_generic({ &iop_ram, f }); -} - // Format enumeration @@ -304,45 +246,37 @@ std::vector> image_handler::identify(c std::vector> res; std::vector variants; - std::string msg = util::string_format("Error opening %s for reading", m_on_disk_path); FILE *f = fopen(m_on_disk_path.c_str(), "rb"); if (!f) { + std::string msg = util::string_format("Error opening %s for reading", m_on_disk_path); perror(msg.c_str()); return res; } - io_generic io; - io.file = f; - io.procs = &stdio_ioprocs_noclose; - io.filler = 0xff; + auto io = util::stdio_read(f, 0xff); for(const auto &e : formats.floppy_format_info_by_key) { - u8 score = e.second->m_format->identify(&io, floppy_image::FF_UNKNOWN, variants); + u8 score = e.second->m_format->identify(*io, floppy_image::FF_UNKNOWN, variants); if(score) res.emplace_back(std::make_pair(score, e.second)); } - fclose(f); - return res; } bool image_handler::floppy_load(const floppy_format_info *format) { std::vector variants; - std::string msg = util::string_format("Error opening %s for reading", m_on_disk_path); FILE *f = fopen(m_on_disk_path.c_str(), "rb"); if (!f) { + std::string msg = util::string_format("Error opening %s for reading", m_on_disk_path); perror(msg.c_str()); return true; } - io_generic io; - io.file = f; - io.procs = &stdio_ioprocs_noclose; - io.filler = 0xff; + auto io = util::stdio_read(f, 0xff); - return !format->m_format->load(&io, floppy_image::FF_UNKNOWN, variants, &m_floppy_image); + return !format->m_format->load(*io, floppy_image::FF_UNKNOWN, variants, &m_floppy_image); } bool image_handler::floppy_save(const floppy_format_info *format) @@ -355,12 +289,9 @@ bool image_handler::floppy_save(const floppy_format_info *format) return true; } - io_generic io; - io.file = f; - io.procs = &stdio_ioprocs_noclose; - io.filler = 0xff; + auto io = util::stdio_read_write(f, 0xff); - return !format->m_format->save(&io, variants, &m_floppy_image); + return !format->m_format->save(*io, variants, &m_floppy_image); } void image_handler::floppy_create(const floppy_create_info *format, fs_meta_data meta) @@ -372,14 +303,13 @@ void image_handler::floppy_create(const floppy_create_info *format, fs_meta_data auto fs = format->m_manager->mount(blockdev); fs->format(meta); - auto iog = ram_open(img); auto source_format = format->m_type(); - source_format->load(iog, floppy_image::FF_UNKNOWN, variants, &m_floppy_image); + auto io = util::ram_read(img.data(), img.size(), 0xff); + source_format->load(*io, floppy_image::FF_UNKNOWN, variants, &m_floppy_image); delete source_format; - delete iog; - - } else + } else { fs_unformatted::format(format->m_key, &m_floppy_image); + } } bool image_handler::floppy_mount_fs(const filesystem_format *format) @@ -390,11 +320,10 @@ bool image_handler::floppy_mount_fs(const filesystem_format *format) std::vector variants; m_floppy_fs_converter = ci->m_type; m_sector_image.clear(); - auto iog = ram_open(m_sector_image); auto load_format = m_floppy_fs_converter(); - load_format->save(iog, variants, &m_floppy_image); + util::random_read_write_fill_wrapper, 0xff> io(m_sector_image); + load_format->save(io, variants, &m_floppy_image); delete load_format; - delete iog; } if(ci->m_image_size == m_sector_image.size()) @@ -425,11 +354,10 @@ bool image_handler::hd_mount_fs(const filesystem_format *format) void image_handler::fs_to_floppy() { std::vector variants; - auto iog = ram_open(m_sector_image); + auto io = util::ram_read(m_sector_image.data(), m_sector_image.size(), 0xff); auto format = m_floppy_fs_converter(); - format->load(iog, floppy_image::FF_UNKNOWN, variants, &m_floppy_image); + format->load(*io, floppy_image::FF_UNKNOWN, variants, &m_floppy_image); delete format; - delete iog; } std::vector image_handler::path_split(std::string path) const diff --git a/src/tools/image_handler.h b/src/tools/image_handler.h index f004bd7d91f..d9a861bb3fd 100644 --- a/src/tools/image_handler.h +++ b/src/tools/image_handler.h @@ -3,27 +3,26 @@ // Image generic handler class and helpers -#ifndef TOOLS_IMAGE_HANDLER_H -#define TOOLS_IMAGE_HANDLER_H +#ifndef MAME_TOOLS_IMAGE_HANDLER_H +#define MAME_TOOLS_IMAGE_HANDLER_H + +#pragma once #include "../emu/emucore.h" + #include "formats/fsmgr.h" +#include #include -#include #include +#include +#include + using u8 = uint8_t; using u16 = uint16_t; using u32 = uint32_t; -struct iofile_ram { - std::vector *data; - int64_t pos; -}; - -io_generic *ram_open(std::vector &data); - struct floppy_format_info { floppy_image_format_t *m_format; std::string m_category; @@ -117,5 +116,4 @@ private: }; -#endif - +#endif // MAME_TOOLS_IMAGE_HANDLER_H diff --git a/src/tools/imgtool/iflopimg.cpp b/src/tools/imgtool/iflopimg.cpp index f6e79e6cd5d..951b75978e8 100644 --- a/src/tools/imgtool/iflopimg.cpp +++ b/src/tools/imgtool/iflopimg.cpp @@ -8,10 +8,15 @@ *********************************************************************/ +#include "iflopimg.h" + #include "imgtool.h" -#include "formats/flopimg.h" #include "library.h" -#include "iflopimg.h" + +#include "formats/flopimg.h" + +#include "ioprocs.h" + imgtoolerr_t imgtool_floppy_error(floperr_t err) { @@ -39,57 +44,6 @@ imgtoolerr_t imgtool_floppy_error(floperr_t err) -/********************************************************************* - Imgtool ioprocs -*********************************************************************/ - -static void imgtool_floppy_closeproc(void *file) -{ - delete reinterpret_cast(file); -} - -static int imgtool_floppy_seekproc(void *file, int64_t offset, int whence) -{ - reinterpret_cast(file)->seek(offset, whence); - return 0; -} - -static size_t imgtool_floppy_readproc(void *file, void *buffer, size_t length) -{ - return reinterpret_cast(file)->read(buffer, length); -} - -static size_t imgtool_floppy_writeproc(void *file, const void *buffer, size_t length) -{ - reinterpret_cast(file)->write(buffer, length); - return length; -} - -static uint64_t imgtool_floppy_filesizeproc(void *file) -{ - return reinterpret_cast(file)->size(); -} - -static const struct io_procs imgtool_ioprocs = -{ - imgtool_floppy_closeproc, - imgtool_floppy_seekproc, - imgtool_floppy_readproc, - imgtool_floppy_writeproc, - imgtool_floppy_filesizeproc -}; - -static const struct io_procs imgtool_noclose_ioprocs = -{ - nullptr, - imgtool_floppy_seekproc, - imgtool_floppy_readproc, - imgtool_floppy_writeproc, - imgtool_floppy_filesizeproc -}; - - - /********************************************************************* Imgtool handlers *********************************************************************/ @@ -102,11 +56,10 @@ struct imgtool_floppy_image -static imgtoolerr_t imgtool_floppy_open_internal(imgtool::image &image, imgtool::stream::ptr &&stream, int noclose) +static imgtoolerr_t imgtool_floppy_open_internal(imgtool::image &image, imgtool::stream::ptr &&stream) { floperr_t ferr; imgtoolerr_t err = IMGTOOLERR_SUCCESS; - imgtool::stream *f = nullptr; struct imgtool_floppy_image *fimg; const imgtool_class *imgclass; const struct FloppyFormat *format; @@ -117,18 +70,13 @@ static imgtoolerr_t imgtool_floppy_open_internal(imgtool::image &image, imgtool: format = (const struct FloppyFormat *) imgclass->derived_param; open = (imgtoolerr_t (*)(imgtool::image &, imgtool::stream *)) imgtool_get_info_ptr(imgclass, IMGTOOLINFO_PTR_FLOPPY_OPEN); - // extract the pointer - f = stream.release(); - // open up the floppy - ferr = floppy_open(f, noclose ? &imgtool_noclose_ioprocs : &imgtool_ioprocs, - "", format, FLOPPY_FLAGS_READWRITE, &fimg->floppy); + ferr = floppy_open(imgtool::stream_read_write(std::move(stream), 0xff), "", format, FLOPPY_FLAGS_READWRITE, &fimg->floppy); if (ferr) { err = imgtool_floppy_error(ferr); goto done; } - f = nullptr; // the floppy object has the stream now if (open) { @@ -138,8 +86,6 @@ static imgtoolerr_t imgtool_floppy_open_internal(imgtool::image &image, imgtool: } done: - if (f) - delete f; if (err && fimg->floppy) { floppy_close(fimg->floppy); @@ -152,7 +98,7 @@ done: static imgtoolerr_t imgtool_floppy_open(imgtool::image &image, imgtool::stream::ptr &&stream) { - return imgtool_floppy_open_internal(image, std::move(stream), false); + return imgtool_floppy_open_internal(image, std::move(stream)); } @@ -161,7 +107,6 @@ static imgtoolerr_t imgtool_floppy_create(imgtool::image &image, imgtool::stream { floperr_t ferr; imgtoolerr_t err = IMGTOOLERR_SUCCESS; - imgtool::stream *f = nullptr; struct imgtool_floppy_image *fimg; const imgtool_class *imgclass; const struct FloppyFormat *format; @@ -174,17 +119,13 @@ static imgtoolerr_t imgtool_floppy_create(imgtool::image &image, imgtool::stream create = (imgtoolerr_t (*)(imgtool::image &, imgtool::stream *, util::option_resolution *)) imgtool_get_info_ptr(imgclass, IMGTOOLINFO_PTR_FLOPPY_CREATE); open = (imgtoolerr_t (*)(imgtool::image &, imgtool::stream *)) imgtool_get_info_ptr(imgclass, IMGTOOLINFO_PTR_FLOPPY_OPEN); - // extract the pointer - f = stream.release(); - // open up the floppy - ferr = floppy_create(f, &imgtool_ioprocs, format, opts, &fimg->floppy); + ferr = floppy_create(imgtool::stream_read_write(std::move(stream), 0xff), format, opts, &fimg->floppy); if (ferr) { err = imgtool_floppy_error(ferr); goto done; } - f = nullptr; // the floppy object has the stream now // do we have to do extra stuff when creating the image? if (create) @@ -203,8 +144,6 @@ static imgtoolerr_t imgtool_floppy_create(imgtool::image &image, imgtool::stream } done: - if (f) - delete f; if (err && fimg->floppy) { floppy_close(fimg->floppy); diff --git a/src/tools/imgtool/iflopimg.h b/src/tools/imgtool/iflopimg.h index 078a1247ae3..d27ba952e16 100644 --- a/src/tools/imgtool/iflopimg.h +++ b/src/tools/imgtool/iflopimg.h @@ -7,13 +7,16 @@ Bridge code for Imgtool into the standard floppy code *********************************************************************/ +#ifndef MAME_TOOLS_IMGTOOL_IFLOPIMG_H +#define MAME_TOOLS_IMGTOOL_IFLOPIMG_H -#ifndef IFLOPIMG_H -#define IFLOPIMG_H +#pragma once -#include "formats/flopimg.h" #include "library.h" +#include "formats/flopimg.h" + + /*************************************************************************** Prototypes @@ -38,4 +41,4 @@ imgtoolerr_t imgtool_floppy_write_sector_from_stream(imgtool::image &img, int he void *imgtool_floppy_extrabytes(imgtool::image &img); -#endif /* IFLOPIMG_H */ +#endif // MAME_TOOLS_IMGTOOL_IFLOPIMG_H diff --git a/src/tools/imgtool/imghd.cpp b/src/tools/imgtool/imghd.cpp index 45ac262a9ba..8e077295b93 100644 --- a/src/tools/imgtool/imghd.cpp +++ b/src/tools/imgtool/imghd.cpp @@ -9,34 +9,21 @@ Raphael Nabet 2003 */ +#include "imghd.h" #include "imgtool.h" #include "harddisk.h" -#include "imghd.h" -static imgtoolerr_t map_chd_error(chd_error chderr) +static imgtoolerr_t map_chd_error(std::error_condition chderr) { - imgtoolerr_t err; - - switch(chderr) - { - case CHDERR_NONE: - err = IMGTOOLERR_SUCCESS; - break; - case CHDERR_OUT_OF_MEMORY: - err = IMGTOOLERR_OUTOFMEMORY; - break; - case CHDERR_FILE_NOT_WRITEABLE: - err = IMGTOOLERR_READONLY; - break; - case CHDERR_NOT_SUPPORTED: - err = IMGTOOLERR_UNIMPLEMENTED; - break; - default: - err = IMGTOOLERR_UNEXPECTED; - break; - } - return err; + if (!chderr) + return IMGTOOLERR_SUCCESS; + else if (std::errc::not_enough_memory == chderr) + return IMGTOOLERR_OUTOFMEMORY; + else if (chd_file::error::FILE_NOT_WRITEABLE == chderr) + return IMGTOOLERR_READONLY; + else + return IMGTOOLERR_UNEXPECTED; } @@ -50,7 +37,7 @@ imgtoolerr_t imghd_create(imgtool::stream &stream, uint32_t hunksize, uint32_t c { imgtoolerr_t err = IMGTOOLERR_SUCCESS; chd_file chd; - chd_error rc; + std::error_condition rc; chd_codec_type compression[4] = { CHD_CODEC_NONE }; /* sanity check args -- see parse_hunk_size() in src/lib/util/chd.cpp */ @@ -73,8 +60,8 @@ imgtoolerr_t imghd_create(imgtool::stream &stream, uint32_t hunksize, uint32_t c const uint64_t logicalbytes = (uint64_t)cylinders * heads * sectors * seclen; /* create the new hard drive */ - rc = chd.create(*stream.core_file(), logicalbytes, hunksize, seclen, compression); - if (rc != CHDERR_NONE) + rc = chd.create(stream_read_write(stream, 0), logicalbytes, hunksize, seclen, compression); + if (rc) { err = map_chd_error(rc); return err; @@ -82,8 +69,8 @@ imgtoolerr_t imghd_create(imgtool::stream &stream, uint32_t hunksize, uint32_t c /* write the metadata */ const std::string metadata = util::string_format(HARD_DISK_METADATA_FORMAT, cylinders, heads, sectors, seclen); - err = (imgtoolerr_t)chd.write_metadata(HARD_DISK_METADATA_TAG, 0, metadata); - if (rc != CHDERR_NONE) + rc = chd.write_metadata(HARD_DISK_METADATA_TAG, 0, metadata); + if (rc) { err = map_chd_error(rc); return err; @@ -118,12 +105,12 @@ imgtoolerr_t imghd_create(imgtool::stream &stream, uint32_t hunksize, uint32_t c */ imgtoolerr_t imghd_open(imgtool::stream &stream, struct mess_hard_disk_file *hard_disk) { - chd_error chderr; + std::error_condition chderr; imgtoolerr_t err = IMGTOOLERR_SUCCESS; hard_disk->hard_disk = nullptr; - chderr = hard_disk->chd.open(*stream.core_file(), !stream.is_read_only()); + chderr = hard_disk->chd.open(stream_read_write(stream, 0), !stream.is_read_only()); if (chderr) { err = map_chd_error(chderr); @@ -174,9 +161,8 @@ void imghd_close(struct mess_hard_disk_file *disk) */ imgtoolerr_t imghd_read(struct mess_hard_disk_file *disk, uint32_t lbasector, void *buffer) { - uint32_t reply; - reply = hard_disk_read(disk->hard_disk, lbasector, buffer); - return (imgtoolerr_t)(reply ? IMGTOOLERR_SUCCESS : map_chd_error((chd_error)reply)); + uint32_t reply = hard_disk_read(disk->hard_disk, lbasector, buffer); + return reply ? IMGTOOLERR_SUCCESS : IMGTOOLERR_READERROR; } @@ -188,9 +174,8 @@ imgtoolerr_t imghd_read(struct mess_hard_disk_file *disk, uint32_t lbasector, vo */ imgtoolerr_t imghd_write(struct mess_hard_disk_file *disk, uint32_t lbasector, const void *buffer) { - uint32_t reply; - reply = hard_disk_write(disk->hard_disk, lbasector, buffer); - return (imgtoolerr_t)(reply ? IMGTOOLERR_SUCCESS : map_chd_error((chd_error)reply)); + uint32_t reply = hard_disk_write(disk->hard_disk, lbasector, buffer); + return reply ? IMGTOOLERR_SUCCESS : IMGTOOLERR_WRITEERROR; } diff --git a/src/tools/imgtool/imghd.h b/src/tools/imgtool/imghd.h index d4ae341af1e..0eadc6e2eb3 100644 --- a/src/tools/imgtool/imghd.h +++ b/src/tools/imgtool/imghd.h @@ -11,8 +11,11 @@ #ifndef IMGHD_H #define IMGHD_H +#include "stream.h" + #include "harddisk.h" + struct mess_hard_disk_file { imgtool::stream *stream; diff --git a/src/tools/imgtool/imgtool.cpp b/src/tools/imgtool/imgtool.cpp index 841147ae26e..ce4dd22d186 100644 --- a/src/tools/imgtool/imgtool.cpp +++ b/src/tools/imgtool/imgtool.cpp @@ -8,14 +8,18 @@ ***************************************************************************/ +#include "imgtool.h" +#include "library.h" +#include "modules.h" + +#include "formats/imageutl.h" + +#include "corefile.h" + #include #include #include -#include "imgtool.h" -#include "formats/imageutl.h" -#include "library.h" -#include "modules.h" /*************************************************************************** diff --git a/src/tools/imgtool/library.h b/src/tools/imgtool/library.h index 7406cc2e526..f0e0532e502 100644 --- a/src/tools/imgtool/library.h +++ b/src/tools/imgtool/library.h @@ -4,29 +4,31 @@ library.h - Code relevant to the Imgtool library; analogous to the MESS/MAME driver - list. + Code relevant to the Imgtool library; analogous to the MAME driver list. - Unlike MESS and MAME which have static driver lists, Imgtool has a - concept of a library and this library is built at startup time. + Unlike MAME which has a static driver lists, Imgtool has a concept of a + library and this library is built at startup time. dynamic for which modules are added to. This makes "dynamic" modules much easier ****************************************************************************/ +#ifndef MAME_TOOLS_IMGTOOL_LIBRARY_H +#define MAME_TOOLS_IMGTOOL_LIBRARY_H -#ifndef LIBRARY_H -#define LIBRARY_H +#pragma once -#include -#include -#include +#include "charconv.h" +#include "stream.h" #include "corestr.h" #include "opresolv.h" -#include "stream.h" -#include "unicode.h" -#include "charconv.h" #include "timeconv.h" +#include "unicode.h" + +#include +#include +#include + namespace imgtool { @@ -542,4 +544,4 @@ private: } // namespace imgtool -#endif // LIBRARY_H +#endif // MAME_TOOLS_IMGTOOL_LIBRARY_H diff --git a/src/tools/imgtool/main.cpp b/src/tools/imgtool/main.cpp index 75fcd52e7a2..77b3d8c6874 100644 --- a/src/tools/imgtool/main.cpp +++ b/src/tools/imgtool/main.cpp @@ -11,6 +11,8 @@ #include "imgtool.h" #include "main.h" #include "modules.h" + +#include "corefile.h" #include "strformat.h" #include diff --git a/src/tools/imgtool/modules/hp85_tape.cpp b/src/tools/imgtool/modules/hp85_tape.cpp index 0198b6251dd..fa32042efd3 100644 --- a/src/tools/imgtool/modules/hp85_tape.cpp +++ b/src/tools/imgtool/modules/hp85_tape.cpp @@ -7,12 +7,16 @@ HP-85 tape format *********************************************************************/ - #include "imgtool.h" -#include "formats/imageutl.h" + #include "formats/hti_tape.h" +#include "formats/imageutl.h" + +#include "ioprocs.h" + #include + // Constants static constexpr unsigned CHARS_PER_FNAME = 6; // Characters in a filename static constexpr unsigned CHARS_PER_EXT = 4; // Characters in (simulated) file extension @@ -158,48 +162,13 @@ void tape_image_85::format_img(void) finalize_allocation(); } -namespace { - int my_seekproc(void *file, int64_t offset, int whence) - { - reinterpret_cast(file)->seek(offset, whence); - return 0; - } - - size_t my_readproc(void *file, void *buffer, size_t length) - { - return reinterpret_cast(file)->read(buffer, length); - } - - size_t my_writeproc(void *file, const void *buffer, size_t length) - { - reinterpret_cast(file)->write(buffer, length); - return length; - } - - uint64_t my_filesizeproc(void *file) - { - return reinterpret_cast(file)->size(); - } - - const struct io_procs my_stream_procs = { - nullptr, - my_seekproc, - my_readproc, - my_writeproc, - my_filesizeproc - }; -} - imgtoolerr_t tape_image_85::load_from_file(imgtool::stream *stream) { - io_generic io; - io.file = (void *)stream; - io.procs = &my_stream_procs; - io.filler = 0; - - if (!image.load_tape(&io)) { + auto io = imgtool::stream_read(*stream, 0); + if (!io || !image.load_tape(*io)) { return IMGTOOLERR_READERROR; } + io.reset(); // Prevent track boundary crossing when reading directory file_track_1 = 0; @@ -422,12 +391,7 @@ imgtoolerr_t tape_image_85::save_to_file(imgtool::stream *stream) file_0.clear(); save_sif_file(track , pos , dir.size() + 1 , file_0); - io_generic io; - io.file = (void *)stream; - io.procs = &my_stream_procs; - io.filler = 0; - - image.save_tape(&io); + image.save_tape(*imgtool::stream_read_write(*stream, 0)); return IMGTOOLERR_SUCCESS; } diff --git a/src/tools/imgtool/modules/hp9845_tape.cpp b/src/tools/imgtool/modules/hp9845_tape.cpp index 7a3e90b08d1..a1ae0377180 100644 --- a/src/tools/imgtool/modules/hp9845_tape.cpp +++ b/src/tools/imgtool/modules/hp9845_tape.cpp @@ -108,11 +108,16 @@ these special characters. *********************************************************************/ -#include - #include "imgtool.h" -#include "formats/imageutl.h" + #include "formats/hti_tape.h" +#include "formats/imageutl.h" + +#include "corefile.h" +#include "ioprocs.h" + +#include + // Constants #define SECTOR_LEN 256 // Bytes in a sector @@ -291,49 +296,16 @@ void tape_image_t::format_img(void) dirty = true; } -static int my_seekproc(void *file, int64_t offset, int whence) -{ - reinterpret_cast(file)->seek(offset, whence); - return 0; -} - -static size_t my_readproc(void *file, void *buffer, size_t length) -{ - return reinterpret_cast(file)->read(buffer, length); -} - -static size_t my_writeproc(void *file, const void *buffer, size_t length) -{ - reinterpret_cast(file)->write(buffer, length); - return length; -} - -static uint64_t my_filesizeproc(void *file) -{ - return reinterpret_cast(file)->size(); -} - -static const struct io_procs my_stream_procs = { - nullptr, - my_seekproc, - my_readproc, - my_writeproc, - my_filesizeproc -}; - imgtoolerr_t tape_image_t::load_from_file(imgtool::stream *stream) { hti_format_t inp_image; inp_image.set_image_format(hti_format_t::HTI_DELTA_MOD_16_BITS); - io_generic io; - io.file = (void *)stream; - io.procs = &my_stream_procs; - io.filler = 0; - - if (!inp_image.load_tape(&io)) { + auto io = imgtool::stream_read(*stream, 0); + if (!io || !inp_image.load_tape(*io)) { return IMGTOOLERR_READERROR; } + io.reset(); unsigned exp_sector = 0; unsigned last_sector_on_track = SECTORS_PER_TRACK; @@ -523,12 +495,7 @@ imgtoolerr_t tape_image_t::save_to_file(imgtool::stream *stream) } } - io_generic io; - io.file = (void *)stream; - io.procs = &my_stream_procs; - io.filler = 0; - - out_image.save_tape(&io); + out_image.save_tape(*imgtool::stream_read_write(*stream, 0)); return IMGTOOLERR_SUCCESS; } diff --git a/src/tools/imgtool/stream.cpp b/src/tools/imgtool/stream.cpp index bb0d95614f3..ed9814e504a 100644 --- a/src/tools/imgtool/stream.cpp +++ b/src/tools/imgtool/stream.cpp @@ -8,19 +8,178 @@ ***************************************************************************/ +#include "stream.h" + +#include "imgtool.h" + +#include "corefile.h" +#include "ioprocs.h" +#include "unzip.h" + +#include #include #include -#include -#include "unzip.h" -#include "imgtool.h" +#include // for crc32 + + +namespace imgtool { + +namespace { + +class stream_read_wrapper : public virtual util::random_read +{ +public: + stream_read_wrapper(stream::ptr &&stream, std::uint8_t filler) noexcept + : m_stream(stream.release()) + , m_filler(filler) + , m_close(true) + { + assert(m_stream); + } + + stream_read_wrapper(stream &stream, std::uint8_t filler) noexcept + : m_stream(&stream) + , m_filler(filler) + , m_close(false) + { + } + + virtual ~stream_read_wrapper() + { + if (m_close) + delete m_stream; + } + + virtual std::error_condition seek(std::int64_t offset, int whence) noexcept override + { + m_stream->seek(offset, whence); + return std::error_condition(); + } + + virtual std::error_condition tell(std::uint64_t &result) noexcept override + { + result = m_stream->tell(); + return std::error_condition(); + } + + virtual std::error_condition length(std::uint64_t &result) noexcept override + { + result = m_stream->size(); + return std::error_condition(); + } + + virtual std::error_condition read(void *buffer, std::size_t length, std::size_t &actual) noexcept override + { + actual = m_stream->read(buffer, length); + if (actual < length) + std::memset(reinterpret_cast(buffer) + actual, m_filler, length - actual); + return std::error_condition(); + } + + virtual std::error_condition read_at(std::uint64_t offset, void *buffer, std::size_t length, std::size_t &actual) noexcept override + { + std::uint64_t const pos = m_stream->tell(); + m_stream->seek(offset, SEEK_SET); + actual = m_stream->read(buffer, length); + m_stream->seek(pos, SEEK_SET); + if (actual < length) + std::memset(reinterpret_cast(buffer) + actual, m_filler, length - actual); + return std::error_condition(); + } + +protected: + stream *const m_stream; + std::uint8_t m_filler; + bool const m_close; +}; + + +class stream_read_write_wrapper : public stream_read_wrapper, public util::random_read_write +{ +public: + using stream_read_wrapper::stream_read_wrapper; + + virtual std::error_condition finalize() noexcept override + { + return std::error_condition(); + } + + virtual std::error_condition flush() noexcept override + { + return std::error_condition(); + } + + virtual std::error_condition write(void const *buffer, std::size_t length, std::size_t &actual) noexcept override + { + std::uint64_t const pos = m_stream->tell(); + std::uint64_t size = m_stream->size(); + if (size < pos) + { + m_stream->seek(size, SEEK_SET); + size += m_stream->fill(m_filler, pos - size); + } + actual = (size >= pos) ? m_stream->write(buffer, length) : 0U; + return (actual == length) ? std::error_condition() : std::errc::io_error; + } + + virtual std::error_condition write_at(std::uint64_t offset, void const *buffer, std::size_t length, std::size_t &actual) noexcept override + { + std::uint64_t const pos = m_stream->tell(); + std::uint64_t size = m_stream->size(); + if (offset > size) + { + m_stream->seek(size, SEEK_SET); + size += m_stream->fill(m_filler, offset - size); + } + else + { + m_stream->seek(offset, SEEK_SET); + } + actual = (size >= offset) ? m_stream->write(buffer, length) : 0U; + m_stream->seek(pos, SEEK_SET); + return (actual == length) ? std::error_condition() : std::errc::io_error; + } +}; + +} // anonymous namespace + + +util::random_read::ptr stream_read(stream::ptr &&s, std::uint8_t filler) noexcept +{ + util::random_read::ptr result; + if (s) + result.reset(new (std::nothrow) stream_read_wrapper(std::move(s), filler)); + return result; +} + +util::random_read::ptr stream_read(stream &s, std::uint8_t filler) noexcept +{ + util::random_read::ptr result(new (std::nothrow) stream_read_wrapper(s, filler)); + return result; +} + +util::random_read_write::ptr stream_read_write(stream::ptr &&s, std::uint8_t filler) noexcept +{ + util::random_read_write::ptr result; + if (s) + result.reset(new (std::nothrow) stream_read_write_wrapper(std::move(s), filler)); + return result; +} + +util::random_read_write::ptr stream_read_write(stream &s, std::uint8_t filler) noexcept +{ + util::random_read_write::ptr result(new (std::nothrow) stream_read_write_wrapper(s, filler)); + return result; +} + //------------------------------------------------- // ctor //------------------------------------------------- -imgtool::stream::stream(bool wp) +stream::stream(bool wp) : imgtype(IMG_FILE) , write_protect(wp) , position(0) @@ -35,7 +194,7 @@ imgtool::stream::stream(bool wp) // ctor //------------------------------------------------- -imgtool::stream::stream(bool wp, util::core_file::ptr &&f) +stream::stream(bool wp, util::core_file::ptr &&f) : imgtype(IMG_FILE) , write_protect(wp) , position(0) @@ -50,7 +209,7 @@ imgtool::stream::stream(bool wp, util::core_file::ptr &&f) // ctor //------------------------------------------------- -imgtool::stream::stream(bool wp, std::size_t size) +stream::stream(bool wp, std::size_t size) : imgtype(IMG_MEM) , write_protect(wp) , position(0) @@ -65,7 +224,7 @@ imgtool::stream::stream(bool wp, std::size_t size) // ctor //------------------------------------------------- -imgtool::stream::stream(bool wp, std::size_t size, void *buf) +stream::stream(bool wp, std::size_t size, void *buf) : imgtype(IMG_MEM) , write_protect(wp) , position(0) @@ -80,7 +239,7 @@ imgtool::stream::stream(bool wp, std::size_t size, void *buf) // dtor //------------------------------------------------- -imgtool::stream::~stream() +stream::~stream() { if (buffer) free(buffer); @@ -91,39 +250,39 @@ imgtool::stream::~stream() // open_zip //------------------------------------------------- -imgtool::stream::ptr imgtool::stream::open_zip(const std::string &zipname, const char *subname, int read_or_write) +stream::ptr stream::open_zip(const std::string &zipname, const char *subname, int read_or_write) { if (read_or_write) - return imgtool::stream::ptr(); + return stream::ptr(); /* check to see if the file exists */ FILE *f = fopen(zipname.c_str(), "r"); if (!f) - return imgtool::stream::ptr(); + return stream::ptr(); fclose(f); - imgtool::stream::ptr imgfile(new imgtool::stream(true)); + stream::ptr imgfile(new stream(true)); imgfile->imgtype = IMG_MEM; util::archive_file::ptr z; util::archive_file::open_zip(zipname, z); if (!z) - return imgtool::stream::ptr(); + return stream::ptr(); int zipent = z->first_file(); while ((zipent >= 0) && subname && strcmp(subname, z->current_name().c_str())) zipent = z->next_file(); if (zipent < 0) - return imgtool::stream::ptr(); + return stream::ptr(); imgfile->filesize = z->current_uncompressed_length(); imgfile->buffer = reinterpret_cast(malloc(z->current_uncompressed_length())); if (!imgfile->buffer) - return imgtool::stream::ptr(); + return stream::ptr(); - if (z->decompress(imgfile->buffer, z->current_uncompressed_length()) != util::archive_file::error::NONE) - return imgtool::stream::ptr(); + if (z->decompress(imgfile->buffer, z->current_uncompressed_length())) + return stream::ptr(); return imgfile; } @@ -134,7 +293,7 @@ imgtool::stream::ptr imgtool::stream::open_zip(const std::string &zipname, const // open //------------------------------------------------- -imgtool::stream::ptr imgtool::stream::open(const std::string &filename, int read_or_write) +stream::ptr stream::open(const std::string &filename, int read_or_write) { static const uint32_t write_modes[] = { @@ -143,7 +302,7 @@ imgtool::stream::ptr imgtool::stream::open(const std::string &filename, int read OPEN_FLAG_READ | OPEN_FLAG_WRITE, OPEN_FLAG_READ | OPEN_FLAG_WRITE | OPEN_FLAG_CREATE }; - imgtool::stream::ptr s; + stream::ptr s; char c; // maybe we are just a ZIP? @@ -152,13 +311,13 @@ imgtool::stream::ptr imgtool::stream::open(const std::string &filename, int read util::core_file::ptr f = nullptr; auto const filerr = util::core_file::open(filename, write_modes[read_or_write], f); - if (filerr != osd_file::error::NONE) + if (filerr) { if (!read_or_write) { int const len = filename.size(); - /* can't open the file; try opening ZIP files with other names */ + // can't open the file; try opening ZIP files with other names std::vector buf(len + 1); strcpy(&buf[0], filename.c_str()); @@ -177,11 +336,11 @@ imgtool::stream::ptr imgtool::stream::open(const std::string &filename, int read return s; } - /* ah well, it was worth a shot */ - return imgtool::stream::ptr(); + // ah well, it was worth a shot + return stream::ptr(); } - imgtool::stream::ptr imgfile(new imgtool::stream(read_or_write ? false : true, std::move(f))); + stream::ptr imgfile(new stream(read_or_write ? false : true, std::move(f))); // normal file return imgfile; @@ -192,11 +351,11 @@ imgtool::stream::ptr imgtool::stream::open(const std::string &filename, int read // open_write_stream //------------------------------------------------- -imgtool::stream::ptr imgtool::stream::open_write_stream(int size) +stream::ptr stream::open_write_stream(int size) { - imgtool::stream::ptr imgfile(new imgtool::stream(false, size)); + stream::ptr imgfile(new stream(false, size)); if (!imgfile->buffer) - return imgtool::stream::ptr(); + return stream::ptr(); return imgfile; } @@ -206,9 +365,9 @@ imgtool::stream::ptr imgtool::stream::open_write_stream(int size) // open_mem //------------------------------------------------- -imgtool::stream::ptr imgtool::stream::open_mem(void *buf, size_t sz) +stream::ptr stream::open_mem(void *buf, size_t sz) { - imgtool::stream::ptr imgfile(new imgtool::stream(false, sz, buf)); + stream::ptr imgfile(new stream(false, sz, buf)); return imgfile; } @@ -218,7 +377,7 @@ imgtool::stream::ptr imgtool::stream::open_mem(void *buf, size_t sz) // core_file //------------------------------------------------- -util::core_file *imgtool::stream::core_file() +util::core_file *stream::core_file() { return (imgtype == IMG_FILE) ? file.get() : nullptr; } @@ -228,7 +387,7 @@ util::core_file *imgtool::stream::core_file() // read //------------------------------------------------- -uint32_t imgtool::stream::read(void *buf, uint32_t sz) +uint32_t stream::read(void *buf, uint32_t sz) { uint32_t result = 0; @@ -262,7 +421,7 @@ uint32_t imgtool::stream::read(void *buf, uint32_t sz) // write //------------------------------------------------- -uint32_t imgtool::stream::write(const void *buf, uint32_t sz) +uint32_t stream::write(const void *buf, uint32_t sz) { void *new_buffer; uint32_t result = 0; @@ -317,7 +476,7 @@ uint32_t imgtool::stream::write(const void *buf, uint32_t sz) // size //------------------------------------------------- -uint64_t imgtool::stream::size() const +uint64_t stream::size() const { return filesize; } @@ -327,7 +486,7 @@ uint64_t imgtool::stream::size() const // getptr //------------------------------------------------- -void *imgtool::stream::getptr() +void *stream::getptr() { void *ptr; @@ -349,7 +508,7 @@ void *imgtool::stream::getptr() // seek //------------------------------------------------- -int imgtool::stream::seek(int64_t pos, int where) +int stream::seek(int64_t pos, int where) { switch(where) { @@ -377,7 +536,7 @@ int imgtool::stream::seek(int64_t pos, int where) // tell //------------------------------------------------- -uint64_t imgtool::stream::tell() +uint64_t stream::tell() { return position; } @@ -387,7 +546,7 @@ uint64_t imgtool::stream::tell() // transfer //------------------------------------------------- -uint64_t imgtool::stream::transfer(imgtool::stream &dest, imgtool::stream &source, uint64_t sz) +uint64_t stream::transfer(stream &dest, stream &source, uint64_t sz) { uint64_t result = 0; uint64_t readsz; @@ -407,7 +566,7 @@ uint64_t imgtool::stream::transfer(imgtool::stream &dest, imgtool::stream &sourc // transfer_all //------------------------------------------------- -uint64_t imgtool::stream::transfer_all(imgtool::stream &dest, imgtool::stream &source) +uint64_t stream::transfer_all(stream &dest, stream &source) { return transfer(dest, source, source.size()); } @@ -417,7 +576,7 @@ uint64_t imgtool::stream::transfer_all(imgtool::stream &dest, imgtool::stream &s // crc //------------------------------------------------- -int imgtool::stream::crc(unsigned long *result) +int stream::crc(unsigned long *result) { size_t sz; void *ptr; @@ -451,12 +610,12 @@ int imgtool::stream::crc(unsigned long *result) // file_crc //------------------------------------------------- -int imgtool::stream::file_crc(const char *fname, unsigned long *result) +int stream::file_crc(const char *fname, unsigned long *result) { int err; - imgtool::stream::ptr f; + stream::ptr f; - f = imgtool::stream::open(fname, OSD_FOPEN_READ); + f = stream::open(fname, OSD_FOPEN_READ); if (!f) return IMGTOOLERR_FILENOTFOUND; @@ -469,7 +628,7 @@ int imgtool::stream::file_crc(const char *fname, unsigned long *result) // fill //------------------------------------------------- -uint64_t imgtool::stream::fill(unsigned char b, uint64_t sz) +uint64_t stream::fill(unsigned char b, uint64_t sz) { uint64_t outsz; char buf[1024]; @@ -490,7 +649,7 @@ uint64_t imgtool::stream::fill(unsigned char b, uint64_t sz) // is_read_only //------------------------------------------------- -bool imgtool::stream::is_read_only() +bool stream::is_read_only() { return write_protect; } @@ -500,7 +659,7 @@ bool imgtool::stream::is_read_only() // putc //------------------------------------------------- -uint32_t imgtool::stream::putc(char c) +uint32_t stream::putc(char c) { return write(&c, 1); } @@ -510,7 +669,7 @@ uint32_t imgtool::stream::putc(char c) // puts //------------------------------------------------- -uint32_t imgtool::stream::puts(const char *s) +uint32_t stream::puts(const char *s) { return write(s, strlen(s)); } @@ -520,7 +679,7 @@ uint32_t imgtool::stream::puts(const char *s) // printf //------------------------------------------------- -uint32_t imgtool::stream::printf(const char *fmt, ...) +uint32_t stream::printf(const char *fmt, ...) { va_list va; char buf[256]; @@ -531,3 +690,5 @@ uint32_t imgtool::stream::printf(const char *fmt, ...) return puts(buf); } + +} // namespace imgtool diff --git a/src/tools/imgtool/stream.h b/src/tools/imgtool/stream.h index 73d0dcb494d..e7cfca9e425 100644 --- a/src/tools/imgtool/stream.h +++ b/src/tools/imgtool/stream.h @@ -7,78 +7,91 @@ Code for implementing Imgtool streams ***************************************************************************/ +#ifndef MAME_TOOLS_IMGTOOL_STREAM_H +#define MAME_TOOLS_IMGTOOL_STREAM_H -#ifndef STREAM_H -#define STREAM_H +#pragma once #include "imgterrs.h" -#include "corefile.h" + +#include "utilfwd.h" + #include "osdcomm.h" -namespace imgtool +#include +#include +#include + + +namespace imgtool { + +class stream { - class stream +public: + typedef std::unique_ptr ptr; + + ~stream(); + + static imgtool::stream::ptr open(const std::string &filename, int read_or_write); /* similar params to mame_fopen */ + static imgtool::stream::ptr open_write_stream(int filesize); + static imgtool::stream::ptr open_mem(void *buf, size_t sz); + + util::core_file *core_file(); + uint32_t read(void *buf, uint32_t sz); + uint32_t write(const void *buf, uint32_t sz); + uint64_t size() const; + int seek(int64_t pos, int where); + uint64_t tell(); + void *getptr(); + uint32_t putc(char c); + uint32_t puts(const char *s); + uint32_t printf(const char *fmt, ...) ATTR_PRINTF(2, 3); + + // transfers sz bytes from source to dest + static uint64_t transfer(imgtool::stream &dest, imgtool::stream &source, uint64_t sz); + static uint64_t transfer_all(imgtool::stream &dest, imgtool::stream &source); + + // fills sz bytes with b + uint64_t fill(unsigned char b, uint64_t sz); + + // returns the CRC of a file + int crc(unsigned long *result); + static int file_crc(const char *fname, unsigned long *result); + + // returns whether a stream is read only or not + bool is_read_only(); + +private: + enum imgtype_t { - public: - typedef std::unique_ptr ptr; - - ~stream(); - - static imgtool::stream::ptr open(const std::string &filename, int read_or_write); /* similar params to mame_fopen */ - static imgtool::stream::ptr open_write_stream(int filesize); - static imgtool::stream::ptr open_mem(void *buf, size_t sz); - - util::core_file *core_file(); - uint32_t read(void *buf, uint32_t sz); - uint32_t write(const void *buf, uint32_t sz); - uint64_t size() const; - int seek(int64_t pos, int where); - uint64_t tell(); - void *getptr(); - uint32_t putc(char c); - uint32_t puts(const char *s); - uint32_t printf(const char *fmt, ...) ATTR_PRINTF(2, 3); - - // transfers sz bytes from source to dest - static uint64_t transfer(imgtool::stream &dest, imgtool::stream &source, uint64_t sz); - static uint64_t transfer_all(imgtool::stream &dest, imgtool::stream &source); - - // fills sz bytes with b - uint64_t fill(unsigned char b, uint64_t sz); - - // returns the CRC of a file - int crc(unsigned long *result); - static int file_crc(const char *fname, unsigned long *result); - - // returns whether a stream is read only or not - bool is_read_only(); - - private: - enum imgtype_t - { - IMG_FILE, - IMG_MEM - }; - - imgtype_t imgtype; - bool write_protect; - std::uint64_t position; - std::uint64_t filesize; - - util::core_file::ptr file; - std::uint8_t *buffer; - - // ctors - stream(bool wp); - stream(bool wp, util::core_file::ptr &&f); - stream(bool wp, std::size_t size); - stream(bool wp, std::size_t size, void *buf); - - // private methods - static stream::ptr open_zip(const std::string &zipname, const char *subname, int read_or_write); + IMG_FILE, + IMG_MEM }; -} + imgtype_t imgtype; + bool write_protect; + std::uint64_t position; + std::uint64_t filesize; + + std::unique_ptr file; + std::uint8_t *buffer; + + // ctors + stream(bool wp); + stream(bool wp, std::unique_ptr &&f); + stream(bool wp, std::size_t size); + stream(bool wp, std::size_t size, void *buf); + + // private methods + static stream::ptr open_zip(const std::string &zipname, const char *subname, int read_or_write); +}; + + +std::unique_ptr stream_read(stream::ptr &&s, std::uint8_t filler) noexcept; +std::unique_ptr stream_read(stream &s, std::uint8_t filler) noexcept; +std::unique_ptr stream_read_write(stream::ptr &&s, std::uint8_t filler) noexcept; +std::unique_ptr stream_read_write(stream &s, std::uint8_t filler) noexcept; +} // namespace imgtool -#endif /* STREAM_H */ +#endif // MAME_TOOLS_IMGTOOL_STREAM_H diff --git a/src/tools/ldresample.cpp b/src/tools/ldresample.cpp index a7dd165c2f9..f7c5fc8b923 100644 --- a/src/tools/ldresample.cpp +++ b/src/tools/ldresample.cpp @@ -8,17 +8,18 @@ ****************************************************************************/ -#include -#include -#include -#include -#include -#include +#include "avhuff.h" #include "bitmap.h" #include "chd.h" -#include "avhuff.h" #include "vbiparse.h" +#include +#include +#include +#include +#include +#include + //************************************************************************** @@ -156,22 +157,22 @@ inline uint32_t sample_number_to_field(const movie_info &info, uint32_t samplenu // information about it //------------------------------------------------- -static chd_error open_chd(chd_file &file, const char *filename, movie_info &info) +static std::error_condition open_chd(chd_file &file, const char *filename, movie_info &info) { // open the file - chd_error chderr = file.open(filename); - if (chderr != CHDERR_NONE) + std::error_condition chderr = file.open(filename); + if (chderr) { - fprintf(stderr, "Error opening CHD file: %s\n", chd_file::error_string(chderr)); + fprintf(stderr, "Error opening CHD file: %s\n", chderr.message().c_str()); return chderr; } // get the metadata std::string metadata; chderr = file.read_metadata(AV_METADATA_TAG, 0, metadata); - if (chderr != CHDERR_NONE) + if (chderr) { - fprintf(stderr, "Error getting A/V metadata: %s\n", chd_file::error_string(chderr)); + fprintf(stderr, "Error getting A/V metadata: %s\n", chderr.message().c_str()); return chderr; } @@ -180,7 +181,7 @@ static chd_error open_chd(chd_file &file, const char *filename, movie_info &info if (sscanf(metadata.c_str(), AV_METADATA_FORMAT, &fps, &fpsfrac, &width, &height, &interlaced, &channels, &rate) != 7) { fprintf(stderr, "Improperly formatted metadata\n"); - return CHDERR_INVALID_DATA; + return chd_file::error::INVALID_METADATA; } // extract movie info @@ -197,7 +198,7 @@ static chd_error open_chd(chd_file &file, const char *filename, movie_info &info info.bitmap.resize(info.width, info.height); info.lsound.resize(info.samplerate); info.rsound.resize(info.samplerate); - return CHDERR_NONE; + return std::error_condition(); } @@ -205,28 +206,28 @@ static chd_error open_chd(chd_file &file, const char *filename, movie_info &info // create_chd - create a new CHD file //------------------------------------------------- -static chd_error create_chd(chd_file_compressor &file, const char *filename, chd_file &source, const movie_info &info) +static std::error_condition create_chd(chd_file_compressor &file, const char *filename, chd_file &source, const movie_info &info) { // create the file chd_codec_type compression[4] = { CHD_CODEC_AVHUFF }; - chd_error chderr = file.create(filename, source.logical_bytes(), source.hunk_bytes(), source.unit_bytes(), compression); - if (chderr != CHDERR_NONE) + std::error_condition chderr = file.create(filename, source.logical_bytes(), source.hunk_bytes(), source.unit_bytes(), compression); + if (chderr) { - fprintf(stderr, "Error creating new CHD file: %s\n", chd_file::error_string(chderr)); + fprintf(stderr, "Error creating new CHD file: %s\n", chderr.message().c_str()); return chderr; } // clone the metadata chderr = file.clone_all_metadata(source); - if (chderr != CHDERR_NONE) + if (chderr) { - fprintf(stderr, "Error cloning metadata: %s\n", chd_file::error_string(chderr)); + fprintf(stderr, "Error cloning metadata: %s\n", chderr.message().c_str()); return chderr; } // begin compressing file.compress_begin(); - return CHDERR_NONE; + return std::error_condition(); } @@ -248,8 +249,8 @@ static bool read_chd(chd_file &file, uint32_t field, movie_info &info, uint32_t file.codec_configure(CHD_CODEC_AVHUFF, AVHUFF_CODEC_DECOMPRESS_CONFIG, &avconfig); // read the field - chd_error chderr = file.read_hunk(field, nullptr); - return (chderr == CHDERR_NONE); + std::error_condition chderr = file.read_hunk(field, nullptr); + return !chderr; } @@ -524,8 +525,8 @@ int main(int argc, char *argv[]) // open the source file chd_file srcfile; movie_info info; - chd_error err = open_chd(srcfile, srcfilename, info); - if (err != CHDERR_NONE) + std::error_condition err = open_chd(srcfile, srcfilename, info); + if (err) { fprintf(stderr, "Unable to open file '%s'\n", srcfilename); return 1; @@ -563,7 +564,7 @@ int main(int argc, char *argv[]) // loop over all the fields in the source file double progress, ratio; osd_ticks_t last_update = 0; - while (dstfile.compress_continue(progress, ratio) == CHDERR_COMPRESSING) + while (dstfile.compress_continue(progress, ratio) == chd_file::error::COMPRESSING) if (osd_ticks() - last_update > osd_ticks_per_second() / 4) { last_update = osd_ticks(); diff --git a/src/tools/ldverify.cpp b/src/tools/ldverify.cpp index e8df214734c..bb95c3fbad4 100644 --- a/src/tools/ldverify.cpp +++ b/src/tools/ldverify.cpp @@ -8,18 +8,19 @@ ****************************************************************************/ -#include -#include -#include -#include -#include -#include "coretmpl.h" -#include "aviio.h" #include "avhuff.h" +#include "aviio.h" #include "bitmap.h" #include "chd.h" +#include "coretmpl.h" #include "vbiparse.h" +#include +#include +#include +#include +#include + //************************************************************************** @@ -174,10 +175,10 @@ static void *open_chd(const char *filename, movie_info &info) auto chd = new chd_file; // open the file - chd_error chderr = chd->open(filename); - if (chderr != CHDERR_NONE) + std::error_condition chderr = chd->open(filename); + if (chderr) { - fprintf(stderr, "Error opening CHD file: %s\n", chd_file::error_string(chderr)); + fprintf(stderr, "Error opening CHD file: %s\n", chderr.message().c_str()); delete chd; return nullptr; } @@ -185,9 +186,9 @@ static void *open_chd(const char *filename, movie_info &info) // get the metadata std::string metadata; chderr = chd->read_metadata(AV_METADATA_TAG, 0, metadata); - if (chderr != CHDERR_NONE) + if (chderr) { - fprintf(stderr, "Error getting A/V metadata: %s\n", chd_file::error_string(chderr)); + fprintf(stderr, "Error getting A/V metadata: %s\n", chderr.message().c_str()); delete chd; return nullptr; } @@ -251,8 +252,8 @@ static int read_chd(void *file, int frame, bitmap_yuy16 &bitmap, int16_t *lsound chdfile->codec_configure(CHD_CODEC_AVHUFF, AVHUFF_CODEC_DECOMPRESS_CONFIG, &avconfig); // read the frame - chd_error chderr = chdfile->read_hunk(frame * interlace_factor + fieldnum, nullptr); - if (chderr != CHDERR_NONE) + std::error_condition chderr = chdfile->read_hunk(frame * interlace_factor + fieldnum, nullptr); + if (chderr) return false; // account for samples read diff --git a/src/tools/pngcmp.cpp b/src/tools/pngcmp.cpp index 43fc9324a06..624023425af 100644 --- a/src/tools/pngcmp.cpp +++ b/src/tools/pngcmp.cpp @@ -73,15 +73,15 @@ static int generate_png_diff(const std::string& imgfile1, const std::string& img bitmap_argb32 finalbitmap; int width, height, maxwidth; util::core_file::ptr file; - osd_file::error filerr; + std::error_condition filerr; util::png_error pngerr; int error = 100; /* open the source image */ filerr = util::core_file::open(imgfile1, OPEN_FLAG_READ, file); - if (filerr != osd_file::error::NONE) + if (filerr) { - printf("Could not open %s (%d)\n", imgfile1.c_str(), int(filerr)); + printf("Could not open %s (%s)\n", imgfile1.c_str(), filerr.message().c_str()); goto error; } @@ -96,9 +96,9 @@ static int generate_png_diff(const std::string& imgfile1, const std::string& img /* open the source image */ filerr = util::core_file::open(imgfile2, OPEN_FLAG_READ, file); - if (filerr != osd_file::error::NONE) + if (filerr) { - printf("Could not open %s (%d)\n", imgfile2.c_str(), int(filerr)); + printf("Could not open %s (%s)\n", imgfile2.c_str(), filerr.message().c_str()); goto error; } @@ -171,9 +171,9 @@ static int generate_png_diff(const std::string& imgfile1, const std::string& img /* write the final PNG */ filerr = util::core_file::open(outfilename, OPEN_FLAG_WRITE | OPEN_FLAG_CREATE, file); - if (filerr != osd_file::error::NONE) + if (filerr) { - printf("Could not open %s (%d)\n", outfilename.c_str(), int(filerr)); + printf("Could not open %s (%s)\n", outfilename.c_str(), filerr.message().c_str()); goto error; } pngerr = util::png_write_bitmap(*file, nullptr, finalbitmap, 0, nullptr); diff --git a/src/tools/regrep.cpp b/src/tools/regrep.cpp index a8877c54899..b0072accfab 100644 --- a/src/tools/regrep.cpp +++ b/src/tools/regrep.cpp @@ -239,7 +239,7 @@ int main(int argc, char *argv[]) /* read the template file into an astring */ std::string tempheader; - if (util::core_file::load(tempfilename.c_str(), &buffer, bufsize) == osd_file::error::NONE) + if (!util::core_file::load(tempfilename.c_str(), &buffer, bufsize)) { tempheader.assign((const char *)buffer, bufsize); free(buffer); @@ -569,7 +569,7 @@ static util::core_file::ptr create_file_and_output_header(std::string &filename, util::core_file::ptr file; /* create the indexfile */ - if (util::core_file::open(filename, OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS | OPEN_FLAG_NO_BOM, file) != osd_file::error::NONE) + if (util::core_file::open(filename, OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS | OPEN_FLAG_NO_BOM, file)) return util::core_file::ptr(); /* print a header */ @@ -730,7 +730,7 @@ static int compare_screenshots(summary_file *curfile) if (curfile->status[listnum] == STATUS_SUCCESS) { std::string fullname; - osd_file::error filerr; + std::error_condition filerr; util::core_file::ptr file; /* get the filename for the image */ @@ -740,7 +740,7 @@ static int compare_screenshots(summary_file *curfile) filerr = util::core_file::open(fullname, OPEN_FLAG_READ, file); /* if that failed, look in the old location */ - if (filerr != osd_file::error::NONE) + if (filerr) { /* get the filename for the image */ fullname = string_format("%s" PATH_SEPARATOR "snap" PATH_SEPARATOR "_%s.png", lists[listnum].dir, curfile->name); @@ -750,7 +750,7 @@ static int compare_screenshots(summary_file *curfile) } /* if that worked, load the file */ - if (filerr == osd_file::error::NONE) + if (!filerr) { util::png_read_bitmap(*file, bitmaps[listnum]); file.reset(); @@ -838,7 +838,7 @@ static int generate_png_diff(const summary_file *curfile, std::string &destdir, int width, height, maxwidth; int bitmapcount = 0; util::core_file::ptr file; - osd_file::error filerr; + std::error_condition filerr; util::png_error pngerr; int error = -1; int starty; @@ -855,7 +855,7 @@ static int generate_png_diff(const summary_file *curfile, std::string &destdir, /* open the source image */ filerr = util::core_file::open(tempname, OPEN_FLAG_READ, file); - if (filerr != osd_file::error::NONE) + if (filerr) goto error; /* load the source image */ @@ -926,7 +926,7 @@ static int generate_png_diff(const summary_file *curfile, std::string &destdir, /* write the final PNG */ filerr = util::core_file::open(dstfilename, OPEN_FLAG_WRITE | OPEN_FLAG_CREATE, file); - if (filerr != osd_file::error::NONE) + if (filerr) goto error; pngerr = util::png_write_bitmap(*file, nullptr, finalbitmap, 0, nullptr); file.reset(); diff --git a/src/tools/romcmp.cpp b/src/tools/romcmp.cpp index 4862f74a769..b65889c70a1 100644 --- a/src/tools/romcmp.cpp +++ b/src/tools/romcmp.cpp @@ -8,25 +8,20 @@ ***************************************************************************/ +#include "hash.h" +#include "path.h" #include "unzip.h" + #include "osdfile.h" #include "osdcomm.h" -#include "hash.h" #include #include +#include #define MAX_FILES 1000 -#ifndef MAX_FILENAME_LEN -#define MAX_FILENAME_LEN 255 -#endif - -#ifndef PATH_DELIM -#define PATH_DELIM '/' -#endif - /* compare modes when one file is twice as long as the other */ @@ -105,382 +100,383 @@ static void compatiblemodes(int mode,int *start,int *end) struct fileinfo { - char name[MAX_FILENAME_LEN+1]; + std::string name; int size; - unsigned char *buf; /* file is read in here */ + std::unique_ptr buf; // file is read in here int listed; -}; - -static fileinfo files[2][MAX_FILES]; -static float matchscore[MAX_FILES][MAX_FILES][TOTAL_MODES][TOTAL_MODES]; -static bool is_ascii_char(int ch) -{ - return (ch >= 0x20 && ch < 0x7f) || (ch == '\n') || (ch == '\r') || (ch == '\t'); -} - -static void checkintegrity(const fileinfo *file, int side, bool all_hashes) -{ - if (file->buf == nullptr) return; - - if (all_hashes) + static constexpr bool is_ascii_char(int ch) { - util::crc32_creator crc32; - util::sha1_creator sha1; - util::sum16_creator sum16; - crc32.append(file->buf, file->size); - sha1.append(file->buf, file->size); - sum16.append(file->buf, file->size); - printf("%-23s %-23s [0x%x] CRC(%s) SHA1(%s) SUM(%s)\n", (side & 1) ? file->name : "", (side & 2) ? file->name : "", file->size, - crc32.finish().as_string().c_str(), sha1.finish().as_string().c_str(), sum16.finish().as_string().c_str()); - side = 0; + return (ch >= 0x20 && ch < 0x7f) || (ch == '\n') || (ch == '\r') || (ch == '\t'); } - /* check for bad data lines */ - unsigned mask0 = 0x0000; - unsigned mask1 = 0xffff; - bool is_ascii = true; - for (unsigned i = 0; i < file->size; i += 2) + void checkintegrity(int side, bool all_hashes) const { - is_ascii = is_ascii && is_ascii_char(file->buf[i]); - mask0 |= file->buf[i] << 8; - mask1 &= (file->buf[i] << 8) | 0x00ff; - if (i < file->size - 1) + if (!buf) + return; + + if (all_hashes) { - is_ascii = is_ascii && is_ascii_char(file->buf[i+1]); - mask0 |= file->buf[i+1]; - mask1 &= file->buf[i+1] | 0xff00; + util::crc32_creator crc32; + util::sha1_creator sha1; + util::sum16_creator sum16; + crc32.append(buf.get(), size); + sha1.append(buf.get(), size); + sum16.append(buf.get(), size); + printf("%-23s %-23s [0x%x] CRC(%s) SHA1(%s) SUM(%s)\n", + (side & 1) ? name.c_str() : "", + (side & 2) ? name.c_str() : "", + size, + crc32.finish().as_string().c_str(), + sha1.finish().as_string().c_str(), + sum16.finish().as_string().c_str()); + side = 0; } - if (mask0 == 0xffff && mask1 == 0x0000) break; - } - - if (is_ascii && mask0 == 0x7f7f && mask1 == 0) - { - printf("%-23s %-23s ASCII TEXT FILE\n", (side & 1) ? file->name : "", (side & 2) ? file->name : ""); - return; - } - if (mask0 != 0xffff || mask1 != 0x0000) - { - int fixedmask; - int bits; + // check for bad data lines + unsigned mask0 = 0x0000; + unsigned mask1 = 0xffff; - fixedmask = (~mask0 | mask1) & 0xffff; + bool is_ascii = true; + for (unsigned i = 0; i < size; i += 2) + { + is_ascii = is_ascii && is_ascii_char(buf[i]); + mask0 |= buf[i] << 8; + mask1 &= (buf[i] << 8) | 0x00ff; + if (i < size - 1) + { + is_ascii = is_ascii && is_ascii_char(buf[i+1]); + mask0 |= buf[i+1]; + mask1 &= buf[i+1] | 0xff00; + } + if (mask0 == 0xffff && mask1 == 0x0000) break; + } - if (((mask0 >> 8) & 0xff) == (mask0 & 0xff) && ((mask1 >> 8) & 0xff) == (mask1 & 0xff)) - bits = 8; - else bits = 16; + if (is_ascii && mask0 == 0x7f7f && mask1 == 0) + { + printf("%-23s %-23s ASCII TEXT FILE\n", (side & 1) ? name.c_str() : "", (side & 2) ? name.c_str() : ""); + return; + } - printf("%-23s %-23s FIXED BITS (", (side & 1) ? file->name : "", (side & 2) ? file->name : ""); - for (int i = 0; i < bits; i++) + if (mask0 != 0xffff || mask1 != 0x0000) { - if (~mask0 & 0x8000) printf("0"); - else if (mask1 & 0x8000) printf("1"); - else printf("x"); + int fixedmask; + int bits; - mask0 <<= 1; - mask1 <<= 1; - } - printf(")\n"); + fixedmask = (~mask0 | mask1) & 0xffff; - /* if the file contains a fixed value, we don't need to do the other */ - /* validity checks */ - if (fixedmask == 0xffff || fixedmask == 0x00ff || fixedmask == 0xff00) - return; - } + if (((mask0 >> 8) & 0xff) == (mask0 & 0xff) && ((mask1 >> 8) & 0xff) == (mask1 & 0xff)) + bits = 8; + else bits = 16; - unsigned addrbit = 1; - unsigned addrmirror = 0; - while (addrbit <= file->size/2) - { - unsigned i = 0; - for (i = 0; i < file->size; i++) + printf("%-23s %-23s FIXED BITS (", (side & 1) ? name.c_str() : "", (side & 2) ? name.c_str() : ""); + for (int i = 0; i < bits; i++) + { + if (~mask0 & 0x8000) printf("0"); + else if (mask1 & 0x8000) printf("1"); + else printf("x"); + + mask0 <<= 1; + mask1 <<= 1; + } + printf(")\n"); + + /* if the file contains a fixed value, we don't need to do the other */ + /* validity checks */ + if (fixedmask == 0xffff || fixedmask == 0x00ff || fixedmask == 0xff00) + return; + } + + unsigned addrbit = 1; + unsigned addrmirror = 0; + while (addrbit <= size/2) { - if ((i ^ addrbit) < file->size && file->buf[i] != file->buf[i ^ addrbit]) break; + unsigned i = 0; + for (i = 0; i < size; i++) + { + if ((i ^ addrbit) < size && buf[i] != buf[i ^ addrbit]) break; + } + + if (i == size) + addrmirror |= addrbit; + + addrbit <<= 1; } - if (i == file->size) - addrmirror |= addrbit; + if (addrmirror != 0) + { + if (addrmirror == size/2) + { + printf("%-23s %-23s 1ST AND 2ND HALF IDENTICAL\n", (side & 1) ? name.c_str() : "", (side & 2) ? name.c_str() : ""); + util::hash_collection hash; + hash.begin(); + hash.buffer(buf.get(), size / 2); + hash.end(); + printf("%-23s %-23s %s\n", (side & 1) ? name.c_str() : "", (side & 2) ? name.c_str() : "", hash.attribute_string().c_str()); + } + else + { + printf("%-23s %-23s BADADDR", (side & 1) ? name.c_str() : "", (side & 2) ? name.c_str() : ""); + for (int i = 0; i < 24; i++) + { + if (size <= (1<<(23-i))) printf(" "); + else if (addrmirror & 0x800000) printf("-"); + else printf("x"); + addrmirror <<= 1; + } + printf("\n"); + } + return; + } - addrbit <<= 1; - } + unsigned sizemask = 1; + while (sizemask < size - 1) + sizemask = (sizemask << 1) | 1; - if (addrmirror != 0) - { - if (addrmirror == file->size/2) + mask0 = 0x000000; + mask1 = sizemask; + for (unsigned i = 0; i < size; i++) { - printf("%-23s %-23s 1ST AND 2ND HALF IDENTICAL\n", (side & 1) ? file->name : "", (side & 2) ? file->name : ""); - util::hash_collection hash; - hash.begin(); - hash.buffer(file->buf, file->size / 2); - hash.end(); - printf("%-23s %-23s %s\n", (side & 1) ? file->name : "", (side & 2) ? file->name : "", hash.attribute_string().c_str()); + if (buf[i] != 0xff) + { + mask0 |= i; + mask1 &= i; + if (mask0 == sizemask && mask1 == 0x00) break; + } } - else + + if (mask0 != sizemask || mask1 != 0x00) { - printf("%-23s %-23s BADADDR", (side & 1) ? file->name : "", (side & 2) ? file->name : ""); + printf("%-23s %-23s ", (side & 1) ? name.c_str() : "", (side & 2) ? name.c_str() : ""); for (int i = 0; i < 24; i++) { - if (file->size <= (1<<(23-i))) printf(" "); - else if (addrmirror & 0x800000) printf("-"); + if (size <= (1<<(23-i))) printf(" "); + else if (~mask0 & 0x800000) printf("1"); + else if (mask1 & 0x800000) printf("0"); else printf("x"); - addrmirror <<= 1; + mask0 <<= 1; + mask1 <<= 1; } - printf("\n"); + printf(" = 0xFF\n"); + + return; } - return; - } - unsigned sizemask = 1; - while (sizemask < file->size - 1) - sizemask = (sizemask << 1) | 1; - mask0 = 0x000000; - mask1 = sizemask; - for (unsigned i = 0; i < file->size; i++) - { - if (file->buf[i] != 0xff) + mask0 = 0x000000; + mask1 = sizemask; + for (unsigned i = 0; i < size; i++) { - mask0 |= i; - mask1 &= i; - if (mask0 == sizemask && mask1 == 0x00) break; + if (buf[i] != 0x00) + { + mask0 |= i; + mask1 &= i; + if (mask0 == sizemask && mask1 == 0x00) break; + } } - } - if (mask0 != sizemask || mask1 != 0x00) - { - printf("%-23s %-23s ", (side & 1) ? file->name : "", (side & 2) ? file->name : ""); - for (int i = 0; i < 24; i++) + if (mask0 != sizemask || mask1 != 0x00) { - if (file->size <= (1<<(23-i))) printf(" "); - else if (~mask0 & 0x800000) printf("1"); - else if (mask1 & 0x800000) printf("0"); - else printf("x"); - mask0 <<= 1; - mask1 <<= 1; - } - printf(" = 0xFF\n"); - - return; - } + printf("%-23s %-23s ", (side & 1) ? name.c_str() : "", (side & 2) ? name.c_str() : ""); + for (int i = 0; i < 24; i++) + { + if (size <= (1<<(23-i))) printf(" "); + else if ((mask0 & 0x800000) == 0) printf("1"); + else if (mask1 & 0x800000) printf("0"); + else printf("x"); + mask0 <<= 1; + mask1 <<= 1; + } + printf(" = 0x00\n"); + return; + } - mask0 = 0x000000; - mask1 = sizemask; - for (unsigned i = 0; i < file->size; i++) - { - if (file->buf[i] != 0x00) + mask0 = 0xff; + for (unsigned i = 0; i < size/4 && mask0 != 0x00; i++) { - mask0 |= i; - mask1 &= i; - if (mask0 == sizemask && mask1 == 0x00) break; + if (buf[ 2*i ] != 0x00) mask0 &= ~0x01; + if (buf[ 2*i ] != 0xff) mask0 &= ~0x02; + if (buf[ 2*i+1] != 0x00) mask0 &= ~0x04; + if (buf[ 2*i+1] != 0xff) mask0 &= ~0x08; + if (buf[size/2 + 2*i ] != 0x00) mask0 &= ~0x10; + if (buf[size/2 + 2*i ] != 0xff) mask0 &= ~0x20; + if (buf[size/2 + 2*i+1] != 0x00) mask0 &= ~0x40; + if (buf[size/2 + 2*i+1] != 0xff) mask0 &= ~0x80; } + + if (mask0 & 0x01) printf("%-23s %-23s 1ST HALF = 00xx\n", (side & 1) ? name.c_str() : "", (side & 2) ? name.c_str() : ""); + if (mask0 & 0x02) printf("%-23s %-23s 1ST HALF = FFxx\n", (side & 1) ? name.c_str() : "", (side & 2) ? name.c_str() : ""); + if (mask0 & 0x04) printf("%-23s %-23s 1ST HALF = xx00\n", (side & 1) ? name.c_str() : "", (side & 2) ? name.c_str() : ""); + if (mask0 & 0x08) printf("%-23s %-23s 1ST HALF = xxFF\n", (side & 1) ? name.c_str() : "", (side & 2) ? name.c_str() : ""); + if (mask0 & 0x10) printf("%-23s %-23s 2ND HALF = 00xx\n", (side & 1) ? name.c_str() : "", (side & 2) ? name.c_str() : ""); + if (mask0 & 0x20) printf("%-23s %-23s 2ND HALF = FFxx\n", (side & 1) ? name.c_str() : "", (side & 2) ? name.c_str() : ""); + if (mask0 & 0x40) printf("%-23s %-23s 2ND HALF = xx00\n", (side & 1) ? name.c_str() : "", (side & 2) ? name.c_str() : ""); + if (mask0 & 0x80) printf("%-23s %-23s 2ND HALF = xxFF\n", (side & 1) ? name.c_str() : "", (side & 2) ? name.c_str() : ""); } - if (mask0 != sizemask || mask1 != 0x00) + int usedbytes(int mode) const { - printf("%-23s %-23s ", (side & 1) ? file->name : "", (side & 2) ? file->name : ""); - for (int i = 0; i < 24; i++) + switch (mode) { - if (file->size <= (1<<(23-i))) printf(" "); - else if ((mask0 & 0x800000) == 0) printf("1"); - else if (mask1 & 0x800000) printf("0"); - else printf("x"); - mask0 <<= 1; - mask1 <<= 1; + case MODE_A: + case MODE_NIB1: + case MODE_NIB2: + return size; + case MODE_12: + case MODE_22: + case MODE_E: + case MODE_O: + return size / 2; + case MODE_14: + case MODE_24: + case MODE_34: + case MODE_44: + case MODE_E12: + case MODE_O12: + case MODE_E22: + case MODE_O22: + return size / 4; + default: + return 0; } - printf(" = 0x00\n"); - - return; } - mask0 = 0xff; - for (unsigned i = 0; i < file->size/4 && mask0 != 0x00; i++) + void basemultmask(int mode, int &base, int &mult, int &mask) const { - if (file->buf[ 2*i ] != 0x00) mask0 &= ~0x01; - if (file->buf[ 2*i ] != 0xff) mask0 &= ~0x02; - if (file->buf[ 2*i+1] != 0x00) mask0 &= ~0x04; - if (file->buf[ 2*i+1] != 0xff) mask0 &= ~0x08; - if (file->buf[file->size/2 + 2*i ] != 0x00) mask0 &= ~0x10; - if (file->buf[file->size/2 + 2*i ] != 0xff) mask0 &= ~0x20; - if (file->buf[file->size/2 + 2*i+1] != 0x00) mask0 &= ~0x40; - if (file->buf[file->size/2 + 2*i+1] != 0xff) mask0 &= ~0x80; - } + mult = 1; + if (mode >= MODE_E) + mult = 2; - if (mask0 & 0x01) printf("%-23s %-23s 1ST HALF = 00xx\n", (side & 1) ? file->name : "", (side & 2) ? file->name : ""); - if (mask0 & 0x02) printf("%-23s %-23s 1ST HALF = FFxx\n", (side & 1) ? file->name : "", (side & 2) ? file->name : ""); - if (mask0 & 0x04) printf("%-23s %-23s 1ST HALF = xx00\n", (side & 1) ? file->name : "", (side & 2) ? file->name : ""); - if (mask0 & 0x08) printf("%-23s %-23s 1ST HALF = xxFF\n", (side & 1) ? file->name : "", (side & 2) ? file->name : ""); - if (mask0 & 0x10) printf("%-23s %-23s 2ND HALF = 00xx\n", (side & 1) ? file->name : "", (side & 2) ? file->name : ""); - if (mask0 & 0x20) printf("%-23s %-23s 2ND HALF = FFxx\n", (side & 1) ? file->name : "", (side & 2) ? file->name : ""); - if (mask0 & 0x40) printf("%-23s %-23s 2ND HALF = xx00\n", (side & 1) ? file->name : "", (side & 2) ? file->name : ""); - if (mask0 & 0x80) printf("%-23s %-23s 2ND HALF = xxFF\n", (side & 1) ? file->name : "", (side & 2) ? file->name : ""); -} - - -static int usedbytes(const fileinfo *file,int mode) -{ - switch (mode) - { - case MODE_A: - case MODE_NIB1: - case MODE_NIB2: - return file->size; - case MODE_12: - case MODE_22: - case MODE_E: - case MODE_O: - return file->size / 2; - case MODE_14: - case MODE_24: - case MODE_34: - case MODE_44: - case MODE_E12: - case MODE_O12: - case MODE_E22: - case MODE_O22: - return file->size / 4; - default: - return 0; + switch (mode) + { + case MODE_A: + case MODE_12: + case MODE_14: + case MODE_E: + case MODE_E12: + base = 0; mask = 0xff; break; + case MODE_NIB1: + base = 0; mask = 0x0f; break; + case MODE_NIB2: + base = 0; mask = 0xf0; break; + case MODE_O: + case MODE_O12: + base = 1; mask = 0xff; break; + case MODE_22: + case MODE_E22: + base = size / 2; mask = 0xff; break; + case MODE_O22: + base = 1 + size / 2; mask = 0xff; break; + case MODE_24: + base = size / 4; mask = 0xff; break; + case MODE_34: + base = 2*size / 4; mask = 0xff; break; + case MODE_44: + base = 3*size / 4; mask = 0xff; break; + } } -} - -static void basemultmask(const fileinfo *file,int mode,int *base,int *mult,int *mask) -{ - *mult = 1; - if (mode >= MODE_E) *mult = 2; - switch (mode) + float compare(const fileinfo &file2, int mode1, int mode2) const { - case MODE_A: - case MODE_12: - case MODE_14: - case MODE_E: - case MODE_E12: - *base = 0; *mask = 0xff; break; - case MODE_NIB1: - *base = 0; *mask = 0x0f; break; - case MODE_NIB2: - *base = 0; *mask = 0xf0; break; - case MODE_O: - case MODE_O12: - *base = 1; *mask = 0xff; break; - case MODE_22: - case MODE_E22: - *base = file->size / 2; *mask = 0xff; break; - case MODE_O22: - *base = 1 + file->size / 2; *mask = 0xff; break; - case MODE_24: - *base = file->size / 4; *mask = 0xff; break; - case MODE_34: - *base = 2*file->size / 4; *mask = 0xff; break; - case MODE_44: - *base = 3*file->size / 4; *mask = 0xff; break; - } -} - -static float filecompare(const fileinfo *file1,const fileinfo *file2,int mode1,int mode2) -{ - int i; - int match = 0; - int size1,size2; - int base1=0,base2=0,mult1=0,mult2=0,mask1=0,mask2=0; + if (!buf || !file2.buf) + return 0.0; + int const size1 = usedbytes(mode1); + int const size2 = file2.usedbytes(mode2); - if (file1->buf == nullptr || file2->buf == nullptr) return 0.0; + if (size1 != size2) + return 0.0; - size1 = usedbytes(file1,mode1); - size2 = usedbytes(file2,mode2); + int base1=0, base2=0, mult1=0, mult2=0, mask1=0, mask2=0; + basemultmask(mode1, base1, mult1, mask1); + file2.basemultmask(mode2, base2, mult2, mask2); - if (size1 != size2) return 0.0; - - basemultmask(file1,mode1,&base1,&mult1,&mask1); - basemultmask(file2,mode2,&base2,&mult2,&mask2); - - if (mask1 == mask2) - { - if (mask1 == 0xff) - { - /* normal compare */ - for (i = 0;i < size1;i++) - if (file1->buf[base1 + mult1 * i] == file2->buf[base2 + mult2 * i]) match++; - } - else + int match = 0; + if (mask1 == mask2) { - /* nibble compare, abort if other half is not empty */ - for (i = 0;i < size1;i++) + if (mask1 == 0xff) + { + // normal compare + for (int i = 0; i < size1; i++) + if (buf[base1 + mult1 * i] == file2.buf[base2 + mult2 * i]) match++; + } + else { - if (((file1->buf[base1 + mult1 * i] & ~mask1) != (0x00 & ~mask1) && - (file1->buf[base1 + mult1 * i] & ~mask1) != (0xff & ~mask1)) || - ((file2->buf[base1 + mult1 * i] & ~mask2) != (0x00 & ~mask2) && - (file2->buf[base1 + mult1 * i] & ~mask2) != (0xff & ~mask2))) + // nibble compare, abort if other half is not empty + for (int i = 0; i < size1; i++) { - match = 0; - break; + if (((buf[base1 + mult1 * i] & ~mask1) != (0x00 & ~mask1) && + (buf[base1 + mult1 * i] & ~mask1) != (0xff & ~mask1)) || + ((file2.buf[base1 + mult1 * i] & ~mask2) != (0x00 & ~mask2) && + (file2.buf[base1 + mult1 * i] & ~mask2) != (0xff & ~mask2))) + { + match = 0; + break; + } + if ((buf[base1 + mult1 * i] & mask1) == (file2.buf[base2 + mult2 * i] & mask2)) match++; } - if ((file1->buf[base1 + mult1 * i] & mask1) == (file2->buf[base2 + mult2 * i] & mask2)) match++; } } - } - return (float)match / size1; -} + return float(match) / size1; + } + void readfile(const char *path) + { + std::string fullname(path ? path : ""); + util::path_append(fullname, name); -static void readfile(const char *path,fileinfo *file) -{ - osd_file::error filerr; - uint64_t filesize; - uint32_t actual; - char fullname[256]; - osd_file::ptr f; + buf.reset(new (std::nothrow) unsigned char [size]); + if (!buf) + { + printf("%s: out of memory!\n", name.c_str()); + return; + } - if (path) - { - char delim[2] = { PATH_DELIM, '\0' }; - strcpy(fullname,path); - strcat(fullname,delim); - } - else fullname[0] = 0; - strcat(fullname,file->name); + std::error_condition filerr; + osd_file::ptr f; + uint64_t filesize; - if ((file->buf = (unsigned char *)malloc(file->size)) == nullptr) - { - printf("%s: out of memory!\n",file->name); - return; - } + filerr = osd_file::open(fullname, OPEN_FLAG_READ, f, filesize); + if (filerr) + { + printf("%s: error %s\n", fullname.c_str(), filerr.message().c_str()); + return; + } - filerr = osd_file::open(fullname, OPEN_FLAG_READ, f, filesize); - if (filerr != osd_file::error::NONE) - { - printf("%s: error %d\n", fullname, int(filerr)); - return; + uint32_t actual; + filerr = f->read(buf.get(), 0, size, actual); + if (filerr) + { + printf("%s: error %s\n", fullname.c_str(), filerr.message().c_str()); + return; + } } - filerr = f->read(file->buf, 0, file->size, actual); - if (filerr != osd_file::error::NONE) + void free() { - printf("%s: error %d\n", fullname, int(filerr)); - return; + buf.reset(); } -} - +}; -static void freefile(fileinfo *file) -{ - free(file->buf); - file->buf = nullptr; -} +static fileinfo files[2][MAX_FILES]; +static float matchscore[MAX_FILES][MAX_FILES][TOTAL_MODES][TOTAL_MODES]; -static void printname(const fileinfo *file1,const fileinfo *file2,float score,int mode1,int mode2) +static void printname(const fileinfo *file1, const fileinfo *file2, float score, int mode1, int mode2) { - printf("%-12s %s %-12s %s ",file1 ? file1->name : "",modenames[mode1],file2 ? file2->name : "",modenames[mode2]); + printf( + "%-12s %s %-12s %s ", + file1 ? file1->name.c_str() : "", + modenames[mode1], + file2 ? file2->name.c_str() : "", + modenames[mode2]); if (score == 0.0f) printf("NO MATCH\n"); else if (score == 1.0f) printf("IDENTICAL\n"); - else printf("%3.6f%%\n",(double) (score*100)); + else printf("%3.6f%%\n", double(score*100)); } @@ -496,24 +492,23 @@ static int load_files(int i, int *found, const char *path) while ((d = dir->read()) != nullptr) { const char *d_name = d->name; - char buf[255+1]; + const std::string buf(util::path_concat(path, d_name)); // FIXME: is this even used for anything? - sprintf(buf, "%s%c%s", path, PATH_DELIM, d_name); if (d->type == osd::directory::entry::entry_type::FILE) { uint64_t size = d->size; while (size && (size & 1) == 0) size >>= 1; //if (size & ~1) - // printf("%-23s %-23s ignored (not a ROM)\n",i ? "" : d_name,i ? d_name : ""); + // printf("%-23s %-23s ignored (not a ROM)\n", i ? "" : d_name, i ? d_name : ""); //else { - strcpy(files[i][found[i]].name,d_name); + files[i][found[i]].name = d_name; files[i][found[i]].size = d->size; - readfile(path,&files[i][found[i]]); + files[i][found[i]].readfile(path); files[i][found[i]].listed = 0; if (found[i] >= MAX_FILES) { - printf("%s: max of %d files exceeded\n",path,MAX_FILES); + printf("%s: max of %d files exceeded\n", path, MAX_FILES); break; } found[i]++; @@ -522,15 +517,13 @@ static int load_files(int i, int *found, const char *path) } dir.reset(); } - - /* if not, try to open as a ZIP file */ else { + /* if not, try to open as a ZIP file */ util::archive_file::ptr zip; /* wasn't a directory, so try to open it as a zip file */ - if ((util::archive_file::open_zip(path, zip) != util::archive_file::error::NONE) && - (util::archive_file::open_7z(path, zip) != util::archive_file::error::NONE)) + if (util::archive_file::open_zip(path, zip) && util::archive_file::open_7z(path, zip)) { printf("Error, cannot open zip file '%s' !\n", path); return 1; @@ -552,26 +545,26 @@ static int load_files(int i, int *found, const char *path) } else { - fileinfo *file = &files[i][found[i]]; + fileinfo &file = files[i][found[i]]; const char *delim = strrchr(zip->current_name().c_str(), '/'); if (delim) - strcpy (file->name,delim+1); + file.name = delim + 1; else - strcpy(file->name,zip->current_name().c_str()); - file->size = zip->current_uncompressed_length(); - if ((file->buf = (unsigned char *)malloc(file->size)) == nullptr) - printf("%s: out of memory!\n",file->name); + file.name = zip->current_name(); + file.size = zip->current_uncompressed_length(); + file.buf.reset(new (std::nothrow) unsigned char [file.size]); + if (!file.buf) + { + printf("%s: out of memory!\n", file.name.c_str()); + } else { - if (zip->decompress(file->buf, file->size) != util::archive_file::error::NONE) - { - free(file->buf); - file->buf = nullptr; - } + if (zip->decompress(file.buf.get(), file.size)) + file.free(); } - file->listed = 0; + file.listed = 0; if (found[i] >= MAX_FILES) { printf("%s: max of %d files exceeded\n",path,MAX_FILES); @@ -612,13 +605,8 @@ int CLIB_DECL main(int argc,char *argv[]) } { - int found[2]; - int i,j,mode1,mode2; - int besti,bestj; - - - found[0] = found[1] = 0; - for (i = 0;i < 2;i++) + int found[2] = { 0, 0 }; + for (int i = 0; i < 2; i++) { if (argc > i+1) { @@ -633,26 +621,26 @@ int CLIB_DECL main(int argc,char *argv[]) else printf("%d files\n",found[0]); - for (i = 0; i < 2; i++) + for (int i = 0; i < 2; i++) { - for (j = 0; j < found[i]; j++) + for (int j = 0; j < found[i]; j++) { - checkintegrity(&files[i][j], 1 << i, all_hashes); + files[i][j].checkintegrity(1 << i, all_hashes); } } if (argc < 3) { - /* find duplicates in one dir */ - for (i = 0;i < found[0];i++) + // find duplicates in one dir + for (int i = 0;i < found[0];i++) { - for (j = i+1;j < found[0];j++) + for (int j = i+1;j < found[0];j++) { - for (mode1 = 0;mode1 < total_modes;mode1++) + for (int mode1 = 0;mode1 < total_modes;mode1++) { - for (mode2 = 0;mode2 < total_modes;mode2++) + for (int mode2 = 0;mode2 < total_modes;mode2++) { - if (filecompare(&files[0][i],&files[0][j],mode1,mode2) == 1.0f) + if (files[0][i].compare(files[0][j],mode1,mode2) == 1.0f) printname(&files[0][i],&files[0][j],1.0,mode1,mode2); } } @@ -661,40 +649,38 @@ int CLIB_DECL main(int argc,char *argv[]) } else { - /* compare two dirs */ - for (i = 0;i < found[0];i++) + // compare two dirs + for (int i = 0;i < found[0];i++) { - for (j = 0;j < found[1];j++) + for (int j = 0;j < found[1];j++) { fprintf(stderr,"%2d%%\r",100*(i*found[1]+j)/(found[0]*found[1])); - for (mode1 = 0;mode1 < total_modes;mode1++) + for (int mode1 = 0;mode1 < total_modes;mode1++) { - for (mode2 = 0;mode2 < total_modes;mode2++) + for (int mode2 = 0;mode2 < total_modes;mode2++) { - matchscore[i][j][mode1][mode2] = filecompare(&files[0][i],&files[1][j],mode1,mode2); + matchscore[i][j][mode1][mode2] = files[0][i].compare(files[1][j],mode1,mode2); } } } } fprintf(stderr," \r"); + int besti; do { - float bestscore; - int bestmode1,bestmode2; - besti = -1; - bestj = -1; - bestscore = 0.0; - bestmode1 = bestmode2 = -1; + int bestj = -1; + float bestscore = 0.0; + int bestmode1 = -1, bestmode2 = -1; - for (mode1 = 0;mode1 < total_modes;mode1++) + for (int mode1 = 0;mode1 < total_modes;mode1++) { - for (mode2 = 0;mode2 < total_modes;mode2++) + for (int mode2 = 0;mode2 < total_modes;mode2++) { - for (i = 0;i < found[0];i++) + for (int i = 0;i < found[0];i++) { - for (j = 0;j < found[1];j++) + for (int j = 0;j < found[1];j++) { if (matchscore[i][j][mode1][mode2] > bestscore || (matchscore[i][j][mode1][mode2] == 1.0f && mode2 == 0 && bestmode2 > 0)) @@ -721,17 +707,17 @@ int CLIB_DECL main(int argc,char *argv[]) matchscore[besti][bestj][bestmode1][bestmode2] = 0.0; /* remove all matches using the same sections with a worse score */ - for (j = 0;j < found[1];j++) + for (int j = 0;j < found[1];j++) { - for (mode2 = 0;mode2 < total_modes;mode2++) + for (int mode2 = 0;mode2 < total_modes;mode2++) { if (matchscore[besti][j][bestmode1][mode2] < bestscore) matchscore[besti][j][bestmode1][mode2] = 0.0; } } - for (i = 0;i < found[0];i++) + for (int i = 0;i < found[0];i++) { - for (mode1 = 0;mode1 < total_modes;mode1++) + for (int mode1 = 0;mode1 < total_modes;mode1++) { if (matchscore[i][bestj][mode1][bestmode2] < bestscore) matchscore[i][bestj][mode1][bestmode2] = 0.0; @@ -740,49 +726,50 @@ int CLIB_DECL main(int argc,char *argv[]) /* remove all matches using incompatible sections */ compatiblemodes(bestmode1,&start,&end); - for (j = 0;j < found[1];j++) + for (int j = 0;j < found[1];j++) { - for (mode2 = 0;mode2 < total_modes;mode2++) + for (int mode2 = 0;mode2 < total_modes;mode2++) { - for (mode1 = 0;mode1 < start;mode1++) + for (int mode1 = 0;mode1 < start;mode1++) matchscore[besti][j][mode1][mode2] = 0.0; - for (mode1 = end+1;mode1 < total_modes;mode1++) + for (int mode1 = end+1;mode1 < total_modes;mode1++) matchscore[besti][j][mode1][mode2] = 0.0; } } compatiblemodes(bestmode2,&start,&end); - for (i = 0;i < found[0];i++) + for (int i = 0;i < found[0];i++) { - for (mode1 = 0;mode1 < total_modes;mode1++) + for (int mode1 = 0;mode1 < total_modes;mode1++) { - for (mode2 = 0;mode2 < start;mode2++) + for (int mode2 = 0;mode2 < start;mode2++) matchscore[i][bestj][mode1][mode2] = 0.0; - for (mode2 = end+1;mode2 < total_modes;mode2++) + for (int mode2 = end+1;mode2 < total_modes;mode2++) matchscore[i][bestj][mode1][mode2] = 0.0; } } } - } while (besti != -1); + } + while (besti != -1); - for (i = 0;i < found[0];i++) + for (int i = 0;i < found[0];i++) { if (files[0][i].listed == 0) printname(&files[0][i],nullptr,0.0,0,0); } - for (i = 0;i < found[1];i++) + for (int i = 0;i < found[1];i++) { if (files[1][i].listed == 0) printname(nullptr,&files[1][i],0.0,0,0); } } - for (i = 0;i < found[0];i++) + for (int i = 0;i < found[0];i++) { - freefile(&files[0][i]); + files[0][i].free(); } - for (i = 0;i < found[1];i++) + for (int i = 0;i < found[1];i++) { - freefile(&files[1][i]); + files[1][i].free(); } } diff --git a/src/tools/split.cpp b/src/tools/split.cpp index f8a8eb79234..24953c3d7cd 100644 --- a/src/tools/split.cpp +++ b/src/tools/split.cpp @@ -66,7 +66,7 @@ static int split_file(const char *filename, const char *basename, uint32_t split void *splitbuffer = nullptr; int index, partnum; uint64_t totallength; - osd_file::error filerr; + std::error_condition filerr; int error = 1; // convert split size to MB @@ -79,7 +79,7 @@ static int split_file(const char *filename, const char *basename, uint32_t split // open the file for read filerr = util::core_file::open(filename, OPEN_FLAG_READ, infile); - if (filerr != osd_file::error::NONE) + if (filerr) { fprintf(stderr, "Fatal error: unable to open file '%s'\n", filename); goto cleanup; @@ -117,7 +117,7 @@ static int split_file(const char *filename, const char *basename, uint32_t split // create the split file filerr = util::core_file::open(splitfilename, OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_NO_BOM, splitfile); - if (filerr != osd_file::error::NONE) + if (filerr) { fprintf(stderr, "Fatal error: unable to create split file '%s'\n", splitfilename.c_str()); goto cleanup; @@ -153,7 +153,7 @@ static int split_file(const char *filename, const char *basename, uint32_t split // create it filerr = util::core_file::open(outfilename, OPEN_FLAG_WRITE | OPEN_FLAG_CREATE, outfile); - if (filerr != osd_file::error::NONE) + if (filerr) { printf("\n"); fprintf(stderr, "Fatal error: unable to create output file '%s'\n", outfilename.c_str()); @@ -216,7 +216,7 @@ static int join_file(const char *filename, const char *outname, int write_output std::string basepath; util::core_file::ptr outfile, infile, splitfile; void *splitbuffer = nullptr; - osd_file::error filerr; + std::error_condition filerr; uint32_t splitsize; char buffer[256]; int error = 1; @@ -224,7 +224,7 @@ static int join_file(const char *filename, const char *outname, int write_output // open the file for read filerr = util::core_file::open(filename, OPEN_FLAG_READ, splitfile); - if (filerr != osd_file::error::NONE) + if (filerr) { fprintf(stderr, "Fatal error: unable to open file '%s'\n", filename); goto cleanup; @@ -264,7 +264,7 @@ static int join_file(const char *filename, const char *outname, int write_output { // don't overwrite the original! filerr = util::core_file::open(outfilename, OPEN_FLAG_READ, outfile); - if (filerr == osd_file::error::NONE) + if (!filerr) { outfile.reset(); fprintf(stderr, "Fatal error: output file '%s' already exists\n", outfilename.c_str()); @@ -273,7 +273,7 @@ static int join_file(const char *filename, const char *outname, int write_output // open the output for write filerr = util::core_file::open(outfilename, OPEN_FLAG_WRITE | OPEN_FLAG_CREATE, outfile); - if (filerr != osd_file::error::NONE) + if (filerr) { fprintf(stderr, "Fatal error: unable to create file '%s'\n", outfilename.c_str()); goto cleanup; @@ -301,7 +301,7 @@ static int join_file(const char *filename, const char *outname, int write_output // read the file's contents infilename.insert(0, basepath); filerr = util::core_file::load(infilename.c_str(), &splitbuffer, length); - if (filerr != osd_file::error::NONE) + if (filerr) { printf("\n"); fprintf(stderr, "Fatal error: unable to load file '%s'\n", infilename.c_str()); diff --git a/src/tools/srcclean.cpp b/src/tools/srcclean.cpp index 052d2a37334..340217c7768 100644 --- a/src/tools/srcclean.cpp +++ b/src/tools/srcclean.cpp @@ -2254,13 +2254,13 @@ int main(int argc, char *argv[]) { // open the file util::core_file::ptr infile; - osd_file::error const err(util::core_file::open(argv[i], OPEN_FLAG_READ, infile)); - if (osd_file::error::NONE != err) + std::error_condition const err(util::core_file::open(argv[i], OPEN_FLAG_READ, infile)); + if (err) { if (affected) std::cerr << std::endl; affected = true; - util::stream_format(std::cerr, "Can't open %1$s\n", argv[i]); + util::stream_format(std::cerr, "Can't open %1$s (%2$s)\n", argv[i], err.message()); ++failures; continue; } diff --git a/src/tools/unidasm.cpp b/src/tools/unidasm.cpp index 14e7dbf2c6d..5395bc6ae01 100644 --- a/src/tools/unidasm.cpp +++ b/src/tools/unidasm.cpp @@ -1219,9 +1219,9 @@ int main(int argc, char *argv[]) void *data = nullptr; u32 length = 0; if(std::strcmp(opts.filename, "-") != 0) { - osd_file::error filerr = util::core_file::load(opts.filename, &data, length); - if(filerr != osd_file::error::NONE) { - std::fprintf(stderr, "Error opening file '%s'\n", opts.filename); + std::error_condition filerr = util::core_file::load(opts.filename, &data, length); + if(filerr) { + std::fprintf(stderr, "Error opening file '%s' (%s)\n", opts.filename, filerr.message().c_str()); return 1; } } -- cgit v1.2.3 From 4f495994c41cd2fbaf89c08f755e828ae3261828 Mon Sep 17 00:00:00 2001 From: Vas Crabb Date: Mon, 6 Sep 2021 06:34:42 +1000 Subject: -ui: Made zoom controls a bit more intuitive. * The UI controls are described as zoom in/out, but they had the opposite effect on the palette and tile viewers. That has been changed to make them consistent with the tilemap viewer. * Made the default zoom key not act as a toggle. People are familiar with the function of Ctrl+0/=/- in web browsers, so making them behave similarly in MAME should make it more approachable. Also added the default zoom key to the relevant documentation page. * Implemented the default zoom key for the palette and tile viewers. * In the tilemap viewer, if the view is in default expand to fit mode, zoom in/out starting from the actual zoom ratio. Once again, this behaves more like the zoom controls in a web browser displaying an image so it should be more intuitive. * Made more messages from the tilemap viewer localisable. -util/zippath.cpp: Fixed MT08074. * There were multiple issues at play here. After #8443 was applied, is_root was simply never returning true on Windows, as OSD_WINDOWS isn't actually defined outside libosd and libocore. This caused phantom parent items to appear in disk roots on Windows, but it meant that the check in zippath_resolve would always fail so the trailing backslash would be trimmed. Fixing the macro test in is_root meant the trailing backslash from C:\ would no longer be trimmed, which caused the stat in zippath_resolve to fail. -bigbord2.cpp: Hooked up floppy DRQ that had somehow got lost. -Reduced tag map lookups in several drivers and devices. -util/coretmpl.h: Removed an overload of bitswap that can be avoided using if constexpr. -Added doxygen comments to some classes, and fixed several doxygen warnings. -util, osd: Test for _WIN32 rather than WIN32. * In C++17 mode, WIN32 is no longer a predefined macro, although various things in 3rdparty define it to maintain legacy support. We're better off moving forward anyway for when WIN32 disappears entirely. (WIN32 is not a reserved name, while _WIN32 is, starting with an underscore follwed by an uppercase letter.) --- docs/source/usingmame/defaultkeys.rst | 7 +- scripts/target/mame/arcade.lua | 2 - src/devices/sound/gaelco.h | 3 +- src/devices/sound/scsp.h | 4 +- src/emu/attotime.h | 12 +- src/emu/devfind.h | 4 - src/emu/inpttype.ipp | 2 +- src/emu/ioport.cpp | 8 +- src/emu/ioport.h | 4 +- src/emu/rendlay.h | 30 ++-- src/emu/screen.h | 9 -- src/frontend/mame/ui/viewgfx.cpp | 193 +++++++++++----------- src/frontend/mame/ui/viewgfx.h | 1 + src/lib/formats/flopimg.h | 8 +- src/lib/netlist/nl_config.h | 4 +- src/lib/netlist/tests/test_pfunction.cpp | 2 +- src/lib/util/bitmap.cpp | 2 +- src/lib/util/chdcodec.cpp | 2 +- src/lib/util/coretmpl.h | 19 +-- src/lib/util/ioprocs.h | 138 ++++++++++++++++ src/lib/util/path.h | 40 +++-- src/lib/util/unicode.cpp | 4 +- src/lib/util/zippath.cpp | 20 +-- src/mame/audio/dcs.cpp | 57 ++++--- src/mame/audio/dcs.h | 12 +- src/mame/audio/m72.h | 4 +- src/mame/drivers/apple2e.cpp | 25 +-- src/mame/drivers/applix.cpp | 2 +- src/mame/drivers/bigbord2.cpp | 20 ++- src/mame/drivers/calchase.cpp | 46 ++---- src/mame/drivers/ccs2810.cpp | 20 ++- src/mame/drivers/cops.cpp | 56 +++---- src/mame/drivers/cortex.cpp | 23 ++- src/mame/drivers/cvicny.cpp | 13 +- src/mame/drivers/cz101.cpp | 68 ++++---- src/mame/drivers/dps1.cpp | 18 ++- src/mame/drivers/dsb46.cpp | 21 ++- src/mame/drivers/excali64.cpp | 115 +++++++------- src/mame/drivers/force68k.cpp | 2 +- src/mame/drivers/galgames.cpp | 5 +- src/mame/drivers/hng64.cpp | 59 +++---- src/mame/drivers/kaypro.cpp | 4 +- src/mame/drivers/konendev.cpp | 46 ++---- src/mame/drivers/mbc200.cpp | 19 ++- src/mame/drivers/mes.cpp | 19 ++- src/mame/drivers/mmd1.cpp | 27 +++- src/mame/drivers/nakajies.cpp | 67 ++++---- src/mame/drivers/pegasus.cpp | 54 ++++--- src/mame/drivers/taxidriv.cpp | 265 ++++++++++++++++++++++++++----- src/mame/drivers/ultim809.cpp | 18 ++- src/mame/drivers/v6809.cpp | 12 +- src/mame/includes/hng64.h | 94 ++++------- src/mame/includes/taxidriv.h | 89 ----------- src/mame/video/hng64.cpp | 2 +- src/mame/video/taxidriv.cpp | 136 ---------------- src/osd/asio.h | 2 +- src/osd/modules/debugger/debugqt.cpp | 12 +- src/osd/modules/file/posixdir.cpp | 6 +- src/osd/modules/file/posixfile.cpp | 34 ++-- src/osd/modules/netdev/taptun.cpp | 14 +- src/osd/modules/sound/pa_sound.cpp | 4 +- src/osd/osdcore.cpp | 12 +- src/osd/strconv.h | 4 +- src/tools/chdman.cpp | 2 +- src/tools/srcclean.cpp | 2 +- 65 files changed, 1071 insertions(+), 957 deletions(-) delete mode 100644 src/mame/includes/taxidriv.h delete mode 100644 src/mame/video/taxidriv.cpp (limited to 'src/tools/srcclean.cpp') diff --git a/docs/source/usingmame/defaultkeys.rst b/docs/source/usingmame/defaultkeys.rst index 31fb6ad7d1a..2f20996be06 100644 --- a/docs/source/usingmame/defaultkeys.rst +++ b/docs/source/usingmame/defaultkeys.rst @@ -110,6 +110,7 @@ and saving/loading save states. * **Page Up**/**Page Down** - scroll up/down one page at a time. * **Home**/**End** - move to top/bottom of list. * **-**/**+** - increase/decrease the number of colors per row. + * **0** - restore the default number of colors per row. * **Enter** - switch to graphics viewer. Graphics mode: @@ -121,6 +122,7 @@ and saving/loading save states. * **Left**/**Right** - change color displayed. * **R** - rotate tiles 90 degrees clockwise. * **-**/**+** - increase/decrease the number of tiles per row. + * **0** - restore the default number of tiles per row. * **Enter** - switch to tilemap viewer. Tilemap mode: @@ -130,10 +132,11 @@ and saving/loading save states. * **Shift+Up**/**Down**/**Left**/**Right** - scroll 1 pixel at a time. * **Control+Up**/**Down**/**Left**/**Right** - scroll 64 pixels at a time. * **R** - rotate tilemap view 90 degrees clockwise. - * **-**/**+** - increase/decrease the zoom factor. + * **-**/**+** - decrease/increase the zoom factor. + * **0** - expand small tilemaps to fill the display. * **Enter** - switch to palette/colortable mode. - Note: Not all games have decoded graphics and/or tilemaps. + Note: Not all systems have decoded graphics and/or tilemaps. **Left Ctrl+F5** Toggle Filter. (*SDL MAME only*) diff --git a/scripts/target/mame/arcade.lua b/scripts/target/mame/arcade.lua index 572f3a05482..375bae3369b 100644 --- a/scripts/target/mame/arcade.lua +++ b/scripts/target/mame/arcade.lua @@ -5139,8 +5139,6 @@ files { MAME_DIR .. "src/mame/drivers/tapatune.cpp", MAME_DIR .. "src/mame/drivers/tattack.cpp", MAME_DIR .. "src/mame/drivers/taxidriv.cpp", - MAME_DIR .. "src/mame/includes/taxidriv.h", - MAME_DIR .. "src/mame/video/taxidriv.cpp", MAME_DIR .. "src/mame/drivers/teamjocs.cpp", MAME_DIR .. "src/mame/drivers/tecnodar.cpp", MAME_DIR .. "src/mame/drivers/thayers.cpp", diff --git a/src/devices/sound/gaelco.h b/src/devices/sound/gaelco.h index 76a77c0bb40..2d0180e290f 100644 --- a/src/devices/sound/gaelco.h +++ b/src/devices/sound/gaelco.h @@ -7,14 +7,13 @@ #include "dirom.h" + //************************************************************************** // TYPE DEFINITIONS //************************************************************************** // ======================> gaelco_gae1_device -#include "dirom.h" - class gaelco_gae1_device : public device_t, public device_sound_interface, public device_rom_interface<27> // Unknown address bits diff --git a/src/devices/sound/scsp.h b/src/devices/sound/scsp.h index 7ff91fdb576..f3d08df9793 100644 --- a/src/devices/sound/scsp.h +++ b/src/devices/sound/scsp.h @@ -9,9 +9,11 @@ #pragma once -#include "dirom.h" #include "scspdsp.h" +#include "dirom.h" + + #define SCSP_FM_DELAY 0 // delay in number of slots processed before samples are written to the FM ring buffer // driver code indicates should be 4, but sounds distorted then diff --git a/src/emu/attotime.h b/src/emu/attotime.h index c6fa441733c..c975bbde0d3 100644 --- a/src/emu/attotime.h +++ b/src/emu/attotime.h @@ -133,15 +133,15 @@ public: static attotime from_double(double _time); static attotime from_ticks(u64 ticks, u32 frequency); static attotime from_ticks(u64 ticks, const XTAL &xtal) { return from_ticks(ticks, xtal.value()); } - /** Create an attotime from a integer count of seconds @seconds */ + /** Create an attotime from an integer count of seconds @p seconds */ static constexpr attotime from_seconds(s32 seconds) { return attotime(seconds, 0); } - /** Create an attotime from a integer count of milliseconds @msec */ + /** Create an attotime from an integer count of milliseconds @p msec */ static constexpr attotime from_msec(s64 msec) { return attotime(msec / 1000, (msec % 1000) * (ATTOSECONDS_PER_SECOND / 1000)); } - /** Create an attotime from a integer count of microseconds @usec */ + /** Create an attotime from an integer count of microseconds @p usec */ static constexpr attotime from_usec(s64 usec) { return attotime(usec / 1000000, (usec % 1000000) * (ATTOSECONDS_PER_SECOND / 1000000)); } - /** Create an attotime from a integer count of nanoseconds @nsec */ + /** Create an attotime from an integer count of nanoseconds @p nsec */ static constexpr attotime from_nsec(s64 nsec) { return attotime(nsec / 1000000000, (nsec % 1000000000) * (ATTOSECONDS_PER_SECOND / 1000000000)); } - /** Create an attotime from at the given frequency @frequency */ + /** Create an attotime from at the given frequency @p frequency */ static attotime from_hz(u32 frequency) { return (frequency > 1) ? attotime(0, HZ_TO_ATTOSECONDS(frequency)) : (frequency == 1) ? attotime(1, 0) : attotime::never; } static attotime from_hz(int frequency) { return (frequency > 0) ? from_hz(u32(frequency)) : attotime::never; } static attotime from_hz(const XTAL &xtal) { return (xtal.dvalue() > 1.0) ? attotime(0, HZ_TO_ATTOSECONDS(xtal)) : from_hz(xtal.dvalue()); } @@ -346,7 +346,7 @@ inline u64 attotime::as_ticks(u32 frequency) const } -/** Create an attotime from a tick count @ticks at the given frequency @frequency */ +/** Create an attotime from a tick count @p ticks at the given frequency @p frequency */ inline attotime attotime::from_ticks(u64 ticks, u32 frequency) { if (frequency > 0) diff --git a/src/emu/devfind.h b/src/emu/devfind.h index 8253fb123f6..c8884d9582f 100644 --- a/src/emu/devfind.h +++ b/src/emu/devfind.h @@ -350,8 +350,6 @@ protected: /// report_missing to print an error message if the region is /// not found. Returns true if the region is required but no /// matching region is found, or false otherwise. - /// \param [in] bytes Desired region length in bytes, or 0U to match - /// any length. /// \param [in] required True if the region is required, or false if /// it is optional. /// \return True if the region is optional, or if the region is @@ -1059,8 +1057,6 @@ public: /// \param [in] tag Memory region tag to search for. This is not /// copied, it is the caller's responsibility to ensure this /// pointer remains valid until resolution time. - /// \param [in] length Desired memory region length in units of the - /// size of the element type, or zero to match any region length. region_ptr_finder(device_t &base, char const *tag) : object_finder_base(base, tag) , m_length(0) diff --git a/src/emu/inpttype.ipp b/src/emu/inpttype.ipp index 172d206f48c..989400b064e 100644 --- a/src/emu/inpttype.ipp +++ b/src/emu/inpttype.ipp @@ -838,7 +838,7 @@ namespace { INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_CLEAR, "UI Clear", input_seq(KEYCODE_DEL) ) \ INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_ZOOM_IN, "UI Zoom In", input_seq(KEYCODE_EQUALS) ) \ INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_ZOOM_OUT, "UI Zoom Out", input_seq(KEYCODE_MINUS) ) \ - INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_ZOOM_AUTO, "UI Toggle Auto Zoom", input_seq(KEYCODE_0) ) \ + INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_ZOOM_DEFAULT, "UI Default Zoom", input_seq(KEYCODE_0) ) \ INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_PREV_GROUP, "UI Previous Group", input_seq(KEYCODE_OPENBRACE) ) \ INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_NEXT_GROUP, "UI Next Group", input_seq(KEYCODE_CLOSEBRACE) ) \ INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_ROTATE, "UI Rotate", input_seq(KEYCODE_R) ) \ diff --git a/src/emu/ioport.cpp b/src/emu/ioport.cpp index cae37f28c17..4d9e8d186f7 100644 --- a/src/emu/ioport.cpp +++ b/src/emu/ioport.cpp @@ -1659,9 +1659,10 @@ ioport_manager::ioport_manager(running_machine &machine) , m_timecode_file(machine.options().input_directory(), OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS) , m_timecode_count(0) , m_timecode_last_time(attotime::zero) - , m_deselected_card_config(nullptr) + , m_deselected_card_config() { - memset(m_type_to_entry, 0, sizeof(m_type_to_entry)); + for (auto &entries : m_type_to_entry) + std::fill(std::begin(entries), std::end(entries), nullptr); } @@ -1837,7 +1838,6 @@ void ioport_manager::exit() ioport_manager::~ioport_manager() { - delete m_deselected_card_config; } @@ -2429,7 +2429,7 @@ void ioport_manager::load_system_config(util::xml::data_node const &portnode, in if (parent_device->interface(slot) && (slot->option_list().find(std::string(child_tag)) != slot->option_list().end())) { if (!m_deselected_card_config) - m_deselected_card_config = util::xml::file::create().release(); + m_deselected_card_config = util::xml::file::create(); portnode.copy_into(*m_deselected_card_config); } break; diff --git a/src/emu/ioport.h b/src/emu/ioport.h index 53e1e9ad5e8..20f21bc4f76 100644 --- a/src/emu/ioport.h +++ b/src/emu/ioport.h @@ -357,7 +357,7 @@ enum ioport_type IPT_UI_CLEAR, IPT_UI_ZOOM_IN, IPT_UI_ZOOM_OUT, - IPT_UI_ZOOM_AUTO, + IPT_UI_ZOOM_DEFAULT, IPT_UI_PREV_GROUP, IPT_UI_NEXT_GROUP, IPT_UI_ROTATE, @@ -1462,7 +1462,7 @@ private: attotime m_timecode_last_time; // storage for inactive configuration - util::xml::file * m_deselected_card_config; // using smart pointer would pull xmlfile.h into emu.h + std::unique_ptr m_deselected_card_config; }; diff --git a/src/emu/rendlay.h b/src/emu/rendlay.h index fb7871bd0ef..5555af820ac 100644 --- a/src/emu/rendlay.h +++ b/src/emu/rendlay.h @@ -52,12 +52,11 @@ class view_environment; /// \brief A description of a piece of visible artwork /// -/// Most view_items (except for those in the screen layer) have exactly +/// Most view items (except for those referencing screens) have exactly /// one layout_element which describes the contents of the item. /// Elements are separate from items because they can be re-used /// multiple times within a layout. Even though an element can contain -/// a number of components, they are treated as if they were a single -/// bitmap. +/// a number of components, they are drawn as a single textured quad. class layout_element { public: @@ -76,13 +75,14 @@ public: void preload(); private: - /// \brief An image, rectangle, or disk in an element + /// \brief A drawing component within a layout element /// - /// Each layout_element contains one or more components. Each + /// Each #layout_element contains one or more components. Each /// component can describe either an image or a rectangle/disk - /// primitive. Each component also has a "state" associated with it, - /// which controls whether or not the component is visible (if the - /// owning item has the same state, it is visible). + /// primitive. A component can also have a state mask and value + /// for controlling visibility. If the state of the item + /// instantiating the element matches the component's state value + /// for the bits that are set in the mask, the component is visible. class component { public: @@ -188,14 +188,14 @@ private: }; -/// \brief A reusable group of elements +/// \brief A reusable group of items /// /// Views expand/flatten groups into their component elements applying -/// an optional coordinate transform. This is mainly useful duplicating -/// the same sublayout in multiple views. It would be more useful -/// within a view if it could be parameterised. Groups only exist while -/// parsing a layout file - no information about element grouping is -/// preserved. +/// an optional coordinate transform. This is useful for duplicating +/// the same sublayout in multiple views, or grouping related items to +/// simplify overall view arrangement. Groups only exist while parsing +/// a layout file - no information about element grouping is preserved +/// after the views have been built. class layout_group { public: @@ -233,7 +233,7 @@ private: }; -/// \brief A single view within a layout_file +/// \brief A single view within a #layout_file /// /// The view is described using arbitrary coordinates that are scaled to /// fit within the render target. Pixels within a view are assumed to diff --git a/src/emu/screen.h b/src/emu/screen.h index bfff28d0f6f..b909c25cecc 100644 --- a/src/emu/screen.h +++ b/src/emu/screen.h @@ -552,13 +552,4 @@ DECLARE_DEVICE_TYPE(SCREEN, screen_device) // iterator helper typedef device_type_enumerator screen_device_enumerator; -/*! - @defgroup Screen device configuration functions - @{ - @def set_type - Modify the screen device type - @see screen_type_enum - @} - */ - #endif // MAME_EMU_SCREEN_H diff --git a/src/frontend/mame/ui/viewgfx.cpp b/src/frontend/mame/ui/viewgfx.cpp index 1da14866c57..1c263fed451 100644 --- a/src/frontend/mame/ui/viewgfx.cpp +++ b/src/frontend/mame/ui/viewgfx.cpp @@ -9,14 +9,15 @@ *********************************************************************/ #include "emu.h" +#include "ui/viewgfx.h" + + #include "emupal.h" -#include "ui/ui.h" -#include "uiinput.h" #include "render.h" #include "rendfont.h" #include "rendutil.h" #include "tilemap.h" -#include "ui/viewgfx.h" +#include "uiinput.h" #include @@ -32,9 +33,9 @@ enum ui_gfx_modes UI_GFX_TILEMAP }; -static const uint8_t MAX_GFX_DECODERS = 8; -static const int MAX_ZOOM_LEVEL = 8; -static const int MIN_ZOOM_LEVEL = 8; +constexpr uint8_t MAX_GFX_DECODERS = 8; +constexpr int MAX_ZOOM_LEVEL = 8; +constexpr int MIN_ZOOM_LEVEL = 8; @@ -49,16 +50,16 @@ struct ui_gfx_info uint8_t setcount; // how many gfx sets device has uint8_t rotate[MAX_GFX_ELEMENTS]; // current rotation (orientation) value uint8_t columns[MAX_GFX_ELEMENTS]; // number of items per row - int offset[MAX_GFX_ELEMENTS]; // current offset of top,left item - int color[MAX_GFX_ELEMENTS]; // current color selected + int offset[MAX_GFX_ELEMENTS]; // current offset of top,left item + int color[MAX_GFX_ELEMENTS]; // current color selected device_palette_interface *palette[MAX_GFX_ELEMENTS]; // associated palette (maybe multiple choice one day?) - int color_count[MAX_GFX_ELEMENTS]; // Range of color values + int color_count[MAX_GFX_ELEMENTS]; // Range of color values }; struct ui_gfx_state { bool started; // have we called ui_gfx_count_devices() yet? - uint8_t mode; // which mode are we in? + uint8_t mode; // which mode are we in? // intermediate bitmaps bool bitmap_dirty; // is the bitmap dirty? @@ -69,19 +70,19 @@ struct ui_gfx_state struct { device_palette_interface *interface; // pointer to current palette - int devcount; // how many palette devices exist - int devindex; // which palette device is visible - uint8_t which; // which subset (pens or indirect colors)? - uint8_t columns; // number of items per row - int offset; // current offset of top left item + int devcount; // how many palette devices exist + int devindex; // which palette device is visible + uint8_t which; // which subset (pens or indirect colors)? + uint8_t columns; // number of items per row + int offset; // current offset of top left item } palette; // graphics-specific data struct { - uint8_t devcount; // how many gfx devices exist - uint8_t devindex; // which device is visible - uint8_t set; // which set is visible + uint8_t devcount; // how many gfx devices exist + uint8_t devindex; // which device is visible + uint8_t set; // which set is visible } gfxset; // information about each gfx device @@ -90,14 +91,14 @@ struct ui_gfx_state // tilemap-specific data struct { - int which; // which tilemap are we viewing? - int xoffs; // current X offset - int yoffs; // current Y offset - int zoom; // zoom factor, either x or 1/x - bool zoom_frac; // zoom via reciprocal fractions - bool auto_zoom; // auto-zoom toggle - uint8_t rotate; // current rotation (orientation) value - uint32_t flags; // render flags + int which; // which tilemap are we viewing? + int xoffs; // current X offset + int yoffs; // current Y offset + int zoom; // zoom factor, either x or 1/x + bool zoom_frac; // zoom via reciprocal fractions + bool auto_zoom; // auto-zoom toggle + uint8_t rotate; // current rotation (orientation) value + uint32_t flags; // render flags } tilemap; }; @@ -130,7 +131,7 @@ static void gfxset_update_bitmap(running_machine &machine, ui_gfx_state &state, static void gfxset_handler(mame_ui_manager &mui, render_container &container, ui_gfx_state &state); // tilemap handling -static void tilemap_handle_keys(running_machine &machine, ui_gfx_state &state, int viswidth, int visheight); +static void tilemap_handle_keys(running_machine &machine, ui_gfx_state &state, float pixelscale); static void tilemap_update_bitmap(running_machine &machine, ui_gfx_state &state, int width, int height); static void tilemap_handler(mame_ui_manager &mui, render_container &container, ui_gfx_state &state); @@ -542,20 +543,13 @@ static void palette_handler(mame_ui_manager &mui, render_container &container, u static void palette_handle_keys(running_machine &machine, ui_gfx_state &state) { device_palette_interface *palette = state.palette.interface; - int rowcount, screencount; - int total; - // handle zoom (minus,plus) if (machine.ui_input().pressed(IPT_UI_ZOOM_OUT)) - state.palette.columns /= 2; + state.palette.columns = std::min(state.palette.columns * 2, 64); if (machine.ui_input().pressed(IPT_UI_ZOOM_IN)) - state.palette.columns *= 2; - - // clamp within range - if (state.palette.columns <= 4) - state.palette.columns = 4; - if (state.palette.columns > 64) - state.palette.columns = 64; + state.palette.columns = std::max(state.palette.columns / 2, 4); + if (machine.ui_input().pressed(IPT_UI_ZOOM_DEFAULT)) + state.palette.columns = 16; // handle colormap selection (open bracket,close bracket) if (machine.ui_input().pressed(IPT_UI_PREV_GROUP)) @@ -584,11 +578,11 @@ static void palette_handle_keys(running_machine &machine, ui_gfx_state &state) } // cache some info in locals - total = state.palette.which ? palette->indirect_entries() : palette->entries(); + const int total = state.palette.which ? palette->indirect_entries() : palette->entries(); // determine number of entries per row and total - rowcount = state.palette.columns; - screencount = rowcount * rowcount; + const int rowcount = state.palette.columns; + const int screencount = rowcount * rowcount; // handle keyboard navigation if (machine.ui_input().pressed_repeat(IPT_UI_UP, 4)) @@ -855,17 +849,14 @@ static void gfxset_handle_keys(running_machine &machine, ui_gfx_state &state, in gfx_element &gfx = *info.interface->gfx(set); // handle cells per line (minus,plus) - if (machine.ui_input().pressed(IPT_UI_ZOOM_OUT)) - { info.columns[set] = xcells - 1; state.bitmap_dirty = true; } - - if (machine.ui_input().pressed(IPT_UI_ZOOM_IN)) + if (machine.ui_input().pressed(IPT_UI_ZOOM_OUT) && (xcells < 128)) { info.columns[set] = xcells + 1; state.bitmap_dirty = true; } - // clamp within range - if (info.columns[set] < 2) - { info.columns[set] = 2; state.bitmap_dirty = true; } - if (info.columns[set] > 128) - { info.columns[set] = 128; state.bitmap_dirty = true; } + if (machine.ui_input().pressed(IPT_UI_ZOOM_IN) && (xcells > 2)) + { info.columns[set] = xcells - 1; state.bitmap_dirty = true; } + + if (machine.ui_input().pressed(IPT_UI_ZOOM_DEFAULT) && (xcells != 16)) + { info.columns[set] = 16; state.bitmap_dirty = true; } // handle rotation (R) if (machine.ui_input().pressed(IPT_UI_ROTATE)) @@ -918,18 +909,16 @@ static void gfxset_handle_keys(running_machine &machine, ui_gfx_state &state, in static void gfxset_update_bitmap(running_machine &machine, ui_gfx_state &state, int xcells, int ycells, gfx_element &gfx) { - int dev = state.gfxset.devindex; - int set = state.gfxset.set; + const int dev = state.gfxset.devindex; + const int set = state.gfxset.set; ui_gfx_info &info = state.gfxdev[dev]; - int cellxpix, cellypix; - int x, y; // compute the number of source pixels in a cell - cellxpix = 1 + ((info.rotate[set] & ORIENTATION_SWAP_XY) ? gfx.height() : gfx.width()); - cellypix = 1 + ((info.rotate[set] & ORIENTATION_SWAP_XY) ? gfx.width() : gfx.height()); + const int cellxpix = 1 + ((info.rotate[set] & ORIENTATION_SWAP_XY) ? gfx.height() : gfx.width()); + const int cellypix = 1 + ((info.rotate[set] & ORIENTATION_SWAP_XY) ? gfx.width() : gfx.height()); // realloc the bitmap if it is too small - if (!state.bitmap.valid() || state.texture == nullptr || state.bitmap.width() != cellxpix * xcells || state.bitmap.height() != cellypix * ycells) + if (!state.bitmap.valid() || !state.texture || state.bitmap.width() != cellxpix * xcells || state.bitmap.height() != cellypix * ycells) { // free the old stuff machine.render().texture_free(state.texture); @@ -948,37 +937,28 @@ static void gfxset_update_bitmap(running_machine &machine, ui_gfx_state &state, if (state.bitmap_dirty) { // loop over rows - for (y = 0; y < ycells; y++) + for (int y = 0, index = info.offset[set]; y < ycells; y++) { - rectangle cellbounds; - // make a rect that covers this row - cellbounds.set(0, state.bitmap.width() - 1, y * cellypix, (y + 1) * cellypix - 1); + rectangle cellbounds(0, state.bitmap.width() - 1, y * cellypix, (y + 1) * cellypix - 1); // only display if there is data to show - if (info.offset[set] + y * xcells < gfx.elements()) + if (index < gfx.elements()) { // draw the individual cells - for (x = 0; x < xcells; x++) + for (int x = 0; x < xcells; x++, index++) { - int index = info.offset[set] + y * xcells + x; - // update the bounds for this cell cellbounds.min_x = x * cellxpix; cellbounds.max_x = (x + 1) * cellxpix - 1; - // only render if there is data - if (index < gfx.elements()) + if (index < gfx.elements()) // only render if there is data gfxset_draw_item(machine, gfx, index, state.bitmap, cellbounds.min_x, cellbounds.min_y, info.color[set], info.rotate[set], info.palette[set]); - - // otherwise, fill with transparency - else + else // otherwise, fill with transparency state.bitmap.fill(0, cellbounds); } } - - // otherwise, fill with transparency - else + else // otherwise, fill with transparency state.bitmap.fill(0, cellbounds); } @@ -1090,19 +1070,21 @@ static void tilemap_handler(mame_ui_manager &mui, render_container &container, u mapboxwidth = (mapboxbounds.x1 - mapboxbounds.x0) * float(targwidth); mapboxheight = (mapboxbounds.y1 - mapboxbounds.y0) * float(targheight); - // determine the maximum integral scaling factor - float pixelscale = state.tilemap.zoom_frac ? (1.0f / state.tilemap.zoom) : float(state.tilemap.zoom); + float pixelscale; if (state.tilemap.auto_zoom) { - uint32_t maxxscale, maxyscale; - for (maxxscale = 1; mapwidth * (maxxscale + 1) < mapboxwidth; maxxscale++) { } - for (maxyscale = 1; mapheight * (maxyscale + 1) < mapboxheight; maxyscale++) { } - pixelscale = float(std::min(maxxscale, maxyscale)); + // determine the maximum integral scaling factor + pixelscale = std::min(std::floor(mapboxwidth / mapwidth), std::floor(mapboxheight / mapheight)); + pixelscale = std::max(pixelscale, 1.0f); + } + else + { + pixelscale = state.tilemap.zoom_frac ? (1.0f / state.tilemap.zoom) : float(state.tilemap.zoom); } // recompute the final box size - mapboxwidth = std::min(mapboxwidth, int(std::round(mapwidth * pixelscale))); - mapboxheight = std::min(mapboxheight, int(std::round(mapheight * pixelscale))); + mapboxwidth = std::min(mapboxwidth, std::lround(mapwidth * pixelscale)); + mapboxheight = std::min(mapboxheight, std::lround(mapheight * pixelscale)); // recompute the bounds, centered within the existing bounds mapboxbounds.x0 += 0.5f * ((mapboxbounds.x1 - mapboxbounds.x0) - float(mapboxwidth) / targwidth); @@ -1137,8 +1119,8 @@ static void tilemap_handler(mame_ui_manager &mui, render_container &container, u ypixel = (mapboxheight - 1) - ypixel; if (state.tilemap.rotate & ORIENTATION_SWAP_XY) std::swap(xpixel, ypixel); - uint32_t col = ((int(std::round(xpixel / pixelscale)) + state.tilemap.xoffs) / tilemap->tilewidth()) % tilemap->cols(); - uint32_t row = ((int(std::round(ypixel / pixelscale)) + state.tilemap.yoffs) / tilemap->tileheight()) % tilemap->rows(); + uint32_t col = ((std::lround(xpixel / pixelscale) + state.tilemap.xoffs) / tilemap->tilewidth()) % tilemap->cols(); + uint32_t row = ((std::lround(ypixel / pixelscale) + state.tilemap.yoffs) / tilemap->tileheight()) % tilemap->rows(); uint8_t gfxnum; uint32_t code, color; tilemap->get_info_debug(col, row, gfxnum, code, color); @@ -1174,7 +1156,7 @@ static void tilemap_handler(mame_ui_manager &mui, render_container &container, u } // update the bitmap - tilemap_update_bitmap(mui.machine(), state, int(std::round(mapboxwidth / pixelscale)), int(std::round(mapboxheight / pixelscale))); + tilemap_update_bitmap(mui.machine(), state, std::lround(mapboxwidth / pixelscale), std::lround(mapboxheight / pixelscale)); // add the final quad container.add_quad(mapboxbounds.x0, mapboxbounds.y0, @@ -1183,7 +1165,7 @@ static void tilemap_handler(mame_ui_manager &mui, render_container &container, u PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA) | PRIMFLAG_TEXORIENT(state.tilemap.rotate)); // handle keyboard input - tilemap_handle_keys(mui.machine(), state, mapboxwidth, mapboxheight); + tilemap_handle_keys(mui.machine(), state, pixelscale); } @@ -1192,7 +1174,7 @@ static void tilemap_handler(mame_ui_manager &mui, render_container &container, u // tilemap view //------------------------------------------------- -static void tilemap_handle_keys(running_machine &machine, ui_gfx_state &state, int viswidth, int visheight) +static void tilemap_handle_keys(running_machine &machine, ui_gfx_state &state, float pixelscale) { // handle tilemap selection (open bracket,close bracket) if (machine.ui_input().pressed(IPT_UI_PREV_GROUP) && state.tilemap.which > 0) @@ -1211,9 +1193,16 @@ static void tilemap_handle_keys(running_machine &machine, ui_gfx_state &state, i // handle zoom (minus,plus) if (machine.ui_input().pressed(IPT_UI_ZOOM_OUT) && !at_min_zoom) { - state.tilemap.auto_zoom = false; - - if (state.tilemap.zoom_frac) + if (state.tilemap.auto_zoom) + { + // auto zoom never uses fractional factors + state.tilemap.zoom = std::lround(pixelscale) - 1; + state.tilemap.zoom_frac = !state.tilemap.zoom; + if (state.tilemap.zoom_frac) + state.tilemap.zoom = 2; + state.tilemap.auto_zoom = false; + } + else if (state.tilemap.zoom_frac) { // remaining in fractional zoom range state.tilemap.zoom++; @@ -1232,14 +1221,19 @@ static void tilemap_handle_keys(running_machine &machine, ui_gfx_state &state, i state.bitmap_dirty = true; - machine.popmessage(state.tilemap.zoom_frac ? "Zoom = 1/%d" : "Zoom = %d", state.tilemap.zoom); + machine.popmessage(state.tilemap.zoom_frac ? _("Zoom = 1/%1$d") : _("Zoom = %1$d"), state.tilemap.zoom); } if (machine.ui_input().pressed(IPT_UI_ZOOM_IN) && !at_max_zoom) { - state.tilemap.auto_zoom = false; - - if (!state.tilemap.zoom_frac) + if (state.tilemap.auto_zoom) + { + // auto zoom never uses fractional factors + state.tilemap.zoom = std::min(std::lround(pixelscale) + 1, MAX_ZOOM_LEVEL); + state.tilemap.zoom_frac = false; + state.tilemap.auto_zoom = false; + } + else if (!state.tilemap.zoom_frac) { // remaining in integer zoom range state.tilemap.zoom++; @@ -1258,17 +1252,14 @@ static void tilemap_handle_keys(running_machine &machine, ui_gfx_state &state, i state.bitmap_dirty = true; - machine.popmessage(state.tilemap.zoom_frac ? "Zoom = 1/%d" : "Zoom = %d", state.tilemap.zoom); + machine.popmessage(state.tilemap.zoom_frac ? _("Zoom = 1/%1$d") : _("Zoom = %1$d"), state.tilemap.zoom); } - if (machine.ui_input().pressed(IPT_UI_ZOOM_AUTO)) + if (machine.ui_input().pressed(IPT_UI_ZOOM_DEFAULT) && !state.tilemap.auto_zoom) { - state.tilemap.auto_zoom = !state.tilemap.auto_zoom; + state.tilemap.auto_zoom = true; - if (state.tilemap.auto_zoom) - machine.popmessage("Auto Zoom"); - else - machine.popmessage(state.tilemap.zoom_frac ? "Zoom = 1/%d" : "Zoom = %d", state.tilemap.zoom); + machine.popmessage(_("Expand to fit")); } // handle rotation (R) @@ -1372,7 +1363,7 @@ static void tilemap_update_bitmap(running_machine &machine, ui_gfx_state &state, std::swap(width, height); // realloc the bitmap if it is too small - if (!state.bitmap.valid() || state.texture == nullptr || state.bitmap.width() != width || state.bitmap.height() != height) + if (!state.bitmap.valid() || !state.texture || state.bitmap.width() != width || state.bitmap.height() != height) { // free the old stuff machine.render().texture_free(state.texture); diff --git a/src/frontend/mame/ui/viewgfx.h b/src/frontend/mame/ui/viewgfx.h index a4d2205d7a8..765384b4bea 100644 --- a/src/frontend/mame/ui/viewgfx.h +++ b/src/frontend/mame/ui/viewgfx.h @@ -13,6 +13,7 @@ #pragma once +#include "ui/ui.h" /*************************************************************************** diff --git a/src/lib/formats/flopimg.h b/src/lib/formats/flopimg.h index 6279def82f8..550c9a62fa8 100644 --- a/src/lib/formats/flopimg.h +++ b/src/lib/formats/flopimg.h @@ -734,9 +734,9 @@ public: //! floppy_image constructor /*! - @param _tracks number of tracks. - @param _heads number of heads. - @param _form_factor form factor of drive (from enum) + @param tracks number of tracks. + @param heads number of heads. + @param form_factor form factor of drive (from enum) */ floppy_image(int tracks, int heads, uint32_t form_factor); virtual ~floppy_image(); @@ -788,7 +788,7 @@ public: //! Returns the variant name for the particular disk form factor/variant //! @param form_factor //! @param variant - //! @param returns a string containing the variant name. + //! @return a string containing the variant name. static const char *get_variant_name(uint32_t form_factor, uint32_t variant); private: diff --git a/src/lib/netlist/nl_config.h b/src/lib/netlist/nl_config.h index 76d1d40d530..8dad2b36cc2 100644 --- a/src/lib/netlist/nl_config.h +++ b/src/lib/netlist/nl_config.h @@ -192,8 +192,8 @@ namespace netlist /// /// This is the recommended clock to be used in fixed clock applications limited /// to 32 bit clock resolution. The MAME code (netlist.cpp) contains code - /// illustrating how to deal with remainders if \ref NETLIST_INTERNAL_RES is - /// bigger than NETLIST_CLOCK. + /// illustrating how to deal with remainders if \ref INTERNAL_RES is bigger than + /// NETLIST_CLOCK. using DEFAULT_CLOCK = std::integral_constant; // NOLINT /// \brief Default logic family diff --git a/src/lib/netlist/tests/test_pfunction.cpp b/src/lib/netlist/tests/test_pfunction.cpp index 3d251d620d0..c87671d8c7a 100644 --- a/src/lib/netlist/tests/test_pfunction.cpp +++ b/src/lib/netlist/tests/test_pfunction.cpp @@ -2,7 +2,7 @@ // copyright-holders:Couriersud /// -/// \file pfunction_test.cpp +/// \file test_pfunction.cpp /// /// tests for pfunction /// diff --git a/src/lib/util/bitmap.cpp b/src/lib/util/bitmap.cpp index 9722fea7218..8757d928fff 100644 --- a/src/lib/util/bitmap.cpp +++ b/src/lib/util/bitmap.cpp @@ -415,7 +415,7 @@ void bitmap_t::set_palette(palette_t *palette) * -------------------------------------------------. * * @param color The color. - * @param cliprect The cliprect. + * @param bounds The bounds. */ void bitmap_t::fill(uint64_t color, const rectangle &bounds) diff --git a/src/lib/util/chdcodec.cpp b/src/lib/util/chdcodec.cpp index eca9403b56c..cd708d0f507 100644 --- a/src/lib/util/chdcodec.cpp +++ b/src/lib/util/chdcodec.cpp @@ -771,7 +771,7 @@ chd_zlib_allocator::chd_zlib_allocator() //------------------------------------------------- -// ~chd_zlib_allocator - constructor +// ~chd_zlib_allocator - destructor //------------------------------------------------- chd_zlib_allocator::~chd_zlib_allocator() diff --git a/src/lib/util/coretmpl.h b/src/lib/util/coretmpl.h index 18b64e7c0ff..49f01f8415c 100644 --- a/src/lib/util/coretmpl.h +++ b/src/lib/util/coretmpl.h @@ -610,20 +610,6 @@ template constexpr T BIT(T x, U n, V w) } -/// \brief Extract and right-align a single bit field -/// -/// This overload is used to terminate a recursive template -/// implementation. It is functionally equivalent to the BIT -/// function for extracting a single bit. -/// -/// \param [in] val The integer to extract the bit from. -/// \param [in] b The bit to extract, where zero is the least -/// significant bit of the input. -/// \return The specified bit of the input extracted to the least -/// significant position. -template constexpr T bitswap(T val, U b) noexcept { return BIT(val, b) << 0U; } - - /// \brief Extract bits in arbitrary order /// /// Extracts bits from an integer. Specify the bits in the order they @@ -641,7 +627,10 @@ template constexpr T bitswap(T val, U b) noexcept { ret /// \return The extracted bits packed into a right-aligned field. template constexpr T bitswap(T val, U b, V... c) noexcept { - return (BIT(val, b) << sizeof...(c)) | bitswap(val, c...); + if constexpr (sizeof...(c)) + return (BIT(val, b) << sizeof...(c)) | bitswap(val, c...); + else + return BIT(val, b); } diff --git a/src/lib/util/ioprocs.h b/src/lib/util/ioprocs.h index 78c06e71318..0a4e5c384f0 100644 --- a/src/lib/util/ioprocs.h +++ b/src/lib/util/ioprocs.h @@ -27,6 +27,14 @@ class osd_file; namespace util { +/// \defgroup ioprocs Generic I/O interfaces +/// \{ + +/// \brief Interface to an input stream +/// +/// Represents a stream producing a sequence of bytes with no further +/// structure. +/// \sa write_stream read_write_stream random_read class read_stream { public: @@ -34,10 +42,29 @@ public: virtual ~read_stream() = default; + /// \brief Read from the current position in the stream + /// + /// Reads up to the specified number of bytes from the stream into + /// the supplied buffer. May read less than the requested number of + /// bytes if the end of the stream is reached or an error occurs. + /// If the stream supports seeking, reading starts at the current + /// position in the stream, and the current position is incremented + /// by the number of bytes read. + /// \param [out] buffer Destination buffer. Must be large enough to + /// hold the requested number of bytes. + /// \param [in] length Maximum number of bytes to read. + /// \param [out] actual Number of bytes actually read. Will always + /// be less than or equal to the requested length. + /// \return An error condition if reading stopped due to an error. virtual std::error_condition read(void *buffer, std::size_t length, std::size_t &actual) noexcept = 0; }; +/// \brief Interface to an output stream +/// +/// Represents a stream that accepts a sequence of bytes with no further +/// structure. +/// \sa read_stream read_write_stream random_write class write_stream { public: @@ -45,12 +72,43 @@ public: virtual ~write_stream() = default; + /// \brief Finish writing data + /// + /// Performs any tasks necessary to finish writing data to the + /// stream and guarantee that the written data can be read in its + /// entirety. Further writes may not be possible. + /// \return An error condition if the operation fails. virtual std::error_condition finalize() noexcept = 0; + + /// \brief Flush application-side caches + /// + /// Flushes any caches to the underlying stream. Success does not + /// guarantee that data has reached persistent storage. + /// \return An error condition if flushing caches fails. virtual std::error_condition flush() noexcept = 0; + + /// \brief Write at the current position in the stream + /// + /// Writes up to the specified number of bytes from the supplied + /// buffer to the stream. May write less than the requested number + /// of bytes if an error occurs. If the stream supports seeking, + /// writing starts at the current position in the stream, and the + /// current position is incremented by the number of bytes written. + /// \param [in] buffer Buffer containing the data to write. Must + /// contain at least the specified number of bytes. + /// \param [in] length Number of bytes to write. + /// \param [out] actual Number of bytes actually written. Will + /// always be less than or equal to the requested length. + /// \return An error condition if writing stopped due to an error. virtual std::error_condition write(void const *buffer, std::size_t length, std::size_t &actual) noexcept = 0; }; +/// \brief Interface to an I/O stream +/// +/// Represents an object that acts as both a source of and sink for byte +/// sequences. +/// \sa read_stream write_stream random_read_write class read_write_stream : public virtual read_stream, public virtual write_stream { public: @@ -58,41 +116,121 @@ public: }; +/// \brief Interface to a byte sequence that supports seeking +/// +/// Provides an interface for controlling the position within a byte +/// sequence that supports seeking. +/// \sa random_read random_write random_read_write class random_access { public: virtual ~random_access() = default; + /// \brief Set the position in the stream + /// + /// Sets the position for the next read or write operation. It may + /// be possible to set the position beyond the end of the stream. + /// \param [in] offset The offset in bytes, relative to the position + /// specified by the whence parameter. + /// \param [in] whence One of SEEK_SET, SEEK_CUR or SEEK_END, to + /// interpret the offset parameter relative to the beginning of + /// the stream, the current position in the stream, or the end of + /// the stream, respectively. + /// \return An error condition of the operation failed. virtual std::error_condition seek(std::int64_t offset, int whence) noexcept = 0; + + /// \brief Get the current position in the stream + /// + /// Gets the position in the stream for the next read or write + /// operation. The position may be beyond the end of the stream. + /// \param [out] result The position in bytes relative to the + /// beginning of the stream. Not valid if the operation fails. + /// \return An error condition if the operation failed. virtual std::error_condition tell(std::uint64_t &result) noexcept = 0; + + /// \brief Get the length of the stream + /// + /// Gets the current length of the stream. + /// \param [out] result The lenght of the stream in bytes. Not + /// valid if the operation fails. + /// \return An error condtion if the operation failed. virtual std::error_condition length(std::uint64_t &result) noexcept = 0; }; +/// \brief Interface to a random-access byte input sequence +/// +/// Provides an interface for reading from aritrary positions within a +/// byte sequence. No further structure is provided. +/// \sa read_stream random_write random_read_write class random_read : public virtual read_stream, public virtual random_access { public: using ptr = std::unique_ptr; + /// \brief Read from specified position + /// + /// Reads up to the specified number of bytes into the supplied + /// buffer. If seeking is supported, reading starts at the + /// specified position and the current position is unaffected. May + /// read less than the requested number of bytes if the end of the + /// stream is encountered or an error occurs. + /// \param [in] offset The position to start reading from, specified + /// as a number of bytes from the beginning of the stream. + /// \param [out] buffer Destination buffer. Must be large enough to + /// hold the requested number of bytes. + /// \param [in] length Maximum number of bytes to read. + /// \param [out] actual Number of bytes actually read. Will always + /// be less than or equal to the requested length. + /// \return An error condition if seeking failed or reading stopped + /// due to an error. virtual std::error_condition read_at(std::uint64_t offset, void *buffer, std::size_t length, std::size_t &actual) noexcept = 0; }; +/// \brief Interface to a random-access byte output sequence +/// +/// Provides an interface for writing to arbitrary positions within a +/// byte sequence. No further structure is provided. +/// \sa write_stream random_read random_read_write class random_write : public virtual write_stream, public virtual random_access { public: using ptr = std::unique_ptr; + /// \brief Write at specified position + /// + /// Writes up to the specified number of bytes from the supplied + /// buffer. If seeking is supported, writing starts at the + /// specified position and the current position is unaffected. May + /// write less than the requested number of bytes if an error + /// occurs. + /// \param [in] offset The position to start writing at, specified + /// as a number of bytes from the beginning of the stream. + /// \param [in] buffer Buffer containing the data to write. Must + /// contain at least the specified number of bytes. + /// \param [in] length Number of bytes to write. + /// \param [out] actual Number of bytes actually written. Will + /// always be less than or equal to the requested length. + /// \return An error condition if seeking failed or writing stopped + /// due to an error. virtual std::error_condition write_at(std::uint64_t offset, void const *buffer, std::size_t length, std::size_t &actual) noexcept = 0; }; +/// \brief Interface to a random-access read/write byte sequence +/// +/// Provides an interface for reading from and writing to arbitrary +/// positions within a byte sequence. No further structure is provided. +/// \sa random_read random_write read_write_stream class random_read_write : public read_write_stream, public virtual random_read, public virtual random_write { public: using ptr = std::unique_ptr; }; +/// \} + random_read::ptr ram_read(void const *data, std::size_t size) noexcept; random_read::ptr ram_read(void const *data, std::size_t size, std::uint8_t filler) noexcept; diff --git a/src/lib/util/path.h b/src/lib/util/path.h index 1291d7b17d3..8638bcb332b 100644 --- a/src/lib/util/path.h +++ b/src/lib/util/path.h @@ -18,15 +18,19 @@ namespace util { -/*************************************************************************** - INLINE FUNCTIONS -***************************************************************************/ - -// is a given character a directory separator? - +/// \defgroup pathutils Filesystem path utilities +/// \{ + +/// \brief Is a character a directory separator? +/// +/// Determine whether a character is used to separate components within +/// a filesystem path. +/// \param [in] c A character to test. +/// \return True if the character is used to separate components in +/// filesystem paths. constexpr bool is_directory_separator(char c) { -#if defined(WIN32) +#if defined(_WIN32) return ('\\' == c) || ('/' == c) || (':' == c); #else return '/' == c; @@ -34,8 +38,15 @@ constexpr bool is_directory_separator(char c) } -// append to a path - +/// \brief Append components to a filesystem path +/// +/// Appends directory components to a filesystem path. +/// \param [in,out] path The path to append to. +/// \param [in] next The first directory component to append to the +/// path. +/// \param [in] more Additional directory components to append to the +/// path. +/// \return A reference to the modified path. template inline std::string &path_append(std::string &path, T &&next, U &&... more) { @@ -49,8 +60,13 @@ inline std::string &path_append(std::string &path, T &&next, U &&... more) } -// concatenate paths - +/// \brief Concatenate filsystem paths +/// +/// Concatenates multiple filesystem paths. +/// \param [in] first Initial filesystem path. +/// \param [in] more Additional directory components to append to the +/// intial path. +/// \return The concatenated filesystem path. template inline std::string path_concat(T &&first, U &&... more) { @@ -60,6 +76,8 @@ inline std::string path_concat(T &&first, U &&... more) return result; } +/// \} + } // namespace util #endif // MAME_LIB_UTIL_PATH_H diff --git a/src/lib/util/unicode.cpp b/src/lib/util/unicode.cpp index a375224fd1e..6787db4a501 100644 --- a/src/lib/util/unicode.cpp +++ b/src/lib/util/unicode.cpp @@ -457,7 +457,7 @@ int utf16f_from_uchar(char16_t *utf16string, size_t count, char32_t uchar) std::wstring wstring_from_utf8(const std::string &utf8string) { -#ifdef WIN32 +#ifdef _WIN32 // for some reason, using codecvt yields bad results on MinGW (but not MSVC) return osd::text::to_wstring(utf8string); #else @@ -473,7 +473,7 @@ std::wstring wstring_from_utf8(const std::string &utf8string) std::string utf8_from_wstring(const std::wstring &string) { -#ifdef WIN32 +#ifdef _WIN32 // for some reason, using codecvt yields bad results on MinGW (but not MSVC) return osd::text::from_wstring(string); #else diff --git a/src/lib/util/zippath.cpp b/src/lib/util/zippath.cpp index 9d2e51a6833..6fad365d6fc 100644 --- a/src/lib/util/zippath.cpp +++ b/src/lib/util/zippath.cpp @@ -48,7 +48,7 @@ int is_path_separator(char c) bool is_root(std::string_view path) { -#if defined(WIN32) +#if defined(_WIN32) // FIXME: don't assume paths are DOS-like - UNC paths, \\?\ long path prefix, etc. complicate this // skip drive letter @@ -58,8 +58,7 @@ bool is_root(std::string_view path) // skip path separators return path.find_first_not_of(PATH_SEPARATOR) == std::string_view::npos; #else - // FIXME: handle multiple successive path separators, current directory references, parent directory references - return (path.length() == 1) && (path[0] == '/'); + return path.find_first_not_of(PATH_SEPARATOR) == std::string_view::npos; #endif } @@ -208,14 +207,11 @@ std::error_condition zippath_resolve(std::string_view path, osd::directory::entr bool went_up = false; do { - if (!is_root(apath)) - { - // trim the path of trailing path separators - auto i = apath.find_last_not_of(PATH_SEPARATOR); - if (i == std::string::npos) - break; - apath = apath.substr(0, i + 1); - } + // trim the path of trailing path separators + auto i = apath.find_last_not_of(PATH_SEPARATOR); + if (i == std::string::npos) + break; + apath = apath.erase(std::min(i + 1, 2)); apath_trimmed = apath; @@ -613,7 +609,7 @@ std::string &zippath_combine(std::string &dst, const std::string &path1, const s { dst.assign(path2); } - else if (!path1.empty() && !is_path_separator(*path1.rbegin())) + else if (!path1.empty() && !is_path_separator(path1.back())) { dst.assign(path1).append(PATH_SEPARATOR).append(path2); } diff --git a/src/mame/audio/dcs.cpp b/src/mame/audio/dcs.cpp index 8ce7402b59e..aeadfc27a21 100644 --- a/src/mame/audio/dcs.cpp +++ b/src/mame/audio/dcs.cpp @@ -693,9 +693,9 @@ dcs_audio_device::dcs_audio_device(const machine_config &mconfig, device_type ty m_channels(0), m_size(0), m_incs(0), - m_reg_timer(nullptr), - m_sport0_timer(nullptr), - m_internal_timer(nullptr), + m_reg_timer(*this, "dcs_reg_timer"), + m_sport0_timer(*this, "dcs_sport0_timer"), + m_internal_timer(*this, "dcs_int_timer"), m_ireg(0), m_ireg_base(0), m_bootrom(nullptr), @@ -790,10 +790,6 @@ void dcs_audio_device::device_start() m_data_bank->configure_entries(0, m_sounddata_banks, m_sounddata, 0x800*2); } - /* create the timers */ - m_internal_timer = subdevice("dcs_int_timer"); - m_reg_timer = subdevice("dcs_reg_timer"); - /* non-RAM based automatically acks */ m_auto_ack = true; /* register for save states */ @@ -882,11 +878,6 @@ void dcs2_audio_device::device_start() /* allocate memory for the SRAM */ m_sram = std::make_unique(0x8000*4/2); - /* create the timers */ - m_internal_timer = subdevice("dcs_int_timer"); - m_reg_timer = subdevice("dcs_reg_timer"); - m_sport0_timer = subdevice("dcs_sport0_timer"); - /* we don't do auto-ack by default */ m_auto_ack = false; @@ -906,14 +897,17 @@ void dcs2_audio_device::device_start() } -void dcs_audio_device::install_speedup(void) +void dcs_audio_device::install_speedup() { - if (m_polling_offset) { - if (m_rev < REV_DSIO) { + if (m_polling_offset) + { + if (m_rev < REV_DSIO) + { m_cpu->space(AS_DATA).install_read_handler(m_polling_offset, m_polling_offset, read16mo_delegate(*this, FUNC(dcs_audio_device::dcs_polling_r))); m_cpu->space(AS_DATA).install_write_handler(m_polling_offset, m_polling_offset, write16s_delegate(*this, FUNC(dcs_audio_device::dcs_polling_w))); } - else { + else + { // ADSP 2181 (DSIO and DENVER) use program memory m_cpu->space(AS_PROGRAM).install_read_handler(m_polling_offset, m_polling_offset, read32mo_delegate(*this, FUNC(dcs_audio_device::dcs_polling32_r))); m_cpu->space(AS_PROGRAM).install_write_handler(m_polling_offset, m_polling_offset, write32s_delegate(*this, FUNC(dcs_audio_device::dcs_polling32_w))); @@ -1560,7 +1554,7 @@ void dcs_audio_device::data_w(uint16_t data) return; /* if we are DCS1, set a timer to latch the data */ - if (m_sport0_timer == nullptr) + if (!m_sport0_timer) machine().scheduler().synchronize(timer_expired_delegate(FUNC(dcs_audio_device::dcs_delayed_data_w_callback),this), data); else dcs_delayed_data_w(data); @@ -1916,15 +1910,18 @@ void dcs_audio_device:: adsp_control_w(offs_t offset, uint16_t data) } // Check SPORT0 enabled - if (m_sport0_timer != nullptr) { - if (data & 0x1000) { + if (m_sport0_timer) + { + if (data & 0x1000) + { // Start the SPORT0 timer // SPORT0 is used as a 1kHz timer m_sport0_timer->adjust(attotime::from_usec(10), 0, attotime::from_hz(1000)); if (LOG_DCS_IO) logerror("adsp_control_w: Setting SPORT0 freqency to 1kHz\n"); } - else { + else + { // Stop the SPORT0 timer m_sport0_timer->reset(); } @@ -2476,7 +2473,7 @@ int dcs_audio_device::preprocess_write(uint16_t data) int result; /* if we're not DCS2, skip */ - if (m_sport0_timer == nullptr) + if (!m_sport0_timer) return 0; /* state 0 - initialization phase */ @@ -2506,8 +2503,8 @@ void dcs_audio_device::add_mconfig_dcs(machine_config &config) dcs.set_addrmap(AS_PROGRAM, &dcs_audio_device::dcs_2k_program_map); dcs.set_addrmap(AS_DATA, &dcs_audio_device::dcs_2k_data_map); - TIMER(config, "dcs_reg_timer").configure_generic(FUNC(dcs_audio_device::dcs_irq)); - TIMER(config, "dcs_int_timer").configure_generic(FUNC(dcs_audio_device::internal_timer_callback)); + TIMER(config, m_reg_timer).configure_generic(FUNC(dcs_audio_device::dcs_irq)); + TIMER(config, m_internal_timer).configure_generic(FUNC(dcs_audio_device::internal_timer_callback)); SPEAKER(config, "mono").front_center(); @@ -2677,9 +2674,9 @@ void dcs2_audio_dsio_device::device_add_mconfig(machine_config &config) ADDRESS_MAP_BANK(config, "data_map_bank").set_map(&dcs2_audio_dsio_device::dsio_rambank_map).set_options(ENDIANNESS_LITTLE, 16, 14, 0x2000); - TIMER(config, "dcs_reg_timer").configure_generic(FUNC(dcs_audio_device::dcs_irq)); - TIMER(config, "dcs_int_timer").configure_generic(FUNC(dcs_audio_device::internal_timer_callback)); - TIMER(config, "dcs_sport0_timer").configure_generic(FUNC(dcs_audio_device::sport0_irq)); // roadburn needs this to pass hardware test + TIMER(config, m_reg_timer).configure_generic(FUNC(dcs_audio_device::dcs_irq)); + TIMER(config, m_internal_timer).configure_generic(FUNC(dcs_audio_device::internal_timer_callback)); + TIMER(config, m_sport0_timer).configure_generic(FUNC(dcs_audio_device::sport0_irq)); // roadburn needs this to pass hardware test SPEAKER(config, "lspeaker").front_left(); SPEAKER(config, "rspeaker").front_right(); @@ -2707,11 +2704,11 @@ void dcs2_audio_denver_device::device_add_mconfig(machine_config &config) denver.set_addrmap(AS_DATA, &dcs2_audio_denver_device::denver_data_map); denver.set_addrmap(AS_IO, &dcs2_audio_denver_device::denver_io_map); - ADDRESS_MAP_BANK(config, "data_map_bank").set_map(&dcs2_audio_denver_device::denver_rambank_map).set_options(ENDIANNESS_LITTLE, 16, 15, 0x2000*2); + ADDRESS_MAP_BANK(config, m_ram_map).set_map(&dcs2_audio_denver_device::denver_rambank_map).set_options(ENDIANNESS_LITTLE, 16, 15, 0x2000*2); - TIMER(config, "dcs_reg_timer").configure_generic(FUNC(dcs_audio_device::dcs_irq)); - TIMER(config, "dcs_int_timer").configure_generic(FUNC(dcs_audio_device::internal_timer_callback)); - TIMER(config, "dcs_sport0_timer").configure_generic(FUNC(dcs_audio_device::sport0_irq)); // Atlantis driver waits for sport0 rx interrupts + TIMER(config, m_reg_timer).configure_generic(FUNC(dcs_audio_device::dcs_irq)); + TIMER(config, m_internal_timer).configure_generic(FUNC(dcs_audio_device::internal_timer_callback)); + TIMER(config, m_sport0_timer).configure_generic(FUNC(dcs_audio_device::sport0_irq)); // Atlantis driver waits for sport0 rx interrupts } dcs2_audio_denver_5ch_device::dcs2_audio_denver_5ch_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : diff --git a/src/mame/audio/dcs.h b/src/mame/audio/dcs.h index 0cebee16dec..38bd283a768 100644 --- a/src/mame/audio/dcs.h +++ b/src/mame/audio/dcs.h @@ -44,8 +44,8 @@ public: uint32_t dsio_idma_data_r(); void dmovlay_remap_memory(); void dmovlay_callback(uint32_t data); - void denver_postload(void); - void install_speedup(void); + void denver_postload(); + void install_speedup(); // non public void dcs_boot(); @@ -63,7 +63,7 @@ public: void dsio_reset(); uint16_t dsio_r(offs_t offset); void dsio_w(offs_t offset, uint16_t data); - void denver_alloc_dmadac(void); + void denver_alloc_dmadac(); void denver_reset(); uint16_t denver_r(offs_t offset); void denver_w(offs_t offset, uint16_t data); @@ -181,9 +181,9 @@ protected: uint16_t m_size; uint16_t m_incs; dmadac_sound_device *m_dmadac[6]; - timer_device *m_reg_timer; - timer_device *m_sport0_timer; - timer_device *m_internal_timer; + required_device m_reg_timer; + optional_device m_sport0_timer; + required_device m_internal_timer; int32_t m_ireg; uint16_t m_ireg_base; uint16_t m_control_regs[32]; diff --git a/src/mame/audio/m72.h b/src/mame/audio/m72.h index be4a31ce2fb..bf6995c10a6 100644 --- a/src/mame/audio/m72.h +++ b/src/mame/audio/m72.h @@ -10,9 +10,11 @@ #pragma once -#include "dirom.h" #include "sound/dac.h" +#include "dirom.h" + + class m72_audio_device : public device_t, public device_rom_interface<32> // unknown address bits { public: diff --git a/src/mame/drivers/apple2e.cpp b/src/mame/drivers/apple2e.cpp index d0279537c2c..4a0b7119b64 100644 --- a/src/mame/drivers/apple2e.cpp +++ b/src/mame/drivers/apple2e.cpp @@ -3222,19 +3222,20 @@ u8 apple2e_state::read_floatingbus() ADDRESS MAP ***************************************************************************/ -u8 apple2e_state::ram0000_r(offs_t offset) { return m_ram_ptr[offset]; } +u8 apple2e_state::ram0000_r(offs_t offset) { return m_ram_ptr[offset]; } void apple2e_state::ram0000_w(offs_t offset, u8 data) { m_ram_ptr[offset] = data; } -u8 apple2e_state::ram0200_r(offs_t offset) { return m_ram_ptr[offset+0x200]; } +u8 apple2e_state::ram0200_r(offs_t offset) { return m_ram_ptr[offset+0x200]; } void apple2e_state::ram0200_w(offs_t offset, u8 data) { m_ram_ptr[offset+0x200] = data; } -u8 apple2e_state::ram0400_r(offs_t offset) { return m_ram_ptr[offset+0x400]; } +u8 apple2e_state::ram0400_r(offs_t offset) { return m_ram_ptr[offset+0x400]; } void apple2e_state::ram0400_w(offs_t offset, u8 data) { m_ram_ptr[offset+0x400] = data; } -u8 apple2e_state::ram0800_r(offs_t offset) { return m_ram_ptr[offset+0x800]; } +u8 apple2e_state::ram0800_r(offs_t offset) { return m_ram_ptr[offset+0x800]; } void apple2e_state::ram0800_w(offs_t offset, u8 data) { m_ram_ptr[offset+0x800] = data; } -u8 apple2e_state::ram2000_r(offs_t offset) { return m_ram_ptr[offset+0x2000]; } +u8 apple2e_state::ram2000_r(offs_t offset) { return m_ram_ptr[offset+0x2000]; } void apple2e_state::ram2000_w(offs_t offset, u8 data) { m_ram_ptr[offset+0x2000] = data; } -u8 apple2e_state::ram4000_r(offs_t offset) { return m_ram_ptr[offset+0x4000]; } +u8 apple2e_state::ram4000_r(offs_t offset) { return m_ram_ptr[offset+0x4000]; } void apple2e_state::ram4000_w(offs_t offset, u8 data) { m_ram_ptr[offset+0x4000] = data; } void apple2e_state::ram8000_w(offs_t offset, u8 data) { m_ram_ptr[offset+0x8000] = data; } + u8 apple2e_state::cec4000_r(offs_t offset) { //printf("cec4000_r: ofs %x\n", offset); @@ -3254,17 +3255,17 @@ u8 apple2e_state::cec8000_r(offs_t offset) } } -u8 apple2e_state::auxram0000_r(offs_t offset) { if (m_aux_bank_ptr) { return m_aux_bank_ptr[offset]; } else { return read_floatingbus(); } } +u8 apple2e_state::auxram0000_r(offs_t offset) { if (m_aux_bank_ptr) { return m_aux_bank_ptr[offset]; } else { return read_floatingbus(); } } void apple2e_state::auxram0000_w(offs_t offset, u8 data) { if (m_aux_bank_ptr) { m_aux_bank_ptr[offset] = data; } } -u8 apple2e_state::auxram0200_r(offs_t offset) { if (m_aux_bank_ptr) { return m_aux_bank_ptr[offset+0x200]; } else { return read_floatingbus(); } } +u8 apple2e_state::auxram0200_r(offs_t offset) { if (m_aux_bank_ptr) { return m_aux_bank_ptr[offset+0x200]; } else { return read_floatingbus(); } } void apple2e_state::auxram0200_w(offs_t offset, u8 data) { if (m_aux_bank_ptr) { m_aux_bank_ptr[offset+0x200] = data; } } -u8 apple2e_state::auxram0400_r(offs_t offset) { if (m_aux_bank_ptr) { return m_aux_bank_ptr[offset+0x400]; } else { return read_floatingbus(); } } +u8 apple2e_state::auxram0400_r(offs_t offset) { if (m_aux_bank_ptr) { return m_aux_bank_ptr[offset+0x400]; } else { return read_floatingbus(); } } void apple2e_state::auxram0400_w(offs_t offset, u8 data) { if (m_aux_bank_ptr) { m_aux_bank_ptr[offset+0x400] = data; } } -u8 apple2e_state::auxram0800_r(offs_t offset) { if (m_aux_bank_ptr) { return m_aux_bank_ptr[offset+0x800]; } else { return read_floatingbus(); } } +u8 apple2e_state::auxram0800_r(offs_t offset) { if (m_aux_bank_ptr) { return m_aux_bank_ptr[offset+0x800]; } else { return read_floatingbus(); } } void apple2e_state::auxram0800_w(offs_t offset, u8 data) { if (m_aux_bank_ptr) { m_aux_bank_ptr[offset+0x800] = data; } } -u8 apple2e_state::auxram2000_r(offs_t offset) { if (m_aux_bank_ptr) { return m_aux_bank_ptr[offset+0x2000]; } else { return read_floatingbus(); } } +u8 apple2e_state::auxram2000_r(offs_t offset) { if (m_aux_bank_ptr) { return m_aux_bank_ptr[offset+0x2000]; } else { return read_floatingbus(); } } void apple2e_state::auxram2000_w(offs_t offset, u8 data) { if (m_aux_bank_ptr) { m_aux_bank_ptr[offset+0x2000] = data; } } -u8 apple2e_state::auxram4000_r(offs_t offset) { if (m_aux_bank_ptr) { return m_aux_bank_ptr[offset+0x4000]; } else { return read_floatingbus(); } } +u8 apple2e_state::auxram4000_r(offs_t offset) { if (m_aux_bank_ptr) { return m_aux_bank_ptr[offset+0x4000]; } else { return read_floatingbus(); } } void apple2e_state::auxram4000_w(offs_t offset, u8 data) { if (m_aux_bank_ptr) { m_aux_bank_ptr[offset+0x4000] = data; } } void apple2e_state::apple2e_map(address_map &map) diff --git a/src/mame/drivers/applix.cpp b/src/mame/drivers/applix.cpp index 4002406aa4c..c9e15828714 100644 --- a/src/mame/drivers/applix.cpp +++ b/src/mame/drivers/applix.cpp @@ -462,7 +462,7 @@ void applix_state::main_mem(address_map &map) map(0x500000, 0x51ffff).rom().region("maincpu", 0); map(0x600000, 0x60007f).w(FUNC(applix_state::palette_w)); map(0x600080, 0x6000ff).w(FUNC(applix_state::dac_latch_w)); - map(0x600100, 0x60017f).w(FUNC(applix_state::video_latch_w)); //video latch (=border colour, high nibble; video base, low nibble) (odd) + map(0x600100, 0x60017f).w(FUNC(applix_state::video_latch_w)); //video latch (=border colour, high nybble; video base, low nybble) (odd) map(0x600180, 0x6001ff).w(FUNC(applix_state::analog_latch_w)); map(0x700000, 0x700007).mirror(0x78).rw("scc", FUNC(scc8530_device::ab_dc_r), FUNC(scc8530_device::ab_dc_w)).umask16(0xff00).cswidth(16); map(0x700080, 0x7000ff).r(FUNC(applix_state::applix_inputs_r)); diff --git a/src/mame/drivers/bigbord2.cpp b/src/mame/drivers/bigbord2.cpp index cd01639c220..144cfc293d4 100644 --- a/src/mame/drivers/bigbord2.cpp +++ b/src/mame/drivers/bigbord2.cpp @@ -71,6 +71,7 @@ X - change banks #include "emu.h" + #include "cpu/z80/z80.h" #include "imagedev/floppy.h" #include "machine/z80daisy.h" @@ -83,11 +84,14 @@ X - change banks #include "machine/z80sio.h" #include "sound/beep.h" #include "video/mc6845.h" + #include "emupal.h" #include "screen.h" #include "speaker.h" +namespace { + class bigbord2_state : public driver_device { public: @@ -334,11 +338,11 @@ void bigbord2_state::syslatch2_w(u8 data) void bigbord2_state::mem_map(address_map &map) { map.unmap_value_high(); - map(0x0000, 0x5fff).bankr("bankr").bankw("bankw"); - map(0x6000, 0x67ff).bankrw("bankv"); - map(0x6800, 0x6fff).bankrw("bankv1"); - map(0x7000, 0x77ff).bankrw("banka"); - map(0x7800, 0x7fff).bankrw("banka1"); + map(0x0000, 0x5fff).bankr(m_bankr).bankw(m_bankw); + map(0x6000, 0x67ff).bankrw(m_bankv); + map(0x6800, 0x6fff).bankrw(m_bankv1); + map(0x7000, 0x77ff).bankrw(m_banka); + map(0x7800, 0x7fff).bankrw(m_banka1); map(0x8000, 0xffff).ram(); } @@ -627,6 +631,7 @@ void bigbord2_state::bigbord2(machine_config &config) MB8877(config, m_fdc, 16_MHz_XTAL / 8); // U10 : 2MHz for 8 inch, or 1MHz otherwise (jumper-selectable) //m_fdc->intrq_wr_callback().set_inputline(m_maincpu, ??); // info missing from schematic + m_fdc->drq_wr_callback().set(FUNC(bigbord2_state::fdc_drq_w)); FLOPPY_CONNECTOR(config, "fdc:0", bigbord2_floppies, "8dsdd", floppy_image_device::default_mfm_floppy_formats).enable_sound(true); FLOPPY_CONNECTOR(config, "fdc:1", bigbord2_floppies, "8dsdd", floppy_image_device::default_mfm_floppy_formats).enable_sound(true); @@ -670,7 +675,6 @@ void bigbord2_state::bigbord2(machine_config &config) /* ROMs */ - ROM_START( bigbord2 ) // for optional roms and eproms ROM_REGION( 0x6000, "maincpu", ROMREGION_ERASEFF ) @@ -683,6 +687,10 @@ ROM_START( bigbord2 ) ROM_LOAD( "pal16l8.u23", 0x0000, 0x0400, NO_DUMP ) ROM_LOAD( "pal10l8.u34", 0x0400, 0x0400, NO_DUMP ) ROM_END + +} // anonymous namespace + + /* System Drivers */ // YEAR NAME PARENT COMPAT MACHINE INPUT CLASS INIT COMPANY FULLNAME FLAGS diff --git a/src/mame/drivers/calchase.cpp b/src/mame/drivers/calchase.cpp index d67a94fa8b5..eed6b695b0d 100644 --- a/src/mame/drivers/calchase.cpp +++ b/src/mame/drivers/calchase.cpp @@ -131,6 +131,7 @@ something wrong in the disk geometry reported by calchase.chd (20,255,63) since #include "emu.h" + #include "bus/isa/trident.h" #include "cpu/i386/i386.h" #include "machine/lpci.h" @@ -141,6 +142,7 @@ something wrong in the disk geometry reported by calchase.chd (20,255,63) since #include "machine/nvram.h" #include "sound/dac.h" #include "video/pc_vga.h" + #include "screen.h" #include "speaker.h" @@ -176,11 +178,6 @@ private: void bios_ram_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0); uint8_t nvram_r(offs_t offset); void nvram_w(offs_t offset, uint8_t data); - uint16_t calchase_iocard1_r(); - uint16_t calchase_iocard2_r(); - uint16_t calchase_iocard3_r(); - uint16_t calchase_iocard4_r(); - uint16_t calchase_iocard5_r(); uint32_t calchase_idle_skip_r(); void calchase_idle_skip_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0); @@ -380,32 +377,6 @@ void calchase_state::nvram_w(offs_t offset, uint8_t data) m_nvram_data[offset] = data; } -uint16_t calchase_state::calchase_iocard1_r() -{ - return ioport("IOCARD1")->read(); -} - -uint16_t calchase_state::calchase_iocard2_r() -{ - return ioport("IOCARD2")->read(); -} - -uint16_t calchase_state::calchase_iocard3_r() -{ - return ioport("IOCARD3")->read(); -} - -/* These two controls wheel pot or whatever this game uses ... */ -uint16_t calchase_state::calchase_iocard4_r() -{ - return ioport("IOCARD4")->read(); -} - -uint16_t calchase_state::calchase_iocard5_r() -{ - return ioport("IOCARD5")->read(); -} - void calchase_state::calchase_map(address_map &map) { @@ -414,11 +385,11 @@ void calchase_state::calchase_map(address_map &map) map(0x000c0000, 0x000c7fff).rom().region("video_bios", 0); map(0x000c8000, 0x000cffff).noprw(); //map(0x000d0000, 0x000d0003).ram(); // XYLINX - Sincronus serial communication - map(0x000d0004, 0x000d0005).r(FUNC(calchase_state::calchase_iocard1_r)); - map(0x000d000c, 0x000d000d).r(FUNC(calchase_state::calchase_iocard2_r)); - map(0x000d0032, 0x000d0033).r(FUNC(calchase_state::calchase_iocard3_r)); - map(0x000d0030, 0x000d0031).r(FUNC(calchase_state::calchase_iocard4_r)); - map(0x000d0034, 0x000d0035).r(FUNC(calchase_state::calchase_iocard5_r)); + map(0x000d0004, 0x000d0005).portr("IOCARD1"); + map(0x000d000c, 0x000d000d).portr("IOCARD2"); + map(0x000d0032, 0x000d0033).portr("IOCARD3"); + map(0x000d0030, 0x000d0031).portr("IOCARD4"); // These two controls wheel pot or whatever this game uses ... + map(0x000d0034, 0x000d0035).portr("IOCARD5"); map(0x000d0008, 0x000d000b).nopw(); // ??? map(0x000d0024, 0x000d0025).w("ldac", FUNC(dac_word_interface::data_w)); map(0x000d0028, 0x000d0029).w("rdac", FUNC(dac_word_interface::data_w)); @@ -496,6 +467,7 @@ static INPUT_PORTS_START( calchase ) PORT_DIPSETTING( 0x0080, DEF_STR( Off ) ) PORT_DIPSETTING( 0x0000, DEF_STR( On ) ) PORT_BIT( 0xff00, IP_ACTIVE_LOW, IPT_UNUSED ) + PORT_START("IOCARD2") PORT_BIT( 0x0001, IP_ACTIVE_LOW, IPT_SERVICE1 ) // guess PORT_BIT( 0x0002, IP_ACTIVE_LOW, IPT_SERVICE2 ) PORT_NAME("Reset SW") @@ -514,6 +486,7 @@ static INPUT_PORTS_START( calchase ) PORT_BIT( 0x0040, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_NAME("Turbo") PORT_BIT( 0x0080, IP_ACTIVE_LOW, IPT_UNKNOWN ) // returns back to MS-DOS (likely to be unmapped and actually used as a lame protection check) PORT_BIT( 0xff00, IP_ACTIVE_LOW, IPT_UNUSED ) + PORT_START("IOCARD3") PORT_BIT( 0x2000, IP_ACTIVE_LOW, IPT_CUSTOM ) PORT_VBLANK("screen") PORT_BIT( 0xdfff, IP_ACTIVE_LOW, IPT_UNUSED ) @@ -565,6 +538,7 @@ static INPUT_PORTS_START( calchase ) PORT_DIPNAME( 0x8000, 0x8000, DEF_STR( Unknown ) ) PORT_DIPSETTING( 0x8000, DEF_STR( Off ) ) PORT_DIPSETTING( 0x0000, DEF_STR( On ) ) + PORT_START("IOCARD5") PORT_DIPNAME( 0x01, 0x01, "DSWA" ) PORT_DIPSETTING( 0x01, DEF_STR( Off ) ) diff --git a/src/mame/drivers/ccs2810.cpp b/src/mame/drivers/ccs2810.cpp index 704d856500c..339ed5f04a5 100644 --- a/src/mame/drivers/ccs2810.cpp +++ b/src/mame/drivers/ccs2810.cpp @@ -99,6 +99,8 @@ ToDo: #include "machine/z80sio.h" +namespace { + class ccs_state : public driver_device { public: @@ -121,6 +123,9 @@ public: void ccs2422(machine_config &config); protected: + void machine_start() override; + void machine_reset() override; + u8 port04_r(); u8 port34_r(); void port04_w(u8 data); @@ -150,9 +155,6 @@ private: u8 io_read(offs_t offset); void io_write(offs_t offset, u8 data); - void machine_start() override; - void machine_reset() override; - void port40_w(u8 data); void ccs2422_io(address_map &map); @@ -173,9 +175,11 @@ public: void ccs300(machine_config &config); -private: +protected: void machine_start() override; void machine_reset() override; + +private: void ccs300_io(address_map &map); void ccs300_mem(address_map &map); void port40_w(u8 data); @@ -978,6 +982,7 @@ void ccs300_state::machine_start() { m_bank1->configure_entry(0, m_ram1); m_bank1->configure_entry(1, m_rom); + save_item(NAME(m_ss)); save_item(NAME(m_dden)); save_item(NAME(m_dsize)); @@ -1139,9 +1144,12 @@ ROM_START( ccs300 ) ROM_LOAD( "ccs300.rom", 0x0000, 0x0800, CRC(6cf22e31) SHA1(9aa3327cd8c23d0eab82cb6519891aff13ebe1d0)) ROM_END +} // anonymous namespace + + /* Driver */ -/* YEAR NAME PARENT COMPAT MACHINE INPUT CLASS INIT COMPANY FULLNAME FLAGS */ +// YEAR NAME PARENT COMPAT MACHINE INPUT CLASS INIT COMPANY FULLNAME FLAGS COMP( 1980, ccs2810, 0, 0, ccs2810, ccs2810, ccs_state, empty_init, "California Computer Systems", "CCS Model 2810 CPU card", MACHINE_NO_SOUND_HW | MACHINE_SUPPORTS_SAVE ) COMP( 1980, ccs2422, ccs2810, 0, ccs2422, ccs2810, ccs_state, empty_init, "California Computer Systems", "CCS Model 2422B FDC card", MACHINE_NOT_WORKING | MACHINE_NO_SOUND_HW | MACHINE_SUPPORTS_SAVE ) -COMP( 1981, ccs300, ccs2810, 0, ccs300, ccs300, ccs300_state, empty_init, "California Computer Systems", "CCS Model 300", MACHINE_NOT_WORKING | MACHINE_NO_SOUND_HW | MACHINE_SUPPORTS_SAVE ) +COMP( 1981, ccs300, ccs2810, 0, ccs300, ccs300, ccs300_state, empty_init, "California Computer Systems", "CCS Model 300", MACHINE_NOT_WORKING | MACHINE_NO_SOUND_HW | MACHINE_SUPPORTS_SAVE ) diff --git a/src/mame/drivers/cops.cpp b/src/mame/drivers/cops.cpp index 52d4d37d927..ac23064fdf7 100644 --- a/src/mame/drivers/cops.cpp +++ b/src/mame/drivers/cops.cpp @@ -31,12 +31,14 @@ #include "emu.h" + #include "cpu/m6502/m6502.h" #include "machine/6522via.h" -#include "sound/sn76496.h" -#include "machine/msm6242.h" #include "machine/ldp1450.h" #include "machine/mos6551.h" +#include "machine/msm6242.h" +#include "sound/sn76496.h" + #include "speaker.h" #include "cops.lh" @@ -60,6 +62,9 @@ public: , m_maincpu(*this, "maincpu") , m_sn(*this, "snsnd") , m_ld(*this, "laserdisc") + , m_switches(*this, "SW%u", 0U) + , m_steer(*this, "STEER") + , m_digits(*this, "digit%u", 0U) , m_irq(0) { } @@ -83,6 +88,9 @@ private: required_device m_maincpu; required_device m_sn; required_device m_ld; + required_ioport_array<3> m_switches; + optional_ioport m_steer; + output_finder<16> m_digits; // screen updates [[maybe_unused]] uint32_t screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect); @@ -581,11 +589,11 @@ uint8_t cops_state::io1_r(offs_t offset) switch( offset & 0x0f ) { case 0x08: /* SW0 */ - return ioport("SW0")->read(); + return m_switches[0]->read(); case 0x09: /* SW1 */ - return ioport("SW1")->read(); + return m_switches[1]->read(); case 0x0a: /* SW2 */ - return ioport("SW2")->read(); + return m_switches[2]->read(); default: logerror("Unknown io1_r, offset = %03x\n", offset); return 0; @@ -599,11 +607,11 @@ uint8_t cops_state::io1_lm_r(offs_t offset) case 0x07: /* WDI */ return 1; case 0x08: /* SW0 */ - return ioport("SW0")->read(); + return m_switches[0]->read(); case 0x09: /* SW1 */ - return ioport("SW1")->read(); + return m_switches[1]->read(); case 0x0a: /* SW2 */ - return ioport("SW2")->read(); + return m_switches[2]->read(); default: logerror("Unknown io1_r, offset = %03x\n", offset); return 0; @@ -612,11 +620,7 @@ uint8_t cops_state::io1_lm_r(offs_t offset) void cops_state::io1_w(offs_t offset, uint8_t data) { - int i; - char output_name[16]; - uint16_t display_data; - - switch( offset & 0x0f ) + switch (offset & 0x0f) { case 0x00: /* WOP0 Alpha display*/ m_lcd_addr_l = data; @@ -625,24 +629,19 @@ void cops_state::io1_w(offs_t offset, uint8_t data) m_lcd_addr_h = data; { // update display - const uint16_t addrs_table[] = { 0x0004, 0x0008, 0x0010, 0x0020, 0x0040, 0x0002, 0x0001, 0x0080, - 0x1000, 0x0800, 0x0400, 0x2000, 0x4000, 0x0200, 0x0100, 0x8000 }; - uint16_t addr = m_lcd_addr_l | (m_lcd_addr_h << 8); - for (i = 0; i < 16; i++ ) + constexpr uint16_t addrs_table[] = { + 0x0004, 0x0008, 0x0010, 0x0020, 0x0040, 0x0002, 0x0001, 0x0080, + 0x1000, 0x0800, 0x0400, 0x2000, 0x4000, 0x0200, 0x0100, 0x8000 }; + const uint16_t addr = m_lcd_addr_l | (m_lcd_addr_h << 8); + for (int i = 0; i < 16; i++) { if (addr == addrs_table[i]) { + const uint16_t display_data = m_lcd_data_l | (m_lcd_data_h << 8); + m_digits[i] = bitswap<16>(display_data, 4, 5, 12, 1, 0, 11, 10, 6, 7, 2, 9, 3, 15, 8, 14, 13); break; } } - - if (i < 16) - { - sprintf(output_name, "digit%d", i); - display_data = m_lcd_data_l | (m_lcd_data_h << 8); - display_data = bitswap<16>(display_data, 4, 5, 12, 1, 0, 11, 10, 6, 7, 2, 9, 3, 15, 8, 14, 13); - output().set_value(output_name, display_data); - } } break; case 0x02: /* WOP2 Alpha display*/ @@ -690,7 +689,7 @@ uint8_t cops_state::io2_r(offs_t offset) switch( offset & 0x0f ) { case 0x03: - return ioport("STEER")->read(); + return m_steer->read(); default: logerror("Unknown io2_r, offset = %02x\n", offset); return 0; @@ -871,11 +870,12 @@ static INPUT_PORTS_START( revlatns ) PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_CUSTOM ) PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_CUSTOM ) PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_CUSTOM ) - INPUT_PORTS_END void cops_state::machine_start() { + m_digits.resolve(); + m_ld_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(cops_state::ld_timer_callback),this)); m_ld_timer->adjust(attotime::from_hz(167*5), 0, attotime::from_hz(167*5)); @@ -941,6 +941,7 @@ void cops_state::base(machine_config &config) void cops_state::cops(machine_config &config) { base(config); + m_maincpu->set_addrmap(AS_PROGRAM, &cops_state::cops_map); via6522_device &via2(MOS6522(config, "via6522_2", MAIN_CLOCK/2)); @@ -955,6 +956,7 @@ void cops_state::cops(machine_config &config) void cops_state::revlatns(machine_config &config) { base(config); + m_maincpu->set_addrmap(AS_PROGRAM, &cops_state::revlatns_map); MSM6242(config, "rtc", XTAL(32'768)); diff --git a/src/mame/drivers/cortex.cpp b/src/mame/drivers/cortex.cpp index e5f2774683f..4b4a7b85d8a 100644 --- a/src/mame/drivers/cortex.cpp +++ b/src/mame/drivers/cortex.cpp @@ -44,16 +44,20 @@ packed into a single address-byte (CRU 0 = bit 0, etc). So the address is ****************************************************************************/ - #include "emu.h" + #include "cpu/tms9900/tms9995.h" #include "machine/74259.h" -#include "video/tms9928a.h" -//#include "machine/tms9902.h" #include "machine/keyboard.h" +//#include "machine/tms9902.h" +#include "video/tms9928a.h" #include "sound/beep.h" + #include "speaker.h" + +namespace { + class cortex_state : public driver_device { public: @@ -69,6 +73,10 @@ public: void cortex(machine_config &config); +protected: + virtual void machine_start() override; + virtual void machine_reset() override; + private: void kbd_put(u8 data); DECLARE_WRITE_LINE_MEMBER(keyboard_ack_w); @@ -76,13 +84,13 @@ private: DECLARE_WRITE_LINE_MEMBER(vdp_int_w); u8 pio_r(offs_t offset); u8 keyboard_r(offs_t offset); + void io_map(address_map &map); void mem_map(address_map &map); + bool m_kbd_ack; bool m_vdp_int; u8 m_term_data; - void machine_reset() override; - void machine_start() override; required_device m_maincpu; required_region_ptr m_rom; required_shared_ptr m_ram; @@ -93,7 +101,7 @@ private: void cortex_state::mem_map(address_map &map) { - map(0x0000, 0x7fff).ram().share("mainram").bankr("bank1"); + map(0x0000, 0x7fff).ram().share(m_ram).bankr(m_bank1); map(0x8000, 0xefff).ram(); map(0xf100, 0xf11f).ram(); // memory mapping unit map(0xf120, 0xf121).rw("crtc", FUNC(tms9928a_device::read), FUNC(tms9928a_device::write)); @@ -245,6 +253,9 @@ ROM_START( cortex ) ROMX_LOAD( "forth.ic46", 0x2000, 0x2000, CRC(8eca54cc) SHA1(0f1680e941ef60bb9bde9a4b843b78f30dff3202), ROM_BIOS(1)) ROM_END +} // anonymous namespace + + /* Driver */ // YEAR NAME PARENT COMPAT MACHINE INPUT CLASS INIT COMPANY FULLNAME FLAGS diff --git a/src/mame/drivers/cvicny.cpp b/src/mame/drivers/cvicny.cpp index b73d9852482..dc2752e7f16 100644 --- a/src/mame/drivers/cvicny.cpp +++ b/src/mame/drivers/cvicny.cpp @@ -34,6 +34,9 @@ Test Paste: #include "video/pwm.h" #include "cvicny.lh" + +namespace { + class cvicny_state : public driver_device { public: @@ -42,16 +45,19 @@ public: , m_maincpu(*this, "maincpu") , m_display(*this, "display") , m_io_keyboard(*this, "X%u", 0U) - { } + { } void cvicny(machine_config &config); +protected: + virtual void machine_start() override; + private: void cvicny_mem(address_map &map); - virtual void machine_start() override; u8 key_r(); void digit_w(u8 data); void segment_w(u8 data); + u8 m_digit; u8 m_seg; required_device m_maincpu; @@ -155,6 +161,9 @@ ROM_START( cvicny ) ROM_LOAD("cvicny8080.bin", 0x0000, 0x05ea, CRC(e6119052) SHA1(d03c2cbfd047f0d090a787fbbde6353593cc2dd8) ) ROM_END +} // anonymous namespace + + /* Driver */ // YEAR NAME PARENT COMPAT MACHINE INPUT CLASS INIT COMPANY FULLNAME FLAGS diff --git a/src/mame/drivers/cz101.cpp b/src/mame/drivers/cz101.cpp index 122e0e86a0b..a10bf9c7537 100644 --- a/src/mame/drivers/cz101.cpp +++ b/src/mame/drivers/cz101.cpp @@ -25,6 +25,8 @@ #include "cz101.lh" +namespace { + //************************************************************************** // TYPE DEFINITIONS //************************************************************************** @@ -266,50 +268,50 @@ HD44780_PIXEL_UPDATE( cz101_state::lcd_pixel_update ) void cz101_state::led_4_w(uint8_t data) { - m_leds[0] = BIT(data, 7) ? 0 : 1; - m_leds[1] = BIT(data, 6) ? 0 : 1; - m_leds[2] = BIT(data, 5) ? 0 : 1; - m_leds[3] = BIT(data, 4) ? 0 : 1; - m_leds[4] = BIT(data, 3) ? 0 : 1; - m_leds[5] = BIT(data, 2) ? 0 : 1; - m_leds[6] = BIT(data, 1) ? 0 : 1; - m_leds[7] = BIT(data, 0) ? 0 : 1; + m_leds[0] = BIT(~data, 7); + m_leds[1] = BIT(~data, 6); + m_leds[2] = BIT(~data, 5); + m_leds[3] = BIT(~data, 4); + m_leds[4] = BIT(~data, 3); + m_leds[5] = BIT(~data, 2); + m_leds[6] = BIT(~data, 1); + m_leds[7] = BIT(~data, 0); } void cz101_state::led_3_w(uint8_t data) { - m_leds[8] = BIT(data, 7) ? 0 : 1; - m_leds[9] = BIT(data, 6) ? 0 : 1; - m_leds[10] = BIT(data, 5) ? 0 : 1; - m_leds[11] = BIT(data, 4) ? 0 : 1; - m_leds[12] = BIT(data, 3) ? 0 : 1; - m_leds[13] = BIT(data, 2) ? 0 : 1; - m_leds[14] = BIT(data, 1) ? 0 : 1; - m_leds[15] = BIT(data, 0) ? 0 : 1; + m_leds[8] = BIT(~data, 7); + m_leds[9] = BIT(~data, 6); + m_leds[10] = BIT(~data, 5); + m_leds[11] = BIT(~data, 4); + m_leds[12] = BIT(~data, 3); + m_leds[13] = BIT(~data, 2); + m_leds[14] = BIT(~data, 1); + m_leds[15] = BIT(~data, 0); } void cz101_state::led_2_w(uint8_t data) { - m_leds[16] = BIT(data, 7) ? 0 : 1; - m_leds[17] = BIT(data, 6) ? 0 : 1; - m_leds[18] = BIT(data, 5) ? 0 : 1; - m_leds[19] = BIT(data, 4) ? 0 : 1; - m_leds[20] = BIT(data, 3) ? 0 : 1; - m_leds[21] = BIT(data, 2) ? 0 : 1; - m_leds[22] = BIT(data, 1) ? 0 : 1; - m_leds[23] = BIT(data, 0) ? 0 : 1; + m_leds[16] = BIT(~data, 7); + m_leds[17] = BIT(~data, 6); + m_leds[18] = BIT(~data, 5); + m_leds[19] = BIT(~data, 4); + m_leds[20] = BIT(~data, 3); + m_leds[21] = BIT(~data, 2); + m_leds[22] = BIT(~data, 1); + m_leds[23] = BIT(~data, 0); } void cz101_state::led_1_w(uint8_t data) { - m_leds[24] = BIT(data, 7) ? 0 : 1; - m_leds[25] = BIT(data, 6) ? 0 : 1; - m_leds[26] = BIT(data, 5) ? 0 : 1; - m_leds[27] = BIT(data, 4) ? 0 : 1; - m_leds[28] = BIT(data, 3) ? 0 : 1; - m_leds[29] = BIT(data, 2) ? 0 : 1; - m_leds[30] = BIT(data, 1) ? 0 : 1; - m_leds[31] = BIT(data, 0) ? 0 : 1; + m_leds[24] = BIT(~data, 7); + m_leds[25] = BIT(~data, 6); + m_leds[26] = BIT(~data, 5); + m_leds[27] = BIT(~data, 4); + m_leds[28] = BIT(~data, 3); + m_leds[29] = BIT(~data, 2); + m_leds[30] = BIT(~data, 1); + m_leds[31] = BIT(~data, 0); } uint8_t cz101_state::keys_r() @@ -412,6 +414,8 @@ ROM_START( cz101 ) ROM_LOAD("5f3_s40.bin", 0x0000, 0x8000, CRC(c417bc57) SHA1(2aa5bfb76dc0a56797cf5dd547197816cedfa370)) ROM_END +} // anonymous namespace + //************************************************************************** // SYSTEM DRIVERS diff --git a/src/mame/drivers/dps1.cpp b/src/mame/drivers/dps1.cpp index 0b1707f3292..d4a30cde501 100644 --- a/src/mame/drivers/dps1.cpp +++ b/src/mame/drivers/dps1.cpp @@ -23,6 +23,9 @@ ToDo: //#include "bus/s100/s100.h" #include "softlist.h" + +namespace { + class dps1_state : public driver_device { public: @@ -39,9 +42,11 @@ public: void dps1(machine_config &config); +protected: + virtual void machine_start() override; + virtual void machine_reset() override; + private: - void machine_reset() override; - void machine_start() override; void portb2_w(u8 data); void portb4_w(u8 data); void portb6_w(u8 data); @@ -55,6 +60,7 @@ private: void io_map(address_map &map); void mem_map(address_map &map); + bool m_dma_dir; u16 m_dma_adr; required_device m_maincpu; @@ -68,8 +74,8 @@ private: void dps1_state::mem_map(address_map &map) { - map(0x0000, 0xffff).ram().share("mainram"); - map(0x0000, 0x03ff).bankr("bank1"); + map(0x0000, 0xffff).ram().share(m_ram); + map(0x0000, 0x03ff).bankr(m_bank1); } void dps1_state::io_map(address_map &map) @@ -176,6 +182,7 @@ void dps1_state::machine_start() { m_bank1->configure_entry(0, m_ram); m_bank1->configure_entry(1, m_rom); + save_item(NAME(m_dma_dir)); save_item(NAME(m_dma_adr)); } @@ -236,4 +243,7 @@ ROM_START( dps1 ) ROM_LOAD( "boot 1280", 0x0000, 0x0400, CRC(9c2e98fa) SHA1(78e6c9d00aa6e8f6c4d3c65984cfdf4e99434c66) ) // actually on the FDC-2 board ROM_END +} // anonymous namespace + + COMP( 1979, dps1, 0, 0, dps1, dps1, dps1_state, empty_init, "Ithaca InterSystems", "DPS-1", MACHINE_NO_SOUND_HW | MACHINE_SUPPORTS_SAVE ) diff --git a/src/mame/drivers/dsb46.cpp b/src/mame/drivers/dsb46.cpp index 9d97d17a692..554dc62b0a0 100644 --- a/src/mame/drivers/dsb46.cpp +++ b/src/mame/drivers/dsb46.cpp @@ -25,15 +25,17 @@ The photos show 3 boards: ********************************************************************************************************************/ - #include "emu.h" + +#include "bus/rs232/rs232.h" #include "cpu/z80/z80.h" -#include "machine/z80daisy.h" #include "machine/z80ctc.h" +#include "machine/z80daisy.h" #include "machine/z80sio.h" -#include "bus/rs232/rs232.h" +namespace { + class dsb46_state : public driver_device { public: @@ -47,9 +49,11 @@ public: void dsb46(machine_config &config); +protected: + virtual void machine_reset() override; + virtual void machine_start() override; + private: - void machine_reset() override; - void machine_start() override; void port1a_w(u8 data); void io_map(address_map &map); void mem_map(address_map &map); @@ -61,8 +65,8 @@ private: void dsb46_state::mem_map(address_map &map) { - map(0x0000, 0xffff).ram().share("mainram"); - map(0x0000, 0x07ff).bankr("bank1"); + map(0x0000, 0xffff).ram().share(m_ram); + map(0x0000, 0x07ff).bankr(m_bank1); } void dsb46_state::io_map(address_map &map) @@ -143,4 +147,7 @@ ROM_START( dsb46 ) ROM_LOAD( "ades.bin", 0x0000, 0x4000, CRC(d374abf0) SHA1(331f51a2bb81375aeffbe63c1ebc1d7cd779b9c3) ) ROM_END +} // anonymous namespace + + COMP( 198?, dsb46, 0, 0, dsb46, dsb46, dsb46_state, empty_init, "Davidge", "DSB-4/6", MACHINE_NOT_WORKING | MACHINE_NO_SOUND_HW | MACHINE_SUPPORTS_SAVE ) diff --git a/src/mame/drivers/excali64.cpp b/src/mame/drivers/excali64.cpp index 30a46d6bb31..dde711a63a1 100644 --- a/src/mame/drivers/excali64.cpp +++ b/src/mame/drivers/excali64.cpp @@ -64,6 +64,8 @@ public: , m_palette(*this, "palette") , m_maincpu(*this, "maincpu") , m_p_chargen(*this, "chargen") + , m_bankr(*this, "bankr%u", 1U) + , m_bankw(*this, "bankw%u", 1U) , m_cass(*this, "cassette") , m_crtc(*this, "crtc") , m_io_keyboard(*this, "KEY.%u", 0) @@ -119,6 +121,8 @@ private: required_device m_palette; required_device m_maincpu; required_region_ptr m_p_chargen; + required_memory_bank_array<4> m_bankr; + required_memory_bank_array<4> m_bankw; required_device m_cass; required_device m_crtc; required_ioport_array<8> m_io_keyboard; @@ -132,11 +136,11 @@ private: void excali64_state::mem_map(address_map &map) { - map(0x0000, 0x1FFF).bankr("bankr1").bankw("bankw1"); - map(0x2000, 0x2FFF).bankr("bankr2").bankw("bankw2"); - map(0x3000, 0x3FFF).bankr("bankr3").bankw("bankw3"); - map(0x4000, 0xBFFF).bankr("bankr4").bankw("bankw4"); - map(0xC000, 0xFFFF).ram(); + map(0x0000, 0x1fff).bankr(m_bankr[0]).bankw(m_bankw[0]); + map(0x2000, 0x2fff).bankr(m_bankr[1]).bankw(m_bankw[1]); + map(0x3000, 0x3fff).bankr(m_bankr[2]).bankw(m_bankw[2]); + map(0x4000, 0xbfff).bankr(m_bankr[3]).bankw(m_bankw[3]); + map(0xc000, 0xffff).ram(); } void excali64_state::io_map(address_map &map) @@ -386,52 +390,57 @@ void excali64_state::port70_w(u8 data) if (BIT(data, 1)) { // select 64k ram - membank("bankr1")->set_entry(0); - membank("bankr2")->set_entry(0); - membank("bankr3")->set_entry(0); - membank("bankr4")->set_entry(0); - membank("bankw2")->set_entry(0); - membank("bankw3")->set_entry(0); - membank("bankw4")->set_entry(0); + m_bankr[0]->set_entry(0); + m_bankr[1]->set_entry(0); + m_bankr[2]->set_entry(0); + m_bankr[3]->set_entry(0); + + m_bankw[1]->set_entry(0); + m_bankw[2]->set_entry(0); + m_bankw[3]->set_entry(0); } else if (BIT(data, 0)) { // select videoram and hiresram - membank("bankr1")->set_entry(1); - membank("bankr2")->set_entry(2); - membank("bankr3")->set_entry(2); - membank("bankw2")->set_entry(2); - membank("bankw3")->set_entry(2); - membank("bankr4")->set_entry(2); - membank("bankw4")->set_entry(2); + m_bankr[0]->set_entry(1); + m_bankr[1]->set_entry(2); + m_bankr[2]->set_entry(2); + m_bankr[3]->set_entry(2); + + m_bankw[1]->set_entry(2); + m_bankw[2]->set_entry(2); + m_bankw[3]->set_entry(2); } else { // select rom, videoram, and main ram - membank("bankr1")->set_entry(1); - membank("bankr2")->set_entry(1); - membank("bankr3")->set_entry(1); - membank("bankw2")->set_entry(2); - membank("bankw3")->set_entry(2); - membank("bankr4")->set_entry(0); - membank("bankw4")->set_entry(0); + m_bankr[0]->set_entry(1); + m_bankr[1]->set_entry(1); + m_bankr[2]->set_entry(1); + m_bankr[3]->set_entry(0); + + m_bankw[1]->set_entry(2); + m_bankw[2]->set_entry(2); + m_bankw[3]->set_entry(0); } // other half of ROM_1 if ((data & 0x22) == 0x20) - membank("bankr1")->set_entry(2); + m_bankr[0]->set_entry(2); } void excali64_state::machine_reset() { - membank("bankr1")->set_entry(1); // read from ROM - membank("bankr2")->set_entry(1); // read from ROM - membank("bankr3")->set_entry(1); // read from ROM - membank("bankr4")->set_entry(0); // read from RAM - membank("bankw1")->set_entry(0); // write to RAM - membank("bankw2")->set_entry(2); // write to videoram - membank("bankw3")->set_entry(2); // write to videoram hires pointers - membank("bankw4")->set_entry(0); // write to RAM + m_bankr[0]->set_entry(1); // read from ROM + m_bankr[1]->set_entry(1); // read from ROM + m_bankr[2]->set_entry(1); // read from ROM + m_bankr[3]->set_entry(0); // read from RAM + + m_bankw[0]->set_entry(0); // write to RAM + m_bankw[1]->set_entry(2); // write to videoram + m_bankw[2]->set_entry(2); // write to videoram hires pointers + m_bankw[3]->set_entry(0); // write to RAM + m_maincpu->reset(); } @@ -492,28 +501,28 @@ void excali64_state::excali64_palette(palette_device &palette) u8 *main = memregion("roms")->base(); // main ram (cp/m mode) - membank("bankr1")->configure_entry(0, r); - membank("bankr2")->configure_entry(0, r+0x2000); - membank("bankr3")->configure_entry(0, r+0x3000); - membank("bankr4")->configure_entry(0, r+0x4000);//boot - membank("bankw1")->configure_entry(0, r);//boot - membank("bankw2")->configure_entry(0, r+0x2000); - membank("bankw3")->configure_entry(0, r+0x3000); - membank("bankw4")->configure_entry(0, r+0x4000);//boot + m_bankr[0]->configure_entry(0, r); + m_bankr[1]->configure_entry(0, r+0x2000); + m_bankr[2]->configure_entry(0, r+0x3000); + m_bankr[3]->configure_entry(0, r+0x4000);//boot + m_bankw[0]->configure_entry(0, r);//boot + m_bankw[1]->configure_entry(0, r+0x2000); + m_bankw[2]->configure_entry(0, r+0x3000); + m_bankw[3]->configure_entry(0, r+0x4000);//boot // rom_1 - membank("bankr1")->configure_entry(1, &main[0x0000]);//boot - membank("bankr1")->configure_entry(2, &main[0x2000]); + m_bankr[0]->configure_entry(1, &main[0x0000]);//boot + m_bankr[0]->configure_entry(2, &main[0x2000]); // rom_2 - membank("bankr2")->configure_entry(1, &main[0x4000]);//boot - membank("bankr3")->configure_entry(1, &main[0x5000]);//boot + m_bankr[1]->configure_entry(1, &main[0x4000]);//boot + m_bankr[2]->configure_entry(1, &main[0x5000]);//boot // videoram - membank("bankr2")->configure_entry(2, v); - membank("bankw2")->configure_entry(2, v);//boot + m_bankr[1]->configure_entry(2, v); + m_bankw[1]->configure_entry(2, v);//boot // hiresram - membank("bankr3")->configure_entry(2, v+0x1000); - membank("bankw3")->configure_entry(2, v+0x1000);//boot - membank("bankr4")->configure_entry(2, h); - membank("bankw4")->configure_entry(2, h); + m_bankr[2]->configure_entry(2, v+0x1000); + m_bankw[2]->configure_entry(2, v+0x1000);//boot + m_bankr[3]->configure_entry(2, h); + m_bankw[3]->configure_entry(2, h); // Set up foreground colours for (u8 i = 0; i < 32; i++) diff --git a/src/mame/drivers/force68k.cpp b/src/mame/drivers/force68k.cpp index 03d594ca831..88b41fb6aad 100644 --- a/src/mame/drivers/force68k.cpp +++ b/src/mame/drivers/force68k.cpp @@ -382,7 +382,7 @@ void force68k_state::machine_start () m_usrrom = (uint16_t*)m_cart->get_rom_base(); #if 0 // This should be the correct way but produces odd and even bytes swapped m_maincpu->space(AS_PROGRAM).install_read_handler(0xa0000, 0xbffff, read16sm_delegate(*m_cart, FUNC(generic_slot_device::read16_rom))); -#else // So we installs a custom very inefficient handler for now until we understand hop to solve the problem better +#else // So we install a custom very inefficient handler for now until we understand how to solve the problem better m_maincpu->space(AS_PROGRAM).install_read_handler(0xa0000, 0xbffff, read16sm_delegate(*this, FUNC(force68k_state::read16_rom))); #endif } diff --git a/src/mame/drivers/galgames.cpp b/src/mame/drivers/galgames.cpp index a96793e50dd..094f875b71a 100644 --- a/src/mame/drivers/galgames.cpp +++ b/src/mame/drivers/galgames.cpp @@ -38,6 +38,7 @@ Notes: ***************************************************************************/ #include "emu.h" + #include "cpu/m68000/m68000.h" #include "cpu/pic16c5x/pic16c5x.h" #include "machine/eepromser.h" @@ -45,10 +46,12 @@ Notes: #include "machine/watchdog.h" #include "sound/okim6295.h" #include "video/cesblit.h" + +#include "dirom.h" #include "emupal.h" #include "screen.h" #include "speaker.h" -#include "dirom.h" + /*************************************************************************** diff --git a/src/mame/drivers/hng64.cpp b/src/mame/drivers/hng64.cpp index 2598f38de5c..569c85e461b 100644 --- a/src/mame/drivers/hng64.cpp +++ b/src/mame/drivers/hng64.cpp @@ -2313,21 +2313,6 @@ void hng64_state::ioport4_w(uint8_t data) LOG("%s: ioport4_w %02x\n", machine().describe_context(), data); } -/*********************************************** - - Other port accesses from MCU side - -***********************************************/ - -uint8_t hng64_state::anport0_r() { return m_an_in[0]->read(); } -uint8_t hng64_state::anport1_r() { return m_an_in[1]->read(); } -uint8_t hng64_state::anport2_r() { return m_an_in[2]->read(); } -uint8_t hng64_state::anport3_r() { return m_an_in[3]->read(); } -uint8_t hng64_state::anport4_r() { return m_an_in[4]->read(); } -uint8_t hng64_state::anport5_r() { return m_an_in[5]->read(); } -uint8_t hng64_state::anport6_r() { return m_an_in[6]->read(); } -uint8_t hng64_state::anport7_r() { return m_an_in[7]->read(); } - /*********************************************** Serial Accesses from MCU side @@ -2418,14 +2403,14 @@ void hng64_state::hng64(machine_config &config) //iomcu.p6_out_cb().set(FUNC(hng64_state::ioport6_w)); // the IO MCU code uses the ADC which shares pins with port 6, meaning port 6 isn't used as an IO port iomcu.p7_out_cb().set(FUNC(hng64_state::ioport7_w)); // configuration / clocking for shared ram (port 0) accesses // most likely the analog inputs, up to a maximum of 8 - iomcu.an0_in_cb().set(FUNC(hng64_state::anport0_r)); - iomcu.an1_in_cb().set(FUNC(hng64_state::anport1_r)); - iomcu.an2_in_cb().set(FUNC(hng64_state::anport2_r)); - iomcu.an3_in_cb().set(FUNC(hng64_state::anport3_r)); - iomcu.an4_in_cb().set(FUNC(hng64_state::anport4_r)); - iomcu.an5_in_cb().set(FUNC(hng64_state::anport5_r)); - iomcu.an6_in_cb().set(FUNC(hng64_state::anport6_r)); - iomcu.an7_in_cb().set(FUNC(hng64_state::anport7_r)); + iomcu.an0_in_cb().set_ioport("AN0"); + iomcu.an1_in_cb().set_ioport("AN1"); + iomcu.an2_in_cb().set_ioport("AN2"); + iomcu.an3_in_cb().set_ioport("AN3"); + iomcu.an4_in_cb().set_ioport("AN4"); + iomcu.an5_in_cb().set_ioport("AN5"); + iomcu.an6_in_cb().set_ioport("AN6"); + iomcu.an7_in_cb().set_ioport("AN7"); // network related? iomcu.serial0_out_cb().set(FUNC(hng64_state::sio0_w)); //iomcu.serial1_out_cb().set(FUNC(hng64_state::sio1_w)); // not initialized / used @@ -2439,14 +2424,14 @@ void hng64_state::hng64_default(machine_config &config) hng64(config); hng64_lamps_device &lamps(HNG64_LAMPS(config, m_lamps, 0)); - lamps.lamps0_out_cb().set(FUNC(hng64_state::hng64_default_lamps0_w)); - lamps.lamps1_out_cb().set(FUNC(hng64_state::hng64_default_lamps1_w)); - lamps.lamps2_out_cb().set(FUNC(hng64_state::hng64_default_lamps2_w)); - lamps.lamps3_out_cb().set(FUNC(hng64_state::hng64_default_lamps3_w)); - lamps.lamps4_out_cb().set(FUNC(hng64_state::hng64_default_lamps4_w)); - lamps.lamps5_out_cb().set(FUNC(hng64_state::hng64_default_lamps5_w)); - lamps.lamps6_out_cb().set(FUNC(hng64_state::hng64_default_lamps6_w)); - lamps.lamps7_out_cb().set(FUNC(hng64_state::hng64_default_lamps7_w)); + lamps.lamps_out_cb<0>().set(FUNC(hng64_state::hng64_default_lamps_w<0>)); + lamps.lamps_out_cb<1>().set(FUNC(hng64_state::hng64_default_lamps_w<1>)); + lamps.lamps_out_cb<2>().set(FUNC(hng64_state::hng64_default_lamps_w<2>)); + lamps.lamps_out_cb<3>().set(FUNC(hng64_state::hng64_default_lamps_w<3>)); + lamps.lamps_out_cb<4>().set(FUNC(hng64_state::hng64_default_lamps_w<4>)); + lamps.lamps_out_cb<5>().set(FUNC(hng64_state::hng64_default_lamps_w<5>)); + lamps.lamps_out_cb<6>().set(FUNC(hng64_state::hng64_default_lamps_w<6>)); + lamps.lamps_out_cb<7>().set(FUNC(hng64_state::hng64_default_lamps_w<7>)); } void hng64_state::hng64_drive(machine_config &config) @@ -2454,9 +2439,9 @@ void hng64_state::hng64_drive(machine_config &config) hng64(config); hng64_lamps_device &lamps(HNG64_LAMPS(config, m_lamps, 0)); - lamps.lamps5_out_cb().set(FUNC(hng64_state::hng64_drive_lamps5_w)); // force feedback steering - lamps.lamps6_out_cb().set(FUNC(hng64_state::hng64_drive_lamps6_w)); // lamps + coin counter - lamps.lamps7_out_cb().set(FUNC(hng64_state::hng64_drive_lamps7_w)); // lamps + lamps.lamps_out_cb<5>().set(FUNC(hng64_state::hng64_drive_lamps5_w)); // force feedback steering + lamps.lamps_out_cb<6>().set(FUNC(hng64_state::hng64_drive_lamps6_w)); // lamps + coin counter + lamps.lamps_out_cb<7>().set(FUNC(hng64_state::hng64_drive_lamps7_w)); // lamps } void hng64_state::hng64_shoot(machine_config &config) @@ -2464,8 +2449,8 @@ void hng64_state::hng64_shoot(machine_config &config) hng64(config); hng64_lamps_device &lamps(HNG64_LAMPS(config, m_lamps, 0)); - lamps.lamps6_out_cb().set(FUNC(hng64_state::hng64_shoot_lamps6_w)); // start lamps (some missing?!) - lamps.lamps7_out_cb().set(FUNC(hng64_state::hng64_shoot_lamps7_w)); // gun lamps + lamps.lamps_out_cb<6>().set(FUNC(hng64_state::hng64_shoot_lamps6_w)); // start lamps (some missing?!) + lamps.lamps_out_cb<7>().set(FUNC(hng64_state::hng64_shoot_lamps7_w)); // gun lamps } void hng64_state::hng64_fight(machine_config &config) @@ -2473,7 +2458,7 @@ void hng64_state::hng64_fight(machine_config &config) hng64(config); hng64_lamps_device &lamps(HNG64_LAMPS(config, m_lamps, 0)); - lamps.lamps6_out_cb().set(FUNC(hng64_state::hng64_fight_lamps6_w)); // coin counters + lamps.lamps_out_cb<6>().set(FUNC(hng64_state::hng64_fight_lamps6_w)); // coin counters } diff --git a/src/mame/drivers/kaypro.cpp b/src/mame/drivers/kaypro.cpp index 933a5d4dfc5..18a56259e03 100644 --- a/src/mame/drivers/kaypro.cpp +++ b/src/mame/drivers/kaypro.cpp @@ -67,8 +67,8 @@ u8 kaypro_state::kaypro484_87_r() { return 0x7f; } /* to bypass unemulated HD void kaypro_state::kaypro_map(address_map &map) { - map(0x0000, 0x2fff).bankr("bankr").bankw("bankw"); - map(0x3000, 0x3fff).bankrw("bank3"); + map(0x0000, 0x2fff).bankr(m_bankr).bankw(m_bankw); + map(0x3000, 0x3fff).bankrw(m_bank3); map(0x4000, 0xffff).ram(); } diff --git a/src/mame/drivers/konendev.cpp b/src/mame/drivers/konendev.cpp index 6736bdbf813..d6bf652d1f6 100644 --- a/src/mame/drivers/konendev.cpp +++ b/src/mame/drivers/konendev.cpp @@ -62,17 +62,22 @@ */ #include "emu.h" -#include "cpu/powerpc/ppc.h" +#include "video/k057714.h" + #include "cpu/h8/h83006.h" +#include "cpu/powerpc/ppc.h" #include "machine/eepromser.h" -#include "machine/nvram.h" #include "machine/msm6242.h" +#include "machine/nvram.h" #include "sound/ymz280b.h" -#include "video/k057714.h" + #include "emupal.h" #include "screen.h" #include "speaker.h" + +namespace { + class konendev_state : public driver_device { public: @@ -99,10 +104,6 @@ public: private: uint32_t mcu2_r(offs_t offset, uint32_t mem_mask = ~0); uint32_t ifu2_r(offs_t offset, uint32_t mem_mask = ~0); - uint32_t ctrl0_r(); - uint32_t ctrl1_r(); - uint32_t ctrl2_r(); - uint32_t ctrl3_r(); void eeprom_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0); uint32_t sound_data_r(); void sound_data_w(uint32_t data); @@ -177,26 +178,6 @@ uint32_t konendev_state::ifu2_r(offs_t offset, uint32_t mem_mask) return r; } -uint32_t konendev_state::ctrl0_r() // doors, switches -{ - return ioport("IN1")->read(); -} - -uint32_t konendev_state::ctrl1_r() // hard meter access, hopper -{ - return ioport("IN2")->read(); -} - -uint32_t konendev_state::ctrl2_r() // main door optic -{ - return ioport("IN3")->read(); -} - -uint32_t konendev_state::ctrl3_r() // buttons -{ - return ioport("IN0")->read(); -} - void konendev_state::eeprom_w(offs_t offset, uint32_t data, uint32_t mem_mask) { if (ACCESSING_BITS_0_7) @@ -224,11 +205,11 @@ void konendev_state::konendev_map(address_map &map) map(0x780c0000, 0x780c0003).rw(FUNC(konendev_state::sound_data_r), FUNC(konendev_state::sound_data_w)); map(0x78100000, 0x78100003).w(FUNC(konendev_state::eeprom_w)); map(0x78800000, 0x78800003).r(FUNC(konendev_state::ifu2_r)); - map(0x78800004, 0x78800007).r(FUNC(konendev_state::ctrl0_r)); - map(0x78a00000, 0x78a00003).r(FUNC(konendev_state::ctrl1_r)); - map(0x78a00004, 0x78a00007).r(FUNC(konendev_state::ctrl2_r)); + map(0x78800004, 0x78800007).portr("IN1"); // doors, switches + map(0x78a00000, 0x78a00003).portr("IN2"); // hard meter access, hopper + map(0x78a00004, 0x78a00007).portr("IN3"); // main door optic map(0x78c00000, 0x78c003ff).ram().share("dpram"); - map(0x78e00000, 0x78e00003).r(FUNC(konendev_state::ctrl3_r)); + map(0x78e00000, 0x78e00003).portr("IN0"); // buttons map(0x79000000, 0x79000003).w(m_gcu, FUNC(k057714_device::fifo_w)); map(0x79800000, 0x798000ff).rw(m_gcu, FUNC(k057714_device::read), FUNC(k057714_device::write)); map(0x7a000000, 0x7a01ffff).ram().share("nvram0"); @@ -702,6 +683,9 @@ void konendev_state::init_enchlamp() rom[0] = 0x5782b930; // new checksum for program rom } +} // anonymous namespace + + // BIOS GAME( 200?, konendev, 0, konendev, konendev, konendev_state, init_enchlamp, ROT0, "Konami", "Konami Endeavour BIOS", MACHINE_NOT_WORKING|MACHINE_IS_BIOS_ROOT ) diff --git a/src/mame/drivers/mbc200.cpp b/src/mame/drivers/mbc200.cpp index f8413ef1e9d..673cef8aa92 100644 --- a/src/mame/drivers/mbc200.cpp +++ b/src/mame/drivers/mbc200.cpp @@ -44,6 +44,7 @@ TODO: ****************************************************************************/ #include "emu.h" + #include "cpu/z80/z80.h" #include "imagedev/floppy.h" #include "machine/i8251.h" @@ -53,11 +54,15 @@ TODO: #include "sound/beep.h" #include "sound/spkrdev.h" #include "video/mc6845.h" + #include "emupal.h" #include "screen.h" #include "softlist.h" #include "speaker.h" + +namespace { + class mbc200_state : public driver_device { public: @@ -79,6 +84,10 @@ public: void mbc200(machine_config &config); +protected: + virtual void machine_start() override; + virtual void machine_reset() override; + private: u8 p2_porta_r(); void p1_portc_w(u8 data); @@ -89,13 +98,11 @@ private: MC6845_UPDATE_ROW(update_row); required_device m_palette; - void main_io(address_map &map); void main_mem(address_map &map); - void sub_io(address_map &map); + void main_io(address_map &map); void sub_mem(address_map &map); + void sub_io(address_map &map); - virtual void machine_start() override; - virtual void machine_reset() override; u8 m_comm_latch; u8 m_term_data; required_device m_crtc; @@ -366,8 +373,10 @@ ROM_START( mbc200 ) ROM_LOAD( "m5l2764.bin", 0x0000, 0x2000, CRC(377300a2) SHA1(8563172f9e7f84330378a8d179f4138be5fda099)) ROM_END +} // anonymous namespace + + /* Driver */ // YEAR NAME PARENT COMPAT MACHINE INPUT CLASS INIT COMPANY FULLNAME FLAGS COMP( 1982, mbc200, 0, 0, mbc200, mbc200, mbc200_state, empty_init, "Sanyo", "MBC-200", MACHINE_SUPPORTS_SAVE ) - diff --git a/src/mame/drivers/mes.cpp b/src/mame/drivers/mes.cpp index de379ba2a96..76bec55abfb 100644 --- a/src/mame/drivers/mes.cpp +++ b/src/mame/drivers/mes.cpp @@ -9,15 +9,19 @@ Schleicher MES ****************************************************************************/ #include "emu.h" + #include "cpu/z80/z80.h" #include "machine/z80ctc.h" #include "machine/z80pio.h" #include "machine/z80sio.h" #include "machine/keyboard.h" + #include "emupal.h" #include "screen.h" +namespace { + class mes_state : public driver_device { public: @@ -30,9 +34,11 @@ public: void mes(machine_config &config); +protected: + virtual void machine_start() override; + virtual void machine_reset() override; + private: - void machine_reset() override; - void machine_start() override; u32 screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect); void kbd_put(u8 data); u8 port00_r(); @@ -99,7 +105,7 @@ void mes_state::machine_reset() Also the screen dimensions are a guess. */ uint32_t mes_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect) { - u16 sy=0,ma=0; + u16 sy = 0, ma = 0; for (u8 y = 0; y < 25; y++) { @@ -112,7 +118,7 @@ uint32_t mes_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, c u8 gfx = 0; if (ra < 9) { - u8 chr = m_p_videoram[x]; + const u8 chr = m_p_videoram[x]; gfx = m_p_chargen[(chr<<4) | ra ]; } @@ -127,7 +133,7 @@ uint32_t mes_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, c *p++ = BIT(gfx, 0); } } - ma+=80; + ma += 80; } return 0; } @@ -177,6 +183,9 @@ ROM_START( mes ) ROM_LOAD( "c10_char.bin", 0x0000, 0x2000, BAD_DUMP CRC(cb530b6f) SHA1(95590bbb433db9c4317f535723b29516b9b9fcbf)) ROM_END +} // anonymous namespace + + /* Driver */ // YEAR NAME PARENT COMPAT MACHINE INPUT CLASS INIT COMPANY FULLNAME FLAGS diff --git a/src/mame/drivers/mmd1.cpp b/src/mame/drivers/mmd1.cpp index d09e61806e3..84b2a07eaff 100644 --- a/src/mame/drivers/mmd1.cpp +++ b/src/mame/drivers/mmd1.cpp @@ -73,15 +73,20 @@ ToDo: ****************************************************************************/ #include "emu.h" + #include "cpu/i8085/i8085.h" #include "imagedev/cassette.h" #include "machine/ay31015.h" #include "machine/clock.h" #include "machine/timer.h" + #include "speaker.h" + #include "mmd1.lh" +namespace { + class mmd1_state : public driver_device { public: @@ -90,6 +95,7 @@ public: , m_maincpu(*this, "maincpu") , m_cass(*this, "cassette") , m_uart(*this, "uart") + , m_lines(*this, "LINE%u", 1U) , m_digits(*this, "digit%u", 0U) , m_p(*this, "p%u_%u", 0U, 0U) { } @@ -98,9 +104,11 @@ public: DECLARE_INPUT_CHANGED_MEMBER(reset_button); -private: +protected: virtual void machine_start() override; virtual void machine_reset() override; + +private: void round_leds_w(offs_t offset, u8 data); u8 keyboard_r(); u8 port13_r(); @@ -119,6 +127,7 @@ private: required_device m_maincpu; required_device m_cass; required_device m_uart; + required_ioport_array<2> m_lines; output_finder<9> m_digits; output_finder<3, 8> m_p; }; @@ -134,21 +143,20 @@ void mmd1_state::round_leds_w(offs_t offset, u8 data) // keyboard has a keydown and a keyup code. Keyup = last keydown + bit 7 set u8 mmd1_state::keyboard_r() { - u8 line1 = ioport("LINE1")->read(); - u8 line2 = ioport("LINE2")->read(); - u8 i, data = 0xff; - + const u8 line1 = m_lines[0]->read(); + const u8 line2 = m_lines[1]->read(); + u8 data = 0xff; - for (i = 0; i < 8; i++) + for (unsigned i = 0; i < 8; i++) { if (!BIT(line1, i)) data = i; } - for (i = 0; i < 8; i++) + for (unsigned i = 0; i < 8; i++) { if (!BIT(line2, i)) - data = i+8; + data = i + 8; } if (data < 0x10) @@ -336,6 +344,9 @@ ROM_START( mmd1 ) ROM_LOAD( "prom1.ic16", 0x0100, 0x0100, BAD_DUMP CRC(d23a6ac3) SHA1(469d981b635058dd23e843a3efc555316f87ece4) ) // Typed in by hand from the manual ROM_END +} // anonymous namespace + + /* Driver */ // YEAR NAME PARENT COMPAT MACHINE INPUT CLASS INIT COMPANY FULLNAME FLAGS diff --git a/src/mame/drivers/nakajies.cpp b/src/mame/drivers/nakajies.cpp index 8551fc700c6..15fd8a41478 100644 --- a/src/mame/drivers/nakajies.cpp +++ b/src/mame/drivers/nakajies.cpp @@ -270,17 +270,20 @@ disabled). Perhaps power on/off related?? ******************************************************************************/ - #include "emu.h" + #include "cpu/nec/nec.h" #include "machine/rp5c01.h" #include "machine/timer.h" #include "sound/spkrdev.h" + #include "emupal.h" #include "screen.h" #include "speaker.h" +namespace { + #define LOG 0 @@ -315,17 +318,9 @@ private: uint8_t unk_a0_r(); void lcd_memory_start_w(uint8_t data); uint8_t keyboard_r(); - void banking_w(offs_t offset, uint8_t data) ; + void banking_w(offs_t offset, uint8_t data); void update_banks(); - void bank_w(uint8_t banknr, offs_t offset, uint8_t data); - void bank0_w(offs_t offset, uint8_t data) ; - void bank1_w(offs_t offset, uint8_t data) ; - void bank2_w(offs_t offset, uint8_t data) ; - void bank3_w(offs_t offset, uint8_t data) ; - void bank4_w(offs_t offset, uint8_t data) ; - void bank5_w(offs_t offset, uint8_t data) ; - void bank6_w(offs_t offset, uint8_t data) ; - void bank7_w(offs_t offset, uint8_t data) ; + template void bank_w(offs_t offset, uint8_t data); void nakajies_palette(palette_device &palette) const; TIMER_DEVICE_CALLBACK_MEMBER(kb_timer); @@ -376,44 +371,36 @@ void nakajies_state::update_banks() m_bank_base[i] = &m_rom_base[(((m_bank[i] & 0x0f) ^ 0xf) << 17) % m_rom_size]; } } - membank( "bank0" )->set_base( m_bank_base[0] ); - membank( "bank1" )->set_base( m_bank_base[1] ); - membank( "bank2" )->set_base( m_bank_base[2] ); - membank( "bank3" )->set_base( m_bank_base[3] ); - membank( "bank4" )->set_base( m_bank_base[4] ); - membank( "bank5" )->set_base( m_bank_base[5] ); - membank( "bank6" )->set_base( m_bank_base[6] ); - membank( "bank7" )->set_base( m_bank_base[7] ); + membank( "bank0" )->set_base(m_bank_base[0]); + membank( "bank1" )->set_base(m_bank_base[1]); + membank( "bank2" )->set_base(m_bank_base[2]); + membank( "bank3" )->set_base(m_bank_base[3]); + membank( "bank4" )->set_base(m_bank_base[4]); + membank( "bank5" )->set_base(m_bank_base[5]); + membank( "bank6" )->set_base(m_bank_base[6]); + membank( "bank7" )->set_base(m_bank_base[7]); } -void nakajies_state::bank_w( uint8_t banknr, offs_t offset, uint8_t data ) +template +void nakajies_state::bank_w(offs_t offset, uint8_t data) { - if ( m_bank[banknr] & 0x10 ) + if (m_bank[N] & 0x10) { - m_bank_base[banknr][offset] = data; + m_bank_base[N][offset] = data; } } -void nakajies_state::bank0_w(offs_t offset, uint8_t data) { bank_w( 0, offset, data ); } -void nakajies_state::bank1_w(offs_t offset, uint8_t data) { bank_w( 1, offset, data ); } -void nakajies_state::bank2_w(offs_t offset, uint8_t data) { bank_w( 2, offset, data ); } -void nakajies_state::bank3_w(offs_t offset, uint8_t data) { bank_w( 3, offset, data ); } -void nakajies_state::bank4_w(offs_t offset, uint8_t data) { bank_w( 4, offset, data ); } -void nakajies_state::bank5_w(offs_t offset, uint8_t data) { bank_w( 5, offset, data ); } -void nakajies_state::bank6_w(offs_t offset, uint8_t data) { bank_w( 6, offset, data ); } -void nakajies_state::bank7_w(offs_t offset, uint8_t data) { bank_w( 7, offset, data ); } - void nakajies_state::nakajies_map(address_map &map) { - map(0x00000, 0x1ffff).bankr("bank0").w(FUNC(nakajies_state::bank0_w)); - map(0x20000, 0x3ffff).bankr("bank1").w(FUNC(nakajies_state::bank1_w)); - map(0x40000, 0x5ffff).bankr("bank2").w(FUNC(nakajies_state::bank2_w)); - map(0x60000, 0x7ffff).bankr("bank3").w(FUNC(nakajies_state::bank3_w)); - map(0x80000, 0x9ffff).bankr("bank4").w(FUNC(nakajies_state::bank4_w)); - map(0xa0000, 0xbffff).bankr("bank5").w(FUNC(nakajies_state::bank5_w)); - map(0xc0000, 0xdffff).bankr("bank6").w(FUNC(nakajies_state::bank6_w)); - map(0xe0000, 0xfffff).bankr("bank7").w(FUNC(nakajies_state::bank7_w)); + map(0x00000, 0x1ffff).bankr("bank0").w(FUNC(nakajies_state::bank_w<0>)); + map(0x20000, 0x3ffff).bankr("bank1").w(FUNC(nakajies_state::bank_w<1>)); + map(0x40000, 0x5ffff).bankr("bank2").w(FUNC(nakajies_state::bank_w<2>)); + map(0x60000, 0x7ffff).bankr("bank3").w(FUNC(nakajies_state::bank_w<3>)); + map(0x80000, 0x9ffff).bankr("bank4").w(FUNC(nakajies_state::bank_w<4>)); + map(0xa0000, 0xbffff).bankr("bank5").w(FUNC(nakajies_state::bank_w<5>)); + map(0xc0000, 0xdffff).bankr("bank6").w(FUNC(nakajies_state::bank_w<6>)); + map(0xe0000, 0xfffff).bankr("bank7").w(FUNC(nakajies_state::bank_w<7>)); } @@ -843,6 +830,8 @@ ROM_START( es210_es ) ROM_LOAD("nakajima_es.ic303", 0x00000, 0x80000, CRC(214d73ce) SHA1(ce9967c5b2d122ebebe9401278d8ea374e8fb289)) ROM_END +} // anonymous namespace + // YEAR NAME PARENT COMPAT MACHINE INPUT CLASS INIT COMPANY FULLNAME FLAGS COMP( 199?, wales210, 0, 0, nakajies210, nakajies, nakajies_state, empty_init, "Walther", "ES-210", MACHINE_NOT_WORKING | MACHINE_NO_SOUND ) // German, 128KB RAM diff --git a/src/mame/drivers/pegasus.cpp b/src/mame/drivers/pegasus.cpp index a8bd6934e77..e454f1afc03 100644 --- a/src/mame/drivers/pegasus.cpp +++ b/src/mame/drivers/pegasus.cpp @@ -38,18 +38,22 @@ ****************************************************************************/ #include "emu.h" + #include "bus/generic/carts.h" #include "bus/generic/slot.h" #include "cpu/m6809/m6809.h" #include "imagedev/cassette.h" #include "machine/6821pia.h" #include "machine/timer.h" + #include "emupal.h" #include "screen.h" #include "softlist.h" #include "speaker.h" +namespace { + class pegasus_state : public driver_device { public: @@ -74,6 +78,10 @@ public: void init_pegasus(); +protected: + virtual void machine_reset() override; + virtual void machine_start() override; + private: u8 pegasus_keyboard_r(); u8 pegasus_protection_r(); @@ -100,8 +108,6 @@ private: u8 m_kbd_row; bool m_kbd_irq; u8 m_control_bits; - virtual void machine_reset() override; - virtual void machine_start() override; std::unique_ptr m_pcg; void pegasus_decrypt_rom(u8 *ROM); required_device m_maincpu; @@ -130,13 +136,13 @@ WRITE_LINE_MEMBER( pegasus_state::pegasus_firq_clr ) u8 pegasus_state::pegasus_keyboard_r() { - u8 i,data = 0xff; - for (i = 0; i < 8; i++) + u8 data = 0xff; + for (unsigned i = 0; i < 8; i++) if (!BIT(m_kbd_row, i)) data &= m_io_keyboard[i]->read(); m_kbd_irq = (data == 0xff) ? 1 : 0; if (BIT(m_control_bits, 3)) - data<<=4; + data <<= 4; return data; } @@ -314,16 +320,16 @@ static const u8 mcm6571a_shift[] = u32 pegasus_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect) { - u16 sy=0,ma=0; - bool pcg_mode = BIT(m_control_bits, 1); + u16 sy=0, ma=0; + const bool pcg_mode = BIT(m_control_bits, 1); - for(u8 y = 0; y < 16; y++ ) + for (u8 y = 0; y < 16; y++) { - for(u8 ra = 0; ra < 16; ra++ ) + for (u8 ra = 0; ra < 16; ra++) { u16 *p = &bitmap.pix(sy++); - for(u16 x = ma; x < ma + 32; x++ ) + for (u16 x = ma; x < ma + 32; x++) { u8 inv = 0xff; u8 chr = m_vram[x]; @@ -373,15 +379,15 @@ u32 pegasus_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, co /* F4 Character Displayer */ static const gfx_layout pegasus_charlayout = { - 8, 16, /* text = 7 x 9, pcg = 8 x 16 */ - 128, /* 128 characters */ - 1, /* 1 bits per pixel */ - { 0 }, /* no bitplanes */ - /* x offsets */ + 8, 16, // text = 7 x 9, pcg = 8 x 16 + 128, // 128 characters + 1, // 1 bits per pixel + { 0 }, // no bitplanes + // x offsets { 0, 1, 2, 3, 4, 5, 6, 7 }, - /* y offsets */ + // y offsets { 0*8, 1*8, 2*8, 3*8, 4*8, 5*8, 6*8, 7*8, 8*8, 9*8, 10*8, 11*8, 12*8, 13*8, 14*8, 15*8 }, - 8*16 /* every char takes 16 bytes */ + 8*16 // every char takes 16 bytes }; static GFXDECODE_START( gfx_pegasus ) @@ -396,10 +402,6 @@ GFXDECODE_END void pegasus_state::pegasus_decrypt_rom(u8 *ROM) { bool doit = false; - u8 b; - u16 j; - std::vector temp_copy; - temp_copy.resize(0x1000); if (ROM[0] == 0x02) doit = true; if (ROM[0] == 0x1e && ROM[1] == 0xfa && ROM[2] == 0x60 && ROM[3] == 0x71) doit = true; // xbasic 2nd rom @@ -409,11 +411,12 @@ void pegasus_state::pegasus_decrypt_rom(u8 *ROM) if (doit) { + std::vector temp_copy; + temp_copy.resize(0x1000); for (int i = 0; i < 0x1000; i++) { - b = ROM[i]; - j = bitswap<16>(i, 15, 14, 13, 12, 11, 10, 9, 8, 0, 1, 2, 3, 4, 5, 6, 7); - b = bitswap<8>(b, 3, 2, 1, 0, 7, 6, 5, 4); + const u16 j = bitswap<16>(i, 15, 14, 13, 12, 11, 10, 9, 8, 0, 1, 2, 3, 4, 5, 6, 7); + const u8 b = bitswap<8>(ROM[i], 3, 2, 1, 0, 7, 6, 5, 4); temp_copy[j & 0xfff] = b; } memcpy(ROM, &temp_copy[0], 0x1000); @@ -575,6 +578,9 @@ ROM_END #define rom_pegasusm rom_pegasus +} // anonymous namespace + + /* Driver */ // YEAR NAME PARENT COMPAT MACHINE INPUT CLASS INIT COMPANY FULLNAME FLAGS diff --git a/src/mame/drivers/taxidriv.cpp b/src/mame/drivers/taxidriv.cpp index 2a0e6bd0d76..d17a623a01a 100644 --- a/src/mame/drivers/taxidriv.cpp +++ b/src/mame/drivers/taxidriv.cpp @@ -12,15 +12,78 @@ OTHER: 5 * M5L8255AP ***************************************************************************/ #include "emu.h" -#include "includes/taxidriv.h" #include "cpu/z80/z80.h" #include "machine/i8255.h" #include "sound/ay8910.h" + +#include "emupal.h" #include "screen.h" #include "speaker.h" +namespace { + +class taxidriv_state : public driver_device +{ +public: + taxidriv_state(const machine_config &mconfig, device_type type, const char *tag) : + driver_device(mconfig, type, tag), + m_maincpu(*this, "maincpu"), + m_gfxdecode(*this, "gfxdecode"), + m_palette(*this, "palette"), + m_vram(*this, "vram%u", 0U), + m_scroll(*this, "scroll"), + m_servcoin(*this, "SERVCOIN") + { } + + void taxidriv(machine_config &config); + +protected: + virtual void machine_start() override; + +private: + required_device m_maincpu; + required_device m_gfxdecode; + required_device m_palette; + + required_shared_ptr_array m_vram; + required_shared_ptr m_scroll; + + required_ioport m_servcoin; + + int m_s1; + int m_s2; + int m_s3; + int m_s4; + int m_latchA; + int m_latchB; + int m_bghide; + int m_spritectrl[9]; + + uint8_t p0a_r(); + uint8_t p0c_r(); + void p0b_w(uint8_t data); + void p0c_w(uint8_t data); + uint8_t p1b_r(); + uint8_t p1c_r(); + void p1a_w(uint8_t data); + void p1c_w(uint8_t data); + uint8_t p8910_0a_r(); + uint8_t p8910_1a_r(); + void p8910_0b_w(uint8_t data); + template void spritectrl_w(uint8_t data); + + void taxidriv_palette(palette_device &palette) const; + + uint32_t screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect); + void cpu2_map(address_map &map); + void cpu3_map(address_map &map); + void cpu3_port_map(address_map &map); + void main_map(address_map &map); +}; + + void taxidriv_state::machine_start() { save_item(NAME(m_s1)); @@ -33,16 +96,6 @@ void taxidriv_state::machine_start() save_item(NAME(m_spritectrl)); } -void taxidriv_state::p2a_w(uint8_t data) { spritectrl_w(0,data); } -void taxidriv_state::p2b_w(uint8_t data) { spritectrl_w(1,data); } -void taxidriv_state::p2c_w(uint8_t data) { spritectrl_w(2,data); } -void taxidriv_state::p3a_w(uint8_t data) { spritectrl_w(3,data); } -void taxidriv_state::p3b_w(uint8_t data) { spritectrl_w(4,data); } -void taxidriv_state::p3c_w(uint8_t data) { spritectrl_w(5,data); } -void taxidriv_state::p4a_w(uint8_t data) { spritectrl_w(6,data); } -void taxidriv_state::p4b_w(uint8_t data) { spritectrl_w(7,data); } -void taxidriv_state::p4c_w(uint8_t data) { spritectrl_w(8,data); } - uint8_t taxidriv_state::p0a_r() { @@ -51,7 +104,7 @@ uint8_t taxidriv_state::p0a_r() uint8_t taxidriv_state::p0c_r() { - return (m_s1 << 7); + return m_s1 << 7; } void taxidriv_state::p0b_w(uint8_t data) @@ -79,7 +132,7 @@ uint8_t taxidriv_state::p1b_r() uint8_t taxidriv_state::p1c_r() { - return (m_s2 << 7) | (m_s4 << 6) | ((ioport("SERVCOIN")->read() & 1) << 4); + return (m_s2 << 7) | (m_s4 << 6) | ((m_servcoin->read() & 1) << 4); } void taxidriv_state::p1a_w(uint8_t data) @@ -110,27 +163,159 @@ void taxidriv_state::p8910_0b_w(uint8_t data) m_s4 = data & 1; } + +template +void taxidriv_state::spritectrl_w(uint8_t data) +{ + m_spritectrl[Offset] = data; +} + + +uint32_t taxidriv_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect) +{ + if (m_bghide) + { + bitmap.fill(0, cliprect); + + + /* kludge to fix scroll after death */ + m_scroll[0] = m_scroll[1] = m_scroll[2] = m_scroll[3] = 0; + m_spritectrl[2] = m_spritectrl[5] = m_spritectrl[8] = 0; + } + else + { + for (int offs = 0;offs < 0x400;offs++) + { + int sx = offs % 32; + int sy = offs / 32; + + m_gfxdecode->gfx(3)->opaque(bitmap,cliprect, + m_vram[3][offs], + 0, + 0,0, + (sx*8-m_scroll[0])&0xff,(sy*8-m_scroll[1])&0xff); + } + + for (int offs = 0;offs < 0x400;offs++) + { + int sx = offs % 32; + int sy = offs / 32; + + m_gfxdecode->gfx(2)->transpen(bitmap,cliprect, + m_vram[2][offs]+256*m_vram[2][offs+0x400], + 0, + 0,0, + (sx*8-m_scroll[2])&0xff,(sy*8-m_scroll[3])&0xff,0); + } + + if (m_spritectrl[2] & 4) + { + for (int offs = 0;offs < 0x1000;offs++) + { + int sx = ((offs/2) % 64-m_spritectrl[0]-256*(m_spritectrl[2]&1))&0x1ff; + int sy = ((offs/2) / 64-m_spritectrl[1]-128*(m_spritectrl[2]&2))&0x1ff; + + int color = (m_vram[5][offs/4]>>(2*(offs&3)))&0x03; + if (color) + { + if (sx > 0 && sx < 256 && sy > 0 && sy < 256) + bitmap.pix(sy, sx) = color; + } + } + } + + if (m_spritectrl[5] & 4) + { + for (int offs = 0;offs < 0x1000;offs++) + { + int sx = ((offs/2) % 64-m_spritectrl[3]-256*(m_spritectrl[5]&1))&0x1ff; + int sy = ((offs/2) / 64-m_spritectrl[4]-128*(m_spritectrl[5]&2))&0x1ff; + + int color = (m_vram[6][offs/4]>>(2*(offs&3)))&0x03; + if (color) + { + if (sx > 0 && sx < 256 && sy > 0 && sy < 256) + bitmap.pix(sy, sx) = color; + } + } + } + + if (m_spritectrl[8] & 4) + { + for (int offs = 0;offs < 0x1000;offs++) + { + int sx = ((offs/2) % 64-m_spritectrl[6]-256*(m_spritectrl[8]&1))&0x1ff; + int sy = ((offs/2) / 64-m_spritectrl[7]-128*(m_spritectrl[8]&2))&0x1ff; + + int color = (m_vram[7][offs/4]>>(2*(offs&3)))&0x03; + if (color) + { + if (sx > 0 && sx < 256 && sy > 0 && sy < 256) + bitmap.pix(sy, sx) = color; + } + } + } + + for (int offs = 0;offs < 0x400;offs++) + { + int sx = offs % 32; + int sy = offs / 32; + + m_gfxdecode->gfx(1)->transpen(bitmap,cliprect, + m_vram[1][offs], + 0, + 0,0, + sx*8,sy*8,0); + } + + for (int offs = 0;offs < 0x2000;offs++) + { + int sx = (offs/2) % 64; + int sy = (offs/2) / 64; + + int color = (m_vram[4][offs/4]>>(2*(offs&3)))&0x03; + if (color) + { + bitmap.pix(sy, sx) = 2 * color; + } + } + } + + for (int offs = 0;offs < 0x400;offs++) + { + int sx = offs % 32; + int sy = offs / 32; + + m_gfxdecode->gfx(0)->transpen(bitmap,cliprect, + m_vram[0][offs], + 0, + 0,0, + sx*8,sy*8,0); + } + return 0; +} + void taxidriv_state::main_map(address_map &map) { map(0x0000, 0x7fff).rom(); - map(0x8000, 0x8fff).ram(); /* ??? */ - map(0x9000, 0x9fff).ram(); /* ??? */ - map(0xa000, 0xafff).ram(); /* ??? */ - map(0xb000, 0xbfff).ram(); /* ??? */ - map(0xc000, 0xc7ff).ram().share("vram4"); /* radar bitmap */ - map(0xc800, 0xcfff).writeonly().share("vram5"); /* "sprite1" bitmap */ - map(0xd000, 0xd7ff).writeonly().share("vram6"); /* "sprite2" bitmap */ - map(0xd800, 0xdfff).ram().share("vram7"); /* "sprite3" bitmap */ - map(0xe000, 0xe3ff).ram().share("vram1"); /* car tilemap */ - map(0xe400, 0xebff).ram().share("vram2"); /* bg1 tilemap */ - map(0xec00, 0xefff).ram().share("vram0"); /* fg tilemap */ - map(0xf000, 0xf3ff).ram().share("vram3"); /* bg2 tilemap */ + map(0x8000, 0x8fff).ram(); // ??? + map(0x9000, 0x9fff).ram(); // ??? + map(0xa000, 0xafff).ram(); // ??? + map(0xb000, 0xbfff).ram(); // ??? + map(0xc000, 0xc7ff).ram().share(m_vram[4]); // radar bitmap + map(0xc800, 0xcfff).writeonly().share(m_vram[5]); // "sprite1" bitmap + map(0xd000, 0xd7ff).writeonly().share(m_vram[6]); // "sprite2" bitmap + map(0xd800, 0xdfff).ram().share(m_vram[7]); // "sprite3" bitmap + map(0xe000, 0xe3ff).ram().share(m_vram[1]); // car tilemap + map(0xe400, 0xebff).ram().share(m_vram[2]); // bg1 tilemap + map(0xec00, 0xefff).ram().share(m_vram[0]); // fg tilemap + map(0xf000, 0xf3ff).ram().share(m_vram[3]); // bg2 tilemap map(0xf400, 0xf403).rw("ppi8255_0", FUNC(i8255_device::read), FUNC(i8255_device::write)); - map(0xf480, 0xf483).rw("ppi8255_2", FUNC(i8255_device::read), FUNC(i8255_device::write)); /* "sprite1" placement */ - map(0xf500, 0xf503).rw("ppi8255_3", FUNC(i8255_device::read), FUNC(i8255_device::write)); /* "sprite2" placement */ - map(0xf580, 0xf583).rw("ppi8255_4", FUNC(i8255_device::read), FUNC(i8255_device::write)); /* "sprite3" placement */ - //map(0xf780, 0xf781).writeonly(); /* more scroll registers? */ - map(0xf782, 0xf787).writeonly().share("scroll"); /* bg scroll (three copies always identical) */ + map(0xf480, 0xf483).rw("ppi8255_2", FUNC(i8255_device::read), FUNC(i8255_device::write)); // "sprite1" placement + map(0xf500, 0xf503).rw("ppi8255_3", FUNC(i8255_device::read), FUNC(i8255_device::write)); // "sprite2" placement + map(0xf580, 0xf583).rw("ppi8255_4", FUNC(i8255_device::read), FUNC(i8255_device::write)); // "sprite3" placement + //map(0xf780, 0xf781).writeonly(); // more scroll registers? + map(0xf782, 0xf787).writeonly().share("scroll"); // bg scroll (three copies always identical) map(0xf800, 0xffff).ram(); } @@ -363,19 +548,19 @@ void taxidriv_state::taxidriv(machine_config &config) ppi1.out_pc_callback().set(FUNC(taxidriv_state::p1c_w)); i8255_device &ppi2(I8255A(config, "ppi8255_2")); - ppi2.out_pa_callback().set(FUNC(taxidriv_state::p2a_w)); - ppi2.out_pb_callback().set(FUNC(taxidriv_state::p2b_w)); - ppi2.out_pc_callback().set(FUNC(taxidriv_state::p2c_w)); + ppi2.out_pa_callback().set(FUNC(taxidriv_state::spritectrl_w<0>)); + ppi2.out_pb_callback().set(FUNC(taxidriv_state::spritectrl_w<1>)); + ppi2.out_pc_callback().set(FUNC(taxidriv_state::spritectrl_w<2>)); i8255_device &ppi3(I8255A(config, "ppi8255_3")); - ppi3.out_pa_callback().set(FUNC(taxidriv_state::p3a_w)); - ppi3.out_pb_callback().set(FUNC(taxidriv_state::p3b_w)); - ppi3.out_pc_callback().set(FUNC(taxidriv_state::p3c_w)); + ppi3.out_pa_callback().set(FUNC(taxidriv_state::spritectrl_w<3>)); + ppi3.out_pb_callback().set(FUNC(taxidriv_state::spritectrl_w<4>)); + ppi3.out_pc_callback().set(FUNC(taxidriv_state::spritectrl_w<5>)); i8255_device &ppi4(I8255A(config, "ppi8255_4")); - ppi4.out_pa_callback().set(FUNC(taxidriv_state::p4a_w)); - ppi4.out_pb_callback().set(FUNC(taxidriv_state::p4b_w)); - ppi4.out_pc_callback().set(FUNC(taxidriv_state::p4c_w)); + ppi4.out_pa_callback().set(FUNC(taxidriv_state::spritectrl_w<6>)); + ppi4.out_pb_callback().set(FUNC(taxidriv_state::spritectrl_w<7>)); + ppi4.out_pc_callback().set(FUNC(taxidriv_state::spritectrl_w<8>)); /* video hardware */ screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_RASTER)); @@ -447,5 +632,7 @@ ROM_START( taxidriv ) ROM_LOAD( "tbp18s030.ic2", 0x0000, 0x020, CRC(c366a9c5) SHA1(d38581e5c425cab4a4f216d99651e86d8034a7d2) ) // color prom located at edge of pcb ROM_END +} // anonymous namespace + GAME( 1984, taxidriv, 0, taxidriv, taxidriv, taxidriv_state, empty_init, ROT90, "Graphic Techno", "Taxi Driver", MACHINE_IMPERFECT_GRAPHICS | MACHINE_NO_COCKTAIL | MACHINE_SUPPORTS_SAVE ) diff --git a/src/mame/drivers/ultim809.cpp b/src/mame/drivers/ultim809.cpp index 8f7e2220cc8..29b69bbb1ba 100644 --- a/src/mame/drivers/ultim809.cpp +++ b/src/mame/drivers/ultim809.cpp @@ -36,14 +36,19 @@ Status: ****************************************************************************************************/ #include "emu.h" + +#include "bus/rs232/rs232.h" #include "cpu/m6809/m6809.h" -#include "video/tms9928a.h" #include "machine/6522via.h" -#include "sound/ay8910.h" #include "machine/ins8250.h" -#include "bus/rs232/rs232.h" +#include "sound/ay8910.h" +#include "video/tms9928a.h" + #include "speaker.h" + +namespace { + class ultim809_state : public driver_device { public: @@ -61,9 +66,11 @@ public: DECLARE_INPUT_CHANGED_MEMBER(nmi_button); +protected: + virtual void machine_start() override; + private: void mem_map(address_map &map); - virtual void machine_start() override; std::unique_ptr m_ram; required_device m_maincpu; required_device m_via; @@ -168,6 +175,9 @@ ROM_START( ultim809 ) ROM_LOAD( "ultim809.u9", 0x0000, 0x2000, CRC(b827aaf1) SHA1(64d9e94542d8ff13f64a4d787508eef7b64d4946) ) ROM_END +} // anonymous namespace + + /* Driver */ // YEAR NAME PARENT COMPAT MACHINE INPUT CLASS INIT COMPANY FULLNAME FLAGS diff --git a/src/mame/drivers/v6809.cpp b/src/mame/drivers/v6809.cpp index 77ad42d0de4..d94b32b958a 100644 --- a/src/mame/drivers/v6809.cpp +++ b/src/mame/drivers/v6809.cpp @@ -46,6 +46,7 @@ ToDo: *******************************************************************************************/ #include "emu.h" + #include "cpu/m6809/m6809.h" #include "imagedev/floppy.h" #include "machine/6821pia.h" @@ -57,11 +58,14 @@ ToDo: #include "machine/wd_fdc.h" #include "sound/spkrdev.h" #include "video/mc6845.h" + #include "emupal.h" #include "screen.h" #include "speaker.h" +namespace { + class v6809_state : public driver_device { public: @@ -81,10 +85,11 @@ public: void v6809(machine_config &config); -private: - virtual void machine_reset() override; +protected: virtual void machine_start() override; + virtual void machine_reset() override; +private: DECLARE_WRITE_LINE_MEMBER(speaker_en_w); DECLARE_WRITE_LINE_MEMBER(speaker_w); u8 pb_r(); @@ -368,6 +373,9 @@ ROM_START( v6809 ) ROM_RELOAD(0x0800, 0x0800) ROM_END +} // anonymous namespace + + /* Driver */ // YEAR NAME PARENT COMPAT MACHINE INPUT CLASS INIT COMPANY FULLNAME FLAGS diff --git a/src/mame/includes/hng64.h b/src/mame/includes/hng64.h index 13ed54c51a1..6d77879759b 100644 --- a/src/mame/includes/hng64.h +++ b/src/mame/includes/hng64.h @@ -5,38 +5,19 @@ #pragma once -#include "machine/msm6242.h" -#include "machine/timer.h" #include "cpu/mips/mips3.h" #include "cpu/nec/v5x.h" -#include "sound/l7a1045_l6028_dsp_a.h" -#include "video/poly.h" #include "cpu/tlcs870/tlcs870.h" #include "machine/mb8421.h" +#include "machine/msm6242.h" +#include "machine/timer.h" +#include "sound/l7a1045_l6028_dsp_a.h" +#include "video/poly.h" + #include "emupal.h" #include "screen.h" #include "tilemap.h" -enum hng64trans_t -{ - HNG64_TILEMAP_NORMAL = 1, - HNG64_TILEMAP_ADDITIVE, - HNG64_TILEMAP_ALPHA -}; - -struct blit_parameters -{ - bitmap_rgb32 * bitmap; - rectangle cliprect; - uint32_t tilemap_priority_code; - uint8_t mask; - uint8_t value; - uint8_t alpha; - hng64trans_t drawformat; -}; - -#define HNG64_MASTER_CLOCK 50000000 - ///////////////// /// 3d Engine /// @@ -141,14 +122,7 @@ class hng64_lamps_device : public device_t public: hng64_lamps_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); - auto lamps0_out_cb() { return m_lamps_out_cb[0].bind(); } - auto lamps1_out_cb() { return m_lamps_out_cb[1].bind(); } - auto lamps2_out_cb() { return m_lamps_out_cb[2].bind(); } - auto lamps3_out_cb() { return m_lamps_out_cb[3].bind(); } - auto lamps4_out_cb() { return m_lamps_out_cb[4].bind(); } - auto lamps5_out_cb() { return m_lamps_out_cb[5].bind(); } - auto lamps6_out_cb() { return m_lamps_out_cb[6].bind(); } - auto lamps7_out_cb() { return m_lamps_out_cb[7].bind(); } + template auto lamps_out_cb() { return m_lamps_out_cb[N].bind(); } void lamps_w(offs_t offset, uint8_t data) { m_lamps_out_cb[offset](data); } @@ -191,7 +165,6 @@ public: m_idt7133_dpram(*this, "com_ram"), m_gfxdecode(*this, "gfxdecode"), m_in(*this, "IN%u", 0U), - m_an_in(*this, "AN%u", 0U), m_samsho64_3d_hack(0), m_roadedge_3d_hack(0) { } @@ -214,17 +187,36 @@ public: required_device m_palette; private: + static constexpr int HNG64_MASTER_CLOCK = 50'000'000; + /* TODO: NOT measured! */ - const int PIXEL_CLOCK = (HNG64_MASTER_CLOCK*2)/4; // x 2 is due to the interlaced screen ... + static constexpr int PIXEL_CLOCK = (HNG64_MASTER_CLOCK*2)/4; // x 2 is due to the interlaced screen ... - const int HTOTAL = 0x200+0x100; - const int HBEND = 0; - const int HBSTART = 0x200; + static constexpr int HTOTAL = 0x200+0x100; + static constexpr int HBEND = 0; + static constexpr int HBSTART = 0x200; - const int VTOTAL = 264*2; - const int VBEND = 0; - const int VBSTART = 224*2; + static constexpr int VTOTAL = 264*2; + static constexpr int VBEND = 0; + static constexpr int VBSTART = 224*2; + enum hng64trans_t + { + HNG64_TILEMAP_NORMAL = 1, + HNG64_TILEMAP_ADDITIVE, + HNG64_TILEMAP_ALPHA + }; + + struct blit_parameters + { + bitmap_rgb32 * bitmap; + rectangle cliprect; + uint32_t tilemap_priority_code; + uint8_t mask; + uint8_t value; + uint8_t alpha; + hng64trans_t drawformat; + }; required_device m_maincpu; required_device m_audiocpu; @@ -257,17 +249,8 @@ private: required_device m_gfxdecode; required_ioport_array<8> m_in; - required_ioport_array<8> m_an_in; - - void hng64_default_lamps0_w(uint8_t data) { logerror("lamps0 %02x\n", data); } - void hng64_default_lamps1_w(uint8_t data) { logerror("lamps1 %02x\n", data); } - void hng64_default_lamps2_w(uint8_t data) { logerror("lamps2 %02x\n", data); } - void hng64_default_lamps3_w(uint8_t data) { logerror("lamps3 %02x\n", data); } - void hng64_default_lamps4_w(uint8_t data) { logerror("lamps4 %02x\n", data); } - void hng64_default_lamps5_w(uint8_t data) { logerror("lamps5 %02x\n", data); } - void hng64_default_lamps6_w(uint8_t data) { logerror("lamps6 %02x\n", data); } - void hng64_default_lamps7_w(uint8_t data) { logerror("lamps7 %02x\n", data); } + template void hng64_default_lamps_w(uint8_t data) { logerror("lamps%u %02x\n", N, data); } void hng64_drive_lamps7_w(uint8_t data); void hng64_drive_lamps6_w(uint8_t data); @@ -405,16 +388,6 @@ private: // unknown access void ioport4_w(uint8_t data); - // analog input access - uint8_t anport0_r(); - uint8_t anport1_r(); - uint8_t anport2_r(); - uint8_t anport3_r(); - uint8_t anport4_r(); - uint8_t anport5_r(); - uint8_t anport6_r(); - uint8_t anport7_r(); - DECLARE_WRITE_LINE_MEMBER( sio0_w ); uint8_t m_port7; @@ -470,6 +443,7 @@ private: uint32_t startx, uint32_t starty, int incxx, int incxy, int incyx, int incyy, int wraparound, uint32_t flags, uint8_t priority, uint8_t priority_mask, hng64trans_t drawformat); + static void hng64_configure_blit_parameters(blit_parameters *blit, tilemap_t *tmap, bitmap_rgb32 &dest, const rectangle &cliprect, uint32_t flags, uint8_t priority, uint8_t priority_mask, hng64trans_t drawformat); diff --git a/src/mame/includes/taxidriv.h b/src/mame/includes/taxidriv.h deleted file mode 100644 index 9c7a2834396..00000000000 --- a/src/mame/includes/taxidriv.h +++ /dev/null @@ -1,89 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Nicola Salmoria -#ifndef MAME_INCLUDES_TAXIDRIV_H -#define MAME_INCLUDES_TAXIDRIV_H - -#pragma once - -#include "emupal.h" - -class taxidriv_state : public driver_device -{ -public: - taxidriv_state(const machine_config &mconfig, device_type type, const char *tag) : - driver_device(mconfig, type, tag), - m_maincpu(*this, "maincpu"), - m_gfxdecode(*this, "gfxdecode"), - m_palette(*this, "palette"), - m_vram0(*this, "vram0"), - m_vram1(*this, "vram1"), - m_vram2(*this, "vram2"), - m_vram3(*this, "vram3"), - m_vram4(*this, "vram4"), - m_vram5(*this, "vram5"), - m_vram6(*this, "vram6"), - m_vram7(*this, "vram7"), - m_scroll(*this, "scroll") - { } - - void taxidriv(machine_config &config); - -protected: - virtual void machine_start() override; - -private: - required_device m_maincpu; - required_device m_gfxdecode; - required_device m_palette; - - required_shared_ptr m_vram0; - required_shared_ptr m_vram1; - required_shared_ptr m_vram2; - required_shared_ptr m_vram3; - required_shared_ptr m_vram4; - required_shared_ptr m_vram5; - required_shared_ptr m_vram6; - required_shared_ptr m_vram7; - required_shared_ptr m_scroll; - - int m_s1; - int m_s2; - int m_s3; - int m_s4; - int m_latchA; - int m_latchB; - int m_bghide; - int m_spritectrl[9]; - - void p2a_w(uint8_t data); - void p2b_w(uint8_t data); - void p2c_w(uint8_t data); - void p3a_w(uint8_t data); - void p3b_w(uint8_t data); - void p3c_w(uint8_t data); - void p4a_w(uint8_t data); - void p4b_w(uint8_t data); - void p4c_w(uint8_t data); - uint8_t p0a_r(); - uint8_t p0c_r(); - void p0b_w(uint8_t data); - void p0c_w(uint8_t data); - uint8_t p1b_r(); - uint8_t p1c_r(); - void p1a_w(uint8_t data); - void p1c_w(uint8_t data); - uint8_t p8910_0a_r(); - uint8_t p8910_1a_r(); - void p8910_0b_w(uint8_t data); - void spritectrl_w(offs_t offset, uint8_t data); - - void taxidriv_palette(palette_device &palette) const; - - uint32_t screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect); - void cpu2_map(address_map &map); - void cpu3_map(address_map &map); - void cpu3_port_map(address_map &map); - void main_map(address_map &map); -}; - -#endif // MAME_INCLUDES_TAXIDRIV_H diff --git a/src/mame/video/hng64.cpp b/src/mame/video/hng64.cpp index b3ff066a323..23228f88733 100644 --- a/src/mame/video/hng64.cpp +++ b/src/mame/video/hng64.cpp @@ -176,7 +176,7 @@ void hng64_state::hng64_videoram_w(offs_t offset, uint32_t data, uint32_t mem_ma /* internal set of transparency states for rendering */ -static void hng64_configure_blit_parameters(blit_parameters *blit, tilemap_t *tmap, bitmap_rgb32 &dest, const rectangle &cliprect, uint32_t flags, uint8_t priority, uint8_t priority_mask, hng64trans_t drawformat) +void hng64_state::hng64_configure_blit_parameters(blit_parameters *blit, tilemap_t *tmap, bitmap_rgb32 &dest, const rectangle &cliprect, uint32_t flags, uint8_t priority, uint8_t priority_mask, hng64trans_t drawformat) { /* start with nothing */ memset(blit, 0, sizeof(*blit)); diff --git a/src/mame/video/taxidriv.cpp b/src/mame/video/taxidriv.cpp deleted file mode 100644 index ddf06c509a5..00000000000 --- a/src/mame/video/taxidriv.cpp +++ /dev/null @@ -1,136 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Nicola Salmoria -#include "emu.h" -#include "includes/taxidriv.h" - - -void taxidriv_state::spritectrl_w(offs_t offset, uint8_t data) -{ - m_spritectrl[offset] = data; -} - - - -uint32_t taxidriv_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect) -{ - if (m_bghide) - { - bitmap.fill(0, cliprect); - - - /* kludge to fix scroll after death */ - m_scroll[0] = m_scroll[1] = m_scroll[2] = m_scroll[3] = 0; - m_spritectrl[2] = m_spritectrl[5] = m_spritectrl[8] = 0; - } - else - { - for (int offs = 0;offs < 0x400;offs++) - { - int sx = offs % 32; - int sy = offs / 32; - - m_gfxdecode->gfx(3)->opaque(bitmap,cliprect, - m_vram3[offs], - 0, - 0,0, - (sx*8-m_scroll[0])&0xff,(sy*8-m_scroll[1])&0xff); - } - - for (int offs = 0;offs < 0x400;offs++) - { - int sx = offs % 32; - int sy = offs / 32; - - m_gfxdecode->gfx(2)->transpen(bitmap,cliprect, - m_vram2[offs]+256*m_vram2[offs+0x400], - 0, - 0,0, - (sx*8-m_scroll[2])&0xff,(sy*8-m_scroll[3])&0xff,0); - } - - if (m_spritectrl[2] & 4) - { - for (int offs = 0;offs < 0x1000;offs++) - { - int sx = ((offs/2) % 64-m_spritectrl[0]-256*(m_spritectrl[2]&1))&0x1ff; - int sy = ((offs/2) / 64-m_spritectrl[1]-128*(m_spritectrl[2]&2))&0x1ff; - - int color = (m_vram5[offs/4]>>(2*(offs&3)))&0x03; - if (color) - { - if (sx > 0 && sx < 256 && sy > 0 && sy < 256) - bitmap.pix(sy, sx) = color; - } - } - } - - if (m_spritectrl[5] & 4) - { - for (int offs = 0;offs < 0x1000;offs++) - { - int sx = ((offs/2) % 64-m_spritectrl[3]-256*(m_spritectrl[5]&1))&0x1ff; - int sy = ((offs/2) / 64-m_spritectrl[4]-128*(m_spritectrl[5]&2))&0x1ff; - - int color = (m_vram6[offs/4]>>(2*(offs&3)))&0x03; - if (color) - { - if (sx > 0 && sx < 256 && sy > 0 && sy < 256) - bitmap.pix(sy, sx) = color; - } - } - } - - if (m_spritectrl[8] & 4) - { - for (int offs = 0;offs < 0x1000;offs++) - { - int sx = ((offs/2) % 64-m_spritectrl[6]-256*(m_spritectrl[8]&1))&0x1ff; - int sy = ((offs/2) / 64-m_spritectrl[7]-128*(m_spritectrl[8]&2))&0x1ff; - - int color = (m_vram7[offs/4]>>(2*(offs&3)))&0x03; - if (color) - { - if (sx > 0 && sx < 256 && sy > 0 && sy < 256) - bitmap.pix(sy, sx) = color; - } - } - } - - for (int offs = 0;offs < 0x400;offs++) - { - int sx = offs % 32; - int sy = offs / 32; - - m_gfxdecode->gfx(1)->transpen(bitmap,cliprect, - m_vram1[offs], - 0, - 0,0, - sx*8,sy*8,0); - } - - for (int offs = 0;offs < 0x2000;offs++) - { - int sx = (offs/2) % 64; - int sy = (offs/2) / 64; - - int color = (m_vram4[offs/4]>>(2*(offs&3)))&0x03; - if (color) - { - bitmap.pix(sy, sx) = 2 * color; - } - } - } - - for (int offs = 0;offs < 0x400;offs++) - { - int sx = offs % 32; - int sy = offs / 32; - - m_gfxdecode->gfx(0)->transpen(bitmap,cliprect, - m_vram0[offs], - 0, - 0,0, - sx*8,sy*8,0); - } - return 0; -} diff --git a/src/osd/asio.h b/src/osd/asio.h index 3ee31a467d7..d59a90b8929 100644 --- a/src/osd/asio.h +++ b/src/osd/asio.h @@ -17,7 +17,7 @@ #pragma GCC diagnostic ignored "-Wunused-variable" #endif -#if defined(WIN32) && !defined(_WIN32_WINNT) +#if defined(_WIN32) && !defined(_WIN32_WINNT) #if defined(OSD_WINDOWS) #define _WIN32_WINNT 0x0501 #else diff --git a/src/osd/modules/debugger/debugqt.cpp b/src/osd/modules/debugger/debugqt.cpp index 6731dc63e21..a48f419a6a3 100644 --- a/src/osd/modules/debugger/debugqt.cpp +++ b/src/osd/modules/debugger/debugqt.cpp @@ -33,7 +33,7 @@ #include "qt/deviceinformationwindow.h" class debug_qt : public osd_module, public debug_module -#if defined(WIN32) && !defined(SDLMAME_WIN32) +#if defined(_WIN32) && !defined(SDLMAME_WIN32) , public QAbstractNativeEventFilter #endif { @@ -50,7 +50,7 @@ public: virtual void init_debugger(running_machine &machine); virtual void wait_for_debugger(device_t &device, bool firststop); virtual void debugger_update(); -#if defined(WIN32) && !defined(SDLMAME_WIN32) +#if defined(_WIN32) && !defined(SDLMAME_WIN32) virtual bool nativeEventFilter(const QByteArray &eventType, void *message, long *) Q_DECL_OVERRIDE; #endif private: @@ -230,7 +230,7 @@ void bring_main_window_to_front() // Core functionality //============================================================ -#if defined(WIN32) && !defined(SDLMAME_WIN32) +#if defined(_WIN32) && !defined(SDLMAME_WIN32) bool winwindow_qt_filter(void *message); bool debug_qt::nativeEventFilter(const QByteArray &eventType, void *message, long *) @@ -246,7 +246,7 @@ void debug_qt::init_debugger(running_machine &machine) { // If you're starting from scratch, create a new qApp new QApplication(qtArgc, qtArgv); -#if defined(WIN32) && !defined(SDLMAME_WIN32) +#if defined(_WIN32) && !defined(SDLMAME_WIN32) QAbstractEventDispatcher::instance()->installNativeEventFilter(this); #endif } @@ -276,7 +276,7 @@ void debug_qt::init_debugger(running_machine &machine) #if defined(SDLMAME_UNIX) || defined(SDLMAME_WIN32) extern int sdl_entered_debugger; -#elif defined(WIN32) +#elif defined(_WIN32) void winwindow_update_cursor_state(running_machine &machine); #endif @@ -343,7 +343,7 @@ void debug_qt::wait_for_debugger(device_t &device, bool firststop) // all the QT windows are already gone. gather_save_configurations(); } -#if defined(WIN32) && !defined(SDLMAME_WIN32) +#if defined(_WIN32) && !defined(SDLMAME_WIN32) winwindow_update_cursor_state(*m_machine); // make sure the cursor isn't hidden while in debugger #endif } diff --git a/src/osd/modules/file/posixdir.cpp b/src/osd/modules/file/posixdir.cpp index 9cd29a84600..63a02925bf1 100644 --- a/src/osd/modules/file/posixdir.cpp +++ b/src/osd/modules/file/posixdir.cpp @@ -22,7 +22,7 @@ #endif #endif -#ifdef WIN32 +#ifdef _WIN32 #define _FILE_OFFSET_BITS 64 #endif @@ -63,13 +63,13 @@ namespace { // CONSTANTS //============================================================ -#if defined(WIN32) +#if defined(_WIN32) constexpr char PATHSEPCH = '\\'; #else constexpr char PATHSEPCH = '/'; #endif -#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__bsdi__) || defined(__DragonFly__) || defined(__EMSCRIPTEN__) || defined(__ANDROID__) || defined(WIN32) || defined(SDLMAME_NO64BITIO) +#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__bsdi__) || defined(__DragonFly__) || defined(__EMSCRIPTEN__) || defined(__ANDROID__) || defined(_WIN32) || defined(SDLMAME_NO64BITIO) using sdl_dirent = struct dirent; using sdl_stat = struct stat; #define sdl_readdir readdir diff --git a/src/osd/modules/file/posixfile.cpp b/src/osd/modules/file/posixfile.cpp index b7c1cde7442..580288c7d10 100644 --- a/src/osd/modules/file/posixfile.cpp +++ b/src/osd/modules/file/posixfile.cpp @@ -22,7 +22,7 @@ #endif #endif -#ifdef WIN32 +#ifdef _WIN32 #define _FILE_OFFSET_BITS 64 #endif @@ -69,7 +69,7 @@ namespace { // CONSTANTS //============================================================ -#if defined(WIN32) +#if defined(_WIN32) constexpr char PATHSEPCH = '\\'; constexpr char INVPATHSEPCH = '/'; #else @@ -102,7 +102,7 @@ public: #if defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__bsdi__) || defined(__DragonFly__) || defined(__EMSCRIPTEN__) || defined(__ANDROID__) result = ::pread(m_fd, buffer, size_t(count), off_t(std::make_unsigned_t(offset))); -#elif defined(WIN32) || defined(SDLMAME_NO64BITIO) +#elif defined(_WIN32) || defined(SDLMAME_NO64BITIO) if (lseek(m_fd, off_t(std::make_unsigned_t(offset)), SEEK_SET) < 0) return std::error_condition(errno, std::generic_category()); result = ::read(m_fd, buffer, size_t(count)); @@ -123,7 +123,7 @@ public: #if defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__bsdi__) || defined(__DragonFly__) || defined(__EMSCRIPTEN__) || defined(__ANDROID__) result = ::pwrite(m_fd, buffer, size_t(count), off_t(std::make_unsigned_t(offset))); -#elif defined(WIN32) || defined(SDLMAME_NO64BITIO) +#elif defined(_WIN32) || defined(SDLMAME_NO64BITIO) if (lseek(m_fd, off_t(std::make_unsigned_t(offset)), SEEK_SET) < 0) return std::error_condition(errno, std::generic_category()); result = ::write(m_fd, buffer, size_t(count)); @@ -142,7 +142,7 @@ public: { int result; -#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__bsdi__) || defined(__DragonFly__) || defined(__EMSCRIPTEN__) || defined(WIN32) || defined(SDLMAME_NO64BITIO) || defined(__ANDROID__) +#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__bsdi__) || defined(__DragonFly__) || defined(__EMSCRIPTEN__) || defined(_WIN32) || defined(SDLMAME_NO64BITIO) || defined(__ANDROID__) result = ::ftruncate(m_fd, off_t(std::make_unsigned_t(offset))); #else result = ::ftruncate64(m_fd, off64_t(offset)); @@ -171,7 +171,7 @@ private: bool is_path_separator(char c) noexcept { -#if defined(WIN32) +#if defined(_WIN32) return (c == PATHSEPCH) || (c == INVPATHSEPCH); #else return c == PATHSEPCH; @@ -205,7 +205,7 @@ std::error_condition create_path_recursive(std::string_view path) noexcept return std::error_condition(); // create the path -#ifdef WIN32 +#ifdef _WIN32 if (mkdir(p.c_str()) < 0) #else if (mkdir(p.c_str(), 0777) < 0) @@ -247,13 +247,13 @@ std::error_condition osd_file::open(std::string const &path, std::uint32_t openf { return std::errc::invalid_argument; } -#if defined(WIN32) +#if defined(_WIN32) access |= O_BINARY; #endif // convert the path into something compatible dst = path; -#if defined(WIN32) +#if defined(_WIN32) for (auto it = dst.begin(); it != dst.end(); ++it) *it = (INVPATHSEPCH == *it) ? PATHSEPCH : *it; #endif @@ -262,7 +262,7 @@ std::error_condition osd_file::open(std::string const &path, std::uint32_t openf // 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) || defined(__ANDROID__) +#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__bsdi__) || defined(__DragonFly__) || defined(__HAIKU__) || defined(_WIN32) || defined(SDLMAME_NO64BITIO) || defined(__ANDROID__) fd = ::open(dst.c_str(), access, 0666); #else fd = ::open64(dst.c_str(), access, 0666); @@ -285,7 +285,7 @@ std::error_condition osd_file::open(std::string const &path, std::uint32_t openf // attempt to reopen the file if (!createrr) { -#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__bsdi__) || defined(__DragonFly__) || defined(__HAIKU__) || defined(WIN32) || defined(SDLMAME_NO64BITIO) || defined(__ANDROID__) +#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__bsdi__) || defined(__DragonFly__) || defined(__HAIKU__) || defined(_WIN32) || defined(SDLMAME_NO64BITIO) || defined(__ANDROID__) fd = ::open(dst.c_str(), access, 0666); #else fd = ::open64(dst.c_str(), access, 0666); @@ -306,7 +306,7 @@ std::error_condition osd_file::open(std::string const &path, std::uint32_t openf } // get the file size -#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__bsdi__) || defined(__DragonFly__) || defined(__HAIKU__) || defined(WIN32) || defined(SDLMAME_NO64BITIO) || defined(__ANDROID__) +#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__bsdi__) || defined(__DragonFly__) || defined(__HAIKU__) || defined(_WIN32) || defined(SDLMAME_NO64BITIO) || defined(__ANDROID__) struct stat st; if (::fstat(fd, &st) < 0) #else @@ -371,7 +371,7 @@ bool osd_get_physical_drive_geometry(const char *filename, uint32_t *cylinders, std::unique_ptr 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) || defined(__ANDROID__) +#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__bsdi__) || defined(__DragonFly__) || defined(__HAIKU__) || defined(_WIN32) || defined(SDLMAME_NO64BITIO) || defined(__ANDROID__) struct stat st; int const err = ::stat(path.c_str(), &st); #else @@ -405,7 +405,7 @@ std::error_condition osd_get_full_path(std::string &dst, std::string const &path { try { -#if defined(WIN32) +#if defined(_WIN32) std::vector path_buffer(MAX_PATH); if (::_fullpath(&path_buffer[0], path.c_str(), MAX_PATH)) { @@ -465,7 +465,7 @@ bool osd_is_absolute_path(std::string const &path) noexcept { if (!path.empty() && is_path_separator(path[0])) return true; -#if !defined(WIN32) +#if !defined(_WIN32) else if (!path.empty() && (path[0] == '.') && (!path[1] || is_path_separator(path[1]))) // FIXME: why is this even here? foo/./bar is a valid way to refer to foo/bar return true; #elif !defined(UNDER_CE) @@ -509,7 +509,7 @@ bool osd_is_valid_filename_char(char32_t uchar) noexcept // The only one that's actually invalid is the slash // The other two are just problematic because they're the escape character and path separator return osd_is_valid_filepath_char(uchar) -#if defined(WIN32) +#if defined(_WIN32) && uchar != PATHSEPCH && uchar != INVPATHSEPCH #else @@ -529,7 +529,7 @@ bool osd_is_valid_filepath_char(char32_t uchar) noexcept // One could argue that colon should be in here too because it functions as path separator return uchar >= 0x20 && !(uchar >= '\x7F' && uchar <= '\x9F') -#if defined(WIN32) +#if defined(_WIN32) && uchar != '<' && uchar != '>' && uchar != '\"' diff --git a/src/osd/modules/netdev/taptun.cpp b/src/osd/modules/netdev/taptun.cpp index 6999d6f63ba..c0d99ec750c 100644 --- a/src/osd/modules/netdev/taptun.cpp +++ b/src/osd/modules/netdev/taptun.cpp @@ -2,7 +2,7 @@ // copyright-holders:Carl #if defined(OSD_NET_USE_TAPTUN) -#if defined(WIN32) +#if defined(_WIN32) #include #include #else @@ -23,7 +23,7 @@ #define IFF_TAP 0x0002 #define IFF_NO_PI 0x1000 #define TUNSETIFF _IOW('T', 202, int) -#elif defined(WIN32) +#elif defined(_WIN32) #include "tap-windows6/tap-windows.h" // for some reason this isn't defined in the header, and presumably it changes @@ -62,7 +62,7 @@ public: protected: int recv_dev(uint8_t **buf) override; private: -#if defined(WIN32) +#if defined(_WIN32) HANDLE m_handle = INVALID_HANDLE_VALUE; OVERLAPPED m_overlapped; bool m_receive_pending; @@ -98,7 +98,7 @@ netdev_tap::netdev_tap(const char *name, class device_network_interface *ifdev, osd_printf_verbose("netdev_tap: network up!\n"); strncpy(m_ifname, ifr.ifr_name, 10); fcntl(m_fd, F_SETFL, O_NONBLOCK); -#elif defined(WIN32) +#elif defined(_WIN32) std::wstring device_path(L"" USERMODEDEVICEDIR); device_path.append(wstring_from_utf8(name)); device_path.append(L"" TAP_WIN_SUFFIX); @@ -121,7 +121,7 @@ netdev_tap::netdev_tap(const char *name, class device_network_interface *ifdev, netdev_tap::~netdev_tap() { -#if defined(WIN32) +#if defined(_WIN32) if (m_handle != INVALID_HANDLE_VALUE) { if (m_receive_pending) @@ -169,7 +169,7 @@ static u32 finalise_frame(u8 buf[], u32 length) return length; } -#if defined(WIN32) +#if defined(_WIN32) int netdev_tap::send(uint8_t *buf, int len) { OVERLAPPED overlapped = {}; @@ -344,7 +344,7 @@ static CREATE_NETDEV(create_tap) int taptun_module::init(const osd_options &options) { -#if defined(WIN32) +#if defined(_WIN32) for (std::wstring &id : get_tap_adapters()) add_netdev(utf8_from_wstring(id).c_str(), utf8_from_wstring(get_connection_name(id)).c_str(), create_tap); #else diff --git a/src/osd/modules/sound/pa_sound.cpp b/src/osd/modules/sound/pa_sound.cpp index c71852df8e8..ce191b6086a 100644 --- a/src/osd/modules/sound/pa_sound.cpp +++ b/src/osd/modules/sound/pa_sound.cpp @@ -24,7 +24,7 @@ #include #include -#ifdef WIN32 +#ifdef _WIN32 #include "pa_win_wasapi.h" #endif @@ -216,7 +216,7 @@ int sound_pa::init(osd_options const &options) // 0 = use default stream_params.suggestedLatency = options.pa_latency() ? options.pa_latency() : device_info->defaultLowOutputLatency; -#ifdef WIN32 +#ifdef _WIN32 PaWasapiStreamInfo wasapi_stream_info; // if requested latency is less than 20 ms, we need to use exclusive mode diff --git a/src/osd/osdcore.cpp b/src/osd/osdcore.cpp index f883e50f321..f5860416381 100644 --- a/src/osd/osdcore.cpp +++ b/src/osd/osdcore.cpp @@ -139,7 +139,7 @@ void osd_vprintf_debug(util::format_argument_pack const &args) osd_ticks_t osd_ticks() { -#ifdef WIN32 +#ifdef _WIN32 LARGE_INTEGER val; QueryPerformanceCounter(&val); return val.QuadPart; @@ -155,7 +155,7 @@ osd_ticks_t osd_ticks() osd_ticks_t osd_ticks_per_second() { -#ifdef WIN32 +#ifdef _WIN32 LARGE_INTEGER val; QueryPerformanceFrequency(&val); return val.QuadPart; @@ -170,7 +170,7 @@ osd_ticks_t osd_ticks_per_second() void osd_sleep(osd_ticks_t duration) { -#ifdef WIN32 +#ifdef _WIN32 // sleep_for appears to oversleep on Windows with gcc 8 Sleep(duration / (osd_ticks_per_second() / 1000)); #else @@ -190,7 +190,7 @@ void osd_sleep(osd_ticks_t duration) std::vector osd_get_command_line(int argc, char *argv[]) { std::vector results; -#ifdef WIN32 +#ifdef _WIN32 { // Get the command line from Windows int count; @@ -206,7 +206,7 @@ std::vector osd_get_command_line(int argc, char *argv[]) LocalFree(wide_args); } -#else // !WIN32 +#else // !_WIN32 { // for non Windows platforms, we are assuming that arguments are // already UTF-8; we just need to convert to std::vector @@ -214,6 +214,6 @@ std::vector osd_get_command_line(int argc, char *argv[]) for (int i = 0; i < argc; i++) results.emplace_back(argv[i]); } -#endif // WIN32 +#endif // _WIN32 return results; } diff --git a/src/osd/strconv.h b/src/osd/strconv.h index f1eed54a49a..3843ee00f98 100644 --- a/src/osd/strconv.h +++ b/src/osd/strconv.h @@ -17,7 +17,7 @@ // FUNCTION PROTOTYPES //============================================================ -#if defined(WIN32) +#if defined(_WIN32) #include @@ -56,7 +56,7 @@ typedef std::string tstring; } } -#endif // defined(WIN32) +#endif // defined(_WIN32) #endif // MAME_OSD_STRCONV_H diff --git a/src/tools/chdman.cpp b/src/tools/chdman.cpp index e0243ce7277..d1cb963a8f8 100644 --- a/src/tools/chdman.cpp +++ b/src/tools/chdman.cpp @@ -39,7 +39,7 @@ using util::string_format; // CONSTANTS & DEFINES //************************************************************************** // MINGW has adopted the MSVC formatting for 64-bit ints as of GCC 4.4 and deprecated it as of GCC 9.3 -#if defined(WIN32) && defined(__GNUC__) && ((__GNUC__ < 9) || ((__GNUC__ == 9) && (__GNUC_MINOR__ < 3))) +#if defined(_WIN32) && defined(__GNUC__) && ((__GNUC__ < 9) || ((__GNUC__ == 9) && (__GNUC_MINOR__ < 3))) #define I64FMT "I64" #elif !defined(__APPLE__) && defined(__LP64__) #define I64FMT "l" diff --git a/src/tools/srcclean.cpp b/src/tools/srcclean.cpp index 340217c7768..85cf28a22a2 100644 --- a/src/tools/srcclean.cpp +++ b/src/tools/srcclean.cpp @@ -2212,7 +2212,7 @@ int main(int argc, char *argv[]) { bool keep_backup(false); bool dry_run(false); -#if defined(WIN32) +#if defined(_WIN32) cleaner_base::newline newline_mode(cleaner_base::newline::DOS); #else cleaner_base::newline newline_mode(cleaner_base::newline::UNIX); -- cgit v1.2.3