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 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