summaryrefslogtreecommitdiffstatshomepage
path: root/src/tools
diff options
context:
space:
mode:
Diffstat (limited to 'src/tools')
-rw-r--r--src/tools/aueffectutil.mm127
-rw-r--r--src/tools/chdman.cpp1500
-rw-r--r--src/tools/floptool.cpp17
-rw-r--r--src/tools/image_handler.cpp17
-rw-r--r--src/tools/imgtool/filtbas.cpp216
-rw-r--r--src/tools/imgtool/filteoln.cpp4
-rw-r--r--src/tools/imgtool/filter.cpp27
-rw-r--r--src/tools/imgtool/filter.h46
-rw-r--r--src/tools/imgtool/imgtool.cpp107
-rw-r--r--src/tools/imgtool/imgtool.h16
-rw-r--r--src/tools/imgtool/library.h261
-rw-r--r--src/tools/imgtool/main.cpp16
-rw-r--r--src/tools/imgtool/modules/amiga.cpp6
-rw-r--r--src/tools/imgtool/modules/bml3.cpp26
-rw-r--r--src/tools/imgtool/modules/dgndos.cpp24
-rw-r--r--src/tools/imgtool/modules/fat.cpp32
-rw-r--r--src/tools/imgtool/modules/hp9845_tape.cpp2
-rw-r--r--src/tools/imgtool/modules/rsdos.cpp24
-rw-r--r--src/tools/imgtool/modules/thomson.cpp206
-rw-r--r--src/tools/imgtool/modules/vzdos.cpp146
-rw-r--r--src/tools/imgtool/stream.cpp15
-rw-r--r--src/tools/ldresample.cpp2
-rw-r--r--src/tools/ldverify.cpp2
-rw-r--r--src/tools/regrep.cpp25
-rw-r--r--src/tools/romcmp.cpp3
-rw-r--r--src/tools/split.cpp30
-rw-r--r--src/tools/srcclean.cpp19
-rw-r--r--src/tools/unidasm.cpp41
28 files changed, 1590 insertions, 1367 deletions
diff --git a/src/tools/aueffectutil.mm b/src/tools/aueffectutil.mm
index 661800a3b48..b8a83de4c64 100644
--- a/src/tools/aueffectutil.mm
+++ b/src/tools/aueffectutil.mm
@@ -16,29 +16,12 @@
#include <cstdlib>
-#ifdef MAC_OS_X_VERSION_MAX_ALLOWED
-
-#if MAC_OS_X_VERSION_MAX_ALLOWED < 1060
-
-typedef ComponentDescription AudioComponentDescription;
-
-@protocol NSApplicationDelegate <NSObject>
-@end
-
-@protocol NSWindowDelegate <NSObject>
-@end
-
-#endif // MAC_OS_X_VERSION_MAX_ALLOWED < 1060
-
-#endif // MAC_OS_X_VERSION_MAX_ALLOWED
-
-
struct EffectInfo
{
- Component component;
- OSType type;
- OSType subtype;
- OSType manufacturer;
+ AudioComponent component;
+ OSType type;
+ OSType subtype;
+ OSType manufacturer;
};
@@ -173,7 +156,7 @@ static void UpdateChangeCountCallback(
if (!customViewValid)
{
forceGenericView = YES;
- [genericViewButton setState:NSOnState];
+ [genericViewButton setState:NSControlStateValueOn];
}
CFIndex const presetCount = (NULL != presets) ? CFArrayGetCount(presets) : 0;
@@ -256,11 +239,11 @@ static void UpdateChangeCountCallback(
- (void)makeWindowControllers {
genericViewButton = [[NSButton alloc] initWithFrame:NSMakeRect(0, 0, 100, 18)];
[genericViewButton setAutoresizingMask:NSViewNotSizable];
- [[genericViewButton cell] setControlSize:NSSmallControlSize];
- [genericViewButton setButtonType:NSSwitchButton];
+ [[genericViewButton cell] setControlSize:NSControlSizeSmall];
+ [genericViewButton setButtonType:NSButtonTypeSwitch];
[genericViewButton setBordered:NO];
[genericViewButton setAllowsMixedState:NO];
- [genericViewButton setState:(forceGenericView ? NSOnState : NSOffState)];
+ [genericViewButton setState:(forceGenericView ? NSControlStateValueOn : NSControlStateValueOff)];
[genericViewButton setTitle:@"Use generic editor view"];
[genericViewButton setAction:@selector(toggleGenericView:)];
[genericViewButton setTarget:self];
@@ -268,8 +251,8 @@ static void UpdateChangeCountCallback(
presetButton = [[NSPopUpButton alloc] initWithFrame:NSMakeRect(0, 0, 100, 22) pullsDown:YES];
[presetButton setAutoresizingMask:NSViewNotSizable];
- [[presetButton cell] setControlSize:NSSmallControlSize];
- [[presetButton cell] setFont:[NSFont systemFontOfSize:[NSFont systemFontSizeForControlSize:NSSmallControlSize]]];
+ [[presetButton cell] setControlSize:NSControlSizeSmall];
+ [[presetButton cell] setFont:[NSFont systemFontOfSize:[NSFont systemFontSizeForControlSize:NSControlSizeSmall]]];
[presetButton setTitle:@"Load preset"];
[[[presetButton menu] addItemWithTitle:@"Load preset" action:NULL keyEquivalent:@""] setHidden:YES];
[presetButton sizeToFit];
@@ -297,9 +280,9 @@ static void UpdateChangeCountCallback(
[presetButton release];
window = [[NSWindow alloc] initWithContentRect:NSMakeRect(0, 0, headerSize.width, headerSize.height)
- styleMask:(NSTitledWindowMask |
- NSClosableWindowMask |
- NSMiniaturizableWindowMask)
+ styleMask:(NSWindowStyleMaskTitled |
+ NSWindowStyleMaskClosable |
+ NSWindowStyleMaskMiniaturizable)
backing:NSBackingStoreBuffered
defer:YES];
[window setReleasedWhenClosed:NO];
@@ -346,22 +329,20 @@ static void UpdateChangeCountCallback(
return NO;
}
- NSString *errDesc = nil;
- id const desc = [NSPropertyListSerialization propertyListFromData:data
- mutabilityOption:0
+ NSError *errDesc = nil;
+ id const desc = [NSPropertyListSerialization propertyListWithData:data
+ options:NSPropertyListImmutable
format:NULL
- errorDescription:&errDesc];
+ error:&errDesc];
if (!desc || ![desc isKindOfClass:[NSDictionary class]] || errDesc)
{
if (error)
{
- NSString *const message = [NSString stringWithFormat:@"Error in file format (%@)", errDesc];
+ NSString *const message = [NSString stringWithFormat:@"Error in file format (%@)", [errDesc localizedDescription]];
NSDictionary *const info = [NSDictionary dictionaryWithObjectsAndKeys:message, NSLocalizedDescriptionKey,
nil];
*error = [NSError errorWithDomain:AUEffectUtilErrorDomain code:0 userInfo:info];
}
- if (errDesc)
- [errDesc release];
return NO;
}
@@ -579,7 +560,7 @@ static void UpdateChangeCountCallback(
&& [[desc objectForKey:ForceGenericViewKey] respondsToSelector:@selector(boolValue)])
{
forceGenericView = [[desc objectForKey:ForceGenericViewKey] boolValue];
- [genericViewButton setState:(forceGenericView ? NSOnState : NSOffState)];
+ [genericViewButton setState:(forceGenericView ? NSControlStateValueOn : NSControlStateValueOff)];
}
if ([desc objectForKey:WindowFrameKey]
&& [[desc objectForKey:WindowFrameKey] isKindOfClass:[NSString class]])
@@ -647,32 +628,31 @@ static void UpdateChangeCountCallback(
return nil;
}
- NSString *errDesc = nil;
- NSData *const data = [NSPropertyListSerialization dataFromPropertyList:desc
+ NSError *errDesc = nil;
+ NSData *const data = [NSPropertyListSerialization dataWithPropertyList:desc
format:NSPropertyListXMLFormat_v1_0
- errorDescription:&errDesc];
+ options:0
+ error:&errDesc];
if (!data || errDesc)
{
if (error)
{
NSString *message;
if (errDesc)
- message = [NSString stringWithFormat:@"Error serialising effect settings: %@", errDesc];
+ message = [NSString stringWithFormat:@"Error serialising effect settings: %@", [errDesc localizedDescription]];
else
message = @"Error serialising effect settings";
NSDictionary *const info = [NSDictionary dictionaryWithObjectsAndKeys:message, NSLocalizedDescriptionKey,
nil];
*error = [NSError errorWithDomain:AUEffectUtilErrorDomain code:0 userInfo:info];
}
- if (errDesc)
- [errDesc release];
return nil;
}
return data;
}
- (IBAction)toggleGenericView:(id)sender {
- forceGenericView = (NSOnState == [sender state]);
+ forceGenericView = (NSControlStateValueOn == [sender state]);
if (view)
{
[[NSNotificationCenter defaultCenter] removeObserver:self
@@ -697,7 +677,7 @@ static void UpdateChangeCountCallback(
[alert setInformativeText:[NSString stringWithFormat:@"Tried to select preset %ld of %ld",
(long)idx + 1,
(long)total]];
- [alert beginSheetModalForWindow:window modalDelegate:nil didEndSelector:NULL contextInfo:NULL];
+ [alert beginSheetModalForWindow:window completionHandler:nil];
return;
}
@@ -715,7 +695,7 @@ static void UpdateChangeCountCallback(
[alert setMessageText:[NSString stringWithFormat:@"Error loading preset %@", preset->presetName]];
[alert setInformativeText:[NSString stringWithFormat:@"Error %ld encountered while setting AudioUnit property",
(long)status]];
- [alert beginSheetModalForWindow:window modalDelegate:nil didEndSelector:NULL contextInfo:NULL];
+ [alert beginSheetModalForWindow:window completionHandler:nil];
return;
}
@@ -728,7 +708,7 @@ static void UpdateChangeCountCallback(
preset->presetName]];
[alert setInformativeText:[NSString stringWithFormat:@"Error %ld encountered while sending notification",
(long)status]];
- [alert beginSheetModalForWindow:window modalDelegate:nil didEndSelector:NULL contextInfo:NULL];
+ [alert beginSheetModalForWindow:window completionHandler:nil];
return;
}
}
@@ -793,7 +773,7 @@ static void UpdateChangeCountCallback(
item = [menu addItemWithTitle:[NSString stringWithFormat:@"Hide %@", appName] action:@selector(hide:) keyEquivalent:@"h"];
item = [menu addItemWithTitle:@"Hide Others" action:@selector(hideOtherApplications:) keyEquivalent:@"h"];
- [item setKeyEquivalentModifierMask:NSCommandKeyMask | NSAlternateKeyMask];
+ [item setKeyEquivalentModifierMask:NSEventModifierFlagCommand | NSEventModifierFlagOption];
item = [menu addItemWithTitle:@"Show All" action:@selector(unhideAllApplications:) keyEquivalent:@""];
[menu addItem:[NSMenuItem separatorItem]];
@@ -895,7 +875,7 @@ static void UpdateChangeCountCallback(
if ((0 > index) || (0 == effects[index].component))
{
NSAlert *const alert = [[NSAlert alloc] init];
- [alert setAlertStyle:NSWarningAlertStyle];
+ [alert setAlertStyle:NSAlertStyleWarning];
[alert setMessageText:@"Invalid effect component"];
[alert addButtonWithTitle:@"OK"];
[alert runModal];
@@ -910,17 +890,18 @@ static void UpdateChangeCountCallback(
subtypeValue, ComponentSubTypeKey,
manufacturerValue, ComponentManufacturerKey,
nil];
- NSString *errDesc = nil;
- NSData *const data = [NSPropertyListSerialization dataFromPropertyList:desc
+ NSError *errDesc = nil;
+ NSData *const data = [NSPropertyListSerialization dataWithPropertyList:desc
format:NSPropertyListXMLFormat_v1_0
- errorDescription:&errDesc];
+ options:0
+ error:&errDesc];
if (!data || errDesc)
{
NSAlert *const alert = [[NSAlert alloc] init];
- [alert setAlertStyle:NSWarningAlertStyle];
+ [alert setAlertStyle:NSAlertStyleWarning];
[alert setMessageText:@"Error serialising properties for new effect"];
if (errDesc)
- [alert setInformativeText:[errDesc autorelease]];
+ [alert setInformativeText:[errDesc localizedDescription]];
[alert addButtonWithTitle:@"OK"];
[alert runModal];
[alert release];
@@ -939,7 +920,7 @@ static void UpdateChangeCountCallback(
else
{
NSAlert *const alert = [[NSAlert alloc] init];
- [alert setAlertStyle:NSWarningAlertStyle];
+ [alert setAlertStyle:NSAlertStyleWarning];
[alert setMessageText:@"Error creating new effect document"];
[alert addButtonWithTitle:@"OK"];
[alert runModal];
@@ -978,38 +959,35 @@ static void UpdateChangeCountCallback(
}
- (void)applicationDidFinishLaunching:(NSNotification *)notification {
- ComponentDescription effectFilter = { kAudioUnitType_Effect, 0, 0, 0, 0 };
- long const count = CountComponents(&effectFilter);
+ AudioComponentDescription effectFilter = { kAudioUnitType_Effect, 0, 0, 0, 0 };
+ long const count = AudioComponentCount(&effectFilter);
if (0 == count)
{
NSAlert *const alert = [[NSAlert alloc] init];
- [alert setAlertStyle:NSWarningAlertStyle];
+ [alert setAlertStyle:NSAlertStyleWarning];
[alert setMessageText:@"No AudioUnit effects found"];
[alert addButtonWithTitle:@"OK"];
[alert runModal];
[alert release];
}
- std::vector<std::pair<Component, OSStatus> > failed;
+ std::vector<std::pair<AudioComponent, OSStatus> > failed;
effects = (EffectInfo *)malloc(count * sizeof(*effects));
- Component effect = FindNextComponent(0, &effectFilter);
- for (long i = 0; (i < count) && (effect != 0); i++, effect = FindNextComponent(effect, &effectFilter))
+ AudioComponent effect = AudioComponentFindNext(nullptr, &effectFilter);
+ for (long i = 0; (i < count) && effect; i++, effect = AudioComponentFindNext(effect, &effectFilter))
{
- ComponentDescription effectDesc;
- Handle const nameHandle = NewHandle(4);
- OSStatus const err = GetComponentInfo(effect, &effectDesc, nameHandle, NULL, NULL);
+ OSStatus err;
+ AudioComponentDescription effectDesc;
+ CFStringRef name = nullptr;
+ err = AudioComponentGetDescription(effect, &effectDesc);
+ if (noErr == err)
+ err = AudioComponentCopyName(effect, &name);
if (noErr == err)
{
effects[i].component = effect;
effects[i].type = effectDesc.componentType;
effects[i].subtype = effectDesc.componentSubType;
effects[i].manufacturer = effectDesc.componentManufacturer;
- HLock(nameHandle);
- CFStringRef const name = CFStringCreateWithPascalString(
- NULL,
- (unsigned char const *)*nameHandle,
- kCFStringEncodingMacRoman);
- HUnlock(nameHandle);
NSMenuItem *const item = [newEffectMenu addItemWithTitle:(NSString *)name
action:@selector(newEffect:)
keyEquivalent:@""];
@@ -1020,9 +998,8 @@ static void UpdateChangeCountCallback(
else
{
effects[i].component = 0;
- failed.push_back(std::make_pair(effect, err));
+ failed.emplace_back(effect, err);
}
- DisposeHandle(nameHandle);
}
if (!failed.empty())
@@ -1031,7 +1008,7 @@ static void UpdateChangeCountCallback(
(unsigned long)failed.size(),
((1U == failed.size()) ? "" : "s")];
NSMutableString *const detail = [NSMutableString stringWithCapacity:(16 * failed.size())];
- std::vector<std::pair<Component, OSStatus> >::const_iterator it = failed.begin();
+ std::vector<std::pair<AudioComponent, OSStatus> >::const_iterator it = failed.begin();
[detail appendFormat:@"%lu (%ld)", (unsigned long)it->first, (long)it->second];
++it;
while (failed.end() != it)
@@ -1040,7 +1017,7 @@ static void UpdateChangeCountCallback(
++it;
}
NSAlert *const alert = [[NSAlert alloc] init];
- [alert setAlertStyle:NSWarningAlertStyle];
+ [alert setAlertStyle:NSAlertStyleWarning];
[alert setMessageText:message];
[alert setInformativeText:[NSString stringWithString:detail]];
[alert addButtonWithTitle:@"OK"];
diff --git a/src/tools/chdman.cpp b/src/tools/chdman.cpp
index 3a4277c50d1..353ac88ce6b 100644
--- a/src/tools/chdman.cpp
+++ b/src/tools/chdman.cpp
@@ -17,13 +17,14 @@
#include "hashing.h"
#include "md5.h"
#include "multibyte.h"
+#include "osdcore.h"
#include "path.h"
#include "strformat.h"
#include "vbiparse.h"
+#include <array>
#include <cassert>
#include <cctype>
-#include <cstdarg>
#include <cstdio>
#include <cstdlib>
#include <cstring>
@@ -32,7 +33,13 @@
#include <limits>
#include <memory>
#include <new>
+#include <optional>
+#include <regex>
+#include <string_view>
+#include <tuple>
#include <unordered_map>
+#include <utility>
+#include <vector>
using util::string_format;
@@ -50,16 +57,23 @@ using util::string_format;
#define I64FMT "ll"
#endif
+// hunk size limits
+constexpr uint32_t HUNK_SIZE_MIN = 16;
+constexpr uint32_t HUNK_SIZE_MAX = 1024 * 1024;
+
// default hard disk sector size
-const uint32_t IDE_SECTOR_SIZE = 512;
+constexpr uint32_t IDE_SECTOR_SIZE = 512;
// temporary input buffer size
-const uint32_t TEMP_BUFFER_SIZE = 32 * 1024 * 1024;
+constexpr uint32_t TEMP_BUFFER_SIZE = 32 * 1024 * 1024;
// modes
-const int MODE_NORMAL = 0;
-const int MODE_CUEBIN = 1;
-const int MODE_GDI = 2;
+constexpr int MODE_NORMAL = 0;
+constexpr int MODE_CUEBIN = 1;
+constexpr int MODE_GDI = 2;
+
+// osd printf verbosity
+constexpr bool OSD_PRINTF_VERBOSE = false;
// command modifier
#define REQUIRED "~"
@@ -88,6 +102,7 @@ const int MODE_GDI = 2;
#define OPTION_INPUT "input"
#define OPTION_OUTPUT "output"
#define OPTION_OUTPUT_BIN "outputbin"
+#define OPTION_OUTPUT_SPLITBIN "splitbin"
#define OPTION_OUTPUT_FORCE "force"
#define OPTION_INPUT_START_BYTE "inputstartbyte"
#define OPTION_INPUT_START_HUNK "inputstarthunk"
@@ -121,7 +136,9 @@ const int MODE_GDI = 2;
typedef std::unordered_map<std::string, std::string *> parameters_map;
-template <typename Format, typename... Params> [[noreturn]] static void report_error(int error, Format &&fmt, Params &&...args);
+template <typename Format, typename... Params>
+[[noreturn]] static void report_error(int error, Format &&fmt, Params &&...args);
+
static void do_info(parameters_map &params);
static void do_verify(parameters_map &params);
static void do_create_raw(parameters_map &params);
@@ -132,7 +149,6 @@ static void do_create_ld(parameters_map &params);
static void do_copy(parameters_map &params);
static void do_extract_raw(parameters_map &params);
static void do_extract_cd(parameters_map &params);
-static void do_extract_dvd(parameters_map &params);
static void do_extract_ld(parameters_map &params);
static void do_add_metadata(parameters_map &params);
static void do_del_metadata(parameters_map &params);
@@ -145,6 +161,46 @@ static void do_list_templates(parameters_map &params);
// TYPE DEFINITIONS
//**************************************************************************
+// Allow chdman to show osd_printf_X messages
+class chdman_osd_output : public osd_output
+{
+public:
+ chdman_osd_output() {
+ osd_output::push(this);
+ }
+
+ ~chdman_osd_output() {
+ osd_output::pop(this);
+ }
+
+ void output_callback(osd_output_channel channel, const util::format_argument_pack<char> &args);
+};
+
+void chdman_osd_output::output_callback(osd_output_channel channel, const util::format_argument_pack<char> &args)
+{
+ switch (channel)
+ {
+ case OSD_OUTPUT_CHANNEL_ERROR:
+ case OSD_OUTPUT_CHANNEL_WARNING:
+ util::stream_format(std::cerr, args);
+ break;
+ case OSD_OUTPUT_CHANNEL_INFO:
+ case OSD_OUTPUT_CHANNEL_LOG:
+ util::stream_format(std::cout, args);
+ break;
+ case OSD_OUTPUT_CHANNEL_VERBOSE:
+ if (OSD_PRINTF_VERBOSE) util::stream_format(std::cout, args);
+ break;
+ case OSD_OUTPUT_CHANNEL_DEBUG:
+#ifdef MAME_DEBUG
+ util::stream_format(std::cout, args);
+#endif
+ break;
+ default:
+ break;
+ }
+}
+
// ======================> option_description
struct option_description
@@ -207,8 +263,7 @@ struct metadata_index_info
class fatal_error : public std::exception
{
public:
- fatal_error(int error)
- : m_error(error) { }
+ fatal_error(int error) : m_error(error) { }
int error() const { return m_error; }
@@ -276,8 +331,7 @@ public:
length = m_maxoffset - offset;
if (m_file.seek(offset, SEEK_SET)) // FIXME: better error reporting?
return 0;
- std::size_t actual;
- m_file.read(dest, length, actual); // FIXME: check for error return
+ auto const [err, actual] = read(m_file, dest, length); // FIXME: check for error return
return actual;
}
@@ -296,10 +350,12 @@ class chd_chdfile_compressor : public chd_file_compressor
public:
// construction/destruction
chd_chdfile_compressor(chd_file &file, uint64_t offset = 0, uint64_t maxoffset = ~0)
- : m_toc(nullptr),
- m_file(file),
- m_offset(offset),
- m_maxoffset(std::min(maxoffset, file.logical_bytes())) { }
+ : m_toc(nullptr)
+ , m_file(file)
+ , m_offset(offset)
+ , m_maxoffset(std::min(maxoffset, file.logical_bytes()))
+ {
+ }
// read interface
virtual uint32_t read_data(void *dest, uint64_t offset, uint32_t length)
@@ -367,9 +423,11 @@ class chd_cd_compressor : public chd_file_compressor
public:
// construction/destruction
chd_cd_compressor(cdrom_file::toc &toc, cdrom_file::track_input_info &info)
- : m_file(),
- m_toc(toc),
- m_info(info) { }
+ : m_file()
+ , m_toc(toc)
+ , m_info(info)
+ {
+ }
~chd_cd_compressor()
{
@@ -393,6 +451,7 @@ public:
{
const cdrom_file::track_info &trackinfo = m_toc.tracks[tracknum];
uint64_t endoffs = startoffs + (uint64_t)(trackinfo.frames + trackinfo.extraframes) * cdrom_file::FRAME_SIZE;
+
if (offset >= startoffs && offset < endoffs)
{
// if we don't already have this file open, open it now
@@ -409,11 +468,11 @@ public:
uint64_t bytesperframe = trackinfo.datasize + trackinfo.subsize;
uint64_t src_track_start = m_info.track[tracknum].offset;
uint64_t src_track_end = src_track_start + bytesperframe * (uint64_t)trackinfo.frames;
- uint64_t pad_track_start = src_track_end - ((uint64_t)m_toc.tracks[tracknum].padframes * bytesperframe);
- uint64_t split_track_start = pad_track_start - ((uint64_t)m_toc.tracks[tracknum].splitframes * bytesperframe);
+ uint64_t split_track_start = src_track_end - ((uint64_t)trackinfo.splitframes * bytesperframe);
+ uint64_t pad_track_start = split_track_start - ((uint64_t)trackinfo.padframes * bytesperframe);
// dont split when split-bin read not required
- if ((uint64_t)m_toc.tracks[tracknum].splitframes == 0L)
+ if ((uint64_t)trackinfo.splitframes == 0L)
split_track_start = UINT64_MAX;
while (length_remaining != 0 && offset < endoffs)
@@ -422,7 +481,7 @@ public:
uint64_t src_frame_start = src_track_start + ((offset - startoffs) / cdrom_file::FRAME_SIZE) * bytesperframe;
// auto-advance next track for split-bin read
- if (src_frame_start == split_track_start && m_lastfile.compare(m_info.track[tracknum+1].fname)!=0)
+ if (src_frame_start >= split_track_start && src_frame_start < src_track_end && m_lastfile.compare(m_info.track[tracknum+1].fname)!=0)
{
m_file.reset();
m_lastfile = m_info.track[tracknum+1].fname;
@@ -434,7 +493,7 @@ public:
if (src_frame_start < src_track_end)
{
// read it in, or pad if we're into the padframes
- if (src_frame_start >= pad_track_start)
+ if (src_frame_start >= pad_track_start && src_frame_start < split_track_start)
{
memset(dest, 0, bytesperframe);
}
@@ -447,7 +506,7 @@ public:
SEEK_SET);
std::size_t count = 0;
if (!err)
- err = m_file->read(dest, bytesperframe, count);
+ std::tie(err, count) = read(*m_file, dest, bytesperframe);
if (err || (count != bytesperframe))
report_error(1, "Error reading input file (%s)'", m_lastfile);
}
@@ -493,13 +552,15 @@ class chd_avi_compressor : public chd_file_compressor
public:
// construction/destruction
chd_avi_compressor(avi_file &file, avi_info &info, uint32_t first_frame, uint32_t num_frames)
- : m_file(file),
- m_info(info),
- m_bitmap(info.width, info.height * (info.interlaced ? 2 : 1)),
- m_start_frame(first_frame),
- m_frame_count(num_frames),
- m_ldframedata(num_frames * VBI_PACKED_BYTES),
- m_rawdata(info.bytes_per_frame) { }
+ : m_file(file)
+ , m_info(info)
+ , m_bitmap(info.width, info.height * (info.interlaced ? 2 : 1))
+ , m_start_frame(first_frame)
+ , m_frame_count(num_frames)
+ , m_ldframedata(num_frames * VBI_PACKED_BYTES)
+ , m_rawdata(info.bytes_per_frame)
+ {
+ }
// getters
const std::vector<uint8_t> &ldframedata() const { return m_ldframedata; }
@@ -515,6 +576,7 @@ public:
int32_t start_frame = offset / m_info.bytes_per_frame;
int32_t end_frame = (offset + length - 1) / m_info.bytes_per_frame;
for (int32_t framenum = start_frame; framenum <= end_frame; framenum++)
+ {
if (framenum < m_frame_count)
{
// determine effective frame number and first/last samples
@@ -571,6 +633,7 @@ public:
dest += bytes_to_copy;
length_remaining -= bytes_to_copy;
}
+ }
return length;
}
@@ -580,11 +643,11 @@ private:
avi_file & m_file;
avi_info & m_info;
bitmap_yuy16 m_bitmap;
- uint32_t m_start_frame;
- uint32_t m_frame_count;
+ uint32_t m_start_frame;
+ uint32_t m_frame_count;
std::vector<int16_t> m_audio[8];
- std::vector<uint8_t> m_ldframedata;
- std::vector<uint8_t> m_rawdata;
+ std::vector<uint8_t> m_ldframedata;
+ std::vector<uint8_t> m_rawdata;
};
@@ -598,10 +661,11 @@ static clock_t lastprogress = 0;
// default compressors
-static const chd_codec_type s_default_raw_compression[4] = { CHD_CODEC_LZMA, CHD_CODEC_ZLIB, CHD_CODEC_HUFFMAN, CHD_CODEC_FLAC };
-static const chd_codec_type s_default_hd_compression[4] = { CHD_CODEC_LZMA, CHD_CODEC_ZLIB, CHD_CODEC_HUFFMAN, CHD_CODEC_FLAC };
-static const chd_codec_type s_default_cd_compression[4] = { CHD_CODEC_CD_LZMA, CHD_CODEC_CD_ZLIB, CHD_CODEC_CD_FLAC };
-static const chd_codec_type s_default_ld_compression[4] = { CHD_CODEC_AVHUFF };
+static const std::array<chd_codec_type, 4> s_no_compression = { CHD_CODEC_NONE, CHD_CODEC_NONE, CHD_CODEC_NONE, CHD_CODEC_NONE };
+static const std::array<chd_codec_type, 4> s_default_raw_compression = { CHD_CODEC_LZMA, CHD_CODEC_ZLIB, CHD_CODEC_HUFFMAN, CHD_CODEC_FLAC };
+static const std::array<chd_codec_type, 4> s_default_hd_compression = { CHD_CODEC_LZMA, CHD_CODEC_ZLIB, CHD_CODEC_HUFFMAN, CHD_CODEC_FLAC };
+static const std::array<chd_codec_type, 4> s_default_cd_compression = { CHD_CODEC_CD_LZMA, CHD_CODEC_CD_ZLIB, CHD_CODEC_CD_FLAC };
+static const std::array<chd_codec_type, 4> s_default_ld_compression = { CHD_CODEC_AVHUFF };
// descriptions for each option
@@ -611,6 +675,7 @@ static const option_description s_options[] =
{ OPTION_INPUT_PARENT, "ip", true, " <filename>: parent file name for input CHD" },
{ OPTION_OUTPUT, "o", true, " <filename>: output file name" },
{ OPTION_OUTPUT_BIN, "ob", true, " <filename>: output file name for binary data" },
+ { OPTION_OUTPUT_SPLITBIN, "sb", false, ": output one binary file per track" },
{ OPTION_OUTPUT_FORCE, "f", false, ": force overwriting an existing file" },
{ OPTION_OUTPUT_PARENT, "op", true, " <filename>: parent file name for output CHD" },
{ OPTION_INPUT_START_BYTE, "isb", true, " <offset>: starting byte offset within the input" },
@@ -623,7 +688,7 @@ static const option_description s_options[] =
{ OPTION_UNIT_SIZE, "us", true, " <bytes>: size of each unit, in bytes" },
{ OPTION_COMPRESSION, "c", true, " <none|type1[,type2[,...]]>: which compression codecs to use (up to 4)" },
{ OPTION_IDENT, "id", true, " <filename>: name of ident file to provide CHS information" },
- { OPTION_CHS, "chs", true, " <cylinders,heads,sectors>: specifies CHS values directly" },
+ { OPTION_CHS, "chs", true, " <cylinders,heads,sectors>: specifies CHS geometry directly" },
{ OPTION_SECTOR_SIZE, "ss", true, " <bytes>: size of each hard disk sector" },
{ OPTION_TAG, "t", true, " <tag>: 4-character tag for metadata" },
{ OPTION_INDEX, "ix", true, " <index>: indexed instance of this metadata tag" },
@@ -651,7 +716,8 @@ static const command_description s_commands[] =
{ COMMAND_VERIFY, do_verify, ": verifies a CHD's integrity",
{
REQUIRED OPTION_INPUT,
- OPTION_INPUT_PARENT
+ OPTION_INPUT_PARENT,
+ OPTION_FIX
}
},
@@ -665,8 +731,8 @@ static const command_description s_commands[] =
OPTION_INPUT_START_HUNK,
OPTION_INPUT_LENGTH_BYTES,
OPTION_INPUT_LENGTH_HUNKS,
- REQUIRED OPTION_HUNK_SIZE,
- REQUIRED OPTION_UNIT_SIZE,
+ OPTION_HUNK_SIZE,
+ OPTION_UNIT_SIZE,
OPTION_COMPRESSION,
OPTION_NUMPROCESSORS
}
@@ -710,6 +776,11 @@ static const command_description s_commands[] =
OPTION_OUTPUT_PARENT,
OPTION_OUTPUT_FORCE,
REQUIRED OPTION_INPUT,
+ OPTION_INPUT_START_BYTE,
+ OPTION_INPUT_START_HUNK,
+ OPTION_INPUT_LENGTH_BYTES,
+ OPTION_INPUT_LENGTH_HUNKS,
+ OPTION_HUNK_SIZE,
OPTION_COMPRESSION,
OPTION_NUMPROCESSORS
}
@@ -759,19 +830,23 @@ static const command_description s_commands[] =
{
REQUIRED OPTION_OUTPUT,
OPTION_OUTPUT_BIN,
+ OPTION_OUTPUT_SPLITBIN,
OPTION_OUTPUT_FORCE,
REQUIRED OPTION_INPUT,
OPTION_INPUT_PARENT,
}
},
- { COMMAND_EXTRACT_DVD, do_extract_dvd, ": extract DVD file from a CHD input file",
+ { COMMAND_EXTRACT_DVD, do_extract_raw, ": extract DVD file from a CHD input file",
{
REQUIRED OPTION_OUTPUT,
- OPTION_OUTPUT_BIN,
OPTION_OUTPUT_FORCE,
REQUIRED OPTION_INPUT,
OPTION_INPUT_PARENT,
+ OPTION_INPUT_START_BYTE,
+ OPTION_INPUT_START_HUNK,
+ OPTION_INPUT_LENGTH_BYTES,
+ OPTION_INPUT_LENGTH_HUNKS
}
},
@@ -867,7 +942,8 @@ static const hd_template s_hd_templates[] =
// report_error - report an error
//-------------------------------------------------
-template <typename Format, typename... Params> static void report_error(int error, Format &&fmt, Params &&...args)
+template <typename Format, typename... Params>
+static void report_error(int error, Format &&fmt, Params &&...args)
{
// output to stderr
util::stream_format(std::cerr, std::forward<Format>(fmt), std::forward<Params>(args)...);
@@ -883,7 +959,8 @@ template <typename Format, typename... Params> static void report_error(int erro
// progress - generic progress callback
//-------------------------------------------------
-template <typename Format, typename... Params> static void progress(bool forceit, Format &&fmt, Params &&...args)
+template <typename Format, typename... Params>
+static void progress(bool forceit, Format &&fmt, Params &&...args)
{
// skip if it hasn't been long enough
clock_t curtime = clock();
@@ -904,17 +981,17 @@ template <typename Format, typename... Params> static void progress(bool forceit
static int print_help(const std::string &argv0, const char *error = nullptr)
{
// print the error message first
- if (error != nullptr)
- fprintf(stderr, "Error: %s\n\n", error);
+ if (error)
+ util::stream_format(std::cerr, "Error: %s\n\n", error);
// print a summary of each command
- printf("Usage:\n");
+ util::stream_format(std::cout, "Usage:\n");
for (auto & desc : s_commands)
{
- printf(" %s %s%s\n", argv0.c_str(), desc.name, desc.description);
+ util::stream_format(std::cout, " %s %s%s\n", argv0, desc.name, desc.description);
}
- printf("\nFor help with any command, run:\n");
- printf(" %s %s <command>\n", argv0.c_str(), COMMAND_HELP);
+ util::stream_format(std::cout, "\nFor help with any command, run:\n");
+ util::stream_format(std::cout, " %s %s <command>\n", argv0, COMMAND_HELP);
return 1;
}
@@ -928,11 +1005,11 @@ static int print_help(const std::string &argv0, const command_description &desc,
{
// print the error message first
if (error != nullptr)
- fprintf(stderr, "Error: %s\n\n", error);
+ util::stream_format(std::cerr, "Error: %s\n\n", error);
// print usage for this command
- printf("Usage:\n");
- printf(" %s %s [options], where valid options are:\n", argv0.c_str(), desc.name);
+ util::stream_format(std::cout, "Usage:\n");
+ util::stream_format(std::cout, " %s %s [options], where valid options are:\n", argv0, desc.name);
for (int valid = 0; valid < std::size(desc.valid_options); valid++)
{
// determine whether we are required
@@ -948,10 +1025,10 @@ static int print_help(const std::string &argv0, const command_description &desc,
if (strcmp(option, s_option.name) == 0)
{
const option_description &odesc = s_option;
- printf(" --%s", odesc.name);
+ util::stream_format(std::cout, " --%s", odesc.name);
if (odesc.shortname != nullptr)
- printf(", -%s", odesc.shortname);
- printf("%s%s\n", odesc.description, required ? " (required)" : "");
+ util::stream_format(std::cout, ", -%s", odesc.shortname);
+ util::stream_format(std::cout, "%s%s\n", odesc.description, required ? " (required)" : "");
}
}
return 1;
@@ -1035,10 +1112,17 @@ uint64_t parse_number(const char *string)
// compute a best guess CHS value set
//-------------------------------------------------
-static void guess_chs(std::string *filename, uint64_t filesize, int sectorsize, uint32_t &cylinders, uint32_t &heads, uint32_t &sectors, uint32_t &bps)
+static void guess_chs(
+ const std::string *filename,
+ uint64_t filesize,
+ int sectorsize,
+ uint32_t &cylinders,
+ uint32_t &heads,
+ uint32_t &sectors,
+ uint32_t &bps)
{
// if this is a direct physical drive read, handle it specially
- if (filename != nullptr && osd_get_physical_drive_geometry(filename->c_str(), &cylinders, &heads, &sectors, &bps))
+ if (filename && osd_get_physical_drive_geometry(filename->c_str(), &cylinders, &heads, &sectors, &bps))
return;
// if we have no length to work with, we can't guess
@@ -1047,11 +1131,14 @@ static void guess_chs(std::string *filename, uint64_t filesize, int sectorsize,
// now find a valid value
for (uint32_t totalsectors = filesize / sectorsize; ; totalsectors++)
+ {
for (uint32_t cursectors = 63; cursectors > 1; cursectors--)
+ {
if (totalsectors % cursectors == 0)
{
uint32_t totalheads = totalsectors / cursectors;
for (uint32_t curheads = 16; curheads > 1; curheads--)
+ {
if (totalheads % curheads == 0)
{
cylinders = totalheads / curheads;
@@ -1059,7 +1146,10 @@ static void guess_chs(std::string *filename, uint64_t filesize, int sectorsize,
sectors = cursectors;
return;
}
+ }
}
+ }
+ }
}
@@ -1095,38 +1185,80 @@ static void parse_input_chd_parameters(const parameters_map &params, chd_file &i
// parameters in a standard way
//-------------------------------------------------
-static void parse_input_start_end(const parameters_map &params, uint64_t logical_size, uint32_t hunkbytes, uint32_t framebytes, uint64_t &input_start, uint64_t &input_end)
+static std::pair<uint64_t, uint64_t> parse_input_start_end(
+ const parameters_map &params,
+ uint64_t logical_size,
+ uint32_t hunkbytes,
+ uint32_t framebytes)
{
- // process start/end if we were provided an input CHD
- input_start = 0;
- input_end = logical_size;
-
// process input start
- auto input_start_byte_str = params.find(OPTION_INPUT_START_BYTE);
- auto input_start_hunk_str = params.find(OPTION_INPUT_START_HUNK);
- auto input_start_frame_str = params.find(OPTION_INPUT_START_FRAME);
+ const auto input_start_byte_str = params.find(OPTION_INPUT_START_BYTE);
+ const auto input_start_hunk_str = params.find(OPTION_INPUT_START_HUNK);
+ const auto input_start_frame_str = params.find(OPTION_INPUT_START_FRAME);
+ uint64_t input_start = 0;
if (input_start_byte_str != params.end())
+ {
+ if (input_start_hunk_str != params.end())
+ report_error(1, "Start offset cannot be specified in both bytes and hunks");
+ if (input_start_frame_str != params.end())
+ report_error(1, "Start offset cannot be specified in both bytes and frames");
input_start = parse_number(input_start_byte_str->second->c_str());
- if (input_start_hunk_str != params.end())
+ }
+ else if (input_start_hunk_str != params.end())
+ {
+ if (input_start_frame_str != params.end())
+ report_error(1, "Start offset cannot be specified in both hunks and frames");
input_start = parse_number(input_start_hunk_str->second->c_str()) * hunkbytes;
- if (input_start_frame_str != params.end())
+ }
+ else if (input_start_frame_str != params.end())
+ {
input_start = parse_number(input_start_frame_str->second->c_str()) * framebytes;
- if (input_start >= input_end)
- report_error(1, "Input start offset greater than input file size");
+ }
// process input length
- auto input_length_bytes_str = params.find(OPTION_INPUT_LENGTH_BYTES);
+ const auto input_length_bytes_str = params.find(OPTION_INPUT_LENGTH_BYTES);
auto input_length_hunks_str = params.find(OPTION_INPUT_LENGTH_HUNKS);
auto input_length_frames_str = params.find(OPTION_INPUT_LENGTH_FRAMES);
- uint64_t input_length = input_end;
+ std::optional<uint64_t> input_length;
if (input_length_bytes_str != params.end())
+ {
+ if (input_length_hunks_str != params.end())
+ report_error(1, "Length cannot be specified in both bytes and hunks");
+ if (input_length_frames_str != params.end())
+ report_error(1, "Length cannot be specified in both bytes and frames");
input_length = parse_number(input_length_bytes_str->second->c_str());
- if (input_length_hunks_str != params.end())
+ }
+ else if (input_length_hunks_str != params.end())
+ {
+ if (input_length_frames_str != params.end())
+ report_error(1, "Length cannot be specified in both hunks and frames");
input_length = parse_number(input_length_hunks_str->second->c_str()) * hunkbytes;
- if (input_length_frames_str != params.end())
+ }
+ else if (input_length_frames_str != params.end())
+ {
input_length = parse_number(input_length_frames_str->second->c_str()) * framebytes;
- if (input_start + input_length < input_end)
- input_end = input_start + input_length;
+ }
+
+ // check that offsets are within input
+ if (input_start >= logical_size)
+ report_error(1, "Input start offset is beyond end of input");
+ if (input_length && ((input_start + *input_length) > logical_size))
+ report_error(1, "Input length is larger than available input from start offset");
+ return std::make_pair(input_start, input_length ? (input_start + *input_length) : logical_size);
+}
+
+static std::tuple<uint64_t, uint64_t, uint64_t> parse_input_start_end(
+ const parameters_map &params,
+ util::random_read &input_file,
+ uint32_t hunkbytes,
+ uint32_t framebytes)
+{
+ uint64_t input_size = 0;
+ const std::error_condition err = input_file.length(input_size);
+ if (err)
+ report_error(1, "Error getting size of input file: %s", err.message());
+ const auto [input_start, input_end] = parse_input_start_end(params, input_size, hunkbytes, framebytes);
+ return std::make_tuple(input_size, input_start, input_end);
}
@@ -1136,7 +1268,7 @@ static void parse_input_start_end(const parameters_map &params, uint64_t logical
// unless --force is specified
//-------------------------------------------------
-static void check_existing_output_file(const parameters_map &params, const char *filename)
+static void check_existing_output_file(const parameters_map &params, std::string_view filename)
{
if (params.find(OPTION_OUTPUT_FORCE) == params.end())
{
@@ -1156,10 +1288,10 @@ static void check_existing_output_file(const parameters_map &params, const char
// standard set of output CHD parameters
//-------------------------------------------------
-static std::string *parse_output_chd_parameters(const parameters_map &params, chd_file &output_parent_chd)
+static const std::string *parse_output_chd_parameters(const parameters_map &params, chd_file &output_parent_chd)
{
// process output parent file
- auto output_chd_parent_str = params.find(OPTION_OUTPUT_PARENT);
+ const auto output_chd_parent_str = params.find(OPTION_OUTPUT_PARENT);
if (output_chd_parent_str != params.end())
{
std::error_condition err = output_parent_chd.open(*output_chd_parent_str->second);
@@ -1168,10 +1300,11 @@ static std::string *parse_output_chd_parameters(const parameters_map &params, ch
}
// process output file
- auto output_chd_str = params.find(OPTION_OUTPUT);
- if (output_chd_str != params.end())
- check_existing_output_file(params, output_chd_str->second->c_str());
- return (output_chd_str != params.end()) ? output_chd_str->second : nullptr;
+ const auto output_chd_str = params.find(OPTION_OUTPUT);
+ if (output_chd_str == params.end())
+ return nullptr;
+ check_existing_output_file(params, *output_chd_str->second);
+ return output_chd_str->second;
}
@@ -1180,17 +1313,32 @@ static std::string *parse_output_chd_parameters(const parameters_map &params, ch
// parameter in a standard way
//-------------------------------------------------
-static void parse_hunk_size(const parameters_map &params, uint32_t required_granularity, uint32_t &hunk_size)
+static uint32_t parse_hunk_size(
+ const parameters_map &params,
+ const chd_file &output_parent,
+ uint32_t required_granularity,
+ uint32_t default_size)
{
- auto hunk_size_str = params.find(OPTION_HUNK_SIZE);
+ const auto hunk_size_str = params.find(OPTION_HUNK_SIZE);
+ uint32_t hunk_size = default_size;
if (hunk_size_str != params.end())
{
hunk_size = parse_number(hunk_size_str->second->c_str());
- if (hunk_size < 16 || hunk_size > 1024 * 1024)
- report_error(1, "Invalid hunk size");
- if (hunk_size % required_granularity != 0)
- report_error(1, "Hunk size is not an even multiple of %d", required_granularity);
+ if (output_parent.opened() && (output_parent.hunk_bytes() != hunk_size))
+ report_error(1, "Specified hunk size %u bytes does not match output parent CHD hunk size %u bytes", hunk_size, output_parent.hunk_bytes());
+ if (hunk_size < HUNK_SIZE_MIN)
+ report_error(1, "Invalid hunk size (minimum %u)", HUNK_SIZE_MIN);
+ if (hunk_size > HUNK_SIZE_MAX)
+ report_error(1, "Invalid hunk size (maximum %u)", HUNK_SIZE_MAX);
+ }
+ else if (output_parent.opened())
+ {
+ hunk_size = output_parent.hunk_bytes();
}
+
+ if (hunk_size % required_granularity)
+ report_error(1, "Hunk size %u bytes is not a whole multiple of %u", hunk_size, required_granularity);
+ return hunk_size;
}
@@ -1199,15 +1347,18 @@ static void parse_hunk_size(const parameters_map &params, uint32_t required_gran
// compression parameter string
//-------------------------------------------------
-static void parse_compression(const parameters_map &params, chd_codec_type compression[4])
+static void parse_compression(const parameters_map &params, const std::array<chd_codec_type, 4> &defaults, const chd_file &output_parent, chd_codec_type compression[4])
{
+ // TODO: should we default to the same compression as the output parent?
+ std::copy(std::begin(defaults), std::end(defaults), compression);
+
// see if anything was specified
- auto compression_str = params.find(OPTION_COMPRESSION);
+ const auto compression_str = params.find(OPTION_COMPRESSION);
if (compression_str == params.end())
return;
// special case: 'none'
- if (compression_str->second->compare("none")==0)
+ if (*compression_str->second == "none")
{
compression[0] = compression[1] = compression[2] = compression[3] = CHD_CODEC_NONE;
return;
@@ -1286,6 +1437,49 @@ static std::string compression_string(chd_codec_type compression[4])
//-------------------------------------------------
+// open_input_file - open input file if specified
+//-------------------------------------------------
+
+static std::pair<util::core_file::ptr, const std::string *> open_input_file(const parameters_map &params)
+{
+ const auto path = params.find(OPTION_INPUT);
+ if (path == params.end())
+ return std::make_pair(nullptr, nullptr);
+
+ util::core_file::ptr file;
+ const std::error_condition err = util::core_file::open(*path->second, OPEN_FLAG_READ, file);
+ if (err)
+ report_error(1, "Unable to open input file (%s): %s", *path->second, err.message());
+
+ return std::make_pair(std::move(file), path->second);
+}
+
+
+//-------------------------------------------------
+// create_output_chd - open output CHD with or
+// without parent CHD file
+//-------------------------------------------------
+
+static void create_output_chd(
+ chd_file_compressor &compressor,
+ std::string_view path,
+ uint64_t logical_size,
+ uint32_t hunk_size,
+ uint32_t unit_size,
+ const chd_codec_type (&compression)[4],
+ chd_file &parent)
+{
+ std::error_condition err;
+ if (parent.opened())
+ err = compressor.create(path, logical_size, hunk_size, compression, parent);
+ else
+ err = compressor.create(path, logical_size, hunk_size, unit_size, compression);
+ if (err)
+ report_error(1, "Error creating CHD file (%s): %s", path, err.message());
+}
+
+
+//-------------------------------------------------
// compress_common - standard compression loop
//-------------------------------------------------
@@ -1317,62 +1511,19 @@ static void compress_common(chd_file_compressor &chd)
// to a CUE file
//-------------------------------------------------
-void output_track_metadata(int mode, util::core_file &file, int tracknum, const cdrom_file::track_info &info, const std::string &filename, uint32_t frameoffs, uint64_t discoffs)
+void output_track_metadata(int mode, util::core_file &file, int tracknum, const cdrom_file::track_info &info, const std::string &filename, uint32_t frameoffs, uint64_t outputoffs)
{
if (mode == MODE_GDI)
{
- int mode = 0, size = 2048;
-
- switch (info.trktype)
- {
- case cdrom_file::CD_TRACK_MODE1:
- mode = 4;
- size = 2048;
- break;
-
- case cdrom_file::CD_TRACK_MODE1_RAW:
- mode = 4;
- size = 2352;
- break;
-
- case cdrom_file::CD_TRACK_MODE2:
- mode = 4;
- size = 2336;
- break;
-
- case cdrom_file::CD_TRACK_MODE2_FORM1:
- mode = 4;
- size = 2048;
- break;
-
- case cdrom_file::CD_TRACK_MODE2_FORM2:
- mode = 4;
- size = 2324;
- break;
-
- case cdrom_file::CD_TRACK_MODE2_FORM_MIX:
- mode = 4;
- size = 2336;
- break;
-
- case cdrom_file::CD_TRACK_MODE2_RAW:
- mode = 4;
- size = 2352;
- break;
-
- case cdrom_file::CD_TRACK_AUDIO:
- mode = 0;
- size = 2352;
- break;
- }
+ const int tracktype = info.trktype == cdrom_file::CD_TRACK_AUDIO ? 0 : 4;
const bool needquote = filename.find(' ') != std::string::npos;
const char *const quotestr = needquote ? "\"" : "";
- file.printf("%d %d %d %d %s%s%s %d\n", tracknum+1, frameoffs, mode, size, quotestr, filename, quotestr, discoffs);
+ file.printf("%d %d %d %d %s%s%s %d\n", tracknum+1, frameoffs, tracktype, info.datasize, quotestr, filename, quotestr, outputoffs);
}
else if (mode == MODE_CUEBIN)
{
- // first track specifies the file
- if (tracknum == 0)
+ // specify a new file when writing to the beginning of a file
+ if (outputoffs == 0)
file.printf("FILE \"%s\" BINARY\n", filename);
// determine submode
@@ -1447,11 +1598,10 @@ void output_track_metadata(int mode, util::core_file &file, int tracknum, const
if (info.pregap > 0)
file.printf("ZERO %s %s\n", modesubmode, msf_string_from_frames(info.pregap));
- // all tracks but the first one have a file offset
- if (tracknum > 0)
- file.printf("DATAFILE \"%s\" #%d %s // length in bytes: %d\n", filename, uint32_t(discoffs), msf_string_from_frames(info.frames), info.frames * (info.datasize + info.subsize));
- else
+ if (outputoffs == 0)
file.printf("DATAFILE \"%s\" %s // length in bytes: %d\n", filename, msf_string_from_frames(info.frames), info.frames * (info.datasize + info.subsize));
+ else
+ file.printf("DATAFILE \"%s\" #%d %s // length in bytes: %d\n", filename, uint32_t(outputoffs), msf_string_from_frames(info.frames), info.frames * (info.datasize + info.subsize));
// tracks with pregaps get a START marker too
if (info.pregap > 0)
@@ -1476,8 +1626,8 @@ static void do_info(parameters_map &params)
parse_input_chd_parameters(params, input_chd, input_parent_chd);
// print filename and version
- printf("Input file: %s\n", params.find(OPTION_INPUT)->second->c_str());
- printf("File Version: %d\n", input_chd.version());
+ util::stream_format(std::cout, "Input file: %s\n", *params.find(OPTION_INPUT)->second);
+ util::stream_format(std::cout, "File Version: %d\n", input_chd.version());
if (input_chd.version() < 3)
report_error(1, "Unsupported version (%d); use an older chdman to upgrade to version 3 or later", input_chd.version());
@@ -1485,27 +1635,27 @@ static void do_info(parameters_map &params)
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(filesize).c_str());
+ util::stream_format(std::cout, "Logical size: %s bytes\n", big_int_string(input_chd.logical_bytes()));
+ util::stream_format(std::cout, "Hunk Size: %s bytes\n", big_int_string(input_chd.hunk_bytes()));
+ util::stream_format(std::cout, "Total Hunks: %s\n", big_int_string(input_chd.hunk_count()));
+ util::stream_format(std::cout, "Unit Size: %s bytes\n", big_int_string(input_chd.unit_bytes()));
+ util::stream_format(std::cout, "Total Units: %s\n", big_int_string(input_chd.unit_count()));
+ util::stream_format(std::cout, "Compression: %s\n", compression_string(compression));
+ util::stream_format(std::cout, "CHD size: %s bytes\n", big_int_string(filesize));
if (compression[0] != CHD_CODEC_NONE)
- printf("Ratio: %.1f%%\n", 100.0 * double(filesize) / double(input_chd.logical_bytes()));
+ util::stream_format(std::cout, "Ratio: %.1f%%\n", 100.0 * double(filesize) / double(input_chd.logical_bytes()));
- // add SHA1 output
+ // add SHA-1 output
util::sha1_t overall = input_chd.sha1();
if (overall != util::sha1_t::null)
{
- printf("SHA1: %s\n", overall.as_string().c_str());
+ util::stream_format(std::cout, "SHA1: %s\n", overall.as_string());
if (input_chd.version() >= 4)
- printf("Data SHA1: %s\n", input_chd.raw_sha1().as_string().c_str());
+ util::stream_format(std::cout, "Data SHA1: %s\n", input_chd.raw_sha1().as_string());
}
util::sha1_t parent = input_chd.parent_sha1();
if (parent != util::sha1_t::null)
- printf("Parent SHA1: %s\n", parent.as_string().c_str());
+ util::stream_format(std::cout, "Parent SHA1: %s\n", parent.as_string());
// print out metadata
std::vector<uint8_t> buffer;
@@ -1538,18 +1688,18 @@ static void do_info(parameters_map &params)
// print either a string representation or a hex representation of the tag
if (isprint((metatag >> 24) & 0xff) && isprint((metatag >> 16) & 0xff) && isprint((metatag >> 8) & 0xff) && isprint(metatag & 0xff))
- printf("Metadata: Tag='%c%c%c%c' Index=%d Length=%d bytes\n", (metatag >> 24) & 0xff, (metatag >> 16) & 0xff, (metatag >> 8) & 0xff, metatag & 0xff, metaindex, int(buffer.size()));
+ util::stream_format(std::cout, "Metadata: Tag='%c%c%c%c' Index=%d Length=%d bytes\n", (metatag >> 24) & 0xff, (metatag >> 16) & 0xff, (metatag >> 8) & 0xff, metatag & 0xff, metaindex, buffer.size());
else
- printf("Metadata: Tag=%08x Index=%d Length=%d bytes\n", metatag, metaindex, int(buffer.size()));
- printf(" ");
+ util::stream_format(std::cout, "Metadata: Tag=%08x Index=%d Length=%d bytes\n", metatag, metaindex, buffer.size());
+ util::stream_format(std::cout, " ");
uint32_t count = buffer.size();
// limit output to 60 characters of metadata if not verbose
if (!verbose)
count = std::min(60U, count);
for (int chnum = 0; chnum < count; chnum++)
- printf("%c", isprint(uint8_t(buffer[chnum])) ? buffer[chnum] : '.');
- printf("\n");
+ util::stream_format(std::cout, "%c", isprint(uint8_t(buffer[chnum])) ? buffer[chnum] : '.');
+ util::stream_format(std::cout, "\n");
}
// print compression stats if verbose
@@ -1581,9 +1731,9 @@ static void do_info(parameters_map &params)
}
// output the stats
- printf("\n");
- printf(" Hunks Percent Name\n");
- printf("---------- ------- ------------------------------------\n");
+ util::stream_format(std::cout, "\n");
+ util::stream_format(std::cout, " Hunks Percent Name\n");
+ util::stream_format(std::cout, "---------- ------- ------------------------------------\n");
for (int comptype = 0; comptype < std::size(compression_types); comptype++)
if (compression_types[comptype] != 0)
{
@@ -1603,8 +1753,8 @@ static void do_info(parameters_map &params)
}
// output the stats
- printf("%10s %5.1f%% %-40s\n",
- big_int_string(compression_types[comptype]).c_str(),
+ util::stream_format(std::cout, "%10s %5.1f%% %-40s\n",
+ big_int_string(compression_types[comptype]),
100.0 * double(compression_types[comptype]) / double(input_chd.hunk_count()),
name);
}
@@ -1613,7 +1763,7 @@ static void do_info(parameters_map &params)
//-------------------------------------------------
-// do_verify - validate the SHA1 on a CHD
+// do_verify - validate the SHA-1 on a CHD
//-------------------------------------------------
static void do_verify(parameters_map &params)
@@ -1623,7 +1773,7 @@ static void do_verify(parameters_map &params)
chd_file input_chd;
parse_input_chd_parameters(params, input_chd, input_parent_chd);
- // only makes sense for compressed CHDs with valid SHA1's
+ // only makes sense for compressed CHDs with valid SHA-1's
if (!input_chd.compressed())
report_error(0, "No verification to be done; CHD is uncompressed");
util::sha1_t raw_sha1 = (input_chd.version() <= 3) ? input_chd.sha1() : input_chd.raw_sha1();
@@ -1654,36 +1804,41 @@ static void do_verify(parameters_map &params)
// finish up
if (raw_sha1 != computed_sha1)
{
- fprintf(stderr, "Error: Raw SHA1 in header = %s\n", raw_sha1.as_string().c_str());
- fprintf(stderr, " actual SHA1 = %s\n", computed_sha1.as_string().c_str());
+ util::stream_format(std::cerr, "Error: Raw SHA1 in header = %s\n", raw_sha1.as_string());
+ util::stream_format(std::cerr, " actual SHA1 = %s\n", computed_sha1.as_string());
// fix it if requested; this also fixes the overall one so we don't need to do any more
if (params.find(OPTION_FIX) != params.end())
{
- input_chd.set_raw_sha1(computed_sha1);
- printf("SHA-1 updated to correct value in input CHD\n");
+ std::error_condition err = input_chd.set_raw_sha1(computed_sha1);
+ if (err)
+ report_error(1, "Error updating SHA1: %s", err.message());
+ util::stream_format(std::cout, "SHA1 updated to correct value in input CHD\n");
}
}
else
{
- printf("Raw SHA1 verification successful!\n");
+ util::stream_format(std::cout, "Raw SHA1 verification successful!\n");
// now include the metadata for >= v4
if (input_chd.version() >= 4)
{
util::sha1_t computed_overall_sha1 = input_chd.compute_overall_sha1(computed_sha1);
if (input_chd.sha1() == computed_overall_sha1)
- printf("Overall SHA1 verification successful!\n");
+ util::stream_format(std::cout, "Overall SHA1 verification successful!\n");
else
{
- fprintf(stderr, "Error: Overall SHA1 in header = %s\n", input_chd.sha1().as_string().c_str());
- fprintf(stderr, " actual SHA1 = %s\n", computed_overall_sha1.as_string().c_str());
+ util::stream_format(std::cerr, "Error: Overall SHA1 in header = %s\n", input_chd.sha1().as_string());
+ util::stream_format(std::cerr, " actual SHA1 = %s\n", computed_overall_sha1.as_string());
// fix it if requested
if (params.find(OPTION_FIX) != params.end())
{
input_chd.set_raw_sha1(computed_sha1);
- printf("SHA-1 updated to correct value in input CHD\n");
+ std::error_condition err = input_chd.set_raw_sha1(computed_sha1);
+ if (err)
+ report_error(1, "Error updating SHA1: %s", err.message());
+ util::stream_format(std::cout, "SHA1 updated to correct value in input CHD\n");
}
}
}
@@ -1699,22 +1854,11 @@ static void do_verify(parameters_map &params)
static void do_create_raw(parameters_map &params)
{
// process input file
- util::core_file::ptr input_file;
- auto input_file_str = params.find(OPTION_INPUT);
- if (input_file_str != params.end())
- {
- 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());
- }
+ auto [input_file, input_file_str] = open_input_file(params);
// process output CHD
chd_file output_parent;
- std::string *output_chd_str = parse_output_chd_parameters(params, output_parent);
-
- // process hunk size
- uint32_t hunk_size = output_parent.opened() ? output_parent.hunk_bytes() : 0;
- parse_hunk_size(params, 1, hunk_size);
+ const auto output_chd_str = parse_output_chd_parameters(params, output_parent);
// process unit size
uint32_t unit_size = output_parent.opened() ? output_parent.unit_bytes() : 0;
@@ -1722,51 +1866,49 @@ static void do_create_raw(parameters_map &params)
if (unit_size_str != params.end())
{
unit_size = parse_number(unit_size_str->second->c_str());
- if (hunk_size % unit_size != 0)
- report_error(1, "Unit size is not an even divisor of the hunk size");
+ if (output_parent.opened() && (output_parent.unit_bytes() != unit_size))
+ report_error(1, "Specified unit size %u bytes does not match output parent CHD unit size %u bytes", unit_size, output_parent.unit_bytes());
}
+ else if (!output_parent.opened())
+ {
+ report_error(1, "Unit size must be specified if no output parent CHD is supplied");
+ }
+
+ // process hunk size
+ const uint32_t hunk_size = parse_hunk_size(params, output_parent, unit_size, std::max((4096 / unit_size) * unit_size, unit_size));
// process input start/end (needs to know hunk_size)
- uint64_t input_start;
- uint64_t input_end;
- uint64_t input_size = 0;
- input_file->length(input_size); // FIXME: check error return
- parse_input_start_end(params, input_size, hunk_size, hunk_size, input_start, input_end);
+ const auto [input_size, input_start, input_end] = parse_input_start_end(params, *input_file, hunk_size, hunk_size);
+ if ((input_end - input_start) % unit_size)
+ report_error(1, "Data size %s is not divisible by unit size %d", big_int_string(input_end - input_start), unit_size);
// process compression
chd_codec_type compression[4];
- memcpy(compression, s_default_raw_compression, sizeof(compression));
- parse_compression(params, compression);
+ parse_compression(params, s_default_raw_compression, output_parent, compression);
// process numprocessors
parse_numprocessors(params);
// print some info
- printf("Output CHD: %s\n", output_chd_str->c_str());
+ util::stream_format(std::cout, "Output CHD: %s\n", *output_chd_str);
if (output_parent.opened())
- printf("Parent CHD: %s\n", params.find(OPTION_OUTPUT_PARENT)->second->c_str());
- printf("Input file: %s\n", input_file_str->second->c_str());
+ util::stream_format(std::cout, "Parent CHD: %s\n", *params.find(OPTION_OUTPUT_PARENT)->second);
+ util::stream_format(std::cout, "Input file: %s\n", *input_file_str);
if (input_start != 0 || input_end != input_size)
{
- printf("Input start: %s\n", big_int_string(input_start).c_str());
- printf("Input length: %s\n", big_int_string(input_end - input_start).c_str());
+ util::stream_format(std::cout, "Input start: %s\n", big_int_string(input_start));
+ util::stream_format(std::cout, "Input length: %s\n", big_int_string(input_end - input_start));
}
- printf("Compression: %s\n", compression_string(compression).c_str());
- printf("Hunk size: %s\n", big_int_string(hunk_size).c_str());
- printf("Logical size: %s\n", big_int_string(input_end - input_start).c_str());
+ util::stream_format(std::cout, "Compression: %s\n", compression_string(compression));
+ util::stream_format(std::cout, "Hunk size: %s\n", big_int_string(hunk_size));
+ util::stream_format(std::cout, "Logical size: %s\n", big_int_string(input_end - input_start));
// catch errors so we can close & delete the output file
try
{
// create the new CHD
- std::unique_ptr<chd_file_compressor> chd(new chd_rawfile_compressor(*input_file, input_start, input_end));
- 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)
- report_error(1, "Error creating CHD file (%s): %s", output_chd_str, err.message());
+ auto chd = std::make_unique<chd_rawfile_compressor>(*input_file, input_start, input_end);
+ create_output_chd(*chd, *output_chd_str, input_end - input_start, hunk_size, unit_size, compression, output_parent);
// if we have a parent, copy forward all the metadata
if (output_parent.opened())
@@ -1778,9 +1920,7 @@ static void do_create_raw(parameters_map &params)
catch (...)
{
// delete the output file
- auto output_chd_str = params.find(OPTION_OUTPUT);
- if (output_chd_str != params.end())
- osd_file::remove(*output_chd_str->second);
+ osd_file::remove(*output_chd_str);
throw;
}
}
@@ -1794,79 +1934,93 @@ static void do_create_raw(parameters_map &params)
static void do_create_hd(parameters_map &params)
{
// process input file
- util::core_file::ptr input_file;
- auto input_file_str = params.find(OPTION_INPUT);
- if (input_file_str != params.end())
- {
- 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());
- }
+ auto [input_file, input_file_str] = open_input_file(params);
// process output CHD
chd_file output_parent;
- std::string *output_chd_str = parse_output_chd_parameters(params, output_parent);
+ const auto output_chd_str = parse_output_chd_parameters(params, output_parent);
- // process sectorsize
+ // process template
+ uint32_t cylinders = 0;
+ uint32_t heads = 0;
+ uint32_t sectors = 0;
uint32_t sector_size = output_parent.opened() ? output_parent.unit_bytes() : IDE_SECTOR_SIZE;
+ const auto template_str = params.find(OPTION_TEMPLATE);
+ uint32_t template_id = 0;
+ if (template_str != params.end())
+ {
+ if (output_parent.opened())
+ report_error(1, "Template cannot be used when a parent CHD is supplied");
+ template_id = parse_number(template_str->second->c_str());
+ if (template_id >= std::size(s_hd_templates))
+ report_error(1, "Template '%s' is invalid\n", *template_str->second);
+
+ cylinders = s_hd_templates[template_id].cylinders;
+ heads = s_hd_templates[template_id].heads;
+ sectors = s_hd_templates[template_id].sectors;
+ sector_size = s_hd_templates[template_id].sector_size;
+ }
+
+ // process CHS
+ const auto chs_str = params.find(OPTION_CHS);
+ if (chs_str != params.end())
+ {
+ if (template_str != params.end())
+ report_error(1, "CHS geometry cannot be specified separately when a template is specified");
+ if (output_parent.opened())
+ report_error(1, "CHS geometry cannot be specified when a parent CHD is supplied");
+ if (sscanf(chs_str->second->c_str(), "%u,%u,%u", &cylinders, &heads, &sectors) != 3)
+ report_error(1, "Invalid CHS string; must be of the form <cylinders>,<heads>,<sectors>");
+ }
+
+ // process sector size
auto sectorsize_str = params.find(OPTION_SECTOR_SIZE);
if (sectorsize_str != params.end())
{
- if (output_parent.opened())
- report_error(1, "Sector size does not apply when creating a diff from the parent");
+ if (template_str != params.end())
+ report_error(1, "Sector size cannot be specified separately when a template is specified");
sector_size = parse_number(sectorsize_str->second->c_str());
}
+ if (output_parent.opened() && (output_parent.unit_bytes() != sector_size))
+ report_error(1, "Sector size %u bytes does not match output parent CHD sector size %u bytes", sector_size, output_parent.unit_bytes());
// process hunk size (needs to know sector_size)
- uint32_t hunk_size = output_parent.opened() ? output_parent.hunk_bytes() : std::max((4096 / sector_size) * sector_size, sector_size);
- parse_hunk_size(params, sector_size, hunk_size);
+ const uint32_t hunk_size = parse_hunk_size(params, output_parent, sector_size, std::max((4096 / sector_size) * sector_size, sector_size));
// process input start/end (needs to know hunk_size)
uint64_t filesize = 0;
+ uint64_t input_size = 0;
uint64_t input_start = 0;
uint64_t input_end = 0;
if (input_file)
{
- uint64_t input_size = 0;
- input_file->length(input_size); // FIXME: check error return
- parse_input_start_end(params, input_size, hunk_size, hunk_size, input_start, input_end);
+ std::tie(input_size, input_start, input_end) = parse_input_start_end(params, *input_file, hunk_size, hunk_size);
filesize = input_end - input_start;
+ if (params.find(OPTION_SIZE) != params.end())
+ report_error(1, "Size cannot be specified when an input file is supplied");
}
else
{
- auto size_str = params.find(OPTION_SIZE);
+ const auto size_str = params.find(OPTION_SIZE);
if (size_str != params.end())
{
- if (sscanf(size_str->second->c_str(), "%" I64FMT"d", &filesize) != 1)
- report_error(1, "Invalid size string");
+ if (sscanf(size_str->second->c_str(), "%" I64FMT"u", &filesize) != 1)
+ report_error(1, "Invalid size specified");
}
+ if ((params.find(OPTION_INPUT_START_BYTE) != params.end()) || (params.find(OPTION_INPUT_START_HUNK) != params.end()) ||
+ (params.find(OPTION_INPUT_LENGTH_BYTES) != params.end()) || (params.find(OPTION_INPUT_LENGTH_HUNKS) != params.end()))
+ report_error(1, "Input start/length cannot be specified when no input file is supplied");
}
// process compression
chd_codec_type compression[4];
- memcpy(compression, s_default_hd_compression, sizeof(compression));
- if (!input_file)
- compression[0] = compression[1] = compression[2] = compression[3] = CHD_CODEC_NONE;
- parse_compression(params, compression);
- if (!input_file && compression[0] != CHD_CODEC_NONE)
- report_error(1, "Blank hard disks must be uncompressed");
+ parse_compression(params, input_file ? s_default_hd_compression : s_no_compression, output_parent, compression);
+ if (!input_file && (compression[0] != CHD_CODEC_NONE))
+ report_error(1, "Blank hard disk images must be uncompressed");
// process numprocessors
parse_numprocessors(params);
- // process chs
- uint32_t cylinders = 0;
- uint32_t heads = 0;
- uint32_t sectors = 0;
- auto chs_str = params.find(OPTION_CHS);
- if (chs_str != params.end())
- {
- if (output_parent.opened())
- report_error(1, "CHS does not apply when creating a diff from the parent");
- if (sscanf(chs_str->second->c_str(), "%d,%d,%d", &cylinders, &heads, &sectors) != 3)
- report_error(1, "Invalid CHS string; must be of the form <cylinders>,<heads>,<sectors>");
- }
-
// process ident
std::vector<uint8_t> identdata;
if (output_parent.opened())
@@ -1887,27 +2041,10 @@ static void do_create_hd(parameters_map &params)
sectors = get_u16le(&identdata[12]);
// ignore CHS for > 8GB drives
- if (cylinders * heads * sectors >= 16514064)
+ if (cylinders * heads * sectors >= 16'514'064)
cylinders = 0;
}
- // process template
- auto template_str = params.find(OPTION_TEMPLATE);
- if (template_str != params.end())
- {
- uint32_t id = parse_number(template_str->second->c_str());
-
- if (id >= std::size(s_hd_templates))
- report_error(1, "Template '%d' is invalid\n", id);
-
- cylinders = s_hd_templates[id].cylinders;
- heads = s_hd_templates[id].heads;
- sectors = s_hd_templates[id].sectors;
- sector_size = s_hd_templates[id].sector_size;
-
- printf("Template: %s %s\n", s_hd_templates[id].manufacturer, s_hd_templates[id].model);
- }
-
// extract geometry from the parent if we have one
if (output_parent.opened() && cylinders == 0)
{
@@ -1919,58 +2056,55 @@ static void do_create_hd(parameters_map &params)
}
// validate the size
- if (filesize % sector_size != 0)
- report_error(1, "Data size is not divisible by sector size %d", sector_size);
+ if (filesize % sector_size)
+ report_error(1, "Data size %s is not divisible by sector size %u", big_int_string(input_end - input_start), sector_size);
// if no CHS values, try to guess them
if (cylinders == 0)
{
if (!input_file && filesize == 0)
- report_error(1, "Blank hard drives must specify either a length or a set of CHS values");
- guess_chs((input_file_str != params.end()) ? input_file_str->second : nullptr, filesize, sector_size, cylinders, heads, sectors, sector_size);
+ report_error(1, "Length or CHS geometry must be specified when creating a blank hard disk image");
+ guess_chs(input_file_str, filesize, sector_size, cylinders, heads, sectors, sector_size);
}
uint32_t totalsectors = cylinders * heads * sectors;
// print some info
- printf("Output CHD: %s\n", output_chd_str->c_str());
+ util::stream_format(std::cout, "Output CHD: %s\n", *output_chd_str);
if (output_parent.opened())
- printf("Parent CHD: %s\n", params.find(OPTION_OUTPUT_PARENT)->second->c_str());
+ util::stream_format(std::cout, "Parent CHD: %s\n", *params.find(OPTION_OUTPUT_PARENT)->second);
if (input_file)
{
- uint64_t input_size = 0;
- input_file->length(input_size); // FIXME: check error return
- printf("Input file: %s\n", input_file_str->second->c_str());
+ util::stream_format(std::cout, "Input file: %s\n", *input_file_str);
if (input_start != 0 || input_end != input_size)
{
- printf("Input start: %s\n", big_int_string(input_start).c_str());
- printf("Input length: %s\n", big_int_string(filesize).c_str());
+ util::stream_format(std::cout, "Input start: %s\n", big_int_string(input_start));
+ util::stream_format(std::cout, "Input length: %s\n", big_int_string(filesize));
}
}
- printf("Compression: %s\n", compression_string(compression).c_str());
- printf("Cylinders: %d\n", cylinders);
- printf("Heads: %d\n", heads);
- printf("Sectors: %d\n", sectors);
- printf("Bytes/sector: %d\n", sector_size);
- printf("Sectors/hunk: %d\n", hunk_size / sector_size);
- printf("Logical size: %s\n", big_int_string(uint64_t(totalsectors) * uint64_t(sector_size)).c_str());
+ util::stream_format(std::cout, "Compression: %s\n", compression_string(compression));
+ if (template_str != params.end())
+ util::stream_format(std::cout, "Template: %s %s\n", s_hd_templates[template_id].manufacturer, s_hd_templates[template_id].model);
+ util::stream_format(std::cout, "Cylinders: %u\n", cylinders);
+ util::stream_format(std::cout, "Heads: %u\n", heads);
+ util::stream_format(std::cout, "Sectors: %u\n", sectors);
+ util::stream_format(std::cout, "Bytes/sector: %u\n", sector_size);
+ util::stream_format(std::cout, "Sectors/hunk: %u\n", hunk_size / sector_size);
+ util::stream_format(std::cout, "Logical size: %s\n", big_int_string(uint64_t(totalsectors) * uint64_t(sector_size)));
// catch errors so we can close & delete the output file
try
{
// create the new hard drive
std::unique_ptr<chd_file_compressor> 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));
- 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);
+ if (input_file)
+ chd.reset(new chd_rawfile_compressor(*input_file, input_start, input_end));
else
- err = chd->create(output_chd_str->c_str(), uint64_t(totalsectors) * uint64_t(sector_size), hunk_size, sector_size, compression);
- if (err)
- report_error(1, "Error creating CHD file (%s): %s", output_chd_str, err.message());
+ chd.reset(new chd_zero_compressor(input_start, input_end));
+ create_output_chd(*chd, *output_chd_str, uint64_t(totalsectors) * sector_size, hunk_size, sector_size, compression, output_parent);
// add the standard hard disk metadata
- std::string metadata = string_format(HARD_DISK_METADATA_FORMAT, cylinders, heads, sectors, sector_size);
+ std::string metadata = string_format(HARD_DISK_METADATA_FORMAT, cylinders, heads, sectors, sector_size);
+ std::error_condition err;
err = chd->write_metadata(HARD_DISK_METADATA_TAG, 0, metadata);
if (err)
report_error(1, "Error adding hard disk metadata: %s", err.message());
@@ -1990,9 +2124,7 @@ static void do_create_hd(parameters_map &params)
catch (...)
{
// delete the output file
- auto output_chd_str = params.find(OPTION_OUTPUT);
- if (output_chd_str != params.end())
- osd_file::remove(*output_chd_str->second);
+ osd_file::remove(*output_chd_str);
throw;
}
}
@@ -2018,21 +2150,21 @@ static void do_create_cd(parameters_map &params)
// process output CHD
chd_file output_parent;
- std::string *output_chd_str = parse_output_chd_parameters(params, output_parent);
+ const auto output_chd_str = parse_output_chd_parameters(params, output_parent);
// process hunk size
- uint32_t hunk_size = output_parent.opened() ? output_parent.hunk_bytes() : cdrom_file::FRAMES_PER_HUNK * cdrom_file::FRAME_SIZE;
- parse_hunk_size(params, cdrom_file::FRAME_SIZE, hunk_size);
+ const uint32_t hunk_size = parse_hunk_size(params, output_parent, cdrom_file::FRAME_SIZE, cdrom_file::FRAMES_PER_HUNK * cdrom_file::FRAME_SIZE);
+ if (output_parent.opened() && (output_parent.unit_bytes() != cdrom_file::FRAME_SIZE))
+ report_error(1, "Output parent CHD sector size %u bytes does not match CD-ROM frame size %u bytes", output_parent.unit_bytes(), cdrom_file::FRAME_SIZE);
// process compression
chd_codec_type compression[4];
- memcpy(compression, s_default_cd_compression, sizeof(compression));
- parse_compression(params, compression);
+ parse_compression(params, s_default_cd_compression, output_parent, compression);
// process numprocessors
parse_numprocessors(params);
- // pad each track to a 4-frame boundary. cdrom.c will deal with this on the read side
+ // pad each track to a 4-frame boundary. cdrom.cpp will deal with this on the read side
uint32_t origtotalsectors = 0;
uint32_t totalsectors = 0;
for (int tracknum = 0; tracknum < toc.numtrks; tracknum++)
@@ -2045,45 +2177,34 @@ static void do_create_cd(parameters_map &params)
}
// print some info
- printf("Output CHD: %s\n", output_chd_str->c_str());
+ util::stream_format(std::cout, "Output CHD: %s\n", *output_chd_str);
if (output_parent.opened())
- printf("Parent CHD: %s\n", params.find(OPTION_OUTPUT_PARENT)->second->c_str());
- printf("Input file: %s\n", input_file_str->second->c_str());
- printf("Input tracks: %d\n", toc.numtrks);
- printf("Input length: %s\n", msf_string_from_frames(origtotalsectors).c_str());
- printf("Compression: %s\n", compression_string(compression).c_str());
- printf("Logical size: %s\n", big_int_string(uint64_t(totalsectors) * cdrom_file::FRAME_SIZE).c_str());
+ util::stream_format(std::cout, "Parent CHD: %s\n", *params.find(OPTION_OUTPUT_PARENT)->second);
+ util::stream_format(std::cout, "Input file: %s\n", *input_file_str->second);
+ util::stream_format(std::cout, "Input tracks: %d\n", toc.numtrks);
+ util::stream_format(std::cout, "Input length: %s\n", msf_string_from_frames(origtotalsectors));
+ util::stream_format(std::cout, "Compression: %s\n", compression_string(compression));
+ util::stream_format(std::cout, "Logical size: %s\n", big_int_string(uint64_t(totalsectors) * cdrom_file::FRAME_SIZE));
// catch errors so we can close & delete the output file
- chd_cd_compressor *chd = nullptr;
try
{
// create the new CD
- chd = new chd_cd_compressor(toc, track_info);
- std::error_condition err;
- if (output_parent.opened())
- err = chd->create(output_chd_str->c_str(), uint64_t(totalsectors) * uint64_t(cdrom_file::FRAME_SIZE), hunk_size, compression, output_parent);
- else
- err = chd->create(output_chd_str->c_str(), uint64_t(totalsectors) * uint64_t(cdrom_file::FRAME_SIZE), hunk_size, cdrom_file::FRAME_SIZE, compression);
- if (err)
- report_error(1, "Error creating CHD file (%s): %s", *output_chd_str, err.message());
+ auto chd = std::make_unique<chd_cd_compressor>(toc, track_info);
+ create_output_chd(*chd, *output_chd_str, uint64_t(totalsectors) * cdrom_file::FRAME_SIZE, hunk_size, cdrom_file::FRAME_SIZE, compression, output_parent);
// add the standard CD metadata; we do this even if we have a parent because it might be different
- err = cdrom_file::write_metadata(chd, toc);
+ const std::error_condition err = cdrom_file::write_metadata(chd.get(), toc);
if (err)
report_error(1, "Error adding CD metadata: %s", err.message());
// compress it generically
compress_common(*chd);
- delete chd;
}
catch (...)
{
- delete chd;
// delete the output file
- auto output_chd_str = params.find(OPTION_OUTPUT);
- if (output_chd_str != params.end())
- osd_file::remove(*output_chd_str->second);
+ osd_file::remove(*output_chd_str);
throw;
}
}
@@ -2097,65 +2218,53 @@ static void do_create_cd(parameters_map &params)
static void do_create_dvd(parameters_map &params)
{
// process input file
- util::core_file::ptr input_file;
- auto input_file_str = params.find(OPTION_INPUT);
- if (input_file_str != params.end())
- {
- 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());
- }
+ auto [input_file, input_file_str] = open_input_file(params);
// process output CHD
chd_file output_parent;
- std::string *output_chd_str = parse_output_chd_parameters(params, output_parent);
+ const auto output_chd_str = parse_output_chd_parameters(params, output_parent);
+
+ // process hunk size
+ const uint32_t hunk_size = parse_hunk_size(params, output_parent, 2048, 2 * 2048);
+ if (output_parent.opened() && (output_parent.unit_bytes() != 2048))
+ report_error(1, "Output parent CHD sector size %u bytes does not match DVD-ROM sector size 2048 bytes", output_parent.unit_bytes());
// process input start/end
- uint64_t filesize = 0;
- input_file->length(filesize); // FIXME: check error return
+ const auto [input_size, input_start, input_end] = parse_input_start_end(params, *input_file, hunk_size, hunk_size);
+ if ((input_end - input_start) % 2048)
+ report_error(1, "Data size %s is not divisible by sector size 2048", big_int_string(input_end - input_start));
// process compression
chd_codec_type compression[4];
- memcpy(compression, s_default_hd_compression, sizeof(compression)); // No reason to be different than HD for compression
- if (!input_file)
- compression[0] = compression[1] = compression[2] = compression[3] = CHD_CODEC_NONE;
- parse_compression(params, compression);
+ parse_compression(params, s_default_hd_compression, output_parent, compression); // No reason to be different than HD for compression
// process numprocessors
parse_numprocessors(params);
- // validate the size
- if (filesize % 2048 != 0)
- report_error(1, "Data size is not divisible by 2048");
-
- uint32_t totalsectors = filesize / 2048;
-
// print some info
- printf("Output CHD: %s\n", output_chd_str->c_str());
+ util::stream_format(std::cout, "Output CHD: %s\n", *output_chd_str);
if (output_parent.opened())
- printf("Parent CHD: %s\n", params.find(OPTION_OUTPUT_PARENT)->second->c_str());
- printf("Input file: %s\n", input_file_str->second->c_str());
- printf("Compression: %s\n", compression_string(compression).c_str());
- printf("Logical size: %s\n", big_int_string(uint64_t(totalsectors) * 2048).c_str());
+ util::stream_format(std::cout, "Parent CHD: %s\n", *params.find(OPTION_OUTPUT_PARENT)->second);
+ util::stream_format(std::cout, "Input file: %s\n", *input_file_str);
+ if (input_start != 0 || input_end != input_size)
+ {
+ util::stream_format(std::cout, "Input start: %s\n", big_int_string(input_start));
+ util::stream_format(std::cout, "Input length: %s\n", big_int_string(input_end - input_start));
+ }
+ util::stream_format(std::cout, "Compression: %s\n", compression_string(compression));
+ util::stream_format(std::cout, "Logical size: %s\n", big_int_string(input_end - input_start));
// catch errors so we can close & delete the output file
try
{
- // create the new dvd
- std::unique_ptr<chd_file_compressor> chd;
- chd.reset(new chd_rawfile_compressor(*input_file, 0, filesize));
- std::error_condition err;
- if (output_parent.opened())
- err = chd->create(output_chd_str->c_str(), uint64_t(totalsectors) * 2048, 2048, compression, output_parent);
- else
- err = chd->create(output_chd_str->c_str(), uint64_t(totalsectors) * 2048, 2048, 2048, compression);
- if (err)
- report_error(1, "Error creating CHD file (%s): %s", output_chd_str, err.message());
+ // create the new DVD
+ auto chd = std::make_unique<chd_rawfile_compressor>(*input_file, input_start, input_end);
+ create_output_chd(*chd, *output_chd_str, input_end - input_start, hunk_size, 2048, compression, output_parent);
- // add the standard dvd type tag
- err = chd->write_metadata(DVD_METADATA_TAG, 0, "");
+ // add the standard DVD type tag
+ const std::error_condition err = chd->write_metadata(DVD_METADATA_TAG, 0, "");
if (err)
- report_error(1, "Error adding dvd metadata: %s", err.message());
+ report_error(1, "Error adding DVD metadata: %s", err.message());
// compress it generically
compress_common(*chd);
@@ -2163,9 +2272,7 @@ static void do_create_dvd(parameters_map &params)
catch (...)
{
// delete the output file
- auto output_chd_str = params.find(OPTION_OUTPUT);
- if (output_chd_str != params.end())
- osd_file::remove(*output_chd_str->second);
+ osd_file::remove(*output_chd_str);
throw;
}
}
@@ -2191,12 +2298,10 @@ static void do_create_ld(parameters_map &params)
// process output CHD
chd_file output_parent;
- std::string *output_chd_str = parse_output_chd_parameters(params, output_parent);
+ const auto output_chd_str = parse_output_chd_parameters(params, output_parent);
// process input start/end
- uint64_t input_start;
- uint64_t input_end;
- parse_input_start_end(params, aviinfo.video_numsamples, 0, 1, input_start, input_end);
+ auto [input_start, input_end] = parse_input_start_end(params, aviinfo.video_numsamples, 0, 1);
// determine parameters of the incoming video stream
avi_info info;
@@ -2221,13 +2326,11 @@ static void do_create_ld(parameters_map &params)
info.bytes_per_frame = avhuff_encoder::raw_data_size(info.width, info.height, info.channels, info.max_samples_per_frame);
// process hunk size
- uint32_t hunk_size = output_parent.opened() ? output_parent.hunk_bytes() : info.bytes_per_frame;
- parse_hunk_size(params, info.bytes_per_frame, hunk_size);
+ const uint32_t hunk_size = parse_hunk_size(params, output_parent, info.bytes_per_frame, info.bytes_per_frame);
// process compression
chd_codec_type compression[4];
- memcpy(compression, s_default_ld_compression, sizeof(compression));
- parse_compression(params, compression);
+ parse_compression(params, s_default_ld_compression, output_parent, compression);
// disable support for uncompressed ones until the extraction code can handle it
if (compression[0] == CHD_CODEC_NONE)
report_error(1, "Uncompressed is not supported");
@@ -2236,39 +2339,33 @@ static void do_create_ld(parameters_map &params)
parse_numprocessors(params);
// print some info
- printf("Output CHD: %s\n", output_chd_str->c_str());
+ util::stream_format(std::cout, "Output CHD: %s\n", *output_chd_str);
if (output_parent.opened())
- printf("Parent CHD: %s\n", params.find(OPTION_OUTPUT_PARENT)->second->c_str());
- printf("Input file: %s\n", input_file_str->second->c_str());
+ util::stream_format(std::cout, "Parent CHD: %s\n", *params.find(OPTION_OUTPUT_PARENT)->second);
+ util::stream_format(std::cout, "Input file: %s\n", *input_file_str->second);
if (input_start != 0 && input_end != aviinfo.video_numsamples)
- printf("Input start: %s\n", big_int_string(input_start).c_str());
- printf("Input length: %s (%02d:%02d:%02d)\n", big_int_string(input_end - input_start).c_str(),
+ util::stream_format(std::cout, "Input start: %s\n", big_int_string(input_start));
+ util::stream_format(std::cout, "Input length: %s (%02d:%02d:%02d)\n", big_int_string(input_end - input_start),
uint32_t((uint64_t(input_end - input_start) * 1000000 / info.fps_times_1million / 60 / 60)),
uint32_t(((uint64_t(input_end - input_start) * 1000000 / info.fps_times_1million / 60) % 60)),
uint32_t(((uint64_t(input_end - input_start) * 1000000 / info.fps_times_1million) % 60)));
- printf("Frame rate: %d.%06d\n", info.fps_times_1million / 1000000, info.fps_times_1million % 1000000);
- printf("Frame size: %d x %d %s\n", info.width, info.height * (info.interlaced ? 2 : 1), info.interlaced ? "interlaced" : "non-interlaced");
- printf("Audio: %d channels at %d Hz\n", info.channels, info.rate);
- printf("Compression: %s\n", compression_string(compression).c_str());
- printf("Hunk size: %s\n", big_int_string(hunk_size).c_str());
- printf("Logical size: %s\n", big_int_string(uint64_t(input_end - input_start) * hunk_size).c_str());
+ util::stream_format(std::cout, "Frame rate: %d.%06d\n", info.fps_times_1million / 1000000, info.fps_times_1million % 1000000);
+ util::stream_format(std::cout, "Frame size: %d x %d %s\n", info.width, info.height * (info.interlaced ? 2 : 1), info.interlaced ? "interlaced" : "non-interlaced");
+ util::stream_format(std::cout, "Audio: %d channels at %d Hz\n", info.channels, info.rate);
+ util::stream_format(std::cout, "Compression: %s\n", compression_string(compression));
+ util::stream_format(std::cout, "Hunk size: %s\n", big_int_string(hunk_size));
+ util::stream_format(std::cout, "Logical size: %s\n", big_int_string(uint64_t(input_end - input_start) * hunk_size));
// catch errors so we can close & delete the output file
- chd_avi_compressor *chd = nullptr;
try
{
// create the new CHD
- chd = new chd_avi_compressor(*input_file, info, input_start, input_end);
- 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)
- report_error(1, "Error creating CHD file (%s): %s", *output_chd_str, err.message());
+ auto chd = std::make_unique<chd_avi_compressor>(*input_file, info, input_start, input_end);
+ create_output_chd(*chd, *output_chd_str, uint64_t(input_end - input_start) * hunk_size, hunk_size, info.bytes_per_frame, compression, output_parent);
// 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);
+ std::error_condition err;
err = chd->write_metadata(AV_METADATA_TAG, 0, metadata);
if (err)
report_error(1, "Error adding AV metadata: %s\n", err.message());
@@ -2283,21 +2380,50 @@ static void do_create_ld(parameters_map &params)
if (err)
report_error(1, "Error adding AVLD metadata: %s\n", err.message());
}
- delete chd;
}
catch (...)
{
- delete chd;
// delete the output file
- auto output_chd_str = params.find(OPTION_OUTPUT);
- if (output_chd_str != params.end())
- osd_file::remove(*output_chd_str->second);
+ osd_file::remove(*output_chd_str);
throw;
}
}
//-------------------------------------------------
+// get_compression_defaults - use CHD metadata to
+// pick the preferred type
+//-------------------------------------------------
+
+static const std::array<chd_codec_type, 4> &get_compression_defaults(chd_file &input_chd)
+{
+ std::error_condition err = input_chd.check_is_hd();
+ if (err == chd_file::error::METADATA_NOT_FOUND)
+ err = input_chd.check_is_dvd();
+ if (!err)
+ return s_default_hd_compression;
+ if (err != chd_file::error::METADATA_NOT_FOUND)
+ throw err;
+
+ err = input_chd.check_is_av();
+ if (!err)
+ return s_default_ld_compression;
+ if (err != chd_file::error::METADATA_NOT_FOUND)
+ throw err;
+
+ err = input_chd.check_is_cd();
+ if (err == chd_file::error::METADATA_NOT_FOUND)
+ err = input_chd.check_is_gd();
+ if (!err)
+ return s_default_cd_compression;
+ if (err != chd_file::error::METADATA_NOT_FOUND)
+ throw err;
+
+ return s_default_raw_compression;
+}
+
+
+//-------------------------------------------------
// do_copy - create a new CHD with data from
// another CHD
//-------------------------------------------------
@@ -2310,71 +2436,49 @@ static void do_copy(parameters_map &params)
parse_input_chd_parameters(params, input_chd, input_parent_chd);
// parse out input start/end
- uint64_t input_start;
- uint64_t input_end;
- parse_input_start_end(params, input_chd.logical_bytes(), input_chd.hunk_bytes(), input_chd.hunk_bytes(), input_start, input_end);
+ const auto [input_start, input_end] = parse_input_start_end(params, input_chd.logical_bytes(), input_chd.hunk_bytes(), input_chd.hunk_bytes());
+ // TODO: should we check that the input range is aligned to the unit size?
// process output CHD
chd_file output_parent;
- std::string *output_chd_str = parse_output_chd_parameters(params, output_parent);
+ const auto output_chd_str = parse_output_chd_parameters(params, output_parent);
// process hunk size
- uint32_t hunk_size = input_chd.hunk_bytes();
- parse_hunk_size(params, 1, hunk_size);
- if (hunk_size % input_chd.hunk_bytes() != 0 && input_chd.hunk_bytes() % hunk_size != 0)
- report_error(1, "Hunk size is not an even multiple or divisor of input hunk size");
+ const uint32_t hunk_size = parse_hunk_size(params, output_parent, input_chd.unit_bytes(), input_chd.hunk_bytes());
+ if ((hunk_size % input_chd.hunk_bytes()) && (input_chd.hunk_bytes() % hunk_size)) // TODO: is this check still necessary, or is the unit size check enough?
+ report_error(1, "Hunk size is not a whole multiple or factor of input hunk size");
// process compression; we default to our current preferences using metadata to pick the type
chd_codec_type compression[4];
- {
- std::vector<uint8_t> metadata;
- 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))
- memcpy(compression, s_default_ld_compression, sizeof(compression));
- 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));
- }
- parse_compression(params, compression);
+ parse_compression(params, get_compression_defaults(input_chd), output_parent, compression);
// process numprocessors
parse_numprocessors(params);
// print some info
- printf("Output CHD: %s\n", output_chd_str->c_str());
+ util::stream_format(std::cout, "Output CHD: %s\n", *output_chd_str);
if (output_parent.opened())
- printf("Parent CHD: %s\n", params.find(OPTION_OUTPUT_PARENT)->second->c_str());
- printf("Input CHD: %s\n", params.find(OPTION_INPUT)->second->c_str());
+ util::stream_format(std::cout, "Parent CHD: %s\n", *params.find(OPTION_OUTPUT_PARENT)->second);
+ util::stream_format(std::cout, "Input CHD: %s\n", *params.find(OPTION_INPUT)->second);
if (input_start != 0 || input_end != input_chd.logical_bytes())
{
- printf("Input start: %s\n", big_int_string(input_start).c_str());
- printf("Input length: %s\n", big_int_string(input_end - input_start).c_str());
+ util::stream_format(std::cout, "Input start: %s\n", big_int_string(input_start));
+ util::stream_format(std::cout, "Input length: %s\n", big_int_string(input_end - input_start));
}
- printf("Compression: %s\n", compression_string(compression).c_str());
- printf("Hunk size: %s\n", big_int_string(hunk_size).c_str());
- printf("Logical size: %s\n", big_int_string(input_end - input_start).c_str());
+ util::stream_format(std::cout, "Compression: %s\n", compression_string(compression));
+ util::stream_format(std::cout, "Hunk size: %s\n", big_int_string(hunk_size));
+ util::stream_format(std::cout, "Logical size: %s\n", big_int_string(input_end - input_start));
// catch errors so we can close & delete the output file
- chd_chdfile_compressor *chd = nullptr;
try
{
// create the new CHD
- chd = new chd_chdfile_compressor(input_chd, input_start, input_end);
- 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)
- report_error(1, "Error creating CHD file (%s): %s", *output_chd_str, err.message());
+ std::unique_ptr<cdrom_file> cdrom; // want this to be unwound after chd
+ auto chd = std::make_unique<chd_chdfile_compressor>(input_chd, input_start, input_end);
+ create_output_chd(*chd, *output_chd_str, input_end - input_start, hunk_size, input_chd.unit_bytes(), compression, output_parent);
// clone all the metadata, upgrading where appropriate
+ std::error_condition err;
std::vector<uint8_t> metadata;
chd_metadata_tag metatag;
uint8_t metaflags;
@@ -2405,9 +2509,9 @@ static void do_copy(parameters_map &params)
// if we need to re-do the CD metadata, do it now
if (redo_cd)
{
- cdrom_file *cdrom = new cdrom_file(&input_chd);
+ cdrom = std::make_unique<cdrom_file>(&input_chd);
const cdrom_file::toc &toc = cdrom->get_toc();
- err = cdrom_file::write_metadata(chd, toc);
+ err = cdrom_file::write_metadata(chd.get(), toc);
if (err)
report_error(1, "Error writing upgraded CD metadata: %s", err.message());
if (cdda_swap)
@@ -2416,15 +2520,11 @@ static void do_copy(parameters_map &params)
// compress it generically
compress_common(*chd);
- delete chd;
}
catch (...)
{
- delete chd;
// delete the output file
- auto output_chd_str = params.find(OPTION_OUTPUT);
- if (output_chd_str != params.end())
- osd_file::remove(*output_chd_str->second);
+ osd_file::remove(*output_chd_str);
throw;
}
}
@@ -2443,22 +2543,20 @@ static void do_extract_raw(parameters_map &params)
parse_input_chd_parameters(params, input_chd, input_parent_chd);
// parse out input start/end
- uint64_t input_start;
- uint64_t input_end;
- parse_input_start_end(params, input_chd.logical_bytes(), input_chd.hunk_bytes(), input_chd.hunk_bytes(), input_start, input_end);
+ const auto [input_start, input_end] = parse_input_start_end(params, input_chd.logical_bytes(), input_chd.hunk_bytes(), input_chd.hunk_bytes());
// verify output file doesn't exist
auto output_file_str = params.find(OPTION_OUTPUT);
if (output_file_str != params.end())
- check_existing_output_file(params, output_file_str->second->c_str());
+ check_existing_output_file(params, *output_file_str->second);
// print some info
- printf("Output File: %s\n", output_file_str->second->c_str());
- printf("Input CHD: %s\n", params.find(OPTION_INPUT)->second->c_str());
+ util::stream_format(std::cout, "Output File: %s\n", *output_file_str->second);
+ util::stream_format(std::cout, "Input CHD: %s\n", *params.find(OPTION_INPUT)->second);
if (input_start != 0 || input_end != input_chd.logical_bytes())
{
- printf("Input start: %s\n", big_int_string(input_start).c_str());
- printf("Input length: %s\n", big_int_string(input_end - input_start).c_str());
+ util::stream_format(std::cout, "Input start: %s\n", big_int_string(input_start));
+ util::stream_format(std::cout, "Input length: %s\n", big_int_string(input_end - input_start));
}
// catch errors so we can close & delete the output file
@@ -2483,9 +2581,8 @@ static void do_extract_raw(parameters_map &params)
report_error(1, "Error reading CHD file (%s): %s", *params.find(OPTION_INPUT)->second, err.message());
// write to the output
- size_t count;
- std::error_condition const writerr = output_file->write(&buffer[0], bytes_to_read, count);
- if (writerr || (count != bytes_to_read))
+ auto const [writerr, count] = write(*output_file, &buffer[0], bytes_to_read);
+ if (writerr)
report_error(1, "Error writing to file; check disk space (%s)", *output_file_str->second);
// advance
@@ -2494,7 +2591,7 @@ static void do_extract_raw(parameters_map &params)
// finish up
output_file.reset();
- printf("Extraction complete \n");
+ util::stream_format(std::cout, "Extraction complete \n");
}
catch (...)
{
@@ -2528,63 +2625,160 @@ static void do_extract_cd(parameters_map &params)
// verify output file doesn't exist
auto output_file_str = params.find(OPTION_OUTPUT);
if (output_file_str != params.end())
- check_existing_output_file(params, output_file_str->second->c_str());
+ check_existing_output_file(params, *output_file_str->second);
- // verify output BIN file doesn't exist
+ // determine output type based on the specified file extension
+ int mode = MODE_NORMAL;
+ if (core_filename_ends_with(*output_file_str->second, ".cue"))
+ mode = MODE_CUEBIN;
+ else if (core_filename_ends_with(*output_file_str->second, ".gdi"))
+ mode = MODE_GDI;
+
+ // determine the output bin filename based on provided input parameters
auto output_bin_file_fnd = params.find(OPTION_OUTPUT_BIN);
std::string default_name(*output_file_str->second);
+
+ // split path and extension
int chop = default_name.find_last_of('.');
- if (chop != -1)
+ if (chop != std::string::npos)
default_name.erase(chop, default_name.size());
- std::string basename = default_name;
- default_name.append(".bin");
+
+ // GDIs will always output as split bin
+ bool is_splitbin = mode == MODE_GDI || params.find(OPTION_OUTPUT_SPLITBIN) != params.end();
+ if (!is_splitbin && cdrom->is_gdrom() && mode == MODE_CUEBIN)
+ {
+ // GD-ROM cue/bin is in Redump format which should always be split by tracks
+ util::stream_format(std::cout, "Warning: --%s is required for this specific combination of input disc type and output format, enabling automatically\n", OPTION_OUTPUT_SPLITBIN);
+ is_splitbin = true;
+ }
+
+ if (is_splitbin)
+ {
+ if (mode == MODE_GDI)
+ {
+ default_name += "%02t";
+ }
+ else
+ {
+ const std::string format = toc.numtrks >= 10 ? "%02t" : "%t";
+ default_name += " (Track " + format + ")";
+ }
+ }
+
+ std::string output_bin_file_ext = ".bin";
std::string *output_bin_file_str;
if (output_bin_file_fnd == params.end())
+ {
output_bin_file_str = &default_name;
+ }
else
+ {
output_bin_file_str = output_bin_file_fnd->second;
- check_existing_output_file(params, output_bin_file_str->c_str());
+ chop = output_bin_file_str->find_last_of('.');
+ if (chop != std::string::npos)
+ {
+ output_bin_file_ext = output_bin_file_str->substr(chop, output_bin_file_str->size() - chop);
+ output_bin_file_str->erase(chop, output_bin_file_str->size());
+ }
+ }
+
+ if (output_bin_file_str->find('"') != std::string::npos || output_bin_file_ext.find('"') != std::string::npos)
+ report_error(1, "Output bin filename (%s%s) must not contain quotation marks", *output_bin_file_str, output_bin_file_ext);
// print some info
- printf("Output TOC: %s\n", output_file_str->second->c_str());
- printf("Output Data: %s\n", output_bin_file_str->c_str());
- printf("Input CHD: %s\n", params.find(OPTION_INPUT)->second->c_str());
+ util::stream_format(std::cout, "Input CHD: %s\n", *params.find(OPTION_INPUT)->second);
+ util::stream_format(std::cout, "Output TOC: %s\n", *output_file_str->second);
// catch errors so we can close & delete the output file
+ std::vector<std::string> track_filenames;
util::core_file::ptr output_bin_file;
util::core_file::ptr output_toc_file;
+ std::vector<std::string> output_bin_filenames;
+ std::string trackbin_name;
try
{
- int mode = MODE_NORMAL;
-
- if (output_file_str->second->find(".cue") != -1)
- {
- mode = MODE_CUEBIN;
- }
- else if (output_file_str->second->find(".gdi") != -1)
- {
- mode = MODE_GDI;
- }
-
// process output file
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)
- report_error(1, "Unable to open file (%s): %s", *output_bin_file_str, filerr.message());
- }
-
- // determine total frames
uint64_t total_bytes = 0;
for (int tracknum = 0; tracknum < toc.numtrks; tracknum++)
+ {
+ // determine total frames
total_bytes += toc.tracks[tracknum].frames * (toc.tracks[tracknum].datasize + toc.tracks[tracknum].subsize);
+ // generate output filename for each track
+ std::string new_trackbin_name = *output_bin_file_str;
+
+ if (mode == MODE_GDI && toc.tracks[tracknum].trktype == cdrom_file::CD_TRACK_AUDIO)
+ new_trackbin_name += ".raw";
+ else
+ new_trackbin_name += output_bin_file_ext;
+
+ // variable replacement in output filename
+ const std::regex variables_regex("(%*)(%([+-]?\\d+)?([a-zA-Z]))");
+ std::string::const_iterator new_trackbin_name_itr = new_trackbin_name.begin();
+ std::string::const_iterator new_trackbin_name_end = new_trackbin_name.end();
+ std::string filename_formatted = new_trackbin_name;
+ std::smatch variable_matches;
+ bool found_track_variable = false;
+
+ while (std::regex_search(new_trackbin_name_itr, new_trackbin_name_end, variable_matches, variables_regex))
+ {
+ // full_match will always have one leading %, so if leading_escape has an even number of %s then
+ // we can know that we're working on an unescaped %
+ const std::string leading_escape = variable_matches[1].str();
+ const std::string full_match = variable_matches[2].str();
+ const std::string format_part = variable_matches[3].str();
+ const std::string format_type = variable_matches[4].str();
+
+ if ((leading_escape.size() % 2) == 0)
+ {
+ std::string replacement;
+
+ if (format_type == "t")
+ {
+ // track number
+ if (is_splitbin)
+ {
+ replacement = util::string_format("%" + format_part + "d", tracknum+1);
+ found_track_variable = true;
+ }
+ }
+ else
+ {
+ util::stream_format(std::cout, "Warning: encountered unknown format value '%s', ignoring\n", format_type);
+ }
+
+ if (!replacement.empty())
+ {
+ // replace all instances of encountered full format token
+ size_t index = std::string::npos;
+ while ((index = filename_formatted.find(full_match)) != std::string::npos)
+ filename_formatted.replace(index, full_match.size(), replacement);
+ }
+ }
+
+ new_trackbin_name_itr = variable_matches.suffix().first; // move past match for next loop
+ }
+
+ if (is_splitbin && !found_track_variable)
+ {
+ report_error(1, "A track number variable (%%t) must be specified in the output bin filename when --%s is enabled\n", OPTION_OUTPUT_SPLITBIN);
+ }
+
+ // verify output BIN file doesn't exist
+ check_existing_output_file(params, filename_formatted);
+
+ // display all new filenames to the user
+ if (track_filenames.empty() || filename_formatted != track_filenames.back())
+ util::stream_format(std::cout, "Output Data: %s\n", filename_formatted);
+
+ track_filenames.push_back(filename_formatted);
+ }
+
// GDI must start with the # of tracks
if (mode == MODE_GDI)
{
@@ -2627,49 +2821,118 @@ static void do_extract_cd(parameters_map &params)
output_toc_file->printf("CD_ROM\n\n\n");
}
+ if (cdrom->is_gdrom() && mode == MODE_CUEBIN)
+ {
+ // modify TOC to match Redump cue/bin format as best as possible
+ cdrom_file::toc *trackinfo = (cdrom_file::toc*)&toc;
+
+ // TOSEC GDI-based CHDs have the padframes field set to non-0 where the pregaps for the next track would be
+ const bool has_physical_pregap = trackinfo->tracks[0].padframes == 0;
+
+ for (int tracknum = 1; tracknum < toc.numtrks; tracknum++)
+ {
+ // pgdatasize should never be set in GD-ROMs currently, so if it is set then assume the TOC has proper pregap values
+ if (trackinfo->tracks[tracknum].pgdatasize != 0)
+ break;
+
+ // don't adjust the first track of the single-density and high-density areas
+ if (toc.tracks[tracknum].physframeofs == 45000)
+ continue;
+
+ if (!has_physical_pregap)
+ {
+ // NOTE: This will generate a cue with PREGAP commands instead of INDEX 00 because the pregap data isn't baked into the bins
+ trackinfo->tracks[tracknum].pregap += trackinfo->tracks[tracknum-1].padframes;
+
+ // "type 1" (only one data track in high-density area) and "type 2" (1 data and then the rest of the tracks being audio tracks in high-density area) don't require any adjustments
+ if (tracknum + 1 >= toc.numtrks && toc.tracks[tracknum].trktype != cdrom_file::CD_TRACK_AUDIO)
+ {
+ if (toc.tracks[tracknum-1].trktype != cdrom_file::CD_TRACK_AUDIO)
+ {
+ // "type 3" where the high-density area is just two data tracks
+ // there shouldn't be any pregap in the padframes from the previous track in this case, and the full 3s pregap is baked into the previous track
+ // Only known to be used by Shenmue II JP's discs 2, 3, 4 and Virtua Fighter History & VF4
+ trackinfo->tracks[tracknum-1].padframes += 225;
+
+ trackinfo->tracks[tracknum].pregap += 225;
+ trackinfo->tracks[tracknum].splitframes = 225;
+ trackinfo->tracks[tracknum].pgdatasize = trackinfo->tracks[tracknum].datasize;
+ trackinfo->tracks[tracknum].pgtype = trackinfo->tracks[tracknum].trktype;
+ }
+ else
+ {
+ // "type 3 split" where the first track and last of the high-density area are data tracks and in between is audio tracks
+ // TODO: These 75 frames are actually included at the end of the previous track so should be written
+ // It's currently not possible to format it as expected without hacky code because the 150 pregap for the last track
+ // is sandwiched between these 75 frames and the actual track data.
+ // The 75 frames seems to normally be 0s so this should be ok for now until a use case is found.
+ trackinfo->tracks[tracknum-1].frames -= 75;
+ trackinfo->tracks[tracknum].pregap += 75;
+ }
+ }
+ }
+ else
+ {
+ int curextra = 150; // 00:02:00
+ if (tracknum + 1 >= toc.numtrks && toc.tracks[tracknum].trktype != cdrom_file::CD_TRACK_AUDIO)
+ curextra += 75; // 00:01:00, special case when last track is data
+
+ trackinfo->tracks[tracknum-1].padframes = curextra;
+
+ trackinfo->tracks[tracknum].pregap += curextra;
+ trackinfo->tracks[tracknum].splitframes = curextra;
+ trackinfo->tracks[tracknum].pgdatasize = trackinfo->tracks[tracknum].datasize;
+ trackinfo->tracks[tracknum].pgtype = trackinfo->tracks[tracknum].trktype;
+ }
+ }
+ }
+
// iterate over tracks and copy all data
+ uint64_t totaloutputoffs = 0;
uint64_t outputoffs = 0;
uint32_t discoffs = 0;
std::vector<uint8_t> buffer;
+
for (int tracknum = 0; tracknum < toc.numtrks; tracknum++)
{
- std::string trackbin_name = basename;
-
- if (mode == MODE_GDI)
+ if (track_filenames[tracknum] != trackbin_name)
{
- trackbin_name += util::string_format("%02d", tracknum+1);
- if (toc.tracks[tracknum].trktype == cdrom_file::CD_TRACK_AUDIO)
- trackbin_name += ".raw";
- else
- trackbin_name += ".bin";
+ totaloutputoffs += outputoffs;
+ outputoffs = 0;
+
+ if (mode != MODE_GDI)
+ discoffs = 0;
output_bin_file.reset();
+ trackbin_name = track_filenames[tracknum];
+
filerr = util::core_file::open(trackbin_name, OPEN_FLAG_WRITE | OPEN_FLAG_CREATE, output_bin_file);
if (filerr)
report_error(1, "Unable to open file (%s): %s", trackbin_name, filerr.message());
- outputoffs = 0;
+ output_bin_filenames.push_back(trackbin_name);
}
- // output the metadata about the track to the TOC file
- const cdrom_file::track_info &trackinfo = toc.tracks[tracknum];
- if (mode == MODE_GDI)
+ if (cdrom->is_gdrom() && mode == MODE_CUEBIN)
{
- output_track_metadata(mode, *output_toc_file, tracknum, trackinfo, std::string(core_filename_extract_base(trackbin_name)), discoffs, outputoffs);
- }
- else
- {
- output_track_metadata(mode, *output_toc_file, tracknum, trackinfo, std::string(core_filename_extract_base(*output_bin_file_str)), discoffs, outputoffs);
+ if (tracknum == 0)
+ output_toc_file->printf("REM SINGLE-DENSITY AREA\n");
+ else if (toc.tracks[tracknum].physframeofs == 45000)
+ output_toc_file->printf("REM HIGH-DENSITY AREA\n");
}
+ // output the metadata about the track to the TOC file
+ const cdrom_file::track_info &trackinfo = toc.tracks[tracknum];
+ output_track_metadata(mode, *output_toc_file, tracknum, trackinfo, std::string(core_filename_extract_base(trackbin_name)), discoffs, outputoffs);
+
// If this is bin/cue output and the CHD contains subdata, warn the user and don't include
// the subdata size in the buffer calculation.
uint32_t output_frame_size = trackinfo.datasize + ((trackinfo.subtype != cdrom_file::CD_SUB_NONE) ? trackinfo.subsize : 0);
if (trackinfo.subtype != cdrom_file::CD_SUB_NONE && ((mode == MODE_CUEBIN) || (mode == MODE_GDI)))
{
- printf("Warning: Track %d has subcode data. bin/cue and gdi formats cannot contain subcode data and it will be omitted.\n", tracknum+1);
- printf(" : This may affect usage of the output image. Use bin/toc output to keep all data.\n");
+ util::stream_format(std::cout, "Warning: Track %d has subcode data. bin/cue and gdi formats cannot contain subcode data and it will be omitted.\n", tracknum+1);
+ util::stream_format(std::cout, " : This may affect usage of the output image. Use bin/toc output to keep all data.\n");
output_frame_size = trackinfo.datasize;
}
@@ -2678,40 +2941,52 @@ static void do_extract_cd(parameters_map &params)
// now read and output the actual data
uint32_t bufferoffs = 0;
- uint32_t actualframes = trackinfo.frames - trackinfo.padframes;
+ uint32_t actualframes = trackinfo.frames - trackinfo.padframes + trackinfo.splitframes;
for (uint32_t frame = 0; frame < actualframes; frame++)
{
- progress(false, "Extracting, %.1f%% complete... \r", 100.0 * double(outputoffs) / double(total_bytes));
+ progress(false, "Extracting, %.1f%% complete... \r", 100.0 * double(totaloutputoffs + outputoffs) / double(total_bytes));
+
+ int trk, frameofs;
+ if (tracknum > 0 && frame < trackinfo.splitframes)
+ {
+ // pull data from previous track, the reverse of how splitframes is used when making the GD-ROM CHDs
+ trk = tracknum - 1;
+ frameofs = toc.tracks[trk].frames - trackinfo.splitframes + frame;
+ }
+ else
+ {
+ trk = tracknum;
+ frameofs = frame - trackinfo.splitframes;
+ }
// read the data
- cdrom->read_data(cdrom->get_track_start_phys(tracknum) + frame, &buffer[bufferoffs], trackinfo.trktype, true);
+ cdrom->read_data(cdrom->get_track_start_phys(trk) + frameofs, &buffer[bufferoffs], toc.tracks[trk].trktype, true);
// for CDRWin and GDI audio tracks must be reversed
// in the case of GDI and CHD version < 5 we assuming source CHD image is GDROM so audio tracks is already reversed
- if (((mode == MODE_GDI && input_chd.version() > 4) || (mode == MODE_CUEBIN)) && (trackinfo.trktype == cdrom_file::CD_TRACK_AUDIO))
- for (int swapindex = 0; swapindex < trackinfo.datasize; swapindex += 2)
+ if (((mode == MODE_GDI && input_chd.version() > 4) || (mode == MODE_CUEBIN)) && (toc.tracks[trk].trktype == cdrom_file::CD_TRACK_AUDIO))
+ for (int swapindex = 0; swapindex < toc.tracks[trk].datasize; swapindex += 2)
{
uint8_t swaptemp = buffer[bufferoffs + swapindex];
buffer[bufferoffs + swapindex] = buffer[bufferoffs + swapindex + 1];
buffer[bufferoffs + swapindex + 1] = swaptemp;
}
- bufferoffs += trackinfo.datasize;
+ bufferoffs += toc.tracks[trk].datasize;
discoffs++;
// read the subcode data
- if (trackinfo.subtype != cdrom_file::CD_SUB_NONE && (mode == MODE_NORMAL))
+ if (toc.tracks[trk].subtype != cdrom_file::CD_SUB_NONE && (mode == MODE_NORMAL))
{
- cdrom->read_subcode(cdrom->get_track_start_phys(tracknum) + frame, &buffer[bufferoffs], true);
- bufferoffs += trackinfo.subsize;
+ cdrom->read_subcode(cdrom->get_track_start_phys(trk) + frameofs, &buffer[bufferoffs], true);
+ bufferoffs += toc.tracks[trk].subsize;
}
// write it out if we need to
if (bufferoffs == buffer.size() || frame == actualframes - 1)
{
output_bin_file->seek(outputoffs, SEEK_SET);
- size_t byteswritten;
- std::error_condition const writerr = output_bin_file->write(&buffer[0], bufferoffs, byteswritten);
- if (writerr || (byteswritten != bufferoffs))
+ auto const [writerr, byteswritten] = write(*output_bin_file, &buffer[0], bufferoffs);
+ if (writerr)
report_error(1, "Error writing frame %d to file (%s): %s\n", frame, *output_file_str->second, "Write error");
outputoffs += bufferoffs;
bufferoffs = 0;
@@ -2724,99 +2999,21 @@ static void do_extract_cd(parameters_map &params)
// finish up
output_bin_file.reset();
output_toc_file.reset();
- printf("Extraction complete \n");
+ util::stream_format(std::cout, "Extraction complete \n");
}
catch (...)
{
// delete the output files
output_bin_file.reset();
output_toc_file.reset();
- osd_file::remove(*output_bin_file_str);
+ for (auto const &output_bin_filename : output_bin_filenames)
+ osd_file::remove(output_bin_filename);
osd_file::remove(*output_file_str->second);
throw;
}
}
-//-------------------------------------------------
-// do_extract_dvd - extract a DVD image from a
-// CHD image, currently identical to extractraw
-//-------------------------------------------------
-
-static void do_extract_dvd(parameters_map &params)
-{
- // parse out input files
- chd_file input_parent_chd;
- chd_file input_chd;
- parse_input_chd_parameters(params, input_chd, input_parent_chd);
-
- // parse out input start/end
- uint64_t input_start;
- uint64_t input_end;
- parse_input_start_end(params, input_chd.logical_bytes(), input_chd.hunk_bytes(), input_chd.hunk_bytes(), input_start, input_end);
-
- // verify output file doesn't exist
- auto output_file_str = params.find(OPTION_OUTPUT);
- if (output_file_str != params.end())
- check_existing_output_file(params, output_file_str->second->c_str());
-
- // print some info
- printf("Output File: %s\n", output_file_str->second->c_str());
- printf("Input CHD: %s\n", params.find(OPTION_INPUT)->second->c_str());
- if (input_start != 0 || input_end != input_chd.logical_bytes())
- {
- printf("Input start: %s\n", big_int_string(input_start).c_str());
- printf("Input length: %s\n", big_int_string(input_end - input_start).c_str());
- }
-
- // catch errors so we can close & delete the output file
- util::core_file::ptr output_file;
- try
- {
- // process output file
- 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<uint8_t> buffer((TEMP_BUFFER_SIZE / input_chd.hunk_bytes()) * input_chd.hunk_bytes());
- for (uint64_t offset = input_start; offset < input_end; )
- {
- progress(false, "Extracting, %.1f%% complete... \r", 100.0 * double(offset - input_start) / double(input_end - input_start));
-
- // determine how much to read
- uint32_t bytes_to_read = (std::min<uint64_t>)(buffer.size(), input_end - offset);
- 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
- size_t count;
- std::error_condition const writerr = output_file->write(&buffer[0], bytes_to_read, count);
- if (writerr || (count != bytes_to_read))
- report_error(1, "Error writing to file; check disk space (%s)", *output_file_str->second);
-
- // advance
- offset += bytes_to_read;
- }
-
- // finish up
- output_file.reset();
- printf("Extraction complete \n");
- }
- catch (...)
- {
- // delete the output file
- if (output_file != nullptr)
- {
- output_file.reset();
- osd_file::remove(*output_file_str->second);
- }
- throw;
- }
-}
-
-
//-------------------------------------------------
@@ -2862,9 +3059,7 @@ static void do_extract_ld(parameters_map &params)
report_error(1, "Frame size does not match hunk size for this CHD");
// parse out input start/end
- uint64_t input_start;
- uint64_t input_end;
- parse_input_start_end(params, input_chd.hunk_count() / interlace_factor, 0, 1, input_start, input_end);
+ auto [input_start, input_end] = parse_input_start_end(params, input_chd.hunk_count() / interlace_factor, 0, 1);
input_start *= interlace_factor;
input_end *= interlace_factor;
@@ -2886,15 +3081,15 @@ static void do_extract_ld(parameters_map &params)
// verify output file doesn't exist
auto output_file_str = params.find(OPTION_OUTPUT);
if (output_file_str != params.end())
- check_existing_output_file(params, output_file_str->second->c_str());
+ check_existing_output_file(params, *output_file_str->second);
// print some info
- printf("Output File: %s\n", output_file_str->second->c_str());
- printf("Input CHD: %s\n", params.find(OPTION_INPUT)->second->c_str());
+ util::stream_format(std::cout, "Output File: %s\n", *output_file_str->second);
+ util::stream_format(std::cout, "Input CHD: %s\n", *params.find(OPTION_INPUT)->second);
if (input_start != 0 || input_end != input_chd.hunk_count())
{
- printf("Input start: %s\n", big_int_string(input_start).c_str());
- printf("Input length: %s\n", big_int_string(input_end - input_start).c_str());
+ util::stream_format(std::cout, "Input start: %s\n", big_int_string(input_start));
+ util::stream_format(std::cout, "Input length: %s\n", big_int_string(input_end - input_start));
}
// catch errors so we can close & delete the output file
@@ -2931,7 +3126,7 @@ static void do_extract_ld(parameters_map &params)
input_chd.codec_configure(CHD_CODEC_AVHUFF, AVHUFF_CODEC_DECOMPRESS_CONFIG, &avconfig);
// read the hunk into the buffers
- std::error_condition err = input_chd.read_hunk(framenum, nullptr);
+ std::error_condition err = input_chd.codec_process_hunk(framenum);
if (err)
{
uint64_t filepos = ~uint64_t(0);
@@ -2958,7 +3153,7 @@ static void do_extract_ld(parameters_map &params)
// close and return
output_file.reset();
- printf("Extraction complete \n");
+ util::stream_format(std::cout, "Extraction complete \n");
}
catch (...)
{
@@ -3029,13 +3224,13 @@ static void do_add_metadata(parameters_map &params)
flags &= ~CHD_MDFLAGS_CHECKSUM;
// print some info
- printf("Input file: %s\n", params.find(OPTION_INPUT)->second->c_str());
- printf("Tag: %c%c%c%c\n", (tag >> 24) & 0xff, (tag >> 16) & 0xff, (tag >> 8) & 0xff, tag & 0xff);
- printf("Index: %d\n", index);
+ util::stream_format(std::cout, "Input file: %s\n", *params.find(OPTION_INPUT)->second);
+ util::stream_format(std::cout, "Tag: %c%c%c%c\n", (tag >> 24) & 0xff, (tag >> 16) & 0xff, (tag >> 8) & 0xff, tag & 0xff);
+ util::stream_format(std::cout, "Index: %d\n", index);
if (text_str != params.end())
- printf("Text: %s\n", text.c_str());
+ util::stream_format(std::cout, "Text: %s\n", text);
else
- printf("Data: %s (%d bytes)\n", file_str->second->c_str(), int(file.size()));
+ util::stream_format(std::cout, "Data: %s (%d bytes)\n", *file_str->second, file.size());
// write the metadata
std::error_condition err;
@@ -3046,7 +3241,7 @@ static void do_add_metadata(parameters_map &params)
if (err)
report_error(1, "Error adding metadata: %s", err.message());
else
- printf("Metadata added\n");
+ util::stream_format(std::cout, "Metadata added\n");
}
@@ -3077,16 +3272,16 @@ static void do_del_metadata(parameters_map &params)
index = atoi(index_str->second->c_str());
// print some info
- printf("Input file: %s\n", params.find(OPTION_INPUT)->second->c_str());
- printf("Tag: %c%c%c%c\n", (tag >> 24) & 0xff, (tag >> 16) & 0xff, (tag >> 8) & 0xff, tag & 0xff);
- printf("Index: %d\n", index);
+ util::stream_format(std::cout, "Input file: %s\n", *params.find(OPTION_INPUT)->second);
+ util::stream_format(std::cout, "Tag: %c%c%c%c\n", (tag >> 24) & 0xff, (tag >> 16) & 0xff, (tag >> 8) & 0xff, tag & 0xff);
+ util::stream_format(std::cout, "Index: %d\n", index);
// write the metadata
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");
+ util::stream_format(std::cout, "Metadata removed\n");
}
@@ -3104,7 +3299,7 @@ static void do_dump_metadata(parameters_map &params)
// verify output file doesn't exist
auto output_file_str = params.find(OPTION_OUTPUT);
if (output_file_str != params.end())
- check_existing_output_file(params, output_file_str->second->c_str());
+ check_existing_output_file(params, *output_file_str->second);
// process tag
chd_metadata_tag tag = CHD_MAKE_TAG('?','?','?','?');
@@ -3142,15 +3337,15 @@ static void do_dump_metadata(parameters_map &params)
// output the metadata
size_t count;
- filerr = output_file->write(&buffer[0], buffer.size(), count);
+ std::tie(filerr, count) = write(*output_file, &buffer[0], buffer.size());
if (!filerr)
filerr = output_file->flush();
- if (filerr || (count != buffer.size()))
+ if (filerr)
report_error(1, "Error writing file (%s)", *output_file_str->second);
output_file.reset();
// provide some feedback
- printf("File (%s) written, %s bytes\n", output_file_str->second->c_str(), big_int_string(buffer.size()).c_str());
+ util::stream_format(std::cout, "File (%s) written, %s bytes\n", *output_file_str->second, big_int_string(buffer.size()));
}
else
{
@@ -3176,13 +3371,13 @@ static void do_dump_metadata(parameters_map &params)
static void do_list_templates(parameters_map &params)
{
- printf("\n");
- printf("ID Manufacturer Model Cylinders Heads Sectors Sector Size Total Size\n");
- printf("------------------------------------------------------------------------------------\n");
+ util::stream_format(std::cout, "\n");
+ util::stream_format(std::cout, "ID Manufacturer Model Cylinders Heads Sectors Sector Size Total Size\n");
+ util::stream_format(std::cout, "------------------------------------------------------------------------------------\n");
for (int id = 0; id < std::size(s_hd_templates); id++)
{
- printf("%2d %-13s %-15s %9d %5d %7d %11d %7d MB\n",
+ util::stream_format(std::cout, "%2d %-13s %-15s %9d %5d %7d %11d %7d MB\n",
id,
s_hd_templates[id].manufacturer,
s_hd_templates[id].model,
@@ -3203,10 +3398,11 @@ static void do_list_templates(parameters_map &params)
int CLIB_DECL main(int argc, char *argv[])
{
const std::vector<std::string> args = osd_get_command_line(argc, argv);
+ chdman_osd_output osdoutput;
// print the header
extern const char build_version[];
- printf("chdman - MAME Compressed Hunks of Data (CHD) manager %s\n", build_version);
+ util::stream_format(std::cout, "chdman - MAME Compressed Hunks of Data (CHD) manager %s\n", build_version);
// handle help specially
if (args.size() < 2)
@@ -3223,6 +3419,7 @@ int CLIB_DECL main(int argc, char *argv[])
// iterate over commands to find our match
for (auto & s_command : s_commands)
+ {
if (command == s_command.name)
{
const command_description &desc = s_command;
@@ -3242,12 +3439,10 @@ int CLIB_DECL main(int argc, char *argv[])
// iterate over valid options
int valid;
- for (valid = 0; valid < std::size(desc.valid_options); valid++)
+ for (valid = 0; (valid < std::size(desc.valid_options)) && desc.valid_options[valid]; valid++)
{
// reduce to the option name
const char *validname = desc.valid_options[valid];
- if (validname == nullptr)
- break;
if (*validname == REQUIRED[0])
validname++;
@@ -3280,8 +3475,8 @@ int CLIB_DECL main(int argc, char *argv[])
}
// if not valid, error
- if (valid == std::size(desc.valid_options))
- return print_help(args[0], desc, "Option not valid for this command");
+ if ((valid == std::size(desc.valid_options)) || !desc.valid_options[valid])
+ return print_help(args[0], desc, string_format("Option '%s' not valid for this command", arg).c_str());
}
// make sure we got all our required parameters
@@ -3302,20 +3497,21 @@ int CLIB_DECL main(int argc, char *argv[])
}
catch (std::error_condition const &err)
{
- fprintf(stderr, "CHD error occurred (main): %s\n", err.message().c_str());
+ util::stream_format(std::cerr, "CHD error occurred (main): %s\n", err.message());
return 1;
}
catch (fatal_error &err)
{
- fprintf(stderr, "Fatal error occurred: %d\n", err.error());
+ util::stream_format(std::cerr, "Fatal error occurred: %d\n", err.error());
return err.error();
}
catch (std::exception& ex)
{
- fprintf(stderr, "Unhandled exception: %s\n", ex.what());
+ util::stream_format(std::cerr, "Unhandled exception: %s\n", ex.what());
return 1;
}
}
+ }
// print generic help if nothing found
return print_help(args[0]);
diff --git a/src/tools/floptool.cpp b/src/tools/floptool.cpp
index ba573e0a0cd..9ac9c3231ae 100644
--- a/src/tools/floptool.cpp
+++ b/src/tools/floptool.cpp
@@ -302,7 +302,7 @@ static void dir_scan(fs::filesystem_t *fs, u32 depth, const std::vector<std::str
head += " ";
auto [err, contents] = fs->directory_contents(path);
if(err)
- return;
+ return; // FIXME: don't swallow errors
for(const auto &c : contents) {
size_t id = entries.size();
entries.resize(id+1);
@@ -472,10 +472,7 @@ static int generic_read(image_handler &ih, const char *srcpath, const char *dstp
std::vector<std::string> path = ih.path_split(srcpath);
auto [err, dfork] = fs->file_read(path);
if(err) {
- if(err == fs::ERR_NOT_FOUND)
- fprintf(stderr, "File not found.\n");
- else
- fprintf(stderr, "Unknown error (%d).\n", err);
+ fprintf(stderr, "File reading failed: %s\n", err.message().c_str());
return 1;
}
@@ -568,14 +565,14 @@ static int generic_write(image_handler &ih, const char *srcpath, const char *dst
auto [err, meta] = fs->metadata(path);
std::ignore = meta;
- if(err) {
+ if(err == fs::error::not_found) {
fs::meta_data meta;
meta.set(fs::meta_name::name, path.back());
auto dpath = path;
dpath.pop_back();
err = fs->file_create(dpath, meta);
if(err) {
- fprintf(stderr, "File creation failure.\n");
+ fprintf(stderr, "File creation failed: %s\n", err.message().c_str());
return 1;
}
}
@@ -583,7 +580,7 @@ static int generic_write(image_handler &ih, const char *srcpath, const char *dst
auto dfork = image_handler::fload(srcpath);
err = fs->file_write(path, dfork);
if(err) {
- fprintf(stderr, "File writing failure.\n");
+ fprintf(stderr, "File writing failed: %s\n", err.message().c_str());
return 1;
}
@@ -594,7 +591,7 @@ static int generic_write(image_handler &ih, const char *srcpath, const char *dst
auto rfork = image_handler::fload_rsrc(rpath);
if(!rfork.empty()) {
err = fs->file_rsrc_write(path, rfork);
- fprintf(stderr, "File resource fork writing failure.\n");
+ fprintf(stderr, "File resource fork writing failed: %s\n", err.message().c_str());
return 1;
}
}
@@ -725,7 +722,7 @@ int CLIB_DECL main(int argc, char *argv[])
return 1;
}
} catch(const std::exception &err) {
- fprintf(stderr, "Error: %s", err.what());
+ fprintf(stderr, "Error: %s\n", err.what());
return 1;
}
}
diff --git a/src/tools/image_handler.cpp b/src/tools/image_handler.cpp
index 60ab72e61f8..14976516e1c 100644
--- a/src/tools/image_handler.cpp
+++ b/src/tools/image_handler.cpp
@@ -15,6 +15,8 @@
#include "multibyte.h"
#include "strformat.h"
+#include <algorithm>
+
// Format enumeration
@@ -43,7 +45,7 @@ namespace {
struct fs_enum : public fs::manager_t::floppy_enumerator {
filesystem_format *m_format;
- fs_enum(filesystem_format *format, const std::vector<u32> &variants) : fs::manager_t::floppy_enumerator(floppy_image::FF_UNKNOWN, variants), m_format(format) {}
+ fs_enum(filesystem_format *format, u32 form_factor, const std::vector<u32> &variants) : fs::manager_t::floppy_enumerator(form_factor, variants), m_format(format) {}
virtual void add_format(const floppy_image_format_t &type, u32 image_size, const char *name, const char *description) override {
m_format->m_floppy = true;
@@ -65,7 +67,7 @@ void formats_table::init()
mame_formats_full_list(en);
for(auto &f : filesystem_formats) {
- fs_enum fen(f.get(), variants);
+ fs_enum fen(f.get(), floppy_image::FF_UNKNOWN, variants);
f->m_manager->enumerate_f(fen);
}
@@ -244,6 +246,9 @@ std::vector<std::pair<u8, const floppy_format_info *>> image_handler::identify(c
res.emplace_back(std::make_pair(score, e.second));
}
+ // Sort results by decreasing score
+ std::stable_sort(res.begin(), res.end(), [](const auto &a, const auto &b) { return a.first > b.first; });
+
return res;
}
@@ -295,8 +300,14 @@ void image_handler::floppy_create(const floppy_create_info &format, fs::meta_dat
bool image_handler::floppy_mount_fs(const filesystem_format &format)
{
+ // Create a restricted copy of the format list based on the known form factor and variant
+ filesystem_format fmtcopy(format.m_manager, format.m_category);
+ std::vector<u32> const var(1, m_floppy_image.get_variant());
+ fs_enum fen(&fmtcopy, m_floppy_image.get_form_factor(), var);
+ format.m_manager->enumerate_f(fen);
+
m_floppy_fs_converter = nullptr;
- for(const auto &ci : format.m_floppy_create) {
+ for(const auto &ci : fmtcopy.m_floppy_create) {
if(ci->m_type != m_floppy_fs_converter) {
std::vector<uint32_t> variants;
m_floppy_fs_converter = ci->m_type;
diff --git a/src/tools/imgtool/filtbas.cpp b/src/tools/imgtool/filtbas.cpp
index 8a84811540d..f4098202c32 100644
--- a/src/tools/imgtool/filtbas.cpp
+++ b/src/tools/imgtool/filtbas.cpp
@@ -32,7 +32,7 @@
CONSTANTS
***************************************************************************/
-#define EOLN (CRLF == 1 ? "\r" : (CRLF == 2 ? "\n" : (CRLF == 3 ? "\r\n" : NULL)))
+#define EOLN (CRLF == 1 ? "\r" : (CRLF == 2 ? "\n" : (CRLF == 3 ? "\r\n" : nullptr)))
@@ -1033,58 +1033,58 @@ static const char *const basic_10[] = /* "BASIC 1.0" - supported by pet */
"LEFT$", /* 0xc8 */
"RIGHT$", /* 0xc9 */
"MID$", /* 0xca */
- NULL, /* 0xcb */
- NULL, /* 0xcc */
- NULL, /* 0xcd */
- NULL, /* 0xce */
- NULL, /* 0xcf */
- NULL, /* 0xd0 */
- NULL, /* 0xd1 */
- NULL, /* 0xd2 */
- NULL, /* 0xd3 */
- NULL, /* 0xd4 */
- NULL, /* 0xd5 */
- NULL, /* 0xd6 */
- NULL, /* 0xd7 */
- NULL, /* 0xd8 */
- NULL, /* 0xd9 */
- NULL, /* 0xda */
- NULL, /* 0xdb */
- NULL, /* 0xdc */
- NULL, /* 0xdd */
- NULL, /* 0xde */
- NULL, /* 0xdf */
- NULL, /* 0xe0 */
- NULL, /* 0xe1 */
- NULL, /* 0xe2 */
- NULL, /* 0xe3 */
- NULL, /* 0xe4 */
- NULL, /* 0xe5 */
- NULL, /* 0xe6 */
- NULL, /* 0xe7 */
- NULL, /* 0xe8 */
- NULL, /* 0xe9 */
- NULL, /* 0xea */
- NULL, /* 0xeb */
- NULL, /* 0xec */
- NULL, /* 0xed */
- NULL, /* 0xee */
- NULL, /* 0xef */
- NULL, /* 0xf0 */
- NULL, /* 0xf1 */
- NULL, /* 0xf2 */
- NULL, /* 0xf3 */
- NULL, /* 0xf4 */
- NULL, /* 0xf5 */
- NULL, /* 0xf6 */
- NULL, /* 0xf7 */
- NULL, /* 0xf8 */
- NULL, /* 0xf9 */
- NULL, /* 0xfa */
- NULL, /* 0xfb */
- NULL, /* 0xfc */
- NULL, /* 0xfd */
- NULL, /* 0xfe */
+ nullptr, /* 0xcb */
+ nullptr, /* 0xcc */
+ nullptr, /* 0xcd */
+ nullptr, /* 0xce */
+ nullptr, /* 0xcf */
+ nullptr, /* 0xd0 */
+ nullptr, /* 0xd1 */
+ nullptr, /* 0xd2 */
+ nullptr, /* 0xd3 */
+ nullptr, /* 0xd4 */
+ nullptr, /* 0xd5 */
+ nullptr, /* 0xd6 */
+ nullptr, /* 0xd7 */
+ nullptr, /* 0xd8 */
+ nullptr, /* 0xd9 */
+ nullptr, /* 0xda */
+ nullptr, /* 0xdb */
+ nullptr, /* 0xdc */
+ nullptr, /* 0xdd */
+ nullptr, /* 0xde */
+ nullptr, /* 0xdf */
+ nullptr, /* 0xe0 */
+ nullptr, /* 0xe1 */
+ nullptr, /* 0xe2 */
+ nullptr, /* 0xe3 */
+ nullptr, /* 0xe4 */
+ nullptr, /* 0xe5 */
+ nullptr, /* 0xe6 */
+ nullptr, /* 0xe7 */
+ nullptr, /* 0xe8 */
+ nullptr, /* 0xe9 */
+ nullptr, /* 0xea */
+ nullptr, /* 0xeb */
+ nullptr, /* 0xec */
+ nullptr, /* 0xed */
+ nullptr, /* 0xee */
+ nullptr, /* 0xef */
+ nullptr, /* 0xf0 */
+ nullptr, /* 0xf1 */
+ nullptr, /* 0xf2 */
+ nullptr, /* 0xf3 */
+ nullptr, /* 0xf4 */
+ nullptr, /* 0xf5 */
+ nullptr, /* 0xf6 */
+ nullptr, /* 0xf7 */
+ nullptr, /* 0xf8 */
+ nullptr, /* 0xf9 */
+ nullptr, /* 0xfa */
+ nullptr, /* 0xfb */
+ nullptr, /* 0xfc */
+ nullptr, /* 0xfd */
+ nullptr, /* 0xfe */
"{PI}" /* 0xff - A single character shaped as greek lowercase 'PI' */
};
@@ -1166,57 +1166,57 @@ static const char *const basic_20[] = /* "BASIC 2.0" - supported by vic20 & clon
"RIGHT$", /* 0xc9 */
"MID$", /* 0xca */
"GO", /* 0xcb */
- NULL, /* 0xcc */
- NULL, /* 0xcd */
- NULL, /* 0xce */
- NULL, /* 0xcf */
- NULL, /* 0xd0 */
- NULL, /* 0xd1 */
- NULL, /* 0xd2 */
- NULL, /* 0xd3 */
- NULL, /* 0xd4 */
- NULL, /* 0xd5 */
- NULL, /* 0xd6 */
- NULL, /* 0xd7 */
- NULL, /* 0xd8 */
- NULL, /* 0xd9 */
- NULL, /* 0xda */
- NULL, /* 0xdb */
- NULL, /* 0xdc */
- NULL, /* 0xdd */
- NULL, /* 0xde */
- NULL, /* 0xdf */
- NULL, /* 0xe0 */
- NULL, /* 0xe1 */
- NULL, /* 0xe2 */
- NULL, /* 0xe3 */
- NULL, /* 0xe4 */
- NULL, /* 0xe5 */
- NULL, /* 0xe6 */
- NULL, /* 0xe7 */
- NULL, /* 0xe8 */
- NULL, /* 0xe9 */
- NULL, /* 0xea */
- NULL, /* 0xeb */
- NULL, /* 0xec */
- NULL, /* 0xed */
- NULL, /* 0xee */
- NULL, /* 0xef */
- NULL, /* 0xf0 */
- NULL, /* 0xf1 */
- NULL, /* 0xf2 */
- NULL, /* 0xf3 */
- NULL, /* 0xf4 */
- NULL, /* 0xf5 */
- NULL, /* 0xf6 */
- NULL, /* 0xf7 */
- NULL, /* 0xf8 */
- NULL, /* 0xf9 */
- NULL, /* 0xfa */
- NULL, /* 0xfb */
- NULL, /* 0xfc */
- NULL, /* 0xfd */
- NULL, /* 0xfe */
+ nullptr, /* 0xcc */
+ nullptr, /* 0xcd */
+ nullptr, /* 0xce */
+ nullptr, /* 0xcf */
+ nullptr, /* 0xd0 */
+ nullptr, /* 0xd1 */
+ nullptr, /* 0xd2 */
+ nullptr, /* 0xd3 */
+ nullptr, /* 0xd4 */
+ nullptr, /* 0xd5 */
+ nullptr, /* 0xd6 */
+ nullptr, /* 0xd7 */
+ nullptr, /* 0xd8 */
+ nullptr, /* 0xd9 */
+ nullptr, /* 0xda */
+ nullptr, /* 0xdb */
+ nullptr, /* 0xdc */
+ nullptr, /* 0xdd */
+ nullptr, /* 0xde */
+ nullptr, /* 0xdf */
+ nullptr, /* 0xe0 */
+ nullptr, /* 0xe1 */
+ nullptr, /* 0xe2 */
+ nullptr, /* 0xe3 */
+ nullptr, /* 0xe4 */
+ nullptr, /* 0xe5 */
+ nullptr, /* 0xe6 */
+ nullptr, /* 0xe7 */
+ nullptr, /* 0xe8 */
+ nullptr, /* 0xe9 */
+ nullptr, /* 0xea */
+ nullptr, /* 0xeb */
+ nullptr, /* 0xec */
+ nullptr, /* 0xed */
+ nullptr, /* 0xee */
+ nullptr, /* 0xef */
+ nullptr, /* 0xf0 */
+ nullptr, /* 0xf1 */
+ nullptr, /* 0xf2 */
+ nullptr, /* 0xf3 */
+ nullptr, /* 0xf4 */
+ nullptr, /* 0xf5 */
+ nullptr, /* 0xf6 */
+ nullptr, /* 0xf7 */
+ nullptr, /* 0xf8 */
+ nullptr, /* 0xf9 */
+ nullptr, /* 0xfa */
+ nullptr, /* 0xfb */
+ nullptr, /* 0xfc */
+ nullptr, /* 0xfd */
+ nullptr, /* 0xfe */
"{PI}" /* 0xff - A single character shaped as greek lowercase 'PI' */
};
@@ -2971,7 +2971,7 @@ static imgtoolerr_t cocobas_writefile(imgtool::partition &partition, const char
return basic_writefile(&cocobas_tokens, partition, filename, fork, sourcef, opts);
}
-void filter_cocobas_getinfo(uint32_t state, union filterinfo *info)
+void filter_cocobas_getinfo(uint32_t state, imgtool::filterinfo *info)
{
switch(state)
{
@@ -3017,7 +3017,7 @@ static imgtoolerr_t dragonbas_writefile(imgtool::partition &partition, const cha
return basic_writefile(&dragonbas_tokens, partition, filename, fork, sourcef, opts);
}
-void filter_dragonbas_getinfo(uint32_t state, union filterinfo *info)
+void filter_dragonbas_getinfo(uint32_t state, imgtool::filterinfo *info)
{
switch(state)
{
@@ -3064,7 +3064,7 @@ static imgtoolerr_t vzbas_writefile(imgtool::partition &partition, const char *f
return basic_writefile(&vzbas_tokens, partition, filename, fork, sourcef, opts);
}
-void filter_vzbas_getinfo(uint32_t state, union filterinfo *info)
+void filter_vzbas_getinfo(uint32_t state, imgtool::filterinfo *info)
{
switch(state)
{
@@ -3110,7 +3110,7 @@ static imgtoolerr_t bml3bas_writefile(imgtool::partition &partition, const char
return basic_writefile(&bml3bas_tokens, partition, filename, fork, sourcef, opts);
}
-void filter_bml3bas_getinfo(uint32_t state, union filterinfo *info)
+void filter_bml3bas_getinfo(uint32_t state, imgtool::filterinfo *info)
{
switch(state)
{
diff --git a/src/tools/imgtool/filteoln.cpp b/src/tools/imgtool/filteoln.cpp
index 6d80e9b2180..41f11769747 100644
--- a/src/tools/imgtool/filteoln.cpp
+++ b/src/tools/imgtool/filteoln.cpp
@@ -13,7 +13,7 @@
#include <cstring>
-#define EOLN (CRLF == 1 ? "\r" : (CRLF == 2 ? "\n" : (CRLF == 3 ? "\r\n" : NULL)))
+#define EOLN (CRLF == 1 ? "\r" : (CRLF == 2 ? "\n" : (CRLF == 3 ? "\r\n" : nullptr)))
@@ -96,7 +96,7 @@ static imgtoolerr_t ascii_writefile(imgtool::partition &partition, const char *f
-void filter_eoln_getinfo(uint32_t state, union filterinfo *info)
+void filter_eoln_getinfo(uint32_t state, imgtool::filterinfo *info)
{
switch(state)
{
diff --git a/src/tools/imgtool/filter.cpp b/src/tools/imgtool/filter.cpp
index 9ecffb19845..9df7c3c1692 100644
--- a/src/tools/imgtool/filter.cpp
+++ b/src/tools/imgtool/filter.cpp
@@ -14,33 +14,33 @@
/* ----------------------------------------------------------------------- */
-int64_t filter_get_info_int(filter_getinfoproc get_info, uint32_t state)
+int64_t filter_get_info_int(imgtool::filter_getinfoproc get_info, uint32_t state)
{
- union filterinfo info;
+ imgtool::filterinfo info;
info.i = 0;
get_info(state, &info);
return info.i;
}
-void *filter_get_info_ptr(filter_getinfoproc get_info, uint32_t state)
+void *filter_get_info_ptr(imgtool::filter_getinfoproc get_info, uint32_t state)
{
- union filterinfo info;
+ imgtool::filterinfo info;
info.p = nullptr;
get_info(state, &info);
return info.p;
}
-void *filter_get_info_fct(filter_getinfoproc get_info, uint32_t state)
+void *filter_get_info_fct(imgtool::filter_getinfoproc get_info, uint32_t state)
{
- union filterinfo info;
+ imgtool::filterinfo info;
info.f = nullptr;
get_info(state, &info);
return info.f;
}
-const char *filter_get_info_string(filter_getinfoproc get_info, uint32_t state)
+const char *filter_get_info_string(imgtool::filter_getinfoproc get_info, uint32_t state)
{
- union filterinfo info;
+ imgtool::filterinfo info;
info.s = nullptr;
get_info(state, &info);
return info.s;
@@ -48,7 +48,7 @@ const char *filter_get_info_string(filter_getinfoproc get_info, uint32_t state)
/* ----------------------------------------------------------------------- */
-const filter_getinfoproc filters[] =
+const imgtool::filter_getinfoproc filters[] =
{
filter_eoln_getinfo,
filter_cocobas_getinfo,
@@ -66,14 +66,11 @@ const filter_getinfoproc filters[] =
-filter_getinfoproc filter_lookup(const char *name)
+imgtool::filter_getinfoproc filter_lookup(const char *name)
{
- int i;
- const char *filter_name;
-
- for (i = 0; filters[i]; i++)
+ for (int i = 0; filters[i]; i++)
{
- filter_name = filter_get_info_string(filters[i], FILTINFO_STR_NAME);
+ char const *const filter_name = filter_get_info_string(filters[i], FILTINFO_STR_NAME);
if (!strcmp(name, filter_name))
return filters[i];
}
diff --git a/src/tools/imgtool/filter.h b/src/tools/imgtool/filter.h
index 75c131906d0..0b9b1f14884 100644
--- a/src/tools/imgtool/filter.h
+++ b/src/tools/imgtool/filter.h
@@ -8,8 +8,10 @@
***************************************************************************/
-#ifndef FILTER_H
-#define FILTER_H
+#ifndef MAME_TOOLS_IMGTOOL_FILTER_H
+#define MAME_TOOLS_IMGTOOL_FILTER_H
+
+#pragma once
#include "library.h"
@@ -34,30 +36,30 @@ enum
FILTINFO_STR_EXTENSION
};
-extern const filter_getinfoproc filters[];
+extern const imgtool::filter_getinfoproc filters[];
-filter_getinfoproc filter_lookup(const char *name);
+imgtool::filter_getinfoproc filter_lookup(const char *name);
/* ----------------------------------------------------------------------- */
-int64_t filter_get_info_int(filter_getinfoproc get_info, uint32_t state);
-void *filter_get_info_ptr(filter_getinfoproc get_info, uint32_t state);
-void *filter_get_info_fct(filter_getinfoproc get_info, uint32_t state);
-const char *filter_get_info_string(filter_getinfoproc get_info, uint32_t state);
+int64_t filter_get_info_int(imgtool::filter_getinfoproc get_info, uint32_t state);
+void *filter_get_info_ptr(imgtool::filter_getinfoproc get_info, uint32_t state);
+void *filter_get_info_fct(imgtool::filter_getinfoproc get_info, uint32_t state);
+const char *filter_get_info_string(imgtool::filter_getinfoproc get_info, uint32_t state);
/* ----------------------------------------------------------------------- */
-extern void filter_eoln_getinfo(uint32_t state, union filterinfo *info);
-extern void filter_cocobas_getinfo(uint32_t state, union filterinfo *info);
-extern void filter_dragonbas_getinfo(uint32_t state, union filterinfo *info);
-extern void filter_macbinary_getinfo(uint32_t state, union filterinfo *info);
-extern void filter_vzsnapshot_getinfo(uint32_t state, union filterinfo *info);
-extern void filter_vzbas_getinfo(uint32_t state, union filterinfo *info);
-extern void filter_thombas5_getinfo(uint32_t state, union filterinfo *info);
-extern void filter_thombas7_getinfo(uint32_t state, union filterinfo *info);
-extern void filter_thombas128_getinfo(uint32_t state, union filterinfo *info);
-extern void filter_thomcrypt_getinfo(uint32_t state, union filterinfo *info);
-extern void filter_bml3bas_getinfo(uint32_t state, union filterinfo *info);
-extern void filter_hp9845data_getinfo(uint32_t state, union filterinfo *info);
-
-#endif /* FILTER_H */
+extern void filter_eoln_getinfo(uint32_t state, imgtool::filterinfo *info);
+extern void filter_cocobas_getinfo(uint32_t state, imgtool::filterinfo *info);
+extern void filter_dragonbas_getinfo(uint32_t state, imgtool::filterinfo *info);
+extern void filter_macbinary_getinfo(uint32_t state, imgtool::filterinfo *info);
+extern void filter_vzsnapshot_getinfo(uint32_t state, imgtool::filterinfo *info);
+extern void filter_vzbas_getinfo(uint32_t state, imgtool::filterinfo *info);
+extern void filter_thombas5_getinfo(uint32_t state, imgtool::filterinfo *info);
+extern void filter_thombas7_getinfo(uint32_t state, imgtool::filterinfo *info);
+extern void filter_thombas128_getinfo(uint32_t state, imgtool::filterinfo *info);
+extern void filter_thomcrypt_getinfo(uint32_t state, imgtool::filterinfo *info);
+extern void filter_bml3bas_getinfo(uint32_t state, imgtool::filterinfo *info);
+extern void filter_hp9845data_getinfo(uint32_t state, imgtool::filterinfo *info);
+
+#endif // MAME_TOOLS_IMGTOOL_FILTER_H
diff --git a/src/tools/imgtool/imgtool.cpp b/src/tools/imgtool/imgtool.cpp
index 6a3fe511fd2..e10558dcce1 100644
--- a/src/tools/imgtool/imgtool.cpp
+++ b/src/tools/imgtool/imgtool.cpp
@@ -260,45 +260,39 @@ void imgtool_warn(const char *format, ...)
static imgtoolerr_t evaluate_module(const char *fname, const imgtool_module *module, float &result)
{
imgtoolerr_t err;
- imgtool::image::ptr image;
- imgtool::partition::ptr partition;
- imgtool::directory::ptr imageenum;
- imgtool_dirent ent;
- float current_result;
result = 0.0;
+ imgtool::image::ptr image;
err = imgtool::image::open(module, fname, OSD_FOPEN_READ, image);
- if (err)
- goto done;
-
- if (image)
+ if (!err && image)
{
- current_result = module->open_is_strict ? 0.9 : 0.5;
-
+ imgtool::partition::ptr partition;
+ imgtool::directory::ptr imageenum;
err = imgtool::partition::open(*image, 0, partition);
- if (err)
- goto done;
+ if (!err)
+ err = imgtool::directory::open(*partition, "", imageenum);
- err = imgtool::directory::open(*partition, "", imageenum);
- if (err)
- goto done;
-
- memset(&ent, 0, sizeof(ent));
- do
+ if (!err)
{
- err = imageenum->get_next(ent);
- if (err)
- goto done;
+ float current_result = module->open_is_strict ? 0.9 : 0.5;
- if (ent.corrupt)
- current_result = (current_result * 99 + 1.00f) / 100;
- else
- current_result = (current_result + 1.00f) / 2;
- }
- while(!ent.eof);
+ imgtool_dirent ent;
+ do
+ {
+ err = imageenum->get_next(ent);
+ if (err)
+ goto done;
- result = current_result;
+ if (ent.corrupt)
+ current_result = (current_result * 99 + 1.00f) / 100;
+ else
+ current_result = (current_result + 1.00f) / 2;
+ }
+ while (!ent.eof);
+
+ result = current_result;
+ }
}
done:
@@ -589,8 +583,8 @@ imgtool::partition::partition(imgtool::image &image, const imgtool_class &imgcla
m_set_attrs = (imgtoolerr_t(*)(imgtool::partition &, const char *, const uint32_t *, const imgtool_attribute *)) imgtool_get_info_fct(&imgclass, IMGTOOLINFO_PTR_SET_ATTRS);
m_attr_name = (imgtoolerr_t(*)(uint32_t, const imgtool_attribute *, char *, size_t)) imgtool_get_info_fct(&imgclass, IMGTOOLINFO_PTR_ATTR_NAME);
m_get_iconinfo = (imgtoolerr_t(*)(imgtool::partition &, const char *, imgtool_iconinfo *)) imgtool_get_info_fct(&imgclass, IMGTOOLINFO_PTR_GET_ICON_INFO);
- m_suggest_transfer = (imgtoolerr_t(*)(imgtool::partition &, const char *, imgtool_transfer_suggestion *, size_t)) imgtool_get_info_fct(&imgclass, IMGTOOLINFO_PTR_SUGGEST_TRANSFER);
- m_get_chain = (imgtoolerr_t(*)(imgtool::partition &, const char *, imgtool_chainent *, size_t)) imgtool_get_info_fct(&imgclass, IMGTOOLINFO_PTR_GET_CHAIN);
+ m_suggest_transfer = (imgtoolerr_t(*)(imgtool::partition &, const char *, imgtool::transfer_suggestion *, size_t)) imgtool_get_info_fct(&imgclass, IMGTOOLINFO_PTR_SUGGEST_TRANSFER);
+ m_get_chain = (imgtoolerr_t(*)(imgtool::partition &, const char *, imgtool::chainent *, size_t)) imgtool_get_info_fct(&imgclass, IMGTOOLINFO_PTR_GET_CHAIN);
m_writefile_optguide = (const util::option_guide *) imgtool_get_info_ptr(&imgclass, IMGTOOLINFO_PTR_WRITEFILE_OPTGUIDE);
const char *writefile_optspec = (const char *)imgtool_get_info_ptr(&imgclass, IMGTOOLINFO_STR_WRITEFILE_OPTSPEC);
@@ -1293,37 +1287,31 @@ done:
imgtoolerr_t imgtool::partition::get_file_size(const char *fname, uint64_t &filesize)
{
imgtoolerr_t err;
- imgtool::directory::ptr imgenum;
- imgtool_dirent ent;
- const char *path;
- path = nullptr; /* TODO: Need to parse off the path */
-
- filesize = ~((uint64_t) 0);
- memset(&ent, 0, sizeof(ent));
+ filesize = ~uint64_t(0);
+ imgtool::directory::ptr imgenum;
+ const char *path = nullptr; // TODO: Need to parse off the path
err = imgtool::directory::open(*this, path, imgenum);
if (err)
- goto done;
+ return err;
+ imgtool_dirent ent;
do
{
err = imgenum->get_next(ent);
if (err)
- goto done;
+ return err;
if (!core_stricmp(fname, ent.filename))
{
filesize = ent.filesize;
- goto done;
+ return err;
}
}
while(ent.filename[0]);
- err = (imgtoolerr_t)IMGTOOLERR_FILENOTFOUND;
-
-done:
- return err;
+ return (imgtoolerr_t)IMGTOOLERR_FILENOTFOUND;
}
@@ -1466,12 +1454,10 @@ imgtoolerr_t imgtool::partition::get_icon_info(const char *path, imgtool_iconinf
//-------------------------------------------------
imgtoolerr_t imgtool::partition::suggest_file_filters(const char *path,
- imgtool::stream *stream, imgtool_transfer_suggestion *suggestions, size_t suggestions_length)
+ imgtool::stream *stream, imgtool::transfer_suggestion *suggestions, size_t suggestions_length)
{
imgtoolerr_t err;
- int i, j;
- imgtoolerr_t (*check_stream)(imgtool::stream &stream, imgtool_suggestion_viability_t *viability);
- size_t position;
+ imgtoolerr_t (*check_stream)(imgtool::stream &stream, imgtool::suggestion_viability_t *viability);
// clear out buffer
memset(suggestions, 0, sizeof(*suggestions) * suggestions_length);
@@ -1493,15 +1479,15 @@ imgtoolerr_t imgtool::partition::suggest_file_filters(const char *path,
// loop on resulting suggestions, and do the following:
// 1. Call check_stream if present, and remove disqualified streams
// 2. Fill in missing descriptions
- i = j = 0;
+ int i = 0, j = 0;
while(suggestions[i].viability)
{
if (stream && suggestions[i].filter)
{
- check_stream = (imgtoolerr_t (*)(imgtool::stream &, imgtool_suggestion_viability_t *)) filter_get_info_fct(suggestions[i].filter, FILTINFO_PTR_CHECKSTREAM);
+ check_stream = (imgtoolerr_t (*)(imgtool::stream &, imgtool::suggestion_viability_t *)) filter_get_info_fct(suggestions[i].filter, FILTINFO_PTR_CHECKSTREAM);
if (check_stream)
{
- position = stream->tell();
+ size_t const position = stream->tell();
err = check_stream(*stream, &suggestions[i].viability);
stream->seek(position, SEEK_SET);
if (err)
@@ -1529,7 +1515,7 @@ imgtoolerr_t imgtool::partition::suggest_file_filters(const char *path,
}
i++;
}
- suggestions[j].viability = (imgtool_suggestion_viability_t)0;
+ suggestions[j].viability = (imgtool::suggestion_viability_t)0;
return IMGTOOLERR_SUCCESS;
}
@@ -1540,17 +1526,15 @@ imgtoolerr_t imgtool::partition::suggest_file_filters(const char *path,
// chain for a file or directory on a partition
//-------------------------------------------------
-imgtoolerr_t imgtool::partition::get_chain(const char *path, imgtool_chainent *chain, size_t chain_size)
+imgtoolerr_t imgtool::partition::get_chain(const char *path, imgtool::chainent *chain, size_t chain_size)
{
- size_t i;
-
assert(chain_size > 0);
if (!m_get_chain)
return imgtoolerr_t(IMGTOOLERR_UNIMPLEMENTED | IMGTOOLERR_SRC_FUNCTIONALITY);
// initialize the chain array, so the module's get_chain function can be lazy
- for (i = 0; i < chain_size; i++)
+ for (int i = 0; i < chain_size; i++)
{
chain[i].level = 0;
chain[i].block = ~0;
@@ -1569,7 +1553,7 @@ imgtoolerr_t imgtool::partition::get_chain(const char *path, imgtool_chainent *c
imgtoolerr_t imgtool::partition::get_chain_string(const char *path, char *buffer, size_t buffer_len)
{
imgtoolerr_t err;
- imgtool_chainent chain[512];
+ imgtool::chainent chain[512];
uint64_t last_block;
uint8_t cur_level = 0;
int len, i;
@@ -2318,9 +2302,8 @@ imgtoolerr_t imgtool::directory::get_next(imgtool_dirent &ent)
{
imgtoolerr_t err;
- // This makes it so that drivers don't have to take care of clearing
- // the attributes if they don't apply
- memset(&ent, 0, sizeof(ent));
+ // This makes it so that drivers don't have to take care of clearing the attributes if they don't apply
+ ent = imgtool_dirent();
err = m_partition.m_next_enum(*this, ent);
if (err)
@@ -2370,7 +2353,7 @@ void unknown_partition_get_info(const imgtool_class *imgclass, uint32_t state, u
{
switch(state)
{
- /* --- the following bits of info are returned as NULL-terminated strings --- */
+ /* --- the following bits of info are returned as NUL-terminated strings --- */
case IMGTOOLINFO_STR_NAME: strcpy(info->s = imgtool_temp_str(), "unknown"); break;
case IMGTOOLINFO_STR_DESCRIPTION: strcpy(info->s = imgtool_temp_str(), "Unknown partition type"); break;
}
diff --git a/src/tools/imgtool/imgtool.h b/src/tools/imgtool/imgtool.h
index 4a66d7f249d..4ad7fc5479d 100644
--- a/src/tools/imgtool/imgtool.h
+++ b/src/tools/imgtool/imgtool.h
@@ -8,8 +8,10 @@
***************************************************************************/
-#ifndef IMGTOOL_H
-#define IMGTOOL_H
+#ifndef MAME_TOOLS_IMGTOOL_IMGTOOL_H
+#define MAME_TOOLS_IMGTOOL_IMGTOOL_H
+
+#pragma once
#include "library.h"
#include "stream.h"
@@ -164,11 +166,11 @@ namespace imgtool
imgtoolerr_t put_file_attribute(const char *path, uint32_t attr, const imgtool_attribute &value);
void get_attribute_name(uint32_t attribute, const imgtool_attribute *attr_value, char *buffer, size_t buffer_len);
imgtoolerr_t get_icon_info(const char *path, imgtool_iconinfo *iconinfo);
- imgtoolerr_t suggest_file_filters(const char *path, imgtool::stream *stream, imgtool_transfer_suggestion *suggestions, size_t suggestions_length);
+ imgtoolerr_t suggest_file_filters(const char *path, imgtool::stream *stream, imgtool::transfer_suggestion *suggestions, size_t suggestions_length);
imgtoolerr_t get_block_size(uint32_t &length);
imgtoolerr_t read_block(uint64_t block, void *buffer);
imgtoolerr_t write_block(uint64_t block, const void *buffer);
- imgtoolerr_t get_chain(const char *path, imgtool_chainent *chain, size_t chain_size);
+ imgtoolerr_t get_chain(const char *path, imgtool::chainent *chain, size_t chain_size);
imgtoolerr_t get_chain_string(const char *path, char *buffer, size_t buffer_len);
imgtool_partition_features get_features() const;
void * get_info_ptr(uint32_t state);
@@ -213,8 +215,8 @@ namespace imgtool
std::function<imgtoolerr_t(imgtool::partition &partition, const char *path, const uint32_t *attrs, const imgtool_attribute *values)> m_set_attrs;
std::function<imgtoolerr_t(uint32_t attribute, const imgtool_attribute *attr, char *buffer, size_t buffer_len)> m_attr_name;
std::function<imgtoolerr_t(imgtool::partition &partition, const char *path, imgtool_iconinfo *iconinfo)> m_get_iconinfo;
- std::function<imgtoolerr_t(imgtool::partition &partition, const char *path, imgtool_transfer_suggestion *suggestions, size_t suggestions_length)> m_suggest_transfer;
- std::function<imgtoolerr_t(imgtool::partition &partition, const char *path, imgtool_chainent *chain, size_t chain_size)> m_get_chain;
+ std::function<imgtoolerr_t(imgtool::partition &partition, const char *path, imgtool::transfer_suggestion *suggestions, size_t suggestions_length)> m_suggest_transfer;
+ std::function<imgtoolerr_t(imgtool::partition &partition, const char *path, imgtool::chainent *chain, size_t chain_size)> m_get_chain;
const util::option_guide *m_writefile_optguide;
std::string m_writefile_optspec;
@@ -262,4 +264,4 @@ char *strncpyz(char *dest, const char *source, size_t len);
void rtrim(char *buf);
std::string extract_padded_filename(const char *source, size_t filename_length, size_t extension_length, char pad = ' ');
-#endif /* IMGTOOL_H */
+#endif // MAME_TOOLS_IMGTOOL_IMGTOOL_H
diff --git a/src/tools/imgtool/library.h b/src/tools/imgtool/library.h
index 312d3bbe30f..023b5fb948f 100644
--- a/src/tools/imgtool/library.h
+++ b/src/tools/imgtool/library.h
@@ -22,6 +22,7 @@
#include "timeconv.h"
#include "utilfwd.h"
+#include <algorithm>
#include <chrono>
#include <cstdint>
#include <ctime>
@@ -32,16 +33,15 @@
#include <vector>
-namespace imgtool
-{
- class image;
- class partition;
- class directory;
- class charconverter;
- class stream;
-};
+namespace imgtool {
+
+class image;
+class partition;
+class directory;
+class charconverter;
+class stream;
-enum imgtool_suggestion_viability_t
+enum suggestion_viability_t
{
SUGGESTION_END,
SUGGESTION_POSSIBLE,
@@ -57,162 +57,171 @@ union filterinfo
imgtoolerr_t (*read_file)(imgtool::partition &partition, const char *filename, const char *fork, imgtool::stream &destf);
imgtoolerr_t (*write_file)(imgtool::partition &partition, const char *filename, const char *fork, imgtool::stream &sourcef, util::option_resolution *opts);
- imgtoolerr_t (*check_stream)(imgtool::stream &stream, imgtool_suggestion_viability_t *viability);
+ imgtoolerr_t (*check_stream)(imgtool::stream &stream, suggestion_viability_t *viability);
};
typedef void (*filter_getinfoproc)(uint32_t state, union filterinfo *info);
-namespace imgtool
+class datetime
{
- class datetime
- {
- public:
- typedef util::arbitrary_clock<std::int64_t, 1600, 1, 1, 0, 0, 0, std::ratio<1, 10000000> > imgtool_clock;
+public:
+ typedef util::arbitrary_clock<std::int64_t, 1600, 1, 1, 0, 0, 0, std::ratio<1, 10000000> > imgtool_clock;
- enum datetime_type
- {
- NONE,
- LOCAL,
- GMT
- };
+ enum datetime_type
+ {
+ NONE,
+ LOCAL,
+ GMT
+ };
- datetime()
- : m_type(datetime_type::NONE)
- {
- }
+ datetime()
+ : m_type(datetime_type::NONE)
+ {
+ }
- template<typename Rep, int Y, int M, int D, int H, int N, int S, typename Ratio>
- datetime(datetime_type type, std::chrono::time_point<util::arbitrary_clock<Rep, Y, M, D, H, N, S, Ratio> > tp)
- : m_type(type)
- , m_time_point(imgtool_clock::from_arbitrary_time_point(tp))
- {
- }
+ template<typename Rep, int Y, int M, int D, int H, int N, int S, typename Ratio>
+ datetime(datetime_type type, std::chrono::time_point<util::arbitrary_clock<Rep, Y, M, D, H, N, S, Ratio> > tp)
+ : m_type(type)
+ , m_time_point(imgtool_clock::from_arbitrary_time_point(tp))
+ {
+ }
- datetime(datetime_type type, std::chrono::time_point<std::chrono::system_clock> tp);
- datetime(datetime_type type, time_t t);
- datetime(datetime_type type, const util::arbitrary_datetime &dt, bool clamp = true);
- datetime(const datetime &that) = default;
- datetime(datetime &&that) = default;
+ datetime(datetime_type type, std::chrono::time_point<std::chrono::system_clock> tp);
+ datetime(datetime_type type, time_t t);
+ datetime(datetime_type type, const util::arbitrary_datetime &dt, bool clamp = true);
+ datetime(const datetime &that) = default;
+ datetime(datetime &&that) = default;
- // accessors
- datetime_type type() const { return m_type; }
- bool empty() const { return type() == datetime_type::NONE; }
- std::chrono::time_point<imgtool_clock> time_point() const { return m_time_point; }
+ // accessors
+ datetime_type type() const { return m_type; }
+ bool empty() const { return type() == datetime_type::NONE; }
+ std::chrono::time_point<imgtool_clock> time_point() const { return m_time_point; }
- // operators
- datetime &operator =(const datetime &that)
- {
- m_type = that.m_type;
- m_time_point = that.m_time_point;
- return *this;
- }
+ // operators
+ datetime &operator =(const datetime &that)
+ {
+ m_type = that.m_type;
+ m_time_point = that.m_time_point;
+ return *this;
+ }
- // returns the current time
- static datetime now(datetime_type type);
+ // returns the current time
+ static datetime now(datetime_type type);
- // returns time structures
- std::tm localtime() const;
- std::tm gmtime() const;
- time_t to_time_t() const;
+ // returns time structures
+ std::tm localtime() const;
+ std::tm gmtime() const;
+ time_t to_time_t() const;
- private:
- static imgtool_clock::duration s_gmt_offset;
- datetime_type m_type;
- std::chrono::time_point<imgtool_clock> m_time_point;
+private:
+ static imgtool_clock::duration s_gmt_offset;
+ datetime_type m_type;
+ std::chrono::time_point<imgtool_clock> m_time_point;
- static imgtool_clock::duration calculate_gmt_offset();
- };
+ static imgtool_clock::duration calculate_gmt_offset();
};
-struct imgtool_dirent
-{
- char filename[1024];
- char attr[64];
- uint64_t filesize;
-
- imgtool::datetime creation_time;
- imgtool::datetime lastmodified_time;
- imgtool::datetime lastaccess_time;
-
- char softlink[1024];
- char comment[256];
- /* flags */
- unsigned int eof : 1;
- unsigned int corrupt : 1;
- unsigned int directory : 1;
- unsigned int hardlink : 1;
-};
-
-struct imgtool_chainent
+struct chainent
{
uint8_t level;
uint64_t block;
};
-namespace imgtool
+class fork_entry
{
- class fork_entry
+public:
+ enum class type_t
{
- public:
- enum class type_t
- {
- DATA,
- RESOURCE,
- ALT
- };
-
- fork_entry(uint64_t size, type_t type = type_t::DATA)
- : m_size(size)
- , m_type(type)
- , m_name(default_name(type))
- {
+ DATA,
+ RESOURCE,
+ ALT
+ };
- }
+ fork_entry(uint64_t size, type_t type = type_t::DATA)
+ : m_size(size)
+ , m_type(type)
+ , m_name(default_name(type))
+ {
- fork_entry(uint64_t size, std::string &&name)
- : m_size(size)
- , m_type(fork_entry::type_t::ALT)
- , m_name(std::move(name))
- {
- }
+ }
- fork_entry(const fork_entry &that) = default;
- fork_entry(fork_entry &&that) = default;
+ fork_entry(uint64_t size, std::string &&name)
+ : m_size(size)
+ , m_type(fork_entry::type_t::ALT)
+ , m_name(std::move(name))
+ {
+ }
- uint64_t size() const { return m_size; }
- type_t type() const { return m_type; }
- const std::string &name() const { return m_name; }
+ fork_entry(const fork_entry &that) = default;
+ fork_entry(fork_entry &&that) = default;
- private:
- static std::string default_name(type_t type)
+ uint64_t size() const { return m_size; }
+ type_t type() const { return m_type; }
+ const std::string &name() const { return m_name; }
+
+private:
+ static std::string default_name(type_t type)
+ {
+ switch (type)
{
- switch (type)
- {
- case type_t::DATA:
- return std::string("");
- case type_t::RESOURCE:
- return std::string("RESOURCE_FORK");
- default:
- throw false;
- }
+ case type_t::DATA:
+ return std::string("");
+ case type_t::RESOURCE:
+ return std::string("RESOURCE_FORK");
+ default:
+ throw false;
}
+ }
- uint64_t m_size;
- type_t m_type;
- std::string m_name;
- };
-}
+ uint64_t m_size;
+ type_t m_type;
+ std::string m_name;
+};
-struct imgtool_transfer_suggestion
+struct transfer_suggestion
{
- imgtool_suggestion_viability_t viability;
+ suggestion_viability_t viability;
filter_getinfoproc filter;
const char *fork;
const char *description;
};
+} // namespace imgtool
+
+struct imgtool_dirent
+{
+ imgtool_dirent()
+ {
+ std::fill(std::begin(filename), std::end(filename), 0);
+ std::fill(std::begin(attr), std::end(attr), 0);
+ filesize = 0;
+
+ std::fill(std::begin(softlink), std::end(softlink), 0);
+ std::fill(std::begin(comment), std::end(comment), 0);
+
+ eof = corrupt = directory = hardlink = 0;
+ }
+
+ char filename[1024];
+ char attr[64];
+ uint64_t filesize;
+
+ imgtool::datetime creation_time;
+ imgtool::datetime lastmodified_time;
+ imgtool::datetime lastaccess_time;
+
+ char softlink[1024];
+ char comment[256];
+
+ /* flags */
+ unsigned int eof : 1;
+ unsigned int corrupt : 1;
+ unsigned int directory : 1;
+ unsigned int hardlink : 1;
+};
+
enum
{
/* --- the following bits of info are returned as 64-bit signed integers --- */
@@ -407,8 +416,8 @@ union imgtoolinfo
imgtoolerr_t (*set_attrs) (imgtool::partition &partition, const char *path, const uint32_t *attrs, const imgtool_attribute *values);
imgtoolerr_t (*attr_name) (uint32_t attribute, const imgtool_attribute *attr, char *buffer, size_t buffer_len);
imgtoolerr_t (*get_iconinfo) (imgtool::partition &partition, const char *path, imgtool_iconinfo *iconinfo);
- imgtoolerr_t (*suggest_transfer) (imgtool::partition &partition, const char *path, imgtool_transfer_suggestion *suggestions, size_t suggestions_length);
- imgtoolerr_t (*get_chain) (imgtool::partition &partition, const char *path, imgtool_chainent *chain, size_t chain_size);
+ imgtoolerr_t (*suggest_transfer) (imgtool::partition &partition, const char *path, imgtool::transfer_suggestion *suggestions, size_t suggestions_length);
+ imgtoolerr_t (*get_chain) (imgtool::partition &partition, const char *path, imgtool::chainent *chain, size_t chain_size);
imgtoolerr_t (*get_geometry) (imgtool::image &image, uint32_t *tracks, uint32_t *heads, uint32_t *sectors);
imgtoolerr_t (*read_sector) (imgtool::image &image, uint32_t track, uint32_t head, uint32_t sector, std::vector<uint8_t> &buffer);
imgtoolerr_t (*write_sector) (imgtool::image &image, uint32_t track, uint32_t head, uint32_t sector, const void *buffer, size_t len, int ddam);
diff --git a/src/tools/imgtool/main.cpp b/src/tools/imgtool/main.cpp
index 9777a8b35f8..ca38d7905cb 100644
--- a/src/tools/imgtool/main.cpp
+++ b/src/tools/imgtool/main.cpp
@@ -51,7 +51,7 @@ static void writeusage(std::wostream &output, bool write_word_usage, const struc
// ----------------------------------------------------------------------
static int parse_options(int argc, char *argv[], int minunnamed, int maxunnamed,
- util::option_resolution *resolution, filter_getinfoproc *filter, const char **fork)
+ util::option_resolution *resolution, imgtool::filter_getinfoproc *filter, const char **fork)
{
int i;
int lastunnamed = 0;
@@ -242,7 +242,6 @@ static int cmd_dir(const struct command *c, int argc, char *argv[])
if (err)
goto done;
- memset(&ent, 0, sizeof(ent));
last_modified[0] = '\0';
total_count = 0;
total_size = 0;
@@ -286,7 +285,7 @@ static int cmd_dir(const struct command *c, int argc, char *argv[])
total_count++;
total_size += ent.filesize;
- memset(&ent, 0, sizeof(ent));
+ ent = imgtool_dirent();
}
freespace_err = partition->get_free_space(freespace);
@@ -317,7 +316,7 @@ static int cmd_get(const struct command *c, int argc, char *argv[])
const char *filename;
char *new_filename;
int unnamedargs = 0;
- filter_getinfoproc filter;
+ imgtool::filter_getinfoproc filter;
const char *fork;
int partition_index = 0;
@@ -354,12 +353,11 @@ done:
static int cmd_put(const struct command *c, int argc, char *argv[])
{
imgtoolerr_t err = IMGTOOLERR_SUCCESS;
- int i;
imgtool::image::ptr image;
imgtool::partition::ptr partition;
const char *filename = nullptr;
int unnamedargs;
- filter_getinfoproc filter;
+ imgtool::filter_getinfoproc filter;
const imgtool_module *module;
std::unique_ptr<util::option_resolution> resolution;
const char *fork;
@@ -417,7 +415,7 @@ static int cmd_put(const struct command *c, int argc, char *argv[])
filename_count = unnamedargs - 3;
/* loop through the filenames, and put them */
- for (i = 0; i < filename_count; i++)
+ for (int i = 0; i < filename_count; i++)
{
filename = filename_list[i];
util::stream_format(std::wcout, L"Putting file '%s'...\n", wstring_from_utf8(filename));
@@ -441,7 +439,7 @@ static int cmd_getall(const struct command *c, int argc, char *argv[])
imgtool::partition::ptr partition;
imgtool::directory::ptr imgenum;
imgtool_dirent ent;
- filter_getinfoproc filter;
+ imgtool::filter_getinfoproc filter;
int unnamedargs;
const char *path = "";
int arg;
@@ -469,8 +467,6 @@ static int cmd_getall(const struct command *c, int argc, char *argv[])
if (err)
goto done;
- memset(&ent, 0, sizeof(ent));
-
while (((err = imgenum->get_next(ent)) == 0) && !ent.eof)
{
util::stream_format(std::wcout, L"Retrieving %s (%u bytes)\n", wstring_from_utf8(ent.filename), (unsigned int)ent.filesize);
diff --git a/src/tools/imgtool/modules/amiga.cpp b/src/tools/imgtool/modules/amiga.cpp
index 2d9a793c54d..fcf1bd779a6 100644
--- a/src/tools/imgtool/modules/amiga.cpp
+++ b/src/tools/imgtool/modules/amiga.cpp
@@ -1712,7 +1712,7 @@ static imgtoolerr_t write_file_ext_data(imgtool::image &img, int block, int *fil
static imgtoolerr_t clear_file_ext_data(imgtool::image &img, int block, int *filesize)
{
- return walk_file_ext_data(img, block, filesize, NULL, false);
+ return walk_file_ext_data(img, block, filesize, nullptr, false);
}
@@ -2340,7 +2340,7 @@ static imgtoolerr_t amiga_image_geticoninfo(imgtool::partition &partition, const
}
-static imgtoolerr_t amiga_image_suggesttransfer(imgtool::partition &partition, const char *fname, imgtool_transfer_suggestion *suggestions, size_t suggestions_length)
+static imgtoolerr_t amiga_image_suggesttransfer(imgtool::partition &partition, const char *fname, imgtool::transfer_suggestion *suggestions, size_t suggestions_length)
{
return IMGTOOLERR_UNIMPLEMENTED;
}
@@ -2387,7 +2387,7 @@ void amiga_floppy_get_info(const imgtool_class *imgclass, uint32_t state, union
case IMGTOOLINFO_INT_SUPPORTS_LASTMODIFIED_TIME: info->i = 1; break;
case IMGTOOLINFO_INT_PATH_SEPARATOR: info->i = '/'; break;
- /* --- the following bits of info are returned as NULL-terminated strings --- */
+ /* --- the following bits of info are returned as NUL-terminated strings --- */
case IMGTOOLINFO_STR_NAME: strcpy(info->s = imgtool_temp_str(), "amiga_floppy"); break;
case IMGTOOLINFO_STR_DESCRIPTION: strcpy(info->s = imgtool_temp_str(), "Amiga floppy disk image (OFS/FFS format)"); break;
case IMGTOOLINFO_STR_FILE_EXTENSIONS: strcpy(info->s = imgtool_temp_str(), "adf"); break;
diff --git a/src/tools/imgtool/modules/bml3.cpp b/src/tools/imgtool/modules/bml3.cpp
index 68c6b8d51ca..8c465032f28 100644
--- a/src/tools/imgtool/modules/bml3.cpp
+++ b/src/tools/imgtool/modules/bml3.cpp
@@ -840,7 +840,7 @@ static imgtoolerr_t bml3_diskimage_deletefile(imgtool::partition &partition, con
-static imgtoolerr_t bml3_diskimage_suggesttransfer(imgtool::partition &partition, const char *fname, imgtool_transfer_suggestion *suggestions, size_t suggestions_length)
+static imgtoolerr_t bml3_diskimage_suggesttransfer(imgtool::partition &partition, const char *fname, imgtool::transfer_suggestion *suggestions, size_t suggestions_length)
{
imgtoolerr_t err;
imgtool::image &image(partition.image());
@@ -856,27 +856,27 @@ static imgtoolerr_t bml3_diskimage_suggesttransfer(imgtool::partition &partition
if (ent.asciiflag == 0xFF)
{
/* ASCII file */
- suggestions[0].viability = SUGGESTION_RECOMMENDED;
+ suggestions[0].viability = imgtool::SUGGESTION_RECOMMENDED;
suggestions[0].filter = filter_eoln_getinfo;
- suggestions[1].viability = SUGGESTION_POSSIBLE;
- suggestions[1].filter = NULL;
+ suggestions[1].viability = imgtool::SUGGESTION_POSSIBLE;
+ suggestions[1].filter = nullptr;
}
else if (ent.ftype == 0)
{
/* tokenized BASIC file */
- suggestions[0].viability = SUGGESTION_RECOMMENDED;
- suggestions[0].filter = NULL;
- suggestions[1].viability = SUGGESTION_POSSIBLE;
+ suggestions[0].viability = imgtool::SUGGESTION_RECOMMENDED;
+ suggestions[0].filter = nullptr;
+ suggestions[1].viability = imgtool::SUGGESTION_POSSIBLE;
suggestions[1].filter = filter_bml3bas_getinfo;
}
}
else
{
- suggestions[0].viability = SUGGESTION_RECOMMENDED;
- suggestions[0].filter = NULL;
- suggestions[1].viability = SUGGESTION_POSSIBLE;
+ suggestions[0].viability = imgtool::SUGGESTION_RECOMMENDED;
+ suggestions[0].filter = nullptr;
+ suggestions[1].viability = imgtool::SUGGESTION_POSSIBLE;
suggestions[1].filter = filter_eoln_getinfo;
- suggestions[2].viability = SUGGESTION_POSSIBLE;
+ suggestions[2].viability = imgtool::SUGGESTION_POSSIBLE;
suggestions[2].filter = filter_bml3bas_getinfo;
}
@@ -911,9 +911,9 @@ void bml3_get_info(const imgtool_class *imgclass, uint32_t state, union imgtooli
/* --- the following bits of info are returned as 64-bit signed integers --- */
case IMGTOOLINFO_INT_PREFER_UCASE: info->i = 1; break;
case IMGTOOLINFO_INT_IMAGE_EXTRA_BYTES: info->i = sizeof(bml3_diskinfo); break;
- case IMGTOOLINFO_INT_DIRECTORY_EXTRA_BYTES: info->i = sizeof(struct bml3_direnum); break;
+ case IMGTOOLINFO_INT_DIRECTORY_EXTRA_BYTES: info->i = sizeof(struct bml3_direnum); break;
- /* --- the following bits of info are returned as NULL-terminated strings --- */
+ /* --- the following bits of info are returned as NUL-terminated strings --- */
case IMGTOOLINFO_STR_NAME: strcpy(info->s = imgtool_temp_str(), "bml3"); break;
case IMGTOOLINFO_STR_DESCRIPTION: strcpy(info->s = imgtool_temp_str(), "Basic Master Level 3 format"); break;
case IMGTOOLINFO_STR_FILE: strcpy(info->s = imgtool_temp_str(), __FILE__); break;
diff --git a/src/tools/imgtool/modules/dgndos.cpp b/src/tools/imgtool/modules/dgndos.cpp
index 147e8e8a6c7..692c010d057 100644
--- a/src/tools/imgtool/modules/dgndos.cpp
+++ b/src/tools/imgtool/modules/dgndos.cpp
@@ -1097,7 +1097,7 @@ static imgtoolerr_t dgndos_diskimage_writefile(imgtool::partition &partition, co
return IMGTOOLERR_SUCCESS;
}
-static imgtoolerr_t dgndos_diskimage_suggesttransfer(imgtool::partition &partition, const char *fname, imgtool_transfer_suggestion *suggestions, size_t suggestions_length)
+static imgtoolerr_t dgndos_diskimage_suggesttransfer(imgtool::partition &partition, const char *fname, imgtool::transfer_suggestion *suggestions, size_t suggestions_length)
{
floperr_t ferr;
imgtoolerr_t err;
@@ -1119,27 +1119,27 @@ static imgtoolerr_t dgndos_diskimage_suggesttransfer(imgtool::partition &partiti
if (strcmp(ent.block.header.filename+8,"DAT") == 0)
{
/* ASCII file */
- suggestions[0].viability = SUGGESTION_RECOMMENDED;
+ suggestions[0].viability = imgtool::SUGGESTION_RECOMMENDED;
suggestions[0].filter = filter_eoln_getinfo;
- suggestions[1].viability = SUGGESTION_POSSIBLE;
- suggestions[1].filter = NULL;
+ suggestions[1].viability = imgtool::SUGGESTION_POSSIBLE;
+ suggestions[1].filter = nullptr;
}
else if (strcmp(ent.block.header.filename+8,"BAS") == 0)
{
/* tokenized BASIC file */
- suggestions[0].viability = SUGGESTION_RECOMMENDED;
- suggestions[0].filter = NULL;
- suggestions[1].viability = SUGGESTION_POSSIBLE;
+ suggestions[0].viability = imgtool::SUGGESTION_RECOMMENDED;
+ suggestions[0].filter = nullptr;
+ suggestions[1].viability = imgtool::SUGGESTION_POSSIBLE;
suggestions[1].filter = filter_dragonbas_getinfo;
}
}
else
{
- suggestions[0].viability = SUGGESTION_RECOMMENDED;
- suggestions[0].filter = NULL;
- suggestions[1].viability = SUGGESTION_POSSIBLE;
+ suggestions[0].viability = imgtool::SUGGESTION_RECOMMENDED;
+ suggestions[0].filter = nullptr;
+ suggestions[1].viability = imgtool::SUGGESTION_POSSIBLE;
suggestions[1].filter = filter_eoln_getinfo;
- suggestions[2].viability = SUGGESTION_POSSIBLE;
+ suggestions[2].viability = imgtool::SUGGESTION_POSSIBLE;
suggestions[2].filter = filter_dragonbas_getinfo;
}
@@ -1234,7 +1234,7 @@ void dgndos_get_info(const imgtool_class *imgclass, uint32_t state, union imgtoo
case IMGTOOLINFO_INT_PREFER_UCASE: info->i = 1; break;
case IMGTOOLINFO_INT_DIRECTORY_EXTRA_BYTES: info->i = sizeof(struct dgndos_direnum); break;
- /* --- the following bits of info are returned as NULL-terminated strings --- */
+ /* --- the following bits of info are returned as NUL-terminated strings --- */
case IMGTOOLINFO_STR_NAME: strcpy(info->s = imgtool_temp_str(), "dgndos"); break;
case IMGTOOLINFO_STR_DESCRIPTION: strcpy(info->s = imgtool_temp_str(), "Dragon DOS format"); break;
case IMGTOOLINFO_STR_FILE: strcpy(info->s = imgtool_temp_str(), __FILE__); break;
diff --git a/src/tools/imgtool/modules/fat.cpp b/src/tools/imgtool/modules/fat.cpp
index f61d073b5f8..d6611932c0d 100644
--- a/src/tools/imgtool/modules/fat.cpp
+++ b/src/tools/imgtool/modules/fat.cpp
@@ -140,6 +140,7 @@
#include "multibyte.h"
#include "unicode.h"
+#include <algorithm>
#include <cctype>
#include <cstdio>
#include <ctime>
@@ -179,6 +180,18 @@ struct fat_file
struct fat_dirent
{
+ fat_dirent() :
+ directory(0),
+ eof(0),
+ filesize(0),
+ first_cluster(0),
+ dirent_sector_index(0),
+ dirent_sector_offset(0)
+ {
+ std::fill(std::begin(long_filename), std::end(long_filename), 0);
+ std::fill(std::begin(short_filename), std::end(short_filename), 0);
+ }
+
char long_filename[512];
char short_filename[13];
unsigned int directory : 1;
@@ -1273,15 +1286,16 @@ static uint32_t fat_setup_time(time_t ansi_time)
-static imgtoolerr_t fat_read_dirent(imgtool::partition &partition, fat_file *file,
- fat_dirent &ent, fat_freeentry_info *freeent)
+static imgtoolerr_t fat_read_dirent(
+ imgtool::partition &partition,
+ fat_file *file,
+ fat_dirent &ent,
+ fat_freeentry_info *freeent)
{
imgtoolerr_t err;
//const fat_partition_info *disk_info;
uint8_t entry[FAT_DIRENT_SIZE];
size_t bytes_read;
- int i, j;
- char32_t ch;
char16_t lfn_buf[512];
size_t lfn_len = 0;
int lfn_lastentry = 0;
@@ -1290,7 +1304,7 @@ static imgtoolerr_t fat_read_dirent(imgtool::partition &partition, fat_file *fil
assert(file->directory);
lfn_buf[0] = '\0';
- memset(&ent, 0, sizeof(ent));
+ ent = fat_dirent();
//disk_info = fat_get_partition_info(partition);
/* The first eight bytes of a FAT directory entry is a blank padded name
@@ -1351,7 +1365,7 @@ static imgtoolerr_t fat_read_dirent(imgtool::partition &partition, fat_file *fil
}
}
}
- while((entry[0] == 0x2E) || (entry[0] == 0xE5) || (entry[11] == 0x0F));
+ while ((entry[0] == 0x2E) || (entry[0] == 0xE5) || (entry[11] == 0x0F));
/* no more directory entries? */
if (entry[0] == '\0')
@@ -1369,14 +1383,14 @@ static imgtoolerr_t fat_read_dirent(imgtool::partition &partition, fat_file *fil
/* only use the LFN if the checksum passes */
if (lfn_checksum == fat_calc_filename_checksum(entry))
{
- i = 0;
- j = 0;
+ int i = 0, j = 0;
+ char32_t ch;
do
{
i += uchar_from_utf16(&ch, &lfn_buf[i], std::size(lfn_buf) - i);
j += utf8_from_uchar(&ent.long_filename[j], std::size(ent.long_filename) - j, ch);
}
- while(ch != 0);
+ while (ch != 0);
}
}
diff --git a/src/tools/imgtool/modules/hp9845_tape.cpp b/src/tools/imgtool/modules/hp9845_tape.cpp
index 8398f63bdce..26cb2f4eb1c 100644
--- a/src/tools/imgtool/modules/hp9845_tape.cpp
+++ b/src/tools/imgtool/modules/hp9845_tape.cpp
@@ -1514,7 +1514,7 @@ static imgtoolerr_t hp9845data_write_file(imgtool::partition &partition, const c
return res;
}
-void filter_hp9845data_getinfo(uint32_t state, union filterinfo *info)
+void filter_hp9845data_getinfo(uint32_t state, imgtool::filterinfo *info)
{
switch (state) {
case FILTINFO_PTR_READFILE:
diff --git a/src/tools/imgtool/modules/rsdos.cpp b/src/tools/imgtool/modules/rsdos.cpp
index c07e215f2da..b4924338309 100644
--- a/src/tools/imgtool/modules/rsdos.cpp
+++ b/src/tools/imgtool/modules/rsdos.cpp
@@ -573,7 +573,7 @@ static imgtoolerr_t rsdos_diskimage_deletefile(imgtool::partition &partition, co
// rsdos_diskimage_suggesttransfer
//-------------------------------------------------
-static imgtoolerr_t rsdos_diskimage_suggesttransfer(imgtool::partition &partition, const char *fname, imgtool_transfer_suggestion *suggestions, size_t suggestions_length)
+static imgtoolerr_t rsdos_diskimage_suggesttransfer(imgtool::partition &partition, const char *fname, imgtool::transfer_suggestion *suggestions, size_t suggestions_length)
{
imgtoolerr_t err;
imgtool::image &image(partition.image());
@@ -589,27 +589,27 @@ static imgtoolerr_t rsdos_diskimage_suggesttransfer(imgtool::partition &partitio
if (ent.asciiflag == (char) 0xFF)
{
/* ASCII file */
- suggestions[0].viability = SUGGESTION_RECOMMENDED;
+ suggestions[0].viability = imgtool::SUGGESTION_RECOMMENDED;
suggestions[0].filter = filter_eoln_getinfo;
- suggestions[1].viability = SUGGESTION_POSSIBLE;
- suggestions[1].filter = NULL;
+ suggestions[1].viability = imgtool::SUGGESTION_POSSIBLE;
+ suggestions[1].filter = nullptr;
}
else if (ent.ftype == 0)
{
/* tokenized BASIC file */
- suggestions[0].viability = SUGGESTION_RECOMMENDED;
- suggestions[0].filter = NULL;
- suggestions[1].viability = SUGGESTION_POSSIBLE;
+ suggestions[0].viability = imgtool::SUGGESTION_RECOMMENDED;
+ suggestions[0].filter = nullptr;
+ suggestions[1].viability = imgtool::SUGGESTION_POSSIBLE;
suggestions[1].filter = filter_cocobas_getinfo;
}
}
else
{
- suggestions[0].viability = SUGGESTION_RECOMMENDED;
- suggestions[0].filter = NULL;
- suggestions[1].viability = SUGGESTION_POSSIBLE;
+ suggestions[0].viability = imgtool::SUGGESTION_RECOMMENDED;
+ suggestions[0].filter = nullptr;
+ suggestions[1].viability = imgtool::SUGGESTION_POSSIBLE;
suggestions[1].filter = filter_eoln_getinfo;
- suggestions[2].viability = SUGGESTION_POSSIBLE;
+ suggestions[2].viability = imgtool::SUGGESTION_POSSIBLE;
suggestions[2].filter = filter_cocobas_getinfo;
}
@@ -645,7 +645,7 @@ void rsdos_get_info(const imgtool_class *imgclass, uint32_t state, union imgtool
case IMGTOOLINFO_INT_PREFER_UCASE: info->i = 1; break;
case IMGTOOLINFO_INT_DIRECTORY_EXTRA_BYTES: info->i = sizeof(struct rsdos_direnum); break;
- /* --- the following bits of info are returned as NULL-terminated strings --- */
+ /* --- the following bits of info are returned as NUL-terminated strings --- */
case IMGTOOLINFO_STR_NAME: strcpy(info->s = imgtool_temp_str(), "rsdos"); break;
case IMGTOOLINFO_STR_DESCRIPTION: strcpy(info->s = imgtool_temp_str(), "RS-DOS format"); break;
case IMGTOOLINFO_STR_FILE: strcpy(info->s = imgtool_temp_str(), __FILE__); break;
diff --git a/src/tools/imgtool/modules/thomson.cpp b/src/tools/imgtool/modules/thomson.cpp
index 495436dbebb..1978e3720ba 100644
--- a/src/tools/imgtool/modules/thomson.cpp
+++ b/src/tools/imgtool/modules/thomson.cpp
@@ -1072,10 +1072,11 @@ static imgtoolerr_t thom_write_file(imgtool::partition &part,
return IMGTOOLERR_SUCCESS;
}
-static imgtoolerr_t thom_suggest_transfer(imgtool::partition &part,
- const char *fname,
- imgtool_transfer_suggestion *suggestions,
- size_t suggestions_length)
+static imgtoolerr_t thom_suggest_transfer(
+ imgtool::partition &part,
+ const char *fname,
+ imgtool::transfer_suggestion *suggestions,
+ size_t suggestions_length)
{
int head = *( (int*) part.extra_bytes() );
imgtool::image &img(part.image());
@@ -1086,30 +1087,30 @@ static imgtoolerr_t thom_suggest_transfer(imgtool::partition &part,
if ( suggestions_length < 1 ) return IMGTOOLERR_SUCCESS;
if ( fname ) {
- if ( ! thom_find_dirent( f, head, fname, &d ) )
- return IMGTOOLERR_FILENOTFOUND;
- if ( d.ftype == 0 && d.format == 0 ) is_basic = 1;
+ if ( ! thom_find_dirent( f, head, fname, &d ) )
+ return IMGTOOLERR_FILENOTFOUND;
+ if ( d.ftype == 0 && d.format == 0 ) is_basic = 1;
}
if ( is_basic ) {
- suggestions[0].viability = SUGGESTION_RECOMMENDED;
- suggestions[0].filter = filter_thombas128_getinfo;
- if ( suggestions_length >= 2 ) {
- suggestions[1].viability = SUGGESTION_POSSIBLE;
- suggestions[1].filter = filter_thombas7_getinfo;
- }
- if ( suggestions_length >= 3 ) {
- suggestions[2].viability = SUGGESTION_POSSIBLE;
- suggestions[2].filter = filter_thombas5_getinfo;
- }
- if ( suggestions_length >= 4 ) {
- suggestions[3].viability = SUGGESTION_POSSIBLE;
- suggestions[3].filter = NULL;
- }
+ suggestions[0].viability = imgtool::SUGGESTION_RECOMMENDED;
+ suggestions[0].filter = filter_thombas128_getinfo;
+ if ( suggestions_length >= 2 ) {
+ suggestions[1].viability = imgtool::SUGGESTION_POSSIBLE;
+ suggestions[1].filter = filter_thombas7_getinfo;
+ }
+ if ( suggestions_length >= 3 ) {
+ suggestions[2].viability = imgtool::SUGGESTION_POSSIBLE;
+ suggestions[2].filter = filter_thombas5_getinfo;
+ }
+ if ( suggestions_length >= 4 ) {
+ suggestions[3].viability = imgtool::SUGGESTION_POSSIBLE;
+ suggestions[3].filter = nullptr;
+ }
}
else {
- suggestions[0].viability = SUGGESTION_RECOMMENDED;
- suggestions[0].filter = NULL;
+ suggestions[0].viability = imgtool::SUGGESTION_RECOMMENDED;
+ suggestions[0].filter = nullptr;
}
return IMGTOOLERR_SUCCESS;
@@ -1211,12 +1212,12 @@ static const char *const thombas7[2][128] = {
/* MO5: some keywords ar missing; DOS and TUNE are added */
static const char *const thombas5[2][128] = {
{ /* statements */
- "END", "FOR", "NEXT", "DATA", "DIM", "READ", NULL, "GO", "RUN", "IF",
+ "END", "FOR", "NEXT", "DATA", "DIM", "READ", nullptr, "GO", "RUN", "IF",
"RESTORE", "RETURN", "REM", "'", "STOP", "ELSE", "TRON", "TROFF", "DEFSTR",
- "DEFINT", "DEFSNG", NULL, "ON", "TUNE", "ERROR", "RESUME", "AUTO",
+ "DEFINT", "DEFSNG", nullptr, "ON", "TUNE", "ERROR", "RESUME", "AUTO",
"DELETE", "LOCATE", "CLS", "CONSOLE", "PSET", "MOTOR", "SKIP", "EXEC",
- "BEEP", "COLOR", "LINE", "BOX", NULL, "ATTRB", "DEF", "POKE", "PRINT",
- "CONT", "LIST", "CLEAR", "DOS", NULL, "NEW", "SAVE", "LOAD", "MERGE",
+ "BEEP", "COLOR", "LINE", "BOX", nullptr, "ATTRB", "DEF", "POKE", "PRINT",
+ "CONT", "LIST", "CLEAR", "DOS", nullptr, "NEW", "SAVE", "LOAD", "MERGE",
"OPEN", "CLOSE", "INPEN", "PEN", "PLAY", "TAB(", "TO", "SUB", "FN",
"SPC(", "USING", "USR", "ERL", "ERR", "OFF", "THEN", "NOT", "STEP",
"+", "-", "*", "/", "^", "AND", "OR", "XOR", "EQV", "IMP", "MOD", "@",
@@ -1229,8 +1230,8 @@ static const char *const thombas5[2][128] = {
},
{ /* functions: 0xff prefix */
"SGN", "INT", "ABS", "FRE", "SQR", "LOG", "EXP", "COS", "SIN",
- "TAN", "PEEK", "LEN", "STR$", "VAL", "ASC", "CHR$", "EOF", "CINT", NULL,
- NULL, "FIX", "HEX$", NULL, "STICK", "STRIG", "GR$", "LEFT$", "RIGHT$",
+ "TAN", "PEEK", "LEN", "STR$", "VAL", "ASC", "CHR$", "EOF", "CINT", nullptr,
+ nullptr, "FIX", "HEX$", nullptr, "STICK", "STRIG", "GR$", "LEFT$", "RIGHT$",
"MID$", "INSTR", "VARPTR", "RND", "INKEY$", "INPUT", "CSRLIN", "POINT",
"SCREEN", "POS", "PTRIG",
/* DOS specific */
@@ -1373,7 +1374,7 @@ static imgtoolerr_t thomcrypt_write_file(imgtool::partition &part,
}
}
-void filter_thomcrypt_getinfo(uint32_t state, union filterinfo *info)
+void filter_thomcrypt_getinfo(uint32_t state, imgtool::filterinfo *info)
{
switch(state) {
case FILTINFO_STR_NAME:
@@ -1601,16 +1602,14 @@ struct {
{ "\xc3\xa7", "\x16" "Kc" },
{ "\xc3\x87", "\x16" "KC" },
- { NULL, NULL }
+ { nullptr, nullptr }
};
static bool thom_basic_is_specialchar(const char *buf,
int *pos,
const char **thom)
{
- int i;
-
- for (i = 0; special_chars[i].utf8 != NULL; i++)
+ for (int i = 0; special_chars[i].utf8 != nullptr; i++)
{
if (!strncmp(&buf[*pos], special_chars[i].utf8, strlen(special_chars[i].utf8)))
{
@@ -1875,32 +1874,33 @@ static imgtoolerr_t thom_basic_write_file(imgtool::partition &partition,
const char *fork, \
imgtool::stream &dst) \
{ \
- return thom_basic_read_file( part, name, fork, dst, short ); \
+ return thom_basic_read_file( part, name, fork, dst, short ); \
} \
- static imgtoolerr_t short##_write_file(imgtool::partition &part, \
- const char *name, \
- const char *fork, \
- imgtool::stream &src, \
- util::option_resolution *opts) \
+ static imgtoolerr_t short##_write_file( \
+ imgtool::partition &part, \
+ const char *name, \
+ const char *fork, \
+ imgtool::stream &src, \
+ util::option_resolution *opts) \
{ \
- return thom_basic_write_file( part, name, fork, src, opts, short ); \
+ return thom_basic_write_file( part, name, fork, src, opts, short ); \
} \
- void filter_##short##_getinfo(uint32_t state, union filterinfo *info) \
+ void filter_##short##_getinfo(uint32_t state, imgtool::filterinfo *info) \
{ \
switch(state) \
{ \
case FILTINFO_STR_NAME: \
- info->s = #short; \
- break; \
+ info->s = #short; \
+ break; \
case FILTINFO_STR_HUMANNAME: \
- info->s = long; \
- break; \
+ info->s = long; \
+ break; \
case FILTINFO_PTR_READFILE: \
- info->read_file = short##_read_file; \
- break; \
+ info->read_file = short##_read_file; \
+ break; \
case FILTINFO_PTR_WRITEFILE: \
- info->write_file = short##_write_file; \
- break; \
+ info->write_file = short##_write_file; \
+ break; \
} \
}
@@ -1946,57 +1946,57 @@ static void thom_basic_get_info(const imgtool_class *clas,
{
switch ( param ) {
case IMGTOOLINFO_INT_IMAGE_EXTRA_BYTES:
- info->i = sizeof(thom_floppy); break;
+ info->i = sizeof(thom_floppy); break;
case IMGTOOLINFO_INT_PARTITION_EXTRA_BYTES:
- info->i = sizeof(int); break;
+ info->i = sizeof(int); break;
case IMGTOOLINFO_INT_DIRECTORY_EXTRA_BYTES:
- info->i = sizeof(int); break;
+ info->i = sizeof(int); break;
case IMGTOOLINFO_INT_SUPPORTS_CREATION_TIME:
case IMGTOOLINFO_INT_PREFER_UCASE:
- info->i = 1; break;
+ info->i = 1; break;
case IMGTOOLINFO_INT_PATH_SEPARATOR:
- info->i = 0; break;
+ info->i = 0; break;
case IMGTOOLINFO_STR_FILE:
- strcpy( info->s = imgtool_temp_str(), __FILE__ ); break;
+ strcpy( info->s = imgtool_temp_str(), __FILE__ ); break;
case IMGTOOLINFO_STR_NAME:
- strcpy( info->s = imgtool_temp_str(), "thom" ); break;
+ strcpy( info->s = imgtool_temp_str(), "thom" ); break;
case IMGTOOLINFO_STR_DESCRIPTION:
- strcpy( info->s = imgtool_temp_str(), "Thomson BASIC filesystem" );
- break;
+ strcpy( info->s = imgtool_temp_str(), "Thomson BASIC filesystem" );
+ break;
case IMGTOOLINFO_PTR_CREATE:
- info->create = thom_create; break;
+ info->create = thom_create; break;
case IMGTOOLINFO_PTR_CREATEIMAGE_OPTGUIDE:
- info->createimage_optguide = &thom_createimage_optguide; break;
+ info->createimage_optguide = &thom_createimage_optguide; break;
case IMGTOOLINFO_PTR_BEGIN_ENUM:
- info->begin_enum = thom_begin_enum; break;
+ info->begin_enum = thom_begin_enum; break;
case IMGTOOLINFO_PTR_NEXT_ENUM:
- info->next_enum = thom_next_enum; break;
+ info->next_enum = thom_next_enum; break;
case IMGTOOLINFO_PTR_READ_FILE:
- info->read_file = thom_read_file; break;
+ info->read_file = thom_read_file; break;
case IMGTOOLINFO_PTR_WRITE_FILE:
- info->write_file = thom_write_file; break;
+ info->write_file = thom_write_file; break;
case IMGTOOLINFO_PTR_WRITEFILE_OPTGUIDE:
- info->writefile_optguide = &thom_writefile_optguide; break;
+ info->writefile_optguide = &thom_writefile_optguide; break;
case IMGTOOLINFO_STR_WRITEFILE_OPTSPEC:
- strcpy( info->s = imgtool_temp_str(), "T[0]-4;F[0]-2;C" ); break;
+ strcpy( info->s = imgtool_temp_str(), "T[0]-4;F[0]-2;C" ); break;
case IMGTOOLINFO_PTR_SUGGEST_TRANSFER:
- info->suggest_transfer = thom_suggest_transfer; break;
+ info->suggest_transfer = thom_suggest_transfer; break;
case IMGTOOLINFO_PTR_DELETE_FILE:
- info->delete_file = thom_delete_file; break;
+ info->delete_file = thom_delete_file; break;
case IMGTOOLINFO_PTR_FREE_SPACE:
- info->free_space = thom_free_space; break;
+ info->free_space = thom_free_space; break;
case IMGTOOLINFO_PTR_GET_GEOMETRY:
- info->get_geometry = thom_get_geometry; break;
+ info->get_geometry = thom_get_geometry; break;
case IMGTOOLINFO_PTR_INFO:
- info->info = thom_info; break;
+ info->info = thom_info; break;
case IMGTOOLINFO_PTR_READ_SECTOR:
- info->read_sector = thom_read_sector; break;
+ info->read_sector = thom_read_sector; break;
case IMGTOOLINFO_PTR_WRITE_SECTOR:
- info->write_sector = thom_write_sector; break;
+ info->write_sector = thom_write_sector; break;
case IMGTOOLINFO_PTR_LIST_PARTITIONS:
- info->list_partitions = thom_list_partitions; break;
+ info->list_partitions = thom_list_partitions; break;
case IMGTOOLINFO_PTR_OPEN_PARTITION:
- info->open_partition = thom_open_partition; break;
+ info->open_partition = thom_open_partition; break;
}
}
@@ -2006,21 +2006,21 @@ void thom_fd_basic_get_info(const imgtool_class *clas,
{
switch ( param ) {
case IMGTOOLINFO_STR_NAME:
- strcpy( info->s = imgtool_temp_str(), "thom_fd" ); break;
+ strcpy( info->s = imgtool_temp_str(), "thom_fd" ); break;
case IMGTOOLINFO_STR_DESCRIPTION:
- strcpy( info->s = imgtool_temp_str(),
- "Thomson .fd disk image, BASIC format" );
- break;
+ strcpy( info->s = imgtool_temp_str(),
+ "Thomson .fd disk image, BASIC format" );
+ break;
case IMGTOOLINFO_STR_FILE_EXTENSIONS:
- strcpy( info->s = imgtool_temp_str(), "fd" ); break;
+ strcpy( info->s = imgtool_temp_str(), "fd" ); break;
case IMGTOOLINFO_PTR_OPEN:
- info->open = thom_open_fd_qd; break;
+ info->open = thom_open_fd_qd; break;
case IMGTOOLINFO_PTR_CLOSE:
- info->close = thom_close_fd_qd; break;
+ info->close = thom_close_fd_qd; break;
case IMGTOOLINFO_STR_CREATEIMAGE_OPTSPEC:
- strcpy( info->s = imgtool_temp_str(), "H[1]-2;T40/[80];D0-[1];N" ); break;
+ strcpy( info->s = imgtool_temp_str(), "H[1]-2;T40/[80];D0-[1];N" ); break;
default:
- thom_basic_get_info( clas, param, info );
+ thom_basic_get_info( clas, param, info );
}
}
@@ -2030,21 +2030,21 @@ void thom_qd_basic_get_info(const imgtool_class *clas,
{
switch ( param ) {
case IMGTOOLINFO_STR_NAME:
- strcpy( info->s = imgtool_temp_str(), "thom_qd" ); break;
+ strcpy( info->s = imgtool_temp_str(), "thom_qd" ); break;
case IMGTOOLINFO_STR_DESCRIPTION:
- strcpy( info->s = imgtool_temp_str(),
- "Thomson .qd disk image, BASIC format" );
- break;
+ strcpy( info->s = imgtool_temp_str(),
+ "Thomson .qd disk image, BASIC format" );
+ break;
case IMGTOOLINFO_STR_FILE_EXTENSIONS:
- strcpy( info->s = imgtool_temp_str(), "qd" ); break;
+ strcpy( info->s = imgtool_temp_str(), "qd" ); break;
case IMGTOOLINFO_PTR_OPEN:
- info->open = thom_open_fd_qd; break;
+ info->open = thom_open_fd_qd; break;
case IMGTOOLINFO_PTR_CLOSE:
- info->close = thom_close_fd_qd; break;
+ info->close = thom_close_fd_qd; break;
case IMGTOOLINFO_STR_CREATEIMAGE_OPTSPEC:
- strcpy( info->s = imgtool_temp_str(), "H[1]-2;T[25];D[0];N" ); break;
+ strcpy( info->s = imgtool_temp_str(), "H[1]-2;T[25];D[0];N" ); break;
default:
- thom_basic_get_info( clas, param, info );
+ thom_basic_get_info( clas, param, info );
}
}
@@ -2054,20 +2054,20 @@ void thom_sap_basic_get_info(const imgtool_class *clas,
{
switch ( param ) {
case IMGTOOLINFO_STR_NAME:
- strcpy( info->s = imgtool_temp_str(), "thom_sap" ); break;
+ strcpy( info->s = imgtool_temp_str(), "thom_sap" ); break;
case IMGTOOLINFO_STR_DESCRIPTION:
- strcpy( info->s = imgtool_temp_str(),
- "Thomson .sap disk image, BASIC format" );
- break;
+ strcpy( info->s = imgtool_temp_str(),
+ "Thomson .sap disk image, BASIC format" );
+ break;
case IMGTOOLINFO_STR_FILE_EXTENSIONS:
- strcpy( info->s = imgtool_temp_str(), "sap" ); break;
+ strcpy( info->s = imgtool_temp_str(), "sap" ); break;
case IMGTOOLINFO_PTR_OPEN:
- info->open = thom_open_sap; break;
+ info->open = thom_open_sap; break;
case IMGTOOLINFO_PTR_CLOSE:
- info->close = thom_close_sap; break;
+ info->close = thom_close_sap; break;
case IMGTOOLINFO_STR_CREATEIMAGE_OPTSPEC:
- strcpy( info->s = imgtool_temp_str(), "H[1];T40/[80];D0-[1];N" ); break;
+ strcpy( info->s = imgtool_temp_str(), "H[1];T40/[80];D0-[1];N" ); break;
default:
- thom_basic_get_info( clas, param, info );
+ thom_basic_get_info( clas, param, info );
}
}
diff --git a/src/tools/imgtool/modules/vzdos.cpp b/src/tools/imgtool/modules/vzdos.cpp
index 0005c0973cf..b7dee751434 100644
--- a/src/tools/imgtool/modules/vzdos.cpp
+++ b/src/tools/imgtool/modules/vzdos.cpp
@@ -19,6 +19,7 @@
#include "multibyte.h"
#include "opresolv.h"
+#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstdlib>
@@ -51,20 +52,21 @@ as track map, with one bit for each sector used.
/* vzdos directry entry */
struct vzdos_dirent
{
- char ftype;
- char delimitor;
- char fname[8];
+ struct {
+ char ftype;
+ char delimitor;
+ char fname[8];
+ } node;
uint8_t start_track;
uint8_t start_sector;
uint16_t start_address;
uint16_t end_address;
- vzdos_dirent()
+ vzdos_dirent() :
+ start_track(0), start_sector(0),
+ start_address(0), end_address(0)
{
- ftype = delimitor = '\0';
- fname[0] = '\0';
- start_track = start_sector = 0;
- start_address = end_address = 0;
+ memset(&node, 0, sizeof(node));
}
};
@@ -160,8 +162,7 @@ static imgtoolerr_t vzdos_write_sector_data(imgtool::image &img, int track, int
static imgtoolerr_t vzdos_clear_sector(imgtool::image &img, int track, int sector)
{
uint8_t data[DATA_SIZE + 2];
-
- memset(data, 0x00, sizeof(data));
+ std::fill(std::begin(data), std::end(data), 0x00);
return vzdos_write_sector_data(img, track, sector, data);
}
@@ -169,21 +170,21 @@ static imgtoolerr_t vzdos_clear_sector(imgtool::image &img, int track, int secto
/* return a directory entry for an index */
static imgtoolerr_t vzdos_get_dirent(imgtool::image &img, int index, vzdos_dirent *ent)
{
- int ret, entry;
uint8_t buffer[DATA_SIZE + 2];
- ret = vzdos_read_sector_data(img, 0, (int) index / 8, buffer);
- if (ret) return (imgtoolerr_t)ret;
+ imgtoolerr_t const ret = vzdos_read_sector_data(img, 0, int(index) / 8, buffer);
+ if (IMGTOOLERR_SUCCESS != ret)
+ return ret;
- entry = ((index % 8) * sizeof(vzdos_dirent));
+ int const entry = ((index % 8) * sizeof(vzdos_dirent));
- memcpy(ent, &buffer[entry], 10);
+ memcpy(&ent->node, &buffer[entry], 10);
ent->start_track = buffer[entry + 10];
ent->start_sector = buffer[entry + 11];
ent->start_address = get_u16le(&buffer[entry + 12]);
ent->end_address = get_u16le(&buffer[entry + 14]);
- if (ent->ftype == 0x00)
+ if (ent->node.ftype == 0x00)
return IMGTOOLERR_FILENOTFOUND;
/* check values */
@@ -224,20 +225,12 @@ static imgtoolerr_t vzdos_set_dirent(imgtool::image &img, int index, vzdos_diren
/* clear a directory entry */
static imgtoolerr_t vzdos_clear_dirent(imgtool::image &img, int index)
{
- int ret;
vzdos_dirent entry;
-
- memset(&entry, 0x00, sizeof(vzdos_dirent));
-
- ret = vzdos_set_dirent(img, index, entry);
- if (ret) return (imgtoolerr_t)ret;
-
- return IMGTOOLERR_SUCCESS;
+ return vzdos_set_dirent(img, index, entry);
}
/* search the index for a directory entry */
static imgtoolerr_t vzdos_searchentry(imgtool::image &image, const char *fname, int *entry) {
- int i, len, ret;
vzdos_dirent ent;
char filename[9];
@@ -249,23 +242,23 @@ static imgtoolerr_t vzdos_searchentry(imgtool::image &image, const char *fname,
*entry = -1;
- for (i = 0; i < MAX_DIRENTS; i++) {
- ret = vzdos_get_dirent(image, i, &ent);
- if (ret) return (imgtoolerr_t)ret;
+ for (int i = 0; i < MAX_DIRENTS; i++) {
+ imgtoolerr_t const ret = vzdos_get_dirent(image, i, &ent);
+ if (IMGTOOLERR_SUCCESS != ret)
+ return ret;
- len = vzdos_get_fname_len(ent.fname) + 1;
+ int const len = vzdos_get_fname_len(ent.node.fname) + 1;
if (strlen(fname) != len)
continue;
- memset(filename, 0x00, sizeof(filename));
- memcpy(filename, ent.fname, len);
+ std::fill(std::begin(filename), std::end(filename), 0x00);
+ memcpy(filename, ent.node.fname, len);
if (!core_stricmp(fname, filename)) {
*entry = i;
break;
}
-
}
if (*entry == -1)
@@ -362,7 +355,6 @@ static imgtoolerr_t vzdos_free_trackmap(imgtool::image &img, int *track, int *se
static imgtoolerr_t vzdos_write_formatted_sector(imgtool::image &img, int track, int sector)
{
- int ret;
uint8_t sector_data[DATA_SIZE + 4 + 24];
static const uint8_t sector_header[24] = {
@@ -371,15 +363,16 @@ static imgtoolerr_t vzdos_write_formatted_sector(imgtool::image &img, int track,
0x80, 0x80, 0x80, 0x00, 0xC3, 0x18, 0xE7, 0xFE
};
- memset(sector_data, 0x00, sizeof(sector_data));
+ std::fill(std::begin(sector_data), std::end(sector_data), 0x00);
memcpy(sector_data, sector_header, sizeof(sector_header));
sector_data[10] = (uint8_t) track; /* current track */
sector_data[11] = (uint8_t) sector; /* current sector */
sector_data[12] = (uint8_t) track + sector; /* checksum-8 */
- ret = floppy_write_sector(imgtool_floppy(img), 0, track, sector_order[sector], 0, sector_data, sizeof(sector_data), 0); /* TODO: pass ddam argument from imgtool */
- if (ret) return (imgtoolerr_t)ret;
+ floperr_t const ret = floppy_write_sector(imgtool_floppy(img), 0, track, sector_order[sector], 0, sector_data, sizeof(sector_data), 0); /* TODO: pass ddam argument from imgtool */
+ if (FLOPPY_ERROR_SUCCESS != ret)
+ return IMGTOOLERR_WRITEERROR;
return IMGTOOLERR_SUCCESS;
}
@@ -427,15 +420,15 @@ static imgtoolerr_t vzdos_diskimage_nextenum(imgtool::directory &enumeration, im
/* kill trailing spaces */
for (len = 7; len > 0; len--) {
- if (dirent.fname[len] != 0x20) {
+ if (dirent.node.fname[len] != 0x20) {
break;
}
}
- memcpy(ent.filename, &dirent.fname, len + 1);
+ memcpy(ent.filename, &dirent.node.fname, len + 1);
ent.filesize = dirent.end_address - dirent.start_address;
- switch (dirent.ftype)
+ switch (dirent.node.ftype)
{
case 0x01: type = "Deleted"; break;
case 'T': type = "Basic"; break;
@@ -620,8 +613,8 @@ static imgtoolerr_t vzdos_writefile(imgtool::partition &partition, int offset, i
return IMGTOOLERR_READONLY;
/* check for already existing filename -> overwrite */
- strcpy(filename, entry->fname);
- filename[vzdos_get_fname_len(entry->fname) + 1] = 0x00;
+ strcpy(filename, entry->node.fname);
+ filename[vzdos_get_fname_len(entry->node.fname) + 1] = 0x00;
ret = vzdos_get_dirent_fname(img, filename, &temp_entry);
if (!ret) {
/* file already exists, delete it */
@@ -705,8 +698,6 @@ static imgtoolerr_t vzdos_writefile(imgtool::partition &partition, int offset, i
/* create a new file or overwrite a file */
static imgtoolerr_t vzdos_diskimage_writefile(imgtool::partition &partition, const char *filename, const char *fork, imgtool::stream &sourcef, util::option_resolution *opts)
{
- imgtoolerr_t ret;
- int ftype;
vzdos_dirent entry;
/* TODO: check for leading spaces and strip */
@@ -714,37 +705,34 @@ static imgtoolerr_t vzdos_diskimage_writefile(imgtool::partition &partition, con
return IMGTOOLERR_BADFILENAME;
/* prepare directory entry */
- ftype = opts->lookup_int('T');
+ int const ftype = opts->lookup_int('T');
switch (ftype) {
case 0:
- entry.ftype = 'T';
+ entry.node.ftype = 'T';
entry.start_address = 31465;
break;
case 1:
- entry.ftype = 'B';
+ entry.node.ftype = 'B';
entry.start_address = 31465; /* ??? */
break;
case 2:
- entry.ftype = 'D';
+ entry.node.ftype = 'D';
entry.start_address = 31465; /* ??? */
break;
default:
break;
}
- entry.delimitor = ':';
- memset(&entry.fname, 0x20, 8); /* pad with spaces */
- memcpy(&entry.fname, filename, strlen(filename));
+ entry.node.delimitor = ':';
+ memset(&entry.node.fname, 0x20, 8); /* pad with spaces */
+ memcpy(&entry.node.fname, filename, strlen(filename));
/* write file to disk */
- ret = vzdos_writefile(partition, 0, sourcef, &entry);
- if (ret) return ret;
-
- return IMGTOOLERR_SUCCESS;
+ return vzdos_writefile(partition, 0, sourcef, &entry);
}
-static imgtoolerr_t vzdos_diskimage_suggesttransfer(imgtool::partition &partition, const char *fname, imgtool_transfer_suggestion *suggestions, size_t suggestions_length)
+static imgtoolerr_t vzdos_diskimage_suggesttransfer(imgtool::partition &partition, const char *fname, imgtool::transfer_suggestion *suggestions, size_t suggestions_length)
{
imgtoolerr_t ret;
imgtool::image &image(partition.image());
@@ -754,37 +742,37 @@ static imgtoolerr_t vzdos_diskimage_suggesttransfer(imgtool::partition &partitio
ret = vzdos_get_dirent_fname(image, fname, &entry);
if (ret) return ret;
- switch (entry.ftype) {
+ switch (entry.node.ftype) {
case 'B':
- suggestions[0].viability = SUGGESTION_RECOMMENDED;
+ suggestions[0].viability = imgtool::SUGGESTION_RECOMMENDED;
suggestions[0].filter = filter_vzsnapshot_getinfo;
suggestions[0].description = "VZ Snapshot";
- suggestions[1].viability = SUGGESTION_POSSIBLE;
- suggestions[1].filter = NULL;
+ suggestions[1].viability = imgtool::SUGGESTION_POSSIBLE;
+ suggestions[1].filter = nullptr;
suggestions[1].description = "Raw";
break;
case 'T':
- suggestions[0].viability = SUGGESTION_RECOMMENDED;
+ suggestions[0].viability = imgtool::SUGGESTION_RECOMMENDED;
suggestions[0].filter = filter_vzsnapshot_getinfo;
suggestions[0].description = "VZ Snapshot";
- suggestions[1].viability = SUGGESTION_POSSIBLE;
- suggestions[1].filter = NULL;
+ suggestions[1].viability = imgtool::SUGGESTION_POSSIBLE;
+ suggestions[1].filter = nullptr;
suggestions[1].description = "Raw";
- suggestions[2].viability = SUGGESTION_POSSIBLE;
+ suggestions[2].viability = imgtool::SUGGESTION_POSSIBLE;
suggestions[2].filter = filter_vzbas_getinfo;
suggestions[2].description = "Tokenized Basic";
break;
default:
- suggestions[0].viability = SUGGESTION_RECOMMENDED;
- suggestions[0].filter = NULL;
+ suggestions[0].viability = imgtool::SUGGESTION_RECOMMENDED;
+ suggestions[0].filter = nullptr;
suggestions[0].description = "Raw";
}
} else {
- suggestions[0].viability = SUGGESTION_RECOMMENDED;
- suggestions[0].filter = NULL;
+ suggestions[0].viability = imgtool::SUGGESTION_RECOMMENDED;
+ suggestions[0].filter = nullptr;
suggestions[0].description = "Raw";
- suggestions[1].viability = SUGGESTION_POSSIBLE;
+ suggestions[1].viability = imgtool::SUGGESTION_POSSIBLE;
suggestions[1].filter = filter_vzsnapshot_getinfo;
suggestions[1].description = "VZ Snapshot";
}
@@ -827,7 +815,7 @@ static imgtoolerr_t vzsnapshot_readfile(imgtool::partition &partition, const cha
header[1] = 'Z';
header[2] = 'F';
- switch (entry.ftype) {
+ switch (entry.node.ftype) {
case 'B':
header[3] = '1';
header[21] = 0xF1;
@@ -842,7 +830,7 @@ static imgtoolerr_t vzsnapshot_readfile(imgtool::partition &partition, const cha
}
memset(header + 4, 0x00, 17);
- memcpy(header + 4, entry.fname, vzdos_get_fname_len(entry.fname) + 1);
+ memcpy(header + 4, entry.node.fname, vzdos_get_fname_len(entry.node.fname) + 1);
put_u16le(&header[22], entry.start_address);
/* write header to file */
@@ -866,21 +854,21 @@ static imgtoolerr_t vzsnapshot_writefile(imgtool::partition &partition, const ch
sourcef.read(header, sizeof(header));
/* prepare directory entry */
- entry.ftype = header[21] == 0xF1 ? 'B' : 'T';
- entry.delimitor = ':';
- entry.start_address = get_u16le(&header[22]);
+ entry.node.ftype = (header[21] == 0xF1) ? 'B' : 'T';
+ entry.node.delimitor = ':';
+ entry.start_address = get_u16le(&header[22]);
/* filename from header or directly? */
fnameopt = opts->lookup_int('F');
if (fnameopt == 0) {
- memcpy(&entry.fname, &header[4], 8);
+ memcpy(&entry.node.fname, &header[4], 8);
} else {
/* TODO: check for leading spaces and strip */
if (strlen(filename) > 8 || strlen(filename) < 1)
return IMGTOOLERR_BADFILENAME;
- memcpy(&entry.fname, filename, strlen(filename) - 3);
+ memcpy(&entry.node.fname, filename, strlen(filename) - 3);
}
/* write file to disk */
@@ -890,7 +878,7 @@ static imgtoolerr_t vzsnapshot_writefile(imgtool::partition &partition, const ch
return IMGTOOLERR_SUCCESS;
}
-void filter_vzsnapshot_getinfo(uint32_t state, union filterinfo *info)
+void filter_vzsnapshot_getinfo(uint32_t state, imgtool::filterinfo *info)
{
switch(state)
{
@@ -939,16 +927,16 @@ void vzdos_get_info(const imgtool_class *imgclass, uint32_t state, union imgtool
case IMGTOOLINFO_INT_PREFER_UCASE: info->i = 1; break;
case IMGTOOLINFO_INT_DIRECTORY_EXTRA_BYTES: info->i = sizeof(vz_iterator); break;
- /* --- the following bits of info are returned as NULL-terminated strings --- */
+ /* --- the following bits of info are returned as NUL-terminated strings --- */
case IMGTOOLINFO_STR_NAME: strcpy(info->s = imgtool_temp_str(), "vzdos"); break;
case IMGTOOLINFO_STR_DESCRIPTION: strcpy(info->s = imgtool_temp_str(), "VZ-DOS format"); break;
case IMGTOOLINFO_STR_FILE: strcpy(info->s = imgtool_temp_str(), __FILE__); break;
case IMGTOOLINFO_STR_WRITEFILE_OPTSPEC: strcpy(info->s = imgtool_temp_str(), "T[0]-2;F[0]-1"); break;
- case IMGTOOLINFO_STR_EOLN: info->s = NULL; break;
+ case IMGTOOLINFO_STR_EOLN: info->s = nullptr; break;
/* --- the following bits of info are returned as pointers to data or functions --- */
case IMGTOOLINFO_PTR_MAKE_CLASS: info->make_class = imgtool_floppy_make_class; break;
- case IMGTOOLINFO_PTR_OPEN: info->open = NULL; break;
+ case IMGTOOLINFO_PTR_OPEN: info->open = nullptr; break;
case IMGTOOLINFO_PTR_BEGIN_ENUM: info->begin_enum = vzdos_diskimage_beginenum; break;
case IMGTOOLINFO_PTR_NEXT_ENUM: info->next_enum = vzdos_diskimage_nextenum; break;
case IMGTOOLINFO_PTR_FREE_SPACE: info->free_space = vzdos_diskimage_freespace; break;
diff --git a/src/tools/imgtool/stream.cpp b/src/tools/imgtool/stream.cpp
index 05f105afbc2..f68f8b4eac6 100644
--- a/src/tools/imgtool/stream.cpp
+++ b/src/tools/imgtool/stream.cpp
@@ -21,6 +21,7 @@
#include <cstdarg>
#include <cstdio>
#include <cstring>
+#include <tuple>
@@ -70,7 +71,7 @@ public:
return std::error_condition();
}
- virtual std::error_condition read(void *buffer, std::size_t length, std::size_t &actual) noexcept override
+ virtual std::error_condition read_some(void *buffer, std::size_t length, std::size_t &actual) noexcept override
{
actual = m_stream->read(buffer, length);
if (actual < length)
@@ -78,7 +79,7 @@ public:
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
+ virtual std::error_condition read_some_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);
@@ -111,7 +112,7 @@ public:
return std::error_condition();
}
- virtual std::error_condition write(void const *buffer, std::size_t length, std::size_t &actual) noexcept override
+ virtual std::error_condition write_some(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();
@@ -124,7 +125,7 @@ public:
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
+ virtual std::error_condition write_some_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();
@@ -391,13 +392,14 @@ util::core_file *stream::core_file()
uint32_t stream::read(void *buf, uint32_t sz)
{
+ std::error_condition err;
size_t result = 0;
switch(imgtype)
{
case IMG_FILE:
if (!file->seek(position, SEEK_SET))
- file->read(buf, sz, result); // FIXME: check error return
+ std::tie(err, result) = util::read(*file, buf, sz); // FIXME: check error return
break;
case IMG_MEM:
@@ -424,6 +426,7 @@ uint32_t stream::read(void *buf, uint32_t sz)
uint32_t stream::write(const void *buf, uint32_t sz)
{
+ std::error_condition err;
size_t result = 0;
switch(imgtype)
@@ -455,7 +458,7 @@ uint32_t stream::write(const void *buf, uint32_t sz)
case IMG_FILE:
if (!file->seek(position, SEEK_SET))
- file->write(buf, sz, result); // FIXME: check error return
+ std::tie(err, result) = util::write(*file, buf, sz); // FIXME: check error return
break;
default:
diff --git a/src/tools/ldresample.cpp b/src/tools/ldresample.cpp
index 0836fd4b7a9..4fcd19c3afc 100644
--- a/src/tools/ldresample.cpp
+++ b/src/tools/ldresample.cpp
@@ -249,7 +249,7 @@ 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
- std::error_condition chderr = file.read_hunk(field, nullptr);
+ std::error_condition chderr = file.codec_process_hunk(field);
return !chderr;
}
diff --git a/src/tools/ldverify.cpp b/src/tools/ldverify.cpp
index bb95c3fbad4..bdb3b8c0a1f 100644
--- a/src/tools/ldverify.cpp
+++ b/src/tools/ldverify.cpp
@@ -252,7 +252,7 @@ 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
- std::error_condition chderr = chdfile->read_hunk(frame * interlace_factor + fieldnum, nullptr);
+ std::error_condition chderr = chdfile->codec_process_hunk(frame * interlace_factor + fieldnum);
if (chderr)
return false;
diff --git a/src/tools/regrep.cpp b/src/tools/regrep.cpp
index fd6f002ac89..316ef805f5a 100644
--- a/src/tools/regrep.cpp
+++ b/src/tools/regrep.cpp
@@ -14,6 +14,7 @@
#include "osdcomm.h"
+#include <algorithm>
#include <cassert>
#include <cctype>
#include <cstdio>
@@ -67,8 +68,8 @@ struct summary_file
summary_file * next;
char name[20];
char source[100];
- uint8_t status[MAX_COMPARES];
- uint8_t matchbitmap[MAX_COMPARES];
+ uint8_t status[MAX_COMPARES];
+ uint8_t matchbitmap[MAX_COMPARES];
std::string text[MAX_COMPARES];
};
@@ -224,7 +225,7 @@ static inline int get_unique_index(const summary_file *curfile, int index)
int main(int argc, char *argv[])
{
- uint32_t bufsize;
+ size_t bufsize;
void *buffer;
int listnum;
int result;
@@ -290,7 +291,7 @@ int main(int argc, char *argv[])
static summary_file *get_file(const char *filename)
{
- summary_file *file;
+ summary_file *file = nullptr;
/* use the first two characters as a lookup */
for (file = filehash[filename[0] & 0x7f][filename[1] & 0x7f]; file != nullptr; file = file->next)
@@ -298,10 +299,14 @@ static summary_file *get_file(const char *filename)
return file;
/* didn't find one -- allocate */
- file = (summary_file *)malloc(sizeof(*file));
+ file = new (std::nothrow) summary_file;
if (file == nullptr)
return nullptr;
- memset(file, 0, sizeof(*file));
+ file->next = nullptr;
+ std::fill(std::begin(file->name), std::end(file->name), '\0');
+ std::fill(std::begin(file->source), std::end(file->source), '\0');
+ std::fill(std::begin(file->status), std::end(file->status), 0);
+ std::fill(std::begin(file->matchbitmap), std::end(file->matchbitmap), 0);
/* set the name so we find it in the future */
strcpy(file->name, filename);
@@ -510,7 +515,7 @@ static int CLIB_DECL compare_file(const void *file0ptr, const void *file1ptr)
into a single, sorted list
-------------------------------------------------*/
-static summary_file *sort_file_list(void)
+static summary_file *sort_file_list()
{
summary_file *listhead, **tailptr, *curfile, **filearray;
int numfiles, filenum;
@@ -577,8 +582,7 @@ static util::core_file::ptr create_file_and_output_header(std::string_view filen
/* print a header */
std::string modified(templatefile);
strreplace(modified, "<!--TITLE-->", title);
- std::size_t written;
- file->write(modified.c_str(), modified.length(), written); // FIXME: check for errors
+ /*auto const [err, written] =*/ write(*file, modified.c_str(), modified.length()); // FIXME: check for errors
/* return the file */
return file;
@@ -594,8 +598,7 @@ static void output_footer_and_close_file(util::write_stream::ptr &&file, std::st
{
std::string modified(templatefile);
strreplace(modified, "<!--TITLE-->", title);
- std::size_t written;
- file->write(modified.c_str(), modified.length(), written); // FIXME: check for errors
+ /*auto const [err, written] =*/ write(*file, modified.c_str(), modified.length()); // FIXME: check for errors
file.reset();
}
diff --git a/src/tools/romcmp.cpp b/src/tools/romcmp.cpp
index 01a234b9736..e3ae03c8f5e 100644
--- a/src/tools/romcmp.cpp
+++ b/src/tools/romcmp.cpp
@@ -559,7 +559,10 @@ static int load_files(int i, int *found, const char *path)
else
{
if (zip->decompress(file.buf.get(), file.size))
+ {
+ printf("%s: Decompression failed\n", file.name.c_str());
file.free();
+ }
}
file.listed = 0;
diff --git a/src/tools/split.cpp b/src/tools/split.cpp
index 10078060448..5668e6e254c 100644
--- a/src/tools/split.cpp
+++ b/src/tools/split.cpp
@@ -12,11 +12,13 @@
#include "corestr.h"
#include "hashing.h"
+#include <cassert>
+#include <cctype>
#include <cstdio>
#include <cstdlib>
#include <cstring>
-#include <cctype>
-#include <cassert>
+#include <tuple>
+#include <type_traits>
#define DEFAULT_SPLIT_SIZE 100
#define MAX_PARTS 1000
@@ -34,11 +36,19 @@
hash over a buffer and return a string
-------------------------------------------------*/
-static void compute_hash_as_string(std::string &buffer, void *data, uint32_t length)
+static void compute_hash_as_string(std::string &buffer, const void *data, size_t length)
{
// compute the SHA1
util::sha1_creator sha1;
- sha1.append(data, length);
+ do
+ {
+ // deal with size_t potentially being bigger than 32 bits
+ auto const chunk = std::min<std::common_type_t<size_t, uint32_t> >(length, std::numeric_limits<uint32_t>::max());
+ sha1.append(data, chunk);
+ length -= chunk;
+ data = reinterpret_cast<const uint8_t *>(data) + chunk;
+ }
+ while (length);
const util::sha1_t sha1digest = sha1.finish();
// expand the digest to a string
@@ -141,7 +151,7 @@ static int split_file(const char *filename, const char *basename, uint32_t split
// read as much as we can from the file
size_t length;
- infile->read(splitbuffer, splitsize, length); // FIXME check error return
+ std::tie(filerr, length) = read(*infile, splitbuffer, splitsize); // FIXME check error return
if (length == 0)
break;
@@ -167,8 +177,8 @@ static int split_file(const char *filename, const char *basename, uint32_t split
// write the data
size_t actual;
- filerr = outfile->write(splitbuffer, length, actual);
- if (filerr || (actual != length) || outfile->flush())
+ std::tie(filerr, actual) = write(*outfile, splitbuffer, length);
+ if (filerr || outfile->flush())
{
printf("\n");
fprintf(stderr, "Fatal error: Error writing output file (out of space?)\n");
@@ -302,7 +312,7 @@ static int join_file(const char *filename, const char *outname, int write_output
// read the file's contents
infilename.insert(0, basepath);
- uint32_t length;
+ size_t length;
filerr = util::core_file::load(infilename.c_str(), &splitbuffer, length);
if (filerr)
{
@@ -328,8 +338,8 @@ static int join_file(const char *filename, const char *outname, int write_output
printf(" writing...");
size_t actual;
- filerr = outfile->write(splitbuffer, length, actual);
- if (filerr || (actual != length) || outfile->flush())
+ std::tie(filerr, actual) = write(*outfile, splitbuffer, length);
+ if (filerr || outfile->flush())
{
printf("\n");
fprintf(stderr, "Fatal error: Error writing output file (out of space?)\n");
diff --git a/src/tools/srcclean.cpp b/src/tools/srcclean.cpp
index d5429ae4823..63809b57f1e 100644
--- a/src/tools/srcclean.cpp
+++ b/src/tools/srcclean.cpp
@@ -2305,11 +2305,22 @@ int main(int argc, char *argv[])
++failures;
continue;
}
- std::size_t block;
- while (remaining && !infile->read(original, (std::min)(std::uint64_t(sizeof(original)), remaining), block) && block)
+ while (remaining)
{
- remaining -= block;
- cleaner->process(original, original + block);
+ std::size_t block((std::min)(std::uint64_t(sizeof(original)), remaining));
+ std::size_t actual;
+ std::error_condition const readerr(infile->read_some(original, block, actual));
+ if (readerr)
+ {
+ if (std::errc::interrupted != readerr)
+ break;
+ }
+ else if (!actual)
+ {
+ break;
+ }
+ remaining -= actual;
+ cleaner->process(original, original + actual);
}
if (remaining)
{
diff --git a/src/tools/unidasm.cpp b/src/tools/unidasm.cpp
index 50c5e5ba7e8..be64dc9cb72 100644
--- a/src/tools/unidasm.cpp
+++ b/src/tools/unidasm.cpp
@@ -27,8 +27,10 @@ using util::BIT;
#include "cpu/asap/asapdasm.h"
#include "cpu/avr8/avr8dasm.h"
#include "cpu/bcp/bcpdasm.h"
+#include "cpu/c33/c33dasm.h"
#include "cpu/capricorn/capricorn_dasm.h"
#include "cpu/ccpu/ccpudasm.h"
+#include "cpu/cdc160/cdc160d.h"
#include "cpu/cdc1700/cdc1700d.h"
#include "cpu/clipper/clipperd.h"
#include "cpu/cop400/cop410ds.h"
@@ -67,6 +69,7 @@ using util::BIT;
#include "cpu/hcd62121/hcd62121d.h"
#include "cpu/hd61700/hd61700d.h"
#include "cpu/hmcs40/hmcs40d.h"
+#include "cpu/hmcs400/hmcs400d.h"
#include "cpu/hp2100/hp2100d.h"
#include "cpu/hpc/hpcdasm.h"
#include "cpu/hphybrid/hphybrid_dasm.h"
@@ -94,11 +97,11 @@ using util::BIT;
#include "cpu/m6502/m6502d.h"
#include "cpu/m6502/m6509d.h"
#include "cpu/m6502/m6510d.h"
-#include "cpu/m6502/m65c02d.h"
#include "cpu/m6502/m65ce02d.h"
#include "cpu/m6502/m740d.h"
#include "cpu/m6502/r65c02d.h"
#include "cpu/m6502/r65c19d.h"
+#include "cpu/m6502/w65c02d.h"
#include "cpu/m6502/xavixd.h"
#include "cpu/m6502/xavix2000d.h"
#include "cpu/m6800/6800dasm.h"
@@ -121,19 +124,24 @@ using util::BIT;
#include "cpu/minx/minxd.h"
#include "cpu/mips/mips3dsm.h"
#include "cpu/mips/mips1dsm.h"
+#include "cpu/mipsx/mipsxdasm.h"
#include "cpu/mk1/mk1dasm.h"
#include "cpu/mn1400/mn1400d.h"
#include "cpu/mn1610/mn1610d.h"
#include "cpu/mn1880/mn1880d.h"
#include "cpu/mn10200/mn102dis.h"
+#include "cpu/mn10300/mn103dasm.h"
+#include "cpu/mpk1839/kl1839vm1dasm.h"
#include "cpu/msm65x2/msm65x2d.h"
#include "cpu/nanoprocessor/nanoprocessor_dasm.h"
#include "cpu/nec/necdasm.h"
#include "cpu/nios2/nios2dasm.h"
#include "cpu/nova/novadasm.h"
-#include "cpu/ns32000/ns32000dasm.h"
+#include "cpu/ns32000/ns32000d.h"
#include "cpu/nuon/nuondasm.h"
+#include "cpu/olms66k/nx8dasm.h"
#include "cpu/pace/pacedasm.h"
+#include "cpu/palm/palmd.h"
#include "cpu/patinhofeio/patinho_feio_dasm.h"
#include "cpu/pdp1/pdp1dasm.h"
#include "cpu/pdp8/pdp8dasm.h"
@@ -191,6 +199,7 @@ using util::BIT;
#include "cpu/unsp/unspdasm.h"
#include "cpu/upd177x/upd177xd.h"
#include "cpu/upd7725/dasm7725.h"
+#include "cpu/upd777/upd777dasm.h"
#include "cpu/upd7810/upd7810_dasm.h"
#include "cpu/upd78k/upd78k0d.h"
#include "cpu/upd78k/upd78k1d.h"
@@ -205,10 +214,12 @@ using util::BIT;
#include "cpu/vt50/vt50dasm.h"
#include "cpu/vt61/vt61dasm.h"
#include "cpu/we32000/we32100d.h"
+#include "cpu/xa/xadasm.h"
#include "cpu/xavix2/xavix2d.h"
#include "cpu/xtensa/xtensad.h"
#include "cpu/z180/z180dasm.h"
#include "cpu/z8/z8dasm.h"
+#include "cpu/z80/r800dasm.h"
#include "cpu/z80/z80dasm.h"
#include "cpu/z8000/8000dasm.h"
@@ -262,7 +273,6 @@ struct g65816_unidasm_t : g65816_disassembler::config
bool x_flag;
g65816_unidasm_t() { m_flag = false; x_flag = false; }
- virtual ~g65816_unidasm_t() override = default;
virtual bool get_m_flag() const override { return m_flag; }
virtual bool get_x_flag() const override { return x_flag; }
} g65816_unidasm;
@@ -338,11 +348,9 @@ struct z8000_unidasm_t : z8000_disassembler::config
struct hyperstone_unidasm_t : hyperstone_disassembler::config
{
bool h;
- u8 fp;
- hyperstone_unidasm_t() { h = false; fp = 0; }
+ hyperstone_unidasm_t() { h = false; }
virtual ~hyperstone_unidasm_t() = default;
- virtual u8 get_fp() const { return fp; }
virtual bool get_h() const { return h; }
} hyperstone_unidasm;
@@ -412,8 +420,11 @@ static const dasm_table_entry dasm_table[] =
{ "b5500", le, 0, []() -> util::disasm_interface * { return new b5500_disassembler; } },
{ "b6000", le, 0, []() -> util::disasm_interface * { return new b6000_disassembler; } },
{ "b6100", le, 0, []() -> util::disasm_interface * { return new b6100_disassembler; } },
+ { "c33", le, 0, []() -> util::disasm_interface * { return new c33_disassembler; } },
{ "capricorn", le, 0, []() -> util::disasm_interface * { return new capricorn_disassembler; } },
{ "ccpu", le, 0, []() -> util::disasm_interface * { return new ccpu_disassembler; } },
+ { "cdc160", be, -1, []() -> util::disasm_interface * { return new cdc160_disassembler; } },
+ { "cdc160a", be, -1, []() -> util::disasm_interface * { return new cdc160a_disassembler; } },
{ "cdc1700", be, -1, []() -> util::disasm_interface * { return new cdc1700_disassembler; } },
{ "cdp1801", le, 0, []() -> util::disasm_interface * { return new cosmac_disassembler(cosmac_disassembler::TYPE_1801); } },
{ "cdp1802", le, 0, []() -> util::disasm_interface * { return new cosmac_disassembler(cosmac_disassembler::TYPE_1802); } },
@@ -468,6 +479,7 @@ static const dasm_table_entry dasm_table[] =
{ "hd6309", be, 0, []() -> util::disasm_interface * { return new hd6309_disassembler; } },
{ "hd63701", be, 0, []() -> util::disasm_interface * { return new m680x_disassembler(63701); } },
{ "hmcs40", le, -1, []() -> util::disasm_interface * { return new hmcs40_disassembler; } },
+ { "hmcs400", le, -1, []() -> util::disasm_interface * { return new hmcs400_disassembler; } },
{ "hp2100", be, -1, []() -> util::disasm_interface * { return new hp2100_disassembler; } },
{ "hp21mx", be, -1, []() -> util::disasm_interface * { return new hp21mx_disassembler; } },
{ "hp_5061_3001", be, -1, []() -> util::disasm_interface * { return new hp_5061_3001_disassembler; } },
@@ -500,6 +512,7 @@ static const dasm_table_entry dasm_table[] =
{ "jaguargpu", be, 0, []() -> util::disasm_interface * { return new jaguar_disassembler(jaguar_disassembler::variant::GPU); } },
{ "konami", be, 0, []() -> util::disasm_interface * { return new konami_disassembler; } },
{ "ks0164", be, 0, []() -> util::disasm_interface * { return new ks0164_disassembler; } },
+ { "kl1839vm1", be, 0, []() -> util::disasm_interface * { return new kl1839vm1_disassembler; } },
{ "lc57", be, 0, []() -> util::disasm_interface * { return new lc57_disassembler; } },
{ "lc58", be, -1, []() -> util::disasm_interface * { return new lc58_disassembler; } },
{ "lc8670", be, 0, []() -> util::disasm_interface * { return new lc8670_disassembler; } },
@@ -514,7 +527,6 @@ static const dasm_table_entry dasm_table[] =
{ "m6502", le, 0, []() -> util::disasm_interface * { return new m6502_disassembler; } },
{ "m6509", le, 0, []() -> util::disasm_interface * { return new m6509_disassembler; } },
{ "m6510", le, 0, []() -> util::disasm_interface * { return new m6510_disassembler; } },
- { "m65c02", le, 0, []() -> util::disasm_interface * { return new m65c02_disassembler; } },
{ "m65ce02", le, 0, []() -> util::disasm_interface * { return new m65ce02_disassembler; } },
{ "m6800", be, 0, []() -> util::disasm_interface * { return new m680x_disassembler(6800); } },
{ "m68000", be, 0, []() -> util::disasm_interface * { return new m68k_disassembler(m68k_disassembler::TYPE_68000); } },
@@ -533,7 +545,7 @@ static const dasm_table_entry dasm_table[] =
{ "m740", le, 0, []() -> util::disasm_interface * { return new m740_disassembler(&m740_unidasm); } },
{ "mb86233", le, -2, []() -> util::disasm_interface * { return new mb86233_disassembler; } },
{ "mb86235", le, -3, []() -> util::disasm_interface * { return new mb86235_disassembler; } },
- { "mb88", le, 0, []() -> util::disasm_interface * { return new mb88_disassembler; } },
+ { "mb88xx", le, 0, []() -> util::disasm_interface * { return new mb88_disassembler; } },
{ "mc88100", be, 0, []() -> util::disasm_interface * { return new mc88100_disassembler; } },
{ "mc88110", be, 0, []() -> util::disasm_interface * { return new mc88110_disassembler; } },
{ "mcs48", le, 0, []() -> util::disasm_interface * { return new mcs48_disassembler(false, false); } },
@@ -542,11 +554,13 @@ static const dasm_table_entry dasm_table[] =
{ "mips1le", le, 0, []() -> util::disasm_interface * { return new mips1_disassembler; } },
{ "mips3be", be, 0, []() -> util::disasm_interface * { return new mips3_disassembler; } },
{ "mips3le", le, 0, []() -> util::disasm_interface * { return new mips3_disassembler; } },
+ { "mipsx", be, 0, []() -> util::disasm_interface * { return new mipsx_disassembler; } },
{ "mk1", le, 0, []() -> util::disasm_interface * { return new mk1_disassembler; } },
{ "mm5799", le, 0, []() -> util::disasm_interface * { return new mm5799_disassembler; } },
{ "mm76", le, 0, []() -> util::disasm_interface * { return new mm76_disassembler; } },
{ "mm78", le, 0, []() -> util::disasm_interface * { return new mm78_disassembler; } },
{ "mn10200", le, 0, []() -> util::disasm_interface * { return new mn10200_disassembler; } },
+ { "mn10300", le, 0, []() -> util::disasm_interface * { return new mn10300_disassembler; } },
{ "mn1400", le, 0, []() -> util::disasm_interface * { return new mn1400_disassembler; } },
{ "mn1610", be, -1, []() -> util::disasm_interface * { return new mn1610_disassembler; } },
{ "mn1613", be, -1, []() -> util::disasm_interface * { return new mn1613_disassembler; } },
@@ -561,7 +575,11 @@ static const dasm_table_entry dasm_table[] =
{ "ns32000", le, 0, []() -> util::disasm_interface * { return new ns32000_disassembler; } },
{ "nuon", be, 0, []() -> util::disasm_interface * { return new nuon_disassembler; } },
{ "nsc8105", be, 0, []() -> util::disasm_interface * { return new m680x_disassembler(8105); } },
+ { "nx8_500s", le, 0, []() -> util::disasm_interface * { return new nx8_500s_disassembler; } },
+ { "p8xc552", le, 0, []() -> util::disasm_interface * { return new p8xc552_disassembler; } },
+ { "p8xc562", le, 0, []() -> util::disasm_interface * { return new p8xc562_disassembler; } },
{ "pace", le, -1, []() -> util::disasm_interface * { return new pace_disassembler; } },
+ { "palm", be, 0, []() -> util::disasm_interface * { return new palm_disassembler; } },
{ "patinho_feio", le, 0, []() -> util::disasm_interface * { return new patinho_feio_disassembler; } },
{ "pdp1", be, -2, []() -> util::disasm_interface * { return new pdp1_disassembler; } },
{ "pdp8", be, -1, []() -> util::disasm_interface * { return new pdp8_disassembler; } },
@@ -581,6 +599,7 @@ static const dasm_table_entry dasm_table[] =
{ "psxcpu", le, 0, []() -> util::disasm_interface * { return new psxcpu_disassembler; } },
{ "r65c02", le, 0, []() -> util::disasm_interface * { return new r65c02_disassembler; } },
{ "r65c19", le, 0, []() -> util::disasm_interface * { return new r65c19_disassembler; } },
+ { "r800", le, 0, []() -> util::disasm_interface * { return new r800_disassembler; } },
{ "romp", be, 0, []() -> util::disasm_interface * { return new romp_disassembler; } },
{ "rsp", le, 0, []() -> util::disasm_interface * { return new rsp_disassembler; } },
{ "rupi44", le, 0, []() -> util::disasm_interface * { return new rupi44_disassembler; } },
@@ -657,6 +676,7 @@ static const dasm_table_entry dasm_table[] =
{ "unsp12", be, -1, []() -> util::disasm_interface * { return new unsp_12_disassembler; } },
{ "unsp20", be, -1, []() -> util::disasm_interface * { return new unsp_20_disassembler; } },
{ "upd177x", be, -1, []() -> util::disasm_interface * { return new upd177x_disassembler; } },
+ { "upd777", be, -1, []() -> util::disasm_interface * { return new upd777_disassembler; } },
{ "upd7725", be, -2, []() -> util::disasm_interface * { return new necdsp_disassembler; } },
{ "upd7801", le, 0, []() -> util::disasm_interface * { return new upd7801_disassembler; } },
{ "upd78c05", le, 0, []() -> util::disasm_interface * { return new upd78c05_disassembler; } },
@@ -709,10 +729,12 @@ static const dasm_table_entry dasm_table[] =
{ "vt50", le, 0, []() -> util::disasm_interface * { return new vt50_disassembler; } },
{ "vt52", le, 0, []() -> util::disasm_interface * { return new vt52_disassembler; } },
{ "vt61", le, -1, []() -> util::disasm_interface * { return new vt61_disassembler; } },
+ { "w65c02", le, 0, []() -> util::disasm_interface * { return new w65c02_disassembler; } },
{ "we32100", be, 0, []() -> util::disasm_interface * { return new we32100_disassembler; } },
{ "x86_16", le, 0, []() -> util::disasm_interface * { i386_unidasm.mode = 16; return new i386_disassembler(&i386_unidasm); } },
{ "x86_32", le, 0, []() -> util::disasm_interface * { i386_unidasm.mode = 32; return new i386_disassembler(&i386_unidasm); } },
{ "x86_64", le, 0, []() -> util::disasm_interface * { i386_unidasm.mode = 64; return new i386_disassembler(&i386_unidasm); } },
+ { "xa", le, 0, []() -> util::disasm_interface * { return new xa_dasm; } },
{ "xavix", le, 0, []() -> util::disasm_interface * { return new xavix_disassembler; } },
{ "xavix2000", le, 0, []() -> util::disasm_interface * { return new xavix2000_disassembler; } },
{ "xavix2", le, 0, []() -> util::disasm_interface * { return new xavix2_disassembler; } },
@@ -1297,8 +1319,7 @@ int disasm_file(util::random_read &file, u64 length, options &opts)
base_buffer.data.resize(rounded_size + 8, 0x00);
base_buffer.size = length;
base_buffer.base_pc = opts.basepc;
- std::size_t actual;
- std::error_condition filerr = file.read_at(opts.skip, &base_buffer.data[0], length - opts.skip, actual);
+ auto const [filerr, actual] = read_at(file, opts.skip, &base_buffer.data[0], length - opts.skip);
if(filerr) {
std::fprintf(stderr, "Error reading from file '%s' (%s)\n", opts.filename, filerr.message().c_str());
return 1;